
简介面向SCADA/HMI项目实施人员与技术维护者这份资料围绕WonderWare Intouch 2014 R2IDE平台与SQL Server 2012的集成应用展开重点解决实时数据写入关系数据库、以及通过定制Excel报表系统读取和展示历史数据的问题。压缩包内共1个doc文档大小2.48MB以图文步骤形式完整呈现从数据库建库、登录权限调整到Intouch标记名字典、SQL访问管理器绑定列表、SQLConnect()/SQLInsert()脚本编写再到Excel模板与VBA配置、SQL数据库备份恢复的全流程操作。已有530人学习适合需要快速搭建SCADA数据落库与报表展示方案的工程师参考。文档中不少细节如系统秒条件触发、计算机名判断、防重复写入标记等能帮助读者避开常见配置误区尤其适合现场实施时对照操练。1. Intouch 与 SQL Server 的报表链路这份文档到底解决什么问题做 SCADA 项目逃不掉的一件事Intouch 趋势上明明有数据月底做日报却要让人对着历史曲线一格格抄。这份操作手册把整条链路给理顺了——在 WonderWare Intouch 2014 R2 的 IDE 里通过标记字典和 SQL 访问管理器把实时数据写进 SQL Server 2012再用 Excel 报表从库里拉数生成日报连数据库 mdf/ldf 的备份恢复都一起收了。它适合两类人一类是刚接手 SCADA 项目、没写过数据库链路的组态工程师另一类是知道 SQLConnect 能连库但每次都被绑定列表和时间格式坑一回的现场老手。文档里给出的连接串、条件脚本和 VBA 代码都能直接照抄但有几处笔误和容易绕弯的地方下面按操作顺序拆开讲。2. SQL Server 侧准备身份验证、登录名与表结构三件套2.1 先改混合身份验证不然后面 SQLConnect 永远连不上文档的第一步是进 SQL Server Management Studio更改数据库访问的登录方式。这里有个细节容易被步子迈得快的同学跳过Intouch 那台机器是拿 SQL 账号去连数据库的不是 Windows 集成登录所以服务器实例属性里必须把身份验证改成「SQL Server 和 Windows 身份验证模式」。不改的话后面 SQLConnect 哪怕连接串写得再对也会一直报无法登录。操作位置要说清楚在 SSMS 左侧对象资源管理器里右键服务器实例不是右键数据库选属性左侧切到「安全性」右侧选「SQL Server 和 Windows 身份验证模式」点确定后重启 SQL Server 服务。原文档里写的是「更改数据库的身份验证方式」实际上是实例级别不是库级别别在数据库属性里找半天。改完之后顺手确认 sa 账号或者专门建的项目账号是启用状态。SQL Server 2012 默认安装时 sa 是禁用的即使你选了混合模式sa 也登不进去。这个点我在现场陪跑过不止一次都是先怀疑连接串最后发现 sa 是灰的。文档里说「如已经有相关的权限则跳过此步骤」注意是跳过了验证不是跳过启用账号。2.2 新建登录名密码、服务器角色一次配齐在「安全性 → 登录名」上右键新建登录名常规页填登录名、选 SQL Server 身份验证、设密码然后到「服务器角色」页把 sysadmin 勾上。文档里写的是「如已经有了合适的用户名则在登录名下点击相关用户名进入属性窗口修改密码及服务器角色」意思是复用现有账号也行但角色的覆盖范围必须包含目标库的读写权限。配置项推荐值说明身份验证SQL Server 身份验证Intouch 脚本走的是账号密码方式不能依赖 Windows 集成服务器角色sysadmin开发阶段最省事生产环境建议收敛为 db_owner默认数据库BZ_BB防止登录后落到 master报表脚本里易混淆密码强密码连接串和 VBA 都是明文引用别设太弱sysadmin 在正式库上权限偏大但组态项目普遍图省事。我一般会先在开发环境用 sysadmin 把链路整个跑通稳定了再收敛到 db_owner不然排错时多一层权限报错很难判断到底是脚本问题还是账号问题。2.3 建库建表列名先按标记字典规划好登录名配好后新建数据库 BZ_BB然后在库里建一张用于日报的表原文档里的表名是 TDays。表结构不用花哨但列名和类型必须跟下一步 Intouch 标记字典里的标记完全对齐否则绑定列表里选不到对应列SQLInsert 执行了也是空操作。典型结构按「时间、节点、参数、值」四列规划CREATE TABLE [dbo].[TDays] ( [记录时间] DATETIME NOT NULL, [节点名] NVARCHAR(50) NULL, [参数名] NVARCHAR(50) NULL, [参数值] FLOAT NULL, [写入标记] INT NULL DEFAULT 0 );这段 SQL 的要点记录时间用 DATETIME别拿 VARCHAR 存日期后面 Excel 拉数排序和 VBA 拼查询条件全靠它参数值用 FLOAT对应 Intouch 里内存实型节点名用 NVARCHAR兼容中文。列名别搞中英混合绑定列表里 Intouch 变量名和 SQL 列名靠字符串匹配两边必须一个字符不差。表建好后先手动插两行测试数据用刚才的登录名确认能查能写再回 Intouch 做绑定。很多项目到最后一步才发现账号只读等脚本全写完再回头查就慢了。3. Intouch 标记与绑定列表数据落库前必须先对齐的变量清单3.1 标记字典里这四个内存变量一个都不能少打开 Intouch 的标记名字典在左侧视图里找到标记名字典窗口右键「新建」。文档要求建四个内存变量Connid1、GetDateTimeS、NodeName、WSQLS。这四个角色完全不一样覆盖了连接句柄、时间基准、节点名、写入互锁四条信息。标记名类型用途Connid1内存整型保存 SQLConnect 返回的连接编号初始建议设为 -1GetDateTimeS内存消息存联接时的时间用于报表时间基准NodeName内存消息存本地计算机节点名用于限定哪台站写库WSQLS内存离散写入互锁标记防止同一周期重复插入关键点是全部用内存型不要用 I/O 型。这些标记不接外部设备纯粹是脚本内部逻辑用 I/O 型反而会被 IO 扫描拖慢。Connid1 初始值设成 -1 是个好习惯SQLConnect 失败返回的就是 -1初始成 0 会让人误以为连上了。WSQLS 在文档里的作用很特殊它是个互锁标志为真表示这一小时内已经写过一次库为假才允许再次写入。没有它条件脚本每 5 秒跑一次一个小时内会插进三百多行重复数据。3.2 绑定列表表名、绑定名、列类型三对齐绑定列表在 IDE 左下角工具视图里的 SQL 访问管理器中右键「绑定列表」新建一个名字然后在里面加入要写库的 Intouch 变量。文档里新建的绑定列表名叫 TDays和数据库表名撞车了。这里有个非常容易搞混的点绑定列表的名字是供 SQLInsert 引用的和数据库里的表名没有必然关系两者重名虽然能跑但排错时看不出到底是表还是绑定出了问题。打开绑定列表窗口后左边是数据库连接和表右边是 Intouch 变量操作时逐列把 Intouch 变量拖到对应 SQL 列上。类型不匹配是最隐蔽的坑Intouch 实型对应 SQL 的 FLOAT整型对应 INT消息对应 NVARCHAR离散对应 BIT一旦错配SQLInsert 执行时不报错但插进去的值是空的。提示绑定列表起一个有区分度的名字比如 Bind_TDays。这样 SQLInsert 写反参数时报错信息能直接看出是表名错了还是绑定名错了。文档强调变量名和类型需与数据库表单完全对应实际操作中值得加一步绑定完先点测试按钮执行一次看返回行数是不是 1。这一步能提前暴露九成以上对应关系问题不用等脚本跑起来才发现库里全是 NULL。4. SQLConnect 与 SQLInsert 脚本连接串参数和写入时机怎么定4.1 系统时间格式和连接串的五个参数文档第零步专门写了「在操作系统的日期和时间中更改日期和时间格式」这一步看着像凑数其实是全流程里最早翻车的地方。Intouch 的 $Second、$Minute 这些系统标记读取的是 Windows 系统时间字符串类的时间和日期格式受区域设置影响。如果系统长日期格式带了「星期」字样写到数据库或 Excel 做日期比对时会解析出错。我接手过的项目里有两次报表数据全是 NULL最后查出来是系统时间格式里带「上午/下午」。连接串的格式文档给得很完整五个参数缺一不可// Intouch 应用脚本里的 SQLConnect第一个参数是连接标记第二个是连接串 SQLConnect(Connid1, providersqloledb;Data SourceZHWSC02;Initial CatalogBZ_BB;UserIDsa;Passwordsingle);代码逻辑说明第一参数 Connid1 是内存整型标记SQLConnect 成功后会把连接编号回填给它之后 SQLInsert 全靠这个编号找到对应连接第二参数是连接串五段之间用分号分隔每段格式是「键值」。Data Source 写的是数据库服务器所在机器名Initial Catalog 是数据库名UserID 和 Password 对应 SSMS 里建的登录名和密码。两点经验要补充一是 Data Source 也可以写 IP 或「主机名\实例名」但前提是 SQL Server 实例开了 TCP/IP 协议。SQL Server 2012 默认配置下命名实例坑很多组态项目里能不装命名实例就别装。二是连接串里的密码是明文的写进脚本后 Intouch 会把脚本存成应用文件注意操作站的文件访问权限。4.2 应用程序脚本里的连接生命周期连接要放在「应用程序脚本」里管理在运行时脚本里先 SQLConnect在关闭时脚本里 SQLDisconnect。文档里特别强调退出时关闭连接这是为了避免程序异常退出后 SQL Server 那边留着死连接时间长了把连接池资源耗尽。// 运行时脚本进系统就建连 SQLConnect(Connid1, providersqloledb;Data SourceZHWSC02;Initial CatalogBZ_BB;UserIDsa;Passwordsingle); // 关闭时脚本退出 Intouch 前断开避免死连接残留 IF Connid1 -1 THEN SQLDisconnect(Connid1); ENDIF;逻辑说明SQLDisconnect 前要判断 Connid1 是否有效。如果连接从来没建立成功Connid1 会是初始值 -1直接调断开反而会报奇怪的错误。这个判断是我在一次现场里加上的——那台操作站网络断过进系统时 SQLConnect 失败退出时 SQLDisconnect 把 Intouch 卡了十几秒。4.3 定时写库脚本5 秒轮询和防重互锁文档给出的写库脚本挂在「脚本」视图下的「条件」里条件 $Second5意思是每分钟第 5 秒执行一次。配合 $Minute58 和 WSQLS 互锁就能做到每小时最后一分钟只写一次数据。文档里还提到一个 $Second3 的条件脚本放在「数据获取」部分这类条件脚本通常用来做时间基准采集把当前时间写入 GetDateTimeS给后续写库提供时间戳。// 条件$Second 5类型为真时执行 GetNodeName(NodeName, 131); // 取本机 Intouch 节点名存到 NodeName IF NodeName OP_01 THEN // 只让操作员站 OP_01 写库 IF $Minute 58 THEN // 58、59 分进入统计窗口 IF WSQLS 0 THEN // 本小时还没写过才执行插入 SQLInsert(Connid1, TDays, TDays); // 按绑定列表 TDays 插一行 WSQLS 1; // 置位锁住本小时 ENDIF; ELSE WSQLS 0; // 没到 58 分时复位让下小时能再写 ENDIF; ENDIF;逐行看GetNodeName 第一个参数是接收字符串的标记第二个参数是缓冲区字符数文档里的 131 够用写大一点没坏处NodeName 的比较严格区分大小写。这里有个文档自带的坑脚本里写的是 OP_OP1解释文字里又说是 OP_01明显是复制串位。建议先在标记字典里加个临时脚本用 MessageBox 把 NodeName 实际取到的值打出来再写死到比较语句里。SQLInsert 的三个参数最容易搞混第一个是连接号 Connid1第二个是数据库表名 TDays第三个是绑定列表名 TDays。文档把后两个都叫 TDays实际项目里建议区分开否则 SQL 访问管理器里报「找不到绑定」时你分不清是表没建还是绑定没建。WSQLS 的复位位置严格说文档写得有歧义如果 WSQLS0 放在整个 IF 块的外面无条件执行那每 5 秒它都会被复位互锁形同虚设一小时内能插出几百行重复数据。正确做法是把复位放进 ELSE 分支里也就是上面代码的写法——非统计窗口期才允许下一次写入。注意条件脚本执行频率越高越要重视互锁标记的作用域。WSQLS 的置位和复位必须出现在同一轮判断逻辑里中间不能夹 SQLDisconnect 之类的操作。5. Excel 报表系统VBA 引用、数据行到单元格的搬运动作5.1 报表模板的两个工作表和 VBA 环境准备Excel 报表模板分为「控制面板」和「参数日报」两个工作表。控制面板页放查询条件比如起始日期、站点和刷新按钮参数日报页放数据明细按固定格式排好列。文档里让你在参数日报页签上右键「查看代码」这里进入的是 VBA 编辑器整个报表的核心逻辑都在这里面。进入 VBA 编辑器后第一件事不是写代码是检查「工具 → 引用」里的库引用。文档说「至少钩选以下三项」按这条链路实际需要这三项缺一不可引用库作用Microsoft ActiveX Data Objects 2.8 LibraryADODB 连接对象没有它 CreateObject 也建不出数据库连接Microsoft Excel Object Library操作工作表和单元格的基础对象库Microsoft Office Object Library提供通用的 Office 对话框等对象经验是引用窗口里同名库可能有好几个版本比如 ADODB 从 2.5 到 6.1 都有选高版本就行。没勾引用的状态下直接运行代码报的错误是「用户定义类型未定义」这个报错特别容易让人误判成数据库问题。先检查引用再查代码能省半小时。5.2 用 ADODB 从 SQL Server 2012 拉数据到日报页报表的思路是打开报表时自动刷新从 BZ_BB 的 TDays 表里按日期条件查出记录逐行写进「参数日报」页。连接串和 Intouch 那边的 SQLConnect 几乎一模一样只是 Data Source 要写成报表电脑能访问到的地址。Sub RefreshDailyReport() Dim conn As Object Dim rs As Object Dim sql As String Dim rowCount As Long Dim queryDate As String 查询日期取控制面板页 B3 单元格格式必须 yyyy-mm-dd queryDate Format(Sheets(控制面板).Range(B3).Value, yyyy-mm-dd) 建 ADODB 连接连接串与 Intouch SQLConnect 同一套 Set conn CreateObject(ADODB.Connection) conn.ConnectionString ProviderSQLOLEDB;Data SourceZHWSC02;Initial CatalogBZ_BB;User IDsa;Passwordsingle; conn.Open 按日期窗口查询左闭右开避免边界查重 sql SELECT 记录时间, 节点名, 参数名, 参数值 _ FROM TDays WHERE 记录时间 queryDate 00:00:00 _ AND 记录时间 DateAdd(d, 1, CDate(queryDate)) 00:00:00 ORDER BY 记录时间 Set rs CreateObject(ADODB.Recordset) rs.Open sql, conn, 1, 1 adOpenKeyset 游标adLockReadOnly 只读 先清旧数据再写新数据避免报表越积越多 Sheets(参数日报).Range(A5:Z200).ClearContents rowCount 5 Do Until rs.EOF Sheets(参数日报).Range(A rowCount).Value rs.Fields(记录时间).Value Sheets(参数日报).Range(B rowCount).Value rs.Fields(节点名).Value Sheets(参数日报).Range(C rowCount).Value rs.Fields(参数名).Value Sheets(参数日报).Range(D rowCount).Value rs.Fields(参数值).Value rowCount rowCount 1 rs.MoveNext Loop rs.Close conn.Close Set rs Nothing Set conn Nothing End Sub代码逻辑分四段取查询日期、建连接、查记录、写单元格。rs.Open 的第三、四个参数 1, 1 对应 adOpenKeyset 和 adLockReadOnly报表只读场景够用别开 adLockOptimistic免得长期锁库。日期过滤写成左闭右开区间查一整天数据不会把第二天的零点数据带进来。要把这段代码变成自动刷新就在 ThisWorkbook 的 Workbook_Open 事件里调一次 RefreshDailyReportPrivate Sub Workbook_Open() RefreshDailyReport End Sub提示别在 VBA 编辑器里手动 F5 跑完就算完事。现场操作员不会开 VBA 编辑器报表打开必须是好的。控制面板页的日期单元格格式要预先设成「yyyy-mm-dd」否则 Format 出来带斜杠SQL Server 能解析但 Excel 显示会很难看。这一章的边界也说明一下这套方案是「数据库到 Excel」的定时拉取方向别搞反。有同学想反过来用 Excel 写回数据库或者用外部工具做实时曲线那不在这份文档范围内别拿 VBA 硬扛实时刷新。原文档标题里把 Excel 拼成 EXCLE是复制文档时常见的手滑内容不影响。6. 数据库备份恢复与避坑清单mdf/ldf 附加和五类现场故障6.1 用 mdf/ldf 整套恢复数据库文档里的恢复路径很直白把 E:\DataBase 下的 YADC_BB.mdf 和 YADC_BB_log.ldf 整个拷贝到目标机器然后在 SSMS 里右键「数据库」选「附加」添加 YADC_BB.mdf 即可。实际操作要点是 mdf 和 ldf 必须放同一个目录附加时只要指着 mdfSQL Server 会自动找同目录的 ldf。容易忽略的是文件权限mdf 从别的机器拷过来后默认可能继承原机器的 ACLSQL Server 服务账号读不了附加时报「无法打开物理文件」。解决方法是右键文件属性给 SQL Server 服务账号加读取权限。另一个常见问题是 ldf 丢了或者和 mdf 不同步这时候可以只附加 mdfSQL Server 会弹提示让你重建日志选「是」就行数据不会丢。版本匹配也要提一句SQL Server 的库文件高版本实例能附加低版本库反过来不行。2012 的 mdf 往 2008 实例上附加报错是「版本 706 不支持」这个数字就是数据库文件版本号706 对应 2012。想往低版本走只能导出脚本加数据别指望直接附加。6.2 五类现场故障现象、原因、解决这五条都是这条链路里真实踩过的按出现频率排1. SQLConnect 一直返回失败日志里没有明确原因。现象Intouch 运行后 Connid1 为 -1数据库里没有任何新行。 原因绝大多数是 SQL Server 没开混合身份验证或 sa 处于禁用状态少数是连接串的 Data Source 写错。 解决先按第 2 章改实例属性确认登录名启用再用 SSMS 用同一个账号手动登录一次验证账号本身可用。2. 数据没写进库但 Intouch 不报错。现象SQLInsert 执行了数据表一查是空的。 原因绑定列表没建全或者 Intouch 变量类型和 SQL 列类型不匹配SQLInsert 静默丢弃。 解决回 SQL 访问管理器检查绑定列表逐列核对类型先在绑定列表窗口手动「执行」一次观察返回记录数。3. 同一小时插入了上百行重复数据。现象TDays 表里同一小时的记录有几百条。 原因WSQLS 复位位置不对无条件放在 IF 外每次 5 秒轮询都把它清零互锁失效。 解决按第 4.3 节的写法把 WSQLS0 移进 ELSE 分支并确认判断顺序是先查 WSQLS 再执行 SQLInsert。4. NodeName 比较永远不成立写库脚本整个不执行。现象$Second5 触发了但库里一条都没有连测试插入都不进。 原因GetNodeName 取到的节点名和你写死的不一致或者文档里那句 OP_OP1 是复制笔误实际节点名是 OP_01。 解决临时在脚本里加 MessageBox 把 NodeName 值打出来和脚本里的字符串逐字符比对注意 Intouch 节点名区分大小写。5. 无法打开 Intouch 应用程序提示请参阅记录器以获取详细信息。现象改完脚本后重新启动 Intouch应用直接起不来只留一句日志提示。 原因脚本里有语法错误或引用了标记字典里不存在的标记Intouch 启动时预编译脚本失败。 解决打开 Intouch 记录器Logger看具体报错行定位到脚本位置排查期间先把可疑脚本整个注释掉确认应用能启动后再逐段放开避免脚本问题和启动问题搅在一起。另外时间格式那一步看着无害但对 Intouch、SQL Server、Excel 三端都有影响。Windows 长日期格式一旦带上「星期」VBA 里 Format 出来的日期字符串就会混入中文SQL Server 解析可能不报错但结果为空。我现在的习惯是装操作站系统时直接把区域格式里的短日期设成 yyyy-MM-dd长日期从不动它。原文档里所有关键连接串、脚本和报表结构都带图保存着对照第 2 到第 5 章的序号走一遍基本能一次跑通。从那以后我每次动这个报表系统之前都强制先看一眼 E:\DataBase 里那两个文件的修改时间顺手在 SSMS 里手动备份一次再开始改脚本——多花五分钟已经替我挡掉三次把库改崩的返工。希望帮到你。本文还有配套的精品资源点击获取