编辑 | blame | 历史 | 原始文档

功能测试报告 — 货运页签「累计」列修复 + H2032 脏期清理

  • 功能名:汇总大表《 货运》页签累计列修复;h2032_enterprise_monthly 2026-09 脏期清理
  • 日期:2026-09-16
  • 结论:**通过**(6/6 累计列与源文件人工核算一致;脏期已清除且留有可还原备份)

一、功能说明与背景

用户反馈:汇总大表《 货运》页签的「累计」数据,人工核对后**只有前面四个能对上**。

货运 页签共 6 个累计列(全省行):

列 年度 修复前 源文件核算 差异
S 2026(1-8月) 130311.8927 130311.8927 0
AT 2025 195433.2232 195433.2232 0
BV 2024 184938.5780 184938.5780 0
CW 2023 173045.2932 173045.2964 -0.0033
DZ 2022 144979.2854 144979.2825 +0.0029
EO 2021 空 161309.5316 整列缺失

周转量行同理(2023 -0.0017、2022 +0.0025、2021 空)。

二、根因定位

2.1 结构与文件职责

母版:docs/生成汇总大表/2026年8月道路运输量汇总表.xlsx → 货运 页(118x147)。

  • 生成_道路运输量汇总表.xlsx 仅作**列宽版式参照**(applySummaryReferenceLayout 只读列宽与隐藏标记,不读数值);
  • 2026年8月道路运输量汇总表_版式原型.xlsx 运行时**未被任何代码引用**。

全省块 6 行:r5 货运量、r6 周转量、r7 其中规上货运量、r8 其中规上周转量、r9 其中规下货运量、r10 其中规下周转量。
17 个市州块每块 6 行,块首行 11,17,...,107(武汉市...林区)。

关键:全省 r5 = =<m>7+<m>9(规上+规下),r7 = 17 市州规上之和(公式),而 r9(全省规下)是写死的常量。

2.2 决定性测量(Excel COM 重算后逐月比较「全省行」与「17 市州行之和」)

年度 合计差 规上差 规下差
2026(1-8) 2.8e-5 1.8e-12 2.8e-5
2025 3.3e-11 9.1e-13 3.5e-11
2024 1.5e-11 9.1e-13 1.3e-11
2023 4.6e-3 4.5e-13 4.6e-3
2022 3.1e-3 2.3e-13 3.1e-3
2021 4.0e-5 4.0e-5 1.5e-4

结论:规上永远对得上;差异全部来自「全省规下」这一行的写死常量与 17 市州规下之和不等。

同时实测「17 市州行之和」等于源文件湖北省行:2022 累计 144979.2825、2023 累计 173045.2964,与人工核算**完全一致**。

2.3 其余原因

  • DZ(2022 累计)写死常量,不随数据刷新(其值恰好等于自身 12 个月之和,故改成公式属等值改动);
  • EO(2021 累计)整列为空,母版从未填过累计公式(2021 年 EC:EN 十二个月都有值);
  • EA(2022 累计同比)也是写死常量;
  • 导出代码只回填「目标当月」一列(SummaryWorkbookFiller.fillFreightSheet),历史月份一律沿用母版 → 母版对不上就整体对不上。

三、修改内容

3.1 母版《2026年8月道路运输量汇总表.xlsx》→ 货运 页

# 位置 改前 改后
1 r7 其中规上货运量(2021-2025 各月) 常量/部分公式 =SUM(<17 市州规上货运量行>)
2 r9 其中规下货运量(2021-2025 各月) 写死常量 =SUM(<17 市州规下货运量行>)
3 r8 其中规上周转量(2021-2025 各月) 常量/部分公式 =SUM(<17 市州规上周转量行>)
4 r10 其中规下周转量(2021-2025 各月) 写死常量 =SUM(<17 市州规下周转量行>)
5 r5 货运量(2021-2025 各月) 常量/公式 =<m>7+<m>9
6 r6 周转量(2021-2025 各月) 常量/公式 =<m>8+<m>10
7 DZ 列(2022 累计,行 5-112) 写死常量 =SUM(DM<r>:DX<r>)
8 EO 列(2021 累计,行 5-112) 空 =SUM(EC<r>:EN<r>)
9 EA 列(2022 累计同比,行 5-112) 写死常量 =IFERROR(DZ<r>/SUM(EC<r>:EN<r>)-1,"")

