walton10 Posted January 10, 2011 Share Posted January 10, 2011 Hello, I am beginning to write in VB.NET now, using Visual Basic 2010 Express. My current knowledge base is basic or intermediate LISP knowledge. For my first project in .NET I am trying to write a command that will delete all blocks matching a certain block name. My current hang up is that I do not know how to tell .NET to find out what the name of a block is so that it can check it against my user-input name. Imports Autodesk.AutoCAD.Runtime Imports Autodesk.AutoCAD.ApplicationServices Imports Autodesk.AutoCAD.DatabaseServices Imports Autodesk.AutoCAD.EditorInput 'required for GetString Public Class DeleteBlock Private acDoc As Document = Application.DocumentManager.MdiActiveDocument Private acCurDb As Database = acDoc.Database Private blkDefs As ObjectIdCollection = New ObjectIdCollection() Private blkRefs As ObjectIdCollection = New ObjectIdCollection() <CommandMethod("DeleteBlock")> Public Sub RemoveMyBlock() Dim myBlockName As String myBlockName = GetString("Block Name to Delete") '' Get the current document and database, and start a transaction Using acTransaction As Transaction = acCurDb.TransactionManager.StartTransaction() '' Open the Block table record for read Dim acBlockTable As BlockTable acBlockTable = acTransaction.GetObject(acCurDb.BlockTableId, OpenMode.ForRead) If (acBlockTable.Has(myBlockName)) Then ' '' Collect information about the block ' '' 1. the block definition ' Dim blkID As ObjectId = acBlockTable(myBlockName) ' blkDefs.Add(blkID) ' Dim acBlockTableRecord As BlockTableRecord ' acBlockTableRecord = acTransaction.GetObject(blkID, OpenMode.ForRead) ' '' 2. the block's contents ' '' ignoring for my work, see http://through-the-interface.typepad.com/through_the_interface/2008/08/preventing-an-a.html ' '' 3. the block's references ' Dim TMPblkRefs As ObjectIdCollection = acBlockTableRecord.GetBlockReferenceIds(True, True) ' For Each Id As ObjectId In TMPblkRefs ' blkRefs.Add(Id) ' Next 'End If 'acTransaction.Commit() '' Open the Block table record Model space for read Dim acBlockTableRec As BlockTableRecord acBlockTableRec = acTransaction.GetObject(acBlockTable(BlockTableRecord.ModelSpace), OpenMode.ForWrite) Dim nCnt As Integer = 0 '' Step through each object in Model space and '' display the type of object found For Each acObjId As ObjectId In acBlockTableRec If ("INSERT" = acObjId.ObjectClass().DxfName) Then ''' I don't know what goes here... If (myBlockName = acObjId.GETEFFECTIVENAME) Then ''' also, I apparantly don't know how to actually ERASE the object... Try Erase (acObjId) Catch ex As Exception End Try End If End If nCnt = nCnt + 1 Next '' If no objects are found then display the following message If nCnt = 0 Then acDoc.Editor.WriteMessage(vbLf & " No objects found") End If End If ' Dispose of the transaction acTransaction.Commit() End Using End Sub Private Function GetString(ByVal pPrompt As String) As String Dim pStrOpts As PromptStringOptions = New PromptStringOptions(vbLf & pPrompt & ": ") pStrOpts.AllowSpaces = True Dim pStrRes As PromptResult = acDoc.Editor.GetString(pStrOpts) 'Application.ShowAlertDialog("The name entered was: " & pStrRes.StringResult) Return pStrRes.StringResult() End Function End Class Thank you for your help. Quote Link to comment Share on other sites More sharing options...
BlackBox Posted January 10, 2011 Share Posted January 10, 2011 Look into the EffectiveName property, for a given Block Object. Hope this helps! Quote Link to comment Share on other sites More sharing options...
SEANT Posted January 10, 2011 Share Posted January 10, 2011 Here’s a method based on your existing process. Another option may be to create a filtered Selection Set to reduce the iterations in the .NET code. I did modify the structure a bit to avoid objects held beyond the scope of the routine. It's probably not critical, just my preference. <CommandMethod("DeleteBlock")> _ Public Sub RemoveMyBlock() Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument 'moved these within the routine Dim acCurDb As Database = acDoc.Database Dim blkDefs As ObjectIdCollection = New ObjectIdCollection() Dim blkRefs As ObjectIdCollection = New ObjectIdCollection() Dim myBlockName As String myBlockName = GetString("Block Name to Delete", acDoc) '' Get the current document and database, and start a transaction Using acTransaction As Transaction = acCurDb.TransactionManager.StartTransaction() '' Open the Block table record for read Dim acBlockTable As BlockTable acBlockTable = acTransaction.GetObject(acCurDb.BlockTableId, OpenMode.ForRead) If (acBlockTable.Has(myBlockName)) Then Dim acBlockTableRec As BlockTableRecord acBlockTableRec = acTransaction.GetObject(acBlockTable(BlockTableRecord.ModelSpace), OpenMode.ForWrite) Dim nCnt As Integer = 0 '' Step through each object in Model space and '' display the type of object found For Each acObjId As ObjectId In acBlockTableRec If ("INSERT" = acObjId.ObjectClass().DxfName) Then Dim entInsert As BlockReference = DirectCast(acTransaction.GetObject(acObjId, OpenMode.ForWrite), BlockReference) If (myBlockName = entInsert.Name) Then entInsert.Erase() End If nCnt = nCnt + 1 Next '' If no objects are found then display the following message If nCnt = 0 Then acDoc.Editor.WriteMessage(vbLf & " No objects found") End If End If ' Dispose of the transaction acTransaction.Commit() End Using End Sub Private Function GetString(ByVal pPrompt As String, ByRef acDoc As Document) As String Dim pStrOpts As PromptStringOptions = New PromptStringOptions(vbLf & pPrompt & ": ") pStrOpts.AllowSpaces = True Dim pStrRes As PromptResult = acDoc.Editor.GetString(pStrOpts) 'Application.ShowAlertDialog("The name entered was: " & pStrRes.StringResult) Return pStrRes.StringResult() End Function Quote Link to comment Share on other sites More sharing options...
walton10 Posted January 10, 2011 Author Share Posted January 10, 2011 Thank you very much. Being this new, I didn't know about the DirectCast method. I will have to look into it and learn more. If you have any links to articles or examples of it's use that you could share, I would be grateful. Quote Link to comment Share on other sites More sharing options...
SEANT Posted January 11, 2011 Share Posted January 11, 2011 Here are two of the basics for .NET programming with AutoCAD http://msdn.microsoft.com/en-us/vbasic/bb466159 http://docs.autodesk.com/ACD/2010/ENU/AutoCAD%20.NET%20Developer's%20Guide/index.html Additionally, this blog is excellent: http://through-the-interface.typepad.com/through_the_interface/ Quote Link to comment Share on other sites More sharing options...
fixo Posted January 11, 2011 Share Posted January 11, 2011 Hi SeanT, Sorry for off-top In my routine at the moment I've used the following code block instead: [size=1][font=Consolas][color=#0000ff][font=Consolas][color=#0000ff][font=Consolas][color=#0000ff]If[/color][/font][/color][/font][/color][/font][font=Consolas][font=Consolas] (myBlockName = EffectiveName(entInsert)) [/font][/font][font=Consolas][color=#0000ff][font=Consolas][color=#0000ff][font=Consolas][color=#0000ff]Then[/color][/font][/color][/font][/color][/font][font=Consolas][font=Consolas] entInsert.Erase()[/font][/font][/size] [size=1][font=Consolas][font=Consolas]End If[/font][/font][/size] ......................... Assuming the next function is follows: Public Shared Function EffectiveName(ByVal blkref As BlockReference) As String If blkref.IsDynamicBlock Then Using obj As BlockTableRecord = DirectCast(blkref.DynamicBlockTableRecord.GetObject(OpenMode.ForRead), BlockTableRecord) Return obj.Name End Using End If Return blkref.Name End Function But by any reason it's not woking with dynamic blocks as well, say I can delete just 4 blockreferences from 20 (thee are NUS blocks btw) How to solve it? ~'J'~ Quote Link to comment Share on other sites More sharing options...
walton10 Posted January 11, 2011 Author Share Posted January 11, 2011 This is actually quite on topic. It's exactly the functionality I am trying to build, and exactly the problem that I run into. I do not know how to get it to reliably delete dynamic blocks, especially once any of their dynamic properties have been changed. I know how to do it in LISP, but my goal here is to start learning this newer, more powerful language. Quote Link to comment Share on other sites More sharing options...
fixo Posted January 11, 2011 Share Posted January 11, 2011 This driving me mad as well, Walton (I use A2009 eng) Quote Link to comment Share on other sites More sharing options...
Jeff H Posted January 12, 2011 Share Posted January 12, 2011 When you change the properties of a dynamic block it creates an anonymous block. This is a simple example to delete the block references and delete the block references of the anonymous blocks created by the dynamic block. Is hard-coded for a block named "C" <[color=#2b91af]CommandMethod[/color]([color=#a31515]"DeleteAllBlockReference"[/color])> _ [color=blue]Public[/color] [color=blue]Sub[/color] DeleteAllBlockReference() [color=blue]Dim[/color] doc [color=blue]As[/color] [color=#2b91af]Document[/color] = [color=#2b91af]Application[/color].DocumentManager.MdiActiveDocument [color=blue]Dim[/color] db [color=blue]As[/color] [color=#2b91af]Database[/color] = doc.Database [color=blue]Using[/color] trx [color=blue]As[/color] [color=#2b91af]Transaction[/color] = db.TransactionManager.StartTransaction() [color=blue]Dim[/color] bt [color=blue]As[/color] [color=#2b91af]BlockTable[/color] = db.BlockTableId.GetObject([color=#2b91af]OpenMode[/color].ForRead) [color=blue]Dim[/color] btr [color=blue]As[/color] [color=#2b91af]BlockTableRecord[/color] = bt([color=#a31515]"C"[/color]).GetObject([color=#2b91af]OpenMode[/color].ForRead) [color=blue]For[/color] [color=blue]Each[/color] objId [color=blue]As[/color] [color=#2b91af]ObjectId[/color] [color=blue]In[/color] btr.GetBlockReferenceIds([color=blue]True[/color], [color=blue]True[/color]) [color=blue]Dim[/color] ent [color=blue]As[/color] [color=#2b91af]Entity[/color] = objId.GetObject([color=#2b91af]OpenMode[/color].ForWrite) ent.Erase() [color=blue]Next[/color] [color=blue]Dim[/color] anonBlkIds [color=blue]As[/color] [color=#2b91af]ObjectIdCollection[/color] = btr.GetAnonymousBlockIds [color=blue]For[/color] [color=blue]Each[/color] btrObjId [color=blue]As[/color] [color=#2b91af]ObjectId[/color] [color=blue]In[/color] anonBlkIds [color=blue]Dim[/color] anonBtr [color=blue]As[/color] [color=#2b91af]BlockTableRecord[/color] = btrObjId.GetObject([color=#2b91af]OpenMode[/color].ForRead) [color=blue]For[/color] [color=blue]Each[/color] objId [color=blue]As[/color] [color=#2b91af]ObjectId[/color] [color=blue]In[/color] anonBtr.GetBlockReferenceIds([color=blue]True[/color], [color=blue]True[/color]) [color=blue]Dim[/color] ent [color=blue]As[/color] [color=#2b91af]Entity[/color] = objId.GetObject([color=#2b91af]OpenMode[/color].ForWrite) ent.Erase() [color=blue]Next[/color] [color=blue]Next[/color] trx.Commit() [color=blue]End[/color] [color=blue]Using[/color] [color=blue]End[/color] [color=blue]Sub[/color] Quote Link to comment Share on other sites More sharing options...
Jeff H Posted January 12, 2011 Share Posted January 12, 2011 Look at this link for pics that might help http://www.theswamp.org/index.php?topic=36618.new#new Quote Link to comment Share on other sites More sharing options...
SEANT Posted January 12, 2011 Share Posted January 12, 2011 Hey guys, I saw the questions about Dynamic Blocks last night and planned on investigating it this morning. I see that the investigation will be pretty easy now. Thanks Jeff. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.