☰
Access数据库写入WinCC变量:ODBC+DSN+VBS脚本实战指南
2026/9/26 9:39:58 网站建设 项目流程

简介:这份文档面向工业自动化与过程控制领域的工程师及WinCC初学者,讲解如何借助VBS脚本将Access数据库中的指定数据写入WinCC变量,实现监控画面的实时数据联动。资料以实际操作为主线,完整演示了建立Wincc_Data数据库与数据表、配置名为Sample的ODBC数据源,并编写脚本查询Tag1字段第50条记录写入U16Tag1变量的全过程。代码中包括了ADODB连接、SQL查询、记录集读取及资源释放等关键步骤,同时涉及连接字符串、字段数量判断与异常输出等细节,可直接参考改造用于其他字段或变量。该文档示例清晰,不仅提供完整VBS代码,还解释了数据库表结构、ODBC配置要点以及脚本运行后的资源清理逻辑,能帮助读者理解数据库与WinCC交互的完整链路。资源为单个PDF文档,大小仅18KB,便于快速查阅;目前已有342人学习,适合在备考或项目开发中需要快速掌握WinCC与数据库通信方法的读者下载使用。

1. Access数据库写入WinCC变量:为什么这条数据通路值得打通

车间里最常见的场景是:MES 或实验室系统把批次号、配方参数、质检结果存在 Access 数据库里,中控室的 WinCC 画面上要实时显示这些数据。手抄进画面既慢又容易出错,直接用 WinCC 的 ODBC 能力把这层数据桥接起来,是很多项目里最省事也最可靠的做法。这篇技术笔记围绕 Access 数据库数据写入 WinCC 变量这个方向,把从 ODBC 驱动配置、DSN 建立、VBS 脚本编写到常见坑的完整过程说清楚。适合正在做 WinCC 画面集成、又不想为一个小功能引入整套数据库中间件的工程师。

2. 动手前先立好地基:ODBC驱动、系统DSN与WinCC变量表

2.1 驱动选型:为什么系统DSN比Jet/ACE直连更省心

要把 Access 数据库里的数据搬进 WinCC 变量,脚本层通常通过 ADO(ActiveX Data Objects)来做,但底层驱动有两条路:OLE DB 直连和 ODBC 数据源。我第一次做这个需求时图省事,直接用了 OLE DB 连接字符串,结果开发机上跑得好好的,打包到现场工控机就报“未找到提供程序”,折腾了快半天才发现是 Access Database Engine 的位数和 WinCC 进程位数不匹配。后来所有项目都改用系统 DSN,这一类的兼容性问题基本绝迹。

所谓系统 DSN,就是在 Windows 的 ODBC 管理器里先把 Access 数据库文件和一个名字绑定好,脚本里只写DSN=AccessData;这样一句话。好处有三个:一是驱动位数问题只在配置 DSN 时处理一次,不用每次改脚本;二是 Access 文件路径变了,只需要改 DSN 里的数据库路径,部署人员不碰代码也能维护;三是以后想把 Access 换成 SQL Server,脚本主体不用重写,DSN 换成 SQL Server 的驱动即可。

也要说清楚边界:Access 是单机文件型数据库,几百条到几万条的小数据量完全没问题,几十个客户端同时读写就会开始“卡”甚至锁库。如果数据量比较大、并发要求高,建议直接把后端换成 SQL Server,但下面这套 VBS + ADO 的写法仍然沿用,切换成本很低。

2.2 配置系统DSN:32位与64位分清楚

配置 DSN 时最容易埋雷的就是位数。WinCC 7.x 的运行时多数是 32 位进程,它只能看见 32 位 ODBC 数据源;64 位 Windows 上控制面板里的“ODBC 数据源管理器(64位)”注册在 System32 目录,给 32 位程序用是无效的。我一般直接在运行框输入:

C:\Windows\SysWOW64\odbcad32.exe

打开的是 32 位版本的 ODBC 管理器。如果安装的 WinCC 是 64 位版本,那就反过来用C:\Windows\System32\odbcad32.exe。判断方法很简单:脚本里用创建出来的 DSN 连接一次,报“未发现数据源名称并且未指定默认驱动程序”,十有八九就是位数不对。

