Author Topic: Changing drawing version in Lisp  (Read 2442 times)

0 Members and 1 Guest are viewing this topic.

sovby

  • Mosquito
  • Posts: 9
Changing drawing version in Lisp
« on: October 02, 2020, 10:32:10 PM »
I am trying to get the current version of a drawing and then change it to version 2007. I run this code without any errors showing but it not working.

(defun c:version_update (/ filepath fe)
(setq filepath (strcat (getvar "dwgprefix")(getvar "dwgname")))
   (setq fe (getenv "DefaultFormatForSave"))
   (setenv "DefaultFormatForSave" "36")
  )

When i open up the drawing I'm getting the message "Opening an AutoCAD 2013 format file", even though when I type in (getenv "DefaultFormatForSave") to the command line it returns "36".

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16899
  • Superior Stupidity at its best
Re: Changing drawing version in Lisp
« Reply #1 on: October 03, 2020, 01:30:57 AM »
I'm not sure what you are trying to accomplish, but you are only changing the save format in the options. You aren't getting the file format of the current drawing. Ostensibly, once the drawing file is opened and in the editor, the drawing file format is non-existent ... well I guess technically its the format of the version of the software you are using.

When you change that variable, you are not changing how the file is read or interpreted by the software.

if you want to change the file version, you will need to open each file then save it as the version you desire.

The only thing you have succeeded in doing is setting the file save as version for all future drawings to 2007 DWG format. You could just as eaily do that with this code and ignore everything else you have because it literally does nothing.

Code: [Select]
(setenv "DefaultFormatForSave" "36")
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

Find me on https://parler.com @kblackie

sovby

  • Mosquito
  • Posts: 9
Re: Changing drawing version in Lisp
« Reply #2 on: October 03, 2020, 09:04:39 AM »
Sorry, i guess i am not explaining things well enough. What i am trying to do is either open up a drawing and save it as a 2007 drawing or wblock some entities with a selection set as a 2007 drawing. I want to this all in lisp without having to go into the drawing manually saveas 2007.dwg format. I have another routine that does some other things to an original file such as change all of the colors to white & wblock them out to a file called pool.dwg The problem is i need pool.dwg to be in 2007 format because it gets inserted into visio and visio doesnt support a later version of autocad.

Marc'Antonio Alessi

  • Swamp Rat
  • Posts: 1453
  • Marco
