Adding attributes to existing blocks

Adding attributes to existing blocks

juanjogo
Contributor Contributor
20,705 Views
6 Replies
Message 1 of 7

Adding attributes to existing blocks

juanjogo
Contributor
Contributor

Hello everyone,

I've been trying to add new attributes to existing blocks but I've been unable to do so. Right now I have a routine that seeks out existing blocks; I can extract and modify attribute values but I can't add new ones. I'm guessing the cause of the problem is that I try to add a new attribute to a particular block instance instead of the block definition itself.

If that is the case, is it possible to modify an existing block definition (adding new attributes), preserving the values of the existing attributes in all instances of the block in the drawing? For example, seeking all blocks and when finding a block with certain name, then adding the new attributes to the entire definition.

Thanks,

 

0 Likes
Accepted solutions (1)
20,706 Views
6 Replies
Replies (6)
Message 2 of 7

norman.yuan
Mentor
Mentor

While block reference can have as many Attribute (AcadAttributeReference) as you want, regardless if the corresponding block definition has the attribute defined or not, if you program with AutoCAD COM API/VBA, you simply have no way to add attribute to existing block (adding AcadAttributeReference to AcadBlockReference), because the COM API creates attribute inside a block reference automatically according to block definition when a block reference is inserted into Model/PaperSpace.

 

So, yes, you need to update the block definition by adding new attribute definition (AcadAttribute) into the block definition. Then you decide how to deal with existing block references to that block definition after the block definition is updated:

 

1. You could use SendCommand() to call "AttSync" command (from Acad Express Tool);

2. Re-insert the block reference at the same location/scale/rotation of each existing block reference. You first insert a new one at the same location/scale/rotation, and then get attribute data of the existing block reference and update the attribute in the newly inserted block reference, then erase the existing one.

 

If you program with AutoCAD .NET API, you can simply directly find the existing block reference, add attribute (AttributeReference) to it as you wish without bothering to update the block definition.

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 3 of 7

juanjogo
Contributor
Contributor

Hello Norman,

thanks for your reply. I managed to put together the following code based on some posts I found which successfully creates a new attribute to a block definition. I then used the AttSync command to update the existing blocks but I encountered an issue: Unfortunately many of the blocks in the drawings that I have to redefine were not "rigorously" created, meaning that after the block was inserted, the initial user made changes to the block parameters such as text font, text location, and even layers.

 

When the AttSync command is executed those modifications are also reset. I'm guessing that an update command which only adds the new attribute to the existing blocks is too much to ask, so my question is now: is there a way to get attributes from an attribute such as font, layer, etc. which I can capture and then pass to the blocks once they have been reset through the AttSync command?

thanks

 

Dim new As AcadAttribute
Dim height1 As Double
Dim mode1 As Long
Dim prompt1 As String
Dim insertionPoint1(0 To 2) As Double
Dim tag1 As String
Dim value1 As String
Dim Blk As AcadBlock

height1 = 1
tag1 = "tag name"
value1 = "attribute value"
mode1 = acAttributeModeVerify
prompt1 = "new attribute"
insertionPoint1(0) = 0
insertionPoint1(1) = 0
insertionPoint1(2) = 0
   
On Error Resume Next
Set Blk = tAcadDoc.Blocks("name of block")
If Err.Number <> 0 Then
    MsgBox "the block does not exist"
Else
    'Create new attribute
    On Error Resume Next
    Set new = Blk.AddAttribute(height1, acAttributeModeInvisible, _
    prompt1, insertionPoint1, tag1, value1)
    If Err.Number <> 0 Then
        MsgBox "could not be accomplished"
    Else
        MsgBox "new attribute created: " & new.TagString
    End If
    tAcadDoc.SendCommand ("attsync n " & "name of block" & vbCr)
End If
0 Likes
Message 4 of 7

norman.yuan
Mentor
Mentor
Accepted solution

So, if the attributes of existing blocks have been edited in someway that the AttributeReference is quite different from the attribute definition, such as its layer/height/style...then you may have to give up on "ATTSync" and go with method 2 as I suggested in previous reply. that is, create a new block reference at the same position/scale/rotation, and then get all existing attribute information and update the new attribute, and then erase the existing block.

 

Yes, you can get existing attribute's detail:

 

Dim existingAtts as Variant

Dim att As AcadAttributeReference

Dim i As Integer

existingAtts=exitingBlockref.GetAttributes()

 

For i=0 to Ubound(existiingAtts)

    Set att=existingAtts(i)

    ''Now you can get AcadAttributeReference's defail here

    ''and save then into variables/collections/arrays

    [height]=att.Height

    [textStyle]=att.StyleName

    [layer]=att.Layer

    ...

Next

 

''Then you go to corresponding new block reference to update the attribute.

 

Norman Yuan

Drive CAD With Code

EESignature

Message 5 of 7

juanjogo
Contributor
Contributor

Thanks for your reply Norman,

I managed to implement your suggestion successfully. I'm still using AttSync, getting the attribute information and then passing it after running AttSync. I just have one thing missing. I searched posts but couldn't figure out how to get the position of the attribute in the block. Is there a way to get the current position so that I can pass it after running AttSync, just like the text style, height and layer?

 

0 Likes
Message 6 of 7

norman.yuan
Mentor
Mentor

In COM API, an CadAttributeReference's position (let's assume AcadAttributeReference.InsertionPoint as its position) is current UDS (let's also assume it is World UCS) coordinate; while Attribute definition's position in block definition is against to the block's base point (insertion point).

 

Say, if you have a block definition with its lower-left corner as base point, and an attribute definition is defined in the block at 1 unit on X and 1 unit on Y. Now, if you insert the block at 10,10 in modelspace, the attribute reference created by COM API will be located at 11,11, when the block reference is not rotated and is scaled at 1, of course; otherwise, you need to factor in block reference's rotation/scale. But it is simply some math work to figure it out. That is, if you know the attribute definition's position relative to block definition's base point, you can then calculate the supposed location of corresponding attribute reference in a block reference..

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 7 of 7

juanjogo
Contributor
Contributor
Ok, thanks Norman,
I'll see if I can manage the position of the attribute in the relative coordinates of the block.
0 Likes