Code Red > .NET

Identifying the existence of a Block (not BlockRef) attribute

(1/2) > >>

pjm8765:
I've inherited a large VB.NET and Delphi (please don't ask, I don't know why) tool/project that's had multiple authors over the years.  I have modified some code to add a new Block attribute and need to be able to check for it's existence (lack of = old drawing which requires a default value inserting), but can only find code that refers to a BlockReference.  Looking at code elsewhere in this system such attempts to identify data is wrapped in a try/catch routine:


--- Code - vb.net: ---            Try                strDepotID = clientDetailsBlock.Item(3).TextString            Catch ex As Exception                'If there is no Depot (old drawing) set to Weston Underwood                strDepotID = enumDepot.Weston.ToString()            End Try 
But on this occasion, regardless of the exception handler, I keep getting an unhandled exception.

I'm afraid rooting around the interweb hasn't helped me on this occasion as everything refers to Block references (which I'm guessing is what my predecessors should have used).  Is there a way to find out if Block.item(3) exists prior to trying to access it?

Keith Brown:
Without knowing alot of the details of what type of object clientDetailsBlock is but if it is a collection/list/IEnumerable can you check to see if the count is >= 4 (if zero based) before checking its existence?

pjm8765:
clientDetailsBlock is of type AcadBlock.  I wouldn't expect a singleton to have the property of a collection, but it does...thanks for making me take another look.

Note to self: Put all notions of proper OOP design away when dealing with AutoCAD...think 80s  :no:

Atook:
I usually cycle through all the attributes looking for a unique tag. You may have to check the attributedefinitions in the block verify that you have a unique property for the one you're trying to update.

This is code that updates an individual blockref, but you could cycle through the attributedefinitions in a blocktablerecord in a similar fashion to check for the DepotID attribute.

--- Code - C#: ---/// <summary>/// Updates the attributes./// </summary>/// <param name="blockRefID">The block reference objectID.</param>/// <param name="atts">Dictionary where the key is the tag, the value the textstring</param>public static int UpdateAttributes(ObjectId blockRefID, Dictionary<string, string> atts){        int updatedAtts = 0;        using (LockedTransaction acTr = Active.Document.TransactionManager.StartLockedTransaction())        {                BlockReference blockRef = acTr.GetObject(blockRefID, OpenMode.ForRead,true) as BlockReference;                if (blockRef!=null)                {                        foreach (KeyValuePair<string, string> att in atts)                        {                                foreach (ObjectId attId in blockRef.AttributeCollection)                                {                                        AttributeReference ar = acTr.GetObject(attId, OpenMode.ForRead) as AttributeReference;                                        if (ar != null && string.Equals(ar.Tag, att.Key, StringComparison.CurrentCultureIgnoreCase))                                        {                                                ar.UpgradeOpen();                                                ar.TextString = att.Value;                                                ar.DowngradeOpen();                                                updatedAtts++;                                        }                                }                         }                 }                acTr.Commit();        }        return updatedAtts;} 

gile:
@Atook
It looks like youre iterating the attribute collection for each entry in the dictionary.
The purpose of a dictionary collection is to directly acces to to an entry by its key.
So it's much more efficient to iterate only the attribute collection:


--- Code - C#: ---        public static int UpdateAttributes(ObjectId blockRefID, Dictionary<string, string> atts)        {            if (blockRefID == ObjectId.Null)                throw new ArgumentNullException("blockRefID");            if (blockRefID.ObjectClass.DxfName != "INSERT")                throw new ArgumentException("Not a block reference.");            int updatedAtts = 0;            using (var tr = blockRefID.Database.TransactionManager.StartTransaction())            {                var br = (BlockReference)tr.GetObject(blockRefID, OpenMode.ForRead);                foreach (ObjectId id in br.AttributeCollection)                {                    var att = (AttributeReference)tr.GetObject(id, OpenMode.ForRead);                    if (atts.ContainsKey(att.Tag))                    {                        att.UpgradeOpen();                        att.TextString = atts[att.Tag];                        updatedAtts++;                    }                }                tr.Commit();            }            return updatedAtts;        }
PS: you should not post code using a third party library without notifying it.

Navigation

[0] Message Index

[#] Next page

Go to full version