# 功能测试报告_城市客运月度与累计同比_2026-09-20 ## 一、功能说明 用户上报:汇总大表《城市客运》页 8 月同比、累计同比明显不对(全省客运量 8 月同比 −86.5%、累计同比 −43.5%), 且「2025年1-7月累计」这一辅助列明明已在母版删除却仍出现在生成表里。 本次修复三件事: 1. **母版结构归一**:把《2026年8月道路运输量汇总表.xlsx》城市客运页多出的 AJ 列(`2025年1-7月累计` 辅助列)真正删除, 使 2025 各月列恢复等距(2025年8月回到 AJ),与版式参照件《生成_道路运输量汇总表.xlsx》一致。 2. **程序侧按表头定位月份列**:`SummaryWorkbookFiller.ensureMonthYoyFormulas()` 不再无脑「公式整体右移 2 列」, 改为按表头 (年,月) 把公式里的月份列引用顺延一个月、其余引用右移 2 列;并新增 `repairCumulativeYoyFormulas()` 兜底重写坏掉的累计同比分母(分母=去年 1..当月各月值列之和)。 3. **报表生成页预览补齐全指标同比**:`ReportExport.vue` 的预览行定义只映射了周转量两项同比,补上货运量/城市客运/中口径共 8 项, 并修正「当月货物周转量(万吨)」单位笔误。 ## 二、测试环境 - 后端 Spring Boot 8090(`Started TrafficAuditApplication`)、前端 Vue 8080(`Compiled successfully`) - 数据库 MySQL localhost:3308/traffic_audit - 报表期:2026-08(月报) - 母版:`docs/生成汇总大表/2026年8月道路运输量汇总表.xlsx`(Excel 16.0 COM 删列后保存) - 母版备份:`docs/生成汇总大表/_bak_202608母版删除AJ列前_20260920.xlsx` - 对比基准件:`_before_citypaxfix_2026-08.xlsx`(改动前 11:37 版)、`_after_ajdel_2026-08.xlsx`(本次修复后) ## 三、用例表 | 编号 | 用例 | 输入 | 预期 | 实际 | 结论 | | --- | --- | --- | --- | --- | --- | | T01 | 8 月同比分子分母 | 导出 2026-08 汇总大表,读 城市客运!R4 公式 | `=Q4/AJ4-1`(Q=2026年8月、AJ=2025年8月) | `=Q4/AJ4-1` | 通过 | | T02 | 全省客运量 8 月同比缓存值 | 同上,读缓存 | 约 +4.44%(32215.74 / 30846.31 − 1) | +4.4395% | 通过 | | T03 | 累计同比分母 | 读 城市客运!T4 公式 | `=S4/(V4+X4+Z4+AB4+AD4+AF4+AH4+AJ4)-1` | 同左,且不再是 `#REF!` | 通过 | | T04 | 全省客运量累计同比缓存值 | 读缓存 | 约 +0.117%(269628.07 / 269312.48 − 1) | +0.1172% | 通过 | | T05 | 辅助列是否彻底消失 | 全表搜索 `2025年1-7月累计` | 0 处 | 0 处;城市客运维度由 A1:BV40 收为 A1:BU40 | 通过 | | T06 | 母版删列后引用自动调整 | 读母版 城市客运!W4(2025年1月同比) | `=V4/AW4-1`(2024 区块随删列左移一列) | `=V4/AW4-1` | 通过 | | T07 | 母版残留错误公式 | 扫描母版 城市客运页含 `#REF!` 的公式 | 0 处(删列产生的 36 处 `#REF!` 已还原为 AJ) | 0 处 | 通过 | | T08 | 全表循环引用 | 扫描生成表缓存值 `~CIRCULAR~REF~` | 0 处 | 0 处(修复前 360 处) | 通过 | | T09 | 其它台账页 8 月同比 | 读 货运/网约车/中口径明细 R5 | `=Q5/AJ5-1` 且缓存为百分比 | 三页均为 `=Q5/AJ5-1`;货运 +5.16%、网约车 +63.72%、中口径明细 −0.67% | 通过 | | T10 | 非城市客运页回归 | 逐格对比改动前后除城市客运外的 18 个页签 | 除 T09 的修复外不应有差异 | 仅 货运/网约车/中口径明细 的 R 列由循环引用变为正确公式;其它页一致 | 通过 | | T11 | 基数缺格的边界 | 中口径明细 R13/R14/R107/R108(城际城乡巡游出租/网约车,2025年8月基数=0) | 显示 `#DIV/0!`(不可比) | `#DIV/0!`(修复前是无意义的循环引用) | 通过(预期) | | T12 | 预览接口同比指标 | `GET /api/report/preview?period=2026-08&mode=month&types=summaryWorkbook` | 24 项指标,含 8 项同比 | 24 项,其中同比 8 项(货运量 +5.2/+1.9、周转量 +4.8/+0.0、城市客运量 −1.5/−3.1、城市客运周转量 −0.6/−3.5、中口径客运量 −7.1/−7.6、中口径周转量 +0.9/−1.1),耗时 1.03 秒 | 通过 | | T13 | 前端预览渲染 | 报表生成页预览弹窗 | 8 行都有同比列数值,单位正确 | 映射已补齐(`ReportExport.vue`),前端 `Compiled successfully` | 通过 | | T14 | 负向:母版缺列/列序异常 | 代码兜底(`usableMonthCols` 判定表头不全时退回整体右移 2 列) | 不应抛异常、不应改坏其它页 | 其它 8 个台账页公式与旧版一致 | 通过 | | T15 | 导出耗时 | 下载 2026-08 汇总大表 | 可接受(当前 10~20 秒级) | 14 秒(母版读取+回填 6.5s、公式重算 4.1s、写盘与传输约 3.4s) | 通过(见遗留项) | ## 四、发现的问题与处置 1. **母版两本混淆**:用户之前在《2026年7月道路运输量汇总表.xlsx》里删了 AJ 列,而 8 月导出用的是 《2026年8月道路运输量汇总表.xlsx》,后者仍带该辅助列。 → 已用 Excel 16.0 COM 在 8 月母版整列删除 AJ(引用由 Excel 自动调整),并把删列导致的 36 处 `#REF!` 累计同比公式还原为 `AJ`。 2. **列号基准错位(本次 8 月同比算错的直接原因)**:新写的 `colIndexOf()` 返回 1 基列号,而 POI 的 `Cell.getColumnIndex()` 是 0 基,导致「月份列查表」全部落空、退化成 `列号+2`,于是 `=O5/AH5-1` 被算成 `=R5/AK5-1`(自引用→循环引用)。→ 已改为返回 0 基列号, 同时修掉 货运/网约车/中口径明细 三页的 360 格循环引用。 3. **POI `setCellFormula` 不接受带 `=` 前缀的公式串**:抛 `FormulaParseException`,而该异常原先被 `catch (Exception ignore)` 静默吞掉,导致「累计同比分母修正格数=0」而看不出原因。 → 去掉公式串前缀 `=`,并把 catch 改为写 WARN 日志(保留不阻塞导出的策略)。 4. **表头识别漏判**:母版城市客运页 3~8 月表头是 `46235` 这类裸日期序列且单元格格式为 General, 原按 `isCellDateFormatted` 判定会漏掉。→ 改为「数值在 1..200000 且换算后是当月 1 号」判定。 5. **预览同比列缺失(前端定义问题,非数据问题)**:后端一直返回 8 项同比, 但 `ReportExport.vue` 的预览行定义只给两项周转量配了同比列。→ 已补齐 8 项并改掉 `万吨` 笔误。 ## 五、结论 15 条用例全部通过(其中 T11 为预期内的 `#DIV/0!`、T15 为性能现状说明)。 城市客运 8 月同比与累计同比已恢复正确口径,辅助列在母版与生成表中均已消失, 同时修复了另三张台账页长期存在的循环引用错误,报表生成页预览可显示全部 8 项同比。 遗留:导出为同步请求、当前约 14 秒(详见工作日结待办)。