.NET

Reply
Active Contributor
RichardCammeray
Posts: 43
Registered: ‎12-08-2010
Message 1 of 15 (379 Views)

Copy of BlockTableRecord (save as)

379 Views, 14 Replies
08-30-2012 05:49 PM

I would like to ask question how to mimic Block Definition Save As function.

So far what I have found in this forum and TheSwamp the best way is to use DeepClone of BlockTableRecord but the objects in original BlockTableRecord need to be DeepCloneObjectes into new block. Otherwise new block will have all objects  with ObjectId from old BlockTabkeRecord

Is that right way how to do it or is there some simpler solution.

 

Thanks,

Richard

ADN Support Specialist
Posts: 349
Registered: ‎05-22-2006
Message 2 of 15 (345 Views)

Re: Copy of BlockTableRecord (save as)

08-31-2012 01:09 PM in reply to: RichardCammeray

Can't you just use Database.WBlockCloneObjects()?

 

 

Cheers,

Stephen Preston
Autodesk Developer Network
Active Contributor
RichardCammeray
Posts: 43
Registered: ‎12-08-2010
Message 3 of 15 (303 Views)

Re: Copy of BlockTableRecord (save as)

09-02-2012 04:33 PM in reply to: StephenPreston

Database.WBlockCloneObjects can be used to copy objects between two databases.

In my case I need to make copy of BlockTableRecord in the same database.

 

Any another idea?

 

Thanks.

*Expert Elite*
Hallex
Posts: 1,561
Registered: ‎10-08-2008
Message 4 of 15 (285 Views)

Re: Copy of BlockTableRecord (save as)

09-02-2012 10:08 PM in reply to: RichardCammeray

I thought you need to deepclone main block first,

then deepclone embedded block in the newly created

copy of main instance

, just an idea sorry

 

~'J'~

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Active Contributor
RichardCammeray
Posts: 43
Registered: ‎12-08-2010
Message 5 of 15 (279 Views)

Re: Copy of BlockTableRecord (save as)

09-02-2012 11:37 PM in reply to: Hallex

Thanks for hint but unfortunately my block consists only single entities (line, text).

But let me explain the problem is simple steps.

 

1)You have BlockTableRecord with one Line only

2)DeepClone this BlockTableRecord

3)Get ObjectId of Line in newly created BlockTable and change the length

4) As result the line will change the length in both old and new BlockTable.

 

As it was mention somewhere in this forum DeepClone of BlockTableRecord apparently does not translate ObjectIds of cloned Entities inside of new BlockTableRecord.

 

*Expert Elite*
Hallex
Posts: 1,561
Registered: ‎10-08-2008
Message 6 of 15 (274 Views)

Re: Copy of BlockTableRecord (save as)

09-03-2012 12:32 AM in reply to: RichardCammeray

Hi Richard,

Here is a sample code how to clone block

with embeddingan another block to the same copy

Try to rewrite it to your needs, this one is from my oldies,

so I haven't have tested it enough, sorry

 

    [CommandMethod("CopyXBref")]
        public void testCopyBlockReference()
        {
            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                PromptEntityOptions peo = new PromptEntityOptions("\nSelect main block instance to copy: ");
                peo.SetRejectMessage("\nMust be a type of the BlockReference!");
                peo.AddAllowedClass(typeof(BlockReference), true);
                PromptEntityResult per = ed.GetEntity(peo);

                if (per.Status != PromptStatus.OK) return;

                BlockReference bref = (BlockReference)tr.GetObject(per.ObjectId, OpenMode.ForRead);
                BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bref.BlockTableRecord, OpenMode.ForRead);
                ed.WriteMessage("\nBlock Selected with name: {0}", btr.Name);
                PromptStringOptions pso = new PromptStringOptions("\nEnter new block name: ");
                pso.AllowSpaces = true;
                PromptResult sres = ed.GetString(pso);
                if (sres.Status != PromptStatus.OK) return;
                string newname = sres.StringResult;
                if (bt.Has(newname))
                {
                    ed.WriteMessage("\nBlock with name: {0} already exist, try again", newname);
                    return;
                }

                BlockTableRecord newbtr = new BlockTableRecord();
                bt.UpgradeOpen();

                newbtr = (BlockTableRecord)btr.DeepClone(bt, new IdMapping(), true);

                newbtr.Name = newname;
                bt.Add(newbtr);
                //----------------------------------------------------------------//
                peo.Message = "\nSelect block instance to be embedded to main block: ";
                per = ed.GetEntity(peo);
                if (per.Status != PromptStatus.OK) return;
                BlockReference xbref = (BlockReference)tr.GetObject(per.ObjectId, OpenMode.ForRead);
                BlockTableRecord xbtr = (BlockTableRecord)tr.GetObject(xbref.BlockTableRecord, OpenMode.ForRead);
                
                PromptPointOptions ppo = new PromptPointOptions("\nSpecify a new location of embedded block: ");
                PromptPointResult ppr = ed.GetPoint(ppo);
                if (ppr.Status != PromptStatus.OK) return;
                Point3d pt = ppr.Value;
              
                foreach (ObjectId id in newbtr)
                {
                    Entity ent = tr.GetObject(id, OpenMode.ForRead) as Entity;
                    if (ent == null)continue;                   
                    ent.UpgradeOpen();
                    ent.ColorIndex = 0;
                }
      
               foreach (ObjectId eid in xbtr)
               {
                   Entity xent = tr.GetObject(eid, OpenMode.ForRead) as Entity;
                   if (xent == null)continue;
                   
                   xent.UpgradeOpen();
                   xent.ColorIndex = 0;

                   DBObject obj=((DBObject)xent).DeepClone(newbtr, new IdMapping(), true);
                   ((Entity)obj).TransformBy(Matrix3d.Displacement(pt - bref.Position));
               }
               tr.AddNewlyCreatedDBObject(newbtr, true);

                tr.Commit();
                
            }
        }

 

