简介:这份文档面向SCADA系统工程师与Intouch组态开发人员,聚焦WonderWare Intouch 2014R2平台与SQL Server 2012数据库的集成及Excel报表系统搭建,帮助解决工业现场实时数据存储、历史数据查询与报表输出的实际问题。资源包共1个doc文件,约2.48MB,内容以图文步骤形式展开,涵盖数据库配置、权限设置、标记名字典建立、SQL访问管理器绑定、SQLConnect与SQLInsert脚本编写,以及Excel VBA报表模板制作和数据库恢复等模块。文档从数据库登录方式调整讲到Intouch变量与表单字段的对应绑定,再到每5秒轮询写入与分钟条件判断逻辑,并给出报表模板的控制面板与参数日报页面设计思路,便于读者按章节对照实操。目前已有531人学习下载,适合需要打通Intouch与SQL数据链路、构建可定期刷新Excel报表的中级自动化从业者参考。
1. 从 Intouch 到 SQL Server 再到 Excel:一份能直接落地的 SCADA 报表链路拆解
很多做 SCADA 现场实施的朋友都遇到过这个场景:Intouch 画面上实时数据跑得好好的,但一到“出报表”就抓瞎——历史数据散在内存标记里,班组长要的日报、周报、月报全靠人工抄表,Excel 里手动填数,错一行就得从头核。这份文档解决的正是这个痛点:在 WonderWare Intouch 2014 R2(IDE 平台)里,把实时数据定时写入 SQL Server 2012,再用 Excel 的 VBA 报表系统把数据拉出来形成可视化报表,最后还附带了数据库文件的备份与恢复操作。整条链路覆盖了数据库配置、Intouch 标记与脚本、SQL 绑定列表、Excel 模板 VBA 引用、以及 mdf/ldf 文件的附加恢复。适合正在做 Intouch 报表模块的自动化工程师、SCADA 系统集成人员,以及需要把现场数据沉淀到关系型数据库做二次分析的从业者。下面按“数据怎么进去 → 报表怎么出来 → 库怎么恢复”的顺序,把每一步的参数和坑讲透。
2. 打通 Intouch 到 SQL Server 2012:登录方式、标记字典与绑定列表
2.1 为什么先改 SQL Server 身份验证模式
Intouch 通过 SQLConnect 函数连接数据库时,用的是连接字符串里的 UserID 和 Password,这属于 SQL Server 身份验证。而 SQL Server 2012 默认安装后往往只启用了 Windows 身份验证模式,这时候你用 sa 账号怎么连都连不上,报错通常是“用户 ‘sa’ 登录失败”或者“无法打开登录所请求的数据库”。所以第一步必须进 SQL Server Management Studio,在服务器属性 → 安全性里,把身份验证方式改成“SQL Server 和 Windows 身份验证模式”,确定后重启 SQL Server 服务生效。
改完模式之后,还要确认 sa 账号是启用状态。在对象资源管理器的“安全性 → 登录名”下找到 sa,右键属性,常规页里改密码,状态页里确认“登录”是已启用。如果你不想用 sa,也可以新建一个专用登录名,但记得在“服务器角色”里至少给 public 和 db_datareader、db_datawriter,否则 Intouch 写入时会因为权限不足被拒。这一步的常见做法是:给报表单独建一个账号,只授权目标数据库的读写,避免用 sa 到处连。
数据库和表单的建立相对直接:新建数据库(比如 BZ_BB 或 YADC_BB),然后在里面建一张表,列名要和后面 Intouch 绑定列表里的变量名一一对应。比如你打算记录日期、时间、温度、压力,那表里就建对应的列,数据类型也要匹配——Intouch 的内存整型对应 SQL 的 int,内存实型对应 float,内存消息对应 nvarchar。这里有个容易翻车的地方:Intouch 的标记名如果带了特殊字符或者中文,绑定列表里可能识别不了,建议全用英文加下划线。
2.2 标记名字典里必须建的三个内存标记
在 Intouch 的标记名字典里,有三个标记是整条链路的“基础设施”,缺一个脚本就跑不起来。
第一个是 Connid1,类型选“内存整型”。它的作用是保存 SQLConnect 返回的连接编号,后续 SQLInsert、SQLDisconnect 都要靠这个编号找到对应的连接。你可以把它理解成数据库连接的“句柄”,没有它,后面所有 SQL 函数都不知道该往哪个连接上发指令。
第二个是 GetDateTimeS,类型选“内存消息”。这个标记用来存连接时的时间字符串,方便在报表里记录数据写入的时间戳。内存消息类型在 Intouch 里就是字符串,长度默认 131 个字符,够放标准日期时间格式了。
第三个是 NodeName,类型也是“内存消息”。它存的是本机计算机名,脚本里用它来判断当前节点是不是需要执行写入的那台机器。多节点部署时这个判断很关键,不然每台机器都往同一个库里写,数据就重复了。
除了这三个,你还需要一个 WSQLS,类型选“内存离散”。它是写入标志位,用来防止同一分钟内重复写入。逻辑是:写入前检查 WSQLS 是否为 0,写完置 1,下一分钟再复位为 0。没有这个标志位,条件脚本每触发一次就写一条,一分钟能给你灌进去几十条重复数据。
2.3 条件脚本的触发时机与 SQLConnect 参数拆解
Intouch 的脚本分两类:条件脚本和应用程序脚本。数据写入的逻辑一般放在条件脚本里,用系统时间做触发条件。文档里用的是$Second==3和$Second==5,意思是每秒判断一次,当秒数等于 3 或 5 时执行对应脚本。这里要注意,$Second是系统秒时间,范围 0 到 59,条件类型选“为真时”,表示条件成立的那一刻执行一次。
数据库连接脚本通常放在应用程序脚本的“启动时”或者条件脚本里。核心函数是:
SQLConnect(Connid1, "provider=sqloledb;Data Source=ZHWSC02;Initial Catalog=BZ_BB;UserID=sa;Password=single");这行代码里,Connid1 是前面建的内存整型标记,用来接收连接编号。连接字符串分五段,每段用分号隔开,等号前面是参数名,后面是值。Provider 固定写 sqloledb,这是 SQL Server 的 OLE DB 提供程序;Data Source 填数据库所在计算机名,如果你数据库和 Intouch 在同一台机器上,可以填 localhost 或者计算机名;Initial Catalog 是数据库名,必须和你实际建的库名一致;User ID 和 Password 就是登录名和密码。
参数改错是最常见的翻车点。Data Source 填了 IP 但 SQL Server 没开 TCP/IP 协议,连不上;Initial Catalog 拼错一个字母,报“无法打开登录所请求的数据库”;Password 里有分号,连接字符串会被截断。我一般建议在 SSMS 里先用同样的账号密码手动登录一次,确认能进再往脚本里填。
2.4 绑定列表:变量名与列名的强制对应关系
绑定列表在 Intouch 左侧工具视图的 SQL 访问管理器里,叫“绑定列表(B)”。它的作用是把 Intouch 的标记和 SQL 表的列关联起来。新建一个绑定列表,名字比如叫 TDays,然后在里面添加行,每行选一个 Intouch 标记,再选对应的数据库列名。
这里有一条硬规则:绑定列表里的变量名必须和 SQL 表里的列名完全一致,数据类型也必须匹配。比如 Intouch 里有个内存实型标记叫 Temp1,SQL 表里就得有个 float 类型的列叫 Temp1。名字对不上,SQLInsert 执行时会报“无效的列名”;类型对不上,比如 Intouch 是字符串但 SQL 列是 int,写入时直接失败,而且错误信息不一定明确指向类型问题,可能只报一个泛泛的“插入失败”。
绑定列表建好之后,SQLInsert 函数才能用:
SQLInsert(Connid1, "TDays", "TDays");第一个参数是连接编号,第二个参数是 SQL 表名,第三个参数是绑定列表名。注意这两个 TDays 含义不同:第一个是数据库里的表单名称,第二个是 Intouch 里建的绑定列表名称。文档里特意强调了这一点,因为很多人会以为两个都填表名,结果绑定列表名对不上,写入的数据全是空值。
2.5 完整写入脚本的逻辑链与关闭时清理
把上面的碎片拼起来,一个完整的写入脚本大概长这样:
GetNodeName(NodeName, 131); IF NodeName == "OP_OP1" THEN IF $Minute >= 58 THEN IF WSQLS == 0 THEN SQLInsert(Connid1, "TDays", "TDays"); WSQLS = 1; ENDIF; ELSE WSQLS = 0; ENDIF; ENDIF;逐行解释:第一行 GetNodeName 把本机计算机名取到 NodeName 变量里,131 是字符串最大长度。第二行判断当前机器是不是 OP_OP1,只有这台机器执行写入,避免多节点重复写。第三行判断当前分钟数是否大于等于 58,意思是每小时的最后两分钟才触发写入,这样一天下来就是 24 条记录,适合做小时级报表。第四行检查 WSQLS 是否为 0,确保这一分钟内还没写过。第五行执行插入。第六行把 WSQLS 置 1,标记已写。如果分钟数不到 58,走 ELSE 分支把 WSQLS 复位为 0,为下一个小时做准备。
退出应用程序时,必须在“应用程序脚本”的“关闭时”里加一行:
SQLDisconnect(Connid1);不写这行,数据库连接不会主动释放,时间长了 SQL Server 那边会积累一堆睡眠连接,严重时把连接池占满,新的连接请求全部被拒。这个坑我在现场见过不止一次,表现是系统跑几天之后突然写不进数据,重启 Intouch 又好了,根源就是连接没关。
3. Excel 报表系统:模板结构、VBA 引用与数据拉取
3.1 报表模板的两个核心 Sheet 与 VBA 入口
Excel 报表模板不是随便建个表格就行,它需要两个关键 Sheet:一个是“控制面板”,用来放按钮、时间选择、查询条件;另一个是“参数日报”,用来展示从 SQL Server 拉出来的数据。控制面板上一般会放一个“刷新”按钮,绑定 VBA 宏,点击后触发数据查询和写入。
进入 VBA 编辑器的方式是:在“参数日报”Sheet 标签上右键 → 查看代码,或者按 Alt+F11。进去之后,在“工具”菜单里选“引用”,这一步非常关键,漏了后面代码全报“用户定义类型未定义”。
3.2 VBA 引用里必须勾选的三项
文档里说“至少钩选以下三项”,结合 SQL Server 2012 和 Excel 的常规搭配,这三项通常是:
| 引用名称 | 作用 | 不勾选的后果 |
|---|---|---|
| Microsoft ActiveX Data Objects 2.8 Library | 提供 ADO 连接和记录集对象 | 无法使用 Connection、Recordset |
| Microsoft ActiveX Data Objects Recordset 2.8 Library | 记录集相关补充 | 部分 Recordset 方法不可用 |
| Microsoft Excel 16.0 Object Library | Excel 对象模型 | 无法操作 Sheet、Range |
版本号可能因 Office 版本不同而有差异,比如 15.0 对应 Office 2013,16.0 对应 2016 及以上。选的时候挑版本号最高的那个通常没问题。如果列表里找不到 ADO 引用,说明系统里没装 MDAC 或者 ADO 组件,需要单独安装。
勾完引用之后,VBA 里就可以用 ADO 连接 SQL Server 了。一个典型的查询过程是:创建 Connection 对象,用连接字符串打开数据库,执行 SELECT 语句把数据取到 Recordset,再把 Recordset 逐行写到“参数日报”Sheet 的指定区域。连接字符串的格式和 Intouch 里类似,但 VBA 用的是 ADO 的 Provider:
Dim conn As New ADODB.Connection Dim rs As New ADODB.Recordset conn.ConnectionString = "Provider=SQLOLEDB;Data Source=ZHWSC02;Initial Catalog=BZ_BB;User ID=sa;Password=single;" conn.Open rs.Open "SELECT * FROM TDays WHERE 日期 >= '" & Range("B2").Value & "'", conn这里 Range("B2") 是控制面板上用户选的起始日期。SQL 语句里拼接字符串要注意日期格式,SQL Server 默认认 yyyy-MM-dd,如果 Excel 单元格是 yyyy/M/d,直接拼进去可能查不到数据。稳妥的做法是在 VBA 里用 Format 函数统一转成 yyyy-MM-dd 再拼。
3.3 报表数据刷新的触发方式与性能边界
报表刷新有两种触发方式:手动按钮和定时刷新。手动按钮就是在控制面板上放一个 Shape,右键指定宏,用户点一下查一次。定时刷新用 Application.OnTime 方法,比如每 5 分钟自动查一次。但定时刷新要小心,如果查询数据量大、SQL 响应慢,上一次还没查完下一次又触发了,Excel 会卡死。我一般建议手动刷新为主,定时刷新间隔不低于 10 分钟,并且加一个状态标志位防止重入。
数据量方面,Excel 单 Sheet 能撑住的行数上限是 104 万行左右,但实际报表没人会拉这么多。日报表一天 24 条,月报表 720 条,年报表 8760 条,对 Excel 来说毫无压力。真正影响性能的是查询本身——如果 SQL 表没建索引,日期范围查询会全表扫描,几万条数据就能让 Excel 转圈半分钟。所以建表的时候在日期列上建个非聚集索引,查询速度会快一个数量级。
3.4 报表模板的复用与参数化设计
一套好的报表模板不应该每次新建都从头画。我的做法是把控制面板上的查询条件做成参数区:起始日期、结束日期、报表类型(日报/月报)三个单元格,VBA 根据这三个参数动态拼 SQL。报表类型决定 GROUP BY 的粒度——日报按天分组,月报按月分组。这样一套模板能覆盖多种报表需求,不用维护多个文件。
参数区的单元格最好加数据验证,日期列限制只能输入日期格式,避免用户填了文本导致 SQL 拼接出错。另外,控制面板上可以放一个“导出”按钮,把查询结果另存为新的 xlsx 文件,方便发给不装数据库客户端的同事。
4. SQL Server 数据库恢复:mdf/ldf 文件附加与常见报错
4.1 数据库文件构成与备份目录约定
SQL Server 的数据库物理文件有两个:一个是数据文件 .mdf,一个是日志文件 .ldf。文档里数据文件叫 YADC_BB.mdf,日志文件叫 YADC_BB_log.ldf,存放在 E:\DataBase 下。备份的时候这两个文件必须一起拷,只拷 mdf 不拷 ldf,附加时会报“日志文件丢失”或者“无法重建日志”。如果 ldf 真的丢了,也不是完全没救,可以用ATTACH_FORCE_REBUILD_LOG方式强制重建,但可能丢事务,生产环境慎用。
恢复的流程是:把 DataBase 目录整个拷到目标服务器的 E:\ 下,然后打开 SSMS,在“数据库”节点上右键 → 附加,在弹出的窗口里点“添加”,定位到 E:\DataBase\YADC_BB.mdf,确定后 SSMS 会自动识别同目录下的 ldf 文件。如果 ldf 不在同目录或者名字对不上,附加会失败,这时候需要手动指定日志文件路径。
4.2 附加失败的三种典型场景与排查
第一种:权限不足。报错“操作系统错误 5(拒绝访问)”。原因是 SQL Server 服务账号没有 E:\DataBase 目录的读取权限。解决办法是给 SQL Server 服务账号(通常是 MSSQL$实例名或者 Network Service)授予该目录的读权限,或者把文件放到 SQL Server 默认的数据目录下再附加。
第二种:文件被占用。报错“无法打开物理文件,操作系统错误 32(另一个程序正在使用此文件)”。这通常是因为源服务器上数据库还在运行,mdf 文件被锁着。拷贝之前先在源服务器上把数据库脱机或者停掉 SQL Server 服务,再拷文件。
第三种:版本不兼容。报错“数据库版本 706 无法打开,此服务器支持版本 655 及更低版本”。这是高版本 SQL Server 的备份文件拿到低版本上附加,比如 SQL Server 2012 的库拿到 2008 R2 上附加。这种情况没有直接解决办法,只能在同版本或更高版本上附加,然后用导出导入的方式迁移数据。
4.3 附加完成后的验证与连接测试
附加成功后,数据库会出现在 SSMS 的对象资源管理器里。别急着收工,先做两件事:一是执行一条SELECT COUNT(*) FROM TDays,确认表和数据都在;二是在 Intouch 里把连接字符串的 Initial Catalog 改成新附加的库名,跑一次写入脚本,看数据能不能正常插进去。这两步都过了,才算恢复完成。
如果附加后表不见了,大概率是附加到了错误的 mdf 文件,或者原库里有多个数据文件但只拷了一个。SQL Server 的数据库可以包含多个 .ndf 次要数据文件,备份时必须全部拷贝,漏一个附加出来的库就是残缺的。
5. 几个让我熬夜排查的坑:从连接字符串到 VBA 引用
5.1 连接字符串里的分号与密码特殊字符
现象:SQLConnect 返回错误,提示“初始化字符串的格式不符合规范”。原因:密码里带了分号,连接字符串按分号分段,密码被截断,后面的参数全部错位。解决:密码里避免用分号,或者用花括号把密码包起来,比如Password={sin;gle}。但 Intouch 的 SQLConnect 对花括号支持不一定好,最稳妥的办法是改密码,别用特殊字符。
5.2 绑定列表变量名大小写不一致
现象:SQLInsert 执行后数据库里多了一行,但所有列都是 NULL。原因:Intouch 标记名是 Temp1,SQL 列名是 temp1,SQL Server 默认不区分大小写,但 Intouch 的绑定列表匹配是区分大小写的,它找不到对应列就写空值。解决:建表时列名和 Intouch 标记名保持完全一致的大小写,别偷懒。
5.3 Excel 加载项被禁用导致 VBA 宏跑不起来
现象:打开报表模板,点刷新按钮没反应,或者提示“宏已被禁用”。原因:Excel 的安全设置把宏禁用了,或者文件来自网络被标记为“受信任位置”之外。解决:文件 → 选项 → 信任中心 → 信任中心设置 → 宏设置,选“启用所有宏”,同时把报表模板所在目录加到“受信任位置”。如果文件是从邮件或聊天工具下载的,右键属性里可能有个“解除锁定”的勾选框,勾上再打开。
5.4 SQL Server 2012 密码到期导致连接突然中断
现象:系统跑了几个月一直正常,某天突然写不进数据,SQLConnect 报“登录失败”。原因:sa 账号的密码设置了过期策略,到期后账号被锁定。解决:在 SSMS 里把 sa 的“强制实施密码过期策略”取消勾选,或者定期改密码。生产环境建议用不过期的专用账号,别用 sa。
5.5 条件脚本触发频率过高导致数据重复
现象:数据库里同一分钟有几十条记录,报表数据翻倍。原因:条件脚本写成了$Second>=3而不是$Second==3,秒数从 3 到 59 每秒都触发一次。解决:条件必须用==精确匹配,配合 WSQLS 标志位做二次防护。改完脚本后,把数据库里重复的数据清掉,不然报表统计全是错的。
6. 进阶:把报表查询做成参数化存储过程,顺带解决 Excel 日期格式玄学
前面 VBA 里直接拼 SQL 字符串,简单场景够用,但遇到日期格式和 SQL 注入就头疼。我的习惯是把查询逻辑下沉到 SQL Server 的存储过程里,VBA 只负责传参数和接收结果。这样做的好处是:日期格式在存储过程里统一处理,VBA 不用管;查询逻辑改的时候只改数据库,不用重新分发 Excel 模板。
先建一个存储过程:
CREATE PROCEDURE GetReportData @StartDate DATE, @EndDate DATE, @ReportType NVARCHAR(10) AS BEGIN IF @ReportType = 'Daily' SELECT CONVERT(DATE, 日期) AS 日期, AVG(Temp1) AS 平均温度, MAX(Temp1) AS 最高温度 FROM TDays WHERE 日期 >= @StartDate AND 日期 <= @EndDate GROUP BY CONVERT(DATE, 日期) ORDER BY 日期; ELSE IF @ReportType = 'Monthly' SELECT YEAR(日期) AS 年, MONTH(日期) AS 月, AVG(Temp1) AS 平均温度 FROM TDays WHERE 日期 >= @StartDate AND 日期 <= @EndDate GROUP BY YEAR(日期), MONTH(日期) ORDER BY 年, 月; END;这个存储过程接收三个参数:起始日期、结束日期、报表类型。日报按天分组算平均和最高温度,月报按月分组算平均温度。VBA 里调用的时候用 ADO 的 Command 对象:
Dim cmd As New ADODB.Command cmd.ActiveConnection = conn cmd.CommandType = adCmdStoredProc cmd.CommandText = "GetReportData" cmd.Parameters.Append cmd.CreateParameter("@StartDate", adDate, adParamInput, , Range("B2").Value) cmd.Parameters.Append cmd.CreateParameter("@EndDate", adDate, adParamInput, , Range("B3").Value) cmd.Parameters.Append cmd.CreateParameter("@ReportType", adVarWChar, adParamInput, 10, Range("B4").Value) Set rs = cmd.Execute用参数化调用之后,日期格式的问题就消失了——ADO 会把 Excel 的日期值转成 SQL Server 认识的 DATE 类型,不用再手动 Format。而且存储过程里可以加索引提示、可以分页、可以做更复杂的聚合,比在 VBA 里拼字符串灵活得多。
还有一个实际场景:报表需要显示“本班次”的数据,班次划分是 8 点到 16 点、16 点到 24 点、0 点到 8 点。这种逻辑放在存储过程里就是一个 CASE WHEN,放在 VBA 里就得写一堆 If-Else。所以只要报表逻辑稍微复杂一点,我都建议往存储过程迁移。
最后说一个 Excel 日期格式的玄学问题。有时候存储过程返回的日期在 Excel 里显示成数字,比如 44562,这是因为单元格格式没设成日期。解决办法是在 VBA 写入数据后,把日期列的 NumberFormat 设成 "yyyy-mm-dd"。还有一种情况是 Excel 把日期识别成了文本,左对齐而不是右对齐,排序和筛选都会乱。这时候用CDate函数强制转换一下再写入。
从那以后我每次部署报表系统,都强制走一遍“存储过程 + 参数化调用 + 日期格式校验”的流程,再也没被日期格式坑过。希望帮到你。
本文还有配套的精品资源,点击获取