| | |
| | | |
| | | private static final int HEADER_SCAN_ROWS = 15; |
| | | |
| | | /** 标题由程序在出表时现写的 7 个页签(母版里的标题文字需按母版期次重写)。 */ |
| | | private static final List<String> TITLE_PAGES = Arrays.asList( |
| | | "货运量排名", "货运周转量排名", "城市汇总", "城市分市州", "中口径排名", "中口径分析", "道路运输周转量"); |
| | | |
| | | /** 标题识别标记(命中其一才改写,避免误伤备注等文字)。 */ |
| | | private static final List<String> TITLE_MARKERS = Arrays.asList( |
| | | "全省分市州累计完成公路货运量情况", "全省分市州完成公路货运量情况", |
| | | "全省分市州累计完成公路货物运输周转量情况", "全省分市州完成公路货物运输周转量情况", |
| | | "全省累计完成城市客运量情况", "全省完成城市客运量情况", |
| | | "分市州1-", "全省分市州累计完成道路客运生产情况", "全省分市州完成道路客运生产情况", |
| | | "中口径客运量及周转量", |
| | | "全省累计完成交通周转量情况", "全省完成交通周转量情况"); |
| | | |
| | | /** 公式里的 A1 引用(可带工作表前缀)。 */ |
| | | private static final Pattern REF = Pattern.compile( |
| | | "(?:('([^']+)'|([A-Za-z_\\u4e00-\\u9fff][A-Za-z0-9_.\\u4e00-\\u9fff\u3001]*))!)?(\\$?)([A-Z]{1,3})(\\$?)(\\d+)"); |
| | |
| | | if (sh == null || expanded.contains(sh.getSheetName())) continue; |
| | | shiftQualifiedRefs(sh, insertColOf); |
| | | } |
| | | int titleFixed = applyTitles(wb, year, targetMonth); |
| | | if (titleFixed > 0) { |
| | | log.info("扩列:标题按 {}年{}月 重写 {} 格", year, targetMonth, titleFixed); |
| | | } |
| | | wb.setForceFormulaRecalculation(true); |
| | | ByteArrayOutputStream out = new ByteArrayOutputStream(); |
| | | wb.write(out); |
| | |
| | | } |
| | | } |
| | | |
| | | /** 只把 7 个标题页的标题按给定期次重写(用于修正母版里滞后的标题)。 */ |
| | | public byte[] fixTitles(byte[] source, int year, int month) { |
| | | try (XSSFWorkbook wb = new XSSFWorkbook(new ByteArrayInputStream(source))) { |
| | | int n = applyTitles(wb, year, month); |
| | | wb.setForceFormulaRecalculation(true); |
| | | ByteArrayOutputStream out = new ByteArrayOutputStream(); |
| | | wb.write(out); |
| | | log.info("汇总大表标题修正完成:{}年{}月,改写 {} 格", year, month, n); |
| | | return out.toByteArray(); |
| | | } catch (Exception e) { |
| | | throw new IllegalStateException("汇总大表标题修正失败: " + e.getMessage(), e); |
| | | } |
| | | } |
| | | |
| | | /** 把 7 个页签的标题文字按「累计=1-M月、当月=M月」重写;命中标记才改,避免误伤备注。 */ |
| | | private int applyTitles(XSSFWorkbook wb, int year, int month) { |
| | | int changed = 0; |
| | | for (String page : TITLE_PAGES) { |
| | | Sheet sh = wb.getSheet(page); |
| | | if (sh == null) continue; |
| | | int lastRow = Math.min(sh.getLastRowNum(), 40); |
| | | for (int r = 0; r <= lastRow; r++) { |
| | | Row row = sh.getRow(r); |
| | | if (row == null) continue; |
| | | for (int c = 0; c <= 1; c++) { |
| | | Cell cell = row.getCell(c); |
| | | if (cell == null || cell.getCellType() != CellType.STRING) continue; |
| | | String t = cell.getStringCellValue(); |
| | | if (t == null || !looksLikeTitle(t)) continue; |
| | | String nt = t.replaceAll("(\\d{4})年", year + "年") |
| | | .replaceAll("(\\d{1,2})月", month + "月"); |
| | | if (!nt.equals(t)) { |
| | | cell.setCellValue(nt); |
| | | changed++; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | return changed; |
| | | } |
| | | |
| | | private boolean looksLikeTitle(String t) { |
| | | for (String m : TITLE_MARKERS) { |
| | | if (t.contains(m)) return true; |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | /** 对单页扩列,返回插入位置(0 基列号)。 */ |
| | | private int expandSheet(Sheet sh, int year, int targetMonth) { |
| | | int lastMonth = targetMonth - 1; |