Author Topic: Replace block, also when to be replaced block is nested  (Read 4771 times)

0 Members and 1 Guest are viewing this topic.

Woabow

  • Newt
  • Posts: 56
Replace block, also when to be replaced block is nested
« on: October 09, 2013, 11:35:55 AM »
There are several methods of replacing a block:

BLOCKREPLACE: does not replace blocks when they are inside another block
-INSERT old=new: works on nested blocks, but does end up with the old blockname. Renaming globally is not possible because there could have been old blocks in the drawing that should not be renamed.
LISP PROGRAMS: As far as I know all lisp programs work with a selection and will not replace nested blocks.

Any suggestions?




kruuger

  • Swamp Rat
  • Posts: 616
Re: Replace block, also when to be replaced block is nested
« Reply #1 on: October 09, 2013, 01:38:22 PM »
There are several methods of replacing a block:

BLOCKREPLACE: does not replace blocks when they are inside another block
-INSERT old=new: works on nested blocks, but does end up with the old blockname. Renaming globally is not possible because there could have been old blocks in the drawing that should not be renamed.
LISP PROGRAMS: As far as I know all lisp programs work with a selection and will not replace nested blocks.

Any suggestions?
maybe you can use design center CTRL+2
kruuger

Woabow

  • Newt
  • Posts: 56
Re: Replace block, also when to be replaced block is nested
« Reply #2 on: October 10, 2013, 02:14:19 AM »
Ok, thanks. But Bricscad does not have Designcenter. Maybe it explains why I can't find a lisp.


roy_043

  • Water Moccasin
  • Posts: 1736
  • BricsCAD 18
Re: Replace block, also when to be replaced block is nested
« Reply #3 on: October 10, 2013, 04:16:45 AM »
-INSERT old=new: works on nested blocks, but does end up with the old blockname. Renaming globally is not possible because there could have been old blocks in the drawing that should not be renamed.
Woabow, globally changing all block references from 'old' to 'new' would be equivalent to this. Can you clarify what you want to do?

Woabow

  • Newt
  • Posts: 56
Re: Replace block, also when to be replaced block is nested
« Reply #4 on: October 10, 2013, 07:06:51 AM »
The goal is to replace a block with another block, say "new"replaces "old". But it should also replace all blocks with the name "old" inside other blocks. And in the end all replaced blocks should have the name "new".

With -INSERT old=new all replaced blocks are named "old", not "new".

I cannot rename "old" to "new" because I might rename blocks with the name "new" which existed before the insert. I tried to use a temporarily name before the insert ("old" > "temp"), but this doesn't work also because afterwards I want to rename "temp" to "new" which is not allowed when "new"already existed in the drawing.


Bhull1985

  • Guest
Re: Replace block, also when to be replaced block is nested
« Reply #5 on: October 10, 2013, 08:11:27 AM »
Please post a sample drawing with examples of the blocks you are dealing with.
I deal with blocks daily but am having a hard time understanding exactly what you are requiring.

Woabow

  • Newt
  • Posts: 56
Re: Replace block, also when to be replaced block is nested
« Reply #6 on: October 10, 2013, 09:11:09 AM »
In attached drawing replace1.dwg are OLD blocks and NEW blocks. There is also a block BLOCKWITHBLOCKS which contains OLD (and NEW).

I just want to replace all OLD blocks with NEW, like in replace2.dwg.

Not by hand, because in real life the OLD blocks are nested in many other blocks, on different levels.


ronjonp

  • Needs a day job
  • Posts: 7060
Re: Replace block, also when to be replaced block is nested
« Reply #7 on: October 10, 2013, 09:50:25 AM »
I think this should do what you want. The new block definition has to exist in the drawing though.
Code: [Select]
(defun _updateblocks (old new)
  (if (tblobjname "block" new)
    (vlax-for b (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object)))
      (vlax-for bb b
(if (and (= (vla-get-objectname bb) "AcDbBlockReference")
(wcmatch (strcase (vla-get-name bb)) (strcase old))
(print (vla-get-name bb))
    )
  (vl-catch-all-apply 'vla-put-name (list bb new))
)
      )
    )
  )
)
(_updateblocks "old" "new")

