简介:这份文档面向使用 WonderWare Intouch 2014 R2 搭建 SCADA 系统的工程技术人员与初学者,聚焦 HMI 与 SQL Server 2012 数据库的集成,以及用 Excel 制作报表系统的完整流程。内容涵盖数据库新建与身份验证、登录名权限配置、Intouch 标记名字典中连接状态与时间变量的定义、条件脚本编写、SQL 访问管理器绑定列表配置,以及 SQLConnect、SQLInsert、SQLDisconnect 等函数的参数说明与调用示例,并延伸到 Excel 报表模板搭建、VBA 引用设置与数据库附加恢复操作,对排查数据写入时序、数据类型匹配等问题有直接参考价值。资源包为单个 doc 文件,大小约 2.48MB,配有大量界面截图辅助理解。目前已有 533 人学习浏览,适合希望打通 Intouch 与数据库数据链路、构建实时报表的中级自动化工程师参考。
1. 凌晨两点的空报表,问题出在写库脚本的复位顺序上
值班的人打电话过来,说日报里昨天最后两个小时的数据是空的。登录 HMI 站翻脚本,写库那段每 5 秒跑一次,日志显示最后一次成功插入之后就再没动静。查下来是写入标记 WSQLS 置位后没有回到零,后面每一次执行都被自己的判据挡在门外。脚本能跑,但你不知道它什么时候会停——这是 Intouch 与关系库对接时最典型的一类事故。
Intouch 2014R2 负责画面和采集,SQL Server 2012 负责把数据写成行,Excel 用 VBA 把行拉成一张能打印的日报,这套组合在厂站班报、日报、批次追溯里用得很多。这份资源把三段操作串成了一条完整链路:SQL 侧建库建表和登录名,Intouch 侧建标记、配绑定列表、写 SQLConnect 和 SQLInsert 脚本,Excel 侧做模板和取数。适合正在给 HMI 补报表功能的一线工程师,也适合接手别人做了一半、脚本注释全是空白的现场。
2. 环境先行:登录模式、库表结构和日期格式三件事必须落地
在 Intouch 里点开脚本之前,先把 SQL Server 和操作系统这三件事处理掉。它们不写在 Intouch 的配置界面里,但每一样没做对,后面的连接都会以“返回 -1”这种极简的方式失败,让人对着屏幕怀疑人生。我一般把这一章叫“开工前的三次检查”,顺序是身份验证模式、库表结构、时间格式。
2.1 混合身份验证模式:不开这个,SQLConnect 一定连不上
SQL Server 2012 安装时默认只启用 Windows 身份验证。Intouch 的SQLConnect函数走的是连接字符串里的User ID和Password,也就是 SQL Server 身份验证,所以这一步必须先改。进 SQL Server Management Studio,在对象资源管理器里右键服务器节点选“属性”,左侧选“安全性”,右侧选“SQL Server 和 Windows 身份验证模式”,确定。
改完之后有个动作容易漏:必须重启 SQL Server 服务才生效。这一步在不少现场文档里被省略,结果配置页面上明明已经改了,脚本还是连不上。我的习惯是改完直接打开“服务”控制台,把 SQL Server 的实例服务重启一次,再去验证。
接下来建登录名。展开“安全性 → 登录名”,右键新建,填用户名、选 SQL Server 身份验证、设密码,服务器角色页里按最小权限给:只做数据写入的账户给db_datareader和db_datawriter就够,不要为了省事直接勾 sysadmin。现场赶工期时经常图方便给 sa,等到交付审计被打回来再改,连接字符串散落在几十个脚本里,返工量更大。
用脚本建账户更稳,可复现,换台机器也能照抄:
-- 建一个只对目标库有读写权限的账户,供 Intouch 脚本使用 USE master; GO CREATE LOGIN hmi_writer WITH PASSWORD = 'Hmi@2014', CHECK_POLICY = OFF; GO USE SIMU_BB; -- 目标库,先建好库再执行这一段 GO CREATE USER hmi_writer FOR LOGIN hmi_writer; GO ALTER ROLE db_datareader ADD MEMBER hmi_writer; ALTER ROLE db_datawriter ADD MEMBER hmi_writer; GOCHECK_POLICY = OFF是为了绕过 Windows 密码复杂度策略,现场很多 HMI 站点的账户密码是固定规律生成的,开着策略反而建不出来。代价是密码强度不受控,所以这个账户只给内网、只给本地实例。上面这段执行完,最好在 SSMS 里用这个账户手动登录一次,在建好的表上执行一条INSERT,确认权限链路是通的,再去改 Intouch。
2.2 建库建表:列名和数据类型就是后面的绑定契约
Intouch 的绑定列表不是“自动映射”,它靠列名和数据类型硬对。库表设计阶段偷的懒,后面都会变成写入失败。表结构建好之后再去改列名或改类型,绑定列表要重建,脚本里的表单名也要跟着改,牵一发动全身。
按项目里的日报场景,一张记录表通常长这样:
CREATE TABLE dbo.TDays ( RecTime datetime NOT NULL, -- 记录时间,对应 Intouch 消息型标记 LineName nvarchar(32) NOT NULL, -- 产线/主机名,对应消息型标记 BatchNo nvarchar(32) NULL, -- 批次号,对应消息型标记 Pv01 float NULL, -- 工艺量,对应实型标记 RunFlag bit NULL -- 运行状态,对应离散型标记 );类型对应关系是有说法的,照下面这张表对,基本不会出类型溢出的问题:
| Intouch 标记类型 | 建议的 SQL 列类型 | 说明 |
|---|---|---|
| 内存离散 / I/O 离散 | bit | 只存 0/1,别用int再在报表里转换 |
| 内存整型 / I/O 整型 | int | 数值超 2^31 的计数要用bigint |
| 内存实型 / I/O 实型 | float | 用decimal(18,4)会让小数位被静默截断 |
| 内存消息 / I/O 消息 | nvarchar(64) | 长度按最长的消息估,宁长勿短 |
| 时间类消息 | datetime或nvarchar(19) | 用datetime便于报表按区间筛选 |
表建好之后,先在 SSMS 里手写一条INSERT塞一行测试数据进去,确认列序和类型都没问题。这一步能挡掉后面 80% 的“写不进去但又不报错”的疑惑。
2.3 操作系统日期时间格式和运行账户权限
原文档里有一句很短的话——“在操作系统的日期和时间中更改日期和时间格式”。很多人直接跳过,然后报表里的日期整列错一天。Intouch 脚本里拼时间字符串、Excel VBA 里Format日期、SQL Server 解析字符串,三处对短日期格式的理解必须一致。Windows 默认的yyyy/M/d和M/d/yyyy在不同区域设置下会互相打架,2024/3/4和03/04/2024到底谁是三月谁是四月,全靠上下文猜。
统一成yyyy-MM-dd,控制面板 → 区域 → 其他设置 → 日期里改短日期,时间改成HH:mm:ss。改完重启一次 Intouch 运行环境,让脚本运行时读到的区域设置是新的。
运行账户权限也得看一眼。Intouch 如果是作为服务随开机启动,它继承的是服务账户的权限;如果是以某个登录用户身份运行,脚本写文件、访问本地目录的权限跟着这个用户走。现场出现过脚本能连库、但写 Excel 临时文件被拒的情况,查到最后是运行账户对报表目录没有写权限。这个坑和数据库无关,但症状会伪装成报表取数失败,排起来很费时间。
3. 标记名字典与脚本编排:SQLConnect 连接串和写入判据的时序
环境备齐之后,才轮到 Intouch 侧。这一章的重点不是“把函数抄进去”,而是搞清楚三个中间标记各自的职责、连接字符串每一段在说什么、以及写入判据的执行顺序为什么能决定数据有没有落库。脚本写得对不对,看的是时序,不是语法。
3.1 Connid1、GetDateTimeS、NodeName:三个内存标记的分工
标记名字典里先建三个标记,全部选“内存”型,不要挂 I/O。原因很直接:这些标记只服务于脚本逻辑,和现场设备无关,挂 I/O 型反而会让通讯状态影响脚本执行。
Connid1,内存整型,存SQLConnect返回的连接号。返回负数代表连接失败,这个值后面要拿来做断线判断。GetDateTimeS,内存消息,存脚本拼出来的时间字符串,用于插入或记录日志。NodeName,内存消息,存本机计算机名,用于多 HMI 站共用一张表时区分数据来源。
这三个标记的初值建议在标记名字典里直接写好,尤其是Connid1给 -1,这样脚本第一次跑的时候能明确判断“还没连上”,而不是拿 0 去当合法连接号。类 C 语言里 0 是有效的文件描述符,SQL 连接号在 Intouch 里也不该拿 0 当失败标志,这个习惯能省掉很多调试时间。
GetNodeName(NodeName, 131)里的第二个参数,各版本说明不完全一致,通常和返回名称的类型或缓冲区长度限制有关。现场复制脚本时容易连带把这个数字一起复制走,换版本后行为不对。我的做法是先在一个测试条件脚本里单独打印这个值,确认它能正确取到本机名,再写进正式脚本,别把它当黑匣子直接抄。
3.2 SQLConnect 的五个参数,逐项拆开看
连接串是整段脚本里最容易出错的地方,因为它出错的方式很安静——函数返回 -1,绑定列表里的变量全部读空,画面上什么都不报。
' 应用程序脚本 —— 开始时 SQLConnect( Connid1, "provider=sqloledb;Data Source=HMI_NODE01\SQLEXPRESS;Initial Catalog=SIMU_BB;User ID=hmi_writer;Password=Hmi@2014" );五个段用分号隔开,每段都是键=值:
provider=sqloledb是 OLE DB 提供程序,连 SQL Server 固定写这个,别写成SQLNCLI之类的客户端驱动名,现场机器上装没装对应驱动是不确定的。
Data Source是实例地址。默认实例只写主机名;命名实例必须写成主机名\实例名,反斜杠不能漏,也不能写成冒号。跨网段时这里可以直接写 IP,但要注意 SQL Server 的远程连接和防火墙端口是否放开。
Initial Catalog是库名,大小写一般无所谓,但如果库名里有空格或特殊字符,要用方括号括起来。
User ID和Password是 2.1 里建的 SQL 账户。这里有个血泪经验:密码明文写在脚本里,运维改过一次数据库密码,没人记得同步改 HMI 脚本,结果当天夜班数据全丢,第二天早上才发现。改善办法是把连接串集中放在一个内部标记或 Ini 文件里,脚本只引用,至少改的时候是一处。
3.3 两个条件脚本和一个关闭脚本
原文档用了两个秒级条件脚本:$Second == 3做数据准备,$Second == 5做连接和写入。分开的意义在于给连接留出执行窗口,避免同一秒里既连又写。
' 条件脚本:$Second == 3,条件类型:为真时 GetDateTimeS = $Date + " " + $Time; ' 拼出后续插入用的时间字符串 GetNodeName( NodeName, 131 ); ' 取本机计算机名,存入 NodeName条件脚本的触发频率是每秒一次,$Second == 3意味着每小时只在这一秒命中。这类脚本不要写耗时操作,取时间、取主机名这种微秒级动作最合适。写库、查询这类可能阻塞的动作放到别的秒上。
关闭脚本别漏:
' 应用程序脚本 —— 关闭时 SQLDisconnect( Connid1 );运行环境退出时不断开连接,数据库侧会留下一批挂起的会话,时间长了连接数打满,表现是新站连不上、老站写入变慢。这个函数没有返回值可查,属于典型的“加了不一定有用,不加迟早出事”。
3.4 判据链:计算机名、分钟数、写入标记的置位与复位顺序
写入脚本是整条链路的收口。原文档给的骨架是四层判据套一个SQLInsert,逻辑上没问题,但置位和复位放在同一分支里,会引出一个隐蔽的重复写入问题。
' 条件脚本:$Second == 5,条件类型:为真时 IF Connid1 < 0 THEN ' 连接号无效时补一次连接,避免运行中掉线后永久写不进去 SQLConnect( Connid1, "provider=sqloledb;Data Source=HMI_NODE01\SQLEXPRESS;Initial Catalog=SIMU_BB;User ID=hmi_writer;Password=Hmi@2014" ); ENDIF; IF NodeName == "HMI_NODE01" THEN ' 多站共用一张表时限定写入源 IF $Minute >= 58 THEN ' 只在每小时最后两分钟写 IF WSQLS == 0 THEN ' 本小时尚未写过 SQLInsert( Connid1, "TDays", "TDays" ); WSQLS = 1; ENDIF; ELSE WSQLS = 0; ' 跨出 58 分区间后复位,为下一小时做准备 ENDIF; ENDIF;$Second == 5让脚本每 5 秒执行一次,$Minute >= 58让它在每小时最后两分钟保持可写。复位放在ELSE分支,是为了让WSQLS在整个 58 到 59 分区间里都保持置位,一个小时内只写一次。如果照原样把复位写在置位后面,同一次执行里立刻归零,下一轮 5 秒后判据又重新成立,58 分到 59 分这两分钟内会重复插入 20 多次,日报里就会出现整段重复行。
Connid1 < 0的补连判断是我加上去的。现场网络抖动、数据库重启都会让连接号失效,而Connid1自己不会恢复。没有这段判断,掉一次线就等于这个站从此不再写库,直到有人重启运行环境。
4. 绑定列表与 SQLInsert:列名、类型、表单三层对齐
脚本把连接建起来了,数据能不能进去还取决于绑定列表。这一层是 Intouch 里最像“配置文件”的东西,界面上点几下就完成,但点错一个列名,症状是插入成功但整行为空。这一章把绑定列表的三层对齐讲清楚,再给三种可以交叉验证的方法。
4.1 在 SQL 访问管理器里建绑定列表
左侧视图最下面的工具里找到 SQL 访问管理器,展开后有绑定列表一项。新建一个绑定列表,命名和数据库里的表名保持一致,比如TDays。然后在列表里逐列添加:左边选 Intouch 的标记,右边填数据库的列名,类型按第二章那张表对。
对齐有三层,缺一不可:
第一层是列名。绑定列表里的列名和dbo.TDays的列名逐字符对应,大小写不敏感,但前后空格、下划线写错都会对不上。
第二层是数据类型。Intouch 的整型绑到float列可以,绑到bit列就写不进去;消息型绑到nvarchar(32),实际值超过 32 个字符会被截断,而且不一定报错。做一次长度自检,把消息标记的典型值打出来看看长度。
第三层是两个“TDays”不是同一个东西。SQLInsert的第二个参数是数据库表单名,第三个参数是 Intouch 绑定列表名。两者同名是最常见的做法,也是最容易混淆的地方——名字一样的时候看不出错,一旦有人为了区分把绑定列表改名成TDays_Bind,脚本里还写原来的TDays,就会出现表单找不到的错误。
绑定列表建好后,建议把每个变量在画面上做一行只读显示,实际跑起来的时候肉眼确认值是不是真的有内容。全是空字符串大部分情况是采集侧没通,而不是绑定错了。
4.2 SQLInsert 三个参数的语义
SQLInsert( Connid1, "TDays", "TDays" );第一个参数必须是SQLConnect返回并存下来的连接号。如果前面连接失败返回负数,这一行不会抛异常,只是什么都不写。这是很多人被误导的地方——没有报错不等于写进去了。
第二个参数是数据库里的表名或表单名,第三个参数是绑定列表名。两个都支持方括号,表名带特殊字符时才需要。函数本身一次性把绑定列表里的所有变量按行插入,不需要拼INSERT语句,这既是方便之处,也是限制:一张表一次只能插一行,且列顺序不由你控制,完全依赖绑定列表的定义。
多表写入就建多个绑定列表、调多次SQLInsert,别试图在一张绑定列表里混装两张表的列。现场见过把日报表和历史表的列混在一个绑定列表里的做法,结果是两张表各插一半,类型对不上的列永远是默认值。
4.3 三种验证方式,从快到慢
写完不要只看画面上有没有报警,用三种方式交叉验证,能快速定位是哪一层出的问题。
最快的是在 SSMS 里直接查最近的行:
-- 看最近写入的 20 行,确认时间、主机名、数值都有 SELECT TOP 20 RecTime, LineName, BatchNo, Pv01, RunFlag FROM dbo.TDays ORDER BY RecTime DESC; -- 按天对行数,正常应该是每小时 1 行,一天 24 行左右 SELECT CAST(RecTime AS date) AS D, COUNT(*) AS Rows FROM dbo.TDays WHERE RecTime >= DATEADD(day, -7, GETDATE()) GROUP BY CAST(RecTime AS date) ORDER BY D DESC;第一种看的是“有没有写、写的内容对不对”,第二种看的是“写得频不频”。如果某天 24 行变成了 480 行,回头看 3.4 节的复位顺序;如果某天只有 10 行,那是连接中途断了或者 HMI 站停机,不是脚本逻辑问题。
第二种验证是在 Intouch 里读回。新建一个内存整型标记,用SQLSelect或者一条查询把刚插入的行数读回来显示在画面上。画面能实时显示行数,值班的人一眼就能看出是不是停写了,比事后翻库快得多。
第三种验证是拿 Excel 报表反查。报表能正常出一行数据,说明从采集到写入到取数整条链路是通的。这是最接近用户视角的验证,也是交付前必须走一遍的。
5. Excel 报表与历史库恢复:VBA 取数、mdf/ldf 附加和五条现场排查记录
数据写进去了,最后一步是把库里的行变成人看得懂的报表。Excel 在这套方案里承担的角色是“轻量客户端”,用 VBA 连库取数,不需要额外的报表服务器。这一章同时把历史数据恢复的附加流程讲完,因为这两件事在现场经常一起做——先把旧库附件上来,报表才有历史可比。
5.1 宏安全设置与 VBA 引用
打开做好的模板,第一件事是处理宏。文件 → 选项 → 信任中心 → 信任中心设置 → 宏设置,选“启用所有宏”,同时勾上“信任对 VBA 工程对象模型的访问”。这一步在受管控的现场机器上可能需要管理员权限,提前确认,别等到交付当天卡在这里。
然后进 VBA 编辑器,工具 → 引用,至少要勾三项:Visual Basic For Applications、Microsoft Excel 对象库、Microsoft ActiveX Data Objects。第三项的版本号在不同机器上不一样,6.1 和 2.8 都见过。如果模板要在多台机器上分发,引用版本不一致会导致打开就报“找不到工程或库”。
绕开的办法是用后期绑定,不勾引用,直接在代码里CreateObject("ADODB.Connection")。代价是没有智能提示、常量要自己定义,好处是换机器不会因为引用版本翻车。我的习惯是开发阶段用早期绑定方便调试,交付前改成后期绑定。
5.2 控制面板页和参数日报页的分工
模板里两个工作表分工明确。“控制面板”页放查询条件——日期、产线、班次,以及一个“刷新”按钮,绑到宏上。“参数日报”页放表头和明细区,明细从第 5 行开始往下填,上面几行是标题和汇总。
这样分的好处是:日报页只负责展示,取数逻辑全在 VBA 里,改查询条件不用动公式。用公式直连数据库(比如用Microsoft Query)也能做,但条件一变就得重做查询,现场维护成本高。VBA 方案里条件是一个单元格的值,改起来只是改个数字。
5.3 一段可以直接改的取数 VBA
Sub LoadDailyReport(ByVal dDate As Date) Dim conn As Object, rs As Object Dim sConn As String, sSQL As String Dim r As Long ' 日期统一按 yyyy-mm-dd 拼接,避免区域设置把 03/04 解释成三月或四月 sSQL = "SELECT RecTime, LineName, BatchNo, Pv01, RunFlag FROM dbo.TDays " & _ "WHERE RecTime >= '" & Format(dDate, "yyyy-mm-dd") & " 00:00:00' " & _ "AND RecTime < '" & Format(dDate + 1, "yyyy-mm-dd") & " 00:00:00' " & _ "ORDER BY RecTime" sConn = "Provider=SQLOLEDB;Data Source=HMI_NODE01\SQLEXPRESS;" & _ "Initial Catalog=SIMU_BB;User ID=rpt_reader;Password=Rpt@2014;" Set conn = CreateObject("ADODB.Connection") ' 后期绑定,免去引用版本问题 conn.ConnectionTimeout = 5 ' 连不上 5 秒就放弃,别让界面假死 conn.CommandTimeout = 30 conn.Open sConn Set rs = CreateObject("ADODB.Recordset") rs.Open sSQL, conn, 0, 1, 1 ' 只读游标,减少锁表风险 r = 5 Do While Not rs.EOF Cells(r, 1).Value = rs.Fields("RecTime").Value Cells(r, 2).Value = rs.Fields("LineName").Value Cells(r, 3).Value = rs.Fields("BatchNo").Value Cells(r, 4).Value = rs.Fields("Pv01").Value Cells(r, 5).Value = rs.Fields("RunFlag").Value r = r + 1 rs.MoveNext Loop rs.Close conn.Close Set rs = Nothing Set conn = Nothing End Sub时间区间用左闭右开,>= 当天零点且< 次日零点,避免BETWEEN在边界上把次日零点那条算进来。ConnectionTimeout = 5是为了防止库挂掉时 Excel 界面卡死几十秒,用户体验差别很大。报表账户建议单独建一个只读账户rpt_reader,不要复用写入账户,报表端出问题不至于影响采集。
如果模板里明细行数不确定,填充前先清空第 5 行以下区域,否则上一次查询多出来的行会残留在表里,看起来像重复数据。
5.4 历史库的 mdf/ldf 附加
SQL Server 的库文件是两个:数据文件.mdf和日志文件.ldf,通常放在同一个目录下。恢复时把整个目录拷到目标服务器的同一路径下,比如E:\DataBase\,两个文件都要,只拷 mdf 会附加失败。
在 SSMS 里右键“数据库”选“附加”,在“要附加的数据库”里点“添加”,定位到E:\DataBase\,选中.mdf文件,确定。如果 .ldf 在同目录且文件名匹配,会自动带出来。附加完成后刷新数据库列表,能看到库名和原来的表。
注意附加用的是文件路径而不是备份文件,所以源库和目标库的版本要兼容——高版本附加到低版本会直接拒绝,这个没有绕过的办法,只能在高版本上导出脚本和数据再导回去。
5.5 五条现场记录:现象、原因、解决
第一条,脚本返回连接号为负,绑定列表里读出来全是空。现象是Connid1 = -1,画面上没有任何报警。原因是 SQL Server 只开了 Windows 身份验证,或者改了身份验证模式但服务没重启。解决是先确认服务器属性里的模式,再重启实例服务,最后用脚本里的账户在 SSMS 里手动执行一条INSERT验证权限。
第二条,日报里整列日期错一天。现象是 3 月 4 日的数据出现在 3 月 3 日的报表里。原因是 Windows 短日期格式与 VBA 里Format的格式串不一致,SQL 端又在做字符串比较。解决是把系统短日期改成yyyy-MM-dd,VBA 里统一Format(dDate, "yyyy-mm-dd"),SQL 端用datetime做区间比较。
第三条,附加数据库报“无法打开物理文件,操作系统错误 5(拒绝访问)”。现象是选了 mdf 之后确定按钮点下去就弹错。原因是 SQL Server 服务账户对E:\DataBase\没有 NTFS 读权限,或者文件被设成了只读。解决是给服务账户加目录读写权限,去掉只读属性,用 sysadmin 角色重新附加。
第四条,同一分钟内出现多条重复记录。现象是某小时的 58 分区间里插入了十几行相同数据。原因是置位和复位写在同一分支,判据每 5 秒重新成立一次。解决是把复位挪到$Minute < 58的分支,让写标记在整个可写区间内保持置位。
第五条,Excel 打开报表一片空白或提示宏被禁用。现象是点刷新没反应,或者打开就报“找不到工程或库”。原因是宏安全级别、引用版本不匹配。解决是信任中心启用宏,VBA 里把早期绑定改成CreateObject后期绑定,交付前在目标机器上完整走一遍。
6. 把“写进去了”变成“对得上”:行数对账、断线重连和报表刷新
到这一步功能已经能跑,但离“能放心交给值班的人”还差一段。我的经验是加三样东西,成本都不高,出问题时能省掉一整晚的排查。
第一样是行数对账。建一张按天汇总的视图,每小时一行,报表取数前先查这张视图,行数明显偏离预期就在画面上给个提示。
CREATE VIEW dbo.v_DayCheck AS SELECT CAST(RecTime AS date) AS D, COUNT(*) AS Rows, MIN(RecTime) AS FirstRec, MAX(RecTime) AS LastRec FROM dbo.TDays GROUP BY CAST(RecTime AS date);正常一天 24 行,Rows少一半说明中途停写过,FirstRec和LastRec能直接定位停的时间段。这个视图给报表端和 HMI 画面共用,两边看到的是同一份事实。
第二样是断线重连。3.4 节里Connid1 < 0的补连判断只是最基础的一层,更稳的做法是定期心跳:新建一个内存整型标记,每 5 分钟执行一次SQLSelect查SELECT 1,把返回状态写到这个标记上,画面上做一个连接状态指示灯。数据库重启、网络切换这类事情在现场是常态,有人在画面上看得见,比事后翻日志强。
第三样是报表的刷新节奏。别把刷新挂在Workbook_Open上,也别指望用户记得点按钮。用Application.OnTime定一个 10 分钟的定时刷新,同时把查询条件里的日期默认值设成“昨天”,这样打开就是完整的一天,不需要人工干预。刷新宏里要处理异常:连不上库就跳过本次,把失败次数记在一个隐藏单元格里,连续失败三次再弹提示,避免网络抖一下就弹窗。
这三样加完,才算把这套 Intouch 2014R2 + SQL Server 2012 + Excel 的链路收口。从那以后我每次上电调试,都强制先把“写入一行、查回一行、报表出一行”这三步走一遍,再谈画面和报警。看起来多花十分钟,实际省下的是凌晨两点的电话。希望帮到你。
本文还有配套的精品资源,点击获取