3dwannab Posted June 3, 2015 Posted June 3, 2015 (edited) Hi all, I'm a casual basic lisper. Where in the code is wrong. I'm getting the ss with ssget. I want some error trapping to tell the users that nothing is selected. LISP selects all text regardless of layer. But this error I can't fix. I've tried looking at some examples but I can't get any to work. This works when objects are selected: (defun c:SEL_TEXT_ALL () (setq ss nil) (setq ss (ssget '((0 . "MTEXT,TEXT")))) (if (> (sslength ss) 0) (progn (command "Pselect" ss "") (princ (strcat "\nNumber of found Text objects : < " (itoa (sslength ss)) " >")) (setq ss nil) (princ) ) (princ (strcat "\n*** Nothing Selected ***")) ) ) Error I get when nothing selected: Select objects: ; error: bad argument type: lselsetp nil EDIT: Is it good practice to clear the selection set before the progn is run? Edited June 3, 2015 by 3dwannab Quote
David Bethel Posted June 3, 2015 Posted June 3, 2015 Maybe a simpler version : [b][color=BLACK]([/color][/b]defun c:stext [b][color=FUCHSIA]([/color][/b]/ ss[b][color=FUCHSIA])[/color][/b] [b][color=FUCHSIA]([/color][/b]if [b][color=NAVY]([/color][/b]setq ss [b][color=MAROON]([/color][/b]ssget '[b][color=GREEN]([/color][/b][b][color=BLUE]([/color][/b]0 . [color=#2f4f4f]"TEXT,MTEXT"[/color][b][color=BLUE])[/color][/b][b][color=GREEN])[/color][/b][b][color=MAROON])[/color][/b][b][color=NAVY])[/color][/b] [b][color=NAVY]([/color][/b]princ [b][color=MAROON]([/color][/b]strcat [color=#2f4f4f]"\n"[/color] [b][color=GREEN]([/color][/b]itoa [b][color=BLUE]([/color][/b]sslength ss[b][color=BLUE])[/color][/b][b][color=GREEN])[/color][/b] [color=#2f4f4f]" Text Entities Found"[/color][b][color=MAROON])[/color][/b][b][color=NAVY])[/color][/b] [b][color=NAVY]([/color][/b]princ [color=#2f4f4f]"\n*** Nothing Selected ***"[/color][b][color=NAVY])[/color][/b][b][color=FUCHSIA])[/color][/b] [b][color=FUCHSIA]([/color][/b]prin1[b][color=FUCHSIA])[/color][/b][b][color=BLACK])[/color][/b] There is no real need to clear ss prior to the call. (ssget) returns either nil or a PICKSET I don't quite understand the PSelect command? You have bound the variable ss to the PICKSET. I declared ss local to this function, but you could just as easily make it part of larger 1. -David Quote
Tharwat Posted June 3, 2015 Posted June 3, 2015 (if (> (sslength ss) 0) Error I get when nothing selected: Select objects: ; error: bad argument type: lselsetp nil That is because you are trying to get the number of the selection set variable while it is equal to nil , so to get sure that the selection set variable has a selection just add the function add with the variable , eg. (if (and ss (> (sslength ss) 0)) EDIT: Is it good practice to clear the selection set before the progn is run? Actually the way you did write the routine is not the recommended one and you did take the longest way to reach the destination , so have a look about the following modification of your codes . (defun c:SEL_TEXT_ALL (/ ss) (if (setq ss (ssget '((0 . "MTEXT,TEXT")))) (princ (strcat "\nNumber of found Text objects : < " (itoa (sslength ss)) " >" )) (princ "\n*** Nothing Selected ***") ) (sssetfirst nil ss) (princ) ) Just ask if you have any doubts Quote
3dwannab Posted June 3, 2015 Author Posted June 3, 2015 Thanks guys for the quick responses. This forums great. Building up a LISP file with handy custom selection sets. Will post when I've completed it. Quote
3dwannab Posted June 3, 2015 Author Posted June 3, 2015 Trying to incorporate a fn found here:http://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/how-to-filter-xrefs-out-from-ssget-list-cons-0-quot-insert-quot/m-p/2852572#M293570 for selection of blocks and not xrefs. Wrapping the if command like before doesn't work. (defun c:SEL_BLOCKS (/ ss) ;; FN by lpseifert @ http://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/how-to-filter-xrefs-out-from-ssget-list-cons-0-quot-insert-quot/m-p/2852572#M293570 (if (setq ss (ssget (list (cons 0 "INSERT"))) idx -1) ( (repeat (sslength ss) (setq en (ssname ss (setq idx (1+ idx))) obj (vlax-ename->vla-object en) ) (if (vlax-property-available-p obj 'Path) (progn (ssdel en ss) (setq idx (1- idx)) ) ) ) (princ (strcat "\nNumber of found Blocks : < " (itoa (sslength ss)) " >")) ) (princ "\n*** Nothing Selected ***") ) (sssetfirst nil ss) (princ) ) Quote
Commandobill Posted June 3, 2015 Posted June 3, 2015 Don't forget your progn! (defun c:SEL_BLOCKS (/ ss) ;; FN by lpseifert @ http://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/how-to-filter-xrefs-out-from-ssget-list-cons-0-quot-insert-quot/m-p/2852572#M293570 (if (setq ss (ssget (list (cons 0 "INSERT"))) idx -1) (progn (repeat (sslength ss) (setq en (ssname ss (setq idx (1+ idx))) obj (vlax-ename->vla-object en) ) (if (vlax-property-available-p obj 'Path) (progn (ssdel en ss) (setq idx (1- idx)) ) ) ) (princ (strcat "\nNumber of found Blocks : < " (itoa (sslength ss)) " >")) ) (princ "\n*** Nothing Selected ***") ) (sssetfirst nil ss) (princ) ) Quote
Commandobill Posted June 3, 2015 Posted June 3, 2015 No, but seriously, that was all that was missing. Quote
3dwannab Posted June 3, 2015 Author Posted June 3, 2015 Thank you. When you're working and trying to learn LISP at the same time it's easy to miss out on the simplest thing. EDIT, tried that but when nothings selected it's come with ; error: bad argument type: lselsetp nil (defun c:SEL_BLOCKS (/ ss) ;; FN by lpseifert @ http://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/how-to-filter-xrefs-out-from-ssget-list-cons-0-quot-insert-quot/m-p/2852572#M293570 (if (setq ss (ssget (list (cons 0 "INSERT"))) idx -1) [color=red][b]([/b][/color](progn (repeat (sslength ss) (setq en (ssname ss (setq idx (1+ idx))) obj (vlax-ename->vla-object en) ) (if (vlax-property-available-p obj 'Path) (progn (ssdel en ss) (setq idx (1- idx)) ) ) ) ) (princ (strcat "\nNumber of found Blocks : < " (itoa (sslength ss)) " >"))[color=red][b])[/b][/color] (princ "\n*** Nothing Selected ***") ) (sssetfirst nil ss) (princ) ) Tried to wrap the progn up so that it was in the if and then (princ "\n*** Nothing Selected ***") outside that for the else with extra parentheses but didn't work. Quote
Lee Mac Posted June 3, 2015 Posted June 3, 2015 Hint: a setq expression will return the last value bound to the last symbol argument - in your case, the initial setq expression will return -1 Quote
Lee Mac Posted June 3, 2015 Posted June 3, 2015 Consider the following: (defun c:sel_blocks ( / def lst sel ) ;; Iterate over the block table and compile a list of xref blocks to exclude (while (setq def (tblnext "block" (not def))) (if (= 4 (logand 4 (cdr (assoc 70 def)))) (setq lst (vl-list* "," (cdr (assoc 2 def)) lst)) ) ) ;; Attempt to retrieve a selection of blocks (but not xrefs) (if (setq sel (ssget (cons '(0 . "INSERT") (if lst (vl-list* '(-4 . "<NOT") (cons 2 (apply 'strcat (cdr lst))) '((-4 . "NOT>"))))))) (princ (strcat "\nNumber of blocks: " (itoa (sslength sel)))) (princ "\nNothing selected.") ) (princ) ) Quote
Commandobill Posted June 3, 2015 Posted June 3, 2015 Way to keep it simple, Lee. To reiterate what Lee's initial point was You need set your 'idx' variable else where, like this. (defun c:SEL_BLOCKS (/ ss) ;; FN by lpseifert @ http://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/how-to-filter-xrefs-out-from-ssget-list-cons-0-quot-insert-quot/m-p/2852572#M293570 (setq idx -1) (if (setq ss (ssget (list (cons 0 "INSERT")))) ((progn (repeat (sslength ss) (setq en (ssname ss (setq idx (1+ idx))) obj (vlax-ename->vla-object en) ) (if (vlax-property-available-p obj 'Path) (progn (ssdel en ss) (setq idx (1- idx)) ) ) ) ) (princ (strcat "\nNumber of found Blocks : < " (itoa (sslength ss)) " >"))) (princ "\n*** Nothing Selected ***") ) (sssetfirst nil ss) (princ) ) Quote
3dwannab Posted June 4, 2015 Author Posted June 4, 2015 Consider the following: Thanks this creates a selection set. after it's run it selects nothing. Is it suppose to? Way to keep it simple, Lee. To reiterate what Lee's initial point was You need set your 'idx' variable else where, like this. (defun c:SEL_BLOCKS (/ ss) ;; FN by lpseifert @ http://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/how-to-filter-xrefs-out-from-ssget-list-cons-0-quot-insert-quot/m-p/2852572#M293570 (setq idx -1) (if (setq ss (ssget (list (cons 0 "INSERT")))) ((progn (repeat (sslength ss) (setq en (ssname ss (setq idx (1+ idx))) obj (vlax-ename->vla-object en) ) (if (vlax-property-available-p obj 'Path) (progn (ssdel en ss) (setq idx (1- idx)) ) ) ) ) (princ (strcat "\nNumber of found Blocks : < " (itoa (sslength ss)) " >"))) (princ "\n*** Nothing Selected ***") ) (sssetfirst nil ss) (princ) ) Thanks, this now creates an error when blocks have been selected. The opposite of what was happening. Number of found Blocks : < 3 >; error: no function definition: nil Quote
David Bethel Posted June 4, 2015 Posted June 4, 2015 '(-4 . "") )[/code] Looks good Lee. Is there no longer a limit to the string length of a filter ? -David Quote
3dwannab Posted June 4, 2015 Author Posted June 4, 2015 Consider the following: Please forgive my blatant disregard for learning anything. Lunch break has helped me figure it out. Working code to select blocks only. Thanks Lee Mac. (defun c:sel_blocks ( / def lst sel ) ; FN by Lee Mac http://www.cadtutor.net/forum/showthread.php?92638-Simple-fix-%28LISP-noob%29-Syntax-problem&p=633824&viewfull=1#post633824 ;; Iterate over the block table and compile a list of xref blocks to exclude (while (setq def (tblnext "block" (not def))) (if (= 4 (logand 4 (cdr (assoc 70 def)))) (setq lst (vl-list* "," (cdr (assoc 2 def)) lst)) ) ) ;; Attempt to retrieve a selection of blocks (but not xrefs) (if (setq sel (ssget (cons '(0 . "INSERT") (if lst (vl-list* '(-4 . "<NOT") (cons 2 (apply 'strcat (cdr lst))) '((-4 . "NOT>"))))))) (princ (strcat "\nNumber of blocks: " (itoa (sslength sel)))) (princ "\n*** Nothing Selected ***") ) (sssetfirst nil sel) (princ) ) How can I expand on this to select only annotative blocks. Where can I find good info for this? EDIT: I have a code for the selection of non associative hatches: (setq ss (ssget '((0 . "HATCH") (-4 . "=") (71 . 0)))) What fn has (-4 . "=") (71 . 0) Do they relate to the standard filter dialog in any way? Quote
Lee Mac Posted June 4, 2015 Posted June 4, 2015 Way to keep it simple, Lee. Thanks this creates a selection set. after it's run it selects nothing. Is it suppose to? Please forgive my blatant disregard for learning anything. Lunch break has helped me figure it out.Working code to select blocks only. Thanks Lee Mac. No problem - as you've gathered, the sssetfirst function will highlight & grip a given selection set, though, even without this function and without highlighting & gripping the selection set, Select > Previous will still acquire the selection set obtained by ssget. Looks good Lee. Thanks David Is there no longer a limit to the string length of a filter ? A character limit for DXF string groups in the selection filter list may still exist, though, I am not sure exactly what that limit may be as I have not encountered issues up to now. Of course, an alternative approach to circumvent any potential character limit could be simply: (defun c:sel_blocks ( / def lst sel ) ;; Iterate over the block table and compile a list of xref blocks to exclude (while (setq def (tblnext "block" (not def))) (if (= 4 (logand 4 (cdr (assoc 70 def)))) (setq lst (cons (assoc 2 def) lst)) ) ) ;; Attempt to retrieve a selection of blocks (but not xrefs) (if (setq sel (ssget (cons '(0 . "INSERT") (if lst (append '((-4 . "<NOT") (-4 . "<OR")) lst '((-4 . "OR>") (-4 . "NOT>"))))))) (princ (strcat "\nNumber of blocks: " (itoa (sslength sel)))) (princ "\nNothing selected.") ) (princ) ) How can I expand on this to select only annotative blocks. Where can I find good info for this? Annotative data complicates matters somewhat - consider the following: (defun c:sel_blocks ( / ano def sel xrf ) (while (setq def (tblnext "block" (not def))) (setq blk (assoc 2 def)) (cond ( (= 4 (logand 4 (cdr (assoc 70 def)))) (setq xrf (cons blk xrf)) ) ( (= 1 (cdr (assoc 1070 (reverse (cadr (assoc -3 (entget (cdr (assoc 330 (entget (tblobjname "block" (cdr blk)) ) ) ) ) ) ) ) ) ) ) (setq ano (cons blk ano)) ) ) ) (if (setq sel (ssget (append '((0 . "INSERT")) (if ano (append '((-4 . "<OR")) ano '((-4 . "OR>")) ) ) (if xrf (append '((-4 . "<NOT") (-4 . "<OR")) xrf '((-4 . "OR>") (-4 . "NOT>")) ) ) ) ) ) (princ (strcat "\nNumber of blocks: " (itoa (sslength sel)))) (princ "\nNothing selected.") ) (sssetfirst nil sel) (princ) ) EDIT: I have a code for the selection of non associative hatches: (setq ss (ssget '((0 . "HATCH") (-4 . "=") (71 . 0)))) What fn has (-4 . "=") (71 . 0) Do they relate to the standard filter dialog in any way? You may find my ssget function reference helpful in this regard - though, in your example, the '(-4 . "=") is not actually required as the ssget filter list uses an implicit AND logic (that is, by default every item in the list must match). Quote
David Bethel Posted June 4, 2015 Posted June 4, 2015 A character limit for DXF string groups in the selection filter list may still exist, though, I am not sure exactly what that limit may be as I have not encountered issues up to now. I still see references of 'approximately 500 character limit' for wcmatch and that ssget follows it's rules. -David Quote
3dwannab Posted June 4, 2015 Author Posted June 4, 2015 Consider the following: Thanks, I've attached an example I've tested on. Saved in 2010 ACAD. The code you posted selects non-Anno blocks in this example. Test Drawing Annotative Verus Non Anno Blocks.dwg So, maybe would the process be easier say if I just wanted to select all annotative objects instead using something like: (setq ss1 (ssget "all" )) and then apply a filter after this to select Anno objects. ACAD Help does not list these filters completely or am I missing something? This will complete my quest for quick selection tools. Quote
Lee Mac Posted June 4, 2015 Posted June 4, 2015 I still see references of 'approximately 500 character limit' for wcmatch and that ssget follows it's rules. After a quick test, I'm not seeing that limit with wcmatch: _$ (setq str "x") "x" _$ (repeat 500 (setq str (strcat "x" str))) "xxxxxxxxxxx...xxxxxxxxxxxxx" _$ (strlen str) 501 _$ (wcmatch str "*x*") T _$ (repeat 500 (setq str (strcat "a" str))) "aaaaaaaaaaaaaaa...xxxxxxxxxxx" _$ (strlen str) 1001 _$ (wcmatch str "*x*") T _$ (repeat 500 (setq str (strcat "b" str))) "bbbbbbbbbbbb...xxxxxxxxxxxxxxx" _$ (strlen str) 1501 _$ (wcmatch str "*x*") T Quote
David Bethel Posted June 4, 2015 Posted June 4, 2015 From 2000 -> 2004 help and 2012 Autodesk exchange A string containing the pattern to match against string. The pattern can contain the wild-card pattern-matching characters shown in the table Wild-card characters. You can use commas in a pattern to enter more than one pattern condition. Only the first 500 characters (approximately) of the string and pattern are compared; anything beyond that is ignored Go figure -David Quote
Lee Mac Posted June 4, 2015 Posted June 4, 2015 Thanks, I've attached an example I've tested on. Saved in 2010 ACAD. The code you posted selects non-Anno blocks in this example. Sorry, I had overlooked a few things: (defun c:sel_blocks ( / blk def lst sel ) (while (setq def (tblnext "block" (not def))) (setq blk (cdr (assoc 2 def))) (cond ( (= 4 (logand 4 (cdr (assoc 70 def)))) (setq lst (cons (cons 2 (LM:escapewildcards blk)) lst)) ) ( (/= 1 (cdr (assoc 1070 (reverse (cadr (assoc -3 (entget (cdr (assoc 330 (entget (tblobjname "block" blk) ) ) ) '("AcadAnnotative") ) ) ) ) ) ) ) (setq lst (cons (cons 2 (LM:escapewildcards blk)) lst)) ) ) ) (if lst (if (setq sel (ssget (append '((0 . "INSERT") (-4 . "<NOT") (-4 . "<OR")) lst '((-4 . "OR>") (-4 . "NOT>"))))) (princ (strcat "\nNumber of blocks: " (itoa (sslength sel)))) (princ "\nNothing selected.") ) (princ "\nNo valid blocks found in drawing.") ) (sssetfirst nil sel) (princ) ) ;; Escape Wildcards - Lee Mac ;; Escapes wildcard special characters in a supplied string (defun LM:escapewildcards ( str ) (vl-list->string (apply 'append (mapcar '(lambda ( c ) (if (member c '(35 64 46 42 63 126 91 93 45 44)) (list 96 c) (list c) ) ) (vl-string->list str) ) ) ) ) Escape Wildcards function from here. Note that the above code will still not be compatible with annotative dynamic blocks, as these will require yet more checks. ACAD Help does not list these filters completely or am I missing something? Correct - the developer documentation in AutoCAD is not complete. 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.