Windows 10 x64 - AutoCAD /C3D 2020

Custom Build PC

roy_043

  • Water Moccasin
  • Posts: 1736
  • BricsCAD 18
Re: Replace block, also when to be replaced block is nested
« Reply #8 on: October 10, 2013, 09:52:05 AM »
Try this:
Code - Auto/Visual Lisp: [Select]
  1. (defun KGA_Conv_Collection_To_List (coll / ret)
  2.     (vlax-for a coll
  3.       (setq ret (cons a ret))
  4.     )
  5.   )
  6. )
  7.  
  8. (defun BKG_ReplaceBlock_InputName (message / input)
  9.   (setq input (getstring T message))
  10.   (if (= input "")
  11.     (if (setq input (car (entsel)))
  12.       (cdr (assoc 2 (entget input)))
  13.     )
  14.     input
  15.   )
  16. )
  17.  
  18. (defun c:BKG_ReplaceBlock ( / actDocObject blockFile blockNameNew blockNameOld count)
  19.   (if (= (logand (getvar 'undoctl) 8) 8)
  20.     (vla-endundomark actDocObject)
  21.   )
  22.   (vla-startundomark actDocObject)
  23.   (if
  24.     (and
  25.       (setq blockNameOld
  26.         (BKG_ReplaceBlock_InputName "\nBlock to replace (Enter to select): ")
  27.       )
  28.       (tblobjname "block" blockNameOld)
  29.       (setq blockNameNew
  30.         (BKG_ReplaceBlock_InputName
  31.           (strcat "\nReplace '" blockNameOld "' block with (Enter to select): ")
  32.         )
  33.       )
  34.       (or
  35.         (tblobjname "block" blockNameNew)
  36.         (and
  37.           (snvalid blockNameNew)
  38.           (setq blockFile (getfiled "Select a drawing" " " "dwg;dxf" 0))
  39.           (setvar 'cmdecho 0)
  40.           (not (command "_.insert" (strcat blockNameNew "=" blockFile) nil))
  41.           (setvar 'cmdecho 1)
  42.           (tblobjname "block" blockNameNew)
  43.         )
  44.       )
  45.     )
  46.     (progn
  47.       (setq blockNameOld (strcase blockNameOld))
  48.       (setq count
  49.         (length
  50.           (vl-remove
  51.             nil
  52.             (apply
  53.               'append
  54.               (mapcar
  55.                 '(lambda (blockDefObject)
  56.                   (mapcar
  57.                     '(lambda (object)
  58.                       (if
  59.                         (and
  60.                           (= (vla-get-objectname object) "AcDbBlockReference")
  61.                           (= (strcase (vla-get-name object)) blockNameOld)
  62.                         )
  63.                         (progn
  64.                           (vla-put-name object blockNameNew)
  65.                           T
  66.                         )
  67.                       )
  68.                     )
  69.                     (KGA_Conv_Collection_To_List blockDefObject)
  70.                   )
  71.                 )
  72.                 (KGA_Conv_Collection_To_List (vla-get-blocks actDocObject))
  73.               )
  74.             )
  75.           )
  76.         )
  77.       )
  78.       (princ (strcat "\n" (itoa count) " block reference(s) updated "))
  79.     )
  80.   )
  81.   (vla-endundomark actDocObject)
  82.   (princ)
  83. )
  84.  
  85. (defun c:BRBL ()
  86.   (c:BKG_ReplaceBlock)
  87. )
  88.  
  89. (princ "\nUse: BKG_ReplaceBlock or BRBL ")
« Last Edit: October 10, 2013, 02:21:12 PM by roy_043 »

CAB

  • Global Moderator
  • Seagull
  • Posts: 10369
Re: Replace block, also when to be replaced block is nested
« Reply #9 on: October 10, 2013, 09:55:13 AM »
An old lisp: (I did not look at your example)
http://www.theswamp.org/index.php?topic=2272.0
I've reached the age where the happy hour is a nap. ()
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Woabow

  • Newt
  • Posts: 56
Re: Replace block, also when to be replaced block is nested
« Reply #10 on: October 10, 2013, 10:29:00 AM »
Thanks! Both programs work great.

The vla-put-name does the trick? I can't find documentation about this function...



CAB

  • Global Moderator
  • Seagull
  • Posts: 10369
Re: Replace block, also when to be replaced block is nested
« Reply #11 on: October 10, 2013, 11:21:16 AM »
Try highlighting  vla-put-name in VLIDE & press Ctrl+Shift+A
I've reached the age where the happy hour is a nap. ()
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Lee Mac

  • Seagull
  • Posts: 12295
  • London, England
Re: Replace block, also when to be replaced block is nested
« Reply #12 on: October 10, 2013, 11:31:07 AM »
Here is an online reference for the Name property:
http://entercad.ru/acadauto.en/idh_name.htm

Here is the full ActiveX & VBA reference:
http://entercad.ru/acadauto.en/

Here is a short explanation of how to use the reference:
http://bit.ly/1ahKh6g

Woabow

  • Newt
  • Posts: 56
Re: Replace block, also when to be replaced block is nested
« Reply #13 on: October 10, 2013, 11:39:33 AM »
Thanks a lot. I have underestimated ActiveX I guess.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10369
Re: Replace block, also when to be replaced block is nested
« Reply #14 on: October 10, 2013, 12:54:23 PM »
Nice explanation Lee, very helpful.
I've reached the age where the happy hour is a nap. ()
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

kruuger

  • Swamp Rat
  • Posts: 616
Re: Replace block, also when to be replaced block is nested
« Reply #15 on: October 10, 2013, 12:54:45 PM »
I think this should do what you want. The new block definition has to exist in the drawing though.
Code: [Select]
(defun _updateblocks (old new)
  (if (tblobjname "block" new)
    (vlax-for b   (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object)))
      (vlax-for   bb b
   (if (and (= (vla-get-objectname bb) "AcDbBlockReference")
       (wcmatch (strcase (vla-get-name bb)) (strcase old))
       (print (vla-get-name bb))
       )
     (vl-catch-all-apply 'vla-put-name (list bb new))
   )
      )
    )
  )
)
(_updateblocks "old" "new")
wow . very interesting way to replace block :)
maybe vla-get-EffectiveName to replace dynamic also
kruuger

Lee Mac

  • Seagull
  • Posts: 12295
  • London, England
Re: Replace block, also when to be replaced block is nested
« Reply #16 on: October 10, 2013, 12:56:21 PM »
Nice explanation Lee, very helpful.

Cheers Alan 8-)

