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

0 Members and 1 Guest are viewing this topic.

tntdraftsol

  • Guest
bad argument issue with fields and viewports
« on: January 09, 2014, 04:06:01 PM »
Greetings All!

I have hit a wall with the program I am working on.  I wrote a routine that would take information from the user via a dialog box and use that information to populate our companies titlemark with a mark number, title, and scale.  I wanted to add some additional functionality regarding the scale; instead of the user typing in the scale in the dialog box I planned to thave them pick the viewport the titilemark would be associated with, and using a field populate the scale that way.  I have attached an image of the desired result.

Here is the code I am using, I think my problem is with the portion in red:

Code: [Select]
(defun C:TLMK ( / TLMK_LEN PT1)
  (setvar "CMDECHO" 0)
  (setq tempunits (getvar "insunits"))
;======================================================================================================================================== LOADS DIALOG BOX
(defun TLMK(/ DCL_ID)
 (setq DCL_ID (load_dialog "n:/tuterj/AutoLISP/Working/TL-MK_Scale_add.DCL"))
 (if (not (new_dialog "TLMK" DCL_ID)) (exit))

 (setq mark_n nil)
 (setq title_n nil)
 
 (action_tile "cancel" "(done_dialog) (exit)")
 (action_tile "mark_n" "(setq mark_n $value)")
 (action_tile "title_n" "(setq title_n $value)")
   
 (start_dialog)
 (unload_dialog DCL_ID)
 (princ)
) ;defun TLMK
 (TLMK)

;======================================================================================================================================== End of Dialog BOx
[color=red](vl-load-com)
 
(setq vpent (car (nentsel "\nselect viewport")))   ;user selects viewport and viewport id is stored under vpent

(vlax-ename->vla-object vpent)    ;vpent is transformed from an entity to a VLA object

(setq scale_fld (strcat "%<\AcObjProp.16.2 Object(%<\_ObjId "(vl-princ-to-string(vla-get-Objectid vpent))">%).CustomScale \f\"%sn\">%"))  ;assigns field expression to variable.[/color] 
 
(setq PT1 (getpoint "\nselect insertion point: "))
(setvar "ATTDIA" 0)

(setq title_u (strcase title_n))   ;declaring additional variable to change case for title_n

(setvar "insunits" 0)  ;setting insertion units to unitless for proper scale of inserted block
 
(command "insert" "N:/Tuterj/AutoLISP/Working/TitleMark-field.dwg" PT1 "" "" title_u scale_fld mark_n)  ;inserting the contents of TitleMark drawing and inserting user input from dialog box.


(setvar "ATTDIA" 1)
(setvar "CMDECHO" 1)
(setvar "insunits" tempunits)

) ;defun C:TLMK 

I have also attached an image of the error I am getting when I run through the program.  I would appriciate any advice and thank you all in advance for your help.  Thanks for reading.

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
Re: bad argument issue with fields and viewports
« Reply #1 on: January 09, 2014, 04:49:21 PM »
You have:
Code: [Select]
(vlax-ename->vla-object vpent)And this should be:
Code: [Select]
(setq vpent (vlax-ename->vla-object vpent))
You should also be aware that a non-rectangular viewport will have a polyline 'attached' to it.
The user may select that polyline instead of the viewport.

tntdraftsol

  • Guest
Re: bad argument issue with fields and viewports
« Reply #2 on: January 10, 2014, 09:48:38 AM »
Thanks Roy!

I did as you suggested and I am now getting the block to insert with the scale having a field, BUT instead of the scale as I was expecting I am getting "####" (see attached).  I took a look at the field expression for the viewport scale with my routine and compared it with a field expression for the same viewport, but not with my routine and I found that the object IDs' DO NOT match (see attached).  Also the field expression from my routine doesn't even register as an object, it says unknown.  I am confused as to why they would not match for the same rectangular viewport.  would the fact that I am transforming the entity into a VLA ojbect change the ID?  I am closer, but not quite there yet.  Again thank you for the help and if you have any other advice I will gladly take it.  I will also be sure to include polygonal viewports in my testing for this program, so thanks for the heads up.

here is the portion of code I revised:

Code: [Select]
(setq vpent (car (nentsel "\nselect viewport")))   ;user selects viewport and viewport id is stored under vpent

(setq vpent (vlax-ename->vla-object vpent))    ;vpent is transformed from an entity to a VLA object

