Ament Posted July 31, 2018 Share Posted July 31, 2018 Hello together, I'm writing a small lisp and get the following problem: If I put the name of my selection set directly to my sslength its working fine, but I'm in a loop, so I would like to put a changing variable but it doesn't accept it. Please see AutoCAD response below. Command: (sslength SELC2) 41 Command: (sslength (read(strcat "SEL" ENT))) ; Error: Bad argument type: lselsetp SELC2 Command: !ENT "C2" From my limited understanding both expressions should give the same result what clearly is not the case. What do I have to change to make it happen? Thanks for your help! Quote Link to comment Share on other sites More sharing options...
Emmanuel Delay Posted July 31, 2018 Share Posted July 31, 2018 (edited) sslength expects an ssget object. (read does not provide this. I see what you are trying to do: make a string that spells SELC2 expecting it to refer to the variable SELC2. (notice: you can do this in php, they call it "variable variable". $myvar = "Hello World!"; $a = "myvar"; print $$a; => will print "Hello World!") I don't know how to do this in lisp. I would like to know this myself, if anybody has an answer. Can you tell us more about that loop? What are you making? Maybe other solutions exist Edited July 31, 2018 by Emmanuel Delay Quote Link to comment Share on other sites More sharing options...
Ament Posted July 31, 2018 Author Share Posted July 31, 2018 Well, it's a bit hard to explain. I'm trying to count the number of occurences of blocks in my drawing and store the result to an individual variable. This variable is later used to put it into a table. ut unfortunately I'm struggeling at the very first steps to count the occurences in a foreach loop. Below you'll find the code: (defun C:TEST () (setq CCLIST (list "C2" "CC" "CS1" "OFF" "PS1" "PS2" "SO")) (foreach ENT CCLIST (set (read(strcat "SEL" ENT)) (ssget "_X" (list (cons 0 "INSERT") (cons 2 (strcat "*_" ENT "_*"))))) (set (read(strcat "NO" ENT)) (sslength (read(strcat "SEL" ENT)))) ) ) If it was working as i expect I would be able to type !NOC2 or !NOOFF into my command bar in AutoCAD and get the amount of blocks in my drawing which have the strings _C2_ and _OFF_ inside their name. This variables will be used later in the code to be written Quote Link to comment Share on other sites More sharing options...
Ament Posted July 31, 2018 Author Share Posted July 31, 2018 I guess my issue might be that there are some values in the list where no corresponding block can be found so that the ssget is nil. That makes the sslength run into an issue. I'll keep testing. Quote Link to comment Share on other sites More sharing options...
ronjonp Posted July 31, 2018 Share Posted July 31, 2018 (edited) Why don't you store these values in a list? The approach you're taking is very atypical. (defun c:test (/ r s) (foreach str '("C2" "CC" "CS1" "OFF" "PS1" "PS2" "SO") (setq r (cons (cons str (if (setq s (ssget "_X" (list '(0 . "INSERT") (cons 2 (strcat "*_" str "_*"))))) (sslength s) 0 ) ) r ) ) ) (if r (print (reverse r)) (print "No data...") ) (princ) ) ;; Returns ;; (("C2" . 0) ("CC" . 0) ("CS1" . 0) ("OFF" . 0) ("PS1" . 0) ("PS2" . 0) ("SO" . 0)) Edited July 31, 2018 by ronjonp Quote Link to comment Share on other sites More sharing options...
Ament Posted August 1, 2018 Author Share Posted August 1, 2018 I'll store the names of the variables NOxx in a list in case it was created. As I said, it's just the beginning of a longer macro I solved my issue using the following code. (defun C:CABIN () (setq CCLIST (list "C2" "CC" "CS1" "OFF" "PS1" "PS2" "SO")) (foreach ENT CCLIST (if (setq SSENT (ssget "_X" (list (cons 0 "INSERT") (cons 2 (strcat "*_" ENT "_*"))))) (progn (set (read(strcat "NO" ENT)) (sslength SSENT)) );progn );if );foreach );defun Now I'll put other stuff into the progn container to go ahead Thank you for your suggestions. Quote Link to comment Share on other sites More sharing options...
BIGAL Posted August 1, 2018 Share Posted August 1, 2018 (edited) You would be better of using ronjonp list method than setting a variable you just use the addrow method to a table as you read the list a simple double nth to put all the details into a table. If you need help with the table bit post. A side note working on project any blocks any number of attributes dynamic table width does count and supports up to 2 deep attribute totalling Door silver handle5 =10 v's Door silver handle6 =8 Can you post a sample dwg I need some real dwgs to work on. Can change my ssget to yours. here is a start for you (defun addsels ( ss1 / x) (repeat (setq x (sslength ss1)) (setq ss (ssadd (ssname ss1 (setq x (- x 1) ))ss)) ) ) ; to be ; 4 choices a hard code list ; a select from all blocks dcl ; select from file ; pick block-s (setq CCLIST (list "C2" "CC" "CS1" "OFF" "PS1" "PS2" "SO" "aaa" "BBB")) ; aaa BBB for testing (setq ss (ssadd)) (foreach ENT CCLIST (if (=(setq SSENT (ssget "_X" (list (cons 0 "INSERT") (cons 2 (strcat "*_" ENT "_*")))))nil) (alert (strcat "missing " ent)) (addsels ssent ) ) ) ;;;;;; starts here (setq lst '()) ;(setq ss (ssget '((0 . "insert")))) (repeat (setq x (sslength ss)) (setq lst2 '()) (setq obj (vlax-ename->vla-object (ssname ss (setq x (- x 1))))) (if (and (vlax-property-available-p obj "hasattributes") (setq atts (vlax-invoke obj "getattributes")) ) (progn (setq lst2 (cons (vla-get-EffectiveName obj) lst2)) (foreach att atts (setq lst2 (cons (vla-get-textstring att) lst2)) ) (setq lst (cons (reverse lst2) lst)) ) ) ) Edited August 1, 2018 by BIGAL Quote Link to comment Share on other sites More sharing options...
Lee Mac Posted August 1, 2018 Share Posted August 1, 2018 Hello together, I'm writing a small lisp and get the following problem: If I put the name of my selection set directly to my sslength its working fine, but I'm in a loop, so I would like to put a changing variable but it doesn't accept it. Please see AutoCAD response below. Command: (sslength SELC2) 41 Command: (sslength (read(strcat "SEL" ENT))) ; Error: Bad argument type: lselsetp SELC2 Command: !ENT "C2" From my limited understanding both expressions should give the same result what clearly is not the case. What do I have to change to make it happen? (sslength (eval (read (strcat "SEL" ENT)))) Quote Link to comment Share on other sites More sharing options...
Emmanuel Delay Posted August 1, 2018 Share Posted August 1, 2018 Ah, cool. LISP has eval too Just know that some people are not the biggest fans I even found a lisp (not Autocad) T-shirt of it Quote Link to comment Share on other sites More sharing options...
ronjonp Posted August 1, 2018 Share Posted August 1, 2018 I'll store the names of the variables NOxx in a list in case it was created. As I said, it's just the beginning of a longer macro I solved my issue using the following code. (defun C:CABIN () (setq CCLIST (list "C2" "CC" "CS1" "OFF" "PS1" "PS2" "SO")) (foreach ENT CCLIST (if (setq SSENT (ssget "_X" (list (cons 0 "INSERT") (cons 2 (strcat "*_" ENT "_*"))))) (progn (set (read(strcat "NO" ENT)) (sslength SSENT)) );progn );if );foreach );defun Now I'll put other stuff into the progn container to go ahead Thank you for your suggestions. Are you familiar with ASSOC? ;; Simple helper function (defun _get (key l)(cdr (assoc key l))) (setq l '(("C2" . 0) ("CC" . 0) ("CS1" . 0) ("OFF" . 88) ("PS1" . 0) ("PS2" . 0) ("SO" . 0))) (_get "OFF" l) ;; Returns 88 Quote Link to comment Share on other sites More sharing options...
Lee Mac Posted August 1, 2018 Share Posted August 1, 2018 Are you familiar with ASSOC? ;; Simple helper function (defun _get (key l)(cdr (assoc key l))) (setq l '(("C2" . 0) ("CC" . 0) ("CS1" . 0) ("OFF" . 88) ("PS1" . 0) ("PS2" . 0) ("SO" . 0))) (_get "OFF" l) ;; Returns 88 I couldn't agree more - it's curious the number of developers starting out in AutoLISP who opt for using individual variables over lists. (defun CabinList ( l ) (mapcar '(lambda ( x / s ) (if (setq s (ssget "_X" (list '(0 . "INSERT") (cons 2 (strcat "*_" x "_*"))))) (cons x (sslength s)) (cons x 0) ) ) l ) ) (defun c:cabin ( / lst qry ) (setq lst (CabinList '("C2" "CC" "CS1" "OFF" "PS1" "PS2" "SO")) qry (strcase (getstring "\nEnter a code to find the quantity <all>: ")) ) (if (= "" qry) (foreach itm lst (princ (strcat "\n" (car itm) ": " (itoa (cdr itm))))) (princ (strcat "\n" qry ": " (itoa (cond ((cdr (assoc qry lst))) (0))))) ) (princ) ) Quote Link to comment Share on other sites More sharing options...
BIGAL Posted August 2, 2018 Share Posted August 2, 2018 Like you lee I have added a lot to my block extraction lisp being developed and use a list and double sorts on the list to work out the block counts 2 attributes deep. this post inspired me to add just this option to it a predefined group of block names including wildcard support. Ament run the code I posted and you will see a list of all the blocks. Quote Link to comment Share on other sites More sharing options...
woolenthreads Posted August 7, 2018 Share Posted August 7, 2018 I couldn't agree more - it's curious the number of developers starting out in AutoLISP who opt for using individual variables over lists. I expect that it's because most of us start as Draft-persons with a familiarity with basic (or should I say "BASIC") programming and no exposure to list manipulation. If you were to take a poll you'd probably find most of us have a tendency to only do programming very occasionally and possibly only after searched diligently for someone else's solution first . Quote Link to comment Share on other sites More sharing options...
ronjonp Posted August 7, 2018 Share Posted August 7, 2018 I expect that it's because most of us start as Draft-persons with a familiarity with basic (or should I say "BASIC") programming and no exposure to list manipulation. If you were to take a poll you'd probably find most of us have a tendency to only do programming very occasionally and possibly only after searched diligently for someone else's solution first . LISt Processing is what you need to learn to do IMO this snippet below is much simpler than what the OP is doing ... but without seeing the end result it's hard to tell. Maybe these globals are used as a lisp variable field? %% ;; Simple helper function (defun _get (key l)(cdr (assoc key l))) (setq l '(("C2" . 0) ("CC" . 0) ("CS1" . 0) ("OFF" . 88) ("PS1" . 0) ("PS2" . 0) ("SO" . 0))) (_get "OFF" l) ;; Returns 88 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.