From dc8d7202354d43658b500951efc5a6af53170ab3 Mon Sep 17 00:00:00 2001
From: zhizhijie <zhizhijie@users.noreply.gitee.com>
Date: 星期五, 18 九月 2026 11:09:52 +0800
Subject: [PATCH] fix(汇总表): 扩页补当月值公式 + 生成件公式重算,修 8 月空白与全省行停在上一期

---
 traffic-audit-server/src/main/java/com/trafficaudit/reportexport/service/ReportExportService.java |   74 +++++++++++++++++++++++++++++++++++++
 1 files changed, 74 insertions(+), 0 deletions(-)

diff --git a/traffic-audit-server/src/main/java/com/trafficaudit/reportexport/service/ReportExportService.java b/traffic-audit-server/src/main/java/com/trafficaudit/reportexport/service/ReportExportService.java
index b006de5..1950983 100644
--- a/traffic-audit-server/src/main/java/com/trafficaudit/reportexport/service/ReportExportService.java
+++ b/traffic-audit-server/src/main/java/com/trafficaudit/reportexport/service/ReportExportService.java
@@ -3360,12 +3360,82 @@
                     + "鎸夈�婄敓鎴恄閬撹矾杩愯緭閲忔眹鎬昏〃銆嬪榻愬垪瀹藉垪鏁�={}锛岀己鏁版彁绀�={}",
                     dbFilled, yoyFilled, monthFormulaFilled, rankRefreshed, cumulativeRefreshed, widthApplied, dbProblems);
             applyTwoDecimalFormat(wb); // 鏁板�兼樉绀轰袱浣嶅皬鏁帮紙淇濈暀鍏ㄧ簿搴︼級锛�% / 鏃ユ湡绛夋棦鏈夋牱寮忎笉鏀瑰彉
+            int inlineFixed = normalizeStaleInlineStrings(wb); // 娓呮帀銆岄潪 inlineStr 鍗存畫鐣� <is>銆嶇殑闈炴硶鏍硷紝鍚﹀垯 Excel 鎷掔粷鎵撳紑
+            if (inlineFixed > 0) log.warn("姹囨�诲伐浣滅翱娓呮帀娈嬬暀 inlineStr 闈炴硶鏍� {} 涓紙姣嶇増鐢� openpyxl 鍐欏嚭鏃剁殑鍏稿瀷闂锛�", inlineFixed);
+            int[] recalc = recalcWorkbookFormulas(wb); // 鍏紡閲嶇畻骞跺啓鍥炵紦瀛樺�硷細鍏ㄧ渷琛�(危甯傚窞)/绱鍒�/鎺掑悕 SUM 鎵嶈兘琚瑙堜笌浜屾澶勭悊璇诲埌
+            log.info("姹囨�诲伐浣滅翱鍏紡閲嶇畻瀹屾垚锛氭垚鍔� {} 鏍硷紝澶辫触 {} 鏍硷紙澶辫触鏍间繚鐣欐瘝鐗堟棫缂撳瓨鍊硷紝鎵撳紑鏃舵寜 fullCalcOnLoad 閲嶇畻锛�", recalc[0], recalc[1]);
             if (!wb.getCTWorkbook().isSetCalcPr()) wb.getCTWorkbook().addNewCalcPr();
             wb.getCTWorkbook().getCalcPr().setFullCalcOnLoad(true); // 杩樺師/鏀瑰啓鍏紡鍚庢墦寮�鍗抽噸绠�
             return toBytes(wb);
         } finally {
             ZipSecureFile.setMinInflateRatio(savedZipRatio);
         }
