BIM

How to export point coordinates in AutoCAD with a lisp that works

Export point coordinates in AutoCAD with labels and a summary table. Full lisp source to download, plus three faults in the version circulating online.

  • TS. Đỗ Quốc Hoàng
  • 13 min read
A five-corner land parcel after running the XTD command: every corner carries a two-line coordinate label, with the summary table on the right Photo: Screenshot taken on AutoCAD 2027 at the Institute

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.

CommandWhat it does
XTDselect points, label them on the drawing and build the summary table
XTDCSVselect 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 table the circulating lisp produces Photo: The table header produced by the circulating lisp: those two words are Vietnamese for "coordinate", written in a 2000s-era code page. The figures have also lost their decimals

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

PointCirculating versionInstitute version
Axis conventionswapped silentlyasks once, defaults to surveying
Decimalsdepends on DIMZIN, often lostforced to two, then the variable is restored
Pressing Escapeundo group left open, CMDECHO stuck at 0*error* handler puts everything back
Table headerold code page, renders as noiseplain letters that work under any font
Column widthsized on the figures, header overflowsthe larger of figure width and header width
Excel exportnonethe 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 repeatedWhat we measured
Any coordinate lisp is as good as anotherThey differ on axes, decimals and error handling — the three things that decide whether the document is right
A garbled table means a missing fontIt comes from the source being written in an old code page; changing fonts does not fix it
Getting the figures into Excel means retypingWrite 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.

About the author

TS. Đỗ Quốc Hoàng — Vice Director of the Institute of Information Technology in Civil Engineering, Hanoi University of Civil Engineering, and a specialist in software development for construction