Step through layers - if *match, then..

Step through layers - if *match, then..

Anonymous
Not applicable
1,328 Views
11 Replies
Message 1 of 12

Step through layers - if *match, then..

Anonymous
Not applicable

Hello. I'm trying to write a bit of code that steps through my layers, and if there's a match of "*EXIST", it runs the function I've written up. Else, moves on to the next.

(defun c:MICKY (/ layOld layNew ss)

(setq layOld (getvar "clayer"))
(setq layNew (strcat layOld "-OFF"))

;STEP THROUGH LAYERS
;> IF MATCH "*EXIST" THEN...

(setq ss (ssget "x" (list (cons 8 (getvar "CLAYER")))))
(command "-COPYTOLAYER" ss "" layNew "y" "0,0,0" "")

;>ELSE NEXT LAYER

)

I feel like it's a pretty simple concept, can't seem to figure it out though.  

Appreciate any help!!

0 Likes
Accepted solutions (1)
1,329 Views
11 Replies
Replies (11)
Message 2 of 12

Moshe-A
Mentor
Mentor

@Anonymous  hi,

 

check this version.

 

i'm not sure that this is what you want about the destination layer so check my command and decide what it should be and we will fix it 😀

 

enjoy

moshe

 

 

 

(defun c:micky (/ layOld layNew tbl layName c70 ss)
 (setvar "cmdecho" 0)
 (command "._undo" "_begin")

 (setq layOld (strcase (getvar "clayer")))
 (setq layNew (strcat layOld "-OFF"))

 ; create layNew if it's not exist 
 (if (null (tblsearch "layer" layNew))
  (command ".layer" "_new" layNew "")
 )
  
 (while (setq tbl (tblnext "layer" (not tbl))) ; step through layers
  (setq layName (strcase (cdr (assoc '2 tbl))))
  (setq c70 (cdr (assoc '70 tbl))) 
   
  (if (and
        (not (= (logand c70 16) 16)) 		; skip xref layer
        (not (= (logand c70 1) 1))   		; skip freeze layer
        (not (= (logand c70 4) 4))   		; skip locked layer
       	(wcmatch layName "*EXIST")		; only layers contains *EXIST
        (not (minusp (cdr (assoc '62 tbl))))    ; skip off layer
      )
   ; do your copytolayer
   (if (setq ss (ssget "_X" (list (cons '8 layName))))
    (command "._copytolayer" "_si" ss layNew "0,0,0" "0,0,0")				   
   ); if
  ); if 
 ); while

 (command "._undo" "_end")
 (setvar "cmdecho" 1)    
     
 (princ)
); c:micky
0 Likes
Message 3 of 12

dbhunia
Advisor
Advisor

Also Try this.......

 

(defun c:micky (/ layOld layNew All_Lay lay layName ss)
	(setq adoc (vla-get-activedocument (vlax-get-acad-object)))
	(setvar 'cmdecho 0)(vla-StartUndoMark adoc)
	(setq layOld (strcase (getvar "clayer")))
	(setq layNew (strcat layOld "-OFF"))
	(setq All_Lay (vla-get-Layers adoc))
	(while (setq lay (tblnext "layer" (not lay))) 					   ; step through layers
		(if (and (not (wcmatch (setq layName (strcase (cdr (assoc 2 lay)))) "*|*")); skip xref layer
			      (= (vla-get-Lock (vla-item All_Lay layName)) :vlax-false)	   ; skip locked layer
			      (wcmatch layName "*EXIST")				   ; only layers contains *EXIST
			)
			(if (setq ss (ssget "_X" (list (cons 8 layName))))
				(progn
					(if (null (tblsearch "layer" layNew))(command ".layer" "_new" layNew "")); create layNew if it's not exist
					(command "_.copytolayer" ss "" layNew "")				 ; copytolayer layNew at same location
					;(command "_.copytolayer" ss "" layNew "" Base_Point Des_Point )	 ; copytolayer layNew at other location use this
				)
			)
		)
	)
	(vla-EndUndoMark adoc)(setvar 'cmdecho 1)
	(princ)
)

 

Or.......

 

(defun c:micky (/ layOld layNew All_Lay lay layName ss)
	(setq adoc (vla-get-activedocument (vlax-get-acad-object)))
	(setvar 'cmdecho 0)(vla-StartUndoMark adoc)
	(setq layOld (strcase (getvar "clayer")))
	(setq layNew (strcat layOld "-OFF"))
	(setq All_Lay (vla-get-Layers adoc))
	(while (setq lay (tblnext "layer" (not lay))) 					   ; step through layers
		(if (and (not (wcmatch (setq layName (strcase (cdr (assoc 2 lay)))) "*|*")); skip xref layer
			      (= (vla-get-Lock (vla-item All_Lay layName)) :vlax-false)	   ; skip locked layer
			      (= (vla-get-freeze (vla-item All_Lay layName)) :vlax-false)  ; skip freeze layer
			      (= (vla-get-Layeron (vla-item All_Lay layName)) :vlax-true)  ; get on layer
			      (wcmatch layName "*EXIST")				   ; only layers contains *EXIST
			)
			(if (setq ss (ssget "_X" (list (cons 8 layName))))
				(progn
					(if (null (tblsearch "layer" layNew))(command ".layer" "_new" layNew "")); create layNew if it's not exist
					(command "_.copytolayer" ss "" layNew "")				 ; copytolayer layNew at same location
					;(command "_.copytolayer" ss "" layNew "" Base_Point Des_Point )	 ; copytolayer layNew at other location  use this
				)
			)
		)
	)
	(vla-EndUndoMark adoc)(setvar 'cmdecho 1)
	(princ)
)

Debashis Bhunia
Co-Founder of Geometrifying Trigonometry(C)
________________________________________________
Walking is the First step of Running, Technique comes Next....
Message 4 of 12

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

... if there's a match of "*EXIST", it runs the function I've written up. ....

....
(setq layOld (getvar "clayer")) (setq layNew (strcat layOld "-OFF")) .... (command "-COPYTOLAYER" ss "" layNew "y" "0,0,0" "") ....

 

I wonder whether you really want the layNew variable like that.  If the current Layer when you run the routine happens to be 0, then everything on any Layer whose name contains "EXIST" will be copied onto a Layer called "0-OFF" regardless of what Layer its source object was on.  Is that the intent?  Wouldn't you want things copied to Layers that are named the same as the Layers the objects are on, with the "-OFF" suffix added?  If something's on a Layer called "WALLEXIST1", don't you want it copied onto a Layer called "WALLEXIST1-OFF", rather than to a Layer called "0-OFF", or "Defpoints-OFF", or some other name based on whatever the current Layer happens to be?

 

If that's the case, here's a different [and look how short!] approach.  Don't do it by Layers, but by objects, using (ssget) to find all things on any  Layer containing "EXIST" in its name, all at once.  Then rather than use COPYTOLAYER, (entmake) a copy of each with a suffixed Layer name.

 

You don't have to exclude Xref Layers, because (ssget) won't see things on those Layers.  And you don't have to check whether a newly-suffixed Layer name exists, because this kind of (entmake (subst....)) approach will create the Layer in the process.  And you would need to decide what you want to do about locked Layers -- this doesn't  prevent making copies of things on locked Layers, because it doesn't affect those things themselves  at all.  Mildly tested:

 

(defun C:TEST (/ ss n edata)
  (if (setq ss (ssget "_X" '((8 . "*EXIST*"))))
    (repeat (setq n (sslength ss))
      (setq edata (entget (ssname ss (setq n (1- n)))))
      (entmake (subst (cons 8 (strcat (cdr (assoc 8 edata)) "-OFF")) (assoc 8 edata) edata))
    ); repeat
  ); if
  (princ)
); defun

But if you really do  want the new suffixed Layer name to be based on whatever the current Layer is, and things from all  those other Layers copied onto the one  common suffixed Layer, just replace

  (cdr (assoc 8 edata))

in the above with

  (getvar 'clayer) 

Kent Cooper, AIA
Message 5 of 12

pbejse
Mentor
Mentor

@Kent1Cooper wrote:

.. Don't do it by Layers, but by objects, using (ssget) to find all things on any  Layer containing "EXIST" in its name, all at once.  

 


 

I concur, that's how i would approach too.

thumbsup.gif

 

 

0 Likes
Message 6 of 12

Anonymous
Not applicable

Yes! You are exactly right, sorry I guess I didn't clarify that well enough. 

And that works perfectly, I guess in my head it just made sense to work down the list layers and copy them as you go. 

Thank you, thank you, thank you. 

0 Likes
Message 7 of 12

Anonymous
Not applicable

One thing I noticed however is the layer properties aren't being copied over 😕

Is this a filter problem? 

 

Also can someone please point me in the direction for a complete list of all the ssget filters?

0 Likes
Message 8 of 12

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

One thing I noticed however is the layer properties aren't being copied over 😕

Is this a filter problem? 

 

Also can someone please point me in the direction for a complete list of all the ssget filters?


Read the >Help entry for (ssget)<.

 

It's not a filter problem.  It's from the fact that in the case of creating a Layer as a result of putting something on it in that way when the Layer doesn't already exist, that new Layer gets all the default properties, such as Continuous linetype and color 7.  I didn't try to do anything else about that because your original didn't assign any such properties, either.

 

That would take some stepping through Layers, looking for those whose names end with "-OFF", digging out the properties of the same Layer name without  the suffix, and assigning those to the one with  it.  I could probably work that out, but not tonight....

Kent Cooper, AIA
0 Likes
Message 9 of 12

dbhunia
Advisor
Advisor

Means you just want to copy all the objects of the particular layer as it is with new layer name .......

 

Then check this.......

 

(defun C:micky (/ ss n Edata Old_Lay_Name Old_Lay_Edata New_Lay_Name New_Lay_Edata)
  (if (setq ss (ssget "_X" '((8 . "*EXIST*"))))
    (repeat (setq n (sslength ss))
		(setq Edata (entget (ssname ss (setq n (1- n)))))
		(setq Old_Lay_Name (cdr (assoc 8 Edata)))
		(setq Old_Lay_Edata (entget (tblobjname "layer" Old_Lay_Name)))
		(setq New_Lay_Name (strcat Old_Lay_Name "-OFF"))
		(entmake (subst (cons 8 New_Lay_Name) (assoc 8 Edata) Edata))
		(setq New_Lay_Edata (entget (tblobjname "layer" New_Lay_Name)))
		(entmod (append (vl-remove-if '(lambda (x) (member (car x) '(70 62 6 290 370 390 347))) New_Lay_Edata)
				(vl-remove-if-not '(lambda (x) (member (car x) '(70 62 6 290 370 390 347)))Old_Lay_Edata)
			)
		)
		(entupd (cdr (assoc -1 New_Lay_Edata)))
    )
  )
  (princ)
)

Debashis Bhunia
Co-Founder of Geometrifying Trigonometry(C)
________________________________________________
Walking is the First step of Running, Technique comes Next....
0 Likes
Message 10 of 12

Kent1Cooper
Consultant
Consultant
Accepted solution

@Anonymous wrote:

One thing I noticed however is the layer properties aren't being copied over....


 

A simpler way to do that is the same way the copies of the objects are made -- take the entity data for the Layer "object" from the table, and (entmake) another the same except for (subst)ituting a suffixed name.  All the other properties are carried over into the new Layer.

(defun C:TEST2 (/ ss n edata ldata oldlay)
  (if (setq ss (ssget "_X" '((8 . "*EXIST*"))))
    (repeat (setq n (sslength ss))
      (setq
        edata (entget (ssname ss (setq n (1- n))))
        ldata (entget (tblobjname "layer" (setq oldlay (cdr (assoc 8 edata)))))
      )
      (entmake (subst (cons 2 (strcat oldlay "-OFF")) (assoc 2 ldata) ldata))
      (entmake (subst (cons 8 (strcat oldlay "-OFF")) (assoc 8 edata) edata))
    ); repeat
  ); if
  (princ)
); defun
Kent Cooper, AIA
Message 11 of 12

john.uhden
Mentor
Mentor

Rather then all that (if (and ...(if stuff, how about the Stephan Koster method?

(and

  (do this)

  (or (do that) (prompt "\nNo can do that."))

  (etc.)

)

The and will cease upon any null evaluation within.

(Not to be confused with Kevin Kostner [Field of Dreams, Danceswithwolves, The Bodyguard, Waterworld])

John F. Uhden

0 Likes
Message 12 of 12

Anonymous
Not applicable

Ok yes that much more sense, seems to be working perfectly too. 

I also really appreciate how you wrote your response - very clear and explanatory.

Thank you!!

0 Likes