AutoCAD – Bản vẽ

Lisp sửa nhiều text và dim theo một mẫu: một cú bấm cho cả loạt

Lisp sửa nhiều text và dim của Viện: chọn cả loạt, bấm một text hoặc dim mẫu là xong. Dim giữ số đo thật, mẫu L=<> cho mỗi dim hiện số của chính nó.

  • TS. Đỗ Quốc Hoàng
  • 13 phút đọc
Ba tình huống của lisp STM: mẫu là text, mẫu là dim ghi đè L=<>, và STMX trả dim về số đo thật Ảnh: Sơ đồ của Viện Tin học Xây dựng

Trên bản vẽ có mười hai ô ghi "D250" giờ phải đổi thành "D300", cộng thêm năm dim phải ghi chữ thay cho con số. Sửa từng cái bằng cách bấm đúp thì mất cả buổi và dễ sót. Lisp sửa nhiều text và dim của Viện làm việc ấy trong một lệnh: quét chọn cả loạt, bấm một text hoặc dim làm mẫu, tất cả nhận nội dung của mẫu.

Tải tệp STM-IIC.lsp7 KB, hai lệnh STMSTMX. Mã in nguyên trong bài để bạn đọc trước khi chạy. Muốn học trọn phần chữ và kích thước, Viện có khoá AutoCAD cho ngành xây dựng.

Lisp này từ đâu ra, và vì sao không đặt tên MT

Ý tưởng lấy từ một bài trên diễn đàn Tin học Xây dựng: chọn các text và dim cần sửa, rồi bấm một cái có sẵn làm mẫu. Viện viết lại toàn bộ mã, chạy thử trên AutoCAD 2027, và sửa ba chỗ.

Thứ nhất là tên lệnh. Bản trên diễn đàn dùng tên MT. Nhưng đọc tệp lệnh tắt acad.pgp của bản 2027 thì thấy dòng MT, *MTEXT: gõ MT vốn là mở lệnh viết chữ nhiều dòng. Nạp lisp đặt tên MT là mất lệnh tắt ấy. Bản của Viện dùng tên STM, đã kiểm không trùng lệnh gốc, lệnh tắt hay lisp nào khác của Viện.

Thứ hai là mẫu dim. Khi mẫu là một dim ghi L=<>, bản của Viện giữ đúng quy tắc ấy, nên mỗi dim hiện số đo của chính nó. Phần này có ví dụ bên dưới.

Thứ ba là lệnh trả lại. Thêm lệnh STMX để xoá chữ ghi đè, cho dim hiện lại số đo thật.

Sửa dim trong CAD: chữ ghi đè và số đo thật

Trước khi dùng lisp, cần hiểu dim có hai phần tách bạch nhau: số đo mà máy tính từ hai điểm gốc, và chữ hiển thị. Bình thường chữ hiển thị chính là số đo. Khi bạn gõ chữ khác vào, đó gọi là ghi đè.

Ghi đè chỉ đổi chữ, không đổi số đo. Hai dim đo 1000 và 1500, ghi đè cùng chữ D300, thì cả hai hiện D300 nhưng số đo bên trong vẫn là 1000 và 1500.

Có một ký hiệu đặc biệt nên biết: cặp dấu <> trong chữ ghi đè được thay bằng số đo thật. Ghi đè L=<> thì dim đo 1000 hiện L=1000, dim đo 1500 hiện L=1500. Cách này giữ được số đo mà vẫn thêm được chữ đứng trước hay sau.

Nói rộng ra, chỉnh sửa dim trong CAD gồm hai việc khác hẳn nhau, và người ta hay tìm nhầm công cụ vì gộp chúng làm một.

Loại chỉnh sửaVí dụCông cụ
Sửa hình của dimDời đường kích thước, cắt chân đường gióng, dóng các dim thẳng hàngKéo điểm móc, lisp dóng thẳng hàng dim, lisp cắt dim
Sửa chữ của dimGhi chữ thay số, thêm tiền tố, trả về số đo thậtBài này: lisp STMSTMX

Sửa chữ từng dim một thì bấm đúp vào nó hoặc mở bảng Properties. Cách ấy ổn với một hai cái, nhưng với vài chục cái thì mất công và dễ sót, nhất là khi các dim nằm rải rác trên nhiều tờ. Phần đường gióng và vị trí chữ nằm ở bài ghi kích thước trong CAD.

Cách sửa dim trong CAD bằng lisp STM

Nạp tệp bằng APPLOAD theo bài lệnh appload trong CAD, rồi gõ STM.

BướcMáy hỏiBạn làm
1Chọn các text, mtext và dim cần sửa:Quét chọn cả vùng, Enter; lisp chỉ lấy text, mtext và dim
2Bấm text hoặc dim mẫu:Bấm một text, mtext hoặc dim làm mẫu

