4. VBS脚本基础语法与WinCC对象模型

在WinCC中编写VBS脚本,本质上是在做两件事:用VBS语法组织逻辑,用WinCC对象模型访问画面与变量。前者决定“怎么算、怎么判断、怎么重复”,后者决定“对谁操作、读什么、写什么”。把这两部分分开理解,再合起来使用,脚本才不容易写成“能跑但看不懂”的状态。

变量、数组与数据类型

VBS是弱类型语言,变量不需要声明类型,直接赋值即可使用:

Dim speed, count, msg
speed = 12.5
count = 3
msg = "运行中"

虽然不强制声明,但建议始终用 Dim 显式声明,避免拼写错误导致隐式新变量。VBS常用类型包括 Integer、Long、Double、String、Boolean、Date 和 Variant。WinCC变量读回来通常是 Variant,参与运算前可用 CDbl()、CInt()、CStr() 显式转换,避免字符串与数值混算。

数组用于存放一组同类型数据,例如保存多个工位的温度:

Dim temps(4)
temps(0) = 65.2
temps(1) = 68.0
temps(2) = 71.5
temps(3) = 69.8
temps(4) = 66.1

VBS数组默认下标从0开始,UBound(temps) 返回4,LBound(temps) 返回0。遍历时用 For i = LBound(temps) To UBound(temps) 最稳妥。若数量不确定,可用 ReDim 动态调整,但频繁重定义会影响性能,工程中更推荐预先估算容量。

条件与循环

条件判断用 If...Then...ElseIf...Else...End If。例如根据液位决定阀门动作:

If level >= 90 Then
    HMIRuntime.Tags("ValveOut").Write 0
ElseIf level <= 20 Then
    HMIRuntime.Tags("ValveIn").Write 1
Else
    HMIRuntime.Tags("ValveIn").Write 0
End If

多分支且判断同一表达式时,Select Case 更清晰:

Select Case mode
    Case 1 : msg = "手动"
    Case 2 : msg = "自动"
    Case 3 : msg = "维护"
    Case Else : msg = "未知"
End Select

循环主要有 For...Next、Do...Loop 和 While...Wend。批量读取变量时常用 For Each 遍历集合。需要注意:WinCC画面脚本运行在UI线程,循环中若包含大量变量读写或 HMIRuntime.Tags 调用,会阻塞画面刷新。工程上应控制单次循环次数,必要时拆分为多次触发。

Sub与Function

Sub 执行动作、不返回值;Function 返回值,可用于计算或判断。例如把“限幅”封装成函数:

Function Clamp(v, lo, hi)
    If v < lo Then
        Clamp = lo
    ElseIf v > hi Then
        Clamp = hi
    Else
        Clamp = v
    End If
End Function

调用时 out = Clamp(in, 0, 100)。把重复逻辑封装成 Sub/Function,是让画面脚本可维护的关键。建议将通用函数放在WinCC全局脚本的“项目模块”中,画面脚本只调用,不重复定义。

WinCC VBS对象模型

WinCC VBS的核心对象层次为:HMIRuntime → Screen → ScreenItem,变量通过 HMIRuntime.Tags 访问。理解这条链,就能定位“我该从哪里拿对象”。

  • HMIRuntime:运行时根对象,提供 Tags、Screens、Trace 等入口。
  • HMIRuntime.Tags("TagName"):变量对象,.Read 读值,.Write 写值。
  • HMIRuntime.Screens("画面名"):画面对象,可访问画面属性与画面内对象。
  • Screen.ScreenItems("对象名"):画面内控件,如按钮、I/O域、圆、矩形。
  • ScreenItem:控件对象,可读写 .Visible、.BackColor、.Text、.Position 等属性,也可调用其方法。

典型写法如下:

Dim v
v = HMIRuntime.Tags("TankLevel").Read
HMIRuntime.Tags("LevelShow").Write v

Dim scr
Set scr = HMIRuntime.Screens("Main")
scr.ScreenItems("lblState").Text = "液位:" & v

注意 Set 用于对象赋值,普通变量直接 =。读变量用 Read,写变量用 Write,不要写成 Tag = value。访问画面对象前要确认画面已加载,否则 ScreenItems 可能返回空对象。

WinCC VBS 对象模型与脚本执行链 HMIRuntime 运行时根对象 HMIRuntime.Tags 变量集合 Tag 对象 Read / Write HMIRuntime.Screens 画面集合 Screen 对象 画面属性 / ScreenItems ScreenItem 对象 Text / Visible / BackColor VBS 逻辑层 变量 / 数组 / 条件 / 循环 Sub / Function 封装与复用 逻辑结果写入对象属性

属性、方法与调用规范

对象属性用点号访问,方法用点号加括号调用。例如让一个圆随液位改变颜色:

Dim lv, c
lv = HMIRuntime.Tags("TankLevel").Read
If lv > 80 Then
    c = RGB(255, 80, 80)
ElseIf lv > 50 Then
    c = RGB(255, 200, 60)
Else
    c = RGB(80, 200, 120)
End If
HMIRuntime.Screens("Main").ScreenItems("cirTank").BackColor = c

这里 BackColor 是属性,RGB() 是VBS内置函数。WinCC中颜色也可用 HMIRuntime.Color 相关常量,但 RGB 更直观。若对象不存在,赋值会报错,因此工程中常先判断:

Dim item
Set item = HMIRuntime.Screens("Main").ScreenItems("cirTank")
If Not item Is Nothing Then
    item.BackColor = c
End If

综合示例:液位越限报警

假设变量 TankLevel 为0~100的浮点数,报警阈值高80、低20。脚本放在画面“Main”的“对象周期”触发中,周期250ms:

Dim lv, state
lv = HMIRuntime.Tags("TankLevel").Read
If lv >= 80 Then
    state = "高报警"
    HMIRuntime.Tags("AlarmHigh").Write 1
ElseIf lv <= 20 Then
    state = "低报警"
    HMIRuntime.Tags("AlarmLow").Write 1
Else
    state = "正常"
    HMIRuntime.Tags("AlarmHigh").Write 0
    HMIRuntime.Tags("AlarmLow").Write 0
End If
HMIRuntime.Screens("Main").ScreenItems("lblAlarm").Text = state

运行后观察:当 TankLevel 超过80,画面标签显示“高报警”,AlarmHigh 变为1;回落到20~80之间,标签恢复“正常”,两个报警位清零。若标签不刷新,先检查触发周期是否设置、变量名是否与WinCC变量管理器一致、画面名与对象名是否拼写正确。这三项是VBS脚本调试中最常见的定位点。

建议把变量读写集中到脚本前部,对象属性赋值放到后部,便于排查“是数据没读到,还是对象没写到”。