.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Get into the blocks and return block names and attributes

33 REPLIES 33
SOLVED
Reply
Message 1 of 34
danijel.radenkovic
17645 Views, 33 Replies

Get into the blocks and return block names and attributes

Hello,

Could someone help me with this? I would like to get all block with attributes in the opened drawing and to list the names of the blocks and their attribute's tags/values. So, firstly, I am trying to get the information about block names.

        'AutoCAD app
        Dim acadApp As AcadApplication
        acadApp = GetObject(, "AutoCAD.Application")

        'Active doc
        Dim dbxDoc As Object
        dbxDoc = acadApp.ActiveDocument
        acadApp.Visible = True

        Dim entity As Object

        'Catch blocks from the opened dwg
        For Each entity In dbxDoc.PaperSpace

            If TypeOf entity Is AcadBlockReference Then
                MsgBox(entity.GetType.Name)
            End If
        Next entity
    End Sub

Using code from the above the form is loaded but I am not getting the response about the block's name.

I am using AutoCAD 2017 and VB2015.

Many thanks!

 

Inventor 2018/Windows 10 x64
If this information was helpful, please consider marking it as an Accepted Solution by using the Accept as Solution. Kudos are also gladly accepted.
33 REPLIES 33
Message 21 of 34
ActivistInvestor
in reply to: _gile


@_gile wrote:

 

        For Each ent In ss
            If TypeOf ent Is AcadBlockReference Then
                blk = ent
                If blk.HasAttributes Then
		    Dim text As String = "Find block with attribute: " & blk.EffectiveName & "."
		    For Each att As AttributeReference In blk.GetAttributes()
			text = text & vbCr & att.TagString & ": " & att.TextString
		    Next
                    MsgBox(text)
                End If
            End If
        Next

 

@_gile, I think you meant 'AcadAttributeReference' (the COM type) rather than 'AttributeReference' (the managed type).

Message 22 of 34


@norman.yuan wrote:

 

 

...

5. You still do not make it clear you want to list all the names of block definitions (with attribute in it), or names of block references that has attribute. 

 


I think @danijel.radenkovic's code (from his first and more-recent) posts make that abundantly clear.  

 

He wants attributes, not attribute definitions.

Message 23 of 34


@danijel.radenkovic wrote:

 

 

I am still confused about the differences between block definition and block refference.

 

 


I can understand your confusion, given the poorly-chosen names for the types involved (in both the COM and managed API's), and some of what's been written in this topic thus far.

 

Assuming you are an experienced AutoCAD user, I think this is the simplest and most easily understandable way to put it:

 

AcadBlockReference (COM) and BlockReference (.net) are what is created by the INSERT command.

 

AcadBlock (COM) and BlockTableRecord (.net) are what is created by the BLOCK command.

 

 

A lot of confusion over attributes and attribute definitions can be attributed to the poorly-chosen names for their respective API types.

 

For example, AcadAttributeReference (in COM) and AttributeReference (in .NET) are both bad names, because attributes do not reference anything, including attribute definitions. Attributes are attached to block insertions, while attribute definitions are contained in block definitions, and only serve as templates for the creation of attributes. 

 

So AcadAttributeReference is what you get from an AcadBlockReference via it's GetAttributes() method, and AcadAttribute are found in an AcadBlock collection.

 

In the code that @_gile posted, you just need to replace AttributeRererence with AcadAttributeReference, and it should do what you need.

 

Message 24 of 34
Anonymous
in reply to: danijel.radenkovic

instead of 

 

Dim doc As Document = Application.DocumentManager.MdiActiveDocument
Use



Dim doc As Document =Autodesk.AutoCAD.ApplicationServices. Application.DocumentManager.MdiActiveDocument

 Check it if it would help you to solve the problem

Message 25 of 34
_gile
in reply to: ActivistInvestor

@ActivistInvestor thanks for having corrected my typo.

 

@danijel.radenkovic about block reference vs block definition, you can also read this topic at TheSwamp.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 26 of 34
danijel.radenkovic
in reply to: _gile

Hello @_gile,

So, where is a problem with this:

 

2.PNG

Inventor 2018/Windows 10 x64
If this information was helpful, please consider marking it as an Accepted Solution by using the Accept as Solution. Kudos are also gladly accepted.
Message 27 of 34

The cause of that was already explained, which is that you cannot use the .NET api from a standalone Windows executable.
Message 28 of 34


@Activist_Investor wrote:
The cause of that was already explained, which is that you cannot use the .NET api from a standalone Windows executable.

From the one of the replies of the above:

1. You are doing an EXE application to automate AutoCAD (get block information from a drawing opened in AutoCAD. Is that correct? If not, stop reading. We are done.

Yes that's correct. I am trying to iterate with AutoCAD using my exe application.

 

I clearly explained that I am working on .exe application. So, why there are provided a codes for .NET API? That made me confused totally.

Inventor 2018/Windows 10 x64
If this information was helpful, please consider marking it as an Accepted Solution by using the Accept as Solution. Kudos are also gladly accepted.
Message 29 of 34
_gile
in reply to: danijel.radenkovic

You keep on confusing .NET API and COM API.

 

As you said you want to build an out-of-process (standalone exe) application, you CANNOT use the .NET API.

So, remove all references to AutoCAD managed libraries (aacormgd, acdbmgd and acmgd) from your project, remove also all imports of the related namespaces.

Reference AutoCAD COM interop libraries (Autodesk.AutoCAD.Interop and Autodesk.AutoCAD.Interop.Common) and Import these namespace.

 

From the last code you said it worked, not tested (VB and COM API are really boring me).

 

Imports Microsoft.Office
Imports Microsoft.Office.Interop
Imports Microsoft.Office.Interop.Word
Imports System.IO
Imports Autodesk.AutoCAD.Interop
Imports Autodesk.AutoCAD.Interop.Common

Public Class Form1

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        '##########################################################################################################################

        'AutoCAD app
        Dim acadApp As AcadApplication
        acadApp = GetObject(, "AutoCAD.Application")

        'Active doc
        Dim dbxDoc As Object
        dbxDoc = acadApp.ActiveDocument
        acadApp.Visible = True

        Dim ss As AcadSelectionSet
        Dim ent As AcadEntity
        Dim blk As AcadBlockReference

        '' Create a selectionset to select everything in drawing (or with filter to select only "INSERT"
        ss = dbxDoc.SelectionSets.Add("test")

        ss.Select(AcSelect.acSelectionSetAll)

        For Each ent In ss
            If TypeOf ent Is AcadBlockReference Then
                blk = ent
                If blk.HasAttributes Then
                    Dim text As String = "Find block with attribute: " & blk.EffectiveName & "."
		    For Each att As AcadAttributeReference In blk.GetAttributes()
			text = text & vbCr & att.TagString & ": " & att.TextString
		    Next
                    MsgBox(text)
                End If
            End If
        Next
	End Sub
End Clas


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 30 of 34
danijel.radenkovic
in reply to: _gile


@_gile wrote:

If I don't misundertand what you're trying to do, for each selected attributed block, you have to iterate through its attribute collection.

 

Have a look at the GetAttributes COM/ActiveX method.

 

Not sure about VB syntax.

 

        For Each ent In ss
            If TypeOf ent Is AcadBlockReference Then
                blk = ent
                If blk.HasAttributes Then
		    Dim text As String = "Find block with attribute: " & blk.EffectiveName & "."
		    For Each att As AttributeReference In blk.GetAttributes()
			text = text & vbCr & att.TagString & ": " & att.TextString
		    Next
                    MsgBox(text)
                End If
            End If
        Next

Hello @_gile,

Your code works perfect.

Imports AutoCAD

Public Class Form1
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        'AutoCAD app
        Dim acadApp As AcadApplication
        acadApp = GetObject(, "AutoCAD.Application")

        'Active doc
        Dim dbxDoc As Object
        dbxDoc = acadApp.ActiveDocument
        acadApp.Visible = True

        Dim ss As AcadSelectionSet
        Dim ent As AcadEntity
        Dim blk As AcadBlockReference

        ' Create a selectionset to select everything in drawing (or with filter to select only "INSERT"
        ss = dbxDoc.SelectionSets.Add("test")
        ss.Select(AcSelect.acSelectionSetAll)


        For Each ent In ss
            If TypeOf ent Is AcadBlockReference Then
                blk = ent
                If blk.HasAttributes Then
                    Dim text As String = "Find block with attribute: " & blk.EffectiveName & "."
                    For Each att As AcadAttributeReference In blk.GetAttributes()
                        text = text & vbCr & att.TagString & ": " & att.TextString
                    Next
                    MsgBox(text)
                End If
            End If
        Next

    End Sub
End Class

There is only one thing that I would like to solve. When I run the code first time it works fine, but when I stop debugging and run it again, it shows a problem to create new "test" cause it will be duplicate with the same name. What do you suggest how to solve this?

ss = dbxDoc.SelectionSets.Add("test") 

 

Inventor 2018/Windows 10 x64
If this information was helpful, please consider marking it as an Accepted Solution by using the Accept as Solution. Kudos are also gladly accepted.
Message 31 of 34
_gile
in reply to: danijel.radenkovic


danijel.radenkovic a écrit :
There is only one thing that I would like to solve. When I run the code first time it works fine, but when I stop debugging and run it again, it shows a problem to create new "test" cause it will be duplicate with the same name. What do you suggest how to solve this?
ss = dbxDoc.SelectionSets.Add("test") 

 


This is the way SelectionSets work with this API, you have to Delete the selection after using.

 

Here's a working VB code (note the using of a selection filter to get only attributed block references)

 

Imports Autodesk.AutoCAD.Interop
Imports Autodesk.AutoCAD.Interop.Common

Public Class Form1
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Try
            'AutoCAD app
            Dim acadApp As AcadApplication = GetObject(, "AutoCAD.Application")
            acadApp.Visible = True

            'Active doc
            Dim acDoc As AcadDocument = acadApp.ActiveDocument

            'Selection filter to select only block references with attributes
            Dim filterType = New Short() {0, 66}
            Dim filterData = New Object() {"INSERT", 1}

            ' Create a selectionset to select only "INSERT" with attributes
            Dim ss As AcadSelectionSet = acDoc.SelectionSets.Add("test")
            ss.Select(AcSelect.acSelectionSetAll,,, filterType, filterData)

            'Iterate through the selection set
            For Each blk As AcadBlockReference In ss
                Dim text As String = "Find block with attribute: " & blk.EffectiveName & "."
                'Iterate through the block attribute collection
                For Each att As AcadAttributeReference In blk.GetAttributes()
                    text = text & vbCr & att.TagString & ": " & att.TextString
                Next
                MsgBox(text)
            Next
            'Delete the selection set
            ss.Delete()
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try
    End Sub
End Class


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 32 of 34
danijel.radenkovic
in reply to: _gile

Hello @Anonymous,

That's what I was looking for.

Thank you!

Inventor 2018/Windows 10 x64
If this information was helpful, please consider marking it as an Accepted Solution by using the Accept as Solution. Kudos are also gladly accepted.
Message 33 of 34
varad.keshatwar
in reply to: _gile

Hello @_gile ,
Can we achieve this using ObjectARX. As I'm struggling with getting the attributes of the blocks appeneded to my BlockTableRecord and BlockTableTransaction

Message 34 of 34
_gile
in reply to: varad.keshatwar


@varad.keshatwar  a écrit :

Hello @_gile ,
Can we achieve this using ObjectARX. As I'm struggling with getting the attributes of the blocks appeneded to my BlockTableRecord and BlockTableTransaction


Please, start a new topic providing more details on your goal and the code you've written so far.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Forma Design Contest


AutoCAD Beta