Author Topic: Identifying the existence of a Block (not BlockRef) attribute  (Read 167 times)

0 Members and 1 Guest are viewing this topic.

pjm8765

  • Mosquito
  • Posts: 5
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: [Select]
  1.            Try
  2.                strDepotID = clientDetailsBlock.Item(3).TextString
  3.            Catch ex As Exception
  4.                'If there is no Depot (old drawing) set to Weston Underwood
  5.                strDepotID = enumDepot.Weston.ToString()
  6.            End Try
  7.  

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

  • Swamp Rat
  • Posts: 566
Re: Identifying the existence of a Block (not BlockRef) attribute
« Reply #1 on: March 21, 2017, 09:13:52 am »
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?
Keith Brown | AutoCAD MEP Blog | RSS Feed
AutoCAD MEP 2014 / Revit MEP 2014 / EastCoast CAD/CAM addon / Visual Studio 2013

pjm8765

  • Mosquito
  • Posts: 5
Re: Identifying the existence of a Block (not BlockRef) attribute
« Reply #2 on: March 21, 2017, 10:11:02 am »
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

  • Swamp Rat
  • Posts: 794
Re: Identifying the existence of a Block (not BlockRef) attribute
« Reply #3 on: March 21, 2017, 11:53:00 am »
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#: [Select]
  1. /// <summary>
  2. /// Updates the attributes.
  3. /// </summary>
  4. /// <param name="blockRefID">The block reference objectID.</param>
  5. /// <param name="atts">Dictionary where the key is the tag, the value the textstring</param>
  6. public static int UpdateAttributes(ObjectId blockRefID, Dictionary<string, string> atts)
  7. {
  8. int updatedAtts = 0;
  9. using (LockedTransaction acTr = Active.Document.TransactionManager.StartLockedTransaction())
  10. {
  11. BlockReference blockRef = acTr.GetObject(blockRefID, OpenMode.ForRead,true) as BlockReference;
  12. if (blockRef!=null)
  13. {
  14. foreach (KeyValuePair<string, string> att in atts)
  15. {
  16. foreach (ObjectId attId in blockRef.AttributeCollection)
  17. {
  18. AttributeReference ar = acTr.GetObject(attId, OpenMode.ForRead) as AttributeReference;
  19. if (ar != null && string.Equals(ar.Tag, att.Key, StringComparison.CurrentCultureIgnoreCase))
  20. {
  21. ar.UpgradeOpen();
  22. ar.TextString = att.Value;
  23. ar.DowngradeOpen();
  24. updatedAtts++;
  25. }
  26. }
  27.  
  28. }
  29.  
  30. }
  31. acTr.Commit();
  32. }
  33. return updatedAtts;
  34. }
  35.  

gile

  • Water Moccasin
  • Posts: 2044
  • Marseille, France
Re: Identifying the existence of a Block (not BlockRef) attribute
« Reply #4 on: March 21, 2017, 12:10:22 pm »
@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#: [Select]
  1.        public static int UpdateAttributes(ObjectId blockRefID, Dictionary<string, string> atts)
  2.        {
  3.            if (blockRefID == ObjectId.Null)
  4.                throw new ArgumentNullException("blockRefID");
  5.            if (blockRefID.ObjectClass.DxfName != "INSERT")
  6.                throw new ArgumentException("Not a block reference.");
  7.            int updatedAtts = 0;
  8.            using (var tr = blockRefID.Database.TransactionManager.StartTransaction())
  9.            {
  10.                var br = (BlockReference)tr.GetObject(blockRefID, OpenMode.ForRead);
  11.                foreach (ObjectId id in br.AttributeCollection)
  12.                {
  13.                    var att = (AttributeReference)tr.GetObject(id, OpenMode.ForRead);
  14.                    if (atts.ContainsKey(att.Tag))
  15.                    {
  16.                        att.UpgradeOpen();
  17.                        att.TextString = atts[att.Tag];
  18.                        updatedAtts++;
  19.                    }
  20.                }
  21.                tr.Commit();
  22.            }
  23.            return updatedAtts;
  24.        }

PS: you should not post code using a third party library without notifying it.
« Last Edit: March 21, 2017, 12:14:46 pm by gile »
Speaking English as a French Frog

Atook

  • Swamp Rat
  • Posts: 794
Re: Identifying the existence of a Block (not BlockRef) attribute
« Reply #5 on: March 21, 2017, 01:06:38 pm »
Thanks Gile, I knew it was inefficient, but hadn't figured the whole dictionary thing when I wrote it. Ugly, but it worked.  :embarrassed:

Your code is much more efficient.

I believe the 3rd party code you're referring to is the LockedTransaction class, which I picked up from Jeff H. I appreciate the prompt.