Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Get user string, check to see if any layers in drawing match user-input

23 REPLIES 23
SOLVED
Reply
Message 1 of 24
bhull1985
975 Views, 23 Replies

Get user string, check to see if any layers in drawing match user-input

Hello everyone, I am attempting to tackle a new project.

I'm writing a small routine to enable layer toggles based off of a few characters inputted by a user, such as:

 

Laymod "IFC" thaw

 

would be the user execution command, and within that I want this program to search for any matches within the list of returned layers in the drawing to what's in the double-quotes, in the example above, it would return any or all layers that have the string "IFC" within them.

 

I've been able to construct the layer list, and have set vars for the layers to be an argument of the subfunction required to toggle the layers.

 

What I need some assistance with is the string matching portion of this routine, that would search the table of layers and return any matches to the user input....if anyone would assist me in this i would be grateful.

 

Thanks and cheeeeeeers!

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Please use code tags and credit where credit is due. Accept as solution, if solved. Let's keep it trim people!
23 REPLIES 23
Message 2 of 24
Lee_Mac
in reply to: bhull1985


@bhull1985 wrote:

What I need some assistance with is the string matching portion of this routine, that would search the table of layers and return any matches to the user input

 


 

Look into the tblsearch function.

Message 3 of 24
bhull1985
in reply to: Lee_Mac

Thanks Lee, I will look into it!

I was wondering on an unrelated note if you had received the email I sent to you yesterday?

Just simply inquiring as to if you've written a specific program or not because I was not able to locate it on your website....yet I would think you've done something similar, so was just hoping to find out.

 

Anyhow, thanks for the hint with this one, i'll study up!

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Please use code tags and credit where credit is due. Accept as solution, if solved. Let's keep it trim people!
Message 4 of 24
Kent1Cooper
in reply to: bhull1985


@bhull1985 wrote:

....

I'm writing a small routine to enable layer toggles based off of a few characters inputted by a user, such as:

 

Laymod "IFC" thaw

 

would be the user execution command, and within that I want this program to search for any matches within the list of returned layers in the drawing to what's in the double-quotes, in the example above, it would return any or all layers that have the string "IFC" within them.

....


If you really mean toggle [that is, switch from one state of a possible pair, whichever it is, to the opposite], it's more complicated, but your sample User input suggests maybe you mean to switch to a specified state, regardless of which of the possible pair of states they start in.  If that User input means you want to thaw all Layers containing "IFC" in their names, rather than toggle their freeze/thaw state, you don't need to make a list, but can do something as simple as this:

 

(defun laymod (substr option)

  (command "_.layer" option (strcat "*" substr "*") "")

)

 

Usage:

 

In your example:

(laymod "IFC" "Thaw")

or even just

(laymod "IFC" "T")

 

Note that the option argument needs to be in double-quotes, in addition the Layer-name substring as in your example.  And as a function with arguments, the whole thing needs to be in parentheses, but:

 

If you want it as a Command, with User inputs in answer to prompts rather than as arguments to a function:

 

(defun C:LAYMOD (/ substr option)

  (setq

    substr (getstring "\nPortion of Layer name(s) to apply option to: ")

    option (getstring "\nLayer option to apply to them: ")

  ); setq

  (command "_.layer" option (strcat "*" substr "*") "")

); defun

 

And then, in answer to the prompts, the User wouldn't include the double-quotes around the substring or option.

 

You could also use (initget) and (getkword) to force the User to supply a valid Layer option [the above will have trouble if they type something wrong].

Kent Cooper, AIA
Message 5 of 24
Kent1Cooper
in reply to: Lee_Mac


@bhull1985 wrote:
....it would return any or all layers that have the string "IFC" within them.
@Lee_Mac wrote:
....
Look into the tblsearch function

Unfortunately, (tblsearch) doesn't like wildcards, but needs a fully spelled-out individual [in this case] Layer name.  It can't find more than one Layer, nor even a single Layer if only one matches, given only a portion of the Layer name(s).

Kent Cooper, AIA
Message 6 of 24
bhull1985
in reply to: Kent1Cooper

