TheSwamp

Code Red => .NET => Topic started by: slappy on August 12, 2010, 04:04:53 PM

Title: Block Replace - Simple question. Complex answer?
Post by: slappy on August 12, 2010, 04:04:53 PM
Looking for the method to replace an existing block with an another definition.

In active drawing, BlockB already exist, replace BlockA with BlockB.

doing this in VB.Net

I'm attempted to rename BlockA via it's BTR, but I get a "eDuplicateRecordName".  I understand why it's erroring just not how to work around it.

All comments appreciated.

Thanks
Chris
Title: Re: Block Replace - Simple question. Complex answer?
Post by: David Hall on August 12, 2010, 04:24:38 PM
I thik you are going to have to search for all instances of A and erase/Replace with B
Title: Re: Block Replace - Simple question. Complex answer?
Post by: David Hall on August 12, 2010, 04:25:28 PM
I guess it should be said that when you grab each instance of A, you get the insertion point and scale and rotation, then erase, insert B and apply captured values.
Title: Re: Block Replace - Simple question. Complex answer?
Post by: mohnston on August 12, 2010, 05:56:35 PM
BlockReference objects have a BlockTableRecord property that can be set.
I haven't tried that but it's worth a shot.
Title: Re: Block Replace - Simple question. Complex answer?
Post by: David Hall on August 12, 2010, 06:06:49 PM
mark, I thought there was something like that, but I couldn't find it.  Having said that, I think I was looking in the wrong spot
Title: Re: Block Replace - Simple question. Complex answer?
Post by: Bryco on August 12, 2010, 09:21:08 PM
db.WblockCloneObjects(new ObjectIdCollection(new ObjectId[] { bt[btr.Name] }),
                    db.BlockTableId, new IdMapping(), DuplicateRecordCloning.Replace, false);

Try this, I use it to updaye blocks in an xref from another drawing.
Title: Re: Block Replace - Simple question. Complex answer?
Post by: LE3 on August 12, 2010, 09:47:45 PM
don't eat vbnet, just c#, but you can do something in the steps below:
1. make a selection of the blocks to change.
2. open for read the block source.
3. open forr write modelspace block table record.
4. then go over all the object ids in the selection set and open for write each BlockReference and just set the BlockTableRecord to the block source object id.
maybe?
Title: Re: Block Replace - Simple question. Complex answer?
Post by: Jeff H on August 13, 2010, 12:55:12 AM
Threw this together real quick but is a simple example to get you started

Create a new drawing and draw a circle then create new block named "C" then insert multiple references

Create a rectangle and create a block named "Rec"

Then run this code and all circles will turn into rectangle

Code: [Select]
  <CommandMethod("ReplaceBlocks")> _
    Public Sub ReplaceBlocks()
        Dim db As Database = HostApplicationServices.WorkingDatabase
        Using tr As Transaction = db.TransactionManager.StartTransaction
            Dim bt As BlockTable = db.BlockTableId.GetObject(OpenMode.ForRead)
            Dim btrCircle As BlockTableRecord = bt("C").GetObject(OpenMode.ForRead)
            Dim btrRectangle As BlockTableRecord = bt("Rec").GetObject(OpenMode.ForRead)
            Dim objIdColl As ObjectIdCollection = btrCircle.GetBlockReferenceIds(True, False)
            For Each objId As ObjectId In objIdColl
                Dim bref As BlockReference = objId.GetObject(OpenMode.ForWrite)
                bref.BlockTableRecord = btrRectangle.ObjectId
            Next
            tr.Commit()
        End Using
    End Sub


Title: Re: Block Replace - Simple question. Complex answer?
Post by: Jeff H on August 13, 2010, 01:10:33 AM
Also using the code above will use each individual references scale and rotation
Title: Re: Block Replace - Simple question. Complex answer?
Post by: Glenn R on August 13, 2010, 08:48:43 AM
Attributes anyone?
Title: Re: Block Replace - Simple question. Complex answer?
Post by: Jeff H on August 13, 2010, 09:01:08 AM
Also That simple example did not take in consideration of dynamic Blocks
Title: Re: Block Replace - Simple question. Complex answer?
Post by: kaefer on August 13, 2010, 09:06:06 AM
Attributes anyone?

