• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 6661
  • Last Modified:

Automating AutoCAD - get block attributes objectdbx method...

I am trying to read block attributes out of autocad with the objectdbx method.  I've it working successfully to a point.. in my code below, I'm connected to AutoCAD, I've opened the drawing, and I'm reading the blocks.

It's reading the blocks and putting them in the datagridview, but where there are two of a block in the file, it's only picking up one of them.  

Also, how can I can get custom Attributes of the block?
Dim Block As AXAUTO15Lib.AcadBlock
            For Each Block In V_AutoCadInterfaceObject.Blocks
                If Block.Name.ToString = "START" Then
 
                    DataGridView1.Rows.Add()
                    DataGridView1.Rows(CurrentDataGridView1Row).Cells(0).Value = Block.Name.ToString
                    CurrentDataGridView1Row = CurrentDataGridView1Row + 1
 
                End If
 
            Next Block

Open in new window

0
LittleOleMeDesigns
Asked:
LittleOleMeDesigns
  • 8
  • 3
  • 2
2 Solutions
 
borgunitCommented:
I pulled this one out of my archives. It should get the block atts into a variant array. You will need to massage this a bit to update for .net
Private Function QueryBlkAttsInDwgMspace(ByVal sDwgFile As String, _
ByVal sBlkName As String) As Variant
'------------------------------------------------------------------------------
'QueryBlkAttsInDrawing:
'------------------------------------------------------------------------------
Dim dwgFile As String
Dim layer As AcadLayer
Dim acItem As AcadObject
Dim AcBlk As AcadBlockReference
Dim vAtts As Variant
Dim acAtt As AcadObject
Dim intCnt As Integer
Dim arrColumn()
'''''''''''''''''''''''''''''''''''''''
If sDwgFile <> "" Then
    'Set mobjdbx = AcadApplication.GetInterfaceObject("ObjectDBX.AxDbDocument")
    mObjDbx.Open sDwgFile
 
    If Err.Number <> 0 Then
        If Err.Number <> -2147467259 Then 'Invalid filename
            regObjectDBX
            mObjDbx.Open sDwgFile
        End If
    End If
 
    '--------------------------------------------------------------------------
    ' Check through the blocks in the drawing
    '--------------------------------------------------------------------------
    For Each acItem In mObjDbx.ModelSpace
        '----------------------------------------------------------------------
        ' If we find a block, check its name against the list of Grob titleblks
        '----------------------------------------------------------------------
        If TypeName(acItem) = "IAcadBlockReference" Then
            Set AcBlk = acItem
            '------------------------------------------------------------------
            ' If we find a match to the block name
            '------------------------------------------------------------------
            If AcBlk.name = sBlkName Then
                vAtts = AcBlk.GetAttributes
                QueryBlkAttsInDwgMspace = vAtts
                Exit Function
            End If
        End If
    Next acItem
End If
 
End Function

Open in new window

0
 
LittleOleMeDesignsAuthor Commented:
Maybe I'm just not awake yet... but I can't make this work.

I think I'm getting mixed up on defining the variables somewhere when I try to integrate what you've got into my program... but I haven't figured out where yet.  I'm going to keep trying though.  This looks like it should work if I can get my head around it enough to integrate into mine.

May be that I'm missing something on defining the variables when I convert it to .NET too... I know vb6 Variant has to be Object, and because of something of with AutoCAD in some cases, Integer has to be Int16, but I don't know of anything else that should need converted.

I'll keep playing with it and see what I can do though, I'm going to leave this question open for now just in case I get completely stuck.  Thank-You for your help.
0
 
darrenmcwiCommented:
I've not gotten deep into .Net yet from Lisp and VB but from whst I saw in your code, it looks like you're querying the Block table for the blocks. The Block table contains the block definitions which would only have 1 instance. The Block table is what get's purged when the block in the table is not used.

You'll want to look for INSERT objects in the drawing which are inserted instances of the block. That's also where you can then extract the attributes,
0
Prepare for your VMware VCP6-DCV exam.

Josh Coen and Jason Langer have prepared the latest edition of VCP study guide. Both authors have been working in the IT field for more than a decade, and both hold VMware certifications. This 163-page guide covers all 10 of the exam blueprint sections.

 
LittleOleMeDesignsAuthor Commented:
Is there any chance you could explain that in more detail... how to look for INSERT objects in the drawing?  I tried googling it, and I'm not finding a good example.
0
 
borgunitCommented:
Once you have a reference to the objectDBX drawing file and have opened it (this is what my snippet references as mObjDbx), you would next have to cycle through all the objects in modelspace (if that is where the blockreference is, otherwise cycle through the objects in layoutSpace). The snippet picks this up at line 29. It goes through each item in the space you are searching and "checks" what it is "TypeName(acItem)". If it is a blockReference then it checks its name to see if it matches the on you are looking for. If it does, the "get" its attributes and set them to a variable. The code does not go any  further than that. Once you have the attributes set, you would need to go through the attributes and "pull" what you want. I hope this is making sense.

    Darrenmcwi is referring to your original code where you show cycling through each block in the block table. This is not the same as a blockreference. A block in AutoCAD can refer to modelspace and its entities, layoutspace and its entities, and all block definitions in the drawing. Blocks can be defined in a drawing but do not have to exist in the drawing. The block table is the database (you might say) where the drawing stores all the data it might need. A blockreference is an instance of a certain block that has been "inserted" into the drawing (it is what we see in the drawing). This is what you need to query, not the block. You need to cycle through all the entites in the drawings modelspace until you come upon a blockreference, once you do you check its name and then as I said above, do with it as you like from there.
0
 
LittleOleMeDesignsAuthor Commented:
@borgunit:

Thank-You for the explanation.  That makes a bit more sense.  I think I'm getting closer.. but it's not returning anything.  When I step through the code, it never goes inside the loop that says:

If TypeOf objEnt is AutoCAD.AcadBlockReference Then.....

I also tried:

If TypeName(objEnt) = "IAcadBlockReference" Then...
            Dim strBlkName As String
            Dim strAttTag As String
            Dim objEnt As AutoCAD.AcadEntity
            Dim objBlkRef As AutoCAD.AcadBlockReference
            Dim varAtts As Object
            Dim objAtt As AutoCAD.AcadAttributeReference
            Dim objLayout As AutoCAD.AcadLayout
            Dim objBlock As AutoCAD.AcadBlock
            Dim I As Long
 
            strBlkName = "START"
            strAttTag = "FILENAME"
            For Each objLayout In V_AutoCad.ActiveDocument.Layouts
                If UCase(objLayout.Name) <> "MODEL" Then
                    objBlock = objLayout.Block
                    For Each objEnt In objBlock
                        If TypeOf objEnt Is AutoCAD.AcadBlockReference Then
                            'If TypeName(objEnt) = "IAcadBlockReference" Then
 
                            objBlkRef = objEnt
                            If objBlkRef.Name = strBlkName Then
                                varAtts = objBlkRef.GetAttributes
                                For I = 0 To UBound(varAtts)
                                    objAtt = (varAtts(I))
                                    If objAtt.TagString = strAttTag Then
                                        MsgBox(objAtt.TextString)
                                    End If
                                Next I
                            End If
                        End If
                    Next
                End If
            Next

Open in new window

0
 
darrenmcwiCommented:
Sorry, Borgunit explained it a little better. From LISP, you'll look for an INSERT entity type which is the data type returned in DXF format from Lisp. The BlockReference is thr same thing but in VB terminology.

It looks like you're trying to loop through the objects within the Layout block definition. Instead, you need to look through the object in the PaperSapce collection,. Look at BorgUnit's code and how it's iterating through the items in the ModelSpace collection. Modify that to go through the PaperSpace collection.

Take a peek at the developer guide, it shows the object model and it's structure which will givef you a better idea how to get to those items.

I'll see if I can't mod your code Monday back at the office if Borg doesn't already beat me to it.
0
 
LittleOleMeDesignsAuthor Commented:
@darrenmcwi:

I've been looking through the developer's guide.. and I can't seem to make heads or tails of how to do this.  Normally I don't have this much trouble grasping things... but it's like I've got "programmer's block" or something when it comes to this.

I'll keep hammering away at it and see if I can figure it out... I'll post back if I manage it.  If you could modify my code that would be wonderful!!  Maybe if I actually see what I'm doing made right then it'll sink out how to do it.

I've basically got about 10 blocks that I'm hunting for, and then I'm looking for specific attributes in those blocks.  For example:

Block Named "START" I need to get:
x insertion point
y insertion point
x scale
"SHEET"
"TITLE"

Block Named "t200" I need to get:
x insertion point
y insertion point
"PARTNO"

Block Named "FIELDPRINT" I need to get:
x insertion point
y insertion point

So maybe there is a much better way to do this that I'm not doing... or I'm heading the right direction sort of and just gotta perfect the code... I'm honestly not sure.  But maybe knowing exactly what I'm trying to do will help.

Thank-You both for being so patient with me and trying to help me understand how to do this!!
0
 
LittleOleMeDesignsAuthor Commented:
Ok... I've finally made some progress... to a point... When I use the code below... it works just like I want it to.. but only if I actually open the drawing in AutoCAD... so apparently something is wrong with how I'm connecting to the objectdbx... or this method just does not work with it or something...  so here's my code for the objectdbx as well as my code for getting the blocks.

Code for objectdbx method:
' ********************************************************************

 V_AutoCad = StartAutoCAD() 'Use the function located in PublicFunctions.vb to initialize AutoCAD

        Dim V_AutoCadInterfaceObject As AxDbDocument
        V_AutoCadInterfaceObject = V_AutoCad.GetInterfaceObject("ObjectDBX.AxDbDocument")

V_AutoCadInterfaceObject.Open(V_FilePathAutoCad)

' ********************************************************************
    Public Function StartAutoCAD() As Object

        On Error Resume Next

        V_AutoCad = GetObject(, "AutoCad.Application.15")
        If Err.Number <> 0 Then 'If they don't have AutoCAD open.. then open it
            Err.Clear()
            Shell("C:\Program Files\Acad2002\acad.exe", AppWinStyle.NormalFocus)
            System.Threading.Thread.Sleep(3000)
            ' Create a new session of AutoCAD using late binding
            V_AutoCad = GetObject(, "AutoCad.Application.15")
        End If
        Return V_AutoCad

    End Function

' ********************************************************************
Code for getting the block info:

            Dim strBlkName As String
            Dim strAttTag As String
            Dim objEnt As AutoCAD.AcadEntity
            Dim objBlkRef As AutoCAD.AcadBlockReference
            Dim varAtts As Object
            Dim objAtt As AutoCAD.AcadAttributeReference
            Dim I As Long

            strBlkName = "START"
            strAttTag = "FILENAME"
            For Each objEnt In V_AutoCad.ActiveDocument.ModelSpace

                If objEnt.ObjectName.ToString = "AcDbBlockReference" Then

                    objBlkRef = objEnt

                    If objBlkRef.Name = strBlkName Then
                        varAtts = objBlkRef.GetAttributes
                        For I = 0 To UBound(varAtts)
                            objAtt = (varAtts(I))
                            If objAtt.TagString = strAttTag Then
                                MsgBox(objAtt.TextString)
                            End If
                        Next I
                    End If
                End If

            Next
        Next
0
 
darrenmcwiCommented:
I'm on the road and don't have access to a lot of my resources, but just a guess, is that "ActiveDocument" is the issue. ActiveDocument I believe is refering to the document that's active in the editor. Can you modify it so it uses the documents collection and references the document you need by index?
0
 
LittleOleMeDesignsAuthor Commented:
That sounds like it could be it... I'm looking around now to see if I can find out more about how to do that... any pointers to get me looking in the right direction for how that code would go??

Thank-You again for your help!
0
 
LittleOleMeDesignsAuthor Commented:
OH MY GOSH... I figured it out finally!!  This works:


For Each V_AutoCadEntity In V_AutoCadInterfaceObject.ModelSpace 'For each Object in Model Space

Open in new window

0
 
LittleOleMeDesignsAuthor Commented:
Thank-You both for all your help!!
0

Featured Post

What is SQL Server and how does it work?

The purpose of this paper is to provide you background on SQL Server. It’s your self-study guide for learning fundamentals. It includes both the history of SQL and its technical basics. Concepts and definitions will form the solid foundation of your future DBA expertise.

  • 8
  • 3
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now