Visual LISP, AutoLISP and General Customization

Reply
Contributor
snkunz
Posts: 25
Registered: ‎07-08-2005
Message 1 of 8 (114 Views)

entsel

114 Views, 7 Replies
09-12-2008 12:39 PM
I have a program that uses the entsel command to select objects. The problem I am having is that when the user misses the object it completely cancels the program and forces them to start over. Is there a way to make entsel repeat until the user selects the object?
*Kent Cooper
Message 2 of 8 (114 Views)

Re: entsel

09-12-2008 12:55 PM in reply to: snkunz
Here's a way to do not only that, but to make sure it's the right kind of object for the command,
and that it's not on a locked layer. This one's looking for a Hatch pattern, but you can change
that aspect of it along with the prompt. It also uses (entsel) as in your question, but see below
for another possibility.

(while
(not
(and
(setq
hpent (car (entsel "\nSelect Hatch Pattern: "))
hpdata (if hpent (entget hpent))
); end setq
(= (cdr (assoc 0 hpdata)) "HATCH")
(= (cdr (assoc 70 (tblsearch "layer" (cdr (assoc 8 hpdata))))) 0); on Unlocked Layer
); end and
); end not
(prompt "\nNothing selected, or it is not a Hatch Pattern, or is on a Locked Layer -- ")
); end while
....then goes on and works on the 'hpent' object....

If what you want to do might be done to different kinds of objects, you can also have it ask again
if they pick anything that the command can't work with, rather than limiting it to one object type.
The following uses (ssget) with the Single option, rather than (entsel), and that takes care of the
not-hitting-something issue. It's for offsetting [with other variables established before it gets
to this point], so it limits it to one object.

(while
(not
(while
(not
(and
(setq offent (ssget ":smileyfrustrated:" '((0 .
"LINE,ARC,CIRCLE,ELLIPSE,LWPOLYLINE,SPLINE,XLINE,RAY"))))
(= (cdr (assoc 70 (tblsearch "layer" (cdr (assoc 8 (entget (ssname offent 0))))))) 0);
on Unlocked Layer
); end and
); end not
(prompt "\nSelected Entity cannot be Offset, or is on a Locked Layer; try again: ")
); end while
); end not
....then goes on and does its specialty Offset thing with the 'offent' object....
); end while

--
Kent Cooper


snkunz wrote...
I have a program that uses the entsel command to select objects. The problem I am having is that
when the user misses the object it completely cancels the program and forces them to start over. Is
there a way to make entsel repeat until the user selects the object?
*Kent Cooper
Message 3 of 8 (114 Views)

Re: entsel

09-12-2008 01:05 PM in reply to: snkunz
[I should also mention that this (ssget) approach is set up for doing the same operation on *as many
things as you want* one at a time, in one call of the routine -- the User can just keeping picking
them, and hit Escape when they're done. If you didn't want that repetition, you could take off the
outermost (while (not .... )) "wrappers" for a single-object selection similar to the (entsel)
version, and omit the processing part that's internal to the outermost (while) loop. And watch out
for the Newsgroup system's word wrapping propensities.]
--
Kent Cooper


"Kent Cooper" wrote...
....
(while
(not
(while
(not
(and
(setq offent (ssget ":smileyfrustrated:" '((0 .
"LINE,ARC,CIRCLE,ELLIPSE,LWPOLYLINE,SPLINE,XLINE,RAY"))))
(= (cdr (assoc 70 (tblsearch "layer" (cdr (assoc 8 (entget (ssname offent 0))))))) 0);
on Unlocked Layer
); end and
); end not
(prompt "\nSelected Entity cannot be Offset, or is on a Locked Layer; try again: ")
); end while
); end not
....then goes on and does its specialty Offset thing with the 'offent' object....
); end while
Contributor
snkunz
Posts: 25
Registered: ‎07-08-2005
Message 4 of 8 (114 Views)

Re: entsel

09-12-2008 01:47 PM in reply to: snkunz
I've tried a few variations to what you've shown here but I must not be getting it quite right. I'll post the program that I am working on. Not really concerned with it telling them what they did wrong since the function is intended only to be used on text anyway

(defun c:textswap2 (/ source CopyTargetName CopyTargetList b en)
(setvar "cmdecho" 0)
(prompt "\nSelect text you wish to copy: ")
(eln)
(setq objecttype (cdr (assoc 0 el)))
(if (= objecttype "MULTILEADER")
(multileaderswap)(originalswap))
(if en
(progn
(redraw en 4)
(setq en nil)
) ;end progn
) ;end if
(if (not CopyTargetName)
(progn
(princ "\nProgram Complete!")
(princ)
) ;end progn
) ;end if
(setvar "cmdecho" 1)
(princ)
) ;end function textswap2

