简介这份文档面向SCADA系统工程师与Intouch组态开发人员聚焦WonderWare Intouch 2014R2平台与SQL Server 2012数据库的集成及Excel报表实现适合需要搭建实时数据存储与报表展示方案的中级技术人员参考。资源包内共1个doc文件约2.48MB以图文步骤形式组织内容涵盖数据库配置、权限设置、数据写入、连接管理及报表生成等模块。文档详细讲解了在Intouch中通过SQL访问管理器绑定变量、使用SQLConnect与SQLInsert函数完成数据写入、借助条件脚本按分钟触发存储以及利用Excel VBA从数据库提取数据形成可视化报表的完整流程并附有数据库恢复与文件附加的操作说明。目前已有531人学习可帮助读者掌握从组态配置到报表输出的关键环节快速构建可实时监控与报告工业数据的SCADA解决方案。1. Intouch 加数据库做 Excel 报表一条被低估的产线数据链路产线上 Intouch 画面上跳动的液位、温度、流量操作工看一眼就过去了可一旦设备科要一份「上周三夜班 2 号反应釜温度曲线」现场往往只能靠人拿手机对着屏幕拍照。这个标题讲的就是把 Intouch 的历史数据落到 SQL Server再用 Excel 把数据变成能打印、能发邮件、能归档的报表。它解决的不是「画面好不好看」而是「数据留不留得住、拿不拿得出来」。适合两类人一类是现场做 SCADA 维护、被报表需求追着跑的自动化工程师另一类是刚接手 Intouch 项目、想给系统补上数据持久化这一环的调试人员。整条链路的核心就三件事——Intouch 侧把数据写进数据库、SQL Server 侧把表结构管好、Excel 侧把查询结果变成报表。下面按这个顺序拆开讲每一步都落到能复现的命令和配置上。2. Intouch 侧打通 SQL Server从 SQLConnect 到绑定表2.1 为什么选 SQLConnect 而不是硬写脚本Intouch 往数据库写数据常见做法有三条路一是用 SQLConnect 函数族二是用第三方 OPC 转数据库网关三是自己写脚本调外部程序。现场用得最多、也最稳的是 SQLConnect原因是它把连接、执行、断开拆成了独立函数出错时能定位到具体是哪一步断的而不是一个黑匣子。SQLConnect 的本质是 Intouch 脚本通过 ODBC 驱动去操作数据库所以第一步不是写脚本而是把 ODBC 数据源配好。配置路径在 Windows 的「ODBC 数据源管理器」里注意要选「系统 DSN」而不是「用户 DSN」因为 Intouch 的运行时进程不一定以当前登录用户身份跑。驱动选 SQL Server 或 SQL Server Native Client名称建议用纯英文比如IntouchDB后面脚本里要原样引用。服务器填127.0.0.1或实例名数据库选你建好的那个比如SCADA_DATA。测试连接通过后这一步才算落地。提示DSN 名称一旦定了就别改改了之后所有引用它的脚本都要跟着改现场最容易在这里翻车。2.2 建表历史数据表结构怎么定数据库侧的表结构决定了后面 Excel 查询好不好写。我一般会建两张表一张是实时快照表一张是历史归档表。实时表只保留最新值历史表按时间追加。下面是最小可用的建表语句-- 历史数据表按时间追加不更新 CREATE TABLE dbo.TagHistory ( ID BIGINT IDENTITY(1,1) PRIMARY KEY, TagName NVARCHAR(64) NOT NULL, -- 位号名如 Reactor2_Temp TagValue FLOAT NULL, -- 数值非数值型可另建字段 Quality TINYINT NULL, -- 质量码0 表示好值 SampleTime DATETIME NOT NULL -- 采样时间由 Intouch 写入 ); CREATE INDEX IX_TagHistory_Time ON dbo.TagHistory(SampleTime, TagName);TagName用 NVARCHAR 是为了兼容中文位号虽然我建议位号全用英文。SampleTime上建联合索引是因为 Excel 报表几乎都是按时间段加位号查没索引的话数据量一上来查询就卡。Quality字段别省现场经常出现某个值其实是通讯中断时的保持值没有质量码你根本分不清。2.3 用 SQLConnect 把位号值写进去Intouch 脚本里写数据库核心是四个函数SQLConnect、SQLPrepare、SQLExecute、SQLDisconnect。下面是一段条件脚本的写法挂在数据变化或定时触发上-- Intouch 条件脚本定时把位号值写入 SQL Server result SQLConnect(IntouchDB, sa, YourPassword); IF result 0 THEN SQLPrepare(INSERT INTO TagHistory (TagName, TagValue, Quality, SampleTime) VALUES (?, ?, ?, ?)); SQLSetParam(1, Reactor2_Temp); SQLSetParam(2, Reactor2_Temp); SQLSetParam(3, Reactor2_Temp_Q); SQLSetParam(4, $DateTime); SQLExecute(); SQLDisconnect(); ENDIF;逻辑说明SQLConnect返回 0 表示连接成功非 0 要查错误码。SQLPrepare里的问号是参数占位符用SQLSetParam按顺序填这样能避免字符串拼接带来的注入和格式问题。$DateTime是 Intouch 的系统时间变量直接写进去就是采样时刻。参数说明第一个参数是 DSN 名必须和 ODBC 里配的一模一样第二个是数据库账号生产环境别用 sa建个只对这张表有 INSERT 权限的账号更稳妥。注意SQLDisconnect一定要在SQLExecute之后调用否则连接会一直挂着时间长了数据库连接数会被占满。3. Excel 报表侧用 VBA 把查询结果变成能打印的表3.1 为什么报表逻辑放在 VBA 而不是数据透视表数据透视表能快速看数但它有两个硬伤一是刷新依赖手动或打开文件时触发二是格式和打印区域不好固化。现场要的是「双击一个按钮选个时间段报表直接出来能打印」这种固定流程用 VBA 更合适。VBA 在这里干三件事连数据库取数、把结果写到工作表、按模板排版。热搜里常出现的「vba数组」「vba字典」在这里都用得上取回来的数据先放数组再按位号分组统计。3.2 用 ADO 连 SQL Server 取数Excel 里连数据库推荐用 ADO 而不是 DAO因为 ADO 对 SQL Server 支持更好。下面是一段最小可用的取数过程Sub QueryTagHistory() Dim conn As Object, rs As Object, sql As String Set conn CreateObject(ADODB.Connection) Set rs CreateObject(ADODB.Recordset) 连接字符串按实际服务器、库、账号改 conn.Open ProviderSQLOLEDB;Data Source127.0.0.1; _ Initial CatalogSCADA_DATA;User IDreport;PasswordYourPassword; sql SELECT TagName, TagValue, SampleTime FROM TagHistory _ WHERE SampleTime BETWEEN ? AND ? ORDER BY SampleTime Set rs conn.Execute(sql) 把结果写到 Sheet2从 A2 开始 Sheet2.Range(A2).CopyFromRecordset rs rs.Close: conn.Close Set rs Nothing: Set conn Nothing End Sub逻辑说明ADODB.Connection负责连接ADODB.Recordset装结果CopyFromRecordset一次性把数据刷到单元格比逐格写快得多。参数说明连接字符串里的Provider用 SQLOLEDB 兼容性最好账号report建议只给 SELECT 权限。时间段参数这里为了简洁直接拼了实际用ADODB.Command加参数更安全能防注入也能处理日期格式。3.3 报表排版与打印区域固化取到数之后报表好不好用全看排版。我一般把报表拆成三块标题区、数据区、汇总区。标题区放报表名和时间段数据区用CopyFromRecordset填汇总区用公式或 VBA 算最大值、平均值、越限次数。打印区域用PageSetup.PrintArea固定页眉页脚设好这样操作工点一下就能出纸。With Sheet2.PageSetup .PrintArea $A$1:$F$100 .Orientation xlLandscape .Zoom False .FitToPagesWide 1 .FitToPagesTall False End WithFitToPagesWide 1保证列宽自动缩到一页FitToPagesTall False表示行数多了可以翻页不会把字缩得看不清。这一步做完报表才算真正能交付。4. 避坑与排查这条链路上最容易翻车的五件事4.1 现象Intouch 脚本执行了但数据库里没数据原因通常是 ODBC 数据源配成了用户 DSN而 Intouch 运行时以服务或别的账号跑读不到这个 DSN。解决方法是改用系统 DSN或者确认运行时账号和配置 DSN 的账号一致。另一个可能是SQLConnect返回了非 0 但脚本没判断连接根本没建立。排查时先把返回值打到 Intouch 的日志或画面上看。4.2 现象Excel 打开报表文件提示「加载项被禁用」这是热搜里高频出现的问题。原因是 Excel 的安全策略把宏或加载项拦了尤其是文件从别的机器拷过来带了「阻止」标记。解决方法是右键文件属性勾选「解除锁定」再到信任中心把该目录加进受信任位置。如果公司有组策略统一管控就得找 IT 放行自己改注册表往往会被策略覆盖回去。4.3 现象查询越来越慢报表打开要等好几分钟原因一般是历史表数据量涨了但没做归档或者查询条件没用上索引。解决方法是给SampleTime和TagName建联合索引再做一个定期归档作业把半年前的数据挪到归档表。另外 Excel 侧别用SELECT *只取报表需要的列能明显减少传输量。4.4 现象日期时间段查询结果对不上原因多半是 Intouch 写入的$DateTime和 Excel 查询用的日期格式或时区不一致。解决方法是统一用数据库的DATETIME类型查询时用参数化传日期别用字符串拼。如果跨时区确认服务器和现场时钟同步。4.5 现象VBA 报「自动化错误」或连接超时原因可能是 SQL Server 的 TCP/IP 协议没启用或者防火墙挡了 1433 端口。解决方法是到 SQL Server 配置管理器里确认 TCP/IP 已启用并重启服务再用 telnet 测一下端口通不通。账号密码过期也会导致连接失败热搜里「sql server 2012 密码到期」说的就是这种情况改密码或设永不过期即可。5. 进阶把报表做成定时自动出、还能追溯质量码5.1 用 SQL Server 代理作业定时跑查询报表不一定非要人点。可以在 SQL Server 里建一个代理作业每天固定时间把当天数据汇总到一张日报表Excel 只负责读这张日报表查询压力就小很多。作业步骤里写 T-SQL调度按班次设比如早班结束、夜班结束各跑一次。-- 日报汇总按位号算当班最大最小平均 INSERT INTO DailySummary (TagName, ShiftDate, MinVal, MaxVal, AvgVal) SELECT TagName, CAST(SampleTime AS DATE), MIN(TagValue), MAX(TagValue), AVG(TagValue) FROM TagHistory WHERE SampleTime ? AND SampleTime ? GROUP BY TagName, CAST(SampleTime AS DATE);参数说明两个问号分别是班次开始和结束时间由作业步骤传。GROUP BY里带上日期是为了跨天班次也能正确分组。5.2 质量码怎么用起来前面建的Quality字段别浪费。报表里可以加一列「有效数据占比」用SUM(CASE WHEN Quality 0 THEN 1 ELSE 0 END) / COUNT(*)算。这样设备科拿到报表时能一眼看出哪些时段的数据是可信的哪些是通讯中断时的保持值。这个细节很多现场报表都缺但恰恰是数据能不能被信任的关键。5.3 一个我踩过的坑早年间我做第一版报表时图省事把 Intouch 的$DateTime直接当字符串写进数据库结果跨月的时候日期格式变了查询全乱。后来统一改成数据库DATETIME类型查询用参数传再没出过问题。还有个习惯每次改完脚本先在测试库跑一遍确认数据对得上再上生产。这条链路不长但每一环都依赖上一环前面偷的懒后面都要还。希望帮到你。本文还有配套的精品资源点击获取