ronjonp

  • Needs a day job
  • Posts: 7060
Re: Replace block, also when to be replaced block is nested
« Reply #17 on: October 10, 2013, 01:58:11 PM »
I think this should do what you want. The new block definition has to exist in the drawing though.
Code: [Select]
...
wow . very interesting way to replace block :)
maybe vla-get-EffectiveName to replace dynamic also
kruuger


Code: [Select]
(defun _updateblocks (old new)
  (if (tblobjname "block" new)
    (vlax-for b (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object)))
      (vlax-for bb b
(if (and (= (vla-get-objectname bb) "AcDbBlockReference")
(wcmatch (strcase (vlax-get bb
     (if (vlax-property-available-p bb 'effectivename)
       'effectivename
       'name
     )
   )
  )
  (strcase old)
)
(print (vla-get-name bb))
    )
  (vl-catch-all-apply 'vla-put-name (list bb new))
)
      )
    )
  )
)
;; (_updateblocks "old" "new")
;D

Windows 10 x64 - AutoCAD /C3D 2020

Custom Build PC

roy_043

  • Water Moccasin
  • Posts: 1736
  • BricsCAD 18
Re: Replace block, also when to be replaced block is nested
« Reply #18 on: October 10, 2013, 02:15:42 PM »
@ronjonp: No need to check if the effectivename property is available.
I will update my code (thank you kruuger).
« Last Edit: October 10, 2013, 02:27:30 PM by roy_043 »