Great, thanks again Kent.

I'll attempt my routine using these instead, and see how it works.

Much appreciated!

 

And ah, alright. I wasn't intent on using wcmatch, just thought that it may be the best option for a user to type a few characters and have it match those few characters with any layers containing those characters from a list of layers obtained earlier in the routine.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Please use code tags and credit where credit is due. Accept as solution, if solved. Let's keep it trim people!
Message 7 of 24
Kent1Cooper
in reply to: bhull1985


@bhull1985 wrote:

Great, thanks again Kent.

I'll attempt my routine using these instead, and see how it works.

Much appreciated!

 

And ah, alright. I wasn't intent on using wcmatch, just thought that it may be the best option for a user to type a few characters and have it match those few characters with any layers containing those characters from a list of layers obtained earlier in the routine.


You're welcome.  The Layer command itself will perform the (wcmatch)-like operation on the Layer collection, without the need for you to make a list of them, in the place where it's asking for Layer name(s), where [unlike (tblsearch)] it can work with (wcmatch)-style wildcards.

Kent Cooper, AIA
Message 8 of 24
bhull1985
in reply to: Kent1Cooper

Okay, and with the quickprop hover over item information boxes in autocad that show the layer of the item being hovered, that will work great. Thanks for the zillionth time 🙂

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Please use code tags and credit where credit is due. Accept as solution, if solved. Let's keep it trim people!
Message 9 of 24
bhull1985
in reply to: Kent1Cooper

Alright I'm getting a strange error message,

one that I haven't seen before.

Perhaps someone else has??

And could tell me why...

 

I'm having a bit of difficulty in establishing the variables in a manner that will have the program display a list of the layers in the drawing (table "layer") within the code to do that, calling a sub.

That's step 1, then I want the users to be able to simply issue on their command line the following:

 

Laymod "Layername-From-list-or-portion-of-layername-from-list" State

 

where Laymod is the command to invoke the routine, the quoted information is the layer to be modified , accepting full or partial layer name from the given list, and then state is the layers property to be modified.

I've got the subroutines all in it and am just having a hard time in establishing a way to inform the user to only enter those 3 words as their terms, and having it set the vars correctly based from that

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Please use code tags and credit where credit is due. Accept as solution, if solved. Let's keep it trim people!
Message 10 of 24
Kent1Cooper
in reply to: bhull1985


@bhull1985 wrote:

Alright I'm getting a strange error message,

one that I haven't seen before.

....

then I want the users to be able to simply issue on their command line the following:

 

Laymod "Layername-From-list-or-portion-of-layername-from-list" State

....


Posting the error message would help.

 

