fei
4 天以前 5de5db24efe1b25896c37f395124a207584bcb38
ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtilManySheet.java
@@ -14,12 +14,13 @@
import com.ruoyi.common.utils.file.ImageUtils;
import com.ruoyi.common.utils.reflect.ReflectUtils;
import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFDataValidation;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
import org.apache.poi.hssf.usermodel.HSSFDataValidation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -58,6 +59,14 @@
     * 导出类型(EXPORT:导出数据;IMPORT:导入模板)
     */
    private Excel.Type type;
    public Workbook getWb() {
        return wb;
    }
    public void setWb(Workbook wb) {
        this.wb = wb;
    }
    /**
     * 工作薄对象
@@ -289,10 +298,34 @@
                if(index == 1) {
                    // 合并第一行的前5个单元格
                    sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 6));
                    // 获取页面设置
                    // 必须先设置为true
                    // 页面布局设置
                    sheet.setAutobreaks(true);
                    sheet.setFitToPage(true);
                    // 创建行并设置高度
                    // 获取打印设置
                    PrintSetup printSetup = sheet.getPrintSetup();
                    // 设置为1页宽度
                    printSetup.setFitWidth((short) 1);   // 宽度调整为1页
                    printSetup.setFitHeight((short) 0);  // 高度不限制
                    // 其他打印设置
                    printSetup.setPaperSize(PrintSetup.A4_PAPERSIZE);  // A4纸
                    printSetup.setLandscape(false);  // 纵向打印
                    // 设置页边距
                    sheet.setMargin(Sheet.LeftMargin, 0.5);
                    sheet.setMargin(Sheet.RightMargin, 0.5);
                    // 设置打印区域,从第0行到第1000行,第0列到第20列(根据实际情况调整)
                 //   sheet.setPrintArea(0, 0, 20, 0, 1000);
                    // 如果是index为1的sheet,设置顶端标题行
                        // 将第1行(索引为0)设置为每页重复的标题行
                        sheet.setRepeatingRows(CellRangeAddress.valueOf("$1:$4"));
                     row = sheet.createRow(0);
                    row.setHeight((short)(40 * 40));
                    row.setHeight((short) (37*20));
                    // 创建单元格并添加图片
                    Cell cell = row.createCell(0);
@@ -301,16 +334,17 @@
                      //  if (Files.exists(Paths.get(imagePath))) {
                          //  byte[] imageBytes = Files.readAllBytes(Paths.get(imagePath));
                            // 将byte数组转换成inputstream,以便插入到Excel中
                            ClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + 5),
                            ClientAnchor anchor = new HSSFClientAnchor(0, 0, 0, 100, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + 5),
                                    cell.getRow().getRowNum() + 1);
                            // 设置锚点类型为MOVE_AND_RESIZE,使图片可以随单元格调整大小
                            anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE);
                                    // 计算居中位置
                    int col1 = 1; // 中间列
                    int col2 = col1 + 5;
                    int col1 = 3; // 中间列
                    int col2 = col1 + 2;
                    anchor.setCol1(col1);
                    anchor.setCol2(col2);
                    anchor.setRow1(0);
                    anchor.setRow2(1);
                  //          anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE);
//                            anchor.set
//                            anchor.setHorizontallyCenter(true);
@@ -330,27 +364,54 @@
                   //     log.error("添加图片失败: {}", e.getMessage());
                   // }
                    row = sheet.createRow(1);
                    row.setHeight((short) (32.5*20));
                    sheet.addMergedRegion(new CellRangeAddress(1, 1, 0, 6));
                    Cell titleCell = row.createCell(0);
                    titleCell.setCellValue("卷内目录");
                    // 设置加粗和居中样式
                    titleCell.setCellValue("卷      内      目      录");
                    // 设置加粗、宋体、18号字体和居中样式
                    CellStyle style = wb.createCellStyle();
                    Font font = wb.createFont();
                    font.setBold(true);
                    font.setFontName("宋体");
                    font.setFontHeightInPoints((short) 18);
                    style.setFont(font);
                    style.setAlignment(HorizontalAlignment.CENTER);
                    titleCell.setCellStyle(style);
                    row = sheet.createRow(2);
                    row.setHeight((short) (20*20));
               //
                    row.createCell(4).setCellValue("档号:");
                    Cell dnumCell = row.createCell(4);
                    dnumCell.setCellValue("档号:");
                    // 设置加粗、宋体、18号字体和居中样式
                    CellStyle style1 = wb.createCellStyle();
                    Font font1 = wb.createFont();
                    font1.setBold(true);
                    font1.setFontName("宋体");
                    font1.setFontHeightInPoints((short) 12);
                    style1.setFont(font1);
                    style1.setAlignment(HorizontalAlignment.RIGHT);
                    dnumCell.setCellStyle(style1);
                 //   row.createCell(4).setCellValue("档号:");
                    //拿到档号
                    String recordId = list.get(index).getRecordId();
                    row.createCell(5).setCellValue(recordId);
                    // 创建带有下划线样式的单元格
                    Cell recordIdCell = row.createCell(5);
                    recordIdCell.setCellValue(recordId);
                    // 创建下划线样式
                    CellStyle underlineStyle = wb.createCellStyle();
                    Font underlineFont = wb.createFont();
                    underlineFont.setFontName("宋体");
                    underlineFont.setFontHeightInPoints((short) 11);
                    underlineFont.setUnderline(Font.U_SINGLE); // 设置下划线
                    underlineStyle.setFont(underlineFont);
                    recordIdCell.setCellStyle(underlineStyle);
                    row = sheet.createRow(3);
                    row.setHeight((short) (17.5*20));
                       row = sheet.createRow(4);
//                     // 添加总页数和当前页码信息
//                     row.createCell(5).setCellValue("总页数: " + list.size() + ", 当前页: " + (index + 1));
//   row = sheet.createRow(4);
                    column = 0;
                } else {
                    // 普通sheet处理
                 //   recordId = (DocumentMaterialsVo)list.get(0)
@@ -461,7 +522,7 @@
//        int endNo = Math.min(startNo + sheetSize, list.size());
        for (int i = 0; i < list.size(); i++) {
            if(index==1)
                row = sheet.createRow(i + 4 );
                row = sheet.createRow(i + 5 );
            else
                row = sheet.createRow(i + 1 );
            // 得到导出对象.
@@ -497,48 +558,74 @@
        style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        style.setBorderBottom(BorderStyle.THIN);
        style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        // 设置自动换行
        style.setWrapText(true);
        Font dataFont = wb.createFont();
        dataFont.setFontName("Arial");
        dataFont.setFontHeightInPoints((short) 10);
        dataFont.setFontHeightInPoints((short) 12);
        style.setFont(dataFont);
        styles.put("data", style);
        style = wb.createCellStyle();
        style.cloneStyleFrom(styles.get("data"));
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        style.setFillForegroundColor(IndexedColors.GREY_50_PERCENT.getIndex());
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        Font headerFont = wb.createFont();
        headerFont.setFontName("Arial");
        headerFont.setFontHeightInPoints((short) 10);
        headerFont.setBold(true);
        headerFont.setColor(IndexedColors.WHITE.getIndex());
        style.setFont(headerFont);
        styles.put("header", style);
        // 创建表头样式映射,根据Excel注解动态生成
        Map<String, CellStyle> headerStyles = new HashMap<String, CellStyle>();
        for (Object[] os : fields)
        {
            Excel excel = (Excel) os[1];
            String key = StringUtils.format("header_{}_{}_{}_{}", excel.headerColor(), excel.headerBackgroundColor(), excel.headerFontName(), excel.headerFontBold());
            if (!headerStyles.containsKey(key))
            {
                 style = wb.createCellStyle();
                style.cloneStyleFrom(styles.get("data"));
                style.setAlignment(HorizontalAlignment.CENTER);
                style.setVerticalAlignment(VerticalAlignment.CENTER);
                // 根据注解设置表头背景色 - 已注释,表头不显示背景色
                /*if (excel.headerBackgroundColor() != IndexedColors.WHITE) {
                    style.setFillForegroundColor(excel.headerBackgroundColor().index);
                    style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
                }*/
                // 设置表头自动换行
                style.setWrapText(true);
                Font headerFont = wb.createFont();
                headerFont.setFontName(excel.headerFontName());
                headerFont.setFontHeightInPoints((short) 12);
                headerFont.setBold(excel.headerFontBold());
                headerFont.setColor(excel.headerColor().index);
                style.setFont(headerFont);
                headerStyles.put(key, style);
            }
        }
        styles.putAll(headerStyles);
        style = wb.createCellStyle();
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        Font totalFont = wb.createFont();
        totalFont.setFontName("Arial");
        totalFont.setFontHeightInPoints((short) 10);
        totalFont.setFontHeightInPoints((short) 12);
        style.setFont(totalFont);
        // 总计行也设置自动换行
        style.setWrapText(true);
        styles.put("total", style);
        style = wb.createCellStyle();
        style.cloneStyleFrom(styles.get("data"));
        style.setAlignment(HorizontalAlignment.LEFT);
        // 左对齐样式也设置自动换行
        style.setWrapText(true);
        styles.put("data1", style);
        style = wb.createCellStyle();
        style.cloneStyleFrom(styles.get("data"));
        style.setAlignment(HorizontalAlignment.CENTER);
        // 居中对齐样式也设置自动换行
        style.setWrapText(true);
        styles.put("data2", style);
        style = wb.createCellStyle();
        style.cloneStyleFrom(styles.get("data"));
        style.setAlignment(HorizontalAlignment.RIGHT);
        // 右对齐样式也设置自动换行
        style.setWrapText(true);
        styles.put("data3", style);
        return styles;
