Layout Names

Layout Names

h_s_walker
Mentor Mentor
1,665 Views
19 Replies
Message 1 of 20

Layout Names

h_s_walker
Mentor
Mentor

Is there a way to put the first layout tab name into a field, and the same with the last layout tab in a drawing, and automatically change them if the order / name of the tab changes?

I'm using LT2025

Howard Walker
Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.

EESignature


Left Handed and Proud

0 Likes
Accepted solutions (1)
1,666 Views
19 Replies
Replies (19)
Message 2 of 20

DGCSCAD
Collaborator
Collaborator

Something like this?

 

https://www.lee-mac.com/layoutfield.html

AutoCad 2018 (full)
Win 11 Pro
0 Likes
Message 3 of 20

h_s_walker
Mentor
Mentor

Not quite. I have been looking at that to try to see how it works.

Our layouts are typically labelled as A2_1234-1 to A2_1234-100 (that's only an example)

We have text in our drawings as below

REPORT No. XX ACCOMPANIES THIS DRAWING.
A TOTAL OF XX DRAWING(S) ARE INCLUDED WITH THIS
REPORT, Dwg. No's XXXX-1 TO -3

I want to change the XXXX-1 to the first layout name and the -3 to the last layout name, but if the layouts change I want the references to update as well.

eg. XXXX-1 TO -3 becomes 1234-1 to 1234-100. Yes I know the A2 bit is missing I just want to get it started first before I start fiddling with removing characters.

and if the 1234 changes to 5678 the text will become 5678-1 to 5678-100 (with a regen)

 

EDIT: I forgot to mention this text is in model space and in shown in each layout via a viewport

 

Howard Walker
Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.

EESignature


Left Handed and Proud

0 Likes
Message 4 of 20

DGCSCAD
Collaborator
Collaborator

Minimally tested...

 

Run this, then set your text field to the variable layup_full and run it when ever the layouts change.

 

 

(defun c:layup ( / ct layup-first layup-last)
(setq ct (length (layoutlist)))
(foreach n (layoutlist)
	(if (= (wcmatch n "*-1") T) (setq layup-first n))
	(if (= (wcmatch n (strcat "*-" (itoa ct))) T) (setq layup-last n))
)
(if (and (/= layup-first nil) (/= layup-last nil))
	(setq layup_full (strcat layup-first " TO " layup-last))
)
(command "REGENALL")
(princ)
)

 

 

AutoCad 2018 (full)
Win 11 Pro
0 Likes
Message 5 of 20

Moshe-A
Mentor
Mentor

@h_s_walker  hi,

 

check this lisp. it's based on layout reactor. save this code to say misc.lsp file and add it to your appload. instead of using simple text you should move to a block and attributes. attached report.dwg, it's a block with 3 attributes where the 3th (tag=line3) attributes is to be changed according layout name. you can insert report block in model space \ paper space or both.

 

all you have to do to activate this lisp is to switch layout and if the lisp was loaded and it finds report block(s) it will do the job 😀

 

enjoy

Moshe

 

 

; callback
(defun OnLayoutSwitch (Reactor layName^ / _first_numeric ; local function
		                          adoc layouts ss AcDbLayout firstLay lastLay ename val p)

 ; anonymous function
 (setq _first_numeric (lambda (s i) (vl-some (function (lambda (n) (setq i (1+ i)) (if (and (>= n 48) (<= n 57)) i))) (vl-string->list s))))
  
 (setq adoc (vla-get-activedocument (vlax-get-acad-object)))
 (setq layouts (vla-get-layouts adoc))

 (if (setq ss (ssget "_x" '((0 . "insert") (2 . "report") (66 . 1))))
  (progn
   (vlax-for AcDbLayout layouts 
    (cond 
      ((= (vla-get-taborder AcDbLayout) 1)
       (setq firstLay (vla-get-name AcDbLayout))
      ); case
      ((= (vla-get-taborder AcDbLayout) (vl-list-length (layoutlist)))
       (setq lastLay (vla-get-name AcDbLayout))
      ); case
    ); cond

    (vlax-release-object AcDbLayout) 
   ); vlax-for

   (foreach ename (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss)))
    (if (and
	  (setq val (getpropertyvalue ename "line3"))
	  (or
	    (setq p (vl-string-search "XXXX" (strcase val)))
            (setq p (_first_numeric val -1))
	  )
	)
     (setpropertyvalue ename "line3" (strcat (substr val 1 p) (substr firstLay 4) " to " (substr lastLay 4)))
    ); if
   ); foreach
   
  ); progn
 ); if
  
 (vlax-release-object layouts)
 (vlax-release-object adoc)
); OnLayoutSwitch


(if (not miscReactor)
 (setq miscReactor (vlr-miscellaneous-reactor nil '((:vlr-layoutSwitched . OnLayoutSwitch)))) ; install Reactor
)

 

 

0 Likes
Message 6 of 20

h_s_walker
Mentor
Mentor

@DGCSCAD Unfortunately I get a error bad function when I run your lisp

@Moshe-A Unfortunately your lisp will not run. Can you make it LT friendly or is that not possible?

Howard Walker
Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.

EESignature


Left Handed and Proud

0 Likes
Message 7 of 20

Moshe-A
Mentor
Mentor

@h_s_walker 

 

I think visual lisp / activex does not support in LT. 

0 Likes
Message 8 of 20

DGCSCAD
Collaborator
Collaborator

@h_s_walker the routine assumes that you have at least 2 layouts named as XXXX-1 and XXXX-# (any number incrementing above -1). The XXXX's can be anything, but there must be a -1 and an ending -#. Also, the number of layouts must match the numbering sequence (if you have 4 layouts, the increments must be -1 -2 -3 -4).

 

Layup1.png

 

Layup2.png

 

Thats about as close as I can get it at the moment.

 

I do like Moshe-A's approach. 

AutoCad 2018 (full)
Win 11 Pro
0 Likes
Message 9 of 20

h_s_walker
Mentor
Mentor
Accepted solution

Thanks for all the help. I've managed to sort out almost what I wanted to do (no automatic updating)

(defun c:UpdateDrawingNos ()
(setq listlayouts (layoutlist))  
  (setq firstLayout (car listlayouts)) ; Get the first layout
    (setq lastLayout (last listlayouts)) 
    (setq firstlayout (substr firstlayout 5)) 
    (setq lastlayout (substr lastlayout 5)) 
    ;; (princ (strcat "The first layout name is: " firstLayout))
    ;; (princ (strcat "The last layout name is: " lastLayout))
(command "regenall")
  (princ) ; Exit quietly
)

Howard Walker
Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.

EESignature


Left Handed and Proud

0 Likes
Message 10 of 20

DGCSCAD
Collaborator
Collaborator

Just a heads -up: The order of (layoutlist) changes each time a layout is renamed.

 

Type (layoutlist) at the command line and note the order.

Rename any Layout and then type (layoutlist) at the command line again to see.

AutoCad 2018 (full)
Win 11 Pro
0 Likes
Message 11 of 20

DGCSCAD
Collaborator
Collaborator

Here's a simple test, seeing the differences between (layoutlist) and vla-get-taborder (which is Moshe-A's approach):

 

Command: (layoutlist)
("1234-1" "1234-2" "1234-3" "1234-4" "1234-5")

Command: *Cancel*

Command: *Cancel*

Command: <Switching to: 1234-1>

Layout 1234-1 was changed here to 1235-1
Restoring cached viewports - Regenerating layout.

Command: (layoutlist)
("1234-2" "1234-3" "1234-4" "1234-5" "1235-1")

Command: (vlax-for lay (vla-get-layouts (vla-get-activedocument (vlax-get-acad-object))) (setq lst (cons (cons (vla-get-name lay) (vla-get-taborder lay)) lst)))
(("Model" . 0) ("1235-1" . 1) ("1234-5" . 5) ("1234-4" . 4) ("1234-3" . 3) ("1234-2" . 2))

AutoCad 2018 (full)
Win 11 Pro
0 Likes
Message 12 of 20

DGCSCAD
Collaborator
Collaborator

I did find this: https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/layout-order/td-p/3749964 

 

(defun Layorder (/ order)(vl-load-com)
      (vlax-for
             lay (vla-get-layouts (vla-get-ActiveDocument (vlax-get-acad-object)))
            (setq order (cons
                              (list (vla-get-name lay)
                                    (vla-get-taborder lay))
                              order
                              )
                  )
            )
      (mapcar 'car (Cdr (vl-sort order '(lambda (j k)
                        (< (cadr j) (cadr k))
                        )
                 )
           )
      )
      )

 

