拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

WinCC报表生成全攻略:从变量归档到VBS自动导出Excel

WinCC报表生成全攻略:从变量归档到VBS自动导出Excel

1. 为什么工业监控离不开报表

1.1 从一次“要报表”的现场经历说起

我在不少工厂现场被问过同一个问题:“你们WinCC能不能生成报表?”问这话的可能是车间主任,也可能是设备管理员,甚至是财务的人。你要是直接说“能”,对面多半马上补一句:“就是那种我点一个按钮,它自己把昨天产量、开机时间、报警次数统统给我列成一张表的。”

我最早接触WinCC报表需求是在一条包装线项目上。当时客户要求每天夜班结束前,班长能看到当班产量、设备运行时长、几条主要报警的发生次数,最好还能打印出来签字归档。我刚看了下任务,第一反应是:WinCC里的报表功能没那么显眼,正儿八经的报表输出能力不算强,它是监控系统,不是BI平台。但工业现场恰恰最缺的就是这件事——数据一直都在画面里跳,可真要落到纸面上、变成一张能拿去开会的表,就得把数据“捞”出来重新组织。

这篇东西不是照着帮助文档抄出来的,是我反复做、反复被现场问题“打脸”之后沉淀下来的做法。从变量归配置开始,到三种主流实现方式,再给一个能直接落地的定时自动报表案例,最后把常见的坑列一份速查清单。适合谁看?正在用WinCC做项目、被工厂提过报表需求的工程师;刚接手老项目、发现历史数据压根没存下来的维护同行;以及准备做MES对接、需要把WinCC数据往外送的集成人员。新手看完至少知道从哪里下手,老手可以对照看看自己有没有踩过类似坑。

1.2 报表到底“报”什么:现场的报表需求远不止一张表

搞清楚了需求再动手,能省一半的时间。我在现场碰到的报表需求,归纳下来无外乎这几类:

  • 生产统计报表:产量累计、班产量、日产量、合格率、原料消耗。这是最普遍的,通常由班长或车间主任看。
  • 设备运行报表:开机时间、停机时间、运行状态时长分布、故障停机次数。设备科和维修工程师最关心。
  • 报警报表:报警发生时间、确认时间、恢复时间、报警次数统计。这是安全与质量追溯的刚需。
  • 能耗报表:水、电、气、蒸汽的累积量与分时用量。现在工厂对能耗考核越来越细,这个需求增长速度很快。
  • 交接班报表:把当班期间的运行概况汇总成一张表,供下一班快速了解状态。

这几类报表的特点很明显,都是“事后查看”型的数据输出,不是实时监控画面。WinCC作为SCADA软件,它的日常工作是实时反映过程状态,而报表是把一段时间内积累的数据重新切片、汇总、呈现。所以你看,做报表这件事,核心不在于WinCC本身,而在于你有没有把该记的数据记下来。这也是我想在第二章节先聊数据归档的原因——报表好不好做,在数据配置那一刻就决定了。

2. 先做数据底子:变量归档配置才是报表的地基

2.1 归档配置的三个基础动作

很多工程师以为报表难在脚本和代码,其实难在数据源。WinCC里的变量分为内部变量和外部变量,外部变量连接PLC等控制器。如果这个变量没有开启归档,那当前值永远只能“看一眼”,历史数据什么都没有。好比监控摄像头没有接硬盘录像机,画面实时能看到,可出了事你想回放,对不起,没录。

所以做报表前,第一个动作就是检查变量有没有归档。打开WinCC项目浏览器里的“变量管理”,选中某个外部变量,右键打开属性,在“归档”选项卡里勾选“记录”,并设置归档周期和归档类型。这一步,很多新手容易漏。

第二件事是最小化数据噪声。如果你准备用一分钟的归档周期,那变量采集周期就不需要每次都存,可以设定一个较长的归档周期。我在一个项目里遇到过这样的配置:客户把采集周期设为100毫秒,归档周期也默认成了100毫秒,结果一台设备一天就能产生几十万行数据,系统越来越卡,报表查询也慢得像蜗牛。后来把归档周期改成1分钟,数据量骤降到原来的1%都不到,报表功能才真正“活”了过来。

