Author Topic: Attribute tag C#  (Read 13772 times)

0 Members and 1 Guest are viewing this topic.

A_LOTA_NOTA

  • Guest
Attribute tag C#
« on: April 21, 2011, 12:02:10 PM »

Can I not use
Code: [Select]
new TypedValue((short)DxfCode.AttributeTag, "REV") as a filter? I would like to get all the blocks in the current space with a specified tag. Then I want to return the attribute value and the name of the block. I'm new so this might not even be close to what I need.


Code: [Select]
Editor acEd = Application.DocumentManager.MdiActiveDocument.Editor;

            TypedValue[] myTVs = new TypedValue[]
                     {
                        new TypedValue((short)DxfCode.Start, "INSERT") ,
                        //the TypedValue can accept a null second parameter
                        new TypedValue((short)DxfCode.AttributeTag, "REV")
                     };
            SelectionFilter myFilter = new SelectionFilter(myTVs);

            PromptSelectionResult result = acEd.SelectAll(myFilter);
            if (result.Status == PromptStatus.OK)
            {
                ObjectId[] idArray = result.Value.GetObjectIds();
                Autodesk.AutoCAD.DatabaseServices.TransactionManager tm = Application.DocumentManager.MdiActiveDocument.Database.TransactionManager;
                Transaction tr = tm.StartTransaction();
                try
                {
                    foreach (ObjectId id1 in idArray)
                    {
                        Entity entity1 = (Entity)tm.GetObject(id1, OpenMode.ForRead, true);
                        acEd.WriteMessage("\nBlocks found: " + entity1.GetType().FullName);
                    }// end foreach
                }// end try
                finally
                {
                    tr.Dispose();
                }// end finally
            }// end if


Lee Mac

  • Seagull
  • Posts: 12926
  • London, England
Re: Attribute tag C#
« Reply #1 on: April 21, 2011, 12:04:25 PM »
The rules may change for C#, but certainly in LISP you can't filter below primary entities and so would have to iterate through all attributed blocks in a SelectionSet.

A_LOTA_NOTA

  • Guest
Re: Attribute tag C#
« Reply #2 on: April 21, 2011, 12:29:02 PM »
The rules may change for C#, but certainly in LISP you can't filter below primary entities and so would have to iterate through all attributed blocks in a SelectionSet.


You might be right. but I had to try  :-D

I feel like lisp needs a lot less code  :lol:

gile

  • Gator
  • Posts: 2520
  • Marseille, France
Re: Attribute tag C#
« Reply #3 on: April 21, 2011, 12:45:53 PM »
Hi,

LISP and .NET selection filters can be written the same way:

