Accessing block references in different layouts via ODBX in VBA

Accessing block references in different layouts via ODBX in VBA

ragarcia
Enthusiast Enthusiast
3,613 Views
5 Replies
Message 1 of 6

Accessing block references in different layouts via ODBX in VBA

ragarcia
Enthusiast
Enthusiast

Well, I'm working with ODBX for the first time and there's a lot of thing I do from Autocad I dont't know are feasible via ODBX. I need to edit block references in different layouts. The PaperSpace propertie can be used to acces the active paperspace object collection, but I wonder if there's a way to acces the block references in other layouts. I've tried changing the ActiveLayout property but ODBX doesn't allow edition for this property. Have you any ideas to access block references in different layers without opening the file in Autocad?

0 Likes
Accepted solutions (1)
3,614 Views
5 Replies
Replies (5)
Message 2 of 6

ragarcia
Enthusiast
Enthusiast

Edit: I meant "layout", not "layer" in the last line of the topic.

0 Likes
Message 3 of 6

norman.yuan
Mentor
Mentor

If you know where the entities on each layout are contained, it would be very easy to access them: each layout has a PaperSpace block as entity container that holds entities for the layout. You only need to look at AcadLayout.Block property. Here is sample code that loop through entities on each layout (except for "Model", and count AcadBlockReference:

 

Option Explicit

Public Sub Test()
    
    Dim doc As AXDBLib.AxDbDocument
    Set doc = New AXDBLib.AxDbDocument
    doc.Open "C:\Temp\Test.dwg"
    
    Dim lay As AXDBLib.AcadLayout
    Dim blkCount As Integer
    For Each lay In doc.Layouts
        If UCase(lay.Name) <> "MODEL" Then
            blkCount = FindBlockReferencesOnLayout(lay)
            MsgBox "Layout: " & lay.Name & vbCrLf & "Block Reference Count: " & blkCount
        End If
    Next
    
    Set doc = Nothing
End Sub

Private Function FindBlockReferencesOnLayout(lay As AXDBLib.AcadLayout) As Integer
    Dim count As Integer
    Dim ent As AXDBLib.AcadEntity
    For Each ent In lay.Block
        If TypeOf ent Is AXDBLib.AcadBlockReference Then
            count = count + 1
        End If
    Next
    FindBlockReferencesOnLayout = count
End Function

As you can see the code is really simple.

 

HTH

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 4 of 6

ragarcia
Enthusiast
Enthusiast

Thanks for the help. But it works only to count block references in each layout. What I need is to be able to edit attributes in block references in different layers. Since I cannot change the active layout via ODBX, the paperspace collection only contains objects in the active layout when the drawing was saved. I can access any block reference using the block property of the layout, but I cannot read its attributes with GetAttributes method. Every time I try to use GetAttributes on a block reference, it returns the attributes of the block reference instance located in the active layout. I'm doing this (ommiting the variable declarations):

 

 

Set objDbx = GetInterfaceObject("ObjectDBX.AxDbDocument.20")
objDbx.Open "C:\Temp\Test.dwg"
For Each lay In objDbx.Layouts
    If lay.Name <> "Model" Then
        For Each elem In lay.Block
            If elem.ObjectName = "AcDbBlockReference" Then
                If elem.HasAttributes Then
                    a = elem.GetAttributes
		    'Here I read attributes scanning the a array
                End If
            End If
        Next
    End If
Next
Set objDbx = Nothing




In my sample drawing I have 8 layouts, each one with a block with an attribute called "page". In layout 1 it holds "1", in layout 2 it holds "2" and so on. But when I read the "a" array, it always returns "8", the value matching the layout 8 that is the last active layout when the file was saved. Maybe ODBX cannot handle this method; maybe I am doing something wrong. Have you any idea of what could be happening? Can I provide more information?

0 Likes
Message 5 of 6

norman.yuan
Mentor
Mentor

Well if you do  not show your code of how you scan the attributes in block reference, no one can tell what is wrong. Here is code runs against a drawing with 2 layouts, on each layout there are 2 block references of the same block definition with 2 attributes. so, there are 4 block references inserted in the drawing will all attributes having different values. See the code and the video below. It works as expected. 

 

Option Explicit

Public Sub DBXTest()

    Dim doc As AxDbDocument
    Dim lay As AXDBLib.AcadLayout
    
    Set doc = New AXDBLib.AxDbDocument
    doc.Open "C:\Temp\Test.dwg"
    
    For Each lay In doc.Layouts
        
        GetBlockAttributeData lay
        
    Next
    
    Set doc = Nothing
    
End Sub

Private Sub GetBlockAttributeData(lay As AXDBLib.AcadLayout)
    
    Dim ent As AXDBLib.AcadEntity
    Dim blk As AXDBLib.AcadBlockReference
    Dim i As Integer
    Dim atts As Variant
    Dim att As AXDBLib.AcadAttributeReference
    
    Dim msg As String
    
    For Each ent In lay.Block
        If TypeOf ent Is AXDBLib.AcadBlockReference Then
            Set blk = ent
            If blk.HasAttributes Then
                msg = "Layout Name: " & lay.Name & vbCrLf
                msg = msg & "Block Name: " & blk.EffectiveName & vbCrLf
                atts = blk.GetAttributes()
                For i = 0 To UBound(atts)
                    Set att = atts(i)
                    msg = msg & "ATT TAG: " & att.TagString & vbTab & _
                    "ATT VALUE: " & att.TextString & vbCrLf
                Next
                MsgBox msg
            End If
        End If
    Next
    
End Sub

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 6 of 6

ragarcia
Enthusiast
Enthusiast
Accepted solution

Thanks a lot for your answer. But what do you mean I'm not showing my code? I did show it right above your message! LOL I just read the attribute array from the debugger to check it's content, no need to do something with it.

 

What you did is exactly what I was doing: search for block references in the layout block collection for each layout. My mistake: I must apologize, I didn't realize the attribute I was reading has a reference to the name of the active layout. That's the reason I always retrieve the same content for the attribute in each layout since opening a drawing using ODBX makes you unable to change the active one. I replaced the attribute with a constant value and it worked like a champ. I'm working from excel, not autocad and giving a try to your code runing from autocad gave me a hint somehow. This issue is now dismissed.

 

Greetings.

 

0 Likes