多表合一审核对比
把多份表格按关键字段合并去重,或两张表逐条比对,把差异精确定位到字段级。
何时使用
触发场景:
- "把这几份明细表合成一张表" → merge
- "对一下 A 和 B 两份表,看看哪里对不上" → reconcile
- "找出重复的记录" / "查重"
- "哪些单号两边都有但金额不一样"
- "按单号合并后导出明细和汇总"
不适用:单表内的统计透视、复杂公式计算、图表绘制(用 workbuddy-sheetagent)。
执行流程
第 1 步:侦察(必做)
不要跳过这步。 表头行位置、列名拼写、多 Sheet 结构千差万别,直接对账会得到错误结果。
python scripts/table_merge.py inspect "<数据目录>" --all-sheets
输出每张表的:表头在第几行、数据行数、字段清单、候选关键字段及唯一率/覆盖率。
若表头探测明显错误(如表头行不是 1),用 --header-row N 显式指定。
第 2 步:选择关键字段
依据 inspect 的结果确定关键字段:
- 优先用
--key显式指定,列名可用模糊匹配(--key 订单号也能匹配到订单 号) - 复合键:
--key 订单号,箱号 - 不确定时:
--key auto或--auto,脚本按"编号类列名 + 文本型 + 唯一率"综合打分推荐
键的规范化:去空格、去 - _ . / 等分隔符、全角转半角、大小写折叠。所以 AB-1234、ab 1234、AB1234 视为同一键。
第 3 步:执行
多表合一:
python scripts/table_merge.py merge "<数据目录>" --key <关键字段> -o "<输出目录>" --name <输出名>
对账:
python scripts/table_merge.py reconcile A.xlsx B.xlsx --key <关键字段> --numeric-cols 金额,运费 -o "<输出目录>" --name <输出名>
常用参数:
| 参数 | 作用 |
|---|---|
--all-sheets |
工作簿内所有 Sheet 一起处理 |
--sheet 名称 |
指定单个 Sheet |
--header-row N |
手工指定表头行(1-based) |
--numeric-cols a,b |
指定数值列(默认自动识别) |
--compare-cols a,b |
指定参与比对的字段(默认取两表交集全部列) |
--tolerance 0.01 |
数值绝对容差 |
--tolerance-pct 0.001 |
数值相对容差(0.1%) |
--auto |
自动推荐关键字段 |
--no-dedupe |
跳过去重 |
--no-html |
只出 Excel |
--single-workbook |
同一文件内两个 Sheet 对账 |
第 4 步:交付
每次运行产出:
名称_对账.xlsx— 5 个 Sheet:对账明细 / 字段差异明细 / 缺失记录 / 表内重复 / 汇总名称_对账.html— 单文件报告,七个可折叠区块 + KPI 卡片 + 全文搜索,PC 与移动端自适应,可直接发同事
HTML 报告特性:关键字段列在手机上固定吸附、宽表横向滑动并有提示、全文搜索高亮、一键展开/折叠、打印时自动展开所有区块。
用 present_files 呈现 HTML(浏览器直接看),Excel 一并给出。
差异口径(四类)
| 类别 | 判定 | 处理 |
|---|---|---|
| 表间记录缺失 | 键只在 A 或只在 B | 全部列出,缺失侧留空 |
| 同键数值不一致 | 键相同,数值字段有差 | 列出差额(A−B)、差异率、各字段双方值 |
| 表内重复 | 同表内键重复 | 分"完全重复"与"键冲突",全部列出 |
| 字段级差异明细 | 逐字段比对 | 每条差异标出字段名、A 值、B 值 |
数值差异率基于 B 值计算;B 为 0 时差异率留空(不写无穷大)。
核心规则(不可违背)
- 缺失一律留空 —— 不推断、不填 0、不用空白字符伪装
- 全量列出 —— 不抽样、不截断,宁可文件大
- 冲突不静默丢弃 —— 同键不同值全部保留并标记,人工决定
- 列名匹配用模糊匹配 —— 用户说的列名与实际表头常有出入
重复的三种性质(合并场景关键)
多表合一时,同一键出现在不同文件属正常业务(如明细表 vs 单据表),必须区分:
| 类型 | 判定 | 处理 |
|---|---|---|
| 完全重复 | 同键 + 所有业务列取值完全一致 | 合并为一行,记重复次数 |
| 跨表同键 | 不同表出现同键,每表内唯一 | 全部保留,不算异常 |
| 表内键冲突 | 同一张表内同键但字段值不同 | 全部保留并标记,需人工核对 |
把"跨表同键"误判成"冲突"会导致大量假警报 —— 合并场景务必区分。
脏值处理
parse_number 已覆盖,识别结果直接参与数值比对:
| 输入 | 解析为 |
|---|---|
¥12,800.00 |
12800.0 |
2.5万元 |
25000.0 |
(500.00) |
-500.0(括号负数) |
12,800 RMB |
12800.0 |
1,234(全角) |
1234.0 |
` /-/N/A/无` |
None(缺失,非 0) |
常见坑
- 表头不在第 1 行:文件顶部常有标题/说明行(如"2026年度汇总"),
inspect会探测;探测错就--header-row - 多 Sheet:
--all-sheets展开全部 Sheet,否则只读第一个 - 列名对不上:A 表叫「订单号」、B 表叫「订单 号」也能匹配上;但 A 表叫「订单号」、B 表叫「业务单号」则需手工指定
- CSV 编码:自动嗅探 UTF-8/GBK/GB18030/Big5,含 BOM 自动处理;分隔符自动识别逗号/制表符/分号/竖线
- 数值列识别不准:金额列若混入文本,自动识别可能失灵,用
--numeric-cols显式指定 - 表头重复行:合并前若源表含"合计"行,需先剔除,否则会被当作数据参与比对
依赖
python -m pip install openpyxl xlrd
openpyxl 读 xlsx/xlsm,xlrd 读旧版 xls。
脚本清单
| 文件 | 职责 |
|---|---|
scripts/table_merge.py |
CLI 入口(inspect / merge / reconcile) |
scripts/tblcore.py |
内核:读表、清洗、键、去重、比对 |
scripts/report.py |
Excel 与 HTML 产物生成(含响应式与前端交互) |
scripts/publish_skillhub.py |
发布到 SkillHub,支持显式改显示名 |
细节口径见 references/rules.md,面向使用者的问题见 README.md。
发布到 SkillHub
# 改显示名或发新版本(推荐,支持显式改名)
cd scripts && PYTHONIOENCODING=utf-8 python publish_skillhub.py \
--slug <slug> --display-name "显示名" --version <x.y.z> --changelog "说明"
# 只看线上状态
PYTHONIOENCODING=utf-8 python publish_skillhub.py --slug <slug> --check
为什么不用官方 CLI 改名:官方 CLI(2026.8.5)无 --display-name 参数,其 payload 只传 displayName;
而服务端把技能级显示名绑定在 payload["name"] 上,缺 name 时会保留线上旧显示名。
publish_skillhub.py 复用 CLI 内部函数并补上 name 字段,故改名才生效。
版本号不可重复,重发同一版本报 409 VERSION_EXISTS。