Script with IF statements stopping once it gets a positive result

Script with IF statements stopping once it gets a positive result

Mark.HarrisBGNSX
Participant Participant
1,246 Views
15 Replies
Message 1 of 16

Script with IF statements stopping once it gets a positive result

Mark.HarrisBGNSX
Participant
Participant

Hi all,

 

hopefully someone can help me - I am trying to script automate the turning on of layers I am interested in in multiple drawings, but the layers don't always exist, so traditional -layer commands would stall when the script comes across a layer it doesn't see.

 

to prevent this, i am using IF statements as below, but the issue is i have the opposite problem now...the script is a long list of layers as below, the script breezes through layers it doesn't know but stops once it gets to a recognised layer in the drawing.  It DOES turn the later on but then it just stops, printing 'nil' next to 'Command:' in the command line

 

does anyone know how to stop it tripping up please?

 

(command (if (tblsearch "layer" "EO-Pr6070-M-LightingFeederPillar") (command "-LAYER" "_on" "EO-Pr6070-M-LightingFeederPillar" "" "_y")))

(command (if (tblsearch "layer" "EO-Pr6070-M-LightingFeederPillar2DView") (command "-LAYER" "_on" "EO-Pr6070-M-LightingFeederPillar2DView" "" "_y")))

(command (if (tblsearch "layer" "EO-Pr6070-M-LightingFeederPillar3DView") (command "-LAYER" "_on" "EO-Pr6070-M-LightingFeederPillar3DView" "" "_y")))

 

Thansk,

 

Mark

0 Likes
1,247 Views
15 Replies
Replies (15)
Message 2 of 16

pbejse
Mentor
Mentor

Consider using a list and the function foreach, might as well check the status of the layer if its off, then turned it on

 

(foreach layername '("EO-Pr6070-M-LightingFeederPillar"
		     "EO-Pr6070-M-LightingFeederPillar2DView"
		     "EO-Pr6070-M-LightingFeederPillar3DView"
		    )
  (if (and
	(setq status (tblsearch "layer" layername))
	(minusp (Cdr (assoc 62 status))))
    (command "-LAYER" "_on" layername "" "_y")
  )
)

 

 

HTH

 

0 Likes
Message 3 of 16

john.kaulB9QW2
Advocate
Advocate

If you find yourself retyping the same code over again, you should make it a function instead. I use an older function written by a friend typically for these actions.

 

(defun layerActions (actions layerName / layer laylst flags color plot)
  ;; LayerActions
  ;;
  ;; 0 = no action
  ;; 1 = freeze
  ;; 2 = thaw
  ;; 4 = off
  ;; 8 = on
  ;; 16 = lock
  ;; 32 = unlock
  ;; 64 = plot on
  ;; 128 = plot off
  ;;
  ;; By: SMadsen on 06-27-2003
  ;; 
  ;; 
  ;; Ex: (layerActions (+ 4 16 32) "myLayer") 
  ;;     Simply adding the values determines the actions taken by 
  ;;     the function. will turn on "myLayer", unlock it and 
  ;;     enable plotting (I hope).
  ;;
  ;; Global variables can also help.
  ;; (setq  *Freeze*  2
  ;;        *Thaw*    1
  ;;        *Off*     8
  ;;        *On*      4
  ;;        *Lock*    32
  ;;        *Unlock*  16
  ;;        *PlotOn*  64
  ;;        *PlotOff* 128)
  ;;
  ;; Now we can use those global variables to help our code readability.
  ;;
  ;; (layerActions (+ *On* *Unlock* *PlotOn*) "mylayer")
  ;;
  (cond ((setq layer (tblobjname "LAYER" layerName))
         (setq laylst (entget layer)
               flags  (cdr (assoc 70 laylst))
               color  (cdr (assoc 62 laylst))
               plot   (cdr (assoc 290 laylst)))
         (cond ((= (logand actions 2) 2) (setq flags (logior flags 1)))
               ((= (logand actions 1) 1) (setq flags (- flags (logand flags 1)))))
         (cond ((= (logand actions 😎 😎 (setq color (- (abs color))))
               ((= (logand actions 4) 4) (setq color (abs color))))
         (cond ((= (logand actions 32) 32) (setq flags (logior flags 4)))
               ((= (logand actions 16) 16)(setq flags (- flags (logand flags 4)))))
         (cond ((= (logand actions 64) 64) (setq plot 1))
               ((= (logand actions 128) 128) (setq plot 0)))
         (setq laylst (subst (cons 70 flags)(assoc 70 laylst) laylst)
               laylst (subst (cons 62 color)(assoc 62 laylst) laylst)
               laylst (subst (cons 290 plot)(assoc 290 laylst) laylst))
         (entmod laylst)
         )
        )
  (princ)
 )

 

another swamper
0 Likes
Message 4 of 16

Kent1Cooper
Consultant
Consultant

@Mark.HarrisBGNSX wrote:

.... the layers don't always exist, so traditional -layer commands would stall when the script comes across a layer it doesn't see. ....


No it won't.  A message will go by that it didn't find the Layer(s), but it will just return to the regular prompt, just as if the Layer(s) did exist.  And your "_y" entries don't fit the prompts that will be issued -- they'll be taken as a new command, and you'll get an unknown-command message, which probably explains your "stops once it gets to" issue.  [Did that get dragged in from copying a Layer command turning off all Layers, in which you would be asked whether you really want the current Layer off?]

 

Another problem is your nesting of (command) functions inside other (command) functions.

 

As for the 'nil' at the conclusion, the (command) function always returns nil [read about it in the AutoLisp Reference] -- that doesn't mean it didn't work.

 

This will do what you want, whether or not any of the Layers exist:

 

(command "_.LAYER" "_on" "EO-Pr6070-M-LightingFeederPillar,EO-Pr6070-M-LightingFeederPillar2DView,EO-Pr6070-M-LightingFeederPillar3DView" "")

(prin1) ;; this [or (princ) or (print), any with no arguments] will suppress the 'nil' return [read about that, too].

 

EDIT:

If those are all your Layers that start that way, you can shortcut the multiple names with a wildcard standing in for any following string content:

(command "_.LAYER" "_on" "EO-Pr6070-M-LightingFeederPillar*" "")

 

[By the way, that's not a Script -- that word has a specific and different (though related) meaning in AutoCAD.]

Kent Cooper, AIA
0 Likes
Message 5 of 16

Mark.HarrisBGNSX
Participant
Participant

brilliant, thanks this worked!

0 Likes
Message 6 of 16

Kent1Cooper
Consultant
Consultant

@pbejse wrote:

.... might as well check the status of the layer if its off, then turned it on ....


That's utterly unnecessary.  Just turn them all on, and it won't matter whether any of them are already on, nor will it matter whether they even exist in the drawing.  See Message 4.

Kent Cooper, AIA
0 Likes
Message 7 of 16

john.kaulB9QW2
Advocate
Advocate

Too much repetition for my taste. Layer operations like this (in a lisp) are meant for standard type operations -i.e. making sure the correct layers are on/off for plotting etc. and in doing so, I prefer to check all instances of the states (on, off, frozen, plot, etc.). So even with the use of a wildcard you'd still repeat yourself a few times. Possibly like:

(command "_.LAYER" "_on" "EO-Pr6070-M-LightingFeederPillar*" "")
(command "_.LAYER" "_thaw" "EO-Pr6070-M-LightingFeederPillar*" "")
(command "_.LAYER" "_unlock" "EO-Pr6070-M-LightingFeederPillar*" "")
...

 

Now, wildcards are a nice typing saver--for the programmer--but horrible come debugging time. The situation that comes to mind is xrefs; If wildcards are used too liberal you end up with a mess.

-e.g. "*EO-Pr6070-M-LightingFeederPillar*"

 

I recommend using something a bit more precise.

 

-e.g.

;...
;; - These layers need to be displayed on all production drawings.
(setq lyrs '("EO-Pr6070-M-LightingFeederPillar"
             "EO-Pr6070-M-LightingFeederPillar2DView"
             "EO-Pr6070-M-LightingFeederPillar3DView"))

;; - Iterate the layers and make sure proper settings are in place.
(mapcar
  (function
    (lambda (lyrname)
      (layerActions (+ *On* *Thaw* *Unlock* *PlotOn*) lyrname)))
  lyrs
  )
;...

 

This is clear, concise and professional (nothing vague which can bite you later) and can easily be changed/added as needs change.

another swamper
0 Likes
Message 8 of 16

Kent1Cooper
Consultant
Consultant

@john.kaulB9QW2 wrote:

....

(command "_.LAYER" "_on" "EO-Pr6070-M-LightingFeederPillar*" "")
(command "_.LAYER" "_thaw" "EO-Pr6070-M-LightingFeederPillar*" "")
(command "_.LAYER" "_unlock" "EO-Pr6070-M-LightingFeederPillar*" "")
...

....


Are you [and others] aware that you can combine as many Layer options as you want into one Layer command?

 

(command "_.LAYER"
  "_on" "EO-Pr6070-M-LightingFeederPillar*"
  "_thaw" "EO-Pr6070-M-LightingFeederPillar*"
  "_unlock" "EO-Pr6070-M-LightingFeederPillar*"
  ""
)

or even:

(setq lname "EO-Pr6070-M-LightingFeederPillar*")
(command "_.LAYER" "_thaw" lname "_on" lname "_unlock" lname "")

 

Kent Cooper, AIA
0 Likes
Message 9 of 16

john.kaulB9QW2
Advocate
Advocate

Of course--I can't speak for others, obviously-- but no matter if the operation is one line or four, it's still messy and error prone (because of the wildcards).  Just list the layers you need/want and do an entmod (you're done).

 

another swamper
0 Likes
Message 10 of 16

Kent1Cooper
Consultant
Consultant

@john.kaulB9QW2 wrote:

....

....
;; - Iterate the layers and make sure proper settings are in place.
(mapcar
  (function
    (lambda (lyrname)
      (layerActions (+ *On* *Thaw* *Unlock* *PlotOn*) lyrname)))
  lyrs
  )
;...

This is clear....


... only if you also have the additional code required to define the (layeractions) function.

Kent Cooper, AIA
0 Likes
Message 11 of 16

john.kaulB9QW2
Advocate
Advocate
0 Likes
Message 12 of 16

Kent1Cooper
Consultant
Consultant

@john.kaulB9QW2 wrote:
I gave it to you here: ....

So you did.  So ignoring comment lines, you're up to over 30 lines of code to do what can be done in two or so, which to me seems a strange definition of "concise."

 

And I disagree about the error-proneness of using wildcards.  They simply need to be used correctly, just as AutoLisp functions, answers to command prompts, etc. need to be used correctly -- those are just as error-prone if not done right.

Kent Cooper, AIA
0 Likes
Message 13 of 16

john.kaulB9QW2
Advocate
Advocate
Oh you're just being obstinate (and if that function was trimmed to only support the operations needed...blah, blah).

I'm sorry but I learned from experience; somehow *I* got roped into doing this very task for a large civil and A and E project with thousands of drawings and I had a lisp with about a hundred or so lines just like your first example in #8. I had to use so many wildcards hoop-jumping and whatnot it became so cumbersome to maintain for the two plus years I had to (I hated it!).

The separate function/list method is scalable. If you or the OP wants to use the "command" method, go ahead. I wouldn't but you can (I honestly don't care). I don't do monolithic programming (I try to keep my functions and code in small chunks).

Wildcards are error prone, just look at the code the OP posted ("one small typing error", "xrefs", etc.).

My posts can be just for the future user that needs something a little more.
another swamper
0 Likes
Message 14 of 16

pbejse
Mentor
Mentor

What i posted is more about the OP question, “stopping once … “ 

 

I included the “check status” thingy as a suggestion to what can be done in case the code requires additional evaluation.

 

Looking at post #5, we can say that it did help, we leave it to @Mark.HarrisBGNSX  to decide what you describe as  “utterly unnecessary”

 

just be happy for the OP will you.

 

0 Likes
Message 15 of 16

pbejse
Mentor
Mentor

You are welcome @Mark.HarrisBGNSX and hope you will learn from it.

 

cheers

0 Likes
Message 16 of 16

john.kaulB9QW2
Advocate
Advocate

pbejse brings up a fun concept. Let's pretend you want to "toggle" the layers on/off property without caring what state the layer visibility is currently in. Instead of adding code to 'check' one way or the other, you can use the 2's compliment to just flip the value (without 'checking'). Obviously, this isn't as useful as demanding the layers visibility state be in one condition for standards reasons, but it demonstrates a fun programming tool called the "2s compliment" (you can do a few fun things with 2s complements like basic math and strcase type operations). But back to the subject at hand.

 

We start by defining a helper function.

(defun ToggleLayerVisibility (layername / 2s layer)
        ;; -Define a 2's compliment helper function.
  (set '2s (lambda (n) (1+ (~ n))))

        ;; -Use a switch to evaluate only if layer exists.
  (cond
        ;; -Check to see if layername exists.
    ((setq layer (tblobjname "LAYER" layername))
        ;; -Get layer properties
     (setq layer (entget layer))
        ;; - Modify layer visibilty properties.
     (entmod
       (subst
         (cons 62 (2s (cdr (assoc 62 layer))))
         (assoc 62 layer)
         layer
       )
     )
    )
  )
)

 

Now in our code we just create a list of layers and pass them to our helper function.

;...
;; - These layers need to be displayed on all production drawings.
(setq lyrs '("EO-Pr6070-M-LightingFeederPillar"
             "EO-Pr6070-M-LightingFeederPillar2DView"
             "EO-Pr6070-M-LightingFeederPillar3DView"))

;; - Iterate the layers and make sure proper settings are in place.
(mapcar 'ToggleLayerVisibility lyrs)
;...

 

 

another swamper
0 Likes