Lisp to search for layers with specific text and freeze all?

Lisp to search for layers with specific text and freeze all?

3rduser
Contributor Contributor
819 Views
10 Replies
Message 1 of 11

Lisp to search for layers with specific text and freeze all?

3rduser
Contributor
Contributor

Looking for a lisp that searches through all layers in a drawing and freezes them based on a user provided term. For example, the drawings I work with show a lot of topography lines that I don't need for my purposes but searching and freezing all of them one by one is time consuming. The pertaining layers (out of hundreds) in one drawing could be:

 

-N-TOPO-MNR

-N-TOPO-MJR

-S-Topogr-cl

-W-topogr-cl

-Main-topog-contr

-E-topog-ctrlne

 

As you can see the layers are all named differently and since I work with different companies doing different drawings the layers will never be the same name drawing to drawing. I need it to be sort of like the "find" command I'd like to type in the command name and then (in this case) just give it the term "topo" (caps wouldn't matter) and it would go and find every layer that directly contains "topo" or has "topo" as part of the layer name and then freeze it.

 

As a further improvement, I'd like to ideally have a catalog of terms to use. Like be able to permanently add terms like "topo", "water", etc... within the code where it would go through said process with each term but also still allows the user to type in new terms as needed. If new terms are found to be common I would simply add them to the catalog list within the code. 

 

0 Likes
Accepted solutions (2)
820 Views
10 Replies
Replies (10)
Message 2 of 11

Kent1Cooper
Consultant
Consultant
Accepted solution

-LAYER command [with the hyphen prefix for command-line usage]

Freeze option

*TOPO* to find all Layer containing "topo" with or without additional characters before and/or after [not case-sensitive]

{Enter to complete}

 

In AutoLisp terms:

(defun C:FATL (); = Freeze All TOPO Layers
  (command "_.layer" "_freeze" "*TOPO*" "")
)
Kent Cooper, AIA
Message 3 of 11

paullimapa
Mentor
Mentor

You can also use the Layer Property Manager's Property Filter feature to filter out the layer names using wildcards.

Then select all layers matching that property filter to change the status like Freeze/Thaw, Off/On and etc.

With the Layer Property Manager open hit combination key Alt+P or click on icon on upper left corner to open the Property Filter window

paullimapa_0-1715881900500.png

paullimapa_1-1715882046399.png

Then give this a name like TOPO & indicate under layer name wildcards *TOPO* of layer names you want to see in this Property Filter.

Now under the Filters column on the left you'll see this new TOPO Property Filters group:

paullimapa_2-1715882094532.png

You can do the same with WATER & etc and then you just select the group you want to see and only layer names matching that group filter will appear on the layer list for you to manipulate.


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
Message 4 of 11

3rduser
Contributor
Contributor

that is awesome! I did not realize it would be such a simple code. I can work off of this further, thank you very much.

0 Likes
Message 5 of 11

3rduser
Contributor
Contributor

thank you for the info! I will use this as well.

0 Likes
Message 6 of 11

3rduser
Contributor
Contributor
Accepted solution

Hey all, just for anyone's future use I have created / edited the code to be exactly what I asked for in the initial post. Thanks @Kent1Cooper for explaining that asterisks can be used to create a "wildcard" in layer command statements. I know a fair amount of lisp but I am still learning new things everyday. Anyways I have made it so that you can have a default catalog of terms you want frozen off the bat or if you would just like to go by a quick new term you can. The "catalog" is the short list provided within the code, just edit between the asterisks and delete / add as necessary. Thanks all!

 

Also I am still learning how to handle error functioning. As of now if you exit the code mid routine you will need to re-edit your current layer and the cmdecho variable.

 

(defun c:3pfrz\ ( / frzsel oldlay catfrzstring newterm newfrzstring )
	(setq oldlay (getvar "clayer"))
	(setvar "cmdecho" 0)
	(command "_.clayer" "0")
	(initget 1 "c t")
	(setq frzsel (getkword "SELECT FREEZE OPTION: [(C)atalog/(T)erm] > "))
	(cond
		(
			(eq frzsel "c")
			(setq catfrzstring
				(strcat
					"*drive*,"
					"*cntr*,"
					"*conc*,"
					"*pipe*,"
					"*swlk,*"
					"*text*,"
					"*topo*,"
					"*util*,"
					"*watr*,"
				)
			)
			(command "_.-layer" "f" catfrzstring "")
		)
		(
			(eq frzsel "t")
			(setq newterm (getstring "ENTER SEARCH TERM > "))
			(setq newfrzstring (strcat "*" newterm "*"))
			(command "_.-layer" "f" newfrzstring "")
		)
	)
	(command "_.clayer" oldlay)
	(setvar "cmdecho" 1)
	(princ)
)

 

