How to save insert scale factor upon quiting dwg session and use the same scale factor working back to the same dwg

How to save insert scale factor upon quiting dwg session and use the same scale factor working back to the same dwg

owitzki
Enthusiast Enthusiast
1,337 Views
15 Replies
Message 1 of 16

How to save insert scale factor upon quiting dwg session and use the same scale factor working back to the same dwg

owitzki
Enthusiast
Enthusiast

We have this routine to insert block with preset scale factor.

 

(defun c:ib () ;Insert block name
(if (null _insscl) (setq _insscl 1.0))
(setq BNAME (getstring T (strcat "Enter block name" "<" (getvar "INSNAME") "> :")))
(command "insert" BNAME "s" _insscl pause)
)
;
(defun c:ip (/) ;Set insert scale factor
(if (null _insscl) (setq _insscl 1.0))
(setq i (getreal (strcat "\nEnter scale factor <" (rtos _insscl 2 3) ">: ")))
(if (/= i nil) (setq _insscl i))
)

 

My goal is to save value I entered for 'ip' (scale factor) upon quitting drawing session and use the same value for my custom command 'ib' when reopening the previous drawing. How can I set to remember that value until someone change it?

 

Thank you!

0 Likes
1,338 Views
15 Replies
Replies (15)
Message 2 of 16

Kent1Cooper
Consultant
Consultant

@owitzki wrote:

.... How can I set to remember that value until someone change it?


You can use an environment variable.  Read about the (setenv) and (getenv) AutoLisp functions.  They can only hold text, so you will need to convert your scale factor number to its text equivalent to set it, and convert it back to a number after you get it, to use it.  But you can have as many of them as you want, called whatever you want, and they will be available to any drawing, since they are not saved in the drawing file, but in the "environment."

 

EDIT:  Something like these? [very lightly tested]:

 

(defun C:IP () ;Set insert scale factor
  (setenv "BlockScale"
    (rtos ; because it needs to be text
      (cond
        ( (getreal ; User input [nil on Enter]
            (strcat
              "\nEnter scale factor <"
              (if (getenv "BlockScale")
                (rtos (atof (getenv "BlockScale")) 2 3); then
                  ;; EDIT # of displayed decimal places [up to 8 in stored value]
                "1.0" ; initial default
              ); if
              ">: "
            ); strcat
          ); getreal
        ); user-entry condition
        ((atof (getenv "BlockScale"))); prior value if present
        (1.0); initial default on Enter with no prior value
      ); cond
      2 8 ; mode/precision [max. precision for e.g. fractional value]
    ); rtos
  ); setenv
  (prin1)
)

