?
Solved

Automating AutoCAD - get block attributes objectdbx method...

Posted on 2009-04-08
13
Medium Priority
?
6,579 Views
Last Modified: 2013-12-04
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
Comment
Question by:LittleOleMeDesigns
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 3
  • 2
13 Comments
 
LVL 10

Accepted Solution

by:
borgunit earned 1000 total points
ID: 24100924
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
 
LVL 4

Author Comment

by:LittleOleMeDesigns
ID: 24106479
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
 
LVL 11

Expert Comment

by:darrenmcwi
ID: 24110019
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
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 4

Author Comment

by:LittleOleMeDesigns
ID: 24115097
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
 
LVL 10

Expert Comment

by:borgunit
ID: 24115239
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
 
LVL 4

Author Comment

by:LittleOleMeDesigns
ID: 24115284
@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
 
LVL 11

Expert Comment

by:darrenmcwi
ID: 24121129
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
 
LVL 4

Author Comment

by:LittleOleMeDesigns
ID: 24122072
@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
 
LVL 4

Author Comment

by:LittleOleMeDesigns
ID: 24123216
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
 
LVL 11

Assisted Solution

by:darrenmcwi
darrenmcwi earned 1000 total points
ID: 24144745
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
 
LVL 4

Author Comment

by:LittleOleMeDesigns
ID: 24147057
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
 
LVL 4

Author Comment

by:LittleOleMeDesigns
ID: 24148828
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
 
LVL 4

Author Closing Comment

by:LittleOleMeDesigns
ID: 31568209
Thank-You both for all your help!!
0

Featured Post

NFR key for Veeam Backup for Microsoft Office 365

Veeam is happy to provide a free NFR license (for 1 year, up to 10 users). This license allows for the non‑production use of Veeam Backup for Microsoft Office 365 in your home lab without any feature limitations.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Most everyone who has done any programming in VB6 knows that you can do something in code like Debug.Print MyVar and that when the program runs from the IDE, the value of MyVar will be displayed in the Immediate Window. Less well known is Debug.Asse…
If you need to start windows update installation remotely or as a scheduled task you will find this very helpful.
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…
Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…
Suggested Courses
Course of the Month9 days, 9 hours left to enroll

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question