Solved

Automating AutoCAD - get block attributes objectdbx method...

Posted on 2009-04-08
13
6,386 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
3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

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

3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
ASP.NET MVC 2 31
Search an image for an image 3 28
MVC DDL Json Not Binding to Model 2 12
Calculate number of nights between two dates 5 18
Introduction While answering a recent question about filtering a custom class collection, I realized that this could be accomplished with very little code by using the ScriptControl (SC) library.  This article will introduce you to the SC library a…
A long time ago (May 2011), I have written an article showing you how to create a DLL using Visual Studio 2005 to be hosted in SQL Server 2005. That was valid at that time and it is still valid if you are still using these versions. You can still re…
Get people started with the utilization of class modules. Class modules can be a powerful tool in Microsoft Access. They allow you to create self-contained objects that encapsulate functionality. They can easily hide the complexity of a process from…
This lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…

786 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