首页/新闻资讯/正文详情

Intouch 2014 R2与SQL Server 2012报表链路搭建

发布时间:2026/11/4 12:33:23 来源:云帆数科 栏目:资讯中心
Intouch 2014 R2与SQL Server 2012报表链路搭建
简介面向SCADA/HMI工程人员与Intouch初学者的操作文档围绕WonderWare Intouch 2014R2与SQL Server 2012的集成讲解数据库配置、权限设置、变量绑定、连接脚本及Excel报表读取数据等常见问题。包内为1个doc文件约2.48MB以图文步骤组织便于按章节查阅。已有533人学习下载适合需要快速搭建数据存储与报表链路的现场调试和二次开发人员。内容覆盖SQL Server身份验证与建库建表、标记名字典和SQL访问管理器绑定、SQLConnect/SQLInsert等脚本用法以及Excel报表模板和VBA引用设置并附数据库文件附加恢复思路。读者可据此梳理从Intouch写入数据库到Excel生成报表的完整流程减少连接配置和数据类型对应上的排错时间。1. 版本先定死Intouch 2014 R2 与 SQL Server 2012 这套组合接手一套别人装了一半的站最怕的不是画面没画完而是 Intouch 2014 R2 的 IDE 里画面跑得好好的SQL Server 2012 也连得上Excel 报表却在凌晨两点空着——第二天早班一看昨天一整天的数据全丢了。这套组合在工控站上太常见了Intouch 2014 R2 做 HMISQL Server 2012 存历史数据Excel 加 VBA 出日报。三样东西单拎出来都不难装难的是它们之间的接缝身份验证模式、时间格式、绑定列表名、VBA 引用任何一处对不上表现出来都只是没数据三个字。这篇按我自己装站的顺序写一遍从版本对齐到标记建立、脚本编写、报表模板、故障排查最后落到怎么确认它真的跑通了。适合第一次搭这套链路的人照着走也适合已经装完但数据时有时无的人对着查。2. 装前环境盘点SQL Server 2012 与 Intouch 2014 R2 的版本对齐2.1 安装顺序与账户权限为什么先装 SQL 再装 Intouch顺序不能反。Intouch 2014 R2 安装时会去探测本机的数据访问组件如果先装 Intouch 后装 SQL Server某些 OLE DB 提供程序注册顺序会乱表现是脚本里 SQLConnect 一直返回 0但用 SSMS 手工连完全正常。我一般的顺序是操作系统补丁 → .NET Framework3.5 和 4.x 都装上2014 R2 的 IDE 主体是 32 位程序在 64 位系统上跑 WOW64两套运行库都得在→ SQL Server 2012实例名用默认实例别图省事起个怪名字→ Intouch 2014 R2 → 授权 → IO 采集侧组件。SQL Server 2012 安装时有个选项容易被一路下一步带过去排序规则。默认是Chinese_PRC_CI_AS如果这台机器以后要跟别的站做数据库附加或者数据合并排序规则不一致会直接导致附加失败或者中文乱码。装之前先问清楚历史站用的是什么统一成一样的。装完先把服务包补齐装完立刻验证实例状态-- 确认实例名、版本号、排序规则三件事出问题先看这三行 SELECT VERSION AS ver, SERVERPROPERTY(InstanceName) AS inst, SERVERPROPERTY(Collation) AS coll, SERVERPROPERTY(IsIntegratedSecurityOnly) AS onlyWinAuth; -- 1 表示只允许 Windows 验证VERSION里能看到 11.0.x 这样的主版本号11 就是 SQL Server 2012InstanceName为空说明是默认实例此时连接串里 Data Source 只写计算机名就行起了命名实例就必须写成主机名\实例名。最后那个IsIntegratedSecurityOnly是后面第 2.2 节要动的开关先记下来。接下来是网络层。SQL Server 2012 装完默认只开共享内存和命名管道TCP/IP 是关的。本机用 SSMS 连没问题但 Intouch 走的是 OLE DB跨机器或者某些配置下必须走 TCP。打开配置管理器把SQL Server 网络配置 → 实例的协议 → TCP/IP启用端口保持 1433然后重启 SQL Server 服务。防火墙按需放行别图省事直接关防火墙# 只对内网网段放行 1433比关防火墙安全得多 New-NetFirewallRule -DisplayName SQL2012-TCP-1433 -Direction Inbound -Protocol TCP -LocalPort 1433 -RemoteAddress 192.168.10.0/24 -Action Allow # 顺便确认 SQL 服务的启动账户后面附加数据库文件要用到 Get-CimInstance Win32_Service -Filter NameMSSQLSERVER | Select-Object Name, StartName, StateRemoteAddress一定要写实际网段工控网络里 IP 段通常很清楚写宽了等于没设防。StartName这一项很关键如果启动账户是NT Service\MSSQLSERVER虚拟账户那么后面第三章附加 .mdf 文件时源目录的 NTFS 权限必须给到这个虚拟账户或者Everyone读权限否则附加时提示无法打开物理文件操作系统错误 5拒绝访问。这个坑我在第一次做数据库迁移时踩过折腾了一下午才发现是权限。端口验证不用等装完 Intouch 再做现在就能测# 从 Intouch 那台机器上测不要在本机测本机走共享内存不经过 TCP Test-NetConnection -ComputerName SCADA-01 -Port 1433TcpTestSucceeded : True才算网络层通了。如果这里就是 False后面所有数据库相关的报错都不用看先把端口和防火墙解决掉这是最省时间的分流点。2.2 身份验证模式与登录名从 Windows 验证切到混合验证SQL Server 2012 默认是仅 Windows 身份验证。Intouch 的 SQLConnect 函数连接串里带 UserID 和 Password走的是 SQL Server 身份验证所以必须切成混合模式。原文的做法是在 SSMS 里右键实例 → 属性 → 安全性 → 选SQL Server 和 Windows 身份验证模式点确定后必须重启 SQL Server 服务才生效。很多人点完确定就直接去建登录名然后发现新建的 SQL 账户登录报 18456就是因为没重启。图形界面之外我习惯留一份 T-SQL 记录方便以后重建环境时照抄-- 把登录模式改成混合验证2 表示混合1 表示仅 Windows -- 改完必须重启 SQL Server 服务否则不生效 USE [master]; GO EXEC xp_instance_regwrite NHKEY_LOCAL_MACHINE, NSOFTWARE\Microsoft\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQLServer, NLoginMode, REG_DWORD, 2; GO -- 确认改动是否落盘 EXEC xp_instance_regread NHKEY_LOCAL_MACHINE, NSOFTWARE\Microsoft\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQLServer, NLoginMode; GO路径里的MSSQL11.MSSQLSERVER是 SQL Server 2012 默认实例的注册表键11 对应 2012如果你的实例是命名实例要把MSSQLSERVER换成实例名。这个路径写错的话xp_instance_regwrite会静默失败不报错但也不生效所以后面那句xp_instance_regread一定要跟着跑一遍看到返回值是 2 才算成。登录名这块原文示例里用的是sa连接串直接写UserIDsa;Password...。这个方法能跑通但我建议别这么干。sa是实例级最高权限一旦连接串写在 Intouch 的应用程序脚本里任何能打开 WindowMaker 的人都能看到明文密码而且这个账户一旦泄露整台数据库服务器就没了。我的做法是建一个专用账户只给目标库的读写权限-- 建一个只服务于报表写入的专用登录名密码策略保持开启 USE [master]; GO CREATE LOGIN [scada_writer] WITH PASSWORD N换成至少12位的强密码, CHECK_POLICY ON, CHECK_EXPIRATION OFF; GO -- 只给 YADC_BB 这个库的读写权限不给 db_owner USE [YADC_BB]; GO CREATE USER [scada_writer] FOR LOGIN [scada_writer]; GO ALTER ROLE [db_datareader] ADD MEMBER [scada_writer]; ALTER ROLE [db_datawriter] ADD MEMBER [scada_writer]; GO -- 验证用新账户查一下自己的权限 SELECT pr.name AS 主体, pe.permission_name, pe.state_desc FROM sys.database_permissions pe JOIN sys.database_principals pr ON pe.grantee_principal_id pr.principal_id WHERE pr.name scada_writer;CHECK_POLICY ON会套用系统的密码复杂度策略CHECK_EXPIRATION OFF是防止密码到期后半夜报表突然断掉——工控站没人会定期改密码到期策略在这里是纯粹的故障源。db_datareader加db_datawriter的组合刚好覆盖建表不用它、写数用它、查数用它的需求比db_owner稳妥得多。如果报表端还要执行存储过程再单独GRANT EXECUTE。这里有个细节容易被忽略SQL Server 2012 里新建的 SQL 登录名默认是启用状态但如果你是从别的机器脚本迁移过来的可能会带上is_disabled 1。装完顺手查一下SELECT name, is_disabled, create_date FROM sys.sql_logins WHERE name scada_writer;is_disabled是 1 就ALTER LOGIN [scada_writer] ENABLE;。这个状态在 SSMS 界面上不明显但对连接来说就是密码对了也登不上属于典型的翻车点。2.3 时间格式与区域设置被忽略的第三个环境变量原文在Intouch 中与数据库联接操作的第一个步骤编号 0就写了在操作系统的日期和时间中更改日期和时间格式很多人觉得这条是凑数的直接跳过。它不是。Intouch 的脚本里经常用$Date、$Time这类系统标记去拼字符串如果系统短日期格式是yyyy/M/d而 SQL Server 的 datetime 列期待的是能被稳定解析的格式中间就会出现在某些日期上写入成功、某些日期上报转换错误的情况——这种时好时坏的问题最难查。我的处理方式是固定成 ISO 风格短日期yyyy-MM-dd长时间HH:mm:ss。控制面板能改但工控站往往是多用户或者服务账户运行改当前用户不够得确认运行 Intouch 的那个账户也拿到了同样的设置# 固定短日期和长时间格式减少字符串拼接后的解析歧义 Set-ItemProperty -Path HKCU:\Control Panel\International -Name sShortDate -Value yyyy-MM-dd Set-ItemProperty -Path HKCU:\Control Panel\International -Name sLongTime -Value HH:mm:ss Set-ItemProperty -Path HKCU:\Control Panel\International -Name sTimeFormat -Value HH:mm:ss # 读回来确认 Get-ItemProperty -Path HKCU:\Control Panel\International | Select-Object sShortDate, sLongTime, sTimeFormat这三项里sShortDate影响日期显示和部分脚本取值sTimeFormat影响带秒的时间格式。注意HKCU是当前用户如果 Intouch 是以某个专门的服务账户登录运行的得用那个账户登录一次再执行或者直接改默认用户配置单元。改完重启 Intouch 的运行时才生效。数据库侧也顺手确认一下语言设置避免日期解析受登录名默认语言影响-- 查看当前会话的日期格式和语言 SELECT LANGUAGE AS lang, DATEFIRST AS first_day; -- 把专用登录名的默认语言固定成中文避免插入时按英文月份解析 ALTER LOGIN [scada_writer] WITH DEFAULT_LANGUAGE [简体中文];LANGUAGE如果不是简体中文字符串2024-05-01这类还能解析但05/01/2024这种就会按 mm/dd 还是 dd/mm 打架。固定默认语言是个成本极低、收益很直接的预防措施。三件事做完环境层就算齐了实例能连、网络能通、账户能登、时间格式不打架。接下来才轮到 Intouch 里面建标记。顺序颠倒过来你会在一堆连接失败里反复怀疑是脚本写错了。3. Intouch 侧建标记与绑定Connid1、NodeName、WSQLS 三个内存标记怎么定3.1 标记名字典里的内存型标记设计Intouch 2014 R2 的标记名字典Tagname Dictionary里跟数据库打交道的那几个标记不需要挂在 PLC 上全部用内存型。原文提到了三个Connid1内存整型记录连接编号、GetDateTimeS内存消息存连接时间、NodeName内存消息存本机名后面脚本里又用到一个WSQLS内存离散标记数据是否已写入。这四个标记是整个链路的骨架建错了后面全是白费功夫。标记名类型初值用途关键注意点Connid1内存整型0保存 SQLConnect 返回的连接句柄必须允许写不能设成只读GetDateTimeS内存消息空字符串存本次连接的时间戳长度给够至少 32 字符NodeName内存消息空字符串存本机计算机名用于判断是不是该写入的站长度 131 是 GetNodeName 的常见上限WSQLS内存离散0假标志本轮数据是否已写入防重复写入必须每次循环复位建标记时最容易出错的是访问权限那几个勾。内存标记默认是允许读写但如果有人从模板拷过来一个只读标记脚本里赋值会静默失败标记值一直是初值 0表现出来就是 Connid1 永远是 0、连接看起来从来没成功过。我一般建完标记后在 WindowMaker 的标记浏览器里手动改一次值再读回来确认可写再做脚本。GetDateTimeS在实际脚本里用得不多但它的价值在于出问题时能看到最后一次成功连接是什么时候。我通常会在 SQLConnect 成功之后紧跟着一句赋值把$Date和$Time拼进去。NodeName的用途更实在一个站上可能有多台操作站同时往同一个库里写脚本里必须判断我是不是那台该写的机器否则同样的数据会被写多份报表数字直接翻倍。3.2 SQL 访问管理器与绑定列表标记建完接下来是 SQL 访问管理器SQL Access Manager里的绑定列表Binding List。这一步的本质是把 Intouch 的标记和数据库表的列做一个映射映射关系是列表名 ↔ 表名、标记名 ↔ 列名、标记类型 ↔ 列类型。原文强调的对应关系有三条变量名与表列名对应、变量数据类型与列数据类型对应、绑定列表名与 SQLInsert 的第二个字符串参数对应。三条里任何一条错了SQLInsert 都不报错但表里没数据。先建表。列名跟 Intouch 标记名保持一致是最省事的做法-- 建日报表列名与 Intouch 绑定列表里的标记名逐一对应 USE [YADC_BB]; GO CREATE TABLE dbo.TDays ( RecID INT IDENTITY(1,1) PRIMARY KEY, -- 自增主键避免并发写入时冲突 RecordTime DATETIME NOT NULL, -- 对应 Intouch 的日期时间标记 NodeName NVARCHAR(64) NOT NULL, -- 对应 NodeName 标记 ShiftNo INT NULL, -- 班次对应整型标记 OutputQty FLOAT NULL, -- 产量对应实型标记 RunFlag BIT NULL -- 运行状态对应离散标记 ); GORecID这个自增列是我自己加的原文的示例表没有。加它的原因是没有主键的表在重复写入时无法区分哪条是重复数据出了问题只能整表翻。有了自增 ID至少能看出同一分钟内写了几条。DATETIME和NVARCHAR的选择也有讲究日期列必须是 datetime 而不是 varchar否则后面 Excel 取数时排序和区间筛选都会出错。类型映射是这一节的核心我整理成一张对照表建绑定列表时对着填Intouch 标记类型SQL Server 列类型常见错误内存整型INT建成 SMALLINT超 32767 溢出内存实型FLOAT建成 DECIMAL(18,0)小数被截断内存离散BIT建成 INTExcel 取出来是 0/1 不是 TRUE/FALSE内存消息NVARCHAR(n)建成 VARCHAR中文变问号内存日期时间DATETIME建成 VARCHAR(20)区间查询失效绑定列表的建立顺序是SQL Access Manager → 绑定列表 → 新建 → 填列表名必须和表名一致比如TDays→ 填表名 → 逐行添加标记名和列名。添加时窗口会自动带出标记的类型如果类型和列类型不匹配有些版本会直接拒绝添加有些版本允许添加但写入时失败——后者更坑所以建完必须实际写一次验证。有一个细节原文没写但实测很有用绑定列表里列的顺序不重要重要的是名字的精确匹配包括大小写。SQL Server 默认排序规则不区分大小写但 Intouch 这一侧是按字符串精确比对的OutputQty和outputqty在绑定列表里可能被当成两个东西。我一般全部统一成首字母大写的驼峰写法建表、建标记、建列表三处保持完全一致。3.3 应用程序脚本SQLConnect / SQLInsert / SQLDisconnect 的写法与参数脚本这一块原文给的条件是$Second5注释写的是表示每 5 秒钟执行一次。这里我要明确指出$Second5是每分钟的第 5 秒执行一次不是每 5 秒。Intouch 的条件脚本每秒被扫描一次$Second在 0 到 59 之间循环等于 5 的时刻一分钟只有一次。如果要每 5 秒执行得写成$Second MOD 5 0。这个理解偏差的影响不大一分钟写一次日报数据是合理的但如果照字面意思以为在每 5 秒写一次后面查数据密度时会对不上。更重要的是脚本的分层。原文把 SQLConnect 也放在$Second5的条件脚本里这个做法在小数据量下能跑但长期运行的风险很大每一次触发都重新建立一次数据库连接连接句柄如果没被正确释放SQL Server 侧的会话数会缓慢增长跑上几天就会看到连接数打满。正确的分层是三条第一条连接放在应用程序脚本的开始时On Startup只执行一次 应用程序脚本 - 开始时 建立数据库连接连接句柄写入 Connid10 表示成功 SQLConnect( Connid1, providersqloledb;Data SourceSCADA-01;Initial CatalogYADC_BB;UserIDscada_writer;Password换成实际密码 ); 连接成功后记一笔时间出问题时能看出最后一次成功连接的时刻 IF Connid1 0 THEN GetDateTimeS $Date $Time; ENDIF;第二条断开放在关闭时On Shutdown 应用程序脚本 - 关闭时 退出运行时之前释放连接避免服务端残留会话 SQLDisconnect( Connid1 ); Connid1 0;第三条写入逻辑放条件脚本每分钟第 5 秒触发一次 条件脚本$Second 5条件类型为真时 1) 取本机名判断是不是该负责写入的那台站 GetNodeName( NodeName, 131 ); IF NodeName OP_01 THEN 2) 只在每小时最后两分钟做结算写入避免全天高频写库 IF $Minute 58 THEN 3) 用 WSQLS 做一次性闸门防止同一分钟内重复写入 IF WSQLS 0 THEN SQLInsert( Connid1, TDays, TDays ); WSQLS 1; ENDIF; ELSE 4) 离开结算窗口就把闸门复位否则第二天永远写不进去 WSQLS 0; ENDIF; ENDIF;逐段说参数。SQLConnect(联接数据库号, SQL 联接字符串)里第一个参数是输出型的整型变量函数把连接句柄写进去后面所有 SQL 函数都用这个句柄第二个参数是标准 OLE DB 连接串五段用分号隔开。providersqloledb是 SQL Server 的 OLE DB 提供程序2012 上仍然可用新版是MSOLEDBSQL但 Intouch 2014 R2 的脚本环境对老 provider 兼容性更好不建议换。Data Source填计算机名命名实例要写成主机名\实例名。Initial Catalog填库名。UserID和Password就是 2.2 节建的专用账户。GetNodeName(NodeName, 131)的第二个参数是缓冲区长度131 是个常见取值给大了浪费给小了名字被截断。截断的后果很隐蔽OP_01被截成OP_0比较永远不成立数据一条也写不进去但脚本本身不报错。SQLInsert( Connid1, TDays, TDays )两个字符串参数看着一样含义完全不同第一个是数据库里的表名第二个是 Intouch 里的绑定列表名。这两个名字在示例里恰好相同很多人就以为它们是同一个东西改表名的时候只改一个结果就是函数执行了但表里没数据。WSQLS的置位和复位是这段脚本里最容易写错的地方。原文的示例是把WSQLS1和WSQLS0写在同一个条件分支里那样等于没起作用——置位完立刻复位下一分钟还会重复写。必须像上面那样把复位放进 ELSE 分支让它在下一次进入非结算窗口时才复位。这个改动很小但决定了数据会不会重复。脚本写完不要急着开运行先在 WindowMaker 里用逻辑查看或者把条件临时改成$Second3做快速验证确认 Connid1 变成非 0、表里出现一行再改回正式条件。4. Excel 报表侧配置从信任中心到 VBA 引用的完整搭法4.1 Excel 的信任中心与宏设置报表模板带 VBA打开时被拦下来是最常见的第一道坎。Excel 默认会禁用宏并显示黄色安全警告条如果模板是放在共享目录里被多人打开还可能触发受保护的视图这时候即使点了启用宏代码里的数据库连接也会因为处于受保护视图而失败报的错还是对象库未注册这种完全不相干的提示。我的做法是三步把模板所在目录加成受信任位置、关掉这个目录的受保护视图、宏设置选禁用所有宏并发出通知不选启用所有宏那是给自己埋雷。这三项都在文件 → 选项 → 信任中心 → 信任中心设置里。 放在工作簿的 ThisWorkbook 模块里用来确认当前不是受保护视图 Private Sub Workbook_Open() If ActiveProtectedViewWindow Is Nothing Then 正常视图什么都不做 End If 更直接的做法判断当前路径是否在受信任位置 Debug.Print 当前文件: ThisWorkbook.FullName Debug.Print 只读状态: ThisWorkbook.ReadOnly End SubThisWorkbook.ReadOnly这一行很关键。模板如果放在共享盘上被别人打开着第二个人打开就是只读模式报表刷新时写回单元格会失败报无法更新单元格。工控站的报表通常是一个人定时打开看一眼但交接班时段很容易撞车所以模板最好每人本地一份或者至少把生成的报表另存到本地再打开。4.2 控制面板页与参数日报页的模板结构原文把模板分成两个页签控制面板和参数日报。这个结构的用意是把操作入口和数据展示分开控制面板负责选日期区间、选班次、点刷新按钮参数日报负责按模板把数据铺进去。照着做的时候有几个细节值得固定下来。控制面板页我一般放这几样东西起始日期单元格 B2、结束日期B3、班次下拉B4数据验证做序列、刷新按钮绑定宏RefreshDaily、状态提示B6显示上次刷新时间和查询到 N 条。参数日报页顶部留三行表头第四行开始是数据区数据区用命名区域RPT_DATA框住VBA 里直接往这个区域写不用去算行列号。 定义命名区域避免 VBA 里硬编码行列 公式 → 名称管理器 → 新建名称填 RPT_DATA 引用位置填 参数日报!$A$4:$F$1000命名区域的好处是模板改版时不用动代码。数据区预留 1000 行是给自己留余地实际查询超过这个行数就得调整所以 VBA 里写数据前要先判断rs.RecordCount超了给个提示而不是直接覆盖。表头列建议固定成日期、班次、产量、运行时长、停机次数、备注。列顺序和 SQL 查询的 SELECT 顺序对齐VBA 里就能按索引循环写不用一列一列拼字段名。4.3 VBA 引用与取数代码原文写至少钩选以下三项但没列全按这套链路的实际需要VBA 编辑器里工具 → 引用至少要勾上这三样引用名称作用版本差异Microsoft ActiveX Data Objects 2.8 LibraryADO 连接和记录集2.5/2.6/2.8 都能用选最高版本Microsoft Office xx.0 Object LibraryOffice 通用对象Excel 2010 是 14.02013 是 15.02016 是 16.0Microsoft Forms 2.0 Object Library控件对象如果有下拉框部分精简安装里缺失需要单独注册 fm20.dll少勾 ADO 是最常见的报错是用户定义类型未定义指向ADODB.Connection那一行。少勾 Forms 2.0 时报错指向下拉框控件提示对象库无效。这两个错误的解决方式都是回引用窗口补勾不是改代码。取数的主过程长这样 按日期区间取日报数据返回记录集 Public Function QueryDaily(ByVal dStart As Date, ByVal dEnd As Date) As ADODB.Recordset Dim cn As ADODB.Connection Dim cmd As ADODB.Command Dim p1 As ADODB.Parameter Dim p2 As ADODB.Parameter Set cn New ADODB.Connection 连接串与 Intouch 侧保持同一套账户便于统一排查 cn.ConnectionString ProviderSQLOLEDB;Data SourceSCADA-01; _ Initial CatalogYADC_BB;User IDscada_writer;Password换成实际密码; cn.ConnectionTimeout 5 5 秒连不上就报错不要无限等 cn.Open Set cmd New ADODB.Command Set cmd.ActiveConnection cn cmd.CommandType adCmdText 用参数化查询不要把日期字符串拼进 SQL cmd.CommandText SELECT RecordTime, ShiftNo, OutputQty, RunFlag _ FROM dbo.TDays WHERE RecordTime ? AND RecordTime ? _ ORDER BY RecordTime Set p1 cmd.CreateParameter(pStart, adDBTimeStamp, adParamInput, , dStart) Set p2 cmd.CreateParameter(pEnd, adDBTimeStamp, adParamInput, , dEnd) cmd.Parameters.Append p1 cmd.Parameters.Append p2 Set QueryDaily cmd.Execute End FunctionConnectionTimeout 5是我加的默认是 30 秒网络一断报表就卡半分钟用户会以为程序死了。adDBTimeStamp是参数类型对应 SQL 的 datetime用adVarChar传日期字符串会走隐式转换遇到非 ISO 格式就报错。参数化查询除了防注入更重要的是让日期值由驱动层去转换绕开 2.3 节说的格式问题。调用侧的代码 刷新按钮绑定的宏 Sub RefreshDaily() Dim rs As ADODB.Recordset Dim ws As Worksheet Dim r As Long On Error GoTo EH Set ws ThisWorkbook.Worksheets(参数日报) ws.Range(RPT_DATA).ClearContents 先清空旧数据避免残留 Set rs QueryDaily(ws.Parent.Worksheets(控制面板).Range(B2).Value, _ ws.Parent.Worksheets(控制面板).Range(B3).Value 1) r 4 Do Until rs.EOF ws.Cells(r, 1).Value rs.Fields(RecordTime).Value ws.Cells(r, 2).Value rs.Fields(ShiftNo).Value ws.Cells(r, 3).Value rs.Fields(OutputQty).Value ws.Cells(r, 4).Value rs.Fields(RunFlag).Value r r 1 rs.MoveNext Loop ThisWorkbook.Worksheets(控制面板).Range(B6).Value _ 刷新于 Format(Now, yyyy-mm-dd hh:mm:ss) 共 (r - 4) 条 rs.Close Set rs Nothing Exit Sub EH: ThisWorkbook.Worksheets(控制面板).Range(B6).Value 刷新失败: Err.Description End Sub结束日期1是因为查询用的是上界用户选到 5 月 1 日实际要包含 5 月 1 日全天所以上界得是 5 月 2 日零点。这个加一不加一直接决定了报表最后一天有没有数据属于典型的差一天问题。错误处理里把Err.Description写到控制面板比弹 MsgBox 好因为现场操作员看不懂英文报错但把错误信息留在单元格里运维远程一看就知道是连接超时还是权限问题。5. 避坑与排查连不上、写不进、报表报错的五条血泪记录5.1 现象Connid1 一直是 0脚本执行了但没连上现象运行时里条件脚本在跑标记监视看到Connid1始终是 0SQL Server 的错误日志里能看到 18456 登录失败或者干脆什么记录都没有。原因分三种。第一种是身份验证模式没切成混合只改了 SSMS 里的选项但没重启 SQL Server 服务IsIntegratedSecurityOnly还是 1。第二种是网络层没通TCP/IP 协议没启用或者防火墙拦了 1433此时从本机 SSMS 能连走共享内存从 Intouch 那台机器连不上。第三种是连接串里的Data Source写错了命名实例漏了\实例名或者计算机名带了域名后缀而 SQL Server 只监听短名。解决按顺序排。先跑SELECT SERVERPROPERTY(IsIntegratedSecurityOnly)返回 1 就回去改注册表并重启服务。再在 Intouch 那台机器上跑Test-NetConnection -ComputerName SCADA-01 -Port 1433不通就先解决网络。最后把连接串里的Data Source换成 IP 试一次IP 能连、主机名不能连就是名称解析的问题在 hosts 文件里加一条静态记录比折腾 DNS 快得多。5.2 现象SQLInsert 执行了表里就是没数据现象Connid1是正数说明连接建立了脚本里的SQLInsert那一行也确实被执行到在脚本里临时加一个计数标记能验证但SELECT COUNT(*) FROM TDays一直是 0。原因九成是绑定列表和表对不上。三种具体形态绑定列表名和SQLInsert第二个参数不一致比如列表叫TDays_List代码里写TDays绑定列表里某个标记的列名拼错了或者大小写和建表时不一致标记类型和列类型不兼容比如离散标记绑到了 INT 列上某些版本会静默丢弃这一行。解决打开 SQL 访问管理器把绑定列表逐行对着sys.columns查一遍-- 列出目标表的所有列和绑定列表逐行对照 SELECT c.name AS 列名, t.name AS 类型, c.max_length, c.is_nullable FROM sys.columns c JOIN sys.types t ON c.user_type_id t.user_type_id WHERE c.object_id OBJECT_ID(dbo.TDays) ORDER BY c.column_id;对照完把不一致的改掉重启运行时再测。另外提醒一句SQLInsert插入的是绑定列表当前时刻的快照如果列表里的标记在这段时间内没有更新过插进去的就是旧值看起来像没写。验证时手动改一个标记的值再触发一次写入看值有没有跟着变。5.3 现象日期列写进去变成 1900-01-01 或者直接报转换溢出现象表里有数据但RecordTime全是1900-01-01 00:00:00或者脚本执行到 SQLInsert 时运行时的日志里出现从字符串转换日期和/或时间时转换失败。原因前者通常是绑定列表里把日期列绑到了一个空的或初值为 0 的标记上1900-01-01 是 SQL Server datetime 类型的零值。后者是字符串格式和服务器语言设置不匹配2024/5/1在某些语言下解析不了05/01/2024会被按 mm/dd 解析成 1 月 5 日。解决先按 2.3 节把短日期固定成yyyy-MM-dd再确认绑定列表里日期列绑的标记确实有值。如果是脚本里自己拼的字符串统一用Format或者 Intouch 的格式化函数输出 ISO 格式 拼日期字符串时强制 ISO 格式不要依赖系统默认 GetDateTimeS Format($Date, yyyy-mm-dd) Format($Time, hh:mm:ss);改完重启运行时把已经写坏的 1900 那几行删掉再测。历史数据里如果有这种脏行Excel 报表按日期排序时它们会全堆在最前面看着像报表坏了。5.4 现象Excel 打开报表提示用户定义类型未定义现象双击模板宏被拦下来点启用宏之后弹出编译错误高亮在Dim cn As ADODB.Connection这一行提示用户定义类型未定义。原因VBA 工程里没有引用 Microsoft ActiveX Data Objects。可能的原因有三种模板是从别的机器拷来的引用路径指向一个本机不存在的版本Office 安装时没装数据访问组件或者引用被手动取消勾选了。解决VBA 编辑器 → 工具 → 引用找到Microsoft ActiveX Data Objects 2.8 Library勾上。如果列表里根本没有这一项说明系统缺 MDAC/MSOLEDB 组件装一下 SQL Server 客户端工具或者单独装数据访问组件就有了。勾完如果提示找不到工程或库说明有别的引用失效了把带MISSING字样的取消勾选再重新勾 ADO。 快速检查引用是否生效放在立即窗口里执行 能打印出版本号说明 ADO 可用 Debug.Print ADO 版本: ADODB.Connection.Version5.5 现象附加数据库失败提示无法打开物理文件现象把YADC_BB.mdf和YADC_BB_log.ldf拷到目标机的E:\DataBase下SSMS 里右键附加选文件后报无法打开物理文件操作系统错误 5拒绝访问或者错误 5120。原因三种。权限问题最常见SQL Server 服务的启动账户对E:\DataBase目录没有读权限。第二种是文件属性带只读从光盘或者压缩包里解出来的文件经常带着只读标记。第三种是版本不兼容高版本实例创建的 mdf 不能附加到低版本实例上反过来也不行。解决先给目录授权用服务的实际启动账户# 先查服务账户再按账户授权不要直接给 Everyone 完全控制 $svc (Get-CimInstance Win32_Service -Filter NameMSSQLSERVER).StartName icacls E:\DataBase /grant ${svc}:(OI)(CI)R # 去掉只读属性 Get-ChildItem E:\DataBase\*.mdf,E:\DataBase\*.ldf | Set-ItemProperty -Name IsReadOnly -Value $false授权完重新附加。如果报的是版本不兼容错误提示里会带版本号比如数据库版本 706 无法降级那就只能找对应版本的实例来附加或者用生成脚本加导入导出的方式迁数据别在附加这条路线上死磕。还有一个小坑附加之前确认E:\DataBase目录下除了这两个文件没有别的同名 mdf否则 SSMS 的文件选择框可能让你选错附加进去的不是你以为的那个库。6. 装完怎么验证从 SQL 里捞出一行数据再到 Excel 出第一张日报验证要从下游往上游倒着走这样每步失败都能定位到具体环节。我一般按这五步顺序验证动作通过标准失败先看哪1SQL 里查表结构列名类型和绑定列表一致建表脚本、排序规则2Intouch 运行时看 Connid1值大于 0身份验证、端口、连接串3手动触发一次写入表里新增一行且值正确绑定列表、WSQLS 闸门4Excel 里点刷新控制面板显示N 条VBA 引用、查询条件5连续跑两小时再查行数增量符合预期条件脚本周期、重复写入第 3 步是分水岭。前面两步都过了、这一步不过问题一定在绑定层这一步过了第 4 步不过问题一定在 Excel 侧。别跳步跳步的结果就是在两边来回猜。第 3 步具体怎么做把条件脚本临时改成$Second3一分钟三次方便观察盯住标记监视里的WSQLS看它是不是从 0 变 1然后立刻去 SSMS 里跑-- 看最近 10 条写入确认时间、机器名、数值都对 SELECT TOP 10 RecID, RecordTime, NodeName, ShiftNo, OutputQty, RunFlag FROM dbo.TDays ORDER BY RecID DESC;RecordTime跟当前时间差在合理范围内、NodeName是OP_01、OutputQty不是 0三条都对才算通过。如果RecordTime差了几个小时回去查时区设置如果NodeName是别的机器名回去查GetNodeName那个 131 参数有没有把名字截断。第 5 步的连续验证最容易被省略但它能抓出一类只在长时间运行后才暴露的问题WSQLS闸门没复位导致第二天不再写入、连接句柄泄漏导致会话数增长、Excel 模板数据区行数写满后覆盖。我一般跑一个班次8 小时再查一次行数日报表按每小时最后两分钟写入8 小时应该多出 16 行左右偏差超过两行就要回头查条件脚本的触发周期。从那以后我每次装这套链路都会在第 3 步之后强制等一个完整的结算窗口再往下走不再相信第一次写成功就代表一直会成功。这套东西的绝大部分故障都不是装的时候暴露的是跑了几天之后才慢慢浮现出来的早等半小时比事后翻日志省事得多。希望帮到你。本文还有配套的精品资源点击获取