roy_043

  • Water Moccasin
  • Posts: 1736
  • BricsCAD 18
Re: Replace block, also when to be replaced block is nested
« Reply #19 on: October 10, 2013, 02:28:29 PM »
Updated code:
Code - Auto/Visual Lisp: [Select]
  1. (defun KGA_Conv_Collection_To_List (coll / ret)
  2.     (vlax-for a coll
  3.       (setq ret (cons a ret))
  4.     )
  5.   )
  6. )
  7.  
  8. (defun BKG_ReplaceBlock_InputName (message / input)
  9.   (setq input (getstring T message))
  10.   (if (= input "")
  11.     (if
  12.       (and
  13.         (setq input (car (entsel)))
  14.         (setq input (vlax-ename->vla-object input))
  15.         (= (vla-get-objectname input) "AcDbBlockReference")
  16.       )
  17.       (vla-get-effectivename input)
  18.     )
  19.     input
  20.   )
  21. )
  22.  
  23. (defun c:BKG_ReplaceBlock ( / actDocObject blockFile blockNameNew blockNameOld count)
  24.   (if (= (logand (getvar 'undoctl) 8) 8)
  25.     (vla-endundomark actDocObject)
  26.   )
  27.   (vla-startundomark actDocObject)
  28.   (if
  29.     (and
  30.       (setq blockNameOld
  31.         (BKG_ReplaceBlock_InputName "\nBlock to replace (Enter to select): ")
  32.       )
  33.       (tblobjname "block" blockNameOld)
  34.       (setq blockNameNew
  35.         (BKG_ReplaceBlock_InputName
  36.           (strcat "\nReplace '" blockNameOld "' block with (Enter to select): ")
  37.         )
  38.       )
  39.       (or
  40.         (tblobjname "block" blockNameNew)
  41.         (and
  42.           (snvalid blockNameNew)
  43.           (setq blockFile (getfiled "Select a drawing" " " "dwg;dxf" 0))
  44.           (setvar 'cmdecho 0)
  45.           (not (command "_.insert" (strcat blockNameNew "=" blockFile) nil))
  46.           (setvar 'cmdecho 1)
  47.           (tblobjname "block" blockNameNew)
  48.         )
  49.       )
  50.     )
  51.     (progn
  52.       (setq blockNameOld (strcase blockNameOld))
  53.       (setq count
  54.         (length
  55.           (vl-remove
  56.             nil
  57.             (apply
  58.               'append
  59.               (mapcar
  60.                 '(lambda (blockDefObject)
  61.                   (mapcar
  62.                     '(lambda (object)
  63.                       (if
  64.                         (and
  65.                           (= (vla-get-objectname object) "AcDbBlockReference")
  66.                           (= (strcase (vla-get-effectivename object)) blockNameOld)
  67.                         )
  68.                         (progn
  69.                           (vla-put-name object blockNameNew)
  70.                           T
  71.                         )
  72.                       )
  73.                     )
  74.                     (KGA_Conv_Collection_To_List blockDefObject)
  75.                   )
  76.                 )
  77.                 (KGA_Conv_Collection_To_List (vla-get-blocks actDocObject))
  78.               )
  79.             )
  80.           )
  81.         )
  82.       )
  83.       (princ (strcat "\n" (itoa count) " block reference(s) updated "))
  84.     )
  85.   )
  86.   (vla-endundomark actDocObject)
  87.   (princ)
  88. )
  89.  
  90. (defun c:BRBL ()
  91.   (c:BKG_ReplaceBlock)
  92. )
  93.  
  94. (princ "\nUse: BKG_ReplaceBlock or BRBL ")

roy_043

  • Water Moccasin
  • Posts: 1736
  • BricsCAD 18
Re: Replace block, also when to be replaced block is nested
« Reply #20 on: October 10, 2013, 02:29:15 PM »
And how about AcDbMInsertBlock...

ronjonp

  • Needs a day job
  • Posts: 7060
Re: Replace block, also when to be replaced block is nested
« Reply #21 on: October 10, 2013, 02:38:12 PM »
@ronjonp: No need to check if the effectivename property is available.
I will update my code (thank you kruuger).


What about for older versions of CAD ?

Windows 10 x64 - AutoCAD /C3D 2020

Custom Build PC

roy_043

  • Water Moccasin
  • Posts: 1736
  • BricsCAD 18
Re: Replace block, also when to be replaced block is nested
« Reply #22 on: October 11, 2013, 04:30:45 AM »
What about for older versions of CAD ?
That is a good point. When were dynamic blocks introduced?

roy_043

  • Water Moccasin
  • Posts: 1736
  • BricsCAD 18
Re: Replace block, also when to be replaced block is nested
« Reply #23 on: October 11, 2013, 06:33:18 AM »
Code: [Select]
;;; ======================================================================
;;; BKG_ReplaceBlock: Change the referenced name of inserts.
;;; ======================================================================
;;; Author:       Roy Klein Gebbinck (www.b-k-g.nl)
;;; Made for:     http://www.theswamp.org/index.php?topic=45490.0
;;; Version:      20131011.
;;; History:      20131011: Added xref and recursion check.
;;;               20131011: Added support for AcDbMInsertBlock.
;;;               20131011: Using effective name (thanks kruuger and ronjonp).
;;;               20131010: First version.
;;; ======================================================================

ronjonp

  • Needs a day job
  • Posts: 7060
Re: Replace block, also when to be replaced block is nested
« Reply #24 on: October 11, 2013, 08:31:51 AM »
What about for older versions of CAD ?
That is a good point. When were dynamic blocks introduced?


I think it was 2006 .. but don't know for sure.

Windows 10 x64 - AutoCAD /C3D 2020

Custom Build PC

CAB

  • Global Moderator
  • Seagull
  • Posts: 10369
Re: Replace block, also when to be replaced block is nested
« Reply #25 on: October 11, 2013, 08:42:48 AM »
I have 2004 & 2006, 2006 has dynamic blocks.

I've reached the age where the happy hour is a nap. ()
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

kruuger

  • Swamp Rat
  • Posts: 616
Re: Replace block, also when to be replaced block is nested
« Reply #26 on: October 11, 2013, 12:39:31 PM »
Code: [Select]
;;; ======================================================================
;;; BKG_ReplaceBlock: Change the referenced name of inserts.
;;; ======================================================================
;;; Author:       Roy Klein Gebbinck (www.b-k-g.nl)
;;; Made for:     http://www.theswamp.org/index.php?topic=45490.0
;;; Version:      20131011.
;;; History:      20131011: Added xref and recursion check.
;;;               20131011: Added support for AcDbMInsertBlock.
;;;               20131011: Using effective name (thanks kruuger and ronjonp).
;;;               20131010: First version.
;;; ======================================================================
works nicely :) may come in handy someday

puzzle...when we replace attribute block with regular block attributes occurs in all inserts. how to attsync existing/inserted block ?

thanks
kruuger

roy_043

  • Water Moccasin
  • Posts: 1736
  • BricsCAD 18
Re: Replace block, also when to be replaced block is nested
« Reply #27 on: October 13, 2013, 06:18:44 AM »
... how to attsync existing/inserted block ?
Code: [Select]
;;; ======================================================================
;;; BKG_ReplaceBlock: Change the referenced name of inserts.
;;; ======================================================================
;;; Author:       Roy Klein Gebbinck (www.b-k-g.nl)
;;; Made for:     http://www.theswamp.org/index.php?topic=45490.0
;;; Version:      20131013.
;;; History:      20131013: If the new block has no editable attributes,
;;;                         existing attribute references are deleted.
;;;                         Else there is an optional call to the Attsync
;;;                         command.
;;;               20131011: Added xref and recursion check.
;;;               20131011: Added support for AcDbMInsertBlock.
;;;               20131011: Using effective name (thanks kruuger and ronjonp).
;;;               20131010: First version.
;;; ======================================================================