第三件事是明确归档类型。WinCC的归档类型有“平均值”“瞬时值”“最大值”“最小值”“求和”等选项。做日报表的时候,产量累计值用“瞬时值”来读最终值,但如果是能耗分时统计,用“求和”或“平均值”更合理。举个例子,你用功率变量做归档,想要电耗数据,就该选“求和”,因为这本质上是时间积分。如果不做这个选择,后面报表里看到的数值可能只是采样瞬间的瞬时值,和电表实际读数对不上。

2.2 采集周期与归档周期怎么定

这里说一个我常用的参考思路:归档周期到底设多大,取决于你想做什么报表。

上一条包装线项目,班长要看的是“每天总产量”“每小时产量”,这种需求归档周期设1分钟完全够用。但如果现场有快速瞬变的过程量,比如压力波动、温度波动,做趋势分析时可能要求秒级甚至更快,那归档周期就得相应缩短。这里牵涉到数据精度与存储容量的平衡,没有绝对正确的值,只有适合现场需求的值。

补充一个细节:归档压缩算法不要乱用。WinCC归档时会为每一个周期内的数据记录压缩值,比如平均值、最小值、最大值、求和等。如果归档类型选成“瞬时值”,它只记录每个归档周期开始瞬间的值,某些变化快的信号可能会丢失关键峰值。所以如果需要做故障追责类分析,建议同时勾选“平均值”和“最大值最小值”,这对后面的趋势与报表都有好处。

还有个容易踩的坑:压缩后的归档表里,数据的更新时间不是“真实事件时间”,而是归档周期对应的间隔时间。比如一分钟归档,几分钟前的故障尖峰,报表上看到的时间可能是一个分钟内整点位置,并非精确到秒。如果工厂要求精确到秒做追责,就得在设计报表时明确告诉客户这个精度差异,不然验收时会被打回来。

2.3 数据类型和单位,报表里最容易翻车的环节

变量归档时,WinCC会按变量的数据类型存储。INT、REAL、BOOL、WORD每个类型在数据库里占用空间不一样,取值方式也不一样。报表脚本里如果用了错误的类型转换,轻则取不到正确的数,重则脚本报错。常见错误是BOOL型变量被当成REAL型读取,结果报表上出现一堆1或者0以外的奇怪数。

单位问题就更常见了。传感器采集到的原始值可能是0到1000的百分比,物理量程却是0到100度。如果你在WinCC变量组态里已经做了线性缩放,那归档里存的是工程单位换算后的数值,报表直接往外用就行。但有一些老项目是在画面脚本里做缩放,而归档存的是原始值,这种项目你直接取归档数值做报表,数据就会差一个斜率系数。碰到这类情况,我一般会先确认PLC侧还是WinCC侧做了量程转换,再决定报表里要不要二次换算。

还要提醒一件事:数据库里的归档表不能随意清理。WinCC后台是SQL Server,很多人图省事直接用SQL工具删历史数据,结果导致WinCC运行系统启动异常或报表模块报错。历史数据的清理应该用WinCC自带的存储管理工具按照周期策略处理,千万别手截DELETE语句。

3. 三种主流报表实现方式,按现场条件选

3.1 方式A:WinCC自带的控制与导出功能

WinCC的画面编辑器里提供了“在线表格控件”和“趋势控件”,把它们拖到画面里,绑定归档变量,运行后就能显示历史数据。这个方式快、零代码,适合临时看一下某时间段的数据,也适合当成操作员站上的普通查询窗口。自带的导出功能可以把表格内容存成CSV或Excel格式,很多现场就把这个当成简易报表。

但这个方式的短板非常明显:样式固化,几乎没法按客户期望的格式输出,比如合并单元格、列宽、表头、统计行这些,它统统做不了。而且它是“手动操作型”报表,没有人点击按钮,它不会自己生成。所以这种方式我通常只用来做“在线历史查询”功能,而不是真正的生产报表。

3.2 方式B:VBS脚本 + Excel自动化

