☰
WinCC报表控件实战:从变量归档到VBS脚本导出Excel
2026/10/20 7:01:15 网站建设 项目流程

简介:WinCC报表控件是西门子WinCC V7.x与博途WinCC环境下高效生成生产数据报表的工具,面向自动化工程师和PLC调试人员,旨在简化实时/历史数据的可视化与报告输出流程,无需编写复杂脚本即可配置出专业美观的报表。该压缩包共15个文件,大小约10.94MB,内含5个dll动态库(核心控件与数据接口)、exe可执行程序、pdf使用手册、mp4入门操作视频、png示例图片及xml/ini配置文件等,结构清晰,便于部署参照。已有6755人学习过该资源。包内提供的WinCCDataReport V35.0程序、操作录屏与详细手册,可帮助用户快速搭建报表环境,掌握动态数据绑定、多类型图表配置、定时/触发生成、打印导出及报警集成等核心功能,有效提升日常监控与数据分析效率。对于正在实施WinCC项目或希望优化报表开发流程的工程师,这是一份可直接上手并反复查阅的实用资料。

1. WinCC报表控件:从“数据能看”到“数据能交差”的那一步

做WinCC项目的工程师基本都经历过这个阶段:画面上的趋势、表格、报警都跑得挺好,操作员也认可,结果某天生产经理过来说“给我弄张日报表,把今天每小时的温度、压力、产量打出来”。这时候你才发现,报表控件不是画面上拖一个控件那么简单,它牵扯到变量归档、时间筛选、打印格式、导出Excel这一整条链路。这篇笔记我把WinCC报表控件的选型思路、配置步骤、脚本写法和几个典型坑完整过一遍,覆盖TIA平台和经典WinCC的通用做法,新手照着能把第一张报表跑起来,老手重点看参数边界和排错顺序。

2. 报表控件的四种实现方式:先选型,再动手

2.1 表格控件:固定格式数据表的最快路径

WinCC自带的表格控件(TableControl)是所有报表需求里优先级最高的候选方案。它的本质是一个ActiveX控件,直接绑定运行系统中的变量或者归档数据源,不需要写一行代码就能把实时值、历史值按行显示出来。它的优势在于和WinCC运行环境天然集成:画面打开就能看到数字,支持时间范围筛选,支持按列排序,打印时走WinCC的打印管理器,页面设置统一。

适合用表格控件的场景有三个特征:格式固定、数据量中等、不需要复杂统计。比如设备的每日温度记录表,一行一条数据,列就是“时间、温度、压力、状态”,这种需求用表格控件十分钟就能搭完。但如果你要的是一张带合计、平均、最大值标注的报表,表格控件自己做不到,得靠脚本去算,这时就该考虑后面几种方式了。

2.2 趋势控件当半报表:曲线回看和采样对齐

有些“报表”其实是曲线,领导要看的不是数字,是趋势走向。WinCC的趋势控件(TrendControl)可以用来做半报表,最常见的是把24小时内的流量曲线打出来,方便对比前后班次的波动。趋势控件支持多条曲线叠加,时间轴可以缩放,光标能读取当前值。

用趋势控件做报表有个隐藏优势:它天然处理了采样对齐问题。归档数据往往是不均匀的,变量动作频繁时记录多,平稳时记录少,表格显示出来会一节一节的难比对。趋势控件按时间轴绘制,数值稀疏时自动连线,这种场景下比表格直观得多。但趋势控件的导出能力弱,想导出成Excel基本只能截屏,所以我的习惯是:给操作员看的实时报表用趋势控件,给管理层交差的文本报表用表格或Excel。

2.3 报表系统与脚本导出:打印级报表的正路

当需求上升到“每天8点自动打印前一天的班报表,带公司抬头、带页脚、带审核签名栏”,原生控件的短板就暴露了。这时候正路有两条。

一条是WinCC Professional版本的报表系统,它自带报表编辑器,可以设计固定样式的打印模板,把归档变量、系统时间、操作员姓名这些字段拖拽到模板上,设定定时打印任务。这套东西的好处是打印样式专业,坏处是版本授权门槛高、设计器用起来需要适应,很多项目组用了不到三分之一的功能就转去脚本了。

另一条是VBS脚本导出Excel。这是绝大多数项目里最终采用的路径,因为它绕开了WinCC打印系统的页面约束,把数据交给Excel去排版。关于这条路径的操作细节,第4章会展开讲。

