rphillips Posted August 26, 2009 Share Posted August 26, 2009 I have a list of blocks that i need to replace when there is one in the dwg file. Below is the code that i use to do that with but i would like to add to this. My problem When we receive files from our surveyor the blocks are repeated; example, if we have a block named X then it creates a new block for every occurrence (like so X_1, X_2, X_3) and so on. So the code below allows me to select all the blocks that have an X_ in the name and then it will replace with the correct name X. Currently I use the quick select command >block reference > Name > wilcard match > to search and find any block with an X_ in the name. My Goal For the code to do all the replaces using a list in the code. I would like to add the search to the lisp and if no blocks in current file the just ignore. the list would be something like X_ APOINT_ MH_ FH_ I will compile the list in the code while testing. then the code will replace name with name from another list X APOINT MH FH and so. Basicly I have a dwg with about 4000 blocks in it and it should only have abut 100. X_1 X_2 X_1000 Should all be X Thanks for the help (DEFUN C:replace () (SETQ SS (SSGET)) (SETQ L 0) (SETQ NB (GETSTRING "\nNEW BLOCK NAME TO REPLACE OLD:")) (SETQ N (SSLENGTH SS)) (WHILE ( (SETQ E (ENTGET (SSNAME SS L))) (SETQ E (SUBST (CONS 2 NB) (ASSOC 2 E) E ) ) (ENTMOD E) (SETQ L (1+ L)) ) ) Quote Link to comment Share on other sites More sharing options...
Freerefill Posted August 26, 2009 Share Posted August 26, 2009 This should get you started. My lunch break is almost over so I can't do it all for you, but it'll help with the automation: (mapcar '(lambda (x) (ssget "X" (list (cons 2 x)))) (list "X_*" "APOINT_*")) That returns a list of selection sets, the first one being all blocks with a name that begins with "X_", and so on. You can make the list as long as you'd like. Alls you need is to loop through and do something with each selection set, like a block replace. Good luck, I'm sure you've got enough smarts to figure out the rest, if you've come so far already. ^.^ EDIT: And before anyone "corrects" me, yes, you could probably just extend the Lambda to include the block replace. I just don't have the time. EDIT EDIT: Meh.. See if this works, it's untested. It'll insert the correct block at the same insertion point of the incorrect block, then delete the incorrect one. At least, that's the idea. My fingers are crossed. (defun c:test( / ss entSet) (mapcar '(lambda (x) (setq ss (ssget "X" (list (cons 2 (strcat x "_*"))))) (if ss (progn (setq entSet (vl-remove-if-not '(lambda (y) (= (type (cadr y)) 'ENAME)) (ssnamex ss))) (mapcar '(lambda (z) (vl-cmdf "-insert" x (cdr (assoc 10 (entget z))) "" "" "" "erase" z "")) entSet) ) ) ) (list "X" "APOINT")) ) Quote Link to comment Share on other sites More sharing options...
rphillips Posted August 26, 2009 Author Share Posted August 26, 2009 First of all thanks for the hlep! This is what i get when running the code. test ; error: bad argument type: lentityp (0 0) Quote Link to comment Share on other sites More sharing options...
Freerefill Posted August 26, 2009 Share Posted August 26, 2009 First of all thanks for the hlep! This is what i get when running the code. test ; error: bad argument type: lentityp (0 0) Yep, I know what went wrong.. forgot to mapcar a 'cadr to the vl-remove-if-not. Try this: (defun c:test( / ss entSet) (mapcar '(lambda (x) (setq ss (ssget "X" (list (cons 2 (strcat x "_*"))))) (if ss (progn (setq entSet (mapcar 'cadr (vl-remove-if-not '(lambda (y) (= (type (cadr y)) 'ENAME)) (ssnamex ss)))) (mapcar '(lambda (z) (vl-cmdf "-insert" x (cdr (assoc 10 (entget z))) "" "" "" "erase" z "")) entSet) ) ) ) (list "X" "APOINT")) ) Quote Link to comment Share on other sites More sharing options...
rphillips Posted August 26, 2009 Author Share Posted August 26, 2009 Thanks, I think that this works but i dont understand the code. This process takes to long there is about 4000 blocks and i belive this code has to repeat for every block. This is what i am going to use (setq SS (ssget "x" (list (cons 2 "X_*")))) (if ss (progn (SETQ L 0) (SETQ N (SSLENGTH SS)) (WHILE ( (SETQ E (ENTGET (SSNAME SS L))) (SETQ E (SUBST (CONS 2 "X") (ASSOC 2 E) E ) ) (ENTMOD E) (SETQ L (1+ L)) ) ) ) then i will repeat the code for to search for other blocks this seams to be a lot faster. At the begining of my code i set cmdecho to 0 and then at the end i set it to 1 but for some reason when i do a purge it still list all the blocks deleted. Is there another way to get the command line not to repeat the info? Quote Link to comment Share on other sites More sharing options...
Lee Mac Posted August 26, 2009 Share Posted August 26, 2009 FYI, ssnamex is a slow process and will take a long time to execute for a large number of blocks. Quote Link to comment Share on other sites More sharing options...
Lee Mac Posted August 26, 2009 Share Posted August 26, 2009 If you are substituting the Block Name, the alternative block definition must be in the drawing also. The old block definitions will also still be in the database and will need to be purged. Quote Link to comment Share on other sites More sharing options...
rphillips Posted August 26, 2009 Author Share Posted August 26, 2009 (DEFUN C:RB ( / OriginalErrorHandling) (vl-load-com) (setq OriginalErrorHandling *error*) (setq *error* ReplaceBlock_Error) (setvar "cmdecho" 0) (command "undo" "begin") (command"ucs" "") (setq SS (ssget "x" (list (cons 2 "X_*")))) (if ss (progn (SETQ L 0) (SETQ N (SSLENGTH SS)) (WHILE ( (SETQ E (ENTGET (SSNAME SS L))) (SETQ E (SUBST (CONS 2 "X") (ASSOC 2 E) E ) ) (ENTMOD E) (SETQ L (1+ L)) ) ) ) (setq SS (ssget "x" (list (cons 2 "APOINT_*")))) (if ss (progn (SETQ L 0) (SETQ N (SSLENGTH SS)) (WHILE ( (SETQ E (ENTGET (SSNAME SS L))) (SETQ E (SUBST (CONS 2 "APOINT") (ASSOC 2 E) E ) ) (ENTMOD E) (SETQ L (1+ L)) ) ) ) (command"-purge" "blocks" "" "no") (command "ucs" "p") (command "undo" "end") (setvar "cmdecho" 1) (princ) ) This is what i have so far the lines in red are the lines that i wll have to change the text in cyan is what will be changed in each line. Does anyone see a better way to do this. thanks Quote Link to comment Share on other sites More sharing options...
Lee Mac Posted August 26, 2009 Share Posted August 26, 2009 Does BLOCKREPLACE from ET not cut it? Quote Link to comment Share on other sites More sharing options...
rphillips Posted August 26, 2009 Author Share Posted August 26, 2009 Sure it will work if i want to go and pick all the blocks. Please read first post for more information. Thanks for the help I know the blocks will still be there that is why there is a purge at the end of the code. I just dont what the end user to see all the blocks being deleted. Quote Link to comment Share on other sites More sharing options...
Lee Mac Posted August 26, 2009 Share Posted August 26, 2009 I don't think Purge messages can be suppressed using CMDECHO, but NOMUTT may do it Quote Link to comment Share on other sites More sharing options...
rphillips Posted August 26, 2009 Author Share Posted August 26, 2009 Nope, But a good one to add to the books. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.