From 9da3d25292f4d5f6f831a2e67757b3a5cdab1cc5 Mon Sep 17 00:00:00 2001
From: 疯狂的狮子Li <15040126243@163.com>
Date: 星期三, 06 十一月 2024 15:40:32 +0800
Subject: [PATCH] !595 修复大数量级联下拉导致的禁止写入错误 Merge pull request !595 from Emil.Zhang/dev

---
 ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/ExportExcelServiceImpl.java  |   48 ++++++++++-----
 ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/ExcelDownHandler.java |  108 ++++++++++++++++++++++-------------
 2 files changed, 98 insertions(+), 58 deletions(-)

diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/ExcelDownHandler.java b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/ExcelDownHandler.java
index b3f68ed..32fee7a 100644
--- a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/ExcelDownHandler.java
+++ b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/ExcelDownHandler.java
@@ -55,6 +55,7 @@
      * 涓嬫媺鍙�夐」
      */
     private final List<DropDownOptions> dropDownOptions;
+    private final DictService dictService;
     /**
      * 褰撳墠鍗曢�夎繘搴�
      */
@@ -63,7 +64,6 @@
      * 褰撳墠鑱斿姩閫夋嫨杩涘害
      */
     private int currentLinkedOptionsSheetIndex;
-    private final DictService dictService;
 
     public ExcelDownHandler(List<DropDownOptions> options) {
         this.dropDownOptions = options;
@@ -139,8 +139,8 @@
             } else if (everyOptions.getOptions().size() > 10) {
                 // 褰撲竴绾ч�夐」鍙傛暟涓暟澶т簬10锛屼娇鐢ㄩ澶栬〃鐨勫舰寮�
                 dropDownWithSheet(helper, workbook, sheet, everyOptions.getIndex(), everyOptions.getOptions());
-            } else if (everyOptions.getOptions().size() != 0) {
-                // 褰撲竴绾ч�夐」涓暟涓嶄负绌猴紝浣跨敤榛樿褰㈠紡
+            } else {
+                // 鍚﹀垯浣跨敤榛樿褰㈠紡
                 dropDownWithSimple(helper, sheet, everyOptions.getIndex(), everyOptions.getOptions());
             }
         });
@@ -171,9 +171,23 @@
         Sheet linkedOptionsDataSheet = workbook.createSheet(WorkbookUtil.createSafeSheetName(linkedOptionsSheetName));
         // 灏嗕笅鎷夎〃闅愯棌
         workbook.setSheetHidden(workbook.getSheetIndex(linkedOptionsDataSheet), true);
-        // 瀹屽杽妯悜鐨勪竴绾ч�夐」鏁版嵁琛�
+        // 閫夐」鏁版嵁
         List<String> firstOptions = options.getOptions();
         Map<String, List<String>> secoundOptionsMap = options.getNextOptions();
+
+        // 閲囩敤鎸夎濉厖鏁版嵁鐨勬柟寮忥紝閬垮厤EasyExcel鍑虹幇鏁版嵁鏃犳硶鍐欏叆鐨勯棶棰�
+        // Attempting to write a row in the range that is already written to disk
+
+        // 浣跨敤ArrayList璁拌浇鏁版嵁锛岄槻姝贡搴�
+        List<String> columnNames = new ArrayList<>();
+        // 鍐欏叆绗竴琛岋紝鍗崇涓�绾х殑鏁版嵁
+        Row firstRow = linkedOptionsDataSheet.createRow(0);
+        for (int columnIndex = 0; columnIndex < firstOptions.size(); columnIndex++) {
+            String columnName = firstOptions.get(columnIndex);
+            firstRow.createCell(columnIndex)
+                .setCellValue(columnName);
+            columnNames.add(columnName);
+        }
 
         // 鍒涘缓鍚嶇О绠$悊鍣�
         Name name = workbook.createName();
@@ -190,28 +204,12 @@
         // 璁剧疆鏁版嵁鏍¢獙涓哄簭鍒楁ā寮忥紝寮曠敤鐨勬槸鍚嶇О绠$悊鍣ㄤ腑鐨勫埆鍚�
         this.markOptionsToSheet(helper, sheet, options.getIndex(), helper.createFormulaListConstraint(linkedOptionsSheetName));
 
