How can I purge linetypes? We get data from outside sources and my goal is to load our linetypes. I have a list of layers and store the previous layer linetypes. I reset them all to "Continuous". Now I have to purge the old linetype definitions but I can't make them go away. I need to purge DASHED and HIDDEN so far. If I open the file and click on the linetype in layer manager, I still see the old DASHED and HIDDEN definitions. I have tried db.purge(linetypeobjectid) but they don't go away.
Do I need to go through the symboltablerecord to find the correct linetypetablerecord and remove it? Will that remove the linetype from the list shown in layer manager? That is what I need to do - make sure DASHED and HIDDEN *have* to be re-loaded from our linetypes.
Solved! Go to Solution.
Solved by dan.glassman. Go to Solution.
Database.Purge() is a bit of a misnomer, in my opinion. That function doesn't purge items, it just tells you whether or not they are safe to erase -- you do have to erase them yourself. You can erase them without using Database.Purge(), but you can easily corrupt your drawing that way.
Something like the following should do the trick. Note that it doesn't guarantee that linetypes other than continuous are unreferenced; your drawings could have entities that reference those linetypes directly. You may want to script a call to the 'setbylayer' command prior to running your purge command, or scan all the BlockTableRecords yourself, or rename any linetypes that remain after calling your purge command, or otherwise deal with that possibility.
[CommandMethod("purgelts")] public void purgelinetypes() { Document doc = Application.DocumentManager.MdiActiveDocument; Editor ed = doc.Editor; Database db = doc.Database; ObjectIdCollection ltypeIds = new ObjectIdCollection(); using (Transaction t = db.TransactionManager.StartTransaction()) { LinetypeTable ltt = t.GetObject(db.LinetypeTableId, OpenMode.ForRead) as LinetypeTable; foreach (ObjectId ltypeId in ltt) { if (ltypeId == SymbolUtilityServices.GetLinetypeByBlockId(db)) continue; if (ltypeId == SymbolUtilityServices.GetLinetypeByLayerId(db)) continue; if (ltypeId == SymbolUtilityServices.GetLinetypeContinuousId(db)) continue; ltypeIds.Add(ltypeId); } LayerTable lt = t.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable; foreach (ObjectId ltrId in lt) { if (ltrId.IsErased) continue; LayerTableRecord ltr = t.GetObject(ltrId, OpenMode.ForWrite) as LayerTableRecord; ltr.LinetypeObjectId = db.ContinuousLinetype; } t.Commit(); } ed.WriteMessage("Checking whether {0} linetypes can be purged.\n", ltypeIds.Count); db.Purge(ltypeIds); ed.WriteMessage("{0} linetypes can be purged.\n", ltypeIds.Count); using (Transaction t = db.TransactionManager.StartTransaction()) { foreach (ObjectId ltypeId in ltypeIds) { DBObject ltype = t.GetObject(ltypeId, OpenMode.ForWrite); ltype.Erase(); } t.Commit(); } db.ReclaimMemoryFromErasedObjects(ltypeIds); }
Thank you very much. That was educational.
Below is a manual vb conversion. It does not include the layertable section.
<CommandMethod("purgelts")> _ Public Sub purgelinetypes() Dim doc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument Dim ed As Editor = doc.Editor Dim db As Database = doc.Database Dim ltypeids As New ObjectIdCollection Using t As Transaction = db.TransactionManager.StartTransaction() Dim ltt As LinetypeTable = CType(t.GetObject(db.LinetypeTableId, OpenMode.ForRead), LinetypeTable) For Each ltypeid As ObjectId In ltt If ltypeid = SymbolUtilityServices.GetLinetypeByBlockId(db) Then Continue For End If If ltypeid = SymbolUtilityServices.GetLinetypeByLayerId(db) Then Continue For End If If ltypeid = SymbolUtilityServices.GetLinetypeContinuousId(db) Then Continue For End If ltypeids.Add(ltypeid) Next t.Commit() End Using ed.WriteMessage("Checking whether {0} linetypes can be purged " & vbCrLf, ltypeids.Count) db.Purge(ltypeids) ed.WriteMessage("{0} linetypes can be purged " & vbCrLf, ltypeids.Count) Using t As Transaction = db.TransactionManager.StartTransaction For Each ltypeid As ObjectId In ltypeids Dim ltype As LinetypeTableRecord = CType(t.GetObject(ltypeid, OpenMode.ForWrite), LinetypeTableRecord) ltype.Erase() Next t.Commit() End Using db.ReclaimMemoryFromErasedObjects(ltypeids) End Sub
I'm glad that helped. Two things about my code are making me cringe, though -- there's no need to check each linetype to see if it's ByBlock, ByLayer, or Continuous -- one check at the end will do. And the call to ReclaimMemoryFromErasedObjects -- I've removed it in this version because it isn't required to achieve the desired result and...I don't really understand it [sorry!].
Corrected:
<CommandMethod("purgelts")> Public Sub purgelinetypes() Dim doc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument Dim ed As Editor = doc.Editor Dim db As Database = doc.Database Dim ltypeids As New ObjectIdCollection Using t As Transaction = db.TransactionManager.StartTransaction() Dim ltt As LinetypeTable = t.GetObject(db.LinetypeTableId, OpenMode.ForRead) For Each ltypeid As ObjectId In ltt ltypeids.Add(ltypeid) Next t.Commit() End Using Dim ltypeContinuousId As ObjectId = SymbolUtilityServices.GetLinetypeContinuousId(db) Dim ltypeByLayerId As ObjectId = SymbolUtilityServices.GetLinetypeByLayerId(db) Dim ltypeByBlockId As ObjectId = SymbolUtilityServices.GetLinetypeByBlockId(db) If ltypeids.Contains(ltypeContinuousId) Then ltypeids.Remove(ltypeContinuousId) If ltypeids.Contains(ltypeByLayerId) Then ltypeids.Remove(ltypeByLayerId) If ltypeids.Contains(ltypeByBlockId) Then ltypeids.Remove(ltypeByBlockId) ed.WriteMessage("Checking whether {0} linetypes can be purged" & Environment.NewLine, ltypeids.Count) db.Purge(ltypeids) ed.WriteMessage("{0} linetypes can be purged" & Environment.NewLine, ltypeids.Count) Using t As Transaction = db.TransactionManager.StartTransaction For Each ltypeid As ObjectId In ltypeids Dim ltype As DBObject = t.GetObject(ltypeid, OpenMode.ForWrite) ltype.Erase() Next t.Commit() End Using End Sub
That was part of the education - the reclaim memory statement. I found that in Keans blog. It is good to know for future reference. My process runs in a batch - open in the editor, modify, save and close a list of files. That adds up to a manual "reclaim", so I am not using it either. I have never used the "symbolutilityservices" namespace, so that is good to know as well.
Deleting the un-used and un-wanted linetype ids makes perfect sense, along with the db.purge to make sure the linetypes are not referenced in a dimension style or something.
Hey, just wondering if anyone knows what language " Public Sub purgelinetypes() " is written in. It has been years since I have done any ARX programming and need to know if it is J# or C so I can compile it. Thanks