I am trying to remove all unprotected layer filters from a DWG and getting the following result:
Command: CLEANLF
Deleting layerfilter[0]: 'Test1'...
Autodesk.AutoCAD.Runtime.Exception: eInvalidInput
at Autodesk.AutoCAD.LayerManager.LayerFilterCollection.Remove(LayerFilter value)
at wauCmds.WauCmd.cleanLF_Method()
Deleting layerfilter[1]: 'Test2'...
Autodesk.AutoCAD.Runtime.Exception: eInvalidInput
at Autodesk.AutoCAD.LayerManager.LayerFilterCollection.Remove(LayerFilter value)
at wauCmds.WauCmd.cleanLF_Method()
Deleting layerfilter[2]: 'Group Filter1'...
Autodesk.AutoCAD.Runtime.Exception: eInvalidInput
at Autodesk.AutoCAD.LayerManager.LayerFilterCollection.Remove(LayerFilter value)
at wauCmds.WauCmd.cleanLF_Method()
Layerfilter 'All Used Layers' is protected
Layerfilter 'Unreconciled New Layers' is protected
Layerfilter 'Viewport Overrides' is protected
Layerfilter 'Xref' is protected
Here is the code that produced this output. Any ideas why the Remove throws this exception?
<CommandMethod("cleanLF")> _ Public Sub cleanLF_Method() Dim ed As Editor = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor Dim db As Database = HostApplicationServices.WorkingDatabase Dim acDocMgr As DocumentCollection = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager Using docLock As DocumentLock = acDocMgr.MdiActiveDocument.LockDocument Using tr As Transaction = db.TransactionManager.StartTransaction() For i As Int32 = 0 To db.LayerFilters.Root.NestedFilters.Count - 1 Dim deleteMe As LayerFilter = db.LayerFilters.Root.NestedFilters(i) If deleteMe.AllowDelete Then Try ed.WriteMessage(String.Format("Deleting layerfilter[{0}]: '{1}'...", i, deleteMe.Name) + vbCrLf) db.LayerFilters.Root.NestedFilters.Remove(deleteMe) Catch ex As Exception ed.WriteMessage(ex.ToString + vbCrLf) End Try Else ed.WriteMessage(String.Format("Layerfilter '{0}' is protected", deleteMe.Name) + vbCrLf) End If Next End Using End Using End Sub
ps I am running AutoCAD 2013 SP1.1 PV: G.114.0
Solved! Go to Solution.
Solved by Balaji_Ram. Go to Solution.
Hi,
Note these lines of code in this blog post : http://through-the-interface.typepad.com/through_the_interface/2008/07/adding-and-remo.html
<<<
lfc.Remove(lf);
db.LayerFilters = lft;
>>>
It is a local copy of the "LayerFilterTree" that is modified by removing a layer filter and then set back to database.
I changed the code as such, same result:
<CommandMethod("cleanLF")> _ Public Sub cleanLF_Method() Dim ed As Editor = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor Dim db As Database = HostApplicationServices.WorkingDatabase Dim acDocMgr As DocumentCollection = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager Using docLock As DocumentLock = acDocMgr.MdiActiveDocument.LockDocument Using tr As Transaction = db.TransactionManager.StartTransaction() Dim lft As LayerFilterTree = db.LayerFilters For i As Int32 = 0 To db.LayerFilters.Root.NestedFilters.Count - 1 Dim deleteMe As LayerFilter = db.LayerFilters.Root.NestedFilters(i) If deleteMe.AllowDelete Then Try ed.WriteMessage(String.Format("Deleting layerfilter[{0}]: '{1}'", i, deleteMe.Name) + vbCrLf) db.LayerFilters.Root.NestedFilters.Remove(deleteMe) Catch ex As Exception ed.WriteMessage(ex.ToString + vbCrLf) End Try Else ed.WriteMessage(String.Format("Layerfilter '{0}' is protected", deleteMe.Name) + vbCrLf) End If Next db.LayerFilters = lft End Using End Using End Sub
I also tried adding tr.Commit() after the for loop, no change, the filters are still there. There is an autocad dialog box that kicks in automatically when I try to open a drawing with 20000 layer filters and it cleans it up correctly. I just need the same functionality through the API to prevent drawings from reaching that point to begin with.
Hi Steve,
Here is a sample code to delete the first deletable layer filter from the Layer filters collection.
<CommandMethod("Test")> _ Public Sub TestMethod() Dim doc As Document = Application.DocumentManager.MdiActiveDocument Dim db As Database = doc.Database Dim ed As Editor = doc.Editor Dim lft As Autodesk.AutoCAD.LayerManager.LayerFilterTree = db.LayerFilters Dim lfc As Autodesk.AutoCAD.LayerManager.LayerFilterCollection = lft.Root.NestedFilters For i As Int32 = 0 To db.LayerFilters.Root.NestedFilters.Count - 1 Dim lf As Autodesk.AutoCAD.LayerManager.LayerFilter = lfc(i) If lf.AllowDelete Then Try ed.WriteMessage(String.Format("Deleting layerfilter[{0}]: '{1}'...", i, lf.Name) + vbCrLf) lfc.Remove(lf) Exit For Catch ex As Exception ed.WriteMessage(ex.ToString + vbCrLf) End Try Else ed.WriteMessage(String.Format("Layerfilter '{0}' is protected", lf.Name) + vbCrLf) End If Next db.LayerFilters = lft End Sub
Ok, thanks Balaji: your code sortof works.
Removing the Exit For still leaves about half of the filters intact but if I nest the for loop in a while loop and do multiple passes it does remove all layerfilters.
What made the difference is the lfc variable. The original code works by simply assigning and using this variable, the last assignment (db.LayerFilters = lft) was not necessary:
Dim ed As Editor = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor Dim db As Database = HostApplicationServices.WorkingDatabase Dim acDocMgr As DocumentCollection = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager Using docLock As DocumentLock = acDocMgr.MdiActiveDocument.LockDocument Using tr As Transaction = db.TransactionManager.StartTransaction() Dim lft As LayerFilterTree = db.LayerFilters Dim lfc As LayerFilterCollection = lft.Root.NestedFilters For i As Int32 = 0 To lfc.Count - 1 Dim deleteMe As LayerFilter = lfc(i) If deleteMe.AllowDelete Then Try ed.WriteMessage(String.Format("Deleting layerfilter[{0}]: '{1}'", i, deleteMe.Name) + vbCrLf) lfc.Remove(deleteMe) Catch ex As Exception ed.WriteMessage(ex.ToString + vbCrLf) End Try Else ed.WriteMessage(String.Format("Layerfilter '{0}' is protected", deleteMe.Name) + vbCrLf) End If Next End Using End Using
Thanks again for your help.
One last thing to qualify my previous statement: that last assignment (db.LayerFilters = lft) was necessary for the while loop I mentioned above to clean up left overs in multiple passes. Just to clarify this here is the solution that seems to be able to remove all layerfilters:
Dim db As Database = HostApplicationServices.WorkingDatabase Dim ed As Editor = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor Dim done As Boolean = False While Not done Dim lft As LayerFilterTree = db.LayerFilters Dim lfc As LayerFilterCollection = lft.Root.NestedFilters Dim filtersLeft As Int32 = 0 For i As Int32 = 0 To lfc.Count - 1 Dim lf As LayerFilter = lfc(i) If lf.AllowDelete Then Try ed.WriteMessage(String.Format("Deleting layerfilter[{0}]: '{1}'...", i, lf.Name) + vbCrLf) lfc.Remove(lf) Catch ex As Exception ed.WriteMessage(ex.ToString + vbCrLf) End Try Else ed.WriteMessage(String.Format("Layerfilter '{0}' is protected. AD={1}", lf.Name, lf.AutoDelete) + vbCrLf) End If Next db.LayerFilters = lft For i As Int32 = 0 To lfc.Count - 1 Dim lf As LayerFilter = lfc(i) If lf.AllowDelete Then filtersLeft += 1 ed.WriteMessage(String.Format("LEFT layerfilter[{0}]: '{1}'...", i, lf.Name) + vbCrLf) End If Next If filtersLeft = 0 Then ed.WriteMessage(String.Format("DONE! filtersleft={0}", filtersLeft) + vbCrLf) done = True End If End While
If there is a less messy more elegant solution that doesn not necessitate multiple passes please let me know.
Thanks,
Steve
Hi Steve,
Can you try this ?
<CommandMethod("DeleteAllLayerFilters")> _ Public Sub DeleteAllLayerFilters() Dim doc As Document = Application.DocumentManager.MdiActiveDocument Dim db As Database = doc.Database Dim ed As Editor = doc.Editor Dim lft As Autodesk.AutoCAD.LayerManager.LayerFilterTree = db.LayerFilters Dim lfc As Autodesk.AutoCAD.LayerManager.LayerFilterCollection = lft.Root.NestedFilters Dim totalFilters As Integer = lfc.Count Dim i As Integer = 0 While i < totalFilters Dim lf As Autodesk.AutoCAD.LayerManager.LayerFilter = lfc.Item(i) ed.WriteMessage([String].Format("{0} Checking {1}...", Environment.NewLine, lf.Name)) If lf.AllowDelete Then lfc.Remove(lf) totalFilters = lfc.Count i -= 1 ed.WriteMessage([String].Format("{0} Deleted {1}", Environment.NewLine, lf.Name)) End If i += 1 End While db.LayerFilters = lft End Sub
Regards,
Balaji,
This is a very elegant fast algorithm, kudos!
Thanks a bunch,
Steve
Hi Friends..!!!!
I am trying to do 1 project using vb.net and AutoCAD. In the drawing we have multiple layers and should separately store the Layer blocks with the block names in an Excel Application. I stored the Layer names.But all the entities in the drawing will be stored in the Excel file. I need one by one.
Can't find what you're looking for? Ask the community or share your knowledge.