The following is a lisp that I wrote that replaces all the blocks within your drawing to the block you choose. The lisp is different than the express command blockreplace because one can replace multiple different blocks at one time with a particular block of your chosing. In addition, the replaced blocks will have the same layer of the block you wanted to replace the others with. Since I couldn't find a lisp like this in the forums, here's my small contribution:
(defun C:CHANGEBLOCKS(/ printDebug ssAll ssAllTotal ss ssTotal ssCount ssCount2 ssTotal ssMainBlock ssMainBlock entListMainBlock ssBlocks entListBlock entListBlock2 entElementNewBlock entElementOldBlock entElementOldBlock2 oldBlockName) ;PROGRAM CHANGES MULTIPLE BLOCKS ;WRITTEN BY --- RAUL BENITEZ ;Command reference ;subst - returns a list with a new item substituted for every occurrence of an old item ;quote (or ') - easy way to make the string into a list. ;cdr - returns a list containing all but the first element of the specified list ;assoc - searches an association list for an element and returns that association list entry ;entmod - modifies the definition data of an object (entity) ;cons - adds an element to the beginning of a list, or constructs a dotted list (vl-load-com) (setvar "CMDECHO" 0) (setq printDebug 0) (setq ss nil) ;set ss variable to nil (princ "\n(1). Pick the blocks you want to replace: ") (setq ss (ssget)) ;Gets selection set (setq ssTotal (sslength ss)) ;Gets the total number of entities within the selection (command "PICKADD" "0") ;Changes the pickadd variable so the user can only select one object at a time ;Obtain the block you want to replace the others with (princ "\n(2). Pick the block you want to replace the others with: ") (setq ssMainBlock (ssget)) ;Create selection set for the main block you want to replace the others with (setq entListMainBlock (entget (ssname ssMainBlock 0))) ;Obtain entity list (group codes) containing definition data of the block (setq entElementNewBlock (assoc 2 entListMainBlock)) ;Searches the block entity list and returns the element associate with 2 (the block name) (if (= printDebug 1) (progn (princ "\nEntity list of the block you want to replace others with") (princ "\n-----------------------------------------------------------\n") (princ entListMainBlock) ) ) ;Cycle thru all the blocks replacing each block one at a time (setq ssCount 0) (while (< ssCount ssTotal) (setq entListBlock (entget (ssname ss ssCount))) ;Obtain entity list (group codes) from each of the entities (blocks) in the selection set (setq entElementOldBlock (assoc 2 entListBlock)) ;Searches the block entity list and returns the element associate with 2 (the block name) (setq oldBlockName (cdr entElementOldBlock)) ;Returns a list containing all but the first element of the specified list, therefore only the block name (setq ssAll nil) ;Set the variable to nil (setq ssAll (ssget "X" (list '(0 . "INSERT") (cons 2 oldBlockName)))) ;Obtain the entire selection of all the blocks throughout the drawing (setq ssAllTotal (sslength ssAll)) ;Gets the total number of entities within the selection (if (= printDebug 1) (progn (princ "\n\n\nCount of all the old blocks in the drawing: ") (princ ssAllTotal) ) ) (setq ssCount2 0) (while (< ssCount2 ssAllTotal) (setq entListBlock2 (entget (ssname ssAll ssCount2))) ;Obtain entity list (group codes) from each of the entities (blocks) in the selection set (setq entElementOldBlock2 (assoc 2 entListBlock2)) ;Searches the block entity list and returns the element associate with 2 (the block name) (entmod (subst entElementNewBlock entElementOldBlock2 entListBlock2)) ;Substitute the new block entity name for the old block entity name within the old block entity list (command "MATCHPROP" (ssname ssMainBlock 0) (ssname ssAll ssCount2) "" ) ;Match the properties of the old block(s) to the new block (setq ssCount2 (+ ssCount2 1)) ;Loop counter ) ;Print out information (if (= printDebug 1) (progn (princ "\n\n\nssCount: ") (princ ssCount) (princ "\nEntity list of the block that is going to be replaced") (princ "\n-----------------------------------------------------------\n") (princ entListBlock) (princ "\n\nName entity of the block that is going to replaced: ") (princ entElementOldBlock) (princ "\nName entity of the new block: ") (princ entElementNewBlock) (princ "\n\n") ) ) (setq ssCount (+ ssCount 1)) ;Loop counter ) (command "PICKADD" "2") ;Changes the pickadd variable so the user select multiple objects at a time (setvar "CMDECHO" 1) (print "Changed multiple blocks.") (princ) )
@raulvaldemar wrote:The following is a lisp that I wrote that replaces all the blocks within your drawing to the block you choose. The lisp is different than the express command blockreplace because one can replace multiple different blocks at one time with a particular block of your chosing. In addition, the replaced blocks will have the same layer of the block you wanted to replace the others with. Since I couldn't find a lisp like this in the forums, here's my small contribution:
(defun C:CHANGEBLOCKS(/ printDebug ssAll ssAllTotal ss ssTotal ssCount ssCount2 ssTotal ssMainBlock ssMainBlock entListMainBlock ssBlocks entListBlock entListBlock2 entElementNewBlock entElementOldBlock entElementOldBlock2 oldBlockName) ;PROGRAM CHANGES MULTIPLE BLOCKS ;WRITTEN BY --- RAUL BENITEZ ;Command reference ;subst - returns a list with a new item substituted for every occurrence of an old item ;quote (or ') - easy way to make the string into a list. ;cdr - returns a list containing all but the first element of the specified list ;assoc - searches an association list for an element and returns that association list entry ;entmod - modifies the definition data of an object (entity) ;cons - adds an element to the beginning of a list, or constructs a dotted list (vl-load-com) (setvar "CMDECHO" 0) (setq printDebug 0) (setq ss nil) ;set ss variable to nil (princ "\n(1). Pick the blocks you want to replace: ") (setq ss (ssget)) ;Gets selection set (setq ssTotal (sslength ss)) ;Gets the total number of entities within the selection (command "PICKADD" "0") ;Changes the pickadd variable so the user can only select one object at a time ;Obtain the block you want to replace the others with (princ "\n(2). Pick the block you want to replace the others with: ") (setq ssMainBlock (ssget)) ;Create selection set for the main block you want to replace the others with (setq entListMainBlock (entget (ssname ssMainBlock 0))) ;Obtain entity list (group codes) containing definition data of the block (setq entElementNewBlock (assoc 2 entListMainBlock)) ;Searches the block entity list and returns the element associate with 2 (the block name) (if (= printDebug 1) (progn (princ "\nEntity list of the block you want to replace others with") (princ "\n-----------------------------------------------------------\n") (princ entListMainBlock) ) ) ;Cycle thru all the blocks replacing each block one at a time (setq ssCount 0) (while (< ssCount ssTotal) (setq entListBlock (entget (ssname ss ssCount))) ;Obtain entity list (group codes) from each of the entities (blocks) in the selection set (setq entElementOldBlock (assoc 2 entListBlock)) ;Searches the block entity list and returns the element associate with 2 (the block name) (setq oldBlockName (cdr entElementOldBlock)) ;Returns a list containing all but the first element of the specified list, therefore only the block name (setq ssAll nil) ;Set the variable to nil (setq ssAll (ssget "X" (list '(0 . "INSERT") (cons 2 oldBlockName)))) ;Obtain the entire selection of all the blocks throughout the drawing (setq ssAllTotal (sslength ssAll)) ;Gets the total number of entities within the selection (if (= printDebug 1) (progn (princ "\n\n\nCount of all the old blocks in the drawing: ") (princ ssAllTotal) ) ) (setq ssCount2 0) (while (< ssCount2 ssAllTotal) (setq entListBlock2 (entget (ssname ssAll ssCount2))) ;Obtain entity list (group codes) from each of the entities (blocks) in the selection set (setq entElementOldBlock2 (assoc 2 entListBlock2)) ;Searches the block entity list and returns the element associate with 2 (the block name) (entmod (subst entElementNewBlock entElementOldBlock2 entListBlock2)) ;Substitute the new block entity name for the old block entity name within the old block entity list (command "MATCHPROP" (ssname ssMainBlock 0) (ssname ssAll ssCount2) "" ) ;Match the properties of the old block(s) to the new block (setq ssCount2 (+ ssCount2 1)) ;Loop counter ) ;Print out information (if (= printDebug 1) (progn (princ "\n\n\nssCount: ") (princ ssCount) (princ "\nEntity list of the block that is going to be replaced") (princ "\n-----------------------------------------------------------\n") (princ entListBlock) (princ "\n\nName entity of the block that is going to replaced: ") (princ entElementOldBlock) (princ "\nName entity of the new block: ") (princ entElementNewBlock) (princ "\n\n") ) ) (setq ssCount (+ ssCount 1)) ;Loop counter ) (command "PICKADD" "2") ;Changes the pickadd variable so the user select multiple objects at a time (setvar "CMDECHO" 1) (print "Changed multiple blocks.") (princ) )
totally works ^_^ thank you 😄
What about a way to replace multiple blocks with multiple blocks, such that i have a client that wants us to change our blocks to their blocks.
@justin wrote:
What about a way to replace multiple blocks with multiple blocks, such that i have a client that wants us to change our blocks to their blocks.
Are you offering a solution for multiple block replacement? considering the fact that you are replying to a post from a year ago or so.
Or are you looking for a solution? Have you considered redefining the block? What kind of changes are you looking at?
One option is Tool palette / Right click / Redefine... easy peasy, Yes?
Another is Design Center / Right click / Redefine..
Or we can do it with lisp if that will make you happy 😊.
I am looking for a solution. I tried to use this LISP routine as advertised, "multiple" block replacement. But then i ran it and it is the same a the regular blockreplace command in autoCAD in that it only replaces multiple blocks with 1 block. What i need is a command to replace multiple blocks with multiple. Like i said i have a client who wants us to convert to their blocks. So our manhole symbol turns into their manhole symbol x 100 other objects.
@justin wrote:
What i need is a command to replace multiple blocks with multiple. Like i said i have a client who wants us to convert to their blocks. So our manhole symbol turns into their manhole symbol x 100 other objects.
How do you determine which block to replace what block? How would you want it ? by a harcoded list? or via selection?
The reason why i'm asking, its too easy to do it with desingn center? The list is already there. You jsut need to direct it to one file that show all the blocks you needed to redefine.
If not, please post a sample drawing. Will code the heck out of that drawing.
So i tried that, but for whatever reason the option to redefine is greyed out. Also this is a pain to do to 100 objects, i might as well just do the blockreplace. I am looking for a way to redifine ALL of them at once. I could be a hard coded list, as it is for a specific client.
I downloaded and attempted to use this LISP routine, but it doesn't seem to do anything, not even an error. The thread was a couple years old.
(defun c:CHMB (/ lst ss i sn en bn nw od o n)
(setq lst '(("SS-MH" . "H:\CLSI Cad standards\Carlson-Settings\Layer Translator\Individual Blocks\SAN SEWER MH.dwg")
("ST-MH" . "H:\CLSI Cad standards\Carlson-Settings\Layer Translator\Individual Blocks\STORM MH.dwg")
)
)
(if (setq ss (ssget "_X" (list '(0 . "INSERT") (cons 2 (apply 'strcat (mapcar '(lambda (x)
(strcat (car x) "," (cdr x) ","))
lst)))
)
)
)
(repeat (setq i (sslength ss))
(setq sn (ssname ss (setq i (1- i)))
en (entget sn)
bn (cdr (assoc 2 en))
)
(if (assoc bn lst)
(setq od (cons (list bn en sn) od))
(if (not (member bn nw))
(setq nw (cons (list bn en) nw))
)
)
)
)
(if (and nw od)
(foreach x od
(and (setq o (assoc (car x) lst))
(setq n (assoc (cdr o) nw))
(entmake
(append
(list '(0 . "INSERT") (cons 2 (car n)))
(vl-remove-if-not
'(lambda (j) (member (car j) '(10 41 42 43 50)))
(cadr x))
(vl-remove-if-not
'(lambda (k) (member (car k) '(6 8 62)))
(cadr n))))
(entdel (caddr x))
)
)
)
(princ)
)(vl-load-com)
The Design Center's Redefine option is good if all their Blocks have the same names as your Blocks that they are to replace. Is that the case? And they would need to be Blocks inside a drawing file [or files -- much easier if all in one], not separate drawings. Is that the case?
If they're separate drawings, a routine could be written pretty easily to go through and change definitions, pulling them from those drawings, and also change to their names if that's part of the task, given a list pairing your-names with their-names.
But there are potential complications. If they want your "horse" Block to become defined as their "donkey" Block instead, and they want you to use their names, but you also have a "donkey" name in use for another Block, there will be trouble....
@Kent1Cooper wrote:
The Design Center's Redefine option is good if all their Blocks have the same names as your Blocks that they are to replace.
Ahh, I see your point there Kent. good call,
They are not named the same, and i need to keep them with their original names, that's the whole point is that when the client gets a drawing from us it acts like it came from them.
As far as separate files, i could do this either way. I have all the blocks in one drawing at the moment, but i could pull them out into separate files if needed. I could keep it clean so none of their names are in there, as it should be by default anyway.
This is going to be a process that is the same every time, so the blocks to be translated could be hard coded, whatever that may look like.
I cant believe they haven't built this into AutoCAD yet. This has been a problem in Survey world forever.
Well in Survey world, you get field data from fancy data collectors, and that data is coded such that an automated "field to finish" process draws the line work and symbols based on our company standards. We would have to completely re code our field standards in order to draft in company B's standards, such we have to translate it to the other companies standards. I have been in survey world a very long time, and it has always been this way.
I don't see how sending the drawings helps, they are just symbols/blocks, i have about 50 of them that need to be translated, and that could be hard coded into a lisp routine for example as it will always be the same set of blocks that need to be translated.
@justin wrote:
I don't see how sending the drawings helps, they are just symbols/blocks, i have about 50 of them that need to be translated, and that could be hard coded into a lisp routine for example as it will always be the same set of blocks that need to be translated.
We just wanted to see what we're dealing with. Like is it annotative? , blocks that are uniformly scaled, are they dynamic blocks.? etc.. to avoid going back to you and asking the questions back and forth.
Jeez., You ask for our help. We're trying to give it to you.
Anyway I'm out.
Okay i get your point, i hadn't thought of all that. I attached my legend, but i will have to get you a drawing of there symbols tomorrow.
I greatly appreciate all of your help, sorry if i came off wrong, not intentional.
@justin wrote:Okay i get your point, i hadn't thought of all that. I attached my legend, but i will have to get you a drawing of there symbols tomorrow.
I greatly appreciate all of your help, sorry if i came off wrong, not intentional.
We can all see for ourselves if you do, but I'm currious:
Do these blocks share the same content, size & insertion points? Besides attributes. (do they have similar attributes if any) ?
I would be surprised if thats the case, which could make this a tedious job.
We are using the map version of AutoCAD, with an add on survey software, Carlson Survey 2018. I don't know if this helps being it is an AutoCAD forum, but we do have a license of Microstation Open Roads as well, so if that tool might help in this regard. My familiarity with Microstation is basically none.
In this case i have one client who needs this process, so a table or spreadsheet or whatever that defines a 1 to 1 block translation is what i am looking for, it could be hard coded because it will always be the same set of blocks being replaced.