状态:**【待验收】本轮只定规格与工作量,不含代码改动**;规格经用户审定后再开工。
依据:docs/汇总大表数据驱动改造方案_2026-09-07.md(含 2026-09-08 附录)、HANDOFF.md的 2026-09-28 / 09-29 两节、2026-09-29 用户手工产出的 9 月母版。
exportSummaryWorkbook 已按「读库计算 → 回填母版 → 整本重算」运行(ReportExportService.java:3634 起,计算层 reportexport/calc)。{year}年{month}月道路运输量汇总表.xlsx 精确匹配母版(ReportExportService.resolveSummaryMother,同文件 4576 行),目标月没有对应母版就直接抛错,不会自动扩列。9 月母版是用户 09-29 在 Excel 里手工扩出来的(本机 docs/生成汇总大表/2026年9月道路运输量汇总表.xlsx、_试做_20260929.xlsx,均未入库)。| 层次 | 现状 | 结论 |
|---|---|---|
| 计算层 | reportexport/calc/{PaxCalc,FreightCalc,MidCalc,WycSplitCalc},约 900 行 |
直接复用 |
| 回填层 | SummaryWorkbookFiller(899 行):fillMonthlyLedger / ensureMonthFormulas / ensureMonthYoyFormulas / repairCumulativeYoyFormulas / yearMonthCols / usableMonthCols / cumulativeHelperCols |
直接复用 |
| 扩列原语 | ReportExportService.java:1039-1200:moveColumnPair / cloneColumnPair / cloneCellForMonth / cloneMergedRegion / copyColumnWidth / fixCumulativeFormulas;且已跑通 extendMonthlyColumns(独立小表 1–6 月 → 1–12 月) |
直接复用 |
| 缺口 | 把上述原语**编排**到汇总大表 19 个页签里的 10 个长表页,并逐页配置规则 + 回归自检 | 本次新增 |
已有投入(不可丢弃):38 个提交、930 格差异核对、A1–E3/Q1–Q3 一轮口径拍板。重写不划算。
| 项 | 规则 |
|---|---|
| 当月值列 | 1 月 = 2(C 列);m 月 = 2 + 2 × (m − 1) |
| 当月同比列 | 当月值列 + 1 |
| 累计列 / 累计同比列 | 2026 组末尾,当前 14/15(O/P);扩到 12 月后为 26/27 |
| 2025 及更早参照组 | 每扩一个月整体右移 2 列 |
| 已确认口径(方案 D1) | 当月值列+同比列插在累计之前、累计滚动、2025+ 参照组右移——等价于本文件的「月度版式重建器」 |
SummaryWorkbookFiller.FIRST_MONTH_COL=2(同文件 47 行)与该公式一致,但属硬编码锚点,见第七节第 4 条。
| 页签 | maxCol | 合并区 | 需平移的公式数 |
|---|---|---|---|
货运(注意前导空格) |
145 | 140 | 6638 |
| 班线包车 | 285 | 204 | 5688 |
| 中口径明细 | 87 | 157 | 6654 |
| 公交 | 86 | 76 | 2004 |
| 出租 | 86 | 76 | 1872 |
| 网约车 | 86 | 70 | 1664 |
| 公路总客运 | 274 | 194 | 未单独统计 |
| 城市客运 | 72 | 55 | 未单独统计 |
| 轨道、轮渡 | 72 | 110 | 未单独统计 |
| 中口径客运量 | 68 | 111 | 未单独统计 |
已知 6 页公式平移合计约 24,520 处(公交 2004 / 出租 1872 / 网约 1664 / 中口径明细 6654 / 货运 6638 / 班线 5688)。
traffic-audit-server/src/main/java/com/trafficaudit/reportexport/layout/SummaryLayoutRebuilder.java:编排层,按目标月重建 10 个长表页的列布局。traffic-audit-server/src/main/java/com/trafficaudit/reportexport/layout/SummarySheetRule.java:逐页规则配置(表头行、数据起止行、月份组起点、累计列位、是否派生页、合并区策略)。traffic-audit-server/src/test/java/com/trafficaudit/reportexport/layout/SummaryLayoutRebuilderTest.java:扩列后 7/9 月数值回归自检。ReportExportService.exportSummaryWorkbook(同文件 3634 行起):母版缺失时不再抛错,改为「取最近可用母版 → 重建到目标月 → 继续回填」。ReportExportService.resolveSummaryMother(同文件 4576 行):放开"仅精确匹配"限制,保留"找不到任何蓝本才报错"。SummaryWorkbookFiller.FIRST_MONTH_COL 硬编码改为按表头 yearMonthCols 语义定位,避免母版挪列后静默写错列。HANDOFF.md 结论;_试做_20260929.xlsx 等过程产物不入库。yearMonthCols 的表头识别(支持文本 2026年8月 与数值日期序列表头,只认今年/去年),在前 5 行内找出各月份组的实际列位——先认位置再动列,不盲信固定列号。setFullCalcOnLoad(true) + 整本重算;输出前跑「#REF! 计数 = 0」「累计列覆盖到当期」自检,不通过则中止。| 编号 | 用例 | 预期 |
|---|---|---|
| 1 | 重建版式后生成 2026-07 | 与已修正 7 月母版被填区域逐格 diff=0,仅列位变化 |
| 2 | 生成 2026-09 | 与用户手工 9 月母版逐格 diff=0 |
| 3 | 公式自检 | 全簿 #REF! = 0;累计/累计同比覆盖到当期 |
| 4 | 版式自检 | 合并区、列宽、隐藏标记、打印区与手工 9 月母版一致;Excel/WPS 打开无修复告警 |
| 5 | 负向:目标月源数据缺失 | 给出缺数清单,不静默输出空表 |
| 6 | 负向:母版被改导致月份表头识别不到 | 明确报错,不猜测列位 |
| 阶段 | 预估 |
|---|---|
| 规格表定稿(本文件 + 用户审定) | 0.5 天 |
| Rebuilder + 逐页规则 + 单测 | 1.5–2.5 天 |
| 7/8 月回归 + 9 月对照核对 | 1 天 |
| 风险缓冲 | 0.5–1 天 |
| 合计 | 约 3.5–5 天(含测试与验收) |
说明:HANDOFF.md 09-29 节曾估「0.5~1 天」,那只是扩列原语的复用估计;按附录实测(约 2.45 万处公式平移 + 2 千余处合并区)重估为 3.5–5 天。
ZipSecureFile.setMinInflateRatio 绕过)与残留 <is> 非法格(normalizeStaleInlineStrings 清理)两类问题,逐列克隆时需保持这两处处理。未覆盖页:中口径分析等 3 个静态页仍沿用母版静态内容,本阶段不改。
| 同事专项统计的做法 | 他为什么能成立 | 汇总大表的对应做法 |
|---|---|---|
一份母版(2026年十一数据.xlsx),**天为行、年为列** |
增长维度是「年」,一年加一组列;天数固定 8 | 冻结《道路运输量汇总表_标准母版.xlsx》:**12 个月满版式一次到位**,只读 |
| 母版同时是数据容器(历史年份的值就在并排年列里) | 历史值随模板一起走 | 反过来做:历史参照值入库,母版只留版式,参照组由 DB 回填 |
表头/行标签语义定位(findYearColumn / parseDayIndex) |
列序变了也能导 | 新增页规则表 SummarySheetRule:按表头认月份组、按行标签认市州/指标,不用硬编码列锚点 |
易漂移口径外置成表(holiday_calendar / passenger_coefficient / vehicle_adjustment) |
规则不散在代码与单元格里 | 参照年保留组数、排名口径(全省不排名)、周转量系数 B=G+L/2+Q/10、缺数置空规则 外置 |
DECIMAL(30,15) + BigDecimal + 按 Excel 显示精度取值 |
精度口径统一,无浮点尾差 | 承接长期待办「16 张表 228 个 double 列改 DECIMAL + BigDecimal」 |
| 导入两阶段确认 + 全程只读核对 | 历史数据不被误覆盖 | 生成前先出缺数/差异清单,人工确认后再出表(现有 B4 基数体检补齐) |
| 输出走模板文件(docx / PNG) | 版式来源单一 | 保留现有做法(快报改 word/document.xml、JFreeChart 出 PNG) |
SummaryLayoutRebuilder / SummarySheetRule / 单测。resolveSummaryMother)+ _备份_ donor(resolveSummaryDonor / restoreSummaryMonthlyBlocks)+ 版式参照件(resolveSummaryLayoutRef)。docs/生成汇总大表/ 下只剩 1 个模板文件 + 输出目录(_bak_* 等本地留存、不入库)。<is> 非法格两类历史坑。