Bấm nhầm vào một nét thẳng ở bước 2 thì máy báo Đối tượng ấy không phải text, mtext hay dim. Bấm lại. rồi hỏi lại, không làm hỏng gì. Lisp cũng hỏi lại khi bấm trượt ra chỗ trống.

Ví dụ 1: mẫu là một dòng chữ

Có hai dòng chữ abcxyz, một khối chữ nhiều dòng cu, và hai dim đo 1000 và 1500. Gõ STM, quét chọn cả năm, Enter, rồi bấm dòng chữ mẫu D300.

Đối tượngTrướcSau
TextabcD300
TextxyzD300
MtextcuD300
Dim đo 10001000D300
Dim đo 15001500D300

Máy báo Đã sửa 5 đối tượng theo mẫu "D300". Hai dim vẫn đo 1000 và 1500 bên trong, chỉ chữ hiển thị đổi.

Không cần lo dòng chữ mẫu có lọt vào vùng quét hay không. Nếu nó nằm trong vùng chọn, lisp tự bỏ qua chính nó khi sửa, nên con số báo cuối lệnh chỉ đếm các đối tượng thật sự được đổi.

Cả lệnh là một bước hoàn tác. Gõ U một lần là năm đối tượng trở về đúng abc, xyz, cu, 1000, 1500.

Ví dụ 2: mẫu là một dim ghi L=<>

Đây là chỗ lisp của Viện khác hẳn cách chép chữ đơn thuần. Có một dim đo 800 đang ghi đè L=<>, nên nó hiện L=800. Chọn hai dim đo 1000 và 1500 cùng một dòng chữ cu, rồi bấm dim L=800 làm mẫu.

Đối tượngTrướcSau
Dim đo 10001000L=1000
Dim đo 15001500L=1500
TextcuL=800

Hai dim nhận quy tắc L=<> chứ không nhận chữ L=800, nên mỗi cái hiện số đo của chính nó. Dòng chữ thì không có số đo, nên nhận đúng chữ đang hiện trên dim mẫu.

Chữ lấy từ dim mẫu đúng như những gì hiện trên màn hình, kể cả số chữ số thập phân. Bản vẽ để bốn chữ số thập phân thì dòng chữ nhận L=800.0000; để không chữ số thập phân thì nhận L=800.

Nếu dim mẫu không ghi đè gì, các dim được chọn cũng bỏ hết ghi đè và hiện lại số đo thật. Đó là cách nhanh để trả cả loạt về đúng như mẫu.

Trả dim về số đo thật bằng STMX

Bản vẽ nhận từ nơi khác hay có dim đã bị ghi đè chữ cố định. Nhìn thì thấy con số, nhưng đó không phải số đo: như ví dụ 1, hai dim đo 1000 và 1500 vẫn cùng hiện một chữ.

STMX, quét chọn các dim, Enter. Máy báo Đã trả 2 dim về số đo thật. Hai dim đang hiện L=1000L=1500 trở lại hiện 10001500. Dim nào không được chọn thì giữ nguyên.

Nên chạy STMX trên mọi bản vẽ nhận về trước khi dùng số đo để tính toán. Một dim ghi đè chữ cố định là một con số có thể đã sai mà không ai biết.

Mã nguồn lisp sửa text theo mẫu

Mọi hàm phụ đều mang tiền tố iic-stm-, để nạp cùng các tệp lisp khác mà không đè lên nhau. Với dòng chữ một dòng, lisp tự bỏ mã định dạng của khối chữ nhiều dòng như \A1; hay \P, vì dòng chữ một dòng không hiểu các mã ấy.

;;; ==================================================================
;;;  STM-IIC.LSP  -  sua nhieu text va dim theo mot text / dim mau
;;;  Vien Tin hoc Xay dung (IIC) - Truong Dai hoc Xay dung Ha Noi
;;;  https://iic.huce.edu.vn  -  Tel: 0989 427 809
;;; ------------------------------------------------------------------
;;;  Lenh:
;;;    STM    quet chon mot loat TEXT, MTEXT va DIM can sua, Enter,
;;;           roi bam MOT text hoac dim mau. Moi doi tuong da chon nhan
;;;           noi dung cua mau.
;;;             - mau la TEXT/MTEXT: text va mtext nhan dung chu ay, dim
;;;               hien chu ay thay cho so do.
;;;             - mau la DIM: dim nhan dung quy tac ghi de cua mau. Mau ghi
;;;               "L=<>" thi dim nao cung hien "L=" kem SO DO CUA CHINH NO.
;;;               Mau khong ghi de gi thi cac dim tro ve hien so do that.
;;;               Text va mtext nhan chu dang hien tren dim mau.
;;;    STMX   chon cac dim, xoa phan ghi de: dim hien lai so do that.
;;;
;;;  Ten lenh KHONG dat la MT nhu nhieu ban lisp tren mang: MT la lenh
;;;  tat co san cua AutoCAD de mo MTEXT, dat trung thi mat lenh tat ay.
;;;
;;;  Nap tep: go APPLOAD, chon tep nay, bam Load.
;;;  Tep luu bang ma UTF-8. Sua bang Notepad thi nho luu lai dung UTF-8.
;;; ==================================================================