-        for (int columIndex = 0; columIndex < firstOptions.size(); columIndex++) {
-            // 鍏堟彁鍙栦富琛ㄤ腑涓�绾т笅鎷夌殑鍒楀悕
+        // 鍒涘缓浜岀骇閫夐」鐨勫悕绉扮鐞嗗櫒
+        for (int columIndex = 0; columIndex < columnNames.size(); columIndex++) {
+            // 鍒楀悕
             String firstOptionsColumnName = getExcelColumnName(columIndex);
-            // 涓�娆″惊鐜槸姣忎竴涓竴绾ч�夐」
-            int finalI = columIndex;
-            // 鏈寰幆鐨勪竴绾ч�夐」鍊�
-            String thisFirstOptionsValue = firstOptions.get(columIndex);
-            // 鍒涘缓绗竴琛岀殑鏁版嵁
-            Optional.ofNullable(linkedOptionsDataSheet.getRow(0))
-                // 濡傛灉涓嶅瓨鍦ㄥ垯鍒涘缓绗竴琛�
-                .orElseGet(() -> linkedOptionsDataSheet.createRow(finalI))
-                // 绗竴琛屽綋鍓嶅垪
-                .createCell(columIndex)
-                // 璁剧疆鍊间负褰撳墠涓�绾ч�夐」鍊�
-                .setCellValue(thisFirstOptionsValue);
-
-            // 绗簩琛屽紑濮嬶紝璁剧疆绗簩绾у埆閫夐」鍙傛暟
-            List<String> secondOptions = secoundOptionsMap.get(thisFirstOptionsValue);
-            if (CollUtil.isEmpty(secondOptions)) {
-                // 蹇呴』淇濊瘉鑷冲皯鏈変竴涓叧鑱旈�夐」锛屽惁鍒欏皢瀵艰嚧Excel瑙f瀽閿欒
-                secondOptions = Collections.singletonList("鏆傛棤_0");
-            }
+            // 瀵瑰簲鐨勪竴绾у��
+            String thisFirstOptionsValue = columnNames.get(columIndex);
 
             // 浠ヨ涓�绾ч�夐」鍊煎垱寤哄瓙鍚嶇О绠$悊鍣�
             Name sonName = workbook.createName();
@@ -222,7 +220,9 @@
                 linkedOptionsSheetName,
                 firstOptionsColumnName,
                 firstOptionsColumnName,
-                secondOptions.size() + 1
+                // 浜岀骇閫夐」瀛樺湪鍒欒缃负(閫夐」涓暟+1)琛岋紝鍚﹀垯璁剧疆涓�2琛�
+                Math.max(Optional.ofNullable(secoundOptionsMap.get(thisFirstOptionsValue))
+                    .orElseGet(ArrayList::new).size(), 1) + 1
             );
             // 璁剧疆鍚嶇О绠$悊鍣ㄧ殑寮曠敤浣嶇疆
             sonName.setRefersToFormula(sonFunction);
@@ -235,25 +235,51 @@
                 // 浜岀骇鍙兘涓昏〃姣忎竴琛岀殑姣忎竴鍒楁坊鍔犱簩绾ф牎楠�
                 markLinkedOptionsToSheet(helper, sheet, i, options.getNextIndex(), helper.createFormulaListConstraint(secondOptionsFunction));
             }
+        }
 
-            for (int rowIndex = 0; rowIndex < secondOptions.size(); rowIndex++) {
-                // 浠庣浜岃寮�濮嬪~鍏呬簩绾ч�夐」
-                int finalRowIndex = rowIndex + 1;
-                int finalColumIndex = columIndex;
-
-                Row row = Optional.ofNullable(linkedOptionsDataSheet.getRow(finalRowIndex))
-                    // 娌℃湁鍒欏垱寤�
-                    .orElseGet(() -> linkedOptionsDataSheet.createRow(finalRowIndex));
-                Optional
-                    // 鍦ㄦ湰绾т竴绾ч�夐」鎵�鍦ㄧ殑鍒�
-                    .ofNullable(row.getCell(finalColumIndex))
-                    // 涓嶅瓨鍦ㄥ垯鍒涘缓
-                    .orElseGet(() -> row.createCell(finalColumIndex))
-                    // 璁剧疆浜岀骇閫夐」鍊�
-                    .setCellValue(secondOptions.get(rowIndex));
+        // 灏嗕簩绾ф暟鎹鐞嗕负鎸夎鍖哄垎
+        Map<Integer, List<String>> columnValueMap = new HashMap<>();
+        int currentRow = 1;
+        while (currentRow >= 0) {
+            boolean flag = false;
+            List<String> rowData = new ArrayList<>();
+            for (String columnName : columnNames) {
+                List<String> data = secoundOptionsMap.get(columnName);
+                if (CollUtil.isEmpty(data)) {
+                    // 娣诲姞绌哄瓧绗︿覆濉厖浣嶇疆
+                    rowData.add(" ");
+                    continue;
+                }
+                // 鍙栫涓�涓�
+                String str = data.get(0);
+                rowData.add(str);
+                // 閫氳繃绉婚櫎鐨勬柟寮忛伩鍏嶉噸澶�
+                data.remove(0);
+                // 璁剧疆鍙互缁х画
+                flag = true;
+            }
+            columnValueMap.put(currentRow, rowData);
+            // 鍙互缁х画锛屽垯澧炲姞琛屾暟锛屽惁鍒欑疆涓鸿礋鏁拌烦鍑哄惊鐜�
+            if (flag) {
+                currentRow++;
+            } else {
+                currentRow = -1;
             }
         }
 
+        // 濉厖绗簩绾ч�夐」鏁版嵁
+        columnValueMap.forEach((rowIndex, rowValues) -> {
+            Row row = linkedOptionsDataSheet.createRow(rowIndex);
+            for (int columnIndex = 0; columnIndex < rowValues.size(); columnIndex++) {
+                String rowValue = rowValues.get(columnIndex);
+                // 濉厖浣嶇疆鐨勯儴鍒嗕笉娓叉煋
+                if (StrUtil.isNotBlank(rowValue)) {
+                    row.createCell(columnIndex)
+                        .setCellValue(rowValue);
+                }
+            }
+        });
+
         currentLinkedOptionsSheetIndex++;
     }
 
diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/ExportExcelServiceImpl.java b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/ExportExcelServiceImpl.java
index 0240e02..ebb6ac6 100644
--- a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/ExportExcelServiceImpl.java
+++ b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/ExportExcelServiceImpl.java
@@ -1,5 +1,6 @@
 package org.dromara.demo.service.impl;
 
+import cn.hutool.core.util.RandomUtil;
 import cn.hutool.core.util.StrUtil;
 import jakarta.servlet.http.HttpServletResponse;
 import lombok.Data;
@@ -121,8 +122,9 @@
         List<DemoCityData> provinceList = new ArrayList<>();
 
         // 瀹為檯涓氬姟涓竴鑸噰鐢ㄦ暟鎹簱璇诲彇鐨勫舰寮忥紝杩欓噷鐩存帴鎷兼帴鍒涘缓
-        provinceList.add(new DemoCityData(0, null, "瀹夊窘鐪�"));
-        provinceList.add(new DemoCityData(1, null, "姹熻嫃鐪�"));
+        provinceList.add(new DemoCityData(0, null, "P100000"));
+        provinceList.add(new DemoCityData(1, null, "P200000"));
+        provinceList.add(new DemoCityData(2, null, "P300000"));
 
         return provinceList;
     }
@@ -137,11 +139,11 @@
         List<DemoCityData> cityList = new ArrayList<>();
 
         // 瀹為檯涓氬姟涓竴鑸噰鐢ㄦ暟鎹簱璇诲彇鐨勫舰寮忥紝杩欓噷鐩存帴鎷兼帴鍒涘缓
-        cityList.add(new DemoCityData(0, 0, "鍚堣偉甯�"));
-        cityList.add(new DemoCityData(1, 0, "鑺滄箹甯�"));
-        cityList.add(new DemoCityData(2, 1, "鍗椾含甯�"));
-        cityList.add(new DemoCityData(3, 1, "鏃犻敗甯�"));
-        cityList.add(new DemoCityData(4, 1, "寰愬窞甯�"));
+        cityList.add(new DemoCityData(0, 0, "C110000"));
+        cityList.add(new DemoCityData(1, 0, "C120000"));
+        cityList.add(new DemoCityData(2, 1, "C210000"));
+        cityList.add(new DemoCityData(3, 1, "C220000"));
+        cityList.add(new DemoCityData(4, 1, "C230000"));
 
         selectParentData(provinceList, cityList);
 
@@ -157,17 +159,29 @@
     private List<DemoCityData> getAreaList(List<DemoCityData> cityList) {
         List<DemoCityData> areaList = new ArrayList<>();
 
+        int minCount = 500;
+        int maxCount = 10000;
+
         // 瀹為檯涓氬姟涓竴鑸噰鐢ㄦ暟鎹簱璇诲彇鐨勫舰寮忥紝杩欓噷鐩存帴鎷兼帴鍒涘缓
-        areaList.add(new DemoCityData(0, 0, "鐟舵捣鍖�"));
-        areaList.add(new DemoCityData(1, 0, "搴愭睙鍖�"));
-        areaList.add(new DemoCityData(2, 1, "鍗楀畞鍘�"));
-        areaList.add(new DemoCityData(3, 1, "闀滄箹鍖�"));
-        areaList.add(new DemoCityData(4, 2, "鐜勬鍖�"));
-        areaList.add(new DemoCityData(5, 2, "绉︽樊鍖�"));
-        areaList.add(new DemoCityData(6, 3, "瀹滃叴甯�"));
-        areaList.add(new DemoCityData(7, 3, "鏂板惔鍖�"));
-        areaList.add(new DemoCityData(8, 4, "榧撴ゼ鍖�"));
-        areaList.add(new DemoCityData(9, 4, "涓板幙"));
+        for (int i = 0; i < RandomUtil.randomInt(minCount, maxCount); i++) {
+            areaList.add(new DemoCityData(areaList.size(), 0, String.format("A11%04d", i)));
+        }
+
+        for (int i = 0; i < RandomUtil.randomInt(minCount, maxCount); i++) {
+            areaList.add(new DemoCityData(areaList.size(), 1, String.format("A12%04d", i)));
+        }
+
+        for (int i = 0; i < RandomUtil.randomInt(minCount, maxCount); i++) {
+            areaList.add(new DemoCityData(areaList.size(), 2, String.format("A21%04d", i)));
+        }
+
+        for (int i = 0; i < RandomUtil.randomInt(minCount, maxCount); i++) {
+            areaList.add(new DemoCityData(areaList.size(), 3, String.format("A22%04d", i)));
+        }
+
+        for (int i = 0; i < RandomUtil.randomInt(minCount, maxCount); i++) {
+            areaList.add(new DemoCityData(areaList.size(), 4, String.format("A23%04d", i)));
+        }
 
         selectParentData(cityList, areaList);
 

--
Gitblit v1.9.3