相关推荐

快慢指针算法解析:环形链表检测与环起点定位
快慢指针算法解析:环形链表检测与环起点定位

1. 环形链表问题概述 遇到环形链表问题时,很多开发者第一反应是使用哈希表记录访问过的节点。这种方法确实可行,但需要O(n)的空间复杂度。更巧妙的解法是使用快慢指针(Floyd判圈算法),它能在O(1)空间复杂度内解决问题。… · 2026/11/4 12:33:23

LSTM网络原理与实战:从门控机制到工业应用
LSTM网络原理与实战:从门控机制到工业应用

1. LSTM网络的前世今生 第一次接触LSTM是在2016年的一个时序预测项目上。当时用传统RNN处理传感器数据时,模型总是记不住三天前的关键特征,直到同事推荐了LSTM这个"记忆大师"。这种能够自主决定记住什么、忘记什么的网络结构,彻底改… · 2026/11/4 12:33:23

从贝尔曼方程到Q-learning:强化学习的数学原理与工程调试
从贝尔曼方程到Q-learning:强化学习的数学原理与工程调试

简介:《强化学习的数学原理》英文专著PDF,由西湖大学赵世钰教授撰写,面向希望从数学层面系统理解强化学习的学习者与研究者,也适合具备一定数学基础、需要夯实理论框架的读者。全书从基础概念与网格世界示例切入,依次讲… · 2026/11/4 12:32:22

