资讯动态

PDMS-AVEVA-E3D二次开发教程(07):数据访问入门——!!CE、DBREF 与集合遍历

发布时间:2026/10/17 7:05:38 来源:尧图企业网站定制
版本声明全系列统一口径本篇基线为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 ... COLLECThttps://docs.aveva.com/bundle/e3d-design/page/911971.htmlPML2 集合对象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 CommunityPML 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 -- 写法 ADO ... VALUE —— 只关心每个都过一遍时用它 var !supp coll all suppo for CE do !x value !supp $!x -- 把当前这一项变成当前元素 q var !!ce.name -- 打印名字只读 enddo -- 写法 BSIZE() 下标 —— 需要知道序号时用它 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——改名与归位是两步。处置把改名 归位 校验当成一个不可拆的最小事务每步都输出审计信息在执行前后各统计一次命中数量数字不一致就不算成功。四动手练习练习 115 分钟只读在 Command Window 里依次执行q var !!ce.name、q var !!ce.type、q var !!ce.position然后在界面里切换当前元素再执行一遍。合格判定两次输出不同且你能用一句话说清为什么!!ce会变。练习 220 分钟只读把 2.3 的巡检宏落在PMLLIB覆盖的目录里跑一次。合格判定能拿到一个准确的总数!grid.size()的输出并且逐项输出的数量与总数一致若为 0能说明是范围问题还是类型问题。练习 320 分钟只读让 2.3 的写法 A 与写法 B 各遍历一次并分别输出名称列表。合格判定两批名称集合相同顺序不限若不同给出原因。练习 425 分钟写操作必须在测试 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 → 对命中项批量改名/改属性 → 输出变更前后对照并重点处理批量改名的命名冲突这一真实风险。文末 FAQQ1!!ce到底是什么为什么它一会儿是设备、一会儿是管子我改一个命令它就变了!!ce是一个全局变量它的值是当前元素的数据库引用“当前由环境决定——你在图形界面里选中了什么、或者上一条命令把谁变成了当前它就跟着变。所以它是环境状态而不是常量。这带来两个实践结论一是写脚本前必须先确认此刻!!ce是谁”二是如果要把某一刻的元素固定下来必须做快照——官方对象示例里的!this.element !!ce就是在存引用!this.name !!ce.name则是在存当时的属性值。Q2DBREF是什么我能在变量里存一个元素吗存了之后怎么用DBREF是数据库引用指向模型里的一个具体元素它既是 PML2 对象成员的类型之一官方对象示例member .element is DBREF也是 SCRM 对象类型名单中的正式类型。你可以把它存进变量或对象成员然后再取出来使用。之所以要用引用而不是名字是因为名字会变、会重名引用是稳定标识。凡是需要真正操作这个元素改属性、复制、移动的场合都必须持有引用只有打印个名字的场合才可以只留字符串。Q3coll all ... for ...这句该怎么读for后面到底能写什么读法是var 集合变量 coll all 元素类型 [with 筛选条件] for 范围——“从某范围里把某类型的全部元素收集起来”。with段是可选的筛选for后面是范围。社区真实宏里出现过两种范围写法for CE当前元素下与for zonezone 范围suppo是社区宏里真实使用的元素类型标识支吊架你应替换成自己项目里的目标类型。范围关键字的完整可选值请以 AVEVA 官方人员给出的两个集合文档页为准PML1 数组式VAR ... COLLECT见 https://docs.aveva.com/bundle/e3d-design/page/911971.htmlPML2 集合对象见 https://docs.aveva.com/bundle/e3d-design/page/962745.html。Q4MATCHW是干什么的为什么筛选名字要用它而不是直接比较matchw是通配匹配第一个参数是要匹配的表达式第二个参数是带通配符*的模式。社区宏里的写法是with matchw(name of suppo,*copy-of-*) for zone含义是名字里含copy-of的支吊架。之所以不能用等号比较是因为你要筛的是按命名规则生成的一类名字如程序产生的中间产物名而不是一个确定的名字——通配匹配是按命名规则筛数据的唯一实用手段这在批量作业里极其常见命名规范本身就是筛选条件。注意被匹配的是表达式name of suppo而不是字符串字面量。Q5SIZE()和!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成员。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