Author Topic: Replacing Dynamic Blocks  (Read 6574 times)

0 Members and 1 Guest are viewing this topic.

cmwade77

  • Swamp Rat
  • Posts: 1443
Replacing Dynamic Blocks
« on: November 19, 2010, 05:18:22 PM »
Ok, we have changed how one of our standard blocks look, I am wondering if anyone has a routine that will replace dynamic blocks and retain everything (including attributes, visibility states, stretch states, etc.)

I have found several replace block routines, but none seem to work with dynamic blocks.

At bare minimum a pointer in the right direction for properties and such would be appreciated.

cmwade77

  • Swamp Rat
  • Posts: 1443
Re: Replacing Dynamic Blocks
« Reply #1 on: November 22, 2010, 07:23:46 PM »
Ok, I got through the basics of this; however, if you run the code below on the attached drawing, you will notice that the title of the detail box is no longer in the correct position....does anyone have any suggestions as to why this is occurring and what to do about it?
Code: [Select]
(defun c:bre ( / ent name obtyp Doc space i j attribs1 attribs2 attribs-list1 attribs-list2)
(vl-load-com)
(vl-cmdf "._-insert" "BEI DETAIL BOX - R3") (command)
(setq Doc (vla-get-activedocument (vlax-get-acad-object))
 space
(if (zerop (vla-get-activespace doc))
(if (= (vla-get-mspace doc) :vlax-true)
(vla-get-modelspace doc) ; active VP
(vla-get-paperspace doc)
)
(vla-get-modelspace doc)
)
)
(while (= ent nil)
(setq ent (entsel))
)
(setq ent (vlax-ename->vla-object (car ent))
 obtyp (vla-get-objectname ent)
)
(cond
((= obtyp "AcDbBlockReference")
(setq name (vla-get-name ent)
     inspt (vla-get-insertionpoint ent)
 ent2 (vla-InsertBlock space (vla-get-insertionpoint ent) "BEI DETAIL BOX - R3" (vla-get-XScaleFactor ent) (vla-get-yscalefactor ent) (vla-get-zscalefactor ent)  (vla-get-rotation ent))
)
(vla-put-layer ent2 (vla-get-layer ent))
(foreach i (vlax-invoke ent 'getdynamicblockproperties)
(foreach j (vlax-invoke ent2 'getdynamicblockproperties)
(cond
((= (strcase (vla-get-propertyname j)) (strcase (vla-get-PropertyName i)))
(cond
((/= (vla-get-propertyname j) "Origin")
(vla-put-Value j (vla-get-value i))
)
)
)
)
)
(setq j nil)
)
(setq attribs1 (vla-GetAttributes ent)
 attrib-list1 (vlax-safearray->list (vlax-variant-value attribs1))
 attribs2 (vla-GetAttributes ent2)
 attrib-list2 (vlax-safearray->list (vlax-variant-value attribs2))
); setq
(foreach i attrib-list1
(foreach j attrib-list2
(cond
((= (strcase (vla-get-tagstring j)) (strcase (vla-get-tagstring i)))
(vla-put-textstring j (vla-get-textstring i))
)
)
)
)
(vla-delete ent)
)
)
)

I would greatly appreciate any and all help with this.

mjfarrell

  • Seagull
  • Posts: 14444
  • Every Student their own Lesson
Re: Replacing Dynamic Blocks
« Reply #2 on: November 22, 2010, 07:25:51 PM »
did anyone change the BASE in the drawing?
Be your Best


Michael Farrell
http://primeservicesglobal.com/

cmwade77

  • Swamp Rat
  • Posts: 1443
Re: Replacing Dynamic Blocks
« Reply #3 on: November 22, 2010, 07:28:15 PM »
Nope, the base is the same for both....I setup this example to make sure it was something drawing specific.

mjfarrell

  • Seagull
  • Posts: 14444
  • Every Student their own Lesson
Re: Replacing Dynamic Blocks
« Reply #4 on: November 22, 2010, 07:43:37 PM »
I suspect...it's getting scaled...by this..

Code: [Select]
ent2 (vla-InsertBlock space (vla-get-insertionpoint ent) "BEI DETAIL BOX - R3" (vla-get-XScaleFactor ent) (vla-get-yscalefactor ent) (vla-get-zscalefactor ent)  (vla-get-rotation ent))
Be your Best


Michael Farrell
http://primeservicesglobal.com/

cmwade77

  • Swamp Rat
  • Posts: 1443
Re: Replacing Dynamic Blocks
« Reply #5 on: November 22, 2010, 07:48:12 PM »
I suspect...it's getting scaled...by this..

Code: [Select]
ent2 (vla-InsertBlock space (vla-get-insertionpoint ent) "BEI DETAIL BOX - R3" (vla-get-XScaleFactor ent) (vla-get-yscalefactor ent) (vla-get-zscalefactor ent)  (vla-get-rotation ent))
Hmm...no, it doesn't seem to have any effect if I change it; however, I have just noticed that if I manually insert the block, I get the same behavior; however, if I insert it using Tool Palettes it is correct.....any ideas on that one?

I am guessing by this behavior that it is somehow related to the block, but I am not sure what would cause that.

mjfarrell

  • Seagull
  • Posts: 14444
  • Every Student their own Lesson
Re: Replacing Dynamic Blocks
« Reply #6 on: November 22, 2010, 08:26:13 PM »
BASE

and

INSBASE

are two commands that come to mind

as the block doesn't appear to be annotative....it should not be affected by the annotation scale(s)
« Last Edit: November 22, 2010, 08:33:33 PM by Anti Quark »
Be your Best


Michael Farrell
http://primeservicesglobal.com/

cmwade77

  • Swamp Rat
  • Posts: 1443
Re: Replacing Dynamic Blocks
« Reply #7 on: November 23, 2010, 12:20:44 PM »
It turned out it was a problem with the block definition it's self.......I have that fixed now.

Now, I have another issue, the following code will not automatically select the blocks in the attached drawing....I am not completely familiar with the filters on ssget, but I think that this should do the trick, yet it isn't for some reason:
Code: [Select]
(defun c:bre ( / ss ent obtyp Doc space i j attribs1 attribs2 attribs-list1 attribs-list2 tst tsttyp)
(vl-load-com)
(vl-cmdf "._-insert" "BEI DETAIL BOX - R3B") (command)
(setq Doc (vla-get-activedocument (vlax-get-acad-object))
 space
(if (zerop (vla-get-activespace doc))
(if (= (vla-get-mspace doc) :vlax-true)
(vla-get-modelspace doc) ; active VP
(vla-get-paperspace doc)
)
(vla-get-modelspace doc)
)
)
(setq ss (ssget "x" '((0 . "INSERT") (2 . "BEI_DETAIL_BOX"))))
(cond
((= ss nil)
(setq ss (ssget "x" '((0 . "INSERT") (2 . "BEI DETAIL BOX"))))
(COND
((= ss nil)
(setq ss (ssget "x" '((0 . "INSERT") (2 . "BEI DETAIL BOX - R2"))))
(cond
((= ss nil)
(setq ss (ssget "x" '((0 . "INSERT") (2 . "BEI DETAIL BOX - R3"))))
(cond
((= ss nil)
(while (= tst nil)
(setq tst (entsel "\nCould not automatically find detail boxes, please select one manually: "))
)
(setq tst (vlax-ename->vla-object (car tst))
 tsttyp (vla-get-objectname tst)
)
(cond
((= tstyp "AcDbBlockReference")
(setq ss (ssget "x" '((0 . "INSERT") (2 . (vla-get-name tst)))))
)
)
(cond
((= ss nil)
(while (= ss nil)
(princ "\rCould not automatically select detail boxes based on selected object, manually select detail boxes: ")
(setq ss (ssget))
)
)
)
)
)
)
)
)
)
)
)
(while (/= ss nil)
(setq ent (vlax-ename->vla-object (ssname ss 0))
 obtyp (vla-get-objectname ent)
)
(cond
((= obtyp "AcDbBlockReference")
(setq inspt (vla-get-insertionpoint ent)
 ent2 (vla-InsertBlock space (vla-get-insertionpoint ent) "BEI DETAIL BOX - R3B" (vla-get-XScaleFactor ent) (vla-get-yscalefactor ent) (vla-get-zscalefactor ent) (vla-get-rotation ent))
)
(vla-put-layer ent2 (vla-get-layer ent))
(foreach i (vlax-invoke ent 'getdynamicblockproperties)
(foreach j (vlax-invoke ent2 'getdynamicblockproperties)
(cond
((= (strcase (vla-get-propertyname j)) (strcase (vla-get-PropertyName i)))
(cond
((/= (vla-get-propertyname j) "Origin")
(vla-put-Value j (vla-get-value i))
)
)
)
)
)
(setq j nil)
)
(setq attribs1 (vla-GetAttributes ent)
 attrib-list1 (vlax-safearray->list (vlax-variant-value attribs1))
 attribs2 (vla-GetAttributes ent2)
 attrib-list2 (vlax-safearray->list (vlax-variant-value attribs2))
); setq
(foreach i attrib-list1
(foreach j attrib-list2
(cond
((= (strcase (vla-get-tagstring j)) (strcase (vla-get-tagstring i)))
(vla-put-textstring j (vla-get-textstring i))
)
)
)
)
(vla-delete ent)
)
)
(ssdel (ssname ss 0) ss)
)
)
I have also attached the new block definition for testing this with.

mjfarrell

  • Seagull
  • Posts: 14444
  • Every Student their own Lesson
Re: Replacing Dynamic Blocks
« Reply #8 on: November 23, 2010, 01:12:08 PM »
It looks like you have it looking for a specifc block name, and not just the block object type...
Be your Best


Michael Farrell
http://primeservicesglobal.com/

cmwade77

  • Swamp Rat
  • Posts: 1443
Re: Replacing Dynamic Blocks
« Reply #9 on: November 23, 2010, 01:14:48 PM »
That is correct.....I only want certain blocks replaced and I don't want to select all blocks in the drawing, because that could mean 500+ blocks to sort through. That is the name of the blocks in the drawing.

Edit: Ok, I get it, there are anonymous block names assigned to each block, now I just need to figure out how to get rid of them.

Edit: Actually, this is a result of dynamic blocks, I got it working thanks to some code from Lee at the following thread: http://www.theswamp.org/index.php?topic=35754.msg409742#msg409742
Code: [Select]
(defun c:bre ( / ss ent obtyp Doc space i j attribs1 attribs2 attribs-list1 attribs-list2 tst tsttyp bname ss2)
(vl-load-com)
(vl-cmdf "._-insert" "BEI DETAIL BOX - R3B") (command)
(setq Doc (vla-get-activedocument (vlax-get-acad-object))
  space
(if (zerop (vla-get-activespace doc))
(if (= (vla-get-mspace doc) :vlax-true)
(vla-get-modelspace doc) ; active VP
(vla-get-paperspace doc)
)
(vla-get-modelspace doc)
)
)
(setq ss (GetBlockSelectionSet "bei*detail*box*"))
    (cond
((or (= (sslength ss) 0) (= ss nil))
(while (= tst nil)
(setq tst (entsel "\nCould not automatically find detail boxes, please select one manually: "))
)
(setq tst (vlax-ename->vla-object (car tst))
  tsttyp (vla-get-objectname tst)
)
(cond
((= tstyp "AcDbBlockReference")
(setq bname (vla-get-name tst)
  ss (GetBlockSelectionSet bname)
)
)
)
(cond
((or (= (sslength ss) 0) (= ss nil))
(while (or (= ss nil) (= (sslength ss) 0))
(princ "\rManually select detail boxes: ")
(setq ss (ssget))
)
)
)
)
)
(while (and (/= ss nil) (> (sslength ss) 0))
(setq ent (vlax-ename->vla-object (ssname ss 0))
  obtyp (vla-get-objectname ent)
)
(cond
((= obtyp "AcDbBlockReference")
(setq inspt (vla-get-insertionpoint ent)
  ent2 (vla-InsertBlock space (vla-get-insertionpoint ent) "BEI DETAIL BOX - R3B" (vla-get-XScaleFactor ent) (vla-get-yscalefactor ent) (vla-get-zscalefactor ent) (vla-get-rotation ent))
)

(vla-put-layer ent2 (vla-get-layer ent))
(foreach i (vlax-invoke ent 'getdynamicblockproperties)
(foreach j (vlax-invoke ent2 'getdynamicblockproperties)
(cond
((= (strcase (vla-get-propertyname j)) (strcase (vla-get-PropertyName i)))
(cond
((/= (vla-get-propertyname j) "Origin")
(vla-put-Value j (vla-get-value i))
)
)
)
)
)
(setq j nil)
)
(setq attribs1 (vla-GetAttributes ent)
  attrib-list1 (vlax-safearray->list (vlax-variant-value attribs1))
  attribs2 (vla-GetAttributes ent2)
  attrib-list2 (vlax-safearray->list (vlax-variant-value attribs2))
); setq
(foreach i attrib-list1
(foreach j attrib-list2
(cond
((= (strcase (vla-get-tagstring j)) (strcase (vla-get-tagstring i)))
(vla-put-textstring j (vla-get-textstring i))
)
)
)
)
(vla-delete ent)
)
)
(ssdel (ssname ss 0) ss)
)
(princ)
)

;Code to select dynamic blocks from Lee Mac at http://www.theswamp.org/index.php?topic=35754.msg409742#msg409742
(defun GetBlockSelectionSet ( name / ss ) (vl-load-com)
  (if (setq ss (ssget "_X" (list (cons 0 "INSERT") (cons 2 (strcat name ",`*U*")))))
    (
      (lambda ( i / e )
        (while (setq e (ssname ss (setq i (1+ i))))
          (if (not (wcmatch (strcase (vla-get-EffectiveName (vlax-ename->vla-object e))) (strcase name))); Line modified by Chris Wade to not be case sensitive and to use wild card matching
            (ssdel e ss)
          )
        )
        ss
      )
      -1
    )
  )
)
« Last Edit: November 23, 2010, 02:59:19 PM by cmwade77 »

cmwade77

  • Swamp Rat
  • Posts: 1443
Re: Replacing Dynamic Blocks
« Reply #10 on: November 23, 2010, 04:12:27 PM »
Ok, actually, I just found a slight bug, if there are multiple tabs with the block on it, everything gets inserted on the current tab, instead of the individual tabs....I know where the problem is, I am just not sure how to fix it yet.

mjfarrell

  • Seagull
  • Posts: 14444
  • Every Student their own Lesson
Re: Replacing Dynamic Blocks
« Reply #11 on: November 23, 2010, 04:20:59 PM »
Ok, actually, I just found a slight bug, if there are multiple tabs with the block on it, everything gets inserted on the current tab, instead of the individual tabs....I know where the problem is, I am just not sure how to fix it yet.
I don't think I recall seeing any list of the insertion points of the desired blocks being stored, and then used later in that code to insert the replacement blocks....
Be your Best


Michael Farrell
http://primeservicesglobal.com/

cmwade77

  • Swamp Rat
  • Posts: 1443
Re: Replacing Dynamic Blocks
« Reply #12 on: November 23, 2010, 04:24:08 PM »
Ok, actually, I just found a slight bug, if there are multiple tabs with the block on it, everything gets inserted on the current tab, instead of the individual tabs....I know where the problem is, I am just not sure how to fix it yet.
I don't think I recall seeing any list of the insertion points of the desired blocks being stored, and then used later in that code to insert the replacement blocks....
No list, I thought this was simpler, as well as faster:
Code: [Select]
ent2 (vla-InsertBlock space (vla-get-insertionpoint ent) "BEI DETAIL BOX - R3B" (vla-get-XScaleFactor ent) (vla-get-yscalefactor ent) (vla-get-zscalefactor ent) (vla-get-rotation ent))
This inserts the block at the insertion point of the old block.......I now need to figure out how to determine the layout for the old block and replace the space variable with it.

I found that I simply needed to modify the line above to be:
Code: [Select]
ent2 (vla-InsertBlock (vla-objectidtoobject doc (vla-get-ownerid ent)) (vla-get-insertionpoint ent) "BEI DETAIL BOX - R3B" (vla-get-XScaleFactor ent) (vla-get-yscalefactor ent) (vla-get-zscalefactor ent) (vla-get-rotation ent))
So, the new code is:
Code: [Select]
;Written by: Chris Wade - 11/23/2010
(defun c:bre ( / ss ent obtyp Doc i j attribs1 attribs2 attribs-list1 attribs-list2 tst tsttyp bname ss2)
(vl-load-com)
(vl-cmdf "._-insert" "BEI DETAIL BOX - R3B")(command);Insert the block, but do not place it on the drawing, so that there is not an error later on.
(setq Doc (vla-get-activedocument (vlax-get-acad-object))); Gets the current document for use later on
(setq ss (GetBlockSelectionSet "bei*detail*box*")); Select all blocks with the word bei, detail and box in their name (dynamic and non dynamic blocks)
    (cond
((or (= (sslength ss) 0) (= ss nil)); If no objects were selected above, ask the user to manually select a block to get the name.
(while (= tst nil)
(setq tst (entsel "\nCould not automatically find detail boxes, please select one manually: "))
)
(setq tst (vlax-ename->vla-object (car tst))
  tsttyp (vla-get-objectname tst)
)
(cond
((= tstyp "AcDbBlockReference")
(setq bname (vla-get-name tst)
  ss (GetBlockSelectionSet bname)
)
)
)
(cond
((or (= (sslength ss) 0) (= ss nil)); If for some reason the selection set is still empty, ask the user to manually select the blocks that they want to update.
(while (or (= ss nil) (= (sslength ss) 0))
(princ "\rManually select detail boxes: ")
(setq ss (ssget))
)
)
)
)
)
(while (and (/= ss nil) (> (sslength ss) 0)); Loop through all instances of the block(s) to make sure they all get replaced
(setq ent (vlax-ename->vla-object (ssname ss 0)); Make an object out of the first entity in the selection set
  obtyp (vla-get-objectname ent); Find the type of object that we are working with
)
(cond
((= obtyp "AcDbBlockReference"); If we are working with a block continue on, otherwise remove the entity and move on to the nect one.
(setq ent2 (vla-InsertBlock (vla-objectidtoobject doc (vla-get-ownerid ent)) (vla-get-insertionpoint ent) "BEI DETAIL BOX - R3B" (vla-get-XScaleFactor ent) (vla-get-yscalefactor ent) (vla-get-zscalefactor ent) (vla-get-rotation ent))); Insert the new block based on how the old block was inserted.
(vla-put-layer ent2 (vla-get-layer ent)); Make sure that the new object is placed on the same layer as the old object
; Code to match dynamic properties adapted from T. Willey's code at http://www.theswamp.org/index.php?topic=31549.msg370876#msg370876
(foreach i (vlax-invoke ent 'getdynamicblockproperties)
(foreach j (vlax-invoke ent2 'getdynamicblockproperties)
(cond
((= (strcase (vla-get-propertyname j)) (strcase (vla-get-PropertyName i)))
(cond
((/= (vla-get-propertyname j) "Origin")
(vla-put-Value j (vla-get-value i))
)
)
)
)
)
(setq j nil)
)
; End of code to match dynamic block properties
; The following code makes sure that attribute values match.
(setq attribs1 (vla-GetAttributes ent)
  attrib-list1 (vlax-safearray->list (vlax-variant-value attribs1))
  attribs2 (vla-GetAttributes ent2)
  attrib-list2 (vlax-safearray->list (vlax-variant-value attribs2))
)
(foreach i attrib-list1
(foreach j attrib-list2
(cond
((= (strcase (vla-get-tagstring j)) (strcase (vla-get-tagstring i)))
(vla-put-textstring j (vla-get-textstring i))
)
)
)
)
; End of attribute code
(vla-delete ent); Delete old object
)
)
(ssdel (ssname ss 0) ss); Remove object from selection set.
)
(princ)
)
;Code to select dynamic blocks from Lee Mac at http://www.theswamp.org/index.php?topic=35754.msg409742#msg409742
(defun GetBlockSelectionSet ( name / ss ) (vl-load-com)
  (if (setq ss (ssget "_X" (list (cons 0 "INSERT") (cons 2 (strcat name ",`*U*")))))
    (
      (lambda ( i / e )
        (while (setq e (ssname ss (setq i (1+ i))))
          (if (not (wcmatch (strcase (vla-get-EffectiveName (vlax-ename->vla-object e))) (strcase name))); Line modified by Chris Wade to not be case sensitive and to use wild card matching
            (ssdel e ss)
          )
        )
        ss
      )
      -1
    )
  )
)
« Last Edit: November 23, 2010, 05:06:26 PM by cmwade77 »

mjfarrell

  • Seagull
  • Posts: 14444
  • Every Student their own Lesson
Re: Replacing Dynamic Blocks
« Reply #13 on: November 23, 2010, 04:48:56 PM »
the reason a list came to mind...is that unless there is ever only going to be ONE of these blocks in the file in either PS, or MS then one might want to grab the insertion point of ALL of them, and then replace them in kind with the new block...keep in mind I'm not a coder myself just evaluating it from a logic standpoint.

Although, I am slowly learning...and the small voice in my head is saying that I should commit serious effort to learning and applying one or more of these languages. 
Be your Best


Michael Farrell
http://primeservicesglobal.com/

cmwade77

  • Swamp Rat
  • Posts: 1443
Re: Replacing Dynamic Blocks
« Reply #14 on: November 23, 2010, 05:05:28 PM »
Well, that is what this forum is great for....learning.....I have updated my code to include some comments that should help, but basically, what my code does is:
Select all instances of blocks that match my criteria (in this case has the words bei, detail and box in the name)
Loop through each one and insert a new block, matching all dynamic properties, attributes and the layer
Erase the old block

I do strongly recommend learning one of the programming languages, LISP is what I deal in mostly and it is extremely powerful.
« Last Edit: November 23, 2010, 05:10:16 PM by cmwade77 »