Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Batch update Layer State in all viewports across multiple files

12 REPLIES 12
Reply
Message 1 of 13
cgentile
5685 Views, 12 Replies

Batch update Layer State in all viewports across multiple files

I'm creating a drawing set that has over 100 sheets with varying amounts of viewports on each sheet (from one to four). Each sheet is its own file, so there is only one layout per file. For each section of the drawing set, the viewports will have the same layer state.

 

Is there were a way to update the layerstate of each viewport through a batch LISP routine? This would save me DAYS in opening each file, importing the layer state, and restoring it for each viewport. It seems straight forward, but I have no idea where to start with batch routines. Any help or reference is appreciated. 

 

Thanks! 

12 REPLIES 12
Message 2 of 13
BlackBox_
in reply to: cgentile

Given that LayerState-Restore takes an ENAME parameter, presumably (as I have not tested for myself) there's a chance that ObjectDBX *might* be able to perform this operation, with the use of Vlax-Vla-Object->Ename function... Again, that's *if* this API feature is exposed to ObjectDBX Documents.

 

If not, then the only other way I can think of... Again having not tried, so I could be mistaken... Would be to batch process each drawing by opening as a side Database via ReadDwgFile() in .NET API, cull the applicable Viewport ObjectIds (skipping the first) for each Layout via GetViewports() Method, and then call the RestoreLayerState() Method on each of said ObjectIds.

 

HTH



"How we think determines what we do, and what we do determines what we get."

Message 3 of 13
cgentile
in reply to: BlackBox_

BlackBox, excellent suggestions! I nailed the lisp with help from MSasu on one of CADTutor's old threads (see code).

 

I tried running it with LeeMac's ScriptWriter; although, acad crashes on the third file it runs through. I'm sure it's the large external references that are are overlaid. The uLS lisp is loaded with acaddoc.lsp thanks for that hint!

 

Is there anything other than .NET that can run through a directory and run the routine (not familiar with .net)? Parital open in a lisp - does that exist?

 

