.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Get BlockReference and Dynamic Block Count

10 REPLIES 10
SOLVED
Reply
Message 1 of 11
Anonymous
1131 Views, 10 Replies

Get BlockReference and Dynamic Block Count

Hello,

 

Im trying to get all Block and Dynamic Blocks from my Drawing and the actual Count. But im having a weird issue where the Count of each block is 1 more than Expected. To get the count of the normal BlockReferences im counting the Duplicates. But for the dynamic Blocks im getting the actual count

with var blockCount= anonymousBtr.GetBlockReferenceIds(true, true).Count;

 

What im trying for Normal Blocks:

 

 public static void GetShelfBlock() {
            var acDoc = Application.DocumentManager.MdiActiveDocument;
            var acDb = acDoc.Database;
            var dataCollection = new List<DataModel>();

            using (var tr = acDb.TransactionManager.StartTransaction()) {

                try {
                    var entClass = RXObject.GetClass(typeof(Entity));
                    var modelSpaceId = SymbolUtilityServices.GetBlockModelSpaceId(acDb);
                    var modelSpace = (BlockTableRecord)tr.GetObject(modelSpaceId, OpenMode.ForRead);

                    foreach (var id in modelSpace) {
                        if (!id.ObjectClass.IsDerivedFrom(entClass)) {
                            continue;
                        }

                        var ent = (Entity)tr.GetObject(id, OpenMode.ForRead);
                        if (!ent.GetType().ToString().Contains(typeof(BlockReference).Name)) {
continue; } var reference = ent as BlockReference; if (reference == null) { continue; } var blockReference = reference; if (CheckPattern(blockReference.Name)) { dataCollection.Add(PrepareShelfObject(blockReference)); } } tr.Commit(); tr.Dispose(); dataCollection.AddRange(GetDynamicBlocks(SearchPatterns)); if (dataCollection.Count > 0) { Serialize(dataCollection, DataType.Regale); } } catch (Exception ex) { acDoc.Editor.WriteMessage(ex.Message); } } }

what im trying for Dynamic Blocks where im getting the count with var blockCount= anonymousBtr.GetBlockReferenceIds(true, true).Count;

 

  public static List<DataModel> GetDynamicBlocks() {
            var db = Application.DocumentManager.MdiActiveDocument.Database;
            var dynamicBlockList = new List<DataModel>();
            var tempList = new List<object>();
            using (var trans = db.TransactionManager.StartTransaction()) {
                var bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);

                foreach (var btrId in bt) {

                    var btr = (BlockTableRecord)trans.GetObject(btrId, OpenMode.ForRead);
                    if (!btr.IsDynamicBlock) {
                        continue;
                    }

                    var anonymousIds = btr.GetAnonymousBlockIds();
                    var dynBlockRefs = new ObjectIdCollection();

                    foreach (ObjectId anonymousBtrId in anonymousIds) {
                        var anonymousBtr = (BlockTableRecord)trans.GetObject(anonymousBtrId, OpenMode.ForRead);
                        var blockRefIds = anonymousBtr.GetBlockReferenceIds(true, true);
                        foreach (ObjectId id in blockRefIds) {
                            dynBlockRefs.Add(id);
                        }
                    }

                    if (searchPattern.Any(btr.Name.StartsWith)) {
                        dynamicBlockList.Add(PrepareDynObject(btr));
                    }
                }
                trans.Commit();
                trans.Dispose();
            }
            return dynamicBlockList;
        }

Is there a way to Get all the blocks and there Count ?? Im before giving up i tried everything for 3 days now .... Maybe somebody can help me out.

Thanks

 

 

10 REPLIES 10
Message 2 of 11
Anonymous
in reply to: Anonymous

Looking quickly at your code and post I'm not quite sure I understand, but maybe sharing some code I use might help.

 

The code which prompts user to select a block reference then it selects all instances in the current space, which I think your trying something similar from what I can gather from your code example.

 

Here is command method

 [CommandMethod("HpadSelection", "BLKSS", CommandFlags.Redraw | CommandFlags.Transparent)]
        public void BLKSS()
        {
            PromptEntityOptions peo = new PromptEntityOptions("\nSelect Block Reference");
            peo.SetRejectMessage("\nNot a Block Reference");
            peo.AddAllowedClass(typeof(BlockReference), true);
            peo.AllowObjectOnLockedLayer = true;

            PromptEntityResult per = Ed.GetEntity(peo);

            if (per.Status == PromptStatus.OK)
            {
                using (Transaction trx = Doc.TransactionManager.StartTransaction())
                {
                    BlockReference bref = per.ObjectId.GetDBObject<BlockReference>();
                    BlockTableRecord btr = bref.GetEffectiveBlockTableRecord();

                    var currentSpaceIds = btr.GetAllBlockReferenceIds(true, false).Where<DBObject>(dbo => dbo.OwnerId == Db.CurrentSpaceId);
                    ObjectId[] ids = currentSpaceIds.ToArray();

                    Ed.SetImpliedSelection(ids);
                    Ed.WriteLine("{0} blocks selected", ids.Length);

                    trx.Commit();
                }
            }
            else
            {
                Ed.WriteLine("Exited");
            }
        }

Some supporting extension methods used.

 

        /// <summary>
        /// Method for getting all blockreference Ids
        /// </summary>
        /// <param name="btr">The BTR.</param>
        /// <param name="trx">The TRX.</param>
        /// <param name="directOnly">if set to <c>true</c> [direct only].</param>
        /// <param name="forceValidity">if set to <c>true</c> [force validity].</param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static ObjectIdCollection GetAllBlockReferenceIds(this BlockTableRecord btr, Transaction trx,
            bool directOnly, bool forceValidity)
        {
            if (trx == null)
            {
                throw new Exception(ErrorStatus.NoActiveTransactions);
            }

            ObjectIdCollection blockReferenceIds = btr.GetBlockReferenceIds(directOnly, forceValidity);

            if (!btr.IsDynamicBlock) return blockReferenceIds;
            foreach (ObjectId id in btr.GetAnonymousBlockIds())
            {
                BlockTableRecord record = trx.GetObject(id, OpenMode.ForRead) as BlockTableRecord;
                blockReferenceIds.Add(record.GetBlockReferenceIds(directOnly, forceValidity));
            }
            return blockReferenceIds;
        }

        /// <summary>
        /// Gets all block reference ids.
        /// </summary>
        /// <param name="btr">The BTR.</param>
        /// <param name="directOnly">if set to <c>true</c> [direct only].</param>
        /// <param name="forceValidity">if set to <c>true</c> [force validity].</param>
        /// <returns></returns>
        public static ObjectIdCollection GetAllBlockReferenceIds(this BlockTableRecord btr, bool directOnly,
            bool forceValidity)
        {
            return btr.GetAllBlockReferenceIds(btr.Database.TransactionManager.TopTransaction, directOnly, forceValidity);
        }

 

 

Message 3 of 11
Anonymous
in reply to: Anonymous

Thanks for your time, 

 

Im trying to get a list of all blocks and dynmic blocks and get the count of each block in the drawing,

Im trying everything but failing for 2 days now. 

 

Just need the block names and the count of each block.

Message 4 of 11
_gile
in reply to: Anonymous

Hi,

 

Here's a simple "count by name" example using Linq extension methods.

 

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

            using (var tr = db.TransactionManager.StartOpenCloseTransaction())
            {
                Func<BlockReference, string> getEffectiveName = (br) => 
                    br.IsDynamicBlock ?
                    ((BlockTableRecord)tr.GetObject(br.DynamicBlockTableRecord, OpenMode.ForRead)).Name :
                    br.Name;
                var modelspace = (BlockTableRecord)tr.GetObject(
                    SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);
                var brclass = RXObject.GetClass(typeof(BlockReference));
                var blocks = modelspace
                    .Cast<ObjectId>()
                    .Where(id => id.ObjectClass == brclass)
                    .Select(id => (BlockReference)tr.GetObject(id, OpenMode.ForRead))
                    .GroupBy(br => getEffectiveName(br));
                foreach (var group in blocks)
                {
                    ed.WriteMessage($"\n{group.Key}: {group.Count()}");
                }
                tr.Commit();
            }
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 5 of 11
Anonymous
in reply to: _gile

Thanks you literally saved my Life !!! 🙂

Message 6 of 11
Alexander.Rivilis
in reply to: Anonymous

@_gile

I do not recommend checking IsDynamicBlock property. It is known issue if dynamic block is non-uniform scale its IsDynamicBlock property is false.

http://adn-cis.org/forum/index.php?topic=7275.msg21893#msg21893

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

Message 7 of 11
_gile
in reply to: Alexander.Rivilis

@Alexander.Rivilis

Thanks, I didn't know this.

 

So, the upper code can be simplified like this:

 

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

            using (var tr = db.TransactionManager.StartOpenCloseTransaction())
            {
                var modelSpace = (BlockTableRecord)tr.GetObject(
                    SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);

                var brclass = RXObject.GetClass(typeof(BlockReference));

                var blocks = modelSpace
                    .Cast<ObjectId>()
                    .Where(id => id.ObjectClass == brclass)
                    .Select(id => (BlockReference)tr.GetObject(id, OpenMode.ForRead))
                    .GroupBy(br => ((BlockTableRecord)tr.GetObject(
                        br.DynamicBlockTableRecord, OpenMode.ForRead)).Name);

                foreach (var group in blocks)
                {
                    ed.WriteMessage($"\n{group.Key}: {group.Count()}");
                }
                tr.Commit();
            }
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 8 of 11
Anonymous
in reply to: Alexander.Rivilis

So is checking for IsDynamic wrong? Because the code from _gile works as excpected.

I cant read the site you linked because its in russian 🙂 

 

Will i have problems checking for IsDynamic ? Will i miss some blocks as a result of it? 

Thanks 

Message 9 of 11
Alexander.Rivilis
in reply to: Anonymous


@Anonymous wrote:

Will i have problems checking for IsDynamic ? Will i miss some blocks as a result of it? 

Thanks 


If some of your dynamic block reference has different scale for X, Y or Z axis, then IsDynamic return false instead of true. Also if such dynamic block reference is mirrored then IsDynamic is false. I've sent this issue year ago to ADN DevHelp. @Virupaksha_aithal can confirm this fact.

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

Message 10 of 11
Anonymous
in reply to: Alexander.Rivilis

Thanks for your answer sir.
Without checking IsDynamic in your solution posted above will i also get the names of dynamic blocks ?
Message 11 of 11
_gile
in reply to: Anonymous


valon.k a écrit :
Thanks for your answer sir.
Without checking IsDynamic in your solution posted above will i also get the names of dynamic blocks ?

Yes, if you look at the GroupBy parameter which is a lambda function which returns the name of the block reference DynamicBlockTableRecord (for static blocks, the DynamicBlockTableRecord is equal to the blockTableRecord).

 

Just try it...



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Forma Design Contest


Autodesk Design & Make Report