Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Trouble with SSget

12 REPLIES 12
Reply
Message 1 of 13
Dpipke
457 Views, 12 Replies

Trouble with SSget

Hi All,

I'm trying my hand at learning autolsp

With that in mind I thought I would just jump in and try to write a simple program. Basically I want to have the program display the number of two different types of objects for me. (in this case circles on different layers) but I keep getting an error bad argument file 2 which I'm not sure how to fix (from research its seems to be a problem with the selection sets). the code is copied below. Any thoughts? (hopefully this is the right place to post it)

(defun C:Halocount ()
(setq HR(ssget "x" (list (cons 8 "HE-HALO-XRED-X") (cons 0 "CIRCLE"))))
(setq HG(ssget "x" (list (cons 8 "HE-HALO-XGRN-X") (cons 0 "CIRCLE"))))
(setq HRC(sslength HR))
(setq HGC(sslength HG))
(Princ "Number of Red Halos=" HRC)
(Princ "Number of Green Halos=" HGC)
)

12 REPLIES 12
Message 2 of 13
Kent1Cooper
in reply to: Dpipke


@Dpipke wrote:

.... I want to have the program display the number of two different types of objects for me. (in this case circles on different layers) but I keep getting an error bad argument file 2 which I'm not sure how to fix (from research its seems to be a problem with the selection sets). ....

(defun C:Halocount ()
(setq HR(ssget "x" (list (cons 8 "HE-HALO-XRED-X") (cons 0 "CIRCLE"))))
(setq HG(ssget "x" (list (cons 8 "HE-HALO-XGRN-X") (cons 0 "CIRCLE"))))
(setq HRC(sslength HR))
(setq HGC(sslength HG))
(Princ "Number of Red Halos=" HRC)
(Princ "Number of Green Halos=" HGC)
)


The problem [or at least one problem] is in the last two lines.  When you use (princ) with more than one argument, the second one [in this case your HRC and HGC] is for a file descriptor, but you haven't opened any files to write to, that those variables could represent.  And if you had, you're using those variable names for something else, anyway.

 

There are a couple of things you could do:

 

Print the two parts independently:

(princ "Number of Red Halos= ") (princ HRC)

 

String them together, in which case you must convert the number to a text string:

(prompt (strcat "\nNumber of Red Halos = " (itoa HRC)))

 

[The \n is a newline character.]

 

[That last could be done via (princ) or (print) or (prin1) instead of (prompt), but those (prinX) functions are designed for the option of sending whatever to a file, so when I don't need to do that, but am just reporting on something to the User, I always use (prompt) instead.  But it's worth considering that the double (princ) approach allows you to put the quantity out there without needing to convert it to a string.]

 

Try putting a

(princ)

with no arguments just above the final right parenthesis, so it won't put the messages out there and repeat the last message as what the last function returns [= "exit quietly"].

 

EDIT: Some further suggestions:

 

You can set more than one variable within one (setq) function.  And in (ssget) filter lists, if there's nothing to be evaluated [no variable names or calculations inside], but everything is known exactly, you can shortcut the format by using a "quoted" list instead of the (list) function explicitly [see Help for the (list) function].  So you could simplify it to this [untested]:

 

