简介:面向SIEMENS WinCC V7.x及博途WinCC工程师的报表控件资源包,针对生产监控中实时与历史数据报表制作繁琐的痛点,提供无脚本编程、多种图表、动态数据绑定、定时触发、PDF与Excel导出及权限管理等能力,工程师无需编写复杂代码即可生成专业报表。压缩包共15个文件,总大小10.94MB,包含5个dll运行库、1个主程序exe、1份PDF使用手册、1个mp4入门录屏,以及xml与ini配置模板、png示意图片和txt说明文档,类型覆盖程序、文档、示例与配置,便于直接部署和对照学习。资源已有6713人学习下载,借助可运行程序、使用手册和操作视频,读者能快速掌握WinCC报表控件的安装、数据源绑定、模板设计和定时报表配置等关键流程。操作视频与手册内容互补,既适合新手从零了解控件布局,也方便老手快速查询参数设置方法。对于正在实施WinCC监控项目或希望提升报表自动化水平的工程师,这套资源能明显缩短上手周期,具有较强的现场参考价值。 做项目这么多年,每次一提“WinCC报表”,现场操作工和车间主任的眼睛就亮了,仿佛报表一出来,一天的生产问题就能自动水落石出。但真自己上手搞过的人都知道,WinCC自带的报表功能用起来有多别扭——格式固定、排版老气、导出数据还得折腾半天,更别提客户临时要加个“早班/晚班对比”或者“按批次统计”,现场改脚本改到头大。
这篇不聊理论,就聊聊我实际项目中“WinCC报表控件”的做法。我做的不是什么高级商业控件,而是基于WinCC自带基础能力,配合C脚本和VBS脚本自己拼出来的实用报表方案。这套东西应付交接班报表、产量统计、设备运行时长汇总这些常规场景完全够用,而且维护起来比集成第三方控件省心得多。如果你是做上位机集成、工厂信息化改造的工程师,手上正被报表需求追着跑,这篇应该能帮你少走不少弯路。
1. 先别急着画画面,把报表需求想清楚
1.1 为什么WinCC自带功能扛不住车间报表
WinCC的老版本里确实自带了一些报表相关控件,比如表格控件、打印任务、Excel报表控件等,但它们的问题很现实:首先,格式极其固定,你很难把表头做成客户想要的样式,客户要的往往是一个有“公司LOGO + 生产日期 + 班次 + 操作员”的规范报表,WinCC自带的表格控件要给每个单元格写脚本控制,累死个人。其次,数据源只支持WinCC归档数据,你想把Excel里的配方数据也塞进来做对比,那就得写大量胶水代码。
还有一个更关键的痛点:WinCC运行画面里的自带的表格控件,一旦数据量大,刷新会肉眼可见地卡顿。因为WinCC的脚本运行在UI线程里,去数据库查询数据再一条条塞进表格,操作一多画面直接变白板,操作工急得拍键盘。
所以我在项目里很少直接依赖WinCC的“报表”功能,而是把它拆成两部分:数据查询和展示,以及数据导出和打印。查询展示用WinCC画面里的表格控件或者ListView,导出和打印用Excel COM对象来做。这套组合拳目前还没有客户投诉过。
1.2 自研报表控件的三条路线,我选了哪条
接到报表需求,一般有三条路:
一是用WinCC自带控件硬怼,适合数据量小、格式要求低的场景,优点是开发快,缺点是后期维护和改版很痛苦。二是外挂第三方报表控件,比如水晶报表、FastReport这类的ActiveX控件嵌入WinCC画面,优点是功能强大、模板美观,缺点是要处理授权、注册、版本兼容,尤其是到现场部署的时候,工控机环境五花八门,很容易因为控件DLL和运行库不匹配翻车。三是自研一套轻量的报表方案,充分利用WinCC本身的归档数据库、SQL查询能力和Windows的COM对象接口,做一套“查询 + 展示 + 导出 + 打印”的闭环。
我最终选的是第三条路。原因很朴素:工控项目里稳定压倒一切,自己用脚本搭出来的东西,虽然开发时多花一点时间,但部署时只需要保证WinCC运行环境和Office(或者WPS)可用就行,没有黑盒依赖。
2. 报表数据从哪来:WinCC归档数据库读取原理
2.1 变量归档是怎么存的,得先弄明白
报表的核心是数据,而WinCC的数据都躺在归档数据库里。WinCC的变量归档分过程值归档、消息归档和用户归档三类。过程值归档是报表最常用的数据源,它按照我们配置的采集周期和归档周期,把变量值不断写入SQL Server数据库(WinCC 7.x以下)或者内置数据库(WinCC 7.5以后是SQL Server 2016/2019,Unified则有自己的存储机制)。
这个过程对新手来说很容易踩坑:如果你只配置了变量采集,没在“运行系统”或“变量管理”里设置归档,查报表的时候查出来的永远是一张空表。第一次做报表项目时,我在画面里折腾了半天,查了半天一支数据都没有,最后才发现连归档都没开,属于是没水还怪水龙头不好使。
还有一个和报表查询直接相关但经常被忽略的点:过程值归档的压缩机制。WinCC为了控制数据库膨胀,超过一定时间的旧数据会按平均值、瞬时值或总和值进行压缩。这个压缩方式和周期配置会直接影响报表数据的准确性。比如设备运行时长报表,如果你归档数据被压缩成了瞬时值,而你本意是想用离散值累加,最后算出来的时长一定会偏小。所以配置归档之前,一定要明确报表要统计什么:瞬时值适合看趋势,平均值适合看性能,累加值适合算产量和时长。
2.2 用WinCC OLE DB Provider把数据查出来
WinCC的数据读取,官方推荐通过“WinCC OLE DB Provider”这个数据库接口来做。它可以让我们像查SQL Server一样,用SQL语句从WinCC的归档库里取数据。
一个典型的连接串长这样:
Provider=WinCCOLEDBProvider;Catalog=CC_机器名_日期;Data Source=机器名\WinCCCatalog名字里的“机器名”是WinCC服务器名,“日期”是项目创建时自动生成的数据库实例名。具体怎么查这个值?在WinCC安装目录下打开“WinCC Explorer”的项目属性,或者直接用SQL Server Management Studio连上去找,不过为了安全,建议通过WinCC自带的“交叉索引”工具来查看归档数据,或者直接在脚本里用动态获取的方式拿数据库名。
查询归档数据的SQL大致是这种风格:
SELECT Value, DateTime FROM "TAG:R" WHERE ValueName = 'Tag1' AND DateTime BETWEEN '2024-01-01 00:00:00' AND '2024-01-01 23:59:59'需要注意的是,不同WinCC版本支持的SQL语法略有不同,尤其是表名的写法。我在WinCC 7.5 SP2上用的是“TAG:R”,在旧版7.0上试过“TAG:R”也没问题,但如果你想踩稳一点,就翻一下安装目录里ODK文档,里面有一章专门讲归档查询的SQL结构,照抄最稳妥。
3. 动手实现:一个能用的交接班报表控件
3.1 画面布局和控件规划
我这里拿一个典型的交接班报表来做例子。场景是:工厂两班倒,白班8:00到20:00,夜班20:00到次日8:00,每个班次结束要打印一张纸质的产量和报警统计报表,操作员签字后存档。
画面布局上,我一般会在WinCC画面编辑器里放这么几个东西:最上面是报表标题和班次信息(用静态文本),中间是一个表格控件(我用的是Microsoft ListView控件或WinCC自带的Table控件),再往下是四个功能按钮:查询、导出Excel、打印、交接确认。
值得一提是现场运行时,按钮的可用性和操作权限要匹配。比如“交接确认”按钮,只有班长权限才能操作,查询和打印操作员都能点。这个用WinCC的“用户管理器”做权限控制,不要省。
3.2 C脚本核心代码:查询、置位复位、跳转
WinCC的C脚本是经典WinCC里最灵活的动态逻辑工具。报表按钮的点击事件里,我用了一个非常标准的套路:先拼时间范围,再查数据库,最后填充表格。
查询按钮的核心思路简化如下(伪代码风格,具体函数名以实际版本为准):
// 获取当前时间和班次起始时间 char szStart[20]; char szEnd[20]; SYSTEMTIME st; GetLocalTime(&st); sprintf(szEnd, "%d-%02d-%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); // 判断当前是否为白班或夜班,得到szStart if (st.wHour >= 8 && st.wHour < 20) { sprintf(szStart, "%d-%02d-%02d 08:00:00", st.wYear, st.wMonth, st.wDay); } else { // 夜班跨天,需要减一天 // ... 处理日期回拨 }上面的日期回拨是个容易出错的细节,夜班如果跨了0点还在查“今天的20:00”,就啥也查不到。我后来干脆写了一个“班次时间计算”的公共函数,传入一个时间点,返回这个时间点所属班次的起止时间,这样不管是查历史还是查当天,逻辑都统一了。
然后就是执行SQL查询并把结果填充到表格里。WinCC的C脚本里可以用DBExecute相关接口或者通过SQLConnect方式执行SQL,不过更简单的方式是用VBS脚本里的ADO连接,配合CreateObject的组件方式。这块我一般是混合着用:C脚本处理复杂逻辑,VBS脚本用ADO查库、填充Excel、弹窗提示。两种脚本在WinCC里可以互相调用,不用死磕一种语法。
如果你涉及的是“按钮跳转到另一画面”这个需求,C脚本里的写法是一行:
SetPictureName("Main.PDL", "Report.PDL");这里的Main.PDL是当前画面名,Report.PDL是目标画面名。在WinCC Unified里,跳转画面的函数名有变化,用的是ActivateScreen,所以如果你从经典WinCC迁移到Unified,这一块脚本要重写。
再来说“变量置位 + 复位 + 二次确认”的操作。现场最典型的场景是交接确认按钮:操作工点击按钮后,需要弹一个确认框“确定完成交接班吗?”,确认后要把某个全局变量(比如“交接确认标志”)置位,然后几秒后再自动复位,给PLC或者MES系统一个脉冲信号。
C脚本里我会这么写:
#include "apdefap.h" void OnClick(char* lpszPictureName, char* lpszObjectName, char* lpszPropertyName) { // 第一次确认 if (MessageBox(NULL, "确认完成交接班?", "二次确认", MB_YESNO | MB_ICONQUESTION) == IDYES) { // 置位 SetTagBit("Con_Handover_Flag", 1); Sleep(500); // 复位 SetTagBit("Con_Handover_Flag", 0); } }这里面有两个注意点。一是SetTagBit写入的是一个WinCC内部变量,如果你写的是外部变量,确保连接和驱动是通的,否则这个脉冲到不了PLC。二是Sleep(500)这个写法在画面线程里会阻塞0.5秒,不影响大局,但如果画面里有动画在跑,这0.5秒动画会卡一下。更优雅的做法是用全局脚本和定时器来实现延时复位,能避开UI卡顿。最基础的做法就是用两个脚本动作:主按钮只置位,另开一个全局脚本500ms扫描一次变量,发现置位后立刻复位。
3.3 按钮打印与导出Excel
报表要落地,打印是最硬的需求。WinCC里打印方式不少,但最灵活的是导出Excel然后走Excel打印。现场普遍能在工控机上装Office或WPS,兼容性基本没问题。
我在按钮里用的是VBS脚本调用Excel COM对象,把表格控件里的数据搬进Excel:
Dim objExcel, objWorkbook, objSheet Set objExcel = CreateObject("Excel.Application") objExcel.Visible = False Set objWorkbook = objExcel.Workbooks.Add() Set objSheet = objWorkbook.Worksheets(1) ' 写表头 objSheet.Cells(1, 1) = "变量名称" objSheet.Cells(1, 2) = "时间" objSheet.Cells(1, 3) = "数值" ' 开始循环填充数据,省略... ' 这里把WinCC表格控件中每一行的内容写到objSheet对应单元格 ' 设置打印区域和页眉页脚 objSheet.PageSetup.PrintArea = "A1:C100" objSheet.PageSetup.Orientation = 2 ' 横向 objSheet.PageSetup.CenterHorizontally = True ' 预览或直接打印 objWorkbook.PrintOut objWorkbook.Close False objExcel.Quit Set objExcel = Nothing这个脚本有几个可以让别人刮目相看的细节:
第一,PrintOut前最好先判断一下打印机是否在线,否则弹出一个“没有安装打印机”的提示框把你卡住,客户体验很糟。第二,导出的时候不要导出所有行,而是只导出查询结果的有效区域,否则大量空白行会被一起打印,浪费纸张。第三,Excel进程要记得退出,Quit之后最好再加一句Set objExcel = Nothing,防止内存里残留Excel进程。这个在工控机上跑几个月之后特别明显:莫名其妙系统变慢,打开任务管理器一看,EXCEL.EXE躺了好几十个。
如果现场没有Office,也可以考虑用ADODB把数据写到CSV文件再打印,用WScript.Shell调用记事本打开CSV,效果虽然简陋但至少不依赖Office授权。
4. 实际调试中的问题和排查实录
4.1 画面模拟、脚本调试的精细活
WinCC工程阶段要调试脚本,离不开画面模拟。经典WinCC里,调试时可以直接在WinCC Explorer里启动“运行系统”,也能在画面编辑器里点“运行”按钮加载单画面。到了WinCC Unified环境,操作方式变了不少,很多从TIA Portal转过来的人会愣住:Unified的画面模拟不是点那个绿色小三角就能跑,而是要在画面编辑器顶部的“运行”菜单里启动Simulation模式。说句实在话,第一次找这个按钮我也找了好一会儿,它的图标藏得有点深。
脚本调试有个深坑:语法检查永远不够用,逻辑错误只能在运行时报出来,而且WinCC的报错弹窗很抽象,往往只给你一个“脚本运行错误”的编号,不告诉你具体哪行。我的做法是:在脚本关键节点故意弹MessageBox或者往WinCC诊断窗口写日志,一步一步看执行到哪一步,快速定位问题。这个习惯帮我排查掉了很多只靠读代码根本发现不了的现场问题。
4.2 数据读不出来、时间不对、数量对不上的坑
做报表查询,最经典的三类现场故障我也踩过:
一是数据读不出来,但归档里明明有数据。这个大概率是连接串的Catalog写错了,或者SQL查询语句里的时间过滤条件格式不对。WinCC的SQL读取时间格式是yyyy-MM-dd HH:mm:ss,如果你用了yyyy/MM/dd或者漏了前导零,WinCC的OLE DB Provider会很安静地返回空结果,不报错也不警告。
二是查询结果数量不对,尤其是用归档压缩之后。前面提到的压缩机制,归档周期越长,压缩得越狠,你查到的是“每5分钟的平均值”而不是“每个秒级采样值”。解决办法是查询时在SQL里显式过滤未压缩的数据,或者将归档的存储周期设置成“不使用压缩”,两个方案按数据量和磁盘情况权衡。
三是跨天数据的日期边界问题。查询夜班数据如果从“今天20:00”查到“明天08:00”跨度没问题,但如果你人工写死日期的起止字符串,最容易犯的错误就是夜班下班后查“今天20:00”查不到昨天晚上的数据。这个其实还是回到了我前面说的“班次时间计算”函数,把日期回拨逻辑写成公共函数,一次写好,到处调用。
4.3 WinCC起不来、安装不干不净的环境问题
报表项目做到后期,最怕的不是报表本身的问题,而是整个WinCC环境突然罢工。现场遇到过几次“WinCC无法启动基本应用程序”的提示,排查下来多数是系统和授权的问题。
有次是WinCC服务被安全软件禁用,导致运行时数据库服务没有启动,整个WinCC项目打开就报错。解决办法是把WinCC相关的服务改为自动启动,并把工控机的杀毒软件白名单加上数据库和WinCC的安装目录。还有一次是变量归档数据库文件损坏,用SQL Server的修复工具搞定的。
安装授权时报CryptAcquireContext错误,这个问题也遇到过。它的原因比较复杂,常见的是Windows加密服务(Cryptographic Services)被禁用或者系统权限不够,也可能是安全软件拦截了加密上下文创建。遇到这类问题,先检查Windows服务状态、再用管理员权限安装,基本上能解决。这类问题的经验法则:安装WinCC前,把杀毒软件和加固工具全部退出,装完再开回来,省事得多。
“如何完全删除已安装的内容”也是社区里高发的提问。WinCC不像普通软件,卸载不干净会导致重装失败。我的建议是走官方工具卸载,卸载后用Windows Installer清理工具把残留的WinCC相关条目清掉,再手动删除安装目录和项目数据库,最后清理注册表里相关的残留键。有条件的话直接重装系统,工控机上如果方便重做系统,那绝对是环境问题最干脆的解法,比在脏系统上折腾几小时要省心得多。
5. 工程落地的性能优化与交付经验
5.1 大数据量报表的性能卡点
报表数据查出来速度很慢,是大数据量场景下最常见的埋怨。排查了半年之后,我总结出三个性能瓶颈:
瓶颈一是数据库查询语句本身。如果你直接查所有归档数据不做时间范围过滤,WinCC的OLE DB Provider会全表扫描,查一年数据能把Excel跑崩。所以我都会在SQL的WHERE条件里限制DateTime的范围,哪怕只精确到小时,性能也能提升好几倍。
瓶颈二是把数据一条条往表格控件里塞的过程。WinCC里填充ListView或表格控件,每填充一行是对UI的一次刷新操作,数据量过万以后,这种刷新操作会极慢。解决办法是先关掉控件的刷新,填完再打开,或者分批填充。
瓶颈三是用Excel批量写数据,如果一条条写单元格,几万条数据能写到天荒地老。最好是把数据放到数组里,一次性赋值给Excel的Range对象,或者用VBS脚本里的CopyFromRecordset方法,直接把查询结果灌进Excel,那就快到飞起了。
5.2 控件的复用和维护
自研的报表控件最大的价值其实是复用。我在多个项目里沉淀了一套固定的画面模板:报表查询画面里,表头是动态生成的,列定义放在一个配置变量里,查询脚本是通用的,后续项目只需要改SQL和变量列表,不需要重写脚本。
我的做法是把查询逻辑、导出逻辑、打印逻辑分别做成全局脚本函数,然后在画面里只放按钮去调用这些函数。这样即使换了一个项目、换了画面布局,全局脚本不用大动,按钮的绑定事件也只需要指定函数名。时间长了,这套东西就变成我自己的“内部框架”,新项目第一天接需求,第二天就能把报表界面搭出来接数据,大大压缩交付周期。
需要注意的一点是,每个版本的WinCC脚本语法和API有一些差异,尤其是经典WinCC和Unified之间几乎不兼容。如果是跨版本复用,不要想着直接复制脚本,更应该复用的是设计思路和数据组织方式。
6. 最后说点实际的
做报表控件这么多年,我个人最大的体会是:报表工作的技术难度其实没有多高,真正难的是把客户“我想要个表格”这种模糊的需求,翻译成清晰的字段、时间范围、统计规则,并且提前预判操作工在运行现场可能遇到的各种误操作。与其做一个复杂炫酷的软件,不如做一个“查询顺畅、导出稳定、打印准确、权限清楚”的踏实功能。
如果你现在正好在搞WinCC报表,我的建议是先小步快跑,用“查询 + 导出Excel + 打印预览”这最简单的组合把流程跑通,再根据客户反馈迭代。不要一上来就贪大求全,报表的坑是可以一点一点填平的。上面提到的“班次时间计算”公共函数、Excel进程防残留、SQL查询时间格式这三个注意点,记住它们,至少能帮你省下三次现场的波折。
本文还有配套的精品资源,点击获取