@@ -553,7 +640,9 @@
        // 写入列信息
        cell.setCellValue(attr.name());
        setDataValidation(attr, row, column);
        cell.setCellStyle(styles.get("header"));
        // 根据Excel注解动态选择表头样式
        String key = StringUtils.format("header_{}_{}_{}_{}", attr.headerColor(), attr.headerBackgroundColor(), attr.headerFontName(), attr.headerFontBold());
        cell.setCellStyle(styles.get(key));
        return cell;
    }
@@ -570,7 +659,7 @@
        } else if (Excel.ColumnType.NUMERIC == attr.cellType()) {
            cell.setCellValue(StringUtils.contains(Convert.toStr(value), ".") ? Convert.toDouble(value) : Convert.toInt(value));
        } else if (Excel.ColumnType.IMAGE == attr.cellType()) {
            ClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + 1),
            ClientAnchor anchor = new HSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + 1),
                    cell.getRow().getRowNum() + 1);
            String imagePath = Convert.toStr(value);
            if (StringUtils.isNotEmpty(imagePath)) {
@@ -617,12 +706,12 @@
        // 如果设置了提示信息则鼠标放上去提示.
        if (StringUtils.isNotEmpty(attr.prompt())) {
            // 这里默认设了2-101列提示.
            setXSSFPrompt(sheet, "", attr.prompt(), 1, 100, column, column);
            setHSSFPrompt(sheet, "", attr.prompt(), 1, 100, column, column);
        }
        // 如果设置了combo属性则本列只能选择不能输入
        if (attr.combo().length > 0) {
            // 这里默认设了2-101列只能选择不能输入.
            setXSSFValidation(sheet, attr.combo(), 1, 100, column, column);
            setHSSFValidation(sheet, attr.combo(), 1, 100, column, column);
        }
    }
@@ -632,15 +721,23 @@
    public Cell addCell(Excel attr, Row row, T vo, Field field, int column) {
        Cell cell = null;
        try {
            // 设置行高
            row.setHeight(maxHeight);
            // 设置行高为自动调整
            row.setHeight((short) -1);
            // 根据Excel中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列.
            if (attr.isExport()) {
                // 创建cell
                cell = row.createCell(column);
//                attr.align();
//                int align = attr.align().value;
//                cell.setCellStyle(styles.get("data" + (align >= 1 && align <= 3 ? align : "")));
                // 设置单元格样式
                HorizontalAlignment align = attr.align();
                String styleKey = "data";
                if (align == HorizontalAlignment.LEFT) {
                    styleKey = "data1";
                } else if (align == HorizontalAlignment.CENTER) {
                    styleKey = "data2";
                } else if (align == HorizontalAlignment.RIGHT) {
                    styleKey = "data3";
                }
                cell.setCellStyle(styles.get(styleKey));
                // 用于读取对象中的属性
                Object value = getTargetValue(vo, field, attr);
@@ -666,7 +763,7 @@
    }
    /**
     * 设置 POI XSSFSheet 单元格提示
     * 设置 POI HSSFSheet 单元格提示
     *
     * @param sheet         表单
     * @param promptTitle   提示标题
@@ -676,7 +773,7 @@
     * @param firstCol      开始列
     * @param endCol        结束列
     */
    public void setXSSFPrompt(Sheet sheet, String promptTitle, String promptContent, int firstRow, int endRow,
    public void setHSSFPrompt(Sheet sheet, String promptTitle, String promptContent, int firstRow, int endRow,
                              int firstCol, int endCol) {
        DataValidationHelper helper = sheet.getDataValidationHelper();
        DataValidationConstraint constraint = helper.createCustomConstraint("DD1");
@@ -698,7 +795,7 @@
     * @param endCol   结束列
     * @return 设置好的sheet.
     */
    public void setXSSFValidation(Sheet sheet, String[] textlist, int firstRow, int endRow, int firstCol, int endCol) {
    public void setHSSFValidation(Sheet sheet, String[] textlist, int firstRow, int endRow, int firstCol, int endCol) {
        DataValidationHelper helper = sheet.getDataValidationHelper();
        // 加载下拉列表内容
        DataValidationConstraint constraint = helper.createExplicitListConstraint(textlist);
@@ -707,11 +804,9 @@
        // 数据有效性对象
        DataValidation dataValidation = helper.createValidation(constraint, regions);
        // 处理Excel兼容性问题
        if (dataValidation instanceof XSSFDataValidation) {
            dataValidation.setSuppressDropDownArrow(true);
            dataValidation.setShowErrorBox(true);
        } else {
        if (dataValidation instanceof HSSFDataValidation) {
            dataValidation.setSuppressDropDownArrow(false);
            dataValidation.setShowErrorBox(true);
        }
        sheet.addValidationData(dataValidation);
@@ -908,7 +1003,7 @@
     * 创建一个工作簿
     */
    public void createWorkbook() {
        this.wb = new SXSSFWorkbook(500);
        this.wb = new HSSFWorkbook();
    }
    /**
@@ -926,6 +1021,42 @@
        } else {
            wb.setSheetName(index, sheetName + index);
        }
        // 设置页面属性
        sheet.setFitToPage(true);
        PrintSetup printSetup = sheet.getPrintSetup();
        printSetup.setPaperSize(PrintSetup.A4_PAPERSIZE); // 设置为A4纸张
        printSetup.setLandscape(false); // 纵向打印
        printSetup.setFitWidth((short) 1);  // 宽度调整为1页
        printSetup.setFitHeight((short) 0); // 0表示高度不限制页数(自动)
        // 设置页边距
        sheet.setMargin(Sheet.TopMargin, 1.0); // 增加顶部边距以容纳页眉
        sheet.setMargin(Sheet.BottomMargin, 0.5);
        sheet.setMargin(Sheet.LeftMargin, 0.5);
        sheet.setMargin(Sheet.RightMargin, 0.5);
        sheet.setMargin(Sheet.HeaderMargin, 0.5); // 设置页眉边距
        sheet.setMargin(Sheet.FooterMargin, 0.5); // 设置页脚边距
        // 设置打印区域,从第0行到第1000行,第0列到第20列(根据实际情况调整)
       //sheet.setPrintArea(0, 0, 20, 0, 1000);
        // 设置页眉,显示总页数和当前页码
        if (wb instanceof HSSFWorkbook) {
            HSSFWorkbook hssfWb = (HSSFWorkbook) wb;
            HSSFSheet hssfSheet = hssfWb.getSheetAt(index);
            HSSFHeader header = hssfSheet.getHeader();
            // 设置页眉字体
         //   header.setFontName("宋体");
         //   header.setFontSize((short) 10);
            // 设置页眉内容
            hssfSheet.setMargin(Sheet.HeaderMargin, 0.5);
            header.setRight("总页数: &P, 当前页: &N");
            // 设置页眉左对齐和右对齐内容(可选)
            header.setLeft("文档标题");
            header.setRight("&D &T"); // 日期和时间
        }
        // 如果是index为1的sheet,设置顶端标题行
        if (index == 1) {
            // 将第1行(索引为0)设置为每页重复的标题行
            sheet.setRepeatingRows(CellRangeAddress.valueOf("$1:$4"));
        }
    }
    /**
     * 创建工作表
@@ -936,6 +1067,40 @@
        this.sheet = wb.createSheet();
        this.styles = createStyles(wb);
        wb.setSheetName(index, sheetName);
        // 获取页面设置
        // 必须先设置为true
        sheet.setFitToPage(true);
        PrintSetup printSetup = sheet.getPrintSetup();
        printSetup.setPaperSize(PrintSetup.A4_PAPERSIZE); // 设置为A4纸张
        printSetup.setLandscape(false); // 纵向打印
        printSetup.setFitWidth((short) 1);  // 宽度调整为1页
        printSetup.setFitHeight((short) 0); // 0表示高度不限制页数(自动)
        // 设置页边距
        sheet.setMargin(Sheet.TopMargin, 1.0); // 增加顶部边距以容纳页眉
        sheet.setMargin(Sheet.BottomMargin, 0.5);
        sheet.setMargin(Sheet.LeftMargin, 0.5);
        sheet.setMargin(Sheet.RightMargin, 0.5);
        sheet.setMargin(Sheet.HeaderMargin, 0.5); // 设置页眉边距
        sheet.setMargin(Sheet.FooterMargin, 0.5); // 设置页脚边距
        // 设置打印区域,从第0行到第1000行,第0列到第20列(根据实际情况调整)
      //  sheet.setPrintArea(0, 0, 20, 0, 1000);
        // 设置页眉,显示总页数和当前页码
        if (wb instanceof HSSFWorkbook) {
            HSSFWorkbook hssfWb = (HSSFWorkbook) wb;
            HSSFSheet hssfSheet = hssfWb.getSheetAt(index);
            HSSFHeader header = hssfSheet.getHeader();
            // 设置页眉字体
           // header.setFontName("宋体");
           // header.setFontSize((short) 10);
            // 设置页眉内容
            hssfSheet.setMargin(Sheet.HeaderMargin, 2.1);
            header.setRight("共 &N 页   第 &P页");
        }
        // 如果是index为1的sheet,设置顶端标题行
        if (index == 1) {
            // 将第1行(索引为0)设置为每页重复的标题行
            sheet.setRepeatingRows(CellRangeAddress.valueOf("$1:$3"));
        }
    }
    /**
     * 获取单元格值
@@ -977,4 +1142,4 @@
        }
        return val;
    }
}
}