【问题标题】:Autolisp routine only works sometimesAutolisp 例程有时只有效
【发布时间】:2023-03-17 05:52:01
【问题描述】:

我不得不在 Autocad 中更改几个块的文本样式和宽度属性。每个 dwg 上有 10-30 个块,将近 100 个 dg,我懒得手动将每个块转换为新标准。

https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/attribute-width-change/td-p/1525357 此链接有一个脚本可以将所有块(标题块和几个电气符号)的宽度更改为 1,并且作为第一遍它执行我想要的操作(由于bad ; error: bad argument type: lentityp nil Command:which 在将其更改为手动选择并仅选择块后失败我想修复它)。但是,我还需要将测试样式从任何类型更改为“标准” https://www.afralisp.net/reference/dxf-group-codes.php 检查此链接后,我发现“文本样式名称”是代码 dxf 7 所以我将脚本更改为以下内容。

(defun C:StandardFromDWGTEXT (/ ss sslen cnt blck ent entinfo)
  (setq ss (ssget))
  (setq cnt 0)
  (setq sslen (sslength ss))
  (while (< cnt sslen)
    (setq blck (ssname ss cnt))
    (setq ent (entnext blck))
    (setq entinfo (entget ent))
    (while
      (and ent (= (cdr (assoc 0 entinfo)) "ATTRIB"))
       (entmod (subst (cons 41 1) (assoc 41 entinfo) entinfo))
;;;    (entupd ent)
;;;    (setq ent (entnext ent))
;;;    (setq entinfo (entget ent))    
       (entmod (subst (cons 7 "Standard") (assoc 7 entinfo) entinfo))
       (entupd ent)
       (setq ent (entnext ent))
       (setq entinfo (entget ent))      
    )
    (setq cnt (1+ cnt))
  )
  (princ)
)

现在它只适用于我注释掉的行(停止使用它们,但这也意味着它只改变文本样式而不是宽度)并且只改变一半时间的文本样式。我设法通过任意重新加载 auto-cad 来处理所有文件,有时当它不起作用时(不起作用意味着当我期望它时没有任何变化)在可视化 lisp 编辑器中打开脚本并点击加载活动窗口修复它。我会把它放在我身边,但为了学习,因为我已经不得不两次更改标准,所以我很有可能不得不再次这样做,我想尝试解决这个问题。

考虑到仅将宽度更改为 1 的脚本在 100% 的情况下有效,我认为问题不在于将其添加到启动套件/在可视化 lisp 编辑器中打开它,而在于我添加到代码中本身。但是我添加的用于更改文本样式的行 (entmod (subst (cons 7 "Standard") (assoc 7 entinfo) entinfo)) 似乎与更改文字宽度的行没有什么不同。

如果有人有任何见解,我将不胜感激。我有其他编程语言的经验,但在 Autolisp/lisp 方面完全是新手。

【问题讨论】:

    标签: autocad autolisp


    【解决方案1】:

    有一些问题可能会影响您的代码:

    • (setq ss (ssget))

      如果没有过滤器列表参数以仅允许属性块,您的选择可能包括 任何 实体类型,这意味着 entnext 调用将返回 nil对于没有子实体的任何对象。因此,这将导致 entget 调用返回您所看到的以下错误:

      错误:错误的参数类型:lentityp nil

      解决方案是包含一个过滤器列表,只允许选择属性块:

        (setq ss (ssget "_:L" '((0 . "INSERT") (66 . 1))))
      

      _:L 模式字符串也排除了锁定层上的实体。

    • (setq sslen (sslength ss))

      如果不测试有效选择,变量ss 可能是nil,这将导致(sslength ss) 返回错误:

      错误:错误的参数类型:lselsetp nil

    • (entmod (subst (cons 41 1) (assoc 41 entinfo) entinfo))
      (entmod (subst (cons 7 "Standard") (assoc 7 entinfo) entinfo))

      这里,第二个 subst 表达式替换了 原始 DXF 数据中的 DXF 组 7列表,而不是在替换 DXF 组 41 后已修改的 DXF 数据。这将导致反转对宽度因子的修改。


    对上述问题实施修复(并调整其他一些事情)可能会产生以下代码:

    (defun c:standardfromdwgtext ( / a i s x )
        (if (setq s (ssget "_:L" '((0 . "INSERT") (66 . 1))))
            (repeat (setq i (sslength s))
                (setq i (1- i)
                      a (entnext (ssname s i))
                      x (entget a)
                )
                (while (= "ATTRIB" (cdr (assoc 0 x)))
                    (if (entmod (subst '(41 . 1.0) (assoc 41 x) (subst '(7 . "Standard") (assoc 7 x) x)))
                        (entupd a)
                    )
                    (setq a (entnext a)
                          x (entget  a)
                    )
                )
            )
        )
        (princ)
    )
    

    【讨论】:

    • 尝试修改锁定层上的实体是否有问题? *会导致脚本崩溃吗?无论哪种方式都将其标记为已接受,因为我返回了一些它已损坏的文件,并且它没有再次静默崩溃。
    • 这取决于修改方法:entmod 将在尝试修改未启用写的实体时简单地返回 nil,因此程序不会崩溃,但由于此类对象不能进行修改显然更有效地将它们从初始选择中排除。其他修改方法,如修改ActiveX属性会返回Automation Error (On Locked Layer),导致程序崩溃。
    【解决方案2】:

    错误

    不好;错误:错误的参数类型:lentityp nil

    是用于实体的空变量的结果。

    当你使用(setq ent (entnext blck))时,你应该检查它是否为nil。

    (setq ent (entnext blck))
        (if ent
          (progn
            (setq entinfo (entget ent))
    

    在对 AutoLisp 进行故障排除时,如果您看到 lentityp 或 stringp = nil,那么您正在使用的变量被设置为 nil,您需要找出位置和原因。

    【讨论】:

    • 我认为错误可能是这样的,这就是为什么我将其更改为手动选择 (setq ss (ssget)) 而不是 (setq ss (ssget "x" '((0 . "INSERT")))) 作为快速修复。我实际上试图编写一个空检查,但它并没有解决我遇到的问题(不改变宽度和文本样式)并且使相同的代码静默失败/不做任何事情,所以我将其恢复。
    猜你喜欢
    • 1970-01-01
    • 2013-02-11
    • 2019-10-04
    • 1970-01-01
    • 2012-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多