大家好,我是小白学编程。
最近在工作中遇到一个导出功能,要求导出表格不同列有不同的样式,我是用EasyExcel实现导出,并根据不同的列设置不同的样式
导出之后是这样的
一、依赖
首先需要引入相关的依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
二、EasyExcel
EasyExcel 中提供了很多样式策略,都放在 com.alibaba.excel.write.style 这个包路径下(version 2.2.2),有针对行样式的,有针对列样式的,还有针对单元格样式的,如下图
三、样式设置
1、常用策略
这个不是文章的重点!设置 EasyExcel 表格的样式相关的文章在网上有很多,查一下就能查到。
1.1、介绍
在 EasyExcel 中提供的样式策略中,HorizontalCellStyleStrategy 是提供的一个水平样式策略,这个是常用的,网上使用的比较多,通过设置构建这个策略对象基本上可以满足一般的要求了,比如:比如设置表头和内容的边框、底色、对齐方式、文字字体、文字颜色、文字大小等。设置完之后,需要创建 HorizontalCellStyleStrategy 对象,然后在导出文件时注册这个策略的 handler 即可。
可以进入 HorizontalCellStyleStrategy 这个类的看一下源码,它有两个构造方法
- 一个是传入一个表头样式和一个内容样式的
public HorizontalCellStyleStrategy(WriteCellStyle headWriteCellStyle, WriteCellStyle contentWriteCellStyle) {
this.headWriteCellStyle = headWriteCellStyle;
contentWriteCellStyleList = new ArrayList<WriteCellStyle>();
contentWriteCellStyleList.add(contentWriteCellStyle);
}
使用这个构造方法的效果是表头用同一种样式,所有的内容使用同一种样式
- 零一个是传入一个表头样式和一个内容样式集合
public HorizontalCellStyleStrategy(WriteCellStyle headWriteCellStyle,
List<WriteCellStyle> contentWriteCellStyleList) {
this.headWriteCellStyle = headWriteCellStyle;
this.contentWriteCellStyleList = contentWriteCellStyleList;
}
使用这个构造方法的效果是表头使用同一种样式,内容根据行序号使用不同的样式的斑马纹。使用样式的方式是根据行序号对集合的长度取模作为样式下标索引进行使用
protected void setContentCellStyle(Cell cell, Head head, Integer relativeRowIndex) {
if (contentCellStyleList == null || contentCellStyleList.isEmpty()) {
return;
}
cell.setCellStyle(contentCellStyleList.get(relativeRowIndex % contentCellStyleList.size()));
}
1.2、举个栗子
先创建一个表格样式的工具
public class ExcelStyleTool {
/**
* 设置excel样式
*/
public static HorizontalCellStyleStrategy getStyleStrategy() {
// 头的策略 样式调整
WriteCellStyle headWriteCellStyle = new WriteCellStyle();
//设置头部样式
setHeadStyle(headWriteCellStyle, true, true);
// 设置细边框
setBorder(headWriteCellStyle);
//表头字体样式
WriteFont headWriteFont = getHeadFont(IndexedColors.SKY_BLUE.getIndex());
headWriteCellStyle.setWriteFont(headWriteFont);
// 内容的策略
WriteCellStyle contentStyle = new WriteCellStyle();
//设置内容样式
setHeadStyle(headWriteCellStyle, false, false);
//设置边框
setBorder(contentStyle);
//内容字体
WriteFont contentWriteFont = getContentFont();
contentStyle.setWriteFont(contentWriteFont);
// 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现
return new HorizontalCellStyleStrategy(headWriteCellStyle, contentStyle);
}
/**
* 获取表头字体
* @param color
* @return
*/
private static WriteFont getHeadFont(Short color){
//表头字体样式
WriteFont headWriteFont = new WriteFont();
// 头字号
headWriteFont.setFontHeightInPoints((short) 12);
// 字体样式
headWriteFont.setFontName("微软雅黑");
// 字体颜色
headWriteFont.setColor(color);
// 字体加粗
headWriteFont.setBold(true);
return headWriteFont;
}
/**
* 获取内容字体
* @return
*/
private static WriteFont getContentFont(){
//内容字体
WriteFont contentWriteFont = new WriteFont();
// 内容字号
contentWriteFont.setFontHeightInPoints((short) 11);
// 字体样式
contentWriteFont.setFontName("宋体");
return contentWriteFont;
}
/**
*
* @param cellStyle
* @param wrappedFlag 自动换行标识,true:开启自动换行
* @param centerFlag 水平居中开关,true:开启水平居中
*/
private static void setHeadStyle(WriteCellStyle cellStyle, boolean wrappedFlag, boolean centerFlag){
// 头背景 白色
cellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
if(wrappedFlag){
// 自动换行
cellStyle.setWrapped(true);
}
if(centerFlag){
// 水平对齐方式
cellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
}
// 垂直对齐方式
cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
}
/**
* 设置边框
* @param cellStyle
*/
private static void setBorder(WriteCellStyle cellStyle){
// 设置细边框
cellStyle.setBorderBottom(BorderStyle.THIN);
cellStyle.setBorderLeft(BorderStyle.THIN);
cellStyle.setBorderRight(BorderStyle.THIN);
cellStyle.setBorderTop(BorderStyle.THIN);
// 设置边框颜色 25灰度
cellStyle.setBottomBorderColor(IndexedColors.BLACK.getIndex());
cellStyle.setTopBorderColor(IndexedColors.BLACK.getIndex());
cellStyle.setLeftBorderColor(IndexedColors.BLACK.getIndex());
cellStyle.setRightBorderColor(IndexedColors.BLACK.getIndex());
}
}
然后在导出文件时调用注册 writeHandler 即可使用,其中Test 是我导出文件的实体类
//导出文件
EasyExcel.write("E:\\Test\\testFile.xlsx", Test.class).sheet("测试")
.registerWriteHandler(ExcelStyleTool.getStyleStrategy()) //注册样式策略
.doWrite(data);
2、自定义策略
有的时候,使用给定的策略无法满足要求,比如不同列的表头文字想展示不同的颜色,不同列想使用不同的对齐方式。因为 HorizontalCellStyleStrategy 只能设置一个表头样式和按行设置的内容样式,所以像这种的要求无法满足
2.1、思路
可以根据 HorizontalCellStyleStrategy 这个类的内容构造一个自定义的样式格式,仿照这个类完成即可。首先创建一个自定义策略类,然后继承 AbstractCellStyleStrategy 抽象类,再参照 HorizontalCellStyleStrategy 中的内容进行改造即可
2.2、举个栗子
先定义一个自定义的样式策略
/**
* 自定义单元格样式
*/
public class CustomCellStyleStrategy extends AbstractCellStyleStrategy {
//这个是 easyexcel 的蓝色表头样式
private WriteCellStyle headWriteCellStyleBlue;
//这个是 easyexcel 的红色表头样式
private WriteCellStyle headWriteCellStyleRed;
//这个是 easyexcel 的左对齐内容样式
private List<WriteCellStyle> contentWriteCellStyleListLeft;
//这个是 easyexcel 的居中对其内容样式
private List<WriteCellStyle> contentWriteCellStyleListCenter;
//这个是 poi 的蓝色表头样式,中间会有一步转换
private CellStyle headCellStyleBlue;
//这个是 poi 的红色表头样式,中间会有一步转换
private CellStyle headCellStyleRed;
//这个是 poi 的左对齐内容样式,中间会有一步转换
private List<CellStyle> contentCellStyleListLeft;
//这个是 poi 的居中对齐内容样式,中间会有一步转换
private List<CellStyle> contentCellStyleListCenter;
//斑马纹构造方法
public CustomCellStyleStrategy(WriteCellStyle headWriteCellStyleBlue, WriteCellStyle headWriteCellStyleRed,
List<WriteCellStyle> contentWriteCellStyleListLeft,List<WriteCellStyle> contentWriteCellStyleListCenter) {
this.headWriteCellStyleBlue = headWriteCellStyleBlue;
this.headWriteCellStyleRed = headWriteCellStyleRed;
this.contentWriteCellStyleListLeft = contentWriteCellStyleListLeft;
this.contentWriteCellStyleListCenter = contentWriteCellStyleListCenter;
}
//统一样式的构造方法
public CustomCellStyleStrategy(WriteCellStyle headWriteCellStyleBlue, WriteCellStyle headWriteCellStyleRed,
WriteCellStyle contentWriteCellStyleLeft, WriteCellStyle contentWriteCellStyleCenter) {
this.headWriteCellStyleBlue = headWriteCellStyleBlue;
this.headWriteCellStyleRed = headWriteCellStyleRed;
contentWriteCellStyleListLeft = new ArrayList<WriteCellStyle>();
contentWriteCellStyleListLeft.add(contentWriteCellStyleLeft);
contentWriteCellStyleListCenter = new ArrayList<>();
contentWriteCellStyleListCenter.add(contentWriteCellStyleCenter);
}
//实例化后进行 easyexcel -> poi 样式的转换
@Override
protected void initCellStyle(Workbook workbook) {
if (headWriteCellStyleBlue != null) {
headCellStyleBlue = StyleUtil.buildHeadCellStyle(workbook, headWriteCellStyleBlue);
}
if (headWriteCellStyleRed != null) {
headCellStyleRed = StyleUtil.buildHeadCellStyle(workbook, headWriteCellStyleRed);
}
if (contentWriteCellStyleListLeft != null && !contentWriteCellStyleListLeft.isEmpty()) {
contentCellStyleListLeft = new ArrayList<CellStyle>();
for (WriteCellStyle writeCellStyle : contentWriteCellStyleListLeft) {
contentCellStyleListLeft.add(StyleUtil.buildContentCellStyle(workbook, writeCellStyle));
}
}
if (contentWriteCellStyleListCenter != null && !contentWriteCellStyleListCenter.isEmpty()) {
contentCellStyleListCenter = new ArrayList<CellStyle>();
for (WriteCellStyle writeCellStyle : contentWriteCellStyleListCenter) {
contentCellStyleListCenter.add(StyleUtil.buildContentCellStyle(workbook, writeCellStyle));
}
}
}
//设置表头样式
@Override
protected void setHeadCellStyle(Cell cell, Head head, Integer relativeRowIndex) {
Integer columnIndex = head.getColumnIndex();
//此处可以根据不同的需求设置不同列使用哪种策略
if(columnIndex == 1 || columnIndex == 2 || columnIndex == 3 || columnIndex == 4){
if (headCellStyleRed == null) {
return;
}
cell.setCellStyle(headCellStyleRed);
} else {
if (headCellStyleBlue == null) {
return;
}
cell.setCellStyle(headCellStyleBlue);
}
}
//设置内容样式
@Override
protected void setContentCellStyle(Cell cell, Head head, Integer relativeRowIndex) {
int columnIndex= cell.getColumnIndex();
//同样,根据不同的列编号选择使用不同的内容样式
if(columnIndex == 10 || columnIndex == 13){
if (contentCellStyleListCenter == null || contentCellStyleListCenter.isEmpty()) {
return;
}
cell.setCellStyle(contentCellStyleListCenter.get(relativeRowIndex % contentCellStyleListCenter.size()));
} else {
if (contentCellStyleListLeft == null || contentCellStyleListLeft.isEmpty()) {
return;
}
cell.setCellStyle(contentCellStyleListLeft.get(relativeRowIndex % contentCellStyleListLeft.size()));
}
}
}
然后再在表格样式工具类中取构造这个自定义样式策略,在 ExcelStyleTool 工具类中添加如下代码
/**
* 设置自定义单元格策略
* @return
*/
public static CustomCellStyleStrategy getCellStyleStrategy(){
//蓝色表头样式
WriteCellStyle headWriteCellStyleBlue = new WriteCellStyle();
setHeadStyle(headWriteCellStyleBlue, true, true);
setBorder(headWriteCellStyleBlue);
WriteFont headWriteFontBlue = getHeadFont(IndexedColors.SKY_BLUE.getIndex());
headWriteCellStyleBlue.setWriteFont(headWriteFontBlue);
//红色表头样式
WriteCellStyle headWriteCellStyleRed = new WriteCellStyle();
setHeadStyle(headWriteCellStyleRed, true, true);
setBorder(headWriteCellStyleRed);
WriteFont headWriteFontRed = getHeadFont(IndexedColors.RED.getIndex());
headWriteCellStyleRed.setWriteFont(headWriteFontRed);
//内容文字
WriteFont contentWriteFont = getContentFont();
//左对齐内容样式
WriteCellStyle contentStyleLeft = new WriteCellStyle();
setHeadStyle(contentStyleLeft, false, false);
setBorder(contentStyleLeft);
contentStyleLeft.setWriteFont(contentWriteFont);
//居中对其内容样式
WriteCellStyle contentStyleCenter = new WriteCellStyle();
setHeadStyle(contentStyleCenter, false, true);
setBorder(contentStyleCenter);
contentStyleCenter.setWriteFont(contentWriteFont);
return new CustomCellStyleStrategy(
headWriteCellStyleBlue,headWriteCellStyleRed,
contentStyleLeft,contentStyleCenter);
}
然后在导出文件时,把样式策略改为自定义样式策略
//导出文件
EasyExcel.write("E:\\Test\\testFile.xlsx", Test.class).sheet("测试")
.registerWriteHandler(ExcelStyleTool.getCellStyleStrategy()) //注册自定义样式策略
.doWrite(data);
3、自定列宽
如果仅是想设置一个固定的宽度,可以通过继承 AbstractHeadColumnWidthStyleStrategy 来实现,通过设置表头的宽度即可
//简单的设置列宽
public class CustomHeadColumnWidthStrategy extends AbstractHeadColumnWidthStyleStrategy {
@Override
protected Integer columnWidth(Head head, Integer columnIndex) {
int width = 0;
//通过列的序号来判断给对应的列设置对应的宽度
switch (columnIndex){
case 0:
width = 10;
break;
case 1:
width = 35;
break;
case 12:
width = 50;
break;
case 13:
width = 5;
break;
default:
width = 20;
}
return width;
}
}
如果想根据单元格中内容长度设置不同的宽度,可以通过继承 AbstractColumnWidthStyleStrategy 类来实行,然后需要计算内容长度来设置想要的宽度。此处我没有这个需求,就没实现。
或者也可以使用 LongestMatchColumnWidthStyleStrategy 这个宽度策略,这个是官方提供的自动调节策略,可以直接注册使用,不用继承重写,可以直接注册 new LongestMatchColumnWidthStyleStrategy() 来使用
4、自定义行高
自定义行高可以通过继承 AbstractRowHeightStyleStrategy 类来实现设置行高
简单的设置如下:
public class CustomRowHightStrategy extends AbstractRowHeightStyleStrategy {
@Override
protected void setHeadColumnHeight(Row row, int relativeRowIndex) {
}
@Override
protected void setContentColumnHeight(Row row, int relativeRowIndex) {
row.setHeight((short) (2 * 256));
}
}
5、使用自定义样式
//导出文件
EasyExcel.write("E:\\Test\\testFile.xlsx", Cosmic.class).sheet("测试")
.registerWriteHandler(ExcelStyleTool.getCellStyleStrategy()) //注册个性化样式策略
.registerWriteHandler(new CustomHeadColumnWidthStrategy()) //注册列宽策略
.registerWriteHandler(new CustomRowHightStrategy()) //注册行高策略
.doWrite(data); //导出的数据
能力决定下限,命运决定上限,守正出奇,心正向善,行正无悔
希望此篇文章对你有帮助