~'J'~

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
*Expert Elite*
Hallex
Posts: 1,561
Registered: ‎10-08-2008
Message 7 of 15 (263 Views)

Re: Copy of BlockTableRecord (save as)

09-03-2012 01:36 AM in reply to: RichardCammeray

Richard,

You can change the subentity properties easily,

see example, just change void name, command name

and default length of line to your needs:

 

    [CommandMethod("reline")]
        static public void SwapSubEntity()
        {
            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            Transaction tr = doc.TransactionManager.StartTransaction();
            using (tr)
            {
                PromptNestedEntityOptions pno = new PromptNestedEntityOptions("\nSelect Line >>");
                pno.AllowNone = false;
                PromptNestedEntityResult rs = ed.GetNestedEntity(pno);
                if (rs.Status != PromptStatus.OK)
                    return;
                Entity selent = (Entity)tr.GetObject(rs.ObjectId, OpenMode.ForWrite);
                BlockTableRecord btrec = tr.GetObject(selent.OwnerId, OpenMode.ForWrite) as BlockTableRecord;
                Line ln = selent as Line;
                if (ln != null)
                {

                 if (!ln.IsWriteEnabled)   ln.UpgradeOpen();
                 double leg = ln.Length;
                 PromptDoubleOptions pdo = new PromptDoubleOptions("\nSpecify new line length: ");
                 pdo.AllowNegative = false;
                 pdo.AllowZero = false;
                 pdo.AllowNone = true;
                 pdo.DefaultValue = 12;
                 PromptDoubleResult res = ed.GetDouble(pdo);
                 if (res.Status != PromptStatus.OK && res.Status != PromptStatus.Keyword) return;
                 double newleg = res.Value;
                 ln.TransformBy(Matrix3d.Scaling(newleg / leg, ln.StartPoint));     
                    btrec.DowngradeOpen();

                }
                doc.TransactionManager.QueueForGraphicsFlush();

                doc.TransactionManager.FlushGraphics();

                doc.Editor.UpdateScreen();

                tr.Commit();

                ed.Regen();
            }
        }

 

Then you can clone this block as I've wrote above,

let me know if you need more help

 

~'J'~

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Active Contributor
RichardCammeray
Posts: 43
Registered: ‎12-08-2010
Message 8 of 15 (233 Views)

Re: Copy of BlockTableRecord (save as)

09-03-2012 07:16 PM in reply to: Hallex

Hi Hallex,

I think I found what problem is in my case.

Probably I should mention on the beginning that I need to also change BlockReference.BlockTableRecord once a new BlockTable is created.

I modified your first example and at the end I added line to change BlockReference.

 

Could you please try create block with some lines and insert at least two blocks into drawing and try run modified CopyXBref command on one block.

When I run REGEN command lines change colour  in both (old and new) blocks

 

Thanks for your examples.

Richard.

 

 

