Autocad - 自动更新 lisp 生成的字段(布局计数器)
Autocad - update lisp generated field automatically (layouts counter)
任务:在自动更新其值的字段中使用 sheet 计数器。最终目标是为每个布局创建类似 "Table {1} of {5}" 的文本,其中 {1} 是布局名称(位于 system variables / ctab
),{5} 是布局总数。后一个在内置字段中找不到,所以唯一知道它的方法是使用 lisp 代码 (length (layoutlist))
.
我创建了一个 AcadDoc.lsp 文件并放在 autodesk 文件夹中。 LISP代码如下:
(setq *LayoutCount*
(length
(vl-remove-if
(function
(lambda (aLayout) (= (strcase aLayout) "MODEL")))
(layoutlist))))
每次我打开 DWG 文件时运行。可悲的是,在重新加载 DWG(关闭并重新打开)之前,该字段不会更新。每次布局从列表中 added/removed 时,有人知道如何更新此 *LayoutCount* 变量吗?
注意 - 我已经检查了切换布局时重新生成的选项,并且强制更新字段不会产生任何结果。我想我的代码只在第一次打开 DWG 时运行,然后就不再运行了。
如您所知,acaddoc.lsp
文件中的代码只会在绘图启动时进行评估,因此您的 *LayoutCount*
变量的值只会在绘图时正确首次打开。
解决此问题的一种可能方法是使用 Visual LISP Reactor 在执行特定操作后更新此变量的值。
例如,您可以按以下方式使用 Miscellaneous Reactor 在活动布局更改时更新变量值:
(
(lambda ( )
(vl-load-com)
(foreach grp (vlr-reactors :vlr-miscellaneous-reactor)
(foreach rtr (cdr grp)
(if (= "layoutcount-reactor" (vlr-data rtr))
(vlr-remove rtr)
)
)
)
(vlr-set-notification
(vlr-miscellaneous-reactor "layoutcount-reactor"
'(
(:vlr-layoutswitched . layoutswitched-callback)
)
)
'active-document-only
)
(defun layoutswitched-callback ( rtr arg )
(setq *layoutcount* (length (layoutlist)))
)
(layoutswitched-callback nil nil)
(princ)
)
)
将以上代码复制到您的 acaddoc.lsp
,*layoutcount*
变量将在绘图启动时定义,并在每次更改活动布局时更新。
此外,没有必要从 layoutlist
函数返回的列表中删除 Model
,因为此函数仅 returns图纸空间布局列表。
但是,使用全局变量提供此信息的缺点是全局变量将仅在 活动 AutoCAD 会话 期间在文档命名空间内定义,并且需要为每个会话重新定义。
因此,如果您的一位同事或第三方要打开绘图文件,除非他们也是 运行 在您的 acaddoc.lsp
中找到的代码,否则 *layoutcount*
变量不会被定义,因此该字段不会正确显示。
因此,另一种方法是利用以下事实:字段表达式实际上可以引用 任何 ActiveX 属性,而不仅仅是 FIELD
中显示的那些命令对话框。
我用我的 Layout Field application 演示了此技术,它允许您创建引用布局集合的 Count
属性 的字段表达式。
这种方法有几个优点:
- 绘图内容不依赖于任何外部代码。
- 未引用
CTAB
系统变量,这意味着DATAEXTRACTION
命令将输出正确的信息,而不是为每个布局输出相同的值。
任务:在自动更新其值的字段中使用 sheet 计数器。最终目标是为每个布局创建类似 "Table {1} of {5}" 的文本,其中 {1} 是布局名称(位于 system variables / ctab
),{5} 是布局总数。后一个在内置字段中找不到,所以唯一知道它的方法是使用 lisp 代码 (length (layoutlist))
.
我创建了一个 AcadDoc.lsp 文件并放在 autodesk 文件夹中。 LISP代码如下:
(setq *LayoutCount*
(length
(vl-remove-if
(function
(lambda (aLayout) (= (strcase aLayout) "MODEL")))
(layoutlist))))
每次我打开 DWG 文件时运行。可悲的是,在重新加载 DWG(关闭并重新打开)之前,该字段不会更新。每次布局从列表中 added/removed 时,有人知道如何更新此 *LayoutCount* 变量吗?
注意 - 我已经检查了切换布局时重新生成的选项,并且强制更新字段不会产生任何结果。我想我的代码只在第一次打开 DWG 时运行,然后就不再运行了。
如您所知,acaddoc.lsp
文件中的代码只会在绘图启动时进行评估,因此您的 *LayoutCount*
变量的值只会在绘图时正确首次打开。
解决此问题的一种可能方法是使用 Visual LISP Reactor 在执行特定操作后更新此变量的值。
例如,您可以按以下方式使用 Miscellaneous Reactor 在活动布局更改时更新变量值:
(
(lambda ( )
(vl-load-com)
(foreach grp (vlr-reactors :vlr-miscellaneous-reactor)
(foreach rtr (cdr grp)
(if (= "layoutcount-reactor" (vlr-data rtr))
(vlr-remove rtr)
)
)
)
(vlr-set-notification
(vlr-miscellaneous-reactor "layoutcount-reactor"
'(
(:vlr-layoutswitched . layoutswitched-callback)
)
)
'active-document-only
)
(defun layoutswitched-callback ( rtr arg )
(setq *layoutcount* (length (layoutlist)))
)
(layoutswitched-callback nil nil)
(princ)
)
)
将以上代码复制到您的 acaddoc.lsp
,*layoutcount*
变量将在绘图启动时定义,并在每次更改活动布局时更新。
此外,没有必要从 layoutlist
函数返回的列表中删除 Model
,因为此函数仅 returns图纸空间布局列表。
但是,使用全局变量提供此信息的缺点是全局变量将仅在 活动 AutoCAD 会话 期间在文档命名空间内定义,并且需要为每个会话重新定义。
因此,如果您的一位同事或第三方要打开绘图文件,除非他们也是 运行 在您的 acaddoc.lsp
中找到的代码,否则 *layoutcount*
变量不会被定义,因此该字段不会正确显示。
因此,另一种方法是利用以下事实:字段表达式实际上可以引用 任何 ActiveX 属性,而不仅仅是 FIELD
中显示的那些命令对话框。
我用我的 Layout Field application 演示了此技术,它允许您创建引用布局集合的 Count
属性 的字段表达式。
这种方法有几个优点:
- 绘图内容不依赖于任何外部代码。
- 未引用
CTAB
系统变量,这意味着DATAEXTRACTION
命令将输出正确的信息,而不是为每个布局输出相同的值。