(defun multileaderswap ()
(setq source (assoc 304 el))
(redraw (setq en (cdr (assoc -1 el))) 3)
(while (setq CopyTargetName (car (entsel "\nSelect text to copy to: ")))
(setq CopyTargetList (entget CopyTargetName)
b (assoc 304 CopyTargetList)
) ;end setq
(setq CopyTargetList (subst source b CopyTargetList))
(entmod CopyTargetList)
) ;end while
);end function multileaderswap


(defun originalswap ()
(setq source (assoc 1 el))
(redraw (setq en (cdr (assoc -1 el))) 3)
(while (setq CopyTargetName (car (entsel "\nSelect text to copy to: ")));end setq
(setq CopyTargetList (entget CopyTargetName)
b (assoc 1 CopyTargetList)
) ;end setq
(setq CopyTargetList (subst source b CopyTargetList))
(entmod CopyTargetList)
) ;end while
);end function originalswap
*Kent Cooper
Message 5 of 8 (114 Views)

Re: entsel

09-12-2008 02:37 PM in reply to: snkunz
Whether or not you have it tell them anything more than to repeat a "Select...whatever...." prompt
is up to you, and what it's used on doesn't really matter, but if you don't want it to crap out on
them if they miss, you're pretty much going to have to have some kind of a (while (not ... ))
situation [*including* the (not) part -- not just the (while) part]. In other words, as long as it
*doesn't* get something it can apply (entget) to, it needs to loop back and ask again. As you have
it, if the User misses, the (setq) is going return nil, and that's what's going to crash the
routine, because the (while) function will give up [what it's checking for returned nil, and that
means skip to the end]. You need something that returns *other than* nil if they *miss*, and that's
what the (not) function does in the things I posted --

(entsel) returns nil to (setq) because nothing was selected;

(setq) therefore assigns nil to the variable, and also returns nil to (not);

(not) therefore returns T to (while), because what it was checking for returned nil;

(while) therefore "goes ahead" to the next step within itself, which is to ask them to try again,
and loops back for another shot.

But when they *do* succeed in picking something, here's what happens:

(setq) gets from (entsel) something *other than nil*, and also returns that to (not);

(not) therefore, having gotten a non-nil response, returns nil to (while);

(while) therefore jumps to its end, bypassing the try-again part;

and all the *processing* of the selected object happens *after* the end of the (while) loop, *not*
within it.