What about them? Did you try ATTSYNC on a block reference when the definition contains none?

<alien> Der gewählte Block verfügt über keine Attribute.</alien>  The choosen block has no attributes. Such lies.

Cheers, Thorsten
Title: Re: Block Replace - Simple question. Complex answer?
Post by: slappy on August 13, 2010, 10:42:07 AM

Code: [Select]
                bref.BlockTableRecord = btrRectangle.ObjectId

This was the bit I was looking for.  I'll work my code around this idea and see what hatches.  Thanks fro.

To touch on some of the other comments.
No dynamics
No Attributes
Block is cloned from side database then used to replace in active file.  No selection needed.

don't eat vbnet, just c#

I like VB.Net, It stems from my early basic days.  c# is just odd.  I can understand it but it's more of a coders code, and I'm just a small time hacker.

Thanks all for your input.

Chris
Title: Re: Block Replace - Simple question. Complex answer?
Post by: Bryco on August 13, 2010, 12:58:36 PM
In that case you may want to use WblockCloneObjects (which was totally inappropriate before).
If you open the database,grab the entities from the block b,  WblockCloneObjects those enties to the new drawing database (neither need to be open) block a. Then rename the block if necessary.
Title: Re: Block Replace - Simple question. Complex answer?
Post by: slappy on August 13, 2010, 05:29:59 PM
In that case you may want to use WblockCloneObjects (which was totally inappropriate before).
If you open the database,grab the entities from the block b,  WblockCloneObjects those enties to the new drawing database (neither need to be open) block a. Then rename the block if necessary.

I am using WblockCloneObjects, however, I can only add the block to the database, Its the replacing part that is throwing me.

Chris
Title: Re: Block Replace - Simple question. Complex answer?
Post by: Jeff H on August 13, 2010, 06:02:38 PM
Code: [Select]
<CommandMethod("ReplaceBlocksFromExternal")> _
    Public Sub ReplaceBlocksFromExternal()
        Dim db As Database = HostApplicationServices.WorkingDatabase
        Dim extDB As New Database(False, True)
        extDB.ReadDwgFile("C:\Users\Jeff\Desktop\Test.dwg", FileOpenMode.OpenForReadAndAllShare, True, "")
        Using tr As Transaction = db.TransactionManager.StartTransaction
            Using extTr As Transaction = extDB.TransactionManager.StartTransaction
                Dim bt As BlockTable = db.BlockTableId.GetObject(OpenMode.ForRead)
                Dim extBT As BlockTable = extDB.BlockTableId.GetObject(OpenMode.ForRead)
                Dim btrCircle As BlockTableRecord = bt("C").GetObject(OpenMode.ForRead)
                Dim btrRectangle As BlockTableRecord = extBT("Rec").GetObject(OpenMode.ForRead)
                Dim map As New IdMapping
                Dim extobjIdColl As New ObjectIdCollection
                extobjIdColl.Add(btrRectangle.ObjectId)
                db.WblockCloneObjects(extobjIdColl, bt.ObjectId, map, _
                                                   DuplicateRecordCloning.Replace, False)
                Dim ip As IdPair = map.Item(btrRectangle.ObjectId)
                Dim clonedBlock As BlockTableRecord = ip.Value.GetObject(OpenMode.ForRead)
                Dim objIdColl As ObjectIdCollection = btrCircle.GetBlockReferenceIds(True, False)
                For Each objId As ObjectId In objIdColl
                    Dim bref As BlockReference = objId.GetObject(OpenMode.ForWrite)
                    bref.BlockTableRecord = clonedBlock.ObjectId
                Next
                tr.Commit()
            End Using
        End Using
    End Sub
Title: Re: Block Replace - Simple question. Complex answer?
Post by: Jeff H on August 13, 2010, 06:08:52 PM
Sorry it does the as the previos code except the the block that will replace the existing block is in a external drawing

