Author Topic: DeepClone VB NET  (Read 4150 times)

0 Members and 1 Guest are viewing this topic.

johnpolob

  • Newt
  • Posts: 29
DeepClone VB NET
« on: November 25, 2015, 05:06:58 AM »
Hi All,

I need to rename some blocks in my drawing with a number extension.

This is not a problem because, my code below does it good.

But when I purge my drawing, all the renamed blocks are disappear.

I don't know if I use the "DeepClone" method properly.

Could someone help me to fix this issue.

All suggestions are welcome.

Thank you in advance.

My code :

Code: [Select]
       
<CommandMethod("test")>
        Public Sub test()

            Dim zDoc As Document = Application.DocumentManager.MdiActiveDocument
            Dim zDb As Database = zDoc.Database
            Dim zEd As Editor = zDoc.Editor


            Using mTrans As Transaction = zDb.TransactionManager.StartTransaction()
                Try
                    Dim mBlkTbl As BlockTable = mTrans.GetObject(zDb.BlockTableId, OpenMode.ForWrite)
                    Dim zBlkTblRec As BlockTableRecord = mTrans.GetObject(mBlkTbl("test"), OpenMode.ForWrite)

                    Dim i As Integer

                    For Each zBlkTableRecId As ObjectId In zBlkTblRec.GetBlockReferenceIds(True, False)

                        Dim BlkRef As BlockReference = mTrans.GetObject(zBlkTableRecId, OpenMode.ForWrite)
                        Dim zMap As New IdMapping
                        Dim newzBlkTblRec As BlockTableRecord = zBlkTblRec.DeepClone(mBlkTbl, zMap, True)

                        newzBlkTblRec.Name = zBlkTblRec.Name & i
                        BlkRef.BlockTableRecord = mBlkTbl.Add(newzBlkTblRec)
                        mTrans.AddNewlyCreatedDBObject(newzBlkTblRec, True)
                        i = i + 1

                    Next

                Catch ex As SystemException
                    MsgBox(ex.Message.ToString, MsgBoxStyle.Critical, "Rename block.")
                End Try

                mTrans.Commit()

            End Using

        End Sub
« Last Edit: November 25, 2015, 05:59:58 AM by johnpolob »

CADbloke

  • Bull Frog
  • Posts: 342
  • Crash Test Dummy
Re: DeepClone VB NET
« Reply #1 on: November 25, 2015, 05:21:52 AM »
Purge will purge all block definitions which don't have at least one Block Reference inserted into the drawing. You've added the new definitions to the block table but you haven't saved the changes to the BlkRef Block References.

To prove this, check the Block Insertions' Block Names in the Properties palette.

But I don't see why you would want to have a lot of duplicate block definitions, could you just add an Attribute to the block and use that to identify each Insertion by name?

johnpolob

  • Newt
  • Posts: 29
Re: DeepClone VB NET
« Reply #2 on: November 25, 2015, 06:16:20 AM »
Hi CADbloke,

Thank you for your fast reply.

I need to rename each block like this by example if the name of the block is "TEST" , all the blocks which are the same name will be renamed as "TEST0", "TEST1", "TEST2" etc. My code does it good.

I see all the renamed blocks in the Block Insertions palette.

When I try to save my drawing, I have the message below on the AutoCAD Text Window : "*Warning* Multiply owned object, handle "193AE""

Could you show me how to save the the changes to the BlkRef Block References?

May be it's my issue.

Thanks.
« Last Edit: November 25, 2015, 06:35:15 AM by johnpolob »

johnpolob

  • Newt
  • Posts: 29
Re: DeepClone VB NET
« Reply #3 on: November 25, 2015, 06:44:34 AM »
Could somebody help me please?

MexicanCustard

  • Swamp Rat
  • Posts: 705
Re: DeepClone VB NET
« Reply #4 on: November 25, 2015, 07:37:58 AM »
There are two parts to a block.
1. The BlockTableRecord, it's the definition located in the BlockTable of the Database
2. The BlockReference, it's the entity you see in ModelSpace/PaperSpace and it references the BlockTableRecord

If there are no BlockReferences referring back to your BlockTableRecord then when you purge, all your BlockTableRecords will be removed.  You have to change all the existing BlockReferences to point to your new BlockTableRecords.

I wouldn't use DeepClone for this application.  I would create new BlockTableRecords and just modify the existing BlockReferences.
Revit 2019, AMEP 2019 64bit Win 10

johnpolob

  • Newt
  • Posts: 29
Re: DeepClone VB NET
« Reply #5 on: November 25, 2015, 07:58:58 AM »
Hi MexicanCustard,

Thank you for your reply.

Do you have an example please?

Thanks.

johnpolob

  • Newt
  • Posts: 29
Re: DeepClone VB NET
« Reply #6 on: November 25, 2015, 09:58:43 AM »
Please need your help.

Thanks.

MexicanCustard

  • Swamp Rat
  • Posts: 705
Re: DeepClone VB NET
« Reply #7 on: November 25, 2015, 10:12:03 AM »
Sorry, I was thinking you could explode and create a new BlockTableRecord but that wouldn't work if you're keeping the original block. So DeepCloning is the way to go.  You just needed to clone the BlockTableRecord not the BlockReferences.

Code - C#: [Select]
  1. var db = Application.DocumentManager.MdiActiveDocument.Database;
  2. using (var tr = db.TransactionManager.StartTransaction())
  3. {
  4.     var bt = (BlockTable) tr.GetObject(db.BlockTableId, OpenMode.ForWrite);
  5.     var ms = (BlockTableRecord) tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead);
  6.  
  7.     var testBlock = (BlockTableRecord) tr.GetObject(bt["test"], OpenMode.ForRead);
  8.     var newBlock = (BlockTableRecord) testBlock.DeepClone(bt, new IdMapping(), true);
  9.     tr.AddNewlyCreatedDBObject(newBlock, true);
  10.  
  11.     var references = testBlock.GetBlockReferenceIds(true, false);
  12.     foreach (var reference in references.Cast<ObjectId>())
  13.     {
  14.         var blockReference = (BlockReference) tr.GetObject(reference, OpenMode.ForWrite);
  15.         blockReference.BlockTableRecord = newBlock.ObjectId;
  16.     }
  17.     tr.Commit();
  18. }
Revit 2019, AMEP 2019 64bit Win 10

johnpolob

  • Newt
  • Posts: 29
Re: DeepClone VB NET
« Reply #8 on: November 25, 2015, 10:25:52 AM »
Thank you MexicanCustard,

I will adapt it and let you know whether is good.

I think is enough to start working.

johnpolob

  • Newt
  • Posts: 29
Re: DeepClone VB NET
« Reply #9 on: November 25, 2015, 11:05:29 AM »
Hi MexicanCustard,

I have a same problem when I purge my drawing --> all the blocks are disappear.

Could you check it on your machine?

Thank you very much.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: DeepClone VB NET
« Reply #10 on: November 25, 2015, 11:24:31 AM »
johnpolob,

Please post a sample drawing and re-state the problem.

kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Atook

  • Swamp Rat
  • Posts: 1027
  • AKA Tim
Re: DeepClone VB NET
« Reply #11 on: November 25, 2015, 12:20:03 PM »
John, MC is pointing you in the right direction.

You are probably creating the new block definition properly, but there are no insertions of the block in the drawing. The previous insertions are probably the old block definition.

I see at least two possibilities,

  • redefine the block definition (this should update the insertions of this block) (modify BlockTableRecord)
  • add new block definition, and update old insertions to the new definition (add BlockTableRecord] modify BlockReference

johnpolob

  • Newt
  • Posts: 29
Re: DeepClone VB NET
« Reply #12 on: November 25, 2015, 01:10:40 PM »
Hi Kerry,

See in attachment the sample drawing.

I need to rename some blocks in my drawing with a number extension.

This is not a problem because, my code below does it good.

But when I purge my drawing, all the renamed blocks are disappear.

I don't know if I use the "DeepClone" method properly.

Could someone help me to fix this issue.

All suggestions are welcome.

Thank you in advance.

Code: [Select]
<CommandMethod("test")>
        Public Sub test()

            Dim zDoc As Document = Application.DocumentManager.MdiActiveDocument
            Dim zDb As Database = zDoc.Database
            Dim zEd As Editor = zDoc.Editor


            Using mTrans As Transaction = zDb.TransactionManager.StartTransaction()
                Try
                    Dim mBlkTbl As BlockTable = mTrans.GetObject(zDb.BlockTableId, OpenMode.ForWrite)
                    Dim zBlkTblRec As BlockTableRecord = mTrans.GetObject(mBlkTbl("test"), OpenMode.ForWrite)

                    Dim i As Integer

                    For Each zBlkTableRecId As ObjectId In zBlkTblRec.GetBlockReferenceIds(True, False)

                        Dim BlkRef As BlockReference = mTrans.GetObject(zBlkTableRecId, OpenMode.ForWrite)
                        Dim zMap As New IdMapping
                        Dim newzBlkTblRec As BlockTableRecord = zBlkTblRec.DeepClone(mBlkTbl, zMap, True)

                        newzBlkTblRec.Name = zBlkTblRec.Name & i
                        BlkRef.BlockTableRecord = mBlkTbl.Add(newzBlkTblRec)
                        mTrans.AddNewlyCreatedDBObject(newzBlkTblRec, True)
                        i = i + 1

                    Next

                Catch ex As SystemException
                    MsgBox(ex.Message.ToString, MsgBoxStyle.Critical, "Rename block.")
                End Try

                mTrans.Commit()

            End Using

        End Sub
« Last Edit: November 25, 2015, 01:14:58 PM by johnpolob »

johnpolob

  • Newt
  • Posts: 29
Re: DeepClone VB NET
« Reply #13 on: November 25, 2015, 01:13:36 PM »
Hi Atook,

I understand but I have already try to do that but no no success.

Could you show me an example?

Thanks.

CADbloke

  • Bull Frog
  • Posts: 342
  • Crash Test Dummy
Re: DeepClone VB NET
« Reply #14 on: November 25, 2015, 05:00:26 PM »
I need to rename each block like this by example if the name of the block is "TEST" , all the blocks which are the same name will be renamed as "TEST0", "TEST1", "TEST2" etc. My code does it good.
I think you need to name the different block References with an Attribute. It does not make sense to me to have many duplicate definitions of exactly the same thing just to give them a different name. It would be the same (in code) as copy-pasting exactly the same code to create a new static class every time you wanted a new instance of exactly the same thing with a different name.

Your real problem seems to be how do you identify each different block reference. Use a property in the block to name it. An Attribute is the easiest way to do this. Make sure the Attribute is not a Constant Attribute.