Table Access |
This lesson explains tables, sometimes called "symbol tables," and how AutoLISP can extract information from them.
What are tables?
AutoCAD uses tables to store information about named items that you create. For example, when you create a new layer, you give it a name and probably assign a particular color and linetype. In addition, the layer will have a certain status depending on how you use it. It may be the current layer, or it may be frozen, or locked. And the information about each other layer in the drawing will have different data, but it will be stored in the same categories (name, color, linetype, freeze-thaw status, etc.). Each of the other tables operates similarly, that is, it has different information about each entry in the table, but the same categories. This sort of information is well suited to be organized into tables where each row holds a different entry, and each column represents a different category appropriate to that particular table.
AutoCAD presents some tables to the user as tables, while others are less obvious. If you use the LAYER command, or DDUCS, or DDVIEW with "?" (especially in a drawing where several layers/ucs's/views already exist) you can see some of AutoCAD's more obvious tables.
Here is a list of the various tables AutoCAD uses.
The tblsearch
function
The tblsearch function allows your program to search for a particular entry in a given table. The first argument can be "block" or "ucs" or any of the table names listed above, as a string (between quotation marks). The second argument will be the name of the entry your program is trying to find. If the entry is found in the specified table, an association list is returned which contains detailed information about that entry, associated with particular codes. If the entry is not found, the tblsearch function returns nil.
Example 1: If your drawing contains a layer called "Hidden" with linetype Hiddenx2 and color red (1) assigned to it.
((0 . "LAYER") (2 . "HIDDEN") (70 . 0) (62 . 1) (6 . "HIDDENX2"))
Code 0, name of table
Code 2, name of layer
Code 6, linetype
Code 62, color number
Code 70, status flags (bitwise), 1 = frozen, 2 = frozen-by-default
in new viewports, 4 = locked
((0 . "STYLE") (2 . "MONO-SPACED") (70 . 0) (40 . 0.0) (41 . 1.0) (50 . 0.0) (71 . 0) (42 . 0.2) (3 . "monos.ttf") (4 . ""))
Code 0, name of table
Code 2, name of text style
Code 3, name of font file
Code 40, text height (0 = variable, non-zero = fixed)
Code 41, width factor
Code 42, last height used
Code 50, obliquing angle
((0 . "VIEW") (2 . "TB") (70 . 0) (40 . 3.0) (10 7.0 1.5) (41 . 6.0) (11 0.0 0.0 1.0) (12 0.0 0.0 0.0) (42 . 50.0) (43 . 0.0) (44 . 0.0) (50 . 0.0) (71 . 0))
Code 0, name of table
Code 2, name of view
Code 10, center of view
Code 11, viewing station (eye location) in WCS
Code 12, viewing target in WCS
Code 40, height of view
Code 41, width of view
Codes 43 and 44, front and back clipping offsets from target point
Code 50, twist angle
The codes are similar to the DXF codes described in the AutoCAD R14 Customization Guide, Appendix C. You can also figure out many codes simply by creating a table entry, using the tblsearch function to display its table information, modifying it, then using tblsearch again and noting the differences.
By the way, these string arguments in the tblsearch function are not case sensitive. That is, "layer" works the same as "LAYER" or "Layer" when used in the tblsearch function. However, what is returned contains all upper case for such things as layer name, linetype name, text style name, etc. This is important to remember if your program needs to search a table entry for a match.
There are several examples of the tblsearch function in previous Lessons, listed below. In each case the tblsearch function is searching the text style table.
The tblnext function
The tblnext function allows your program to "read through" a table, getting information from each subsequent entry in the table. Usually, it is used in an iteration loop. The first argument to the tblnext function is the name of the table, as a string. Suppose, for example, that you want your program to read through every entry in the layer table. You could place an expression like the one below inside a while loop.
(tblnext "layer")
With each successive iteration, it returns information on the next layer. If there are no more layers, nil is returned.
In order to force the tblnext function to read the first entry in the table, include a second argument which is non-nil, as shown below. This is known as the "rewind" form of the tblnext function, since it rewinds the pointer back to the beginning of the table.
(tblnext "layer" 1)
For example, the following could be used to read through every entry in the text style table and print each entry to screen.
(print (tblnext "style" 1))
(while (print (tblnext "style")))
By the way, when tables are listed in a dialog box (such as the drop-down list in the "Style name" section of the text style dialog box, or the listing in the layer dialog box) they are alphabetized. However, when you use the tblnext function to retrieve the same information, it appears in the order in which the items were created.
Sample program 1, balloon3
Balloon3 is a revision of the balloon2 program found in Lesson 12. In addition to storing the balloon diameter in a file (similar to balloon2), this program also stores, in the same file, the layer on which the balloon should be created and the color assigned to that layer. When the user wants to change one of these three items, he/she enters "S" instead of picking the startpoint of the balloon leader.
Some of the sections are similar to balloon2. The lines that have been added (and that pertain especially to the use of the tblsearch function) and marked "ADDED" in the program, but other lines have also been added or altered, and the overall program has been re-organized.
Similar to balloon2, this program must exist in its own file called balloon3.lsp, and should be located on the AutoCAD default folder or on one of the folders in the AutoCAD search path.
You will need to study this program carefully if you want to understand its logic. For example, note the use of a setup "subroutine" or "module" (section 50 - 58) which gets the desired layer, color, and balloon diameter from the user. This blnsetup function is called from two places in the program -- sections 140 and 150. Each time the setup module is run, it stores the information in a file called balloon3.lcd, which it places in the same folder as the program file. (The "lcd" stands for Layer, Color, Diameter.)
Also, it may appear that it is overloaded with if statements. However, remember that there are many different situations that can exist which the program must test for. For example, if the program is being run for the first time, it will not know the desired layer, color, or balloon diameter, so it must run the setup module to get these from the user. If the program is being run for the second time in the same editing session, it already knows these three items and does not need to run the setup module. If the program is being run for the first time in a new editing session (but has been run previously), it will read these three items from the balloon3.lcd file. What happens if the drawing in the new editing session does not have the layer identified by the balloon3.lcd file? Or, what happens if the user runs the setup option and enters a layer that already exists? Or enters a layer that does not exist? All of these contingencies, and several others, must be "covered" by the program, which accounts for the over abundance of if statements.
There are four occurrences of the tblsearch function in this program:
------
marker ------ beginning of working program ------ try it out ------
;| BALLOON3 -- Stores balloon information in a
file named balloon3.lcd
Copyright © 1988,1998,1999 Ronald W. Leigh
Input: (layer, color, balloon diameter), arrow
location,
balloon
location, number
Output: draws assembly balloon
Variables:
blncol Balloon layer color, GLOBAL
ADDED
blndia Balloon diameter, GLOBAL
blnfl Balloon info. file location, GLOBAL
blnlay Balloon layer name, GLOBAL
ADDED
blnnum Balloon number, GLOBAL
cen Center of balloon
ep Endpoint of arrow
fr/fw File descriptors: file opened for reading/writing
olay Old layer
ADDED
oom Old osnap mode
sp Start point of arrow
temp Temporary value for blnlay, blndia, &
blnnum input
ts Name of current text style
tshei Text style height
|;
;50====BLNSETUP ROUTINE, Gets layer, color, diameter from user
(defun blnsetup ()
(princ "\n** Setup **")
;52--------Get blnlay from user
(setq temp
(getstring (strcat "\n** Balloon layer name <" blnlay
">: "))) ; ADDED
(if (/= "" temp) (setq blnlay temp))
;54--------If layer blnlay does not exist, create layer
(if (null (tblsearch "layer" blnlay)) (progn
(setq blncol (acad_colordlg blncol nil))
(princ (strcat "\n** Creating layer " blnlay " with color
" (itoa blncol) " **"))
(setvar "cmdecho" 0)
(command ".layer" "N" blnlay "C" blncol blnlay "")
(setvar "cmdecho" 1)
))
;56--------Get blndia from user
(initget 6)
(setq temp (getreal (strcat "\n** Balloon diameter <" (rtos
blndia 2 3) ">: ")))
(if temp (setq blndia temp))
;58--------Store information in file.
(if (= (type blnfl) 'STR) (progn
(setq fw (open (strcat blnfl "balloon3.lcd") "w"))
(write-line blnlay fw)
; ADDED
(write-line (itoa blncol) fw)
; ADDED
(write-line (rtos blndia 2 4) fw)
(close fw))))
;100====MAIN PROGRAM, SETUP
(defun c:balloon3 (/ cen ep fr fw olay oom sp temp ts tshei)
(setq olay (getvar "clayer"))
; ADDED
(setq oom (getvar "osmode"))
(graphscr)
;110====GET LOCATION OF BALLOON3.LSP PROGRAM FILE
(if (/= (type blnfl) 'STR) (progn
(setq blnfl (findfile "balloon3.lsp"))
(if (= (type blnfl) 'STR)
(setq blnfl (substr blnfl 1 (- (strlen blnfl)
12))))))
;120====IF BLNLAY OR BLNDIA NOT SET, AND IF BLNFL IS A STRING,
; AND IF FILE BALLOON3.LCD
HAS BEEN LOCATED, READ INFO.
; FROM THE FILE.
(if (and (or (/= (type blnlay) 'STR) (/= (type blndia) 'REAL))
; ADDED
(= (type blnfl)
'STR)
(findfile (strcat
blnfl "balloon3.lcd"))) (progn
(setq fr (open (strcat blnfl "balloon3.lcd") "r"))
(setq blnlay (read-line fr))
; ADDED
(setq blncol (atoi (read-line fr)))
; ADDED
(setq blndia (atof (read-line fr)))
(close fr)))
;130====IF PREVIOUS SECTION FAILED, SET LAYER, COLOR, AND DIAMETER
; FROM INTERNAL DATA
(if (or (/= (type blnlay) 'STR) (/= (type blncol) 'INT))
(setq blnlay (getvar "clayer")
blncol (cdr (assoc 62
(tblsearch "layer" blnlay)))))
(if (/= (type blndia) 'REAL)
(if (= 0 (getvar "dimscale"))
(setq blndia (/ (getvar "dimtxt") 0.28))
(setq blndia (/ (* (getvar "dimtxt") (getvar
"dimscale")) 0.28))))
;140====IF LAYER (RETRIEVED FROM FILE) DOES NOT EXIST, RUN SETUP,
; THEN REPORT SETTINGS
(if (null (tblsearch "layer" blnlay)) (blnsetup))
(foreach v
(list "\n** Balloon layer = " blnlay " (color " blncol
") Diameter = " (rtos
blndia 2 4) " **")
(princ v))
;150====GET STARTPOINT, CENTER, AND NUMBER FROM USER
(setvar "osmode" 512)
(while
(progn
(initget 1 "Setup")
(= "Setup" (setq sp
(getpoint "\nStartpoint
of arrow (or 'S' for Setup): "))))
(blnsetup))
(setvar "osmode" 0)
(initget 1)
(setq cen (getpoint sp "\nLocation of balloon: "))
(if (null blnnum) (setq blnnum 0))
(setq blnnum (1+ blnnum))
(initget 6)
(setq temp (getint (strcat "\nBalloon number <" (itoa blnnum)
">: ")))
(if temp (setq blnnum temp))
;160====CALC. END POINT OF ARROW, GET TEXT STYLE HEIGHT, DRAW BALLOON
(setq ep (polar cen (angle cen sp) (/ blndia 2)))
(setq ts (getvar "textstyle"))
(setq tshei (cdr (assoc 40 (tblsearch "style" ts))))
(if (> tshei 0)
(princ "\nText style has fixed height; may not fit balloon."))
(setvar "cmdecho" 0)
(command ".layer" "S" blnlay "")
; ADDED
(command ".dim1" "leader" sp ep) (command)
(command ".circle" cen "D" blndia)
(if (> tshei 0)
(command ".text" "M" cen 0 blnnum)
(command ".text" "M" cen (* 0.28 blndia) 0 blnnum)
)
(command ".layer" "S" olay "")
; ADDED
;170====RESET
(setvar "cmdecho" 1)
(setvar "osmode" oom)
(princ)
)
-------- marker
-------- end of working program -------- try it out --------
Sample program 2, tstyles
The following program, called tstyles (short for text styles), illustrates the use of the tblnext function. It creates a table which lists all the text styles in the current drawing, listing those with variable height first, then those with fixed height. The table also includes the font file that is used by the style, and, in the case of the fixed height styles, it lists the fixed height as well.
The program reads through the style table twice -- once in section 20 to build a list of variable height styles, and once in section 30 to build a list of fixed height styles. In order to be sure that the first style returned is actually the first one in the table, each section uses the tblnext function in its "rewind" form first (with a non-nil second argument). Then the while loop reads through the remaining items in the table.
------ marker ------ beginning of working program ------ try it out ------
;| TSTYLES -- Creates a two-part table that lists the fixed
height and variable height text styles in a
drawing
Copyright © 1999 Ronald W. Leigh
Input: none
Output: table of styles
Variables:
fhlist Fixed height list
font Font file used by style
hei Height
item Each subsequent item retrieved from the
table
name Style name
vhlist Variable height list
|;
;10====PROGRAM
(defun c:tstyles ()
(textscr)
;20====BUILD LIST OF TEXT STYLES WITH VARIABLE HEIGHT
(setq vhlist ())
(setq item (tblnext "style" 1))
(if (zerop (cdr (assoc 40 item)))
(setq vhlist (cons item vhlist)))
(while (setq item (tblnext "style"))
(if (zerop (cdr (assoc 40 item)))
(setq vhlist (cons item vhlist))))
(setq vhlist (reverse vhlist))
;30====BUILD LIST OF TEXT STYLES WITH FIXED HEIGHT
(setq fhlist ())
(setq item (tblnext "style" 1))
(if (not (zerop (cdr (assoc 40 item))))
(setq fhlist (cons item fhlist)))
(while (setq item (tblnext "style"))
(if (not (zerop (cdr (assoc 40 item))))
(setq fhlist (cons item fhlist))))
(setq fhlist (reverse fhlist))
;40====PRINT TABLE OF STYLES TO SCREEN
(terpri)
(repeat 12 (princ "-----"))
(princ "\n
TEXT STYLES WITH VARIABLE HEIGHT\n")
(if (zerop (length vhlist)) (princ "\n (none)"))
(foreach v vhlist
(setq name (cdr (assoc 2 v)))
(while (< (strlen name) 16) (setq name (strcat name "
")))
(setq font (cdr (assoc 3 v)))
(princ (strcat "\n " name " Font file " font)))
(princ "\n\n
TEXT STYLES WITH FIXED HEIGHT\n")
(if (zerop (length fhlist)) (princ "\n (none)"))
(foreach v fhlist
(setq name (cdr (assoc 2 v)))
(while (< (strlen name) 16) (setq name (strcat name "
")))
(setq font (cdr (assoc 3 v)))
(while (< (strlen font) 18) (setq font (strcat font "
")))
(setq hei (cdr (assoc 40 v)))
(princ (strcat "\n " name " Font file " font
" Height " (rtos hei 2 3))))
(terpri)
(repeat 12 (princ "-----"))
(terpri)
(princ)
)
-------- marker
-------- end of working program -------- try it out --------