.NET

Reply
Distinguished Contributor
vince1327
Posts: 117
Registered: ‎11-02-2011
Message 1 of 7 (2,133 Views)

Add Attributes to Block References

2133 Views, 6 Replies
02-09-2012 11:46 AM

Hey Everyone,

 

I think what i'm trying to do is pretty simple. I've already had some help designing code whereas I was able to take the attributes from block references in independent .dwg files and and bring them across to a new drawing via import. At this point, there are a few attributes that I would like to be able to add to each block reference once it's created. I've designed a GUI where users can input data, and this input (string data) I'd like to add to the block reference as a tag and a corresponding value.

 

The basics I understand are to create an attribute reference object. Set the properties/parameters for this object (tag and value (originally as a string) and them append the attribute to the block reference. What i don't know how to do is to actually create the new tags and values in the code so that they can later be appended. I'm in C# and so far i've got this:

 

foreach (ObjectId id in blockBtr)
{
if (id.ObjectClass == RXClass.GetClass(typeof(AttributeDefinition)))
{
AttributeDefinition attdef = tr.GetObject(id, OpenMode.ForRead) as AttributeDefinition;
AttributeReference attref = new AttributeReference();
attref.SetAttributeFromBlock(attdef, bref.BlockTransform);

 

// here is where I would like to specify my new tags and values


bref.AttributeCollection.AppendAttribute(attref);
tr.AddNewlyCreatedDBObject(attref, true);



}

}

 

pCenter += vOffset;
bref.ExplodeToOwnerSpace();
bref.Erase();


}

tr.Commit();
this.Close();
}

Valued Contributor
FFlix
Posts: 95
Registered: ‎11-15-2011
Message 2 of 7 (2,129 Views)

Re: Add Attributes to Block References

02-09-2012 12:18 PM in reply to: vince1327

hi vince

 

the attdef-constructor takes the attrdef tag as one of its parameters, so in the example given you:

use the user input to first create the attdef and set its other parameters before

create a blocktablerecord from the blocktable block's blockname,

traverse the objids of this blocktablerecord, 

open them as entity,

check for typeof attref,

if attref, first setattributefromblock with the attdef and blocktransform as parameters,

append the attref to the blockref's attribute collection and add attref to transaction,

look for the tag you used in the attdef and when found,

fill in the value.

 

it may seem a little long-winded but you'll be fine.

 

felix

 

Distinguished Contributor
vince1327
Posts: 117
Registered: ‎11-02-2011
Message 3 of 7 (2,126 Views)

Re: Add Attributes to Block References

02-09-2012 12:27 PM in reply to: FFlix

Logical, not that long winded though haha...is there an example of this somewhere...i dug up something relevant from the swamp in F# but it more concerns converting dtext objects to attributes....if not no worries, i'll tack at it until it goes.

 

Cheers

Vince

*Expert Elite*
Hallex
Posts: 1,569
Registered: ‎10-08-2008
Message 4 of 7 (2,122 Views)

Re: Add Attributes to Block References

02-09-2012 12:34 PM in reply to: vince1327

Hi Vince,

Try this code

