Pause Script for User Input in LISP

Pause Script for User Input in LISP

AGGilliam
Collaborator Collaborator
1,136 Views
10 Replies
Message 1 of 11

Pause Script for User Input in LISP

AGGilliam
Collaborator
Collaborator

I've come across a few posts discussing this topic but can't seem to find a solution for when you're running a LISP routine in the script. It's a very basic script, opens a file, runs the LISP routine, saves and closes. The LISP routine was created to swap out attribute values in our drawings for updating part numbers. The script and LISP routine work fine as is (when I hard code the attribute values anyway), but I was hoping to allow the user to enter the old and new attribute values rather than edit the LISP routine every time. Here's the LISP routine with my attempt at getting a user input:

;
; A LISP routine to replace an old part number attribute with a new part number
; This is intended to be used with a script for mass changes
;

(defun c:ReplaceParts ()
  
  ; Part Numbers
  (if (or (= (vl-bb-ref 'OLDPART) nil) (= (vl-bb-ref 'NEWPART) nil))
    (progn
      (vl-bb-set 'OLDPART (getstring nil "Enter the old part number: "))
      (vl-bb-set 'NEWPART (getstring nil "Enter the new part number: "))
    )
  )
  
  ; Attributes
  (SETQ attblock "ATT") ; keep this line in here, needed for the attribute extract
  (SETQ attnm "ITEM") ; keep this line in here
  
  ; Verify Attribute Exists
  (setq ss (ssget "_X" (list (cons 0 "INSERT") (cons 2 attblock))))
  (setq i 0) ; was 0
  (IF (/= ss nil)(PROGN ; if there is a selection set
    (setq n_ent (sslength ss)) ; then set n_ent  = length of selection set
    (wHILE (< i  n_ent)
      (setq en  (SSNAME ss i)) ;- Get the entity name of the block
      (setq enlist (entget en)) ;- Get the DXF group codes
      (if(= (cdr(assoc 66 enlist)) 1)(PROGN ;- See if the attribute flag equals one (if so, attributes follow)
        (setq en2(entnext en)) ;- Get the next sub-entity
        (setq enlist2(entget en2)) ;- Get the DXF group codes
        (IF (/= (assoc 1 enlist2) NIL)(SETQ ATTITEM  (cdr (assoc 1 enlist2))))
        (while (/= (cdr(assoc 0 enlist2)) "SEQEND") ;- Start the while loop and keep    
          (setq en2 (entnext en2)) ;- Get the next sub-entity
          (setq enlist2 (entget en2)) ;- Get the DXF group codes
        ) ; end while
      )) ; end prog
      (if (= ATTITEM (vl-bb-ref 'OLDPART))
        (COMMAND "ATTEDIT" "N" "N" attblock attnm "*" (vl-bb-ref 'OLDPART) (vl-bb-ref 'NEWPART))
      )
      (setq i (+ 1 i)) ; up the counter
    )
  ))
  
  ; Attributes
  (SETQ attblock "ITEM") ; keep this line in here, needed for the attribute extract
  (SETQ attnm "PART") ; keep this line in here
  
  ; Verify Attribute Exists
  (setq ss (ssget "_X" (list (cons 0 "INSERT") (cons 2 attblock))))
  (setq i 0) ; was 0
  (IF (/= ss nil)(PROGN ; if there is a selection set
    (setq n_ent (sslength ss)) ; then set n_ent  = length of selection set
    (wHILE (< i  n_ent)
      (setq en  (SSNAME ss i)) ;- Get the entity name of the block
      (setq enlist (entget en)) ;- Get the DXF group codes
      (if(= (cdr(assoc 66 enlist)) 1)(PROGN ;- See if the attribute flag equals one (if so, attributes follow)
        (setq en2(entnext en)) ;- Get the next sub-entity
        (setq enlist2(entget en2)) ;- Get the DXF group codes
        (IF (/= (assoc 1 enlist2) NIL)(SETQ ATTITEM  (cdr (assoc 1 enlist2))))
        (while (/= (cdr(assoc 0 enlist2)) "SEQEND") ;- Start the while loop and keep    
          (setq en2 (entnext en2)) ;- Get the next sub-entity
          (setq enlist2 (entget en2)) ;- Get the DXF group codes
        ) ; end while
      )) ; end prog
      (if (= ATTITEM (vl-bb-ref 'OLDPART))
        (COMMAND "ATTEDIT" "N" "N" attblock attnm "*" (vl-bb-ref 'OLDPART) (vl-bb-ref 'NEWPART))
      )
      (setq i (+ 1 i)) ; up the counter
    )
  ))
)

I should also add, this version of the LISP routine works as intended outside of the script, but within the script it just opens and closes the drawings without doing anything. Is this possible or should I just go back to hard coding the values?

0 Likes
Accepted solutions (2)
1,137 Views
10 Replies
Replies (10)
Message 2 of 11

CADaSchtroumpf
Advisor
Advisor

In a script user input is not possible.
However, in a full or 2024LT version, a solution remains possible.
This is the lisp function (grread) which manages to take over in a script, but this will require development.
I have nothing to offer specific to your desire.
An example of how to enter xxx.xxx,yyy.yyy,zzz.zzz coordinates in a script.
I hope this will be a clue for you...

((lambda ( / char Input)
  (setq char "")
  (while (and (setq Input (grread T 4 2)) (or (eq (car Input) 5) (eq (car Input) 2)) (not (equal Input '(2 13))) (not (equal Input '(2 32))))
    (cond
      ((eq (car Input) 2)
        (if (member (cadr Input) '(44 46 48 49 50 51 52 53 54 55 56 57))
          (setq char (strcat char (chr (cadr Input))))
        )
        (if (eq (cadr Input) 8)
          (progn
            (setq char (substr char 1 (1- (strlen char))))
            (prompt (chr 8))
          )
          (prompt (chr (cadr Input)))
        )
      )
    )
  )
  (print)
  char
))
Message 3 of 11

paullimapa
Mentor
Mentor
Accepted solution

This is what you can do in your script file before you call your lisp function:

(if (or (= (vl-bb-ref 'OLDPART) nil) (= (vl-bb-ref 'NEWPART) nil))(progn(load"sample0")(c:sample0)))

Remember to save attached Sample0.lsp in location that's in AutoCAD's Support File Search Path

Sample0.lsp will only bring up a dialog box for you to enter & set OLDPART & NEWPART if those have not be defined.

Now when your lisp code runs it should bypass the request for those two variables & complete the function.


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

AGGilliam
Collaborator
Collaborator

@CADaSchtroumpf Thanks for the tip! I think that route might be a bit too complex for what I need but I'll keep that in mind for the future.

 

@paullimapa Thanks for the sample routine! Would the same concept work with a simple getstring or is the dialog box required for it to work? Also, I appreciate the dcl example, I didn't know you could create a dcl on the fly like that.

0 Likes
Message 5 of 11

paullimapa
Mentor
Mentor
Accepted solution

If you want to enter the info on the command line then you don't need my dcl code.

All you need to do is include in your script the responses for what your code will be prompting as shown here:

  ; Part Numbers
  (if (or (= (vl-bb-ref 'OLDPART) nil) (= (vl-bb-ref 'NEWPART) nil))
    (progn
      (vl-bb-set 'OLDPART (getstring nil "Enter the old part number: "))
      (vl-bb-set 'NEWPART (getstring nil "Enter the new part number: "))
    )
  )

So when your script file loads and runs your code then the lines immediately following should answer OLDPART & NEWPART for example:

(load"ReplaceParts")
ReplaceParts
ThisIsOldPartReply
ThatIsNewPartReply

 


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

AGGilliam
Collaborator
Collaborator
I meant for the user to enter it into the command line so my coworkers don't have to mess with the script or LISP routine. As I'm learning more about how the script functions though, I'm beginning to see why that wouldn't be possible. I'll probably use this for now and I might implement your dcl if my coworkers ask for it. Thanks for all of your help!
0 Likes
Message 7 of 11

paullimapa
Mentor
Mentor

glad to have helped...cheers!!!


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

Sea-Haven
Mentor
Mentor

"I didn't know you could create a dcl on the fly like that."

 

A couple of freebies for you. These go a step further usable in any code. Example code at start.

0 Likes
Message 9 of 11

AGGilliam
Collaborator
Collaborator
Thanks for the examples! What does the AH: in front of the function mean? I can't seem to find the right term to get any relevant search results.
0 Likes
Message 10 of 11

Sea-Haven
Mentor
Mentor

Some of us add that as like a signature Lee-mac LM:. Also adds a difference between Chkblk ah:chkblk this would be 2 different functions but with similar naming so one does not overwrite the other, there is always when writing code "What will I call this function". The other important one is C:mydefun the C: implies that you can type it as a command. The AH: examples would be like this on command line (AH:getvalsmulti) calling a predefined lisp function, including brackets.

 

Some of the others maybe *ACDOC* its about working out a name that someone else has not thought of, that is why some posts here have long command names. (defun c:DOMYTHINGNOW ( /.... you can also go the other way (defun c:1 you would type 1 as a command, I have a defun c:47 which sets the osmode to 47 the number is really irrelevant could have called it 4. It was just had various staff wanting other osmodes so a few different numbers. 

 

For say a company maybe every function starts with 3D: the company name. 

0 Likes
Message 11 of 11

AGGilliam
Collaborator
Collaborator
Oh okay, I knew C: had a functional purpose so I assumed that was always the case for letters in front of a colon like that. Thanks for clarifying!
0 Likes