TheSwamp

Code Red => AutoLISP (Vanilla / Visual) => Topic started by: GDF on July 28, 2009, 11:13:02 AM

Title: Purge excess scales
Post by: GDF on July 28, 2009, 11:13:02 AM
Ok, I"ve just switched from version 2006 to 2010. I'm looking for a routine to automatically purge excess scales.

I keep getting this message in my drawings when opened:
It is recommended you open and resave the Xref file to remove excess scales.

Can anyone point me in the right direction?
Title: Re: Purge excess scales
Post by: Matt__W on July 28, 2009, 11:14:13 AM
I would try opening and resaving the xref file to remove excess scales.
Title: Re: Purge excess scales
Post by: GDF on July 28, 2009, 11:15:30 AM
I would try opening and resaving the xref file to remove excess scales.

Thanks Matt

Is there a way to automatically keep this from happening?
Title: Re: Purge excess scales
Post by: T.Willey on July 28, 2009, 11:18:49 AM
Maybe here will help:

[ http://www.theswamp.org/index.php?topic=23963.0 ]
Title: Re: Purge excess scales
Post by: Krushert on July 28, 2009, 11:18:57 AM
Do a search for scalelist

here is what I do.

http://www.theswamp.org/index.php?topic=23501.msg302279#msg302279

*Edit*
Tim beat me to it
Title: Re: Purge excess scales
Post by: GDF on July 28, 2009, 11:32:22 AM
Thanks

Sorry, I should have done a search first...
Title: Re: Purge excess scales
Post by: Crank on July 28, 2009, 06:02:33 PM
http://www.theswamp.org/index.php?topic=23970.msg290321#msg290321
Title: Re: Purge excess scales
Post by: VVA on July 29, 2009, 07:05:09 AM
My five cents
Code: [Select]
(defun SetScale (/ lst pat tmp)
;;; Pat - the pattern scale is made up of lists of species
;;; (("Name of the Scale 1" Scale_paper_unit_1 Scale_drawing_unit_1)
;;; ("Name of the Scale 2"  Scale_paper_unit_2 Scale_drawing_unit_2)
;;; ...
;;;)
;;; Usage: (SetScale)
  (setq pat '(("1:1" 1 1)  ;_Correct scale here
              ("1:2" 1 2)
              ("1:10" 1 10)
              ("1:50" 1 50)
              ("1:100" 1 100)
              ("2:1" 2 1)
             )
  ) ;_ end of setq
  (setq tmp (mapcar 'car pat))
  (if (dictsearch (namedobjdict) "ACAD_SCALELIST")
    (progn
      (foreach item (dictsearch (namedobjdict) "ACAD_SCALELIST")
        (if
          (and (= 350 (car item))
               (not (member (cdr (assoc 300 (entget (cdr item)))) tmp))
          ) ;_ end of and
           (vl-catch-all-apply 'entdel (list (cdr item)))
        ) ;_ end of if
      ) ;_ end of foreach
      (foreach item (dictsearch (namedobjdict) "ACAD_SCALELIST")
        (if (= 350 (car item))
          (setq lst (cons (cdr (assoc 300 (entget (cdr item)))) lst))
        ) ;_ end of if
      ) ;_ end of foreach
      (if (and lst
               (setq
                 pat (vl-remove-if '(lambda (x) (member (car x) lst)) pat)
               ) ;_ end of setq
          ) ;_ end of and
        (progn
          (while (> (getvar "CMDACTIVE") 0) (command))
          (command "_.-scalelistedit")
          (foreach item pat
            (command "_Add"
                     (car item)
                     (strcat (rtos (cadr item)) ":" (rtos (caddr item)))
            ) ;_ end of command
          ) ;_ end of foreach
          (command "_Exit")
          (while (> (getvar "CMDACTIVE") 0) (command))
        ) ;_ end of progn
      ) ;_ end of if
    ) ;_ end of progn
  ) ;_ end of if
  (princ)
) ;_ end of defun
Title: Re: Purge excess scales
Post by: rkmcswain on July 29, 2009, 10:10:33 AM
Quote from: GDF
Is there a way to automatically keep this from happening?

By default, scale list entries in top level xrefs will always be imported into the parent drawing, but entries from nested xrefs no longer are.
Title: Re: Purge excess scales
Post by: Crank on July 29, 2009, 11:05:51 AM
That was fixed in Acad2008 SP1.

In order to be complete, in acad2009 the following annotation scaling changes were made:
     "# annotation scales detected.  It is recommended you open and resave the Xref file to remove excess scales."

Purging the unused scales would have been a much easier solution.
Title: Re: Purge excess scales
Post by: rkmcswain on July 29, 2009, 04:46:38 PM
The "Hide Xref Scales" thing is silly - just a mask for the problem. Now for unsuspecting users, if "Hide Xref Scales" may be on, and they won't know they have thousands of scale list entries until it's too late...
Title: Re: Purge excess scales
Post by: Crank on July 30, 2009, 04:25:43 AM
The whole SCALELIST is silly as it is. Why are the default scales fixed by Autocad? They only needed a fixed scale of 1:1, other scales can be added easy. Even after the 'MEASUREMENT fix' we get all kind of scales we will never use and scales we need aren't there...

Our company never had problems with the excessive scales. I recognized most of the problems before we switched to 2008, so we've purged all unused scales from day 1. When you need a scale that doesn't exist, you can just type it or create it from a toolbar (code here (http://www.theswamp.org/index.php?topic=23970.msg290743#msg290743)):
(http://www.theswamp.org/screens/Crank/ScaleList.jpg)
Title: Re: Purge excess scales
Post by: gile on July 30, 2009, 06:26:14 AM
Hi,

My 2 cents (I'm new to all this cause I just upgrade from 2007 to 2010)

2 sub routines: one to get the current scale list, the other to set a scale list (the lists returned by GetScaleList or requiered by SetScaleList are the same format as VVA's)

EDIT: added PURGESCALES command (and some sub routines too)

Code: [Select]
;;;============================================================;;;
;;;======================= SUB ROUTINES =======================;;;
;;;============================================================;;;

;; GetCurrentScaleList (gile)
;; Returns the current scales as a list of sublists
;; Each sublist type is : (ScaleName PaperUnit DrawingUnit)

(defun GetCurrentScaleList (/ elst result)
  (and
    (setq elst (dictsearch (namedobjdict) "ACAD_SCALELIST"))
    (setq elst (vl-member-if '(lambda (x) (= 3 (car x))) elst))
    (while elst
      (setq result  (cons
      (ScaleList (cdadr elst))
      result
    )
    elst (cddr elst)
      )
    )
  )
  (reverse result)
)

;;;============================================================;;;

;; SetScaleList (gile)
;; Sets the scale list according to the lst argument
;;
;; Argument : lst a list of sublists which type is: (ScaleName PaperUnit DrawingUnit)

(defun SetScaleList (lst / dict)
  (entmod (vl-remove-if
    '(lambda (x) (or (= (car x) 3) (= (car x) 350)))
    (setq dict (dictsearch (namedobjdict) "ACAD_SCALELIST"))
  )
  )
  (setq dict (cdr (assoc -1 dict))
n    -1
  )
  (foreach s lst
    (dictadd dict
     (strcat "A" (itoa (setq n (1+ n))))
     (entmakex
       (list
'(0 . "SCALE")
'(100 . "AcDbScale")
(cons 300 (car s))
(cons 140 (cadr s))
(cons 141 (caddr s))
       )
     )
    )
  )
)

;;;============================================================;;;

;; ScaleList (gile)
;; Returns the "SCALE" object list as (ScaleName PaperUnit DrawingUnit)
;;
;; Argument scl (ENAME) a "SCALE" object

(defun ScaleList (scl / elst)
  (setq elst (entget scl))
  (list
    (cdr (assoc 300 elst))
    (cdr (assoc 140 elst))
    (cdr (assoc 141 elst))
  )
)

;;;============================================================;;;

;; GetAnnotativeScaleList (gile)
;; Returns the list of the currently used annotative scales as a list
;; of sublists which type is (ScaleName PaperUnit DrawingUnit)

(defun GetAnnotativeScaleList (/ n ss ent xDict dict slst result)
  (setq n 0)
  (if (setq ss (ssget "_X" '((-3 ("AcadAnnotative")))))
    (while (setq ent (ssname ss n))
      (setq n (1+ n))
      (if (and
    (setq xDict (GetExtDict ent))
    (setq dict (dictsearch xDict "AcDbContextDataManager"))
    (setq dict (dictsearch (cdr (assoc -1 dict)) "ACDB_ANNOTATIONSCALES"))
  )
(foreach p dict
  (if (= (car p) 350)
    (setq slst (ScaleList (cdr (assoc 340 (entget (cdr p)))))
  result  (if (not (vl-position slst result))
    (cons slst result)
    result
  )
    )
  )
)
      )
    )
  )
  result
)

;;;============================================================;;;

;; GetExtDict (gile)
;; Returns the entity extension dictionary ename (or nil)
;;
;; Argument : ent (ENAME)

(defun GetExtDict (ent)
  (cdr
    (assoc 360
   (member '(102 . "{ACAD_XDICTIONARY") (entget ent))
    )
  )
)

And two three little commands:
- SAVESCALES: runs the SCALELISTEDIT native command and stores the resulted scale list in an environment variable (registry).
- RESTORESCALES: restores the scale list stored in the environment variable (or runs SAVESCALES if no previous saving)
- PURGESCALES: purges all unused annotative scales except "1:1"[color]

Code: [Select]
;;;============================================================;;;
;;;========================= COMMANDS =========================;;;
;;;============================================================;;;

;; SAVESCALES (gile)
;; Runs SCALELISTEDIT command and save the resulting list in an
;; environment variable

(defun c:SaveScales ()
  (initdia)
  (vl-cmdf "_.scalelistedit")
  (while (/= (getvar 'cmdactive) 0)
    (vl-cmdf pause)
  )
  (setenv "SavedScaleList"
  (vl-prin1-to-string (GetCurrentScaleList))
  )
  (princ)
)

;;;============================================================;;;

;; RESTORESCALES (gile)
;; Restores the scale list previously saved with SAVESCALES
;; or runs SCALAESAVE if no previous saving

(defun c:RestoreScales (/ lst)
  (if (and
(setq lst (getenv "SavedScaleList"))
(setq lst (read lst))
      )
    (SetScaleList lst)
    (c:SaveScales)
  )
  (princ)
)

;;;============================================================;;;

;; PURGESCALES (gile)
;; Purges all unused annotative scales except "1:1"

(defun c:PurgeScales (/ alst cnt)
  (setq alst (GetAnnotativeScaleList)
cnt 0
)
  (foreach p (dictsearch (namedobjdict) "ACAD_SCALELIST")
    (and
      (= 350 (car p))
      (setq slst (ScaleList (cdr p)))
      (/= "1:1" (car slst))
      (null (member slst alst))
      (entdel (cdr p))
      (setq cnt (1+ cnt))
    )
  )
  (princ (strcat (itoa cnt) " échelle(s) purgée(s)."))
  (princ)
)
Title: Re: Purge excess scales
Post by: gile on August 01, 2009, 03:46:09 PM
Hi,

I revised the upper code: add a PURGESCALES command which removes from the scale list all the scales which aren't currently used by an annotative object (except "1:1").
Title: Re: Purge excess scales
Post by: GDF on August 03, 2009, 10:53:38 AM
Thanks Gile.

I can sure make use of these, thanks for sharing.
Title: Re: Purge excess scales
Post by: gile on August 03, 2009, 11:44:32 AM
You're welcome.
Hope it helps...
Title: Re: Purge excess scales
Post by: 3dwannab on April 24, 2024, 05:42:25 PM
Thanks Gile, I was trying to remove a corrupt scale with the name of 1:1000 and at a ratio of 1:1 and your code was the only one that removed it and kept remaining objects and their scale intact.  See the attached file for your reference.

How do I call the function to create the scale list after purging?

I've tried:
Code: [Select]
(setq lst '(("20:1" 20 1)
            ("10:1" 10 1)
            ("5:1" 5 1)
            ("2:1" 2 1)
            ("1:1" 1 1)
            ("1:2" 1 2)
            ("1:5" 1 5)
            ("1:10" 1 10)
            ("1:20" 1 20)
            ("1:25" 1 25)
            ("1:50" 1 50)
            ("1:75" 1 75)
            ("1:100" 1 100)
            ("1:200" 1 200)
            ("1:250" 1 250)
            ("1:400" 1 400)
            ("1:500" 1 500)
            ("1:1000" 1 1000)
            ("1:1250" 1 1250)
            ("1:2500" 1 2500)
            ("1:5000" 1 5000)
           )
) ;_ end of setq

(SetScaleList lst)

I get the error:
Code: [Select]
error: bad argument type: lentityp nil