Hope that helps
Title: Re: Block Replace - Simple question. Complex answer?
Post by: Kerry on August 13, 2010, 06:19:04 PM
To Slappy
Chris,
Were you wanting to replace all instances of the block or only selected instances ?
What are your rules about replacing attribute values ??



[added]
ahhh .. I see you've touched on that in  Reply #12
Title: Re: Block Replace - Simple question. Complex answer?
Post by: Bryco on August 13, 2010, 06:29:18 PM
fro's looks pretty good.
If you didnt want to change the name of the block, but only replace what's in it, you can clone the objects from within the block in the existing drawing into the block itself, (first you need to delete all in the block). That way the inserts are still there
Title: Re: Block Replace - Simple question. Complex answer?
Post by: Jeff H on August 13, 2010, 06:57:22 PM
Like Kerry and Glenn brought up
 I do not know what files you are dealing with for replacing blocks but with the code I posted would not work for files I recieve.  It might be a good idea to create a catch all for dynamics, attributes, overlay the block over the block to be replace to selct a point if you want change the insertion point. etc.
Title: Re: Block Replace - Simple question. Complex answer?
Post by: slappy on August 16, 2010, 12:03:24 PM
It's a simple idea with complex ramfications.

We are an Architectual firm and sometimes we send out construction documents that need all company information removed.  We need to replace our company border with one that is blank.  So I know what kind of blocks are coming in.  Here's the trick.  I want to give the users a range of options for border replacement via a batch processor.  So currently my code reviews all of our templates and returns a list of available borders.  They pick one and run the processor.  The code pulls the choosen block, clones it into the processed file, and overwrites the old block.  I think fro's code is putting me on the right track, as long as I can plugin all the special bells and whistles.   :evil:

I think the key aspect was running a transaction within a transaction which I was avoiding for some unknown reason.  I've almost got it working, just some syntax issues to work out.

Thanks for all the help.

Chris
Title: Re: Block Replace - Simple question. Complex answer?
Post by: slappy on August 16, 2010, 12:26:02 PM
You ROCK fro!

Worked like a charm.  ....now for those whistles.   :ugly:
Title: Re: Block Replace - Simple question. Complex answer?
Post by: kaefer on August 16, 2010, 03:50:03 PM
... It might be a good idea to create a catch all for dynamics, attributes, overlay the block over the block to be replace to selct a point if you want change the insertion point. etc.

Hi fro2001,

I still don't get what the problem with attributes might be. If you subst the (2 . "BLOCKNAME") part of the good ol' entity list, the attributes of the old block still stay in place. If that's not what was desired, you might want to sync with the new definition. The internal command ATTSYNC does exactly this; what it doesn't do is synching only a selection of block references and/or attributes. Would you want to replicate that functionality?

Cheers, Thorsten
Title: Re: Block Replace - Simple question. Complex answer?
Post by: Jeff H on August 16, 2010, 04:45:24 PM
Sorry for not being clear
 I was just commenting that the code would not replace any of the original block references if they were anonoymous.
Title: Re: Block Replace - Simple question. Complex answer?
Post by: kaefer on August 16, 2010, 06:53:18 PM
Sorry for not being clear
 I was just commenting that the code would not replace any of the original block references if they were anonoymous.

Sorry for being obstinate.
Your code would also replace any of the original block references if they were references to anonymous blocks, and even replaces them with other anonymous blocks. That is, blocks of the *U variety.

Besides, you're opening the target BlockTableRecord only to retrieve the ObjectId property...

Cheers, Thorsten
Title: Re: Block Replace - Simple question. Complex answer?
Post by: Jeff H on August 16, 2010, 07:57:45 PM
I must apologize again because I should not post a comment without being clear about what I meant

If the orginal Block was dynamic and anonymous blocks were created from the dynamic definition

The code could be updated to check if the block to be replaced is dynamic and take advantage of the  GetAnonymousBlockIDs Method