0 Likes
Message 7 of 11

MrJSmith
Advocate
Advocate

You can either do a global error handler or a local one. I typically use a global one and would in this case. Locals are good for doing some additional/extra steps. For setting up a global error handler, I would follow this example and use their global error handler as a good starting template that you can then build from as you need to address additional variables/changes. https://www.afralisp.net/autolisp/tutorials/error-trapping.php

 

If you were to use a local error handler for this example, you could add something like this at the start of the code.

 

(defun *error* ( msg )
	(setvar "clayer" oldlay)
	(setvar "cmdecho" 1)
	(or (wcmatch (strcase msg) "*BREAK,*CANCEL*,*EXIT*")
		(princ (strcat "\n** Error: " msg " **")))
	(princ)
)

 

 

You'd also have to add the defun *error* to your localized variables.

 

(defun c:3pfrz\ ( / *error* frzsel oldlay catfrzstring newterm newfrzstring )

 

 

0 Likes
Message 8 of 11

Sea-Haven
Mentor
Mentor

As you mentioned various companies supply a dwg. Have you thought about having a text file with the layer names for that company. So you make the catfrzstring by reading the file. Its pretty easy to add more to that file if they introduce new layer names. You can either have one file with 1st line being company name, then end the company layers with a blank line. Repeating that pattern in the file. Or a file per company. Its easy to select company name using my Multi radio buttons.lsp as I have posted many times.

 

0 Likes
Message 9 of 11

john.uhden
Mentor
Mentor

@MrJSmith ,

I like to use what @Kent1Cooper showed me several years ago...

(defun c:MyCommand ( / *error* var vals etc)
  (setq vars '("cmdecho" "etc"))
  (setq vals (mapcar 'getvar vars))
  (defun *error* (err)
    (mapcar 'setvar vars vals)
    ;; etc.
    (princ)
  )
  (*error* nil)
)

John F. Uhden

0 Likes
Message 10 of 11

Kent1Cooper
Consultant
Consultant

Yes, I like that way of putting the system variables [any number of them] into a list, and both extracting and resetting them all collectively with simple (mapcar) functions.  [You may have gotten that from me, but I don't think I originated the concept.]  By the way, you don't need the quotation marks around the System Variable names.

 

And you can also use that list of names to change the settings for in-routine purposes collectively, too.  For instance, if these are the ones you want to deal with:

 

(setq vars '(cmdecho blipmode ucsfollow cecolor clayer))

 

Then after you've pulled the starting values with your line 3, you can turn off the first three of those, and set values into the other two, without separate (setvar) functions for each one, by using that same list:

 

(mapcar 'setvar vars '(0 0 0 "BYLAYER" "YourWorkingLayer"))

 

But personally, I never use your line 9 at the end of a routine:

 

(*error* nil)

 

I know it "works," but it just goes against the grain for me to trigger the *error* handler when there hasn't been an error.  I just use this instead at the end of a routine:

 

(mapcar 'setvar vars vals)

 

Yes, it means a little additional code at the end if the *error* handler does more than just that [for instance ending an Undo wrapper].

Kent Cooper, AIA
0 Likes
Message 11 of 11

john.uhden
Mentor
Mentor

@Kent1Cooper ,

Thankyou for exacerbating on the use of (mapcar 'setvar ...).

As to (*error* nil), back in the days when locals weren't localized at all, I created an @reset function to clean up everything.  Then I included a call to it in the *error* function before I realized that AutoCAD had fixed the localization disorder.  Then I realized that I didn't need a separate function, instead just include it all in the *error* function, which could serve a dual purpose... cleaning up in case of an error AND cleaning up at the end of a routine (even if there wasn't an error), complete with undo starts and ends, and a closing (princ).

Less code and tastes great, unless of course I produced an error within the error function.  To me, that is really ugly.

John F. Uhden

0 Likes