Comparison after running the above:

 

Command: LAYORDER
("1235-1" "1234-2" "1234-3" "1234-4" "1234-5")

Command:
Command: (layoutlist)
("1234-2" "1234-3" "1234-4" "1234-5" "1235-1")

 

Run the Layorder function, then apply the same CAR and LAST calls to that list instead of using (layoutlist).

AutoCad 2018 (full)
Win 11 Pro
Message 13 of 20

h_s_walker
Mentor
Mentor

@DGCSCAD That looks like it could be very helpful

I shall give it a test

Yep that worked cheers.

 

 

Howard Walker
Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.

EESignature


Left Handed and Proud

0 Likes
Message 14 of 20

DGCSCAD
Collaborator
Collaborator

Cheers 🙂

AutoCad 2018 (full)
Win 11 Pro
0 Likes
Message 15 of 20

Sea-Haven
Mentor
Mentor

Just a comment you can use taborder in a field so an attribute/text etc can reflect the layout number, and the text part can be added as part of the field. No need for any code.

 

The taborder may not be supported in other CAD software, it is on their to do list hopefully in new version now available. Will down load soon.

0 Likes
Message 16 of 20

Moshe-A
Mentor
Mentor

@h_s_walker ,

 

Turn out if you are willing to deep dig inside drawing database you might find

