Creating a table of block attributes in AutoCAD using .NET
Imports System
Imports System.Collections.Specialized
Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.Geometry
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.ApplicationServices
Namespace TableCreation
    Public Class Commands
        ' Set up some formatting constants
        ' for the table
        Const colWidth As Double = 1500
        Const rowHeight As Double = 300
        Const textHeight As Double = 100
        Const cellAlign As CellAlignment = CellAlignment.MiddleCenter
        ' Helper function to set text height
        ' and alignment of specific cells,
        ' as well as inserting the text
        Public Shared Sub SetCellText(ByVal tb As Autodesk.AutoCAD.DatabaseServices.Table, ByVal row As Long, ByVal col As Long, ByVal value As String)
            tb.Cells(row, col).Alignment = cellAlign
            tb.Cells(row, col).TextHeight = textHeight
            tb.Cells(row, col).TextString = value
            'tb.SetAlignment(row, col, cellAlign)
            'tb.SetTextHeight(row, col, textHeight)
            'tb.SetTextString(row, col, value)
        End Sub
        <CommandMethod("BAT")> _
        Public Shared Sub BlockAttributeTable()
            Dim doc As Document = Application.DocumentManager.MdiActiveDocument
            Dim db As Database = doc.Database
            Dim ed As Editor = doc.Editor
            ' Ask for the name of the block to find
            Dim opt As New PromptStringOptions(vbLf & "Enter name of block to list: ")
            Dim pr As PromptResult = ed.GetString(opt)
            If pr.Status = PromptStatus.OK Then
                Dim blockToFind As String = pr.StringResult.ToUpper()
                Dim embed As Boolean = False
                ' Ask whether to embed or link the data
                Dim pko As New PromptKeywordOptions(vbLf & "Embed or link the attribute values: ")
                pko.AllowNone = True
                pko.Keywords.Add("Embed")
                pko.Keywords.Add("Link")
                pko.Keywords.[Default] = "Embed"
                Dim pkr As PromptResult = ed.GetKeywords(pko)
                If pkr.Status = PromptStatus.None OrElse pkr.Status = PromptStatus.OK Then
                    If pkr.Status = PromptStatus.None OrElse pkr.StringResult = "Embed" Then
                        embed = True
                    Else
                        embed = False
                    End If
                End If
                Dim tr As Transaction = doc.TransactionManager.StartTransaction()
                Using tr
                    ' Let's check the block exists
                    Dim bt As BlockTable = CType(tr.GetObject(doc.Database.BlockTableId, OpenMode.ForRead), BlockTable)
                    If Not bt.Has(blockToFind) Then
                        ed.WriteMessage(vbLf & "Block " + blockToFind + " does not exist.")
                    Else
                        ' And go through looking for
                        ' attribute definitions
                        Dim colNames As New StringCollection()
                        Dim bd As BlockTableRecord = CType(tr.GetObject(bt(blockToFind), OpenMode.ForRead), BlockTableRecord)
                        For Each adId As ObjectId In bd
                            Dim adObj As DBObject = tr.GetObject(adId, OpenMode.ForRead)
                            ' For each attribute definition we find...
                            Dim ad As AttributeDefinition = TryCast(adObj, AttributeDefinition)
                            If ad IsNot Nothing Then
                                ' ... we add its name to the list
                                colNames.Add(ad.Tag)
                            End If
                        Next
                        If colNames.Count = 0 Then
                            ed.WriteMessage(vbLf & "The block " + blockToFind + " contains no attribute definitions.")
                        Else
                            ' Ask the user for the insertion point
                            ' and then create the table
                            Dim ppr As PromptPointResult = ed.GetPoint(vbLf & "Enter table insertion point: ")
                            If ppr.Status = PromptStatus.OK Then
                                Dim tb As New Table()
                                tb.TableStyle = db.Tablestyle
                                'tb.NumRows = 1
                                'tb.NumColumns = colNames.Count
                                tb.SetSize(1, colNames.Count)
                                tb.SetRowHeight(rowHeight)
                                tb.SetColumnWidth(colWidth)
                                tb.Position = ppr.Value
                                ' Let's add our column headings
                                Dim i As Integer = 0
                                While i < colNames.Count
                                    SetCellText(tb, 0, i, colNames(i))
                                    i += 1
                                End While
                                ' Now let's search for instances of
                                ' our block in the modelspace
                                Dim ms As BlockTableRecord = CType(tr.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForRead), BlockTableRecord)
                                Dim rowNum As Integer = 1
                                For Each objId As ObjectId In ms
                                    Dim obj As DBObject = tr.GetObject(objId, OpenMode.ForRead)
                                    Dim br As BlockReference = TryCast(obj, BlockReference)
                                    If br IsNot Nothing Then
                                        Dim btr As BlockTableRecord = CType(tr.GetObject(br.BlockTableRecord, OpenMode.ForRead), BlockTableRecord)
                                        Using btr
                                            If btr.Name.ToUpper() = blockToFind Then
                                                ' We have found one of our blocks,
                                                ' so add a row for it in the table
                                                tb.InsertRows(rowNum, rowHeight, 1)
                                                ' Assume that the attribute refs
                                                ' follow the same order as the
                                                ' attribute defs in the block
                                                Dim attNum As Integer = 0
                                                For Each arId As ObjectId In br.AttributeCollection
                                                    Dim arObj As DBObject = tr.GetObject(arId, OpenMode.ForRead)
                                                    Dim ar As AttributeReference = TryCast(arObj, AttributeReference)
                                                    If ar IsNot Nothing Then
                                                        ' Embed or link the values
                                                        Dim strCell As String
                                                        If embed Then
                                                            strCell = ar.TextString
                                                        Else
                                                            Dim strArId As String = arId.ToString()
                                                            strArId = strArId.Trim(New Char() {"("c, ")"c})
                                                            strCell = "%<\AcObjProp Object(" + "%<\_ObjId " + strArId + ">%).TextString>%"
                                                        End If
                                                        SetCellText(tb, rowNum, attNum, strCell)
                                                    End If
                                                    attNum += 1
                                                Next
                                                rowNum += 1
                                            End If
                                        End Using
                                    End If
                                Next
                                tb.GenerateLayout()
                                ms.UpgradeOpen()
                                ms.AppendEntity(tb)
                                tr.AddNewlyCreatedDBObject(tb, True)
                                tr.Commit()
                            End If
                        End If
                    End If
                End Using
            End If
        End Sub
    End Class
End Namespace
[本日志由 tiancao1001 于 2019-06-29 06:32 PM 编辑]
      暂时没有评论