工单逾期台账填充 Skill
处理《工单逾期》WPS 表格:把最新一批(当天新增)的行按表内既有公式规律补全 A/B/C/P/Q 五列,
并按工单编号从最近批次复制 R 列(事件描述)。只写新增批次的行,其余单元格一律不碰。
When to Use
- 用户发来工单逾期台账
*.xlsx,说「填充」「补一下」「结合日期填充前三列」「P列和Q列按前面的公式填充」 - 用户要求「R列按上一天的复制」「前后对比后复制内容」
- Don't use for: 与工单逾期台账无关的 Excel 任务(改用 productivity 分类下的 Excel 技能)
铁律(用户硬性要求,违反即返工)
- 只动最新批次的行。 更早的行一律不碰——不补空、不修公式、不统一格式、不「顺手」修复。
- 参考范围最多回溯 5 个批次(该台账基本每个工作日检查一次,所以「往前 5 天」≈ 往前 5 个批次);更早的批次完全不用看。
注意:R 列复制必须包含紧邻的上一批——即使它距今天超过 5 个自然日(实测发生过:上一批 09-07,本次 09-23)。 - 确需改动旧行时先问,得到明确点名才动。
- 检查日期 = 检查当天日期(用户原话),不要从表内数据去推断。
表结构
- 工作表按年命名(如
2026工单逾期);只处理当年那张,其他 sheet 不用管。 - 第 1 行是底色说明,第 2 行才是表头,数据从第 3 行开始。
- 主要列:A 序号|B 类型|C 检查日期|D 工单编号|E 工单标题|F 工单状态|G 分解工单编号|
H 分解工单状态|I 当前处理人|J 当前节点|K 所属部门|L 所属系统|M 事件类型|N 期望完成时间|
O 更新时间|P 用户期望时间逾期情况|Q 处置要求|R 事件描述|S 记录人|T 值班经理审核 - 新增批次 = 表格末尾若干行:只有 D~O 有值,A/B/C/P/Q 与 R 全空,等着拖公式。
列公式(逐行套用,只换行号)
| 列 | 公式 |
|---|---|
| A 序号 | =ROW()-2 |
| B 类型 | =IF(COUNTIF(D$3:D{上一行},D{本行})>0,"往期","新增") |
| C 检查日期 | 手填常量 = 检查当天日期 |
| P 逾期情况 | =IF(AND(_xlfn.DAYS(N{r},O{r})>0,_xlfn.DAYS(N{r},C{r})>=0),"未超期望时间","已超期望时间") |
| Q 处置要求 | =_xlfn.IFS(P{r}="未超期望时间","忽略",AND(P{r}="已超期望时间",R{r}=""),"须通报",R{r}<>"","因后方原因无需通报") |
- 保留
_xlfn.前缀(WPS/Excel 内部就存这个样子,去掉会变 #NAME?)。 - B 列第 3 行(首个数据行)没有「上一行」可引用 → 填字面量
新增。 - C 列的 B 公式参考区间要排除本行,即第 r 行用
D$3:D{r-1}。
R 列复制规则(用户口述)
看上一批的 R 列 → 空的跳过;有内容的取其工单编号;与今天新增批次的工单编号比对,
今天也有同一工单的,把内容复制到今天的 R 列。参照窗口=往前 5 个批次(由近及远,先到先得),
紧邻的上一批必须有参加。
工具
本机没有全局 pandas/openpyxl,用 uv 临时装:
terminal(command='/home/ubuntu/.hermes/bin/uv run --with openpyxl python <skill_dir>/scripts/fill_batch.py IN.xlsx OUT.xlsx [--batches 5] [--date YYYY-MM-DD]')
fill_batch.py 会在保存后自动调用 finalize_xlsx.py(还原空字符串 + 设置 fullCalcOnLoad)。
单独重跑后处理:... python <skill_dir>/scripts/finalize_xlsx.py IN.xlsx OUT.xlsx
Procedure
- 确认处理对象:哪张 sheet、新增批次从第几行开始(完成判据:能说出新增批次的起止行号)。
- 先看再写:读表头与相邻行,确认列位置与公式形态没变(完成判据:P/Q 归一化行号后各只有 1 种形态)。
- 跑脚本:
fill_batch.py自动识别末尾无日期的行作为新增批次并填充。 - 逐格验收:把输出与原文件对比,差异只应落在新增批次行(完成判据:差异行号全部 ≥ 新增批次首行;其他 sheet 差异 = 0)。
- 交付:把
OUT.xlsx作为 MEDIA 发给用户,并附上「改了什么 + 校验结果」简报。
Pitfalls
- openpyxl 回写有两个副作用,必须靠
finalize_xlsx.py收尾:
- 源文件里值为「空字符串」的单元格(可达数千处)会被写成<c t="inlineStr"/>—— 连<is>都没有,
既变成空白、又不合规。后处理会改写成合法的空串写法。
- 不写xl/sharedStrings.xml(3.1.x 默认全用内联字符串)。数值上等价,不影响打开。
- 正确性判定(关键):只含一个空格的单元格' '不是空字符串,绝不能被当成空串改写。
判定要用<t>标签内部原文是否为空,而不是先把整个<si>的空白剥掉再比——那样会把空格吃掉。 - 不要用
data_only=True判断公式列——读出来是缓存值或 None,会误判为空。判断「有没有公式」要data_only=False。 - 首行 B 列必须字面量,否则 COUNTIF 区间反向(如
D$3:D2)会报错。 - 表里可能存在历史坏值(如某年表 B3~B5 的
#REF!、A2001被填成「暂时不扩」)——按铁律不主动修,只在用户点名时才动。 - 别把
.xlsx当二进制复制来处理公式——新增批次的 P/Q 是公式,不是算好的值。已设fullCalcOnLoad=1,WPS/Excel 打开会自动重算。 - 用户会亲自验收并精确回报问题;交付前务必自己跑完第 4 步的逐格 diff。
Verification
- 归一化行号后,P 列与 Q 列各只应有 1 种公式形态(全表一致,仅行号不同)。
若形态数 >1,先看是不是历史遗留:实测 2026 表 Q 列有 298 个公式 + 5 个空白(行 138/139/141/143/144,用户明确不补)→ 会报 2 种,属正常,不要自作主张去填。 - 新增批次的 A/B/C/P/Q 无空单元格。
- 与源文件逐格 diff:差异行号应全部 ≥ 新增批次首行。
- R 列复制数量 = 上一批 R 非空条数 ∩ 今天仍存在的工单数。