How to read BlockReference objects from ActiveDocumets with rich performance

How to read BlockReference objects from ActiveDocumets with rich performance

manohar2375
Advocate Advocate
6,686 Views
11 Replies
Message 1 of 12

How to read BlockReference objects from ActiveDocumets with rich performance

manohar2375
Advocate
Advocate

Hi All,

 

I have made a function as below for read all BlockReference objects from ActiveDocument, then have to do my required validation. But its showing poor performance while reading objects. Is there any rich performance procedure/function to real all BlockReference objects from ActiveDocument ?.

 

Document acDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
Editor acDocEd = acDoc.Editor;
TypedValue[] acTypValAr = new TypedValue[1];
acTypValAr[0] = new TypedValue(0, "INSERT");
SelectionFilter acSelFtr = new SelectionFilter(acTypValAr);
var _selAll = acDocEd.SelectAll(acSelFtr);
var _SelectionSet = _selAll.Value;
if (_SelectionSet == null)
{
return ;
}
if (_SelectionSet.Count > 0)
{
using (var tr = acDoc.TransactionManager.StartTransaction())
{
foreach (var ObjIdBlock in _SelectionSet.GetObjectIds())
{
using (DBObject obj = tr.GetObject(ObjIdBlock, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForRead))
{
BlockReference br = (BlockReference)tr.GetObject(obj.Id, OpenMode.ForRead);
}
}
}
}

 

Could you please help me with sample code to improve performance ?

 

Thanks in Advance.

 

Regards,

Manohar.

0 Likes
Accepted solutions (1)
6,687 Views
11 Replies
Replies (11)
Message 2 of 12

_Tharwat
Advisor
Advisor

Hi,

 

Maybe if you iterate through layouts via Block table record or via Layouts collection, so this may help you to get started.

 

 Document acDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            Editor acDocEd = acDoc.Editor;
            Database db = acDoc.Database;
            var btl = (BlockTable)db.BlockTableId.GetObject(OpenMode.ForRead);

            using (var tr = db.TransactionManager.StartTransaction())
            {
                foreach (var item in btl)
                {
                    var bk = (BlockTableRecord)tr.GetObject(item, OpenMode.ForRead);
                    if (bk.IsLayout)
                    {
                        // ............
                    }
                }
            }
0 Likes
Message 3 of 12

_gile
Consultant
Consultant

Hi,

 

@_Tharwat

 

You shouldn't open a database resident object (block table here) outside a transaction.

 

 

@manohar2375

 

Here's a way using linq

 

        public int BlockCounter(Database db)
        {
            using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction())
            {
                return ((BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead))
                    .Cast<ObjectId>()
                    .Select(id => (BlockTableRecord)tr.GetObject(id, OpenMode.ForRead))
                    .Where(btr => btr.IsLayout)
                    .Select(btr => btr.Cast<ObjectId>().Count(id => id.ObjectClass.DxfName == "INSERT"))
                    .Sum();
            }
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 4 of 12

manohar2375
Advocate
Advocate

@_Tharwat

 

Thanks for your valuable reply.

 

@_gile

 

Thank you very much for your valuable reply.  Could you please help to share sample code for to get list of the block objects instead of count because i am poor in Auto CAD API's. please help me.

 

Thanks in Advance.

 

Regards,

Manohar.

0 Likes
Message 5 of 12

_Tharwat
Advisor
Advisor

Thank you Gile for your advise. 

 

Here is my attempt and it  may not look professional because I am also learning C# but it works.

 

All comments are welcome.

 

 using (var tr = db.TransactionManager.StartTransaction())
            {
                var btl = (BlockTable)db.BlockTableId.GetObject(OpenMode.ForRead);
                foreach (var item in btl)
                {
                    var bk = (BlockTableRecord)tr.GetObject(item, OpenMode.ForRead);
                    if (bk.IsLayout)
                    {
                        foreach (var obj in bk)
                        {
                            Entity ent = (Entity)tr.GetObject(obj, OpenMode.ForRead);
                            if (ent != null && ent.GetType() == typeof(BlockReference))
                            {
                                BlockReference br = (BlockReference)tr.GetObject(obj, OpenMode.ForRead);
                                ed.WriteMessage("\nBlock Name: (" + br.Name + ").");
                            }                        
                        }
                    }
                }
                tr.Commit();
            }
0 Likes
Message 6 of 12

manohar2375
Advocate
Advocate

Hi All,

 

Could you please help me to share sample code to get list of the block objects from ActiveDocument because i am poor in Auto CAD API's. please help me with sample code.

 

Thanks in Advance.

 

Regards,

Manohar.

0 Likes
Message 7 of 12

_Tharwat
Advisor
Advisor

Hi,

 

If you are after counting blocks in a drawing, you can use the commnad: Bcount for that task otherwise just explain what is the need of getting the block objects as you have mentioned into your last reply.

0 Likes
Message 8 of 12

manohar2375
Advocate
Advocate

@_Tharwat

 

Thanks for your valuable reply.

 

As i specified earlier, my requirement is need to collect all the block objects on the ActiveDocument then iterate all one by one and check whether it has block attributes or not, if has then need to apply some business logic to them. For this requirement i made a function which is already specified above, but its showing poor performance, i am requesting you, Is there any other way to get rich performance for the this requirement?, really i am struggling more.

 

Please help me with sample code.

 

Thanks in Advance.

 

Regards,

Manohar.

0 Likes
Message 9 of 12

_Tharwat
Advisor
Advisor

Hi,

 

What do you mean by ActiveDocument? Current drawing with Model and All paper spaces?

Or current space eg: Model or Layout1 or Layout2 ... etc?

 

The codes that I have posted earlier should get you started and the BlockReference object that assigned to the variable ( br ) is the one that you should do your business on as you want.

0 Likes
Message 10 of 12

manohar2375
Advocate
Advocate

@_Tharwat

 

Good morning.

 

Thank you so much for your patients and valuable clarity.

 

My understanding as ActiveDocument is the Model Space and I understood your earlier code, it is also showing poor performance.

Is there any other way to get list of block objects with rich performance from Model Space ActiveDocument.

 

Thanks in Advance.

 

Regards,

Manohar.

0 Likes
Message 11 of 12

_gile
Consultant
Consultant
Accepted solution

Hi,

 

What do you mean with "poor performance" and "high performance"?

 

AFAIK, this is one of the fatest way to get all block references in model space and get attributes in block references.

 

            using (var tr = db.TransactionManager.StartTransaction())
            {
                var modelSpace = (BlockTableRecord)tr.GetObject(
                    SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);
                var brClass = RXObject.GetClass(typeof(BlockReference));
                foreach (ObjectId id in modelSpace)
                {
                    if (id.ObjectClass == brClass)
                    {
                        var br = (BlockReference)tr.GetObject(id, OpenMode.ForRead);
                        // do what you need with the block reference here.
                         
                        foreach (ObjectId attId in br.AttributeCollection)
                        {
                            var attRef = (AttributeReference)tr.GetObject(attId, OpenMode.ForRead);
                            // do what you need with the attribute here.
                        }
                    }
                }
                tr.Commit();
            }

 

You could theorically improve it a little using StartOpenCloseTransaction () instead of StartTransaction() and declaring br and attRef outside the loop, but I'm not certain it will be sensible...



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 12 of 12

manohar2375
Advocate
Advocate

Hi @_gile

 

I made a function to get list of block objects from Model space but its taking more time then i though it was poor performance. So i am looking for best way(high performance) than me.

 

Hence, previous your code is working. Thank you very much.

 

Regards,

Manohar.

0 Likes