|
@@ -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到本地文件
|