Harness套Harness:双层架构实现Coding Agent连续70轮不崩
Harness套Harness:双层架构实现Coding Agent连续70轮不崩

1. 从"套娃"说起:Harness 套 Harness 到底在解决什么问题 第一次看到"Harness 套 Harness"这个说法,我脑子里蹦出来的画面是俄罗斯套娃——一层包一层,每层都在干自己的活。但真正跑过几轮之后才明白,这个比喻… · 2026/11/4 13:22:02

Windows Sandbox中CreateProcessAsUserW失败原因与修复方案
Windows Sandbox中CreateProcessAsUserW失败原因与修复方案

1. 这个错误不是权限问题,而是沙盒环境的“身份错位” 第一次在某跨平台系统开发中遇到 CreateProcessAsUserW failed: 2 报错时,我下意识去查 Windows 权限策略、UAC 设置、管理员组成员关系——整整花了三小时翻文档、改组策略、重装沙盒功能&#x… · 2026/11/4 13:22:02

MCP协议:AI工具间的高效通信解决方案
MCP协议:AI工具间的高效通信解决方案

1. 项目概述:AI时代的"巴别塔"解决方案 在AI工具爆发式增长的当下,每个开发者都深有体会:不同AI系统间的沟通成本高得惊人。就像一群说着不同方言的人试图合作,明明都在讨论同一个话题,却因为语言不通导致效… · 2026/11/4 13:22:02

