Author Topic: bad argument issue with fields and viewports  (Read 7752 times)

0 Members and 1 Guest are viewing this topic.

ronjonp

  • Needs a day job
  • Posts: 7528
Re: bad argument issue with fields and viewports
« Reply #15 on: January 15, 2014, 09:15:23 AM »
My only question that I've noticed when seeing this use of mapcar is where are the users original settings stored? If the program is modifying attreq to do it's duty, shouldn't attreq be put back to what it's value was before the program was initiated ? ...


Here is a simple example to show how the variables are reset in Lee's code:

Code: [Select]
(defun c:foo (/ *error* p val var)
  ;; Error function to account for program sh!++ing the bed .. LOCALIZE IT! ^^
  (defun *error* (msg)
    ;; Reset the variables
    (mapcar 'setvar var val)
    (if (not (wcmatch (strcase msg t) "*break,*cancel*,*exit*"))
      (princ (strcat "\nError: " msg))
    )
    (princ)
  )
  ;; Get variables current settings
  (setq var '(cmdecho insunits attreq)
val (mapcar 'getvar var)
  )
  ;; Change them to what you want
  (mapcar 'setvar var '(0 0 1))
  ;; Do your stuff
  (setq p (getpoint))
  ;; Reset the variables
  (mapcar 'setvar var val)
)

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

tntdraftsol

  • Guest
Re: bad argument issue with fields and viewports
« Reply #16 on: January 16, 2014, 09:43:04 AM »
Sorry, I should have explained more clearly:
Since the suggested ssget expression will return a selection set, you would need to replace:
Code: [Select]
(setq vpent (_selvp (car (nentsel "\nselect viewport"))))With:
Code: [Select]
(setq vpent (ssname (ssget "_+.:E:S" '((0 . "VIEWPORT"))) 0))However, note that this does not include error trapping to allow for the user failing to select a Viewport, for which the program will currently error.

Where error trapping is concerned, I would suggest the following for your code:
Code: [Select]
;; Example program written for Swamp thread:
;; http://www.theswamp.org/index.php?topic=45993.0
;; by Lee Mac 2014-01-14

(defun c:tlmk ( / *error* blk dch dcl dwg mark_n sel title_n val var )

    (setq dwg "N:/Tuterj/AutoLISP/Working/TitleMark-field.dwg" ;; Block to insert
          dcl "N:/tuterj/AutoLISP/Working/TL-MK_Scale_add.dcl" ;; DCL file
    )

    (defun *error* ( msg )
        (mapcar 'setvar var val)
        (if (< 0 dch) (unload_dialog dch))
        (if (not (wcmatch (strcase msg t) "*break,*cancel*,*exit*"))
            (princ (strcat "\nError: " msg))
        )
        (princ)
    )
   
    (cond
        (   (not
                (or (tblsearch "block" (setq blk (vl-filename-base dwg)))
                    (setq blk (findfile dwg))
                )
            )
            (princ (strcat "\n" dwg " file not found."))
        )
        (   (<= (setq dch (load_dialog dcl)) 0)
            (princ (strcat "\n" dcl " file not found."))
        )
        (   (not (new_dialog "TLMK" dch))
            (princ (strcat "\n" dcl " file contains an error, dialog could not be loaded."))
        )
        (   t
            (action_tile "mark_n"  "(setq mark_n  $value)")
            (action_tile "title_n" "(setq title_n $value)")
            (action_tile "accept"
                (vl-prin1-to-string
                   '(cond
                        (   (null mark_n)
                            (alert "Please enter a value for the mark_n tile.")
                            (mode_tile "mark_n" 2)
                        )
                        (   (null title_n)
                            (alert "Please enter a value for the title_n tile.")
                            (mode_tile "title_n" 2)
                        )
                        (   (done_dialog 1))
                    )
                )
            )
            (if (= 1 (start_dialog))
                (if (setq sel (LM:ssget "\nSelect viewport: " '("_+.:E:S" ((0 . "VIEWPORT")))))
                    (progn
                        (setq var '(cmdecho insunits attreq)
                              val  (mapcar 'getvar var)
                        )
                        (mapcar 'setvar var '(0 0 1))
                        (princ "\nSpecify insertion point for block: ")
                        (vl-cmdf "_.-insert" blk "_S" 1.0 "_R" 0.0 "\\"
                            (strcase title_n)
                            (strcat
                                "%<\\AcObjProp.16.2 Object(%<\\_ObjId "
                                (LM:objectid (vlax-ename->vla-object (ssname sel 0)))
                                ">%).CustomScale \\f \"%sn\">%"
                            )
                            mark_n
                        )
                        (mapcar 'setvar var val)
                    )
                )
                (princ "\n*Cancel*")
            )
        )
    )
    (if (< 0 dch) (setq dch (unload_dialog dch)))
    (princ)
)

;; ssget  -  Lee Mac
;; A wrapper for the ssget function to permit the use of a custom selection prompt
;; msg - [str] selection prompt
;; arg - [lst] list of ssget arguments

(defun LM:ssget ( msg arg / sel )
    (princ msg)
    (setvar 'nomutt 1)
    (setq sel (vl-catch-all-apply 'ssget arg))
    (setvar 'nomutt 0)
    (if (not (vl-catch-all-error-p sel)) sel)
)

;; ObjectID  -  Lee Mac
;; Returns a string containing the ObjectID of a supplied VLA-Object
;; Compatible with 32-bit & 64-bit systems

(defun LM:objectid ( obj )
    (eval
        (list 'defun 'LM:objectid '( obj )
            (if
                (and
                    (wcmatch (getenv "PROCESSOR_ARCHITECTURE") "*64*")
                    (vlax-method-applicable-p (vla-get-utility (LM:acdoc)) 'getobjectidstring)
                )
                (list 'vla-getobjectidstring (vla-get-utility (LM:acdoc)) 'obj ':vlax-false)
               '(itoa (vla-get-objectid obj))
            )
        )
    )
    (LM:objectid obj)
)

;; Active Document  -  Lee Mac
;; Returns the VLA Active Document Object

(defun LM:acdoc nil
    (eval (list 'defun 'LM:acdoc 'nil (vla-get-activedocument (vlax-get-acad-object))))
    (LM:acdoc)
)
(vl-load-com) (princ)

Please note that the above code is written in haste & completely untested!

Please refer to this reference from my site  :-)

Lee Mac, Thank you!  except for the error trapping the routine is working perfectly.  Thank you also for the error trapping suggestions, that is quite a bit for me to study over to make sure I understand what you have written.  Besides the error trapping, my CAD manager has one more thing he wants me to add to the routine.  This block that is being inserted is a titlemark block that numbers and identifies the details on each of our sheets, so there could be any number of titlemarks on a sheet depending on how many views and details we can fit.  His request was to have the mark number fill in with a sequential number each time the routine is ran so the user could just fill in the title, but still have the option to put whatever number they want in that spot.  I came up with a counter with a while loop,

Code: [Select]
(setq count 1)                              ;variable set up for counter to populate mark_n box in dialog box
  (while (< count 99)           
    (setq count (1+ count))
   );(while

but what I'm having trouble with is taking that value from the main fucntion to the dcl file.  I thought set_tile would work, but no joy.  a thought that occured to me though was can I send input to the dialog box if that particular part of the dialog box is an edit_box? 

Code: [Select]
: edit_box {               //Edit box for the Title Mark number.
  label = "Mark:";
  alignment = left;
  key = "mark_n";
  fixed_width = true;
  edit_limit = 2;
  edit_width = 2; 
 
  }//:edit_box { 

I still want the user to have the ability to edit that box when the dialog is up, but just have it intially populated with the information from the counter back in the main fucntion.  Anyway thank you again for your time and help.  I greatly appriciate it.  I owe you a couple of pints!

Lee Mac

  • Seagull
  • Posts: 12913
  • London, England
Re: bad argument issue with fields and viewports
« Reply #17 on: January 16, 2014, 04:47:01 PM »
These lines of code do a magnificent job of explaining mapcar....(place glowing light bulb here)

Excellent to hear Bruce!  :-)

It just goes to show - after all the extensive explanations on the topic of mapcar, it just takes a simple few lines of code for it to click.

My only question that I've noticed when seeing this use of mapcar is where are the users original settings stored?

You've actually answered this yourself in your dissection of the code  :wink:
Code: [Select]
(setq val (mapcar 'getvar var)) ;set a variable 'val' which holds the values when mapcar applies the "getvar" command to each item in the 'var' list
As you can see, the original values for each system variable are stored in the list 'val' (for VALues).

If the program is modifying attreq to do it's duty, shouldn't attreq be put back to what it's value was before the program was initiated ? j/w, typically heard this is good coding practice and perhaps just a quick and dirty routine was given, still- trying to be clear on the topic!

Indeed! - All programs should return the user's AutoCAD environment to exactly how they found it, resetting any modified system variables to their original values.

My posted example resets these values on line 69, and also in the error handler on line 12 (in case the program encounters an error after the system variables have been modified, but not yet reset).

So let me be clear myself! I'm not asking this to point out any inadequacies in the given code as any code given is a gem and should be respected, ie. not everyone can do it, it's time consuming, and it's very useful for the person intended for. That's a heck of a combination. I did, however, ask because i'm genuinely wondering if there's a mapcar method to save the sys vars beforehand, or is it handled in another fashion when this setup is used.....or...? Thanks! that's why i'm asking.

Certainly - don't worry about raising these questions!

I appreciate the flattering compliments, but I am the first to admit that I am certainly not infallible and will make mistakes from time to time. If you believe you have found a mistake in my code, or feel there is a better way to tackle a problem, I welcome you to post your questions & constructive criticism!

Then, if the reported issue is already addressed by the code (as in this case), I will usually offer an explanation as to why the issue is already covered by the code, thus aiding the understanding of the person raising the issue and of the community as a whole; and, if the issue needs to be addressed, the code will be improved as a result, and I may also learn something new.

It's a win-win!

Here is a simple example to show how the variables are reset in Lee's code:

Many thanks Ron for providing an explanation & covering whilst I was preoccupied - I've been incredibly busy these past few weeks and just haven't been able to check-in here as often as I used to.

Lee Mac, Thank you!  except for the error trapping the routine is working perfectly.  Thank you also for the error trapping suggestions, that is quite a bit for me to study over to make sure I understand what you have written.

You're welcome! - Take as long as you need to study the code I have posted, and I will be happy to answer any questions about its operation as my time permits.  :-)

Besides the error trapping, my CAD manager has one more thing he wants me to add to the routine. His request was to have the mark number fill in with a sequential number each time the routine is ran

Yes - this is indeed possible - consider the following code (again entirely untested!):

Code - Auto/Visual Lisp: [Select]
  1. ;; Example program written for Swamp thread:
  2. ;; http://www.theswamp.org/index.php?topic=45993.0
  3. ;; by Lee Mac 2014-01-16
  4.  
  5. (defun c:tlmk ( / *error* blk dch dcl dwg mark_n sel title_n val var )
  6.  
  7.     (setq dwg "N:/Tuterj/AutoLISP/Working/TitleMark-field.dwg" ;; Block to insert
  8.           dcl "N:/tuterj/AutoLISP/Working/TL-MK_Scale_add.dcl" ;; DCL file
  9.     )
  10.  
  11.     (defun *error* ( msg )
  12.         (mapcar 'setvar var val)
  13.         (if (< 0 dch) (unload_dialog dch))
  14.         (if (not (wcmatch (strcase msg t) "*break,*cancel*,*exit*"))
  15.             (princ (strcat "\nError: " msg))
  16.         )
  17.         (princ)
  18.     )
  19.  
  20.     (if (/= 'int (type tlmk:num))
  21.         (setq tlmk:num 1)
  22.         (setq tlmk:num (1+ tlmk:num))
  23.     )
  24.     (cond
  25.         (   (not
  26.                 (or (tblsearch "block" (setq blk (vl-filename-base dwg)))
  27.                     (setq blk (findfile dwg))
  28.                 )
  29.             )
  30.             (princ (strcat "\n" dwg " file not found."))
  31.         )
  32.         (   (<= (setq dch (load_dialog dcl)) 0)
  33.             (princ (strcat "\n" dcl " file not found."))
  34.         )
  35.         (   (not (new_dialog "TLMK" dch))
  36.             (princ (strcat "\n" dcl " file contains an error, dialog could not be loaded."))
  37.         )
  38.         (   t
  39.             (set_tile    "mark_n"  "(setq mark_n (itoa tlmk:num))")
  40.             (action_tile "mark_n"  "(setq mark_n  $value)")
  41.             (action_tile "title_n" "(setq title_n $value)")
  42.             (action_tile "accept"
  43.                 (vl-prin1-to-string
  44.                    '(cond
  45.                         (   (null mark_n)
  46.                             (alert "Please enter a value for the mark_n tile.")
  47.                             (mode_tile "mark_n" 2)
  48.                         )
  49.                         (   (null title_n)
  50.                             (alert "Please enter a value for the title_n tile.")
  51.                             (mode_tile "title_n" 2)
  52.                         )
  53.                         (   (done_dialog 1))
  54.                     )
  55.                 )
  56.             )
  57.             (if (= 1 (start_dialog))
  58.                 (if (setq sel (LM:ssget "\nSelect viewport: " '("_+.:E:S" ((0 . "VIEWPORT")))))
  59.                     (progn
  60.                         (setq var '(cmdecho insunits attreq)
  61.                               val  (mapcar 'getvar var)
  62.                         )
  63.                         (mapcar 'setvar var '(0 0 1))
  64.                         (princ "\nSpecify insertion point for block: ")
  65.                         (vl-cmdf "_.-insert" blk "_S" 1.0 "_R" 0.0 "\\"
  66.                             (strcase title_n)
  67.                             (strcat
  68.                                 "%<\\AcObjProp.16.2 Object(%<\\_ObjId "
  69.                                 (LM:objectid (vlax-ename->vla-object (ssname sel 0)))
  70.                                 ">%).CustomScale \\f \"%sn\">%"
  71.                             )
  72.                             mark_n
  73.                         )
  74.                         (setq tlmk:num (atoi mark_n))
  75.                         (mapcar 'setvar var val)
  76.                     )
  77.                 )
  78.                 (princ "\n*Cancel*")
  79.             )
  80.         )
  81.     )
  82.     (if (< 0 dch) (setq dch (unload_dialog dch)))
  83.     (princ)
  84. )
  85.  
  86. ;; ssget  -  Lee Mac
  87. ;; A wrapper for the ssget function to permit the use of a custom selection prompt
  88. ;; msg - [str] selection prompt
  89. ;; arg - [lst] list of ssget arguments
  90.  
  91. (defun LM:ssget ( msg arg / sel )
  92.     (princ msg)
  93.     (setvar 'nomutt 1)
  94.     (setq sel (vl-catch-all-apply 'ssget arg))
  95.     (setvar 'nomutt 0)
  96.     (if (not (vl-catch-all-error-p sel)) sel)
  97. )
  98.  
  99. ;; ObjectID  -  Lee Mac
  100. ;; Returns a string containing the ObjectID of a supplied VLA-Object
  101. ;; Compatible with 32-bit & 64-bit systems
  102.  
  103. (defun LM:objectid ( obj )
  104.     (eval
  105.         (list 'defun 'LM:objectid '( obj )
  106.             (if
  107.                 (and
  108.                     (wcmatch (getenv "PROCESSOR_ARCHITECTURE") "*64*")
  109.                     (vlax-method-applicable-p (vla-get-utility (LM:acdoc)) 'getobjectidstring)
  110.                 )
  111.                 (list 'vla-getobjectidstring (vla-get-utility (LM:acdoc)) 'obj ':vlax-false)
  112.                '(itoa (vla-get-objectid obj))
  113.             )
  114.         )
  115.     )
  116.     (LM:objectid obj)
  117. )
  118.  
  119. ;; Active Document  -  Lee Mac
  120. ;; Returns the VLA Active Document Object
  121.  
  122. (defun LM:acdoc nil
  123.     (LM:acdoc)
  124. )

Anyway thank you again for your time and help.  I greatly appriciate it.  I owe you a couple of pints!

You're welcome - I'm happy to offer my assistance :-)

Lee