(defun c:uLS ( / vportlist vport)
  (layerstate-import "P:\\AutoCAD\\Layer States\\L1.las")
  (if (/= (getvar "ctab") "model")
    (progn
      (setq vportlist (vl-sort (vports) '(lambda (v1 v2) (< (car v1) (car v2)))))
      (if (> (length vportlist) 1)
	(progn
	  (command "_mspace");activate vport
	  (foreach vport (cdr vportlist)
	    (setvar "cvport" (car vport))
	    (layerstate-restore "L1"
	      (vlax-vla-object->ename (vla-get-activepviewport (vla-get-activedocument (vlax-get-acad-object)))) 4);restore
	    );foreach
	  (command "pspace");deactivate vport
	  );progn
	);if
      );progn
    );if
  );defun

 

Message 4 of 13
BlackBox_
in reply to: cgentile

You're welcome; I'm happy to help.

 

Sorry for the delay in getting back to you - I'm actually a CAD production guy by day, and have several deadlines to meet this week. 

 

I did throw some code together in my spare time, but need to do more testing to be certain... In preliminary, it doesn't appear the ObjectDBX will be an option, but I do not receive any exceptions (errors) when calling LayerState-Restore on each Viewport via DBX, so I want to re-confirm.

 

*If* in fact DBX cannot be used to keep this in LISP, I'll look into putting together a .NET option for you.

 

For the time being, this may help with drawings opened in the editor, and will apply the selected layer state to each Viewport, on every Layout (with exception to the first - the Layout), for the current drawing:

 

(vl-load-com)

(defun c:LayerStateRestoreAll (/ *error* ss layouts options lastRestored option acDoc n i found)

  (defun *error* (msg)
    (if acDoc
      (vla-endundomark acDoc)
    )
    (cond ((not msg))                                                   ; Normal exit
          ((member msg '("Function cancelled" "quit / exit abort")))    ; <esc> or (quit)
          ((princ (strcat "\n** Error: " msg " ** ")))                  ; Fatal error, display it
    )
    (princ)
  )

  (if
    (and
      (setq ss (ssget "_x" '((0 . "VIEWPORT"))))
      (< (length (setq layouts (layoutlist))) (sslength ss))
      (setq options (layerstate-getnames))
      (not (initget 
             (setq options
                    (vl-string-right-trim
                      " "
                      (apply
                        'strcat
                        (mapcar (function (lambda (x) (strcat x " ")))
                                options
                        )
                      )
                    )
             )
           )
      )
      (or
        (setq option
               (getkword
                 (strcat
                   "\nEnter layer state to restore to all viewports ["
                   (vl-string-translate " " "/" options)
                   "]"
                   (if (setq lastRestored (layerstate-getlastrestored))
                     (strcat "<" lastRestored ">:")
                     ":"
                   )
                 )
               )
        )
        (setq option
               (cond (lastRestored lastRestored)
                     ((= 1 (length options)) (car options))
               )
        )
      )
    )
     (progn
       (vla-startundomark
         (setq acDoc (vla-get-activedocument (vlax-get-acad-object)))
       )
       (foreach layout layouts
         (setq found (setq ss nil))
         (if (setq ss
                    (ssget "_x" (list '(0 . "VIEWPORT") (cons 410 layout)))
             )
           (progn
             (repeat (setq i (setq n (sslength ss)))
               (if found
                 (layerstate-restore
                   option
                   (ssname ss (setq i (1- i)))
                   4
                 )
                 (setq found (setq i (1- i)))
               )
             )
             (prompt
               (strcat "\nLayer state \""
                       option
                       "\" applied to "
                       (itoa (setq n (1- n)))
                             " viewport"
                             (if (= 1 n)
                               ""
                               "s"
                             )
                             " on \""
                             layout
                             "\" tab. "
                       )
             )
           )
         )
       )
     )
     (cond (ss (prompt "\n** No layer states found ** "))
           ((prompt "\n** No viewports found ** "))
     )
  )
  (*error* nil)
)

 

 

Cheers



"How we think determines what we do, and what we do determines what we get."

Message 5 of 13
edcordner9121
in reply to: cgentile

Hello

I too would love to be able to change layerstates per viewport in each tab, where the tab has more than 1 viewport, bu the layerstate is a differnet one based on the first letter of the TAB name

 

 

A tab may be named P 93     ( Plan that starts at 93+00)

or

A tab may be named s 93     ( Striping that starts at 93+00)

 

so if the LSP open the next tab the viewports in the P xx tab would be layerstate PLAN

and if

the LSP opens the next tab the viewports in the S xx tab would be layerstate Striping

and then

the LSP opens the next tab the viewports in the X xx tab would be layerstate Xsections

 

 

so this LSp would change layerstates based on the TAB 1st letter.

 

I hope this can be done as I now have to visit every darn tab, open the viewports and then

 

I use a button I made with this   ^C^C(layerstate-restore "_PLAN" (acet-currentviewport-ename))

 

Its a real pain for a 4.5 mile road with viewports for each layerstate every 600 feet

 

Thanks for any help / Ed

Message 6 of 13
kylei7449
in reply to: BlackBox_

I have the same situation as the first poster, wanting to be able to update layerstates once through-out the entire drawing. This seems like something Autodesk could fix. Instead of editing one layerstate and then having to go to every viewport that the layerstate pertains to and manually restore is a huge time killer. I should only need to edit a layerstate once and then that should filter to all viewports it applies to. 

 

I tried running this code and it does work, "however" it applies the same layerstate to all viewports--regardless of their current layerstate. Which isn't something I'd want since all viewports have layerstates based on different needs.

 

Can the code be altered so it applies the restore (of the LS you enter at the command line) only if it matches a viewport's current layerstate?

 

Also note: in order for this to run your layerstate names cannot contain any spaces. If they do you'll need to rename them. 

Message 7 of 13
henry
in reply to: BlackBox_

Hi,

I am hoping you can help me. I use ACAD 2016. I am trying to find a lisp routine that could restore a given layer state to all viewports on all layout tabs at the same time. I came across this but when I run it I get this error right after I pick the layer state name that I want to restore.

 

 

Invalid option keyword

 

 

Can you help me? Did I misunderstand the intended use of this lisp?

 

Thank you.

Tags (1)
Message 8 of 13
cgentile
in reply to: henry

Henry, this routine has developed quite a bit in the years. The command runs as part of a script that recognizes the drawing name and associates it with a layerstate name then applies it to each viewport on the layout tab. There's a particular workflow and naming convention associated with this as well. 

 

If you can list out how you prefer this operation to work, I can help you out. 

 

A few comments I gathered from your post: First, a lisp routine will not "run in the background" or operate "all at the same time." If you're looking for something to do this, I suggest looking into .NET. Next, I have not experimented with the routine running on multiple layout tabs, but I believe it cycles through them. Thrid, the layerstate name can vary as long as there is a condition that is unique to each name. Finally, If you're looking to modify the appearance across all viewports, you may want to check out the variable VISRETAIN. 

Message 9 of 13
henry
in reply to: henry

Thank you for your response and willingness to help me. Let me first say that if this becomes too time consuming please feel free to say so.

My disclaimer: I know enough about lisp routines to load and run them and I know they can be very powerful and time saving and that's all I know. 🙂 Being a one man office (and business for that matter) leaves me in the inenviable position of knowing there are things I can learn that would save me time but being unable to take the time to learn them. It's the old, "I can't take time to sharpen the saw because I'm too busy cutting down trees".:)

At your suggestion, I looked at .Net, it's all Greek to me. 🙂

I will list what I am specifically looking for but 1st allow me to explain some of my previous comments because I know my terminology is misused or vague. When I said "running in the background" I meant that it could change the layer states of viewports on multiple layout tabs without actually activating those tabs. For instance the attached lisp keeps the current layout tab active while affecting all instances of the dynamic block "drawing status stamp" regardless of which layout tab it is on.

When I said running on multiple layouts I meant progressively which I believe is the same as you mean when you say cycling through them. This of course is irrelevant if it keeps the current layout tab active while it cycles through the others behind the scenes so to speak (in the background).

My layer state names that I currently use are always:

FP_Submittal
FP_Installation
FP_Sleeves

Regarding your statement about "Visretain". I am familiar with that variable and I always have it set at "1".

The overall goal is to be able to publish my layout tabs with them in a certain layer state without having to activate each tab and restore each individual viewport when I go to publish the work for different phases of the project construction or different purposes as the case may be.


In my perfect world scenario, here is how I would like the lisp to work. First let me say that when I refer to restoring a layer state I am talking about within the model space viewport, not in the paper space view.


1. Allow me to pick the desired layer state I want to restore from a list of available layer states (optionally it would be fine if it just allowed me to type in the layer state name I want to restore).
2. Allow me to select which layout tabs to apply that layer state to from a list of available tab names (optionally it would be fine if it applied it to all layout tabs although that would require that I go manually reset any that I did not need to change)

If it then restored the chosen layer state to the appropriate layout tabs without it actually activating the tab (loss of regen time) that's perfect, if it can't run that way it's still a big improvement over manually going through each tab changing the layout states, publishing the drawings in that state just to have to repeat that process again to publish them in an alternate state. I realize I can accomplish the same thing by having multiple tabs with different sheet names for different states but that just seems archaic. The other issue is that it is not uncommon for me to realize that I did not create the layer state correctly. In that case I could have twice as many layout tabs to restore layer states to manually.

I hope this makes helping me easier.

Thanks again from those of us who can't to those of you who can!:)



Henry Leon Jr.
Managing Member

LEON & ASSOCIATES, LLC
FLORIDA FIRE PROTECTION CONTRACTOR I

Email: Henry@LeonAssociates.com
Website: www.LeonAssociates.com

Cell: 813-504-4510
Message 10 of 13
cgentile
in reply to: henry

Cool, I believe I follow you. Can you send over an example file that has multiple tabs set up with each layerstate saved?

 

I'll relay back what I got from you and see if this matches the overall goal and command processes:

 

There is one drawing with multiple layouts.

 

There are three layerstates saved within the drawing that represent different stages of construction or submittals as the case may be.

 

Your ideal procedure is to...

 

1. be prompted with a list of layerstates saved within the current drawing and user selects the desired layerstate;

 

2. be prompted with a list of layout tabs within the current drawing and users selected the desired layouts;

 

3. the selected layerstate is applied to the user selected layouts.

 

Also, are you using external references, or is all the linework drawn within the current drawing?

Message 11 of 13
henry
in reply to: henry

Sounds like you understand it perfectly. There are always lots of xrefs. I don't know if it matters to you but not only do I keep visretain at 1, I also keep xrefoverride at 1.

Here is a link to the etransmit file.

https://leonassociates.box.com/s/l70e9zu22vm0dhtgwkjewxy0isigbg3k


The drawing is Test FP and is down this path
C:\Users\Henry.User-PC\Box Sync\WORKING\JAMES BLAIR\TEST FP - As Is Folder Structure.zip\DRIVE_C\Users\Henry.User-PC\Box Sync\WORKING\JAMES BLAIR


Thanks again!

Henry Leon Jr.
Managing Member

LEON & ASSOCIATES, LLC
FLORIDA FIRE PROTECTION CONTRACTOR I

Email: Henry@LeonAssociates.com
Website: www.LeonAssociates.com

Cell: 813-504-4510
Message 12 of 13
henry
in reply to: cgentile

Hi,

I replied to your last post on 2/11 but haven't heard back yet. Just checking to see if you even saw that reply.

 

Thanks again.

Message 13 of 13
ebrahim.rawat
in reply to: cgentile

Hi Black box

 

I have 74 layouts with 2 viewport in each one, I need to update the Layer State only in one viewport which is on the top left (Key View).  At the moment I am using the Action Recorder, pick Layer State name & Restore (see attachment) for each layout, can this be batch updated with a lisp routine?

 


Thanks

 

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost