yosso 发表于 2014-2-16 00:00:54

动态块和有效名称...

AUGI论坛上有一个电子表格工具,它将打开一个图形文件夹,并从图形中提取块,并用属性填充excel工作表。 如果你没有动态块,效果很好。
秘诀与块的“有效名称”有关,但我很难理解如何获取块的有效名称。
以下是代码摘录:
For Each MyBlock In MyDbx.Blocks
                If MyBlock.IsDynamicBlock Then
                  If UCase(MyBlock.EffectiveName) = UCase(Range("BlkName").Value) Then
                        BlkExist = True
                        Exit For
                  End If
                End If
                If UCase(MyBlock.Name) = UCase(Range("BlkName").Value) Then
                  BlkExist = True
                  Exit For
                End If
Next MyBlock

这是错误号和描述:
任何帮助将不胜感激。
**** Hidden Message *****

n.yuan 发表于 2014-2-19 10:10:42

没有看到更多相关的代码,我不能说我理解你显示的代码的确切目的。
但是,错误消息是预期的:
“对于每个...”循环遍历图形的块定义,以查看图形中是否存在块定义。
因此,MyBlock 声明为 AcadBlock,而不是 AcadBlockreference,因此,MyBlock.EffectiveName 是错误的,并引发了异常。
块定义,无论是否是动态块,总是有一个名称,而块引用,如果是动态块引用,可以有一个“异常块”名称,因此,需要一个只读的“EffectiveName”来指示它从哪个动态块定义派生出来。
很明显,您在处理动态块时获得的工具存在错误。

yosso 发表于 2014-2-19 21:44:46

