我不太熟悉 AutoLISP,在编写将文本或多行文本中的数字递增 1 的脚本时遇到问题,最好是所有选定的文本。
(defun c:IncrementTextNumbers (/ ss obj)
(setq ss (ssget '((0 . "TEXT")(62 . 1))))
(if ss
(progn
(setq obj (ssname ss 0))
(while obj
(if (and (= (cdr (assoc 0 (entget obj))) "TEXT")
(numberp (atoi (cdr (assoc 1 (entget obj))))))
(progn
(setq num (atoi (cdr (assoc 1 (entget obj)))))
(setq new-num (+ num 1))
(command "_.CHANGE" obj "" new-num)
)
)
(setq obj (ssname ss (1+ (ssname ss (sslength ss) obj))))
)
(princ "\nHighlighted text numbers incremented successfully.")
)
(princ "\nNo highlighted text objects found.")
)
(princ)
您应该使用
(entmod )
而不是零钱。还简化了您的示例。试试这个代码。
(defun c:IncrementTextNumbers (/ ss obj)
(setq ss (ssget '((0 . "*TEXT"))))
(if ss
(progn
(setq index 0)
(setq obj (ssname ss index))
(while obj
(setq content (cdr (assoc 1 (entget obj))))
(setq num (atoi content))
(if (numberp num)
(progn
(setq new-num (1+ num ))
(setq ed (entget obj))
(setq ed (subst (cons 1 (itoa new-num)) (assoc 1 ed) ed))
(entmod ed)
)
)
(setq index(1+ index ))
(setq obj (ssname ss index))
)
(princ "\nHighlighted text numbers incremented successfully.")
)
(princ "\nNo highlighted text objects found.")
)
(princ)
)
您的代码的主要问题是用于迭代选择集的方法 - 具体来说,这一行:
(setq obj (ssname ss (1+ (ssname ss (sslength ss) obj))))
ssname
函数接受一个选择集和一个索引作为参数;在这里,在最里面的表达式中,您提供了一个选择集 (ss
)、一个索引 ((sslength ss)
) 和一个实体名称 (obj
)。 ssname
还返回一个实体名称,您不能使用 1+
函数增加它。
我建议学习我关于 Selection Set Processing 的教程,以了解迭代选择集的各种方法。
对于这个特定的例子,我可能会使用我的教程中描述的 'reverse repeat' 技术,因为这会产生简洁高效的代码,例如:
(defun c:IncrementTextNumbers ( / idx sel )
(if (setq sel (ssget "_:L" '((0 . "TEXT,MTEXT"))))
(repeat (setq idx (sslength sel))
(setq idx (1- idx)
;; ... do stuff ...
)
)
)
(princ)
)
在这里,你还会注意到我已经按照以下方式修改了
ssget
表达式:
"_:L"
模式字符串排除锁定层上的对象 - 下划线确保使用模式字符串的非本地化版本。TEXT,MTEXT
允许用户选择单行文本和多行文本,同时排除RTEXT
.首先,我要注意你的程序中的这一行不是必需的:
(= (cdr (assoc 0 (entget obj))) "TEXT")
因为您已经在
TEXT
选择过滤器中过滤ssget
实体。
其次,你应该知道
atoi
总是无益地返回一个数值,不管输入文本如何,观察:
_$ (atoi "abc")
0
因此,对于所有文本内容,表达式
(numberp (atoi ...))
将始终返回 T
。
由于在这种情况下您也无法测试非零内容(因为内容可能合法为零),我建议使用
distof
函数将字符串转换为数字(因为此函数将返回 nil
用于非数字输入),或者如果您想将输入限制为仅整数,则可以使用 wcmatch
函数来测试字符串是否仅包含数字(或者更好的是,将此测试合并到 ssget
选择中过滤器)。
以下是每种方法的示例:
使用
distof
(defun c:IncrementTextNumbers ( / enx idx sel str )
(if (setq sel (ssget "_:L" '((0 . "TEXT,MTEXT"))))
(repeat (setq idx (sslength sel))
(setq idx (1- idx)
enx (entget (ssname sel idx))
str (cdr (assoc 1 enx))
)
(if (distof str 2)
;; ... do stuff ...
)
)
)
(princ)
)
使用
wcmatch
(测试正整数)
(defun c:IncrementTextNumbers ( / enx idx sel str )
(if (setq sel (ssget "_:L" '((0 . "TEXT,MTEXT"))))
(repeat (setq idx (sslength sel))
(setq idx (1- idx)
enx (entget (ssname sel idx))
str (cdr (assoc 1 enx))
)
(if (wcmatch str "~*[~0-9]*")
;; ... do stuff ...
)
)
)
(princ)
)
使用
ssget
过滤器(测试正整数
(defun c:IncrementTextNumbers ( / enx idx sel str )
(if (setq sel (ssget "_:L" '((0 . "TEXT,MTEXT") (1 . "~*[~0-9]*"))))
(repeat (setq idx (sslength sel))
(setq idx (1- idx)
enx (entget (ssname sel idx))
str (cdr (assoc 1 enx))
)
;; ... do stuff ...
)
)
(princ)
)
entmod
代替命令最后,您可以使用
entmod
直接修改图形数据库的内容,而不是使用 AutoCAD 命令执行此操作(这更慢且不太可靠,因为您依赖于提示的顺序保持不变在 AutoCAD 版本之间)。
考虑以下代码:
(defun c:IncrementTextNumbers ( / enx idx itm sel )
(if (setq sel (ssget "_:L" '((0 . "TEXT,MTEXT") (1 . "~*[~0-9]*"))))
(repeat (setq idx (sslength sel))
(setq idx (1- idx)
enx (entget (ssname sel idx))
itm (assoc 1 enx)
)
(entmod (subst (cons 1 (itoa (1+ (atoi (cdr itm))))) itm enx))
)
)
(princ)
)