Delete Block Attributes

Delete Block Attributes

seabrahenrique
Advocate Advocate
1,404 Views
6 Replies
Message 1 of 7

Delete Block Attributes

seabrahenrique
Advocate
Advocate

Hello Guys,

 

I've been try to write a code that simple remove all attributes of a block, and then i'll put new ones.

 

To do that, i tried to clean the AttDefinitions of BlockTableRecord, and then synchronize the attributes like that:

 

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

            PromptEntityOptions promptEntity = new PromptEntityOptions("Selecione o bloco para limpar os atributos");
            PromptEntityResult result = edt.GetEntity(promptEntity);

            if (result.Status == PromptStatus.OK)
            {
                using (Transaction tr = db.TransactionManager.StartTransaction())
                {
                    Entity ent = tr.GetObject(result.ObjectId, OpenMode.ForWrite) as Entity;
                    edt.WriteMessage(ent.GetType().ToString());

                    if (ent is BlockReference br)
                    {
                        BlockTableRecord btr = tr.GetObject(br.BlockTableRecord, OpenMode.ForWrite) as BlockTableRecord;

                        foreach (ObjectId objID in btr)
                        {
                            Entity internalEnty = tr.GetObject(objID, OpenMode.ForWrite) as Entity;

                            if (internalEnty is AttributeDefinition attDef)
                            {
                                attDef.Erase();
                            }
                        }

                        tr.Commit();
                    }
                }

                using (Transaction tr = db.TransactionManager.StartTransaction())
                {
                    BlockReference br = tr.GetObject(result.ObjectId, OpenMode.ForWrite) as BlockReference;

                    BlockTableRecord btr = tr.GetObject(br.BlockTableRecord, OpenMode.ForWrite) as BlockTableRecord;

                    btr.SynchronizeAttributes();

                    tr.Commit();
                }
            }
        }

 

 

Note that i used the extension method of that post to do the Synchronize.

 

The code works perfect, except for one detail: after i run it, the block stay in a state that always i try to do something with they (for example change the scale factors) i face that message bellow:

 

seabrahenrique_1-1713894685223.png

 

Actually, i was ignoring that problem... but i started to face other problems related with that...

 

Mysteriously, when i close and open the drawing the message desapear... and also if i deleted the AttDefinition and use the AutoCAD command "ATTSYNC" i also can "solve" the problem...

 

Even so, I'm looking for a more "solid" solution using .NET itself...

 

Thanks in advance.

0 Likes
1,405 Views
6 Replies
Replies (6)
Message 2 of 7

_gile
Consultant
Consultant

Hi,

Thanks for reporting.

I seems there's an issue after erasing attribute references from the attribute collection.

The AttributeCollection.Count returns 0 but it still contains the ObjectId of one erased attribute reference.

Try this code:

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

    var options = new PromptEntityOptions("\nSelect block reference: ");
    options.SetRejectMessage("\nSelected object is not a block reference.");
    options.AddAllowedClass(typeof(BlockReference), true);
    var result = ed.GetEntity(options);
    if (result.Status != PromptStatus.OK) return;

    using (var tr = db.TransactionManager.StartTransaction())
    {
        var br = (BlockReference)tr.GetObject(result.ObjectId, OpenMode.ForRead);
        var btr = (BlockTableRecord)tr.GetObject(br.BlockTableRecord, OpenMode.ForWrite);
        foreach (ObjectId id in btr)
        {
            if (id.ObjectClass.Name == "AcDbAttributeDefinition")
            {
                var attRef = (AttributeDefinition)tr.GetObject(id, OpenMode.ForWrite);
                attRef.Erase();
            }
        }
        btr.SynchronizeAttributes();

        // Check the AttributeCollection
        ed.WriteMessage($"\nNumber of attribute references = {br.AttributeCollection.Count}");
        foreach (ObjectId id in br.AttributeCollection)
        {
            ed.WriteMessage($"\nAttribute reference {id} IsErased = {id.IsErased}");
        }
        tr.Commit();
    }
}

I haven't yet found a way to solve this problem.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 3 of 7

_gile
Consultant
Consultant

This seems to be an old bug: http://www.theswamp.org/index.php?topic=41945



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 4 of 7

seabrahenrique
Advocate
Advocate

Thanks! That help for now.

0 Likes
Message 5 of 7

denisyukJ
Advocate
Advocate

Hello, @_gile 

I coudn't find SynchronizeAttributes() method in BlockTableRecord class. ACAD 24.

 

BR,

Evgeniy

 

0 Likes
Message 6 of 7

_gile
Consultant
Consultant

@denisyukJ 

SynchronizeAttributes is an extension method I wrote.

The link provided by @seabrahenrique points to a topic that have been archived erased by Autodesk.

You can find a version of the SynchronizeAttributes extension method in the Gile.AutoCAD.Extension library.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 7 of 7

denisyukJ
Advocate
Advocate

@_gile, thank you!

0 Likes