(vl-load-com)

;;; ------------------------------------------------------------------
;;;  Phan chung - moi ham phu mang tien to iic-stm- de khong de len
;;;  ham cung ten cua tep lisp khac dang nap trong cung ban ve.
;;; ------------------------------------------------------------------

(defun iic-stm-bang-ten ()
  (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")
  (princ "\nTel: 0989 427 809")
  (princ)
)

(defun iic-stm-tai-lieu () (vla-get-ActiveDocument (vlax-get-acad-object)))

;; Bo ma dinh dang cua MTEXT (\A1; \H2.5; \fArial|b0; \C1; \P ...) de lay
;; chu tron, dung cho TEXT vi TEXT khong hieu cac ma ay.
(defun iic-stm-tron (s / kq i n c k p)
  (setq kq "" i 1 n (strlen s))
  (while (<= i n)
    (setq c (substr s i 1))
    (cond
      ((or (= c "{") (= c "}")) nil)
      ((and (= c "\\") (< i n))
       (setq k (substr s (1+ i) 1))
       (cond
         ((member (strcase k) '("A" "H" "F" "C" "Q" "T" "W" "S"))
          (setq p (vl-string-search ";" s i))
          (setq i (if p (1+ p) n)))
         ((= (strcase k) "P") (setq kq (strcat kq " ") i (1+ i)))
         ((member (strcase k) '("L" "O" "K")) (setq i (1+ i)))
         (t (setq kq (strcat kq k) i (1+ i)))
       ))
      (t (setq kq (strcat kq c)))
    )
    (setq i (1+ i))
  )
  kq
)

;; Chu dang HIEN tren mot kich thuoc: lay MTEXT nam trong khoi an danh
;; cua no. Day moi la chu nguoi xem thay, da tinh ca ghi de lan so do.
(defun iic-stm-chu-dim (d / e ed kq)
  (setq e (entnext (tblobjname "BLOCK" (cdr (assoc 2 d)))) kq "")
  (while (and e (= kq ""))
    (setq ed (entget e))
    (if (= (cdr (assoc 0 ed)) "MTEXT")
      (setq kq (vla-get-TextString (vlax-ename->vla-object e)))
    )
    (setq e (entnext e))
  )
  (iic-stm-tron kq)
)

;; Doc mau. Tra ve (chu-tron chu-mtext ghi-de-dim).
(defun iic-stm-doc-mau (en / d loai o gd)
  (setq d (entget en) loai (cdr (assoc 0 d)) o (vlax-ename->vla-object en))
  (cond
    ((= loai "TEXT")
     (list (cdr (assoc 1 d)) (cdr (assoc 1 d)) (cdr (assoc 1 d))))
    ((= loai "MTEXT")
     (list (iic-stm-tron (vla-get-TextString o)) (vla-get-TextString o)
           (iic-stm-tron (vla-get-TextString o))))
    ((= loai "DIMENSION")
     (setq gd (vla-get-TextOverride o))
     (list (iic-stm-chu-dim d) (iic-stm-chu-dim d) gd))
  )
)

;; Ap mau vao mot doi tuong. Tra ve T neu da sua.
(defun iic-stm-ap (en mau / d loai o)
  (setq d (entget en) loai (cdr (assoc 0 d)) o (vlax-ename->vla-object en))
  (cond
    ((= loai "TEXT")
     (entmod (subst (cons 1 (car mau)) (assoc 1 d) d)) (entupd en) T)
    ((= loai "MTEXT")
     (vla-put-TextString o (cadr mau)) T)
    ((= loai "DIMENSION")
     (vla-put-TextOverride o (caddr mau)) (vla-Update o) T)
    (t nil)
  )
)

;;; ------------------------------------------------------------------
;;;  Lenh STM
;;; ------------------------------------------------------------------

(defun c:STM (/ *error* ss e nguon mau xong i en n)
  (defun *error* (m)
    (vla-EndUndoMark (iic-stm-tai-lieu))
    (if (not (wcmatch (strcase m) "*CANCEL*,*QUIT*,*BREAK*"))
      (princ (strcat "\nLỗi: " m))
    )
    (princ)
  )
  (iic-stm-bang-ten)
  (princ "\nChọn các text, mtext và dim cần sửa:")
  (setq ss (ssget '((0 . "TEXT,MTEXT,DIMENSION"))))
  (if ss
    (progn
      ;; bam mau: bam truot thi bam lai, bam nham loai thi bao roi bam lai,
      ;; Enter de thoi.
      (while (not xong)
        (setvar "ERRNO" 0)
        (setq e (entsel "\nBấm text hoặc dim mẫu: "))
        (cond
          ((and (null e) (= (getvar "ERRNO") 7)) (princ "\nBấm trượt, bấm lại."))
          ((null e) (setq xong T))
          ((member (cdr (assoc 0 (entget (car e)))) '("TEXT" "MTEXT" "DIMENSION"))
           (setq nguon (car e) mau (iic-stm-doc-mau nguon) xong T))
          (t (princ "\nĐối tượng ấy không phải text, mtext hay dim. Bấm lại."))
        )
      )
      (if mau
        (progn
          (vla-StartUndoMark (iic-stm-tai-lieu))
          (setq i 0 n 0)
          (while (< i (sslength ss))
            (setq en (ssname ss i))
            (if (and (not (equal en nguon)) (iic-stm-ap en mau))
              (setq n (1+ n))
            )
            (setq i (1+ i))
          )
          (vla-EndUndoMark (iic-stm-tai-lieu))
          (princ (strcat "\nĐã sửa " (itoa n) " đối tượng theo mẫu \"" (car mau) "\"."))
        )
      )
    )
    (princ "\nKhông chọn được text, mtext hay dim nào.")
  )
  (princ)
)

;;; ------------------------------------------------------------------
;;;  Lenh STMX - xoa ghi de, dim hien lai so do that
;;; ------------------------------------------------------------------

(defun c:STMX (/ *error* ss i o n)
  (defun *error* (m)
    (vla-EndUndoMark (iic-stm-tai-lieu))
    (if (not (wcmatch (strcase m) "*CANCEL*,*QUIT*,*BREAK*"))
      (princ (strcat "\nLỗi: " m))
    )
    (princ)
  )
  (iic-stm-bang-ten)
  (princ "\nChọn các dim cần trả về số đo thật:")
  (setq ss (ssget '((0 . "DIMENSION"))))
  (if ss
    (progn
      (vla-StartUndoMark (iic-stm-tai-lieu))
      (setq i 0 n 0)
      (while (< i (sslength ss))
        (setq o (vlax-ename->vla-object (ssname ss i)))
        (if (/= (vla-get-TextOverride o) "")
          (progn (vla-put-TextOverride o "") (vla-Update o) (setq n (1+ n)))
        )
        (setq i (1+ i))
      )
      (vla-EndUndoMark (iic-stm-tai-lieu))
      (princ (strcat "\nĐã trả " (itoa n) " dim về số đo thật."))
    )
    (princ "\nKhông chọn được dim nào.")
  )
  (princ)
)

(princ "\nĐã nạp STM-IIC: gõ STM để sửa theo mẫu, STMX để trả dim về số đo thật.")
(iic-stm-bang-ten)

Bản dòng nhắc tiếng Anh: stm-iic-en.lsp.

Lệnh sửa dim trong CAD: chọn công cụ nào

Việc cần làmNên dùng
Nhiều text và dim cùng nhận một nội dungLisp STM
Nhiều dim thêm chữ mà vẫn giữ số đoLisp STM với một dim mẫu ghi ...<>...
Trả dim về số đo thậtLisp STMX
Thay một cụm chữ bằng cụm khác trong cả bản vẽLệnh FIND, xem bài sửa text hàng loạt trong CAD
Cộng, căn lề, đổi cỡ chữ hàng loạtlisp xử lý chữ hàng loạt

Câu hỏi thường gặp

Lisp sửa nhiều text và dim dùng thế nào?

Nạp stm-iic.lsp, gõ STM, quét chọn các text và dim cần sửa, Enter, rồi bấm một text hoặc dim làm mẫu.

Sửa dim bằng lisp có làm sai số đo không?

Không. Lisp chỉ đổi chữ hiển thị, số đo của dim giữ nguyên.

Muốn thêm chữ trước số đo cho cả loạt dim thì sao?

Ghi đè một dim thành dạng L=<>, rồi dùng nó làm mẫu cho STM. Mỗi dim sẽ hiện L= kèm số đo của chính nó.

Làm sao trả các dim đã bị ghi đè về số đo thật?

STMX và chọn các dim ấy.

Vì sao không đặt tên lệnh là MT như bản trên mạng?

MT là lệnh tắt có sẵn để mở MTEXT. Nạp lisp tên MT là mất lệnh tắt ấy.

Lỡ sửa nhầm thì sao?

U một lần. Cả lệnh STM gộp thành một bước hoàn tác.

Về tác giả

TS. Đỗ Quốc Hoàng — Phó Viện trưởng Viện Tin học Xây dựng, Trường Đại học Xây dựng Hà Nội, chuyên gia phát triển phần mềm cho ngành xây dựng