EasyExcel 碰到问题记录
- 2025-01-13 北京
本文字数:3512 字
阅读完需:约 12 分钟
作者:京东工业 孙磊
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); } } }}
版权声明: 本文为 InfoQ 作者【京东科技开发者】的原创文章。
原文链接:【http://xie.infoq.cn/article/79d7f11b9ffa9916f923d4b83】。文章转载请联系作者。
京东科技开发者
拥抱技术,与开发者携手创造未来! 2018-11-20 加入
我们将持续为人工智能、大数据、云计算、物联网等相关领域的开发者,提供技术干货、行业技术内容、技术落地实践等文章内容。京东云开发者社区官方网站【https://developer.jdcloud.com/】,欢迎大家来玩









评论