add atribute tag and value to autocad block

imagination_s
Advocate
Advocate

add atribute tag and value to autocad block

imagination_s
Advocate
Advocate

Hello Everyone,

Please help me with this

 

I need to add a attribute Tag and a value (position Z) to  each block on my dwg

But doing this in vb.net

Here is my code so far

 

 <CommandMethod("LISTATT")> _
    Public Sub ListAttributes()

        Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor

        Dim db2 As Database = Application.DocumentManager.MdiActiveDocument.Database
        Dim db As Database = HostApplicationServices.WorkingDatabase


        Dim tr As Transaction = db.TransactionManager.StartTransaction()

        ' Start the transaction

        Try

            ' Build a filter list so that only

            ' block references are selected

            Dim values() As TypedValue = { _
         New TypedValue(DxfCode.BlockName, "DOT")
         }
            Dim sfilter As New SelectionFilter(values)


            Dim opts As New PromptSelectionOptions()

            opts.MessageForAdding = "Select blocks: "


            Dim res As PromptSelectionResult = ed.GetSelection(opts, sfilter)

            ' Do nothing if selection is unsuccessful

            If res.Status <> PromptStatus.OK Then

                Return
            End If

            Dim selSet As SelectionSet = res.Value

            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)


                ed.WriteMessage(vbLf & "Block: " + btr.Name)

                btr.Dispose()


                Dim attCol As AttributeCollection = blkRef.AttributeCollection

                For Each attId As ObjectId In attCol
                ' Dim attRef As AttributeReference = DirectCast(tr.GetObject(attId, OpenMode.ForWrite), AttributeReference)
          
               
                ' attRef.Tag = "COTA" ---------it repace other attribute
                ' attRef.TextString = attRef.Position.Z

                ' Dim str As String = ((vbLf & "  Attribute Tag: " + attRef.Tag &

vbLf & "    Attribute String: ") + attRef.TextString)

                ' ed.WriteMessage(str)
        Next

            Next

            tr.Commit()

        Catch ex As Autodesk.AutoCAD.Runtime.Exception


            ed.WriteMessage(("Exception: " + ex.Message))
        Finally


            tr.Dispose()
        End Try

    End Sub

 

The problem is that it  replace other atribute with COTa and the value of Position Z

0 Likes
Reply
Accepted solutions (1)
970 Views
7 Replies
Replies (7)

norman.yuan
Mentor
Mentor

From you code, if it dificult to tell what you are trying to do. Your description is alos a bit vague. It seems that you want to add a new attribute (AttributeReference) in all existing BlockReferences, based in the same block definition, named as "DOT". 

 

There could be 2 situation:

 

1. When the block references were inserted, the block definition didi not have an atribute tagged as "COTA". But now, you modified the block definition and added a new attribute definition "COTA", and you want all the corresponding block references have this new AttributeReference added by code; (you can run "AttSync" command for this, I believe).

 

2. Regardless the block definition having attribute "COTA" or not, you can add as many new attributereference to a block reference as you want by code.

 

If so, what you need is (after obtaining the BlockReference object) to simply create a new AttributeReference, and append it to the Blcokreference.AttributeCollection.

 

However, if you do not have a corresponding AttributeDefinition available in the BlockDefinition as template, you need to decide the AttributeReference's text properties (style, height...) and its geometric location.

 

Maybe, you want to clarify which situation you are in.

 

 

Norman Yuan

Drive CAD With Code

EESignature

0 Likes

imagination_s
Advocate
Advocate

YEs is correct

Number 2

 

2. Regardless the block definition having attribute "COTA" or not, you can add as many new attributereference to a block reference as you want by code

 

I dont have attribute COTA  and a value based on the z coodonate of same attribute i want to ad it to same block

Pleas tell me how to do that

 

"what you need is (after obtaining the BlockReference object) to simply create a new AttributeReference, and append it to the Blcokreference.AttributeCollection."  and this

 

However, if you do not have a corresponding AttributeDefinition available in the BlockDefinition as template, you need to decide the AttributeReference's text properties (style, height...) and its geometric location.

 

