In the last lesson, we begin to worry about user interface enhancements and learn about the Car, Cdr, RtoS, and StrCat functions to our Label.Lsp AutoLISP program. What started out as two lines of code has now bulged out into 23 lines of code. This month, we add the ability to save data to a file and learn how to fight feature bloat.
"The LISP file comes in very handy with some of the programs I use but I would like to be able to save the data collected on the x,y,z coordinates in a text file."
Thanks for the feedback. Saving the data to file is easily done with the (open "a"), (write-line), and (close) functions. Let's take a look at how to do this. Dealing with files in AutoLISP is simpler than for most programming languages because AutoLISP has very weak file access functions. All it can do is read and write ASCII files in sequential order; AutoLISP cannot deal with binary file nor can it access data in random order. While AutoCAD users have often asked for those abilities, Autodesk has chosen not to add them. There are three steps in writing data to a file:
AutoLISP has the (open) function for opening a file. This function lets me open a file for one of three purposes: (1) read data from the file; (2) write data to the file; and (3) append data to the file. I have to choose one of these at a time; I cannot do all three at once. In all three cases, AutoLISP takes care of creating the file if it does not already exist. Reading data is easy enough to understand but what's the difference between "writing" and "appending" data?
For my purposes. I want to keep adding data to the file, so I will choose append mode. The AutoLISP code looks like this:
(setq FIL (open "xyzdata.txt" "a"))
Here I am setting something (setq) to a variable named FIL. What is it? In pretty much all programming languages, I don't deal with the filename directly but instead deal with a "file descriptor." This is a name (some sequenceof letters and numbers) that the operating system assigns the filename. Now that I have the file descriptor stored in variable FIL, I work with FIL, not the filename, which I have decided to call "xyzdata.txt".
The final "a tells AutoLISP we want to open xyzdata.txt for appending data. It is important that the "a" be lowercase; this is the only occasion where AutoLISP is case-sensitive. The options for the open function are:
Option | Meaning |
"a" | Append data to end of file |
"w" | Write data to file (erase existing data) |
"r" | Read data from file |
To write the data to the file, I use the write-line function. This function writes a line of data to the file. (Another function, the write function, writes a single character to the file.) The code looks like this:
(write-line xyz1 fil)
However, I can't just write the raw data to the file because it would look like three decimal points and a lot of numbers:
8.15483.27520.0000
Most software is able to read data that has commas separating numbers, like this:
8.1548, 3.2752, 0.0000
That includes spreadsheets, database programs, and even some word processing software. I tell these programs that when they read the data, they should consider the comma to be a separator and not a comma. In that way, the spreadsheet program places every number in its own cell. With every number in its own cell, I can manipulate the data. For this reason, I need code that formats the data. Fortunately, I've already done that. Last lesson, I used the StrCat function along with the Cdr, Cadr, and Caddr functions to separate the x, y, and z components of the coordinate triplet. So I can reuse the code, which looks like this:
(setq ptx (car xyz) pty (cadr xyz) ptz (caddr xyz) ) (setq xyz1 (strcat ptx ", " pty ", " ptz))
Finally, for good housekeeping purposes, close the file. AutoCAD will automatically close the file for you if you forget but a good programmers cleans up after themself. Closing the file is as simple as:
(close fil)
I now add the code for opening, formatting, writing, and closing to the Lable.Lsp program:
(defun c:label ( / xyz xyz1 uprec ptx pty ptz) (setq uprec (getint "Label precision: ")) (setq xyz (getpoint "Pick point: ")) (setq ptx (car xyz) pty (cadr xyz) ptz (caddr xyz) ) ; Format the x,y,z coordinates: (setq ptx (rtos ptx 2 uprec) pty (rtos pty 2 uprec) ptz (rtos ptz 2 uprec) ) ; Add commas between the three coordinates: (setq xyz1 (strcat ptx ", " pty ", " ptz)) ; Write coordinates to the drawing: (command "text" xyz 200 0 xyz1) ; Open the data file for appending: (setq fil (open "xyzdata.txt" "a")) ; Write the line of data to the file: (write-line xyz1 fil) ; Close the file: (close fil) )
Using a text editor, such as Notepad, make those additions to your copy of Lable.Lsp. Load it into AutoCAD with the Load function:
Command: (load "label")
And run the program by typing Label at the Commandprompt:
Command: label
Label precision: 4
Pick point: [pick]
As you pick points on the screen, the routine labels the picked points but also writes the 3D point data to file. After a while, this is what the data file looks something like this:
8.1548, 3.2752, 0.0000
7.0856, 4.4883, 0.0000
6.4295, 5.6528, 0.0000
5.5303, 6.7688, 0.0000
5.4331, 8.3215, 0.0000
Let's take a moment to go back and revisit our wish list. One wishlist item was to control the layer that text is placed on. There are two ways to approach this wishlist item:
1. The no-code method is to set the layer before starting the AutoLISP function; or,
2. The AutoLISP code version is to ask the user for the name of the layer, then use the system variable CLAYER to set it (much easier than using the Layer command), as follows:
(setq lname (getstring "Label layer: ")) (setvar "CLAYER" lname)
Add those two line before the line with the "Pick point" prompt.
To specify the text style, there are the same two methods as with setting the layer name. The no-code method is to simply set the text style before starting the routine. Otherwise, you can write AutoLISP code similar to the following:
(setq tsname (getstring "Label text style: ")) (setvar "TEXTSTYLE" tsname)
Once again, add those two line before the line with the "Pick point" prompt. By now, you might be noticing that our program is starting to look big. That's called "feature bloat" and explains why ten years ago AutoCAD used to fit on a single floppy disk but now takes up 40MB of disk space. More features, especially in the area of user interface, makes software grow far beyond the size of its basic algorithm.
Comments on this tutorial series? Tell me about it.
Return to home page.