AI代码助手实战避坑:漏洞排查与兼容性验证指南
AI代码助手实战避坑:漏洞排查与兼容性验证指南

1. AI代码助手实战避坑:自动生成代码看似高效,隐藏的漏洞、兼容性问题如何排查用AI代码助手写代码这件事,我从两年前就开始深度使用了。从最初的新鲜感,到后来被生成的代码坑得加班到凌晨,再到现在形成一套相对成熟的排… · 2026/11/4 13:22:02

AI代码助手避坑指南:漏洞、兼容性与规范排查实战
AI代码助手避坑指南:漏洞、兼容性与规范排查实战

1. 自动生成的代码为什么总在联调时翻车 用AI代码助手写代码这件事,我身边不少同行已经从"尝鲜"变成了"日常"。尤其是Java后端和做工业控制的朋友,前者用Copilot、通义灵码这类工具补全Service层和Controller层,后者甚至… · 2026/11/4 13:22:02

工业机器人控制器软件选项配置与运动性能选型指南
工业机器人控制器软件选项配置与运动性能选型指南

简介:《ABB机器人系统选项介绍.pdf》面向ABB机器人调试、维护及自动化集成学习者,帮助解决系统选项认识零散、选型与配置依据不足的问题,适合具备一定基础、希望系统梳理RobotWare功能体系的工程师查阅。整包仅含1个PDF文件,约3.9… · 2026/11/4 13:21:00

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 3:16:49

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 6:59:29

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 7:02:38