(setq scale_fld (strcat "%<\\AcObjProp.16.2 Object(%<\\_ObjId "(vl-princ-to-string(vla-get-Objectid vpent))">%).CustomScale \\f \"%sn\">%"))  ;assigns field expression to variable.
   

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
Re: bad argument issue with fields and viewports
« Reply #3 on: January 10, 2014, 10:20:25 AM »
I am a BricsCAD user and BricsCAD does not (yet) support the creation of fields using string values. Maybe somebody else can help you here.

kruuger

  • Swamp Rat
  • Posts: 633
Re: bad argument issue with fields and viewports
« Reply #4 on: January 10, 2014, 01:16:27 PM »
is you r system 64bit ?
try to get id this way:
Code: [Select]
;; 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
                    (vl-string-search "64" (getenv "PROCESSOR_ARCHITECTURE"))
                    (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)
)
k.

Lee Mac

  • Seagull
  • Posts: 12912
  • London, England
Re: bad argument issue with fields and viewports
« Reply #5 on: January 10, 2014, 01:40:31 PM »
Thanks for the recommendation kruuger  :-)

The OP will also need (LM:acdoc):
Code - Auto/Visual Lisp: [Select]
  1. ;; ObjectID  -  Lee Mac
  2. ;; Returns a string containing the ObjectID of a supplied VLA-Object
  3. ;; Compatible with 32-bit & 64-bit systems
  4.  
  5. (defun LM:objectid ( obj )
  6.     (eval
  7.         (list 'defun 'LM:objectid '( obj )
  8.             (if
  9.                 (and
  10.                     (wcmatch (getenv "PROCESSOR_ARCHITECTURE") "*64*")
  11.                     (vlax-method-applicable-p (vla-get-utility (LM:acdoc)) 'getobjectidstring)
  12.                 )
  13.                 (list 'vla-getobjectidstring (vla-get-utility (LM:acdoc)) 'obj ':vlax-false)
  14.                '(itoa (vla-get-objectid obj))
  15.             )
  16.         )
  17.     )
  18.     (LM:objectid obj)
  19. )
  20.  
  21. ;; Active Document  -  Lee Mac
  22. ;; Returns the VLA Active Document Object
  23.  
  24. (defun LM:acdoc nil
  25.     (LM:acdoc)
  26. )

tntdraftsol

  • Guest
Re: bad argument issue with fields and viewports
« Reply #6 on: January 10, 2014, 03:05:25 PM »
Lee Mac & Kruuger thank you for your replies!

I ended up using something similar to what you two suggested.  We are on a 64 bit system here.  I got this from AUGI via Tharwat, with the function by Gile

Code: [Select]
(defun gc:GetObjectIdString (obj)    ;By Gile via Tharwat from AUGI
  (or *util*
      (setq *util* (vla-get-Utility (vla-get-activedocument (vlax-get-acad-object))
     );vla-get-utility
);setq *util*
   );or *util*
  (if (vlax-method-applicable-p *util* 'GetObjectIdString)
    (vla-GetObjectIdString *util* obj :vlax-false)
    (itoa (vla-get-ObjectId obj))
   );if
);defun gc:GetObjectIdString
 

(setq scale_fld (strcat "%<\\AcObjProp.16.2 Object(%<\\_ObjId "(gc:GetObjectIdString vpent)">%).CustomScale \\f \"%sn\">%"))  ;assigns field expression to variable.
   

with this function I got the block to insert properly and display the scale as a field.  The only problem I have left is, as Roy said in a previous post, that if you have a polygonal viewport the polyline is on top, so the user selects the polyline instead of the viewport.  This can be avoided either by having the user change the rectangular viewport to polygonal after the titlemark has been inserted, or as they are going through the routine have them hover over the polygonal viewport and before they select it hit the spacebar to have the selection be the viewport instead of the polyline.

Again thank you both for your help.

ronjonp

  • Needs a day job
  • Posts: 7527
Re: bad argument issue with fields and viewports
« Reply #7 on: January 10, 2014, 03:41:29 PM »
This should help with non rectangular viewport selection:
Code: [Select]
(defun _selvp (ename)
  (if (= (type ename) 'ename)
    (cond ((= "VIEWPORT" (cdr (assoc 0 (entget ename)))) ename)
  ((and (setq ename (cdr (assoc 330 (entget ename))))
(= "VIEWPORT" (cdr (assoc 0 (entget ename))))
   )
   ename
  )
    )
  )
)
(_selvp (car (entsel)))

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

Lee Mac

  • Seagull
  • Posts: 12912
  • London, England
Re: bad argument issue with fields and viewports
« Reply #8 on: January 10, 2014, 07:23:55 PM »
Or just:
Code: [Select]
(ssget "_+.:E:S" '((0 . "VIEWPORT")))

ronjonp

  • Needs a day job
  • Posts: 7527
Re: bad argument issue with fields and viewports
« Reply #9 on: January 10, 2014, 09:31:22 PM »
Or just:
Code: [Select]
(ssget "_+.:E:S" '((0 . "VIEWPORT")))
Leave it to me to over think. .. That's why you get paid the big bux.  :-D

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

tntdraftsol

  • Guest
Re: bad argument issue with fields and viewports
« Reply #10 on: January 13, 2014, 12:51:16 PM »
This should help with non rectangular viewport selection:
Code: [Select]
(defun _selvp (ename)
  (if (= (type ename) 'ename)
    (cond ((= "VIEWPORT" (cdr (assoc 0 (entget ename)))) ename)
  ((and (setq ename (cdr (assoc 330 (entget ename))))
(= "VIEWPORT" (cdr (assoc 0 (entget ename))))
   )
   ename
  )
    )
  )
)
(_selvp (car (entsel)))

RonJonp, thank you for your reply and your suggestion.  That function worked perfectly! I must admit, I am trying to follow along with what you did there, but am coming up short.  If you would be willing to explain what the function is doing at each step that would go a long ways to helping me understand.

Or just:
Code: [Select]
(ssget "_+.:E:S" '((0 . "VIEWPORT")))

Lee Mac, thank you as well for your reply!  I tried inserting this into my routine and it did not work, but I believe it is because I did not insert this piece of code in the correct spot.  Where should I have put this code in the overall structure of my program?  Again thank you for your time and expertise.  :-)

and as of now here is my entire routine with everyone's suggestions.  I have tested it several times with differently shaped viewports and in differnt drawings with different units and it has performed great!

Code: [Select]
;File Name: Title_Mark_Scale_add.LSP
;Description: Initiate and populate Title Mark Block & select viewport to populate scale
;
;Designed by: Mike Tuter
;Date: 01-08-2014
;Updated:
;Info: Launch from the MDC Plan Sheet tool Palette and intiate the populating and placement of the Title Mark block.
;                               User will provide input to dialog box for mark number and title, then user will be prompted to select a viewport
;                               Once a viewport is selected user will be prompted for an insertion point where the title mark block will be inserted
;                               and populated with the information from the dialog box and the scale from the viewport selection.
;
;
;Combined Programs:
;
;-----------------------------------------------------------------------------------------------------------------------------------------------------
(defun C:TLMK ( / TLMK_LEN PT1)
  (setvar "CMDECHO" 0)
  (setq tempunits (getvar "insunits"))
;======================================================================================================================================== LOADS DIALOG BOX
(defun TLMK(/ DCL_ID)
 (setq DCL_ID (load_dialog "n:/tuterj/AutoLISP/Working/TL-MK_Scale_add.DCL"))
 (if (not (new_dialog "TLMK" DCL_ID)) (exit))

 (setq mark_n nil)
 (setq title_n nil)
 
 (action_tile "cancel" "(done_dialog) (exit)")
 (action_tile "mark_n" "(setq mark_n $value)")
 (action_tile "title_n" "(setq title_n $value)")
   
 (start_dialog)
 (unload_dialog DCL_ID)
 (princ)
) ;defun TLMK
 (TLMK)

;======================================================================================================================================== End of Dialog BOx
(vl-load-com)

(defun _selvp (ename)                                                ;function to account for polygonal viewports by ronjonp from the swamp
  (if (= (type ename) 'ename)
    (cond ((= "VIEWPORT" (cdr (assoc 0 (entget ename)))) ename)
  ((and (setq ename (cdr (assoc 330 (entget ename))))
(= "VIEWPORT" (cdr (assoc 0 (entget ename))))
   );and
   ename
  );((and
    );(cond
   );(if
  );(defun

   
(setq vpent (_selvp (car (nentsel "\nselect viewport"))))   ;user selects viewport and viewport id is stored under vpent

(setq vpent (vlax-ename->vla-object vpent))    ;vpent is transformed from an entity to a VLA object

(defun gc:GetObjectIdString (obj)    ;By Gile via Tharwat from AUGI. This function deals with having a 64 bit OS.
  (or *util*
      (setq *util* (vla-get-Utility (vla-get-activedocument (vlax-get-acad-object))
     );vla-get-utility
);setq *util*
   );or *util*
  (if (vlax-method-applicable-p *util* 'GetObjectIdString)
    (vla-GetObjectIdString *util* obj :vlax-false)
    (itoa (vla-get-ObjectId obj))
   );if
);(defun gc:GetObjectIdString
 

(setq scale_fld (strcat "%<\\AcObjProp.16.2 Object(%<\\_ObjId "(gc:GetObjectIdString vpent)">%).CustomScale \\f \"%sn\">%"))  ;assigns field expression to variable.
 
 
(setq PT1 (getpoint "\nselect insertion point: "))   
(setvar "ATTDIA" 0)

(setq title_u (strcase title_n))   ;declaring additional variable to change case for title_n

(setvar "insunits" 0)  ;setting insertion units to unitless for proper scale of inserted block
 
(command "insert" "N:/Tuterj/AutoLISP/Working/TitleMark-field.dwg" PT1 "" "" title_u scale_fld mark_n)  ;inserting the contents of TitleMark drawing, user input from dialog box, &
                                                                                                        ;the viewport scale infromation from the user selection.

(setvar "ATTDIA" 1)
(setvar "CMDECHO" 1)
(setvar "insunits" tempunits)

) ;defun C:TLMK

tntdraftsol

  • Guest
Re: bad argument issue with fields and viewports
« Reply #11 on: January 14, 2014, 02:43:57 PM »
Or just:
Code: [Select]
(ssget "_+.:E:S" '((0 . "VIEWPORT")))

Lee Mac, I have been looking at your code here and trying to get it to work in my routine, but with no sucess yet.  One question I had was what mode does the "_+.:E:S" represent for the selection set get function?

Thank you for your time!

Lee Mac

  • Seagull
  • Posts: 12912
  • London, England
Re: bad argument issue with fields and viewports
« Reply #12 on: January 14, 2014, 05:19:48 PM »
Or just:
Code: [Select]
(ssget "_+.:E:S" '((0 . "VIEWPORT")))
Lee Mac, thank you as well for your reply!  I tried inserting this into my routine and it did not work, but I believe it is because I did not insert this piece of code in the correct spot.  Where should I have put this code in the overall structure of my program?

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!

Or just:
Code: [Select]
(ssget "_+.:E:S" '((0 . "VIEWPORT")))
Lee Mac, I have been looking at your code here and trying to get it to work in my routine, but with no sucess yet.  One question I had was what mode does the "_+.:E:S" represent for the selection set get function?

Please refer to this reference from my site  :-)

snownut2

  • Swamp Rat
  • Posts: 971
  • Bricscad 22 Ultimate
Re: bad argument issue with fields and viewports
« Reply #13 on: January 14, 2014, 07:38:12 PM »
Lee,

These lines of code do a magnificent job of explaining mapcar....(place glowing light bulb here)

Code - Auto/Visual Lisp: [Select]
  1. (setq var '(cmdecho insunits attreq)
  2.        val  (mapcar 'getvar var)
  3.       )
  4.  (mapcar 'setvar var '(0 0 1))
  5.  

Bruce
« Last Edit: January 15, 2014, 06:53:46 AM by snownut2 »

Bhull1985

  • Guest
Re: bad argument issue with fields and viewports
« Reply #14 on: January 15, 2014, 08:53:10 AM »
Yeah that's a really effective way of seeing mapcar in action and I'm surprised it didn't come up during the various mapcar discussions. Or if it did I've read too much and don't remember it.
That said, let's break it down for anyone who may learn from this:
Code: [Select]
(setq var '(cmdecho insunits attreq))     ;set a variable 'var' which is a list to contain the sysvars to be modified
(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
(mapcar 'setvar var '(0 0 1))               ;so we're mapping "setvar" over the var list this time, with quoted 0 0 1, so basically it's a shorthand way to express the following:
                                                    ; (setvar "cmdecho" 0) (setvar "insunits" 0) (setvar "attreq" 1), this has the added benefit of when you're ready to expand this list to contain
                                                    ;more variables you can do so by typing the sysvar name and the value wanted for that var, much easier than even the typical commands
                                                    ;to set and store user settings beforehand.

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 ? 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!

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.
« Last Edit: January 15, 2014, 08:57:46 AM by Bhull1985 »