alternate method to VisualLISP\ActiveX 😀

 

So here is an update to my version, check it out and tell me if LT can run it?

(pure AutoLISP code no VisualLisp \ ActiveX)

the only drawback...you need to manually invoke LAYUPD command after reorder layout tabs.

reminder:

you have to use "report" block with attributes (attached again)

 

enjoy

Moshe

 

 

 

(defun c:layupd (/ _first_numeric _get_layouts _taborder _working_layouts ; local functions
		    adoc ss layouts^ firstlay lastLay ename val p)

; anonymous function
 (setq _first_numeric (lambda (s i) (vl-some (function (lambda (n) (setq i (1+ i)) (if (and (>= n 48) (<= n 57)) i))) (vl-string->list s))))
  
 ; anonymous function
 (setq _get_layouts (lambda () (vl-remove-if-not (function (lambda (item) (member (car item) '(3 350))))
                               		         (entget (cdr (assoc '350 (member '(3 . "ACAD_LAYOUT") (entget (namedobjdict))))))
			       )
		    )
 ); get_layouts

 ; anonymous function
 (setq _taborder (lambda () (vl-sort (mapcar (function (lambda (item) (cons (car item) (cdr (assoc '71 (entget (cadr item))))))) (_working_layouts))
  				    (function (lambda (e0 e1) (< (cdr e0) (cdr e1)))))))

 ; chop Model tab
 (defun _working_layouts (/ lst0 lst1 i dxf003 dxf350 l)
  (setq lst0 (_get_layouts))
  (setq i 0 dxf003 (nth i lst0) dxf350 (nth 1 lst0) l (vl-list-length lst0))

  (while (< i l)
   (if (not (eq (cdr dxf003) "Model"))
    (setq lst1 (cons (list (cdr dxf003) (cdr dxf350)) lst1))
   ) 
  
   (setq i (+ i 2))
   (setq dxf003 (nth i lst0) dxf350 (nth (1+ i) lst0))
  ); while

  lst1
 ); _working_layouts
 

 ; here start c:layupd
 (setq adoc (vla-get-activedocument (vlax-get-acad-object)))
 (vla-startUndoMark adoc) 
  
 (if (and
       (setq ss (ssget "_x" '((0 . "insert") (2 . "report") (66 . 1))))
       (setq layouts^ (_taborder))
     )
  (progn
   (setq firstLay (caar layouts^))
   (setq lastlay (car (last layouts^)))
 
   (foreach ename (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss)))
    (if (and
	  (setq val (getpropertyvalue ename "line3"))
	  (or
	    (setq p (vl-string-search "XXXX" (strcase val)))
            (setq p (_first_numeric val -1))
	  )
	)
     (setpropertyvalue ename "line3" (strcat (substr val 1 p) (substr firstLay 4) " to " (substr lastLay 4)))
    ); if
   ); foreach
  ); progn
 ); if

 (vla-endUndoMark adoc)
 (vlax-release-object adoc)

 (princ) 
); c:layupd

 

 

 

0 Likes
Message 17 of 20

Moshe-A
Mentor
Mentor

@h_s_walker ,

 

fix a bug, use the attached file.

 

 

0 Likes
Message 18 of 20

h_s_walker
Mentor
Mentor

@Moshe-A It's a nice idea. Thank you for trying to help, but I should have mentioned this a the start. All the text is in a table, and sometimes we don't need the lines saying how many drawings.

I did try your lisp out though and it does mostly work with one little niggle. I renamed the layouts and ran it and it worked. I then swapped the layouts around and the below happened

h_s_walker_0-1730712464597.png

 

Howard Walker
Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.

EESignature


Left Handed and Proud

0 Likes
Message 19 of 20

Moshe-A
Mentor
Mentor

@h_s_walker ,

 

first, attached is an update (a bit shorter code) 😀

 

second if the text is inside a table then give me the info how i can access this text inside that table. the command can pause to ask you to pick the table but which row, column i should go?

 

third post a sample dwg with the niggle so i can check.

specify the layout names before and after.

 

Moshe

 

 

0 Likes
Message 20 of 20

h_s_walker
Mentor
Mentor

Thanks for your efforts @Moshe-A , but I've got what I need now

Howard Walker
Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.

EESignature


Left Handed and Proud

0 Likes