ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

FactoryTalk View SE中VBA编程实战:画面脚本、PLC标签读写与自动化报表

FactoryTalk View SE中VBA编程实战:画面脚本、PLC标签读写与自动化报表 简介FactoryTalk View Site Edition的VBA基本应用.doc是一份面向工业自动化与HMI开发者的技术资料讲解如何在SE中利用VBA实现与PLC的数据交互、标签读写、逻辑控制及运行历史数据记录。内容涵盖创建应用程序、区域、HMI Server通过RSLogix Emulate 5000与RSLogix 5000搭建仿真PLC环境以及使用ADO连接SQL Server数据库并写入带时间戳的标签数据。资源为单个doc文档大小1.27MB适合熟悉FactoryTalk View SE或机器人产线HMI开发的工程师、发那科机器人相关技术人员参考学习。文档内含可直接参考的VBA代码示例、控件属性配置说明与数据库建表语句能帮助读者从环境搭建到代码实现快速上手。已有100人浏览学习。1. 先搞清楚 FactoryTalk View SE 里的 VBA 能干什么从一份没人读的 .doc 说起很多工厂的服务器里都躺着一份《FactoryTalk View Site Edition的VBA基本应用.doc》系统上线那年由组态工程师写好后来接手的人翻几页就合上了全是能看懂的单词拼不成一条能跑的通路。其实 FactoryTalk View SE下文按现场习惯写成 FTView SE作为罗克韦尔的上位机组态软件常规组态只负责摆按钮、连指示灯、画趋势曲线真要塞自定义逻辑VBA 就是那条缝。它的能力边界大致是这样调用 Windows 的 COM 对象去操作 Excel、读写文本文件按业务规则算数据再和画面上的输入输出对象配合把值和 PLC 标签对接。特别适合系统集成商、工厂自动化维护人员和被老项目交接文档困住的人。下面直接从脚本写在哪开始按一条能做事的路径走到底。2. 让 VBA 在 FTView SE 里跑起来编辑器入口、最小事件和调试办法2.1 先找到 VBA 编辑器脚本不在项目树里而是挂在每个画面上FTView SE 的 VBA 和 Office 里那种宏不太一样它不是全局共享的一个工程文件而是每个图形显示画面Graphic Display各自带一份代码模块。打开 View Studio在项目树里选中一个显示画面双击进入画面编辑环境这时候菜单栏才会出现 VBA 相关的入口。有的版本把入口放在菜单栏直接叫 VBA有的版本需要在画面空白处右键找类似 VBA Code 的选项。我见过不少人卡在这一步他们在项目树的根节点上找脚本入口找半天找不到就下结论说这个软件不支持 VBA。其实只要进入某个画面入口就在画面环境里。这样设计也有道理——画面被加载和关闭时脚本跟着画面走不用在一个巨大的全局代码库里做切换判断对新手反而友好。有一点要注意如果画面编辑器里始终找不到 VBA 菜单大概率不是操作问题而是安装时没有装 VBA 相关组件或者软件授权没有包含这个功能。先回安装程序里看组件勾选再去罗克韦尔授权工具里确认。别在客户端和开发机上反复重装先把这一个点排除掉。2.2 写第一个能自己触发的脚本OnOpen 与 Click 的最小示例进入 VBA 编辑器后左侧工程资源管理器里能看到当前显示画面对应的代码模块右侧是代码窗口。最常用的入口有两个一个是画面生命周期事件一个是画面对象事件。先看画面打开时触发的最小脚本Private Sub Display_OnOpen() 画面打开时弹一个提示框带上当前时间 MsgBox 画面已打开当前时间 Format(Now, yyyy-mm-dd hh:nn:ss) End Sub这段代码是显示画面的内建事件子程序画面被打开并激活时自动执行。Now取操作系统当前时间Format的第二个参数是格式化模板。这里有一个新手必踩的细节VBA 里分钟的占位符是nn不是mm。mm在日期格式里代表月份如果用mm你把2025-07-11 09:07格式化出来分钟那一节会被显示成2025-07-11 09:07里的07还是月份07往往要等运行时才能发现真假。所以时间模板里写分钟的地方老老实实用hh:nn:ss。再看一个由画面对象触发的例子。画一个按钮在它的属性面板里把名称Name改成Btn_Help然后双击按钮进入代码区选择它的点击事件Private Sub Btn_Help_Click() MsgBox 当前画面主操作画面 End Sub这里真正关键的不是 MsgBox 这行而是子过程名字里的Btn_Help必须和画面上按钮的对象名完全一致。名字对不上时编译可能不报错但按钮怎么点都没反应。这种问题排查起来很恼火所以我现在的习惯是只要打算写脚本对象名一定先改成有业务含义的名字比如Btn_Start、Btn_Stop、NumericDisplay_Level不要留Button1、Button2。2.3 调试 VBA 的三板斧断点、立即窗口和本地窗口FTView SE 的 VBA 环境和 Office 共享同一套调试工具这点上手快。想在某一行暂停执行点代码窗口左侧灰色区域出现红点就是断点。程序运行到那一行会停下来这时候可以按 F8 单步跟进逐行看数值变化。更常用的是立即窗口快捷键 CtrlG 呼出。在立即窗口里可以直接输入? 11回车看结果也可以输入? Format(Now, yyyy-mm-dd hh:nn:ss)验证时间格式不用每次跑一遍整个脚本。这个习惯帮我省了大量试错时间。本地窗口会在运行时展示当前子过程里的所有变量比如currentLevel读出来的数值是多少一眼就能看出来。这套调试逻辑和 Excel VBA 一模一样如果你之前写过 Excel 宏这里几乎没有学习成本。唯一要记住的是改完 VBA 代码后Runtime 状态的画面不会自动热加载。把画面关掉重新打开或者退出测试模式再进一次你的新代码才会生效。这属于改了代码像没改的经典现场后面避坑章节还会提到。3. 把画面对象和 PLC 标签连接起来VBA 读写项目数据的三种写法3.1 认清对象 Value 和标签连接的关系很多从 Excel VBA 转过来的人上来就写读标签的代码然后发现 FTView SE 里根本没有那么直接的函数入口。原因在于 FTView SE 的画面对象和标签不是一回事。画面上那个数值显示框本质是一个对象对象有Value属性这个对象是否和某个标签连接取决于你在属性面板里的连接配置。所以 VBA 与项目数据交互的第一步不是写代码而是先想清楚你要读的是对象当前显示出来的值还是 PLC 里的原始标签值。通常的做法是在画面上放一个数值显示对象在属性面板里把它的连接指向::[PLC]Tank_Level这类标签再给对象起名NumericDisplay_Level。然后在 VBA 里读它的ValueDim currentLevel As Double currentLevel Val(NumericDisplay_Level.Value) If currentLevel 80 Then NumericDisplay_Alarm.Value 1 End If代码里用了Val()把对象值转成数值。这个细节很重要画面对象的Value属性在某些版本里可能是字符串类型尤其是从显示对象读出来的值时字符串型数值如果不转换直接参与加减乘除轻则结果为零重则类型不匹配当场报错。Val()是 VBA 里最皮实的转换函数它会把字符串开头的数字部分提取出来比如Val(80.5)返回80.5。这里的判断逻辑是当前液位超过 80就给另一个显示对象赋 1用来触发画面上的报警变色动画。注意给NumericDisplay_Alarm.Value赋值只是改了显示对象的值如果这个对象连接了一个内存标签标签会跟着变如果它只是独立的显示框那就只会动画面PLC 不会有一丝变化。这正是下一节要展开的边界。3.2 汇总数组的典型写法五个测温点的平均温度VBA 入门绕不开数组现场也到处是这种需求五个测点取平均、六个电机统计运行台数、八段温度找最大值。用散装变量写也能跑但后面改测点数量时能改到怀疑人生。下面是一段可以抄进 FTView SE 的数组汇总代码Dim temp(1 To 5) As Double Dim i As Integer Dim total As Double Dim avgValue As Double 从五个温度显示对象里读当前值 temp(1) Val(NumericDisplay_T1.Value) temp(2) Val(NumericDisplay_T2.Value) temp(3) Val(NumericDisplay_T3.Value) temp(4) Val(NumericDisplay_T4.Value) temp(5) Val(NumericDisplay_T5.Value) total 0 For i 1 To 5 total total temp(i) Next i avgValue total / 5 NumericDisplay_Avg.Value Round(avgValue, 1)数组声明temp(1 To 5)把下标从 1 开始而不是 VBA 默认的 0。这样做的好处是下标直接对应测点编号读代码时不用心里做index - 1的换算。Round(avgValue, 1)的第二个参数 1 表示保留一位小数适合显示但如果这个平均值还要参与下一步报警判断建议不要舍入把完整的avgValue写进一个隐藏显示对象画面显示用舍入后的值判断就用原始精度避免报警阈值卡在边界值上反复跳。这里顺便说全局变量。如果你希望这个平均值在同一个画面里的多个事件之间共享可以在模块顶部的声明区写一行Public g_AvgValue As Double。g_前缀是我个人习惯提醒自己这是个全局量。但要特别提醒FTView SE 的 VBA 代码模块是跟着画面走的画面一旦关闭模块里的全局变量值就丢了。跨画面的数据共享请使用内存标签Memory Tag不要指望 VBA 全局变量能当网关用。这一点在写交接班报表时会非常关键。3.3 把计算结果写回 PLC 标签的可靠做法把 VBA 算出来的结果真正写进 PLC 标签是这套方案里最容易翻车的一步。先说一个常见误区想在 VBA 里直接通过标签名写数据需要调用 FTView SE 底层接口不同版本的对象模型差异不小新手照看网上的片段代码经常在编译阶段就卡住。我给现场做项目时一般不会直接跟 PLC 标签名硬刚而是借用画面上的输入对象在画面上放一个数值输入对象把它的连接指向目标标签这个输入对象本身就承担了写 PLC的动作。具体做法是三步第一步从画面工具箱拖一个数值输入对象在属性面板里把连接改为要写入的标签例如::[PLC]Recipe_Temp第二步把对象的名称改成NumericInput_Target第三步在 VBA 里给这个输入对象的Value赋新值然后让它获得焦点并触发回车NumericInput_Target.Value 88.5 NumericInput_Target.SetFocus SendKeys {ENTER}, TrueSendKeys {ENTER}, True的意思是向当前激活窗口发送回车键第二个参数True表示等待按键被处理完再执行下一行。这种写法看起来有点暴力但它绕开了不同版本之间VBA 直接写标签接口不一致的问题因为最终写 PLC 的动作是输入对象自己完成的VBA 只是扮演了操作员的角色。如果现场安全策略不允许 SendKeys退一步的做法是VBA 只负责把计算结果填进输入对象的值然后由操作员手动按回车确认。表面上多了一步人工动作但好处是操作员清楚知道这个值是谁填进去的出问题时少背一次黑锅。还有一点输入对象如果属性里设置了允许输入为否那你赋完值它也不会去写 PLC检查时先把这个开关看明白别让脚本在最后一步哑火。4. 用 VBA 自动生成 Excel 班报与文本日志可直接套用的代码4.1 一键生成 Excel 班报CreateObject 全套代码与参数说明现场最常见也最刚需的 VBA 应用就是自动生成班报。值班员以前是每个整点抄一次表再把数字敲进 Excel 模板用 FTView SE 的 VBA 做这件事一次点击就能把当前画面上的数据抓出来写入 Excel 再保存。下面是一段完整代码按钮的事件子过程Private Sub Btn_Report_Click() Dim xlApp As Object Dim xlBook As Object Dim xlSheet As Object Dim rowNum As Long On Error GoTo ReportErr 启动 Excel 进程 Set xlApp CreateObject(Excel.Application) If xlApp Is Nothing Then MsgBox 本机没有安装 Excel无法生成班报。 Exit Sub End If xlApp.Visible False Set xlBook xlApp.Workbooks.Add Set xlSheet xlBook.Worksheets(1) 写表头 xlSheet.Cells(1, 1).Value 日期 xlSheet.Cells(1, 2).Value 时间 xlSheet.Cells(1, 3).Value 液位 xlSheet.Cells(1, 4).Value 温度 写数据行 rowNum 2 xlSheet.Cells(rowNum, 1).Value Format(Now, yyyy-mm-dd) xlSheet.Cells(rowNum, 2).Value Format(Now, hh:nn:ss) xlSheet.Cells(rowNum, 3).Value Val(NumericDisplay_Level.Value) xlSheet.Cells(rowNum, 4).Value Val(NumericDisplay_Temp.Value) 保存为 xlsx 格式文件名带时间戳避免互相覆盖 xlBook.SaveAs D:\ShiftReports\report_ Format(Now, yyyymmdd_hhnnss) .xlsx, 51 xlBook.Close False Set xlSheet Nothing Set xlBook Nothing xlApp.Quit Set xlApp Nothing Label_Status.Caption 班报已生成 Format(Now, hh:nn:ss) Exit Sub ReportErr: 出错时也要把 Excel 进程清掉 If Not xlBook Is Nothing Then xlBook.Close False If Not xlApp Is Nothing Then xlApp.Quit Set xlApp Nothing End If MsgBox 生成班报失败 Err.Description End Sub这段代码的核心是CreateObject(Excel.Application)它启动一个独立的 Excel 进程后续所有操作都通过对象变量xlApp进行。If xlApp Is Nothing是判断对象创建是否成功这个习惯来自 VBA 编程里最常见的防御性写法对象不存在时给操作员一个明确的提示而不是让脚本在下一行报对象变量或 With 块变量未设置。SaveAs后面的数字51是文件格式常量表示xlOpenXMLWorkbook也就是.xlsx格式。文件名里拼接了Format(Now, yyyymmdd_hhnnss)生成的例子是report_20250715_183025.xlsx同一班次哪怕点两次生成也不会把上一个文件覆盖掉。如果你想把数据追加到同一个表里那就不能每次Workbooks.Add要在启动后先用Workbooks.Open打开既有文件。另外xlBook.Close False里的False表示保存后关闭时不再弹是否保存更改的对话框。4.2 不依赖 Excel 的备选文本日志加日期判断不是所有工厂操作站都装了 Office尤其是不允许办公软件进入工控网的场合。这时候文本文件就是最好的替代品稳定性远高于 Excel——不需要外部进程文件写入是文件系统的事断点续写在工控机上也没那么娇气。下面这段是一个通用的日志写入函数我一般把它放在画面代码模块的顶部Public Sub WriteLog(sMessage As String) Dim fso As Object Dim fFile As Object Dim sLine As String Dim sDir As String Dim sShift As String sDir D:\Logs 创建文件系统对象 Set fso CreateObject(Scripting.FileSystemObject) 目录不存在就创建 If Not fso.FolderExists(sDir) Then fso.CreateFolder sDir End If 用当前小时判断班次6点至18点为早班其余为晚班 If Hour(Now) 6 And Hour(Now) 18 Then sShift 早班 Else sShift 晚班 End If sLine Format(Now, yyyy-mm-dd hh:nn:ss) , sShift , sMessage 8 表示追加模式True 表示文件不存在时自动创建 Set fFile fso.OpenTextFile(sDir \event.log, 8, True) fFile.WriteLine sLine fFile.Close Set fFile Nothing Set fso Nothing End Sub这段里有三个值得留意的点。第一Hour(Now)返回当前小时用它跟 6 和 18 做比较就是 VBA 里最朴素的日期比较大小用法。如果你要在交接班时判断现在是不是刚过换班点用DateDiff或直接比较两个Date变量都可以但读小时判断班次这种场景整数比较最直观。第二OpenTextFile的三个参数路径、打开方式、是否创建。数字8是 VBA 文本流里追加写入的常量值意味着每次调用都把新行追加到文件末尾而不会覆盖历史记录。第三这个函数被定义成Public Sub同模块内任何一个按钮事件都能直接调用省得把文件操作逻辑复制好几遍。4.3 在画面状态栏上显示脚本进度别让操作员干等Excel 启动有时候慢尤其操作站内存吃紧时点完生成班报按钮可能两三秒没反应。操作员不知道脚本卡了还是在跑很容易再点一次结果就是生成两个文件或者两个脚本互相争抢同一个 COM 对象反而拖垮画面。FTView SE 没有 Windows 那种底部状态栏但它有标签控件拿标签控件当状态栏用是现场最普遍的做法。Label_Status.Caption 正在生成班报请稍候... DoEvents —— 中间放表格写入代码 —— Label_Status.Caption 班报已生成 Format(Now, hh:nn:ss)Label_Status是画面上的一个文本标签对象改它的Caption属性就是显示文字。DoEvents是 VBA 里一个特殊语句它让出执行权给操作系统去刷新画面这样标签上的文字会立刻显示出来而不是等整个脚本跑完才一起刷新。如果不加DoEvents操作员看到的画面是点完按钮毫无反应过两秒钟直接变结果。这个细节很微小但对车间里的使用体验差很多。如果脚本里有多步操作我会在每步结束后给标签加一个后缀时间步骤1完成 Format(Now, hh:nn:ss)。这样万一脚本中途死掉操作员截图发到维护群里你能直接看出卡在哪个环节而不用靠猜。5. FTView SE 的 VBA 避坑清单现场最容易翻车的五个问题5.1 标签值没写进去现象、原因与排查顺序现象脚本里给输入对象赋了值MsgBox 也弹了操作工和仪表工都看见画面上数字变了但 PLC 里的标签数值纹丝不动。原因最常见的是输入对象根本没连接 PLC 标签或者连接的是一个只读动画连接排在第二的是输入对象勾选了允许输入为否对象只承担显示不承担写入还有可能你赋完值没有触发回车或焦点移出而项目里设置的是输入后按回车才写入。解决先不跑脚本在画面上手动改一次这个输入对象看 PLC 标签是否变化如果手动改都不行问题一定出在连接配置而不是 VBA 代码。手动改能通再上脚本脚本里要么加SendKeys触发写入要么把属性改为输入即写入。把排查顺序固定成先手动、再脚本、后 PLC 侧写权限能省掉大半无效排查时间。5.2 Excel 进程常驻后台对象没释放现象生成了几次班报后操作站明显变卡任务管理器里躺着两三个 EXCEL.EXE结束进程后过段时间又冒出来。原因VBA 脚本在中途报错跳出了子过程后面的xlApp.Quit和Set xlApp Nothing根本没有机会执行。Excel 是被 CreateObject 拉起来的外部进程它只认最后有没有收到 Quit 指令不认你的脚本是不是正常结束。如果不加错误捕获任何一行出错都会导致进程泄漏。解决每个创建了 COM 对象的子过程必须配错误处理器在第 4.1 节模板里那个ReportErr:标签后面的清理逻辑就是干这个的。另外能不用 Excel 的场合尽量不用文本文件日志完全够日常生产记录用只有在需要格式化的正式报表时才启用 Excel并且要设置xlApp.DisplayAlerts False避免各种弹窗把退出流程卡住。5.3 日期时间格式错乱月份被当成分钟写现象日志和班报里出现两种日期格式并存的乱象有的行是2025-07-11 09:07:11有的行变成07/11/2025 09:07:11更隐蔽的是把09:07写成了09:07但那个 07 是分钟还是七月看着像其实不对。原因VBA 的Format函数完全听从系统区域设置和格式化模板。mm在日期部分代表月份在时间部分却被人习惯地当成分钟而 VBA 里时间部分的正式占位符是nn。系统区域设置要是中文、英文、德文各不同直接输出Now的默认格式也会跟着变。解决项目里统一硬编码日期时间模板我只用这一个yyyy-mm-dd hh:nn:ss把它定义在模块顶部常量里所有写日志、写报表、拼文件名的地方都引用这个常量。文件名里的时间戳用yyyymmdd_hhnnss。宁可多打几个字不要偷懒用默认格式。5.4 OnOpen 多次触发画面预加载和重复代码现象主画面明明打开一次日志里却出现两三条Display_OnOpen记录从别的画面切回来又追加一条。操作员没觉得画面卡但脚本里如果有弹窗代码就会连着弹好几个窗当场劝退操作员。原因FTView SE 客户端对显示画面可能做预加载尤其是配置了画面缓存的场景画面先被加载一次等真正显示时又触发一次另外就是组态人员在显示打开动作和 VBA 的Display_OnOpen事件里各写了一遍初始化代码双份执行。解决把Display_OnOpen里的代码严格控制为每次打开都必须做的事比如刷新状态文字需要只执行一次的初始化工作挪到按钮触发或者用内存标签做标志位第一次进来置位后续事件判断标志位后直接跳过。多加一行标志位判断省掉深夜接到操作员画面弹三次窗的投诉电话。5.5 开发机能跑客户端不跑VBA 没装进去现象工程师在开发站上测试一切正常发布到操作员站之后按钮点了没反应也不报错画面其他功能正常。原因开发站安装了完整的 View Studio 和 VBA 组件操作员站安装时只选了运行环境漏掉了 VBA 相关组件或者杀毒软件把 COM 调用路径拦了VBA 里涉及的 CreateObject 被当成启动外部程序的动作拦截。解决先在操作员站的 Windows 事件查看器里翻应用日志找有没有与脚本或 COM 相关的错误记录再放一个临时测试按钮只执行一句MsgBox VBA OK用来判断 VBA 运行环境本身是否可用最后查软件安装组件清单。注意改完 VBA 代码重新发布时画面文件要完整发布不要只发布图形资源而漏掉代码模块。这个问题排查起来最玄学但按这个顺序走基本十分钟能定位。提示VBA 脚本属于现场逻辑的一部分任何改动前记得备份画面文件。老项目尤其如此别问我怎么知道的。6. 从抄脚本到能维护错误处理模板、日志探针与验证顺序6.1 一个能兜底的错误处理模板大多数 VBA 教程会教On Error Resume Next让脚本出错时继续往下跑。在 FTView SE 里我强烈不建议这么干——工控画面一旦继续往下跑很可能是带着一个错误的中间值去写 PLC那比弹窗严重得多。我的做法是统一用On Error GoTo ErrHandler每个创建了外部对象的子过程都套同一个模板Private Sub Btn_Save_Click() On Error GoTo ErrHandler 这里是具体业务逻辑例如读取画面对象、计算、写日志 WriteLog 保存按钮被点击当前液位 Val(NumericDisplay_Level.Value) Exit Sub ErrHandler: WriteLog 错误发生错误号 Err.Number 描述 Err.Description MsgBox 操作失败请查看日志。错误号 Err.Number End SubExit Sub这行不能省。如果没有它正常执行完业务逻辑后代码会继续往下走进ErrHandler把没发生的错误也当成错误报一遍。错误处理器里用WriteLog记现场上下文比只弹一个 MsgBox 有用得多——弹窗关掉就没了日志能留到第二天早上分析。6.2 上线前用日志探针验证而不是站在画面前面看最后分享一个我现在的固定习惯任何带 VBA 逻辑的画面交付前都要先打日志探针。所谓探针就是在关键路径上临时加几行WriteLog把画面打开了、标签读到值了、分支走进了哪一边、文件保存成功这些节点依次打点。上线运行一个班次把日志文件拖出来按时间戳串一遍能立刻看出脚本到底在执行哪一步还是在哪一步之后没了下文。验证顺序我也固定下来了先验证画面对象能不能读到正确的值再验证逻辑分支计算结果对不对最后验证写 PLC、写文件这种动手操作。前两步在开发机上就能完成第三步一定要在实在的现场环境里跑一遍。我现在接手的每个老项目第一件事就是加这种入口日志它能帮我少翻很多次车也让我敢跟车间说这个脚本我修过了。希望帮到你。本文还有配套的精品资源点击获取
返回列表