没错,这个工具对动态块有问题。
我非常感谢对有效名称的解释。
我正在尝试修改现有代码,但尚未成功,但正在取得进展(见下文)。
刚买了杰里·温特·VB.net的书,可能会尝试VB.net的方法。
下面是原始代码(它适用于非动态块)。
Sub GetBlockInfo()
    Dim DwgCnt As Integer
    Dim DwgName As String
    Dim StrPath As String
    Dim BlkExist As Boolean
    Dim intType(1) As Integer
    Dim varData(1) As Variant
    Dim BlkFound As Boolean
    Dim AttTitles As Boolean
    Dim ChkSht As Worksheet, DwgLstSht As Worksheet
   
    Dim MyDbx As AxDbDocument
    Dim MyLayouts As AcadLayouts
    Dim MyLayout As Variant
    Dim MyEnt As AcadEntity
    Dim MyBlock As AcadBlock
    Dim MyBlockR As AcadBlockReference
    Dim MyAtt As AcadAttributeReference
    Dim AttCt1, AttCt2 As Integer
    Dim Atts As Variant
    Dim MyBlkCount As Integer
   
    Set DwgLstSht = Sheets("DrawingList")
    Set ChkSht = Sheets("CheckList")
   
    GetFileNames
   
    ' Set up error control
    On Error GoTo Error_Control
   
    Init ' initialize global variables
   
    ' Get the Current Path
    StrPath = ThisWorkbook.Path
    If (Right(StrPath, 1)"\") Then
      StrPath = StrPath & "\"
    End If
   
    ' Unprotect sheet for drawing modifications
    DwgLstSht.Unprotect
    ChkSht.Unprotect
    ' Replace the Layout header since it was deleted when the attributes where cleared
    DwgLstSht.Cells(ROWOFF - 1, 2) = "Layout"
   
    ' Get the first drawing in the list and store in DwgName
    DwgCnt = 0
    AttTitles = False ' Set the Attribute Titles Flag to False (no titles yet)
    DwgName = DwgLstSht.Cells(DwgCnt + ROWOFF, 1)
   
    ' Call display status function
    temp = Status_Bar(True, "Activating ObjectDBX...")
    Set MyDbx = GetInterfaceObject("ObjectDBX.AxDbDocument.18")
   
    While DwgName""
      ' Call Display Status Function
      temp = Status_Bar(True, "Opening drawing " & DwgName)
      
      ' Open a drawing in ObjectDbx
      Set MyDbx = dbxOpen(StrPath, DwgName)
      
      ' If there are no errors and there is a file open
      If Err.Number = 0 And MyDbx.Name"" Then
            
            ' Determine if the chosen block is present in the drawing
            For Each MyBlock In MyDbx.Blocks
                If UCase(MyBlock.Name) = UCase(Range("BlkName").Value) Then
                  BlkExist = True
                  Exit For
                End If
            Next MyBlock
   
            ' If the block was found , then proceed
            If BlkExist Then
                BlkFound = False
               
                MyBlkCount = 0
                ' Iterate through all Layouts
                Set MyLayouts = MyDbx.Layouts
                For Each MyLayout In MyDbx.Layouts
                  ' Avoid Modelspace if the Check Modelspace checkbox is NOT checked
                  If Sheets("DrawingList").Model_Check.Value Or MyLayout.Name"Model" Then
                  ' Call display status function
                  temp = Status_Bar(True, "Searching " & DwgName & " Layout " & MyLayout.Name & " " & Range("BlkName").Value)
                  
                  ' Loop through each entity in the layout.block group
                  For Each MyEnt In MyLayout.Block
                        ' Check if the current Entity is a Block Reference
                        If TypeOf MyEnt Is AcadBlockReference Then
                            ' Check that the block name matches what we are looking for
                            If UCase(MyEnt.Name) = UCase(Range("BlkName").Value) Then
                              ' Store the current Entity as a Block Reference
                              Set MyBlockR = MyEnt
                              ' Make sure that the Block Reference has attributes
                              If MyBlockR.HasAttributes Then
                                    ' If we have already found a block in the current drawing, add another row
                                    If MyBlkCount > 0 Then
                                        DwgLstSht.Cells(DwgCnt + ROWOFF + 1, 1).EntireRow.Insert
                                        DwgCnt = DwgCnt + 1
                                        DwgLstSht.Cells(DwgCnt + ROWOFF, 1) = DwgName
                                        ChkSht.Cells(DwgCnt + ROWOFF, 1) = DwgName
                                    End If
                                    DwgLstSht.Cells(DwgCnt + ROWOFF, 2) = MyLayout.Name
                                    ChkSht.Cells(DwgCnt + ROWOFF, 2) = MyLayout.Name
                                    
                                    ' Store all attributes in the matrix Atts
                                    Atts = MyEnt.GetAttributes
                                    
                                    ' Step through each attribute in Atts
                                    For AttCt1 = LBound(Atts) To UBound(Atts)
                                        ' Get the next attribute
                                        Set MyAtt = Atts(AttCt1)
                                       
                                        ' Call Display Status Function
                                        temp = Status_Bar(True, "Accessing " & DwgName & " attributes: " & MyAtt.TagString & ".")
                                       
                                        ' Write the attribute information to DrawingList and CheckList sheets
                                        DwgLstSht.Cells(DwgCnt + ROWOFF, AttCt1 + COLOFF).NumberFormat = "@" 'C. White 27/09/11 added to ensure attribute is listed as a string in Excel
                                        DwgLstSht.Cells(DwgCnt + ROWOFF, AttCt1 + COLOFF) = MyAtt.TextString
                                        ChkSht.Cells(DwgCnt + ROWOFF, AttCt1 + COLOFF) = MyAtt.TextString
                                       
                                        ' If this is the first drawing, store the attribute tags in the header row
                                        If AttTitles = False Then
                                          DwgLstSht.Cells(ROWOFF - 1, AttCt1 + COLOFF) = MyAtt.TagString
                                          ChkSht.Cells(ROWOFF - 1, AttCt1 + COLOFF) = MyAtt.TagString
                                          If AttCt1 = UBound(Atts) Then
                                                AttTitles = True
                                          End If
                                        End If
                                    Next AttCt1
                                    MyBlkCount = MyBlkCount + 1
                              End If
                              Exit For
                            End If
                        End If
                  Next
               End If
                Next
            End If
            ' Clean the mydbx variable
            Set MyDbx = Nothing
      ElseIf Err.Number = 0 And MyDbx.Name = "" Then
            ' Turn off the Status bar
            temp = Status_Bar(False)
            Exit Sub
      End If
      
      ' Clean up Variables
      Set MyBlock = Nothing
      Set MyBlockR = Nothing
      Set MyAtt = Nothing
      
      DwgCnt = DwgCnt + 1
      DwgName = Cells(DwgCnt + ROWOFF, 1)
    Wend
Error_Control:
    If Err.Number0 Then
      Set MyBlock = Nothing
      Set MyAtt = Nothing
      If Err.Number = 13 Then
            MsgBox "Failed to initiate ObjectDbx, probably due to another version of Autocad...", vbCritical, "ObjectDBX Fail"
      Else
            MsgBox "Error #" & Err.Number & vbCr & Err.Description
      End If
    End If
   
   
    If Not MyDbx Is Nothing Then Set MyDbx = Nothing
    ' Adjust column widths to match the data in the cells
    DwgLstSht.Activate
    DwgLstSht.Columns.AutoFit
    DwgLstSht.Cells(4, 2) = Now
    DwgLstSht.Range("A6").Select
    ' Protect sheet
    DwgLstSht.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True
    ChkSht.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True
   
    ' Turn off the Status bar
    temp = Status_Bar(False)
End Sub

谢谢你的鼓励。
M

yosso 发表于 2014-2-20 07:16:35

在取得进展的同时,它能够找到并提取动态块及其属性,只需对原始VBA代码进行一些修改
下一步是提取图形中块实例的动态特性和句柄
M.
页: [1]
查看完整版本: 动态块和有效名称...