How to create a new attribute referene

is this ? -

dim new_att as atrributecollection

dim new_ref as blockeference

0 Likes

norman.yuan
Mentor
Mentor
Accepted solution

OK, assume there is a block definition, called "TestBlock" with no attribute included; and there are a few block references of this block have already been inserted into the drawing, say, ModelSpace; now you want to make all the block referneces show an attribute tagged as "TAG1" with a given value. Here is the code to do that:

 

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using CadApp = Autodesk.AutoCAD.ApplicationServices.Application;

[assembly: CommandClass(typeof(AddAttrToBref.MyCadCommands))]

namespace AddAttrToBref
{
    public class MyCadCommands
    {
        [CommandMethod("AddAtt")]
        public static void AddAttributeToBlock()
        {
            Document dwg = CadApp.DocumentManager.MdiActiveDocument;
            Editor ed = dwg.Editor;

            try
            {
                ObjectId[] blkIds = SelectBlocks(ed, "TestBlock");
                AddNewAttributeToBlocks(dwg, blkIds, "TAG1");

            }
            catch (System.Exception ex)
            {
                ed.WriteMessage("\nError: {0}\n{1}", ex.Message, ex.StackTrace);
            }
            finally
            {
                Autodesk.AutoCAD.Internal.Utils.PostCommandPrompt();
            }
        }

        private static ObjectId[] SelectBlocks(Editor ed, string blkName)
        {
            TypedValue[] vals = new TypedValue[]
            {
                new TypedValue((int)DxfCode.BlockName,blkName)
            };

            PromptSelectionResult res = ed.SelectAll(new SelectionFilter(vals));
            if (res.Status == PromptStatus.OK)
                return res.Value.GetObjectIds();
            else
                return null;
        }

        private static void AddNewAttributeToBlocks(
            Document dwg, ObjectId[] blkIds, string newTag)
        {
            using (var tran=dwg.TransactionManager.StartTransaction())
            {
                int i = 0;
                foreach (var blkId in blkIds)
                {
                    i++;
                    AddAttToBlockReference(dwg.Database, blkId, newTag, "No. " + i, tran);
                }

                tran.Commit();
            }
        }

        private static void AddAttToBlockReference(
            Database db, ObjectId blkId, string tagName, string tagValue, Transaction tran)
        {
            BlockReference bref = (BlockReference)tran.GetObject(blkId, OpenMode.ForWrite);

            AttributeReference aref = new AttributeReference();

            aref.SetDatabaseDefaults();
            aref.Layer = "0";
            aref.TextStyleId = db.Textstyle;
            aref.Height = 0.5;

            aref.SetAttributeFromBlock(bref.BlockTransform);

            aref.Tag = tagName;
            aref.TextString = tagValue;

            bref.AttributeCollection.AppendAttribute(aref);
            tran.AddNewlyCreatedDBObject(aref, true);
        }
    }
}

 
See attached drawing for the effect of before and after the command runs:

 

Before (the block references have no attribute, based on the block definition)

 Before.png

 

 

 After:

 

After.png

 

 

 

 

HTH.

 

Norman Yuan

Drive CAD With Code

EESignature

0 Likes

SENL1362
Advisor
Advisor

Hello Norman,
Good sample and well written.
Just out of curiosity, is there any particular reason why you add both Database and Transaction in AddAttToBlockReference(..).

The Transaction could being extracted from the Database argument, so what's you're story behind this?

0 Likes

norman.yuan
Mentor
Mentor

It was just some code coming quick into my head, did not put too much thought.

 

At first I only had Transaction as argument. And when creating the new Attributereference, I realized that I needed to know the current TextStyle, which I can get from the Database object, thus, I quickly added Database as another argument for that method. That was it: not too much thought, just meant to show a working sample.

 

 

Norman Yuan

Drive CAD With Code

EESignature

0 Likes

SENL1362
Advisor
Advisor
ok. Thanks for the explanation.
0 Likes

imagination_s
Advocate
Advocate

Norman ,your the best! 🙂

Good code

Thankyou so much for your efforts

0 Likes