如何提取源TEXT/MTEXT的文字高度并应用到待替换文字?
AutoLISP代码问题排查与修正
问题描述
我基于gileCAD的代码自行调整了一段AutoLISP程序,需求是替换选中TEXT/MTEXT内容的同时,继承源TEXT/MTEXT/ATTRIB的文字高度与颜色。但遇到两个问题:
- 自行修改的代码运行时报错:
Program ERROR: bad DXF group: 50.0 - CAD开发者修改后的代码无报错,能正确应用源文本的高度与颜色,但无法替换选中TEXT/MTEXT的内容
第一段(自行修改报错)的代码
(defun c:MTP (/ cEnt elst text color ss i textSize) (if (and (setq cEnt (car (nentsel "\nSelect Source Text: "))) (member (cdr (assoc 0 (entget cEnt))) '("TEXT" "MTEXT" "ATTRIB") ) 1) (progn (setq elst (entget cEnt) text (assoc 1 elst) color (cond ((assoc 62 elst)) (T '(62 . 256)) ) textSize (cdr (assoc 40 elst)) ; get text size ) (redraw cEnt 3) (if (setq ss (ssget '((0 . "TEXT,MTEXT")))) (repeat (setq i (sslength ss)) (setq elst (entget (ssname ss (setq i (1- i))))) (entmod (subst text (assoc 1 elst) (if (assoc 62 elst) (entmod (subst color (assoc 62 elst) elst)) (append elst (list color)) ) (entmod (subst textSize (assoc 40 elst) elst)) (append elst (list textSize)) ) ) ) ) ) ) (command "_regenall") (princ) )
CAD开发者修改后的代码(内容替换失效)
(defun c:MTP (/ cEnt elst text color ss i textSize) (if (and (setq cEnt (car (nentsel "\nSelect Source Text: "))) (member (cdr (assoc 0 (entget cEnt))) '("TEXT" "MTEXT" "ATTRIB") ) 1) (progn (setq elst (entget cEnt) text (assoc 1 elst) color (cond ((assoc 62 elst)) (T '(62 . 256)) ) textSize (cdr (assoc 40 elst)) ; get text size ) (redraw cEnt 3) (if (setq ss (ssget '((0 . "TEXT,MTEXT")))) (repeat (setq i (sslength ss)) (setq elst (entget (ssname ss (setq i (1- i))))) (entmod (subst text (assoc 1 elst) (if (assoc 62 elst) (entmod (subst color (assoc 62 elst) elst)) (append elst (list color)) ) ) ) (entmod (if (assoc 40 elst) (subst (cons 40 textSize) (assoc 40 elst) elst) (append elst (list (cons 40 textSize))) ) ) ) ) ) ) (command "_regenall") (princ) )
问题原因分析
第一段代码报错原因
- DXF组对格式错误:
textSize是单纯的数值(比如2.5),但subst需要替换的是完整的DXF组对(格式为(40 . 数值)),直接传入数值会导致CAD识别无效的DXF组,触发bad DXF group错误。 - entmod嵌套调用错误:
entmod是用于修改实体的函数,它的返回值不是供subst使用的DXF列表,在subst内部嵌套调用entmod会导致传递给entmod的参数混乱。
开发者修改后代码的内容替换失效原因
在文字替换的entmod中,嵌套调用了(entmod (subst color ...)):
- 第一次
entmod修改颜色后,返回的是修改后的DXF列表,但此时外部的elst还是旧的实体数据 - 用旧的
elst去替换文字内容,会导致文字替换的逻辑基于旧数据执行,最终无法正确更新内容
修正后的代码
(defun c:MTP (/ cEnt srcElst srcText srcColor srcTextSize ss i targetEnt targetElst) ;; 选择源文本并验证类型 (if (and (setq cEnt (car (nentsel "\n选择源文本: "))) (member (cdr (assoc 0 (setq srcElst (entget cEnt)))) '("TEXT" "MTEXT" "ATTRIB") ) ) (progn ;; 提取源文本的内容、颜色、高度 (setq srcText (assoc 1 srcElst) srcColor (cond ((assoc 62 srcElst)) (T '(62 . 256)) ; 默认随层颜色 ) srcTextSize (cons 40 (cdr (assoc 40 srcElst))) ; 转为DXF组对格式 ) (redraw cEnt 3) ; 高亮源文本 ;; 选择需要替换的目标文本 (if (setq ss (ssget '((0 . "TEXT,MTEXT")))) (repeat (setq i (sslength ss)) (setq targetEnt (ssname ss (setq i (1- i))) targetElst (entget targetEnt) ) ;; 构建修改后的DXF列表:先处理颜色,再处理文字,最后处理高度 (setq targetElst (if (assoc 62 targetElst) (subst srcColor (assoc 62 targetElst) targetElst) (append targetElst (list srcColor)) ) targetElst (subst srcText (assoc 1 targetElst) targetElst) targetElst (if (assoc 40 targetElst) (subst srcTextSize (assoc 40 targetElst) targetElst) (append targetElst (list srcTextSize)) ) ) ;; 一次性应用所有修改 (entmod targetElst) ) ) ) ) (command "_regenall") (princ) )
修正点说明
- 统一DXF组对格式:将源高度转为
(40 . 数值)的标准DXF组对,避免格式错误。 - 取消entmod嵌套:先在内存中构建完整的修改后DXF列表,再一次性调用
entmod应用所有修改,确保数据一致性。 - 变量命名更清晰:区分源文本和目标文本的变量,避免混淆。
- 逻辑顺序优化:先修改颜色,再替换文字,最后设置高度,确保每一步都基于最新的实体数据。
内容的提问来源于stack exchange,提问作者codeTester-
相关产品推荐
相关产品推荐

