ARTICLE · 1342679
WinCC 历史数据导出 Excel 的三种做法,附完整脚本
数据本来就在 WinCC 归档库里,导不出来多数是没找对接口。三种做法按数据量和工作量选,脚本可直接照抄。
月底给质量部交生产数据,很多同事还在翻画面手抄。其实数据都在 WinCC 归档里,缺的只是导出的办法。
01 现象:报表要历史数据,画面里没有导出按钮
现场基本都遇过这三件事:
质量追溯要原始数据。审核来了要某天某小时的温度、压力记录,画面趋势能看,但把一个月的数据拿成表格,没人愿意手工抄。 领导要看日报。每天早上八点要一版前一天的过程数据汇总,格式固定,最好自动生成,不要人守着。 第三方系统要接数据。MES、能源管理要历史数据,接口一问三不知,最后变成"你先导个 Excel 给我"。
这个问题拖久了很贵:追溯拿不出数据,审核扣分;日报靠人手抄,抄错一次,第二天全班组对数。数据其实一直躺在归档里,只是没人给它开个口子。
这三件事对应三种做法:定时记录用全局脚本写 CSV,补历史数据用 OLE DB 直查归档库,固定格式报表交给报表模板。先选对路,再写代码。
02 三种方案怎么选:一张对比表
把三条路拉到一张表里:
动手前先估算数据量:5 个变量按 1 分钟周期记一行,一天 1440 行、一个月四万行出头,CSV 装得下;要是 1 秒周期的十几个变量,一天就是上百万行,靠逐行追加 CSV 明显吃力,这种量级要么查归档库,要么放宽归档周期。
选型一句话:数据量小、只记当下,用方案一;要任意时间段的历史,用方案二;格式固定、要现成 Excel 版式,用方案三。三条路不互斥,很多项目是方案一在线记加方案二补查的组合。
03 方案一:全局脚本定时写 CSV,十几行 VBS 上线
思路:在 WinCC 全局脚本(VBS)里建一个周期动作,比如每 1 分钟触发一次,读当前变量值,追加到按日期切分的 CSV 文件。组态路径:打开全局脚本编辑器新建 VBS 动作,贴入代码;在动作的触发器里新建"周期"触发,周期设 1 分钟;再在计算机启动属性里确认全局脚本模块已勾选,激活运行系统即生效。
注意它记的是触发那一刻的实时值,不是从归档取数,相当于在归档之外旁路再记一份轻量流水。触发周期要与记录需求对齐:要秒级数据就别配 1 分钟;反过来说,只是为了月底对账,也没必要每秒导一行。
' WinCC 全局脚本(VBS)周期动作:每 1 分钟追加一行到 CSVOptionExplicitDim fso, logFile, logPath, nowStr' 1. 按日期切分文件,每天一个logPath = "D:\Export\ProdData_" & Year(Date) & _Right("0" & Month(Date), 2) & Right("0" & Day(Date), 2) & ".csv"Set fso = CreateObject("Scripting.FileSystemObject")IfNot fso.FolderExists("D:\Export") Then fso.CreateFolder("D:\Export")' 2. 新文件先写表头IfNot fso.FileExists(logPath) ThenSet logFile = fso.CreateTextFile(logPath, True, False) ' False=ASCII logFile.WriteLine "Time,Temp,Press,State" logFile.CloseEndIf' 3. 读变量,追加一行nowStr = Year(Now) & "-" & Right("0" & Month(Now), 2) & "-" & _Right("0" & Day(Now), 2) & " " & Right("0" & Hour(Now), 2) & _":" & Right("0" & Minute(Now), 2) & ":" & Right("0" & Second(Now), 2)Set logFile = fso.OpenTextFile(logPath, 8, True) ' 8=追加,True=不存在则创建logFile.WriteLine nowStr & "," & _ HMIRuntime.Tags("TI_101_Temp").Read & "," & _ HMIRuntime.Tags("PI_102_Press").Read & "," & _ HMIRuntime.Tags("ST_103_State").ReadlogFile.CloseSet logFile = NothingSet fso = Nothing三个细节:
文件按日期切分,月底交付直接拷当月文件,避免单文件过大打开卡死。 OpenTextFile第二个参数 8 是追加模式,第三个参数 True 表示不存在就创建。正式项目建议把路径和变量名做成配置读进来,别硬编码在脚本里。
验证方法:跑满一天,用 Excel 打开核对行数是否等于预期触发行数(1 分钟周期就是 1440 行),再抽几个时间点和画面趋势对数值。断电或异常中断可能留下半行脏数据,月底交付前过一遍空行和异常值。
04 方案二:OLE DB 直查归档库,任意时间段任意变量
原理一句话:经典 WinCC 运行时把变量记录写进本机 SQL Server 实例(默认实例名 计算机名\WinCC),运行库以 CC_ 开头;西门子提供的 OLE DB Provider(WinCCOLEDBProvider.1)是这套库的只读查询接口,任何能用 ADODB 的语言都能调。
动手前先确认两件事:一是变量记录里这些变量确实开了归档,没归档的变量在库里一行都查不到;二是归档分段周期和保留时间,它们决定你能查到多久以前的数据。
连接串三要素:Provider 固定写 WinCCOLEDBProvider.1,Catalog 填运行库名,Data Source 填计算机名加实例。运行库名在项目每次重新生成后会变,用 SQL Server Management Studio 连上实例看一眼最稳妥,现场以实际库名为准。
' WinCC 全局脚本(VBS):OLE DB 直查归档库,导出两个变量一天的历史OptionExplicitDim conn, rs, sql, catalogName' 1. 运行库名形如 CC_项目名_计算机名_日期_时分秒,以现场实际为准catalogName = "CC_DemoLine_PC01_2026_11_01_08_30_00"Set conn = CreateObject("ADODB.Connection")' 2. 连接串:Provider 固定,Catalog=运行库,Data Source=计算机名\WinCCconn.Open "Provider=WinCCOLEDBProvider.1;" & _"Catalog=" & catalogName & ";" & _"Data Source=PC01\WinCC"' 3. TAG:R 查询:变量名分号分隔;时间段是 UTC(北京时间要减 8 小时);tsasc=1 升序sql = "TAG:R,'TI_101_Temp;PI_102_Press'," & _"'2026-11-09 16:00:00.000'," & _"'2026-11-10 15:59:59.000'," & _"'tsasc=1'"Set rs = conn.Execute(sql)DoWhileNot rs.EOF' 字段:ValueID、TimeStamp、RealValue、Quality 等' Quality 不好的点在这里过滤,别导进表里 rs.MoveNextLooprs.Closeconn.Close四个关键点:
TAG:R是查归档的固定语法,单引号内用分号分隔归档变量名,后接起止时间,tsasc=1表示按时间升序。时间参数是 UTC,不是本地时间,这是这套接口最大的坑,下一节细说。 返回结果集里有 ValueID、TimeStamp、RealValue、Quality等字段,Quality不好的点要过滤,否则表里混着坏值。这是只读接口,别拿它去写库;大批量查询别放在产线高峰期跑。
还有一个编号问题:返回里的 ValueID 是归档库内部的变量编号,项目重新生成后会变,所以脚本里尽量用变量名查询,别把 ValueID 写死在代码里。
05 方案三:报表与控件导出,低代码但有模板天花板
如果需求就是每天一张固定格式的 Excel,用经典 WinCC 自带的报表能力比写脚本划算:
报表系统:用 Excel 做模板,通过 ODBC/OLE DB 数据源连归档库,配合打印作业定时生成,适合日报月报。 归档控件导出:在线趋势、表格控件自带导出功能,操作员手动导一段数据给客户,最省事。 上位机直连:C# 或 Python 直接连 WinCC 的 SQL Server 实例读归档,灵活度最高,这是上位机专栏的话题,之后单独写一篇。
我的经验:操作员手动场景用控件导出,定时自动的日报用报表系统,要自由格式和数据再加工才上脚本或上位机。别一上来就写代码,能用组态解决的,维护成本最低。
局限也要说清楚:模板格式改一次就要重配一次,批量自动化能力有限;报表组件的授权和版本支持差异大,组态前先确认你手上这套 WinCC 版本有没有装、可不可用,现场以实际版本为准。
06 验证与踩坑:时区、编码、分段三道坎
三种做法各自的坑不一样,把最高频的四个列出来:
时区这个坑值得单独展开:OLE DB 的查询和返回时间都是 UTC。要查北京时间 11 月 10 日 0 点到 24 点,参数应写 11 月 9 日 16:00 到 11 月 10 日 15:59:59,返回的 TimeStamp 同样加回 8 小时再给人看。判断是不是时区问题很简单:数据总是差 8 小时,就是它。
编码的坑在 FSO:CreateTextFile 第三个参数 True 是 UTF-16,Excel 双击打开这种 CSV 不会按逗号切列;False 是 ASCII,中文表头必乱。简单做法表头用英文,讲究一点用 ADODB.Stream 写 UTF-8 带 BOM。
最后一条纪律:别在运行服务器上做重查询。要大批量导历史,安排在非生产时段,或者从备份段上查,别拖累画面刷新。
上线前做一轮验证:先按 OLE DB 查一天的数据,和画面趋势对几行关键值,时间戳、数值、小数位都对上,再放开跑;第一个月每周核对一次导出行数,确认没有因为异常中断丢过数据。
结语
一句话结论:在线记流水用全局脚本写 CSV,补历史数据用 OLE DB 查归档库,固定报表交给模板——先把接口找对,再纠结格式。你们车间的生产数据报表现在靠什么导出来的?评论区聊聊。















































































