07 July 2008

Finding all title blocks on all layouts

I recently came across a pretty common problem where I needed to find all of the title block entities on each layout in the active drawing. The solution lies in the database layout dictionary as can be seen below. Special consideration needs to be taken if you're working with dynamic blocks. If you don't check if the block is dynamic, you're only getting the anonymous block, not the true dynamic block reference.

  <CommandMethod("CollectTblocks")> _

  Public Sub CollectTblocks()

    ' Get the current document database and active drawing

    Dim oDb As Database = HostApplicationServices.WorkingDatabase

    Dim oDwg As Autodesk.AutoCAD.ApplicationServices.Document = Application.DocumentManager.MdiActiveDocument

 

    ' Start a transaction

    Dim oTrans As Transaction = oDb.TransactionManager.StartTransaction

 

    ' Get the current layout id and layout name

    Dim curLayoutID As ObjectId = LayoutManager.Current.GetLayoutId(LayoutManager.Current.CurrentLayout)

    Dim curLayout As Layout = CType(curLayoutID.GetObject(OpenMode.ForRead), Layout)

 

    ' Create an arraylist to store our layout entity ids in

    Dim oTblocks As New ArrayList

 

    Try

      ' Lock the drawing

      Using locked As Autodesk.AutoCAD.ApplicationServices.DocumentLock = oDwg.LockDocument()

        ' Get the drawings layout dictionary

        Dim layoutDict As DBDictionary = CType(oTrans.GetObject(oDb.LayoutDictionaryId, _

                                                                OpenMode.ForRead), DBDictionary)

        Dim indexTb As Integer = 1

 

        For Each id As DictionaryEntry In layoutDict

          ' Get the layout object

          Dim oLayout As Layout = CType(oTrans.GetObject(CType(id.Value, ObjectId), _

                                                        OpenMode.ForRead), Layout)

 

          Dim oBtr As BlockTableRecord = CType(oTrans.GetObject(oLayout.BlockTableRecordId, _

                                                                OpenMode.ForRead), BlockTableRecord)

          If oBtr.IsLayout = True Then

            ' Get the enumerator

            Dim oBtre As BlockTableRecordEnumerator = oBtr.GetEnumerator

 

            ' Loop through all blocks in the block table

            While oBtre.MoveNext

              Dim oEnt As Entity = CType(oTrans.GetObject(oBtre.Current, _

                                                          OpenMode.ForRead), Entity)

 

              If TypeOf oEnt Is BlockReference Then

                ' Change the entity to a block reference

                Dim oBr As BlockReference = CType(oEnt, BlockReference)

 

                If oBr.IsDynamicBlock Then

                  ' Get the object id of the dynamic block's parent

                  Dim oDoId As ObjectId = oBr.DynamicBlockTableRecord

                  ' Get the block table record

                  Dim oDBtr As BlockTableRecord = CType(oTrans.GetObject(oDoId, _

                                                                        OpenMode.ForRead), BlockTableRecord)

 

                  ' Store the block reference id if the name matches

                  If oDBtr.Name.Equals("TITLEBLOCK") Then oTblocks.Add(oBtr.ObjectId)

                Else

                  ' Store the block reference id if the name matches

                  If oBr.Name.Equals("TITLEBLOCK") Then oTblocks.Add(oBtr.ObjectId)

                End If

              End If

            End While

          End If

        Next

      End Using

 

      ' Write a message stating how many title blocks were found

      Dim oEd As Editor = oDwg.Editor

      oEd.WriteMessage(oTblocks.Count.ToString & " title blocks were found in the drawing.")

 

      ' Close the transaction, aborting is faster than committing

      oTrans.Abort()

    Catch ex As System.Exception

      MsgBox(ex.Message, MsgBoxStyle.Information, "Error in CollectTblocks")

    Finally

      ' Clean up

      oTrans.Dispose()

    End Try

  End Sub


So what does it do? In a nutshell, the routine above loops through each layout in the active drawing and looks for block references. If it finds a block reference it checks to see if the block is dynamic and then checks to see if the block name matches "TITLEBLOCK". If it finds a match, it stores the block reference object id in the array list.

No comments:

Disclaimer

All materials on this site are provided "as is" and without any warranty. Any express or implied warranties, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed. In no event shall the authors be liable to any party for any direct, indirect, incidental, special, exemplary, or consequential damages arising in any way out of the use or misuse of this site.