打开管理器后按以下步骤配置:

  1. 切到“系统 DSN”选项卡,点“添加”。
  2. 在驱动列表里选“Microsoft Access Driver (*.mdb, *.accdb)”。如果列表里没有这个驱动,说明本机没装 Access 数据库引擎,需要先安装对应版本的 AccessDatabaseEngine 再重试。
  3. 填数据源名,例如 AccessData,点“选择”定位到 .mdb 或 .accdb 文件。
  4. 如果 Access 数据库设了密码,在“高级”里填登录名称和密码。
  5. 点“测试连接”,弹窗提示连接成功就算配好了。

注意这里要选“系统 DSN”而不是“用户 DSN”。WinCC 运行系统有时以服务方式启动,用户 DSN 只对当前登录用户可见,服务进程里很可能读不到;系统 DSN 对所有用户可见,更牢靠。另外,Access 驱动选错了也会出问题,旧版“Microsoft Access Driver (*.mdb)”只认 mdb 格式,遇到 accdb 文件就会提示“不是有效的文件路径”,这时优先找带 accdb 的那个驱动。

2.3 WinCC变量表设计:目标类型与Access字段一一对应

DSN 只是把路修通了,落数据还要靠 WinCC 变量。建议在变量管理里建一组专用的“DB_”前缀变量,和 PLC 变量分开,后面排查问题会省很多事。变量类型要和 Access 字段类型对应上,否则脚本写入时会自动转换甚至报错。

Access 字段类型WinCC 变量类型注意事项
整数(LONG/INT)有符号 32 位数数值超过 21 亿时改用 64 位变量
小数(DOUBLE/FLOAT)浮点数 32 位/双精度温度、压力这类过程值用浮点
文本(TEXT)文本变量注意 Access 旧版文本字段只有 255 字符
日期/时间(DATETIME)文本变量建议先在 SQL 里格式化,别直接写原始 OLE 日期
是/否(BIT)二进制变量读出来可能是 -1/0,写入前做一下转换

这里有一个容易被忽略的点:画面上的文本变量默认刷新周期可能不匹配,如果你把 Access 里的数值写到文本变量里,画面却半天不更新,先检查变量的更新周期,把它改成“画面周期”或“按需”再试。内部变量一般没有刷新周期问题,这也是我建议优先写内部变量的原因。

2.4 用脚本先验证连接:最小测试代码

DSN 配好、变量表建好之后,别急着写完整逻辑,先跑一段最小验证脚本。这段代码可以放在画面任意一个按钮的鼠标事件里,或者在全局脚本编辑器里手动执行。它只做一件事:通过 DSN 打开 Access,取第一条记录,弹窗显示出来。

Option Explicit Dim conn, rs Set conn = CreateObject("ADODB.Connection") conn.ConnectionString = "DSN=AccessData;" conn.Open Set rs = conn.Execute("SELECT TOP 1 id, batch_no FROM t_recipe") If Not rs.EOF Then MsgBox "连接成功,第一条记录 id=" & rs.Fields("id").Value & ",批次=" & rs.Fields("batch_no").Value Else MsgBox "连接成功,但表 t_recipe 是空的" End If rs.Close Set rs = Nothing conn.Close Set conn = Nothing

这段脚本里有两个关键点。第一,conn.Execute执行的是 SQL 查询,TOP 1限定了只取一条记录,既验证了连接,也验证了表名和字段名是否正确。第二,用rs.EOF判断是否查到了数据,空表时不会报“下标越界”。如果弹窗里显示的是“连接成功”,说明 DSN、表名、字段名这三个基础条件都过了,后面的写入逻辑可以放心往下写。

如果这里弹出错误,不用急着改脚本,先把错误原因分成两类:报“未发现数据源名称”是 DSN 位数或名称不对;报“文件正由另一个用户以独占方式打开”是 Access 文件被占用了。这两类问题在脚本层怎么改都解决不了,必须回到 DSN 配置或文件权限上处理。

3. 写出第一版可用的VBS脚本:连接、查询、写入三步走

3.1 脚本放在哪:全局脚本与画面脚本的取舍

WinCC 里能跑 VBS 的地方就那么几个:画面对象的属性/事件动作、全局脚本编辑器的函数动作。我的习惯是:通用逻辑放进全局脚本函数,画面按钮或者周期触发器只负责调用。

这样做的原因是,画面里可能要放一个“手动刷新”按钮,也可能要求每 5 秒自动刷新,如果把整段数据库逻辑复制到每个按钮里,后面要改 SQL 时就得改好几处,漏改一次就翻车。抽出全局函数后,按钮动作里就一句话:

