PDA

View Full Version : Print Tabs Names (or export)



mjavy7
18th Apr 2013, 03:38 pm
Hello All.
I need help with AutoCAD 2013
I have multiple drawings with 100's of tabs inside, I would like to either export or print out all of the tab names.

If anyone knows a way to do this, I would love to hear about it.

Thank you in advanced,
Javier

BlackBox
18th Apr 2013, 03:43 pm
Here's a simple example for the active document:



(defun c:Tabs ()
(prompt "\nTab Names: ")
(foreach layout (layoutlist)
(print layout)
)
(princ)
)

mjavy7
18th Apr 2013, 03:58 pm
now how do I use this? LOL
Sorry man, this is a bit over my head.
If you could please explain how to use this code, I would highly appreciate it.
If there is already a place in here were it is explained let me know and I will go there to learn.

BlackBox
18th Apr 2013, 04:13 pm
No worries; we all start somewhere. :beer:

First, to use LISP code posted on forums, simply copy + paste the code into an empty text file, and save with a .LSP file extension. See this tutorial (http://www.afralisp.net/autolisp/tutorials/loading-autolisp-files.php) for loading LISP routines.



After posting that quick sample above, I re-read your post, and saw that you said you're needing to process multiple drawings, so I thought I'd provide a 'Batch Report' routine... Once you've created the LISP file, and loaded the code into your drawing, simply invoke by entering BFINDTABS EXPORTLAYOUT Command.



[Edit :: 2013-04-19]

Modified code to allow for Active (current drawing), or Browse (single/multiple drawing) selection.

I have added a DOSLIB dependency specifically to gain access to multiple file selection offered by DOS_GETFILEM (http://www.en.na.mcneel.com/doslib/index.html) function. Please download DOSLIB here (http://www.en.na.mcneel.com/doslib.htm), and use ARXLOAD (http://docs.autodesk.com/ACD/2014/ENU/files/GUID-965A0D2A-CFD0-4D7C-9D2B-2D8188F0DAC8.htm) to load your version's ARX file.

This modification also provides a LISP callable function BBOX:ExportLayout.

Multiple miscellaneous items corrected as well, such as non-localized variable, and non-essential code included by mistake when pulling from another routine.

Additional handling needed for open / read-only Documents.





(vl-load-com)

(defun BBOX:ExportLayout (dwgs / *error* BBOX:GetDate BBOX:GetTime
BBOX:WriteData acApp oDocuments oShell path
filePath dbxDoc file openDoc oLayouts layoutName
)

(defun *error* (msg)
(if file
(close file)
)
(if oShell
(vlax-release-object oShell)
)
(if dbxDoc
(vlax-release-object dbxDoc)
)
(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)
)

(defun BBOX:GetDate (date)
(setq date (mapcar '(lambda (x) (itoa x)) date))
(strcat (nth 0 date) "-" (nth 1 date) "-" (nth 3 date))
)

(defun BBOX:GetTime (date / hr mn)
(setq hr (nth 4 date))
(setq mn (itoa (nth 5 date)))
(if (= 1 (strlen mn))
(setq mn (strcat "0" mn))
)
(cond ((> 12 hr) (strcat (itoa hr) ":" mn " AM"))
((strcat (itoa (- hr 12)) ":" mn " PM"))
)
)

(defun BBOX:WriteData (path dwg layoutName file / filePath date)
(write-line
(vl-string-right-trim
","
(apply
'strcat
(mapcar
'(lambda (x) (strcat x ","))
(list (setq filePath (strcat path dwg))
(if (setq date (vl-file-systime filePath))
(BBOX:GetDate date)
"{ Read-Only }"
)
(if date
(BBOX:GetTime date)
"{ Read-Only }"
)
layoutName
)
)
)
)
file
)
)

(if (and (setq acApp (vlax-get-acad-object))
(setq oDocuments (vla-get-documents acApp))
(setq oShell (vla-getinterfaceobject
acApp
"Shell.Application"
)
)
(setq path (car dwgs))
(setq filePath
(strcat
(vl-filename-directory
(vl-filename-mktemp)
)
"\\Export Layout Report_"
(menucmd
"M=$(edtime,$(getvar,date),YYYY-MO-DD)"
)
".csv"
)
)
(princ "\nWorking, please wait...")
(princ)
(setq dbxDoc (vla-getinterfaceobject
acApp
(strcat "ObjectDBX.AxDbDocument."
(substr (getvar 'acadver) 1 2)
)
)
)
)
(progn
(setq file (open filePath "w"))
(write-line "Directory Searched:" file)
(write-line path file)
(write-line "" file)
(write-line "Drawing:,Date:,Time:,Layout Name:" file)
(foreach dwg (cdr dwgs)
(if (not (vl-catch-all-error-p
(setq openDoc (vl-catch-all-apply
'vla-item
(list oDocuments dwg)
)
)
)
)
(setq oLayouts (vla-get-layouts openDoc))
(progn
(vl-catch-all-apply
'vla-open
(list dbxDoc (strcat path dwg))
)
(setq oLayouts (vla-get-layouts dbxDoc))
)
)
(vlax-for oLayout oLayouts
(if (/= "Model" (setq layoutName (vla-get-name oLayout)))
(BBOX:WriteData path dwg layoutName file)
)
)
)
(princ "Done.")
(princ)
(setq file (close file))
(vlax-invoke oShell 'open filePath)
(*error* nil)
)
(cond
(filePath
(*error*
"Unable to create \"ObjectDBX.AxDbDocument\" Object"
)
)
(acApp
(*error* "Unable to create \"Shell.Application\" Object")
)
)
)
)

(defun c:ExportLayout (/ opt dwgs)

(initget "Active Browse")
(if
(not
(setq opt
(getkword
"\nWhat drawing would you like to process [Active/Browse]<Active>: "
)
)
)
(setq opt "Active")
)

(cond ((= "Active" opt)
(if (= 1 (getvar 'dwgtitled))
(BBOX:ExportLayout
(list (getvar 'dwgprefix) (getvar 'dwgname))
)
(prompt "\n** Drawing not saved ** ")
)
)
((= "Browse" opt)
(if (setq dwgs
(dos_getfilem
"Select Drawings"
(getvar 'dwgprefix) ;<-- default path here
"Drawing files (*.dwg)|*.dwg"
)
)
(BBOX:ExportLayout dwgs)
)
)
)
(princ)
)


Inspired by a favorite routine of mine, BFIND, from Lee. :)

mjavy7
18th Apr 2013, 04:51 pm
:thumbsup:
You are the man!!
They both work great but I must say the second one is very impressive!!!
This is exactly what I need!!!

BlackBox
18th Apr 2013, 04:55 pm
That is kind of you to say; I'm happy to help :) ... I've had a lot of help along the way.

mjavy7
18th Apr 2013, 09:33 pm
Here's a simple example for the active document:



(defun c:Tabs ()
(prompt "\nTab Names: ")
(foreach layout (layoutlist)
(print layout)
)
(princ)
)


How hard is to make this code export the list to excel like the second code?

BlackBox
18th Apr 2013, 09:34 pm
How hard is to make this code export the list to excel like the second code?

You mean, where it only prompts for a single drawing, rather than a directory of?

Or do you mean no prompt at all; as in it only works on the drawing open when invoked?

BIGAL
19th Apr 2013, 03:48 am
A very simplified version


(defun c:Tabs ()
(setq fname "C:\acadtemp\mytabs")
(setq fo (open fname "w"))
(prompt "\nTab Names: ")
(foreach layout (layoutlist)
(print layout)
(write-line layout fo)
)
(close fo)
(princ)
)
;just open file mytabs in excel

mjavy7
19th Apr 2013, 03:20 pm
You mean, where it only prompts for a single drawing, rather than a directory of?

Or do you mean no prompt at all; as in it only works on the drawing open when invoked?

Either way it works for me, what ever is easier for you. I can work with either.

mjavy7
19th Apr 2013, 03:46 pm
A very simplified version


Thank you.
This one works but adds a few steps to my process. Since I have to do many files, I have to go thru explorer, copy file to different location, rename and modify.
The previous code (BTABS) automatically spits out and excell file ready for saving which makes it more user friendly. I am not trying to discredit your effort....I do appreciate it.

BlackBox
19th Apr 2013, 04:54 pm
Either way it works for me, what ever is easier for you. I can work with either.

Why pick one, when you can do both... Code revised here (http://www.cadtutor.net/forum/showthread.php?78786-Print-Tabs-Names-(or-export)&p=532480&viewfull=1#post532480)... Please read the [Edit ...] Comments closely. :thumbsup:

BlackBox
19th Apr 2013, 04:58 pm
The previous code (BTABS) automatically spits out and excell file ready for saving which makes it more user friendly.


Just to clarify, the code I offered actually generates a .CSV file, and uses Shell.Application to open the resultant file in one's own default application for .CSV files... In your case, that's Excel, others who do not have Office may find that Notepad opens the file, etc.... That's the part I credit my learning to Lee (not that he invented it, the code was there before his time, but I personally learned this 'trick' from him :geek:).

In any event, I hope that makes (more?) sense to you now. :beer:

mjavy7
19th Apr 2013, 07:25 pm
[Edit :: 2013-04-19]

Modified code to allow for Active (current drawing), or Browse (single/multiple drawing) selection.

I have added a DOSLIB dependency specifically to gain access to multiple file selection offered by DOS_GETFILEM (http://www.en.na.mcneel.com/doslib/index.html) function. Please download DOSLIB here (http://www.en.na.mcneel.com/doslib.htm), and use ARXLOAD (http://docs.autodesk.com/ACD/2014/ENU/files/GUID-965A0D2A-CFD0-4D7C-9D2B-2D8188F0DAC8.htm) to load your version's ARX file.


Ok, this is also a bit over my head so here is what I got so far:
1. I created a *.lsp file with the code provided
2. I went to the link and downloaded the DOSLIB files and double cliked in the *.EXE file.
3. In Auto CAD loaded my new *.lsp file and added the folder to the support search path.

The part that looses me is the ARX... is shouls I rename the *.lsp to *.ARX? and in autocad loaded with the ARX command?

BlackBox
19th Apr 2013, 07:48 pm
Ok, this is also a bit over my head so here is what I got so far:
1. I created a *.lsp file with the code provided
2. I went to the link and downloaded the DOSLIB files and double cliked in the *.EXE file.
3. In Auto CAD loaded my new *.lsp file and added the folder to the support search path.

The part that looses me is the ARX... is shouls I rename the *.lsp to *.ARX? and in autocad loaded with the ARX command?

See the ARXLOAD function (linked above) to load DOSLIB's ARX file... Then the dependent function (dos_getfilem) will be available... Either use the DOSLIB Command, or an ARXLOAD call in your Acad.lsp to ensure that DOSLIB's ARX file is loaded each time you start AutoCAD.

** Note - ObjectARX files (C++ for AutoCAD), like .NET assemblies, need only be loaded once per session, so no need to add to AcadDoc.lsp

mjavy7
19th Apr 2013, 08:08 pm
I am doing something work and I dont know what...

Command:
EXPORTLAYOUT
What drawing would you like to process [Active/Browse]<Active>: B
Working, please wait...
** Error: bad argument type: consp nil **
Command:

...I choose the drawing file that I need and it comes back with a bad argument.
Any advise?

BlackBox
19th Apr 2013, 08:35 pm
While successful in my limited tests, I always chose files that were not read-only... It appears that the routine doesn't obtain SysTime on read-only files... Looking at a work around and will post back shortly.

BlackBox
19th Apr 2013, 09:05 pm
Problem fixed. :thumbsup:... Revised code here (http://www.cadtutor.net/forum/showthread.php?78786-Print-Tabs-Names-(or-export)&p=532480&viewfull=1#post532480).



The issue was in handling Documents that were either already open in one's own session, or those read-only (open by others) causing vl-File-SysTime to return Nil. So, I built in some checking for that, but then needed to add some code to check for Documents open in one's own session to also avoid attempts to open a second time (it's already open, and then ObjectDBX tries to open which caused some undesirable results).

Again, all fixed AFAIK, so please let me know what issues (if any) you might encounter... I may come back to streamline a bit, but that will come later. Sorry for any confusion.

Cheers

juanjrvn
28th May 2015, 09:11 pm
Hello!


I know this is a couple years old, but the solution offered by BlackBox works for me. Thank you. Hopefully you're all still around and will respond.


When using the "browse" option, is it possible to select a top-level folder and process all the drawing files within it and all its sub-folders? I have about 27,000 files whose layout tab names I'd like to export, but they exist in a mess of folders, sub-folders, and so on.


Thanks again!


Juan

BlackBox
29th May 2015, 07:25 am
Hello!


I know this is a couple years old, but the solution offered by BlackBox works for me. Thank you. Hopefully you're all still around and will respond.


When using the "browse" option, is it possible to select a top-level folder and process all the drawing files within it and all its sub-folders? I have about 27,000 files whose layout tab names I'd like to export, but they exist in a mess of folders, sub-folders, and so on.


Thanks again!


Welcome to CADTutor! :)

I'm glad you found the code helpful.

Yes, the code could be revised to iterate all drawings in all sub-directories using ObjectDBX, however I would advise against this due to the fact that it would essentially lock up your session, overflowing the memory stack, or even if successful, would take an immeasurable amount of time depending on workstation specs.

That said, it is technically possible using LISP... If you're serious about actually wanting to process that amount of data, I'd instead suggest we power this functionality over to .NET API for performance gains alone, let alone the ability to batch process in parallel (multiple instances at once), in addition to in series (one-at-a-time).

Just turning in for a few hours of shut eye, as I have to be back at the office soon, but wanted to make this quick reply.

Cheers

juanjrvn
29th May 2015, 02:46 pm
Welcome to CADTutor! :)

I'm glad you found the code helpful.

Yes, the code could be revised to iterate all drawings in all sub-directories using ObjectDBX, however I would advise against this due to the fact that it would essentially lock up your session, overflowing the memory stack, or even if successful, would take an immeasurable amount of time depending on workstation specs.

That said, it is technically possible using LISP... If you're serious about actually wanting to process that amount of data, I'd instead suggest we power this functionality over to .NET API for performance gains alone, let alone the ability to batch process in parallel (multiple instances at once), in addition to in series (one-at-a-time).

Just turning in for a few hours of shut eye, as I have to be back at the office soon, but wanted to make this quick reply.

Cheers


Thank you for the welcome and your reply.


I am interested in processing all 27,000 files, but it doesn't necessarily need run together all at once. The folder structure I'd be working with has 15 top-level folders; the largest folder containing about 7,000 drawing files. The rest of the folders each contains less than 3,000 drawing files.


So would it be feasible to run the code 15 times on smaller sets of files? I could even break down the 7,000-file folder if I needed to.


Let me know if I could provide any other piece of information for you to better understand what I'm dealing with here and thank you in advance for your help.


Cheers!


Juan

BlackBox
29th May 2015, 05:03 pm
I am interested in processing all 27,000 files, but it doesn't necessarily need run together all at once. The folder structure I'd be working with has 15 top-level folders; the largest folder containing about 7,000 drawing files. The rest of the folders each contains less than 3,000 drawing files.


So would it be feasible to run the code 15 times on smaller sets of files? I could even break down the 7,000-file folder if I needed to.


Let me know if I could provide any other piece of information for you to better understand what I'm dealing with here and thank you in advance for your help.


It's good that you realize the need to break the task down into smaller groups.

I suppose that implementing the option to include sub-folders wouldn't present an unexpected consumption of time/resources, so long as following the 'root' folder being specified, I first culled the number of drawings that would in fact be processed, and prompt the user an 'are you sure you want to do that' sort of message (if more than 100, 200, N, etc. are found?).

Just thinking out loud so-to-speak, so when I come back after some production deadlines, I know where to pick back up. :geek:

Cheers

juanjrvn
29th May 2015, 05:20 pm
It's good that you realize the need to break the task down into smaller groups.

I suppose that implementing the option to include sub-folders wouldn't present an unexpected consumption of time/resources, so long as following the 'root' folder being specified, I first culled the number of drawings that would in fact be processed, and prompt the user an 'are you sure you want to do that' sort of message (if more than 100, 200, N, etc. are found?).

Just thinking out loud so-to-speak, so when I come back after some production deadlines, I know where to pick back up. :geek:

Cheers


What I'm currently doing, since I cannot change the location of the files in their sub-folders, is using Windows Explorer to search for "*.dwg" then copying all the drawing files from that search result into a new folder without sub-folders. I should then easily be able to run your routine on the copied files in the new folder. That's a good work-around for now, but it would be nice to be able to run the routine on files in their original sub-folders.


I appreciate your help.


Juan