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!
Solved! Go to Solution.
Solved by _gile. Go to Solution.
Solved by _gile. Go to Solution.
@_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).
@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.
@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.
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
@ActivistInvestor thanks for having corrected my typo.
@danijel.radenkovic about block reference vs block definition, you can also read this topic at TheSwamp.
@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.
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
@_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")
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
Hello @Anonymous,
That's what I was looking for.
Thank you!
@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.
Can't find what you're looking for? Ask the community or share your knowledge.