Stories

Detail Return Return

EasyExcel碰到問題記錄 - Stories Detail

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);
            }
        }
    }
}
user avatar AmbitionGarden Avatar yangrd Avatar alluxio_com Avatar ouysh1981 Avatar sectrend Avatar sean_5efd514dcd979 Avatar _61e9689d548cc Avatar ifat3 Avatar q8462880 Avatar
Favorites 9 users favorite the story!
Favorites

Add a new Comments

Some HTML is okay.