Re: Changing drawing version in Lisp
« Reply #3 on: October 03, 2020, 11:07:40 AM »
>> (vlax-invoke cdoc 'wblock dfile ass)
I believe that the wblock Lisp command (or equivalent) always saves in the version of CAD you are using ignoring the value of DefaultFormatForSave
or SaveAsType > (vla-get-opensave (vla-get-preferences (vlax-get-acad-object)))
If I remember correctly the 2007 version saved the file based on DefaultFormatForSave...

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: Changing drawing version in Lisp
« Reply #4 on: October 03, 2020, 11:53:40 AM »
Sorry, i guess i am not explaining things well enough. What i am trying to do is either open up a drawing and save it as a 2007 drawing ...

Not understanding why code is needed to accomplish that. Open it, saveas 2007. Hocuscadabra. What am I missing?

... or wblock some entities with a selection set as a 2007 drawing.

Could be done by some slight of hand -- wblock entities -- use a hidden | visible instance of accoreconsole.exe to open the wblocked dwg, do as "Save as 2007" then close. Abracapocus.

(objectdbx will kick you in the crotch, spit on your neck if you try to invoke saveas with a version argument)
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

sovby

  • Mosquito
  • Posts: 9
Re: Changing drawing version in Lisp
« Reply #5 on: October 03, 2020, 12:11:29 PM »
Sorry, i guess i am not explaining things well enough. What i am trying to do is either open up a drawing and save it as a 2007 drawing ...

Not understanding why code is needed to accomplish that. Open it, saveas 2007. Hocuscadabra. What am I missing?

... or wblock some entities with a selection set as a 2007 drawing.

Could be done by some slight of hand -- wblock entities -- use a hidden | visible instance of accoreconsole.exe to open the wblocked dwg, do as "Save as 2007" then close. Abracapocus.

(objectdbx will kick you in the crotch, spit on your neck if you try to invoke saveas with a version argument)

I was hoping to do this all as part of my WBPool.lsp file so i only have to run one routine. wblock the entities in the selection set as a 2007 version would be my preference. I have heard about acccoreconsole, but i was not sure how to use it. That's a scripting program? Currently i just have this code:

(cond (ss
            (setq ass (vlax-get-property cdoc 'activeselectionset)
                  dfile (strcat (getvar 'dwgprefix) dnme ".dwg")
            );end_setq
            (vlax-for itm ass (vlax-put itm 'color 7))
            (vlax-invoke cdoc 'wblock dfile ass)
            (setq dcnt (1+ dcnt) dnme (strcat dnme (itoa dcnt)))
          )
          (t (alert "Nothing Selected"))
    )

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: Changing drawing version in Lisp
« Reply #6 on: October 03, 2020, 02:54:47 PM »
Here's some code to play with:

Edit: Rewrote mp-wblock-ss because the vla-wblock call was "noisy" -- temporarilly showing a thumbnail preview -- so rewrote it.

mp-console-process-drawing:
Code: [Select]
(defun mp-console-process-drawing ( dwg-path script-text visible wait / acconsole folder quoted scr-path scr-handle bat-path bat-handle result )
    (and
        ;;  This function does not care what write state the passed dwg is
        ;;  in, what script-text does, nor does it do any syntax checks etc.
        ;;  on script-text. i.e. No sanity check's are performed -- that
        ;;  responsibility falls on the shoulders of the caller. For example,
        ;;  if the dwg opened was read-only because it's opened by another
        ;;  process (accoreconsole.exe doesn't care per se and will open it)
        ;;  and the script attempts to perform a ".qsave" without checking
        ;;  writestat beforehand that would be kinda stupid. Bonus, depending
        ;;  how reckless the script is, the accoreconsole.exe session may
        ;;  never terminate. SAD. TLDR: it's the caller's responsibility to
        ;;  use this function judiciously.
        (cond
            ((setq acconsole (findfile "accoreconsole.exe")))
            ((princ "\nCan't find accoreconsole.exe, cue sad trombone.") nil)
        )
        (findfile dwg-path)
        (setq folder (vl-filename-directory dwg-path))
        (setq folder (if (wcmatch folder "*\\") folder (strcat folder "\\")))
        (setq quoted (lambda (x) (strcat "\"" x "\"")))
        (setq scr-path (vl-filename-mktemp "accore.scr"))
        (setq scr-handle (open scr-path "w"))
        (progn
            (princ script-text scr-handle)
            (close scr-handle)
            (findfile scr-path)
        )
        (setq bat-path (vl-filename-mktemp "accore.bat"))
        (setq bat-handle (open bat-path "w"))
        (progn
            (princ
                (strcat
                    "set acconsole="  (quoted acconsole) "\n"
                    "set scriptname=" (quoted scr-path) "\n"
                    "%acconsole% /i " (quoted dwg-path) " /s %scriptname%\n"
                )
                bat-handle
            )
            (close bat-handle)
            (findfile bat-path)
        )
        (progn
            (setq shell (vlax-create-object "WScript.Shell"))
            (setq result (vl-catch-all-apply 'vlax-invoke (list shell 'run bat-path (if visible 8 0) (if wait -1 0))))
            (vl-catch-all-apply 'vlax-release-object (list shell))
            (gc)
            ;; Not really definitive, only means the run request did not
            ;; throw an error. You may wish to code other means to
            ;; determine if the script achieved what you desired.
            (not (vl-catch-all-error-p result))
        )
    )
)

mp-ss-to-array:
Code: [Select]
(defun mp-ss-to-array ( ss / i lst )
    (if (and (eq 'pickset (type ss)) (< 0 (setq i (sslength ss))))
        (vlax-safearray-fill
            (vlax-make-safearray
                vlax-vbObject
                (cons 0 (1- (length (repeat i (setq lst (cons (ssname ss (setq i (1- i))) lst))))))
            )
            (mapcar 'vlax-ename->vla-object lst)
        )
    )
)

mp-convert-activex-ss-to-vanilla-ss:
Code: [Select]
(defun mp-convert-activex-ss-to-vanilla-ss ( axss / vss )
    (and
        (eq 'vla-object (type axss))
        (vlax-method-applicable-p axss 'SelectOnScreen)
        (< 0 (vla-get-count axss))
        ;; error trapped in case maximum number of selection sets exceeded
        (vl-catch-all-apply 'eval
           '((progn
                (setq vss (ssadd))
                (vlax-for x axss (ssadd (vlax-vla-object->ename x) vss))
            ))
        )
    )
    vss
)

mp-wblock-ss:
Code: [Select]
(defun mp-wblock-ss ( ss new-dwg-path / tss ss! ss-old cmdecho handle result )
    (and
        (cond
            (   (eq 'vla-object (setq tss (type ss)))
                (and
                    (vlax-method-applicable-p ss 'SelectOnScreen)
                    (setq ss! (mp-convert-activex-ss-to-vanilla-ss ss))
                )
            )
            (   (and
                    (eq 'pickset tss)
                    (< 0 (sslength ss))
                    (setq ss! ss)
                )   
            )
        )
        (setq handle (open new-dwg-path "w"))
        (progn
            (close handle)
            (vl-file-delete new-dwg-path)
            (not (findfile new-dwg-path))
        )
        (progn
            (setq cmdecho (getvar 'cmdecho))
            (setvar 'cmdecho 0)
            (if (setq ss-old (cadr (ssgetfirst))) (progn (setq setfirst t) (sssetfirst nil nil)))
            (vl-cmdf ".wblock" new-dwg-path "" "_non" "*0,0,0" ss! "")
            (if (setq result (findfile new-dwg-path)) (vl-cmdf ".oops"))
            (if ss-old (sssetfirst nil ss-old))
            (setvar 'cmdecho cmdecho)
        )
    )
    result
)

Based on the generic functions above write a sample solution loosely based on your requirements:

mp-send-activess-to-new-dwg-and-process:
Code: [Select]
(defun mp-send-activess-to-new-dwg-and-process ( / ss new-dwg-path my-script result )
    (and
        (cond
            (   (setq ss (cadr (ssgetfirst)))
                (cond
                    ((zerop (sslength ss)) (princ "\nActive selection set is empty; SAD.") nil)
                    (t)
                )
            )
            (   (princ "\nNo active selection set, SAD.") nil)
        )
        ;;  It ain't pool.dwg, then again this code is free ;p
        (setq new-dwg-path (vl-filename-mktemp "vogon.dwg"))
        (mp-wblock-ss ss new-dwg-path)
        (setq my-script
            (strcat
                ;;  Note: Can't use any activex calls in accoreconsole.exe.
                "(command \".layer\" \"_color\" 7 \"*\" \"_unlock\" \"*\" \"\")\n"
                "(if (setq ss (ssget \"x\"))\n"
                "   (repeat (setq i (sslength ss))\n"
                "       (vl-catch-all-apply 'eval\n"
                "          '(   (entmod\n"
                "                   (subst\n"
                "                      '(62 . 7)\n"
                "                       (assoc 62 (setq data (entget (ssname ss (setq i (1- i))))))\n"
                "                       data\n"
                "                   )\n"
                "               )\n"
                "           )\n"
                "       )\n"
                "   )\n"
                ")\n"
                "(if (eq 1 (getvar 'writestat))\n"
                "    (progn\n"
                "        (setvar 'expert 5)\n"
                "        (command \".saveas\" \"2007\" (strcat (getvar 'dwgprefix) (getvar 'dwgname)))\n"
                "    )\n"
                ")\n"
                "(if (< 0 (getvar 'dbmod))\n"
                "    (command \".close\" \"_yes\")\n"
                "    (command \".close\")\n"
                ")\n" ;; last carriage return is important
            )
        )
        (mp-console-process-drawing
            new-dwg-path
            my-script
            nil  ;; don't show accoreconsole.exe working
            t    ;; wait | work synchonously
        )
    )
    (princ
        (cond
            ((null new-dwg-path) "")
            ((setq result (findfile new-dwg-path)) (strcat "\nCreated: " result))
            ("\nUnexpected error in module 'deep thought'.")
        )
    )   
    (princ)   
)

Run our custom solution:
(mp-send-activess-to-new-dwg-and-process)

Sample output if successful:
Created: C:\Users\Arthur Dent\Temp\vogon042.dwg
« Last Edit: October 04, 2020, 03:11:24 PM by MP »
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst