状态:**【待验收】本轮只定规格与工作量,不含代码改动**;规格经用户审定后再开工。
依据: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 | 按 F10「按月按需扩列」:读 N 月母版自动产出 N+1 月版式(不预留空列),母版只当版式来源 |
| 母版同时是数据容器(历史年份的值就在并排年列里) | 历史值随模板一起走 | 反过来做:历史参照值入库,母版只留版式,参照组由 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_* 等本地留存、不入库)。母版改为只读,可顺带规避 WPS/openpyxl 重存带来的高压缩与残留 <is> 非法格两类历史坑。
| 表 | 主键(粒度) | 值 | 类别 |
|---|---|---|---|
| holiday_passenger_flow | 年 + 日期 + 运输方式 | 客运量 | 原始值 |
| holiday_vehicle_flow | 年 + 日期 + 道路类别 + 车型 | 车流量、环比基期 | 原始值 |
| holiday_calendar | 年 + 节假日类型 + 第几日 | 日期 | 配置值 |
| holiday_passenger_coefficient | 年 + 日期类别 | 客运系数 | 配置值 |
| holiday_vehicle_adjustment | 年 + 日期 | 调整后值 + 原因 | 人工调整值 |
我们现有导入表同样满足该约定:city_bus_monthly(报表期 + 地区 + 企业)、city_taxi_monthly(报表期 + 地区)、freight_turnover_import(报表期 + 地区)、scale_split_transport(报表期 + 地区 + 月/累计)、h2031_enterprise_monthly(报表期 + 企业)、h2032_enterprise_monthly、wyc_order_monthly / wyc_total_monthly、passenger_individual_monthly。存储层形态是对的。
holiday_vehicle_adjustment)。实测库 127.0.0.1:3308 / traffic_audit(MySQL 8.0.29):
| 表 | 2025 月份数 | 结论 |
|---|---|---|
| city_bus_monthly | 12/12 | 齐全 |
| city_taxi_monthly | 12/12 | 齐全 |
| wyc_order_monthly / wyc_total_monthly | 12/12 | 齐全 |
| h2031_enterprise_monthly / h2032_enterprise_monthly | 12/12 | 齐全 |
| passenger_individual_monthly | 12/12 | 齐全 |
| freight_turnover_import | 1/12(仅 2025-12) | 不构成缺口:表带 last_freight_m01..m12 / last_turnover_m01..m12,2026 各期文件自带去年同月值 |
| scale_split_transport | 0/12 | 不构成缺口:表带 above/below/total_yoy,同比已随 2026 各期入库 |
ReportExportService.java:499 / 558 / 561)**已过期**,触发条件不再成立;同比取数走的是库内去年同期(aggOf(data, year-1, m, "湖北省"),约 540 行)。readMidDetailLastYearCumulative,ReportExportService.java:2745 起),代码注释(2686-2689 行)说明原因——"排名页原先查库现算,两者在 2025-03/04 网约车拆分上不同"。docs/要求与验收基线清单.md F8、确认回执 Q1);库内 2025 现算值**不得**直接替代母版静态定稿值,仅当人工核对并重导一致后才切库值。详见第十三节。母版里不允许存在「只有它才有的数据」。
判定方法:把母版所有值清空后,程序能否重新生成一张完全一致的表?能 → 数据都在库;不能 → 还有数据藏在 Excel 里,继续往库里搬。
M0 阶段 2「停用 _备份_ donor 还原」的数据前提**已基本满足**(2025 已在库);但仍需先关闭 12.4 的差异,否则切换取数来源会让数字变动、无法通过 diff=0 回归。
| 出处 | 原文要点 | 状态 |
|---|---|---|
docs/要求与验收基线清单.md F8 |
2025 年前数据以母版缓存为准;**母版缓存优先作同比基准,库只做校验**,人工核对重导一致后才切库值(Q1) | ✅ 口径确认 |
docs/确认回执汇总与剩余疑问_汇总大表数据驱动改造_2026-09-07.md Q1 |
以母版缓存为同比基准并仅提示;待人工核对后重导一致再切换为库值("母版缓存优先,库仅作校验参考") | 已确认 |
docs/汇总大表数据驱动改造方案_2026-09-07.md 第九节 |
2025 定稿数据"前台导入校验"另立任务;**本期同比一律以母版缓存为基准** | — |
docs/待确认_汇总大表数据驱动改造问题清单_2026-09-07.md A1 |
2025 及以前历史列一律**保留母版缓存、不重算** | — |
docs/问题汇总/汇总大表问题交接_2026-09-21.md 方案 A |
中口径排名取去年同期累计改用母版 2025 静态列(与中口径明细同源),已实施 | 已实施 |
结论:**库内 2025 现算值不能直接替代母版 2025 静态定稿值**;切换的唯一前提是"人工核对并重导一致"。第十二节 12.4 中"交业务确认以哪边为准"的表述据此修正(见该节 2026-10-09 修正行)。
| 出处 | 原文要点 | 状态 |
|---|---|---|
docs/要求与验收基线清单.md F10 |
扩列按月按需(加月份才扩列,不预做 12 月满版);新增列"当月/同比"标题为两行合并单元格,扩列须保留 | ✅ M0 v4 |
docs/汇总大表数据驱动改造方案_2026-09-07.md v1.1 修订(2026-09-08 用户拍板) |
正文"12 月满版列版式"建议**作废**;扩列按"每月需增月份时再扩列"执行(=D1 原口径) | 已拍板 |
→ 已裁定(2026-10-09 用户确认):沿用既有口径 F10「按月按需」,本文档第九/十一节的"满版式"建议**作废**(上文已就地标注)。
docs/问题汇总/_*.md 已被 gitignore 命中)docs/问题汇总/_扩列规格表_2026-09-29.md / .csv:19 页逐页规格——类型(A 月份对+累计 / B 部分月份对 / C 未识别月份对)、各页月份对列位、累计列、建议插入位置、数据行范围、标题写法。docs/问题汇总/_扩列配置初稿_20260929.md / .csv、_扩列计划_v3..v10.json:配置与计划迭代(v10 仅剩 轨道、轮渡 一页)。docs/问题汇总/_扩列进度_20260929.md:8 月→9 月扩列进度——8 页已插列;6 项待修(表头显示/合并区/累计只到 8 月且多写 +Q/累计同比去年基数只到 8 月/标题月份未 +1/轨道轮渡需按块分别插列);若干页插入位置待确认。docs/生成汇总大表/2026年9月道路运输量汇总表_试做_20260929.xlsx(结构可看、数值未修完,勿用于出表)。→ 本规格应与上述产物对齐推进,不再另行设计。
docs/待确认_汇总大表数据驱动改造问题清单_2026-09-07.md A4:**"稳定后母版只当版式模板,月度数据一律程序填"**——与本文档目标一致。
做法:本次只做一件事——**把"扩列"变成程序的常规能力**,其余已确认口径一律不动。
| # | 动作 | 依据 |
|---|---|---|
| 1 | 实现**按月按需扩列器**:读 N 月母版 → 克隆 N+1 月"值列+同比列"一对 → 累计列后移 → 显式重写累计/累计同比 → 同步表头(两行纵向合并标题)与页面标题 → 输出(**只到当月、不预留空列**);同时把结果落盘为下期母版 | F10 / D1 / D2 / 确认回执六.4 |
| 2 | 三条必改点做全:① 新月份同比公式;② 累计列枚举补当月;③ 插列右侧 2025/2024/2023 历史区几千条公式引用 +2 | 09-21 交接 §5.2 |
| 3 | 先修两处写死的列位置:SM_CUR_COL0=2(2026年1月=C)、SM_LAST_COL0=21(2025年1月=V)改为**按表头动态定位**;否则 2025 块一右移,四张跨页合成页会读错去年基数 |
docs/汇总大表母版扩列配置初稿_2026-09-29.md 第五节 |
| 4 | 累计同比分母**按表头定位"去年 M 月"列**重写公式(只累加奇数列),不写死列清单;版式对齐改为按表头文字匹配列 | C3 / C4(09-18 长效方案) |
| 5 | 同比基准不动:2025 列原样保留;库只做校验(B4 基数体检可作校验位),**不切库值**;_备份_ donor 还原先保留作回归对照 |
F8 / Q1 / A3 / 09-21 方案 A |
| 6 | 每页规则用配置钉死、不靠自动识别;识别不了的页跳过并报告 | 配置初稿 §六.3 |
验收(沿用既有 E1 / §5.4)
_试做_20260929.xlsx 只作结构参考,不作数值真值);#REF!=0、8 月及以前列逐格未变、累计=1~M 月、累计同比含 2025 年第 M 月、两行合并标题保留、错误值不增。规格来源(2026-10-09 由本地过程产物转正入库)
docs/汇总大表母版扩列规格_2026-09-29.md / .csv —— 19 页逐页规格(A/B/C 类型、月份对列位、累计列、插入位置、数据行范围、标题)docs/汇总大表母版扩列配置初稿_2026-09-29.md —— 逐页列位配置 + 硬前提(写死列位置)+ 建议方案已定(2026-10-09 用户确认)
货运、班线包车、城市客运、公交、出租、网约车、轨道、轮渡、中口径明细。公路总客运、2025年城市客运量、中口径客运量、中口径计算过程(用户 2026-10-09 拍板;依据 09-03《自动生成汇总工作簿落地方案》§1)。**不插列、不改公式**(独立 sheet,别的页插列不会带错它们)。本拍板同时消解 09-29 规格表把 中口径客运量 标为 A 类、配置初稿标为"无 2026 月份对"的矛盾。城市汇总/城市分市州/中口径分析/道路运输周转量 由程序刷新(refreshSummaryCumulativeSheets);货运量排名/货运周转量排名/中口径排名 按模板填数。state="hidden",非 veryHidden,右键标签可取消隐藏)。落盘与文件管理(2026-10-09 用户确认;非待确认项)
docs/生成汇总大表/输出/**(命名 _扩列_YYYY年M月_待确认.xlsx),**人工确认后**才重命名落盘为当期母版 {年}年{月}月道路运输量汇总表.xlsx。docs/生成汇总大表/归档/;2026年8月…_版式原型.xlsx 一并归档。生成_道路运输量汇总表.xlsx:**扩列器跑通后归档**;归档前完成 C4 两步——① 把参照件的列宽/隐藏一次性固化进当期母版;② applySummaryReferenceLayout(:3785)改按**表头文字匹配列**(现为按列序号,一插列即错位)。_备份_* / _bak_*:按 A3 保留到回归验证通过后再清理。实施要点(实测得出,非决策项)
货运 77+8、班线包车 109、中口径明细 32+14、中口径排名 17+9 等)→ 固化不是空操作。copyColumnWidth(ReportExportService.java:1186)**只复制宽度、不复制 hidden** → 扩列器克隆月份列时须补 hidden,否则新列永远要靠参照件补版式。