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

Get all dynamic block definitions names and all of their visibilities names

3 REPLIES 3
SOLVED
Reply
Message 1 of 4
bsaidiDG51
363 Views, 3 Replies

Get all dynamic block definitions names and all of their visibilities names

I'm implementing a macro with the purpose to export the names of all blocks in a drawing, wether they're present in the model space or not.

The issue I'm encountring is when I try to include the visibilities of the dynamic blocks in the export.

So I would appreciate if anyone could help show me how to collect the information about the visibilities of a dynamic block. Thank you in advance.

 

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

    // Get the path of the open drawing file
    string drawingPath = db.Filename;
    string csvFilePath = drawingPath.Replace(".dwg", " Blocks.csv"); 

    List<string> blockNames = new List<string>();

    using (Transaction tr = db.TransactionManager.StartTransaction())
    {
        // Open the block table
        BlockTable blockTable = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
        if (blockTable != null)
        {
            // Iterate through each block table record (block definition)
            foreach (ObjectId btrId in blockTable)
            {
                BlockTableRecord btr = tr.GetObject(btrId, OpenMode.ForRead) as BlockTableRecord;
                if (btr == null || btr.IsLayout || btr.IsAnonymous)
                {
                    continue;
                }

                blockNames.Add(btr.Name);

                if (btr.IsDynamicBlock)
                {
                    //INSERT CODE HERE WHERE YOU ADD THE VISIBILITIES OF THE DYNAMIC BLOCK TO THE LIST blockNames.

                }
            }
        }

        tr.Commit();
    }
    _exportListToCsv(blockNames, csvFilePath);
}
3 REPLIES 3
Message 2 of 4
stefanome
in reply to: bsaidiDG51

I think you need to work with a BlockReference, not with a BlockTableRecord, and then iterate blockReference.DynamicBlockReferencePropertyCollection.

 

If you don't have any references already inserted, then you can insert one temporarily, look at the list and delete it.

Message 3 of 4
_gile
in reply to: bsaidiDG51

Hi,

 

To get the dynamic properties of a block definition, you can use its DXF data.

Here's a example using some extension methods

 

Extension methods

using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;

using AcRx = Autodesk.AutoCAD.Runtime;

namespace DynamicBlockPropertyExtension
{
    public static class Extension
    {
        // Replace the DLL name according to the AutoCAD targeted version
        // 2013-2014:   "acdb19.dll"
        // 2015-2016:   "acdb20.dll"
        // 2017:        "acdb21.dll"
        // 2018:        "acdb22.dll"
        // 2019-2020:   "acdb23.dll"
        // 2021-2024:   "acdb24.dll"
        // Replace the EntryPoint according to AutoCAD plateform
        // 32 bits:     "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AAY01JVAcDbObjectId@@@Z"
        // 64 bits:     "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AEAY01_JVAcDbObjectId@@@Z"
        [System.Security.SuppressUnmanagedCodeSecurity]
        [DllImport("acdb24.dll", CallingConvention = CallingConvention.Cdecl,
            EntryPoint = "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AEAY01_JVAcDbObjectId@@@Z")]
        static extern AcRx.ErrorStatus acdbGetAdsName(out AdsName ename, ObjectId id);

        [System.Security.SuppressUnmanagedCodeSecurity]
        [DllImport("accore.dll", CallingConvention = CallingConvention.Cdecl,
            EntryPoint = "acdbEntGet")]
        static extern IntPtr acdbEntGet(AdsName ename);

        public static ResultBuffer EntGet(ObjectId id)
        {
            var errorStatus = acdbGetAdsName(out AdsName ename, id);
            if (errorStatus != AcRx.ErrorStatus.OK)
                throw new AcRx.Exception(errorStatus);
            var result = acdbEntGet(ename);
            if (result != IntPtr.Zero)
                return ResultBuffer.Create(result, true);
            return null;
        }

        public static IEnumerable<IEnumerable<TypedValue>> GetDynamicPropertiesDxfData(this BlockTableRecord btr, Transaction tr)
        {
            if (btr == null)
                throw new ArgumentNullException(nameof(btr));
            if (tr == null)
                throw new ArgumentNullException(nameof(tr));
            var xDictId = btr.ExtensionDictionary;
            if (xDictId.IsNull)
                throw new Exception("eNoExtensionDictionary");
            var xDict = (DBDictionary)tr.GetObject(xDictId, OpenMode.ForRead);
            if (!xDict.Contains("ACAD_ENHANCEDBLOCK"))
                throw new Exception("eNotDynamicBlock");
            var resbuf = EntGet(xDict.GetAt("ACAD_ENHANCEDBLOCK"));
            if (resbuf == null)
                throw new AcRx.Exception(AcRx.ErrorStatus.InvalidResultBuffer);
            return resbuf.Cast<TypedValue>()
                .Where(tv => tv.TypeCode == 360)
                .Select(tv => EntGet((ObjectId)tv.Value).Cast<TypedValue>());
        }

        public static T GetValue<T>(this IEnumerable<TypedValue> typedValues, short typeCode) =>
            (T)typedValues.First(tv => tv.TypeCode == typeCode).Value;

        public static IEnumerable<T> GetValues<T>(this IEnumerable<TypedValue> typedValues, short typeCode) =>
            typedValues.Where(tv => tv.TypeCode == typeCode).Select(tv => (T)tv.Value);
    }
}

 

Command example:

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

            using (var tr = db.TransactionManager.StartTransaction())
            {
                var blockTable = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                foreach (ObjectId id in blockTable)
                {
                    var btr = (BlockTableRecord)tr.GetObject(id, OpenMode.ForRead);
                    if (btr.IsLayout || 
                        btr.IsAnonymous || 
                        btr.IsDependent || 
                        btr.IsFromExternalReference || 
                        btr.IsFromOverlayReference)
                        continue;
                    ed.WriteMessage($"\nBlock name: {btr.Name}");
                    if (btr.IsDynamicBlock)
                    {
                        var visibParam = btr.GetDynamicPropertiesDxfData(tr)
                            .FirstOrDefault(tvs => tvs.GetValue<string>(0) == "BLOCKVISIBILITYPARAMETER");
                        if (visibParam != null)
                        {
                            ed.WriteMessage($"\n\tVisibilty parameter name: {visibParam.GetValue<string>(301)}" +
                                $"\n\t\tAllowed values:");
                            foreach (string value in visibParam.GetValues<string>(303))
                            {
                                ed.WriteMessage($"\n\t\t- {value}");
                            }
                        }
                    }
                }
                tr.Commit();
            }
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 4 of 4
bsaidiDG51
in reply to: _gile

Merci boss!

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

Post to forums  

AutoCAD Inside the Factory


Autodesk Design & Make Report