Call ReadAccessToWinCC()

可读性也高。全局脚本编辑器在 WinCC 项目管理器的“全局脚本”节点下,VBS 函数创建后,先编译通过再引用。这段逻辑不依赖画面对象,调试时可以在编辑器的测试环境里直接跑,不用先激活项目再反复操作画面。

3.2 核心VBS脚本:Access查询结果写入WinCC变量

下面这段脚本是完整示例,功能是从 Access 的配方表里查一条“状态为 active”的记录,把批次号、温度设定值和最后更新时间分别写入三个 WinCC 变量。

Option Explicit ' 读取 Access 配方数据,写入 WinCC 内部变量 Dim conn, rs, sConn, sSQL ' 使用系统 DSN 连接 sConn = "DSN=AccessData;" ' 如果 Access 设置了密码,加上 PWD 参数 ' sConn = "DSN=AccessData;PWD=123456;" ' 查询条件:取状态为 active 的最新一条 sSQL = "SELECT TOP 1 batch_no, temp_set, last_time " & _ "FROM t_recipe " & _ "WHERE status='active' " & _ "ORDER BY last_time DESC" Set conn = CreateObject("ADODB.Connection") conn.ConnectionString = sConn conn.Open Set rs = conn.Execute(sSQL) If Not rs.EOF Then ' 写入 WinCC 变量,Write 方法返回布尔值 If HMIRuntime.Tags("DB_batch_no").Write(rs.Fields("batch_no").Value) Then HMIRuntime.Tags("DB_read_ok").Write 1 End If ' 浮点字段做一下类型转换,避免字符串写入 HMIRuntime.Tags("DB_temp_set").Write CDbl(rs.Fields("temp_set").Value) ' 日期字段格式化成字符串再写 HMIRuntime.Tags("DB_last_time").Write FormatDateTime(rs.Fields("last_time").Value, 2) Else HMIRuntime.Tags("DB_read_ok").Write 0 End If rs.Close Set rs = Nothing conn.Close Set conn = Nothing

脚本的逻辑是三步。第一步,用 DSN 建立 ADODB 连接,注意sConn只写了DSN=AccessData;,末尾分号是 ADO 连接字符串的固定写法,别省略。第二步,执行 SQL 查询得到记录集rs,通过Not rs.EOF判断是否有数据。第三步,用HMIRuntime.Tags("变量名").Write 值把字段值写入 WinCC 变量。

这里有几个参数值得单独说。HMIRuntime.Tags()是 WinCC VBS 访问变量的标准入口,变量名必须和变量管理里完全一致,大小写不敏感但建议统一。Write方法会返回布尔值,写入失败时是 False,所以代码里用一个状态变量记录结果,方便画面上显示。CDbl是把字段值强制转成双精度浮点,避免 Access 里数字字段被当成字符串写入 WinCC 浮点变量时出错。

3.3 连接字符串和SQL关键参数逐个说

连接字符串是整段脚本里最不能错的地方。用系统 DSN 时最简写法是:

DSN=AccessData;

如果 Access 数据库设了密码,追加PWD=...。有人会顺手写上UID=admin,对大多数 Access 文件是多余的,写了反而可能报“用户名无效”。如果你接的不是 DSN 而是直连 ACE 驱动,连接字符串要写成:

Provider=Microsoft.ACE.OLEDB.12.0;Data Source=D:\data\recipe.accdb;Persist Security Info=False;

两行都能用,但现场部署时 DSN 方案的重试成本更低,因为驱动问题在 ODBC 管理器里就能看见,而直连报错时只能对着连接字符串逐字检查。

SQL 语句建议用显式列名,不要写SELECT *。Access 表里如果有备注字段或 OLE 对象字段,SELECT *会把大字段也读出来,网络传输和记录集解析都会变慢。查询条件里用到字符串时,注意单引号包裹,像status='active'这样。如果这个条件来自画面输入框,直接把用户输入拼进 SQL 会有 Access 注入风险,稳妥做法是过滤掉单引号,或者用 ADODB.Command 参数化查询:

Dim cmd Set cmd = CreateObject("ADODB.Command") cmd.ActiveConnection = conn cmd.CommandText = "SELECT batch_no FROM t_recipe WHERE batch_no=?" cmd.Parameters.Append cmd.CreateParameter("p1", 202, 1, 50, batchNo) Set rs = cmd.Execute

这段代码里202是 adVarChar 的类型常量,1表示输入参数,50是字段长度。参数化之后,用户输入里的单引号不会再破坏 SQL 结构。Access 项目里日常操作也就是增删改查,本文场景常用的是“查”,用SELECT;如果还要从 WinCC 画面回写操作记录,换成UPDATE或INSERT语句即可,但这类写操作建议单独放一个函数,别混在周期刷新里。

3.4 加定时器:用触发器让数据自动刷新

手动执行脚本只能刷新一次,生产画面上通常要求周期性刷新。WinCC 的定时器做法有两种,最常见的是在全局脚本里给函数创建周期性触发器。在全局脚本编辑器中选中函数,右键“创建触发器”,选“周期”并设置时间,比如 5 秒。周期不建议小于 1 秒,脚本每次要建连接、执行查询、解析记录集,太频繁会出现上一次还没执行完下一次又触发的情况。

第二种是在画面上给某个对象设置触发器。比如把一个“文本”对象的属性挂上周期性触发器,并在它的动作里调用读库函数。这种做法适合只在画面打开时才刷新,画面关闭就不跑,能减轻数据库压力。

不管用哪种定时器,建议在脚本开头加一个执行时间判断,逻辑是:

Dim startTime startTime = Timer ' ...原有逻辑... If Timer - startTime > 3 Then HMIRuntime.Tags("DB_read_ok").Write -1 Exit Function End If

如果数据库文件放在网络共享盘上,网络抖动会让单次查询耗时变长,这个超时处理能避免脚本积压。超时时写一个 -1 到状态变量,画面上就能看到这次刷新是失败的,而不是傻等。

4. 数据写不进去或者写错值:5个高频坑与排查路径

4.1 找不到提供程序:Microsoft.ACE.OLEDB.12.0未注册

现象:脚本一执行就弹窗,提示“未找到提供程序”或者“未指定的错误”,用系统 DSN 时则提示“未发现数据源名称”。

原因:两种情况。第一种是用直连方式写了Provider=Microsoft.ACE.OLEDB.12.0;,但现场机器没装 Access Database Engine,或者装的是 64 位而 WinCC 进程是 32 位,驱动在 32 位环境里不可见。第二种是 DSN 配置到了错误的 ODBC 管理器里,位数对不上。

解决:统一改回系统 DSN 方案,在SysWOW64\odbcad32.exe里确认系统 DSN 列表里有 AccessData 这条记录。如果一定要用 ACE 直连,就安装对应位数的 AccessDatabaseEngine,装完再打开 ODBC 管理器看驱动列表里是否出现 ACE 相关条目。这里提示一点:装了 Access 数据库引擎后再装 Office,可能把驱动版本搞乱,最好在工控机上先把驱动装好再装 Office。

4.2 变量刚写进去就被打回原形:外部变量被PLC侧覆盖

现象:脚本执行后,WinCC 变量“看起来”写成功了,但画面上的值闪了一下又变回原来的。脚本里 Write 返回 True,但画面就是不对。

原因:最典型的情况是目标变量是外部变量,PLC 程序每个周期都在往这个地址写值。WinCC 的Write只把数据放到通信发送队列里,PLC 的下一次周期写入会把这个值覆盖回去,画面因此“反弹”。这种现象经常会被误报成 WinCC 握手错误,其实通道握手正常,问题出在变量写入竞争上。

解决:Access 数据先进内部变量,内部变量不与 PLC 通信,不存在外部写入竞争。画面显示用内部变量,如果 PLC 确实需要这份数据,再做一次内部变量到外部变量的同步,同步时机由 PLC 侧逻辑决定。临时排查时,可以先把变量管理里的目标变量类型改成内部变量试试,如果画面不再反弹,就证实了是覆盖问题。

4.3 “脚本语句未结束”:VBS换行与符号问题

现象:在 WinCC VBS 编辑器里保存脚本或编译时,报“脚本语句未结束”,有时还带“缺少对象”之类的后续错误。

原因:VBS 的合法语句以换行为界,一条逻辑行写不下时要加续行符“_”(下划线)。SQL 很长时很容易漏掉,或者写了续行符但下划线后面跟了空格,VBS 不认。另一个常见来源是字符串内部用了中文引号或全角分号,VBS 分词直接断掉。

