Anyone producing land or infrastructure documents wants to export point coordinates in AutoCAD for the same reason: to write each corner's coordinates onto the drawing and build a summary table, instead of typing every figure by hand.
We downloaded the version circulating online, read all 104 lines of it, found three faults, and then wrote our own. This article carries both the source and the file. For the whole drafting and documentation workflow, see the AutoCAD for Construction course.
What a point label and coordinate table must contain
Anyone who has to export point coordinates in AutoCAD for a cadastral file meets the same four parts. A proper coordinate label has four parts: a leader from the point out to clear space, two figures stacked, a numbered circle, and finally a table gathering them all.
The decision that matters is which figure goes first. Vietnamese surveying practice puts X on the north axis and Y on the east axis, while AutoCAD calls the horizontal axis X and the vertical one Y. In other words, the X column of a coordinate table has to be fed from AutoCAD's Y.
Every circulating lisp swaps the axes already, and asks nothing. On a cadastral sheet that is right. On an architectural plan the figures come out reversed with no warning at all.
Another phrasing people search for is a lisp that simply picks a coordinate, which is a narrower job: click a point and read the pair, with no label and no table. AutoCAD does that itself with the ID command, and typing coordinates from the keyboard is covered in our article on entering coordinates in AutoCAD. A lisp earns its place only when you need labels and a table, which is to say when you are producing documents rather than checking a figure.
The Institute file
Download XTD-IIC.lsp — 7 KB, two commands. The source stays in the article, because running unknown code on your own machine deserves care.
| Command | What it does |
|---|---|
XTD | select points, label them on the drawing and build the summary table |
XTDCSV | select points and write straight to a .csv that Excel opens |
Both ask which convention to use before doing anything, defaulting to surveying. Anyone drawing architecture types C to keep AutoCAD's own axes.
(vl-load-com)
(defun IIC-GIOI-THIEU ()
(princ "\nLisp được lập trình bởi RDSIC - Viện Tin học Xây dựng")
(princ "\nwebsite: https://iic.huce.edu.vn - Tel: 0989 427 809")
)
;; Tao chu bang entmake, KHONG dung (command "text" ...): kieu chu co chieu cao
;; co dinh thi dong hoi chieu cao bien mat va moi doi so sau do lech mot nhip.
;; can: 0 trai, 1 giua
(defun IIC:CHU (p cao noi can)
(entmake (list (cons 0 "TEXT") (cons 10 p) (cons 11 p) (cons 40 cao)
(cons 1 noi) (cons 72 can) (cons 73 0)))
)
(defun IIC:NET (a b)
(entmake (list (cons 0 "LINE") (cons 10 a) (cons 11 b)))
)
(defun IIC:TRON (p r)
(entmake (list (cons 0 "CIRCLE") (cons 10 p) (cons 40 r)))
)
;; Tra ve (chuoi-X chuoi-Y) theo quy uoc dang chon.
(defun IIC:CAP (p td)
(if td
(list (rtos (cadr p) 2 2) (rtos (car p) 2 2))
(list (rtos (car p) 2 2) (rtos (cadr p) 2 2))
)
)
(defun IIC:HOI-TRUC ( / k )
(initget "TracDia Cad")
(setq k (getkword "\nQuy uoc truc [TracDia/Cad] <TracDia>: "))
(/= k "Cad")
)
(defun IIC:CHON-DIEM ( / p ds )
(setq ds nil)
(while (setq p (getpoint "\nChon diem (Enter de dung): "))
(setq ds (cons p ds))
)
(reverse ds)
)
(defun c:XTD ( / e-cu os-cu ce-cu h td ds n i p cap sx sy
p1 p2 p3 rong r pb hang cot1 cot2 cot3 y0 td1 td2 dz-cu )
(IIC-GIOI-THIEU)
(setq e-cu *error*
os-cu (getvar "osmode")
ce-cu (getvar "cmdecho"))
;; Khoi phuc du nguoi dung bam ESC giua chung. Thieu doan nay thi bat diem bi
;; tat am tham va nhom hoan tac bi bo ngo - dung loi cua cac ban dang luu hanh.
(defun *error* (m)
(setvar "osmode" os-cu) (setvar "cmdecho" ce-cu)
(if dz-cu (setvar "dimzin" dz-cu))
(command "_.UNDO" "_End")
(setq *error* e-cu)
(if (and m (not (wcmatch (strcase m) "*CANCEL*,*QUIT*")))
(princ (strcat "\nIIC loi: " m)))
(princ)
)
(command "_.UNDO" "_Begin")
(setvar "cmdecho" 0)
;; DIMZIN = 8 lam rtos cat het so 0 thua, toa do 3200.00 ra thanh 3200.
;; Tat trong luc chay roi tra lai, ke ca khi bam ESC.
(setq dz-cu (getvar "dimzin"))
(setvar "dimzin" 0)
(setq h (getvar "TEXTSIZE"))
(if (<= h 0) (setq h 2.5))
(setq h (cond ((getreal (strcat "\nChieu cao chu <" (rtos h 2 2) ">: "))) (h)))
(setq td (IIC:HOI-TRUC))
(setq ds (IIC:CHON-DIEM))
(if (null ds)
(princ "\nKhong chon diem nao.")
(progn
(setvar "osmode" 0)
(setq n (length ds) i 0 rong 0.0 r (* 1.5 h))
(while (< i n)
(setq p (nth i ds)
cap (IIC:CAP p td)
sx (car cap)
sy (cadr cap)
p1 (list (+ (car p) (* 3 h)) (+ (cadr p) (* 3 h)))
rong (max rong (* (max (strlen sx) (strlen sy)) h 0.72))
)
;; Khe ho chu - net: 0.55 lan chieu cao chu o tren, va o duoi cung vay.
;; De 0.35 thi chu dinh sat net, nhin roi (anh Binh bat 20/09/2026).
(setq p2 (list (+ (car p1) rong (* 0.6 h)) (cadr p1))
p3 (list (+ (car p2) r (* 0.3 h)) (cadr p1)))
(IIC:NET p p1)
(IIC:NET p1 p2)
(IIC:CHU (list (+ (car p1) (* 0.3 h)) (+ (cadr p1) (* 0.55 h))) h sx 0)
(IIC:CHU (list (+ (car p1) (* 0.3 h)) (- (cadr p1) (* 1.55 h))) h sy 0)
(IIC:TRON p3 r)
(IIC:CHU (list (car p3) (- (cadr p3) (* 0.5 h))) h (strcat "N" (itoa (1+ i))) 1)
(setq i (1+ i))
)
(setq pb (getpoint "\nVi tri dat bang (goc tren ben trai): "))
(if pb
(progn
(setq td1 (if td "Toa do X (bac)" "Toa do X")
td2 (if td "Toa do Y (dong)" "Toa do Y")
cot1 (* 5 h)
cot2 (max (+ rong (* 2 h)) (* (strlen td1) h 0.78))
cot3 (max (+ rong (* 2 h)) (* (strlen td2) h 0.78))
hang (* 2.2 h) y0 (cadr pb) i 0)
(IIC:NET pb (list (+ (car pb) cot1 cot2 cot3) y0))
(setq y0 (- y0 hang))
(IIC:CHU (list (+ (car pb) (* 0.5 cot1)) (+ y0 (* 0.6 h))) h "STT" 1)
(IIC:CHU (list (+ (car pb) cot1 (* 0.5 cot2)) (+ y0 (* 0.7 h))) h td1 1)
(IIC:CHU (list (+ (car pb) cot1 cot2 (* 0.5 cot3)) (+ y0 (* 0.7 h))) h td2 1)
(IIC:NET (list (car pb) y0) (list (+ (car pb) cot1 cot2 cot3) y0))
(while (< i n)
(setq cap (IIC:CAP (nth i ds) td))
(IIC:CHU (list (+ (car pb) (* 0.5 cot1)) (- y0 (* 1.4 h))) h
(strcat "N" (itoa (1+ i))) 1)
(IIC:CHU (list (+ (car pb) cot1 (* 0.5 cot2)) (- y0 (* 1.5 h))) h (car cap) 1)
(IIC:CHU (list (+ (car pb) cot1 cot2 (* 0.5 cot3)) (- y0 (* 1.5 h))) h (cadr cap) 1)
(setq y0 (- y0 hang) i (1+ i))
(IIC:NET (list (car pb) y0) (list (+ (car pb) cot1 cot2 cot3) y0))
)
(IIC:NET pb (list (car pb) y0))
(IIC:NET (list (+ (car pb) cot1) (cadr pb)) (list (+ (car pb) cot1) y0))
(IIC:NET (list (+ (car pb) cot1 cot2) (cadr pb)) (list (+ (car pb) cot1 cot2) y0))
(IIC:NET (list (+ (car pb) cot1 cot2 cot3) (cadr pb))
(list (+ (car pb) cot1 cot2 cot3) y0))
)
)
(princ (strcat "\nDa ghi " (itoa n) " diem."))
)
)
(setvar "osmode" os-cu) (setvar "cmdecho" ce-cu)
(setvar "dimzin" dz-cu)
(command "_.UNDO" "_End")
(setq *error* e-cu)
(princ)
)
;; XTDCSV - ghi thang ra tep .csv, mo bang Excel duoc ngay.
(defun c:XTDCSV ( / e-cu td ds n i cap f duong dz-cu )
(IIC-GIOI-THIEU)
(setq e-cu *error* f nil)
(setq dz-cu (getvar "dimzin"))
(setvar "dimzin" 0)
(defun *error* (m)
(if f (close f))
(if dz-cu (setvar "dimzin" dz-cu))
(setq *error* e-cu)
(if (and m (not (wcmatch (strcase m) "*CANCEL*,*QUIT*")))
(princ (strcat "\nIIC loi: " m)))
(princ)
)
(setq td (IIC:HOI-TRUC))
(setq ds (IIC:CHON-DIEM))
(if (null ds)
(princ "\nKhong chon diem nao.")
(progn
(setq duong (getfiled "Ghi toa do ra tep" "toado" "csv" 1))
(if duong
(progn
(setq f (open duong "w") n (length ds) i 0)
(write-line (if td "STT,X (bac),Y (dong)" "STT,X,Y") f)
(while (< i n)
(setq cap (IIC:CAP (nth i ds) td))
(write-line (strcat "N" (itoa (1+ i)) "," (car cap) "," (cadr cap)) f)
(setq i (1+ i))
)
(close f)
(setq f nil)
(princ (strcat "\nDa ghi " (itoa n) " diem ra " duong))
)
)
)
)
(setvar "dimzin" dz-cu)
(setq *error* e-cu)
(princ)
)
Using it, step by step: labels then csv export
Step 1 — Load the file
Type APPLOAD, point at the file, click Load, then Close. To avoid loading it again on every start, add it to the Startup Suite in that same dialog. The loading route is covered in detail in our article on a lisp that shortens extension lines.
Step 2 — Run XTD
Type XTD and press Enter. Three questions follow in order:
Chieu cao chu <2.50>:
Quy uoc truc [TracDia/Cad] <TracDia>:
Chon diem (Enter de dung):
Leave the text height alone and it follows the drawing's TEXTSIZE. Press Enter through the convention question for cadastral work. Then click each corner in turn and press Enter when done.
Step 3 — Place the table
Vi tri dat bang (goc tren ben trai):
Click a point in clear space. The table builds itself with three columns, each sized to the longest figure in it, and headers saying which column is north and which is east. AutoCAD reports:
Da ghi 5 diem.
Step 4 — Or write straight to Excel
Type XTDCSV, select the points as above, and choose where to save. The .csv opens in Excel as three clean columns, with no copying figures across from the drawing.
Getting northing and easting the right way round is not a detail. A parcel boundary entered into the land registry with the two columns swapped describes a different piece of ground, and the mistake survives every later check because both figures look perfectly plausible. This is the one place where a lisp that asks a question beats a lisp that is clever.
Northing and easting: three faults in the circulating version
We downloaded the most popular one, unpacked it, and read all 104 lines. It runs, and the idea behind it is sound. But three things are broken, and all three can be checked on the machine.
The first is the code page. In the source, the column header is written as a string that only renders correctly under an old Vietnamese code page from the early 2000s. On a machine with an ordinary Unicode text style it comes out exactly as the image above shows.
The second is the decimals. Autodesk's rtos page states that the function works "according to the settings of mode, precision, and the AutoCAD UNITMODE, DIMZIN, LUNITS, and LUPREC system variables". With DIMZIN at 8, which is what most metric drawings carry, trailing zeros are stripped and 584320.00 prints as 584320. A survey document that loses two decimal places is not a survey document. Our file switches DIMZIN off while it runs and puts the old value back, including when you press Escape.
The third is the missing error handler. The old file opens an undo group with Undo Begin but defines no *error* function. Press Escape part way through and that group is left open, while CMDECHO stays at 0 — we measured exactly that after pressing Escape. From then on the command line stops echoing and the user has no idea why.
In fairness, one of our guesses was wrong. We expected object snap to be left switched off too, but measurement showed OSMODE restored correctly. That part they got right.
One more difference sits where few people look: local variables. The old file lets seven variables escape its own scope, including names as collision-prone as k and n. Another lisp loaded in the same session that uses the same names will overwrite them, and the error shows up somewhere unrelated. Ours declares every variable local.
What our version changes, from dimzin to the point label
| Point | Circulating version | Institute version |
|---|---|---|
| Axis convention | swapped silently | asks once, defaults to surveying |
| Decimals | depends on DIMZIN, often lost | forced to two, then the variable is restored |
| Pressing Escape | undo group left open, CMDECHO stuck at 0 | *error* handler puts everything back |
| Table header | old code page, renders as noise | plain letters that work under any font |
| Column width | sized on the figures, header overflows | the larger of figure width and header width |
| Excel export | none | the XTDCSV command |
A second habit worth copying: keep the table's column widths tied to the content rather than fixed. Survey coordinates in a national grid run to seven digits, while a local site grid may use four. A table sized for one looks wrong with the other, and a header that overflows into the next column is the first thing a reviewer notices.
One technical detail is worth naming. The old file creates text with (command "text" ...). That breaks when the current text style has a fixed height, because the height question disappears and every argument after it lands one step out of place. Ours builds text with entmake, which does not depend on the style at all.
Three things often repeated that are not true
| Often repeated | What we measured |
|---|---|
| Any coordinate lisp is as good as another | They differ on axes, decimals and error handling — the three things that decide whether the document is right |
| A garbled table means a missing font | It comes from the source being written in an old code page; changing fonts does not fix it |
| Getting the figures into Excel means retyping | Write straight to .csv from the lisp and open it |
Frequently asked questions
The figures came out with no decimals. Why?
That is DIMZIN. Set it to 0 before running, or use the file from this article, which handles it and restores the old value.
Why does the X column hold the vertical figure?
Because Vietnamese surveying puts X on the north axis. AutoCAD calls the vertical axis Y, so the table has to swap. For an architectural plan, choose Cad and nothing is swapped.
Is it slow with hundreds of points?
No. The command only draws lines and text and calls nothing heavy. The time goes into clicking the points.
I clicked a wrong point. Now what?
Type U once. The whole pass is wrapped as a single undo step, so one press is enough.
Excel puts the whole csv in one column.
Excel is expecting semicolons as the separator. Import the file and choose comma, or change the list separator in the Windows regional settings.