开发者社区 > 博文 > EasyExcel碰到问题记录
分享
  • 打开微信扫码分享

  • 点击前往QQ分享

  • 点击前往微博分享

  • 点击复制链接

EasyExcel碰到问题记录

  • loveofyou
  • 2025-01-10
  • IP归属:北京
  • 4浏览

    1、富文本中文字设置不同颜色和字体不生效

                    String stringCellValue = cell.getStringCellValue();
                    if (StringUtils.isNotBlank(stringCellValue) && stringCellValue.contains(startIndex) && stringCellValue.contains(endIndex)) {
                        RichTextString richStringCellValue = cell.getRichStringCellValue();
                        Font redFont = workbook.createFont();
                        redFont.setColor(IndexedColors.RED.getIndex());
    
                        if (richStringCellValue instanceof XSSFRichTextString) {
                            XSSFRichTextString xssfRichTextString = new XSSFRichTextString(cell.getStringCellValue());
                            xssfRichTextString.applyFont(stringCellValue.indexOf(startIndex),stringCellValue.indexOf(endIndex) +endIndex.length() ,redFont);
                            cell.setCellValue(xssfRichTextString);
                        } else if (richStringCellValue instanceof HSSFRichTextString) {
                            HSSFRichTextString hssfRichTextString = new HSSFRichTextString(cell.getStringCellValue());
                            hssfRichTextString.applyFont(stringCellValue.indexOf(startIndex),stringCellValue.indexOf(endIndex) +endIndex.length() ,redFont);
                            cell.setCellValue(hssfRichTextString);
                        }
                        cellStyle.setFont(redFont);
                    } else {
                        // 清空样式
                        cell.setCellStyle(cellStyle);
                    }

    上面代码设置了富文本指定范围的文字设置新的字体,但是生成的文件还是不生效。

    EasyExcelFactory.write(new File(pathName)).head(titleList())
            .inMemory(Boolean.TRUE)  // 指定这个属性为true,才支持富文本和注释
            .registerWriteHandler(new HeadRowWriteHandler()).sheet(0).doWrite(Lists.newArrayList());

    原因:

    在 EasyExcel 中,inMemory 方法用于设置是否在内存中生成 Excel 文件。默认情况下,EasyExcel 会在磁盘上创建一个缓存文件,然后将数据写入这个缓存文件,最后再将缓存文件写入到 Excel 文件中。

    如果你调用 inMemory(true),EasyExcel 将会在内存中生成 Excel 文件,而不是使用缓存文件。这意味着:

    1. 更快的写入速度:因为不需要频繁地读写磁盘,内存模式下的写入速度通常会更快。
    2. 支持 Comment 和 RichTextString:如果你需要在单元格中添加注释或使用富文本字符串,这些功能只能在内存模式下使用。
    3. 限制大文件写入:内存模式下,所有的数据都会被加载到内存中,这可能会导致内存溢出问题,特别是当你处理大型数据集时。

    使用内存模式的主要优点是它可以支持更复杂的单元格操作,如添加注释或使用富文本字符串。然而,如果你的数据量很大,可能需要避免使用内存模式以防止内存问题。


    2、冻结单元格

    可以通过sheet.createFreezePane(column,row);方法指定冻结的列和行索引。

    import com.alibaba.excel.write.handler.SheetWriteHandler;
    import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
    import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
    import org.apache.poi.ss.usermodel.Sheet;
    
    import java.util.Objects;
    
    /**
     * 冻结单元格
     **/
    public class FreezePaneWriteHandler implements SheetWriteHandler {
    
        private int column;
    
        private int row;
    
        public FreezePaneWriteHandler(Integer column, Integer row) {
            this.column = column;
            this.row = row;
        }
    
        @Override
        public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
            Sheet sheet = writeSheetHolder.getSheet();
            if (Objects.nonNull(sheet)) {
                sheet.createFreezePane(column,row);
            }
        }
    }

    3、不合并单元格

    Easyexcel使用中,生成多行表头模版时,同一行如果多个列内容一样,会被自动合并单元格,要避免这个问题,需要通过特殊处理。

    import com.alibaba.excel.constant.OrderConstant;
    import com.alibaba.excel.write.handler.RowWriteHandler;
    import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
    import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
    import org.apache.commons.collections4.CollectionUtils;
    import org.apache.poi.ss.usermodel.Row;
    import org.apache.poi.ss.usermodel.Sheet;
    import org.apache.poi.ss.util.CellRangeAddress;
    
    import java.util.Set;
    
    /**
     * 表头不合并策略
     * @author sunlei61
     * @date 2024/8/17
     **/
    public class HeadNoMergeWriteHandler implements RowWriteHandler {
        /**
         * 指定哪些行需要合并单元格
         */
        private Set<Integer> rowNum;
        /**
         * 排除哪些不合并单元格的行
         */
        private Set<Integer> excludeRowNum;
    
        @Override
        public int order() {
            return OrderConstant.FILL_STYLE + 3;
        }
    
        public HeadNoMergeWriteHandler(){}
    
        public HeadNoMergeWriteHandler(Set<Integer> rowNum){
            this.rowNum = rowNum;
        }
    
        public HeadNoMergeWriteHandler(Set<Integer> rowNum, Set<Integer> excludeRowNum){
            this.rowNum = rowNum;
            this.excludeRowNum = excludeRowNum;
        }
    
        @Override
        public void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Integer relativeRowIndex, Boolean isHead) {
           if (!isHead){
               return;
           }
    
            if (CollectionUtils.isEmpty(rowNum) || rowNum.contains(row.getRowNum())) {
                // 如果是表头,取消合并
                Sheet sheet = writeSheetHolder.getSheet();
                int totalMergedRegions = sheet.getNumMergedRegions();
                for (int i = totalMergedRegions - 1; i >= 0; i--) {
                    CellRangeAddress mergedRegion = sheet.getMergedRegion(i);
                    if (CollectionUtils.isEmpty(excludeRowNum) || !excludeRowNum.contains(mergedRegion.getFirstRow())) {
                        sheet.removeMergedRegion(i);
                    }
                }
            }
        }
    }
    

    4、列宽自适应宽度

    生成表格列比较多,制定特定的宽度会让表格很长,即使单元格内容一个字,也会很宽,不是很友好,可以通过设置sheet的自适应宽度来设置。

    import com.alibaba.excel.write.handler.RowWriteHandler;
    import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
    import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
    import org.apache.commons.collections4.CollectionUtils;
    import org.apache.poi.ss.usermodel.Row;
    import org.apache.poi.ss.usermodel.Sheet;
    
    import java.util.Set;
    
    /**
     * 列宽度自动适应
     * @author sunlei61
     * @date 2024/9/26
     **/
    public class AutoSizeColumnWriterHandler implements RowWriteHandler {
        /**不需要自动适用宽度的列集合*/
        private Set<Integer> excludeColumns;
    
        public AutoSizeColumnWriterHandler(){
        }
    
        public AutoSizeColumnWriterHandler(Set<Integer> excludeColumns) {
           this.excludeColumns = excludeColumns;
        }
    
        @Override
        public void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Integer relativeRowIndex, Boolean isHead) {
            Integer sheetNo = writeSheetHolder.getSheetNo();
            if (sheetNo == 0 ) {
                Sheet sheet = writeSheetHolder.getSheet();
                int columns = row.getPhysicalNumberOfCells();
                for (int i = 0; i < columns; i++) {
                    if (CollectionUtils.isNotEmpty(excludeColumns) && excludeColumns.contains(i)) {
                        continue;
                    }
                    sheet.autoSizeColumn(i);
                }
            }
        }
    }


    文章数
    3
    阅读量
    31