Jump to content

Simple fix (LISP noob) Syntax problem


3dwannab

Recommended Posts

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 by 3dwannab
Link to comment
Share on other sites

  • Replies 24
  • Created
  • Last Reply

Top Posters In This Topic

  • 3dwannab

    9

  • Lee Mac

    7

  • David Bethel

    5

  • Commandobill

    3

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

Link to comment
Share on other sites

     (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 :)

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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)
)

Link to comment
Share on other sites

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)
)

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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)
)

Link to comment
Share on other sites

Way to keep it simple, Lee. :P

 

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)
)

Link to comment
Share on other sites

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. :P

 

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

Link to comment
Share on other sites

'(-4 . "")

)[/code]

 

Looks good Lee.

 

Is there no longer a limit to the string length of a filter ?

 

-David

Link to comment
Share on other sites

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?

Link to comment
Share on other sites

Way to keep it simple, Lee. :P

 

o:)

 

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 :thumbsup:

 

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).

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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 :shock: -David

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...