+    }
+
+    /**
+     * 姹囨�诲伐浣滅翱鍏紡閲嶇畻锛歅OI 鍐欐枃浠朵笉甯︾紦瀛樺�硷紝瀵艰嚧銆屽叏鐪佽锛埼�17甯傚窞锛夈�嶃�岀疮璁″垪銆嶃�屾帓鍚� SUM銆�
+     * 鍦ㄩ瑙�/浜屾澶勭悊閲屽彧鐪嬪埌姣嶇増涓婁竴鏈熺殑鏃у�硷紙2026-09-18 鐢ㄦ埛鎶モ��8鏈堟病鏁版嵁 / 鍏ㄧ渷琛屽仠鍦ㄤ笂涓�鏈熲�濈殑鏍瑰洜涔嬩竴锛夈��
+     * 閫愭牸 evaluate 骞舵妸缁撴灉鍐欏洖缂撳瓨鍊硷紱涓埆涓嶆敮鎸佸嚱鏁�/澶栭儴寮曠敤鏍煎け璐ュ垯璺宠繃骞惰鏁帮紝涓嶉樆濉炲鍑恒��
+     */
+    private int[] recalcWorkbookFormulas(XSSFWorkbook wb) {
+        if (wb == null) return new int[]{0, 0};
+        org.apache.poi.ss.usermodel.FormulaEvaluator ev;
+        try {
+            ev = wb.getCreationHelper().createFormulaEvaluator();
+        } catch (Exception e) {
+            log.warn("姹囨�诲伐浣滅翱鍏紡閲嶇畻锛氬垱寤烘眰鍊煎櫒澶辫触锛岃烦杩囷紙{}锛�", e.getMessage());
+            return new int[]{0, 0};
+        }
+        int ok = 0, fail = 0;
+        java.util.List<String> samples = new java.util.ArrayList<>();
+        for (int i = 0; i < wb.getNumberOfSheets(); i++) {
+            Sheet sh = wb.getSheetAt(i);
+            if (sh == null) continue;
+            for (Row row : sh) {
+                if (row == null) continue;
+                for (Cell c : row) {
+                    if (c == null || c.getCellType() != CellType.FORMULA) continue;
+                    try {
+                        ev.evaluateFormulaCell(c); // 娉ㄦ剰锛歟valuate() 鏃犲壇浣滅敤锛屽繀椤荤敤 evaluateFormulaCell 鎵嶄細鎶婄粨鏋滃啓鍥炵紦瀛樺��
+                        ok++;
+                    } catch (Exception ex) {
+                        fail++;
+                        if (samples.size() < 10) {
+                            samples.add(sh.getSheetName() + "!" + c.getAddress() + " :: " + ex.getClass().getSimpleName());
+                        }
+                    }
+                }
+            }
+        }
+        if (!samples.isEmpty()) log.warn("姹囨�诲伐浣滅翱鍏紡閲嶇畻澶辫触鏍蜂緥锛歿}", samples);
+        return new int[]{ok, fail};
+    }
+
+    /**
+     * 娓呮帀銆岄潪 inlineStr 鍗存畫鐣� &lt;is&gt;銆嶇殑闈炴硶鍗曞厓鏍笺��
+     *
+     * 姣嶇増鑻ョ敱 openpyxl 鍐欏嚭锛屾枃鏈崟鍏冩牸鐢� &lt;is&gt;锛坕nlineStr锛夊瓨鍌紱POI 鐨� setCellValue 鍙敼鍐� t 涓� &lt;v&gt;锛�
+     * 涓嶄細娓呮帀鏃� &lt;is&gt;锛屼簬鏄骇鍑� &lt;c t="n"&gt;&lt;v&gt;67.0&lt;/v&gt;&lt;is&gt;&lt;t&gt;67.00&lt;/t&gt;&lt;/is&gt;&lt;/c&gt; 杩欑闈炴硶鏍硷紝
+     * Excel 鍒ゅ畾涓恒�屾棤娉曡鍙栫殑鍐呭銆嶈�岀洿鎺ユ嫆缁濇墦寮�锛圕OM 琛ㄧ幇涓恒�屼笉鑳藉彇寰楃被 Workbooks 鐨� Open 灞炴�с�嶏級銆�
+     * 2026-07 瀵煎嚭浠跺嵆鍥犳鎵撲笉寮�锛堛�婂叕浜ゃ��17 鏍� +銆婅建閬撱�佽疆娓°��2 鏍硷級銆傝惤鐩樺墠缁熶竴娓呯悊锛屽箓绛夈��
+     */
+    private int normalizeStaleInlineStrings(XSSFWorkbook wb) {
+        int fixed = 0;
+        for (int i = 0; i < wb.getNumberOfSheets(); i++) {
+            org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet ctw = wb.getSheetAt(i).getCTWorksheet();
+            if (ctw == null || ctw.getSheetData() == null) continue;
+            for (org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRow row : ctw.getSheetData().getRowArray()) {
+                for (org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell c : row.getCArray()) {
+                    if (!c.isSetIs()) continue;
+                    STCellType.Enum t = c.getT();
+                    if (t == null || !STCellType.INLINE_STR.equals(t)) {
+                        c.unsetIs();
+                        fixed++;
+                    }
+                }
+            }
+        }
+        return fixed;
     }
 
     /**
@@ -4454,6 +4524,9 @@
             if (bs == null) continue;
             // 涓彛寰勬帓鍚嶉〉 A..H 闄堟棫宸﹀潡宸蹭簬 2026-09-09 鎷嶆澘鏁村潡鍒犻櫎锛氳鍖哄煙姘镐笉浠庡浠芥瘝鐗堝洖濉紝閬垮厤鈥滅敓鎴愬張澶嶆椿鈥�
             boolean skipMidRankLeftBlock = "涓彛寰勬帓鍚�".equals(ds.getSheetName());
+            // 銆� 璐ц繍銆嬮〉 2025..2021 骞村害鍧楋紙T 鍒楄捣锛屽惈鍚勫勾绱/绱鍚屾瘮鍒楋級鍦ㄦ瘝鐗堥噷鏄�屽競宸炴淳鐢熷叕寮忋�嶏紝
+            // 澶囦唤姣嶇増鍚屽尯浠嶆槸鏃х殑鍐欐甯搁噺锛堝叏鐪佽涓嬬瓑锛夛紝鍥炲~浼氳 2021/2022/2023 绱鍙堝涓嶄笂锛堚�滅敓鎴愬張澶嶆椿鈥濓級锛屾晠璇ュ尯涓嶅洖濉��
+            boolean skipFreightHistoryBlocks = " 璐ц繍".equals(ds.getSheetName());
             for (int r = ds.getFirstRowNum(); r <= ds.getLastRowNum(); r++) {
                 Row dr = ds.getRow(r);
                 if (dr == null) continue;
@@ -4461,6 +4534,7 @@
                 for (Cell dc : dr) {
                     if (dc == null) continue;
                     if (skipMidRankLeftBlock && dc.getColumnIndex() < 8) continue;
+                    if (skipFreightHistoryBlocks && dc.getColumnIndex() >= 19) continue; // T 鍒楀強浠ュ悗 = 2025..2021 骞村害鍧�
                     CellType t = dc.getCellType();
                     if (t == CellType.BLANK) continue;
                     String dtx = summaryCellText(dc);

--
Gitblit v1.9.1