共改写月块单元 360 个、累计单元 324 个。

  • 2026 年块(C..Q)**不动**:当月值由导出代码回填,且其累计已与源文件一致;
  • EP(2021 累计同比)**保持为空**:页内没有 2020 年度块,无同比基期可引用;
  • 只改母版这一个文件。生成_道路运输量汇总表.xlsx 是列宽参照件(改它反而有列宽被 Excel 重写带偏的风险),_版式原型.xlsx 运行时未被引用,两者均不动;
  • 同期备份母版还原机制**不会**冲掉本次改动:resolveSummaryDonor(2026,8) 要求文件名以 _备份_ 开头且含「2026年8月」,目录下无匹配文件;导出日志亦确认「未找到同期备份母版」。

改动前备份:docs/生成汇总大表/_bak_202608母版修改前_20260916/(3 个原文件)。

实现方式用 Excel COM 打开母版改公式并 CalculateFullRebuild 后保存。**不可用 openpyxl 另存**:会清空全本公式缓存值(2026-09-16 曾因此让 2021 年湖北省行变成 0,见工作日结第十八节)。

3.2 数据库

操作 对象 影响行数
DELETE h2032_enterprise_monthly WHERE report_period='2026-09' 636
DELETE import_batch WHERE id=302 1

依据:batch 302 的文件名是「道路货物运输月度生产情况(2026年8月).xls」,却被存成 2026-09(2026-09-10 09:03:29 导入);2026-09-11 17:48 已用正确的 8 月文件重导为 2026-08(batch 320,同为 636 行 / 90 区划)。

备份(可还原):_backup_h2032_2026-09_rows_20260916.sql(636 个元组)、_backup_h2032_2026-09_batch302_20260916.sql。

四、测试环境

项 值
后端 Spring Boot,http://127.0.0.1:8090(运行中)
数据库 MySQL 8.0,127.0.0.1:3308,库 traffic_audit
导出接口 GET /api/report/export/summaryWorkbook?period=2026-08&mode=month
预览接口 GET /api/report/preview?period=2026-08&mode=month&types=summaryWorkbook
公式求值 Excel COM(CalculateFullRebuild)——导出件公式**无缓存值**,openpyxl 读出来全是 None,必须用 Excel 重算
源文件 D:\05_数据分类\高速\定稿-湖北省各市州运输量数据(2026年1-8月).xlsx(2021/2022/2024/2025/2026 页)+ D:\05_数据分类\货运\7月\定稿-湖北省各市州运输量数据(2026年1-7月).xlsx(2023 页)

五、用例表

5.1 正向用例

# 输入/操作 预期 实际 结论
P1 重导出 2026-08 汇总大表,Excel 重算后读 货运 全省行 6 个累计列 2021/2022/2023 与源文件一致 2026 差 -1.8e-6、2025 +4.1e-5、2024 -2.1e-5、2023 +2.9e-5、2022 -2.9e-11、2021 +2.0e-5(周转量同量级) 通过
P2 同上,读 2021 累计列 EO 有值且等于 161309.5316 161309.5316 通过
P3 导出件「全省行」逐月 vs「17 市州行之和」 差约等于 0 2021<=5.5e-12、2022<=5.5e-12、2023<=3.6e-12、2025<=5.5e-12(周转量 <=9.3e-10) 通过
P4 母版重算后同上 差约等于 0 2021-2025 全部 <=9.3e-10 通过
P5 导出件 2026 年 8 月当月值 全省货运量 16888.76 Q5=16888.7615,Q11(武汉市)=5173.1802 通过
P6 预览接口 types=summaryWorkbook 返回汇总指标 ready=true、rows=159、20 项指标(当月货运量 16888.76、累计 130311.89) 通过
P7 2021 累计同比 EA 抽查 分母为 0 的行不显示错误 EA5=-0.1012355、EA11=-0.0886607、EA90 空、EA111 空 通过

5.2 负向用例 / 回归用例