2.4 选型对照与决策建议

实现方式定时自动出表时间范围筛选打印质量数据统计能力维护成本适用阶段
表格控件支持但配置繁琐支持游标区间一般无低在线查看
趋势控件支持支持一般无低曲线对比
报表系统原生支持支持高弱中正式打印
VBS脚本导出Excel支持脚本控制高强高交差报表

优先顺序我一般这样定:先确认交付形式(屏幕看还是纸上看),再看要不要定时,最后看要不要统计函数。如果只是屏幕上点按钮看某个时间段的历史数据,用表格控件加一个时间筛选就够了,没必要上脚本。如果涉及跨班次汇总、平均值、合格率这类计算,请直接进入第3章把归档配好,同时准备第4章的Excel脚本,两条腿走路。

3. 核心实现:把归档数据装进表格控件

3.1 归档配置:报表的数据地基

所有报表都建立在一件事上:变量发生过什么历史记录。WinCC里这块叫变量归档(经典WinCC的Tag Logging)或数据记录(TIA平台的Data Logging)。很多时候表格控件查出空数据,不是控件没配好,而是归档根本没启动。

归档配置的通用逻辑分三步。第一步建立记录变量,把需要出现在报表里的物理量全部加进去,比如反应釜温度、夹套压力、循环水流量。第二步设定采集周期,这个参数直接决定报表的粒度,默认是1秒或1分钟,我的建议是普通过程量按“变化时归档”或者1分钟周期即可,不要无脑选1秒,否则一天的报表会有八万多行数据,查询和打印都拖垮。第三步勾选“启动采集”,然后在运行环境激活归档,这一步非常容易被忘记,尤其是TIA平台里新增数据记录后没有重新激活。

除了周期,还有两个参数会影响报表准确性:采集死区和归档死区。采集死区是变量值变化多少才写入,归档死区是变化的百分比阈值。现场压力变送器在小范围波动时,如果死区设小了,归档里会堆满无效波动数据;设大了,真实的小幅变化被过滤掉,报表曲线变成一条直线。经验值是0.5%到1%之间起步,确认现场波动后微调。

3.2 表格控件的三处关键参数:数据源、时间范围、刷新方式

表格控件拖到画面上之后,属性面板里有三处是必须挨个过一遍的。第一处是数据源,表格控件支持两种模式,实时模式和归档模式,做报表必须切到归档数据源,否则你只能看到当前值,看不到历史。第二处是时间范围,表格控件通常提供“起始时间”和“结束时间”属性,可以直接填固定时间,也可以绑定内部变量实现运行期修改。第三处是刷新方式,默认是手动刷新,也就是必须在脚本里调刷新方法或属性,数据才会按最新筛选条件重新加载。

常见的错误是把时间范围写死在属性里,结果画面跑了一个月,报表还是那几天的数据。对应做法是规划两个内部变量,例如ReportStartTime和ReportEndTime,在画面打开时或者按钮点击时通过脚本写入DateTime值,再把表格控件的时间属性绑定到这两个变量上。这样每次刷新按钮一按,控件自动按新区间查询。

3.3 定时出表:用计划任务或内部变量触发

很多项目要求“早上8点自动生成昨天的报表”,这时候触发方式有两个选择。经典WinCC有自带的定时任务,在脚本触发器的界面里添加“每日”触发器,设定执行时间和执行脚本,脚本里重算时间范围并刷新控件。TIA平台的HMI脚本触发器一样可以做,但界面上叫法不同,常见的是在“计划任务”里新增任务,事件类型选“每日/每周/每月”,再绑定脚本。

如果不想用计划任务,还有一个土办法:画面放一个隐藏的按钮,用一个周期1秒的内部变量计数,到设定时刻触发按钮事件里的报表生成脚本。这个方式的好处是逻辑完全透明,排错的时候直接看变量值就知道触发没触发;缺点是占一个周期变量,而且WinCC的脚本执行优先级不如系统任务,高峰时段可能延迟个几秒。对于报表这种早几分钟晚几分钟都无所谓的场景,完全够用。

3.4 VBS脚本实例:刷新报表并重置时间范围

下面这段脚本是在按钮事件里写的最典型的刷新过程,它做了两件事:把时间范围指向“昨天零点到今天零点”,然后触发表格控件重新加载数据。

