I'm trying to write code for block replacement in C#

I'm trying to write code for block replacement in C#

yoshikazu_satoWU7C6
Participant Participant
460 Views
1 Reply
Message 1 of 2

I'm trying to write code for block replacement in C#

yoshikazu_satoWU7C6
Participant
Participant

I'm new to C# and AutoCAD plug-in development.

I wrote the code to replace the block, but I was able to confirm that SourceBlock does not have Attribute.
I think there is something missing or wrong in this code, can you help me?


What I want to do with this custom command is:

  1. When you start the custom command, you will be prompted to click the replacement source symbol. Click the replacement source symbol.
  2. Click the symbol to replace when prompted to click the symbol to replace (you can also select multiple symbols with range selection)
  3. Symbols are replacemant

I want to do something like this with this code.

I will write the code below.
Waiting for your reply.
thank you

 

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;

namespace BlockReplace
{
    public class Class1
    {
        [CommandMethod("BlockReplace")]
        public static void BolockReplace()
        {


            Document doc = Application.DocumentManager.MdiActiveDocument;
            Editor ed = doc.Editor;

            using (Transaction tr = doc.TransactionManager.StartTransaction())
            {

            // Select block to replace
            PromptEntityOptions peo1 = new PromptEntityOptions("\nSelect source block:");
            peo1.SetRejectMessage("\nPlease select a block.");
            peo1.AddAllowedClass(typeof(BlockReference), true);
            PromptEntityResult per1 = ed.GetEntity(peo1);
            if (per1.Status == PromptStatus.OK)
            {
                ed.WriteMessage("Entity selected: " + per1.ObjectId.ToString());
            }
            else
            {
                ed.WriteMessage("No entity selected.");
            }
            if (per1.Status != PromptStatus.OK || per1.ObjectId.IsNull || per1.ObjectId.IsErased)
            {
                ed.WriteMessage("\nThe selected object is invalid or erased.");
                return;
            }

            BlockReference sourceBlock = per1.ObjectId.GetObject(OpenMode.ForRead) as BlockReference;
                if (sourceBlock == null)
                {
                    ed.WriteMessage("\nError: Could not get source block.");
                    return;
                }


            // Select block to replace
            PromptEntityOptions peo2 = new PromptEntityOptions("\nSelect target block:");
            peo2.SetRejectMessage("\nPlease select a block.");
            peo2.AddAllowedClass(typeof(BlockReference), true);
            PromptEntityResult per2 = ed.GetEntity(peo2);
            if (per2.Status == PromptStatus.OK)
            {
                ed.WriteMessage("Entity selected: " + per2.ObjectId.ToString());
            }
            else
            {
                ed.WriteMessage("No entity selected.");
            }
            if (per1.Status != PromptStatus.OK || per2.ObjectId.IsNull || per2.ObjectId.IsErased)
            {
                ed.WriteMessage("\nThe selected object is invalid or erased.");
                return;
            }
            BlockReference targetBlock = per2.ObjectId.GetObject(OpenMode.ForRead) as BlockReference;
                if (targetBlock == null)
                {
                    ed.WriteMessage("\nError: Could not get target block.");
                    return;
                }


                if(sourceBlock.AttributeCollection.Count == 0)
                {
                    ed.WriteMessage("\nError: Source block does not have any attributes.");
                    return;
                }

                // Replacement
                BlockTable bt = tr.GetObject(doc.Database.BlockTableId, OpenMode.ForRead) as BlockTable;
                foreach (ObjectId id in sourceBlock.AttributeCollection)
                {
                    AttributeReference ar = tr.GetObject(id, OpenMode.ForRead) as AttributeReference;
                    if (ar == null) 
                    {
                        ed.WriteMessage("\nError: Could not get attribute reference.");
                        return;
                    }
                   

                    BlockReference newBlock = new BlockReference(targetBlock.Position, targetBlock.BlockTableRecord);
                    newBlock.Rotation = targetBlock.Rotation;
                    newBlock.ScaleFactors = targetBlock.ScaleFactors;

                    foreach (ObjectId attDefId in newBlock.AttributeCollection)
                    {
                        AttributeReference newAttRef = tr.GetObject(attDefId, OpenMode.ForRead) as AttributeReference;
                        if (newAttRef.Tag == ar.Tag) 
                        {
                            newBlock.UpgradeOpen();
                            newBlock.Position = sourceBlock.Position;
                            newBlock.TransformBy(Matrix3d.Displacement(targetBlock.Position.GetVectorTo(sourceBlock.Position)));
                            newBlock.DowngradeOpen();

                            newAttRef.UpgradeOpen();
                            newAttRef.TextString = ar.TextString;
                            newAttRef.DowngradeOpen();

                            sourceBlock.Erase();

                            ed.WriteMessage("\nSymbol replaced.");
                            break;
                        }
                    }
                }

                tr.Commit();
            }
        }
    }
}

 

0 Likes
461 Views
1 Reply
Reply (1)
Message 2 of 2

a.kouchakzadeh
Advocate
Advocate

Hi, you should be able to start with this.

var doc = Application.DocumentManager.MdiActiveDocument;
            var ed = doc.Editor;
            var db = doc.Database;


            using (var tr= db.TransactionManager.StartTransaction())
            {
                var blockTable = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                var curSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);

                var srcblk = ed.GetEntity("select source block");
                var sourceBlockRef = (BlockReference) tr.GetObject(srcblk.ObjectId,OpenMode.ForRead);
                var srcblkDefID = blockTable[sourceBlockRef.Name];

                var trgetblk = ed.GetEntity("select target block");
                var targetBlockRef = (BlockReference)tr.GetObject(trgetblk.ObjectId, OpenMode.ForRead);
                var trgetblkDef = blockTable[targetBlockRef.Name];


                var tpv = new TypedValue[1];
                tpv.SetValue(new TypedValue((int)DxfCode.BlockName,targetBlockRef.Name), 0);
                var selectionfilter = new SelectionFilter(tpv);
                var blkpsr = ed.SelectAll(selectionfilter);
                var blksset = blkpsr.Value;

                foreach(SelectedObject so in blksset)
                {
                    var blk = (BlockReference)tr.GetObject(so.ObjectId, OpenMode.ForWrite);
                    var newBlkRef = new BlockReference(blk.Position, srcblkDefID);

                    curSpace.AppendEntity(newBlkRef);
                    tr.AddNewlyCreatedDBObject(newBlkRef, true);
                    blk.Erase();
                }



                tr.Commit();


            }

add complexity to your code step by step.
you can set options for your "GetEntity" method.

you can check if the source block does not contain attributes as well.

note that this code does not have any error handling so if you pick a line, instead of a block reference, you will get an exception.