A command defined by way of

  (defun C:Something ...

cannot contain arguments [entries before the backslash in the parentheses following the command name].

 

If you want it as a command the User can type in as a command name, remove those [it looks like the first is not used except inside sub-routines anyway, and the second is also in the localized variables list after the parentheses, which I imagine would be a conflict].

 

If you want it as a function with arguments, then remove the C:, and it has to be used with those three terms in parentheses, and the last one would also need to be in double-quotes [see my first Reply on this thread].

Kent Cooper, AIA
Message 11 of 24
bhull1985
in reply to: Kent1Cooper

Oh duh, my bad

was getting rushed away to complete another task 😛

 Here's the error msg:

 

Command: (LOAD "Y:/bhull/_layermod.lsp") too few arguments in SETQ: (SETQ
LSTATE (GETKWORD "\nChoose layer control:") (COND ((= LSTATE "Freeze") (FRZTOG
LAYOBJ) (COMMAND "regen")) ((= LSTATE "Thaw") (THAWTOG LAYOBJ) (COMMAND
"regen")) ((= LSTATE "On") (LAYERONOFF LAYOBJ T LAYOBJ) (COMMAND "regen")) ((=
LSTATE "Off") (LAYERONOFF LAYOBJ nil) (COMMAND "regen")) ((= LSTATE "Lock")
(LOCKTOG LAYOBJ) (COMMAND "regen")) ((= LSTATE "Unlock") (UNLOCKTOG LAYOBJ)
(COMMAND "regen"))))

 

 

And yeah, I want it to be however is required for the users to call the functions by typing

Laymod "layer" On

Laymod "layer" freeze

...etc

 

 

I was thinking that I could require arguments in the command to call the function, but apparently this is not true?

Hrm...how do you make a command-line-issued function that uses subfunctions if not able to require arguments in the (defun C:laymod) ? Ugh, i'm missing something here that'll connect these dots together I feel that my routine is pretty close....

 

 

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Please use code tags and credit where credit is due. Accept as solution, if solved. Let's keep it trim people!
Message 12 of 24
Kent1Cooper
in reply to: bhull1985


@bhull1985 wrote:

....

Here's the error msg:

 

Command: (LOAD "Y:/bhull/_layermod.lsp") too few arguments in SETQ: (SETQ
LSTATE (GETKWORD "\nChoose layer control:") (COND .... 

 

And yeah, I want it to be however is required for the users to call the functions by typing

Laymod "layer" On

Laymod "layer" freeze

...etc

 

I was thinking that I could require arguments in the command to call the function, but apparently this is not true?

.... 


On the error message, you need an additional right parenthesis after the (getkword) function to close the (setq) function, before going on to the (cond) function:

(SETQ LSTATE (GETKWORD "\nChoose layer control:")) (COND ....

 

That's right, it's not true.  A command function can call sub-routines without their being listed as arguments, and may not have listed arguments before the backslash in the parentheses following the command name, but may have only localized variables after the backslash [or nothing, not even the backslash, if there are no localized variables, though even then it still needs the parentheses].

 

When used as a command in that way, the User's input of the second term in your examples can be without the double-quotes around it [it can have them, but they're superfluous], except when the string they want to put in contains any space(s), in which case the quotes would be needed.

Kent Cooper, AIA
Message 13 of 24
bhull1985
in reply to: Kent1Cooper

Oh, doh!

Thanks Kent, didn't see that'n and the error message through me off .

I thought it normally mentions parenthesis missing? Oh well.

And yeah, thanks for explaining that some, I'll try and finish it up now

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Please use code tags and credit where credit is due. Accept as solution, if solved. Let's keep it trim people!
Message 14 of 24
dgorsman
in reply to: bhull1985

Have a look at the basic AutoCAD commands; how many of them are formatted/take arguments that way?  Commands which take additional parameters ask for them one at a time.  Since this is the pattern users are used to following with existing commands, then its a good idea to follow it as well.

 

The upside is, by using a single "LAYMOD" command line function which prompts for arguments you can script in answers in the command macros and scripts e.g. ^C^CLAYMOD;TEST;FREEZE.  By using a command line wrapper function to call a non-command function with arguments, you can create single-purpose commands to do the same thing e.g.

 

(defun c:TEST_FREEZE_COMMAND ( / )
   (laymod "TEST" "FREEZE")
   (princ)
)

(defun c:TEST_THAW_COMMAND ( / )
   (laymod "TEST" "THAW")
   (princ)
)

 

----------------------------------
If you are going to fly by the seat of your pants, expect friction burns.
"I don't know" is the beginning of knowledge, not the end.


Message 15 of 24
bhull1985
in reply to: dgorsman

Precisely, and that's interesting to read your post because most of it was my last few moments of thought.

Here's what I've got , and it works alright except for the case-sensitive getstring, though I've just noticed it and via strcase should be able to fix it.

 

It's kinda neat, just a command version to execute the layfrz and layoff and other express tool selection layer modifiers.

 

And it's handy for us because as you said, this can be used in scripts rather easily

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Please use code tags and credit where credit is due. Accept as solution, if solved. Let's keep it trim people!
Message 16 of 24
bhull1985
in reply to: dgorsman

And in fact i was just able to fix the case-sensitivity by changing the following:

 

(if (setq layobj (getstring "\n Select layer to modify from this list."))     ;;
(progn        
 (tblsearch "LAYER" "layobj")
(princ "Freeze Thaw On oFF Lock Unlock eXit")        
(setq lstate (strcase (getstring "\nChoose layer control:")))  
  (cond           
 ((= lstate "FREEZE")(FRZTOG layobj)(command "regen"))      ;; freeze layer
 ((= lstate "THAW")(THAWTOG layobj)(command "regen"))      ;; thaw layer
 ((= lstate "ON")(LAYERONOFF layobj t layobj)(command "regen"))     ;; on layer
 ((= lstate "OFF")(LAYERONOFF layobj nil)(command "regen"))     ;; off layer
 ((= lstate "LOCK")(LOCKTOG layobj)(command "regen"))      ;; lock layer
 ((= lstate "UNLOCK")(UNLOCKTOG layobj)(command "regen"))     ;; unlock layer
 )             ;; cond
)             ;; setq
)             ;; progn
)             ;; if

 

 

hooray for getting something , even as minor as this, right 🙂

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Please use code tags and credit where credit is due. Accept as solution, if solved. Let's keep it trim people!
Message 17 of 24
bhull1985
in reply to: bhull1985

Thought KentCooper,

this line

 

(command "_.layer" option (strcat "*" substr "*") "")

 

caused this error, and I am interested to hear your thoughts as to why, when you see this

 

Error: bad argument type: stringp #<SUBR @000000002bc8e570 SUBSTR>*

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Please use code tags and credit where credit is due. Accept as solution, if solved. Let's keep it trim people!
Message 18 of 24
bhull1985
in reply to: bhull1985

And alright, cleaned up. Solved. Thanks guys 🙂

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Please use code tags and credit where credit is due. Accept as solution, if solved. Let's keep it trim people!
Message 19 of 24
Kent1Cooper
in reply to: bhull1985


@bhull1985 wrote:

Thought KentCooper,

this line

 

(command "_.layer" option (strcat "*" substr "*") "")

 

caused this error, and I am interested to hear your thoughts as to why, when you see this

 

@Anonymous: bad argument type: stringp #<SUBR @000000002bc8e570 SUBSTR>*


That's probably because I shouldn't have used an AutoLisp function name as a variable name -- didn't think of the fact that it is a function name.  I expect if you changed 'substr' to something else, it shouldn't have a problem.

Kent Cooper, AIA
Message 20 of 24
Kent1Cooper
in reply to: bhull1985


@bhull1985 wrote:

And in fact i was just able to fix the case-sensitivity by changing the following:

 

(if (setq layobj (getstring "\n Select layer to modify from this list."))     ;;
....

(princ "Freeze Thaw On oFF Lock Unlock eXit")        
(setq lstate (strcase (getstring "\nChoose layer control:")))  
  (cond           
    ((= lstate "FREEZE")(FRZTOG layobj)(command "regen"))      ;; freeze layer
....


A slightly better way to do that is this:

 

(initget "Freeze Thaw On oFF Lock Unlock eXit")        ;; establish controls
(setq lstate (getkword "\nChoose layer control {Freeze/Thaw/On/oFF/Lock/Unlock/eXit}:")))      ;; get state
(cond             ;; which option selected
  ((= lstate "Freeze") (FRZTOG layobj)(command "regen"))      ;; freeze layer

... etc. ...

 

The advantages of the (initget)/(getkword) approach are:

 

1)  The user doesn't need to enter the entire word as they do for your (getstring) version to work, but just the capitalized key letter(s) [as they're used to doing in typical commands], and the (getkword) function will return the appropriate word in exactly the format it has in the (initget) function [so you need to duplicate that in each test in the (cond) function -- note the case agreement of the green words].

 

2)  It's not case-sensitive.  The user can type F or f or Freeze or freeze, or even some more of the word than the key letter(s), in any case combination [e.g. FrE], and it will still return it in the "correct" case combination, and no (strcase) is required.

 

By the way, if you have people who are accustomed to the Command:-line version of the Layer command, you might consider changing your key letter(s) to agree with those for the options in LAYER:  ON and OFF in all-capitals, and LOck with the first two letters capitalized.

Kent Cooper, AIA

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost