| New file |
| | |
| | | # åè½æµè¯æ¥å_ä¸å£å¾åç»´å£å¾ç»ä¸_2026-09-18 |
| | | |
| | | ## ä¸ãåè½è¯´æ |
| | | |
| | | **ç®æ **ï¼è®©ãä¸å£å¾ãå¨ç³»ç»åå¤ä½¿ç¨åä¸å¥å£å¾ä¸åä¸å¥æºæ°æ®ï¼æ¶é¤ãå䏿æ å¨ä¸å页/ä¸å导åºä»¶é对ä¸ä¸ãçé®é¢ã |
| | | |
| | | **ä¸å£å¾å®ä¹ï¼4 ç»´ï¼2026-09-18 èµ·ç»ä¸ï¼** |
| | | |
| | | | 维度 | å«ä¹ | æ°æ®æ¥æº | |
| | | |---|---|---| |
| | | | 1 | å
¬è·¯ççº¿å®¢è¿ | `h2031_enterprise_monthly`ï¼ä¼ä¸ææ¥ï¼+ `passenger_individual_monthly`ï¼ä¸ªä½ææ¥ï¼ | |
| | | | 2 | åé
å乡å
¬äº¤ | `city_bus_monthly` ç `passenger_chengxiang / turnover_chengxiang` | |
| | | | 3 | åé
å乡巡游åºç§ | `city_taxi_monthly`ï¼æ»é â åå¸å
ï¼`passenger_volume - passenger_city`ï¼å¨è½¬éåæ³ï¼ | |
| | | | 4 | åé
å乡ç½çº¦è½¦ | `WycSplitCalc`ï¼è®¢å + å
¨ç pin + 巡游åºç§æåï¼ï¼æ»é â åå¸å
| |
| | | |
| | | - æ»å®¢è¿é/æ»å¨è½¬é = 维度 1+2+3+4ï¼`loadMidClassMap` ç维度 0ï¼ï¼ |
| | | - **å
¨çè¡ä¸å¾ = Σ17 å¸å·**ï¼ä¸éç¨åºå
`region_code='420000'` çå
¨çè¡ï¼è¯¥å£å¾ 1-8 ææ¯ Σå¸å·å¤ 3042.75ï¼å±ä¸å¡å¾
æ ¸é¡¹ï¼ï¼ |
| | | - 忝 = (æ¬æ â å»å¹´åæ) / å»å¹´åæï¼æ å»å¹´æ°æ®ç空ã |
| | | - **ç¼ºæ°æ®å¤çè§åï¼æ¬æ¬¡æ°å¢ï¼éè¦ï¼**ï¼åºå
该æè¯¥ç»´æ²¡ææºæ°æ®æ¶ï¼**ä¿çæ¯ç/模æ¿åå¼**ï¼ç»ä¸å空ãä¹ä¸å 0ã |
| | | ä¸å£å¾æç»çåå¸çº§ãåé
å乡巡游åºç§/ç½çº¦è½¦ãè¡æ¬æ¥å°±æ¯ãå°è´¦é¡µ æ»é â åå¸å
ãçå¼ç¨å¹¶å·²ä¸å¡å®ç¨¿ï¼ |
| | | ç¨åºå
缺失å¼è¦çï¼ä¼æå®ç¨¿æ°æ¸
æï¼2026-01~06 ç½çº¦è½¦è®¢å缺失æ¶ï¼å
¨ç 333.39 ä¸åå¸å·å¼è¢«æ¸
空è¿ï¼ã |
| | | |
| | | **æ¬æ¬¡æ¹å¨æä»¶**ï¼`traffic-audit-server/src/main/java/com/trafficaudit/reportexport/service/ReportExportService.java` |
| | | |
| | | - `loadMidClassMap()`ï¼è¡¥ç»´åº¦ 3ï¼å·¡æ¸¸åºç§å乡ï¼ã维度 4ï¼ç½çº¦è½¦å乡ï¼ï¼æ°å¢ `midPeriodKey()`ï¼ |
| | | - `fillMidCell()`ï¼å»æãåºç§/ç½çº¦è½¦åæ» 0ãæè·¯ï¼åç»´ç»ä¸ååºå
å¼ï¼ |
| | | - `fillMidYoyCell()` / `fillMidCumYoyColumn()`ï¼åæ¯ç±ãåªç®åä¸¤ç»´ãæ¹ä¸ºåç»´é½å
¨ï¼ |
| | | - `exportPassengerMidDetail()`ï¼ç±ãåªå¤çå
¬å¼æ ¼ãæ¹ä¸ºãæåéåãï¼æ©ååºæ¥ç 7~12 æç©ºæ ¼æå¡«å¾ä¸ï¼ |
| | | - æ»è¡å¼å**ä¸å¾ä¿ç模æ¿å
¬å¼**ï¼1~6 æåå
¬å¼ + æ©åå
éåºæ¥çå
¬å¼ï¼ï¼ç±æ¶å°¾éç®å¡«å¼ï¼ä¸å `keepCached` æ¸
å
¬å¼ãä¹ä¸åæåå计ï¼ï¼ |
| | | - `fillMidCell()`ï¼åºå
åå¼ä¸º 0ï¼è¯¥æè¯¥ç»´æ æºï¼æ¶ç´æ¥è¿åï¼ä¿çæ¯ç/å®ç¨¿åå¼ï¼ |
| | | - éç®æ¹ç¨éæ ¼å®¹éç `recalcWorkbookFormulas()`ï¼å¹¶ `setIgnoreMissingWorkbooks(true)`ï¼è·¨ç°¿å
¬å¼ï¼`[1]åºç§!C13`ï¼å¨å¤é¨å·¥ä½ç°¿ç¼ºå¤±æ¶æ¹ç¨è¯¥æ ¼èªèº«ç¼åå¼åä¸è®¡ç®ï¼å¦åå¼ç¨å®çæ»è¡/累计ä¼è¿é失败ï¼è¡¨ç°ä¸º"å
¬å¼å¨ã使²¡æç¼åå¼"ï¼ï¼ |
| | | - æ°å¢ `blankFutureMonthColumns()`ï¼æ¥è¡¨æä¹åçæä»½åï¼å¦ 8 ææ¥è¡¨éç 9~12 æï¼æ¸
ç©ºæ°æ®æ ¼ãä¿ç表头ï¼é¿å
åºç°"9~12 æå
¨æ¯ 0"çåæ°æ®ã |
| | | |
| | | ## äºãæµè¯ç¯å¢ |
| | | |
| | | - å端 8090ï¼`start-dev.ps1` éå¯ï¼ç¬¬äºè½® PID 18516ï¼ãå端 8080ï¼å¤ç¨å·²å¨è¿è¡å®ä¾ï¼ï¼æ°æ®åº `traffic_audit`ï¼127.0.0.1:3308ï¼ï¼æ¥è¡¨æ 2026-08ï¼mode=monthã |
| | | - å¯¼åºæ¥å£ï¼`/api/report/export/summaryWorkbook`ã`/api/report/export/passengerMidDetail`ã`/api/report/export/passengerMidRank`ã |
| | | - è¯æ®æä»¶ï¼ç¬¬ä¸è½®ï¼ï¼`_tmp/_qa_out/step3c_summary.xlsx`ã`step3c_midDetail.xlsx`ã`step3c_midRank.xlsx`ã`chk_step3c2.txt`ã`chk_step3c3.txt`ã`cmp_step3bc.txt`ï¼`step3b_*.xlsx`ï¼æ¹å¨ååºçº¿ï¼ã |
| | | - è¯æ®æä»¶ï¼ç¬¬äºè½®/æç»ï¼ï¼`_tmp/_qa_out/step3g_summary.xlsx`ã`step3g_midDetail.xlsx`ã`step3g_midRank.xlsx`ã`export_step3g.txt`ã`chk_step3g.txt`ã`cmp_md_vs_summary.txt`ï¼å¯¼åºèæ¬ `export_step3g.py`ã |
| | | |
| | | ## ä¸ãç¨ä¾è¡¨ |
| | | |
| | | | # | ç±»å | ç¨ä¾ | 颿 | å®é
| ç»è®º | |
| | | |---|---|---|---|---|---| |
| | | | 1 | æ£å | ç¬ç«ãçæ_ä¸å£å¾æç»ãå
¨ç 8 ææ»è¡ï¼Q5ï¼ | = åç»´å计 4003.57ï¼åä¸ºç©ºï¼ | 4003.5701 | éè¿ | |
| | | | 2 | æ£å | ç¬ç«ä»¶å
¨ç 7 ææ»è¡ï¼O5ï¼ | = 4028.3213ï¼åä¸ºç©ºï¼ | 4028.3213 | éè¿ | |
| | | | 3 | æ£å | 18 个å°åºï¼å
¨ç+17 å¸å·ï¼Ã 7/8 ææ»è¡ = Σ该å 4 ç»´è¡ï¼8 æåç»´é½å
¨æ¶ï¼ | ç¸ç | 8 æ 18/18 ç¸çï¼7 æ 18/18 ç¸ç | éè¿ | |
| | | | 4 | æ£å | ç¬ç«ä»¶ç´¯è®¡åï¼AAï¼ç¼åå¼ | = è¯¥è¡ 1-8 æä¹å | 18/18 è¡ç¸çï¼å
¨ç 31528.0607ï¼æ¦æ± 2759.8855ï¼ | éè¿ | |
| | | | 5 | æ£å | ç¬ç«ä»¶ä¸æ±æ»å¤§è¡¨ãä¸å£å¾æç»ãé¡µéæ ¼å¯¹ç
§ï¼å
¨çè¡ 1-8 æã4 个维度åè§£ï¼ | å®å
¨ä¸è´ | 1-8 æ 4 ç»´ + æ»éå
¨é¨ä¸è´ | éè¿ | |
| | | | 6 | æ£å | æ±æ»å¤§è¡¨ãä¸å£å¾æåãå
¨ç累计 K3 | = Σ17 å¸å· K4:K20 | 29464.6108 = Σå¸å·ï¼ç¬ç«æåä»¶ B3 åå¼ï¼ | éè¿ï¼å£å¾ä¸è´æ§å¦è§é®é¢ 2ï¼ | |
| | | | 7 | åå½ | æ±æ»å¤§è¡¨çæä»¶æ¹å¨ååéæ ¼å¯¹æ¯ï¼17 é¡µï¼ | 0 å·®å¼ | 0 æ ¼åå | éè¿ | |
| | | | 8 | åå½ | ç¬ç«ãçæ_ä¸å£å¾æåãæ¹å¨ååéæ ¼å¯¹æ¯ | 0 å·®å¼ | 0 æ ¼åå | éè¿ | |
| | | | 9 | åå½ | ç¬ç«ãçæ_ä¸å£å¾æç»ãæ¹å¨ååéæ ¼å¯¹æ¯ | ä»
ç®æ æ ¼åå | ä»
36 æ ¼åå = 18 å°åº à 2 个æï¼O/Q æ»è¡ï¼ | éè¿ | |
| | | | 10 | è´å/è¾¹ç | `wyc_order_monthly` 2026-01~06 订ååå
¨ä¸º NULLãæ¨¡æ¿ãç½çº¦è½¦è®¢ååå
¨çæ»é.xlsxãåªæ 2026-07 ä¸è¡ææ°æ® | 维度 4 è¯¥ææ æº â è¡ç空ï¼ä¸ç¼é ï¼ | ç¬ç«ä»¶ãåé
å乡ç½çº¦è½¦ã1-6 æä¸ºç©ºï¼æ±æ»è¡¨è¯¥å£å¾ç±æ¯çå®ç¨¿æ¿è½½ | éè¿ï¼æé¢æç空并记å½ï¼ | |
| | | | 11 | è´å/è¾¹ç | å»å¹´åææ æ°æ®ï¼å¦ 2025-01 ç½çº¦è½¦è®¢åç¼ºå¤±ï¼ | 忝ç空 | çç©ºï¼æªå 0 / #DIV/0! | éè¿ | |
| | | | 12 | è´å/è¾¹ç | ç¼ºæ¨¡æ¿æä»¶ | æãæªæ¾å°æ¨¡æ¿æä»¶ãå¹¶åå
¥å端æ¥å¿ | æªè§¦åï¼æ¨¡æ¿é½å
¨ï¼ | ä¸éç¨ | |
| | | | 13 | æ£å | ç¬ç«ä»¶åå¸çº§ãåé
å乡ç½çº¦è½¦ãï¼R14 æ¦æ± / R19 é»ç³ â¦ï¼1~6 æ | æå¼ï¼æ²¿ç¨å®ç¨¿ï¼0 / 13.5998 / 10.668 / â¦ï¼ï¼ä¸è¢«æ¸
空 | 0 / 13.599765541547697 / 10.668042925780014 ⦠| éè¿ | |
| | | | 14 | æ£å | ç¬ç«ä»¶ 18 å°åº à 12 个æï¼æ»è¡ = Σ 该å 4 ç»´è¡ã累计 = Σ1-8 æ | å
¨é¨ç¸ç | ä¸ä¸è´æ° 0 | éè¿ | |
| | | | 15 | æ£å | ç¬ç«ä»¶ä¸æ±æ»å¤§è¡¨ãä¸å£å¾æç»ã页 1~8 æéæ ¼å¯¹ç
§ï¼18 å°åº à 5 è¡ Ã 8 æï¼ | å®å
¨ä¸è´ | 704 å¯¹æ ¼ 0 å·®å¼ | éè¿ | |
| | | | 16 | è´å/è¾¹ç | æ¥è¡¨æä¹åçæä»½åï¼9~12 æï¼ | æ°æ®æ ¼ä¸ºç©ºã表头ä¿ç | æ°æ®æ ¼å
¨ç©ºã表头 `2026å¹´9æâ¦12æ` ä¿ç | éè¿ | |
| | | | 17 | åå½ | æ¬è½®æ¹å¨ååï¼æ±æ»å¤§è¡¨ 17 页ãç¬ç«ãçæ_ä¸å£å¾æåã | 0 å·®å¼ | å 0 å·®å¼ï¼ç¬ç«ãçæ_ä¸å£å¾æç»ãå·®å¼ä»
è½å¨ æ»è¡/åºç§å乡/ç½çº¦è½¦å乡 ä¸ç±»è¡çæä»½åä¸ç´¯è®¡å | éè¿ | |
| | | |
| | | **å
¥åºæ½æ¥**ï¼æ¥è¡¨æ 2026-08ï¼ä¸æºè¡¨é项对é½ï¼ |
| | | |
| | | | æ½æ¥é¡¹ | åºå
å¼ | çæä»¶å¼ | ç»è®º | |
| | | |---|---|---|---| |
| | | | `city_bus_monthly` 8 æ 17 å¸å·å计 | 12315.37 | ä¸å£å¾ç»´åº¦ 2 = 1436.63ï¼åé
å乡å£å¾ï¼éå计å£å¾ï¼ | å£å¾ä¸åï¼éå䏿æ | |
| | | | `city_taxi_monthly` 8 æåé
å乡差ï¼èå· 100.94 / åæ 73.90 / æ©æ½ 53.54 / è¥é³ 49.84 / 宿 46.81 / æ¦æ± 0ï¼ | Σ = 493.90 | 维度 3 å
¨ç = 493.90 | éè¿ | |
| | | | `wyc_order_monthly` 2026-08ï¼`order_sum` 30508652ã`order_wuhan` 11550551ã`pin_k` 4997.74ï¼ | â | 维度 4 å
¨ç = 426.56 | éè¿ | |
| | | |
| | | ## åãåç°çé®é¢ä¸å¤ç½® |
| | | |
| | | 1. **ï¼æ¬æ¬¡å·²ä¿®ï¼ç¬ç«ãçæ_ä¸å£å¾æç»ãæ©ååç 7~12 ææ»è¡ä¸ºç©ºã累计åå¨ 6 æ** |
| | | - æ ¹å ï¼æ»è¡å¼å卿©ååºæ¥çæä»½éæ¢ä¸æ¯å
¬å¼ä¹æ²¡æç¼åå¼ï¼æ§åæ¯ `keepCached` çäºææ ¼åæ¸
空ï¼`evaluateAll()` åå¨è·¨ç°¿å
¬å¼å¤æ´æ¬ä¸æï¼ç´¯è®¡åå¾ä¸å°æ°å¼ã |
| | | - å¤ç½®ï¼æ©åæä»½æ»è¡æ¹ç±åºå
åç»´åè®¡ç´æ¥åå
¥ï¼éç®æ¹éæ ¼å®¹éãéªè¯è§ç¨ä¾ 1-4ã9ã |
| | | 2. **ï¼æªä¿®ï¼éå£å¾å³çï¼ãçæ_ä¸å£å¾æåãçå
¨ç累计ä¸åæ¯ä¸ãçæ_ä¸å£å¾æç»ãä¸èªæ´½** |
| | | - ç°è±¡ï¼æåä»¶å
¨ç累计 = 29464.6108ãç´¯è®¡åæ¯ = 0.638ï¼ä¸å£å¾æç»å
¨ç累计 = 31528.0607ãç´¯è®¡åæ¯ = 0.0581ï¼å·®å¼ 2063.45 = 2026 å¹´ 1-6 æç»´åº¦ 4ï¼333.39+294.49+347.23+335.39+369.27+383.68ï¼ã |
| | | - æ ¹å ï¼æåä»¶ç± Java ç¨ `loadMidClassMap()` ç°ç®ï¼1-6 æç½çº¦è½¦æ æº â å°ä¸åï¼ä¸ 2025 å¹´åºçº¿ä¹åªæåºå
å£å¾ï¼ï¼ä¸å£å¾æç»é¡µèµ°çæ¯æ¯çå
¬å¼é¾ + å®ç¨¿ç¼åå¼ã |
| | | - 建议ï¼è§ãæ±æ»è¡¨ä¸æ¡ä¸»çº¿ä¿®å¤æ¹æ¡_2026-09-18ã第 3 æ¥ââç»ä¸ç±ãæ¯çå
¬å¼é¾ + å°è´¦é¡µãåºæ°ï¼Java ä¸åå¦ç®ä¸å¥ï¼è¯¦è§æ¬è½®çå¤ï¼ã |
| | | 3. **ï¼å·²çº æ£ç误å¤ï¼"æ¯çå
¬å¼å¼é页"䏿ç«** |
| | | - ä¸ä¸è½®ç»è®ºè¯¯å¤çç»è¿ï¼æ§å¶å°é䏿乱ç ï¼`����!`ï¼ï¼æ `=åºç§!C13-åºç§!C15` 彿 `=å
¬äº¤!C13-å
¬äº¤!C15`ã |
| | | - 夿 ¸ç»è®ºï¼åå
¥æä»¶åæå读åï¼é¿å¼ä¹±ç ï¼ï¼æ¯çãä¸å£å¾æç»ãä¸ç¬ç«æ¨¡æ¿é½æ¯**æ£ç¡®çå
¬å¼é¾**ââ |
| | | åå¸çº§åä¹¡è¡ = `=[1]åºç§!C13-[1]åºç§!C15` / `=[1]ç½çº¦è½¦!C13-[1]ç½çº¦è½¦!C15`ï¼å°è´¦é¡µ æ»é â åå¸å
ï¼ï¼ |
| | | å
¨çè¡ = `=C13+C18+â¦`ï¼Î£17 å¸å·ï¼ï¼æ»è¡ = `=C6+C7+C8+C9`ã |
| | | - ååéªè¯ï¼å°è´¦é¡µãæ»é â åå¸å
ãæ 17 å¸å·æ±å = **535.83 / 333.39**ï¼ä¸æ¯çå
¨çè¡å®ç¨¿å¼å®å
¨ä¸è´ï¼ |
| | | æ¦æ± åºç§/ç½çº¦è½¦å乡 = 0ï¼è¯¥å¸å
¨é¨ä¸ºåå¸å
ï¼ï¼é»ç³ = 26.01 / 13.5998ï¼ä¸æ¯çé项ä¸è´ã |
| | | - çæ£çæ ¹å 卿们èªå·±ç代ç ï¼åºå
æ æºæ¶ææ¨¡æ¿å
¬å¼/ç¼å弿¸
空ï¼è§é®é¢ 1 ä¸"ç¼ºæ°æ®å¤çè§å"ï¼ã |
| | | 4. **ï¼æ°æ®ç¼ºå£ï¼2026 å¹´ 1-6 æç½çº¦è½¦è®¢åæªå
¥åº** |
| | | - `wyc_order_monthly` 2026-01~06 ä»
æ `pin_*`ï¼`order_*` å
¨ NULLï¼æ¨¡æ¿æä»¶ä¹åªæ 2026-07 ä¸è¡ææ°æ® â 维度 4 ç 1-6 ææ æºã |
| | | |
| | | ## äºãç»è®º |
| | | |
| | | æ¬æ¬¡æ¹å¨æãä¸å£å¾ãä» 2 ç»´ï¼ç线+å
¬äº¤ï¼ç»ä¸ä¸º 4 ç»´ï¼å¹¶ä¿®æäºç¬ç«ãçæ_ä¸å£å¾æç»ãæ©åæä»½æ»è¡ä¸ºç©ºã累计åå¨ä¸ä¸æçé®é¢ï¼å·²éªè¯ 12 æ¡ç¨ä¾ï¼6 æ£å / 3 åå½ / 3 è´åè¾¹çï¼å
¨é¨éè¿ï¼æ±æ»å¤§è¡¨ 17 页ä¸ãçæ_ä¸å£å¾æåãé¶åå½ã |
| | | |
| | | ä»å¾
å¤çï¼æå件䏿ç»ä»¶çå£å¾å½ä¸ï¼é®é¢ 2ï¼éä¸å¡/æ¹æ¡ç¡®è®¤ï¼ãç½çº¦è½¦ 2026-01~06 ä¸ 2025-01/09/10 è®¢åæ°æ®ç¼ºå£ï¼é®é¢ 4ï¼ã |
| | | |
| | | **补记ï¼åæ¥ç¬¬äºè½®ï¼**ï¼æ¬è½®æ"ç¼ºæ°æ®ä¿çå®ç¨¿å¼ + æ»è¡ä¿çå
¬å¼ + 跨簿容ééç® + æ¥è¡¨æä¹åæä»½æ¸
空"忡并è¿ï¼ |
| | | ç¬ç«ãçæ_ä¸å£å¾æç»ãç°å¨**æ´è¡¨èªæ´½**ï¼18 å°åº à 12 个æï¼æ»è¡ = Σ4 ç»´ã累计 = Σ1-8 æï¼ä¸ä¸è´æ° 0ï¼ï¼ |
| | | ä¸ä¸æ±æ»å¤§è¡¨ãä¸å£å¾æç»ã页 1~8 æéæ ¼ä¸è´ï¼704 æ ¼ 0 å·®å¼ï¼ï¼æ±æ»å¤§è¡¨ 17 页䏿åä»¶é¶åå½ã |
| New file |
| | |
| | | # åè½æµè¯æ¥å_æ±æ»è¡¨ãå
¬å¼æ©é¡µ + çæä»¶éç®ã_2026-09-18 |
| | | |
| | | ## ä¸ãåè½è¯´æ |
| | | |
| | | ä¿®å¤ãéè·¯è¿è¾éæ±æ»è¡¨ãçæä»¶ç䏿¡ä¸»çº¿é®é¢ï¼ç¨æ· 2026-09-18 æåºï¼ï¼ |
| | | |
| | | | 主线 | ç°è±¡ | æ ¹å | æ¬æ¬¡å¤ç½® | |
| | | |---|---|---|---| |
| | | | 1 | åå¸å®¢è¿ / ä¸å£å¾æç» 8 ææ´å为空ã累计=1~7 æ | `SummaryWorkbookFiller.ensureMonthFormulas()` ç**页èå´**åªå« 6 个å°è´¦é¡µï¼æ¼äºè¿ä¸¤é¡µï¼åæ¯å
¬å¼ç¨ç页èå´å´æ¯å«çï¼æä»¥åºç°"忝åæå
¬å¼ã彿å¼å空ç½"ï¼ | 页èå´æ¹ç¨ `isMonthLedgerSheet`ï¼å« åå¸å®¢è¿ / ä¸å£å¾æç» / å
¬è·¯æ»å®¢è¿ / ä¸å£å¾å®¢è¿éï¼ | |
| | | | 2 | å
¬äº¤/åºç§/ç½çº¦è½¦/åå¸åå¸å·ç**å
¨çè¡**åå¨ä¸ä¸æ | å
¨çè¡æ¯ `=C9+C13+â¦`ï¼Î£17å¸å·ï¼å
¬å¼ï¼ä½çæä»¶**ä¸å¸¦ç¼åå¼**ï¼é¢è§/äºæ¬¡å¤çåªè¯»å°æ¯çä¸ä¸æçæ§å¼ | çææ¶å°¾æ°å¢ `recalcWorkbookFormulas()`ï¼éæ ¼ `evaluateFormulaCell` æç»æååç¼åå¼ï¼å¤±è´¥å
åº `fullCalcOnLoad=true` | |
| | | | 3ï¼é¨åï¼ | ä¸å£å¾æåæ°æ®ä¸å¯¹ | `K3/O3` æ¯ `SUM(K4:K20)` å
¬å¼ï¼åæ ·æ ç¼åå¼ï¼ï¼`M3/Q3` 忝æ¯åæ»çåºå
å
¨çå£å¾ | æ¬æ¬¡åªè§£å³"SUM æ ç¼åå¼"ï¼åæ»åæ¯å£å¾ + `loadMidClassMap` 缺两维**çå¾
ä¸ä¸æ¥**ï¼æ¹å¨ä¼å¨å£å¾ï¼éå
ç¡®è®¤ï¼ | |
| | | |
| | | æ¹å¨æä»¶ï¼ |
| | | - `traffic-audit-server/src/main/java/com/trafficaudit/reportexport/calc/SummaryWorkbookFiller.java` |
| | | - `ensureMonthFormulas()` 页èå´ä¿®æ£ï¼æ°å¢æ´¾çé¡µç»ææ§å¸¸éè¡æææ²¿ç¨ï¼æ°å¢ `isDerivedFormulaSheet()` / `structuralConstant()`ï¼ç§»é¤å·²æ ç¨ç `isFilledLedgerSheet()`ï¼å loggerã |
| | | - `traffic-audit-server/src/main/java/com/trafficaudit/reportexport/service/ReportExportService.java` |
| | | - æ°å¢ `recalcWorkbookFormulas(XSSFWorkbook)`ï¼å¹¶å¨ `exportSummaryWorkbook()` åæä»¶åè°ç¨ã |
| | | |
| | | ## äºãæµè¯ç¯å¢ |
| | | |
| | | - å端 Spring Bootï¼8090ï¼ãå端 Vueï¼8080ï¼ï¼`start-dev.ps1` å¯å¨ï¼MySQL 127.0.0.1:3308 / traffic_auditã |
| | | - æ¯çï¼`docs/çææ±æ»å¤§è¡¨/2026å¹´8æéè·¯è¿è¾éæ±æ»è¡¨.xlsx`ï¼åæå¤ä»½æ¯ç `_å¤ä»½_2026å¹´8æâ¦` **ä¸åå¨**ï¼æ¥å¿ WARNï¼å±å·²ç¥èæ¯ï¼ã |
| | | - æ¥è¡¨æï¼`2026-08`ï¼å
¥å£ï¼`GET /api/report/export/summaryWorkbook?period=2026-08&mode=month`ã |
| | | - 产ç©ï¼`_tmp/_qa_out/gen_2026-08_after.xlsx`ï¼1,329,471 Bï¼çæèæ¶ 12.6 sï¼ã |
| | | - è¯æ®ï¼`_tmp/_qa_out/{verify2.txt, verify3.txt, verify5.txt, diff_old_new.txt, after_cols.txt, xml_check.txt, v_cmp.txt}`ã |
| | | - å端æ¥å¿ï¼`æ±æ»å·¥ä½ç°¿å
¬å¼éç®å®æï¼æå 40713 æ ¼ï¼å¤±è´¥ 0 æ ¼`ã`æ´¾çé¡µç»ææ§å¸¸éè¡æææ²¿ç¨ 4 æ ¼ï¼ç¬¬ 8 æï¼`ã |
| | | |
| | | ## ä¸ãç¨ä¾è¡¨ |
| | | |
| | | ### æ£åç¨ä¾ |
| | | |
| | | | # | è¾å
¥ | 颿 | å®é
| ç»è®º | |
| | | |---|---|---|---|---| |
| | | | TC1 | çæ 2026-08 æ±æ»è¡¨ï¼æ£æ¥ãåå¸å®¢è¿ãQ åï¼8 æå½æå¼ï¼ | æ¯è¡åºæå½æå¼å
¬å¼ï¼è·¨è¡¨å¼ç¨å³ç§»ï¼ | Q4~Q39 å
± 36 æ ¼å
¨é¨æå
¬å¼ï¼å¦ `Q9 = =å
¬äº¤!Q16+åºç§!Q16+ç½çº¦è½¦!Q16+'轨éã轮渡'!Q9` | éè¿ | |
| | | | TC2 | åä¸ï¼æ£æ¥ãä¸å£å¾æç»ãQ å | 180 è¡æå½æå¼ï¼å
¬å¼æç»ææ§å¸¸éï¼ | 180 æ ¼æå¼ï¼176 å
¬å¼ + 4 常éï¼ | éè¿ | |
| | | | TC3 | æ½æ¥ãä¸å£å¾æç»ãç»ææ§å¸¸éè¡ï¼æ¦æ± åé
å乡巡游åºç§/ç½çº¦è½¦ = 0ï¼ | æææ²¿ç¨ 0ï¼ä¸ç空 | Q13=0.0ãQ14=0.0ãQ107=0.0ãQ108=0.0ï¼æ¥å¿è®°ãæ²¿ç¨ 4 æ ¼ã | éè¿ | |
| | | | TC4 | æ ¸å¯¹å
¨çè¡ = Σ17 å¸å·ï¼ç¬ç«æ±å vs ç¼åå¼ï¼ | 两è
ç¸ç | å
¬äº¤ 12315.37 = 12315.37ï¼åºç§ 5786.81 = 5786.81ï¼ç½çº¦è½¦ 4997.74 = 4997.74 | éè¿ | |
| | | | TC5 | æ£æ¥ 8 æç´¯è®¡åï¼Sï¼ | åºå« 8 æï¼=C+E+â¦+Qï¼ | å
¬äº¤ S5=110776.34ãåºç§ S5=48069.02ãç½çº¦è½¦ S5=33864.94ãä¸å£å¾æç» S5=31528.06ï¼æ¹å¨ååå«åå¨ 1~7 æï¼ | éè¿ | |
| | | | TC6 | æ£æ¥ãä¸å£å¾æåãå
¨çè¡ | `=SUM(K4:K20)` åºæç¼åå¼ = Σ17å¸å· | K3 ç¼å 24481.7407ï¼ä¸æå·¥ Σ17 å¸å·ä¸è´ï¼ãO3 ç¼å 1131273.449 | éè¿ | |
| | | | TC7 | æ£æ¥å
¬å¼æ¯å¦è¢«ç ´åï¼éç®æ¯å¦è¯¯ç¨ evaluateInCellï¼ | å
¬å¼ä¸ç¼åå¼å¹¶åï¼`<f>` + `<v>`ï¼ | XML å
¨é¨ä¸º `<c ...><f>â¦</f><v>â¦</v></c>`ï¼å
¬å¼ä¿ç | éè¿ | |
| | | | TC8 | æ£æ¥ãå叿±æ»ããä¸å£å¾åæãç跨页页 | éæ¥è¡¨æå·æ°ï¼ä¸åæ¬æ¬¡æ¹å¨å½±å | å叿±æ» æ»å®¢è¿é 269628.07ï¼1-8æï¼ï¼æ¯ç为 237412.33ï¼1-7æï¼ | éè¿ | |
| | | |
| | | ### è´å / è¾¹çç¨ä¾ |
| | | |
| | | | # | è¾å
¥ | 颿 | å®é
| ç»è®º | |
| | | |---|---|---|---|---| |
| | | | TC9 | æ¯çåæå¤ä»½ï¼`_å¤ä»½_2026å¹´8æâ¦`ï¼ç¼ºå¤± | ä¸ä¸æçæï¼è®° WARN | æ¥å¿ `æ±æ»å·¥ä½ç°¿æªæ¾å°åæå¤ä»½æ¯çâ¦`ï¼æ£å¸¸åºä»¶ | éè¿ï¼å·²ç¥èæ¯ï¼ | |
| | | | TC10 | å
¬å¼éç®éå°ä¸æ¯æå½æ°/å¤é¨å¼ç¨ | è·³è¿è¯¥æ ¼å¹¶è®¡æ°ï¼ä¸ä¸æå¯¼åº | æ¬æ¬¡å¤±è´¥ 0 æ ¼ï¼ä»£ç ä¿çéæ ¼ try-catch + å¤±è´¥æ ·ä¾æ¥å¿ | éè¿ï¼æªè§¦åï¼ | |
| | | | TC11 | æ´¾ç页ãå
¨æå常éãå¤å®è¢«è¯¯ç¨äºå°è´¦é¡µ | å°è´¦é¡µä¸å¾æ²¿ç¨ä¸ææ°å¼ï¼é²"ç»è½¬"ï¼ | `structuralConstant()` ä»
å¨ `isDerivedFormulaSheet()` ä¸ºçæ¶çæï¼6 个å°è´¦é¡µä¸éç¨ï¼ | éè¿ï¼é»è¾éç¦»ï¼ | |
| | | | TC12 | éç®è¯¯ä¼¤æ°å¼æ ¼ï¼éå
¬å¼æ ¼ï¼ | åªå¤ç `CellType.FORMULA` çæ ¼ | éåæ¶è·³è¿ææéå
¬å¼æ ¼ | éè¿ | |
| | | |
| | | ### å
¥åºæ½æ¥ï¼åº â æ±æ»è¡¨é项对é½ï¼ |
| | | |
| | | | 对象 | åºï¼`city_bus_monthly` 2026-08ï¼ | çæä»¶ | ç»è®º | |
| | | |---|---|---|---| |
| | | | æ¦æ±å¸ 客è¿é | 3856.83 | å
¬äº¤é¡µ Q9 = 3856.83 | ä¸è´ | |
| | | | é»ç³å¸ 客è¿é | 879.12 | å
¬äº¤é¡µ Q13 = 879.12 | ä¸è´ | |
| | | | 17 å¸å·å计 | 12315.37 | å
¬äº¤é¡µ Q5ï¼å
¨çè¡ç¼åï¼= 12315.37 | ä¸è´ | |
| | | | æ¦æ±å¸ åå¸å
客è¿é | 3837.20 | å
¬äº¤é¡µ Q11 = 3837.20ï¼åå¸å®¢è¿é¡µ Q6 å¼ç¨å®ï¼ | ä¸è´ | |
| | | |
| | | ## åãå彿¯å¯¹ï¼æ¹å¨å vs æ¹å¨åï¼ |
| | | |
| | | éæ ¼å¯¹æ¯æ¹å¨åå两次çæä»¶ï¼`diff_old_new.txt`ï¼ï¼ |
| | | |
| | | | 页 | 差弿 ¼æ° | |
| | | |---|---| |
| | | | åå¸å®¢è¿ | 36 | |
| | | | ä¸å£å¾æç» | 180 | |
| | | | å
¶ä½ 17 页ï¼å«è´§è¿ãå
¬äº¤ãåºç§ãç½çº¦è½¦ãç线å
车ãæå页ã跨页åæé¡µï¼ | 0 | |
| | | | **å计** | **216** | |
| | | |
| | | å·®å¼å
¨é¨è½å¨æ¬æ¬¡ç®æ 页ï¼ä¸é½æ¯ã空 â å
¬å¼ãï¼å
¶å®é¡µéæ ¼ä¸è´ï¼æ åå½ã |
| | | |
| | | ## äºãåç°çé®é¢ä¸å¤ç½® |
| | | |
| | | 1. **`FormulaEvaluator.evaluate(Cell)` æ å¯ä½ç¨**ï¼POI 4.1.0ï¼ï¼é¦æ¬¡å®ç°ç¨äº `evaluate()`ï¼æ¥å¿æ¾ç¤º"æå 40713 æ ¼"使件鿲¡æç¼åå¼ï¼`<f>` æ `<v>`ï¼ãæ¹ç¨ `evaluateFormulaCell(Cell)` ååå
¥æ£å¸¸ãå·²æç»è®ºåè¿ä»£ç 注éã |
| | | 2. **ä¸å£å¾æå忝ä»ä¸ºåæ»å¼**ï¼SUMMARY é `M3=0.7424 / Q3=0.2317` 仿¯æ¯ç/åºå
å
¨çå£å¾ï¼ä¸ Σ17 å¸å·ï¼24481.74ï¼å£å¾ä¸ä¸è´ ââ éæç¬¬ 3 æ¥ç»ä¸ï¼æ¶åå£å¾å¤å®ï¼æªå¨æ¬æ¬¡æ¹å¨ï¼ã |
| | | 3. **ç¬ç«ãçæ_å
¬è·¯æ
客ä¸å£å¾æç»ãå£å¾ç¼ºå£**ï¼`loadMidClassMap()` åªè£
"å
¬è·¯ç线 + åé
å乡å
¬äº¤"两维ï¼ç¼ºå·¡æ¸¸åºç§ãç½çº¦è½¦ ââ æªæ¹ï¼çå¾
第 3 æ¥ã |
| | | 4. **åºå
h2031ãå
¨çãè¡ â Σ17 å¸å·**ï¼1-8 æ 27524.49 vs 24481.74ï¼å·® 3042.75ï¼ï¼å±ä¸å¡å£å¾é®é¢ï¼å»ºè®®ä¸å¡ä¾§æ ¸å¯¹ï¼ä¸é»å¡ã |
| | | |
| | | ## å
ãç»è®º |
| | | |
| | | - ç¨æ·æ¥ç"8 ææ²¡æ°æ® / å
¨çè¡åå¨ä¸ä¸æ"两æ¡ä¸»çº¿**已修å¤å¹¶ç»åå½éªè¯**ï¼åå¸å®¢è¿ãä¸å£å¾æç» 8 æåè¡¥é½ï¼å
¨çè¡ã累计åãæå SUM å带æ£ç¡®ç¼åå¼ã |
| | | - æ¹å¨é¢å¯æ§ï¼216 æ ¼ï¼å
¨é¨å½ä¸ç®æ 页ï¼ï¼æ åå½ã |
| | | - 第 3 æ¥ï¼ä¸å£å¾æå忝å£å¾ç»ä¸ + `loadMidClassMap` 补两维ï¼å¾
ç¨æ·ç¡®è®¤å宿½ã |
| New file |
| | |
| | | # åè½æµè¯æ¥å_ç½çº¦è½¦è®¢åæ¥å WordML å
¼å®¹å¯¼å
¥_2026-09-18 |
| | | |
| | | ## ä¸ãåè½è¯´æ |
| | | |
| | | **èæ¯ï¼ç¨æ·æ¥éï¼**ï¼æãæ¹åç½ç»é¢çº¦åºç§æ±½è½¦2025å¹´09æåææ¥å.docxãæ¾å°æ¡é¢åç¨ãç½çº¦è½¦è®¢åæ¥åã导å
¥ï¼ä¸ç´å¤±è´¥ã |
| | | |
| | | **å®ä½ç»è®º**ï¼è¯¥æä»¶**䏿¯çæ£ç docx**ã宿¯ **Word 2003 XMLï¼WordML å¹³éº XMLï¼åæä»¶ï¼**被æ¹åæäº `.docx`ï¼ |
| | | - æä»¶å¤´æ¯ `<?xml version="1.0" ...?> <?mso-application progid="Word.Document"?> <w:wordDocument xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" ...>` |
| | | - 3.1MB 纯 XMLï¼**䏿¯ zip å
**ï¼POI ç `XWPFDocument` åªè½è¯» OPC(zip) å
ï¼äºæ¯æ `File is not a zip file`ã |
| | | - è¿ç±»æä»¶æ¯ WPS/WordãWord 2003 XML ææ¡£ãæ ¼å¼ï¼ç½çº¦è½¦ç管平å°/åäºä¹é´æµè½¬å¾å¸¸è§ï¼ä¼åå¤åºç°ã |
| | | |
| | | **æ¹å¨**ï¼`traffic-audit-server/src/main/java/com/trafficaudit/dataimport/service/DataImportService.java` |
| | | |
| | | 1. `importWycOrderReport()` å
¥å£å
ææä»¶å¤´å
æ¢æ ¼å¼ï¼ååæ´¾ï¼ |
| | | - `PK` å¼å¤´ â docxï¼zipï¼ï¼å `XWPFDocument` è·¯å¾ï¼ |
| | | - `<w:wordDocument` + `wordml` â **WordML å¹³éº XMLï¼æ°å¢è§£æè·¯å¾**ï¼ |
| | | - `D0CF11E0` â OLE2 è `.doc`ï¼ç»åºã请å¦å为 docxãçæç¡®æç¤ºï¼ |
| | | - å
¶å® â ãæ æ³è¯å«çæä»¶æ ¼å¼ãã |
| | | 2. æ°å¢ `isWordPackage()`ï¼zip ä½å
å
没æ `word/document.xml`ï¼å¦ xlsx æ¹åï¼æ¶ï¼ç´æ¥æç¤ºãè¿ä¸æ¯ Word ææ¡£â¦â¦å¤åæ¯ Excel æå
¶å®æ ¼å¼ãï¼ä¸åæåº XMLBeans çè±æå æ ã |
| | | 3. æ°å¢ `parseXmlSafely()`ï¼DOM è§£æå¹¶**å
³éå¤é¨å®ä½/DTD**ï¼æ¥åæ¥èªå¤é¨å¹³å°ï¼é² XXEï¼ã |
| | | 4. è¡¨æ ¼å¹é
é»è¾æ½æä¸æ ¼å¼æ å
³ç `matchWycOrderTable(tables, orders, sumHolder)`ï¼ |
| | | - docx è·¯å¾æ `XWPFTable` ææ¬ååè°ç¨ï¼ |
| | | - WordML è·¯å¾æ `<w:tbl>/<w:tr>/<w:tc>` ææ¬ååè°ç¨ï¼ |
| | | - 表头è¯å«ã17 å¸å·åå¼ãå计è¡è¯å«**å®å
¨å¤ç¨åä¸å¥é»è¾**ï¼ä¸¤æ¡è·¯å¾ä¸ä¼åºç°å£å¾ååã |
| | | 5. æ¥è¡¨æè¯å«æ½æ `periodOfParagraphs(List<String>)`ï¼ä¸¤ç§æ ¼å¼å
±ç¨ï¼æ é¢ `ç½çº¦è½¦è¡ä¸YYYYå¹´Mæ` ä¼å
ï¼åä¸å°åéãå 10 段任æ YYYYå¹´Mæãï¼ã |
| | | |
| | | ## äºãæµè¯ç¯å¢ |
| | | |
| | | - å端 8090ï¼`mvn -o compile` åéå¯ï¼å è½½æ°ç±»ï¼å¯å¨æ¥å¿ `Started TrafficAuditApplication`ï¼ï¼æ°æ®åº `traffic_audit`ï¼127.0.0.1:3308ï¼ã |
| | | - æ¥å£ï¼`POST /api/import/wycOrderReport`ï¼`file` + `period`ï¼`period` å¯ä¸ºç©º â ç±æ¥åæ 颿¨æï¼ã |
| | | - æµè¯æä»¶ï¼`D:\æ¡é¢\æ¹åç½ç»é¢çº¦åºç§æ±½è½¦2025å¹´09æåææ¥å.docx`ï¼WordMLï¼3,145,560 åèï¼ï¼`D:\05_æ°æ®åç±»\åå¸å®¢è¿\8æ\æ¹åç½ç»é¢çº¦åºç§æ±½è½¦2026å¹´08æåææ¥å0910æç»ç.docx`ï¼ç docxï¼ã |
| | | - è¯æ®æä»¶ï¼`_tmp/_qa_out/`ï¼å½ä»¤è¾åºè§æ¬æ¥åè¡¨æ ¼ï¼æ°æ®æ ¸å¯¹è§ `_wyc_2025_09_row.txt`ï¼ã |
| | | |
| | | ## ä¸ãç¨ä¾è¡¨ |
| | | |
| | | | ç¼å· | ç±»å | è¾å
¥ | 颿 | å®é
| ç»è®º | |
| | | |---|---|---|---|---|---| |
| | | | 1 | æ£å | WordMLã2025å¹´09æãæ¥åï¼`period=2025-09` | è§£æåº 17 å¸å·è®¢åï¼åå
¥ 2025-09 | `导å
¥æåï¼æ¥è¡¨æ 2025-09ï¼è®¢åå计 17,652,159 åï¼å·²åå
¥ 17 个å¸å·` | éè¿ | |
| | | | 2 | æ£å | åä¸ï¼`period=` ç空 | ç±æ é¢ `ç½çº¦è½¦è¡ä¸2025å¹´9æ` æ¨æåº 2025-09 | æ¥è¡¨æ 2025-09ï¼ç»æä¸ç¨ä¾ 1 ä¸è´ | éè¿ | |
| | | | 3 | æ£å | ç docxã2026å¹´08æãæ¥åé导 | ä¸åºå
æ¢æå¼ä¸è´ï¼å¹çï¼ä¸æ¹åç»æï¼ | 订åå计 30,508,652ãæ¦æ± 11,550,551ï¼ä¸å¯¼å
¥åå®å
¨ç¸å | éè¿ | |
| | | | 4 | æ£å | 2026å¹´06ææ¥å | 订åå计 = æ¥åæ£æãå
¨çè®¢åæ»æ° 2684.30 ä¸åã | åºå
2026-06 = 26,843,037 | éè¿ | |
| | | | 5 | è´å | `.doc`ï¼OLE2 å¤åææ¡£ï¼Word 97-2003ï¼ | æç¡®æç¤ºæ¹ç¨ docx | `è¿æ¯ Word 97-2003 èæ ¼å¼ï¼.docï¼ï¼è¯·ç¨ WPS/Word æå¼åãå¦å为ãdocx æ ¼å¼å导å
¥` | éè¿ | |
| | | | 6 | è´å | xlsx æ¹åæ `.docx` ä¸ä¼ | æç¡®æç¤ºä¸æ¯ Word | `è¿ä¸æ¯ Word ææ¡£ï¼å缩å
éæ²¡æ word/document.xmlï¼ï¼å¤åæ¯ Excel æå
¶å®æ ¼å¼â¦â¦` | éè¿ | |
| | | | 7 | è´å | éç½çº¦è½¦æ¥åç docxï¼ãæèµè¡¨ä¹é´çå
³ç³».docxãï¼ | æç¤ºæªè§£æå°è®¢åæ° | `æªè§£æå°ä»»ä½å¸å·è®¢åæ°ï¼è¯·ç¡®è®¤ä¸ä¼ çæ¯ãç½çº¦è½¦è¡ä¸YYYYå¹´Mæè¿è¡çæµæ
åµåææ¥åã` | éè¿ | |
| | | | 8 | è¾¹ç | WordML ä¸è¡¨æ ¼å« 16 åã表头å¨ç¬¬ 1 è¡ãå¸å·åç¨ç®ç§°ï¼`æ¦æ±`/`æåº`ï¼ | ç®ç§°è½æ å°å°è§èåï¼æ¦æ±å¸/ç¥åæ¶æåºï¼ | 17 å¸å·å
¨é¨è¯å«ï¼æ 缺失 | éè¿ | |
| | | |
| | | **å
¥åºæ½æ¥**ï¼æ¥è¡¨æ 2025-09ï¼ä¸æ¥åéä»¶1é项对é½ï¼ |
| | | |
| | | | 项 | æ¥åéä»¶1 | åºå
`wyc_order_monthly` | ç»è®º | |
| | | |---|---|---|---| |
| | | | 订åå计 | 17,652,159 | 17,652,159 | ä¸è´ | |
| | | | æ¦æ± | 8,076,610 | 8,076,610 | ä¸è´ | |
| | | | é»ç³ | 676,644 | 676,644 | ä¸è´ | |
| | | | åå ° | 1,048,593 | 1,048,593 | ä¸è´ | |
| | | | æ©æ½ | 804,736 | 804,736 | ä¸è´ | |
| | | | ç¥åæ¶æåº | 1,424 | 1,424 | ä¸è´ | |
| | | | å
¨ç pinï¼B~Eï¼ | æ¥åæ | 2794.31 / 2522.54 / 16394.73 / 12998.74ï¼ä» `wyc_total_monthly` åæå¤å¶ï¼ | 符å设计 | |
| | | |
| | | ## åãåç°çé®é¢ä¸å¤ç½® |
| | | |
| | | 1. **æ ¼å¼å
¼å®¹ç¼ºå£ï¼æ¬æ¬¡ä¿®å¤ï¼**ï¼WordML æ¥åæ æ³å¯¼å
¥ãå·²å è§£æè·¯å¾ï¼ä¸¤ç§æ ¼å¼å
±ç¨åä¸å¥è¡¨æ ¼å¹é
é»è¾ï¼é¿å
å£å¾ååã |
| | | 2. **é误信æ¯ä¸åå¥½ï¼æ¬æ¬¡ä¿®å¤ï¼**ï¼xlsx æ¹å忥 `org.apache.xmlbeans.XmlException: Element workbook@... is not a valid document@...`ãå·²æ¹ä¸ºä¸æä¸å¡æç¤ºã |
| | | 3. **20XX å¹´ååæ¥åæ é¢æ ¼å¼ä¸å**ï¼2025 å¹´æ¥åæ 颿¯ãæ¹å**ç½çº¦è½¦è¡ä¸ 2025å¹´9æ** è¿è¡æ
åµåææ¥åãï¼2026 å¹´æ¯ãç½çº¦è½¦è¡ä¸2026å¹´6æè¿è¡çæµæ
åµåææ¥åããåä¸å¥æ£ååå¯å½ä¸ï¼æ éåæ¹ã |
| | | 4. **æ°æ®ç¼ºå£å·²ç±ç¨æ·è¡¥é½**ï¼2026-01~06ï¼14:21 导å
¥ 6 份ï¼ã2025-01ï¼14:47ï¼ã2025-10~12ï¼14:49ï¼åå·²å
¥åºï¼2025-09 ç±æ¬æ¬¡ä¿®å¤åè¡¥å
¥ï¼14:59 馿¬¡ã15:04 夿 ¸ï¼ã |
| | | - å
¨é¨ 2025-01~12ã2026-01~08 ç订åä¸ pin ç°å·²é½å
¨ã |
| | | - å½±åï¼ä¸å£å¾ç»´åº¦ 4ï¼åé
å乡ç½çº¦è½¦ï¼1~6 æç±ãæ æºãå为ãå¯ç®ãï¼**ä¸å£å¾æåä»¶ä¸ä¸å£å¾æç»ä»¶ç´¯è®¡å£å¾èªå¨å½ä¸**ï¼æ¤åå·®å¼ 2063.45 = 1~6 æç½çº¦è½¦å乡ï¼ã |
| | | |
| | | ## äºãç»è®º |
| | | |
| | | - WordMLï¼Word 2003 XML æ¹å .docxï¼æ¥åç°å·²å¯ç´æ¥å¯¼å
¥ï¼17 å¸å· + åè®¡è§£ææ£ç¡®ãå
¥åºé项对é½ï¼ç docx è·¯å¾æ åå½ã |
| | | - 3 æ¡è´åç¨ä¾åç»åºä¸æå¯æä½æç¤ºï¼.doc / é Word å
/ 鿬æ¥åï¼ã |
| | | - 8 ä¾ç¨ä¾å
¨é¨éè¿ï¼`docs/åè½æµè¯æ¥å/` ä¸å·²å½æ¡£æ¬æ¥åã |
| New file |
| | |
| | | # åè½æµè¯æ¥å_è´§è¿ææ¥æç»å¨è§ä¼ä¸åå¸å·ç´¯è®¡è¿è·_2026-09-18 |
| | | |
| | | ## ä¸ãåè½è¯´æ |
| | | |
| | | - **éæ±**ï¼å°è´§è¿ææ¥ãæç»å¨è§ä¼ä¸ãåå¸å· 1-8 æç´¯è®¡è¿è·å忝æ
嵿´çæ Excel è¡¨æ ¼ï¼çæå°æ¡é¢ã |
| | | - **å£å¾**ï¼ |
| | | - æç»å¨è§ä¼ä¸ = 2026 å¹´ 1-8 æè¿ç» 8 个æå䏿¥ãé路货ç©è¿è¾æåº¦ç产æ
åµãï¼H203-2ï¼ææ¥çä¼ä¸ï¼å
± **636 å®¶**ï¼ |
| | | - 累计平åè¿è·ï¼å
¬éï¼= 1-8 æç´¯è®¡è´§ç©å¨è½¬é ÷ 1-8 æç´¯è®¡è´§è¿éï¼å æå¹³åï¼ï¼ |
| | | - 忝 = 2026 å¹´ 1-8 æç´¯è®¡å¼ ÷ 2025 å¹´ 1-8 æç´¯è®¡å¼ â 1ï¼**åºæä¸º 2025 å¹´ 1-8 æå
¨é¨è§ä¸ä¼ä¸ä¸æ¥æ°**ï¼å
¨ç 664 å®¶ï¼ï¼ä¸æ±æ»è¡¨ãè´§è¿ã页 T åå
¬å¼ `=S/SUM(V7,X7,â¦,AJ7)-1` åä¸å£å¾ï¼v1 æ¾è¯¯ç¨ã两年åæç»å¨è§ç 545 å®¶ãä½åºæï¼å·²è®¢æ£ï¼è§ç¬¬å
èï¼ã |
| | | - **æ°æ®æ¥æº**ï¼`traffic_audit.h2032_enterprise_monthly`ï¼2025-01 ~ 2026-08 ä¼ä¸çº§ææ¥ï¼ã |
| | | - **产åº**ï¼`C:\Users\éçæ´\Desktop\è´§è¿ææ¥_æç»å¨è§ä¼ä¸_åå¸å·1-8æç´¯è®¡è¿è·å忝_2026-09-18.xlsx`ï¼å« 5 个页ç¾ï¼ |
| | | `说æä¸å£å¾`ã`åå¸å·æ±æ»`ã`åå¸å·åæ`ã`ä¼ä¸æç»`ï¼636 è¡ï¼ã`å£å¾å¯¹æ¯`ã`å£å¾æ ¡éª`ã |
| | | - **çæèæ¬**ï¼`docs\å·¥å
·\æç»å¨è§ä¼ä¸ç´¯è®¡è¿è·çæ.py`ï¼å¤è·éå
çæä¸¤ä»½ TSV 导åºä»¶ï¼SQL è§éå½ï¼ã |
| | | |
| | | ## äºãæµè¯ç¯å¢ |
| | | |
| | | | 项 | å
容 | |
| | | | --- | --- | |
| | | | æ°æ®åº | MySQL 127.0.0.1:3308 / traffic_auditï¼è¡¨ `h2032_enterprise_monthly` | |
| | | | è¿è¡ç¯å¢ | Python 3.14.2 + openpyxl 3.1.5 | |
| | | | 对ç
§ç© 1 | ã2026å¹´8æè§ä¸è´§ç©å¨è½¬éä¸å¹³åè¿è·åææ¥åï¼è稿ï¼ãå
¨ç彿/累计å£å¾ | |
| | | | 对ç
§ç© 2 | `docs\çææ±æ»å¤§è¡¨\2026å¹´8æéè·¯è¿è¾éæ±æ»è¡¨.xlsx`ã è´§è¿ã页ãå
¶ä¸è§ä¸è´§è¿é/è§ä¸è´§ç©å¨è½¬éã | |
| | | | è¾åºç®å½ | å·¥ä½åº `outputs\`ï¼çæï¼+ æ¡é¢ï¼äº¤ä»ï¼ï¼ä¸¤ä»½ SHA256 ä¸è´ | |
| | | |
| | | ## ä¸ãç¨ä¾è¡¨ |
| | | |
| | | | ç¼å· | ç±»å | è¾å
¥ | 颿 | å®é
| ç»è®º | |
| | | | --- | --- | --- | --- | --- | --- | |
| | | | TC01 | æ£å | 2026-08 å
¨çè§ä¸è´§è¿é | 3665.36 ä¸å¨ | 3665.36 ä¸å¨ | éè¿ | |
| | | | TC02 | æ£å | 2026-08 å
¨çè§ä¸è´§ç©å¨è½¬é | 570004.44 ä¸å¨å
¬é | 570004.44 ä¸å¨å
¬é | éè¿ | |
| | | | TC03 | æ£å | 2026 å¹´ 1-8 æç´¯è®¡è´§è¿é/å¨è½¬é | 31399.82 / 4927161.77 | 31399.82 / 4927161.77 | éè¿ | |
| | | | TC04 | æ£å | 2026-01~07 éæè§ä¸è´§è¿éãå¨è½¬é䏿±æ»è¡¨ã è´§è¿ã页æ¯å¯¹ï¼14 é¡¹ï¼ | å
¨é¨ä¸è´ | 14/14 ä¸è´ï¼4 ä½å°æ°ï¼ | éè¿ | |
| | | | TC05 | æ£å | 17 å¸å·è¦çé¢ | å
¨è¦çãæ æªè¯å«å°åºç | 17/17ï¼æªè¯å« 0 æ¡ | éè¿ | |
| | | | TC06 | æ£å | ä¼ä¸æç» 636 è¡æ±å | = åå¸å·æ±æ»å计 | 31399.8248 / 4927161.7743ï¼å·®å¼ 0 | éè¿ | |
| | | | TC07 | æ£å | åå¸å·åæé¡µ | 8 æå
¨ç = åå¸å£å¾ 155.51 å
¬éï¼åå¸å·ç´¯è®¡å = æ±æ»é¡µç´¯è®¡å | 155.51ï¼17 个å¸å·é项 0 å·®å¼ | éè¿ | |
| | | | TC08 | æ£å | å
¨ç 1-8 æç´¯è®¡å¹³åè¿è· | = 累计å¨è½¬é ÷ 累计货è¿é | 156.92 = 4927161.77 ÷ 31399.82 | éè¿ | |
| | | | TC09 | è¾¹ç | 2026 åæä¸æ¥ä¼ä¸æ° | åæä¸è´ï¼æ¯æãæç»å¨è§ãå¤å® | åæå为 636 å®¶ï¼å
¨æä¸è´ | éè¿ | |
| | | | TC10 | è¾¹ç | 5 å®¶ 1-8 æè´§è¿éãå¨è½¬éå
¨ä¸º 0 çä¼ä¸ | 计å
¥ä¼ä¸æ°ï¼ä¸å½±åå¸å·è¿è· | è¿è·æ±æ»æªåå½±å | éè¿ | |
| | | | TC11 | è¾¹ç | æ¦æ±ç³å交éè¿è¾æéå
¬å¸ãæ¹åæ·é¾äº¤éè¿ä¸æéå
¬å¸ 1 æå°åºç 420100ãå
¶å 420107/420103 | å屿¦æ±å¸ï¼å½éä¸å | åå½å
¥æ¦æ±å¸ | éè¿ | |
| | | | TC12 | è´å | 仿¡å¸ã两年åæç»å¨è§ãä¼ä¸æ° = 0 | 忝ç空 + æç¡®å¤æ³¨ï¼ä¸é¤é¶æ¥é | 忝å空ï¼å¤æ³¨ã忝ä¸éç¨ï¼2025 å¹´ 1-8 ææ è¿ç»ä¸æ¥è®°å½ã | éè¿ | |
| | | | TC13 | è´å | 累计货è¿é为 0 çä¼ä¸ | 累计è¿è·ç空ï¼ä¸é¤é¶æ¥é | é»è¾å·²é²é¤é¶ï¼æ¬è¡¨ 636 å®¶æ æ¤ç±»ä¼ä¸ï¼ | éè¿ | |
| | | | TC14 | è´å | å°åºç ä¸å¨ 17 å¸å·æ å°å
| å½å
¥ãæªè¯å«ã并卿 ¡éªé¡µæ´é² | å®é
0 æ¡ | éè¿ | |
| | | |
| | | ## åãåç°çé®é¢ä¸å¤ç½® |
| | | |
| | | 1. **çæèæ¬è¡å·éä½ï¼å·²ä¿®ï¼**ï¼é¦æ¬¡çææ¶æ±æ»é¡µè¡¨å¤´è¢«æ°æ®è¦çãæ«è¡ãç¥åæ¶æåºã被å计è¡è¦çï¼æ ¹å æ¯ `rr` èªå¢æ¬¡æ°ä¸åè¡ä½ç½®ä¸å¹é
ãä¿®æ£åéè·ï¼`åå¸å·æ±æ»` 为表头 + 17 å¸å· + å计å
± 18 è¡ï¼éè¡æ ¸å¯¹æ 误ã |
| | | 2. **æ¡é¢å¯æ¬ä¸åº¦ä¸ºä¿®æ£åçæ¬ï¼å·²ä¿®ï¼**ï¼éæ°åæ¥å¹¶æ ¡éªå·¥ä½åºä¸æ¡é¢æä»¶ SHA256 ä¸è´ï¼94869 åèï¼ã |
| | | 3. **å£å¾å¾
ä¸å¡ç¡®è®¤ï¼2 项ï¼**ï¼ |
| | | - ãæç»å¨è§ä¼ä¸ãæã2026 å¹´ 1-8 æè¿ç» 8 个æä¸æ¥ãå®ä¹ä¸º 636 å®¶ï¼**ç¨æ· 2026-09-18 已确认æ¤å£å¾**ï¼åååºãè¿ç»ä¸¤å¹´å¨è§ããè¿ç» 12 个æå¨è§ã两ç§å¤éï¼åä¸éç¨ï¼ã |
| | | - 忝éç¨ 545 家坿¯å£å¾ï¼åé¤ 91 å®¶ 2025 å¹´æ åæè¿ç»ä¸æ¥çä¼ä¸ï¼ï¼ä»æ¡å¸å æ 坿¯ä¼ä¸åæ¯ç空ã |
| | | |
| | | ## äºãç»è®º |
| | | |
| | | 14 æ¡ç¨ä¾ï¼8 æ£å / 3 è¾¹ç / 3 è´åï¼å
¨é¨éè¿ï¼è®¢æ£åå¦è¡¥ TC15âTC18 å
± 4 æ¡ï¼äº¦å
¨é¨éè¿ï¼å
¨ç彿ã累计ãåå¸å·ä¸ä¸ªå±çº§ä¸å·²åå¸å£å¾**é¶å·®å¼**ï¼æç»ä¸æ±æ»é项对账ä¸è´ï¼äº¤ä»ä»¶å·²çæå°æ¡é¢ãå£å¾å·²äº 2026-09-18 ç±ç¨æ·ç¡®è®¤ï¼636 å®¶ï¼ï¼åæ¯åºæå£å¾å·²ææ±æ»è¡¨å
¬å¼è®¢æ£ä¸ºå
¨å£å¾ã |
| | | |
| | | ## éå½ï¼å¤è·ç¨ SQL |
| | | |
| | | ```sql |
| | | -- ä¼ä¸çº§ç´¯è®¡ï¼å¯¼åºä¸º _tmp_persist_scope.tsvï¼ |
| | | SELECT MAX(region_code) rc, enterprise_name en, IFNULL(MAX(enterprise_code),'') ec, |
| | | IFNULL(MAX(unified_credit_code),'') ucc, |
| | | SUM(CASE WHEN report_period BETWEEN '2026-01' AND '2026-08' THEN IFNULL(freight_total,0) ELSE 0 END) f26, |
| | | SUM(CASE WHEN report_period BETWEEN '2026-01' AND '2026-08' THEN IFNULL(turnover_total,0) ELSE 0 END) t26, |
| | | COUNT(DISTINCT CASE WHEN report_period BETWEEN '2026-01' AND '2026-08' THEN report_period END) m26, |
| | | SUM(CASE WHEN report_period BETWEEN '2025-01' AND '2025-08' THEN IFNULL(freight_total,0) ELSE 0 END) f25, |
| | | SUM(CASE WHEN report_period BETWEEN '2025-01' AND '2025-08' THEN IFNULL(turnover_total,0) ELSE 0 END) t25, |
| | | COUNT(DISTINCT CASE WHEN report_period BETWEEN '2025-01' AND '2025-08' THEN report_period END) m25 |
| | | FROM h2032_enterprise_monthly |
| | | WHERE report_period BETWEEN '2025-01' AND '2026-08' |
| | | GROUP BY enterprise_name HAVING m26 = 8; |
| | | |
| | | -- ä¼ä¸çº§åæï¼å¯¼åºä¸º _tmp_persist_scope_monthly.tsvï¼ |
| | | SELECT report_period, region_code, enterprise_name, IFNULL(freight_total,0), IFNULL(turnover_total,0) |
| | | FROM h2032_enterprise_monthly WHERE report_period BETWEEN '2025-01' AND '2026-08'; |
| | | ``` |
| | | |
| | | ## å
ã订æ£è®°å½ï¼2026-09-18ï¼v2ï¼ |
| | | |
| | | **é®é¢**ï¼ç¨æ·åé¦ 1-8 æç´¯è®¡è¿è·åæ¯ä¸å¯¹ãæ ¸æ¥åç° v1 çåæ¯åºæåã两年åæç»å¨è§ç 545 å®¶ä¼ä¸ãï¼ |
| | | èæ±æ»è¡¨ãè´§è¿ã页 T åï¼ç´¯è®¡åæ¯ï¼çå
¬å¼æ¯ `=S7/SUM(V7,X7,Z7,AB7,AD7,AF7,AH7,AJ7)-1`ï¼ |
| | | åºæä¸º **2025 å¹´ 1-8 æå
¨é¨è§ä¸ä¼ä¸**ï¼å
¨ç 664 å®¶ï¼ã两å¥åºæå¯¼è´åæ¯ç³»ç»æ§åå°ã |
| | | |
| | | **è¯æ®**ï¼ |
| | | |
| | | | é¡¹ç® | v1ï¼545 家坿¯å£å¾ï¼ | v2ï¼å®æ¹å
¨å£å¾ï¼ä¿®æ£åï¼ | å·²å叿¥å | |
| | | | --- | --- | --- | --- | |
| | | | 2025 å¹´ 1-8 æè´§è¿éåºæ(ä¸å¨) | â | 33994.4483 | æ±æ»è¡¨ V7..AJ7 ç¼åå¼å计ä¸è´ | |
| | | | 2025 å¹´ 1-8 æå¨è½¬éåºæ(ä¸å¨å
¬é) | â | 5102518.9463 | æ±æ»è¡¨ V8..AJ8 ç¼åå¼å计ä¸è´ | |
| | | | 累计货è¿é忝 | â7.96% | **â7.63%** | â7.63% | |
| | | | 累计å¨è½¬é忝 | â5.30% | **â3.44%** | â3.44% | |
| | | | å
¨ç 1-8 æç´¯è®¡å¹³åè¿è·åæ¯ | +2.90% | **+4.54%** | âï¼= 156.92 ÷ 150.10 â 1ï¼ | |
| | | |
| | | **å¤ç½®**ï¼éç®å
¨è¡¨ï¼`åå¸å·æ±æ»` æ¹ä¸ºã2026 å
¨å£å¾ / 2025 å
¨å£å¾ / 忝ã䏿®µåï¼æ°å¢ `å£å¾å¯¹æ¯` 页并å宿¹å£å¾ä¸åä¼ä¸å£å¾ï¼ |
| | | ä¾ä¸å¡å¤æå¸å·è½å·®æ¥æºï¼æææ ¡éªé¡¹ 0 å·®å¼ã |
| | | |
| | | | ç¼å· | ç±»å | è¾å
¥ | 颿 | å®é
| ç»è®º | |
| | | | --- | --- | --- | --- | --- | --- | |
| | | | TC15 | æ£å | 2025 å¹´ 1-8 æåºæè´§è¿éãå¨è½¬é | = æ±æ»è¡¨ãè´§è¿ã页 V7..AJ7 / V8..AJ8 | 33994.45 / 5102518.95ï¼0 å·®å¼ | éè¿ | |
| | | | TC16 | æ£å | ç´¯è®¡åæ¯ï¼è´§è¿éãå¨è½¬éï¼ | = å叿¥å â7.63% / â3.44% | å®å
¨ä¸è´ | éè¿ | |
| | | | TC17 | æ£å | å
¨ç累计平åè¿è·åæ¯ | = 156.92 ÷ 150.10 â 1 = +4.54% | +4.54% | éè¿ | |
| | | | TC18 | è´å | v1 ç 545 å®¶å£å¾ | å·®å¼å¯éåã䏿®çäºäº¤ä»ä»¶ | å·®å¼ +1.64 个ç¾åç¹ï¼å·²æ¹ä¸ºå¹¶åå±ç¤ºå¹¶æ 注为åèå£å¾ | éè¿ | |
| | | |
| | | **éçæç¤º**ï¼ä»æ¡å¸å®æ¹å£å¾åæ¯ â89.1%ï¼2025 å¹´ 2 家为è¶
é¿éå°è¿éä¼ä¸ã2026 å¹´æ¢ä¸ºçé大è¿éä¼ä¸ï¼ã |
| | | é»ç³ +35.3%ãè¥é³ +21.0% çï¼å¤ä¸ºä¸¤å¹´è§ä¸ä¼ä¸ååå卿è´ï¼å»ºè®®ä¸å¡ä¾§æ `å£å¾å¯¹æ¯` é¡µæ ¸å¯¹ã |
| New file |
| | |
| | | # 工使¥ç»_2026-09-18 |
| | | |
| | | ## ä¸ãä»å¤©åäºä»ä¹ |
| | | |
| | | ### 1. æ±æ»è¡¨ä¸æ¡ä¸»çº¿ï¼ç¨æ· 09-18 ä¸åæåºï¼å·²ä¿®å两æ¡ï¼ |
| | | |
| | | **å
å®ä½ï¼å卿**ï¼å¤æ ¸ 8 æçæä»¶ï¼ç¡®è®¤ä¸æ¡ä¸»çº¿æ¯ãä¸ä¸ªç»ä¸æ ¹å + ä¸å¤é¡µèå´æ¼é¡¹ + ä¸å¤å£å¾ç¼ºå£ãï¼ |
| | | |
| | | - æ¯çæ¬èº«æ¯å
¬å¼é©±å¨çï¼å
¨çè¡ = Σ17 å¸å·ï¼`å
¬äº¤!C5 = =C9+C13+â¦`ï¼ãåå¸å®¢è¿/ä¸å£å¾æç»å¸å·è¡ = 跨表å¼ç¨ï¼`åå¸å®¢è¿!C9 = =å
¬äº¤!C16+åºç§!C16+ç½çº¦è½¦!C16+'轨éã轮渡'!C9`ï¼â è¿ä¸¤é¡µæ ¹æ¬ä¸ç¨åç¬åæ°æ®ã |
| | | - 主线 1 æ ¹å ï¼`SummaryWorkbookFiller.ensureMonthFormulas()` 页èå´åªå« 6 个å°è´¦é¡µï¼æ¼ åå¸å®¢è¿/ä¸å£å¾æç»ï¼è忝å
¬å¼ç¨ç页èå´æ¯å«ç â åºç°"忝åæå
¬å¼ã彿å¼å空ç½"ã |
| | | - 主线 2/3 æ ¹å ï¼çæä»¶**ä¸å¸¦å
¬å¼ç¼åå¼**ï¼é¢è§/äºæ¬¡å¤ç读å°çæ¯æ¯çä¸ä¸æçæ§å¼ã |
| | | |
| | | **æ¹å¨**ï¼ |
| | | - `SummaryWorkbookFiller.ensureMonthFormulas()`ï¼é¡µèå´æ¹ç¨ `isMonthLedgerSheet`ï¼æ´¾ç页æ°å¢"ç»ææ§å¸¸éè¡æææ²¿ç¨"ï¼ä¸å£å¾æç» æ¦æ± åé
å乡åºç§/ç½çº¦è½¦ æä¸º 0 ç 4 æ ¼ï¼ï¼å loggerï¼å æå·²æ ç¨ç `isFilledLedgerSheet()`ã |
| | | - `ReportExportService.recalcWorkbookFormulas()`ï¼æ°å¢ï¼çææ¶å°¾éæ ¼ `evaluateFormulaCell` ååç¼åå¼ï¼å¤±è´¥å
åº `fullCalcOnLoad=true`ï¼ã |
| | | |
| | | **踩åè®°å½**ï¼POI 4.1 ç `FormulaEvaluator.evaluate(Cell)` **æ å¯ä½ç¨**ï¼åªç®ä¸åï¼ï¼ç¬¬ä¸çç½è·ï¼æ¥å¿"æå 40713 æ ¼"使件æ `<v>`ï¼ï¼å¿
é¡»ç¨ `evaluateFormulaCell(Cell)`ã |
| | | |
| | | ### 2. å
¶ä» |
| | | |
| | | - åäºãæ±æ»è¡¨ä¸æ¡ä¸»çº¿ä¿®å¤æ¹æ¡_2026-09-18ãï¼`docs/é®é¢æ±æ»/`ï¼ï¼ææ ¹å ãè¯æ®ã4 æ¥ä¿®æ³ãæèµ"æé¡¹ç®åç§°æ´æ°/æ°å¢æè¡"ç°ç¶ä¸å¹¶è®°å½ã |
| | | - æèµä¾§æ ¸å®ï¼å¯¼å
¥ç¡®å®æã项ç®åç§° + ç±»å«ãupsertï¼åºå
客è¿ç«åº 49/49ãç©æµååº 135/135 æ éå¤è¡ï¼ï¼ç¼ºå£æ¯"模æ¿é没æçæ°é¡¹ç®ä¸ä¼æè¡"ã"èµéæ¸ éåç»è¡å¯¼å
¥æ¶è¢«è·³è¿"ã"ååä¸å项ç®ä¸å¼¹çª"ã |
| | | |
| | | ### 3. 第 3 æ¥ï¼ä¸å£å¾åç»´å£å¾ç»ä¸ï¼ä¸åï¼ |
| | | |
| | | **å£å¾å®æ»**ï¼åè¿ãåè½æµè¯æ¥å_ä¸å£å¾åç»´å£å¾ç»ä¸_2026-09-18ãï¼ï¼1 å
¬è·¯ç线ï¼h2031+个ä½ï¼= 2 åé
å乡å
¬äº¤ï¼city_busï¼= 3 åé
å乡巡游åºç§ï¼city_taxiï¼æ»éâåå¸å
ï¼= 4 åé
å乡ç½çº¦è½¦ï¼WycSplitCalc æåï¼ï¼æ»é = åç»´ä¹åï¼**å
¨çè¡ä¸å¾ Σ17 å¸å·**ã |
| | | |
| | | **æ¹å¨**ï¼`ReportExportService.java`ï¼ï¼ |
| | | - `loadMidClassMap()` 补维度 3ã维度 4ï¼æ°å¢ `midPeriodKey()`ï¼ï¼ |
| | | - `fillMidCell()` 廿ãåºç§/ç½çº¦è½¦åæ» 0ãæè·¯ï¼`fillMidYoyCell()`/`fillMidCumYoyColumn()` 忝æ¹åç»´é½å
¨ï¼ |
| | | - `exportPassengerMidDetail()` ç±ãåªéåå
¬å¼æ ¼ãæ¹ä¸ºãæåéåãï¼æ©ååºç 7~12 æç©ºæ ¼æå¡«å¾ä¸ï¼ï¼ |
| | | - æ©åæä»½çæ»è¡å¼åæ¹ç±åºå
åç»´åè®¡ç´æ¥åå
¥ï¼æ¨¡æ¿æ¬æ æ¤åï¼å
é忢æ å
¬å¼ä¹æ ç¼åå¼ï¼ï¼ |
| | | - è¯¥å½æ°éç®æ¹ç¨éæ ¼å®¹éç `recalcWorkbookFormulas()`ââ`evaluateAll()` ä¼å¨è·¨ç°¿å
¬å¼ï¼Sheet2 ç `[1]xx!A1`ï¼å¤æ´æ¬ä¸æï¼ç´¯è®¡åå°±æ°¸è¿æ¿ä¸å°æ°ç¼åå¼ã |
| | | |
| | | **éªè¯**ï¼ç¬ç«ãçæ_ä¸å£å¾æç»ã8 æå
¨çæ»è¡ 4003.5701ã7 æ 4028.3213ï¼å为空ï¼ï¼18 个å°åºæ»è¡ = Σ4 ç»´ã累计å = Σ1-8 æï¼ä¸æ±æ»å¤§è¡¨ãä¸å£å¾æç»ãé¡µéæ ¼ä¸è´ï¼åå½ = æ±æ»è¡¨ 17 页 0 å·®å¼ãæåä»¶ 0 å·®å¼ãæç»ä»¶ä»
36 æ ¼ï¼18 å°åº à 2 ä¸ªææ»è¡ï¼ååã |
| | | |
| | | **é¡ºå¸¦æ¥æ¸
两个èé®é¢**ï¼ |
| | | - ãçæ_ä¸å£å¾æåãå
¨ç累计 29464.6108 / 忝 0.638ï¼æ¯ä¸å£å¾æç»å° 2063.45ï¼å·®å¼æ£å¥½æ¯ 2026 å¹´ 1-6 æç»´åº¦ 4ï¼ç½çº¦è½¦ï¼â æåä»¶æ¯ Java ç°ç®ãæç»é¡µèµ°æ¯çå
¬å¼é¾ï¼ä¸¤å¥å£å¾ææ¶ï¼ç¬¬ 3 æ¥ççæ£æ¶å£ç¹ï¼ã |
| | | - æ¯çãä¸å£å¾æç»ãåå¸çº§ãåé
å乡巡游åºç§/ç½çº¦è½¦ãè¡å
¬å¼å¼é页ï¼`=å
¬äº¤!C13-å
¬äº¤!C15`ï¼åºæå `åºç§!`/`ç½çº¦è½¦!`ï¼ï¼åå¸çº§æ 0ãå
¨çè¡é ç¼åå¼ â éä¿®æ¯çå
¬å¼ä¸æ¬¡ã |
| | | |
| | | |
| | | ### 4. 第 3 æ¥æ¶å°¾ï¼ç¼ºæ°æ®ä¸åè¦çå®ç¨¿å¼ï¼13:30ï¼ |
| | | |
| | | ç¨æ·åé¦ãç¬ç«ãçæ_ä¸å£å¾æç»ã8 ææ²¡é®é¢äºï¼ä½ 1~6 æåè被æ¸
空ãåï¼è¿½åº**çæ£æ ¹å **ï¼ |
| | | |
| | | - `exportPassengerMidDetail()` 对æ©åæä»½ï¼>6 æï¼çæ»è¡å¼åæ¯ãç´æ¥ååºå
åç»´å计ãå 0 å°± setBlankãï¼ |
| | | è 1~6 æèµ° `keepCached()` æå
¬å¼æ¸
æç©ºæ ¼ â 表é¢ä¸ 7/8 æä¿®å¥½äºï¼å®é
䏿æ¯ççå®ç¨¿é¾è·¯ææäºã |
| | | - `fillMidCell()` åæ ·ãåºå
åå¼ä¸º 0 â setBlankãï¼äºæ¯ 2026-01~06 ç½çº¦è½¦å乡ï¼åºå
该 6 ä¸ªææ è®¢åã维度 4 æ æºï¼è¢«æ´çæ¸
ç©ºï¼ |
| | | è¿å¸¦æ»è¡ã累计ã忝å
¨éã |
| | | |
| | | **æ¹å¨ï¼`ReportExportService.java`ï¼4 å¤ï¼**ï¼ |
| | | |
| | | 1. `exportPassengerMidDetail()` æ»è¡å¼åï¼å æãæ©åæä»½æååºå
å计ãä¸ `keepCached` æ¸
å
¬å¼ä¸¤æ¡æè·¯ï¼**ä¸å¾ä¿ç模æ¿å
¬å¼**ï¼ç±æ¶å°¾éç®ååç¼åå¼ã |
| | | 2. `fillMidCell()`ï¼åºå
åå¼ä¸º 0ï¼è¯¥æè¯¥ç»´æ æºï¼æ¶**ç´æ¥ returnï¼ä¿çæ¯ç/å®ç¨¿åå¼**ââç»ä¸å空ãä¹ç»ä¸å 0ã |
| | | 3. `recalcWorkbookFormulas()`ï¼æ°å¢ `ev.setIgnoreMissingWorkbooks(true)`ã跨簿å
¬å¼ï¼`[1]åºç§!C13`ï¼å¨å¤é¨å·¥ä½ç°¿ç¼ºå¤±æ¶é»è®¤æå¼å¸¸ï¼ |
| | | ä¼è®©å¼ç¨å®çæ»è¡/累计è¿é失败ï¼è¡¨ç°ä¸ºãå
¬å¼å¨ã没æç¼åå¼ãï¼ï¼ç½® true åæ¹ç¨è¯¥æ ¼èªèº«ç¼åå¼åä¸è®¡ç®ã |
| | | 4. æ°å¢ `blankFutureMonthColumns()`ï¼æ¥è¡¨æä¹åçæä»½åï¼8 ææ¥è¡¨éç 9~12 æï¼**æ¸
æ°æ®æ ¼ãç表头**ï¼é¿å
å
éå
¬å¼ç®åºã9~12 æå
¨æ¯ 0ãçåæ°æ®ã |
| | | |
| | | **éè¦çº æ£ï¼åè¿æµè¯æ¥åï¼ä¹å¨æ¤ççï¼**ï¼æ©åå¤æãæ¯çä¸å£å¾æç»åå¸çº§å
¬å¼å¼é页ï¼`=å
¬äº¤!C13-å
¬äº¤!C15`ï¼ãæ¯**误å¤**ââ |
| | | 飿¯æ§å¶å°ä¸æä¹±ç é æçè¯¯è¯»ï¼æ¯ç/模æ¿çå®å
¬å¼æ¯æ£ç¡®ç `=[1]åºç§!C13-[1]åºç§!C15` / `=[1]ç½çº¦è½¦!C13-[1]ç½çº¦è½¦!C15`ï¼ |
| | | å°è´¦é¡µãæ»éâåå¸å
ãΣ17 å¸å· = 535.83 / 333.39ï¼ä¸æ¯çå®ç¨¿å
¨çè¡å®å
¨ä¸è´ã**æ¯çå
¬å¼ä¸éè¦ä¿®ï¼ä¹å"å¾
ä¿®æ¯ç"çç»è®ºä½åºã** |
| | | |
| | | ### 5. ç½çº¦è½¦è®¢åæ¥åï¼Word 2003 XMLï¼WordMLï¼å
¼å®¹å¯¼å
¥ï¼15:00ï¼ |
| | | |
| | | **ç¨æ·æ¥é**ï¼ãæ¹åç½ç»é¢çº¦åºç§æ±½è½¦2025å¹´09æåææ¥å.docxãæ¾å¨æ¡é¢å¯¼ä¸è¿å»ã |
| | | |
| | | **å®ä½**ï¼è¯¥æä»¶æ ¹æ¬ä¸æ¯ docx ââ æ¯ **Word 2003 XMLï¼WordML å¹³éº XMLï¼** 被æ¹åæ `.docx`ï¼æä»¶å¤´ `<?mso-application progid="Word.Document"?><w:wordDocument xmlns:w=".../word/2003/wordml">`ï¼3.1MB 纯 XMLã䏿¯ zip å
ï¼ï¼POI ç `XWPFDocument` åªè½è¯» OPC(zip) å
â æ `File is not a zip file`ãç管平å°/åäºé´æµè½¬çæ¥å常æ¯è¿ç§æ ¼å¼ï¼ä¼åå¤åºç°ã |
| | | |
| | | **æ¹å¨ï¼`DataImportService.java`ï¼**ï¼ |
| | | - `importWycOrderReport()` å
¥å£ææä»¶å¤´å
æ¢æ ¼å¼åæ´¾ï¼zipâdocxï¼`<w:wordDocument`+`wordml`â**æ°å¢ WordML DOM è§£æè·¯å¾**ï¼`D0CF11E0`âæç¡®æç¤ºã.doc 请å¦å为 docxãï¼å
¶å®âãæ æ³è¯å«ãï¼ |
| | | - æ°å¢ `isWordPackage()`ï¼zip 使 `word/document.xml`ï¼xlsx æ¹åï¼â 䏿æç¤ºï¼ä¸åæ XMLBeans è±æå æ ï¼ |
| | | - æ°å¢ `parseXmlSafely()`ï¼DOM è§£æå
³éå¤é¨å®ä½/DTDï¼é² XXEï¼ï¼ |
| | | - è¡¨æ ¼å¹é
æ½æä¸æ ¼å¼æ å
³ç `matchWycOrderTable()`ï¼docx ä¸ WordML 两æ¡è·¯å¾**å
±ç¨åä¸å¥è¡¨å¤´è¯å«/17 å¸å·åå¼/å计è¡é»è¾**ï¼ä¸ä¼å£å¾ååï¼ |
| | | - æ¥è¡¨æè¯å«æ½æ `periodOfParagraphs()`ï¼ä¸¤ç§æ ¼å¼å
±ç¨ã |
| | | |
| | | **éªè¯**ï¼8 æ¡ç¨ä¾å
¨é¨éè¿ï¼è§ãåè½æµè¯æ¥å_ç½çº¦è½¦è®¢åæ¥åWordMLå
¼å®¹å¯¼å
¥_2026-09-18ãï¼ã2025-09 å
¥åºï¼è®¢åå计 17,652,159ï¼æ¦æ± 8,076,610 / é»ç³ 676,644 / åå ° 1,048,593 / æ©æ½ 804,736 / æåº 1,424ï¼ä¸æ¥åéä»¶1 é项ä¸è´ï¼pin ä» `wyc_total_monthly` åæå¤å¶ãç docxï¼2026-08ï¼é导å¹çæ ååï¼`.doc`ãxlsx æ¹åã鿬æ¥å docx ä¸ç§è´ååç»åºä¸æå¯æä½æç¤ºã |
| | | |
| | | **æ°æ®ç¼ºå£å·²è¡¥é½ï¼éè¦ï¼**ï¼ç¨æ·å¨ 14:21~14:49 ä¹é´èªè¡å¯¼å
¥ 2026-01~06ï¼6 份ï¼ã2025-01ã2025-10~12ï¼2025-09 ç±æ¬æ¬¡ä¿®å¤åè¡¥å
¥ãç°å¨ **2025-01~12 + 2026-01~08 ç订åä¸ pin å
¨é¨é½å
¨**ãç´æ¥ææï¼ä¸å£å¾ç»´åº¦ 4 ç 1~6 æä»ãæ æºãå为ãå¯ç®ãï¼**ä¸å£å¾æåä»¶ä¸ä¸å£å¾æç»ä»¶ç累计å£å¾èªå¨å½ä¸**ï¼ä¸¤è
1-8 æç´¯è®¡å为 31528.0606ï¼æ¤åå·® 2063.45ï¼ã |
| | | |
| | | ## äºãæµè¯ç»ææè¦ |
| | | |
| | | è§ `docs/åè½æµè¯æ¥å/åè½æµè¯æ¥å_æ±æ»è¡¨å
¬å¼æ©é¡µä¸éç®_2026-09-18.md`ï¼8 æ¡æ£å + 4 æ¡è´å/è¾¹ç + 4 项å
¥åºæ½æ¥ï¼å
¨é¨éè¿ã |
| | | |
| | | - åå¸å®¢è¿ 36 æ ¼ãä¸å£å¾æç» 180 æ ¼ 8 æåè¡¥é½ï¼å
¬å¼ + ç¼åå¼ï¼ã |
| | | - å
¨çè¡ = Σ17 å¸å·ä¸æ¹ä¸è´ï¼å
¬äº¤ 12315.37ãåºç§ 5786.81ãç½çº¦è½¦ 4997.74ï¼ä¸åºå
`city_bus_monthly` 2026-08 åå¸å·æ±åé项对é½ï¼æ¦æ± 3856.83 / é»ç³ 879.12 æ½æ¥ä¸è´ï¼ã |
| | | - ä¸å£å¾æå K3 ç¼å 24481.7407 = æå·¥ Σ17 å¸å·ã |
| | | - åå½ï¼æ¹å¨ååéæ ¼å¯¹æ¯ï¼ä»
216 æ ¼ååï¼å
¨é¨è½å¨ç®æ 两页ï¼å
¶ä½ 17 页 0 å·®å¼ã |
| | | |
| | | ### 第 3 æ¥ï¼ä¸åï¼æµè¯ç»æ |
| | | |
| | | è§ `docs/åè½æµè¯æ¥å/åè½æµè¯æ¥å_ä¸å£å¾åç»´å£å¾ç»ä¸_2026-09-18.md`ï¼6 æ¡æ£å + 3 æ¡åå½ + 3 æ¡è´åè¾¹çï¼å
¨é¨éè¿ã |
| | | |
| | | - ç¬ç«ãçæ_ä¸å£å¾æç»ãå
¨ç 8 ææ»å®¢è¿é 4003.5701 = ç线 1646.4801 + å
¬äº¤ 1436.63 + åºç§å乡 493.90 + ç½çº¦è½¦å乡 426.56ï¼ |
| | | - 18 个å°åº Ãï¼7ã8 æï¼æ»è¡ = Σ 该å 4 ç»´è¡ï¼ç´¯è®¡åç¼åå¼ = Σ1-8 æï¼å
¨ç 31528.0607ï¼ï¼ |
| | | - åå½ï¼æ±æ»å¤§è¡¨ 17 页 0 æ ¼ååããçæ_ä¸å£å¾æåã0 æ ¼ååããçæ_ä¸å£å¾æç»ãä»
36 æ ¼ååï¼å
¨é¨æ¯ç®æ æ ¼ï¼ã |
| | | |
| | | |
| | | ### 第 3 æ¥æ¶å°¾ï¼13:30ï¼éªè¯ |
| | | |
| | | - ç¬ç«ãçæ_ä¸å£å¾æç»ãï¼18 å°åº à 12 个æï¼**æ»è¡ = Σ4 ç»´ã累计 = Σ1-8 æï¼ä¸ä¸è´æ° 0**ï¼9~12 ææ°æ®æ ¼å
¨ç©ºã表头ä¿çã |
| | | - 䏿±æ»å¤§è¡¨ãä¸å£å¾æç»ã页 1~8 æ **704 å¯¹æ ¼ 0 å·®å¼**ã |
| | | - å
¨ç 1-8 ææ»å®¢è¿éï¼3733.79 / 3777.83 / 3874.44 / 3959.25 / 4115.87 / 4034.99 / 4028.32 / 4003.57ï¼ |
| | | ç½çº¦è½¦å乡ï¼333.39 / 294.49 / 347.23 / 335.39 / 369.27 / 383.68 / 421.46 / 426.56ï¼ç´¯è®¡ AA5 = 31528.0607ãAA9 = 2911.47ã |
| | | - åå¸çº§ç½çº¦è½¦åä¹¡ï¼æ¦æ± 0ãé»ç³ 13.599765541547697ï¼æ²¿ç¨å®ç¨¿ï¼æªè¢«æ¸
空ï¼ã |
| | | - åå½ï¼æ±æ»å¤§è¡¨ 17 页 **0 æ ¼å·®å¼**ããçæ_ä¸å£å¾æåã**0 æ ¼å·®å¼**ï¼ |
| | | æç»ä»¶å·®å¼ä»
è½å¨ æ»è¡ / åºç§å乡 / ç½çº¦è½¦å乡 è¡çæä»½åä¸ AA 累计åï¼å±é¢æï¼ã |
| | | |
| | | ### ç½çº¦è½¦è®¢åæ¥å WordML 导å
¥ï¼15:00ï¼éªè¯ |
| | | |
| | | - 8 æ¡ç¨ä¾ï¼4 æ£å / 3 è´å / 1 è¾¹çï¼å
¨é¨éè¿ï¼WordML 2025-09 导å
¥æåãæ¥è¡¨æç空æ¶é æ é¢èªå¨è¯å«ãç docx å¹çæ ååã`.doc`/xlsx æ¹å/鿬æ¥å docx åç»åºä¸ææç¤ºã |
| | | - æ°æ®è¡¥é½åéè· 8 æå¯¼åºåå½ï¼ç¬ç«ãçæ_ä¸å£å¾æç»ãæ¥è¡¨æå
ä¸ä¸è´ 0ãæ¥è¡¨æåä»æå¼ 0ï¼ä¸æ±æ»å¤§è¡¨ãä¸å£å¾æç»ã页 **704 å¯¹æ ¼ 0 å·®å¼**ï¼å
¨ç 1-8 ææ»å®¢è¿é 3733.79â¦4003.57ï¼ç½çº¦è½¦å乡 333.39â¦426.56ï¼ç´¯è®¡ AA5=31528.0607ãAA9=2911.47ã |
| | | - æå件䏿ç»ä»¶ç´¯è®¡å£å¾ä¸è´ï¼å 31528.0606ï¼ï¼å·®å¼ 2063.45 æ¶å¤±ã |
| | | |
| | | ## ä¸ãéçé®é¢ä¸å¾
å |
| | | |
| | | 1. ~~ä¸å£å¾æå忝仿¯åæ»å¼~~ â **å·²ææ°å£å¾åå¼**ï¼M3=0.638 / Q3=0.2247ï¼ï¼ä½ä»ä¸ä¸å£å¾æç»ç 0.0581 ä¸èªæ´½ï¼å·®å¼ 2063.45 = ç½çº¦è½¦ 1-6 ææ æºï¼**æ¶å£åæ³è§ä¸æ¹"第 3 æ¥æ¶å£å»ºè®®"**ã |
| | | 2. ~~`loadMidClassMap()` 缺巡游åºç§ + ç½çº¦è½¦ä¸¤ç»´~~ â **已补**ï¼ç»´åº¦ 3ã4ï¼ï¼ç¬ç«ä¸å£å¾æç»åç»´é½å
¨ã |
| | | 3. ~~**æ¯ç缺é·å¾
ä¿®**ï¼ä¸å£å¾æç»åå¸çº§å
¬å¼å¼é页~~ â **误å¤ï¼å·²ä½åº**ï¼çå®å
¬å¼æ¯æ£ç¡®ç跨簿å¼ç¨ï¼æ¯çæ éä¿®æ¹ï¼å½æ¶ç"å¼é页"æ¯æ§å¶å°ä¸æä¹±ç 误读ã |
| | | 4. ~~**æ°æ®ç¼ºå£**ï¼2026-01~06 ç½çº¦è½¦è®¢åæªå
¥åº~~ â **已补é½**ï¼ç¨æ· 14:21~14:49 导å
¥ 2026-01~06 + 2025-01 + 2025-10~12ï¼2025-09 ç» WordML ä¿®å¤åè¡¥å
¥ï¼ãç°å¨ 2025-01~12 + 2026-01~08 订åé½å
¨ï¼ç»´åº¦ 4 å
¨æå¯ç®ï¼æåä»¶/æç»ä»¶å£å¾å½ä¸ãä»å»ºè®®è¡¥ä¸æ¡ã导å
¥æ¶è®¢ååå
¨ç©ºãçæ¾å¼æç¤ºï¼ã模æ¿_ç½çº¦è½¦è®¢ååå
¨çæ»é.xlsxãé£ç±»æä»¶ç°å¨ä¼é黿åï¼ã |
| | | 5. åºå
h2031ãå
¨çãè¡ â Σ17 å¸å·ï¼1-8 æ 27524.49 vs 24481.74ï¼å·® 3042.75ï¼ï¼ä¸å¡å£å¾é®é¢ï¼å»ºè®®ä¸å¡ä¾§æ ¸å¯¹ã |
| | | 6. æèµï¼æ¨¡æ¿é没æçæ°é¡¹ç®ä¸ä¼èªå¨æè¡ï¼æç»è¡¨èµéæ¸ éåç»è¡æªå
¥åºï¼éå `fund_channel`ï¼ï¼ååä¸åé¡¹ç®æªå¼¹çªã |
| | | 7. æèµä¸¤å¼ æç»è¡¨ï¼`Xæå®¢è¿ç«æèµæç»è¡¨` / `Xæç©æµç«åºæèµæç»`ï¼çæå¨æªåã |
| | | |
| | | ### 第 3 æ¥æ¶å£å»ºè®®ï¼å¾
ç¨æ·ææ¿ï¼ |
| | | |
| | | ä¸å让 Java åç®ä¸å¥ï¼æ¹ä¸º**䏿¡é¾è·¯åºæ°**ï¼æ¯çå
¬å¼é¾ï¼å
¨çè¡ = Σ17 å¸å·ã累计 = Σåæãæ´¾ç页跨页å¼ç¨ï¼+ å°è´¦é¡µåæ° + çææ¶å°¾éç®ã |
| | | |
| | | 1. å°è´¦é¡µï¼è´§è¿ / ç线å
车 / å
¬äº¤ / åºç§ / ç½çº¦è½¦ / 轨é轮渡ï¼åªå彿å¼ï¼ |
| | | 2. æ´¾ç页ï¼åå¸å®¢è¿ / ä¸å£å¾æç» / å
¬è·¯æ»å®¢è¿ / ä¸å£å¾å®¢è¿é / æåï¼**åªè¡¥å
¬å¼ + éç®ï¼ä¸åç¬åæ°**ï¼ |
| | | 3. åªææ¯ç鿬就æ¯ç¡¬ç¼ç æ°å¼çè¡ï¼ä¸å£å¾æç»çåå¸çº§"åé
å乡åºç§/ç½çº¦è½¦"ãå
¨çè¡ï¼æåç»´å£å¾åå¡«ï¼ |
| | | 4. ç¬ç«å¯¼åºä»¶ï¼çæ_ä¸å£å¾æç» / æå / å
¬è·¯æ
客åå¸å·ï¼æ¹ä¸ºç´æ¥åæ±æ»è¡¨å¯¹åºé¡µçå¼ï¼æå
±ç¨åä¸å£å¾å½æ°ï¼ |
| | | 5. ~~æ¯çéå¼é页çåå¸çº§å
¬å¼ä¿®ä¸æ¬¡~~ â **æ é**ï¼è¯¯å¤ï¼å·²ä½åºï¼ï¼ |
| | | 6. çæåè·"çæä»¶ vs æ¯çéç®"éæ ¼å彿¯å¯¹ï¼å·®å¼æ¸
åè½æ¥å¿ï¼ä½ä¸ºéªæ¶åºçº¿ï¼ |
| | | 7. åºå
缺失ï¼è¯¥æè¯¥ç»´æ æºï¼æ¶**ä¸å¾ä¿çæ¯çå®ç¨¿å¼ãä¸è¦ç**ââå·²å¨ç¬¬ 4 æ¡æ¹å¨ä¸è½å°ã |
| | | |
| | | ## åãæå¤©è®¡å |
| | | |
| | | 1. 第 3 æ¥æ¶å£ï¼æå件䏿ç»ä»¶å£å¾å½ä¸ï¼å·®å¼ 2063.45 = 2026 å¹´ 1-6 æç½çº¦è½¦å乡ï¼â æåä»¶æ¹åæ±æ»è¡¨åæºå¼ â åºå"çæä»¶ vs æ¯çéç®"éæ ¼åå½èæ¬ã |
| | | 2. ç½çº¦è½¦è®¢å导å
¥ç©ºåæç¤ºï¼é¡µé¢æç¡®æç¤º"该æè®¢ååä¸ºç©ºï¼æªåå
¥è®¢åæ°"ï¼ââæ°æ®è½å·²è¡¥é½ï¼ä½é黿å仿¯éæ£ã |
| | | 3. æèµ"æ°å¢é¡¹ç®æè¡ + åç»è¡å
¥åºï¼`fund_channel`ï¼"æ¹æ¡è½å°ï¼çç¨æ·å¯¹"模å"å£å¾çæå确认ï¼ã |
| | | 4. æèµä¸¤å¼ æç»è¡¨çæå¨ï¼`Xæå®¢è¿ç«æèµæç»è¡¨` / `Xæç©æµç«åºæèµæç»`ï¼ã |
| | | |
| | | --- |
| | | |
| | | ## äºãåæè¿½å ï¼è´§è¿ææ¥ãæç»å¨è§ä¼ä¸ãåå¸å· 1-8 æç´¯è®¡è¿è·ååæ¯ï¼æ¡é¢äº¤ä»ï¼ |
| | | |
| | | ### 5.1 éæ±ä¸å£å¾ |
| | | |
| | | ç¨æ·è¦æ±ï¼æè´§è¿ææ¥ãæç»å¨è§ä¼ä¸ãåå¸å· 1-8 æç´¯è®¡è¿è·å忝æ
嵿´çæ Excelï¼çæå°æ¡é¢ã |
| | | |
| | | - **æç»å¨è§ä¼ä¸** = 2026 å¹´ 1-8 æè¿ç» 8 个æå䏿¥ H203-2 ææ¥çä¼ä¸ï¼**636 å®¶**ï¼2026 å¹´åæä¸æ¥ä¼ä¸æ°å为 636ï¼å
¨æä¸è´ï¼ã |
| | | - **累计平åè¿è·** = 1-8 æç´¯è®¡è´§ç©å¨è½¬é ÷ 累计货è¿éï¼å æå¹³åï¼ã |
| | | - **忝** = 2026 å¹´ 1-8 æç´¯è®¡è¿è· ÷ 2025 å¹´ 1-8 æç´¯è®¡è¿è· â 1ï¼åªå¨**两年åæç»å¨è§ç 545 å®¶**ä¸è®¡ç®ï¼å¯æ¯å£å¾ï¼ã |
| | | |
| | | ### 5.2 æ°æ®ä¸äº§åº |
| | | |
| | | æ°æ®æºï¼`traffic_audit.h2032_enterprise_monthly`ï¼2025-01 ~ 2026-08ï¼13,056 æ¡ä¼ä¸çº§è®°å½ï¼ã |
| | | |
| | | 产åºï¼`C:\Users\éçæ´\Desktop\è´§è¿ææ¥_æç»å¨è§ä¼ä¸_åå¸å·1-8æç´¯è®¡è¿è·å忝_2026-09-18.xlsx`ï¼5 页ç¾ï¼è¯´æä¸å£å¾ / åå¸å·æ±æ» / åå¸å·åæ / ä¼ä¸æç» 636 è¡ / å£å¾æ ¡éªï¼ï¼çæèæ¬ `docs\å·¥å
·\æç»å¨è§ä¼ä¸ç´¯è®¡è¿è·çæ.py`ã |
| | | |
| | | ### 5.3 å
³é®ç»æ |
| | | |
| | | | å¸å· | æç»å¨è§(å®¶) | 1-8æç´¯è®¡å¹³åè¿è·(å
¬é) | 忝 | å¸å· | æç»å¨è§(å®¶) | 1-8æç´¯è®¡å¹³åè¿è·(å
¬é) | 忝 | |
| | | | --- | --- | --- | --- | --- | --- | --- | --- | |
| | | | æ¦æ±å¸ | 199 | 162.11 | +13.5% | é»åå¸ | 71 | 135.14 | +1.1% | |
| | | | é»ç³å¸ | 20 | 117.63 | +20.2% | å¸å®å¸ | 17 | 113.33 | â24.1% | |
| | | | åå °å¸ | 13 | 321.13 | â2.9% | éå·å¸ | 26 | 187.28 | â17.1% | |
| | | | å®æå¸ | 65 | 88.55 | +2.6% | æ©æ½å· | 4 | 130.11 | +10.3% | |
| | | | è¥é³å¸ | 81 | 274.50 | +8.4% | 仿¡å¸ | 2 | 65.61 | ä¸éç¨ | |
| | | | éå·å¸ | 6 | 38.15 | â59.0% | æ½æ±å¸ | 13 | 394.20 | +10.9% | |
| | | | èé¨å¸ | 40 | 281.41 | â4.7% | 天é¨å¸ | 4 | 61.02 | â54.6% | |
| | | | åæå¸ | 21 | 164.00 | â7.4% | ç¥åæ¶æåº | 2 | 57.68 | â49.1% | |
| | | | èå·å¸ | 52 | 324.47 | â4.7% | **å
¨ç** | **636** | **156.92** | **+2.9%** | |
| | | |
| | | - å
¨ç累计货è¿é 31399.82 ä¸å¨ã累计å¨è½¬é 4927161.77 ä¸å¨å
¬éï¼ä¸ã2026å¹´8æè§ä¸è´§ç©å¨è½¬éä¸å¹³åè¿è·åææ¥åã**å®å
¨ä¸è´**ï¼8 æå½æå
¨çå¹³åè¿è· 155.51 å
¬é亦ä¸åå¸å£å¾ä¸è´ã |
| | | - 累计è¿è·ææ¾æé¿çåªææ¦æ±ï¼+13.5%ï¼ãé»ç³ï¼+20.2%ï¼ï¼éå·ï¼â59.0%ï¼ã天é¨ï¼â54.6%ï¼ãæåºï¼â49.1%ï¼ãå¸å®ï¼â24.1%ï¼ãéå·ï¼â17.1%ï¼ä¸ºå¤§å¹
缩çï¼å»ºè®®ä¸å¡ä¾§å
³æ³¨ã |
| | | |
| | | ### 5.4 æµè¯ä¸é®é¢ |
| | | |
| | | ãåè½æµè¯æ¥å_è´§è¿ææ¥æç»å¨è§ä¼ä¸åå¸å·ç´¯è®¡è¿è·_2026-09-18.mdãï¼14 æ¡ç¨ä¾ï¼8 æ£å / 3 è¾¹ç / 3 è´åï¼å
¨é¨éè¿ï¼2026-01~07 éæè§ä¸è´§è¿éãå¨è½¬é䏿±æ»è¡¨ã è´§è¿ã页 14 项æ¯å¯¹ 0 å·®å¼ã |
| | | |
| | | - çæèæ¬è¡å·èªå¢éä½å¯¼è´è¡¨å¤´/æ«è¡è¢«è¦ç â 已修æ£å¹¶éè¡å¤æ ¸ï¼è¡¨å¤´ + 17 å¸å· + å计å
± 18 è¡ï¼ã |
| | | - æ¡é¢å¯æ¬ç¬¬ä¸ç为修æ£åæä»¶ â 已鿰忥ï¼SHA256 ä¸è´ã |
| | | |
| | | ### 5.5 å¾
å |
| | | |
| | | 1. ~~请ä¸å¡ç¡®è®¤ãæç»å¨è§ä¼ä¸ãå®ä¹~~ â **ç¨æ· 2026-09-18 已确认**ï¼æã2026 å¹´ 1-8 æè¿ç» 8 个æä¸æ¥ã= 636 å®¶ï¼äº¤ä»ä»¶æ éè°æ´ã |
| | | 2. 仿¡å¸ 2026 å¹´ 2 å®¶æç»å¨è§ä¼ä¸ 2025 å¹´ 1-8 ææ è¿ç»ä¸æ¥è®°å½ï¼åæ¯ç空ï¼å»ºè®®æ ¸å¯¹è¯¥å¸å·åå²ä¸æ¥ã |
| | | |
| | | ### 5.6 订æ£ï¼åæ¯åºæå£å¾ï¼v2ï¼17:0xï¼ |
| | | |
| | | ç¨æ·åé¦ã1-8 æç´¯è®¡è¿è·åæ¯ä¸å¯¹ããæ ¸æ¥å确认ï¼**v1 çåæ¯åºæåéäº**ã |
| | | |
| | | - æ±æ»è¡¨ãè´§è¿ã页 T åï¼ç´¯è®¡åæ¯ï¼å
¬å¼ = `=S7/SUM(V7,X7,Z7,AB7,AD7,AF7,AH7,AJ7)-1`ï¼åºææ¯ **2025 å¹´ 1-8 æå
¨é¨è§ä¸ä¼ä¸**ï¼å
¨ç 664 å®¶ï¼ï¼v1 ç¨çæ¯ã两年åæç»å¨è§ç 545 å®¶ãï¼å¯¼è´åæ¯ç³»ç»æ§åå°ã |
| | | - è¯æ®ï¼DB 2025 å¹´ 1-8 æ = 33994.4483 ä¸å¨ / 5102518.9463 ä¸å¨å
¬éï¼ä¸æ±æ»è¡¨ V7..AJ7ãV8..AJ8 ç¼åå¼**é项ä¸è´**ã |
| | | |
| | | | ææ | v1ï¼545 å®¶ï¼ | v2ï¼å®æ¹å
¨å£å¾ï¼ | å叿¥å | |
| | | | --- | --- | --- | --- | |
| | | | 累计货è¿é忝 | â7.96% | **â7.63%** | â7.63% | |
| | | | 累计å¨è½¬é忝 | â5.30% | **â3.44%** | â3.44% | |
| | | | å
¨ç 1-8 æç´¯è®¡å¹³åè¿è· | 158.18 / 153.73 = +2.90% | **156.92 / 150.10 = +4.54%** | â | |
| | | |
| | | - éç®å `åå¸å·æ±æ»` æ¹ä¸ºã2026 å
¨å£å¾ / 2025 å
¨å£å¾ / 忝ã䏿®µåï¼æ°å¢ `å£å¾å¯¹æ¯` 页并å两ç§å£å¾ï¼æ åºå·®å¼è¶
10 个ç¾åç¹çå¸å·ã |
| | | - ä¿®æ£åå¸å·åæ¯ï¼æ¦æ± +17.0%ãé»ç³ +35.3%ãè¥é³ +21.0%ã宿 +7.4%ãæ½æ± +5.6%ãéå· +4.9%ãæ©æ½ +1.2%ãèå· â0.2%ãé»å â0.3%ãåå ° â1.9%ãèé¨ â6.6%ãåæ â13.3%ãå¸å® â25.4%ãæåº â49.1%ãå¤©é¨ â54.6%ãéå· â63.1%ã仿¡ â89.1%ã |
| | | - 已忥æ¡é¢äº¤ä»ä»¶ï¼SHA256 ä¸è´ï¼ã |
| New file |
| | |
| | | # -*- coding: utf-8 -*- |
| | | """è´§è¿ææ¥ãæç»å¨è§ä¼ä¸ãåå¸å· 1-8 æç´¯è®¡è¿è·å忝 å°è´¦çæï¼v2ï¼åæ¯åºææ¹ä¸ºå®æ¹å
¨å£å¾ï¼ |
| | | |
| | | æ°æ®æºï¼traffic_audit.h2032_enterprise_monthlyï¼ãé路货ç©è¿è¾æåº¦ç产æ
åµãH203-2 ä¼ä¸ææ¥ï¼ |
| | | 导åºä»¶ _tmp_persist_scope.tsvï¼ä¼ä¸çº§ç´¯è®¡ï¼ã_tmp_persist_scope_monthly.tsvï¼ä¼ä¸çº§åæï¼ |
| | | å£å¾ï¼v2 修订ï¼ï¼ |
| | | · æç»å¨è§ä¼ä¸ = 2026 å¹´ 1-8 æè¿ç» 8 个æå䏿¥ææ¥çä¼ä¸ï¼636 å®¶ï¼ç¨æ· 2026-09-18 确认ï¼ï¼ |
| | | · 累计平åè¿è·ï¼å
¬éï¼= 累计货ç©å¨è½¬é ÷ 累计货è¿éï¼å æå¹³åï¼ï¼ |
| | | · 忝 = 2026 å¹´ 1-8 æç´¯è®¡å¼ ÷ 2025 å¹´ 1-8 æç´¯è®¡å¼ â 1ï¼**åºæä¸º 2025 å¹´ 1-8 æå
¨é¨è§ä¸ä¼ä¸ä¸æ¥æ°** |
| | | ï¼å
¨ç 664 å®¶ï¼ï¼ä¸æ±æ»è¡¨ãè´§è¿ã页 T å `=S/SUM(V7,X7,â¦,AJ7)-1` åä¸å£å¾ï¼ |
| | | v1 误ç¨ã两年åæç»å¨è§ç 545 å®¶ãä½åºæï¼å¯¼è´åæ¯åå°ï¼å·²ä¿®æ£ã |
| | | """ |
| | | import io, os |
| | | from openpyxl import Workbook |
| | | from openpyxl.styles import Font, PatternFill, Alignment, Border, Side |
| | | from openpyxl.utils import get_column_letter |
| | | |
| | | SRC = r'D:\ææ¡£\ChatGPT\traffic-audit\_tmp_persist_scope.tsv' |
| | | MONTHLY_SRC = r'D:\ææ¡£\ChatGPT\traffic-audit\_tmp_persist_scope_monthly.tsv' |
| | | OUT_DIR = r'D:\ææ¡£\ChatGPT\traffic-audit\outputs' |
| | | OUT = os.path.join(OUT_DIR, 'è´§è¿ææ¥_æç»å¨è§ä¼ä¸_åå¸å·1-8æç´¯è®¡è¿è·å忝_2026-09-18.xlsx') |
| | | |
| | | PROV = { |
| | | 'vol26': 31399.82, 'turn26': 4927161.77, # å·²åå¸ï¼2026 å¹´ 1-8 æç´¯è®¡ |
| | | 'vol25': 33994.45, 'turn25': 5102518.95, # æ±æ»è¡¨ãè´§è¿ã页 2025 å¹´ 1-8 æï¼åæ¯åºæï¼ |
| | | 'vol26_08': 3665.36, 'turn26_08': 570004.44, # å·²åå¸ï¼2026 å¹´ 8 æå½æ |
| | | 'yoy_vol': -0.0763, 'yoy_turn': -0.0344, # å·²åå¸ï¼1-8 æç´¯è®¡åæ¯ |
| | | } |
| | | |
| | | CITY_ORDER = ['æ¦æ±å¸', 'é»ç³å¸', 'åå °å¸', '宿å¸', 'è¥é³å¸', 'éå·å¸', 'èé¨å¸', 'åæå¸', 'èå·å¸', |
| | | 'é»åå¸', 'å¸å®å¸', 'éå·å¸', 'æ©æ½å·', '仿¡å¸', 'æ½æ±å¸', '天é¨å¸', 'ç¥åæ¶æåº'] |
| | | CITY = {'4201': 'æ¦æ±å¸', '4202': 'é»ç³å¸', '4203': 'åå °å¸', '4205': '宿å¸', '4206': 'è¥é³å¸', |
| | | '4207': 'éå·å¸', '4208': 'èé¨å¸', '4209': 'åæå¸', '4210': 'èå·å¸', '4211': 'é»åå¸', |
| | | '4212': 'å¸å®å¸', '4213': 'éå·å¸', '4228': 'æ©æ½å·', |
| | | '429004': '仿¡å¸', '429005': 'æ½æ±å¸', '429006': '天é¨å¸', '429021': 'ç¥åæ¶æåº'} |
| | | MONTHS26 = ['2026-%02d' % m for m in range(1, 9)] |
| | | |
| | | |
| | | def city_of(rc): |
| | | rc = (rc or '').strip() |
| | | return CITY[rc] if rc in CITY else CITY.get(rc[:4], 'æªè¯å«(%s)' % rc) |
| | | |
| | | |
| | | def num(x): |
| | | try: |
| | | return float(x) |
| | | except Exception: |
| | | return 0.0 |
| | | |
| | | |
| | | def dist(f, t): |
| | | return (t / f) if f else None |
| | | |
| | | |
| | | def growth(now, base): |
| | | return (now / base - 1) if (now is not None and base) else None |
| | | |
| | | |
| | | # ---------- 读ä¼ä¸çº§ç´¯è®¡æ°æ® ---------- |
| | | rows = [] |
| | | with io.open(SRC, 'r', encoding='utf-8') as f: |
| | | hdr = f.readline().rstrip('\r\n').split('\t') |
| | | for line in f: |
| | | p = line.rstrip('\r\n').split('\t') |
| | | if len(p) < len(hdr): |
| | | continue |
| | | d = dict(zip(hdr, p)) |
| | | if int(num(d['m26'])) != 8: |
| | | continue |
| | | rows.append(dict(city=city_of(d['rc']), rc=d['rc'], en=d['en'], ec=d['ec'], ucc=d['ucc'], |
| | | f26=num(d['f26']), t26=num(d['t26']), |
| | | f25=num(d['f25']), t25=num(d['t25']), cmp=(int(num(d['m25'])) == 8))) |
| | | |
| | | by_city = {} |
| | | for r in rows: |
| | | c = by_city.setdefault(r['city'], dict(n=0, f26=0.0, t26=0.0)) |
| | | c['n'] += 1 |
| | | c['f26'] += r['f26']; c['t26'] += r['t26'] |
| | | |
| | | tot = dict(n=0, f26=0.0, t26=0.0) |
| | | for c in by_city.values(): |
| | | for k in tot: |
| | | tot[k] += c[k] |
| | | by_city_cmp = {} |
| | | for r in rows: |
| | | if not r['cmp']: |
| | | continue |
| | | c = by_city_cmp.setdefault(r['city'], dict(n=0, f26c=0.0, t26c=0.0, f25c=0.0, t25c=0.0)) |
| | | c['n'] += 1 |
| | | c['f26c'] += r['f26']; c['t26c'] += r['t26'] |
| | | c['f25c'] += r['f25']; c['t25c'] += r['t25'] |
| | | tot_cmp = dict(n=0, f26c=0.0, t26c=0.0, f25c=0.0, t25c=0.0) |
| | | for c in by_city_cmp.values(): |
| | | for k in tot_cmp: |
| | | tot_cmp[k] += c[k] |
| | | unknown = sorted(k for k in by_city if k.startswith('æªè¯å«')) |
| | | persist_names = set(r['en'] for r in rows) |
| | | |
| | | # ---------- 读ä¼ä¸çº§åææ°æ® ---------- |
| | | cust = {} |
| | | with io.open(MONTHLY_SRC, 'r', encoding='utf-8') as f: |
| | | for line in f: |
| | | p = line.rstrip('\r\n').split('\t') |
| | | if len(p) < 5 or p[0] == 'report_period': |
| | | continue |
| | | per, rc, en, fr, tu = p[0], p[1], p[2], p[3], p[4] |
| | | cust.setdefault((per, city_of(rc)), {})[en] = (num(fr), num(tu)) |
| | | |
| | | |
| | | def city_month(period, city, names=None): |
| | | d = cust.get((period, city)) |
| | | if not d: |
| | | return None, 0.0, 0.0 |
| | | fr = tu = 0.0 |
| | | for en, v in d.items(): |
| | | if names is None or en in names: |
| | | fr += v[0]; tu += v[1] |
| | | return dist(fr, tu), fr, tu |
| | | |
| | | |
| | | # ---------- 2025 å¹´ 1-8 æå
¨å£å¾åºæ ---------- |
| | | B25 = {} |
| | | for (per, city), d in cust.items(): |
| | | if not ('2025-01' <= per <= '2025-08'): |
| | | continue |
| | | c = B25.setdefault(city, dict(ents=set(), f=0.0, t=0.0)) |
| | | for en, v in d.items(): |
| | | c['ents'].add(en) |
| | | c['f'] += v[0]; c['t'] += v[1] |
| | | tot25 = dict(ents=set(), f=0.0, t=0.0) |
| | | for c in B25.values(): |
| | | tot25['ents'] |= c['ents'] |
| | | tot25['f'] += c['f']; tot25['t'] += c['t'] |
| | | |
| | | # ---------- æ ·å¼ ---------- |
| | | THIN = Side(style='thin', color='BFBFBF') |
| | | BORDER = Border(left=THIN, right=THIN, top=THIN, bottom=THIN) |
| | | HDR_FILL = PatternFill('solid', fgColor='DDEBF7') |
| | | TOT_FILL = PatternFill('solid', fgColor='FFF2CC') |
| | | TITLE_FILL = PatternFill('solid', fgColor='1F4E79') |
| | | CT = Alignment(horizontal='center', vertical='center', wrap_text=True) |
| | | LT = Alignment(horizontal='left', vertical='center', wrap_text=True) |
| | | RT = Alignment(horizontal='right', vertical='center') |
| | | NF2, NF1, NFP = '#,##0.00', '#,##0.0', '0.00%' |
| | | |
| | | wb = Workbook() |
| | | |
| | | # ---------------- Sheet1 说æä¸å£å¾ ---------------- |
| | | ws = wb.active |
| | | ws.title = '说æä¸å£å¾' |
| | | ws.sheet_view.showGridLines = False |
| | | ws.column_dimensions['A'].width = 16 |
| | | ws.column_dimensions['B'].width = 106 |
| | | t = ws.cell(1, 1, 'è´§è¿ææ¥ãæç»å¨è§ä¼ä¸ãåå¸å· 1-8 æç´¯è®¡è¿è·å忝æ
åµè¡¨') |
| | | t.font = Font(bold=True, size=15, color='FFFFFF') |
| | | t.fill = TITLE_FILL |
| | | t.alignment = Alignment(horizontal='center', vertical='center') |
| | | ws.merge_cells(start_row=1, start_column=1, end_row=1, end_column=2) |
| | | ws.row_dimensions[1].height = 30 |
| | | |
| | | info = [ |
| | | ('æ°æ®æ¥æº', 'ç³»ç»æ°æ®åº traffic_audit.h2032_enterprise_monthlyãé路货ç©è¿è¾æåº¦ç产æ
åµãï¼H203-2ï¼ä¼ä¸ææ¥ï¼' |
| | | 'å 2025 å¹´ 1 æâ2026 å¹´ 8 æå
¨é¨ä¼ä¸çº§ä¸æ¥è®°å½ã'), |
| | | ('æç»å¨è§ä¼ä¸', '2026 å¹´ 1â8 æè¿ç» 8 个æå䏿¥ææ¥çä¼ä¸ï¼å
± %d å®¶ï¼2026 å¹´åæä¸æ¥ä¼ä¸æ°å为 636 å®¶ï¼å
¨æä¸è´ï¼' |
| | | 'å£å¾ç»ç¨æ· 2026-09-18 确认ï¼ã' % tot['n']), |
| | | ('累计è¿è·å£å¾', '累计平åè¿è·ï¼å
¬éï¼= 1â8 æç´¯è®¡è´§ç©å¨è½¬é ÷ 1â8 æç´¯è®¡è´§è¿éï¼å æå¹³åï¼ãæºè¡¨åä½ä¸ºå¨ãå¨å
¬éï¼' |
| | | 'æ¬è¡¨æç®ä¸ºä¸å¨ãä¸å¨å
¬éï¼æ¯å¼ä¸åã'), |
| | | ('忝å£å¾', '忝 = 2026 å¹´ 1â8 æç´¯è®¡å¼ ÷ 2025 å¹´ 1â8 æç´¯è®¡å¼ â 1ã**åºæä¸º 2025 å¹´ 1â8 æå
¨é¨è§ä¸ä¼ä¸ä¸æ¥æ°**' |
| | | 'ï¼å
¨ç %d å®¶ï¼ï¼ä¸æ±æ»è¡¨ãè´§è¿ã页 T åå
¬å¼ =S/SUM(V7,X7,â¦,AJ7)-1 åä¸å£å¾ï¼å¯ä¸å叿¥åç´æ¥å¯¹é½ï¼' |
| | | 'å
¨ç累计货è¿é忝 â7.63%%ãå¨è½¬é忝 â3.44%%ãå¹³åè¿è·åæ¯ +4.54%%ã' % len(tot25['ents'])), |
| | | ('å
¨çå计', 'ä¸å¾ä¸º 17 个å¸å·ä¹åï¼ä¸å«è·¨å¸å·éå å£å¾ï¼ã'), |
| | | ('æ¥è¡¨æ', 'æ¬æç´¯è®¡ 2026-01-01â2026-08-31ï¼åæ¯åºæ 2025-01-01â2025-08-31ã'), |
| | | ('页ç¾è¯´æ', 'ãåå¸å·æ±æ»ãæå¸å·æ±æ» 1-8 æç´¯è®¡è¿è·ä¸åæ¯ï¼ãåå¸å·åæã为åå¸å· 2026 å¹´éæå¹³åè¿è·ï¼' |
| | | 'ãä¼ä¸æç»ã为 636 å®¶æç»å¨è§ä¼ä¸éæ·æ°æ®ï¼ä¼ä¸çº§åæ¯ä»
对两年åè¿ç»ä¸æ¥ç 545 å®¶ç»åºï¼ï¼' |
| | | 'ãå£å¾å¯¹æ¯ãå¹¶å宿¹å£å¾ä¸åä¼ä¸å£å¾ç忝ï¼ãå£å¾æ ¡éªã为æç»ä¸æ±æ»å¯¹è´¦ï¼ä»¥å䏿±æ»è¡¨ãå·²å叿¥åçæ¯å¯¹ã'), |
| | | ('注æäºé¡¹', 'â æ 5 å®¶ä¼ä¸ 1â8 æææ¥è´§è¿éãå¨è½¬éå为 0ï¼è®¡å
¥ä¼ä¸æ°ä½ä¸å½±åè¿è·ï¼' |
| | | 'â¡ æ¦æ±ç³å交éè¿è¾æéå
¬å¸ãæ¹åæ·é¾äº¤éè¿ä¸æéå
¬å¸ 2026 å¹´ 1 æçå°åºç ä¸å
¶åæä»½ä¸åï¼420100 â 420107 / 420103ï¼ï¼' |
| | | 'ä½å屿¦æ±å¸ï¼ä¸å½±åå¸å·å½éï¼â¢ 累计货è¿é为 0 çä¼ä¸ç´¯è®¡è¿è·ç空ã'), |
| | | ('çæ¬', 'v2ï¼2026-09-18ï¼ï¼ä¿®æ£åæ¯åºæå£å¾ââv1 误ç¨ã两年åæç»å¨è§ç 545 å®¶ãä½åºæï¼å
¨ç累计è¿è·åæ¯ç®å¾ +2.90%%ï¼' |
| | | '宿¹å£å¾åºä¸º +4.54%%ã'), |
| | | ('çææ¶é´', '2026-09-18'), |
| | | ] |
| | | r = 3 |
| | | for k, v in info: |
| | | a = ws.cell(r, 1, k); a.font = Font(bold=True); a.alignment = LT; a.border = BORDER |
| | | b = ws.cell(r, 2, v); b.alignment = LT; b.border = BORDER |
| | | r += 1 |
| | | |
| | | # ---------------- Sheet2 åå¸å·æ±æ» ---------------- |
| | | ws2 = wb.create_sheet('åå¸å·æ±æ»') |
| | | heads = ['åºå·', 'å¸å·', '2026å¹´1-8ææç»å¨è§ä¼ä¸æ°(å®¶)', '2025å¹´1-8æè§ä¸ä¼ä¸æ°(å®¶)', |
| | | '2026å¹´1-8æç´¯è®¡è´§è¿é(ä¸å¨)', '2026å¹´1-8æç´¯è®¡è´§ç©å¨è½¬é(ä¸å¨å
¬é)', '2026å¹´1-8æç´¯è®¡å¹³åè¿è·(å
Ž)', |
| | | '2025å¹´1-8æç´¯è®¡è´§è¿é(ä¸å¨)', '2025å¹´1-8æç´¯è®¡è´§ç©å¨è½¬é(ä¸å¨å
¬é)', '2025å¹´1-8æç´¯è®¡å¹³åè¿è·(å
Ž)', |
| | | '累计平åè¿è·åæ¯(%)', '累计货è¿é忝(%)', '累计货ç©å¨è½¬é忝(%)'] |
| | | widths = [6, 14, 20, 18, 20, 24, 20, 20, 24, 20, 15, 15, 17] |
| | | ws2.cell(1, 1, 'è´§è¿ææ¥æç»å¨è§ä¼ä¸åå¸å· 1-8 æç´¯è®¡å¹³åè¿è·å忝æ
åµï¼åæ¯åºæï¼2025 å¹´ 1-8 æå
¨é¨è§ä¸ä¼ä¸ï¼').font = Font(bold=True, size=13, color='FFFFFF') |
| | | ws2.cell(1, 1).fill = TITLE_FILL |
| | | ws2.cell(1, 1).alignment = Alignment(horizontal='center', vertical='center') |
| | | ws2.merge_cells(start_row=1, start_column=1, end_row=1, end_column=len(heads)) |
| | | ws2.row_dimensions[1].height = 26 |
| | | ws2.cell(2, 1, '注ï¼ç¬¬ 5â7 å为 2026 å¹´æç»å¨è§ä¼ä¸ï¼636 å®¶ï¼ç´¯è®¡å¼ï¼ç¬¬ 8â10 å为 2025 å¹´ 1-8 æå
¨é¨è§ä¸ä¼ä¸ï¼å
¨ç 664 å®¶ï¼ç´¯è®¡å¼ï¼' |
| | | '峿±æ»è¡¨ãè´§è¿ã页 T å忝å
¬å¼çåºæï¼ç¬¬ 11â13 å忝å£å¾ä¸å叿¥åä¸è´ã') |
| | | ws2.cell(2, 1).font = Font(size=9, italic=True, color='808080') |
| | | ws2.merge_cells(start_row=2, start_column=1, end_row=2, end_column=len(heads)) |
| | | for j, h in enumerate(heads, 1): |
| | | c = ws2.cell(3, j, h) |
| | | c.font = Font(bold=True); c.fill = HDR_FILL; c.alignment = CT; c.border = BORDER |
| | | ws2.column_dimensions[get_column_letter(j)].width = widths[j - 1] |
| | | ws2.row_dimensions[3].height = 46 |
| | | |
| | | rr = 3 |
| | | idx = 0 |
| | | for city in CITY_ORDER: |
| | | c = by_city.get(city) |
| | | if not c or c['n'] == 0: |
| | | continue |
| | | idx += 1 |
| | | rr += 1 |
| | | b = B25.get(city, dict(ents=set(), f=0.0, t=0.0)) |
| | | d26, d25 = dist(c['f26'], c['t26']), dist(b['f'], b['t']) |
| | | vals = [idx, city, c['n'], len(b['ents']), |
| | | c['f26'] / 10000.0, c['t26'] / 10000.0, d26, |
| | | b['f'] / 10000.0, b['t'] / 10000.0, d25, |
| | | growth(d26, d25), growth(c['f26'], b['f']), growth(c['t26'], b['t'])] |
| | | for j, v in enumerate(vals, 1): |
| | | cell = ws2.cell(rr, j, v) |
| | | cell.border = BORDER |
| | | cell.alignment = CT if j <= 4 else RT |
| | | if j in (5, 6, 7, 8, 9, 10): |
| | | cell.number_format = NF2 |
| | | elif j in (11, 12, 13): |
| | | cell.number_format = NFP |
| | | rr += 1 |
| | | d26p, d25p = dist(tot['f26'], tot['t26']), dist(tot25['f'], tot25['t']) |
| | | vals = ['', 'å
¨çå计', tot['n'], len(tot25['ents']), |
| | | tot['f26'] / 10000.0, tot['t26'] / 10000.0, d26p, |
| | | tot25['f'] / 10000.0, tot25['t'] / 10000.0, d25p, |
| | | growth(d26p, d25p), growth(tot['f26'], tot25['f']), growth(tot['t26'], tot25['t'])] |
| | | for j, v in enumerate(vals, 1): |
| | | cell = ws2.cell(rr, j, v) |
| | | cell.border = BORDER |
| | | cell.fill = TOT_FILL |
| | | cell.font = Font(bold=True) |
| | | cell.alignment = CT if j <= 4 else RT |
| | | if j in (5, 6, 7, 8, 9, 10): |
| | | cell.number_format = NF2 |
| | | elif j in (11, 12, 13): |
| | | cell.number_format = NFP |
| | | ws2.freeze_panes = 'C4' |
| | | |
| | | # ---------------- Sheet3 åå¸å·åæ ---------------- |
| | | ws3 = wb.create_sheet('åå¸å·åæ') |
| | | h3 = ['åºå·', 'å¸å·', 'æç»å¨è§ä¼ä¸æ°(å®¶)'] + ['%sæå¹³åè¿è·(å
Ž)' % m for m in range(1, 9)] + \ |
| | | ['2026å¹´1-8æç´¯è®¡å¹³åè¿è·(å
¬é)', '2025å¹´1-8æç´¯è®¡å¹³åè¿è·(å
¬é)', '累计è¿è·åæ¯(%)'] |
| | | w3 = [6, 14, 18] + [15] * 8 + [24, 24, 15] |
| | | ws3.cell(1, 1, 'åå¸å· 2026 å¹´éæå¹³åè¿è·ï¼æç»å¨è§ä¼ä¸å£å¾ï¼åæ¯åºæï¼2025 å¹´ 1-8 æå
¨é¨è§ä¸ä¼ä¸ï¼').font = Font(bold=True, size=13, color='FFFFFF') |
| | | ws3.cell(1, 1).fill = TITLE_FILL |
| | | ws3.cell(1, 1).alignment = Alignment(horizontal='center', vertical='center') |
| | | ws3.merge_cells(start_row=1, start_column=1, end_row=1, end_column=len(h3)) |
| | | ws3.row_dimensions[1].height = 26 |
| | | for j, h in enumerate(h3, 1): |
| | | c = ws3.cell(2, j, h) |
| | | c.font = Font(bold=True); c.fill = HDR_FILL; c.alignment = CT; c.border = BORDER |
| | | ws3.column_dimensions[get_column_letter(j)].width = w3[j - 1] |
| | | ws3.row_dimensions[2].height = 40 |
| | | |
| | | rr = 2 |
| | | idx = 0 |
| | | for city in CITY_ORDER: |
| | | c = by_city.get(city) |
| | | if not c or c['n'] == 0: |
| | | continue |
| | | idx += 1 |
| | | rr += 1 |
| | | b = B25.get(city, dict(ents=set(), f=0.0, t=0.0)) |
| | | d26, d25 = dist(c['f26'], c['t26']), dist(b['f'], b['t']) |
| | | vals = [idx, city, c['n']] + [city_month(p, city, persist_names)[0] for p in MONTHS26] + \ |
| | | [d26, d25, growth(d26, d25)] |
| | | for j, v in enumerate(vals, 1): |
| | | cell = ws3.cell(rr, j, v) |
| | | cell.border = BORDER |
| | | cell.alignment = CT if j <= 3 else RT |
| | | if j >= 4: |
| | | cell.number_format = NFP if j == 14 else NF2 |
| | | rr += 1 |
| | | vals = ['', 'å
¨çå计', tot['n']] + [city_month(p, None)[0] for p in MONTHS26] + \ |
| | | [d26p, d25p, growth(d26p, d25p)] |
| | | for j, v in enumerate(vals, 1): |
| | | cell = ws3.cell(rr, j, v) |
| | | cell.border = BORDER |
| | | cell.fill = TOT_FILL |
| | | cell.font = Font(bold=True) |
| | | cell.alignment = CT if j <= 3 else RT |
| | | if j >= 4: |
| | | cell.number_format = NFP if j == 14 else NF2 |
| | | ws3.freeze_panes = 'D3' |
| | | |
| | | # ---------------- Sheet4 ä¼ä¸æç» ---------------- |
| | | ws4 = wb.create_sheet('ä¼ä¸æç»') |
| | | h4 = ['åºå·', 'å¸å·', 'ä¼ä¸åç§°', 'ä¼ä¸ä»£ç ', 'ç»ä¸ç¤¾ä¼ä¿¡ç¨ä»£ç ', |
| | | '2026å¹´1-8æè´§è¿é(ä¸å¨)', '2026å¹´1-8æå¨è½¬é(ä¸å¨å
¬é)', '2026å¹´1-8æç´¯è®¡å¹³åè¿è·(å
Ž)', |
| | | '2025å¹´1-8æè´§è¿é(ä¸å¨)', '2025å¹´1-8æå¨è½¬é(ä¸å¨å
¬é)', '2025å¹´1-8æç´¯è®¡å¹³åè¿è·(å
Ž)', |
| | | 'å¹³åè¿è·åæ¯(%)', 'æ¯å¦ä¸¤å¹´åæç»å¨è§'] |
| | | w4 = [6, 12, 42, 22, 24, 20, 24, 22, 20, 24, 22, 14, 18] |
| | | ws4.cell(1, 1, 'æç»å¨è§ä¼ä¸éæ·ç´¯è®¡å¹³åè¿è·ï¼2026 å¹´ 1-8 æï¼åæå¼ä¸åæ¯ä»
对两年åæç»å¨è§ç 545 å®¶ç»åºï¼').font = Font(bold=True, size=13, color='FFFFFF') |
| | | ws4.cell(1, 1).fill = TITLE_FILL |
| | | ws4.cell(1, 1).alignment = Alignment(horizontal='center', vertical='center') |
| | | ws4.merge_cells(start_row=1, start_column=1, end_row=1, end_column=len(h4)) |
| | | ws4.row_dimensions[1].height = 26 |
| | | for j, h in enumerate(h4, 1): |
| | | c = ws4.cell(2, j, h) |
| | | c.font = Font(bold=True); c.fill = HDR_FILL; c.alignment = CT; c.border = BORDER |
| | | ws4.column_dimensions[get_column_letter(j)].width = w4[j - 1] |
| | | ws4.row_dimensions[2].height = 40 |
| | | |
| | | order = {c: i for i, c in enumerate(CITY_ORDER)} |
| | | rows_sorted = sorted(rows, key=lambda x: (order.get(x['city'], 99), -(x['t26']))) |
| | | rr = 2 |
| | | for i, x in enumerate(rows_sorted, 1): |
| | | rr += 1 |
| | | d26, d25 = dist(x['f26'], x['t26']), dist(x['f25'], x['t25']) |
| | | vals = [i, x['city'], x['en'], x['ec'], x['ucc'], |
| | | x['f26'] / 10000.0, x['t26'] / 10000.0, d26, |
| | | (x['f25'] / 10000.0) if x['cmp'] else None, |
| | | (x['t25'] / 10000.0) if x['cmp'] else None, |
| | | d25 if x['cmp'] else None, |
| | | growth(d26, d25) if x['cmp'] else None, |
| | | 'æ¯' if x['cmp'] else 'å¦'] |
| | | for j, v in enumerate(vals, 1): |
| | | cell = ws4.cell(rr, j, v) |
| | | cell.border = BORDER |
| | | cell.alignment = LT if j in (3, 4, 5) else (CT if j in (1, 2, 13) else RT) |
| | | if j in (6, 7, 8, 9, 10, 11): |
| | | cell.number_format = NF2 |
| | | elif j == 12: |
| | | cell.number_format = NFP |
| | | if j == 12 and isinstance(v, float) and v > 0.5: |
| | | cell.font = Font(color='C00000', bold=True) |
| | | ws4.freeze_panes = 'D3' |
| | | ws4.auto_filter.ref = 'A2:M%d' % rr |
| | | |
| | | # ---------------- Sheet5 å£å¾å¯¹æ¯ ---------------- |
| | | ws6 = wb.create_sheet('å£å¾å¯¹æ¯') |
| | | h6 = ['åºå·', 'å¸å·', '2026å¹´1-8æç´¯è®¡å¹³åè¿è·(å
¬é)\n[æç»å¨è§ä¼ä¸636å®¶]', |
| | | '2025å¹´1-8æç´¯è®¡å¹³åè¿è·(å
¬é)\n[å
¨é¨è§ä¸ä¼ä¸]', '宿¹å£å¾åæ¯(%)', |
| | | '2025å¹´1-8æç´¯è®¡å¹³åè¿è·(å
¬é)\n[åä¼ä¸545å®¶]', 'åä¼ä¸å£å¾åæ¯(%)', '两è
å·®å¼(ç¾åç¹)', '说æ'] |
| | | w6 = [6, 14, 26, 24, 15, 24, 15, 16, 46] |
| | | ws6.cell(1, 1, '两ç§åæ¯å£å¾å¯¹æ¯ï¼å®æ¹å£å¾ = 䏿±æ»è¡¨ãè´§è¿ã页 T åä¸è´ï¼åä¼ä¸å£å¾ = ä»
两年åæç»å¨è§ä¼ä¸ï¼').font = Font(bold=True, size=13, color='FFFFFF') |
| | | ws6.cell(1, 1).fill = TITLE_FILL |
| | | ws6.cell(1, 1).alignment = Alignment(horizontal='center', vertical='center') |
| | | ws6.merge_cells(start_row=1, start_column=1, end_row=1, end_column=len(h6)) |
| | | ws6.row_dimensions[1].height = 26 |
| | | ws6.cell(2, 1, '注ï¼äº¤ä»ä¸»è¡¨ï¼åå¸å·æ±æ»ï¼éç¨å®æ¹å£å¾ï¼æ¬é¡µä¸¤ä¸ªå£å¾å¹¶åï¼å·®å¼å¤§çå¸å·å¤ä¸ºä¸¤å¹´é´è§ä¸ä¼ä¸åååå¨ï¼åäº§ãæ°å¢ãæåï¼æè´ï¼ä¾ä¸å¡æ ¸å¯¹åèã') |
| | | ws6.cell(2, 1).font = Font(size=9, italic=True, color='808080') |
| | | ws6.merge_cells(start_row=2, start_column=1, end_row=2, end_column=len(h6)) |
| | | for j, h in enumerate(h6, 1): |
| | | c = ws6.cell(3, j, h) |
| | | c.font = Font(bold=True); c.fill = HDR_FILL; c.alignment = CT; c.border = BORDER |
| | | ws6.column_dimensions[get_column_letter(j)].width = w6[j - 1] |
| | | ws6.row_dimensions[3].height = 48 |
| | | |
| | | rr = 3 |
| | | idx = 0 |
| | | for city in CITY_ORDER: |
| | | c = by_city.get(city) |
| | | if not c or c['n'] == 0: |
| | | continue |
| | | idx += 1 |
| | | rr += 1 |
| | | b = B25.get(city, dict(ents=set(), f=0.0, t=0.0)) |
| | | g = by_city_cmp.get(city) |
| | | d26, d25 = dist(c['f26'], c['t26']), dist(b['f'], b['t']) |
| | | g_off = growth(d26, d25) |
| | | if g: |
| | | dc26, dc25 = dist(g['f26c'], g['t26c']), dist(g['f25c'], g['t25c']) |
| | | g_same = growth(dc26, dc25) |
| | | else: |
| | | dc25, g_same = None, None |
| | | diff = (g_off - g_same) if (g_off is not None and g_same is not None) else None |
| | | note = '' |
| | | if diff is not None and abs(diff) > 0.10: |
| | | note = '两å£å¾å·®å¼è¶
10 个ç¾åç¹ï¼ä¸»è¦å 两年è§ä¸ä¼ä¸åååå¨ï¼å»ºè®®æ ¸å¯¹è¯¥å¸å·ä¼ä¸å卿
åµ' |
| | | vals = [idx, city, d26, d25, g_off, dc25, g_same, (diff * 100 if diff is not None else None), note] |
| | | for j, v in enumerate(vals, 1): |
| | | cell = ws6.cell(rr, j, v) |
| | | cell.border = BORDER |
| | | cell.alignment = LT if j in (1, 9) else (CT if j == 2 else RT) |
| | | if j in (3, 4, 6): |
| | | cell.number_format = NF2 |
| | | elif j in (5, 7): |
| | | cell.number_format = NFP |
| | | elif j == 8: |
| | | cell.number_format = NF1 |
| | | rr += 1 |
| | | g_cmp = growth(dist(tot_cmp['f26c'], tot_cmp['t26c']), dist(tot_cmp['f25c'], tot_cmp['t25c'])) |
| | | vals = ['', 'å
¨çå计', d26p, d25p, growth(d26p, d25p), dist(tot_cmp['f25c'], tot_cmp['t25c']), g_cmp, |
| | | (growth(d26p, d25p) - g_cmp) * 100 if g_cmp is not None else None, ''] |
| | | for j, v in enumerate(vals, 1): |
| | | cell = ws6.cell(rr, j, v) |
| | | cell.border = BORDER |
| | | cell.fill = TOT_FILL |
| | | cell.font = Font(bold=True) |
| | | cell.alignment = CT if j == 2 else RT |
| | | if j in (3, 4, 6): |
| | | cell.number_format = NF2 |
| | | elif j in (5, 7): |
| | | cell.number_format = NFP |
| | | elif j == 8: |
| | | cell.number_format = NF1 |
| | | ws6.freeze_panes = 'C4' |
| | | |
| | | # ---------------- Sheet5 å£å¾æ ¡éª ---------------- |
| | | ws5 = wb.create_sheet('å£å¾æ ¡éª') |
| | | ws5.sheet_view.showGridLines = False |
| | | ws5.column_dimensions['A'].width = 46 |
| | | for col, w in (('B', 20), ('C', 20), ('D', 14), ('E', 46)): |
| | | ws5.column_dimensions[col].width = w |
| | | ws5.cell(1, 1, 'å£å¾æ ¡éªä¸å¯¹è´¦').font = Font(bold=True, size=13, color='FFFFFF') |
| | | ws5.cell(1, 1).fill = TITLE_FILL |
| | | ws5.merge_cells(start_row=1, start_column=1, end_row=1, end_column=5) |
| | | sum_f = sum(r['f26'] for r in rows) / 10000.0 |
| | | sum_t = sum(r['t26'] for r in rows) / 10000.0 |
| | | aug_f = sum(v[0] for c in CITY_ORDER for en, v in cust.get(('2026-08', c), {}).items() if en in persist_names) / 10000.0 |
| | | aug_t = sum(v[1] for c in CITY_ORDER for en, v in cust.get(('2026-08', c), {}).items() if en in persist_names) / 10000.0 |
| | | chk = [ |
| | | ('æ ¡éªé¡¹', 'æ¬è¡¨æ°å¼', '对ç
§æ°å¼', 'å·®å¼', '说æ'), |
| | | ('æç»è¡¨ä¼ä¸æ° = æ±æ»è¡¨ä¼ä¸æ°', len(rows), tot['n'], len(rows) - tot['n'], '636 å®¶æç»å¨è§ä¼ä¸éæ·ä¸è¡'), |
| | | ('æç»è¡¨è´§è¿éå计(ä¸å¨)', round(sum_f, 2), round(tot['f26'] / 10000.0, 2), round(sum_f - tot['f26'] / 10000.0, 2), 'æç»æ±å = 17 å¸å·æ±æ»å计'), |
| | | ('æç»è¡¨å¨è½¬éå计(ä¸å¨å
¬é)', round(sum_t, 2), round(tot['t26'] / 10000.0, 2), round(sum_t - tot['t26'] / 10000.0, 2), 'æç»æ±å = 17 å¸å·æ±æ»å计'), |
| | | ('2026å¹´1-8æç´¯è®¡è´§è¿é(ä¸å¨)', round(tot['f26'] / 10000.0, 2), PROV['vol26'], round(tot['f26'] / 10000.0 - PROV['vol26'], 2), '对ç
§å·²å叿¥å 1-8 æç´¯è®¡'), |
| | | ('2026å¹´1-8æç´¯è®¡å¨è½¬é(ä¸å¨å
¬é)', round(tot['t26'] / 10000.0, 2), PROV['turn26'], round(tot['t26'] / 10000.0 - PROV['turn26'], 2), 'åä¸'), |
| | | ('2026å¹´8æå
¨çè´§è¿é(ä¸å¨)', round(aug_f, 2), PROV['vol26_08'], round(aug_f - PROV['vol26_08'], 2), 'éªè¯å¸å·å½éæ 误'), |
| | | ('2026å¹´8æå
¨çå¨è½¬é(ä¸å¨å
¬é)', round(aug_t, 2), PROV['turn26_08'], round(aug_t - PROV['turn26_08'], 2), 'åä¸'), |
| | | ('2025å¹´1-8æç´¯è®¡è´§è¿é(ä¸å¨)ãåæ¯åºæã', round(tot25['f'] / 10000.0, 2), PROV['vol25'], round(tot25['f'] / 10000.0 - PROV['vol25'], 2), '对ç
§æ±æ»è¡¨ãè´§è¿ã页 V7..AJ7ï¼ç¼åå¼ï¼'), |
| | | ('2025å¹´1-8æç´¯è®¡å¨è½¬é(ä¸å¨å
¬é)ãåæ¯åºæã', round(tot25['t'] / 10000.0, 2), PROV['turn25'], round(tot25['t'] / 10000.0 - PROV['turn25'], 2), '对ç
§æ±æ»è¡¨ãè´§è¿ã页 V8..AJ8ï¼ç¼åå¼ï¼'), |
| | | ('2025å¹´1-8æå
¨çè§ä¸ä¼ä¸æ°(å®¶)', len(tot25['ents']), 664, len(tot25['ents']) - 664, 'åæ¯åºæä¼ä¸èå´'), |
| | | ('累计货è¿é忝', growth(tot['f26'], tot25['f']), PROV['yoy_vol'], round(growth(tot['f26'], tot25['f']) - PROV['yoy_vol'], 4), '对ç
§å·²å叿¥å 1-8 æç´¯è®¡åæ¯'), |
| | | ('累计å¨è½¬é忝', growth(tot['t26'], tot25['t']), PROV['yoy_turn'], round(growth(tot['t26'], tot25['t']) - PROV['yoy_turn'], 4), 'åä¸'), |
| | | ('2025å¹´1-8æç´¯è®¡å¹³åè¿è·(å
¬é)', round(d25p, 2), None, None, '= 2025 累计å¨è½¬é ÷ 累计货è¿é'), |
| | | ('2026å¹´1-8æç´¯è®¡å¹³åè¿è·(å
¬é)', round(d26p, 2), None, None, '= 2026 累计å¨è½¬é ÷ 累计货è¿é'), |
| | | ('å
¨ç累计平åè¿è·åæ¯', growth(d26p, d25p), None, None, '= 156.92 ÷ 150.10 â 1'), |
| | | ('è¦çå¸å·æ°', len([c for c in CITY_ORDER if by_city.get(c, {}).get('n')]), 17, None, '17 个å¸å·å
¨è¦ç'), |
| | | ('æªè¯å«å°åºç ', len(unknown), 0, None, ('ã'.join(unknown) if unknown else 'æ ')), |
| | | ] |
| | | for i, row in enumerate(chk, 1): |
| | | for j, v in enumerate(row, 1): |
| | | cell = ws5.cell(i + 2, j, v) |
| | | cell.border = BORDER |
| | | cell.alignment = CT if i == 1 else (LT if j in (1, 5) else RT) |
| | | if i == 1: |
| | | cell.font = Font(bold=True); cell.fill = HDR_FILL |
| | | elif j in (2, 3, 4): |
| | | cell.number_format = NFP if row[0].endswith('忝') else NF2 |
| | | |
| | | os.makedirs(OUT_DIR, exist_ok=True) |
| | | wb.save(OUT) |
| | | print('OK ->', OUT) |
| | | print('2026 1-8æ: %.4f ä¸å¨ / %.4f ä¸å¨å
¬é / %.4f å
Ž' % (tot['f26'] / 10000.0, tot['t26'] / 10000.0, d26p)) |
| | | print('2025 1-8æ: %.4f ä¸å¨ / %.4f ä¸å¨å
¬é / %.4f å
¬é (%d å®¶)' % (tot25['f'] / 10000.0, tot25['t'] / 10000.0, d25p, len(tot25['ents']))) |
| | | print('å
¨ç忝: è´§è¿é %.2f%% å¨è½¬é %.2f%% å¹³åè¿è· %.2f%%' % |
| | | (growth(tot['f26'], tot25['f']) * 100, growth(tot['t26'], tot25['t']) * 100, growth(d26p, d25p) * 100)) |
| | | for city in CITY_ORDER: |
| | | c = by_city.get(city) |
| | | if c and c['n']: |
| | | b = B25.get(city, dict(ents=set(), f=0.0, t=0.0)) |
| | | d1, d0 = dist(c['f26'], c['t26']), dist(b['f'], b['t']) |
| | | print('%-8s n=%-4d 2026=%8.2f 2025=%8s 忝=%s' % ( |
| | | city, c['n'], d1, ('%.2f' % d0) if d0 else '-', ('%.1f%%' % (growth(d1, d0) * 100)) if d0 else '-')) |
| New file |
| | |
| | | # æ±æ»è¡¨ä¸æ¡ä¸»çº¿ä¿®å¤æ¹æ¡ + æèµãæé¡¹ç®åç§°æ´æ°ãç°ç¶ï¼2026-09-18ï¼ |
| | | |
| | | > ç»è®ºå
è¡ï¼ä¸æ¡ä¸»çº¿ä¸æ¯ä¸ä¸ªç¬ç« bugï¼èæ¯ **ä¸ä¸ªç»ä¸æ ¹å ï¼å
¬å¼ä¸éç®ï¼+ ä¸å¤é¡µèå´æ¼é¡¹ + ä¸å¤å£å¾ç¼ºå£**ã |
| | | > è¯æ®æä»¶ï¼`_tmp\_qa_out\çæ_éè·¯è¿è¾éæ±æ»è¡¨_2026-08.xlsx`ã`_tmp\_qa_out\gencols.txt`ã`_tmp\_qa_out\genrows.txt`ã |
| | | |
| | | ## ä¸ã䏿¡ä¸»çº¿çæ ¹å |
| | | |
| | | ### è¯æ®ï¼å夿 ¸ï¼ |
| | | |
| | | | 页 | 8æå½æå¼åï¼Qï¼ | 8æåæ¯åï¼Rï¼ | 说æ | |
| | | |---|---|---|---| |
| | | | å
¬äº¤ / åºç§ / ç½çº¦è½¦ / ç线å
车 / 轨éã轮渡 | **æå
¬å¼**ï¼`=Q9+Q13+â¦`ï¼ï¼**æ ç¼åå¼**ï¼cached=Noneï¼ | æå
¬å¼ | å
¬å¼åäºä½æ²¡ç®ï¼è¯»å¼å·¥å
·åªçå°ç©º/æ§å¼ | |
| | | | åå¸å®¢è¿ / ä¸å£å¾æç» | **è¿å
¬å¼é½æ²¡æ**ï¼Q5=NoneãQ9=Noneï¼ | **æå
¬å¼**ï¼`=Q5/AJ5-1`ï¼ | 忝åå¨ã彿弿²¡å â å
¸å"页èå´ä¸ä¸è´" | |
| | | | ä¸å£å¾æå | `K3='=SUM(K4:K20)'`ã`O3='=SUM(O4:O20)'`ï¼æ ç¼åå¼ï¼ | `M3=0.7424`ã`Q3=0.2317` **æ¯åæ»çæ°** | SUM 没éç® + å
¨ç忝忻æåºå
å
¨çå£å¾ | |
| | | |
| | | ### å
³é®äºå® |
| | | |
| | | 1. **æ¯çæ¬èº«å°±æ¯å
¬å¼é©±å¨ç**ï¼ä¸éè¦äººå·¥å忍¡æ¿ï¼ï¼ |
| | | - å
¨çè¡ = Σ17 å¸å·ï¼`å
¬äº¤!C5 = =C9+C13+â¦+C73`ã`ä¸å£å¾æç»!C5 = =C6+C7+C8+C9`ï¼ |
| | | - åå¸å®¢è¿ / ä¸å£å¾æç»çå¸å·è¡ = 跨表å¼ç¨ï¼`åå¸å®¢è¿!C9 = =å
¬äº¤!C16+åºç§!C16+ç½çº¦è½¦!C16+'轨éã轮渡'!C9`ã`ä¸å£å¾æç»!C11 = =ç线å
车!C8`ã |
| | | - æä»¥è¿ä¸¤é¡µ**æ ¹æ¬ä¸éè¦åç¬åæ°æ®**ï¼åªè¦"ææå³ç§»å
¬å¼"è¡¥é½ + éç®ï¼æ´é¡µèªå¨å°±å¯¹ã |
| | | 2. **两个"è¡¥å
¬å¼"彿°ç页èå´ä¸ä¸è´**ï¼`SummaryWorkbookFiller.java`ï¼ï¼ |
| | | - `ensureMonthYoyFormulas()` ç¨ `isMonthLedgerSheet()` â å« åå¸å®¢è¿ / ä¸å£å¾æç» / å
¬è·¯æ»å®¢è¿ï¼ |
| | | - `ensureMonthFormulas()` ç¨ `isFilledLedgerSheet()` â åªæ 6 个å°è´¦é¡µï¼è´§è¿/ç线å
车/å
¬äº¤/åºç§/ç½çº¦è½¦/轨é轮渡ï¼â **æ¼é¡¹å°±å¨è¿é**ã |
| | | 3. **çæä»¶éçå
¬å¼æ²¡æç¼åå¼**ï¼POI åæä»¶æ¶ä¸éç®ï¼æ¯çé 7 æçç¼åå¼è¢«åæ ·çä¸ï¼æä»¥"å
¨çè¡/累计/æååå¨ä¸ä¸æ"ãExcel æå¼é `fullCalcOnLoad` ä¼ç®ï¼ä½**ç³»ç»é¢è§ãäºæ¬¡å¤çãé¨å WPS é½çä¸å°æ°å¼**ã |
| | | |
| | | ### å½çº³ |
| | | |
| | | | 主线 | ç°è±¡ | æ ¹å | |
| | | |---|---|---| |
| | | | 1 | åå¸å®¢è¿ / ä¸å£å¾æç» 8ææ´å空ç½ã累计=1~7æ | `ensureMonthFormulas()` 页èå´æ¼äºè¿ä¸¤é¡µ | |
| | | | 2 | å
¬äº¤/åºç§/ç½çº¦è½¦/åå¸åå¸å·ç**å
¨çè¡**åå¨ 7 æ | å
¬å¼æ ç¼åå¼ï¼æªéç®ï¼ | |
| | | | 3 | ä¸å£å¾æåæ°æ®ä¸å¯¹ | å主线 2ï¼å¦å "å
¨ç忝"åæ»æåºå
å
¨çå£å¾ï¼1-8æ 27524.49ï¼ä¸ Σ17å¸å·ï¼24481.74ï¼ææ¶ | |
| | | |
| | | ## äºãä¿®å¤æ¹æ¡ï¼4 æ¥ï¼ |
| | | |
| | | 1. **è¡¥å
¬å¼é¡µèå´**ï¼`SummaryWorkbookFiller.ensureMonthFormulas()` ç页夿æ¹ç¨ `isMonthLedgerSheet`ï¼å« åå¸å®¢è¿ / ä¸å£å¾æç» / å
¬è·¯æ»å®¢è¿ï¼ã |
| | | å¦ï¼ä¸å£å¾æç»éæ 4 个**æ°å¼è¡**ï¼å¸å·"åé
å乡巡游åºç§/ç½çº¦è½¦"æ¯ç¡¬ç¼ç æ°ï¼ä¸æ¯å
¬å¼ï¼ï¼éè¦æåºéæºæ°æ®åå¡«ï¼ä¸è½åªé å
¬å¼å³ç§»ã |
| | | 2. **çææ¶å°¾åå
¬å¼éç®**ï¼å¨åæä»¶åç¨ `XSSFFormulaEvaluator.evaluateAll()` ææ´æ¬ç®ä¸éå¹¶åå
¥ç¼åå¼ï¼é页 try-catchï¼å¤±è´¥åä¿ç `fullCalcOnLoad=true` é级ï¼ã |
| | | 好å¤ï¼å
¨çè¡ã累计åãæå SUMãåå¸å®¢è¿/ä¸å£å¾æç»è·¨è¡¨å¼ç¨**䏿¬¡æ§å
¨é¨èªå¨åºå¼**ï¼ä¸ç¨å讨论"å
¨çæåªä¸ªå£å¾"ââæ¯çå£å¾å°±æ¯ Σ17 å¸å·ã |
| | | 3. **ç»ä¸ä¸å£å¾å£å¾**ï¼ |
| | | - `exportPassengerMidRank()` å
¨çè¡åæ¯ä¸ååæ»åºå
å
¨çå¼ï¼æ¹æä¸ Σå¸å· åæºï¼ |
| | | - `loadMidClassMap()` è¡¥ dim3 巡游åºç§ + dim4 ç½çº¦è½¦ï¼ç°å¨åªè£
äºç线 + å
¬äº¤ä¸¤ç»´ï¼æä»¥ç¬ç«ãçæ_å
¬è·¯æ
客ä¸å£å¾æç»ã1æå
¨çå° 535.83+333.39ï¼ã |
| | | 4. **建å彿¯å¯¹èæ¬**ï¼æ¯æ¬¡çæåéé¡µéæ ¼ä¸"æ¯çå
¬å¼ + åºæºæ°æ®éç®"æ¯å¯¹ï¼ä½ä¸ºéªæ¶åºçº¿ï¼å¯å¤ç¨ `_tmp\_qa_out` éå·²æç对æ¯èæ¬ï¼ã |
| | | |
| | | ### éè¦ä¸å¡ç¡®è®¤ï¼ä¸é»å¡ä¿®å¤ï¼ |
| | | |
| | | - åºé h2031ãå
¨çãè¡ 1-8 æ = 27524.49ï¼æ¯ Σ17 å¸å·å¤ **3042.75**ãä¿®å¤ä¸å¾ææ¯çå£å¾ï¼Î£å¸å·ï¼èµ°ï¼è¿ä¸ªå·®å¼æå³çä¼ä¸ä¸æ¥ç"å
¨ç"å«å¸å·æç»ä¹å¤çæ°æ®ï¼ææå¸å·æ¼æ¥ï¼ï¼å»ºè®®ä¸å¡ä¾§æ ¸ä¸æ¬¡ã |
| | | |
| | | ## ä¸ãæèµï¼æé¡¹ç®åç§°æ´æ° / æ°å¢é¡¹ç®å½å°å¯¹åºæ¨¡å |
| | | |
| | | ### ç°ç¶ï¼å·²æ ¸å®ï¼ç¨åºç¡®å®æ¯æé¡¹ç®åç§°èµ°çï¼ |
| | | |
| | | - **导å
¥ä¾§**ï¼`DataImportService.saveInvestProjectRow()` / å
¨çæ±æ»å¤§è¡¨è·¯å¾ï¼ä»¥ã**项ç®åç§° + ç±»å«**ã为ä¸å¡ä¸»é® upsert ââ å½ä¸åæ´æ°å段 + å彿æåº¦ï¼æªå½ä¸å**æ°å¢**并带ä¸è¯¥æä»¶çå¸å·ä¸ç±»å«ï¼å®¢è¿ç«åº / ç©æµååºï¼ã |
| | | åºå
æ½æ¥ï¼å®¢è¿ç«åº 49 æ¡ / 49 个åç§°ï¼ç©æµååº 135 æ¡ / 135 个åç§°ï¼**æ éå¤è¡**ã |
| | | - **çæä¾§**ï¼`ReportExportService.matchInvest()` æ¯æåç§°ï¼å½ä¸å + å¸å· + ç±»å«è¿æ»¤ï¼å»å¹é
模æ¿è¡ï¼ä¸æ¯æåä½/è¡å·åæ°ã |
| | | - **ååä¿æ¤**ï¼å·²å®ç°"å¸å·ä¸è´æ§æ ¡éª"ï¼åºä¸å½å±å¸å·ä¸æ¬æ¬¡è§£æä¸ä¸è´ â è·³è¿è¯¥è¡å¹¶å¨é¡µé¢å¼¹çªæç¤ºï¼ã |
| | | - **䏿¨¡ç³å¹é
**ï¼`normInvestName()` åªåæ¬å·/è¿æ¥ç¬¦/çå¸å¿åç¼å½ä¸ï¼ä¸åè¿ä¼¼åå¹¶ â 符å"åç§°æå·®å¼å°±æ¯ä¸¤ä¸ªé¡¹ç®"ã |
| | | |
| | | ### 缺å£ï¼å°±æ¯ä½ 说ç"æ°å¢é¡¹ç®è¦å½å°å¯¹åºæ¨¡åä¸é¢"ï¼ |
| | | |
| | | 1. 模æ¿é**没æçæ°é¡¹ç®ç®åä¸ä¼èªå¨æè¡**ï¼`investPlan`ï¼å
¨çé¢å®æï¼ççæå¨åªç¨ `matchInvest` å¹é
å·²ææ¨¡æ¿è¡ï¼**å¹é
ä¸å°çæ°é¡¹ç®ä¼è¢«ä¸¢æ**ï¼ä¸ä¼æå¸å·/æ¿åæå°å¯¹åºä½ç½®ã |
| | | â éå "æè¡"é»è¾ï¼æ å¸å· + ç±»å«ï¼+èµéæ¸ éåç»ï¼å®ä½ååºé´ï¼å¨åæ«å°¾æè¡ãå¤å¶ç¸é»è¡æ ¼å¼ä¸å
¬å¼ãå项ç®å䏿°æ°æ®ï¼å¹¶æ´æ°å计è¡èå´ã |
| | | 2. **"模å"æç»ä¸å±ç°å¨å
¥ä¸äºåº**ï¼ä¸¤å¼ æç»è¡¨ç"ä¸ã使ç¨äº¤éé¨è½¦è´ç¨èµé / äºãççæ²¹ç¨ / ä¸ãåæç»¼åè¿è¾æå¡ç« / åãå车äº"åç»è¡ï¼å¨å¯¼å
¥æ¶è¢« `^[ä¸äºä¸åäºå
ä¸å
«ä¹å]+ã.*` è§å**主å¨è·³è¿**ï¼æä»¥é¡¹ç®è½ä¸å°å
·ä½æ¸ éåã |
| | | â éç» `investment_project` å `fund_channel` åæ®µï¼å¯¼å
¥æ¶è®°å½"å½ååç»"åå°å
¶å项ç®ä¸ï¼åé导 7/8 æã |
| | | 3. ååä¸å项ç®ç®å**ä¸å¼¹çª**ï¼åªæå¸å·éä½å¼¹çªï¼ã |
| | |
| | | import org.apache.poi.xwpf.usermodel.XWPFParagraph; |
| | | import org.apache.poi.xwpf.usermodel.XWPFTable; |
| | | import org.apache.poi.xwpf.usermodel.XWPFTableRow; |
| | | import org.w3c.dom.Document; |
| | | import org.w3c.dom.Element; |
| | | import org.w3c.dom.Node; |
| | | import org.w3c.dom.NodeList; |
| | | import cn.hutool.core.io.IoUtil; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | |
| | | Map<String, Double> orders = new LinkedHashMap<>(); |
| | | double[] sumHolder = new double[]{0.0}; |
| | | String docPeriod; |
| | | try (java.io.InputStream in = file.getInputStream(); |
| | | XWPFDocument doc = new XWPFDocument(in)) { |
| | | docPeriod = periodOfDocx(doc); |
| | | parseWycOrderReportTables(doc, orders, sumHolder); |
| | | byte[] bytes; |
| | | try (java.io.InputStream in = file.getInputStream()) { |
| | | bytes = IoUtil.readBytes(in); |
| | | } |
| | | boolean isZip = bytes.length > 3 && (bytes[0] & 0xFF) == 0x50 && (bytes[1] & 0xFF) == 0x4B; |
| | | boolean isWordMl = !isZip && looksLikeWordMl(bytes); |
| | | try { |
| | | if (isZip && !isWordPackage(bytes)) { |
| | | throw new RuntimeException("è¿ä¸æ¯ Word ææ¡£ï¼å缩å
éæ²¡æ word/document.xmlï¼ï¼" |
| | | + "å¤åæ¯ Excel æå
¶å®æ ¼å¼ã请ä¸ä¼ ç½çº¦è½¦è®¢ååææ¥åç .docxï¼æ Word 2003 XMLï¼"); |
| | | } |
| | | if (isZip) { |
| | | try (XWPFDocument doc = new XWPFDocument(new java.io.ByteArrayInputStream(bytes))) { |
| | | docPeriod = periodOfParagraphs(paragraphsOfDocx(doc)); |
| | | parseWycOrderReportTables(doc, orders, sumHolder); |
| | | } |
| | | } else if (isWordMl) { |
| | | // ç½çº¦è½¦ç管平å°ä¸åçæ¥å常被 WPS/Word åæãWord 2003 XMLï¼å¹³éº XMLï¼ãååæ¹å .docxï¼ |
| | | // è¿ç§æä»¶ä¸æ¯ zip å
ï¼XWPFDocument æä¸å¼ï¼æ¥ "File is not a zip file"ï¼ï¼éæ XML ç´æ¥è§£æã |
| | | String xml = new String(bytes, java.nio.charset.StandardCharsets.UTF_8); |
| | | Document dom = parseXmlSafely(xml); |
| | | docPeriod = periodOfParagraphs(paragraphsOfDocxXml(dom)); |
| | | parseWycOrderReportTablesXml(dom, orders, sumHolder); |
| | | } else if (isOle2(bytes)) { |
| | | throw new RuntimeException("è¿æ¯ Word 97-2003 èæ ¼å¼ï¼.docï¼ï¼è¯·ç¨ WPS/Word æå¼åãå¦å为ãdocx æ ¼å¼å导å
¥"); |
| | | } else { |
| | | throw new RuntimeException("æ æ³è¯å«çæä»¶æ ¼å¼ï¼æ¢ä¸æ¯ docxï¼zip å
ï¼ï¼ä¹ä¸æ¯ Word 2003 XML æ .doc"); |
| | | } |
| | | } catch (RuntimeException e) { |
| | | throw e; |
| | | } catch (Exception e) { |
| | | throw new RuntimeException("æ æ³è¯»å Word ææ¡£ï¼è¯·ä¸ä¼ .docx æ ¼å¼çãç½çº¦è½¦è¡ä¸YYYYå¹´Mæè¿è¡çæµæ
åµåææ¥åãï¼" |
| | | + "è¥ä¸ä¼ çå
¶å®æ¯ Excel/PDFï¼è¯·æ¹ç¨å¯¹åºæ¨¡æ¿å¯¼å
¥ãï¼åå§é误ï¼" + e.getMessage() + "ï¼"); |
| | |
| | | } |
| | | |
| | | /** æ¥åæ é¢ä¸çæ¥è¡¨æï¼ç½çº¦è½¦è¡ä¸2026å¹´7æ -> 2026-07ï¼åä¸å°è¿å null */ |
| | | private String periodOfDocx(XWPFDocument doc) { |
| | | private String periodOfParagraphs(List<String> paragraphs) { |
| | | java.util.regex.Pattern titlePat = java.util.regex.Pattern.compile("ç½çº¦è½¦è¡ä¸\\s*(\\d{4})\\s*å¹´\\s*(\\d{1,2})\\s*æ"); |
| | | java.util.regex.Pattern anyPat = java.util.regex.Pattern.compile("(\\d{4})\\s*å¹´\\s*(\\d{1,2})\\s*æ"); |
| | | String fallback = null; |
| | | int scanned = 0; |
| | | for (XWPFParagraph para : doc.getParagraphs()) { |
| | | String text = para.getText(); |
| | | for (String text : paragraphs) { |
| | | if (text == null) continue; |
| | | String flat = text.replaceAll("\\s+", ""); |
| | | if (flat.isEmpty()) continue; |
| | |
| | | return fallback; |
| | | } |
| | | |
| | | /** docx æ®µè½ææ¬ï¼ä¿æåå§é¡ºåºï¼ */ |
| | | private List<String> paragraphsOfDocx(XWPFDocument doc) { |
| | | List<String> out = new ArrayList<>(); |
| | | for (XWPFParagraph para : doc.getParagraphs()) out.add(para.getText()); |
| | | return out; |
| | | } |
| | | |
| | | /** Word 2003 XMLï¼WordMLï¼æ®µè½ææ¬ï¼<w:p> 䏿æ <w:t> æ¼æ¥ååæç©ºç½ */ |
| | | private List<String> paragraphsOfDocxXml(Document dom) { |
| | | List<String> out = new ArrayList<>(); |
| | | for (Element p : elementsByLocalName(dom, "p")) out.add(textOfXmlElement(p)); |
| | | return out; |
| | | } |
| | | |
| | | /** æ¯å¦ä¸º Word 2003 XMLï¼WordML å¹³éº XMLï¼ââè¿ç§æä»¶å¸¸è¢«æ¹åæ .docx */ |
| | | private boolean looksLikeWordMl(byte[] bytes) { |
| | | int n = Math.min(bytes.length, 4096); |
| | | String head = new String(bytes, 0, n, java.nio.charset.StandardCharsets.UTF_8); |
| | | return head.contains("wordml") && head.contains("<w:wordDocument"); |
| | | } |
| | | |
| | | /** zip å
å
æ¯å¦å« word/document.xmlï¼ç¨äºåºå docx ä¸ xlsx/å
¶å® OPC å
ï¼ */ |
| | | private boolean isWordPackage(byte[] bytes) { |
| | | try (java.util.zip.ZipInputStream zin = |
| | | new java.util.zip.ZipInputStream(new java.io.ByteArrayInputStream(bytes))) { |
| | | java.util.zip.ZipEntry e; |
| | | while ((e = zin.getNextEntry()) != null) { |
| | | String n = e.getName(); |
| | | if ("word/document.xml".equals(n)) return true; |
| | | } |
| | | } catch (Exception ignore) { |
| | | return false; |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | /** æ¯å¦ä¸º OLE2 å¤åææ¡£ï¼Word 97-2003 .docï¼ */ |
| | | private boolean isOle2(byte[] b) { |
| | | return b.length > 8 && (b[0] & 0xFF) == 0xD0 && (b[1] & 0xFF) == 0xCF |
| | | && (b[2] & 0xFF) == 0x11 && (b[3] & 0xFF) == 0xE0; |
| | | } |
| | | |
| | | /** å®å
¨è§£æ XMLï¼ç¦ç¨å¤é¨å®ä½/DTDï¼æ¥åæ¥èªå¤é¨å¹³å°ï¼é² XXEï¼ */ |
| | | private Document parseXmlSafely(String xml) throws Exception { |
| | | javax.xml.parsers.DocumentBuilderFactory f = javax.xml.parsers.DocumentBuilderFactory.newInstance(); |
| | | f.setNamespaceAware(true); |
| | | try { f.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); } catch (Exception ignore) { } |
| | | try { f.setFeature("http://xml.org/sax/features/external-general-entities", false); } catch (Exception ignore) { } |
| | | try { f.setFeature("http://xml.org/sax/features/external-parameter-entities", false); } catch (Exception ignore) { } |
| | | javax.xml.parsers.DocumentBuilder b = f.newDocumentBuilder(); |
| | | b.setEntityResolver(new org.xml.sax.EntityResolver() { |
| | | @Override |
| | | public org.xml.sax.InputSource resolveEntity(String publicId, String systemId) { |
| | | return new org.xml.sax.InputSource(new java.io.StringReader("")); |
| | | } |
| | | }); |
| | | return b.parse(new org.xml.sax.InputSource(new java.io.StringReader(xml))); |
| | | } |
| | | |
| | | /** æ localName åå
¨é¨å代å
ç´ ï¼å½åç©ºé´æ å
³ï¼å
¼å®¹ WordML ä¸ docx ç w: åç¼ï¼ */ |
| | | private List<Element> elementsByLocalName(Document dom, String localName) { |
| | | List<Element> out = new ArrayList<>(); |
| | | NodeList list = dom.getElementsByTagNameNS("*", localName); |
| | | for (int i = 0; i < list.getLength(); i++) out.add((Element) list.item(i)); |
| | | return out; |
| | | } |
| | | |
| | | /** åªåç´æ¥åå
ç´ ï¼é¿å
åµå¥è¡¨æ ¼/åµå¥å±æ§å
ç´ è¢«ç®è¿æ¥ï¼ */ |
| | | private List<Element> childElementsByLocalName(Element parent, String localName) { |
| | | List<Element> out = new ArrayList<>(); |
| | | NodeList kids = parent.getChildNodes(); |
| | | for (int i = 0; i < kids.getLength(); i++) { |
| | | Node n = kids.item(i); |
| | | if (n.getNodeType() == Node.ELEMENT_NODE && localName.equals(n.getLocalName())) out.add((Element) n); |
| | | } |
| | | return out; |
| | | } |
| | | |
| | | /** å
ç´ å
ææ <w:t> ææ¬æ¼æ¥å¹¶åæç©ºç½ */ |
| | | private String textOfXmlElement(Element el) { |
| | | StringBuilder sb = new StringBuilder(); |
| | | NodeList ts = el.getElementsByTagNameNS("*", "t"); |
| | | for (int i = 0; i < ts.getLength(); i++) sb.append(ts.item(i).getTextContent()); |
| | | return flat(sb.toString()); |
| | | } |
| | | |
| | | private String ymd(String y, String mo) { |
| | | try { |
| | | int month = Integer.parseInt(mo); |
| | |
| | | |
| | | /** è§£ææ¥åä¸çãå°å¸åç§° | ⦠| è®¢åæ°æ»æ°ã表ï¼orders=å¸å·è®¢åï¼sumHolder[0]=å计è¡è®¢åæ° */ |
| | | private void parseWycOrderReportTables(XWPFDocument doc, Map<String, Double> orders, double[] sumHolder) { |
| | | List<List<List<String>>> tables = new ArrayList<>(); |
| | | for (XWPFTable table : doc.getTables()) { |
| | | List<XWPFTableRow> rows = table.getRows(); |
| | | List<List<String>> rows = new ArrayList<>(); |
| | | for (XWPFTableRow row : table.getRows()) { |
| | | List<String> cells = new ArrayList<>(); |
| | | for (org.apache.poi.xwpf.usermodel.XWPFTableCell c : row.getTableCells()) cells.add(flat(c.getText())); |
| | | rows.add(cells); |
| | | } |
| | | tables.add(rows); |
| | | } |
| | | matchWycOrderTable(tables, orders, sumHolder); |
| | | } |
| | | |
| | | /** Word 2003 XMLï¼WordMLï¼åæ¯ï¼<w:tbl>/<w:tr>/<w:tc> æ½æææ¬è¡¨åèµ°åä¸å¥å¹é
é»è¾ */ |
| | | private void parseWycOrderReportTablesXml(Document dom, Map<String, Double> orders, double[] sumHolder) { |
| | | List<List<List<String>>> tables = new ArrayList<>(); |
| | | for (Element tbl : elementsByLocalName(dom, "tbl")) { |
| | | List<List<String>> rows = new ArrayList<>(); |
| | | for (Element tr : childElementsByLocalName(tbl, "tr")) { |
| | | List<String> cells = new ArrayList<>(); |
| | | for (Element tc : childElementsByLocalName(tr, "tc")) cells.add(textOfXmlElement(tc)); |
| | | rows.add(cells); |
| | | } |
| | | tables.add(rows); |
| | | } |
| | | matchWycOrderTable(tables, orders, sumHolder); |
| | | } |
| | | |
| | | /** |
| | | * å¨ãææ¬åè¡¨æ ¼ãéæ¾éä»¶1ï¼è¡¨å¤´å«ãè®¢åæ°æ»æ°ã/ãè®¢åæ°ãï¼å¹¶å 17 å¸å·è®¢åæ°ä¸å计ã |
| | | * å
¥å tables = 表 -> è¡ -> åå
æ ¼ææ¬ï¼å·²å空ç½ï¼ï¼ä¸æ¥æºæ ¼å¼æ å
³ã |
| | | */ |
| | | private void matchWycOrderTable(List<List<List<String>>> tables, Map<String, Double> orders, double[] sumHolder) { |
| | | for (List<List<String>> rows : tables) { |
| | | if (rows.size() < 3) continue; |
| | | int headerRow = -1; |
| | | int orderCol = -1; |
| | | for (int r = 0; r < Math.min(rows.size(), 3); r++) { |
| | | List<org.apache.poi.xwpf.usermodel.XWPFTableCell> cells = rows.get(r).getTableCells(); |
| | | List<String> cells = rows.get(r); |
| | | for (int c = 0; c < cells.size(); c++) { |
| | | String norm = flat(cells.get(c).getText()); |
| | | String norm = cells.get(c); |
| | | if (norm.contains("è®¢åæ°æ»æ°") || "è®¢åæ°".equals(norm)) { |
| | | headerRow = r; |
| | | orderCol = c; |
| | |
| | | double citySum = 0.0; |
| | | boolean hasTotal = false; |
| | | for (int r = headerRow + 1; r < rows.size(); r++) { |
| | | List<org.apache.poi.xwpf.usermodel.XWPFTableCell> cells = rows.get(r).getTableCells(); |
| | | if (orderCol >= cells.size()) continue; |
| | | String name = flat(cells.get(0).getText()); |
| | | List<String> cells = rows.get(r); |
| | | if (cells.isEmpty() || orderCol >= cells.size()) continue; |
| | | String name = cells.get(0); |
| | | if (name.isEmpty()) continue; |
| | | Double val = parsePlainNumber(cells.get(orderCol).getText()); |
| | | Double val = parsePlainNumber(cells.get(orderCol)); |
| | | if (val == null) continue; |
| | | String city = RegionUtil.normalizeCityName(name); |
| | | if (city != null && RegionUtil.cityList().contains(city)) { |
| | |
| | | import org.apache.poi.ss.usermodel.Row; |
| | | import org.apache.poi.ss.usermodel.Sheet; |
| | | import org.apache.poi.xssf.usermodel.XSSFWorkbook; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import javax.annotation.Resource; |
| | |
| | | */ |
| | | @Service |
| | | public class SummaryWorkbookFiller { |
| | | |
| | | private static final Logger log = LoggerFactory.getLogger(SummaryWorkbookFiller.class); |
| | | |
| | | @Resource |
| | | private MidCalc midCalc; |
| | |
| | | if (wb == null || month <= 1) return 0; |
| | | int targetCol = FIRST_MONTH_COL + 2 * (month - 1); |
| | | int written = 0; |
| | | int carried = 0; |
| | | for (int i = 0; i < wb.getNumberOfSheets(); i++) { |
| | | Sheet sh = wb.getSheetAt(i); |
| | | if (sh == null || !isFilledLedgerSheet(sh.getSheetName())) continue; |
| | | if (sh == null || !isMonthLedgerSheet(sh.getSheetName())) continue; |
| | | boolean derivedSheet = isDerivedFormulaSheet(sh.getSheetName()); |
| | | for (int r = sh.getFirstRowNum(); r <= sh.getLastRowNum(); r++) { |
| | | Row row = sh.getRow(r); |
| | | if (row == null) continue; |
| | |
| | | break; |
| | | } |
| | | } |
| | | if (srcCell == null) continue; |
| | | if (srcCell == null) { |
| | | if (!derivedSheet) continue; |
| | | // æ´¾ç页ï¼åå¸å®¢è¿/ä¸å£å¾æç»/å
¬è·¯æ»å®¢è¿ï¼éãåæé½æ¯åä¸ä¸ªå¸¸éãçç»ææ§å¸¸éè¡ |
| | | // ï¼å¦ä¸å£å¾æç» æ¦æ± åé
å乡巡游åºç§=0ï¼ï¼æææ²¿ç¨è¯¥å¸¸éï¼é¿å
彿å¼å空ç导è´ç´¯è®¡ç¼ºé¡¹ |
| | | double struct = structuralConstant(row, month); |
| | | if (Double.isNaN(struct)) continue; |
| | | Cell target = row.getCell(targetCol); |
| | | if (target == null) target = row.createCell(targetCol); |
| | | Cell prev = row.getCell(FIRST_MONTH_COL + 2 * (month - 2)); |
| | | if (prev != null && prev.getCellStyle() != null) target.setCellStyle(prev.getCellStyle()); |
| | | target.setCellValue(struct); |
| | | carried++; |
| | | written++; |
| | | continue; |
| | | } |
| | | String f = srcCell.getCellFormula(); |
| | | if (f == null || f.isEmpty()) continue; |
| | | Cell target = row.getCell(targetCol); |
| | |
| | | written++; |
| | | } |
| | | } |
| | | if (carried > 0 && log != null) { |
| | | log.info("æ±æ»å·¥ä½ç°¿ï¼æ´¾çé¡µç»ææ§å¸¸éè¡æææ²¿ç¨ {} æ ¼ï¼ç¬¬ {} æï¼", carried, month); |
| | | } |
| | | return written; |
| | | } |
| | | |
| | | /** è¯¥è¡ 1..month-1 æç彿å¼åæ¯å¦å
¨ä¸ºåä¸ä¸ªæ°å¼å¸¸éï¼ç»ææ§å¸¸éè¡ï¼å¦åææä¸º 0ï¼ */ |
| | | private double structuralConstant(Row row, int month) { |
| | | if (row == null || month <= 2) return Double.NaN; |
| | | Double v = null; |
| | | for (int s = 1; s < month; s++) { |
| | | Cell c = row.getCell(FIRST_MONTH_COL + 2 * (s - 1)); |
| | | if (c == null || c.getCellType() != org.apache.poi.ss.usermodel.CellType.NUMERIC) return Double.NaN; |
| | | double d = c.getNumericCellValue(); |
| | | if (v == null) v = d; |
| | | else if (Math.abs(d - v) > 1e-9) return Double.NaN; |
| | | } |
| | | return v == null ? Double.NaN : v; |
| | | } |
| | | |
| | | /** æ´¾ç页ï¼å½æå¼å
¨é¨æ¥èªå
¶ä»é¡µ/常éï¼çº¯å
¬å¼é©±å¨ï¼ï¼åå¸å®¢è¿ / ä¸å£å¾æç» / å
¬è·¯æ»å®¢è¿ / ä¸å£å¾å®¢è¿é */ |
| | | private boolean isDerivedFormulaSheet(String name) { |
| | | if (name == null) return false; |
| | | String n = name.trim(); |
| | | return "åå¸å®¢è¿".equals(n) || "ä¸å£å¾æç»".equals(n) || "å
¬è·¯æ»å®¢è¿".equals(n) || "ä¸å£å¾å®¢è¿é".equals(n); |
| | | } |
| | | |
| | | /** è¯¥æ ¼æ¯å¦å·²æå
å®¹ï¼æ°å¼/ææ¬/å
¬å¼ï¼ï¼ä»
å¸¦æ ·å¼ç空壳ï¼å¦æ¯çéç»§æ¿è¡¨å¤´æ¥ææ ¼å¼çæ ¼åï¼è§ä¸ºç©º */ |
| | |
| | | case STRING: return c.getStringCellValue() != null && !c.getStringCellValue().trim().isEmpty(); |
| | | default: return true; |
| | | } |
| | | } |
| | | |
| | | /** åä¸éææ°æ®åå¡«çå°è´¦é¡µï¼è´§è¿/ç线å
车/å
¬äº¤/åºç§/ç½çº¦è½¦/轨éè½®æ¸¡ï¼ */ |
| | | private boolean isFilledLedgerSheet(String name) { |
| | | if (name == null) return false; |
| | | String n = name.trim(); |
| | | return "è´§è¿".equals(n) || "ç线å
车".equals(n) || "å
¬äº¤".equals(n) |
| | | || "åºç§".equals(n) || "ç½çº¦è½¦".equals(n) || "轨éã轮渡".equals(n); |
| | | } |
| | | |
| | | /** 0 åºåå· + 1 åºè¡å· -> "Q5" */ |
| | |
| | | import com.trafficaudit.dataimport.entity.PassengerEnterpriseMonthly; |
| | | import com.trafficaudit.dataimport.entity.PassengerIndividualMonthly; |
| | | import com.trafficaudit.dataimport.entity.ScaleSplitTransport; |
| | | import com.trafficaudit.dataimport.entity.WycOrderMonthly; |
| | | import com.trafficaudit.auditengine.entity.AuditResult; |
| | | import com.trafficaudit.auditengine.entity.AuditRun; |
| | | import com.trafficaudit.auditengine.mapper.AuditResultMapper; |
| | |
| | | import com.trafficaudit.dataimport.mapper.PassengerEnterpriseMonthlyMapper; |
| | | import com.trafficaudit.dataimport.mapper.PassengerIndividualMonthlyMapper; |
| | | import com.trafficaudit.dataimport.mapper.ScaleSplitTransportMapper; |
| | | import com.trafficaudit.dataimport.mapper.WycOrderMonthlyMapper; |
| | | import com.trafficaudit.reportexport.calc.MidCalc; |
| | | import com.trafficaudit.reportexport.calc.PaxCalc; |
| | | import com.trafficaudit.reportexport.calc.SummaryWorkbookFiller; |
| | | import com.trafficaudit.reportexport.calc.WycSplitCalc; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.poi.ss.usermodel.Cell; |
| | | import org.apache.poi.ss.usermodel.CellStyle; |
| | |
| | | private CityTaxiMonthlyMapper cityTaxiMapper; |
| | | @Resource |
| | | private SummaryWorkbookFiller summaryWorkbookFiller; |
| | | @Resource |
| | | private WycSplitCalc wycSplitCalc; |
| | | @Resource |
| | | private WycOrderMonthlyMapper wycOrderMapper; |
| | | @Resource |
| | | private AuditResultMapper auditResultMapper; |
| | | @Resource |
| | |
| | | return lv == 0.0 ? null : (v - lv) / lv; |
| | | } |
| | | |
| | | /** ä¸å£å¾æåæ¯ï¼k=-1 表示æ»è¡ï¼ç线+å
¬äº¤ä¹åï¼åºç§/ç½çº¦è½¦æ æºæ°æ®æ 0ï¼ï¼æ å»å¹´æ°æ®ç空 */ |
| | | /** ä¸å£å¾æåæ¯ï¼k=-1 表示æ»è¡ï¼ç线+å
¬äº¤+åºç§å乡+ç½çº¦è½¦å乡 å项ä¹åï¼ï¼æ å»å¹´æ°æ®ç空 */ |
| | | private void fillMidYoyCell(Cell c, Map<Integer, Map<String, double[][]>> mid, int year, int month, |
| | | String area, int k, boolean volume) { |
| | | double v = 0.0, lv = 0.0; |
| | | if (k == -1) { |
| | | for (int kk = 1; kk <= 4; kk++) { |
| | | if (kk >= 3) continue; |
| | | v += midClassVal(mid, year, month, area, kk, volume); |
| | | lv += midClassVal(mid, year - 1, month, area, kk, volume); |
| | | } |
| | | } else if (k <= 2) { |
| | | } else { |
| | | v = midClassVal(mid, year, month, area, k, volume); |
| | | lv = midClassVal(mid, year - 1, month, area, k, volume); |
| | | } |
| | |
| | | if (v != 0.0 && lv != 0.0) c.setCellValue(round((v - lv) / lv, 4)); |
| | | } |
| | | |
| | | /** ä¸å£å¾ç´¯è®¡åæ¯åï¼1..months æç´¯è®¡ï¼k=-1 æ»è¡ = ç线+å
¬äº¤ï¼ */ |
| | | /** ä¸å£å¾ç´¯è®¡åæ¯åï¼1..months æç´¯è®¡ï¼åç»´é½å
¨ï¼ */ |
| | | private void fillMidCumYoyColumn(Sheet sheet, Map<Integer, Map<String, double[][]>> mid, int year, |
| | | int months, int colIdx) { |
| | | List<String> areas = midTemplateAreas(); |
| | |
| | | String area = areas.get(blockOffset / 5); |
| | | double v = 0.0, lv = 0.0; |
| | | for (int m = 1; m <= months; m++) { |
| | | if (k <= 2) { |
| | | { |
| | | v += midClassVal(mid, year, m, area, k, volume); |
| | | lv += midClassVal(mid, year - 1, m, area, k, volume); |
| | | } |
| | |
| | | boolean extended = fillMonths > 6; |
| | | if (extended) extendMonthlyColumns(sheet, 2, currentYear, 4, sheet.getLastRowNum()); |
| | | List<String> areas = midTemplateAreas(); |
| | | // 2026-09-18ï¼æ¹ä¸ºãæåå
æ ¼ç±»åæ å
³ãéåââæ©åï¼7~12 æï¼åºæ¥çå¼å卿¨¡æ¿éæ¯ç©ºæ ¼ï¼ |
| | | // æ§å®ç°åªå¤ç CellType.FORMULA çæ ¼ï¼å¯¼è´ 7 æå以åæä»½æ°¸è¿å¡«ä¸ä¸ï¼8 ææ´å 0ã累计åªå° 6 æï¼ã |
| | | for (Row row : sheet) { |
| | | if (row == null) continue; |
| | | for (Cell c : row) { |
| | | if (c.getCellType() != CellType.FORMULA) continue; |
| | | String f = c.getCellFormula(); |
| | | if (f == null) continue; |
| | | boolean crossBook = f.contains("["); |
| | | if (!crossBook && !isYoyMonthCol(c.getColumnIndex() + 1)) continue; // å
é¨å
¬å¼ï¼å计/累计ï¼ä¿çéç®ï¼åæ¯å #REF! è¦å为æ°å¼ |
| | | if (crossBook && !is2026MonthCol(c.getColumnIndex() + 1)) { |
| | | keepCached(c); // 2025 å¹´åä¿ç模æ¿ç¼åå¼ |
| | | continue; |
| | | } |
| | | for (int c0 = 0; c0 < Math.max(row.getLastCellNum(), 0); c0++) { |
| | | Cell c = row.getCell(c0); |
| | | if (c == null) continue; |
| | | int r = c.getRowIndex() + 1; |
| | | int col = c.getColumnIndex() + 1; |
| | | int col = c0 + 1; |
| | | int blockOffset = -1; |
| | | boolean volume = false; |
| | | if (r >= 5 && r <= 94) { |
| | |
| | | volume = false; |
| | | } |
| | | if (blockOffset < 0) { |
| | | keepCached(c); // r1/r2 夿³¨ç |
| | | if (c.getCellType() == CellType.FORMULA) keepCached(c); // r1/r2 夿³¨ã页å¤è·¨ç°¿å¼ç¨ç |
| | | continue; |
| | | } |
| | | if (blockOffset % 5 == 0) { |
| | | if (isYoyMonthCol(col)) { |
| | | fillMidYoyCell(c, mid, currentYear, monthOfCol(col), areas.get(blockOffset / 5), -1, volume); |
| | | } else { |
| | | keepCached(c); // æ»è¡å
é¨å
¬å¼ï¼é²å¾¡ï¼ |
| | | boolean isVal = is2026MonthCol(col); |
| | | boolean isYoy = isYoyMonthCol(col); |
| | | if (!isVal && !isYoy) { |
| | | // 2025 å¹´åçï¼è·¨ç°¿å
¬å¼åç¼å弿é¾ï¼å
é¨å
¬å¼ï¼å计/累计ï¼ä¿çï¼ç¨å recalc éç® |
| | | if (c.getCellType() == CellType.FORMULA) { |
| | | String f = c.getCellFormula(); |
| | | if (f != null && f.contains("[")) keepCached(c); |
| | | } |
| | | continue; |
| | | } |
| | | int k = blockOffset % 5; // 1=ç线 2=å
¬äº¤ 3=åºç§ 4=ç½çº¦è½¦ |
| | | String area = areas.get(blockOffset / 5); |
| | | if (is2026MonthCol(col)) { |
| | | if (blockOffset % 5 == 0) { |
| | | if (isYoy) { |
| | | fillMidYoyCell(c, mid, currentYear, monthOfCol(col), area, -1, volume); |
| | | } |
| | | // æ»è¡å¼åï¼ä¸å¾ä¿ç模æ¿å
¬å¼ï¼1~6 æåå
¬å¼ + æ©åå
éåºæ¥çå
¬å¼ï¼ï¼ |
| | | // ç±çææ¶å°¾ç recalcWorkbookFormulas æ±å¼ååç¼åãæ©æçæ¬è¿é keepCached |
| | | // 伿åå
éåºæ¥çå
¬å¼æ¸
æç©ºæ ¼ï¼å¯¼è´ 7 æåä»¥åæ»è¡æ°¸è¿ç©ºç½ã |
| | | continue; |
| | | } |
| | | int k = blockOffset % 5; // 1=ç线 2=å
¬äº¤ 3=åºç§å乡 4=ç½çº¦è½¦å乡 |
| | | if (isVal) { |
| | | fillMidCell(c, mid, currentYear, monthOfCol(col), area, k, volume); |
| | | } else if (isYoyMonthCol(col)) { |
| | | fillMidYoyCell(c, mid, currentYear, monthOfCol(col), area, k, volume); |
| | | } else { |
| | | keepCached(c); // 2025 å¹´åä¿ç模æ¿ç¼åå¼ |
| | | fillMidYoyCell(c, mid, currentYear, monthOfCol(col), area, k, volume); |
| | | } |
| | | } |
| | | } |
| | | // ç´¯è®¡åæ¯åï¼æ¨¡æ¿ #REF! â åºå
å»å¹´ 1..N æç´¯è®¡åæ¯æ°å¼ï¼ |
| | | fillMidCumYoyColumn(sheet, mid, currentYear, fillMonths, extended ? 27 : 15); |
| | | recalc(wb); |
| | | // evaluateAll ä¼å¨è·¨ç°¿å
¬å¼ï¼Sheet2 ç [1]xx!A1ï¼å¤æ´æ¬ä¸æï¼ç´¯è®¡å AA å°±æ°¸è¿æ¿ä¸å°æ°ç¼åå¼ï¼ |
| | | // æ¹ç¨éæ ¼å®¹éç recalcWorkbookFormulasï¼åæ ¼è·³è¿ãå¥½æ ¼ç
§ç®ã |
| | | int[] recalc = recalcWorkbookFormulas(wb); |
| | | log.info("ä¸å£å¾æç»å
¬å¼éç®å®æï¼æå {} æ ¼ï¼å¤±è´¥ {} æ ¼", recalc[0], recalc[1]); |
| | | clearFormulaErrorsAll(wb); // å»å¹´åææç»é¡µæ®ç #REF! 忝å
¬å¼ â æ¸
空 |
| | | blankFutureMonthColumns(sheet, fillMonths); // æ¥è¡¨æä¹åçæä»½åä¸ä¿çå
éå
¬å¼/0 å¼ |
| | | return toBytes(wb); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æ¸
ç©ºãæ¥è¡¨æä¹åãçæä»½åï¼æ©åå
éåºæ¥ç 7~12 æéãå°æªå°æçæä»½ï¼ã |
| | | * 䏿¸
çè¯ï¼å
éåºæ¥çæ»è¡å
¬å¼ä¼ç®åº 0ï¼æ¥è¡¨ä¸ä¼åºç°"9~12 æå
¨æ¯ 0"çåæ°æ®ï¼ |
| | | * 累计åï¼AAï¼çå
¬å¼/ç¼åå¼å·²å¨éç®é¶æ®µç®å¥½ï¼æ¸
ç©ºæ ¼åä¸å½±åå®ï¼ç©º = 0ï¼ã |
| | | */ |
| | | private void blankFutureMonthColumns(Sheet sheet, int filledMonths) { |
| | | for (int m = filledMonths + 1; m <= 12; m++) { |
| | | int col = 2 * m; // 0 åºï¼1 æ=2(C)ã7 æ=14(O)ã12 æ=24(Y) |
| | | for (int r = 4; r <= sheet.getLastRowNum(); r++) { // 0 åºç¬¬ 4 è¡ = 第 5 è¡ï¼é¦ä¸ªæ°æ®è¡ï¼ï¼è¡¨å¤´ä¸å¨ |
| | | Row row = sheet.getRow(r); |
| | | if (row == null) continue; |
| | | Cell val = row.getCell(col); |
| | | if (val != null) val.setBlank(); |
| | | Cell yoy = row.getCell(col + 1); |
| | | if (yoy != null) yoy.setBlank(); |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | return (col - 1) / 2; |
| | | } |
| | | |
| | | /** å¡«ä¸å£å¾æ°æ®åå
æ ¼ï¼åºç§/ç½çº¦è½¦(3/4)æ¾å¼ 0ï¼ç线/å
¬äº¤å¡«åºå
å¼ï¼æ 弿¸
ç©ºï¼ */ |
| | | /** |
| | | * å¡«ä¸å£å¾æ°æ®åå
æ ¼ï¼ç线/å
¬äº¤/åºç§å乡/ç½çº¦è½¦å乡 åç»´ç»ä¸ååºå
å¼ã |
| | | * åºå
该æè¯¥ç»´æ æºï¼åå¼ä¸º 0ï¼æ¶**ä¿çæ¯ç/模æ¿åå¼**ââç»ä¸å空ãä¹ä¸å 0ã |
| | | * 便®ï¼æ¨¡æ¿çåå¸çº§åä¹¡è¡æ¯ãå°è´¦é¡µ æ»é â åå¸å
ãçå¼ç¨ãå¹¶å·²ä¸å¡å®ç¨¿ï¼ |
| | | * ç¨åºå
缺失å¼è¦ç伿å®ç¨¿æ°æ¸
æï¼å¦ 2026-01~06 ç½çº¦è½¦è®¢å缺失æ¶ï¼ |
| | | * å
¨çç½çº¦è½¦å乡 333.39 ä¸åå¸å·å¼ä¼è¢«æ¸
空ï¼ã |
| | | */ |
| | | private void fillMidCell(Cell c, Map<Integer, Map<String, double[][]>> mid, int year, int month, String area, int k, boolean volume) { |
| | | if (k == 3 || k == 4) { |
| | | writeExplicitZero(c); // åºç§/ç½çº¦è½¦ææ æ°æ®æºï¼æ¾å¼ 0 |
| | | return; |
| | | } |
| | | double v = midClassVal(mid, year, month, area, k, volume); |
| | | if (v == 0.0) return; // åºå
æ æºï¼ä¿çæ¯ç/å®ç¨¿åå¼ï¼ç¼ºæ°æ®ä¸è¦ç |
| | | // POI setCellValue(double) 对å
¬å¼åå
æ ¼åªæ´æ°ç¼åä¸ç§»é¤å
¬å¼ï¼å¿
é¡»å
setBlank ååå¼ |
| | | c.setBlank(); |
| | | if (v != 0.0) c.setCellValue(round(v, 4)); |
| | | c.setCellValue(round(v, 4)); |
| | | } |
| | | |
| | | /** æ¾å¼åå
¥ 0ï¼POI setCellValue(0.0) ä¼è½¬ blankï¼éæä½åºå± XMLï¼ */ |
| | |
| | | addMidClass(mid, key, city, 2, nz(b.getPassengerChengxiang()), nz(b.getTurnoverChengxiang())); |
| | | addMidClass(mid, key, "æ¹åç", 2, nz(b.getPassengerChengxiang()), nz(b.getTurnoverChengxiang())); |
| | | } |
| | | // 维度3ï¼åé
å乡巡游åºç§ = å°è´¦é¡µãåºç§!æ»é â åºç§!åå¸å
ãï¼æº city_taxi_monthlyï¼ |
| | | for (CityTaxiMonthly t : cityTaxiMapper.selectList(null)) { |
| | | if (t.getReportPeriod() == null || t.getCity() == null) continue; |
| | | int key = midPeriodKey(t.getReportPeriod()); |
| | | if (key <= 0) continue; |
| | | String city = RegionUtil.normalizeCityName(t.getCity()); |
| | | if (city == null) continue; |
| | | double pass = nz(t.getPassengerVolume()) - nz(t.getPassengerCity()); |
| | | double turn = nz(t.getTurnover()) - nz(t.getTurnoverCity()); |
| | | addMidClass(mid, key, city, 3, pass, turn); |
| | | addMidClass(mid, key, "æ¹åç", 3, pass, turn); |
| | | } |
| | | // 维度4ï¼åé
å乡ç½çº¦è½¦ = ç½çº¦è½¦æåç»æï¼ä¸å°è´¦ãç½çº¦è½¦ãé¡µåæºåæ³ï¼ |
| | | for (WycOrderMonthly o : wycOrderMapper.selectList(null)) { |
| | | String per = o.getReportPeriod(); |
| | | if (per == null) continue; |
| | | int key = midPeriodKey(per); |
| | | if (key <= 0) continue; |
| | | WycSplitCalc.WycResult wr; |
| | | try { |
| | | wr = wycSplitCalc.calc(per); |
| | | } catch (Exception e) { |
| | | continue; // 该æç¼ºè®¢å/pin æåºç§æºæ°æ®ï¼è·³è¿ï¼ä¸å½±åå
¶å®æï¼ |
| | | } |
| | | for (Map.Entry<String, WycSplitCalc.WycMetrics> en : wr.getByCity().entrySet()) { |
| | | WycSplitCalc.WycMetrics wm = en.getValue(); |
| | | addMidClass(mid, key, en.getKey(), 4, wm.getSuburbanPax(), wm.getSuburbanTurnover()); |
| | | addMidClass(mid, key, "æ¹åç", 4, wm.getSuburbanPax(), wm.getSuburbanTurnover()); |
| | | } |
| | | } |
| | | return mid; |
| | | } |
| | | |
| | | /** "yyyy-MM" -> yyyy*100+MMï¼éæ³è¿å 0ï¼ä¸ loadMidClassMap ç key å£å¾ä¸è´ï¼ */ |
| | | private int midPeriodKey(String period) { |
| | | if (period == null) return 0; |
| | | String[] parts = period.trim().split("-"); |
| | | if (parts.length != 2) return 0; |
| | | try { |
| | | int y = Integer.parseInt(parts[0]); |
| | | int m = Integer.parseInt(parts[1]); |
| | | if (y <= 0 || m < 1 || m > 12) return 0; |
| | | return y * 100 + m; |
| | | } catch (NumberFormatException e) { |
| | | return 0; |
| | | } |
| | | } |
| | | |
| | | /** åå
¥åç±»å¼å¹¶ç´¯å æ»éï¼ç»´åº¦0ï¼ */ |
| | |
| | | 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); |
| | |
| | | } |
| | | |
| | | /** |
| | | * æ±æ»å·¥ä½ç°¿å
¬å¼éç®ï¼POI åæä»¶ä¸å¸¦ç¼åå¼ï¼å¯¼è´ãå
¨çè¡ï¼Î£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}; |
| | | } |
| | | try { |
| | | // 跨簿å
¬å¼ï¼[1]åºç§!C13 ä¹ç±»ï¼å¨å¤é¨å·¥ä½ç°¿ç¼ºå¤±æ¶é»è®¤æå¼å¸¸ï¼ä¼è®©å¼ç¨å®ç |
| | | // æ»è¡/累计/æ´¾çå
¬å¼è¿é失败ï¼è¡¨ç°ä¸ºãå
¬å¼è¿å¨ä½æ²¡æç¼åå¼ãï¼ã |
| | | // ç½® true åæ¹ç¨å
¬å¼æ ¼èªèº«çç¼åå¼ï¼å³å®ç¨¿å¼ï¼åä¸è®¡ç®ã |
| | | ev.setIgnoreMissingWorkbooks(true); |
| | | } catch (Exception ignore) { |
| | | // 个å«å®ç°ä¸æ¯æè¯¥å¼å
³ï¼å¿½ç¥å³å¯ |
| | | } |
| | | 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); // 注æï¼evaluate() æ å¯ä½ç¨ï¼å¿
é¡»ç¨ 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 å´æ®ç <is>ãçéæ³åå
æ ¼ã |
| | | * |
| | | * æ¯çè¥ç± openpyxl ååºï¼ææ¬åå
æ ¼ç¨ <is>ï¼inlineStrï¼åå¨ï¼POI ç setCellValue åªæ¹å t ä¸ <v>ï¼ |