版本声明(全系列统一口径)
本篇基线为AVEVA E3D Design 3.1。属性名与集合写法出自官方示例与官方人员在该产品社区回复中给出的官方文档坐标;完整宏出自AVEVA Community 的真实帖,正文已逐段标注为社区来源。
凡本系列按官方已发表写法组合构造、未在本机跑通的代码,均标注**“按官方已发表的写法组合构造,需在本地 E3D Design 环境验证”**;官方材料未给出的名称(如元素引用的href/tref/cref一类、以及交互输入对象的确切方法名)本篇一律不写,只在文中显式说明"未核实、去查哪一章"。
写库操作不可逆:本篇正文中的复制、重命名、include等写操作用例,必须在测试 MDB 上执行或先做备份。
官方把 PML 交互入口称为Command Window(命令窗口):Tools 标签 → Display 组 → Commands。
一句话结论
模型数据访问就三件事——用!!ce知道"现在在哪"、用DBREF的引用去读写属性、用coll all ... for ...把"一批元素"装进集合再do ... value逐个处理;而被无数人搞错的一点是:PML 的 collection 与界面上那个 “My Collections” 完全不是一回事。
〇认知问题
!!ce到底是什么?为什么它一会儿是设备、一会儿是管子,我改一个命令它就变了?DBREF是什么?我能在变量里"存一个元素"吗?存了之后怎么用?coll all ... for ...这句该怎么读?for后面到底能写什么?MATCHW是干什么的?为什么筛选名字要用它而不是直接比较?SIZE()和!b[$!i]是什么关系?遍历到底该用DO ... VALUE还是用下标循环?- 界面上不是有个 “My Collections” 吗?我在 PML 里能不能直接用它?
一机制解析
1.1!!ce是什么:一个"跟随界面"的全局引用
!!ce是本系列出现频率最高的符号。它的真实含义是:
ce是一个全局变量(!!前缀),它的值是当前元素的数据库引用;- "当前"由环境决定——你在图形界面里选中了什么、上一条命令把谁变成了当前,它就跟着变;
- 所以它是环境状态,不是常量。这也是第 05 篇里"把
!!ce快照进对象成员"之所以有意义的原因:!!ce会变,快照不会。
官方示例里出现过两个很典型的用法:
-- 官方表单示例的方法体:读出当前元素的信息 q var !!ce.flnn-- 官方对象示例:把当前元素及其属性快照进对象 !this.element = !!ce !this.name = !!ce.name !this.type = !!ce.type !this.position = !!ce.position工作要求:写任何脚本前,先在心里问一句"此刻!!ce是谁"。所有"跑错对象"的事故,根因都是这个问题没回答。
1.2DBREF与属性读取
DBREF是"数据库引用"——它指向模型里的一个元素。它是 PML2 对象成员的类型之一(官方对象示例中member .element is DBREF),也是 SCRM 对象类型名单里的正式类型。
为什么用引用而不是名字?因为名字会变、会重名,而引用是稳定标识。真正要"操作某个元素"的场景(改属性、复制、移动),必须持有引用;只打印名字的场景才可以只留字符串。
属性读取的写法是点号:!!ce.<属性名>。本篇只使用在官方示例与社区真实宏中确证出现过的属性名:
| 属性写法 | 含义(按已核实示例的用法) | 出处 |
|---|---|---|
!!ce.name | 元素名 | 官方对象示例、社区宏 |
!!ce.type | 元素类型 | 官方对象示例 |
!!ce.position | 元素位置 | 官方对象示例 |
!!ce.flnn | 输出用属性(官方表单示例q var !!ce.flnn原样) | 官方表单示例 |
!!ce.namn | 名称类属性(社区宏中!a = !!ce.namn) | 社区来源 |
重要提醒:PML 元素的属性远不止这五个,而且有些极其常用的引用类属性(例如表示"头/尾/所属"方向引用的属性名)在本篇依据的材料中没有出现。这些属性名请到SCRM 的 “Methods Available to All Objects” 与 “Object Type Details”两节核对后再使用——本篇不提供一个未经核实的属性名清单,因为编造属性名的代价是读者照抄后必然失败。
读属性与写属性的差别:读是安全的;写是不可逆的。官方数据库接口在写操作上不会替你兜底——写库前必须可回退(测试 MDB 或先在备份上验证),这是本系列的硬纪律。
1.3 集合:两种实现,以及和 “My Collections” 的区别
先说一个真实存在的两套实现。官方人员在该产品社区的回复中给出了集合相关的官方文档坐标:
- PML1 数组式
VAR ... COLLECT:https://docs.aveva.com/bundle/e3d-design/page/911971.html - PML2 集合对象:https://docs.aveva.com/bundle/e3d-design/page/962745.html
- 文件对象:https://docs.aveva.com/bundle/e3d-design/page/1026879.html
也就是说:"集合"在你用的那种 PML 风格里有不同的形态——PML1 侧偏"数组式收集",PML2 侧是"集合对象"。这与第 05 篇讲的"两代风格各有擅长"是同一件事的具体体现。
再说那个必须扭正的误解。官方人员在同一条回复里明确强调:PML 中的 collection 与界面上的 “My Collections” 不是一回事;界面上看到的Shared Collections 实际上是 GPWL / GPSET / GPITEMS 体系(可以用GADD PIPE /name这类命令往里添加)。PMLCG 目录里另有Core Managed Objects一章,与这类受管的界面对象有关。
实践含义:不要假设"界面上攒的那个 Collection,我在 PML 里用coll all ...就能遍历出来"。要在 PML 里遍历,就用命令在模型里建立集合(coll all ... for ...);要在界面体系里组织元素,走的是GPWL/GPSET/GPITEMS +GADD这条线。两者不要混。
1.4 集合遍历三件套
把社区真实宏里的写法提炼出来,"遍历一批元素"这件事由三段构成:
第一段:建立集合。写法形如(社区来源):
var !supp coll all suppo for CE var !b coll all suppo with matchw(name of suppo,'*copy-of-*') for zone读法:var <集合变量> coll all <元素类型> [with <筛选条件>] for <范围>。
coll all:收集全部匹配项("all"是"取全部"的语义);suppo:要收集的元素类型——这里用的是社区宏里的真实类型标识suppo(支吊架),你在自己的项目里要替换成目标类型;with ...:可选筛选段;for CE/for zone:范围。社区宏里出现了for CE与for zone两种写法。范围关键字的完整可选值,请以两个官方集合文档页为准(https://docs.aveva.com/bundle/e3d-design/page/911971.html、https://docs.aveva.com/bundle/e3d-design/page/962745.html)。
第二段:逐个处理(DO ... VALUE)。写法形如:
do !x value !supp $!x ... enddo语义要点:do !x value !集合把集合里的元素逐个取出赋给!x;而真正让"处理对象"变成它的关键是$!x这一行单独摆放——它把!x的内容注入成一条命令,从而把当前元素切换到这个元素。之后所有不带显式对象名的命令(读!!ce.xxx、NEW、RENAME等)都作用在它身上。
这是 PML1 数据访问的核心套路:不是"给函数传对象",而是"把当前元素切换过去"。
第三段:按下标访问(SIZE()+$!b[$!i])。写法形如:
do !i from 1 to !b.size() $!b[$!i] ... enddo!b.size():集合中元素个数;!b[$!i]:按位置取第!i个元素。- 两套写法怎么选?只求"每个都过一遍"→
DO ... VALUE更简洁;需要知道当前是第几个(打进度、按序号算偏移、中途BREAK)→ 用下标循环。社区宏里两种都用了,正是因为这个区别。
1.5MATCHW:为什么名字筛选要用它
社区宏里的筛选段是:
var !b coll all suppo with matchw(name of suppo,'*copy-of-*') for zonematchw是通配匹配:第一个参数是"要匹配的表达式"(这里是name of suppo,即"支吊架的名字"),第二个参数是带通配符的模式('*copy-of-*'表示"名字里含 copy-of")。
为什么不能直接用等号比较?因为你要筛的是"某一类名字"(按命名规则生成的中间产物,如xxx-copy-of-yyy),而不是一个确定的名字。通配匹配是"按命名规则筛数据"的唯一实用手段——这在批量作业里极其常见:命名规范就是你的筛选条件。
注意模式里的两个细节:
- 通配符是
*,可出现在模式两端('*copy-of-*'); - 被匹配的对象是"表达式"而不是"字符串字面量":写的是
name of suppo而不是'name'。这种X of Y的写法在 PML 里表示"取 Y 的 X 属性",是筛选条件里常用的形式。
1.6 本篇有意未写的两块内容
按本系列的真实性纪律,下面两块在本篇依据的材料里没有核实到确切名称与语法,因此本篇不给代码,只给"去哪查":
(一)元素引用类的属性。在以本产品为主题的社区经验里,常会提到形如href、tref、cref这类"头/尾/所属引用"属性,以及用它们配合添加类命令做筛选的惯用法。本篇依据的官方示例与社区宏中并未出现这些名称,因此本篇不提供它们的用法。请到SCRM 的 Methods Available to All Objects 与 Object Type Details两节,以及PMLCG 的 Using PML in AVEVA Products / Core Managed Objects章查证后再用。
(二)交互式输入对象的方法名。ALERT既是 SCRM 对象类型名单里的正式类型,PMLCG 目录里也有独立的Alert Objects章。但"如何弹出输入框、方法名叫什么"在本篇依据的材料中没有出现,故本篇不写任何alert方法名——请查上述两处。
替代方案:在学会交互输入之前,用"参数化宏 + 表单"两条路顶替——把用户要输入的值做成宏参数($1、$2),或做成表单上的 gadget 再用.val取值。
二完整代码与逐行剖析
2.1 社区真实宏完整复刻(社区来源)
下面这段代码原样来自 AVEVA Community 的 PML and PML2 子板块(https://community.aveva.com/aveva-engineering/pdms-e3d-forum/f/pml-and-pml2),属社区来源,不是官方结论。它的业务目标是支吊架的批量复制与重命名。
-- 来源:AVEVA Community(PML and PML2 子板块)真实帖,社区来源 -- 用途:支吊架批量"复制 + 按命名规则重命名 + 移动到目标 zone" -- 警告:含 NEW / RENAME ALL / INCLUDE 等写操作,务必在测试 MDB 上运行 -- 说明:本系列原样照录,未做改写;其中 !e、!f 这两个变量在本帖摘录中没有出现赋值, -- 属于"依赖帖外上下文"的写法——这也是社区代码的典型特征,引用时必须留意。 var !supp coll all suppo for CE do !x value !supp $!x !a = !!ce.namn new suppo /copy-of-$!a copy prev rename /$!a /copy-of-$!a var !b coll all suppo with matchw(name of suppo,'*copy-of-*') for zone do !i from 1 to !b.size() $!b[$!i] !q = !!ce.name !c = !!ce.name.replace('copy-of-','').split('-') !d = !c[1] + '-' + !c[2] + '-' + '$!e' q var !q rename all $!q $!d $!f $* destination zone include $!d enddo enddo2.2 逐步拆解
外层:遍历当前范围内的全部支吊架。
var !supp coll all suppo for CE:建立集合,收集范围是CE(当前元素)下的支吊架,存入!supp。注意集合变量名!supp只有 5 个字符,符合 16 字符限制。do !x value !supp…enddo:逐个取出,!x是当前这一轮的元素。$!x:把!x变成当前元素。这一行是整段代码"能工作"的前提——后面所有!!ce.xxx与命令都作用在它身上。!a = !!ce.namn:把当前支吊架的namn(名称类属性)读进!a。做法上先落到局部变量再拼命令,而不是直接写进命令里,这是更稳的风格。
内层第一步:复制出一个带标记的副本。
new suppo /copy-of-$!a copy prev rename /$!a /copy-of-$!a:这条命令链做了三件事——新建一个支吊架、从PREV(上一个元素)复制(copy prev,与第 03 篇的PREV相对定位词同源)、并在这条链内做一次改名。- 注意这里的
rename是NEW命令链中的一段,与后面独立出现的rename all不是同一种用法——这是极易混淆的一处,务必分清。 - 命名上用
copy-of-<原名>作为"中间产物名",这是一种可被通配筛选识别的标记,也是下面matchw能生效的原因。这是一套完整的工程手法:先打标记、再按标记筛选、最后统一整理。
- 注意这里的
内层第二步:把刚产生的那批副本收集起来。
var !b coll all suppo with matchw(name of suppo,'*copy-of-*') for zone:按"名字含copy-of"筛选,范围是zone。这一行是MATCHW的教科书用法:命名规则即筛选条件。do !i from 1 to !b.size():改用下标循环,因为下面要用到序号信息(并且需要能控制遍历过程)。$!b[$!i]:把第!i个副本设为当前元素。这是"按下标访问 + 注入"的组合写法。
内层第三步:按规则重命名,并归位。
!q = !!ce.name:读当前副本的名字(即xxx-copy-of-yyy形态)存入!q。!c = !!ce.name.replace('copy-of-','').split('-'):先删除copy-of-段,再按-切分,得到名字的各段数组(!c[1]、!c[2]……)。这是把命名规则"解析回结构化数据"的手法。!d = !c[1] + '-' + !c[2] + '-' + '$!e':用字符串拼接重新组装新名。- 必须留意:这里用到了
!e,而!e在这段摘录里没有赋值——它依赖帖外上下文。这正是社区代码的典型特征:能跑,但上下文不完整。引用社区代码时,一定要自己把"来源不明的变量"标出来。
- 必须留意:这里用到了
q var !q:把改名前的旧名输出到 Command Window。作用是留审计痕迹——批量改名必须能事后对照。rename all $!q $!d:按旧名到新名批量重命名(该方法出自本社区帖;本系列在第 03 篇已用过同一写法并标注了来源性质)。$!f $* destination zone:把元素移动到目标 zone。!f同样在摘录中没有赋值(帖外上下文);$* destination zone是"目标区"这一层语义的写法。include $!d:按新名把元素纳入/挂接到指定位置。INCLUDE与RENAME ALL的配合是批量改名的关键环节:改名之后必须确保元素落在正确的位置上,否则名字对了、位置错了,同样是一次生产事故。
这段宏给我们的四条可迁移经验:
- 命名规则是批量作业的骨架:先产生"可识别的中间名",再按规则筛、按规则解析、按规则重命名。
- “先落变量、再拼命令”:
!a = !!ce.namn这种做法比把属性直接写进命令串里更稳,也更易调试。 - 批量改名必须留审计:
q var !q这类输出不是可选项。 - 社区代码要标出"上下文缺口":
!e、!f就是例子;照抄而不检查变量来源,是事故的常见起点。
2.3 只读巡检骨架(按社区宏中已验证写法构造,需在本地 E3D Design 环境验证)
把上面那段里只读、无副作用的部分抽出来,做成一个可以随手跑的数据巡检宏。它不做任何写操作,适合放在"写脚本之前先看清数据"这一步。
-- 文件:suppInspect.mac -- 用途:只读巡检——列出当前范围内的支吊架及其名称,不做任何写操作 -- 说明:所有写法均取自社区宏中已验证的形态(coll all / do value / size / 下标访问), -- 类型标识 suppo 为社区宏中的真实写法;请按你的项目替换为目标类型。 -- 本宏按官方/社区已发表写法组合构造,需在本地 E3D Design 环境验证。 P ===== suppInspect: begin ===== -- 写法 A:DO ... VALUE —— 只关心"每个都过一遍"时用它 var !supp coll all suppo for CE do !x value !supp $!x -- 把当前这一项变成当前元素 q var !!ce.name -- 打印名字(只读) enddo -- 写法 B:SIZE() + 下标 —— 需要知道序号时用它 var !grid coll all suppo for CE P ---- indexed pass, total count below ---- q var !grid.size() do !i from 1 to !grid.size() $!grid[$!i] q var !!ce.name enddo P ===== suppInspect: end =====逐行剖析:
P ===== ... =====:给输出加起止标记。批量脚本的日志必须能分段,否则你无法判断"这次到底跑完了没有"。var !supp coll all suppo for CE:集合建立。两次遍历用了两个集合变量(!supp与!grid),刻意不重用——因为写作 A 的遍历过程中模型状态可能变化,复用同一个集合变量会让结果不可解释。这是个便宜的保险。do !x value !supp/$!x/q var !!ce.name/enddo:写法 A 的最小闭环。q var !grid.size():先打印总数。这是数据巡检的第一条硬指标——没有总数,你无法判断"少遍历了一部分"。do !i from 1 to !grid.size()/$!grid[$!i]:写法 B。注意!grid[$!i]里注入的是下标,说明$!注入在位置参数上是通用的。- 这个骨架可直接当模板:换掉
suppo、把输出换成你要读的属性即可。
2.4 三条分工线(建议贴在显示器边上)
- 在 PML 里遍历"某范围下的一类元素":用
var !x coll all <类型> for <范围>+do;不要指望读界面的 “My Collections”。 - 往界面的 Shared Collections 里加内容:走GPWL / GPSET / GPITEMS体系(官方人员指出可用
GADD PIPE /name这类命令);不要用coll。 - 需要"一批元素"跨步骤携带:用集合变量,或把引用存进 PML2 对象的
DBREF成员;不要用"名字字符串"当引用。
这三条里混用任何一条,代价都是重写。
三常见报错与排查
症状一:脚本遍历出来的元素数量明显不对,或者干脆是 0。
- 现象:集合建立成功但没有内容,或数量远少于预期。
- 原因:范围(
for后面的词)写错了,或类型标识不对(例如把suppo用在了别的产品对象上),或当前元素根本不是你以为的那个。 - 处置:先用 2.3 的骨架打印
!grid.size()看总数;再核对!!ce.name、!!ce.type(确认"我在哪");范围关键字与类型标识请以两个官方集合文档页(https://docs.aveva.com/bundle/e3d-design/page/911971.html、https://docs.aveva.com/bundle/e3d-design/page/962745.html)为准。
症状二:遍历时"处理到了同一个元素好几次",或者结果互相覆盖。
- 现象:日志里同一个名字反复出现;或者明明遍历了 10 个,最后只有一个被改了。
- 原因:忘了写
$!x(或写在了错误的位置),导致!!ce一直停在同一个元素上——于是十条命令都作用在它身上;也可能在循环里又用了同一个集合变量做新的收集(嵌套收集时变量重用)。 - 处置:确认
$!x(或$!b[$!i])是循环体第一条可执行语句;嵌套遍历用不同集合变量名;每轮都打印"当前处理对象",出问题能立刻看出卡在谁身上。
症状三:想遍历用户在界面上攒的 Collection,怎么写都不对。
- 现象:界面上明明有内容,PML 里遍历不到。
- 原因:两者不是一回事。官方人员明确:PML 中的 collection 与界面上的 “My Collections” 不同;界面侧实为GPWL/GPSET/GPITEMS体系(可用
GADD PIPE /name添加)。 - 处置:PML 侧遍历用
coll all ... for ...建立集合;界面侧组织走 GPWL/GPSET/GPITEMS。别试图用一个机制跨界解决两件事。
症状四:批量重命名之后名字对了,但元素位置/归属不对。
- 现象:改名成功,后续检查发现元素挂错了地方。
- 原因:只做了改名,没有做归位。社区宏里
rename all之后紧跟的是$!f $* destination zone与include $!d——"改名"与"归位"是两步。 - 处置:把"改名 + 归位 + 校验"当成一个不可拆的最小事务;每步都输出审计信息;在执行前后各统计一次命中数量,数字不一致就不算成功。
四动手练习
练习 1(15 分钟,只读):在 Command Window 里依次执行q var !!ce.name、q var !!ce.type、q var !!ce.position,然后在界面里切换当前元素,再执行一遍。合格判定:两次输出不同,且你能用一句话说清"为什么!!ce会变"。
练习 2(20 分钟,只读):把 2.3 的巡检宏落在PMLLIB覆盖的目录里,跑一次。合格判定:能拿到一个准确的总数(!grid.size()的输出),并且逐项输出的数量与总数一致;若为 0,能说明是范围问题还是类型问题。
练习 3(20 分钟,只读):让 2.3 的写法 A 与写法 B 各遍历一次并分别输出名称列表。合格判定:两批名称集合相同(顺序不限);若不同,给出原因。
练习 4(25 分钟,写操作,必须在测试 MDB 上做):复刻 2.1 社区宏里"复制 → 按copy-of-筛选 → 解析名字 → 重命名"这四步,但把来源不明的变量(!e、!f)换成你自己定义的固定值(例如把!e换成一个固定后缀、把目标 zone 换成你测试库里的真实 zone)。合格判定:能给出"改名前的名称 → 改名后的名称"对照清单;matchw筛选出的数量与预期一致;执行前后的元素总数差值与副本数量相符(数字对不上就不算通过)。
五小结与下一篇预告
本篇的四条要点:!!ce是全局的"当前元素引用",随环境变化,是所有数据访问的锚点;DBREF是元素引用,能被存进变量或 PML2 对象成员,读写属性走点号,写操作不可逆;集合遍历是三段式——var !x coll all <类型> [with <筛选>] for <范围>建立、do !x value !集合+$!x逐个切换、或do !i from 1 to !集合.size()+$![$!i]按下标访问;MATCHW用通配模式按命名规则筛数据,是批量作业的核心手段。以及那个必须记住的纠正:PML 的 collection 与界面的 “My Collections”(GPWL/GPSET/GPITEMS)不是一回事,用GADD这类命令操作界面集合,用coll做 PML 遍历。
下一篇《第一个实战:模型数据巡检与批量改写》把第 05 到 07 篇的知识攒成一个完整脚本:遍历指定层级 → 采集关键属性 → 落成 CSV → 对命中项批量改名/改属性 → 输出变更前后对照,并重点处理"批量改名的命名冲突"这一真实风险。
文末 FAQ
Q1:!!ce到底是什么?为什么它一会儿是设备、一会儿是管子,我改一个命令它就变了?!!ce是一个全局变量,它的值是当前元素的数据库引用;“当前"由环境决定——你在图形界面里选中了什么、或者上一条命令把谁变成了当前,它就跟着变。所以它是环境状态而不是常量。这带来两个实践结论:一是写脚本前必须先确认"此刻!!ce是谁”,二是如果要把某一刻的元素固定下来,必须做快照——官方对象示例里的!this.element = !!ce就是在存引用,!this.name = !!ce.name则是在存当时的属性值。
Q2:DBREF是什么?我能在变量里"存一个元素"吗?存了之后怎么用?DBREF是数据库引用,指向模型里的一个具体元素;它既是 PML2 对象成员的类型之一(官方对象示例member .element is DBREF),也是 SCRM 对象类型名单中的正式类型。你可以把它存进变量或对象成员,然后再取出来使用。之所以要用引用而不是名字,是因为名字会变、会重名,引用是稳定标识。凡是需要真正"操作这个元素"(改属性、复制、移动)的场合都必须持有引用;只有"打印个名字"的场合才可以只留字符串。
Q3:coll all ... for ...这句该怎么读?for后面到底能写什么?
读法是:var <集合变量> coll all <元素类型> [with <筛选条件>] for <范围>——“从某范围里,把某类型的全部元素收集起来”。with段是可选的筛选,for后面是范围。社区真实宏里出现过两种范围写法:for CE(当前元素下)与for zone(zone 范围);suppo是社区宏里真实使用的元素类型标识(支吊架),你应替换成自己项目里的目标类型。范围关键字的完整可选值,请以 AVEVA 官方人员给出的两个集合文档页为准:PML1 数组式VAR ... COLLECT见 https://docs.aveva.com/bundle/e3d-design/page/911971.html,PML2 集合对象见 https://docs.aveva.com/bundle/e3d-design/page/962745.html。
Q4:MATCHW是干什么的?为什么筛选名字要用它而不是直接比较?matchw是通配匹配:第一个参数是要匹配的表达式,第二个参数是带通配符*的模式。社区宏里的写法是with matchw(name of suppo,'*copy-of-*') for zone,含义是"名字里含copy-of的支吊架"。之所以不能用等号比较,是因为你要筛的是按命名规则生成的一类名字(如程序产生的中间产物名),而不是一个确定的名字——通配匹配是"按命名规则筛数据"的唯一实用手段,这在批量作业里极其常见:命名规范本身就是筛选条件。注意被匹配的是表达式name of suppo而不是字符串字面量。
Q5:SIZE()和!b[$!i]是什么关系?遍历到底该用DO ... VALUE还是用下标循环?!b.size()给出集合里的元素个数;!b[$!i]是按位置取第!i个元素。两者常配合成do !i from 1 to !b.size()的循环,并在循环体里用$!b[$!i]把这一项设为当前元素。选择标准很直接:只关心"每个都过一遍"→ 用do !x value !集合+$!x,更简洁;需要知道当前是第几个(打进度、按序号计算、需要中途BREAK)→ 用下标循环。社区那段真实宏两种都用了,正是因为内层需要序号信息。无论用哪种,循环体的第一条可执行语句都要是"把当前元素切到这一项",否则命令会全部作用在同一个元素上。
Q6:界面上不是有个 “My Collections” 吗?我在 PML 里能不能直接用它?
不能混用。官方人员在该产品社区的回复里明确强调:PML 中的 collection 与界面上的 “My Collections” 不是一回事;界面侧看到的 Shared Collections 实际上是GPWL / GPSET / GPITEMS体系(可用GADD PIPE /name这类命令添加内容)。所以:在 PML 里要做遍历,正确做法是用coll all ... for ...在模型里建立集合;要在界面体系里组织元素,则走 GPWL/GPSET/GPITEMS 那条线。另外,若需要在多个步骤之间携带"一批元素",除了集合变量,也可以把引用存进 PML2 对象的DBREF成员。