{code}

     [CommandMethod("AppendAttributeToBlock","appatt", CommandFlags.Session | CommandFlags.Modal | CommandFlags.UsePickSet | CommandFlags.Redraw)]
        public static void AppendAttributeTest()
           {         
            Document doc = acadApp.DocumentManager.MdiActiveDocument;

            Editor ed = doc.Editor;

            Database db = doc.Database;

            try
            {
                using (doc.LockDocument())
                {
                    using (Transaction tr = db.TransactionManager.StartTransaction())
                    {
                        BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;

                        BlockTableRecord currSp = tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;

                      
                        PromptNestedEntityOptions pno =

                         new PromptNestedEntityOptions("\nSelect source attribute to append new attribute below this one >>");

                        PromptNestedEntityResult nres =

                                                ed.GetNestedEntity(pno);

                        if (nres.Status != PromptStatus.OK)

                            return;

                        ObjectId id = nres.ObjectId;

                        Entity ent = (Entity)tr.GetObject(id, OpenMode.ForRead);

                        Point3d pnt = nres.PickedPoint;

                        ObjectId owId = ent.OwnerId;

                        AttributeReference attref = null;

                        if (id.ObjectClass.IsDerivedFrom(RXClass.GetClass(typeof(AttributeReference))))
                        {
                            attref = tr.GetObject(id,OpenMode.ForWrite) as AttributeReference;
                        }
                    

                        BlockTableRecord btr = null;

                        BlockReference bref = null;

                        if (owId.ObjectClass.IsDerivedFrom(RXClass.GetClass(typeof(BlockReference))))
                        {
                            bref = tr.GetObject(owId,OpenMode.ForWrite) as BlockReference;

                            if (bref.IsDynamicBlock)
                            {
                                btr = tr.GetObject(bref.DynamicBlockTableRecord,OpenMode.ForRead) as BlockTableRecord;
                            }
                            else
                            {
                                btr = tr.GetObject(bref.BlockTableRecord,OpenMode.ForRead) as BlockTableRecord;
                            }
                        }
                       
                        Point3d insPt = attref.Position.TransformBy(bref.BlockTransform);

                        btr.UpgradeOpen();

                        ObjectIdCollection bids = new ObjectIdCollection();

                        AttributeDefinition def = null;

                        foreach (ObjectId defid in btr)
                        {
                            if (defid.ObjectClass.IsDerivedFrom(RXClass.GetClass(typeof(AttributeDefinition))))
                            {
                                def = tr.GetObject(defid, OpenMode.ForRead) as AttributeDefinition;

                                if (def.Tag == attref.Tag)
                                {
                                    def.UpgradeOpen();

                                    bids.Add(defid);

                                    break;
                                }
                            }
                        }

                    

                        IdMapping map = new IdMapping();

                        db.DeepCloneObjects(bids, btr.ObjectId, map,true);

                        ObjectIdCollection coll = new ObjectIdCollection();

                        AttributeDefinition attDef = null;

                        foreach (IdPair pair in map)
                        {
                            if (pair.IsPrimary)
                            {
                                Entity oent = (Entity)tr.GetObject(pair.Value, OpenMode.ForWrite);

                                if (oent != null)
                                {

                                    if (pair.Value.ObjectClass.IsDerivedFrom(RXClass.GetClass(typeof(AttributeDefinition))))
                                    {
                                         attDef = oent as AttributeDefinition;

                                        attDef.UpgradeOpen();

                                        attDef.SetPropertiesFrom(def as Entity);
                                        // add other properties from source attribute definition to suit here:

                                        attDef.Justify = def.Justify;

                                        attDef.Position = btr.Origin.Add(

                                            new Vector3d(attDef.Position.X, attDef.Position.Y - attDef.Height * 1.25, attDef.Position.Z)).TransformBy(Matrix3d.Identity

                                            );

                                        attDef.Tag = "NEW_TAG";

                                        attDef.TextString = "New Prompt";

                                        attDef.TextString = "New Textstring";

                                        coll.Add(oent.ObjectId);


                                    }
                                }
                            }
                        }
                        btr.AssumeOwnershipOf(coll);

                        btr.DowngradeOpen();

                        attDef.Dispose();//optional

                        bref.RecordGraphicsModified(true);

                        tr.TransactionManager.QueueForGraphicsFlush();

                        doc.TransactionManager.FlushGraphics();//optional

                        ed.UpdateScreen();

                        tr.Commit();
                    }

                }
            }
              
            catch (System.Exception ex)
            {
                ed.WriteMessage(ex.Message + "\n" + ex.StackTrace);
            }
            finally
            {
                acadApp.ShowAlertDialog("Call command \"ATTSYNC\" manually");

            }

        }

{code}

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Valued Contributor
FFlix
Posts: 95
Registered: ‎11-15-2011
Message 5 of 7 (2,112 Views)

Re: Add Attributes to Block References

02-09-2012 01:46 PM in reply to: vince1327

