Jump to content

[.NET] Getting a block name


walton10

Recommended Posts

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.

Link to comment
Share on other sites

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


Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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'~

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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]

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...