LISP
Code: [Select]
'((0 . "INSERT") (66 . 1))
C#
Code: [Select]
TypedValue[] filter = new TypedValue[2]{ new TypedValue(0, "INSERT"), new TypedValue(66, 1) };
As Lee said, theres no way to directly filter with an attribute tag, you have to first select all attributed blocks (with the upper filter) or with the block name (if you know the attribute tag, you propably know the block name) and then, iterate throught the AttributeCollection to find the tag (the same way you'll do it in LISP).
« Last Edit: April 21, 2011, 03:27:07 PM by gile »
Speaking English as a French Frog

kaefer

  • Guest
Re: Attribute tag C#
« Reply #4 on: April 21, 2011, 01:44:26 PM »
I feel like lisp needs a lot less code  :lol:

I feeld like a bicycle uses a lot less ressources, but then it won't run faster than your family car.

Let's see. You mean some Lisp like this?
Code: [Select]
(DEFUN atma (ss0 attpat valpat / getatts ss1 en obj match)
  (DEFUN getAtts (bl / atts)
    (IF (AND (= :vlax-true (vla-get-HasAttributes bl))
             (NOT (MINUSP (vlax-safearray-get-u-bound (SETQ atts (vlax-variant-value (vla-GetAttributes bl))) 1)))
)
      (SETQ atts (vlax-safearray->list atts)
            atts (MAPCAR 'CONS (MAPCAR 'vla-get-TagString atts) (mapcar 'vla-get-textstring atts))
      )
    )
  )
  (SETQ ss1 (SSADD))
  (WHILE (AND ss0
      (= 'PICKSET (TYPE ss0))
      (< 0 (SSLENGTH ss0))
)
    (SETQ en (SSNAME ss0 0)
  obj (vlax-ename->vla-object en)
  match ()
    )
    (SSDEL en ss0)
    (IF (= "AcDbBlockReference" (vla-get-ObjectName obj))
      (PROGN
(FOREACH att (getatts obj)
  (IF (AND (WCMATCH (CAR att) attpat)
   (WCMATCH (CDR att) valpat)
      )
    (SETQ match T)
  )
)
(IF match (SSADD en ss1))
      )
    )
  )
  (IF (< 0 (SSLENGTH ss1)) ss1)
)

That compares to an aquivalent .NET program like this (the actual language used is not so important).
Code: [Select]
open Autodesk.AutoCAD.DatabaseServices
open Autodesk.AutoCAD.EditorInput
open Autodesk.AutoCAD.Runtime
type acApp = Autodesk.AutoCAD.ApplicationServices.Application

[<CommandMethod("AttrMatch", CommandFlags.UsePickSet)>]
let AttrMatchCmd() =
   
    let doc = acApp.DocumentManager.MdiActiveDocument
    let db = doc.Database
    let ed = doc.Editor
    let pStrTag =
        new PromptStringOptions(
            "Enter Attribute Tag",
            DefaultValue = "*" )
        |> ed.GetString
    if pStrTag.Status = PromptStatus.OK then
        let pStrVal =
            new PromptStringOptions(
                "Enter Attribute Value",
                DefaultValue = "*",
                AllowSpaces = true )
            |> ed.GetString
        if pStrVal.Status = PromptStatus.OK then
            let tag = pStrTag.StringResult.ToUpperInvariant()
            let value = pStrVal.StringResult
            let wcmatch s p =
                Autodesk.AutoCAD.Internal.Utils.WcMatch(s, p)
            let pred (aid: ObjectId) =
                let ar = aid.GetObject OpenMode.ForRead :?> AttributeReference
                wcmatch ar.Tag tag && wcmatch ar.TextString value
                 
            use tr = db.TransactionManager.StartTransaction()
            let selectionAdded _ (e: SelectionAddedEventArgs) =
                seq{ for so in e.AddedObjects -> so.ObjectId }
                |> Seq.mapi (fun i oid -> i, oid.GetObject OpenMode.ForRead)
                |> Seq.choose
                    (function
                        | _, (:? BlockReference as br) when
                            seq{ for aid in br.AttributeCollection -> aid }
                            |> Seq.exists pred -> None
                        | i, _ -> Some i
                    )
                |> Seq.iter e.Remove
            let selectionAddedHandler =
                new SelectionAddedEventHandler(
                    selectionAdded )
            let selectionFilter =
                new SelectionFilter[|
                    new TypedValue(int DxfCode.Start, "INSERT") |]
            let psr =
                try
                    ed.SelectionAdded.AddHandler selectionAddedHandler
                    let psr = ed.GetSelection selectionFilter
                    if psr.Status <> PromptStatus.Error then psr
                    else ed.SelectAll selectionFilter
                finally
                    ed.SelectionAdded.RemoveHandler selectionAddedHandler
            if psr.Status = PromptStatus.OK && psr.Value.Count > 0 then
                ed.WriteMessage("\n{0} Objects selected", psr.Value.Count)
                ed.SetImpliedSelection psr.Value
            else
                ed.WriteMessage("\nNo Objects selected. ")
            tr.Commit()

You will notice that the actual filtering went into an event handler, which allows for a cleaner and more flexible solution than the selection set juggling above.

Lee Mac

  • Seagull
  • Posts: 12926
  • London, England
Re: Attribute tag C#
« Reply #5 on: April 21, 2011, 01:56:54 PM »
Not sure how I'd convert this to C#  :|

Code: [Select]
(defun GetBlocksWithTag ( tag / ss i e )
  (if (setq ss (ssget "_X" '((0 . "INSERT") (66 . 1))))
    (repeat (setq i (sslength ss)) (setq e (ssname ss (setq i (1- i))))     
      (if
        (not
          (vl-some '(lambda ( a ) (eq tag (vla-get-tagstring a)))
            (vlax-invoke (vlax-ename->vla-object e) 'getattributes)
          )
        )
        (ssdel e ss)
      )
    )
  )
  ss
)

dgorsman

  • Water Moccasin
  • Posts: 2437
Re: Attribute tag C#
« Reply #6 on: April 21, 2011, 02:21:38 PM »
The rules may change for C#, but certainly in LISP you can't filter below primary entities and so would have to iterate through all attributed blocks in a SelectionSet.


You might be right. but I had to try  :-D

I feel like lisp needs a lot less code  :lol:

"With great power, comes great responsibility."  ... like better error handling.
If you are going to fly by the seat of your pants, expect friction burns.

try {GreatPower;}
   catch (notResponsible)
      {NextTime(PlanAhead);}
   finally
      {MasterBasics;}

gile

  • Gator
  • Posts: 2520
  • Marseille, France
Re: Attribute tag C#
« Reply #7 on: April 21, 2011, 03:26:49 PM »
Not sure how I'd convert this to C#  :|

Code: [Select]
(defun GetBlocksWithTag ( tag / ss i e )
  (if (setq ss (ssget "_X" '((0 . "INSERT") (66 . 1))))
    (repeat (setq i (sslength ss)) (setq e (ssname ss (setq i (1- i))))     
      (if
        (not
          (vl-some '(lambda ( a ) (eq tag (vla-get-tagstring a)))
            (vlax-invoke (vlax-ename->vla-object e) 'getattributes)
          )
        )
        (ssdel e ss)
      )
    )
  )
  ss
)

Maybe something like this:

Code: [Select]
        public ObjectIdCollection SelByTag(string tag)
        {
            Document doc = AcAp.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            tag = tag.ToUpper();
            TypedValue[] filter = new TypedValue[2] { new TypedValue(0, "INSERT"), new TypedValue(66, 1) };
            PromptSelectionResult psr = ed.GetSelection(new SelectionFilter(filter));
            if (psr.Status != PromptStatus.OK) return null;
            ObjectIdCollection idCol = new ObjectIdCollection(psr.Value.GetObjectIds());
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                for (int i = 0; i < idCol.Count;)
                {
                    BlockReference br = (BlockReference)tr.GetObject(idCol[i], OpenMode.ForRead);
                    bool has = false;
                    foreach (ObjectId id in br.AttributeCollection)
                    {
                        AttributeReference att = (AttributeReference)tr.GetObject(id, OpenMode.ForRead);
                        if (att.Tag == tag)
                        {
                            has = true;
                            break;
                        }
                    }
                    if (has)
                        i++;
                    else
                        idCol.RemoveAt(i);
                }
            }
            return idCol;
        }
Speaking English as a French Frog

Lee Mac

  • Seagull
  • Posts: 12926
  • London, England
Re: Attribute tag C#
« Reply #8 on: April 21, 2011, 03:31:30 PM »
Thanks Gile! That definitely helps with my learning  :-)

gile

  • Gator
  • Posts: 2520
  • Marseille, France
Re: Attribute tag C#
« Reply #9 on: April 21, 2011, 03:48:44 PM »
F# is quite more closed to LISP

Code: [Select]
let selByAtt (tag : string) =
    let doc = AcAp.DocumentManager.MdiActiveDocument
    let db = doc.Database
    let ed = doc.Editor
    let filter = [| new TypedValue(0, "INSERT"); new TypedValue(66, 1) |]
    let psr = ed.GetSelection(new SelectionFilter(filter))
    if psr.Status = PromptStatus.OK then
        use tr = db.TransactionManager.StartTransaction()
        psr.Value.GetObjectIds()
        |> Array.filter (fun brId ->
            let br = tr.GetObject(brId, OpenMode.ForRead) :?> BlockReference
            br.AttributeCollection
            |> Seq.cast<_>
            |> Seq.exists(fun attId ->
                let att = tr.GetObject(attId, OpenMode.ForRead) :?> AttributeReference
                att.Tag = tag.ToUpper()))
    else null
« Last Edit: April 21, 2011, 04:13:30 PM by gile »
Speaking English as a French Frog

Bobby C. Jones

  • Swamp Rat
  • Posts: 516
  • Cry havoc and let loose the dogs of war.
Re: Attribute tag C#
« Reply #10 on: April 21, 2011, 04:44:50 PM »
You could also make the C# code a bit more expressive, although not lisp-ish

Code: [Select]
    public List<ObjectId> SelByTag(string tag)
    {
        Document doc = acadApp.DocumentManager.MdiActiveDocument;
        Database db = doc.Database;
        Editor ed = doc.Editor;

        TypedValue[] filter = new TypedValue[2] { new TypedValue(0, "INSERT"), new TypedValue(66, 1) };
        PromptSelectionResult selectionResult = ed.GetSelection(new SelectionFilter(filter));

        if (selectionResult.Status != PromptStatus.OK)
            return null;

        using (Transaction tr = db.TransactionManager.StartTransaction())
        {
            var atts = from blockRefId in selectionResult.Value.GetObjectIds()
                       let blockRef = (BlockReference)tr.GetObject(blockRefId, OpenMode.ForRead)
                       from ObjectId attribRefId in blockRef.AttributeCollection
                       let attribRef = (AttributeReference)tr.GetObject(attribRefId, OpenMode.ForRead)
                       where attribRef.Tag.Equals(tag, StringComparison.OrdinalIgnoreCase)
                       select attribRefId;

            return atts.ToList();
        }
    }
Bobby C. Jones

kaefer

  • Guest
Re: Attribute tag C#
« Reply #11 on: April 21, 2011, 05:03:37 PM »
You could also make the C# code a bit more expressive, although not lisp-ish

Linq-ish is almost lisp-ish.

To iterate: filtering during the (interactive) selection using the SelectionAdded event seems better to me than doing it afterwards.
Code: [Select]
using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using acApp = Autodesk.AutoCAD.ApplicationServices.Application;
using acUtils = Autodesk.AutoCAD.Internal.Utils;

namespace AttrMatchTest
{
    public class SelectionAddedCmd
    {
        private string tagPat = "*";
        private string valPat = "*";

        // SelectionAdded event handler
        void selectionAdded(object sender, SelectionAddedEventArgs e)
        {
            IEnumerable<int> objsToRemove =
                e.AddedObjects
                .Cast<SelectedObject>()
                .Select((so, i) => new{ I = i, Br = so.ObjectId.GetObject(OpenMode.ForRead) as BlockReference })
                .Where(f =>
                    f.Br == null ||
                    !(f.Br.AttributeCollection
                        .Cast<ObjectId>()
                        .Select(id => (AttributeReference)id.GetObject(OpenMode.ForRead))
                        .Any(ar => acUtils.WcMatch(ar.Tag, tagPat) && acUtils.WcMatch(ar.TextString, valPat))))
                .Select(f => f.I);
            foreach (int i in objsToRemove) e.Remove(i);
        }
       
        [CommandMethod("AttrMatch")]
        public void AttrMatch()
        {
            var doc = acApp.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;

            PromptStringOptions pso = new PromptStringOptions("Enter Attribute Tag"){ DefaultValue = tagPat };
            PromptResult pr = ed.GetString(pso);
            if(pr.Status != PromptStatus.OK) return;
            tagPat = pr.StringResult.ToUpperInvariant();
            pso = new PromptStringOptions("Enter Attribute Value") { DefaultValue = valPat, AllowSpaces = true };
            pr = ed.GetString(pso);
            if(pr.Status != PromptStatus.OK) return;
            valPat = pr.StringResult;
            TypedValue[] filter = new TypedValue[2]{ new TypedValue(0, "INSERT"), new TypedValue(66, 1) };

            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                PromptSelectionResult psr = null;
                try
                {
                    ed.SelectionAdded += new SelectionAddedEventHandler(selectionAdded);
                    psr = ed.GetSelection(new SelectionFilter(filter));
                }
                finally
                {
                    ed.SelectionAdded -= new SelectionAddedEventHandler(selectionAdded);
                }
                if (psr != null &&  psr.Status == PromptStatus.OK && psr.Value.Count > 0)
                    ed.WriteMessage("\n{0} Objects selected", psr.Value.Count);
                else
                    ed.WriteMessage("\nNo Objects selected. ");
            }
        }
    }
}


gile

  • Gator
  • Posts: 2520
  • Marseille, France
Re: Attribute tag C#
« Reply #12 on: April 22, 2011, 02:08:27 AM »
Thanks Bobby and Thorsten for these nice examples.
I was off topic with my F# code, LINQ is the way to write C# in a 'functional style'.
Speaking English as a French Frog

Jeff H

  • Needs a day job
  • Posts: 6151
Re: Attribute tag C#
« Reply #13 on: April 22, 2011, 05:16:39 AM »
Trying to start posting a little more quality than quantity.

Sorry first intentions were to show how the code works by MgdDbg, then to explain the code, but it is taking a longer then expected and do want to spend any more time if no one cares or will not look at it.
I would be more than happy to go in more detail on any part, any line, or the whole thing if anyone wants but if not I will not waste the time.

I do not know if this will help but hopefully it will help a little on looking at things with MgdDbg and docs.
Just did it for an example not to show best practices

Your 3 best friends
1. Swamp
2. MgdDbg
3. Docs .chm help files from ObjectArx SDK


Recorded while tired, trying not to be loud so not to wake the kid, & the redneck accent might make it hard to understand.

Setup:
Have a drawing with three blocks
1. C -- Contains the tag we want
2. AnotherBlockWithSameTag -- Contains Block we want
3. Rec -- Does not contain the block we want

The tag we are after is ONEWEWANT

Here are 2 possible options to do it
1. Iterate current space to find blocks
2. Iterate BlockTable to find blocks

This link FirstOptionMgdDbg  shows MdgDbg where we would iterate all entities in current space and check to see if it is a BlockReference and if it is get the AttributeCollection and check the AttributesReference's Tag property.

This link SecondOptionMgdDbg    shows MgdDbg where would iterate through the BlockTable if the BlockTableRecord's IsLayout property is true then skip it(IsLayout is true if it is model space or any paper space) or,
If HasAttributeDefinitions property is false we will skip it, else we will look at the Attribute definition and see if the Tag property contains same value as the one we want.
If it does we will get the GetBlockReferenceIds and make sure to add  the ones in the current space.


Code: [Select]

[CommandMethod("AttributeTags")]
        public void AttributeTags()
        {


            Document doc = Application.DocumentManager.MdiActiveDocument;//Assign the Current Document to doc
            Database db = doc.Database;// Assign doc's(Current Active Document) database to db
            Editor ed = doc.Editor;// Assign Editor to doc

            using (Transaction trx = db.TransactionManager.StartTransaction())// Start Transaction
            {
                BlockTable blocktable = trx.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;//Assign BlockTable

                ed.WriteMessage("\n*******************\nItterate CurrentSpace\n****************\n");

                // Using Database.CurrentSpaceId --- Accesses the ObjectId of the BlockTableRecord of the current space
                //                                   (e.g., model space or paper space.)
                BlockTableRecord currentSpace = trx.GetObject(db.CurrentSpaceId, OpenMode.ForRead) as BlockTableRecord;
                
              
                // Iterate all the entites in the current space
                foreach (ObjectId objId in currentSpace)
                {
                    // This is quicker than opening the actual object and checking the type
                    // When a object is created or loaded AutoCAD creates the Object and a ObjectId---(look @ ObjectId structure in docs)
                    // The value of the ObjectId is it's memory address and it contains the memory address or pointer to actual object returned by GetObject()
                    if (!(objId.ObjectClass.Name == "AcDbBlockReference"))// If not a BlockReference then skip it  
                    {// objId.ObjectClass.DxfName == "BLOCKREFERENCE" could have been used
                        continue;
                    }

                    BlockReference blockreference = trx.GetObject(objId, OpenMode.ForRead) as BlockReference;
                    
                    AttributeCollection attributeCollection = blockreference.AttributeCollection;

                    foreach (ObjectId attId in attributeCollection)
                    {
                        AttributeReference attributeReference = (AttributeReference)trx.GetObject(attId, OpenMode.ForRead);
                        
                        if (attributeReference.Tag.ToUpper() == "ONEWEWANT")// If we do not care about casing make it all upper so not to worry
                        {
                            BlockTableRecord btr = (BlockTableRecord)trx.GetObject(blockreference.BlockTableRecord, OpenMode.ForRead);
                            ed.WriteMessage("{0} with Attribute Value {1}\n", btr.Name, attributeReference.TextString);
                        }
                    }

                }


                ed.WriteMessage("\n*******************\nItterate BlockTable\n****************\n");

                // Itterating BlockTable
                foreach (ObjectId objId in blocktable)
                {
                    BlockTableRecord blkTbleRecord = trx.GetObject(objId, OpenMode.ForRead) as BlockTableRecord;
                    if (blkTbleRecord.IsLayout || !blkTbleRecord.HasAttributeDefinitions)
                    {
                        continue;
                    }

                  
                    foreach (ObjectId entityId in blkTbleRecord)
                    {

                        if (!(entityId.ObjectClass.Name == "AcDbAttributeDefinition"))
                        {
                            continue;
                        }

                        AttributeDefinition attributeDef = trx.GetObject(entityId, OpenMode.ForRead) as AttributeDefinition;
                        if (!(attributeDef.Tag.ToUpper() == "ONEWEWANT"))
                        {
                            continue;
                        }
                        // Get the BlockReferenceIds
                        ObjectIdCollection blockreferenceIds = blkTbleRecord.GetBlockReferenceIds(true, false);

                        foreach (ObjectId brefId in blockreferenceIds)
                        {
                            BlockReference blockreference = trx.GetObject(brefId, OpenMode.ForRead) as BlockReference;

                            AttributeCollection attributeCollection = blockreference.AttributeCollection;
                          
                            // Make Sure It is in Current Space
                            if (!(blockreference.BlockId == currentSpace.ObjectId))
                            {
                                continue;
                            }

                            foreach (ObjectId attId in attributeCollection)
                            {
                                AttributeReference attributeReference = (AttributeReference)trx.GetObject(attId, OpenMode.ForRead);
                                // Make Sure It is right Tag
                                if (attributeReference.Tag.ToUpper() == "ONEWEWANT")
                                {
                                    ed.WriteMessage("{0} with Attribute Value {1}\n", blkTbleRecord.Name, attributeReference.TextString);
                                }
                            }

                        }


                    }


                }




                trx.Commit();
            }
            

        }







« Last Edit: April 22, 2011, 05:23:10 AM by Jeff H »

Bobby C. Jones

  • Swamp Rat
  • Posts: 516
  • Cry havoc and let loose the dogs of war.
Re: Attribute tag C#
« Reply #14 on: April 22, 2011, 07:53:12 AM »
I was off topic with my F# code,

I think NOT!  The day that I come to the Swamp and don't see multiple solutions to a problem is the day that I stop coming to the Swamp.  Thank you for taking the time to share your most excellent F# example.

clarified my objection :-)
« Last Edit: April 22, 2011, 03:19:59 PM by Bobby C. Jones »
Bobby C. Jones

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: Attribute tag C#
« Reply #15 on: April 22, 2011, 08:46:28 AM »
Thanks Bobby and Thorsten for these nice examples.

Ditto that.

I was off topic with my F# code

Are you lost? This is the swamp. Off topic IS on topic. Please continue to post your most valued code + comments my friend.
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

A_LOTA_NOTA

  • Guest
Re: Attribute tag C#
« Reply #16 on: April 25, 2011, 08:53:00 AM »
Thank you for all the replies. I hope to have time today to look at it all. Thanks again.

gile

  • Gator
  • Posts: 2520
  • Marseille, France
Re: Attribute tag C#
« Reply #17 on: May 03, 2011, 06:45:44 PM »
Another way using Linq extension methods

Code: [Select]
        public ObjectId[] SelByTag(string tag)
        {
            Document doc = AcAp.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            tag = tag.ToUpper();
            TypedValue[] filter = new TypedValue[2] { new TypedValue(0, "INSERT"), new TypedValue(66, 1) };
            PromptSelectionResult psr = ed.GetSelection(new SelectionFilter(filter));
            if (psr.Status != PromptStatus.OK) return null;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                return psr
                    .Value
                    .GetObjectIds()
                    .Where(brId => ((BlockReference)tr.GetObject(brId, OpenMode.ForRead))
                        .AttributeCollection
                        .Cast<ObjectId>()
                        .Any(attId => ((AttributeReference)tr.GetObject(attId, OpenMode.ForRead))
                            .Tag == tag))
                    .ToArray();
            }
        }
« Last Edit: May 04, 2011, 02:10:34 AM by gile »
Speaking English as a French Frog