my lines are based on jerry winters' book on vb.net for acad2010; in there are a few examples on blocks from which you have to pull the relevant info together; the lines that i mention are actually from an assembly that works, apparently, still... or have a look at kean walmsley's site (though i hadn't, in this instance)

Distinguished Contributor
vince1327
Posts: 117
Registered: ‎11-02-2011
Message 6 of 7 (2,045 Views)

Re: Add Attributes to Block References

03-01-2012 10:11 AM in reply to: vince1327

Hey Guys,

 

Sorry it's been a while. I think i'm looking for something quite a bit simpler. I've tried the examples posted but have been unlucky so far. All that i'm trying to do is essentially add a new tag and value...something like:

 

attDef.Tag = "Test Tag";

attDef.TextString = "Test Content";

 

and to be able to append that to the existing attributes of the block. I was thinking that i'd have to create a new attribute defintion based upon my desired tags and content and then somehow merge the one in my original post with this new one. Sorry if this is confusing, it's slowly getting to me, haha.

 

Cheers

Distinguished Contributor
vince1327
Posts: 117
Registered: ‎11-02-2011
Message 7 of 7 (1,982 Views)

Re: Add Attributes to Block References

03-30-2012 07:10 AM in reply to: vince1327

Hey Everyone,

 

I've just come back to this command. I was going through "Through the Interface" and i stumbled across a bit of code that can update attributes of a block. I wanted to have a look at using the ideas in this code to add attributes to a block. I know that there are methods such as "UpdateAttributesInDatabase" but I can't seem to find anything related to creating or adding new attributes. Where would I start?

 

Cheers

Vince

 

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;

namespace BlockIterator
{
    public class Commands
    {
        [CommandMethod("UA")]
        public void UpdateAttribute()
        {
            Document doc =
              Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            // Have the user choose the block and attribute
            // names, and the new attribute value

            PromptResult pr =
              ed.GetString(
                "\nEnter name of block to search for: "
              );
            if (pr.Status != PromptStatus.OK)
                return;
            string blockName = pr.StringResult.ToUpper();

            pr =
              ed.GetString(
                "\nEnter tag of attribute to update: "
              );
            if (pr.Status != PromptStatus.OK)
                return;
            string attbName = pr.StringResult.ToUpper();

            pr =
              ed.GetString(
                "\nEnter new value for attribute: "
              );
            if (pr.Status != PromptStatus.OK)
                return;
            string attbValue = pr.StringResult;

            UpdateAttributesInDatabase(
              db,
              blockName,
              attbName,
              attbValue
            );
        }

        private void UpdateAttributesInDatabase(
          Database db,
          string blockName,
          string attbName,
          string attbValue
        )
        {
            Document doc =
              Application.DocumentManager.MdiActiveDocument;
            Editor ed = doc.Editor;

            // Get the IDs of the spaces we want to process
            // and simply call a function to process each

            ObjectId msId, psId;
            Transaction tr =
              db.TransactionManager.StartTransaction();
            using (tr)
            {
                BlockTable bt =
                  (BlockTable)tr.GetObject(
                    db.BlockTableId,
                    OpenMode.ForRead
                  );
                msId =
                  bt[BlockTableRecord.ModelSpace];
                psId =
                  bt[BlockTableRecord.PaperSpace];

                // Not needed, but quicker than aborting
                tr.Commit();
            }
            int msCount =
              UpdateAttributesInBlock(
                msId,
                blockName,
                attbName,
                attbValue
              );
            int psCount =
              UpdateAttributesInBlock(
                psId,
                blockName,
                attbName,
                attbValue
              );
            ed.Regen();

            // Display the results

            ed.WriteMessage(
              "\nProcessing file: " + db.Filename
            );
            ed.WriteMessage(
              "\nUpdated {0} instance{1} of " +
              "attribute {2} in the modelspace.",
              msCount,
              msCount == 1 ? "" : "s",
              attbName
            );
            ed.WriteMessage(
              "\nUpdated {0} instance{1} of " +
              "attribute {2} in the default paperspace.",
              psCount,
              psCount == 1 ? "" : "s",
              attbName
            );
        }

        private int UpdateAttributesInBlock(
          ObjectId btrId,
          string blockName,
          string attbName,
          string attbValue
        )
        {
            // Will return the number of attributes modified

            int changedCount = 0;
            Document doc =
              Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            Transaction tr =
              doc.TransactionManager.StartTransaction();
            using (tr)
            {
                BlockTableRecord btr =
                  (BlockTableRecord)tr.GetObject(
                    btrId,
                    OpenMode.ForRead
                  );

                // Test each entity in the container...

                foreach (ObjectId entId in btr)
                {
                    Entity ent =
                      tr.GetObject(entId, OpenMode.ForRead)
                      as Entity;

                    if (ent != null)
                    {
                        BlockReference br = ent as BlockReference;
                        if (br != null)
                        {
                            BlockTableRecord bd =
                              (BlockTableRecord)tr.GetObject(
                                br.BlockTableRecord,
                                OpenMode.ForRead
                            );

                            // ... to see whether it's a block with
                            // the name we're after

                            if (bd.Name.ToUpper() == blockName)
                            {

                                // Check each of the attributes...

                                foreach (
                                  ObjectId arId in br.AttributeCollection
                                )
                                {
                                    DBObject obj =
                                      tr.GetObject(
                                        arId,
                                        OpenMode.ForRead
                                      );
                                    AttributeReference ar =
                                      obj as AttributeReference;
                                    if (ar != null)
                                    {
                                        // ... to see whether it has
                                        // the tag we're after

                                        if (ar.Tag.ToUpper() == attbName)
                                        {
                                            // If so, update the value
                                            // and increment the counter

                                            ar.UpgradeOpen();
                                            ar.TextString = attbValue;
                                            ar.DowngradeOpen();
                                            changedCount++;
                                        }
                                    }
                                }
                            }

                            // Recurse for nested blocks
                            changedCount +=
                              UpdateAttributesInBlock(
                                br.BlockTableRecord,
                                blockName,
                                attbName,
                                attbValue
                              );
                        }
                    }
                }
                tr.Commit();
            }
            return changedCount;
        }
    }
}

 

Post to the Community

Have questions about Autodesk products? Ask the community.

New Post
Need installation help?

Start with some of our most frequented solutions or visit the Installation and Licensing Forum to get help installing your software.