I am trying to open a DWG file, read the number of specific blocks found inside, and then close the drawing. The problem I am having is that after opening my file from a form using the OpenFileDialog component, I get the eNotApplicable Error on the following line:
Dim dwg As Document = Application.DocumentManager.Open(fileName, True) Using tr As Transaction = dwg.TransactionManager.StartTransaction Dim tv(0 To 1) As TypedValue tv(0) = New TypedValue(0, "INSERT") tv(1) = New TypedValue(2, "SB128") Dim fil As New SelectionFilter(tv) Dim psr As PromptSelectionResult = dwg.Editor.SelectAll(fil) 'FAILS HERE (eNotApplicable ) If psr.Value IsNot Nothing Then newAttribCnt = psr.Value.Count End If End Using dwg.CloseAndDiscard()
I thought it might have something to do with my filter or Typed value so to confirm I tried similar code, but this time instead of opening the target drawing like above, I *manually* opened my file first then ran the following code:
Dim dwg As Document = Application.DocumentManager.MdiActiveDocument Using tr As Transaction = dwg.TransactionManager.StartTransaction Dim tv(0 To 1) As TypedValue tv(0) = New TypedValue(0, "INSERT") tv(1) = New TypedValue(2, "SB128") Dim fil As New SelectionFilter(tv) Dim psr As PromptSelectionResult = dwg.Editor.SelectAll(fil) 'WORKS FINE HERE If psr.Value IsNot Nothing Then newAttribCnt = psr.Value.Count End If End Using
As you can see the only difference is it works when opening the file first and using MdiActiveDocument but does not when opening the file via DocumentManager.Open. When I check "dwg.name" during debugging on the failed code, I can see that "dwg" does reference the file just opened and not the drawing I opened my form from. I bet this is really something simple and fundamental that I just don't know about. I also have made sure that I am calling form.Hide before calling SelectAll, just to make sure that the active form isn't blocking the selection. But even in my MdiActiveDocument example, I am hiding the form and am able to return a valid filtered selection.
Any ideas?
spanqy
Solved! Go to Solution.
Solved by MarkSanchezSPEC. Go to Solution.
I assume the form you used to trigger of your open drawing code (a button click?) is a modeless form (or your code would not able able to open a drawing).
So, you need to lock the document before starting the Transaction. That is:
Dim dwg as Document=Application.DocumentManager.Open(...)
Using lck As DocumentLock=dwg.LockDocument()
''Select entities here.
....
''Then only start transaction if the SelectSet.Count>0
Using tr As Transaction=dwg.Database.TRansactionManager.StartTransaction()
End Using
End Using
Norman Yuan
Try to add before problem line this one:
Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor.StartUserInteraction(Me)
~'J'~
I tried your locking suggestion but it staill fails with the same error at:
Dim psr As PromptSelectionResult = dwg.Editor.SelectAll(fil)
I even took out the OpenFileDialog part and just hard-coded the path to the file - same result. The file always opens, but I cannot seem to select with this filter, which is valid based on my test using the MdiActiveDocument method.
This is really odd - I do a lot of batch routines where I open a drawing, do something, close the drawing, then move on to the next one. In this particular app I am NOT batch processing but my call to Open the drawing is the same as always. I thinlk I might have to drop this for a while and move on with somehting else.
I tried adding this line but if Me.Hide is called *before* it, then I get "Form is not active" error. Removing Me.Hide results in "Invalid execution context" error when trying to select objects. Finally, calling Me.Hide *after* it bring me back to the same "eNotApplicable" error.
Thanks anyway
So you selected blocks in Model, in this case add to your filter,
not sure about if this helps, anyway:
Dim tv(2) AsTypedValue tv(0) = NewTypedValue(0, "INSERT") tv(1) = NewTypedValue(2, "SB128") tv(2) = NewTypedValue(410, "Model") Dim fil AsNewSelectionFilter(tv) Dim psr AsPromptSelectionResult = dwg.Editor.SelectAll(fil)
~'J'~
I am selecting from Model but adding the 410 dxfCode did not help - same error.
I think I am going to post this on the ADN site. I will definitely post any solution.
Thanks for all your help.
Regards
I'm writing something similar weeks ago,
see if this is helps in your case
Class BlockCommands.vb 'Imports System.IO 'Imports System.Linq ''------------------------------------------------------------------------------------------------------------------------------------------------------------'' Public Shared Function GetDirectoryDrawings(directoryFullName As String, subDirsBrowse As Boolean) As List(Of FileInfo) Dim dirinfo As New DirectoryInfo(directoryFullName) If Not dirinfo.Exists Then Throw New DirectoryNotFoundException() Return Nothing End If Dim opt As SearchOption = SearchOption.AllDirectories If subDirsBrowse = False Then opt = SearchOption.TopDirectoryOnly Return dirinfo.GetFiles("*dwg", opt).AsEnumerable().OrderBy(Function(x) x.FullName).ToList() End Function ''-----------------------------------------------------------------------------'' Public Shared Sub testDirFiles(blkname As String, dirpath As String) Dim csvfile As String = Path.Combine(dirpath, blkname) csvfile = csvfile & ".csv" Dim doc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument Dim db As Database = doc.Database Dim ed As Editor = doc.Editor Using doclock As DocumentLock = doc.LockDocument() Try Dim fd As List(Of FileInfo) = GetDirectoryDrawings(dirpath, False) '' True for processing the subdirectories Dim collect As New StringBuilder If fd IsNot Nothing Then For n As Integer = 0 To fd.Count - 1 Dim dwgname As String = fd(n).FullName Using newdb As Database = New Database(False, True) ed.WriteMessage(vbLf + dwgname + vbLf) Try newdb.ReadDwgFile(dwgname, FileOpenMode.OpenForReadAndAllShare, False, Nothing) Catch ex As Autodesk.AutoCAD.Runtime.Exception If ex.ErrorStatus = ErrorStatus.DwgNeedsRecovery Then Continue For End If End Try Using newtr As Transaction = newdb.TransactionManager.StartTransaction ' Open dictionary for reading Dim layoutDict As DBDictionary = DirectCast(newtr.GetObject(newdb.LayoutDictionaryId, OpenMode.ForRead), DBDictionary) ' Loop through dictionary entries For Each entry As DictionaryEntry In layoutDict Dim ltr As Layout = DirectCast(newtr.GetObject(DirectCast(entry.Value, ObjectId), OpenMode.ForRead), Layout) Dim btr As BlockTableRecord = DirectCast(newtr.GetObject(ltr.BlockTableRecordId, OpenMode.ForRead), BlockTableRecord) For Each id As ObjectId In btr Dim obj As DBObject = DirectCast(newtr.GetObject(id, OpenMode.ForRead), DBObject) If TypeOf obj Is BlockReference Then '' Dim bref As BlockReference = TryCast(obj, BlockReference) If bref IsNot Nothing AndAlso bref.Name = blkname Then collect.AppendLine(String.Format("---------------------------------------")) collect.AppendLine(String.Format("Drawing name: {0}", dwgname)) collect.AppendLine(String.Format("Tab: {0}", ltr.LayoutName)) Dim bdef As BlockTableRecord = TryCast(newtr.GetObject(bref.BlockTableRecord, OpenMode.ForRead, False), BlockTableRecord) If bdef IsNot Nothing Then If bdef.HasAttributeDefinitions Then Dim atts As Autodesk.AutoCAD.DatabaseServices.AttributeCollection = bref.AttributeCollection For Each attid As ObjectId In atts Dim rowline As New List(Of String) Dim line As String = String.Empty Dim attref As AttributeReference = TryCast(newtr.GetObject(attid, OpenMode.ForRead, False), AttributeReference) collect.AppendLine(attref.Tag + vbTab + attref.TextString) Next End If End If End If End If Next Next newtr.Commit() End Using End Using Next End If WriteTableToFile(csvfile, collect) Catch ex As System.Exception ed.WriteMessage(vbLf + ex.ToString + vbLf) Finally ed.WriteMessage(vbLf + vbTab + "---> File saved as: {0} <---" + vbLf, csvfile) End Try End Using End Sub Public Shared Sub WriteTableToFile(fpath As String, data As StringBuilder) Using fs As New FileStream(fpath, FileMode.Append, FileAccess.Write) Using sw As New StreamWriter(fs, Encoding.ASCII) sw.WriteLine(data.ToString) End Using End Using End Sub ''------------------------------------------------------------------------------------'' '' On Form module: '' Imports System.IO ''------------------------------------------------------------------------------------'' Private Sub btnBatch_Click(sender As System.Object, e As System.EventArgs) Handles btnBatch.Click Me.Hide() Dim df As String = "Put your directory here" If Not Directory.Exists(df) Then MessageBox.Show("Folder does not exist") Return End If BlockCommands.testDirFiles("Put block name here", df) Me.Show() End Sub
~'J'~
Hi Hallex - and thank you for your continued efforts in this forum.
I see this in your last code posted:
Dim layoutDict As DBDictionary = DirectCast(newtr.GetObject(newdb.LayoutDictionaryId, OpenMode.ForRead), DBDictionary)
and then:
For Each entry As DictionaryEntry In layoutDict
I had trouble with this syntax iterating through layoutdictionary. When I changed to
For Each entry As DBDictionaryEntry In layoutDict, I got different results. I am not convinced DictionaryEntry and DBDictionaryEntry are equal. Perhaps someone from Autodesk can answer that?
Also, my task was locating viewports in layouts and that process is still not clear to me. I have found some old dwg files that have 100's of invisible viewports and have not yet built rules to determine (in code) if they are valid. That problem is back on the shelf.
I posted this as a "heads up". My wish is that the compiler throws a type mismatch error or warning, but it does not.
I think you want to look at ObjectARX docs about this difference,
unfortunatelly there is no docs on my native language,
try to find in there by yoursef, please
Thanks for your warm words, mate
Regards,
Oleg
Eureka!
I solved it myself by adding CommandFlags.Session to my CommandMethod attribute:
<CommandMethod("XX", CommandFlags.Session)> _
Public Sub Main()
End Sub
hi,spanqy
i met this 'filter' error too, how could you know this problem has ties with the '<CommandMethod("XX", CommandFlags.Session)>'?
where were you get the help?
thanks!
Editor interactive methods (Getxxx, Selectxxx) can only be called on the active document (the one that receive user input)
Can't find what you're looking for? Ask the community or share your knowledge.