先上代码
main
方法代码
EasyExcel.write()
.file(Files.newOutputStream(Paths.get("test.xlsx"))).sheet("sheet1")
.registerWriteHandler(new CellStyleWriteHandler())
.head(new ArrayList<List<String>>() {{
add(Collections.singletonList("ID"));
add(Collections.singletonList("Name"));
}})
.doWrite(new ArrayList<List<String>>() {{
add(Arrays.asList("123", "789"));
add(Arrays.asList("465", "987"));
}});
CellStyleWriteHandler
类代码
import com.alibaba.excel.util.BooleanUtils;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.handler.context.CellWriteHandlerContext;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFill;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTGradientFill;
public class CellStyleWriteHandler implements CellWriteHandler {
private XSSFCellStyle headCellStyle = null;
private XSSFCellStyle contentCellStyle = null;
@Override
public void afterCellDispose(CellWriteHandlerContext context) {
Sheet sheet = context.getWriteSheetHolder().getSheet();
Cell cell = context.getCell();
// 拿到poi的workbook
Workbook workbook = context.getWriteWorkbookHolder().getWorkbook();
if (!BooleanUtils.isNotTrue(context.getHead())) {
if (Utils.isEmpty(headCellStyle)) {
//设置首行冻结
sheet.createFreezePane(0, 1, 0, 1);
// 这里千万记住 想办法能复用的地方把他缓存起来 一个表格最多创建6W个样式
// 不同单元格尽量传同一个 cellStyle
headCellStyle = (XSSFCellStyle) workbook.createCellStyle();
// 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND
headCellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
Font cellFont = workbook.createFont();
cellFont.setFontName("Arial");
cellFont.setBold(true);
cellFont.setFontHeightInPoints((short) 10);
headCellStyle.setFont(cellFont);
// 水平居中
headCellStyle.setAlignment(HorizontalAlignment.CENTER);
//垂直居中
headCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
//自动换行
headCellStyle.setWrapText(true);
//边框
headCellStyle.setBorderLeft(BorderStyle.MEDIUM);
headCellStyle.setBorderRight(BorderStyle.MEDIUM);
headCellStyle.setLeftBorderColor(IndexedColors.WHITE.getIndex());
headCellStyle.setRightBorderColor(IndexedColors.WHITE.getIndex());
//设置渐变色
//get fill index used in this CellStyle
int fillIdx = (int) headCellStyle.getCoreXf().getFillId();
//get the low level CTFill used in this CellStyle
CTFill ctfill = ((SXSSFWorkbook) workbook).getXSSFWorkbook().getStylesSource().getFillAt(fillIdx).getCTFill();
//unset the pattern fill
ctfill.unsetPatternFill();
CTGradientFill ctgradientfill = ctfill.addNewGradientFill();
ctgradientfill.setDegree(90.0);
ctgradientfill.addNewStop().setPosition(0.0);
ctgradientfill.getStopArray(0).addNewColor().setRgb(new byte[]{(byte) 0xFF, (byte) 0xFF, (byte) 0xFF});
ctgradientfill.addNewStop().setPosition(1);
ctgradientfill.getStopArray(1).addNewColor().setRgb(new byte[]{(byte) 0xF3, (byte) 0xDD, (byte) 0xDC});
}
cell.setCellStyle(headCellStyle);
//设置首行行高
cell.getRow().setHeight((short) (20 * 20));
//设置列宽
sheet.setColumnWidth(cell.getColumnIndex(), (int) (14.5 * 256));
// 这里要把 WriteCellData的样式清空, 不然后面还有一个拦截器 FillStyleCellWriteHandler 默认会将 WriteCellStyle 设置到
// cell里面去 会导致自己设置的不一样
context.getFirstCellData().setWriteCellStyle(null);
} else {
//设置内容行高
cell.getRow().setHeight((short) (13 * 20));
if (Utils.isEmpty(contentCellStyle)) {
contentCellStyle = (XSSFCellStyle) workbook.createCellStyle();
Font cellFont = workbook.createFont();
cellFont.setFontName("Arial");
cellFont.setFontHeightInPoints((short) 9);
contentCellStyle.setFont(cellFont);
//垂直居中
contentCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
//自动换行
contentCellStyle.setWrapText(true);
}
cell.setCellStyle(contentCellStyle);
//设置内容行高
cell.getRow().setHeight((short) (12.5 * 20));
}
}
}
最终效果
pom依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>ooxml-schemas</artifactId>
<version>1.4</version>
</dependency>
常见问题
main
方法中主要注意第三行的registerWriteHandler
方法、这里注入的CellStyleWriteHandler
中实现了单元格样式的配置、具体使用方式请参考EasyExcel官方文档。
表头样式不生效
注意查看你是否缺少CellStyleWriteHandler
类第73行代码、这里的代码用于清空EasyExcel默认表头样式。
CTFill
类找不到
检查pom文件是否引入了ooxml-schemas
、具体详情请参考这篇文章java - Apache poi 将渐变颜色应用于单元格 - 堆栈溢出 (stackoverflow.com)。
为何记录本文
- 再做修改表头背景色时虽然看过EasyExcel官网、但是发现只能用
IndexedColors
、最后掉入POI样式不生效的坑、在里面挣扎了一天、找了各种写法、最后还是在官方文档中找到解决方案、需要使用context.getFirstCellData().setWriteCellStyle(null);
去除默认样式、第一次看文档时其实已经快看到这了、往下多翻几行就是。所以在这里记录一下、希望各位引以为戒。 - 关于使用POI实现渐变背景色、试了几个AI发现都是在乱回答、百度也搜不到准确的结果、最后还是用bing国际版用英文关键词
poi Gradient excel
才搜到结果、希望这篇文章能收录到国内搜索引里吧、顺便喂给AI、让未来有同样需求的兄弟们少走点弯路。