Lisp script to generate list of all layouts / table of contents as a csv

Lisp script to generate list of all layouts / table of contents as a csv

studiomaybebxl
Participant Participant
2,066 Views
24 Replies
Message 1 of 25

Lisp script to generate list of all layouts / table of contents as a csv

studiomaybebxl
Participant
Participant

Hi forum

 

Below is a lisp I use to generate a .csv list of all layouts that exist in the active document to a subfolder in the same directory named "table of contents". 

 

The problem with this lisp is that is that the layouts are listed alphabetically instead of following the order in which they are organized in the dwg. 

 

Can somebody help me to transform the lisp into following the document order, so I can actually consider this list as a table of contents? Thanks!

 

(defun c:ExportLayoutsToCSV ()
(if (not (vl-load-com)) (vl-load-com)) ; Load COM support if not already loaded

;; Get the full path of the active document
(setq doc (vla-get-ActiveDocument (vlax-get-Acad-Object)))
(setq doc-path (vlax-get-property doc 'Path))
(setq doc-name (vlax-get-property doc 'Name))

;; Ensure the document path exists
(if doc-path
(progn
;; Construct the "table of contents" folder path
(setq toc-folder (strcat doc-path "\\table of contents"))

;; Check if folder exists, if not create it
(if (not (vl-file-directory-p toc-folder))
(vl-mkdir toc-folder)
)

;; Construct the CSV file path
(setq csv-file-name (strcat "Table of Contents - " (vl-filename-base doc-name) ".csv"))
(setq csv-file-path (strcat toc-folder "\\" csv-file-name))

;; Get the list of layout names
(setq layout-list (layoutlist))

;; Open file for writing
(setq file-handle (open csv-file-path "w"))
(if file-handle
(progn
;; Write the layout names to the file
(foreach layout layout-list
(write-line layout file-handle)
)
(princ (strcat "\nLayout names exported to: " csv-file-path))
(close file-handle)
)
(princ "\nError: Unable to open file for writing.")
)
)
(princ "\nError: Unable to determine the document path.")
)
(princ) ; Suppress return value in the command line
)

0 Likes
Accepted solutions (2)
2,067 Views
24 Replies
Replies (24)
Message 2 of 25

paullimapa
Mentor
Mentor
Accepted solution

Maybe try replacing this line:

 

;; Get the list of layout names
(setq layout-list (layoutlist))

 

with these:

 

; getLayoutOrderList retrieves layout names by order they're positioned in dwg
; https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/retrieve-layout-names-by-order-of-which-they-sit-to-populate-in/td-p/10117384
(defun getLayoutOrderList( / lst mklist mappend flatten)
	(defun mklist (x) (if (listp x) x (list x)))
	(defun mappend (fn lst)(apply 'append (mapcar fn lst))) 
	(defun flatten (expr)(mappend 'mklist expr))
	(vlax-for lay 
		(vla-get-layouts (vla-get-activedocument (vlax-get-acad-object)))
		(setq lst (cons (list (vla-get-taborder lay)(vla-get-name lay)) lst))
	)
	(cdr(flatten(mapcar 'cdr (vl-sort lst '(lambda (a b) (< (car a)(car b)))))))
)

;; Get the list of layout names in tab order
(setq layout-list (getLayoutOrderList))

 

 


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes
Message 3 of 25

studiomaybebxl
Participant
Participant
Accepted solution

Hi, thanks for the input.

This seems to work for Autocad LT

0 Likes
Message 4 of 25

paullimapa
Mentor
Mentor

Unfortunately, I'm running on AutoCAD and not LT. Perhaps others can jump in here to confirm if this function would cause that error on LT:

(defun getLayoutOrderList( / lst mklist mappend flatten)
	(defun mklist (x) (if (listp x) x (list x)))
	(defun mappend (fn lst)(apply 'append (mapcar fn lst))) 
	(defun flatten (expr)(mappend 'mklist expr))
	(vlax-for lay 
		(vla-get-layouts (vla-get-activedocument (vlax-get-acad-object)))
		(setq lst (cons (list (vla-get-taborder lay)(vla-get-name lay)) lst))
	)
	(cdr(flatten(mapcar 'cdr (vl-sort lst '(lambda (a b) (< (car a)(car b)))))))
)

Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes
Message 5 of 25

paullimapa
Mentor
Mentor

just to rule out any typos, can you copy and paste the following directly onto the command line in LT to see what it returns?

(defun getLayoutOrderList( / lst mklist mappend flatten)
	(defun mklist (x) (if (listp x) x (list x)))
	(defun mappend (fn lst)(apply 'append (mapcar fn lst))) 
	(defun flatten (expr)(mappend 'mklist expr))
	(vlax-for lay 
		(vla-get-layouts (vla-get-activedocument (vlax-get-acad-object)))
		(setq lst (cons (list (vla-get-taborder lay)(vla-get-name lay)) lst))
	)
	(cdr(flatten(mapcar 'cdr (vl-sort lst '(lambda (a b) (< (car a)(car b)))))))
)(GETLAYOUTORDERLIST)

Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
Message 6 of 25

paullimapa
Mentor
Mentor

glad that worked out for you...cheers!!!


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
Message 7 of 25

studiomaybebxl
Participant
Participant

Thank you this works very well on autocad LT! It gives me back a list with the layouts in the correct order

0 Likes
Message 8 of 25

paullimapa
Mentor
Mentor

you are welcome...cheers!!!


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes
Message 9 of 25

studiomaybebxl
Participant
Participant

Hi @paullimapa 

 

If you don't mind me asking,

 

Would you see a way to extend this script with an additional feature that generates an extra column in the CSV containing the title of each layout? The user will need to write the title somewhere on the corresponding layout in text or mtext format on a specific designated layer. 

 

Thank you for helping me out so far!

0 Likes
Message 10 of 25

paullimapa
Mentor
Mentor

Isn’t the title of the layout the same as the layout name?  If not where is the title on each layout coming from?


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes
Message 11 of 25

studiomaybebxl
Participant
Participant

Ah yes, I see how this is confusing.

 

In fact the layout name is actually an abbreviation of the actual title. We tend to keep those compact to have a better overview of the layouts when working in the document. The full title is always a bit longer and clarifies the set layout more specifically. We have it on a set spot on each layout tab inserted as text / mtext.

 

So I was thinking if we stick to using a designated layer for these full titles, it might be somehow achievable to also export these in a separate column in the .csv in the same lisp-routine. That way the csv will show rows of 2 columns with both the layout-name as well as the corresponding full title.

0 Likes
Message 12 of 25

paullimapa
Mentor
Mentor

Yes, using a designated layer where only that Text/MText object would be placed in each layout would work.

Or you create a Block that has an Attribute that contains the Title inserted once in each layout.

This would be another way to select and filter that out per layout.


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes
Message 13 of 25

Sea-Haven
Mentor
Mentor

Best way to go "Or you create a Block that has an Attribute that contains the Title"

 

The attached makes a dwg index as a table reading all layouts and getting values from the title block in each layout may be useful. You will need to edit to suit your title block.

 

0 Likes
Message 14 of 25

studiomaybebxl
Participant
Participant

@Sea-Haven 

 

Thank you for the lisp. I have been trying to use it and managed to setup the value of the DRG_NO (drawing number attribute) as the "ctab" field. It still works as intended, great!

 

However, when it comes to the order in which the rows of the table are generated, it seems like it is also doing it alphabetically, instead of following the order of how the layouts are organized in the document.

 

Do you see a way on how to adjust the lisp to genrate a list where the rows are ordered following the document layout order?

0 Likes
Message 15 of 25

Sea-Haven
Mentor
Mentor

To get the layouts in the visual order it should work if you use (layoutlist) it returns a list of the layout names in correct order. need a foreach loop making the selection set.

 

I wrote the program like 5 years ago so will look at updating. Added to my to list.

 

0 Likes
Message 16 of 25

paullimapa
Mentor
Mentor

I’ve used this function in case you want to keep the order as positioned within the drawing

 ; getLayoutOrderList retrieves layout names by order they're positioned in dwg
; https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/retrieve-layout-names-by-order-of-which-they-sit-to-populate-in/td-p/10117384
 (defun getLayoutOrderList( / lst mklist mappend flatten)
	(defun mklist (x) (if (listp x) x (list x)))
	(defun mappend (fn lst)(apply 'append (mapcar fn lst))) 
	(defun flatten (expr)(mappend 'mklist expr))
	(vlax-for lay 
		(vla-get-layouts (vla-get-activedocument (vlax-get-acad-object)))
		(setq lst (cons (list (vla-get-taborder lay)(vla-get-name lay)) lst))
	)
	(cdr(flatten(mapcar 'cdr (vl-sort lst '(lambda (a b) (< (car a)(car b)))))))
 )

Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes
Message 17 of 25

Sea-Haven
Mentor
Mentor

Thanks @paullimapa something like this. Will look at updating.

(setq bname "DA1DRTXT")
(setq lst '())
(vlax-for lay 
		(vla-get-layouts (vla-get-activedocument (vlax-get-acad-object)))
		(setq lst (cons (list (vla-get-taborder lay)(vla-get-name lay)) lst))
	)
(setq lst (vl-sort lst '(lambda (a b) (< (car a)(car b)))))
(setq ssl (ssadd))
(foreach val lst
  (if (= (car val) 0)
  (princ)
  (progn
   (setq ss (ssget "X" (list (cons 0 "INSERT")(cons 2 bname)(cons 410 (cadr val)))))
   (setq ssl (ssadd (ssname ss 0) ssl))
  )
)
)

  

0 Likes
Message 18 of 25

studiomaybebxl
Participant
Participant

Hi, I find it difficult to combine these functions, I don't seem to get it to work and get the layout order right with my limited understanding of it. Also one thing I noticed is that the Dwgindex lisp only works succesfully if each individual layout has been opened during the session. Layouts that were not accessed during the session will be skipped in the eventual table. Curious to know if you're aware of this? It is mostly a bit inconvenient when you have lots of layouts, and don't necessarily open each one individually each session...

0 Likes
Message 19 of 25

studiomaybebxl
Participant
Participant
I assume this is the best method to continue to achieve incorporating more detailed title text in the .csv file, but I struggle a bit with finding the right strings of code here. Do you think you could elaborate a bit more on how to include such a filter system to generate title information using a custom text attribute? Thanks
0 Likes
Message 20 of 25

paullimapa
Mentor
Mentor

That will depend on what method you’ve decided to go with to store the longer title in each layout. Are you going with Text object on a specific layer or block with attribute?  Perhaps share a sample dwg with multiple layouts so we can all test


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes