Announcements

The Autodesk Community Forums has a new look. Read more about what's changed on the Community Announcements board.

Replace a block with another block with same name that has 'open' added to the name

johnw
Collaborator

Replace a block with another block with same name that has 'open' added to the name

johnw
Collaborator
Collaborator

I attempted to create a lisp routine but it's not working.

 

Routine is called SGDO for "SGD Open" command.

 

Goal/example: user "picks" a block in a drawing named 80sgd. The command would then instantly insert a block called 80sgdopen and replace the old block. The orientation, scale, insertion point, and layer would all be the same as the old block. The command should swap out each block as they are picked, but allow the user to continue going around and picking other blocks if they wish to do so.

 

Attached is what I have written so far but I think it definitely needs help before it will work. Any assistance is appreciated. 

 

Thanks, John

0 Likes
Reply
Accepted solutions (1)
851 Views
18 Replies
Replies (18)

pendean
Community Legend
Community Legend

@johnw wrote:

...The orientation, scale, insertion point, and layer would all be the same as the old block. ....


That's a function of how you create the replacement block, all you have to do is remain consistent, then a simple commandline version of INSERT command oldname=newname is all you ever need to do.

 

ADCENTER will let you replace old-with-new blocks too.

 

Do your blocks (new or old) have any attributes that need to be sync-ed?

MrJSmith
Advocate
Advocate

@johnw One of the first LISPs I wrote! Might help?

 

;Info: Replaces blocks. Updates a selected "old" block with a selected "new" block.
(defun c:BlockReplaceNew (/ ss ct oldBlock newBlock elist sync) ;Replace an old block with a new one
	(while (= oldBlock nil)
		(print "Select OLD block to replace.")
		(setq oldBlock (ssget "_+.:E:S"))
		(if (and (/= oldBlock nil) (assoc 2 (entget (ssname oldBlock 0))))
			(setq oldBlock (assoc 2 (entget (ssname oldBlock 0))))
			(setq oldBlock nil)
		)
	)
	(while (= newBlock nil)
		(print "Select NEW block to use.")
		(setq newBlock (ssget "_+.:E:S"))
		; (print newBlock)
		; (print (tovla newBlock))
		(if (and (/= newBlock nil) (assoc 2 (entget (setq newBlock (ssname newBlock 0)))))
			(setq 
				; sync (= :vlax-true (vla-get-hasattributes (tovla newBlock)))
				newBlock (entget newBlock)
			)
			(setq newBlock nil)
		)
		
	)
	(print "Select OLD BLOCKS in area to change.")
	; (debug "Old Block: " (list oldBlock))
	(setq ss (ssget (list oldBlock)))
	
	;Update the Blocks
	(setq ct 0)
	(repeat (sslength ss)
		(setq elist(entget (ssname ss ct))) 
		(setq elist(subst (assoc 2 newBlock) (assoc 2 elist) elist)) 
		(entmod elist) ;Update the entity
		(setq ct (1+ ct)) ;Count through the selection set, check all the items
	)
	
	; (if sync (command "ATTSYNC" "S" ss "Y"))
	(print "Blocks have been updated!")
)
0 Likes

johnw
Collaborator
Collaborator

Its close to what I need but there are steps not needed in your code. I just need to simplify it. 

 

"Select a block" it gets the name, it then adds "open" to the that block name, then inserts the new block in the same location, orientation, and layer.

 

Example. I select a block called 80sgd, I want the command to then insert a block called 80sgdopen in the same location, automatically with only me having to pick the initial block.

 

If there is not replacement block with that name it would simply state "That block cannot be found". 

 

I hope I'm explaining myself good enough.

0 Likes

MrJSmith
Advocate
Advocate

@johnw See if this works for you.

 

(defun c:SGDO  (/ oldBlock oldBlockss newBlock elist) 
	(while (= oldBlock nil)
		(print "Select OLD block to replace.")
		(setq oldBlockss (ssget "_+.:E:S"))
		(if (and (/= oldBlockss nil) (assoc 2 (entget (ssname oldBlockss 0))))
			(setq oldBlock (assoc 2 (entget (ssname oldBlockss 0))))
			(setq oldBlock nil)
		)
	)
	(setq newBlock (strcat (cdr oldBlock) "open"))
	(if (tblsearch "block" newBlock)
		(progn
			(setq elist (entget (ssname oldBlockss 0)))
			(setq elist(subst newBlock (assoc 2 elist) elist)) 
			(entmod elist) ;Update the entity
		)
		(print (strcat "Block could not be found: " newBlock))
	)
)

 

 

 

0 Likes

johnw
Collaborator
Collaborator

When I select the block, nothing happens. It doesn't even appear to 'select' the block. Command line still says 'select old block to replace'... no matter how many times I attempt to pick the block.

0 Likes

MrJSmith
Advocate
Advocate

@johnw  Haha whoops! Try the code now. I edited it to hopefully fix the issue.

0 Likes

johnw
Collaborator
Collaborator

When I select the block I received this message at command line:

 

Error: bad argument type: stringp (2 . "80sg")

0 Likes

MrJSmith
Advocate
Advocate