(defun C:IB () ;Insert block name
  (if (not (getenv "BlockScale")) (setenv "BlockScale" "1.0"))
  (setq BNAME
    (getstring T
      (strcat
        "\nEnter block name"
        (if (/= (getvar 'insname) ""); there's a prior Block name
          (strcat " <" (getvar 'insname) ">"); then -- offer as default
          "" ; elses -- no default
        ); if
        ": "
      ); strcat
    ); getstring
  ); setq
  (command "_.insert" BNAME "s" (atof (getenv "BlockScale")))
  (prin1)
)

 

Line 27 in IB will not be needed after the very first use of IP, so if you use IP even once before ever using IB, that line can be eliminated.

 

Consider adding an option in IB to change the scale factor there, with a notification of what the current scale factor is before the prompt for the Block name.

Kent Cooper, AIA
Message 3 of 16

scot-65
Advisor
Advisor

@owitzki,

 

Kent has a very good suggestion.

If you need variables stored in your own personal/work menu area,

consider reading and writing to the registry itself.

 

(if (not (setq a (vl-registry-read "HKEY_CURRENT_USER\\Software\\MyMenu" "MyScaleFactor")))

  (setq a (vl-registry-write "HKEY_CURRENT_USER\\Software\\MyMenu" "MyScaleFactor" 1.0)))

 

 

The setenv and getenv does this, but in AutoCAD's area of the registry.

 

(if (null _insscl) (setq _insscl 1.0))

 =

(or _insscl (setq _insscl 1.0))

 

Hope this helps.


Scot-65
A gift of extraordinary Common Sense does not require an Acronym Suffix to be added to my given name.

0 Likes
Message 4 of 16

john.uhden
Mentor
Mentor

@owitzki ,

As an alternate to using the registry, you might prefer that the setting travels with the drawing.  In such a case you can save the setting (and many more) as an xrecord in a dictionary in each drawing.  Use the vlax-ldata-put and vlax-ldata-get functions.

I have a problem where I work now in that the company, that is rather large, is very keen on security and prevents anyone not authorized from writing to the registry.  And they want things simple, so my work sets a few defaults within the code that I can save to and read from the bulletin board (vl-bb-set and vl-bb-ref) by symbol name, which is available to all drawings in the same AutoCAD session, but not between sessions.

John F. Uhden

Message 5 of 16

owitzki
Enthusiast
Enthusiast

Thank you Kent!

Your code works. My only concern is that the value is being saved across all drawings. Is there a way to save just the value of scale factor for each individual drawing? This way I don’t need to change scale factor every time I switch to different drawing. Say, I am working on one drawing in 1/4" scale at the same time working on the other drawing with 1/8" scale, the 1/4" scale has half of 1/8" scale scale factor. Therefore, it’s a bit of a hassle to keep changing the value. 

 

0 Likes
Message 6 of 16

Sea-Haven
Mentor
Mentor

Like John here is ldata example I use this method and works great.

 

 

(vlax-ldata-put "AlanH" "ht" ht)

(setq ht (vlax-ldata-get "AlanH" "ht" ))

 

For a new dwg use this first.

 

(if (= ht nil)(vlax-ldata-put "AlanH" "ht" 2))

 

Message 7 of 16

Kent1Cooper
Consultant
Consultant

@owitzki wrote:

Thank you Kent!

.... Is there a way to save just the value of scale factor for each individual drawing? ..... 


Not with environment variables.  But you can use one of the USERR1 through USERR5 System Variables if you're sure nothing else is going to use the same one.  Or if your scale factors are always whole numbers, USERI1 through USERI5.  Those are saved separately in every drawing.

Kent Cooper, AIA
0 Likes
Message 8 of 16

owitzki
Enthusiast
Enthusiast

@john.uhden 

 

I would like to try your your code John. Please note, we have a very odd blocks in which, when we insert them to our drawings, say 3/32" = 1'-0", the scale has 4 decimal places. Would that be an issue for vlax-ldata-put?

0 Likes
Message 9 of 16

owitzki
Enthusiast
Enthusiast

This seems to work. I just don't get to show the last input here

owitzki_0-1710619304164.png

(defun C:IP () ;Set insert scale factor
(if (= BlockScale nil)(vlax-ldata-put "dict" "BlockScale" 2))
(vlax-ldata-put "dict" "BlockScale" BlockScale)
(setq BlockScale (vlax-ldata-get "dict" "BlockScale" ))
(vlax-ldata-put "dict" "BlockScale" (rtos (cond ( (getreal
(strcat "\nEnter scale factor <"
(if (vlax-ldata-get "dict" "BlockScale")
(rtos (atof (vlax-ldata-get "dict" "BlockScale")) 2 3) "1.0" ) ">: " )))
((atof (vlax-ldata-get "dict" "BlockScale")))(1.0)) 2 8 ))
(prin1)
)

(defun C:IB () ;Insert block name
(if (not (vlax-ldata-get "dict" "BlockScale")) (vlax-ldata-put "dict" "BlockScale" "1.0"))
(setq BNAME (getstring T (strcat "\nEnter block name"
(if (/= (getvar 'insname) "")(strcat " <" (getvar 'insname) ">") "" ) ": " )))
(command "_.insert" BNAME "s" (atof (vlax-ldata-get "dict" "BlockScale")))
(prin1)
)

 

Anyway, big thanks to all of you!

0 Likes
Message 10 of 16

john.uhden
Mentor
Mentor

@owitzki ,

You picked that up quickly!

But you don't need to have two separate commands, and nor do you need to repeat the vlax-ldata functions so often (use local variables instead), and what if the BNAME you enter doesn't exist?

Oh, and you can save most any type of value with vlax-ldata* including reals.  They don't have to be strings.  That requirement is for DCL tiles.

See if this works any better:

BTW, I think it's okay to have nothing between the default brackets ("<>").

(defun C:IB ( / blockscale bname ans) ;Insert block name and scale
(if (not (setq blockscale (vlax-ldata-get "dict" "BlockScale")))
  (setq blockscale 1.0)
)
(initget 6)
(if (setq ans (getreal (strcat "\nBlock scale <" (rtos blockscale 2 4) ">: ")))
  (vlax-ldata-put "dict" "BlockScale" (setq blockscale ans))
)
(setq BNAME (getvar "insname"))
(setq ans (getstring T (strcat "\nEnter block name <" BNAME ">: ")))
(if (/= ans "")(setq BNAME ans))
(if (tblsearch "block" BNAME)(command "_.insert" BNAME "s" blockscale))
(prin1)
)

Actually, it would probably be better to get the scale after the name (if there is a name).

 

 

John F. Uhden

0 Likes
Message 11 of 16

owitzki
Enthusiast
Enthusiast

@john.uhden 

I'm getting this error John

owitzki_0-1710644940899.png

 

0 Likes
Message 12 of 16

john.uhden
Mentor
Mentor

@owitzki ,

My apologies.  I hadn't considered that the dictionary entry may have already been set as a string.

I also followed my own suggestion to ask for the BNAME before the blockscale (as in what's the point of asking for the scale if the block definition doesn't exist?).

This ought to work much better (though it is a tad longer):

(defun C:IB ( / bname ans blockscale) ;Insert block name and scale
  (and
    (setq BNAME (getvar "insname"))
    (setq ans (getstring T (strcat "\nEnter block name <" BNAME ">: ")))
    (if (/= ans "")(setq BNAME ans))
    (or
      (tblsearch "block" BNAME)
      (prompt "\nBlock name does not exist.")
    )
    (or (setq blockscale (vlax-ldata-get "dict" "BlockScale")) 1)
    (cond
      ((numberp blockscale))
      ((= (type blockscale) 'STR)(setq blockscale (read blockscale)))
      ((setq blockscale 1.0))
    )
    (not (initget 6)) ;; disallow 0 and negative.
    (if (setq ans (getreal (strcat "\nBlock scale <" (rtos blockscale 2 4) ">: ")))
      (vlax-ldata-put "dict" "BlockScale" (setq blockscale ans))
      blockscale
    )
    (vl-cmdf "_.insert" BNAME "s" blockscale)
  ) ;; and
  (prin1)
)

BTW, if you don't need precision to 4 places after the decimal, then change 4 to 2.
You can still enter the scale to whatever precision you choose and it will be saved that way.  It's just that the next time you run the command the default will show to only 2 places.  It's just my personal preference to not see a bunch of trailing zeros or numbers of repeated value.  For instance 0.83 is close enough to 0.8333 for me.

John F. Uhden

0 Likes
Message 13 of 16

Sea-Haven
Mentor
Mentor

My $0.05 "dict" I would use a more custom name as some one else may use that sort of generic name. Ie Dictionary is an object in Acad, even more practical "Insbnamesc" so its relevant to the task. I have seen Dict used in lots of Dictionary code.

Message 14 of 16

john.uhden
Mentor
Mentor

@Sea-Haven ,

I was going to mention that, but didn't.

My 5 cents is "Igzlpig."

John F. Uhden

0 Likes
Message 15 of 16

owitzki
Enthusiast
Enthusiast

Still getting pause at blockscale, the main goal of IP (preset scale factor) is to go to insertion point right away upon invoking IB. And maybe a repeat placement is a very helpful too.

0 Likes
Message 16 of 16

owitzki
Enthusiast
Enthusiast

I'll take your your advise re; custom name @Sea-Haven, tnx for the info!

0 Likes