TheSwamp
Code Red => .NET => Topic started 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
-
I thik you are going to have to search for all instances of A and erase/Replace with B
-
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.
-
BlockReference objects have a BlockTableRecord property that can be set.
I haven't tried that but it's worth a shot.
-
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
-
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.
-
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?
-
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
<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
-
Also using the code above will use each individual references scale and rotation
-
Attributes anyone?
-
Also That simple example did not take in consideration of dynamic Blocks
-
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
-
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
-
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.
-
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
-
<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
-
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
-
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
-
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
-
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.
-
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
-
You ROCK fro!
Worked like a charm. ....now for those whistles. :ugly:
-
... 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
-
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 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
-
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