Request for AutoLISP

Request for AutoLISP

SnickerinTurtles
Enthusiast Enthusiast
3,352 Views
41 Replies
Message 1 of 42

Request for AutoLISP

SnickerinTurtles
Enthusiast
Enthusiast

Hi all, I am new to posting so please forgive me if I make any mistakes. 

 

I am looking to create an Lisp that will change the color of a specific layer name. For example in a landscape drawing I have xrefenced in some civil files that contain layers "Project#-HC|C-BLDG-OTLN" or "Project#-HC|C-UTIL-WATR". Now I have to go through and change these layers to their specific color in when working in a landscape drawing for landscape plotting purposes. Is there a way to make a lisp so that anytime I run the command it will change layer color  of "Project#-HC|C-BLDG-OTLN" to color 152 and "Project#-HC|C-UTIL-WATR" to color 190. 

 

Hopefully I am making sense if not please let me know and I will try to be more clear.

Thank you.

0 Likes
Accepted solutions (1)
3,353 Views
41 Replies
Replies (41)
Message 2 of 42

cadffm
Consultant
Consultant

For LAyer properties you can easily use the -LAYER command,

if ok for you, use the -LAYER command in Lisp too. (Command "_.-LAYER" and so on "")

 

Because of -LAYER is a normal command, you can also use a simple menumacro - with the same command sequence

 

 

'_.-LAYER;_co;152;Project`#-HC|C-BLDG-OTLN;_co;190;Project`#-HC|C-UTIL-WATR;;

Sebastian

0 Likes
Message 3 of 42

dlanorh
Advisor
Advisor

try this

 

