traffic-audit-server/src/main/java/com/trafficaudit/reportexport/layout/SummaryLayoutExpander.java
@@ -208,8 +208,8 @@
            if (headerRows.contains(r)) continue;
            Row row = sh.getRow(r);
            if (row == null) continue;
            cloneDataCell(row, srcVal, insertCol, shiftable, insertCol);
            cloneDataCell(row, srcYoy, insertCol + 1, shiftable, insertCol);
            cloneDataCell(row, srcVal, insertCol, shiftable);
            cloneYoyCell(row, srcYoy, insertCol + 1, insertCol, lastYearSameMonth + 2);
        }
        // 5) 累计列补当月项;累计同比分母补去年同月列
        int cumCol = insertCol + 2, cumYoyCol = insertCol + 3;
@@ -348,17 +348,47 @@
        }
    }
    private void cloneDataCell(Row row, int srcCol, int dstCol, Set<String> shiftable, int insertCol) {
    private void cloneDataCell(Row row, int srcCol, int dstCol, Set<String> shiftable) {
        Cell s = row.getCell(srcCol);
        if (s == null) return;
        Cell d = getOrCreate(row, dstCol);
        d.setBlank();
        d.setCellStyle(s.getCellStyle());
        if (s.getCellType() == CellType.FORMULA) {
            d.setCellFormula(shiftRefs(s.getCellFormula(), insertCol, shiftable));
            d.setCellFormula(shiftRefsAll(s.getCellFormula(), shiftable));
        }
    }
    /** 当月同比列:不克隆上月公式,直接按「本月值 / 去年同月 − 1」重写(去年同月列已按表头定位) */
    private void cloneYoyCell(Row row, int srcCol, int dstCol, int valCol0, int denCol0) {
        Cell s = row.getCell(srcCol);
        if (s == null) return;
        Cell d = getOrCreate(row, dstCol);
        d.setBlank();
        d.setCellStyle(s.getCellStyle());
        if (s.getCellType() == CellType.FORMULA) {
            int excelRow = row.getRowNum() + 1;
            d.setCellFormula(colLetter(valCol0) + excelRow + "/" + colLetter(denCol0) + excelRow + "-1");
        }
    }
    /** 相对复制用的平移:把本页/已扩列页的引用整体 +2(不做列号阈值判断) */
    private String shiftRefsAll(String formula, Set<String> shiftable) {
        Matcher m = REF.matcher(formula);
        StringBuffer sb = new StringBuffer();
        while (m.find()) {
            String sheet = m.group(2) != null ? m.group(2) : m.group(3);
            if ((sheet != null && !shiftable.contains(sheet)) || isFunctionName(formula, m)) {
                m.appendReplacement(sb, Matcher.quoteReplacement(m.group(0)));
                continue;
            }
            int colIdx = colIndex(m.group(5));
            m.appendReplacement(sb, Matcher.quoteReplacement(rebuild(m, sheet, colIdx + 2)));
        }
        m.appendTail(sb);
        return sb.toString();
    }
    private void shiftAllRefs(Sheet sh, int insertCol, Set<String> shiftable) {
        for (int r = 0; r <= sh.getLastRowNum(); r++) {
            Row row = sh.getRow(r);