这是我在绝大多数项目里的主力方案。原理不复杂:WinCC的全局脚本或者画面脚本支持VBS,可以通过脚本创建Excel.Application对象,然后在Excel里写入数据、设置格式、做公式统计、保存成文件,甚至通过邮件发送。

这样做的好处是报表的格式完全自定义。你想怎么做表头、怎么设边框、怎么调字号,Excel能做的WinCC脚本里都能做。而且可以做成完全自动化的定时触发,不需要任何人工干预。对于交接班报表、日报表这类需求,第二天早晨8点自动生成一张格式固定的表,放到指定共享目录,这个方案非常合适。

实现方式上有个细节:数据读取一般有两种路径。第一种是直接在WinCC运行时内部通过脚本读取变量当前值、读取归档查询对象(即WinCC自带的“归档数据查询”API),这种方式和项目耦合度高,必须在WinCC运行环境中跑;第二种是通过WinCC OLEDB Provider或者直接连SQL Server查归档表,把查询结果导入Excel,这种方式更稳定,查询历史数据也更容易。

第二种方式我实际用得更多,因为它可以把历史数据查询的复杂度放到SQL语句里,脚本只负责“取结果、写表格”。比如想统计某天每个小时的产量,直接对归档表做GROUP BY就可以,脚本逻辑简单得多。后面第四节的实战案例就是按这个思路写的。

3.3 方式C:数据库 + 专业报表工具或开源BI

如果报表需求已经上升到“统计分析和多维度展示”,比如同时要看三个车间、十几条产线的产量对比,或者要和MES、ERP系统做数据对接,那WinCC脚本和Excel组合就显得吃力了。这时候推荐直接访问WinCC归档数据库,用专业报表工具来做数据可视化与汇总。

常见做法是把WinCC后台SQL Server里的归档数据通过视图或定时同步外推到独立报表数据库,再用帆软报表、Power BI,或者开源图表库做展示。工业和互联网圈的报表工具非常多,找一个支持数据源连接、能做参数查询、能定时刷新的即可。这个方案的好处是性能好、可扩展、能做复杂的统计分析;代价是需要单独部署一套报表服务和数据同步机制,开发和维护成本更高。

另外一个不能忽略的点:直接用第三方工具连WinCC归档库是有一定风险的,因为WinCC的归档库表结构属于系统内部实现,官方不保证兼容性。更稳妥的方式是使用WinCC提供的OLEDB Provider(连接字符串形如Provider=WinCCOLEDBProvider.1;...),或者通过WinCC的“数据导出/外部数据接口”把数据同步到外部库再做分析。安全第一,别把生产系统的数据库搞出问题。

3.4 三种方式对比

实现方式开发难度报表格式自动化能力适用场景
在线控件+导出低固定手动临时查数、趋势浏览
VBS+Excel中高度自定义支持定时触发日报/月报/交接班报表
数据库+报表工具高灵活,可做BI支持定时与交互多维度统计、MES/ERP对接

我在实际选型时的经验法则是:需求简单、要得快,选方式A;格式要求明确、要自动生成,选方式B;数据量大、统计维度多、要对接上层系统,选方式C。很多项目往往是B和C混着用:日常生产报表用B,月度经营分析用C。

4. 实战:自动生成“昨日生产日报表”并导出Excel

4.1 需求定义:把模糊的“要报表”变成清晰功能表

假设这样一个场景:客户提出“每天早上一上班,我要看到昨天每个班次的产量、设备运行时间和报警次数,最好自动生成Excel表格放到共享文件夹里”。

我拿到这类需求后,一般先写成下面几条具体指标,再动工:

  • 统计周期:昨日00:00:00到23:59:59。
  • 统计对象:3台设备的产量累计变量、运行状态变量、一个报警汇总变量。
  • 输出格式:Excel表格,第一行是标题,第二行是日期,第三行开始按设备列行,最后一行有合计。
  • 触发方式:每天01:00自动运行,生成文件名为“生产日报_YYYYMMDD.xlsx”。
  • 存放位置:服务器D盘指定共享目录。

把需求落到这个颗粒度之后,后面开发和验收都会顺畅很多。很多报表项目拖垮在模糊需求上,就是因为客户一开始只说“要个表”,等到你交了货他又说格式不对、缺了哪个字段,反复改。所以做报表第一个技巧就是“先定义再开发”。

4.2 用VBS读取归档数据并写入Excel

这一节是核心。我给出一个思路完整、可直接改写的VBS脚本框架。先说下数据获取的逻辑:由于WinCC归档数据表名和项目相关,具体表名需要通过查询确认,常见的历史归档表名形如PV_1、PV_2等,对应你在变量归档中分配的表ID。更稳妥的做法是在WinCC自带的“OLAP”或者数据库连接测试界面里确认表名,也可以在WinCC项目数据库中查看。生产部署前,一定要把表名核对清楚,别直接照搬网上的脚本。

准备一份查询昨日产量累计值的SQL思路:

SELECT TagName, Value, ValueTime FROM PV_1 WHERE TagName = 'Line1_TotalCount' AND ValueTime BETWEEN '2024-01-01 00:00:00' AND '2024-01-01 23:59:59' ORDER BY ValueTime

有了查询结果之后,VBS脚本要做的事情就是连接数据库、执行查询、把结果写入Excel。下面是一段我在项目里实际使用过的脚本框架(手动调整过变量名和文件路径):

Option Explicit Dim conn, rs, xlApp, xlBook, xlSheet Dim strConn, strSQL, strExcelPath Dim iRow, strDate '昨天日期字符 strDate = DateAdd("d", -1, Date()) strDate = Year(strDate) & "-" & Right("0" & Month(strDate), 2) & "-" & Right("0" & Day(strDate), 2) '连接WinCC归档数据库(这里以SQL Server方式为例) strConn = "Provider=SQLOLEDB;Data Source=localhost;Initial Catalog=WinCCProjectDB;User ID=sa;Password=******;" Set conn = CreateObject("ADODB.Connection") conn.Open strConn '查询昨日归档数据,注意表名需据项目核实 strSQL = "SELECT TagName, Value, ValueTime FROM PV_1 " & _ "WHERE ValueTime >= '" & strDate & " 00:00:00' " & _ "AND ValueTime <= '" & strDate & " 23:59:59' " & _ "ORDER BY ValueTime" Set rs = CreateObject("ADODB.Recordset") rs.Open strSQL, conn, 1, 1 '创建Excel对象 Set xlApp = CreateObject("Excel.Application") xlApp.Visible = False Set xlBook = xlApp.Workbooks.Add Set xlSheet = xlBook.Worksheets(1) '写表头 xlSheet.Cells(1,1) = "设备名称" xlSheet.Cells(1,2) = "时间" xlSheet.Cells(1,3) = "产量" '写数据 iRow = 2 Do While Not rs.EOF xlSheet.Cells(iRow,1) = rs.Fields("TagName").Value xlSheet.Cells(iRow,2) = rs.Fields("ValueTime").Value xlSheet.Cells(iRow,3) = rs.Fields("Value").Value iRow = iRow + 1 rs.MoveNext Loop '保存文件 strExcelPath = "D:\Report\生产日报_" & Replace(strDate, "-", "") & ".xlsx" xlBook.SaveAs strExcelPath, 51 '51表示xlsx格式 '清理对象 rs.Close conn.Close Set rs = Nothing Set conn = Nothing xlBook.Close False xlApp.Quit Set xlSheet = Nothing Set xlBook = Nothing Set xlApp = Nothing MsgBox "报表已生成:" & strExcelPath

这个脚本实际执行前要特别留意几件事:Excel对象如果创建失败,八成是服务器上没有安装Excel或者DCOM权限没配好;文件保存路径如果目录不存在,SaveAs会报错;查询结果为空也要先判断一下,别让Excel生成一张只有表头没数据的空表。

4.3 定时自动触发:让报表不依赖人工点击

脚本写好了,怎么让它每天自动跑?WinCC全局脚本里有定时触发器。打开全局脚本编辑器的“触发器管理”,新建一个触发器,触发方式选“定时器”,设置每天01:00触发一次,再把上述脚本挂到这个触发器下面即可。

说起来简单,实际现场有好多隐含条件。WinCC服务器本身必须开机,而且运行系统得处于激活状态,脚本才能按触发条件执行。如果服务器设置了自动睡眠或者有人手动关闭了运行系统,定时脚本是跑不起来的。所以在实施时,我会在服务器上写一个计划任务作为“双保险”,每天早上8点检查一下报表文件是否生成,没生成就发一个告警消息到微信群或者短信平台——工业项目里“没数据”和“数据错了”一样要命,宁可让机器多说一句话,也别让车间主任来问你。

还有一个容易被忽略的问题:运行系统的脚本执行需要登录用户权限。如果WinCC运行系统以服务方式运行,脚本里创建Excel等COM对象时使用的是服务账户的权限,通常没有Excel许可,就会失败。我的做法是把WinCC和Excel都放在同一个具备本地桌面权限的登录会话里运行,这也是工业项目里很多自动化报表的基本前提。

4.4 给报表加一个“手动查询”入口

定时自动报表解决的是“定期要数”的问题,可现场经常有人问“能不能把上个月的报表也导出来看看”。我建议除了自动任务,再做一个画面按钮,绑定一段手动触发脚本,让操作员可以选择起始时间和结束时间,生成自定义时间段的报表。

实现上,可以在WinCC画面里放几个“输入输出域”,绑定到内部变量,比如@StartTime、@EndTime,操作员填好时间段后点击按钮,按钮的VBS事件里读取这两个内部变量的值,替换SQL语句里的时间条件,再执行和自动报表类似的导出逻辑。这个做法的好处是复用同一段核心代码,减少重复开发。

编码时记住一个原则:把查询和导出做成一个子过程,自动任务和手动按钮都调用它。这样以后要改报表格式,只改一处,不用同时改两边。

5. 报表实战中绕不开的故障与排查速查表

5.1 报表全都是0或者一片空白

这个问题我碰到过太多次了。第一先查归档配置,第二个查通讯状态,第三个查脚本的时间条件。

归档没开启是最容易发生的。有些变量你看画面里值有变化,以为存下来了,其实变量属性里“记录”根本没打勾。排查方法很简单:在WinCC运行系统的“变量归档”模块里打开归档数据视图,查一下目标时间段有没有数据。如果没有,说明数据源就有问题,后面脚本写得再好也是白搭。

还有一种情况是通讯问题。WinCC和PLC之间连接异常时,变量值不变或者变成0,归档下来的自然全是0。这时WinCC的诊断里会报通讯握手失败或连接中断,需要先恢复通讯连接再谈报表。我遇到过一次现场把PLC网线误拔导致当日报表全部为0,后来在报表逻辑里加了一个“通讯状态判断”,如果变量质量代码为0,就把对应数据标记为异常,免得报表看着正常却是错数。

5.2 查询时间范围正确,但Excel里数据缺失或偏移

做一个项目时遇到过:明明选了昨天的时间段,导出的数据却少了最后几分钟,或者出现了一些“看似整点整分”却不是真实事件时间的数据。原因多半出在时间格式和数据库查询条件上。

SQL查询时间范围时,最好带上毫秒或者使用数据库的ISODATE格式,避免边界条件漏数据。比如19:00:00这个时刻,很多系统存储的是19:00:00.000,如果你只写到“19:00:00”在某些OLEDB访问场景下没问题,但在有些连接字符串下就会被截断或者格式不识别。我在时间字符串拼接时统一使用“yyyy-mm-dd hh:mm:ss.000”标准格式,省掉很多麻烦。

还有一个和时区相关的小坑:WinCC服务器的本地时间,和PLC的系统时间不一定一致。如果PLC和上位机之间时间不同步,归档数据里记录的是WinCC服务器接收时打上的时间戳,而不是PLC侧真正发生事件的时间。所以现场实施时,第一件事就是把上位机、PLC、HMI的时间源统一,否则报表上和报警记录里的时间会对不上,客户第一时间就会质疑报表的正确性。

5.3 WinCC“握手错误”与报表数据缺失的关系

热搜词里频繁出现“WinCC 握手错误”,这部分值得单独说一下。

“握手错误”一般出现于WinCC通信连接建立失败的场景。例如使用S7协议族连接时,WinCC作为客户端与PLC建立TCP连接,如果PLC的IP地址配置错误、子网掩码不对、访问点没指对、或者PLC侧没有开放对应连接资源,通信握手就会失败。现场表现往往是变量状态变灰、值不更新、诊断里报连接故障。

这和报表有什么关系?关系很大。报表的数据源说到底就是这些变量。通信都握不上手,归档必然缺了一段数据,哪怕后期脚本再聪明也补不回来。所以我在项目调试阶段就会要求客户先把所有通信连接的状态做成一个画面汇总,绿、黄、红三色显示,每天检查一次。一旦报表发现数据空白,先看这个汇总页,凡是红黄的连接,那段数据缺失都是可以解释的。

排查握手上问题的思路,我一般按照:网络通不通(PING)→ 访问点对不对(设置PG/PC接口)→ PLC连接资源够不够(S7 CPU属性里连接数)→ WinCC变量连接配置有没有错(逻辑设备名、插槽号、机架号)这条流程走。最常见的原因是访问点或者插槽号搞错,细心检查一遍基本都能定位。

5.4 报表导出Excel慢、服务器卡顿

定时报表脚本跑起来后,CPU占用不高,但Excel导出经常要卡几十秒甚至几分钟,尤其在数据库表数据量很大的时候。原因基本出在查询和写入的方式上。

Excel写入的瓶颈通常是逐行Cells赋值。如果你查询出几千行数据,用循环一行一行的写,速度会非常慢。优化办法是把查询结果一次性读入数组,然后用Excel的Range对象一次性赋值,速度能提升一个数量级。我在数据量大的情况下会把脚本改成:

Dim arrData arrData = rs.GetRows() xlSheet.Range(xlSheet.Cells(2,1), xlSheet.Cells(2 + UBound(arrData,2), 3)).Value = Application.Transpose(arrData)

另外,数据库查询要尽量在SQL里完成汇总,比如用SUM、AVG、COUNT、GROUP BY,别把几万条原始记录全拉到Excel里再算。报表要的是“结论”而非“过程数据”,在数据库侧算好再导出,速度快得多,也更容易保证统计口径一致。

5.5 其他几个高频现场问题

现象可能原因处理方法
打开WinCC工程无显示项目缓存异常、授权文件缺失、分辨率或显卡兼容问题先检查项目复制路径和授权,尝试重置视图缓存
脚本定时没执行运行系统没激活、触发器没绑定、服务登录会话无权限检查运行系统状态、触发器和用互登录会话
Excel文件被锁定上一天报表文件没关、杀毒软件占用脚本里先关闭同路径文件,检查杀毒白名单
报表中文字符乱码Excel导入或写入字符集不匹配,常见于CSV统一使用UTF-8或GBK,Excel中用文本导入指定编码
归档数据量膨胀过快归档周期太短、保留策略没配调整归档周期,设置压缩与清理策略

6. 一点真实的使用体会

做WinCC报表这些年,我最大的感受是:报表本身不是一个独立功能,它是数据链条的最后一环。前面的变量定义、归档周期、通讯质量、时间同步,哪一个环节松懈了,报表都会给你颜色看。很多工程师一上来就研究脚本怎么写、Excel格式怎么调,却忽略了数据源的有无与准确度,结果折腾半天,做出来的报表根本没人敢用。

如果让我给刚入手的同事一个排序建议,我会说:先花三天把归档配好,再花一天写脚本,最后留半天测故障场景。不要把时间全花在争奇斗艳的表格样式上,工厂里真正有用的报表永远是“数据可靠、逻辑清晰、按时送达”这一条。

最后分享一个小技巧:在报表文件名里加入“年月日+班次”字段,生成后不要覆盖旧文件,保留至少一个月的历史版本。这样万一哪天对账的时候发现数据有异常,还能回头查究竟是报表脚本有问题,还是某个时间段的归档数据本身就缺了。这个习惯救过我很多次,也希望它能在你的项目里少几次无谓的扯皮。

返回列表