(defun C:Halocount ()
  (setq

    HR (ssget "x" '((8 . "HE-HALO-XRED-X") (0 . "CIRCLE")))
    HG (ssget "x" '((8 . "HE-HALO-XGRN-X") (0 . "CIRCLE")))
    HRC (sslength HR)
    HGC (sslength HG)

  ); end setq
  (princ "\nNumber of Red Halos=") (princ HRC)
  (princ "\nNumber of Green Halos=") (princ HGC)

  (princ)
)

 

In fact, you can shorten it even more, if you're saving variables that are used only once, and don't need to keep them for some further use in other functions, by just doing the calculation or selection-set creation at the point where you would use the variable, and skipping the variable as a middle-man.  You can nest functions inside each other to do that:

 

(defun C:Halocount ()

  (princ "\nNumber of Red Halos=")

  (princ (sslength (ssget "x" '((8 . "HE-HALO-XRED-X") (0 . "CIRCLE")))

  (princ "\nNumber of Green Halos=")

  (princ (sslength (ssget "x" '((8 . "HE-HALO-XGRN-X") (0 . "CIRCLE")))

  (princ)
)

Kent Cooper, AIA
Message 3 of 13
Dpipke
in reply to: Kent1Cooper

Thanks! That was a great and in depth reply. I appreciate you taking the time to explain the different ways to write the code. I will give your suggestions a shot. 

Message 4 of 13
hgasty1001
in reply to: Dpipke

Hi,

 

In addition to the Kent's post, you need to check if the selection set was created or not (is not nil), just add (if TheSelectionSet...)

 

Gaston Nunez

Message 5 of 13
scot-65
in reply to: Dpipke

Gasty is also helping. 🙂

When writing programs in any type of language, keep these things in mind:
1) Gather [User] input.
2) Test to see if input is valid.
3) Execute program when item 2 is true.

Items 1 and 2 can be combined to a certain extent, however
items 1 and 2 cannot be combined with item 3. In other words,
do not pause for user input while executing the program. It
could be disasterous.
For your posted situation, #1 is gather drawing information,
you have no #2, and you have four lines of #3.

Hope this helps.

Scot-65
A gift of extraordinary Common Sense does not require an Acronym Suffix to be added to my given name.


Message 6 of 13
pbejse
in reply to: hgasty1001


@hgasty1001 wrote:

Hi,

 

In addition to the Kent's post, you need to check if the selection set was created or not (is not nil), just add (if TheSelectionSet...)

 

Gaston Nunez


Its always a good habit to check for validity of variables . as some function will generate an error if supllied by an invalid or nil value like for example  sslength 

 

(defun C:Halocount ()
      (foreach itm '(("Red" "HE-HALO-XRED-X")( "Green" "HE-HALO-XGRN-X"))
            (princ (strcat "\nNumber of "(car itm) " Halos = "))
            (princ 
            	(if (setq ss (ssget "x" (list (cons 8 (Cadr itm))'(0 . "CIRCLE"))))
            		(sslength ss) 0)
                ))
  (princ)
)


That also goes for setting more than one variable within one (setq) function  Be mindful of the function you use .[but of course its just an example from kent] 

 

Cheers

 

Message 7 of 13
Kent1Cooper
in reply to: Kent1Cooper


@Kent1Cooper wrote:
....

  (princ "\nNumber of Red Halos=")

  (princ (sslength (ssget "x" '((8 . "HE-HALO-XRED-X") (0 . "CIRCLE")))

  (princ "\nNumber of Green Halos=")

  (princ (sslength (ssget "x" '((8 . "HE-HALO-XGRN-X") (0 . "CIRCLE")))

....


[Someone kindly pointed out to me in a private message that I had neglected to add the necessary two additional right parentheses at the ends of the two longer lines above, to finish up the (princ) and (sslength) functions -- ....(0 . "CIRCLE))))) ]

Kent Cooper, AIA
Message 8 of 13
alanjt_
in reply to: Kent1Cooper

A simple example and ALWAY localize your variables, unless you secifically want gloabl ones (def. not in this case).

 

(defun c:HaloCount (/ hr hg)
  (if (setq hr (ssget "_X" '((0 . "CIRCLE") (8 . "HE-HALO-XRED-X"))))
    (princ (strcat "\nNumber of red halos: " (itoa (sslength hr))))
  )
  (if (setq hg (ssget "_X" '((0 . "CIRCLE") (8 . "HE-HALO-XGRN-X"))))
    (princ (strcat "\nNumber of green halos: " (itoa (sslength hg))))
  )
  (princ)
)

 

Message 9 of 13
Dpipke
in reply to: Dpipke

Once again thanks for all the help. I ended up going with this for code:

(defun C:Halocount ()
(setq HR(ssget "x" (list (cons 8 "HE-HALO-XRED-X") (cons 0 "HATCH"))))
(setq HG(ssget "x" (list (cons 8 "HE-HALO-XGRN-X") (cons 0 "HATCH"))))
(setq HRC(sslength HR))
(setq HGC(sslength HG))
(princ "Number of Red Halos=") (princ HRC)
(princ "\nNumber of Green Halos=") (princ HGC)
(princ)
)


The check if the input is valid seems like a good idea. but I'm confused how to do that (sorry this is all brand new to me). so if say there were no red halos and I wanted it to display Red halos=0. would it be something like:

(defun C:Halocount ()
(setq HR(ssget "x" (list (cons 8 "HE-HALO-XRED-X") (cons 0 "CIRCLE"))))
(setq HG(ssget "x" (list (cons 8 "HE-HALO-XGRN-X") (cons 0 "CIRCLE"))))
(if (HR= nil F) (setq HRC(sslength HR)))

(if (HR= nil T) (HR=0))

(if (HG= nil F) (setq HGC(sslength HG)))

(if (HG= nil T) (HG=0))

(princ "Number of Red Halos=") (princ HRC)
(princ "\nNumber of Green Halos=") (princ HGC)
(princ)
)

I left the code in the longer form right now as it makes more sense to me. Then I figured I can experiment with shortening it.

Message 10 of 13
Kent1Cooper
in reply to: Dpipke


@Dpipke wrote:

... if say there were no red halos and I wanted it to display Red halos=0. would it be something like:

(defun C:Halocount ()
(setq HR(ssget "x" (list (cons 8 "HE-HALO-XRED-X") (cons 0 "CIRCLE"))))
(setq HG(ssget "x" (list (cons 8 "HE-HALO-XGRN-X") (cons 0 "CIRCLE"))))
(if (HR= nil F) (setq HRC(sslength HR)))

(if (HR= nil T) (HR=0))

(if (HG= nil F) (setq HGC(sslength HG)))

(if (HG= nil T) (HG=0))

(princ "Number of Red Halos=") (princ HRC)
(princ "\nNumber of Green Halos=") (princ HGC)
(princ)
)
....


A left parenthesis wants to be followed by a function name, which HR= is not.  It looks like you're checking HR and HG, and setting HRC and HGC to the length of them but to 0 if they returned nil -- here's one way to do that:

 

(setq HRC (if HR (sslength HR) 0))

(setq HGC (if HG (sslength HG) 0))

 

[Some are inclined to do something like (if (= HR nil) ...), but that's bulkier than necessary -- you can just check whether the variable exists at all, as above, because any non-nil return will satisfy the test.]

 

Read about the (if) function in the AutoLISP Reference to get a feeling for what the arguments are.

 

But even with checking whether there's a selection set to check the length of, you could still bypass the need for the HRC and HGC variables [unless you want them for other purposes later]:

 

(defun C:Halocount ()
  (setq

    HR (ssget "x" (list (cons 8 "HE-HALO-XRED-X") (cons 0 "CIRCLE")))
    HG (ssget "x" (list (cons 8 "HE-HALO-XGRN-X") (cons 0 "CIRCLE")))

  ); setq
  (princ "\nNumber of Red Halos=") (princ (if HR (sslength HR) 0))
  (princ "\nNumber of Green Halos=") (princ (if HG (sslength HG) 0))
  (princ)
)

Kent Cooper, AIA
Message 11 of 13
alanjt_
in reply to: Dpipke


@Dpipke wrote:

Once again thanks for all the help. I ended up going with this for code:

(defun C:Halocount ()
(setq HR(ssget "x" (list (cons 8 "HE-HALO-XRED-X") (cons 0 "HATCH"))))
(setq HG(ssget "x" (list (cons 8 "HE-HALO-XGRN-X") (cons 0 "HATCH"))))
(setq HRC(sslength HR))
(setq HGC(sslength HG))
(princ "Number of Red Halos=") (princ HRC)
(princ "\nNumber of Green Halos=") (princ HGC)
(princ)
)


The check if the input is valid seems like a good idea. but I'm confused how to do that (sorry this is all brand new to me). so if say there were no red halos and I wanted it to display Red halos=0. would it be something like:

(defun C:Halocount ()
(setq HR(ssget "x" (list (cons 8 "HE-HALO-XRED-X") (cons 0 "CIRCLE"))))
(setq HG(ssget "x" (list (cons 8 "HE-HALO-XGRN-X") (cons 0 "CIRCLE"))))
(if (HR= nil F) (setq HRC(sslength HR)))

(if (HR= nil T) (HR=0))

(if (HG= nil F) (setq HGC(sslength HG)))

(if (HG= nil T) (HG=0))

(princ "Number of Red Halos=") (princ HRC)
(princ "\nNumber of Green Halos=") (princ HGC)
(princ)
)

I left the code in the longer form right now as it makes more sense to me. Then I figured I can experiment with shortening it.


If you look at the example I've provided above, it gives a simple way of checking if each selection is valid and *only* returning a value if so.

Never assume a variable will be valid and always localize your variables.

Message 12 of 13
Dpipke
in reply to: alanjt_

Ah I see it now. I somehow missed your post

Ok So I ran into another issue. Is there a way to isolate the SSget to model space? It seems to be counting the halos in paper space as well

Message 13 of 13
alanjt_
in reply to: Dpipke


@Dpipke wrote:

Ah I see it now. I somehow missed your post

Ok So I ran into another issue. Is there a way to isolate the SSget to model space? It seems to be counting the halos in paper space as well


Add (410 . "Model") to the ssget filter.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost