多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

WinCC用户归档从建表到脚本读写:点检记录数字化实战

WinCC用户归档从建表到脚本读写:点检记录数字化实战 简介面向工业自动化与SCADA开发者的西门子WinCC用户归档专题案例聚焦生产数据存储与检索场景系统讲解动作Actions与标准模块之间的协同机制帮助解决历史数据管理、报表生成与故障排查中的实际难题。压缩包内共290个文件大小36.21MB以250个rpl脚本文件为主体辅以mdf/ldf数据库文件、pdl画面文件、dum备份、cfg配置文件等覆盖归档触发逻辑、数据筛选转换、压缩存储与调用显示等完整环节。已有1150人参与学习内容包含示例项目文件、脚本代码、配置文件及分步实践指南可直接对照案例项目进行配置与调试。通过学习可掌握用户归档的触发条件设置、标准模块复用方式、归档间隔与保留期限等策略设计并能理解动作与模块配合提高项目效率的关键思路适合需要深化WinCC数据管理能力的自动化工程师与项目集成人员使用。1. wincc 用户归档案例事件型数据不该塞进过程值归档班组长让你把每天的设备点检记录存下来要求能按操作员查、按时间段导出来。第一反应是拉一个变量归档结果发现点检是事件型数据——一天百来条查的时候还要跟过程值混在一起这不是变量归档该干的活。WinCC 用户归档就是为这种场景设计的它把数据按记录存成一张张结构化表字段你自己定运行时可以手动录入、脚本写入、按条件检索还能绑定表格控件直接展示。这篇文章用一个设备点检归档案例把建表、画面绑定、脚本读写和踩坑整条路走一遍。适合做批次追溯、操作日志、报表底表的工程师也适合刚接触用户归档、想把概念落到现场的人。2. 用户归档和变量归档的选型边界先定数据模型再动手建表2.1 一张表看清用户归档与变量归档的分工很多人把用户归档和变量归档当成同一种东西的两种叫法实际上两者分工完全不同。变量归档解决的是“过程值怎么存下来、怎么压缩、怎么画趋势”用户归档解决的是“业务记录怎么结构化、怎么按条件查、怎么改”。下面这张对比表是我每次给现场同事培训时必放的。对比维度变量归档用户归档存储对象模拟量、开关量的过程值快照操作日志、点检记录、批次信息等结构化记录触发方式周期采集或变化采集系统自动写手动录入、脚本写入、事件触发数据量高频、大按秒甚至毫秒积累低频、小一天几十到几千条查询方式按时间轴查询适合画趋势曲线按任意字段组合条件查询支持增删改编辑能力运行时只读不能改历史值可插入、可修改、可删除受权限控制典型场景温度曲线、压力趋势、能耗分析点检表、交接班记录、生产追溯、质检结果关键结论是拿用户归档存模拟量趋势是常见误用。有人觉得用户归档也能存数值就把一个温度测点每分钟写一条用户归档结果一个月下来数据库膨胀、查询卡顿而趋势控件还不直接读这张表最后还得回到变量归档。反过来拿变量归档存点检记录也别扭——你没法按操作员名字过滤也没法在运行界面里补一条漏记的数据。选型时先问一句这条数据是要“画曲线”还是要“查记录”答案直接决定用哪套机制。2.2 点检记录的数据模型字段命名、类型和长度怎么定用户归档的本质是数据库表字段设计直接决定后面查询顺不顺。以设备点检为例一条完整记录至少包含点检时间、设备编号、点检人、设备状态、关键温度值、备注。对应到用户归档字段我一般这样设计字段名数据类型长度/精度说明RecordTime日期/时间固定点检时间排序和过滤的主键字段DeviceID文本8设备编号如 P-101OperatorName文本16点检人姓名按 4 个汉字加余量设计Status整型固定设备状态码1 正常、0 异常TempValue浮点数保留两位关键温度值Remark文本50备注注意给足长度字段命名这里有一条血泪经验尽量用英文不要用中文。中文不是不能用但你在脚本里拼 SQL 时每次都要加引号跨项目迁移时还会遇到编码问题排查起来非常痛苦。另外避开 SQL 保留字比如 Name、Status 这种在很多数据库语境里容易出问题稳妥做法是统一加前缀比如 F_RecordTime、F_DeviceID。类型和长度在项目运行后修改受限尤其是文本字段长度一开始就按最坏情况给。备注只给 20 个字符现场多打几个字就截断等发现时历史数据已经写坏了没有后悔药。2.3 在项目管理器里创建一个能跑的归档三个关键步骤创建用户归档的位置在项目管理器左侧树里的“用户归档”节点。我用的版本是 TIA WinCC V15.1老版 WinCC 7.x 位置也类似逻辑不变。第一步右键“用户归档”选择“新建归档”归档名填 EquipmentInsp。归档名就是后面脚本连接时的关键标识建议只允许字母和数字不要带空格。第二步在新建归档对话框的字段选项卡里按上一节的字段表逐条添加每添加一个字段就设置数据类型和长度。这里有三个属性容易忽略允许为空、索引、锁定。RecordTime 建议勾选索引按时间过滤会快很多允许为空按业务需求设置点检记录的设备和时间建议必填。第三步编译项目。编译不是走个形式它会校验字段定义和页面引用编译通过后这个归档才算在运行库里真正创建出来。运行系统启动后这个归档会对应项目数据库里的一张实际表。单用户项目默认数据库实例是 .\WinCC归档名就是表名。你可以用 SQL Server Management Studio 连上去看一眼表结构这一步能帮你建立“用户归档表”的直觉后面脚本写错了也知道去哪查。建好表之后先别急着写脚本下一章先走画面绑定这条路把手工录入跑通。3. 画面绑定用户归档控件从拖入控件到完成第一条真实记录3.1 用户归档控件的功能区表格、工具栏和过滤条各自管什么用户归档控件在 WinCC 画面编辑器里叫 WinCC UserArchive Control拖到画面上之后第一眼会看到一大块表格区域。这个控件默认分成三块顶部是工具栏中间是数据表格底部是状态栏。工具栏里提供的是运行时操作按钮——新建记录、删除记录、保存、撤销、过滤这些按钮能否点取决于你在属性里给了哪些权限而不是全部默认可用。表格区域显示的就是用户归档里的实际记录一行一条列名对应你建的字段。底部还有一个小过滤条运行时可以直接输入条件过滤表格内容不用写脚本适合给操作员用。很多人第一次用这个控件运行起来发现表格是空的第一反应是归档没建对。其实大概率是表里本来就没数据或者在属性里没绑定归档名。控件本身只是个容器它不会自动找到你的归档必须显式指定。这个“没绑定”的问题是我见过最多的新手翻车点。3.2 控件属性里必须改的四个参数归档名、编辑权限、删除权限和排序选中控件右键打开属性对话框重点看四个地方。参数位置建议值说明用户归档名属性页“用户归档”EquipmentInsp不选的话控件运行起来白板一块允许插入记录属性页“运行时行为”是控制运行时能否新增行允许删除记录属性页“运行时行为”是控制运行时能否删除行默认排序字段属性页“表格”RecordTime 降序保证最新记录显示在最上面前两个是基础第三个是安全边界。如果这个画面只给班长看、不让他改数据就把插入和删除都关掉只留查看能力。默认排序字段容易被忽略不设的话按数据库物理顺序显示新插入的记录跑到表格最后面现场操作员会以为数据丢了。排序字段选 RecordTime 并按降序最上面永远是最新记录贴近日常检查习惯。另外注意一点控件的过滤功能依赖查询界面运行时过滤只影响显示不会改数据库原始数据。这点可以在交接班时明确告诉操作员——误过滤不是误删除不用担心。3.3 手动增删改查验证填一条、存一条、再到数据库里核对一条控件配置完成并编译运行后按下面这套步骤做第一次真实录入验证。第一步启动运行系统打开绑定控件的画面点击工具栏上的“新建记录”按钮表格底部会出现一条空行。第二步依次填入 RecordTime、DeviceID、OperatorName、Status、TempValue 和 Remark。日期时间字段可以直接点单元格弹出选择器文本字段直接输入。第三步点击保存按钮确认没有报错弹窗。第四步切换到 SQL Server Management Studio连接到 .\WinCC展开表目录找到 EquipmentInsp 表执行最简单的查询确认刚填的记录已经落到数据库里。这里有两个必踩的细节。第一保存按钮灰着点不动大概率是“允许插入记录”没打开或者当前记录里有必填字段为空。第二往数值字段里输入“abc”这类非数字内容控件会拒绝并把光标停在原单元格这不是故障是类型校验在起作用。类型校验按你建字段时选的类型走所以建表时不要把温度字段误建成文本型否则后面排序和趋势都会出问题。4. 用脚本读写用户归档VBS 写记录C 脚本查记录4.1 为什么建议脚本直连项目库而不是操作控件控件适合人工录入和查看但现场很多场景需要自动化PLC 报某个信号后自动写一条点检记录交班时按工号批量查记录定时统计当班异常次数。这些靠手工点控件做不了。常见做法是用脚本直连项目数据库对用户归档对应的表执行 SQL。这样做的优势是不依赖画面是否打开——后台全局脚本也能写劣势是你要自己管理连接字符串和错误处理比调用控件接口更“裸”。我一般混用两种语言VBS 写业务逻辑读起来直白适合保存、批量插入这类低频操作C 脚本适合放在按钮事件里做查询回显性能比 VBS 稳。下面两段代码分别是“按信号写一条记录”和“查询最新记录回显到画面”可以直接抄到自己的项目里改字段名。4.2 VBS 写入PLC 信号触发一条点检记录在画面某对象的 VBS 事件里写如下代码。常见触发方式是脚本触发器定时调用或者关联一个 PLC 变量变量变化时执行写入。Dim conn, sql Set conn CreateObject(ADODB.Connection) conn.ConnectionString ProviderSQLOLEDB.1;Data Source.\WinCC;Initial CatalogEquipmentInsp conn.Open sql INSERT INTO EquipmentInsp _ (RecordTime, DeviceID, OperatorName, Status, TempValue, Remark) _ VALUES ( _ Now , _ P-101, _ 张工, _ 1, _ 36.5, _ 例行点检无异常) conn.Execute sql conn.Close Set conn Nothing这段代码的逻辑是先建立 ADO 连接连接串里 Data Source 写成 .\WinCC指代 WinCC 项目运行库Initial Catalog 写成用户归档名 EquipmentInsp。很多第一次接触的人卡在这里——不知道归档名可以直接作为库名使用。如果连接失败下一步去 SSMS 里确认数据库实例名和表名以实际为准不要死磕代码。SQL 语句里显式列出字段名而不是用位置赋值是避免字段错位的必要习惯。VALUES 里字符串用单引号包数字直接写日期用 Now 函数生成当前时间。备注里如果可能包含单引号比如“设备’A’异常”直接拼接会把 SQL 截断正式项目要么做单引号替换要么改成 ADO 参数化查询。这里有个参数值得注意ConnectionString 里的 Provider 用 SQLOLEDB.1 是最通用的写法。如果你的 WinCC 版本较新也可以用 MSOLEDBSQL但现场机器不一定装了新驱动SQLOLEDB.1 兼容性最好我至今没遇到跑不起来的机器。4.3 C 脚本查询最新记录并回显到画面把下面的 C 脚本放在画面一个查询按钮的 Click 事件里。作用是把 EquipmentInsp 里最新一条记录的 OperatorName 和 TempValue 取出来写到画面上两个 IO 域的变量里。#include apdefap.h void OnClick(char* lpszPictureName, char* lpszObjectName, char* lpszPropertyName) { #pragma code(kernel32.dll) #include winbase.h #pragma code(msado15.dll) #import msado15.dll no_namespace rename(EOF, adoEOF) #pragma code() _ConnectionPtr pConn; _RecordsetPtr pRs; CoInitialize(NULL); pConn.CreateInstance(__uuidof(Connection)); pConn-Open(ProviderSQLOLEDB.1;Data Source.\WinCC;Initial CatalogEquipmentInsp, sa, , -1); pRs.CreateInstance(__uuidof(Recordset)); pRs-Open(SELECT TOP 1 OperatorName, TempValue FROM EquipmentInsp ORDER BY RecordTime DESC, _variant_t((IDispatch*)pConn), adOpenForwardOnly, adLockReadOnly, adCmdText); if (!pRs-adoEOF) { SetTagChar(LastOperator, (LPCTSTR)(_bstr_t)pRs-Fields-GetItem(OperatorName)-Value); SetTagDouble(LastTemp, (double)pRs-Fields-GetItem(TempValue)-Value); } pRs-Close(); pConn-Close(); pRs.Release(); pConn.Release(); CoUninitialize(); }这段脚本的核心逻辑是用 TOP 1 加 ORDER BY RecordTime DESC 取最新一条避免把整张表拉进内存。adOpenForwardOnly 表示只向前滚动针对这种只取一条记录的查询最省资源adLockReadOnly 表示只读打开防止误写。取到记录后 SetTagChar 和 SetTagDouble 是 WinCC 的 C 脚本 API把字段值写到内部变量里画面上的 IO 域直接关联这两个变量就能显示出来。参数说明里有一个关键点连接串的用户名和密码我直接写了 sa 和空密码。实际项目中很多 WinCC 运行库是不开 sa 的更稳妥的方式是用 Windows 集成认证把 Open 的认证参数改成 SQLOLEDB 支持的安全模式。不管用哪种密码不要写死在脚本里项目交付后维护人员翻代码看到明文密码总是隐患。4.4 把用户归档数据接到历史趋势曲线上变量中转的脚本思路有人会问用户归档里的温度值能不能直接画在 WinCC 的趋势控件里答案是不能。趋势控件只认变量归档和过程变量不认用户归档表。常见做法是变量中转脚本定时把用户归档最新值写到内部变量趋势控件的数据源指向这个内部变量。比如用定时触发器每秒执行一次SetTagDouble(TrendTemp, (double)最新TempValue)趋势曲线就能跟着更新。这个思路能解决“给领导看趋势”的需求但它有一个边界投放趋势的是实时刷新值不是完整的归档历史。如果要画某个时间段的历史追溯曲线脚本要按时间段查用户归档表再把结果逐点写进数组变量或转存到变量归档里。这属于进阶玩法我放到最后一章讲验证的时候一并说。5. 用户归档常见翻车现场乱码、表锁、找不到许可证的排查顺序5.1 中文写入控件变成问号代码页与字段长度现象控件和数据库里都能看到记录但中文字符全部显示成问号英文和数字正常。原因有两类。第一类是字段长度不够文本字段按字节存储中文在部分编码下占两个字节长度给 10 实际只能存 5 个汉字超出部分变成乱码。第二类是 WinCC 项目代码页与 SQL 排序规则不一致SQL 直连写入时字符集转换出问题。解决办法建表时文本字段长度按最坏情况乘 2确认项目属性里代码页设置为简体中文936 或 65001视版本而定SQL 直连时在连接串里显式指定语言选项。这个坑最阴险的地方在于它不是必现的——偶尔一段长备注写进去才翻车等发现时历史数据已经污染了。5.2 报表写入时提示表被锁定连接未关闭与记录锁定现象脚本批量插入几十条记录后后续操作提示“表被锁定”或“无法删除记录”。原因上一段脚本执行完 SQL 后连接没有关闭事务一直悬着或者用户归档组态里勾选了“记录锁定”运行时控件编辑某条记录会锁住该行。我排查的顺序是先看脚本里conn.Close是否执行到了——脚本中间报错跳出连接就漏关了再看是不是有人正在控件里编辑那条记录。解决写入和查询代码里用On Error Resume Next配合最后统一关闭连接组态里的锁定选项如果不是业务必需就关掉多客户端项目里避免两个画面同时编辑同一条记录。这条属于典型的“自己把自己锁死”排查本身往往比解决更费时间。5.3 V15.1 打开用户归档编辑器提示找不到许可证 WinCC Comfort现象TIA WinCC V15.1 环境里打开用户归档相关组态或编译运行时弹窗提示“找不到许可证 WinCC Comfort”项目能建、画面能画就是用户归档用不了。原因用户归档组态功能属于 Professional 级别能力如果你创建项目时选的是 Comfort/Advanced 项目类型授权检查就过不去还有一种情况是电脑上只装了 Comfort 版本的试用授权Professional 授权没装或版本号对不上。解决第一步检查项目类型新建项目时选择 Professional第二步打开授权管理器确认安装了对应 V15.1 的 Professional/Advanced 授权V15 的授权不能拿来顶替 V15.1第三步重启授权服务再重新打开项目。这个坑不是你的脚本问题是授权边界问题别浪费时间查代码。5.4 SQL 直接写入后控件显示对不上字段顺序与时间格式现象脚本用 INSERT 写入数据数据库里查没问题但控件表格里某几列的值串位了。原因INSERT 语句没有显式列出字段名直接按表结构默认顺序写值 — 一旦建表时调整过字段顺序脚本里的值就错位了。另一个高频原因是时间格式WinCC 控件对日期时间字符串的解析严格写成2024/05/01它能认写成2024-5-1就可能显示成 1900 年。解决INSERT 永远显式列出字段名不要偷懒时间统一用YYYY-MM-DD HH:MM:SS格式VBS 里用FormatDateTime(Now, 2)控制格式再拼进 SQL。这条赏罚分明写规范了没问题写野了就出怪数据。5.5 数据量上来后查询越来越慢索引、分表和清理现象归档跑了两三个月打开控件要等好几秒脚本查询也越来越慢。原因RecordTime 字段没建索引每次查询都全表扫描或者每天几千条记录全堆在一张表里没有任何清理策略。解决建表时给 RecordTime 勾选索引查询永远加 WHERE 时间范围不要查全表控件里默认加载条数限制在能看够用的范围内。更彻底的办法是按月拆归档每个月一张表脚本里动态拼表名。用户归档不是数据仓库别指望它扛几年的数据。定期把旧数据导出到 Excel 或 SQL Server 别的库里再从用户归档里删掉这个动作要写进运维手册。6. 进阶批量补录、趋势联动和迁移验证的完整核对流程6.1 用 VBS 把 CSV 批量补录进用户归档现场经常遇到历史点检记录在纸面上、需要补录的情况。逐条手工点控件太慢可以用 VBS 脚本读 CSV 文件循环插入。核心逻辑是逐行解析 CSV拼 INSERT 语句执行。注意 CSV 里的时间文本先做格式标准化字段顺序和表结构对清楚再跑。批量补录前先在测试归档里跑一遍确认没有字段错位再切到正式归档。Dim fso, ts, line Set fso CreateObject(Scripting.FileSystemObject) Set ts fso.OpenTextFile(D:\backfill.csv, 1) Do Until ts.AtEndOfStream line ts.ReadLine 按逗号拆字段拼 INSERT注意转义 示例2024-05-01 08:30:00,P-101,张工,1,36.5,补录 Loop ts.Close这里的转义处理要特别小心。CSV 里如果有包含逗号的备注简单的 Split 会拆错。常见做法是用分隔符引号处理函数解析或者要求现场导出的 CSV 不用逗号做分隔符改用制表符。我倾向后者因为点检记录备注里很少出现制表符。6.2 迁移后的验收脚本条数、字段、时间戳一次对完用户归档从开发机迁到生产机或者从旧项目迁到新项目时组态还能靠导入导出数据表就要靠备份恢复。迁移完成别急着让现场用先跑一遍核对脚本对比源表和目标表的记录条数、字段类型、时间范围。我用得最多的验收 SQL 只有三行SELECT COUNT(*) FROM EquipmentInsp; SELECT MIN(RecordTime), MAX(RecordTime) FROM EquipmentInsp; SELECT OperatorName, COUNT(*) FROM EquipmentInsp GROUP BY OperatorName;条数对得上说明数据没丢时间范围对得上说明归档段完整按操作员分组能顺带验证字段内容没有整体偏移。这三个查询跑完心里就有底了。最后补一个我的教训最早做用户归档项目时我图省事把文本字段长度全按 20 设结果三个月后备注被截断返工时数据已经坏了。现在我每做一个归档先写字段字典交底再动建表脚本里只用显式字段名迁移完必跑验收查询。这套流程看着笨但能拦住绝大多数翻车。希望帮到你。本文还有配套的精品资源点击获取
返回列表