简介基于 IFIX 组态软件的历史报警数据存储与查询实操文档面向工业监控实施与运维人员、组态软件学习者解决报警记录经 ODBC 写入 Access 并按时间段查询的问题。内容从 ODBC 数据源创建讲起逐步覆盖 SCU 报警 ODBC 服务配置、日期时间控件与 vxData/vxGrid 控件绑定并给出 VBA 初始化及查询按钮完整代码涉及 Myalarm 数据源、FIXALARMS 报警表、SQL 时间参数等关键细节。资源包仅含 1 个 doc 文件大小 53KB篇幅紧凑适合现场调试直接参考或用于培训讲解。通过学习可掌握 IFIX 连接 Access 的完整配置流程理解报警表字段与查询语句写法并借助完整代码快速搭建报警查询界面。目前已有 179 人学习浏览是一份小巧实用的工业数据存储案例资料。1. IFIX 历史报警存储查询这套 Access ODBC 方案为什么还在用做组态项目的人应该都遇到过这个场景现场报警来了操作员问“昨天下午三点那几条报警到底是什么时候恢复的”你翻开 IFIX 的历史报警表发现数据要么没存下来要么存下来了根本查不出来。我拆过不少 IFIX 4.0 的老项目发现大部分报警存储查询问题归根结底不是 IFIX 本身的问题而是 ODBC 数据源没配好、SCU 报警服务没启动、VBA 查询语句里的时间参数格式不对这三件事。这份《关于 IFIX 历史报警数据存储与查询实例》正是围绕这三件事展开的先用 ODBC 把 IFIX 报警写到 Access 数据库再在 SCU 里把报警 ODBC 服务启起来然后用 vxData vxGrid 两个控件做查询界面最后用 VBA 脚本按时间段检索 FIXALARMS 表。整个链路不复杂但每一步都有容易翻车的细节尤其是 Access 数据库的压缩处理和 ODBC 连接池的设置。适合正在做 IFIX 组态项目、需要把报警记录落库并做简单查询的工程师也适合维护老项目时被报警数据只存不查困扰的人。2. ODBC 与 SCU 配置把报警数据先落进 Access 再谈查询2.1 数据源配置用户 DNS 和连接池必须一起处理IFIX 报警要写进 Access第一步不是在 IFIX 里配置而是先在 Windows 的控制面板里建 ODBC 数据源。打开 控制面板 → 管理工具 → 数据源 ODBC选“用户 DSN”点添加驱动选 Microsoft Access Driver (*.mdb)。数据源名填 Myalarm数据库指向你准备好的 Access 文件 Alarm.mdb注意这里有个容易忽略的选项连接池。提示原文里特别强调了连接池要“禁止”这一步很多人跳过。IFIX 报警服务是通过 ODBC 持续写数据库的如果开了连接池Access 文件会被长期占用后面做数据库压缩、备份、替换文件时会出现文件被锁的情况直接报“无法更新”或者“记录锁定”错误。这个数据源名的拼写很关键因为后面 SCU 的数据库标识符、vxData 控件的 DNS 名、VBA 脚本里的连接串全部都要用 Myalarm 这个名字一处不一致就连接不上。我一般会把这个名字记在项目的配置说明文档里避免后面维护的人自己另起一个名字导致连不上。2.2 SCU 报警 ODBC 服务区域选择决定哪些报警会落库ODBC 数据源建好之后打开 IFIX 的 SCU进入 配置 → 报警 → 报警 ODBC 服务。启动这个服务后点修改按钮在报警区域数据库里选择你项目对应的区域。以这份文档里的项目为例区域是 CLQS-ALM选中后点增加然后配置数据库类型为 Access数据库标识符填 Myalarm也就是上一步建的那个 DSN 名称。列配置默认选 9 项这里不要随便缩减。IFIX 报警写入 Access 时FIXALARMS 表里的字段数量和顺序是由这个列配置决定的如果你只选了 5 项后续 VBA 查询里用的 ALM_NATIVETIMEIN、ALM_NATIVETIMELAST 这些字段就没有数据查询结果全是空记录。表名默认是 FIXALARMS一般不建议改因为后面的 SQL 语句里直接用了这个表名改成别的名字意味着所有查询脚本都要跟着改徒增出错概率。这里有一个很容易被忽视的逻辑SCU 的报警 ODBC 服务启动后IFIX 运行时只要产生报警就会自动 INSERT 一条记录到 FIXALARMS 表。如果这个服务没有启动前面 ODBC 数据源建得再好也没用报警记录不会自动落库。你可以这样验证在 IFIX 运行画面里触发一条报警然后用 Access 打开 Alarm.mdb看 FIXALARMS 表有没有新增记录。2.3 权限与文件位置Access 文件的物理路径不要乱放Access 数据库文件 Alarm.mdb 放在哪个盘、哪个目录看起来是小事实际影响很大。文档里写的是 D 盘但我在实际项目中见过有人放在 C 盘 Program Files 目录下结果 Windows 的 UAC 权限控制导致 IFIX 写入时被拒绝报警数据一条都没存进去。Access 文件建议放在数据盘的专用目录比如 D:\AlarmDB\并且给 Users 组授予完全控制权限避免因为权限问题导致写入失败。另外要确认 Access 驱动程序版本。IFIX 4.0 时代默认用的驱动路径是 Microsoft Access Driver (*.mdb)如果你在 64 位系统上装 32 位的 IFIXODBC 里会同时出现 32 位和 64 位两个版本的 Access 驱动选错了位数就会测试连接失败。这个在后面排查章节会细说。3. 控件引用与变量绑定日期控件、vxData、vxGrid 三层搭档3.1 日期时间控件VB6 组件在 IFIX 画面里的引用方式IFIX 画面的 VBA 环境基于 VB6所以日期时间控件用的是 Microsoft date and time picker 控件典型安装 VB6.0 之后在 IFIX 画面工具箱里双击即可添加。日期控件的属性设置有两个关键点格式选择 1-dtpShortDate有效选项前不打勾时间控件的格式选择 2-dtpTime同样不打勾。“有效前不打勾”指的是控件的 CheckBox 属性默认是打勾的表示控件前面会显示一个勾选框。报警查询界面里不需要用户去勾选日期是否有效直接显示日期就行所以这里要去掉。如果你不打勾这项运行界面上日期控件旁边会出现一个小方块用户容易误操作查询时传进去的时间值也可能带上无效状态。日期控件和时间控件分开设置是为了查询界面更直观。左边选日期右边选时间默认值由 VBA 初始化脚本控制后面会讲。这里需要注意日期控件的 Value 属性返回的是 Date 类型时间控件的 Value 属性返回的是 Time 类型两者不能直接拼字符串必须用 Format 函数统一格式化。3.2 vxData 控件ODBC 数据管道是整套方案的中枢vxData 是 IFIX 里的数据管道控件负责执行 SQL 查询并把结果集交给显示控件。在 IFIX 工具箱底部找到 vxData 图标右键打开属性页提供者选择 Microsoft OLE DB Provider for ODBC Drivers数据库 DNS 名填 Myalarm用户名和密码留空先点测试连接确认弹出“测试连接成功”的提示再继续。测试连接成功只说明 ODBC 链路通了不代表查询能出数据。下一步要设置记录源的命令类型为“SQL 命令”这样 vxData 才会按照你后面写的 SQLCommand 去执行动态查询。很多人在这一步翻车命令类型默认是“表”VBA 里写 SQLCommand 赋值不生效vxGrid 上什么都不显示。vxData 有 QP1、QP2 等参数占位符这是这套方案查询时间范围的机制。在 VBA 脚本里给 QP1、QP2 赋值后SQLCommand 字符串里用 {ts QP1} 这样的写法引用参数vxData 会自动把参数值替换进 SQL 语句。这个设计的好处是不用在 VBA 里手动拼 SQL 字符串避免日期格式转义问题。3.3 vxGrid 控件把结果集显示到画面上的最后一步vxGrid 是数据显示网格同类控件还有 IFIX 的 Grid 控件但 vxGrid 跟 vxData 配合更直接。在工具箱底部选中 vxGrid 图标放到画面里右键进入动画 → 高级动画配置找到行为选项卡把 ADORecords 动画打勾数据源选“报警记录一览表.vxData1.ADORecords”数据转换选“对象”。这一步的操作顺序不能反必须先建好 vxData 并完成连接配置再配置 vxGrid 的数据源。如果先配置 vxGrid下拉列表里找不到 vxData1.ADORecords还得回来重新绑。报警记录一览表是 vxData 所在画面的名字如果你的画面叫别的名字这里要对应修改。数据转换选“对象”而不是其他选项是因为 ADORecords 本身已经是 ADO 记录集对象选对象模式直接绑定不需要经过格式转换。选错了转换类型运行时会提示类型不匹配网格上只有列头没有数据。我把三个控件的关系整理成了表格式的对应关系方便对照检查控件作用关键配置常见错误Date/Time Picker提供查询起止时间格式 1-dtpShortDate / 2-dtpTime有效选项打勾导致界面多选框vxData执行 SQL 查询提供者 ODBCDNS 名 Myalarm命令类型默认“表”导致 SQL 不生效vxGrid显示查询结果ADORecords 绑定 vxData1.ADORecords数据源选不到 ADORecords 属性4. VBA 脚本与时间查询QP1/QP2 参数和 SQL 别写错格式4.1 初始化脚本默认查询范围是昨天到现在画面初始化的时候要给两个日期时间控件设置默认值让用户一打开查询界面就能直接点查询不需要手动选时间。在 CFixPicture_Initialize 事件里写这段代码初始化设置 Private Sub CFixPicture_Initialize() 设定默认开始时间 Me.DTPFromDate DateAdd(d, -1, Now) Me.DTPFromTime (00:00:00) 设默认结束时间 Me.DTPEndDate Now Me.DTPEndTime Now End Sub这段代码的逻辑是把起始日期设为昨天起始时间设为零点结束日期和结束时间都设为当前时刻这样默认查询范围就是最近 24 小时。DateAdd(d, -1, Now) 是 VB6 里对当前时间减一天的标准写法比 Now - 1 更明确不容易产生歧义。需要说明的是原文档里初始化脚本中有一段被注释掉的 QP1/QP2 赋值代码那是在画面加载时预填查询参数实际上是没必要的因为真正触发查询是在 CmbSearch_Click 事件里。保留初始化脚本里对日期控件的赋值就够了QP1/QP2 在查询事件里再赋画面加载时不触发数据刷新避免画面一打开就去查一次库。4.2 查询按钮事件QP1/QP2 参数赋值是核心点击“查询”按钮后执行的逻辑是从日期时间控件读取用户选择的时间范围赋值给 vxData1 的 QP1、QP2 参数刷新 vxData 和 vxGrid。完整代码如下开始查询 Private Sub CmbSearch_Click() 连接自动刷新 Me.vxData1.AutoRefresh True Format 函数用于设定时间格式 vxData1.QP1 Format(Me.DTPFromDate.Value, yyyy-MM-DD) Format(Me.DTPFromTime.Value, HH:MM:SS) vxData1.QP2 Format(Me.DTPEndDate.Value, yyyy-MM-DD) Format(Me.DTPEndTime.Value, HH:MM:SS) 设定查询内容 从数据库中查询符合时间段的数据 Me.vxData1.SQLCommand SELECT * FROM FIXALARMS WHERE _ (FIXALARMS.ALM_NATIVETIMEIN {ts QP1}) AND (FIXALARMS.ALM_NATIVETIMELAST {ts QP2}) 刷新数据 Me.vxData1.Refresh Me.vxGrid1.Refresh End Sub这里每个点都能拆开讲。AutoRefresh 属性设为 True意思是每次执行 SQLCommand 赋值后自动刷新记录集不设的话你还要手动调用 Refresh而且可能拿到的是上一次查询的缓存结果。Format 函数里 yyyy-MM-DD 和 HH:MM:SS 是关键IFIX 的 Access 表里时间字段是标准日期时间类型必须格式化成这种字符串才能被 SQL 正确识别。SQL 语句里用了 {ts QP1} 这种 ODBC 转义语法。{ts ...} 表示这是一个 ODBC 时间戳字面量Access 的 ODBC 驱动认识这种写法比直接传 2024-01-15 14:30:00 字符串更可靠。需要注意的是原文档里 SQL 语句的 WHERE 后面直接跟了 FIXALARMS.ALM_NATIVETIMEIN字段名是表名前缀加列名如果你在 SCU 里改了默认表名这里的前缀也要同步改。4.3 SQL 语义与参数替换机制为什么是 IN 和 LAST 两个字段FIXALARMS 表里有多个时间字段查询条件只用了其中两个ALM_NATIVETIMEIN 和 ALM_NATIVETIMELAST。前者是报警发生时的本机时间后者是报警恢复到正常状态的时间。查询条件这样写的意思是报警的发生时间晚于查询开始时间并且恢复时间早于查询结束时间。这里隐含了一个业务逻辑报警记录可能跨查询窗口。比如你查 8:00 到 10:00 的报警有一条报警 7:55 发生、8:30 恢复它按 ALM_NATIVETIMEIN QP1 是不成立的所以不会被查出来尽管它的大部分时间在查询窗口内。如果你希望把这类跨窗口的报警也查出来需要增加一个 OR 条件ALM_NATIVETIMELAST QP1 AND ALM_NATIVETIMEIN QP2。我一般根据现场需求二选一默认按原文档的写法多数情况下够用。vxData 的参数替换机制是SQLCommand 字符串里的实物参数占位符会被 QP1、QP2 的当前值替换。所以 QP1/QP2 赋值必须放在 SQLCommand 赋值之前否则 vxData 执行的是上次查询的参数或者第一次执行时参数为空查出来零条记录。4.4 查询结果为空时先检查这个顺序写完了 VBA运行后发现点查询没有数据第一反应不要去看 SQL 语法先按照这个顺序排查vxData 测试连接是否成功 → SCU 报警 ODBC 服务是否启动 → FIXALARMS 表里是否有数据 → QP1/QP2 时间范围是否覆盖了报警时间 → SQLCommand 赋值语句是否被执行。这个顺序是从数据流向逆推的能快速定位问题在哪一层。5. 避坑排查与翻车现场从连接到时间格式的五个常见问题5.1 ODBC 测试连接成功但 vxData 报错“未找到提供程序”现象ODBC 数据源测试连接正常IFIX 画面里 vxData 测试连接却报“未找到提供程序”之类的错误。原因IFIX 4.0 是 32 位应用如果你在 64 位 Windows 上运行控制面板里默认打开的是 64 位 ODBC 管理工具你创建的 DSN 是 64 位的32 位的 IFIX 根本看不到。常见做法是用 C:\Windows\SysWOW64\odbcad32.exe 打开 32 位 ODBC 管理器重新创建 Myalarm 数据源。解决先确认 IFIX 位数如果是 32 位就用 SysWOW64 目录下的 ODBC 管理器建数据源如果是 64 位用常规管理器。创建完后在 vxData 测试连接之前先重启一次 SCU让 IFIX 重新读取 ODBC 配置。5.2 报警不落库FIXALARMS 表一直是空的现象IFIX 画面运行正常报警也触发了但打开 Access 的 FIXALARMS 表一条记录都没有。原因SCU 里的报警 ODBC 服务没有启动或者启动了但区域选择错误。报警 ODBC 服务是按区域过滤的如果 SCU 里选择的区域和触发报警的画面区域不一致报警不会写入 ODBC 数据库。“区域”选错不是报错而是静默失败这也是这条坑容易漏的原因。解决打开 SCU → 配置 → 报警 → 报警 ODBC 服务确认服务状态是启动并检查区域列表里有没有你项目的区域。改完之后要退出 IFIX 重新进入SCU 配置在运行时修改不能即时生效。5.3 查询时间范围只有 00:00:00 一条数据现象点查询按钮vxGrid 只显示一条记录时间正好是零点其他报警都没显示。原因日期控件和时间控件的 Value 值拼接时出了问题。时间控件用的是 dtpTime 格式如果 DTPFromTime 没有被正确赋值默认可能是 00:00:00而 Format 函数把它格式化成了固定的 00:00:00导致 QP1 里的时间部分恒为零点。解决检查初始化脚本里 DTPFromTime 和 DTPToTime 的赋值语句是否在 CFixPicture_Initialize 里如果画面加载时事件没触发控件保持默认值就会出这个问题。另外把 Format 的时间格式改成 HH:mm:ss 更严谨但 VB6 的 Format 函数默认情况下两者都能识别如果你改了 24 小时制要注意系统区域设置。5.4 查询按钮第一次点击无反应第二次才出数据现象运行画面后第一次点查询网格空白第二次点才有数据。原因vxData 的 AutoRefresh 属性在第一次执行时没有生效或者 SQLCommand 赋值比 Refresh 执行晚。vxData 在打开画面时已经执行了一次默认的 SQL你第一次赋值后直接 Refresh它执行的还是旧 SQL。解决在查询按钮事件开头先执行 vxData1.Close 和 vxData1.Open然后再赋 QP1/QP2 和 SQLCommand最后 Refresh。这样做能强制 vxData 清理旧记录集避免第一次查询拿到缓存结果。5.5 时间格式不一致导致查询结果不完整现象部分报警能查到部分查不到查不到的报警看 Access 表里的时间是有的格式和界面显示的一样。原因Access 数据库里 ALM_NATIVETIMEIN 字段的存储格式受区域设置影响。如果你的系统区域设置是中文IFIX 写入 Access 的时间字段可能带“上午/下午”信息而 Format 函数生成的字符串没有SQL 比较时字段值强制转换失败或者比较结果不正确。解决在 ODBC 连接串里指定区域设置或者把 Access 字段格式强制改为 yyyy-mm-dd hh:nn:ss。更省事的做法是在 VBA 查询前先执行一条 SQL 把时间字段标准化可以用这个方式先 UPDATE FIXALARMS SET ALM_NATIVETIMEIN Format(ALM_NATIVETIMEIN, yyyy-mm-dd hh:nn:ss) 把存量数据清洗一遍再执行查询。6. Access 自动压缩防止报警库无限增长的实操技巧Access 数据库有个让人头疼的特性删除记录后文件不会自动变小因为删除操作只做物理标记不做物理清理数据页仍然占用空间。IFIX 报警表 FIXALARMS 是天天空增记录的如果长期不清理Alarm.mdb 会从几十 MB 涨到几个 GB打开变慢、写入变慢、备份更是噩梦。IFIX 运行时是以独占方式访问 Access 报警库的这种情况下你没法直接在 Access 里执行“工具 → 数据库实用工具 → 压缩和修复数据库”文件被锁住了。常见的做法是用一个替换法先把正在使用的 mdb 文件复制一份到临时目录用 Access 程序打开临时文件触发它的“关闭时压缩”设置等几秒后 Access 自动压缩完临时文件并退出再把压缩后的临时文件复制回原位置覆盖原文件。代码如下Private Declare Function FindWindow Lib user32 Alias FindWindowA _ (ByVal lpClassName As String, ByVal lpWindowName As String) As Long Private Declare Function SendMessage Lib user32 Alias SendMessageA _ (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Any) Dim Fso As New FileSystemObject Dim srcfile As String, desfile As String srcfile C:\Dynamics\MXLAlarm\S123.mdb desfile C:\Dynamics\MXLAlarm\Back\S123.mdb 先把库文件复制到临时目录 Fso.CopyFile srcfile, desfile, True 用 Access 打开临时文件注意要最小化运行 Shell C:\Program Files\Microsoft Office\OFFICE11\MSACCESS.EXE desfile, vbMinimizedNoFocus 等 5 秒让 Access 完成打开和压缩 Dim start As Single start Timer Do While Timer start 5 DoEvents Loop 找到 Access 窗口并发送关闭消息 Dim hw As Long, cnt As Long hw FindWindow(vbNullString, Microsoft Access) If hw 0 Then cnt SendMessage(hw, H10, 0, 0) End If 压缩完成后覆盖回原位置 Fso.CopyFile desfile, srcfile, True这段代码有两个前提需要先手工完成。第一用 Access 打开 S123.mdb在 工具 → 选项 → 常规 里勾选“关闭时压缩”这是压缩行为的触发开关代码本身不执行压缩只是打开再关闭真正的压缩动作由 Access 完成。第二VBA 环境里要勾选“Microsoft Scripting Runtime”的引用否则 FileSystemObject 对象无法创建。代码里 Shell 命令用的是 MSACCESS.EXE 和临时目录下的 mdb 文件如果你换成了别的 Access 版本OFFICE11 路径要改成对应版本的目录。注意 Shell 的启动方式是 vbMinimizedNoFocus这样 Access 窗口不会弹到前台干扰操作。FindWindow 查找窗口名 Microsoft Access如果机器上同时开着其他 Access 窗口可能误关比较稳妥的写法是用你临时数据库文件的完整路径作为窗口标题来查找。真正用时我会把它包装成一个子程序先删 FIXALARMS 表里 90 天前的记录再执行压缩。删除用一条 ADO SQL:Dim conn As New ADODB.Connection conn.ConnectionString ProviderMicrosoft.Jet.OLEDB.4.0;Data SourceD:\AlarmDB\Alarm.mdb; conn.Open conn.Execute DELETE FROM FIXALARMS WHERE ALM_NATIVETIMELAST DateAdd(d, -90, Now()), , adExecuteNoRecordsSet conn.Close Set conn Nothing删除后马上执行上面的压缩代码库文件体积能显著变小。如果压缩后文件大小没变化先看 Access 的“关闭时压缩”是否勾选再看临时目录和目标目录是否在同一分区跨分区复制可能导致压缩动作没生效。那以后我每次给 IFIX 项目做报警存储方案时都会强制走一遍这六个步骤ODBC 连接池禁止、SCU 区域核对、FIXALARMS 表字段确认、vxData 命令类型改 SQL、时间格式统一、压缩调度挂上这套流程做完再交付基本不会再收到半夜报警查不到数据的电话希望帮到你。本文还有配套的精品资源点击获取
