From fc00eb79fce982425f9a83d63894a51549ed758a Mon Sep 17 00:00:00 2001
From: zhizhijie <zhizhijie@users.noreply.gitee.com>
Date: 星期一, 12 十月 2026 17:11:58 +0800
Subject: [PATCH] fix(汇总大表): 扩列表头行改按基准月份列判定并清理9月母版被写入日期的13格(待验收)

---
 traffic-audit-server/src/main/java/com/trafficaudit/dataimport/service/DataImportService.java |  209 ++++++++++++++++++++++++++++++---------------------
 1 files changed, 123 insertions(+), 86 deletions(-)

diff --git a/traffic-audit-server/src/main/java/com/trafficaudit/dataimport/service/DataImportService.java b/traffic-audit-server/src/main/java/com/trafficaudit/dataimport/service/DataImportService.java
index da66293..23d340e 100644
--- a/traffic-audit-server/src/main/java/com/trafficaudit/dataimport/service/DataImportService.java
+++ b/traffic-audit-server/src/main/java/com/trafficaudit/dataimport/service/DataImportService.java
@@ -1808,6 +1808,43 @@
         }
     }
 
+    /** 鍙牎楠屻�屽繀闇�鍒楁寜鍚嶅瓨鍦ㄣ�嶏紙涓嶆牎楠屽垪浣嶏級锛氱敤浜庡吋瀹瑰悓浜嬬増妯℃澘鐨勫垪浣嶅樊寮� */
+    private void requireHeaderColsByName(Sheet sheet, String typeLabel, String templateHint, String[] keywords) {
+        Row header = sheet == null ? null : sheet.getRow(0);
+        if (header == null) {
+            throw new RuntimeException("鎵�閫夋暟鎹被鍨嬨��" + typeLabel + "銆戞枃浠惰〃澶寸己澶憋紝璇蜂娇鐢ㄧ郴缁熸ā鏉裤��" + templateHint + "銆嬫暣鐞嗗悗鍐嶅鍏�");
+        }
+        List<String> missing = new ArrayList<>();
+        for (String keyword : keywords) {
+            if (findColByKeywords(header, keyword) < 0) missing.add(keyword);
+        }
+        if (!missing.isEmpty()) {
+            throw new RuntimeException("鎵�閫夋暟鎹被鍨嬨��" + typeLabel + "銆戜笌鏂囦欢鍐呭涓嶇锛氳〃澶寸己灏戝繀闇�鍒椼��"
+                + String.join("銆戙��", missing) + "銆戯紝璇风‘璁ゆ槸鍚﹂�夐敊浜嗘暟鎹被鍨嬶紙妯℃澘锛�" + templateHint + "锛�");
+        }
+    }
+
+    /** 琛ㄥご鍚� 鈫� 鍒楀彿锛堥娆″嚭鐜帮級锛涙湭鍛戒腑鏃跺洖閫� fallback锛屼繚鎸佸鏃фā鏉垮吋瀹� */
+    private int colByName(Row header, int fallback, String name) {
+        return colByName(header, fallback, name, 1);
+    }
+
+    /** 琛ㄥご鍚� 鈫� 鍒楀彿锛堢 occurrence 娆″嚭鐜帮級锛涙湭鍛戒腑鏃跺洖閫� fallback */
+    private int colByName(Row header, int fallback, String name, int occurrence) {
+        if (header == null) return fallback;
+        int hit = 0;
+        for (int c = 0; c <= header.getLastCellNum(); c++) {
+            Cell cell = header.getCell(c);
+            if (cell == null) continue;
+            String v = FORMATTER.formatCellValue(cell).trim();
+            if (v.contains(name)) {
+                hit++;
+                if (hit == occurrence) return c;
+            }
+        }
+        return fallback;
+    }
+
     /** 鎸夎〃澶村叧閿瓧瀹氫綅鍒楀彿锛氫粠绗� 1 鍒楀悜鍙虫壂锛屽懡涓换涓�鍏抽敭瀛楀嵆杩斿洖璇ュ垪锛涙湭鍛戒腑杩斿洖 -1 */
     private int findColByKeywords(Row header, String... keywords) {
         if (header == null) return -1;
@@ -3071,59 +3108,59 @@
         List<CityBusRow> rows = new ArrayList<>();
         try (Workbook wb = WorkbookFactory.create(file.getInputStream())) {
             Sheet sheet = wb.getSheetAt(0);
-            requireHeaderLayout(sheet, "鍩庡競鍏氦", "妯℃澘_浜や紒缁烾203琛╛鍩庡競鍏叡浜ら�氭湀搴﹁繍钀ユ儏鍐碉紙2026骞�7鏈堬級.xls",
-                CITY_BUS_HEADER_COLS, CITY_BUS_HEADER_KEYWORDS);
+            Row hdr = sheet.getRow(0);
+            requireHeaderColsByName(sheet, "鍩庡競鍏氦", "妯℃澘_浜や紒缁烾203琛╛鍩庡競鍏叡浜ら�氭湀搴﹁繍钀ユ儏鍐碉紙2026骞�7鏈堬級.xls", CITY_BUS_HEADER_KEYWORDS);
             for (int r = 1; r <= sheet.getLastRowNum(); r++) {
                 Row row = sheet.getRow(r);
                 if (row == null) continue;
-                String name = getString(row, 2);
+                String name = getString(row, colByName(hdr, 2, "浼佷笟鍚嶇О"));
                 if (name == null || name.trim().isEmpty()) continue;
                 CityBusMonthly item = new CityBusMonthly();
                 item.setReportPeriod(period);
-                item.setRegionCode(getString(row, 0));
-                item.setCity(RegionUtil.cityByCode(getString(row, 0)));
-                item.setEnterpriseCode(getString(row, 1));
+                item.setRegionCode(getString(row, colByName(hdr, 0, "鎵�灞炲湴鍖�")));
+                item.setCity(RegionUtil.cityByCode(getString(row, colByName(hdr, 0, "鎵�灞炲湴鍖�"))));
+                item.setEnterpriseCode(getString(row, colByName(hdr, 1, "浼佷笟浠g爜")));
                 item.setEnterpriseName(name.trim());
-                item.setOpVehicles(getDecimal(row, 5));
-                item.setStopTotal(getDecimal(row, 6));
-                item.setStopCity(getDecimal(row, 7));
-                item.setPassengerVolume(getDecimal(row, 8));
-                item.setPassengerCity(getDecimal(row, 9));
-                item.setTurnover(getDecimal(row, 10));
-                item.setTurnoverCity(getDecimal(row, 11));
-                item.setRailPassengerVolume(getDecimal(row, 13));
-                item.setRailTurnover(getDecimal(row, 14));
-                item.setFerryPassengerVolume(getDecimal(row, 17));
-                item.setFerryTurnover(getDecimal(row, 18));
-                item.setAvgDistance(getDecimal(row, 19));
-                item.setAvgDistanceCity(getDecimal(row, 20));
-                item.setContactPerson(getString(row, 24));
-                item.setContactPhone(getString(row, 25));
-                item.setReportDate(getDateString(row, 26));
-                item.setRateOpVehiclesMom(getDecimal(row, 29));
-                item.setRatePassengerMom(getDecimal(row, 30));
-                item.setRatePassengerCityMom(getDecimal(row, 31));
-                item.setRateChengxiangMom(getDecimal(row, 32));
-                item.setRateChengxiangTurnoverMom(getDecimal(row, 33));
-                item.setAvgDistanceMomChange(getDecimal(row, 34));
-                item.setAvgDistanceCityMomChange(getDecimal(row, 35));
-                item.setDailyPassengerPerVehicle(getDecimal(row, 36));
-                item.setRateOpVehiclesYoy(getDecimal(row, 39));
-                item.setRatePassengerYoy(getDecimal(row, 40));
-                item.setRatePassengerCityYoy(getDecimal(row, 41));
-                item.setRateChengxiangYoy(getDecimal(row, 42));
-                item.setRateChengxiangTurnoverYoy(getDecimal(row, 43));
-                item.setStopCityRatio(getDecimal(row, 44));
-                item.setPassengerCityRatio(getDecimal(row, 45));
-                item.setChengxiangRatio(getDecimal(row, 46));
-                item.setRateTurnoverYoy(getDecimal(row, 47));
-                item.setRateTurnoverMom(getDecimal(row, 48));
-                item.setPassengerChengxiang(getDecimal(row, 49));
-                item.setTurnoverChengxiang(getDecimal(row, 50));
-                item.setAvgDistanceChengxiang(getDecimal(row, 51));
-                item.setVerifyExplanation(getString(row, 65));
-                item.setReportNote(getString(row, 66));
-                item.setModifyRecord(getString(row, 67));
+                item.setOpVehicles(getDecimal(row, colByName(hdr, 5, "鍏叡姹界數杞杩愯惀杞︽暟")));
+                item.setStopTotal(getDecimal(row, colByName(hdr, 6, "杩愯惀绔欑偣鎬讳釜鏁�")));
+                item.setStopCity(getDecimal(row, colByName(hdr, 7, "鍏朵腑锛氬煄甯傚唴")));
+                item.setPassengerVolume(getDecimal(row, colByName(hdr, 8, "鍏叡姹界數杞瀹㈣繍閲�")));
+                item.setPassengerCity(getDecimal(row, colByName(hdr, 9, "鍏朵腑锛氬煄甯傚唴", 2)));
+                item.setTurnover(getDecimal(row, colByName(hdr, 10, "鏂板鍏叡姹界數杞︽梾瀹㈠懆杞噺")));
+                item.setTurnoverCity(getDecimal(row, colByName(hdr, 11, "鏂板鍏叡姹界數杞︽梾瀹㈠懆杞噺_鍏朵腑鍩庡競鍐�")));
+                item.setRailPassengerVolume(getDecimal(row, colByName(hdr, 13, "杞ㄩ亾浜ら�歘瀹㈣繍閲�")));
+                item.setRailTurnover(getDecimal(row, colByName(hdr, 14, "杞ㄩ亾浜ら�歘鏃呭鍛ㄨ浆閲�")));
+                item.setFerryPassengerVolume(getDecimal(row, colByName(hdr, 17, "鍩庡競瀹㈣繍杞浮_瀹㈣繍閲�")));
+                item.setFerryTurnover(getDecimal(row, colByName(hdr, 18, "鍩庡競瀹㈣繍杞浮鏃呭鍛ㄨ浆閲�")));
+                item.setAvgDistance(getDecimal(row, colByName(hdr, 19, "鍏叡姹界數杞﹀钩鍧囪繍璺�")));
+                item.setAvgDistanceCity(getDecimal(row, colByName(hdr, 20, "鍏叡姹界數杞﹀煄甯傚唴骞冲潎杩愯窛")));
+                item.setContactPerson(getString(row, colByName(hdr, 24, "濉〃浜�")));
+                item.setContactPhone(getString(row, colByName(hdr, 25, "鑱旂郴鐢佃瘽")));
+                item.setReportDate(getDateString(row, colByName(hdr, 26, "鎶ュ嚭鏃ユ湡")));
+                item.setRateOpVehiclesMom(getDecimal(row, colByName(hdr, 29, "鍏叡姹界數杞杩愯惀杞︽暟鐜瘮澧為��")));
+                item.setRatePassengerMom(getDecimal(row, colByName(hdr, 30, "鍏叡姹界數杞瀹㈣繍閲忕幆姣斿閫�")));
+                item.setRatePassengerCityMom(getDecimal(row, colByName(hdr, 31, "鍩庡競鍐呭杩愰噺鐜瘮")));
+                item.setRateChengxiangMom(getDecimal(row, colByName(hdr, 32, "鍩庨檯鍩庝埂瀹㈣繍閲忕幆姣斿閫�")));
+                item.setRateChengxiangTurnoverMom(getDecimal(row, colByName(hdr, 33, "鍩庨檯鍩庝埂鏃呭鍛ㄨ浆閲忕幆姣斿閫�")));
+                item.setAvgDistanceMomChange(getDecimal(row, colByName(hdr, 34, "骞冲潎杩愯窛鐜瘮澧炲噺锛堝叕閲岋級")));
+                item.setAvgDistanceCityMomChange(getDecimal(row, colByName(hdr, 35, "骞冲潎杩愯窛_鍩庡競鍐呯幆姣斿鍑忥紙鍏噷锛�")));
+                item.setDailyPassengerPerVehicle(getDecimal(row, colByName(hdr, 36, "鍏叡姹界數杞鍗曡溅鏃ュ潎瀹㈣繍閲�")));
+                item.setRateOpVehiclesYoy(getDecimal(row, colByName(hdr, 39, "鍏叡姹界數杞杩愯惀杞︽暟鍚屾瘮澧為��")));
+                item.setRatePassengerYoy(getDecimal(row, colByName(hdr, 40, "鍏叡姹界數杞瀹㈣繍閲忓悓姣斿閫�")));
+                item.setRatePassengerCityYoy(getDecimal(row, colByName(hdr, 41, "瀹㈣繍閲廮鍩庡競鍐呭悓姣斿閫�")));
+                item.setRateChengxiangYoy(getDecimal(row, colByName(hdr, 42, "鍩庨檯鍩庝埂瀹㈣繍閲忓悓姣斿閫�")));
+                item.setRateChengxiangTurnoverYoy(getDecimal(row, colByName(hdr, 43, "鍩庨檯鍩庝埂鏃呭鍛ㄨ浆閲忓悓姣斿閫�")));
+                item.setStopCityRatio(getDecimal(row, colByName(hdr, 44, "鍩庡競鍐呰繍钀ョ珯鐐瑰崰姣�")));
+                item.setPassengerCityRatio(getDecimal(row, colByName(hdr, 45, "鍩庡競鍐呭杩愰噺鍗犳瘮")));
+                item.setChengxiangRatio(getDecimal(row, colByName(hdr, 46, "鍩庨檯鍩庝埂瀹㈣繍閲忓崰姣�")));
+                item.setRateTurnoverYoy(getDecimal(row, colByName(hdr, 47, "鏃呭鍛ㄨ浆閲忓悓姣斿閫�")));
+                item.setRateTurnoverMom(getDecimal(row, colByName(hdr, 48, "鏃呭鍛ㄨ浆閲忕幆姣斿閫�")));
+                item.setPassengerChengxiang(getDecimal(row, colByName(hdr, 49, "鍩庨檯鍩庝埂瀹㈣繍閲�")));
+                item.setTurnoverChengxiang(getDecimal(row, colByName(hdr, 50, "鍩庨檯鍩庝埂鏃呭鍛ㄨ浆閲�")));
+                item.setAvgDistanceChengxiang(getDecimal(row, colByName(hdr, 51, "鍩庨檯鍩庝埂骞冲潎杩愯窛")));
+                item.setVerifyExplanation(getString(row, colByName(hdr, 65, "鏍稿疄鎬у師鍥犺В閲�")));
+                item.setReportNote(getString(row, colByName(hdr, 66, "涓婃姤璇存槑")));
+                item.setModifyRecord(getString(row, colByName(hdr, 67, "淇敼璁板綍")));
                 rows.add(new CityBusRow(r + 1, item));
             }
         } catch (Exception e) {
@@ -3186,52 +3223,52 @@
         List<TaxiRow> rows = new ArrayList<>();
         try (Workbook wb = WorkbookFactory.create(file.getInputStream())) {
             Sheet sheet = wb.getSheetAt(0);
-            requireHeaderLayout(sheet, "宸℃父鍑虹", "妯℃澘_浜よ缁烾402琛�-宸℃父鍑虹姹借溅杩愯惀鏈嶅姟鎯呭喌鏈堟姤(2026).xls",
-                CITY_TAXI_HEADER_COLS, CITY_TAXI_HEADER_KEYWORDS);
+            Row hdr = sheet.getRow(0);
+            requireHeaderColsByName(sheet, "宸℃父鍑虹", "妯℃澘_浜よ缁烾402琛�-宸℃父鍑虹姹借溅杩愯惀鏈嶅姟鎯呭喌鏈堟姤(2026).xls", CITY_TAXI_HEADER_KEYWORDS);
             for (int r = 1; r <= sheet.getLastRowNum(); r++) {
                 Row row = sheet.getRow(r);
                 if (row == null) continue;
-                String name = getString(row, 2);
+                String name = getString(row, colByName(hdr, 2, "浼佷笟鍚嶇О"));
                 if (name == null || name.trim().isEmpty()) continue;
                 CityTaxiMonthly item = new CityTaxiMonthly();
                 item.setReportPeriod(period);
-                item.setRegionCode(getString(row, 0));
-                item.setCity(cityOf(getString(row, 0), name));
-                item.setTripTotal(getDecimal(row, 4));
-                item.setTripCity(getDecimal(row, 5));
-                item.setPassengerVolume(getDecimal(row, 6));
-                item.setPassengerCity(getDecimal(row, 7));
-                item.setTurnover(getDecimal(row, 8));
-                item.setTurnoverCity(getDecimal(row, 9));
-                item.setOpVehicles(getDecimal(row, 10));
-                item.setAvgDistance(getDecimal(row, 11));
-                item.setAvgDistanceCity(getDecimal(row, 12));
-                item.setContactPerson(getString(row, 15));
-                item.setContactPhone(getString(row, 16));
-                item.setReportDate(getDateString(row, 17));
-                item.setDailyTripsPerVehicle(getDecimal(row, 18));
-                item.setDailyPassengerPerVehicle(getDecimal(row, 19));
-                item.setPassengersPerTrip(getDecimal(row, 20));
-                item.setRateOpVehiclesMom(getDecimal(row, 21));
-                item.setRateOpVehiclesYoy(getDecimal(row, 22));
-                item.setRateTripMom(getDecimal(row, 23));
-                item.setRateTripYoy(getDecimal(row, 24));
-                item.setRatePassengerMom(getDecimal(row, 25));
-                item.setRatePassengerYoy(getDecimal(row, 26));
-                item.setAvgDistanceMomChange(getDecimal(row, 27));
-                item.setPassengersPerTripCity(getDecimal(row, 28));
-                item.setRateTripCityMom(getDecimal(row, 29));
-                item.setRatePassengerCityMom(getDecimal(row, 30));
-                item.setAvgDistanceCityMomChange(getDecimal(row, 31));
-                item.setTripCityRatio(getDecimal(row, 32));
-                item.setPassengerCityRatio(getDecimal(row, 33));
-                item.setPassengersPerTripChengxiang(getDecimal(row, 34));
-                item.setRateTripChengxiangMom(getDecimal(row, 35));
-                item.setRatePassengerChengxiangMom(getDecimal(row, 36));
-                item.setAvgDistanceChengxiang(getDecimal(row, 37));
-                item.setVerifyExplanation(getString(row, 38));
-                item.setReportNote(getString(row, 39));
-                item.setModifyRecord(getString(row, 40));
+                item.setRegionCode(getString(row, colByName(hdr, 0, "鎵�灞炲湴鍖�")));
+                item.setCity(cityOf(getString(row, colByName(hdr, 0, "鎵�灞炲湴鍖�")), name));
+                item.setTripTotal(getDecimal(row, colByName(hdr, 4, "杞藉杞︽鎬绘暟")));
+                item.setTripCity(getDecimal(row, colByName(hdr, 5, "杞藉杞︽鎬绘暟_鍩庡競鍐�")));
+                item.setPassengerVolume(getDecimal(row, colByName(hdr, 6, "瀹㈣繍閲�")));
+                item.setPassengerCity(getDecimal(row, colByName(hdr, 7, "瀹㈣繍閲廮鍏朵腑鍩庡競鍐�")));
+                item.setTurnover(getDecimal(row, colByName(hdr, 8, "鏃呭鍛ㄨ浆閲�")));
+                item.setTurnoverCity(getDecimal(row, colByName(hdr, 9, "鏃呭鍛ㄨ浆閲廮鍩庡競鍐�")));
+                item.setOpVehicles(getDecimal(row, colByName(hdr, 10, "杩愯惀杞﹁締鏁�")));
+                item.setAvgDistance(getDecimal(row, colByName(hdr, 11, "宸℃父鍑虹姹借溅骞冲潎杩愯窛")));
+                item.setAvgDistanceCity(getDecimal(row, colByName(hdr, 12, "鍩庡競鍐呭钩鍧囪繍璺�")));
+                item.setContactPerson(getString(row, colByName(hdr, 15, "濉〃浜�")));
+                item.setContactPhone(getString(row, colByName(hdr, 16, "鑱旂郴鐢佃瘽")));
+                item.setReportDate(getDateString(row, colByName(hdr, 17, "鎶ュ嚭鏃ユ湡")));
+                item.setDailyTripsPerVehicle(getDecimal(row, colByName(hdr, 18, "鍗曡溅鏃ュ潎杞藉杞︽")));
+                item.setDailyPassengerPerVehicle(getDecimal(row, colByName(hdr, 19, "鍗曡溅鏃ュ潎瀹㈣繍閲�")));
+                item.setPassengersPerTrip(getDecimal(row, colByName(hdr, 20, "鍗曡溅娆¤浇瀹汉鏁�")));
+                item.setRateOpVehiclesMom(getDecimal(row, colByName(hdr, 21, "杩愯惀杞︽暟鐜瘮澧為��")));
+                item.setRateOpVehiclesYoy(getDecimal(row, colByName(hdr, 22, "杩愯惀杞︽暟鍚屾瘮澧為��")));
+                item.setRateTripMom(getDecimal(row, colByName(hdr, 23, "杞藉杞︽鎬绘暟鐜瘮澧為��")));
+                item.setRateTripYoy(getDecimal(row, colByName(hdr, 24, "杞藉杞︽鍚屾瘮澧為��")));
+                item.setRatePassengerMom(getDecimal(row, colByName(hdr, 25, "瀹㈣繍閲忕幆姣斿閫�")));
+                item.setRatePassengerYoy(getDecimal(row, colByName(hdr, 26, "瀹㈣繍閲忓悓姣斿閫�")));
+                item.setAvgDistanceMomChange(getDecimal(row, colByName(hdr, 27, "骞冲潎杩愯窛鐜瘮澧炲噺")));
+                item.setPassengersPerTripCity(getDecimal(row, colByName(hdr, 28, "鍗曡溅娆¤浇瀹汉鏁癬鍩庡競鍐�")));
+                item.setRateTripCityMom(getDecimal(row, colByName(hdr, 29, "杞藉杞︽鎬绘暟鐜瘮澧為�焈鍩庡競鍐�")));
+                item.setRatePassengerCityMom(getDecimal(row, colByName(hdr, 30, "瀹㈣繍閲忕幆姣斿閫焈鍩庡競鍐�")));
+                item.setAvgDistanceCityMomChange(getDecimal(row, colByName(hdr, 31, "骞冲潎杩愯窛_鍩庡競鍐呯幆姣斿鍑�")));
+                item.setTripCityRatio(getDecimal(row, colByName(hdr, 32, "杞藉杞︽鎬绘暟_鍩庡競鍐呭崰姣�")));
+                item.setPassengerCityRatio(getDecimal(row, colByName(hdr, 33, "瀹㈣繍閲廮鍩庡競鍐呭崰姣�")));
+                item.setPassengersPerTripChengxiang(getDecimal(row, colByName(hdr, 34, "鍗曡溅娆¤浇瀹汉鏁癬鍩庨檯鍩庝埂")));
+                item.setRateTripChengxiangMom(getDecimal(row, colByName(hdr, 35, "杞藉杞︽鎬绘暟_鍩庨檯鍩庝埂鐜瘮澧為��")));
+                item.setRatePassengerChengxiangMom(getDecimal(row, colByName(hdr, 36, "瀹㈣繍閲廮鍩庨檯鍩庝埂鐜瘮澧為��")));
+                item.setAvgDistanceChengxiang(getDecimal(row, colByName(hdr, 37, "骞冲潎杩愯窛_鍩庨檯鍩庝埂")));
+                item.setVerifyExplanation(getString(row, colByName(hdr, 38, "鏍稿疄鎬у師鍥犺В閲�")));
+                item.setReportNote(getString(row, colByName(hdr, 39, "涓婃姤璇存槑")));
+                item.setModifyRecord(getString(row, colByName(hdr, 40, "淇敼璁板綍")));
                 rows.add(new TaxiRow(r + 1, item));
             }
         } catch (Exception e) {

--
Gitblit v1.9.1