| docs/功能测试报告/功能测试报告_汇总表公式扩页与重算_2026-09-18.md | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| docs/工作日结/工作日结_2026-09-18.md | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| docs/问题汇总/汇总表三条主线修复方案_2026-09-18.md | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| traffic-audit-server/src/main/java/com/trafficaudit/reportexport/calc/SummaryWorkbookFiller.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| traffic-audit-server/src/main/java/com/trafficaudit/reportexport/service/ReportExportService.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
docs/¹¦ÄܲâÊÔ±¨¸æ/¹¦ÄܲâÊÔ±¨¸æ_»ã×Ü±í¹«Ê½À©Ò³ÓëÖØËã_2026-09-18.md
New file @@ -0,0 +1,85 @@ # åè½æµè¯æ¥å_æ±æ»è¡¨ãå ¬å¼æ©é¡µ + çæä»¶éç®ã_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` 补两维ï¼å¾ ç¨æ·ç¡®è®¤å宿½ã docs/¹¤×÷ÈÕ½á/¹¤×÷ÈÕ½á_2026-09-18.md
New file @@ -0,0 +1,45 @@ # 工使¥ç»_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 æ éå¤è¡ï¼ï¼ç¼ºå£æ¯"模æ¿é没æçæ°é¡¹ç®ä¸ä¼æè¡"ã"èµéæ¸ éåç»è¡å¯¼å ¥æ¶è¢«è·³è¿"ã"ååä¸å项ç®ä¸å¼¹çª"ã ## äºãæµè¯ç»ææè¦ è§ `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 å·®å¼ã ## ä¸ãéçé®é¢ä¸å¾ å 1. **ä¸å£å¾æå忝仿¯åæ»å¼**ï¼M3=0.7424 / Q3=0.2317ï¼åºå å ¨çå£å¾ï¼ï¼éä¸ Î£17 å¸å·å£å¾ç»ä¸ ââ 第 3 æ¥ã 2. **`loadMidClassMap()` 缺巡游åºç§ + ç½çº¦è½¦ä¸¤ç»´**ï¼å¯¼è´ç¬ç«ãçæ_å ¬è·¯æ 客ä¸å£å¾æç»ãå° 535.83+333.39ï¼1 æï¼ââ 第 3 æ¥ã 3. **åºå h2031ãå ¨çãè¡ â Σ17 å¸å·**ï¼1-8 æ 27524.49 vs 24481.74ï¼å·® 3042.75ï¼ï¼ä¸å¡å£å¾é®é¢ï¼å»ºè®®ä¸å¡ä¾§æ ¸å¯¹ã 4. æèµï¼æ¨¡æ¿é没æçæ°é¡¹ç®ä¸ä¼èªå¨æè¡ï¼æç»è¡¨èµéæ¸ éåç»è¡æªå ¥åºï¼éå `fund_channel`ï¼ï¼ååä¸åé¡¹ç®æªå¼¹çªã 5. æèµä¸¤å¼ æç»è¡¨ï¼`Xæå®¢è¿ç«æèµæç»è¡¨` / `Xæç©æµç«åºæèµæç»`ï¼çæå¨æªåã ## åãæå¤©è®¡å 1. 第 3 æ¥ï¼ç»ä¸ä¸å£å¾å£å¾ï¼rank å ¨ç忝æ¹ä¸ºåæº + `loadMidClassMap` 补两维ï¼ï¼æ¹å®å¯¹ç¬ç«ä¸å£å¾æç»ä¸æ±æ»è¡¨é项æ¯å¯¹ã 2. æèµ"æ°å¢é¡¹ç®æè¡ + åç»è¡å ¥åº"æ¹æ¡è½å°ï¼çç¨æ·å¯¹"模å"å£å¾çæå确认ï¼ã 3. 建çæä»¶ vs æ¯çéç®çå彿¯å¯¹èæ¬ï¼åºåä¸ºæ¯æ¬¡æ¹å¨çéªæ¶åºçº¿ã docs/ÎÊÌâ»ã×Ü/»ã×ܱíÈýÌõÖ÷ÏßÐÞ¸´·½°¸_2026-09-18.md
New file @@ -0,0 +1,66 @@ # æ±æ»è¡¨ä¸æ¡ä¸»çº¿ä¿®å¤æ¹æ¡ + æèµãæé¡¹ç®åç§°æ´æ°ãç°ç¶ï¼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. ååä¸å项ç®ç®å**ä¸å¼¹çª**ï¼åªæå¸å·éä½å¼¹çªï¼ã traffic-audit-server/src/main/java/com/trafficaudit/reportexport/calc/SummaryWorkbookFiller.java
@@ -7,6 +7,8 @@ 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; @@ -33,6 +35,8 @@ */ @Service public class SummaryWorkbookFiller { private static final Logger log = LoggerFactory.getLogger(SummaryWorkbookFiller.class); @Resource private MidCalc midCalc; @@ -429,9 +433,11 @@ 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; @@ -446,7 +452,21 @@ 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); @@ -456,7 +476,31 @@ 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); } /** è¯¥æ ¼æ¯å¦å·²æå å®¹ï¼æ°å¼/ææ¬/å ¬å¼ï¼ï¼ä» å¸¦æ ·å¼ç空壳ï¼å¦æ¯çéç»§æ¿è¡¨å¤´æ¥ææ ¼å¼çæ ¼åï¼è§ä¸ºç©º */ @@ -467,14 +511,6 @@ 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" */ traffic-audit-server/src/main/java/com/trafficaudit/reportexport/service/ReportExportService.java
@@ -3362,6 +3362,8 @@ 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); @@ -3371,6 +3373,45 @@ } /** * æ±æ»å·¥ä½ç°¿å ¬å¼éç®ï¼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}; } 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>ï¼