(defun c:xrlyrc ( / c_doc c_lyrs)
  (setq c_doc (vla-get-activedocument (vlax-get-acad-obect))
        c_lyrs (vla-get-layers c_doc)
  )
  (vlax-for lyr c_lyrs
    (cond ( (or (wcmatch (vlax-get lyr 'name) "*|C-BLDG-OTLN")
                (wcmatch (vlax-get lyr 'name) "*|C-UTIL-WATR")
            )
            (if (wcmatch (vlax-get lyr 'name) "*|C-BLDG-OTLN") (vlax-put lyr 'color 152) (vlax-put lyr 'color 190))
          )
    )
  )
  (princ)
)

I am not one of the robots you're looking for

0 Likes
Message 4 of 42

SnickerinTurtles
Enthusiast
Enthusiast

When I run the code I get this error.

"error: no function definition: VLAX-GET-ACAD-OBECT"

 I am guessing I need a way to select the xrefence before telling the layers on that xref to change color?

0 Likes
Message 5 of 42

dlanorh
Advisor
Advisor

Sorry a spelling mistake on my part. Corrected code below

 

(defun c:xrlyrc ( / c_doc c_lyrs)
 (vl-load-com)
  (setq c_doc (vla-get-activedocument (vlax-get-acad-object))
        c_lyrs (vla-get-layers c_doc)
  )
  (vlax-for lyr c_lyrs
    (cond ( (or (wcmatch (vlax-get lyr 'name) "*|C-BLDG-OTLN")
                (wcmatch (vlax-get lyr 'name) "*|C-UTIL-WATR")
            )
            (if (wcmatch (vlax-get lyr 'name) "*|C-BLDG-OTLN") (vlax-put lyr 'color 152) (vlax-put lyr 'color 190))
          )
    )
  )
  (princ)
)

. C

I am not one of the robots you're looking for

0 Likes
Message 6 of 42

SnickerinTurtles
Enthusiast
Enthusiast

Sorry I don't know very much about coding in CAD, but I do know an okay amount of C++.

I do think I understand  and correct me if I am wrong , that it would be several lines of if this then that nested several times. Asking does it match any of these layers if so make it color 1, if it matches any of these layers if so make it color 2, so on and so forth. I tested it but I replaced the * with the xref file name and it ran perfectly.

I am not sure how to replace the * with the xref selected. I thought it may have been the first few lines of code with get-acad-object but it did not asking for an xref. Also I would assume we can freeze specific layers instead of changing the color and linetype?   

 

 

0 Likes
Message 7 of 42

Sea-Haven
Mentor
Mentor

A variation pick color then object for layer.

 

(defun c:xrlyrc2 ( / c_lyrs obj lay)
  (vl-load-com)
  (setvar 'xrefoverride 1)
  (setq c_lyrs (vla-get-layers (vla-get-activedocument (vlax-get-acad-object))))
  (while (setq col (getreal "\nEnter colour number 1-255 Enter to Exit "))
    (setq obj (vlax-ename->vla-object (car (nentsel "\nselect xref layer"))))
    (setq lay (vla-get-layer obj))
    (vlax-for lyr c_lyrs
      (if (= (vlax-get lyr 'name) lay) (vlax-put lyr 'color col))
    )
	(command "regen")
  )
  (princ)
)
(c:xrlyrc2)
0 Likes
Message 8 of 42

SnickerinTurtles
Enthusiast
Enthusiast

This is really useful did a few tests on it at home and works well so far. Like the idea and I do admit this is more versatile for more than just one use. Thanks for coming up with a different solution. 

0 Likes
Message 9 of 42

Sea-Haven
Mentor
Mentor

No worries had a little bit of time.

0 Likes
Message 10 of 42

SnickerinTurtles
Enthusiast
Enthusiast

Although, I do like your way and see that it is more versatile, I would like to know how to do it the other way as well. I think using a conditional would be better than a nested if statement if I were to go the other way. I am still trying to do some more research and learn how to do this but grabbing the first part of any xref to check with my conditional statements and how to create those, but I am slowing getting it. 

0 Likes
Message 11 of 42

dlanorh
Advisor
Advisor

@SnickerinTurtles wrote:

Sorry I don't know very much about coding in CAD, but I do know an okay amount of C++.

I do think I understand  and correct me if I am wrong , that it would be several lines of if this then that nested several times. Asking does it match any of these layers if so make it color 1, if it matches any of these layers if so make it color 2, so on and so forth. I tested it but I replaced the * with the xref file name and it ran perfectly.

I am not sure how to replace the * with the xref selected. I thought it may have been the first few lines of code with get-acad-object but it did not asking for an xref. Also I would assume we can freeze specific layers instead of changing the color and linetype?   

 

 


The "*" is a wild card character in the match string and was intended to negate using the x-ref file name since any layer that has a "|" is an x-ref layer (it is forbidden/restricted character and you cannot create a layer which contains it). The bar divides the x-ref file name from the layer name, but wont pick up non x-ref drawing layers as these cannot contain a bar. WCMATCH

 

That said I should probably have done this

 

 

(defun c:xrlyrc ( / c_doc c_lyrs)
  (setq c_doc (vla-get-activedocument (vlax-get-acad-obect))
        c_lyrs (vla-get-layers c_doc)
  )
  (vlax-for lyr c_lyrs
    (cond ( (or (wcmatch (strcase (vlax-get lyr 'name)) "*|C-BLDG-OTLN")
                (wcmatch (strcase (vlax-get lyr 'name)) "*|C-UTIL-WATR")
            )
            (if (wcmatch (vlax-get lyr 'name) "*|C-BLDG-OTLN") (vlax-put lyr 'color 152) (vlax-put lyr 'color 190))
          )
          ( (wcmatch (strcase (vlax-get lyr 'name)) "*|C-BLDG-CLMN")
            (vlax-put-property lyr 'freeze :vlax-true)
          )
    )
  )
  (princ)
)

 

 

As wcmatch is case sensitive in its checking

 

The (vlax-put lyr 'color ..) is easily replaced with (vlax-put lyr 'freeze ..) see above; or any of the other layer properties

 

I am not one of the robots you're looking for

0 Likes
Message 12 of 42

ВeekeeCZ
Consultant
Consultant

@dlanorh wrote:

 

...
    (cond ( (or (wcmatch (strcase (vlax-get lyr 'name)) "*|C-BLDG-OTLN")
                (wcmatch (strcase (vlax-get lyr 'name)) "*|C-UTIL-WATR")
            )
...

...


 

Or just use a comma to delimit the masks.

 

(cond ((wcmatch (strcase (vlax-get lyr 'name)) "*|C-BLDG-OTLN,*|C-UTIL-WATR")
...)

 

Message 13 of 42

dlanorh
Advisor
Advisor

@ВeekeeCZ wrote:

@dlanorh wrote:

 

...
    (cond ( (or (wcmatch (strcase (vlax-get lyr 'name)) "*|C-BLDG-OTLN")
                (wcmatch (strcase (vlax-get lyr 'name)) "*|C-UTIL-WATR")
            )
...

...


 

Or just use a comma to delimit the masks.

 

(cond ((wcmatch (strcase (vlax-get lyr 'name)) "*|C-BLDG-OTLN,*|C-UTIL-WATR")
...)

 


You learn something new every day 😁

I am not one of the robots you're looking for

Message 14 of 42

Kent1Cooper
Consultant
Consultant

@SnickerinTurtles wrote:

..... Is there a way to make a lisp so that anytime I run the command it will change layer color  of "Project#-HC|C-BLDG-OTLN" to color 152 and "Project#-HC|C-UTIL-WATR" to color 190. 

....


This can be a lot simpler.  The following uses no variables, is not  case-sensitive as (wcmatch) is, nor will it care if a Layer does not exist in the drawing:

 

(defun C:CallItWhatYouWill ()

  (command "_.layer"

    "_color" 152 "*-HC|C-BLDG-OTLN"

    "_color" 190 "*-HC|C-UTIL-WATR"

    ""

  )

)

Kent Cooper, AIA
0 Likes
Message 15 of 42

SnickerinTurtles
Enthusiast
Enthusiast

Pretty cool and it works. But I have a question how does the program know to make the C-UTIL-WATR layer to 190 and not 152. Is it for each layer specified there needs to be a corresponding color associated with it? 

Like this line here. There isn't a "*|C-UTIL-WATR" to be set to color 190. But it still took the 2nd layer listed and made it 190.

(if (wcmatch (vlax-get lyr 'name) "*|C-BLDG-OTLN") (vlax-put lyr 'color 152) (vlax-put lyr 'color 190))

 Or is it that it takes everything in this list and makes it 152 and then everything in the next list 190? Such that if I did this it would make everything in the 1st list color 152 the next 190 and the next 156.

(defun c:xrlyrc ( / c_doc c_lyrs)
  (setq c_doc (vla-get-activedocument (vlax-get-acad-object))
        c_lyrs (vla-get-layers c_doc)
  )
  (vlax-for lyr c_lyrs
    (cond ( (or (wcmatch (strcase (vlax-get lyr 'name)) "*|C-BLDG-OVHG","*|C-BLDG-DOOR","*|C-BLDG-WNDW")
                (wcmatch (strcase (vlax-get lyr 'name)) "*|C-UTIL-MNHL","*|C-UTIL-SEWR","*|C-WATR-INLT","*|C-UTIL-WATR")
                (wcmatch (strcase (vlax-get lyr 'name)) "*|C-BLDG")
            )
            (if (wcmatch (vlax-get lyr 'name) "*|C-BLDG-OTLN") (vlax-put lyr 'color 152) (vlax-put lyr 'color 190) (vlax-put ltr 'color 156))
          )
          ( (wcmatch (strcase (vlax-get lyr 'name)) "*|C-BLDG-CLMN")
            (vlax-put-property lyr 'freeze :vlax-true)
          )
    )
  )
  (princ)
)
0 Likes
Message 16 of 42

Kent1Cooper
Consultant
Consultant

@SnickerinTurtles wrote:

.... how does the program know to make the C-UTIL-WATR layer to 190 and not 152. .... is it that it takes everything in this list and makes it 152 and then everything in the next list 190? Such that if I did this it would make everything in the 1st list color 152 the next 190 and the next 156.

....
            (if (wcmatch (vlax-get lyr 'name) "*|C-BLDG-OTLN") (vlax-put lyr 'color 152) (vlax-put lyr 'color 190) (vlax-put ltr 'color 156))
....

No.  Read about (if) -- it wants a 'then' expression and an optional 'else' expression, but that has a third expression it won't be able to do anything with.

 

What that code does [which is serious overkill in my opinion] is to step through every Layer in the drawing  [what purpose is served by that?], and if one is among a certain group of Layer names, then  if it's the ...BLDG-OTLN one, it makes it color 152, otherwise color 190.  What a lot of work!  Just tell it what color you want what Layer(s).  You can give it multiple Layer names with comma separators, and use wildcards.  See Message 14 again, but to extend that to do more of what's in your latest [I'm not sure I've got the Layer names all assigned to the right colors, but I hope you get the idea]:

 

(defun c:xrlyrc ()
  (command "_.layer"
    "_color" 152 "*|C-BLDG-OTLN"
    "_color" 190 "*|C-BLDG-OVHG,*|C-BLDG-DOOR,*|C-BLDG-WNDW"
    "_color" 156 "*|C-UTIL-MNHL,*|C-UTIL-SEWR,*|C-WATR-INLT,*|C-UTIL-WATR"
    "_freeze" "*|C-BLDG-CLMN"
    "" ; [complete Layer command]
  ); command
); defun

 

No variables, no digging through every Layer needlessly, hugely less code.

Kent Cooper, AIA
0 Likes
Message 17 of 42

SnickerinTurtles
Enthusiast
Enthusiast

I can see how this code is more simplified and I can use this code just fine for all the layers we go through. It does make it easier on me. I just have a question with * being a wild card. Lets say have 2 xrefs one is Civil and the other one is Topo and they both have the C-BLDG-OTLN layer in them. Will this function change the color on both xrefs with the layer "C-BLDG-OTLN"  to  color 152 or will it only happen to one xref? I would assume it would happen to both since it is * is a wildcard it won't care what xref is in the drawing it only care is it contains "|C-BLDG-OTLN". Is that correct?

 

0 Likes
Message 18 of 42

dlanorh
Advisor
Advisor

The layer must first pass the (cond) statement which has two matches. If it does then it must be one or other of the layers. The (if) statement tests for one of the layers, if it's true then it carries out the first statement if this is false then it must be the layer not tested for. This is an either or scenario.

 

Yes, if you run this code on a drawing with multiple x-refs and each contain the layers then all layers that match will be changed across all of the x-refs. If you want to select a specific x-ref then the match pattern can be altered to include a unique part of the x-ref file name.

 

Your code snippet wouldn't work, as the "pattern_string" for the wcmatch must be a single comma delimited string.

 

(defun c:xrlyrc ( / c_doc c_lyrs c_lst f_lst)
  (setq c_doc (vla-get-activedocument (vlax-get-acad-object))
        c_lyrs (vla-get-layers c_doc)
  );end_setq
  
  (vlax-for lyr c_lyrs
    (if (wcmatch (strcase (vlax-get lyr 'name)) "PROJECT#-HC*");This should uniquely identify a single x-ref
      (cond ( (wcmatch (strcase (vlax-get lyr 'name)) "*|C-BLDG-OVHG,*|C-BLDG-DOOR,*|C-BLDG-WNDW") (vlax-put lyr 'color 152))
            ( (wcmatch (strcase (vlax-get lyr 'name)) "*|C-UTIL-MNHL,*|C-UTIL-SEWR,*|C-WATR-INLT,*|C-UTIL-WATR") (vlax-put lyr 'color 190))
            ( (wcmatch (strcase (vlax-get lyr 'name)) "*|C-BLDG") (vlax-put lyr 'color 156))
            ( (wcmatch (strcase (vlax-get lyr 'name)) "*|C-BLDG-CLMN") (vlax-put-property lyr 'freeze :vlax-true))
      );end_cond
    );end_if
  );end_for
  (princ)
);end_defun

 

The (if) statement tests if the first part of the layer name matches the specific x-ref file. If it does it drops into the condition (cond) statement. If it doesn't it loops to the next layer

 

I am not one of the robots you're looking for

0 Likes
Message 19 of 42

Kent1Cooper
Consultant
Consultant

@SnickerinTurtles wrote:

.... Lets say have 2 xrefs ... and they both have the C-BLDG-OTLN layer in them. Will this function change the color on both xrefs with the layer "C-BLDG-OTLN"  ...? I would assume it would happen to both .... Is that correct?


Yes, I believe [without setting up the situation to confirm -- presumably you have that ready for trial] that is correct.

Kent Cooper, AIA
0 Likes
Message 20 of 42

SnickerinTurtles
Enthusiast
Enthusiast

Thanks for staying with me dlanorh. I really do appreciate it. I see my mistake as you mentioned, my synat was incorrect I did "LAYER1","LAYER2","LAYER3" when I should have done "LAYER1, LAYER2, LAYER3". And I also needed to say what to happen to each grouping before setting out the next list of layers. Thank you for showing me what I had done wrong. 

So these xrefs will change from project to project. You said that there is a way to select a specific x-ref then the match pattern can be altered to include a unique part of the x-ref file name. I would like feature as well.  So in your code here:

 

(setq c_doc (vla-get-activedocument (vlax-get-acad-object))
        c_lyrs (vla-get-layers c_doc)
  );end_setq

 

And please correct me if this wrong. This where you set the variable "c_doc" to be able to grab document objects (such as color,layer name, linetypes) from the document we are in. In the next line you set c_lyrs to be the layer name from the (vla-get-layers c_doc). Right? And as you stated the code then "tests if the first part of the layer name matches the specific x-ref file. If it does it drops into the condition (cond) statement." And between these two parts there would be a need for another variable and that variable would have to set, by user input, so it could replace the 

 

(if (wcmatch (strcase (vlax-get lyr 'name)) "PROJECT#-HC*");This should uniquely identify a single x-ref

So that "PROJECT#-HC" is what the user types in or more preferable clicking the xref in the drawing. So it checks everything before the "|" to make sure it is part of the specific xref. Then goes through the layers and checks to see if they match and makes the according adjustments.   Something like that? Thanks again for keeping with me.

0 Likes