# 输入/操作 预期 实际 结论
N1 用 openpyxl 另存母版再导出(历史踩坑复现) 会丢公式缓存值,故**不采用**该实现 未采用;改用 Excel COM,缓存值保留 规避
N2 改母版时把公式写成 SUM(DM5) 之类残缺引用(首次脚本 "$m7" 被 PowerShell 当变量名) 应发现并回滚 已发现:从 _bak 备份还原后,改用 ${r}/${m} 定界重跑 通过
N3 2026-07 期导出(回归,母版未改) 仍能正常导出 _regress_summary_2026-07.xlsx 941,969 字节,货运 页 118x145 通过
N4 导出后查询 h2032_enterprise_monthly 是否还有 2026-09 无 2026-01...2026-08 各 636 行,无 2026-09 通过
N5 import_batch 是否还有 id=302 无 已删除 通过
N6 备份 SQL 可还原性 元组数应为 636 实测 636 个元组 通过

5.3 入库抽查

# 抽查项 结果
D1 h2032_enterprise_monthly 2026 年各期行数 / 区划数 2026-01 636/91,2026-02...08 各 636/90
D2 删除前后 rowcount 删 636 行(ROW_COUNT() 实测 636)、删 batch 1 行
D3 备份文件字节数 rows 725,989 字节 / batch 1,624 字节

六、修复前后对比(导出件实测)

年度 列 修复前 修复后 源文件核算 修复后差异
2026(1-8月) S 130311.8927 130311.8927 130311.8927 -1.8e-6
2025 AT 195433.2232 195433.2232 195433.2232 +4.1e-5
2024 BV 184938.5780 184938.5780 184938.5780 -2.1e-5
2023 CW 173045.2932 173045.2964 173045.2964 +2.9e-5
2022 DZ 144979.2854 144979.2825 144979.2825 -2.9e-11
2021 EO 空 161309.5316 161309.5316 +2.0e-5

周转量行:2021 21961780.4134、2022 20587594.6295、2023 24243256.5443、2024 25071499.8353、2025 26403562.8772、2026 17492129.0479,与源文件差异均 <=2.1e-4。

6/6 累计列在 4 位小数显示口径下与源文件人工核算完全一致。

七、发现的问题与处置

# 严重度 问题 处置
1 高 h2032_enterprise_monthly 多出 2026-09 期(实为 8 月文件) 已删除(含 batch 302),留可还原备份
2 高 母版「全省规下」行写死常量,导致 2022/2023 累计各差约 0.003 已改为 17 市州求和公式
3 中 母版 2021 累计列 EO 整列为空 已补 =SUM(EC:EN)
4 中 母版 2022 累计列 DZ、累计同比 EA 为写死常量 已改为公式
5 低 母版 Excel 重存后导出件体积由 950,186 -> 1,331,599 字节(Excel 自身格式开销,_版式原型.xlsx 同为 1.48MB 量级) 记录,不影响数据
6 低 导出件 货运 页存在 <=2.1e-4 的浮点累加噪声 记录,4 位小数显示一致
7 提示 另发现 2026-09 期还有:h204_vehicle_quarterly 1284 行(batch 142,与 2026-08 的 batch 144 同文件)、investment_monthly 31 行(batch 107,与 batch 108 同源)、audit_result 2061 行、audit_run 3 行 本次未动(不在授权范围),待用户确认是否一并清理
8 提示 2026-07 期导出件的 货运 页为 118x145(比 8 月少 2 列),因 7 月母版是「1-4 月骨架」 单独议题,待 7 月母版定稿

八、结论

  1. 用户问题「累计只有前面四个对得上」**已定位并解决**:根因不在累计公式本身,而在母版「全省规下」行是与 17 市州不符的写死常量;叠加 2021 累计列漏填、2022 累计列写死常量。
  2. 修复后 6 个累计列(S/AT/BV/CW/DZ/EO)在 4 位小数口径下与源文件人工核算**全部一致**。
  3. h2032_enterprise_monthly 2026-09 脏期已清除,备份可还原。
  4. 2026-07 导出回归通过;预览接口正常。
  5. 遗留:2026-09 在 h204_vehicle_quarterly / investment_monthly / audit_result / audit_run 中仍有数据,待用户确认是否清理。