AI辅助技术栈评估:提升研发决策效率60%
AI辅助技术栈评估:提升研发决策效率60%

1. 项目背景与核心价值技术决策一直是研发团队面临的重大挑战。随着技术生态的快速演进,技术栈的选择、维护和迭代变得愈发复杂。我们团队在过去两年里,先后经历了三次重大技术栈迁移,每次都需要投入大量人力进行技术评估和风险分析。直到去年… · 2026/11/4 0:00:17

从生成Token到直接决策:Jev如何重塑AI Agent工程实践
从生成Token到直接决策:Jev如何重塑AI Agent工程实践

1. 从"生成文字"到"拍板决策":Jev 到底在解决什么问题大多数人第一次接触大模型,脑子里建立的模型是"输入问题、输出文字"。你问它今天天气怎么样,它给你一段描述;你让它写个周报,它给你… · 2026/11/4 0:00:17

32G统一内存跑大模型:内存账、TPS实测与端云分流
32G统一内存跑大模型:内存账、TPS实测与端云分流

想在一台 32G 统一内存的小主机上把大模型跑成"日常可用",这件事我前后折腾了小半年。标题里说的这台 Mac mini M6,是我们这次讨论的目标平台,具体到手规格以实物为准;但下面这套推算方法和实测思路,对任何统… · 2026/11/4 0:00:17

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 3:16:49

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 6:59:29

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 7:02:38

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码