解决:SQL 拼接时每行末尾主动加一个空格再加下划线,这是最省心的写法。中英文标点问题更隐蔽,写完语句后检查引号、分号的输入法状态。在 WinCC 里特别容易踩的是从网页或 Word 里复制 SQL,复制进来的隐形空格会让“脚本语句未结束”反复出现,处理办法是在编辑器里把粘贴的内容全选后重新敲一遍关键行。

4.4 Access文件被锁死:.laccdb锁文件“假死”

现象:连接正常,脚本执行时却抛“文件正由另一个用户使用”或“磁盘或网络错误”,有时候只在现场出现,开发机上完全复现不了。

原因:Access 引擎在打开文件时会生成一个 .laccdb 锁文件,如果脚本没有正常关闭连接,或进程异常结束,残留的锁文件会继续占着文件。还有一种情况是 Access 数据库以独占方式打开,比如有人正在 Access 界面里编辑表,此时外部脚本只能读不能写,某些操作就报错。

解决:脚本里务必成对执行rs.Close、conn.Close,并把对象置为Nothing,让连接及时释放。部署现场约定:Access 文件所在目录不允许人工用 Access 界面直接打开编辑,只允许部署的只读查询。如果锁文件确实残留了,关闭相关进程后手动删除 .laccdb 文件再试。如果 Access 文件放在网络共享上,断网瞬间产生的锁文件最难清,建议用共享目录的读写权限控制代替人工管理。

4.5 日期类型变了样:OLE日期与文本字段转换

现象:Access 里的日期字段,比如 2025-03-14 08:30,写入 WinCC 文本变量后显示成数字,比如 45745.35417。

原因:Access 的日期时间在底层是 OLE 自动化日期,存储为双精度浮点数,整数部分是天数,小数部分是时间。直接把字段值写入文本变量时,WinCC 拿到的是原始浮点数值,没有格式化成可见日期。

解决:在 SQL 里格式化,或者在脚本里用FormatDateTime。SQL 写法更直接:

SELECT TOP 1 Format(last_time, 'yyyy-mm-dd hh:nn:ss') AS last_time_str FROM t_recipe

脚本写法是HMIRuntime.Tags("DB_last_time").Write FormatDateTime(rs.Fields("last_time").Value, 2),其中参数 2 表示短日期格式。两种方式都要注意:如果字段值本身是 Null,FormatDateTime会报“无效使用 Null”,写之前先做IsNull判断,再决定写空字符串还是写默认值。

5. 更进一步:批量变量刷新和多表联动

5.1 批量写入:循环遍历记录集时不阻塞画面刷新

有时 Access 表里不只一条数据要上画面,可能是一组配方参数或者一批质检结果。把这组数据写到多个 WinCC 变量时,常见写法是循环记录集:

Dim i i = 0 Do While Not rs.EOF And i < 20 ' 变量名约定为 DB_PARA_0, DB_PARA_1, ... HMIRuntime.Tags("DB_PARA_" & CStr(i)).Write rs.Fields("para_value").Value i = i + 1 rs.MoveNext Loop

前提是变量管理里已经预先建好了 DB_PARA_0 到 DB_PARA_19 这一组变量。VBS 不支持运行时动态创建 WinCC 变量,变量必须提前定义,这是最容易踩的一步。循环里有个上限 i < 20,防止 Access 表里混入异常数据把变量名拼到超出范围去。

批量写内部变量通常很快,但如果目标变量是外部变量,一次Write会进入通信队列,循环几百个会排队,画面刷新看起来就像卡死。优化策略是把批量写入的临时结果先放在内部变量里,再由通信驱动统一同步;或者分批加延时,每写 10 个变量就暂停几十毫秒,避免通信队列长时间占满。WinCC 的 VBS 环境不一定提供WScript.Sleep,我一般会用画面侧的周期触发把批次拆小,或者干脆牺牲一点实时性,把批量写放在独立脚本里一次完成,画面上用状态变量提示“刷新中”。

5.2 多表联动:一条SQL代替多个脚本

Access 项目里数据一般不会只在一张表里,典型情况是配方主表和批次记录表分开。如果脚本里先查表 A,再拿结果去查表 B,逻辑会变得很碎。用一条 JOIN 查询能同时取出两张表的数据,脚本只维护一个记录集:

SELECT r.batch_no, r.temp_set, p.actual_temp, p.actual_speed FROM t_recipe r INNER JOIN t_production p ON r.batch_no = p.batch_no WHERE r.status = 'active'

配合前面读变量的套路,rs.Fields("actual_temp")就能直接取到联表后的字段。注意 Access 的 JOIN 语法里表别名写在表名后面,不需要 AS 关键字,别名之间用点号引用字段。如果两张表的字段名冲突,SELECT 里必须用“别名.字段名”写清楚,否则 ADO 解析记录集时可能取了错误的列。

多表联动的另外一个好处是,如果以后想让 WinCC 侧通过 Access 做“增删改查”里的写操作,脚本里改成conn.Execute执行 UPDATE 或 INSERT 语句即可,但因为写操作会改变库内容,建议把写库动作单独放进一个函数,不要在周期刷新的查询函数里混着做。写库操作还要加事务保护,避免 SQL 只执行了一半。典型做法是先BEGIN TRANSACTION,执行完再COMMIT TRANSACTION,出错了就ROLLBACK,保证整批数据一致。

5.3 触发方式:用内部变量做数据开关

周期触发器是固定节奏运行,但工程上经常希望“PLC 说刷新,我这边才去刷”。做法是定义一个内部变量DB_refresh_cmd,周期脚本里每个周期去读这个变量,为 1 时才执行 Access 查询,执行完写回 0:

Dim iCmd iCmd = HMIRuntime.Tags("DB_refresh_cmd").Read If iCmd = 1 Then Call ReadAccessToWinCC() HMIRuntime.Tags("DB_refresh_cmd").Write 0 End If

配合起来,PLC 侧通过 WinCC 通道把外部变量同步到这个内部变量,就实现了“PLC 发刷新命令,WinCC 查数据库”的联动。这个模式的优点是 Access 不会被一直轮询,只在需要时被触发,锁库和网络抖动的风险都会小很多。调试时可以直接在变量监视器里把DB_refresh_cmd置 1 来触发一次刷新,观察DB_read_ok是不是先变 1 再被脚本复位。如果置 1 后DB_read_ok没变化,问题就锁定在条件判断之前的连接和查询环节,不用瞎猜整段脚本。

6. 收尾:怎么确认每次写入都靠得住

脚本能跑、画面能看到数据只是第一步,工程上还要能证明每次写入都成功。我一般在项目里加三样东西:状态显示、日志记录、超时保护。

状态显示不复杂,在画面角落里放一个文本框绑定DB_read_ok,正常写 1,失败写 0,超时写 -1。再放一个DB_last_refresh变量记录最后一次成功刷新的时间。操作员看到时间和状态都正常,就知道这条数据链路是通的;如果状态变了而时间没变,说明脚本执行了但连接或查询出了问题。这一段看起来不起眼,但排障时能省掉大量的对讲机沟通。

日志记录建议用 FileSystemObject 写文本文件,每次脚本执行后追加一行,内容包括执行时间、查询条数和写入返回码:

Dim fso, f Set fso = CreateObject("Scripting.FileSystemObject") Set f = fso.OpenTextFile("D:\logs\db_access.log", 8, True) f.WriteLine Now & " | rows=" & rowCount & " | ok=" & HMIRuntime.Tags("DB_read_ok").Read f.Close

日志文件不要放在 Access 的同一目录,避免和锁文件混在一起。锁文件是 Access 自己生成的,日志却可能因为目录权限问题写不进去,两个问题叠在一起会很难排查。记录超过一定大小后建议按天建文件,或者定期清空,免得磁盘被日志塞满。日志里的时间用完整的Now,只记日期不记时刻的话,排障时根本分不清哪条写入是最后成功的。

最后是我的一个习惯:连接字符串和 SQL 语句不写死在脚本里,而是放在单独的配置文件,脚本启动时读进来。这样换数据库路径或改查询条件时,运维只需要编辑文本文件,不需要打开 WinCC 脚本编辑器重新编译。这几年我在多个项目里都是这个套路,坑主要栽在驱动位数和外部变量竞争上,每次写新项目都会先确认 DSN 位数、再确认目标变量是内部还是外部、最后补日志。把这三件事做在前面,Access 到 WinCC 这条路基本就不会再翻车。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询