Dim startTime, endTime ' 计算昨天零点 startTime = DateSerial(Year(Now), Month(Now), Day(Now) - 1) ' 计算今天零点 endTime = DateSerial(Year(Now), Month(Now), Day(Now)) ' 写入内部变量,表格控件的时间属性绑定到这两个变量 SmartTags("ReportStartTime") = CDate(startTime & " 00:00:00") SmartTags("ReportEndTime") = CDate(endTime & " 00:00:00") ' 刷新表格控件,不同版本写法略有差异 ScreenItems("ReportTable").Refresh

逻辑说明:DateSerial是VBScript里最可靠的日期偏移函数,直接传年月日三个参数,Day(Now)-1就是昨天的日期,避开跨月、跨年时手工算日期的麻烦。SmartTags是读写WinCC内部变量的标准入口,这里要求表格控件的起始时间属性绑定的是ReportStartTime这个变量,绑定关系在控件属性里提前配置好。Refresh方法在经典WinCC和TIA里都存在,但部分版本要求写ScreenItems("ReportTable").OutputUS或类似属性,如果你的版本里Refresh报错,先确认控件的对象名是否正确,再查这个版本控件提供的方法清单。

参数说明:这段脚本没有处理跨年,因为DateSerial会自动处理年份进位,12月31日的昨天会正确算成12月30日,1月1日的昨天会算成上年12月31日,这是DateSerial比DateAdd更直观的地方。如果你要做“前七天”这样的区间,把Day(Now)-1换成Day(Now)-7即可,月份和年份自动进位,不需要额外判断。

3.5 数据量大的时候要分页

日报表的默认粒度是1分钟,一天1440行,表格控件加载没有问题。但如果有人要求“把过去三个月每分钟的数据都打出来”,那就是十三万行,表格控件直接在运行画面里卡死,重则整个HMI页面白屏。

这种场景不能靠表格控件硬撑,备选方案有两个。一个是按天切割查询,报表界面留一个日期选择框,一天一查,查询脚本只处理当天数据;另一个是走SQL直接查归档数据库,用分页查询或者汇总查询把结果按小时聚合,只返回平均值和极值,数据量从13万行降到几百行。后面这个思路的实际价值很大,后面第6章的班报表就是按时间聚合思路展开的。

4. 打印与导出:从屏幕到纸面与Excel

4.1 导出Excel的三种路径

WinCC里导出Excel的需求几乎每个项目都会遇到,路径主要有三条。第一条是表格控件自带的导出功能,不少版本的表格控件在右键菜单里带“导出CSV”或“复制表格”选项,CSV可以直接被Excel打开,缺点是格式需要重新整理,而且只能导出控件当前显示的内容,数据行数多了会截断。

第二条是VBS创建Excel对象,这是最通用也最灵活的路,脚本先把数据写入Excel单元格,再按需设置边框、字体、合并单元格,最后另存为xlsx文件。

第三条是CSV中转,脚本把数据写成CSV文本文件,再用Excel打开另存。这条路径在服务器没有安装Excel的场合很有用,因为WinCC脚本启动Excel需要本机装了Office,没装就创建对象失败,CSV中转则不需要。

### 4.2 VBS脚本导出Excel:按模板写数据的常见写法 ```vbscript Dim objExcel, objSheet, objRow Dim i, fileName ' 创建Excel对象 Set objExcel = CreateObject("Excel.Application") objExcel.Visible = False objExcel.DisplayAlerts = False ' 新工作簿 Set objSheet = objExcel.Workbooks.Add.Worksheets(1) objSheet.Name = "班次报表" ' 表头 objSheet.Cells(1, 1).Value = "时间" objSheet.Cells(1, 2).Value = "温度(℃)" objSheet.Cells(1, 3).Value = "压力(MPa)" objSheet.Cells(1, 4).Value = "状态" objRow = 2 ' 从归档查询结果循环写入 For i = 0 To UBound(arrResult) objSheet.Cells(objRow, 1).Value = arrResult(i, 0) objSheet.Cells(objRow, 2).Value = arrResult(i, 1) objSheet.Cells(objRow, 3).Value = arrResult(i, 2) objSheet.Cells(objRow, 4).Value = arrResult(i, 3) objRow = objRow + 1 Next ' 保存文件,文件名带日期时间 fileName = "D:\Reports\" & Year(Now) & Month(Now) & Day(Now) & "_" & Hour(Now) & Minute(Now) & ".xlsx" objSheet.SaveAs fileName objExcel.Quit Set objSheet = Nothing Set objExcel = Nothing

逻辑说明:这段脚本的核心在CreateObject("Excel.Application"),只要运行环境装了Excel,这个调用就能成功。数据来源arrResult是前面从WinCC归档里查出来的二维数组,实际项目里可以由SQL查询构造,也可以由表格控件提供的数据源导出。行号变量objRow从第二行开始,是因为第一行留给了表头,这符合Excel报表的习惯。

参数说明:文件名拼接直接用了年月日时分,没有加分隔符,这样做是为了避免文件名里出现冒号等Excel不接受的字符。Year(Now) & Month(Now)拼接的结果是2025137这样的数字,一眼看得出日期但不好读,你可以改成Year(Now) & "-" & Month(Now) & "-" & Day(Now)。想保留整数,可以用FormatDateTime函数,但那个函数的格式受系统区域影响,跨语言版本的工控机上容易出幺蛾子,不如手工拼接稳。

4.3 打印模板与页面设置

报表打印的坑经常不在数据而在于版式。WinCC画面自带打印功能,把画面整页打印出来,但表格行数多了会自动拆页,拆页位置不固定,相当难看。正确做法是给报表单独做一版“打印画面”,这个画面不用于操作,只用于打印,画面长宽比设置为A4竖版或横版。

页面设置里要调整三个参数:打印比例建议直接缩放到适合一页宽度,默认是100%,行多时会超宽;上下左右边距设成5到10毫米,给页眉页脚留出空间;打印方向根据表格列数决定,超过五列就转横版。我们群里有个工程师跟我讲过他让表格跑到第三页背面、领导没看到后面数据的经历,从那以后他所有的报表画面都把“适合一页宽度”写在设计说明里。

打印触发可以用按钮,也可以和定时报表联动。定时触发打印时,WinCC的打印任务会走打印管理器队列,如果现场打印机离线或卡纸,任务会堆积,后面正常的打印全被堵住。所以自动打印场景一定要在脚本里加一个“打印机在线状态”判断,离线则弹提示或者把打印结果重定向成PDF文件。HTML的打印输出到PDF在很多版本里都支持,选打印机时选系统自带的Microsoft Print to PDF即可。

5. 避坑:WinCC报表控件里最常见的五个问题与排查顺序

报表功能上线后最折磨人的不是功能写不出来,而是写出来之后某些边界时间、某些操作顺序下数据对不上。下面这五条是我在不同项目里踩过、也帮人排过的实际案例,按现象、原因、解决的顺序写清楚。

5.1 报表时间整体慢八小时

现象:报表查询区间的数据显示出来,每天的数据整体偏移了8个小时左右。查询近三天数据时,昨天中午的记录显示在早上四点钟。

原因:WinCC的变量归档时间戳默认存的是本地时间,但时区设置成UTC之后,归档和显示会出现时差。很多工程师在部署工控机时为了日志规范把系统时区改成了UTC,而WinCC的归档服务仍然按本地Windows时间记录,两边各差八小时,叠加起来就出现了偏移。

解决:以工控机的本地时间为准,不要换区。打开系统时间设置,把时区改回北京时间(或项目所在地时区),去掉“自动设置时区”的勾选,然后重启WinCC运行系统,归档数据自动对齐。注意归档数据本身不用清空,时间戳存的是绝对时间,系统时区改回来后读取自然恢复正常。

5.2 表格控件一片空白,查询无数据

现象:表格控件绑定好了归档数据源,运行画面里按筛选条件查一天的数据,控件区域空白,没有报错也没有数据行。

原因:八成是归档压根没在记录。常见情况有三种:记录变量没有勾选“归档”;变量采集周期设成了“只在变化时”,而现场值一直保持恒定,就永远没有变化,自然没有数据;或者TIA平台里数据记录新增之后没有激活运行。

解决:先查归档状态,在WinCC变量管理器里找到对应记录,看记录变量的“状态”列是不是“正在采集”。没有就在线激活。如果激活了还没数据,把采集方式改成“周期采集”并设一个固定周期,比如5秒或1分钟。改完之后旧数据不会补录,要等新的周期时间过去后再验证。

5.3 导出的Excel打开就报格式损坏

现象:VBS脚本导出xlsx文件,脚本执行成功,文件大小也正常,但用Excel打开时弹“文件格式与扩展名不匹配”或直接打不开。

