Hey guys,
Just wondering how I would be able to grab the block constant attribute by searching via tag.
eg block has a constant attribute 'Color' with value of 'red' and I wish to attain 'red'
I am currently obtaining non constant attributes using:
Dim attRef As AttributeReference = DirectCast(tr.GetObject(attId, OpenMode.ForRead), AttributeReference)
and grabbing the '.textstring' when looking at the '.tag'
How do I go about this with similar logic but pointing to constant attributes?
I have tried searching thoroughly and almost all results for me were in VBA.
Many thanks
Solved! Go to Solution.
Solved by norman.yuan. Go to Solution.
Constant attributes are stored as AttributeDefinitions in the BlockTableRecord. They're not stored with the BlockReference because they are constant across all BlockReferences.
Ah thank you for the answer. I'm still trying to get my head around this as there aren't many examples available.
How would I cycle through my blocks and point to a specific constant tag and grab the textstring?
Could anyone please provide an example or something related in vb.net?
Or if anyone could please show how I would implement it into the below code I am currently using, that would be much appreciated.
Dim idArray As ObjectId() = selSet.GetObjectIds()
For Each blkId As ObjectId In idArray
Dim blkRef As BlockReference = DirectCast(tr.GetObject(blkId, OpenMode.ForRead), BlockReference)
Dim btr As BlockTableRecord = DirectCast(tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead), BlockTableRecord)
Dim attCol As AttributeCollection = blkRef.AttributeCollection
For Each attId As ObjectId In attCol
Dim attRef As AttributeReference = DirectCast(tr.GetObject(attId, OpenMode.ForRead), AttributeReference)
Dim str As String = ((vbLf & " Attribute Tag: " + attRef.Tag & vbLf & " Attribute String: ") + attRef.TextString)
If attRef.Tag = "COLOR" Then
If grouparray.Contains(attRef.TextString) = False Then
grouparray.Add(attRef.TextString)
End If
End If
Next
Next
Many thanks,
HD
As Stephem has already pointed out, constant attribute is defined in BlockTableRecord (block definition). There is no AttributeReference created in Blockreference if an AttributeDefinition is defined as Constant.
You need to understand
1. AttributeReference is an entitiy created in BlockReference with AttributeDefinition as TEMPLATE, but does not have to be te same as he AttributeDefinition. In fact, you can add AttributeReference to a BlockReference without AttributeDefition.
2. Constant AttributeDefition defined in a BlockTableRecord acts the same as a Text entity in BlockTableRecord. That is, the Attribute will go with all other entities in the block definition into a BlockReference.
So, if you need to get value of a constant atribute, the code would like this (assume you seelcteda BlockReferenece' ObjectId, just off my head, not compiled/tested):
using (Transaction tran=theDatabase.TransactionManager.StartTransaction()) { BlockReference bRef=(BlockReference)tran.GetObject(blkrefId, OpenMode.ForRead); BlockTableRecord blk=(BlockTableRecord)tran.GetObject(bRef.BlockTableRecord, OpenMode.ForRead); foreach (ObjectId id in blk) { AttributeDefinition att=tran.GetObject(id,OpenMode.ForRead) As AttributeDefinition; if (att!=null) { if (att.Constant) { if (att.Tag.ToUpper()=="MY_TARGET_ATT") { MessageBox.Show("The value I am looking for is " + att.TextString); att.UpgradeOpen(); att.TextString="New Value; } } } } tran.Commit(); } //since you changed constant attribute's value in block definition, all //Blockreferences of this block in the drawing will also change. Do //a Regen will show the effect Editor.Regen();
HTH.
Norman Yuan
Thank you very much for the reply. That has helped me a lot in gauging a clear understanding.
I have implemented your suggestion into my code but there is still an issue.
I keep getting this error on creating the Attributedefinition:
Unable to cast object of type
'Autodesk.AutoCAD.DatabaseServices.Polyline' to type 'Autodesk.AutoCAD.DatabaseServices.Attributedefinition'
This happens to all types of blocks, whether it be polyline, solid3d etc.
What type should the object be for it to be changed successfully?
Here is my new code below, the 'For Each id As ObjectId In btr' loop has been added in as suggested.
What am I doing wrong here?
Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
Dim doc As Document = Application.DocumentManager.MdiActiveDocument
Dim db As Database = HostApplicationServices.WorkingDatabase
Dim tr As Transaction = db.TransactionManager.StartTransaction()
Try
Dim filList As TypedValue() = New TypedValue(0) {New TypedValue(CInt(DxfCode.Start), "INSERT")}
Dim filter As New SelectionFilter(filList)
Dim opts As New PromptSelectionOptions()
opts.MessageForAdding = "Select block references: "
Dim res As PromptSelectionResult = ed.GetSelection(opts, filter)
If res.Status <> PromptStatus.OK Then
Return
End If
Dim selSet As SelectionSet = res.Valu
Dim idArray As ObjectId() = selSet.GetObjectIds()
For Each blkId As ObjectId In idArray
Dim obj As DBObject = tr.GetObject(blkId, OpenMode.ForRead)
Dim blkRef As BlockReference = DirectCast(tr.GetObject(blkId, OpenMode.ForRead), BlockReference)
Dim btr As BlockTableRecord = DirectCast(tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead), BlockTableRecord)
For Each id As ObjectId In btr
Dim ad As AttributeDefinition = DirectCast(tr.GetObject(id, OpenMode.ForRead), AttributeDefinition)
If ad IsNot Nothing Then
If ad.Constant = False Then
If ad.Tag.ToUpper = "CATEGORY" Then
grouparray.Add(ad.TextString)
End If
End If
End If
Next
Again .. Many thanks for everyones time, it is much appreciated,
HD
The c# statement
[Type] something=...... as [Type]
is not the same as DirectCast() in VB, rather it is similar to TryCast(). You cannot DirectCast() whatever in a block definition into an AttributeDefinition, if it is not an AttributeDefinition.
So, simple change this line:
Dim ad As AttributeDefinition = DirectCast(tr.GetObject(id, OpenMode.ForRead), AttributeDefinition)
To:
Dim ad As AttributeDefinition = TryCast(tr.GetObject(id, OpenMode.ForRead), AttributeDefinition)
Norman Yuan
Thanks Norman, that did the trick!
Much appreciated with the time spent helping me with my issue.