Seek and Ye Shall Find: Quickly Locate AutoCAD Files That Contain Specific Entities25 Oct, 2012 By: Bill Fane
Learning Curve tutorial: AutoLISP routine makes short work of an otherwise arduous task.
It was a warm and sunny day. Captain LearnCurve and his gorgeous wife were staying at their summer cabin at the lake. They were relaxing between waterskiing runs, idly watching a great blue heron soaring by. The only cloud in the sky had a pointed shape … that’s it!
The topic for this article: point clouds! No, this article won’t be about AutoCAD point clouds and how they work, but instead will be a learned treatise on how to automatically search through a set of drawings looking for entities that meet certain criteria.
I say again: Huh?
It all started with an e-mail from reader Dave Sasko. His problem was that he had a large number of drawing files spread through a complex folder structure, and he needed to find those files that contained at least one of the new point cloud entities. This article will show you how easy it is to find drawings that contain any particular type of entity, or even entities with specific characteristics. For example, if you need to find all drawings that contain a 12-inch-diameter circle that lives on layer "Cake," then stick around to see how easy it is.
Where to Begin
Finding drawings that contain specific entities is a very simple 4-step process:
- First, we need to create a trivial AutoLISP program that specifies our search criteria.
- Next, we use a good old-fashioned DOS command to create a list of all the drawing files in the folders to be searched.
- We then use Notepad to turn the file list into an AutoCAD "script."
- Finally, we run the script in AutoCAD. It opens every file in turn and the AutoLISP program checks for the desired entities. If it finds any, then the file name is added to the end of a log file, the drawing is closed, and the script moves on to open the next drawing. When the script has finished, then the log file is a simple text file that lists all the target drawings.
Needle, Meet Haystack
Let’s start with the ACADDOC.LSP file: You can either create it yourself using Notepad, or you can download it from the Cadalyst CAD Tips site. Let’s look for files that contain at least one XLine. If you don’t have any, it’s easy to create a sample or three.
(princ "\nEntity Finder by Bill Fane 28 Aug 2012\n") ;; This program searches a drawing for the specified entity type and/or properties. ;; If it finds any, it opens a log file and appends the full ;; path and file name to the end of the file. ;; If it doesn't find any it simply moves on without reacting. (if ;; start of IF (ssget "x" '( (0 . "xline") ;;Object type &/or properties to find. ) ) (progn ;; start of THEN (setq FH (open "c://foundfiles.txt" "a") ;; Name & location of log file. ) (write-line ;; write out to the log file... (strcat (getvar "dwgprefix") ;; …path to drawing file, plus (getvar "dwgname") ;; …drawing file name ) FH ) (close FH) (princ "\nYes!\n") ;; Lets you know it found something ) (princ "\nNo.\n") ;; ELSE it didn't ) (princ)
Probably the single most powerful command in any programming language is the If–Then–Else sequence, because it allows the program to make decisions based on information that is fed to it. The basic operation is that If certain conditions are met, Then take one action, but if they aren’t met, then do something Else. Note that the Else can often be left out; if the conditions aren’t met, then do nothing.
Here’s an example of the If–Then relationship at work: A wife sends her programmer husband to the store. "Buy a quart of milk, and if they have eggs then get a dozen." He returns with twelve quarts of milk. "Why on earth did you buy twelve quarts of milk?" she asks. "Because they had eggs," he replies.
In our case, the If condition is:
(ssget "x" '( (0 . "xline") ) )
In AutoLISP, the (ssget) (Selection Set GET) function is used to get a selection set of entities that meet the specified criteria. The (0 . "xline") expression tells ssget to build a selection set that is composed of all the XLine entities in the drawing.
Now for the cunning part: We don’t really care about the specific entities. All we want to know is if one or more exists. If they do, then a valid selection set is created, and the If statement moves on to perform the Then operations. If (ssget) returns nil (no selection set), then Else kicks in.
Okay, so what happens if a selection set of one or more XLines does exist? It's simple: The program creates a "file handle" by opening a log file called "c://foundfiles.txt" in Append mode, concatenates (adds together) the path to the current drawing file plus the name of the drawing file itself, writes this information out and adds it to the end of the log file, closes the log file, and carries on. If there are no XLines in the drawing, then the AutoLISP program simply terminates.
So far so good, but now we have to get the ACADDOC.LSP program to run in every drawing file. No problem; simply copy the ACADDOC.LSP file into a folder that is in AutoCAD’s search path. You can find the list of folders that AutoCAD searches when looking for support files by clicking on AutoCAD’s Application menu (the big red A), then the Options button, then the Files tab, and expanding the Support Files Search Path. (For best results, put it in a folder at or near the top of the list, or add a new folder and move it to the top, because AutoCAD searches for support files from the top down and uses the first one it finds.)
The file ACADDOC.LSP doesn’t normally exist, but AutoCAD searches for it anyway every time it opens a drawing file. If it finds it, then it loads and runs the program it contains.
You can test it by opening several files, some of which contain XLines and others that don’t. Press F2 after you open each drawing to bring up AutoCAD’s text screen and it will include "Yes!" or "No" as appropriate. Now open the log file using Notepad, and hey, presto, it contains a list of the drawings that contain one or more XLines!
It could be very tedious to manually open each drawing in turn, so now comes the really cunning bit. You need to know (or you need to know some old fart who knows) two good old-fashioned DOS commands.
At the AutoCAD Command: prompt, enter the Shell command. When it prompts you for "OS command:" just press Enter. You are now facing an old-style, pre-Windows system command prompt. If you don’t want your search to start in the default folder, then use the CD (Change Directory) command to navigate to the top-level folder where you want the search to start. For example, to search all folders on network drive J: starting at \Data\Projects, enter the DOS command:
to change to the network drive and then
to go to the desired folder. Now issue the DOS command
DIR *.dwg /s /b > find.scr
Nothing seems to happen for a while, depending on how many files in how many folders are involved, but eventually the DOS command prompt will return. Enter the DOS command EXIT to return to AutoCAD.
Next, use Notepad to open the find.scr file. It will be located in the folder from which you started the DIR command in the previous step, and will contain a brief listing of every DWG file in all the sub-folders below the current one.
It will look something like this:
N:\Data\Projects\doughnut.dwg N:\Data\Projects\Ordinate dims.dwg N:\Data\Projects\Target.dwg N:\Data\Projects\Water shutoff.dwg
Now use Notepad’s Edit > Replace function twice, as follows:
Find what: N:\
Replace with: open "N:\
Find what: .dwg
Replace with: .dwg" close
Your file will now look something like this:
open "N:\Data\Projects\doughnut.dwg" close open "N:\Data\Projects\Ordinate dimensions.dwg" close open "N:\Data\Projects\Target.dwg" close open "N:\Data\Projects\Water shutoff.dwg" close
Save the file and exit from Notepad. Now, back to AutoCAD. Start the Scipt command and browse to the find.scr file. Select it, then watch in awe as AutoCAD sequentially opens every drawing file in turn in the log file, runs ACADDOC.LSP, and then closes each drawing. Depending on the number and size of files involved you may want to go for coffee, lunch, home for the night, or to your cabin at the lake for the weekend.
When you return, the c:\foundfiles.txt log file will contain a list of all drawings that contain at least one AutoCAD XLine entity.
Now for a Few Crunchy Bits
First, this includes no error checking. For example, if AutoCAD opens a file and can’t find a required support file such as a font file or an xref, then everything grinds to a sickening halt. If this happens, tell AutoCAD to ignore the problem and everything will resume from where it left off.
Next, if you run it again then it simply keeps on adding to the log file, even if the file already exists in the log file. The solution is to simply delete the log before each run of the find.scr file.
Note: The ACADDOC.LSP program will run every time you open any file unless you delete it, rename it, or move it out of AutoCAD’s search path.
Finally, if you want to edit the ACADDOC.LSP file to change the name or location of the output log file, you must use two forward slashes as folder delimiters (not the single backslash that DOS uses).
And Now for the Bonus Round
You can edit ACADDOC.LSP to search for any entity type with any properties. For example:
(ssget "x" '( (0 . "circle") (8 . "Cake") ) )
will find any drawing that has one or more circles on the layer named Cake. The (number . value) format is known as a Group, and is based on AutoCAD’s DXF (Drawing eXchange Format) file format. The item to the left of the dot is always a whole number, while the value to the right might be a whole number, a decimal number, or a text string depending on the whole number to the left. Each entity in the drawing is defined by a series of group codes that specify its type, layer, location, and so on. There are about 500 group codes, but a very few will cover most of your needs.
You can easily build searches with multiple filters, all of which must be met to return "true." For example:
(ssget "x" '( (0 . "circle") (8 . "Cake") (40 . 2.5) ) )
will find all circles on layer "Cake" with a radius of 2.5 units, but will ignore other circles on the same layer if their radius isn’t 2.5 units.
Conversely, it isn’t necessary to have an entity type. For example:
(ssget "x" '( (8 . "Cake") ) )
will return "true" if layer "Cake" contains any entities of any type, or "false" if it is completely empty.
In closing, here’s a quick trick that can help in defining your search criteria. Simply enter the expression (entget (car (entsel))) at AutoCAD’s Command prompt, then select an entity. The text screen will now display all the group codes and specific values that define the selected object.
And Now for Something Completely Different
If you own an older, high-powered two-stroke outboard motor that incorporates oil injection, you should replace the tubes between the reservoir, the oil pump, and the fuel system because they get brittle with age and can crack. When you do so, it is extremely important to purge the air from the tubes before running the engine or else you could end up spending several thousand dollars for parts plus the first two weeks of the summer waterski season frantically doing a total rebuild of the engine yourself (which is still a lot cheaper than buying a new four-stroke engine).