Procházet zdrojové kódy

质检-表单模板下载excel错乱问题处理

LHB před 4 měsíci
rodič
revize
baae6ad1ba

+ 69 - 2
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsTreeContractController.java

@@ -383,7 +383,57 @@ public class WbsTreeContractController extends BladeController {
                 Sheet poiSheet = poiWorkbook.getSheetAt(0); //获取第一个工作表
                 //存储需要修改的单元格和相关信息的列表
                 List<CellModificationInfo> cellsToModify = new ArrayList<>();
+                //解析html 获取合并单元格
+                InputStream inputStreamByUrl = FileUtils.getInputStreamByUrl(tab.getHtmlUrl());
+                String htmlString = IoUtil.readToString(inputStreamByUrl);
+                Document doc = Jsoup.parse(htmlString);
+                Element table = doc.select("table").first();
+                Elements rows = table.select("tr");
+                //最大列数
+                int maxColumns = calculateMaxColumns(rows);
+                List<CellRangeAddress> mergedRegions = new ArrayList<>();
+                // 保存需要保留的单元格内容和样式
+                Map<CellRangeAddress, String> data = new HashMap<>();
+                // 记录每个单元格的位置和合并信息
+                for (Element row1 : rows) {
+                    Elements cells = row1.select("td, th");
+                    for (Element cell : cells) {
+
+                        int rowspan = cell.hasAttr("rowspan") ? Integer.parseInt(cell.attr("rowspan")) : -1;
+                        int colspan = cell.hasAttr("colspan") ? Integer.parseInt(cell.attr("colspan")) : -1;
+                        int x1 = cell.hasAttr("x1") ? Integer.parseInt(cell.attr("x1")) - 1 : -1;//起始列
+                        int x2 = cell.hasAttr("x2") ? Integer.parseInt(cell.attr("x2")) - 1 : -1;//结束列
+                        int y1 = cell.hasAttr("y1") ? Integer.parseInt(cell.attr("y1")) - 1 : -1;//起始行
+                        int y2 = cell.hasAttr("y2") ? Integer.parseInt(cell.attr("y2")) - 1 : -1;//结束行
+                        // 记录合并区域
+                        if (x1 != -1 && x2 != -1 && y1 != -1 && y2 != -1) {
+                            if(rowspan != -1 || colspan != -1){
+                                CellRangeAddress region = new CellRangeAddress(y1, y2, x1, x2);
+                                mergedRegions.add(region);
+                                data.put(region, cell.text());
+                            }
+                        }
+                    }
+                }
+                // 按顺序合并单元格(从上到下、从左到右)
+                for (int i = poiSheet.getNumMergedRegions() - 1; i >= 0; i--) {
+                    poiSheet.removeMergedRegion(i);
+                }
+                for (CellRangeAddress region : mergedRegions) {
+                    poiSheet.addMergedRegion(region);
+                }
+
                 for (Row row : poiSheet) {
+                    //判断当前行是否是最大列 如果不是 就补充到最大列
+                    short lastCellNum = row.getLastCellNum();
+                    if(maxColumns > lastCellNum){
+                        for (int i = maxColumns - 1; i > lastCellNum; i--) {
+                            row.createCell(i);
+                            Cell cell = row.getCell(i);
+                            //设置新单元格的样式为第一个单元格的样式
+                            cell.setCellStyle(row.getCell(0).getCellStyle());
+                        }
+                    }
                     for (Cell cell : row) {
                         int cellType = cell.getCellType();
                         if (cellType == CellType.STRING.getCode() && ObjectUtil.isNotEmpty(cell.getStringCellValue())) {
@@ -393,6 +443,9 @@ public class WbsTreeContractController extends BladeController {
                         //获取单元格所属的合并单元格区域
                         CellRangeAddress mergedRegion = findMergedRegion(poiSheet, cell.getRowIndex(), cell.getColumnIndex());
                         if (mergedRegion != null) {
+                            //合并单元格的数据 为之前记录的数据
+                            cell.setCellValue(data.get(mergedRegion));
+
                             //存储需要修改的合并单元格信息
                             cellsToModify.add(new CellModificationInfo(cell, mergedRegion));
                         }
@@ -402,10 +455,10 @@ public class WbsTreeContractController extends BladeController {
                 //遍历结束后,实际修改单元格样式和内容
                 for (CellModificationInfo info : cellsToModify) {
                     Cell cell = info.getCell();
-                    if (info.hasStringContent()) {
+                    //只更新非合并单元格的数据
+                    if (info.getMergedRegion() == null && info.hasStringContent()) {
                         cell.setCellValue(info.getStringContent());
                     }
-
                     //复制单元格样式
                     CellStyle cellStyle = poiWorkbook.createCellStyle();
                     CellStyle sourceCellStyle = cell.getCellStyle(); //获取原单元格的样式
@@ -452,6 +505,20 @@ public class WbsTreeContractController extends BladeController {
             }
         }
     }
+    // 计算最大列数以对齐所有行
+    private static int calculateMaxColumns(Elements rows) {
+        return rows.stream()
+                .mapToInt(row -> row.select("td, th").stream()
+                        .mapToInt(c -> Math.max(getColspan(c), 1))
+                        .sum())
+                .max().orElse(0);
+    }
+
+    private static int getColspan(Element cell) {
+        String attr = cell.attr("colspan");
+        return attr.isEmpty() ? 1 : Integer.parseInt(attr);
+    }
+
 
     //在CellModificationInfo类中,根据需要存储单元格内容和合并单元格信息
     static class CellModificationInfo {