Your (while) functions are set up in a way that makes them fundamentally no different than (if)
functions [with (progn) heading up the 'then' arguments so they can do more than one thing], because
there's no "loop" opportunity. But (while) is made to check on something that might return nil or
otherwise, *and* if that check is satisfied, when it gets to the end, there's some point in going
back and checking it again, hoping it will then be nil, so the (while) loop can end. So yours may
work if they hit something [as long as it's the right kind of thing, and so on], but as with an (if)
function with no 'else' argument, when they miss, nothing happens. And [again if they hit
something], I suspect the (while) loops get to the end, go back as (while) functions are meant to
do, and ask the User to select something all over again unnecessarily, because once you've done what
you want to do, *there's nothing to "nil out" what (while) is checking for* so that the surrounding
routine can move on. The (not) functions nested inside the (while) functions in my suggestions are
what do that.

--
Kent Cooper


snkunz wrote...
I've tried a few variations to what you've shown here but I must not be getting it quite right.
I'll post the program that I am working on. Not really concerned with it telling them what they did
wrong since the function is intended only to be used on text anyway

(defun c:textswap2 (/ source CopyTargetName CopyTargetList b en)
(setvar "cmdecho" 0)
(prompt "\nSelect text you wish to copy: ")
(eln)
(setq objecttype (cdr (assoc 0 el)))
(if (= objecttype "MULTILEADER")
(multileaderswap)(originalswap))
(if en
(progn
(redraw en 4)
(setq en nil)
) ;end progn
) ;end if
(if (not CopyTargetName)
(progn
(princ "\nProgram Complete!")
(princ)
) ;end progn
) ;end if
(setvar "cmdecho" 1)
(princ)
) ;end function textswap2

(defun multileaderswap ()
(setq source (assoc 304 el))
(redraw (setq en (cdr (assoc -1 el))) 3)
(while (setq CopyTargetName (car (entsel "\nSelect text to copy to: ")))
(setq CopyTargetList (entget CopyTargetName)
b (assoc 304 CopyTargetList)
) ;end setq
(setq CopyTargetList (subst source b CopyTargetList))
(entmod CopyTargetList)
) ;end while
);end function multileaderswap


(defun originalswap ()
(setq source (assoc 1 el))
(redraw (setq en (cdr (assoc -1 el))) 3)
(while (setq CopyTargetName (car (entsel "\nSelect text to copy to: ")));end setq
(setq CopyTargetList (entget CopyTargetName)
b (assoc 1 CopyTargetList)
) ;end setq
(setq CopyTargetList (subst source b CopyTargetList))
(entmod CopyTargetList)
) ;end while
);end function originalswap
Contributor
snkunz
Posts: 25
Registered: ‎07-08-2005
Message 6 of 8 (114 Views)

Re: entsel

09-12-2008 03:15 PM in reply to: snkunz
I made a small adjustment to my code. Adding the not function into it and everything that you explained earlier was happening each command returns what I would expect it to return. However when I run the command as a whole and select nothing the command still ends and it returns a bad argument type: lentityp nil error. Here is the part of the code I changed. Thanks for all the help. I suspect that the end parentheses for the not command is in the wrong place but that's just my guess.

(while (not (setq CopyTargetName (car (entsel "\nSelect text to copy to: "))));end not
(setq CopyTargetList (entget CopyTargetName)
b (assoc 1 CopyTargetList)
) ;end setq
(setq CopyTargetList (subst source b CopyTargetList))
(entmod CopyTargetList)
) ;end while
Distinguished Contributor
EC-CAD
Posts: 5,929
Registered: ‎12-12-2003
Message 7 of 8 (114 Views)

Re: entsel

09-14-2008 07:21 AM in reply to: snkunz
You need to move the ...
);end while
line, to 'just' below the ...
(while (not ........
line.

So, it looks like:
(while (not (setq CopyTargetName (car (entsel "\nSelect text to copy to: "))));end not
) ;end while
(setq CopyTargetList (entget CopyTargetName)
b (assoc 1 CopyTargetList)
) ;end setq
(setq CopyTargetList (subst source b CopyTargetList))
(entmod CopyTargetList)

Bob
*Kent Cooper
Message 8 of 8 (114 Views)

Re: entsel

09-15-2008 07:47 AM in reply to: snkunz
Bob's correct -- as I said previously, "...all the *processing* of the selected object happens
*after* the end of the (while) loop, *not*
within it", because the (while) loop has to be satisfied by finding something, before it does
anything with it.

But if you're trying to put the end of the (while) loop at the end of the routine because you want
to be able to continuously pick a bunch of things and do this to each of them, in one call of the
routine, you can embed the whole thing in another (while) loop, something like:

(while T
....
(while ..... the same kind of thing for the "\nSelect text you wish to copy: " part....)
(....the extracting of sourceb or whatever from the selected text....)
....
(while
(not
(setq CopyTargetName (car (entsel "\nSelect text to copy to: ")))
); end not
); end while
(setq
CopyTargetList (entget CopyTargetName)
b (assoc 1 CopyTargetList)
); end setq
(setq CopyTargetList (subst source b CopyTargetList))
(entmod CopyTargetList)
....
); end while

That should let the User do it repeatedly, until they hit Escape.
--
Kent Cooper


snkunz wrote...
I made a small adjustment to my code. Adding the not function into it and everything that you
explained earlier was happening each command returns what I would expect it to return. However when
I run the command as a whole and select nothing the command still ends and it returns a bad argument
type: lentityp nil error. Here is the part of the code I changed. Thanks for all the help. I
suspect that the end parentheses for the not command is in the wrong place but that's just my guess.

(while (not (setq CopyTargetName (car (entsel "\nSelect text to copy to: "))));end not
(setq CopyTargetList (entget CopyTargetName)
b (assoc 1 CopyTargetList)
) ;end setq
(setq CopyTargetList (subst source b CopyTargetList))
(entmod CopyTargetList)
) ;end while

You are not logged in.

Log into access your profile, ask and answer questions, share ideas and more. Haven't signed up yet? Register

Announcements
Are you familiar with the Autodesk Expert Elites? The Expert Elite program is made up of customers that help other customers by sharing knowledge and exemplifying an engaging style of collaboration. To learn more, please visit our Expert Elite website.

Need installation help?

Start with some of our most frequented solutions to get help installing your software.

Ask the Community