原因:SaveAs方法的参数没有指定文件格式。Excel的SaveAs如果不带第二个参数,默认按当前版本的默认格式保存,但有些Office版本在无人值守调用时会把xlsx存成XML格式或者文本格式,扩展名却是xlsx,导致文件头不对。

解决:SaveAs时显式传文件格式编号,xlsx格式对应的编号是51。改成objSheet.SaveAs fileName, 51。如果是在老Office环境,xls对应的是56,根据现场装的版本选一个。这个参数值不同版本有些区别,装完Excel先在开发环境手动验证一次再下发画面。

5.4 查询大时间段控件卡死

现象:操作员点了一个月的时间范围,表格控件转圈十几秒,画面失去响应,严重的直接退出运行系统。

原因:表格控件一次性加载了全部查询结果,归档数据里有几万甚至十几万行,控件渲染时内存飙升,加上运行环境本来就在实时刷新其他画面元素,CPU被打满。

解决:限制单次查询的数据量上限。实现方式主要有两种,一种是在查询逻辑里按天循环,一天查一次,每次加载完把数据二次处理;另一种是改用SQL聚合查询,把分钟级数据按小时取平均值和极值,报表展现小时粒度就足够,把数据库的压力降下来。数据量硬需求超过五万行的场景,建议彻底放弃表格控件,走SQL加Excel导出。

5.5 打印报表时页边距和画面预览不一致

现象:画面预览时表格正好一页,打印出来却左右缺了一块,右边列被截掉。

原因:WinCC画面的显示分辨率与实际打印机分辨率不一致,画面设计时用的是1920×1080工作站,操作站的打印机是老旧针打或驱动异常,打印比例又不匹配。

解决:打印专用画面的页面设置里把缩放方式从“实际大小”改为“缩放以适应纸张”,纸张类型选A4。同时设计打印画面时只放报表相关的内容,宽度最好不超过800像素(A4竖版),这样在大多数打印机上都能完整输出。如果现场有多台不同品牌打印机,测试时每台都打一份样张。

6. 把报表做成班报:时间参数联动与边界验证

报表做到最后,最常被点名要的是班报:早班、中班、夜班,每班一张。我一般把实现拆成三个组件:班次配置表、时间区间计算脚本、和一张带筛选条件的存根画面。

班次配置表用内部变量存班次开关时间,比如早班是8点到16点,中班是16点到0点,夜班是0点到8点。在画面里用下拉列表控件选班次,脚本里根据当前选中的班次索引去算起始时间和结束时间,然后把这两个时间写进归档查询。核心代码如下:

Dim shiftIdx, startTime, endTime shiftIdx = SmartTags("CurrentShiftIndex") ' 0=早班(08:00-16:00),1=中班(16:00-00:00),2=夜班(00:00-08:00) Select Case shiftIdx Case 0 startTime = DateSerial(Year(Now), Month(Now), Day(Now)) & " 08:00:00" endTime = DateSerial(Year(Now), Month(Now), Day(Now)) & " 16:00:00" Case 1 startTime = DateSerial(Year(Now), Month(Now), Day(Now)) & " 16:00:00" endTime = DateSerial(Year(Now), Month(Now), Day(Now)) & " 00:00:00" endTime = DateAdd("d", 1, endTime) Case 2 startTime = DateSerial(Year(Now), Month(Now), Day(Now)) & " 00:00:00" endTime = DateSerial(Year(Now), Month(Now), Day(Now)) & " 08:00:00" End Select SmartTags("ReportStartTime") = startTime SmartTags("ReportEndTime") = endTime

中班结束时间跨天这个点是最容易翻车的,直接写0点意味着当前时刻的零点,查询区间变成了负值,数据永远查不出来。加一行DateAdd把日期推到明天,这是吃过亏之后留下的固定写法。夜班查询要特别注意月初和月初数据核对,因为跨月的时候归档表里上月末的数据只能从数据库侧查,避免出现“今天1号,夜班查不到上个月31号晚上”的乌龙。

验证方法我习惯做三件事:设定当前时间为班次切换前最后一分钟,验证查询包含整个班次区间;设定当前时间为切换后第一分钟,验证不带上一个班的数据;再跑一遍跨天班次的查询,确认结束时间正确后移。从那以后我每次做完报表功能都强制走一遍这组边界验证,报表导出前也会先拿同一台机器上另一份手动汇总的数据比对平均值,确认后才上线发布。这些流程不复杂,但能拦住绝大多数“客户刚看一眼报表就质疑数据真实性”的尴尬场面,希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询