Author Topic: Block Replace - Simple question. Complex answer?  (Read 7831 times)

0 Members and 1 Guest are viewing this topic.

slappy

  • Guest
Block Replace - Simple question. Complex answer?
« 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

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4075
Re: Block Replace - Simple question. Complex answer?
« Reply #1 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
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4075
Re: Block Replace - Simple question. Complex answer?
« Reply #2 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.
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

mohnston

  • Bull Frog
  • Posts: 305
  • CAD Programmer
Re: Block Replace - Simple question. Complex answer?
« Reply #3 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.
It's amazing what you can do when you don't know what you can't do.
CAD Programming Solutions

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4075
Re: Block Replace - Simple question. Complex answer?
« Reply #4 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
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

Bryco

  • Water Moccasin
  • Posts: 1883
Re: Block Replace - Simple question. Complex answer?
« Reply #5 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.

LE3

  • Guest
Re: Block Replace - Simple question. Complex answer?
« Reply #6 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?

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Block Replace - Simple question. Complex answer?
« Reply #7 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



Jeff H

  • Needs a day job
  • Posts: 6150
Re: Block Replace - Simple question. Complex answer?
« Reply #8 on: August 13, 2010, 01:10:33 AM »
Also using the code above will use each individual references scale and rotation

Glenn R

  • Guest
Re: Block Replace - Simple question. Complex answer?
« Reply #9 on: August 13, 2010, 08:48:43 AM »
Attributes anyone?

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Block Replace - Simple question. Complex answer?
« Reply #10 on: August 13, 2010, 09:01:08 AM »
Also That simple example did not take in consideration of dynamic Blocks

kaefer

  • Guest
Re: Block Replace - Simple question. Complex answer?
« Reply #11 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

slappy

  • Guest
Re: Block Replace - Simple question. Complex answer?
« Reply #12 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

Bryco

  • Water Moccasin
  • Posts: 1883
Re: Block Replace - Simple question. Complex answer?
« Reply #13 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.

slappy

  • Guest
Re: Block Replace - Simple question. Complex answer?
« Reply #14 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

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Block Replace - Simple question. Complex answer?
« Reply #15 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

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Block Replace - Simple question. Complex answer?
« Reply #16 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

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Block Replace - Simple question. Complex answer?
« Reply #17 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
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.

Bryco

  • Water Moccasin
  • Posts: 1883
Re: Block Replace - Simple question. Complex answer?
« Reply #18 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

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Block Replace - Simple question. Complex answer?
« Reply #19 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.

slappy

  • Guest
Re: Block Replace - Simple question. Complex answer?
« Reply #20 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

slappy

  • Guest
Re: Block Replace - Simple question. Complex answer?
« Reply #21 on: August 16, 2010, 12:26:02 PM »
You ROCK fro!

Worked like a charm.  ....now for those whistles.   :ugly:

kaefer

  • Guest
Re: Block Replace - Simple question. Complex answer?
« Reply #22 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

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Block Replace - Simple question. Complex answer?
« Reply #23 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.

kaefer

  • Guest
Re: Block Replace - Simple question. Complex answer?
« Reply #24 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

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Block Replace - Simple question. Complex answer?
« Reply #25 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