cr 1 miesiąc temu
rodzic
commit
4af309e0b0

+ 199 - 20
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsTreeContractController.java

@@ -1190,12 +1190,86 @@ public class WbsTreeContractController extends BladeController {
 
     // 应用合并单元格 - 添加居中样式参数
     private void applyMergedRegions(Sheet sheet, Map<Integer, List<CellRangeAddress>> mergeMap, CellStyle centerStyle) {
-        for (List<CellRangeAddress> regions : mergeMap.values()) {
+        // 使用Set来记录已经合并的区域,避免重复合并
+        Set<String> mergedRegions = new HashSet<>();
+
+        // 首先处理名称列的合并
+        Map<Integer, List<CellRangeAddress>> nameColumnMerges = new HashMap<>();
+
+        // 名称列的索引:1, 4, 7, 10, 13
+        int[] nameColumns = {1, 4, 7, 10, 13};
+
+        // 收集名称列的合并信息
+        for (int nameCol : nameColumns) {
+            if (mergeMap.containsKey(nameCol)) {
+                nameColumnMerges.put(nameCol, new ArrayList<>(mergeMap.get(nameCol)));
+            }
+        }
+
+        // 合并名称列和对应的划分编码列
+        for (Map.Entry<Integer, List<CellRangeAddress>> entry : nameColumnMerges.entrySet()) {
+            int nameCol = entry.getKey();
+            List<CellRangeAddress> regions = entry.getValue();
+
+            if (regions.size() > 1) {
+                // 按行号排序
+                regions.sort(Comparator.comparingInt(CellRangeAddress::getFirstRow));
+
+                int mergeStart = -1;
+                int mergeEnd = -1;
+                String lastValue = null;
+
+                for (CellRangeAddress region : regions) {
+                    int rowNum = region.getFirstRow();
+                    Row row = sheet.getRow(rowNum);
+                    if (row == null) continue;
+
+                    Cell cell = row.getCell(nameCol);
+                    if (cell == null) continue;
+
+                    String currentValue = getCellStringValue(cell);
+
+                    if (lastValue == null) {
+                        // 第一个单元格
+                        mergeStart = rowNum;
+                        mergeEnd = rowNum;
+                        lastValue = currentValue;
+                    } else if (currentValue.equals(lastValue)) {
+                        // 值相同,扩展合并范围
+                        mergeEnd = rowNum;
+                    } else {
+                        // 值不同,合并之前的区域
+                        if (mergeStart < mergeEnd) {
+                            mergeNameAndCodeColumns(sheet, nameCol, mergeStart, mergeEnd, centerStyle, mergedRegions);
+                        }
+                        // 开始新的合并区域
+                        mergeStart = rowNum;
+                        mergeEnd = rowNum;
+                        lastValue = currentValue;
+                    }
+                }
+
+                // 合并最后一段区域
+                if (mergeStart < mergeEnd) {
+                    mergeNameAndCodeColumns(sheet, nameCol, mergeStart, mergeEnd, centerStyle, mergedRegions);
+                }
+            }
+        }
+
+        // 处理其他列的合并(pkeyId列等)
+        for (Map.Entry<Integer, List<CellRangeAddress>> entry : mergeMap.entrySet()) {
+            int col = entry.getKey();
+            List<CellRangeAddress> regions = entry.getValue();
+
+            // 跳过已经处理过的名称列
+            if (isNameColumn(col)) {
+                continue;
+            }
+
             if (regions.size() > 1) {
                 // 按行号排序
                 regions.sort(Comparator.comparingInt(CellRangeAddress::getFirstRow));
 
-                int col = regions.get(0).getFirstColumn();
                 int mergeStart = -1;
                 int mergeEnd = -1;
                 String lastValue = null;
@@ -1206,7 +1280,7 @@ public class WbsTreeContractController extends BladeController {
                     if (row == null) continue;
 
                     Cell cell = row.getCell(col);
-                    if (cell == null) continue;  // 修复:这里应该是 continue 而不是跳过
+                    if (cell == null) continue;
 
                     String currentValue = getCellStringValue(cell);
 
@@ -1221,10 +1295,7 @@ public class WbsTreeContractController extends BladeController {
                     } else {
                         // 值不同,合并之前的区域
                         if (mergeStart < mergeEnd) {
-                            CellRangeAddress mergedRegion = new CellRangeAddress(mergeStart, mergeEnd, col, col);
-                            sheet.addMergedRegion(mergedRegion);
-                            // 设置合并后单元格居中
-                            setMergedRegionStyle(sheet, mergedRegion, centerStyle);
+                            mergeSingleColumnIfNotExists(sheet, col, mergeStart, mergeEnd, centerStyle, mergedRegions);
                         }
                         // 开始新的合并区域
                         mergeStart = rowNum;
@@ -1235,21 +1306,72 @@ public class WbsTreeContractController extends BladeController {
 
                 // 合并最后一段区域
                 if (mergeStart < mergeEnd) {
-                    CellRangeAddress mergedRegion = new CellRangeAddress(mergeStart, mergeEnd, col, col);
-                    sheet.addMergedRegion(mergedRegion);
-                    // 设置合并后单元格居中
-                    setMergedRegionStyle(sheet, mergedRegion, centerStyle);
+                    mergeSingleColumnIfNotExists(sheet, col, mergeStart, mergeEnd, centerStyle, mergedRegions);
                 }
             }
         }
     }
 
-    // 获取单元格的字符串值
-    private String getCellStringValue(Cell cell) {
-        if (cell == null) {
-            return "";
+    // 合并名称列和对应的划分编码列(检查是否已存在)
+    private void mergeNameAndCodeColumns(Sheet sheet, int nameCol, int startRow, int endRow, CellStyle centerStyle, Set<String> mergedRegions) {
+        // 合并名称列
+        mergeSingleColumnIfNotExists(sheet, nameCol, startRow, endRow, centerStyle, mergedRegions);
+
+        // 合并对应的划分编码列
+        int codeCol = getCorrespondingCodeColumn(nameCol);
+        if (codeCol != -1) {
+            mergeSingleColumnIfNotExists(sheet, codeCol, startRow, endRow, centerStyle, mergedRegions);
+        }
+    }
+
+    // 合并单列并设置样式(检查是否已存在)
+    private void mergeSingleColumnIfNotExists(Sheet sheet, int col, int startRow, int endRow, CellStyle style, Set<String> mergedRegions) {
+        String regionKey = col + ":" + startRow + ":" + endRow;
+
+        if (!mergedRegions.contains(regionKey)) {
+            CellRangeAddress mergedRegion = new CellRangeAddress(startRow, endRow, col, col);
+
+            // 检查是否已经存在相同的合并区域
+            boolean alreadyExists = false;
+            for (int i = 0; i < sheet.getNumMergedRegions(); i++) {
+                CellRangeAddress existingRegion = sheet.getMergedRegion(i);
+                if (existingRegion.getFirstColumn() == col &&
+                        existingRegion.getFirstRow() == startRow &&
+                        existingRegion.getLastRow() == endRow) {
+                    alreadyExists = true;
+                    break;
+                }
+            }
+
+            if (!alreadyExists) {
+                sheet.addMergedRegion(mergedRegion);
+                setMergedRegionStyle(sheet, mergedRegion, style);
+                mergedRegions.add(regionKey);
+            }
+        }
+    }
+
+    // 判断是否是名称列
+    private boolean isNameColumn(int columnIndex) {
+        int[] nameColumns = {1, 4, 7, 10, 13};
+        for (int nameCol : nameColumns) {
+            if (columnIndex == nameCol) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    // 获取对应的划分编码列
+    private int getCorrespondingCodeColumn(int nameColumn) {
+        switch (nameColumn) {
+            case 1: return 0;  // 单位工程名称(1) -> 单位工程划分编码(0)
+            case 4: return 3;  // 分部工程名称(4) -> 分部工程划分编码(3)
+            case 7: return 6;  // 子分部工程名称(7) -> 子分部工程划分编码(6)
+            case 10: return 9; // 分项工程名称(10) -> 分项工程划分编码(9)
+            case 13: return 12; // 子分项工程名称(13) -> 子分项工程划分编码(12)
+            default: return -1;
         }
-        return cell.getStringCellValue();
     }
 
     // 设置合并区域样式为居中
@@ -1267,15 +1389,72 @@ public class WbsTreeContractController extends BladeController {
         }
     }
 
+    // 获取单元格的字符串值
+    private String getCellStringValue(Cell cell) {
+        if (cell == null) {
+            return "";
+        }
+
+        try {
+            return cell.getStringCellValue();
+        } catch (Exception e) {
+            return "";
+        }
+    }
+
     // 自动调整列宽
     private void autoSizeColumns(Sheet sheet) {
         for (int i = 0; i < 15; i++) {
-            sheet.autoSizeColumn(i);
-            // 设置最小列宽
-            if (sheet.getColumnWidth(i) < 3000) {
-                sheet.setColumnWidth(i, 3000);
+            // 先手动计算列宽
+            int maxWidth = calculateColumnWidth(sheet, i);
+
+            // 设置列宽,至少3000(约30个字符宽度)
+            int columnWidth = Math.max(maxWidth + 1000, 3000); // 加一些边距
+            sheet.setColumnWidth(i, columnWidth);
+        }
+    }
+
+    // 手动计算列宽
+    private int calculateColumnWidth(Sheet sheet, int columnIndex) {
+        int maxWidth = 0;
+
+        for (int rowNum = 0; rowNum <= sheet.getLastRowNum(); rowNum++) {
+            Row row = sheet.getRow(rowNum);
+            if (row != null) {
+                Cell cell = row.getCell(columnIndex);
+                if (cell != null) {
+                    String cellValue = getCellStringValue(cell);
+                    if (cellValue != null && !cellValue.isEmpty()) {
+                        // 估算字符串宽度(中文字符算2个英文字符宽度)
+                        int width = estimateStringWidth(cellValue);
+                        maxWidth = Math.max(maxWidth, width);
+                    }
+                }
+            }
+        }
+
+        return maxWidth * 256; // POI中列宽的单位是1/256个字符宽度
+    }
+
+    // 估算字符串宽度
+    private int estimateStringWidth(String text) {
+        if (text == null || text.isEmpty()) {
+            return 0;
+        }
+
+        int width = 0;
+        for (char c : text.toCharArray()) {
+            // 中文字符或全角字符宽度为2,英文字符宽度为1
+            if (c >= 0x4E00 && c <= 0x9FA5) {
+                width += 2; // 中文字符
+            } else if (c > 0xFF00 && c < 0xFF5F) {
+                width += 2; // 全角字符
+            } else {
+                width += 1; // 英文字符
             }
         }
+
+        return width;
     }
 
     // 保存Workbook到本地文件