@johnw  Making progress. Try now.

0 Likes

johnw
Collaborator
Collaborator

Ok. the pick worked and when I selected the block it said "Cannot find block 80sgopen", that's good and bad. Its good because the command seems to be getting closer to working. Bad because it didn't search outside of my drawing along my file search paths to located the block to insert. Typically if I go to insert a block and it's not in the current drawing it will go out and find it via my search paths.

Secondly, when I inserted the 80sgopen block manually into the drawing first, then ran this command, I received this error message when I picked the block to change.

Error: bad argument type: listp "80sgopen"

0 Likes

MrJSmith
Advocate
Advocate

Yeah..... I am not sure about the insert via your paths without doing something like Lee Mac's steal function. This isn't an AutoCAD Command....

 

As for the listP issue, try this.

 

(defun c:SGDO  (/ oldBlock oldBlockss newBlock elist) 
	(while (= oldBlock nil)
		(print "Select OLD block to replace.")
		(setq oldBlockss (ssget "_+.:E:S"))
		(if (and (/= oldBlockss nil) (assoc 2 (entget (ssname oldBlockss 0))))
			(setq oldBlock (assoc 2 (entget (ssname oldBlockss 0))))
			(setq oldBlock nil)
		)
	)
	(setq newBlock (strcat (cdr oldBlock) "open"))
	(if (tblsearch "block" newBlock)
		(progn
			(setq elist (entget (ssname oldBlockss 0)))
			(setq elist(subst (cons 2 newBlock) (assoc 2 elist) elist)) 
			(entmod elist) ;Update the entity
		)
		(print (strcat "Block could not be found: " newBlock))
	)
)

 

 

0 Likes

johnw
Collaborator
Collaborator

got this error when picking the block:

 

Error: bad DXF group: "80sgopen"

0 Likes

MrJSmith
Advocate
Advocate

@johnw Death by a million paper cuts. Try now.

0 Likes

johnw
Collaborator
Collaborator

Good news! Command works now!! as long as the block that ends in "open" is already inside the drawing. So at least we got that going for us. thanks for your help.

 

I just need to figure out how the command can use the regular 'insert' command to retrieve a block outside of a drawing just like any regular insert command does.... I appreciate your help on this!!! 

0 Likes

MrJSmith
Advocate
Advocate
Accepted solution

@johnw I played around with that idea. Check to see if this works.

 

 

(defun c:SGDO  (/ ss oldBlock oldBlockss newBlock elist) 
	(while (= oldBlock nil)
		(print "Select OLD block to replace.")
		(setq oldBlockss (ssget "_+.:E:S"))
		(if (and (/= oldBlockss nil) (assoc 2 (entget (ssname oldBlockss 0))))
			(setq oldBlock (assoc 2 (entget (ssname oldBlockss 0))))
			(setq oldBlock nil)
		)
	)
	(setq newBlock (strcat (cdr oldBlock) "open"))
	(if (tblsearch "block" newBlock)
		(progn
			(setq elist (entget (ssname oldBlockss 0)))
			(setq elist(subst (cons 2 newBlock) (assoc 2 elist) elist)) 
			(entmod elist) ;Update the entity
			(print (strcat "OldBlock: " (cdr oldBlock) " has been updated too: " newBlock "!"))
			(princ)
		)
		(progn
			(command "-INSERT" newBlock (list 0 0) "1"  "1" "0")
			(if (setq ss (ssget "_A" (list (cons 2 newBlock))))
				(progn
					(command "erase" "p" "")
					(setq elist (entget (ssname oldBlockss 0)))
					(setq elist (subst (cons 2 newBlock) (assoc 2 elist) elist)) 
					(entmod elist) ;Update the entity
					(print (strcat "OldBlock: " (cdr oldBlock) " has been updated too: " newBlock "!"))
					(princ)
				)
				(print (strcat "Block could not be found: " newBlock))
			)
		)
	)
)

 

 

 

johnw
Collaborator
Collaborator

That worked! I did get a lot of command line 'unknown command' type stuff... see below:

 

Select objects:
Unknown command "-ERASE". Press F1 for help.
Unknown command "P". Press F1 for help.
Unknown command "SGD4". Press F1 for help.
((-1 . <Entity name: 21b20d12990>) (0 . "INSERT") (330 . <Entity name: 21b7bde4180>) (5 . "10C309") (100 . "AcDbEntity") (67 . 0) (410 . "Model") (8 . "DRSWIND") (100 . "AcDbBlockReference") (2 . "80sgopen") (10 2285.0 596.0 0.0) (41 . 1.0) (42 . 1.0) (43 . 1.0) (50 . 3.14159) (70 . 0) (71 . 0) (44 . 0.0) (45 . 0.0) (210 0.0 0.0 1.0))

0 Likes

MrJSmith
Advocate
Advocate

@johnw So close! šŸ˜ Try it now. Should work properly.

0 Likes

johnw
Collaborator
Collaborator

 IT WORKS! Thanks a lot for your help on this! Have a great weekend! 

MrJSmith
Advocate
Advocate

Awesome! Did you want me to wrap it in a while loop so it continues until your press esc?

0 Likes