Author Topic: Lisp routine working for some users, not for others  (Read 1676 times)

0 Members and 1 Guest are viewing this topic.

Dan

  • Guest
Lisp routine working for some users, not for others
« on: May 20, 2016, 10:57:21 AM »
I created this program for quickly labelling dados of varying sizes in our drawings. On a few users' machines, this program runs perfectly and does what it's supposed to. There's others for whom the code aborts after putting <Selection set:blahblah> into the message window.

The problem occurs in the section starting on Line 119.

Is there a different way to do what I've got here, or is there some system variable that I can temporarily change to prevent the routine stopping for those users?

Code - Auto/Visual Lisp: [Select]
  1. ;Set defaults
  2. (setq dadwid "3/4")
  3. (setq daddep "1/4")
  4.  
  5. (defun c:dado ()
  6.   (setq echovar (getvar "cmdecho"))
  7.   (setvar 'cmdecho 0)
  8. ;Get origin point for multileader
  9.   (setq orig (getpoint "\nDado - Leader Origin"))
  10.   (setq x (car orig))
  11.   (setq y (cadr orig))
  12. ;Choose one of 8 layouts with real-time preview
  13.   (princ "\nChoose orientation: ")
  14.   (setq loop 1)
  15. ;Update on mouse movement
  16.   (while (and (setq gr (grread T 12 0)) loop)
  17.     (cond
  18.       ((= (car gr) 5) (preview)) ;On movement
  19.       ((= (car gr) 3)
  20.        (setq dest (cadr gr))
  21.        (setq loop nil)
  22.       ) ;On click, store click location, end routine
  23.       (T (redraw) (setq loop nil))
  24.     )
  25.   )
  26. ;Display current default size, offer user option to change it
  27.   (setq dquestion
  28.          (strcat
  29.            "\nEnter New Dado Depth (Leave blank to skip dado size entry) <"
  30.            daddep
  31.            "\"D x "
  32.            dadwid
  33.            "\"W Dado>:"
  34.           )
  35.   )
  36.   (setq danswer (getstring
  37.                   dquestion
  38.                 )
  39.   )
  40. ;Skips both entry options if the user is satisfied with the current values
  41.   (if (/= danswer "")
  42.     (progn
  43.       (setq daddep danswer)
  44.       (setq
  45.         dquestion (strcat
  46.                     "\nEnter New Dado Width or (Enter) to confirm: <"
  47.                     daddep
  48.                     "\"D x "
  49.                     dadwid
  50.                     "\"W Dado>:"
  51.                    )
  52.       )
  53.       (setq danswer2 (getstring
  54.                        dquestion
  55.                      )
  56.       )
  57.       (if (/= danswer2 "")
  58.         (setq dadwid danswer2)
  59.       )
  60.     )
  61.   )
  62. ;Set X multiplier, Y multiplier, angle of rotation based on which hemiquadrant was chosen
  63.   (cond
  64.     ((= ang 1)
  65.      (setq xd 1.0
  66.            yd 1.0
  67.            rd 0.0
  68.      )
  69.     )
  70.     ((= ang 2)
  71.      (setq xd -1.0
  72.            yd 1.0
  73.            rd -90.0
  74.      )
  75.     )
  76.     ((= ang 3)
  77.      (setq xd 1.0
  78.            yd 1.0
  79.            rd 90.0
  80.      )
  81.     )
  82.     ((= ang 4)
  83.      (setq xd -1.0
  84.            yd 1.0
  85.            rd 0.0
  86.      )
  87.     )
  88.     ((= ang 5)
  89.      (setq xd -1.0
  90.            yd -1.0
  91.            rd 0.0
  92.      )
  93.     )
  94.     ((= ang 6)
  95.      (setq xd -1.0
  96.            yd 1.0
  97.            rd 90.0
  98.      )
  99.     )
  100.     ((= ang 7)
  101.      (setq xd 1.0
  102.            yd 1.0
  103.            rd -90.0
  104.      )
  105.      
  106.     )
  107.     ((= ang 8)
  108.      (setq xd 1.0
  109.            yd -1.0
  110.            rd 0.0
  111.      )
  112.     )
  113.   )
  114.   (redraw)
  115. ;
  116. ;
  117. ;
  118. ;THIS SECTION IS WHERE THE GLITCH HAPPENS
  119.   (command "leader"
  120.            orig
  121.            (list (xm 2) (ym 2))
  122.            ""
  123.            (setq leaderset (ssget "_L")) ;Start selection set, grabbing multileader line just created - ERROR OCCURS HERE FOR SOME USERS, NO ERROR FOR OTHERS
  124.            ""
  125.            (strcat daddep "\"D x " dadwid "\"W Dado")
  126.            ""
  127.   )
  128.   (setq leaderset (ssadd (entlast) leaderset)) ;Adds the text to the selection set
  129.   (command "rotate" leaderset "" orig rd) ; If it's a vertical-oriented label, rotates as needed
  130.   (setvar "cmdecho" echovar)
  131.   (princ)
  132. )
  133.  
  134.  
  135. (defun horizontal ()
  136.  
  137.   (grvecs (list -6
  138.                 orig
  139.                 (list (xm 1) (ym 2))
  140.                 (list (xm 1) (ym 2))
  141.                 (list (xm 2) (ym 2))
  142.                 (list (xm 2.5) (ym 1.2))
  143.                 (list (xm 2.5) (ym 2.8))
  144.                 (list (xm 2.5) (ym 2.8))
  145.                 (list (xm 17) (ym 2.8))
  146.                 (list (xm 17) (ym 2.8))
  147.                 (list (xm 17) (ym 1.2))
  148.                 (list (xm 17) (ym 1.2))
  149.                 (list (xm 2.5) (ym 1.2))
  150.           )
  151.   )
  152. )
  153. (defun vertical ()
  154.  
  155.   (grvecs (list -6
  156.                 orig
  157.                 (list (xm 2) (ym 1))
  158.                 (list (xm 2) (ym 1))
  159.                 (list (xm 2) (ym 2))
  160.                 (list (xm 1.2) (ym 2.5))
  161.                 (list (xm 2.8) (ym 2.5))
  162.                 (list (xm 2.8) (ym 2.5))
  163.                 (list (xm 2.8) (ym 17))
  164.                 (list (xm 2.8) (ym 17))
  165.                 (list (xm 1.2) (ym 17))
  166.                 (list (xm 1.2) (ym 17))
  167.                 (list (xm 1.2) (ym 2.5))
  168.           )
  169.   )
  170. )
  171. ;Takes the XD directional multiplier and uses it plus the absolute value given
  172. ;to find the relevant X coordinate.
  173. (defun xm (xm1 /)
  174.   (cond
  175.     ((= xd 1.0) (+ x xm1))
  176.     ((= xd -1.0) (- x xm1))
  177.   )
  178. )
  179. ;Same as XM but for Y axis
  180. (defun ym (ym1 /)
  181.   (cond
  182.     ((= yd 1.0) (+ y ym1))
  183.     ((= yd -1.0) (- y ym1))
  184.   )
  185. )
  186. (defun preview ()
  187.   (setq ppt (list (car (cadr gr)) (cadr (cadr gr))))
  188.   (redraw)
  189.   (setq
  190.     ang (fix
  191.           (+ 1 (* 4 (/ (angle (list (car orig) (cadr orig)) ppt) pi)))
  192.         )
  193.   )
  194. ;Sets variable "Ang" to an integer 1-8 corresponding to the number of the half-quadrant the
  195. ;mouse cursor is currently in relative to the selected startpoint
  196.   (setq
  197.     realang (* 180 (/ (angle (list (car orig) (cadr orig)) ppt) pi))
  198.   )
  199. ;Conditional statements to show the preview above or below the X and Y axis, as well as
  200. ;whether to orient horizontally or vertically
  201.   (cond
  202.     ((= 1 ang)
  203.      (setq xd 1.0
  204.            yd 1.0
  205.      )
  206.  
  207.      (horizontal)
  208.     )
  209.     ((= 2 ang)
  210.      (setq xd 1.0
  211.            yd 1.0
  212.      )
  213.      (vertical)
  214.     )
  215.     ((= 3 ang)
  216.      (setq xd -1.0
  217.            yd 1.0
  218.      )
  219.      (vertical)
  220.     )
  221.     ((= 4 ang)
  222.      (setq xd -1.0
  223.            yd 1.0
  224.      )
  225.      (horizontal)
  226.     )
  227.     ((= 5 ang)
  228.      (setq xd -1.0
  229.            yd -1.0
  230.      )
  231.      (horizontal)
  232.     )
  233.     ((= 6 ang)
  234.      (setq xd -1.0
  235.            yd -1.0
  236.      )
  237.      (vertical)
  238.     )
  239.     ((= 7 ang)
  240.      (setq xd 1.0
  241.            yd -1.0
  242.      )
  243.      (vertical)
  244.     )
  245.     ((= 8 ang)
  246.      (setq xd 1.0
  247.            yd -1.0
  248.      )
  249.      (horizontal)
  250.     )
  251.   )
  252. )
  253.  

hmspe

  • Bull Frog
  • Posts: 362
Re: Lisp routine working for some users, not for others
« Reply #1 on: May 20, 2016, 11:10:01 AM »
Autocad?  What year(s)?  Base or vertical?
"Science is the belief in the ignorance of experts." - Richard Feynman

Dan

  • Guest
Re: Lisp routine working for some users, not for others
« Reply #2 on: May 20, 2016, 11:37:54 AM »
AutoCAD 2014, base.

Matt__W

  • Seagull
  • Posts: 12955
  • I like my water diluted.
Re: Lisp routine working for some users, not for others
« Reply #3 on: May 20, 2016, 11:43:28 AM »
All of your variables are defined globally, meaning they don't lose their value once the program ends, so I would be inclined to think that values of some of the variables are being pulled from other programs that are also using global variables with the same name.

Could you maybe replace SSGET _L with ENTLAST and see what happens?
Autodesk Expert Elite
Revit Subject Matter Expert (SME)
Owner/FAA sUAS Pilot @ http://skyviz.io

ronjonp

  • Needs a day job
  • Posts: 7527
Re: Lisp routine working for some users, not for others
« Reply #4 on: May 20, 2016, 11:48:16 AM »
What M@hem said. Try localizing your variables.
Quote
[CHECKING TEXT <Untitled-2> loading... SELECTION]
.
; === Top statistic:
; Global variables: (DADWID)
.
; === Top statistic:
; Global variables: (DADDEP)
.
; === Top statistic:
; Global variables: (ANG DADDEP DADWID DANSWER DANSWER2 DEST DQUESTION ECHOVAR GR LEADERSET LOOP ORIG RD X XD Y YD)
; Function definition (with number of arguments): ((C:DADO . 0))
.
; === Top statistic:
; Global variables: (ORIG)
; Function definition (with number of arguments): ((HORIZONTAL . 0))
.
; === Top statistic:
; Global variables: (ORIG)
; Function definition (with number of arguments): ((VERTICAL . 0))
.
; === Top statistic:
; Global variables: (X XD)
; Function definition (with number of arguments): ((XM . 1))
.
; === Top statistic:
; Global variables: (Y YD)
; Function definition (with number of arguments): ((YM . 1))
.
; === Top statistic:
; Global variables: (ANG GR ORIG PPT REALANG XD YD)
; Function definition (with number of arguments): ((PREVIEW . 0))
; Check done.

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

Dan

  • Guest
Re: Lisp routine working for some users, not for others
« Reply #5 on: May 20, 2016, 02:21:42 PM »
Tried switching to entlast, tried localizing variables, nothing has worked. I tried a few experiments, and finally figured it out. It seems having the LISP selection in the middle of the multileader command is what's causing the issues - and only for some people.

To work around it, this is the code that was used instead:

Code - Auto/Visual Lisp: [Select]
  1. (setq prioritem (entlast))
  2.     (command "leader"
  3.            orig
  4.            (list (xm 2) (ym 2))
  5.            "a"
  6.            ""
  7.            "m"
  8.            (strcat daddep "\"D x " dadwid "\"W Dado")
  9.            ""
  10.   )
  11.   (setq leaderset (ssadd))
  12.   (setq leaderset (ssadd (entlast) leaderset))
  13.   (setq leaderset (ssadd (entnext prioritem) leaderset))
  14.   (command "rotate" leaderset "" orig rd)
  15.  

Thank you all for your help! Without having your suggestions as starting points, I probably would not have figured this out.

ChrisCarlson

  • Guest
Re: Lisp routine working for some users, not for others
« Reply #6 on: May 23, 2016, 09:34:39 AM »
Definitely good practice localize all of your variables and specifically globalize variables with asterisks ex; *var*.

Sounds like there is an issue with SSGET getting the last entity. Looking at your routine really quick I do not see an entity created before line 119?

Refernce lee-mac's website on the SSGET function, specifically "L".
Quote
Selects the last visible object added to the drawing database.

Caution: when using the "L" selection method in an MDI environment, you cannot always count on the last object drawn to remain visible. For example, if your application draws a line, and the user subsequently minimizes or cascades the AutoCAD drawing window, the line may no longer be visible. If this occurs, ssget with the "L" option will return nil.

http://www.lee-mac.com/ssget.html

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Lisp routine working for some users, not for others
« Reply #7 on: May 23, 2016, 10:26:48 AM »
I would take a different approach. Use these functions: Call one before the command & the other after the command.
Code: [Select]
  ;; Rune Wold and Michael Puckett - modified ale_lastent ale_ss-after
  (defun ale_lastent (/ entnam outval)
    (and
      (setq outval (entlast))
      (while (setq entnam (entnext outval))
        (setq outval entnam)
      )
    )
    outval
  )

  (defun ale_ss-after (entnam / entnxt selset)
    (cond
      ((not entnam) (ssget "_X"))
      ((setq entnxt (entnext entnam))
       (setq selset (ssadd entnxt))
       (while (setq entnxt (entnext entnxt))
         (if (entget entnxt)
           (ssadd entnxt selset)
         )
       )
       selset
      )
    )

This will get the leader & text objects.
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Dan

  • Guest
Re: Lisp routine working for some users, not for others
« Reply #8 on: May 23, 2016, 04:52:56 PM »
Chris - I stopped using SSGet entirely. I wound up changing it to store the last entity drawn before creating the leader, then after the leader and text item are created, create an empty selection set, add the Entnext from that stored item (The leader) and then add the EntLast (the text attached to the leader). Not very versatile but it does what I need it to.

CAB - I'm not good enough at this point to be able to look through that code and see clearly what it does. I know this is a "stupid newbie" kind of question, but could you explain what those two functions are doing?

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: Lisp routine working for some users, not for others
« Reply #9 on: May 23, 2016, 05:09:09 PM »
The first returns the very last entity in the drawing, the second returns a selection set of every entity after the one you supply as an argument.
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

Marc'Antonio Alessi

  • Swamp Rat
  • Posts: 1451
  • Marco
Re: Lisp routine working for some users, not for others
« Reply #10 on: May 24, 2016, 03:18:38 AM »
Full history (?) and description:
Code: [Select]
; Function: ALE_LastEnt - original by Rune Wold and Michael Puckett (lastent) 
;
; Version 1.01 - 20/12/2004 - modified with (and ...)
;
; Description:
;   get the absolute last entity in the database,
;   for problems in >=r15 in blocks with attrib, and polylines
;
; Arguments: none
;
; Return Values:
;   An entity name;
;   otherwise nil, if there are no entities in the current drawing
;
; Example: (setq marker (ALE_LastEnt)) see ALE_Ss-After
;
(defun ALE_LastEnt ( / EntNam OutVal)
  (and
    (setq OutVal (entlast))
    (while (setq EntNam (entnext OutVal))
      (setq OutVal EntNam)
    )
  )
  OutVal
)
;
; Marc'Antonio Alessi
; Function: ALE_Ss-After thanks to Michael Puckett (Ss-After)
;
; Version 1.01 - 20/12/2004 for empty DWG
; Version 1.02 - 30/09/2005
; Version 1.03 - 06/05/2010 to support Bricscad
;
; Description:
;   get a selection set of items after EntNam in the database
;
; Arguments: An entity name
;
; Return Values:
;   A selection set;
;   otherwise nil, if there are no entities after EntNam
;
; Examples:
;   (setq marker (ALE_LASTENT)) ...create new entities...
;   to include reference entity:
;   (command "_.MOVE" (ALE_SS-AFTER marker) marker "" ...)
;   Note: NOT valid if marker is a SEQEND of
;   blocks with attrib or old polylines (PLINETYPE = 0)
;
;   not include reference entity:
;   (command "_.MOVE" (ALE_SS-AFTER marker) "" ...)
;
(defun ALE_Ss-After (EntNam / SelSet)
  (cond
    ( (not EntNam) (ssget "_X" '((0 . "~VIEWPORT"))) ); "~VIEWPORT" x Bricscad
    ( (setq EntNam (entnext EntNam))
      (setq SelSet (ssadd EntNam))
      (while (setq EntNam (entnext EntNam))
        (if (entget EntNam) (ssadd EntNam SelSet))
      )
      SelSet
    )
  )
)

Dan

  • Guest
Re: Lisp routine working for some users, not for others
« Reply #11 on: May 24, 2016, 08:11:24 AM »
Ah, that's definitely more versatile and elegant than what I wound up slapping in there - thank you very much!

ChrisCarlson

  • Guest
Re: Lisp routine working for some users, not for others
« Reply #12 on: May 24, 2016, 08:17:11 AM »
Can I ask what the workflow is? Relying on the last entity in a drawing created outside of a routine can be problematic. Perhaps the creation of that entity and this routine can be consolidated?

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Lisp routine working for some users, not for others
« Reply #13 on: May 24, 2016, 09:44:23 AM »
substitute this:
Code: [Select]
;THIS SECTION IS WHERE THE GLITCH HAPPENS
  (command "leader"
       orig
       (list (xm 2) (ym 2))
       ""
       (setq leaderset (ssget "_L")) ;Start selection set, grabbing multileader line just created - ERROR OCCURS HERE FOR SOME USERS, NO ERROR FOR OTHERS
       ""
       (strcat daddep "\"D x " dadwid "\"W Dado")
       ""
  )
  (setq leaderset (ssadd (entlast) leaderset)) ;Adds the text to the selection set
 

with this:


Code: [Select]
; Function: ALE_LastEnt - original by Rune Wold and Michael Puckett (lastent)
;
; Version 1.01 - 20/12/2004 - modified with (and ...)
;
; Description:
;   get the absolute last entity in the database,
;   for problems in >=r15 in blocks with attrib, and polylines
;
; Arguments: none
;
; Return Values:
;   An entity name;
;   otherwise nil, if there are no entities in the current drawing
;
; Example: (setq marker (ALE_LastEnt)) see ALE_Ss-After
;
(defun ALE_LastEnt ( / EntNam OutVal)
  (and
    (setq OutVal (entlast))
    (while (setq EntNam (entnext OutVal))
      (setq OutVal EntNam)
    )
  )
  OutVal
)
;
; Marc'Antonio Alessi
; Function: ALE_Ss-After thanks to Michael Puckett (Ss-After)
;
; Version 1.01 - 20/12/2004 for empty DWG
; Version 1.02 - 30/09/2005
; Version 1.03 - 06/05/2010 to support Bricscad
;
; Description:
;   get a selection set of items after EntNam in the database
;
; Arguments: An entity name
;
; Return Values:
;   A selection set;
;   otherwise nil, if there are no entities after EntNam
;
; Examples:
;   (setq marker (ALE_LASTENT)) ...create new entities...
;   to include reference entity:
;   (command "_.MOVE" (ALE_SS-AFTER marker) marker "" ...)
;   Note: NOT valid if marker is a SEQEND of
;   blocks with attrib or old polylines (PLINETYPE = 0)
;
;   not include reference entity:
;   (command "_.MOVE" (ALE_SS-AFTER marker) "" ...)
;
(defun ALE_Ss-After (EntNam / SelSet)
  (cond
    ( (not EntNam) (ssget "_X" '((0 . "~VIEWPORT"))) ); "~VIEWPORT" x Bricscad
    ( (setq EntNam (entnext EntNam))
      (setq SelSet (ssadd EntNam))
      (while (setq EntNam (entnext EntNam))
        (if (entget EntNam) (ssadd EntNam SelSet))
      )
      SelSet
    )
  )
)

(setq entlast (ALE_LastEnt))
;THIS SECTION IS WHERE THE GLITCH HAPPENS
  (command "leader"
       orig
       (list (xm 2) (ym 2))
       ""
       ""
       (strcat daddep "\"D x " dadwid "\"W Dado")
       ""
  )

  (setq lst (mapcar 'cadr (ssnamex (ALE_Ss-After lastent))))
  (setq ent (vl-remove-if-not '(lambda(e) (equal (assoc 0 (entget e)) '(0 . "LEADER"))) lst))
  (setq leaderset (ssadd ent leaderset)) ;Adds the text to the selection set

Note that I did not test the COMMAND leader function so it may need adjustment. 8)
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Dan

  • Guest
Re: Lisp routine working for some users, not for others
« Reply #14 on: May 24, 2016, 04:57:50 PM »
Chris - this is for annotating shop drawings. We're a store fixture shop, and almost all of our construction uses dados of varying depths. I'm the CNC programmer, and usually the last stop before drawings go out to the shop, as well as doing drafting myself when needed. I wanted to be able to annotate my dados quickly and neatly without having to either make a bunch of macros or stop and adjust the position of each leader. Rather than relying on a standard macro and then going back and editing, this lets me simply run this lisp and generate an annotation in the orientation needed with a couple of mouse clicks, and allows for adjusting the width and depth with a minimal number of keystrokes.

It's one of a series of simple routines I've written that save time on repetitive tasks, and it is doubtlessly the most complicated one I've written. I'm certainly not going to pretend it's anything professional level, but thanks to the help of everyone on here, it now does the job it is needed to do, and will work for all members of the engineering department.