[CommandMethod("CopyXBref")]
        public void testCopyBlockReference()
        {
            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                PromptEntityOptions peo = new PromptEntityOptions("\nSelect main block instance to copy: ");
                peo.SetRejectMessage("\nMust be a type of the BlockReference!");
                peo.AddAllowedClass(typeof(BlockReference), true);
                PromptEntityResult per = ed.GetEntity(peo);

                if (per.Status != PromptStatus.OK) return;

                BlockReference bref = (BlockReference)tr.GetObject(per.ObjectId, OpenMode.ForWrite);
                BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bref.BlockTableRecord, OpenMode.ForRead);
                ed.WriteMessage("\nBlock Selected with name: {0}", btr.Name);
                PromptStringOptions pso = new PromptStringOptions("\nEnter new block name: ");
                pso.AllowSpaces = true;
                PromptResult sres = ed.GetString(pso);
                if (sres.Status != PromptStatus.OK) return;
                string newname = sres.StringResult;
                if (bt.Has(newname))
                {
                    ed.WriteMessage("\nBlock with name: {0} already exist, try again", newname);
                    return;
                }

                BlockTableRecord newbtr = new BlockTableRecord();
                bt.UpgradeOpen();

                newbtr = (BlockTableRecord)btr.DeepClone(bt, new IdMapping(), true);

                newbtr.Name = newname;
                bt.Add(newbtr);
                //----------------------------------------------------------------//

                foreach (ObjectId id in newbtr)
                {
                    Entity ent = tr.GetObject(id, OpenMode.ForRead) as Entity;
                    if (ent == null) continue;
                    ent.UpgradeOpen();
                    ent.ColorIndex = 0;
                }


                tr.AddNewlyCreatedDBObject(newbtr, true);

 

                //Change BlockReference
                bref.BlockTableRecord = newbtr.Id;

 

                tr.Commit();

            }
        }

 

*Expert Elite*
Hallex
Posts: 1,561
Registered: ‎10-08-2008
Message 9 of 15 (221 Views)

Re: Copy of BlockTableRecord (save as)

09-03-2012 09:50 PM in reply to: RichardCammeray

In this case you have to change properties

of all subentities inside the both BlockTableRecords,

try this one

 

        [CommandMethod("CopyXBref")]
        public void testCopyBlockReference()
        {
            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                PromptEntityOptions peo = new PromptEntityOptions("\nSelect main block instance to copy: ");
                peo.SetRejectMessage("\nMust be a type of the BlockReference!");
                peo.AddAllowedClass(typeof(BlockReference), true);
                PromptEntityResult per = ed.GetEntity(peo);

                if (per.Status != PromptStatus.OK) return;

                BlockReference bref = (BlockReference)tr.GetObject(per.ObjectId, OpenMode.ForWrite);

                BlockTableRecord bdef = (BlockTableRecord)tr.GetObject(bref.BlockTableRecord, OpenMode.ForRead);
                foreach (ObjectId id in bdef)
                {
                    Entity ent = tr.GetObject(id, OpenMode.ForRead) as Entity;
                    if (ent == null) continue;
                    ent.UpgradeOpen();
                    ent.ColorIndex = 1;
                }
               // BlockTableRecord cursp = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                ed.WriteMessage("\nBlock Selected with name: {0}", bdef.Name);
                PromptStringOptions pso = new PromptStringOptions("\nEnter new block name: ");
                pso.AllowSpaces = true;
                PromptResult sres = ed.GetString(pso);
                if (sres.Status != PromptStatus.OK) return;
                string newname = sres.StringResult;
                if (bt.Has(newname))
                {
                    ed.WriteMessage("\nBlock with name: {0} already exist, try again", newname);
                    return;
                }

                BlockTableRecord newbtr = new BlockTableRecord();
                bt.UpgradeOpen();

                newbtr = (BlockTableRecord)bdef.DeepClone(bt, new IdMapping(), true);

                newbtr.Name = newname;
                bt.Add(newbtr);
                //----------------------------------------------------------------//

                foreach (ObjectId id in newbtr)
                {
                    Entity ent = tr.GetObject(id, OpenMode.ForRead) as Entity;
                    if (ent == null) continue;
                    ent.UpgradeOpen();
                    ent.ColorIndex = 1;
                }


                tr.AddNewlyCreatedDBObject(newbtr, true);

 

                //Change BlockReference
                bref.BlockTableRecord = newbtr.Id;


                ed.Regen();
                tr.Commit();

            }
        }

 

~'J'~

 

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Active Contributor
RichardCammeray
Posts: 43
Registered: ‎12-08-2010
Message 10 of 15 (215 Views)

Re: Copy of BlockTableRecord (save as)

09-03-2012 10:09 PM in reply to: Hallex

I think you misunderstood my last message.

I don’t want to change original block at all. What I was trying to show you in my example is that changing of colour of entities in new block will change colour of entities in original block (that is what I do not want).

 

Thanks,

Richard

You are not logged in.

Log into access your profile, ask and answer questions, share ideas and more. Haven't signed up yet? Register

Announcements
Are you interested in helping shape the Autodesk Community?
We’re looking at a few different ways to improve the “All Forums” landing page and need your feedback! If interested, please take a few minutes to fill out the following Usability Study. Thank you for your time!

Need installation help?

Start with some of our most frequented solutions to get help installing your software.

Ask the Community