Bản vẽ móng có ba trăm ký hiệu cọc. Cần biết chính xác bao nhiêu cái, cần đổi màu cả loạt cho dễ nhìn, và cuối buổi cần phá riêng một loại ký hiệu ra để sửa. Ba việc, không việc nào AutoCAD làm sẵn cho ra hồn.
Bài này phát hành tệp lisp của Viện làm bốn việc ấy, và in trọn mã nguồn để bạn đọc trước khi chạy. Lisp đếm block trong CAD là lệnh hay dùng nhất trong bộ, nhưng ba lệnh còn lại mới là chỗ tiết kiệm thời gian. Muốn học trọn cách dùng block trong hồ sơ thì xem khóa AutoCAD Xây Dựng.
Vì sao AutoCAD sẵn có không đủ
Bốn việc, bốn chỗ hụt:
| Việc | Cách sẵn có | Hụt ở đâu |
|---|---|---|
| Đếm block | BCOUNT | Nằm trong Express Tools, không phải máy nào cũng cài |
| Đổi màu theo tên block | QSELECT rồi đổi | Phải qua hộp thoại, mỗi lần một điều kiện |
| Đổi tên block | RENAME | Làm được, nhưng không cảnh báo hậu quả |
| Phá riêng một loại block | không có | Phải tự chọn bằng tay từng cái |
Việc cuối là chỗ đau nhất. Trên một mặt bằng dày ký hiệu, muốn phá riêng loại ký hiệu cọc mà giữ nguyên ký hiệu cột thì không có cách nào ngoài chọn tay — hoặc phá hết rồi hối hận. Lệnh phá nói chung có trong bài lệnh explode trong CAD.
Tải tệp của Viện
| Lệnh | Việc nó làm |
|---|---|
BKD | đếm block theo tên, in bảng thống kê ra dòng lệnh |
BKM | đổi màu mọi bản chèn của một block |
BKT | đổi tên một block, mọi bản chèn tự theo |
BKP | phá hết bản chèn của một block, các block khác giữ nguyên |
;;; ==================================================================
;;; BLK-IIC.LSP - lam viec voi BLOCK hang loat
;;; Vien Tin hoc Xay dung (IIC) - Truong Dai hoc Xay dung Ha Noi
;;; https://iic.huce.edu.vn - Tel: 0989 427 809
;;; ------------------------------------------------------------------
;;; Bon lenh:
;;; BKD dem block theo ten, in bang thong ke ra dong lenh
;;; BKM doi mau MOI ban chen cua mot block
;;; BKT doi ten mot block, moi ban chen tu theo
;;; BKP pha het cac ban chen cua MOT block (cac block khac giu nguyen)
;;;
;;; Vi sao can tep nay: AutoCAD co lenh BCOUNT dem block nhung no nam
;;; trong Express Tools, va khong phai may nao cung cai. Con viec doi
;;; mau hay pha rieng mot loai block thi khong co lenh nao lam duoc:
;;; lenh QSELECT chon duoc theo ten block nhung phai qua hop thoai, va
;;; moi lan chi mot dieu kien.
;;;
;;; BON DIEU CAN BIET TRUOC KHI CHAY:
;;; 1. BKD dem BAN CHEN, khong dem dinh nghia. Mot block chen 40 lan
;;; thi dem ra 40. Ban chen nam trong block khac (block long nhau)
;;; KHONG duoc dem - chi dem lop ngoai cung.
;;; 2. BKM doi mau cua BAN CHEN chu khong doi mau cac net ben trong.
;;; Net nao ben trong dat mau CUNG (khong phai ByBlock) thi giu
;;; nguyen mau cu, doi bao nhieu lan cung the. Day la ly do quen
;;; thuoc cua "doi mau roi ma no khong doi".
;;; 3. BKT doi ten dinh nghia block. Ban ve nao dang xref toi ban ve
;;; nay, hay bang thong ke nao dang tra theo ten cu, deu hong.
;;; 4. BKP pha ban chen; block chen voi ti le X khac Y VAN pha duoc,
;;; nhung duong tron ben trong se thanh ELIP. Khong tranh duoc.
;;; Moi lenh deu IN ra so ban chen da dung toi, de doi chieu.
;;;
;;; Ten lenh da do truoc khi dat: tep bi danh acad.pgp cua ban 2027
;;; khong co BKD, BKM, BKT lan BKP.
;;;
;;; 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)
;;; canh trai / canh phai trong o rong n
(defun iic-dem (s n) (while (< (strlen s) n) (setq s (strcat s " "))) s)
(defun iic-phai (s n) (while (< (strlen s) n) (setq s (strcat " " s))) s)
;;; ------------------------------------------------------------------
;;; Ten that cua mot ban chen. Block dong thi ten hien la "*U123",
;;; phai hoi EffectiveName moi ra ten goc.
;;; ------------------------------------------------------------------
(defun iic-ten (e / o tn)
;; KHONG dat bien cuc bo ten "t": trong AutoLISP T la hang so dung,
;; gan no lam bien thi may bao "; error: incorrect object to bind: T".
(setq o (vlax-ename->vla-object e))
(setq tn (vl-catch-all-apply 'vlax-get (list o 'EffectiveName)))
(if (or (vl-catch-all-error-p tn) (null tn))
(cdr (assoc 2 (entget e)))
tn
)
)
;;; ------------------------------------------------------------------
;;; BKD - dem block theo ten
;;; ------------------------------------------------------------------
(defun c:BKD (/ ss i e ten bang o tong)
(princ "\nChon vung can dem (Enter de dem ca ban ve): ")
(setq ss (ssget '((0 . "INSERT"))))
(if (null ss) (setq ss (ssget "_X" '((0 . "INSERT")))))
(if ss
(progn
(setq bang nil i 0)
(while (< i (sslength ss))
(setq e (ssname ss i)
ten (iic-ten e)
o (assoc ten bang))
(if o
(setq bang (subst (cons ten (1+ (cdr o))) o bang))
(setq bang (cons (cons ten 1) bang))
)
(setq i (1+ i))
)
(setq bang (vl-sort bang (function (lambda (a b) (> (cdr a) (cdr b))))))
(setq tong 0)
(princ "\n")
(princ "\n Ten block So ban chen")
(princ "\n ---------------------------------------------")
(foreach o bang
(setq tong (+ tong (cdr o)))
(princ (strcat "\n " (iic-dem (car o) 32) (iic-phai (itoa (cdr o)) 11)))
)
(princ "\n ---------------------------------------------")
(princ (strcat "\n Tong so ban chen" (iic-phai (itoa tong) 29)))
(princ (strcat "\n So ten block khac nhau" (iic-phai (itoa (length bang)) 23)))
(princ "\n")
)
(princ "\nKhong co ban chen block nao.")
)
(princ)
)
;;; ------------------------------------------------------------------
;;; BKM - doi mau moi ban chen cua mot block
;;; ------------------------------------------------------------------
(defun c:BKM (/ ten mau ss i e n)
(setq ten (getstring T "\nTen block can doi mau: "))
(if (= ten "") (progn (princ "\nChua khai ten.") (exit)))
(setq mau (getint "\nSo mau (1 do, 2 vang, 3 luc, 4 lam nhat, 5 lam, 7 trang): "))
(if (null mau) (progn (princ "\nChua khai mau.") (exit)))
(setq ss (ssget "_X" '((0 . "INSERT"))) i 0 n 0)
(if ss
(progn
(while (< i (sslength ss))
(setq e (ssname ss i))
(if (= (strcase (iic-ten e)) (strcase ten))
(progn
(entmod (append (vl-remove-if (function (lambda (x) (= (car x) 62)))
(entget e))
(list (cons 62 mau))))
(setq n (1+ n))
)
)
(setq i (1+ i))
)
(princ (strcat "\nDa doi mau " (itoa n) " ban chen cua block \"" ten "\"."))
(if (= n 0)
(princ "\nKhong tim thay ban chen nao mang ten do. Go BKD de xem danh sach ten.")
(princ "\nLuu y: net nao ben trong block dat mau cung thi khong doi theo.")
)
)
(princ "\nBan ve khong co block nao.")
)
(princ)
)
;;; ------------------------------------------------------------------
;;; BKT - doi ten block
;;; ------------------------------------------------------------------
(defun c:BKT (/ cu moi bl kq)
(setq cu (getstring T "\nTen block hien tai: "))
(setq moi (getstring T "\nTen moi: "))
(if (or (= cu "") (= moi ""))
(progn (princ "\nThieu ten.") (exit))
)
(setq bl (tblobjname "BLOCK" cu))
(if (null bl)
(princ (strcat "\nKhong co block nao ten \"" cu "\". Go BKD de xem danh sach."))
(if (tblobjname "BLOCK" moi)
(princ (strcat "\nDa co block ten \"" moi "\" roi. Chon ten khac."))
(progn
(setq kq (vl-catch-all-apply
'vla-put-Name
(list (vla-item (vla-get-Blocks
(vla-get-ActiveDocument
(vlax-get-acad-object))) cu) moi)))
(if (vl-catch-all-error-p kq)
(princ (strcat "\nKhong doi duoc: " (vl-catch-all-error-message kq)))
(progn
(princ (strcat "\nDa doi \"" cu "\" thanh \"" moi "\"."))
(princ "\nLuu y: bang thong ke nao tra theo ten cu se khong tim thay nua.")
)
)
)
)
)
(princ)
)
;;; ------------------------------------------------------------------
;;; BKP - pha het ban chen cua MOT block
;;; ------------------------------------------------------------------
(defun c:BKP (/ ten ss i e ds ds2 n x)
(setq ten (getstring T "\nTen block can pha: "))
(if (= ten "") (progn (princ "\nChua khai ten.") (exit)))
(setq ss (ssget "_X" '((0 . "INSERT"))) i 0 ds (ssadd))
(if ss
(progn
(while (< i (sslength ss))
(setq e (ssname ss i))
(if (= (strcase (iic-ten e)) (strcase ten))
(setq ds (ssadd e ds))
)
(setq i (1+ i))
)
(setq n (sslength ds))
(if (= n 0)
(princ (strcat "\nKhong co ban chen nao ten \"" ten "\"."))
(progn
;; Pha TUNG ban chen mot. Truyen ca tap chon vao
;; (command "_.EXPLODE" ds) thi may chi pha DUNG MOT cai roi thoi
;; - da do tren ban 2027: chon 5 ban chen ma chi sinh 1 doi tuong
;; moi. Phai nhat het ename ra danh sach TRUOC khi pha, vi pha
;; xong la ename cu bien mat khoi ban ve.
(setq i 0 ds2 nil)
(while (< i n)
(setq ds2 (cons (ssname ds i) ds2) i (1+ i))
)
(foreach x ds2 (command "_.EXPLODE" x))
(princ (strcat "\nDa pha " (itoa n) " ban chen cua block \"" ten "\"."))
(princ "\nLuu y: duong tron trong block chen lech ti le se thanh elip.")
)
)
)
(princ "\nBan ve khong co block nao.")
)
(princ)
)
(princ "\nBLK-IIC da nap. Lenh: BKD (dem), BKM (doi mau), BKT (doi ten), BKP (pha).")
(princ)
Lisp đếm block trong CAD: con số in ra khớp bản vẽ đếm được
Dựng một bản vẽ có số bản chèn biết trước rồi chạy lệnh đếm:
| Block | Số lần chèn |
|---|---|
IIC_COT | 5 |
IIC_COC | 3 |
IIC_CUA | 1 |
IIC_TO | 1 |
| Cộng | 10 |
Chạy BKD, máy in ra:
Ten block So ban chen
---------------------------------------------
IIC_COT 5
IIC_COC 3
IIC_CUA 1
IIC_TO 1
---------------------------------------------
Tong so ban chen 10
So ten block khac nhau 4
Khớp từng dòng. Bảng xếp theo số lượng giảm dần nên loại nhiều nhất nằm trên cùng, tiện khi bản vẽ có vài chục tên block.
Enter thẳng ở câu hỏi đầu là đếm cả bản vẽ. Muốn đếm riêng một khu thì khoanh vùng rồi Enter.
Block nằm trong block thì không được đếm
Đây là chỗ khiến hai người đếm cùng một bản vẽ ra hai con số khác nhau.
Trong bản vẽ thử, block IIC_TO có chứa sẵn một bản chèn IIC_COC bên trong nó. Vậy trên màn hình có tất cả bốn hình IIC_COC: ba cái đặt trực tiếp, một cái nằm trong IIC_TO.
Bảng in ra ghi IIC_COC là 3, không phải 4.
Lệnh chỉ đếm lớp ngoài cùng. Về mặt hồ sơ thì cách đếm này thường là đúng: cái nằm trong IIC_TO là một phần của IIC_TO chứ không phải một ký hiệu độc lập. Nhưng phải biết để khỏi cãi nhau về con số. Cách tạo và lồng block có trong bài block trong CAD.
Đáng chú ý là công cụ của chính Autodesk cũng làm y như vậy. Trang BCOUNT của Autodesk ghi rõ: "BCOUNT does not select or count nested blocks or blocks nested in associative array objects." Nghĩa là con số bạn nhận được từ tệp của Viện và con số từ Express Tools sẽ giống nhau, và cả hai đều bỏ qua block lồng.
Câu cuối của trích dẫn ấy còn thêm một trường hợp nữa đáng nhớ: block nằm trong một mảng liên kết cũng không được đếm. Trên bản vẽ dùng lệnh mảng để rải ký hiệu, đây là chỗ con số hụt đi mà không ai ngờ. Lệnh mảng có trong bài lệnh array trong CAD.
Lisp đổi màu block trong CAD và lý do màu không đổi
Chạy BKM, khai tên block rồi khai số màu, cả loạt đổi ngay. Trong phép thử, khai IIC_COT và màu 1 thì cả 5 bản chèn đổi sang màu 1.
Nhưng rất nhiều người gặp cảnh đổi xong mà hình trên màn hình không đổi. Lý do đo được như sau.
Dựng hai block giống hệt nhau về hình, chỉ khác một điểm: đường tròn trong block thứ nhất để ByLayer, đường tròn trong block thứ hai đặt cứng màu 2. Đổi màu cả hai bản chèn sang màu 1:
| Màu bản chèn sau khi đổi | Màu nét bên trong | |
|---|---|---|
Block để ByLayer | 1 | vẫn 256, tức ByLayer — nên hiện theo màu 1 |
| Block đặt cứng màu 2 | 1 | vẫn là 2 |
Bản chèn thứ hai đã mang màu 1 thật, nhưng trên màn hình nó vẫn vàng. Vì nét bên trong nó được đặt cứng màu 2, và màu cứng thì không nghe theo bản chèn.
Cách chữa duy nhất: sửa định nghĩa block, đặt các nét bên trong về ByLayer hoặc ByBlock. Cách sửa có trong bài sửa block trong CAD, còn khác biệt giữa ByLayer và ByBlock có trong bài layer trong CAD.
Lisp đổi tên block trong CAD: làm được, nhưng nghĩ trước
Lệnh BKT hỏi tên cũ, hỏi tên mới, rồi đổi. Trong phép thử, đổi IIC_COC thành IIC_COC_MOI thì cả ba bản chèn lập tức mang tên mới — vì bản chèn không giữ tên riêng, nó chỉ trỏ về định nghĩa.
Lệnh từ chối trong hai trường hợp, và cả hai đều có báo rõ: không có block nào mang tên cũ, hoặc tên mới đã có block khác dùng rồi.
Điều cần cân nhắc trước khi đổi: mọi thứ tra theo tên cũ sẽ hỏng. Bảng thống kê lập theo tên block, tệp lisp của người khác lọc theo tên, bản vẽ khác đang xref sang — đổi tên là gãy hết. Xref có trong bài xref trong CAD.
Nên đổi tên block vào đúng một lúc: khi vừa nhận bản vẽ về, trước khi bắt đầu làm gì trên nó.
Có một việc đổi tên hoàn toàn đáng làm, và nhiều phòng vẽ bỏ qua. Bản vẽ nhận từ bốn đơn vị khác nhau thường mang bốn bộ tên block đặt tuỳ hứng, kiểu A$C1de05, Block1, 123, hay tên tiếng Anh viết tắt không ai đoán được. Gõ BKD một lần là thấy hết danh sách ấy, rồi đổi sang một bộ tên có quy tắc là bảng thống kê về sau đọc được ngay.
Quy tắc đặt tên nên gọn và bắt đầu bằng nhóm: CO-D300 cho cọc đường kính 300, CT-C1 cho cột C1. Tên bắt đầu bằng nhóm thì danh sách tự xếp cạnh nhau theo thứ tự chữ cái, khỏi phải tìm.
Lisp phá block trong CAD nhưng chỉ phá một loại
Đây là lệnh không có cách thay thế trong AutoCAD sẵn có.
Chạy BKP, khai tên block, máy phá hết bản chèn của riêng block ấy. Phép thử: bản vẽ có 10 bản chèn, khai IIC_COT:
| Trước | Sau | |
|---|---|---|
| Số đối tượng | 10 | 10 |
| Bản chèn block | 10 | 5 |
| Đường tròn rời | 0 | 5 |
Năm bản chèn IIC_COT thành năm đường tròn rời, năm bản chèn của ba block còn lại không bị đụng tới. Đúng như mong muốn.
Một lưu ý đã đo được ở bài về lệnh phá: block chèn với tỉ lệ X khác tỉ lệ Y vẫn phá được, nhưng đường tròn bên trong sẽ hoá thành elip. Không có cách tránh, nên với loại block ấy thì sửa định nghĩa là hơn.
Mấy điều hay nghe nhưng không đúng
| Người ta hay nói | Thực tế đo được |
|---|---|
| AutoCAD có sẵn lệnh đếm block | BCOUNT nằm trong Express Tools, không phải bản cài nào cũng có |
| Đếm block là đếm hết mọi bản chèn | Bản chèn nằm trong block khác không được đếm |
| Đổi màu block xong là hình đổi màu | Nét đặt cứng màu bên trong giữ nguyên màu cũ |
| Đổi tên block chỉ là đổi cái nhãn | Bảng thống kê và xref tra theo tên cũ đều gãy |
| Muốn phá một loại block thì phải chọn tay | BKP phá đúng loại đã khai, loại khác không đụng |
Câu hỏi thường gặp
Lệnh nào đếm block?
BKD. Enter thẳng ở câu hỏi đầu là đếm cả bản vẽ, hoặc khoanh vùng để đếm riêng một khu.
Vì sao con số đếm ít hơn tôi thấy?
Vì có bản chèn nằm bên trong một block khác. Lệnh chỉ đếm lớp ngoài cùng.
Đổi màu rồi mà hình không đổi thì sao?
Nét bên trong định nghĩa block đang đặt cứng màu. Phải sửa định nghĩa block, đặt các nét về ByLayer hoặc ByBlock.
Đổi tên block có làm hỏng gì không?
Có. Mọi bảng thống kê và mọi bản vẽ tra theo tên cũ sẽ không tìm thấy nữa. Nên đổi ngay lúc mới nhận bản vẽ.
Phá được riêng một loại block không?
Được, dùng BKP rồi khai tên. Các block khác giữ nguyên.
Block động thì đếm có đúng tên không?
Đúng. Lệnh hỏi tên gốc của block chứ không lấy cái tên tạm dạng *U123 mà bản vẽ sinh ra cho block động.