How to get a collection of all block table records in a file?

How to get a collection of all block table records in a file?

OrmArTHe
Enthusiast Enthusiast
838 Views
12 Replies
Message 1 of 13

How to get a collection of all block table records in a file?

OrmArTHe
Enthusiast
Enthusiast

How to get a collection of all block table records in a file?


0 Likes
Accepted solutions (1)
839 Views
12 Replies
Replies (12)
Message 2 of 13

OrmArTHe
Enthusiast
Enthusiast

Solved - by using this method:

 

TransactionManager.GetAllObjects

 

 

Edit: Not a solution. The method above gets all opened DBObjects in a transaction.

 
0 Likes
Message 3 of 13

norman.yuan
Mentor
Mentor

The object you need to open in order to get all BlockTableRecords, is, not surprisingly, BlockTable. You do:

 

using (var tran=[db].TransactionManager.StartTransaction())
{
    var tbl=(BlockTable)tran.GetObject([db].BlockTableId, OpenMode4.ForRead);
    IEnumerable<BlockTableRecord> allRecords=
          tbl.Cast<ObjectId>().Select(id=>(BlockTableRecord)tran.GetObject(id, OpenMode.ForRead);
   // work with the records as needed
   ... ...
   tran.Commit();
}

 

Norman Yuan

Drive CAD With Code

EESignature

Message 4 of 13

ActivistInvestor
Mentor
Mentor
public static class MyExtensions
{

   public static IEnumerable<T> GetObjects<T>(this IEnumerable<ObjectId> ids,
      Transaction tr,
      OpenMode mode = OpenMode.ForRead)
      where T : DBObject
   {
      if(ids == null)
         throw new ArgumentNullException(nameof(ids));
      if(tr == null)
         throw new ArgumentNullException(nameof(tr));
      RXClass rxclass = RXObject.GetClass(typeof(T));
      foreach(ObjectId id in ids)
      {
         if(id.ObjectClass.IsDerivedFrom(rxclass))
         {
            yield return Unsafe.As<T>(tr.GetObject(id, mode));
         }
      }
   }
   
}

public static class Example
{
   [CommandMethod("LISTBLOCKNAMES")]
   public static void ListBlockNames()
   {
      Document doc = Application.DocumentManager.MdiActiveDocument;
      Editor ed = doc.Editor;
      Database db = doc.Database;
      
      using(var trans = doc.TransactionManager.StartTransaction())
      {
         var blockTable = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
         var ids = blockTable.Cast<ObjectId>();
         var blockTableRecords = ids.GetObjects<BlockTableRecord>(trans);
         foreach(BlockTableRecord btr in blockTableRecords)
         {
            /// btr is only usable up to the call to Commit() below.
            
            ed.WriteMessage($"\n{btr.Name}");
         }
         trans.Commit();
      }
   }
}
Message 5 of 13

OrmArTHe
Enthusiast
Enthusiast
ed.WriteMessage($"\n{btr.Name}");

 I'm checking the docs and I don't see that block table records have 'Name' property...

0 Likes
Message 6 of 13

_gile
Consultant
Consultant

@OrmArTHe  a écrit :
ed.WriteMessage($"\n{btr.Name}");

 I'm checking the docs and I don't see that block table records have 'Name' property...


BlockTableRecord derives from SymbolTableRecord which has a Name property.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 7 of 13

OrmArTHe
Enthusiast
Enthusiast

Could you please explain this line:

var blockTableRecords = ids.GetObjects<BlockTableRecord>(trans);

 

I can't seem to find GetObjects method in the docs...

0 Likes
Message 8 of 13

OrmArTHe
Enthusiast
Enthusiast

Got it. But GetObject method returns ObjectId... How do I convert it to BlockTableRecord so I can access its Name property?

0 Likes
Message 9 of 13

_gile
Consultant
Consultant

@OrmArTHe  a écrit :

Could you please explain this line:

var blockTableRecords = ids.GetObjects<BlockTableRecord>(trans);

 

I can't seem to find GetObjects method in the docs...


GetObjects<T> method is defined in MyExtensions class.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 10 of 13

_gile
Consultant
Consultant
Accepted solution

Here's a method wich return a collection of all the the block table record names.

private static IEnumerable<string> GetBlockNames(Database db)
{
    using (var tr = new OpenCloseTransaction())
    {
        var blockTable = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
        foreach (ObjectId id in blockTable)
        {
            var btr = (BlockTableRecord)tr.GetObject(id, OpenMode.ForRead);
            yield return btr.Name;
        }
        tr.Commit();
    }
}

 

Here's a testing command:

[CommandMethod("TEST")]
public static void Test()
{
    var doc = Application.DocumentManager.MdiActiveDocument;
    var db = doc.Database;
    var ed = doc.Editor;

    foreach (string name in GetBlockNames(db))
    {
        ed.WriteMessage($"\n{name}");
    }
}


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 11 of 13

jabowabo
Mentor
Mentor

This is not directly related to this topic, but I just want to thank @ActivistInvestor and @_gile for your contributions. Even if a topic is not something I'm directly needing help on, I almost always learn something from your posts. Thank you both!

0 Likes
Message 12 of 13

ActivistInvestor
Mentor
Mentor

The GetObjects method is in the code that I posted, it is not built into the api. Did you try the code or are you simply looking at it?

0 Likes
Message 13 of 13

OrmArTHe
Enthusiast
Enthusiast

Generally, I try to understand it before trying it, but yes, I was too hasty and I missed your 'MyExtensions' Class... Sorry about that... I appreciate your help, your solution if really robust...

0 Likes