资讯动态

InTouch通过ODBC写库,Excel自动生成交接班报表的完整方案

发布时间:2026/10/14 7:38:26 来源:尧图企业网站定制
简介这是一份面向SCADA系统工程师、HMI开发人员及自动化运维人员的实操型技术文档围绕WonderWare Intouch 2014 R2与SQL Server 2012的集成展开重点解决工业现场实时数据写入数据库、历史数据查询以及基于Excel自动生成报表等典型问题。文档以图文步骤为主完整覆盖了SQL Server Management Studio中的登录与权限配置、新建数据库及表单Intouch标记名字典中内存型标记的创建、SQL访问管理器绑定列表的建立以及SQLConnect()、SQLDisconnect()、SQLInsert()等核心函数的脚本编写方法还包含Excel报表模板、VBA引用设置与定时刷新机制以及SQL数据库文件备份恢复的操作细节内容从最基础的数据库身份验证修改开始逐步深入到条件脚本与报表联动实现每一步均有界面截图辅助理解。包体为单个doc文件大小约2.48MB内容按“写入数据库—连接操作—数据绑定—Excel报表—数据库恢复”五部分清晰组织。已有531人学习下载适合需要快速落地Intouch数据库应用的工程技术人员参考。1. 在 InTouch 里接数据库做 Excel 报表交接班不再靠截图和手抄交接班时值班长要产量、报警次数、关键参数曲线很多项目现场的现状是先从 InTouch 画面上截图再人工抄到 Excel 里拼表。夜班数据一多漏一行就要返工核对半天。这篇要讲的路线很直接——InTouch 通过 ODBC 把实时值写入数据库Excel 通过外部数据源直接读库用 VBA 和 Windows 定时任务把报表自动刷出来。一句话概括InTouch 负责采数和写数数据库负责存Excel 负责算和展示。适合正在维护组态画面、想补上报表和追溯能力又不想上重型 BI 平台的工程师。2. 先打通数据库连接ODBC 数据源与 SQL Access Manager 的正确配置顺序数据库连接是整套方案的地基。我见过太多人一上来就写 SQLInsert 脚本结果运行时弹 ODBC 错误框最后查出来是 DSN 位数不对或者账号权限不足。正确的顺序应该是先定数据库选型再建 ODBC 系统 DSN然后在 InTouch 侧建好表映射最后才写脚本。顺序反了排查成本会翻倍。2.1 数据库选型SQL Server 还是 Access先看点位数和并发选型不只看项目大小要看三个硬指标点位总数、写入频率、同时读报表的客户端数量。Access 在单机、低并发场景下完全够用文件即库备份直接复制但一旦多个客户端同时打开报表查询Access 容易锁库表现就是报表刷新时卡死或提示“数据库已被锁定”。SQL Server Express 是中小项目最稳的中间选择支持网络访问备份恢复有向导数据库大小限制对大多数工控报表项目来说足够。如果项目要集中采集多个车间数据、报表要保留三年以上直接上 SQL Server 标准版别在 Express 上硬撑。选型适合规模并发读写备份恢复维护成本Access点数少、单机、记录频率低弱多客户端易锁库复制文件即可低SQL Server Express中小项目、单服务器较好支持网络访问备份/还原向导中SQL Server 标准版多车间集中、长周期存储强完整备份方案高具体判断标准点数少于 500、写入间隔大于 1 分钟、报表只有一两个人看Access 够用只要有两个以上客户端要同时连库查询就老老实实上 SQL Server。写频率高于每 5 秒一条的还要额外考虑索引和分区这一步别省。2.2 ODBC DSN 配置位数不对配得再漂亮也没用数据库建好后下一步是建 ODBC 系统 DSN。这里有一个最典型的坑64 位 Windows 上“管理工具”里默认打开的是 64 位 ODBC 数据源管理器而很多 InTouch 版本是 32 位进程它只认 32 位 DSN。你在 64 位管理器里配得再完整InTouch 里就是看不到或者连接时报“找不到数据源名称”。我一般的做法是直接到C:\Windows\SysWOW64\odbcad32.exe打开 32 位 ODBC 管理器在“系统 DSN”里新建。驱动优先选较新的 SQL Server ODBC 驱动没有就用系统自带的 SQL Server Native Client关键是位数要和 InTouch 进程一致。DSN 名称建议用纯英文不要带空格和中文后面要写进连接字符串。DSNPlantDSN;UIDscada;PWD123456;连接字符串里的 UID 和 PWD 是数据库登录账号不要在 DSN 配置里勾选“使用 Windows 身份验证”后又在字符串里混用账号密码。给 InTouch 用的账号权限最小化只给 SELECT 和 INSERT报表查询走只读账号写库走专用账号避免画面脚本被误操作拖垮。2.3 SQL Access Manager告诉 InTouch 你的表在哪ODBC DSN 建好后打开 InTouch 的组态工具找到 SQL Access Manager常见于 WindowMaker 的 SQL/ODBC 菜单下。这里做的是把数据库表和 InTouch 内部对象做一个映射关系。实际操作中我更推荐在脚本里直接用绑定列表字符串来完成映射而不是全部塞进 SQL Access Manager 的静态配置里。先建一张产量记录表这是整套报表的数据基础CREATE TABLE output_log ( id INT IDENTITY(1,1) PRIMARY KEY, tag_name NVARCHAR(50), value FLOAT, record_time DATETIME DEFAULT GETDATE() );表结构里注意三个细节id自增主键保证行唯一tag_name用NVARCHAR而不是VARCHAR避免中文标签乱码record_time默认值用数据库的GETDATE()不要在 InTouch 端拼本地时间。表建好后先在 Excel 里通过“获取数据”功能试连一下 DSN能拉到数据再回 InTouch 配脚本这个验证顺序能帮你把连接问题提前炸出来。3. 用 SQL 函数把实时值写成历史记录SQLInsert 与绑定列表的用法数据库连接通了接下来是 InTouch 脚本里的核心逻辑。很多人第一次写 InTouch 的 SQL 脚本都会拿高级语言的经验去套结果被 SQL 函数的异步模型坑得够呛。这一章把连接、写入、查询三件事拆开讲清楚。3.1 SQL 函数是异步的连接、写入、查询的调用顺序不能乱InTouch 的 QuickScript 里SQL 相关函数不是同步阻塞的。SQLConnect只是发起连接请求SQLSelect只是提交查询结果集要后续逐行取。这个模型和 C#、Java 里“调用即返回结果”完全不同最容易翻车的点是执行完SQLSelect后立刻去读绑定的标记名读到的还是旧值。函数职责划分是这样的SQLConnect(ConnectionId, SessionMode, ConnectionString)建立会话SessionMode 填 0 表示共享连接填 1 表示独立连接。我习惯用独立连接调试时问题少一些。SQLInsert(ConnectionId, TableName, BindingList)把绑定列表里的标记值插入指定表。SQLSelect(ConnectionId, TableName, WhereClause, BindList, MaxRows, StartRow)发起查询结果行数由 MaxRows 限制。SQLGetRow(ConnectionId)从结果集取一行并把列值刷新到绑定列表对应的标记里。SQLDisconnect(ConnectionId)关闭会话。这里的关键是理解“SQLSelect 只是把查询交出去SQLGetRow 才是真正拿数据回来”。每次调用SQLGetRow取到一行后绑定列表里对应的标记才会被刷新。取完所有行后继续调用会返回无效值所以要控制循环次数。3.2 绑定列表数据库列名和 InTouch 标记名的一一对应绑定列表是 InTouch 里理解成本最高的概念。它不是 SQL 语句而是一个映射串格式是“数据库列名 InTouch 标记名”多个绑定用逗号分隔。SQLInsert执行时InTouch 会读取当前标记的值填入对应的数据库列SQLSelect执行后SQLGetRow又会把数据库列的值写回标记。绑定项说明示例列名数据库表里真实的列名tag_name标记名InTouch 内存标记类型要和列匹配TagName分隔符多个绑定用逗号列与标记用等号valueOutputValue标记名类型要提前规划数据库VARCHAR/NVARCHAR列绑定到 InTouch 消息型标记默认 256 字符FLOAT/INT列绑定到内存实型或内存整型标记。类型对不上运行时数据写不进去但不报错表里出现 NULL 或空字符串这种问题排查起来最头疼。绑定列表字符串里不要出现多余空格比如tag_name TagName这种写法看着整齐但 InTouch 可能把空格也当成列名的一部分导致“列名无效”的 SQL 错误。我吃过这个亏后来统一写成紧凑格式不再加空格。3.3 一个可用的写库脚本按钮触发一次产量记录下面这段是 InTouch QuickScript放在一个“记录当前产量”按钮的动作脚本里{ // 建立连接connId 是内存整型标记SessionMode1 独立连接 SQLConnect(connId, 1, DSNPlantDSN;UIDscada;PWD123456); // 绑定列表数据库列名 InTouch 标记名逗号分隔 SQLInsert(connId, output_log, tag_nameTagName, valueOutputValue, record_time$Time); // 断开连接写完就释放会话 SQLDisconnect(connId); }逻辑说明脚本先建立数据库会话然后执行插入最后断开连接。connId要预先建为内存整型标记TagName是消息型标记OutputValue是内存实型标记。这里把record_time绑定了$Time但如果你按 2.3 的表结构设计record_time列有默认值绑定里可以直接去掉这一项让数据库服务器统一生成时间戳能省掉时钟同步的麻烦。连接失败时InTouch 运行时通常会在画面左下角弹出 ODBC 错误码。看到08001这类 SQLState先查网络和账号权限别急着改脚本。另外不要把连接和断开写进每个扫描周期里高频写入时连接开销会拖慢画面刷新应该用共享连接并在应用启动时建立退出时再断开。再给一个查询示例把最近 100 条记录取回来显示{ SQLConnect(connId, 1, DSNPlantDSN;UIDscada;PWD123456); // 无条件查询最多取 100 行从第 0 行开始 SQLSelect(connId, output_log, , tag_nameTagName, valueOutputValue, record_timeOutTime, 100, 0); // 取第一行OutTime 等绑定标记被刷新为当前行数据 SQLGetRow(connId); SQLDisconnect(connId); }这个查询脚本只取了一行如果要填满报表需要在脚本里做循环反复调用SQLGetRow直到取完。表格显示控件要提前设计好行数或者用循环动态填充。实际项目里我通常把报表查询放到独立页面避免主画面加载时卡顿。4. 把数据库表变成 Excel 报表数据源刷新、VBA 和定时任务三件事数据库里有了历史记录Excel 报表这部分就相对轻松了。核心思路是Excel 只做展示层所有原始数据直接从数据库表读取不在 Excel 里手工录入任何生产过程数据。这样报表文件本身可以反复重算不会因为改了一个数导致整个表失真。4.1 报表数据源Excel 直接连数据库别让 InTouch 导出中间文件我见过不少项目让 InTouch 把数据导出成 CSV再让 Excel 打开 CSV。这个做法在数据量小的时候能跑但 CSV 是静态快照交接班表单稍微改一点需求就要改导出脚本和 Excel 模板两处维护成本翻倍。改成都市更可靠。Excel 连接数据库的标准路径数据 → 获取数据 → 来自数据库 → 来自 SQL Server 数据库。输入服务器名和库名选择output_log表加载为表。这里有一个参数要特别注意在连接的属性里勾选“打开文件时刷新数据”。否则报表文件打开后看到的还是上次保存时的旧快照值班长一旦忘了手动刷新交班数据就是错的。加载进来的数据表建议另存为 Excel 表格ListObject不要用普通区域。表格对象在每次刷新后行列会自动扩展透视表和数据验证都会跟着更新不会出现“新数据追加到表外”的尴尬。报表里的汇总行全部用结构化引用或透视表不要直接SUM(A2:A100)写死区域。4.2 VBA 刷新一个按钮把整张报表的数据全部更新Excel 外部数据源刷新可以手动点但一张报表里如果有多个连接手动逐个刷新很容易漏。我习惯在报表里加一个“刷新”按钮绑一个 VBA 宏把所有连接、透视表、公式重算一次搞定。Sub RefreshAllData() Dim conn As Object For Each conn In ThisWorkbook.Connections conn.Refresh Next conn ThisWorkbook.Sheets(汇总).Calculate End Sub逻辑说明遍历工作簿里的所有连接逐个刷新刷新完成后强制重算汇总表。注意Calculate是有必要的外部数据刷新后Excel 不会自动重算所有易失函数和自定义公式特别是用NOW()、TODAY()这类函数做时间条件时不重算就会出现界面上数据是新的、汇总却是旧值的情况。刷新完成的提示不要用MsgBox弹窗交接班场景下弹窗容易被误关。可以在状态栏写提示或者做个简单标签显示“最后刷新时间”NOW()。人员交接时扫一眼刷新时间就知道报表是不是最新的。4.3 定时生成任务计划程序 VBScript交接班前自动出表如果每天早上 8 点交接班报表最好 7:55 就自动生成好值班长打开就能看到。实现方式不是让 InTouch 去调 Excel而是用 Windows 任务计划程序定时跑一个 VBScriptVBScript 启动 Excel 打开报表文件、执行刷新宏、保存并退出。Dim xl, wb Set xl CreateObject(Excel.Application) xl.Visible False xl.DisplayAlerts False Set wb xl.Workbooks.Open(D:\Reports\ShiftReport.xlsm) xl.Run RefreshAllData wb.Save wb.Close False xl.Quit Set wb Nothing Set xl Nothing逻辑说明脚本创建 Excel 后台实例打开报表文件执行刷新宏保存后退出。DisplayAlerts False是为了避免刷新过程中弹出连接提示框时脚本卡死。任务计划程序里配置cscript.exe //nologo D:\Reports\refresh.vbs触发器选“每天”时间设为交接班前 5 分钟。这个方案的坑在于如果报表文件正被某个用户打开着脚本里的wb.Save会失败而且任务计划程序默认的报错提示可能不会引起任何人注意。我的做法是让宏里加文件占用判断捕获错误并写日志文件任务计划里同时配置“启动时若任务正在运行则忽略”避免上一轮没跑完就开启新一轮。交接班结束后的报表建议再另存一份 PDF 归档VBScript 里调用wb.ExportAsFixedFormat即可存档文件按日期命名后续审计直接查 PDF不依赖 Excel 环境。5. InTouch Excel 报表联动排查5 个高频坑与解决记录这套方案上线后真正让你加班的不是功能设计而是那些看起来“哪里都对但就是不工作”的怪问题。下面这 5 个坑是我在多个项目里反复踩过的每一条都有至少两个现场案例背书。5.1 坑一ODBC 配了但连接失败原因是位数不匹配现象InTouch 运行时 SQL 操作弹 ODBC 错误错误码类似08001或找不到数据源名称SQL Access Manager 里也看不到刚才创建的 DSN。原因64 位系统默认打开的是 64 位 ODBC 管理器InTouch 是 32 位进程只认 32 位 DSN。两边位数不一致相当于在楼上配了门禁楼下的人拿着卡根本刷不开。解决打开C:\Windows\SysWOW64\odbcad32.exe重新配置系统 DSN。配置完成后用 Excel 的“获取数据 → 来自 ODBC”先验证一遍确认能查到表再回 InTouch 折腾。以后凡是遇到“配置没问题但连不上”第一反应就查位数别急着重装驱动。5.2 坑二查询没结果SQLSelect 之后忘了 SQLGetRow现象查询脚本执行了绑定标记没有变化画面上的表格控件始终空白但数据库里明明有数据。原因SQLSelect只是提交查询请求结果集需要SQLGetRow逐行取回。很多半路转工控的开发者用惯了同步查询接口天然认为调用SQLSelect后数据就在标记里了。解决在SQLSelect后完整调用取行流程。取到行为止的循环要控制次数用MaxRows限制结果集大小不要做无界循环。调试阶段可以在画面加一个计数标记显示实际取到几行一眼就能看出是哪一步断了。5.3 坑三写进去的中文标签Excel 里显示乱码现象数据库表里中文正常InTouch 画面也正常但 Excel 报表刷新后中文变问号或乱码。原因大多数情况是 ODBC 驱动的字符集和 Excel 导入编码不一致。如果走数据库连接优先检查驱动版本和连接字符串里是否强制指定了非 UTF-8 编码如果走 CSV 文件Excel 双击打开默认按系统 ANSI 编码读文本UTF-8 无 BOM 的文件必乱。解决数据库列统一用NVARCHAR连接字符串优先用较新的 ODBC 驱动避免旧驱动在中文环境下表现异常。CSV 场景不要双击打开用“数据 → 自文本/CSV”导入在向导里选择“65001: Unicode (UTF-8)”。这一步能省掉大量脏数据清洗时间。5.4 坑四数据少了一段重启之后查不到缺失记录现象交接班核对时发现某几个小时的记录整体缺失数据库表里时间戳断层但 InTouch 画面趋势是连续的。原因脚本里每次写完立即SQLDisconnect写入语句可能还没真正提交进程重启或网络瞬断导致数据丢失还有一种情况是表没有主键和索引高频写入时查询阻塞报表时间窗恰好覆盖了写入失败的时间段。解决高频写入场景用共享连接SessionMode0应用启动时建连接退出时断开避免每条记录重复握手。表结构加自增主键record_time建索引查询和写入互不拖累。每次SQLInsert后可以做失败计数写入失败时在画面弹一个持久化告警而不是让错误静默消失。5.5 坑五报表数字和现场对不上刷新时机与时间戳的锅现象Excel 报表里的产量和值班长手记的产量差了几百件但数据库明细单独看没错。原因两个来源一是 Excel 打开时没有刷新看到的还是上次快照生产还在继续写库报表数据停在旧时点二是时间戳来源不统一InTouch 端绑定$Time时用的是组态软件所在机器的时间数据库服务器时间快慢几分钟班次边界统计就会错位。解决报表连接属性里必须勾选“打开文件时刷新数据”时间戳统一改成数据库生成用默认值GETDATE()不在 InTouch 脚本里拼时间。班次划分建议用整点不要用 08:30、16:30 这种带半点的边界现场时钟漂移一点就分错班次。6. 用时间戳对齐做报表自校验让 Excel 里的数和现场 DCS 能对上报表能做出来只是第一步能让人相信才是交付。我后来形成的习惯是给每张报表加一个“数据完整性校验”页不直接展示业务数据而是回答“这份报表的数全不全”。具体做法是加一列source_flag值为 1 表示 InTouch 自动写入2 表示人工补录。核对时只需要统计自动写入的记录数和时间覆盖区间。在 Excel 校验页里用COUNTIFS按班次统计自动记录数再和现场 DCS 汇总值交叉对比。公式示例COUNTIFS(record_time,B2, record_time,B3, source_flag,1)其中 B2、B3 是班次起止时间。如果自动记录数比现场手记少说明存在未捕获时段这时才需要去查 InTouch 脚本和数据库连接。这个校验页最大的价值不是抓谁出错而是让每次交接班时值班长能基于同一把尺子说话。数据完整、时间戳来自数据库统一时钟、刷新时机可控这三件事做到位报表系统才算真正稳定下来。我以前第一次做这套方案时就在 ODBC 位数和 SQLGetRow 上各熬了一个夜班后来把“数据库生成时间戳”和“自动刷新”变成固定习惯报表几乎不再返工。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