Solved

Automating AutoCAD - get block attributes objectdbx method...

Posted on 2009-04-08
13
6,321 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
  • 8
  • 3
  • 2
13 Comments
 
LVL 10

Accepted Solution

by:
borgunit earned 250 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
 
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
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
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 250 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

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

The debugging module of the VB 6 IDE can be accessed by way of the Debug menu item. That menu item can normally be found in the IDE's main menu line as shown in this picture.   There is also a companion Debug Toolbar that looks like the followin…
You can of course define an array to hold data that is of a particular type like an array of Strings to hold customer names or an array of Doubles to hold customer sales, but what do you do if you want to coordinate that data? This article describes…
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…

747 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

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now