Dear autocad / lisp users,
Could you please help me with my question.
I'm trying to create a field in a block (titleblock) that will automaticly update when I
change the viewportscale.
It's mostly only 1 viewport, sometimes a second of even 3rd but, they are not important to the titleblock.
I've read aboud fields and diesel expressions. I've tried and it works. there is only 1 problem,
It only works with the object (when field expresssion, object, custom scale) in this case the viewport
pressent at that time.
When i use the same field with the same expressions, it does not recognize the viewport/object.
Is there a way to make the field, diesel expression or even something else, work without it's need for a
object name. Perhabs that the expression gets the viewportname from a lisp, something like:
(setq ss(ssget "X")) ;some thing like this
Can it be done?
Anny help will be great.
Solved! Go to Solution.
Thank you for replying to my message.
Unfortunaly it's not what I'm looking for.
I've tried the customscale field, and it works. The only problem is. It works with the
current viewport, pressent at the time i place the field.
In other words.
The field is given a certain name, for example: viewport12048v, This name is given to
the field expression. When I copy or place the field in a other drawing or layout tab.
It does not reconize the name of the viewport.
Do you perhabs know a way to work around this... Name Problem?
Anny suggestions will be fine.
after replying, I realized that I was giving the same solution that you already had.
Unfortunately, I don't have way to help you with the field problem, but if meanwhile I find something that can help, I come back to to share.
For a field to provide the viewport scale it must have a reference from which to get/update the scale. It is my understanding that the only way to access the viewport scale field is through the SheetSet reference or the object itself and the viewport must be present.
It is not possible to have a field include the scale for a non-existent viewport as it has no way of knowing what that scale is. Prior to using Sheet Sets I would get a viewport scale by calculating it from the variables associated with the view. You could do this and update your titleblock with it but if you have more than one viewport you may have more than one scale.
You say that you may have multiple viewports or just one viewport and the existence of the viewport is not important to your title block scale field. It seems that just having fixed text for the scale would best suit your needs.
If you want it to reflect your viewport scale automatically then you have multiple problems to solve.
1) you need a reactor to fire when you open the drawing or make it current.
2) you need to find the correct viewport and calculate or otherwise obtain its scale.
3) you need to update the title block with the scale.
If you can solve the reactor and viewport selection problems I know how to calculate and update the scale.
P.S. it may work to obtain the object ID and format the string to include the object ID. It should match what your system shows for the object custom scale per hmsilva's post (see the bottom of hmsilva's posted image).
Or, put a sheetset callout block in the viewport (does not need to be visible) and then get the field value from it and put it in your titleblock. The callout block will automatically update. Maybe the titleblock will as well if it has the same value?
Thank you verry mucht for you help.
I don't know if I'll be able to create something with your input. But I'll sure try.
I was thinking, working, on a way to get the Viewport Custom Scale from the Viewport,
without clicking or selection the viewport. Since I have only 1 (99% of the time) viewport
it shouldn't be so hard.
I've found something I think, can be formed into something I want.
It's called VPSCALE.lsp, from the Express tools.
It works perfect. The only problem is, I have to tell the lisp where to find the correct viewport.
Here is the code:
;;; ;;; VPSCALE.LSP ;;; Copyright © 1999 by Autodesk, Inc. ;;; ;;; Your use of this software is governed by the terms and conditions of the ;;; License Agreement you accepted prior to installation of this software. ;;; Please note that pursuant to the License Agreement for this software, ;;; "[c]opying of this computer program or its documentation except as ;;; permitted by this License is copyright infringement under the laws of ;;; your country. If you copy this computer program without permission of ;;; Autodesk, you are violating the law." ;;; ;;; AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. ;;; AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF ;;; MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC. ;;; DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE ;;; UNINTERRUPTED OR ERROR FREE. ;;; ;;; Use, duplication, or disclosure by the U.S. Government is subject to ;;; restrictions set forth in FAR 52.227-19 (Commercial Computer ;;; Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii) ;;; (Rights in Technical Data and Computer Software), as applicable. ;;; ;;; --------------------------------------------------
-------------- ; find the scale of a viewport relative to paper space ; Carl Bethea 11 April 91 ; ; Paul Vine 20 April 1999 Ported to 2000. ; ;--- paper ------------------------------------------------- ; returns T if in paper space (defun paper () (> 2 (getvar "cvport")(getvar "tilemode")) ; port=1 & tile=0 ) ; ;--- getx -------------------------------------------------- ; return <nth> dotted pair of the extended entity data ; from an entity association list <data> ; (defun getx (n data) (nth n (cdadr (assoc -3 data))) ) ; ; ; ;--- c:vpscale ---------------------------------------------- ; get the xp scale factor of a pspace viewport ; (defun c:vpscale (/ ent data cvsize cvhgt units vpna flag) (cond ((not (equal 0 (getvar "tilemode"))) (princ "\n Command not allowed unless TILEMODE is set to 0 ") ) ((and (/= 1 (getvar "cvport")) (setq vpna (acet-currentviewport-ename)) (equal 1 (logand 1 (cdr (assoc 90 (entget vpna))))) ) (princ "\n Command not allowed in perspective view ") ) (T (acet-error-init (list (list "cmdecho" 0 "luprec" (getvar "luprec") "dimzin" 8 ) T ;flag. True means use undo for error clean up. );list );acet-error-init (if (paper) ;(setq ent (car (entsel "\nSelect edge of viewport: "))) ;;Added the following code to replace the above line. Irregularly shaped floating viewports actuall ;;consist fo two entities (a pline and a viewport) with reactors on each other to point to each other ;;so a simple (entsel) returned a pline instead of a viewport. Had to uise the built-in filtering ;;capability of 'acet-ui-single-select' to get around this problem. (progn (while (not flag) (princ "\nSelect edge of viewport.") (setq ent (acet-ui-single-select '((0 . "viewport")) T )) ;setq (if (and ent (= 1 (logand 1 (cdr (assoc 90 (entget ent))))) ) (progn (princ "\nViewports with perspective view on are not allowed.") (setq flag nil) );progn (setq flag T) );if );while );progn (setq ent (acet-currentviewport-ename)) ) (cond ((and ent (setq data (entget ent '("ACAD"))) (= "VIEWPORT" (acet-dxf 0 DATA)) );and (setq cvhgt (acet-dxf 41 DATA) ; viewport height cvsize (cdr (getx 6 data)) ; viewsize from extended data ) (prompt "\nPS:MS == ") (cond ((< cvsize cvhgt) (princ (rtos (/ cvhgt cvsize) 2)) (princ ":1") ) (T (princ "1:") (princ (rtos (/ cvsize cvhgt) 2)) ) );cond (setq units (getvar "lunits")) (setvar "luprec" 8) (cond ((= units 4) (prompt (strcat "\nViewport Scale: " (rtos (/ 12 (/ cvsize cvhgt))) " = 1'-0\"")) ) ((= units 3) (prompt (strcat "\nViewport Scale: 1\" = " (rtos (/ cvsize cvhgt)))) ) ) ) (T (prompt " no viewport found.")) );cond (acet-error-restore) ; Retsore values ) );cond close (princ) );c:vpscale (princ)
I've tried serveral things, listed below:
(setq ss (ssget "_X" (list (cons 410 (getvar "ctab")) '(0 . "VIEWPORT")))vp (ssname ss 0)) ; Unfortunaly, I don't have the knowlage to put this into the, well written lisp.
(command "mspace") ; worked once... after the one time it keeps giving error's about not knowing the mpsace command.
(setq RecivedVpScale (rtos (/ cvsize cvhgt)))
; The output of the lisp it written to this $Variable.
; The last thing to do with it is, (rtos ...number/$var... 2 1) to get a clean output.
If i'm able to retrieve the last numers of the VpCustom Scale (cannoscale) I could use a little lisp
routine to place it into my titleblock, like this:
1: (static value) + the ouput of the lisp.
I believe that, or something like that, could work
I hope i wrote my question / remarks a little understandable.
Anny suggestions for the above "story / stuff" are welcome.
as far as I understood, you have a title block with several attributes, and a field in one of the attributes linked to
the viewport scale, and if you copy to another drawing or other viewport, the field is no longer linked to the new viewport.
This code reconnect the field to the new viewport, selecting the new viewport and the text field in the attribute block.
This code was written, from one that was posted here in Discussion Groups, a few years ago, by OwenWhitehouse, where he managed to discover the objectid if the platform was x64.
(defun c:test (/ vpObj fldObj vpID util fldtxt) (vl-load-com) (setq vpObj (vlax-ename->vla-object (car (nentsel "\nSelect the viewport: ")) ) fldObj (vlax-ename->vla-object (car (nentsel "\nSelect the Field: "))) vpID (vla-get-objectid vpObj) );; setq (if (> (vl-string-search "x64" (getvar "platform")) 0) (progn (setq util (vla-get-Utility (vla-get-activedocument (vlax-get-acad-object)) ) vpID (vlax-invoke-method util "GetObjectIdString" vpObj :vlax-False ) );; setq );; progn (setq vpID (vl-princ-to-string (vla-get-Objectid vpObj))) );; if (setq fldtxt (strcat "%<\\AcObjProp.16.2 Object(%<\\_ObjId " vpID ">%).CustomScale \\f \"%sn\">%" ) ) (vla-put-textstring fldObj fldtxt) (vla-update fldObj) (vla-regen (vla-get-activedocument (vlax-get-acad-object)) 1 ) (princ) );; test
hope that helps
Thank you verry, verry much for your post.
I think i wlll be able to create something so suite my needs with this lisp.
It looks perfect.
In the meanwhile I've even found a way (lisp) to extract the custom viewportscale.
In combination with the lisp you gave me. I could create a lisp that will update the
block with the extracted vpscale.
It's going to be perfect
Again, Thank you verry verry much.
here is the code to extract the custom vpscale:
For those who might have intrest in getting the custom viewportscale:
The lisp extracts the viewportscale in mm (milimeters)
If you want the scale to return as INCH, you just have to turn the output to
INCH. 1mm = 25.4mm
(defun C:vpsc () ;/ a ts n vpsf th index b1 b c d b2) ; defines function and variables (setq ss (ssget "X" (list '(0 . "Viewport")(cons 69 2)))) ; defines selection set '(cons 69 1)(cons 410 "*") (setq n (sslength ss)) ; gets number of items selected (setq index 0) ; sets counter for loop to 0 (repeat n ; begin loop for number of items (setq ent (ssname ss index)) ; get the entity name (setq entnm (entget (ssname ss index))) ; get the entity name ;(princ entnm) ; show ent data (setq index (+ index 1)) ; adds to counter (setq entyp (assoc 0 entnm)) ; pulls out entity type (if (= "VIEWPORT" (cdr entyp)) ; checks for text entity (progn ; begins actual program (setq vpnme (cdr (assoc 410 entnm))) ; gets viewport name (princ "\nViewportname = ")(princ vpnme) (setq data (entget ent '("ACAD*"))) (setq cvhgt (acet-dxf 41 DATA)) ; viewport height (setq cvsize (cdr (getx 6 data))) ; viewsize from extended data (princ (strcat "\n1:" (rtos (/ cvsize cvhgt) 2 0))) ;Print output, 1: scale (setq gvpsc (rtos (/ cvsize cvhgt) 2 0)) ;Place output into $var "gvpsc" ) ; end progn ) ; ends if ) ; ends loop (print) ; cleans command line ) (defun getx (n data) (nth n (cdadr (assoc -3 data))) ) ;(princ "VPSC Loaded...scales text to viewport scale.") ; loading information