ahyin Posted May 25, 2011 Posted May 25, 2011 If I running a AutoCAD command inside a loop, is it possible to count how many times unsuccessful inside this loops and store into a variable ? Thank you! Quote
irneb Posted May 25, 2011 Posted May 25, 2011 Well, the idea seems possible. You need a variable initialized to 0 before the loop starts, then simply increment it inside an if statement. Though the "problem" may be: "How to test for unsuccessful?" A possible way could be to start a command reactor on :vlr-commandFailed. Then instead of having the if & increment in the loop, you start the reactor before the loop. The reactor call-back would then check if the counting variable is assigned something (i.e. not nil), if so increment it. Of course after the loop you'll need to remove the reactor. Quote
ahyin Posted May 26, 2011 Author Posted May 26, 2011 Well, the idea seems possible. You need a variable initialized to 0 before the loop starts, then simply increment it inside an if statement. Though the "problem" may be: "How to test for unsuccessful?" A possible way could be to start a command reactor on :vlr-commandFailed. Then instead of having the if & increment in the loop, you start the reactor before the loop. The reactor call-back would then check if the counting variable is assigned something (i.e. not nil), if so increment it. Of course after the loop you'll need to remove the reactor. Thank you for your suggestion. Quote
ahyin Posted May 26, 2011 Author Posted May 26, 2011 Well, the idea seems possible. You need a variable initialized to 0 before the loop starts, then simply increment it inside an if statement. Though the "problem" may be: "How to test for unsuccessful?" A possible way could be to start a command reactor on :vlr-commandFailed. Then instead of having the if & increment in the loop, you start the reactor before the loop. The reactor call-back would then check if the counting variable is assigned something (i.e. not nil), if so increment it. Of course after the loop you'll need to remove the reactor. As you said, can I write the code like this ? (defun c:tmp (/ ctr tte sset item r ) (setq sset (ssget "_a" (LIST '(0 . "*polyline") (cons 410 (getvar "CTAB"))))) (setq ctr 0 tte 0 r 0) (repeat (sslength sset ) (setq item (ssname sset ctr)) (if (/= sset 0) (porgn (vl-cmdf "explode" item "") (princ "All objects exploded") ) (progn (setq r (1+ r)) );end if (if (/= r 0) (alert (strcat "total"(itoa r) "nos of polyline can't explode")) (princ "All polyline exploded") );end if );end if );end defun Quote
CHLUCFENG Posted May 26, 2011 Posted May 26, 2011 One quick notice: ... (if (/= sset 0) (progn (vl-cmdf "explode" item "") (princ "All objects exploded") ) ... Quote
CHLUCFENG Posted May 26, 2011 Posted May 26, 2011 Another quick tweak... This exploded all polylines I placed on screen: (defun c:tmp (/ ctr sset item r) [color=red]; tte [/color] (setq sset (ssget "_a" (LIST '(0 . "*polyline") (cons 410 (getvar "CTAB"))) ) ) (setq ctr 0 r 0) [color=red] ; tte 0)[/color] (repeat (sslength sset) (setq item (ssname sset ctr)) (if (/= sset 0) ([color=red]progn [/color] (vl-cmdf "[color=red]_.[/color]explode" item "") (princ "[color=red]\nThis[/color] object exploded") ) ;end progn [color=red] ;; (progn [/color] (setq r (1+ r)) [color=red] ;; ) ;end progn [/color] ) ;end if [color=red] (setq ctr (1+ ctr)) [/color] ) ;end repeat (if (/= r 0) (alert (strcat "[color=red]\n[/color][color=black]T[/color][color=black]otal[/color]" (itoa r) "nos of polyline can't explode") ) (princ "[color=red]\n[/color][color=black]All[/color] polyline exploded") ) ;end if [color=red] (princ) ; exit quietly [/color]) ;end defun The \n starts a new line that make the code easier to read, and the ending (princ) keeps the code from returning the final message twice. Quote
ahyin Posted May 26, 2011 Author Posted May 26, 2011 Another quick tweak... This exploded all polylines I placed on screen: (defun c:tmp (/ ctr sset item r) [color=red]; tte[/color] (setq sset (ssget "_a" (LIST '(0 . "*polyline") (cons 410 (getvar "CTAB"))) ) ) (setq ctr 0 r 0) [color=red] ; tte 0)[/color] (repeat (sslength sset) (setq item (ssname sset ctr)) (if (/= sset 0) ([color=red]progn[/color] (vl-cmdf "[color=red]_.[/color]explode" item "") (princ "[color=red]\nThis[/color] object exploded") ) ;end progn [color=red] ;; (progn[/color] (setq r (1+ r)) [color=red] ;; ) ;end progn[/color] ) ;end if [color=red](setq ctr (1+ ctr))[/color] ) ;end repeat (if (/= r 0) (alert (strcat "[color=red]\n[/color][color=black]T[/color][color=black]otal[/color]" (itoa r) "nos of polyline can't explode") ) (princ "[color=red]\n[/color][color=black]All[/color] polyline exploded") ) ;end if [color=red] (princ) ; exit quietly[/color] ) ;end defun The \n starts a new line that make the code easier to read, and the ending (princ) keeps the code from returning the final message twice. Thank you for your help, but when I try to work on a drawing without polylines. It failed to run. It can't return how many polylines can't explode. Quote
irneb Posted May 26, 2011 Posted May 26, 2011 Unfortunately what you want to do is not going to produce any errors, since the Explode command checks prior to attempting to explode. Just a small alternative: instead of sending each to the explode command, rather check if it is explodable through its ActiveX object: (vl-load-com) (defun c:ExpPolys (/ ss eo err res) (if (ssget "_a" (LIST '(0 . "*polyline") (cons 410 (getvar "CTAB")))) (progn (setq err 0 ss (vla-get-ActiveSelectionSet (vla-get-ActiveDocument (vlax-get-acad-object))) ) (vlax-for eo ss (if (vl-catch-all-error-p (setq res (vl-catch-all-apply 'vla-Explode (list eo)))) (setq err (1+ err)) ) ) (princ (strcat "\nOff " (itoa (vla-get-Count ss)) " polylines, " (itoa err) " couldn't be exploded.")) ;; Ensure selection set is cleared from RAM (vla-Delete ss) (vlax-release-object ss) (setq ss nil) (gc) ) (princ "\nNo polylines to explode.") ) (princ) ) However, that code will even explode polylines on LockedLayers. If you need to stick with those on Locked layers, then you need a bit more complex code: (vl-load-com) (defun c:ExpPolys (/ ss eo err lck res LckLay) ;; Firsth get all the locked layer names (vlax-for eo (vla-get-Layers (vla-get-ActiveDocument (vlax-get-acad-object))) (if (= (vla-get-Lock eo) :vlax-true) (setq LckLay (cons (vla-get-Name eo) LckLay)) ) ) ;; Next select and initialize variables (if (ssget "_a" (LIST '(0 . "*polyline") (cons 410 (getvar "CTAB")))) (progn (setq err 0 lck 0 ss (vla-get-ActiveSelectionSet (vla-get-ActiveDocument (vlax-get-acad-object))) ) ;; Step through all items in the selection set (vlax-for eo ss ;; Check if on locked layer (if (vl-position (vla-get-Layer eo) LckLay) (setq lck (1+ lck)) ;If locked increment lck ;; Else attempt to explode (if (vl-catch-all-error-p (setq res (vl-catch-all-apply 'vla-Explode (list eo)))) (setq err (1+ err)) ;If failed increment err ) ) ) (princ (strcat "\nOff " (itoa (vla-get-Count ss)) " polylines, " (itoa lck) " were on locked layers and " (itoa err) " couldn't be exploded." ) ) ;; Ensure selection set is cleared from RAM (vla-Delete ss) (vlax-release-object ss) (setq ss nil) (gc) ) (princ "\nNo polylines to explode.") ) (princ) ) Quote
ahyin Posted May 27, 2011 Author Posted May 27, 2011 Unfortunately what you want to do is not going to produce any errors, since the Explode command checks prior to attempting to explode. Just a small alternative: instead of sending each to the explode command, rather check if it is explodable through its ActiveX object: (vl-load-com) (defun c:ExpPolys (/ ss eo err res) (if (ssget "_a" (LIST '(0 . "*polyline") (cons 410 (getvar "CTAB")))) (progn (setq err 0 ss (vla-get-ActiveSelectionSet (vla-get-ActiveDocument (vlax-get-acad-object))) ) (vlax-for eo ss (if (vl-catch-all-error-p (setq res (vl-catch-all-apply 'vla-Explode (list eo)))) (setq err (1+ err)) ) ) (princ (strcat "\nOff " (itoa (vla-get-Count ss)) " polylines, " (itoa err) " couldn't be exploded.")) ;; Ensure selection set is cleared from RAM (vla-Delete ss) (vlax-release-object ss) (setq ss nil) (gc) ) (princ "\nNo polylines to explode.") ) (princ) ) However, that code will even explode polylines on LockedLayers. If you need to stick with those on Locked layers, then you need a bit more complex code: (vl-load-com) (defun c:ExpPolys (/ ss eo err lck res LckLay) ;; Firsth get all the locked layer names (vlax-for eo (vla-get-Layers (vla-get-ActiveDocument (vlax-get-acad-object))) (if (= (vla-get-Lock eo) :vlax-true) (setq LckLay (cons (vla-get-Name eo) LckLay)) ) ) ;; Next select and initialize variables (if (ssget "_a" (LIST '(0 . "*polyline") (cons 410 (getvar "CTAB")))) (progn (setq err 0 lck 0 ss (vla-get-ActiveSelectionSet (vla-get-ActiveDocument (vlax-get-acad-object))) ) ;; Step through all items in the selection set (vlax-for eo ss ;; Check if on locked layer (if (vl-position (vla-get-Layer eo) LckLay) (setq lck (1+ lck)) ;If locked increment lck ;; Else attempt to explode (if (vl-catch-all-error-p (setq res (vl-catch-all-apply 'vla-Explode (list eo)))) (setq err (1+ err)) ;If failed increment err ) ) ) (princ (strcat "\nOff " (itoa (vla-get-Count ss)) " polylines, " (itoa lck) " were on locked layers and " (itoa err) " couldn't be exploded." ) ) ;; Ensure selection set is cleared from RAM (vla-Delete ss) (vlax-release-object ss) (setq ss nil) (gc) ) (princ "\nNo polylines to explode.") ) (princ) ) Thank you so much ! Quote
dbroada Posted May 27, 2011 Posted May 27, 2011 I'm not following the code here but when you had to keep purging a drawing to get rid of sub entities I used to QSAVE before the purge and then check the value of DBMOD after the purge. If there had been a change in the drawing database DBMOD will have changed but when all items had been purged there was no change to the database. I'm not sure that it would work with explode but its just another possible route to explore. Quote
irneb Posted May 27, 2011 Posted May 27, 2011 That's a very good suggestion! Unfortunately it won't help in all cases for the OP. He wants to make a command which automatically explodes all polylines in the current space, but lists how many couldn't be exploded (for whatever reason). I suppose you could run the explode command, QSAVE, then run it again and see ... Wait a minute! That just gave me another idea! It's actually extremely simple! : (defun c:ExpPolys1 (/ ss len) (if (and (setq ss (ssget "_a" (LIST '(0 . "*polyline") (cons 410 (getvar "CTAB"))))) (setq len (sslength ss)) ) (progn (command "_.EXPLODE" ss "") (setq ss nil) (gc) (if (setq ss (ssget "_a" (LIST '(0 . "*polyline") (cons 410 (getvar "CTAB"))))) (princ (strcat "\nAttempted to explode " (itoa len) " polylines, but " (itoa (sslength ss)) " wouldn't explode." ) ) (princ (strcat "\nAll of " (itoa len) " polylines were exploded.")) ) (setq ss nil) (gc) ) (princ "\nThere were no polylines to explode.") ) (princ) ) Quote
irneb Posted May 27, 2011 Posted May 27, 2011 does that mean I helped? By all means: Yes! If it wasn't for your suggestion, I'd probably not have thought of doing it in a 2 step process! BTW, I'm probably still overcooking it by clearing selection sets twice. Probably a single gc call anywhere in the defun would have sufficed: (defun c:ExpPolys1 (/ ss len) (gc) (if (and (setq ss (ssget "_a" (LIST '(0 . "*polyline") (cons 410 (getvar "CTAB"))))) (setq len (sslength ss)) ) (progn (command "_.EXPLODE" ss "") (if (setq ss (ssget "_a" (LIST '(0 . "*polyline") (cons 410 (getvar "CTAB"))))) (princ (strcat "\nAttempted to explode " (itoa len) " polylines, but " (itoa (sslength ss)) " wouldn't explode." ) ) (princ (strcat "\nAll of " (itoa len) " polylines were exploded.")) ) ) (princ "\nThere were no polylines to explode.") ) (princ) ) You could even have left it out, but it's safer to try and clear selections sets since there's only a finite amount available. Quote
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.