谈到新技术,每个人都会有点恐惧,怕处理不好,确实第一次使用新技术会遇到很多坑,本人以前使用poi也遇到了很多的坑,但是很快就解决了,这次使用EasyExcel这个新技术去做excel表的导出,还要给表格加样式,遇到不同的版本问题,遇到颜色加错了地方,反正是各种效果都达不到自己想要的那种,幸好最终看文档解决了,特此写下这篇博客。本篇博客会写下自己遇到的各种效果,供自己或者看到这篇博客的人使用。(注意:这里使用的是最新的 3.0以上的版本,以后的小伙伴用了不同的版本最好看源码或者文档)
目录
1. 导入maven 依赖
2. 实体类
3. 导出接口的实现
4. 自定义样式
1. 导入maven 依赖
<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.0.5</version>
</dependency>
2. 实体类
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.metadata.data.WriteCellData;
import lombok.Data;
import lombok.EqualsAndHashCode;import java.util.Date;/*** @Description* @Date 2022/1/19* @Version 1.0*/
@Data
@EqualsAndHashCode
public class ExcelDemo {// 导出信息 为表头// 序号@ExcelProperty({"导出信息", "序号"})private String orderId;// 姓名@ExcelProperty({"导出信息", "姓名"})private String contact;// 导出时间@ColumnWidth(22) // 设置列宽度@ExcelProperty({"导出信息", "导出时间"})private Date registeTime;// 审核状态(待审核 0,未通过 1,已通过 2)@ExcelProperty({"导出信息", "审核状态"})private String status;/*** 指定单元格的样式。当然样式 也可以用注解等方式。** @since 3.0.0-beta1*/@ExcelIgnoreprivate WriteCellData<String> writeCellStyle;
}
3. 导出接口的实现
@ApiOperation("导出")@PostMapping("/export")public void export(@RequestBody ExcelDemo excelDemo, HttpServletResponse response) {// 这里是个查询列表的语句List<ExcelDemo> list = xxService.queryList(excelDemo);// 当前用户桌面File desktopDir = FileSystemView.getFileSystemView().getHomeDirectory();String desktopPath = desktopDir.getAbsolutePath() + "\\导出信息.xlsx";EasyExcel.write(desktopPath, ExcelDemo.class).inMemory(true) // 富文本.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 字体居中显示.registerWriteHandler(new CustomCellWriteHandler()) // 自定义的样式.sheet("导出信息").doWrite(list);}
4. 自定义样式
这里我们需要继承 Easyexcel 的 AbstractCellWriteHandler 控制器异步处理去对相应的方法做自己定义的样式,主要在 beforeCellCreate 前置处理方法和 afterCellDispose 后置处理方法完成,这里也是本文中最关键的样式处理的点。
4.1 设置整体行高
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.CellData;
import com.alibaba.excel.metadata.data.DataFormatData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.util.BooleanUtils;
import com.alibaba.excel.write.handler.AbstractCellWriteHandler;
import com.alibaba.excel.write.handler.context.CellWriteHandlerContext;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import org.apache.poi.ss.usermodel.*;import java.util.List;/*** @Description* @Date 2022/1/18* @Version 1.0*/
public class CustomCellWriteHandler extends AbstractCellWriteHandler {@Overridepublic void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {// 设置行高测试int rowIndex = row.getRowNum();System.out.println("当前行: " + rowIndex);short height = 600;row.setHeight(height);}}
下面是样式:
4.2 (这次的重点来了)把状态为已通过的列背景色设置成绿色
public class CustomCellWriteHandler extends AbstractCellWriteHandler {@Overridepublic void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {// 设置行高测试int rowIndex = row.getRowNum();System.out.println("当前行: " + rowIndex);short height = 600;row.setHeight(height);}@Overridepublic void afterCellDispose(CellWriteHandlerContext context) {Cell cell = context.getCell();int rowIndex = cell.getRowIndex();int cellIndex = cell.getColumnIndex();// 自定义宽度处理// 自定义样式处理// 当前事件会在 数据设置到poi的cell里面才会回调// 判断不是头的情况 如果是fill 的情况 这里会==null 所以用not trueif (BooleanUtils.isNotTrue(context.getHead())) {if (cell.getColumnIndex() == 8 && cell.getStringCellValue().contains("已通过")) {// 拿到poi的workbookWorkbook workbook = context.getWriteWorkbookHolder().getWorkbook();// 这里千万记住 想办法能复用的地方把他缓存起来 一个表格最多创建6W个样式// 不同单元格尽量传同一个 cellStyleCellStyle cellStyle = workbook.createCellStyle();cellStyle.setFillForegroundColor(IndexedColors.GREEN.getIndex());// 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUNDcellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);cell.setCellStyle(cellStyle);// 由于这里没有指定dataformat 最后展示的数据 格式可能会不太正确// 这里要把 WriteCellData的样式清空, 不然后面还有一个拦截器 FillStyleCellWriteHandler 默认会将 WriteCellStyle 设置到// cell里面去 会导致自己设置的不一样(很关键)context.getFirstCellData().setWriteCellStyle(null);} else if (cell.getColumnIndex() == 8 && cell.getStringCellValue().contains("未通过")) {// 拿到poi的workbookWorkbook workbook = context.getWriteWorkbookHolder().getWorkbook();// 这里千万记住 想办法能复用的地方把他缓存起来 一个表格最多创建6W个样式// 不同单元格尽量传同一个 cellStyleCellStyle cellStyle = workbook.createCellStyle();cellStyle.setFillForegroundColor(IndexedColors.RED1.getIndex());// 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUNDcellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);cell.setCellStyle(cellStyle);// 由于这里没有指定dataformat 最后展示的数据 格式可能会不太正确// 这里要把 WriteCellData的样式清空, 不然后面还有一个拦截器 FillStyleCellWriteHandler 默认会将 WriteCellStyle 设置到// cell里面去 会导致自己设置的不一样(很关键)context.getFirstCellData().setWriteCellStyle(null);} else if (cell.getColumnIndex() == 8 && cell.getStringCellValue().contains("待审核")) {// 拿到poi的workbookWorkbook workbook = context.getWriteWorkbookHolder().getWorkbook();// 这里千万记住 想办法能复用的地方把他缓存起来 一个表格最多创建6W个样式// 不同单元格尽量传同一个 cellStyleCellStyle cellStyle = workbook.createCellStyle();cellStyle.setFillForegroundColor(IndexedColors.YELLOW.getIndex());// 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUNDcellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);cell.setCellStyle(cellStyle);// 由于这里没有指定dataformat 最后展示的数据 格式可能会不太正确// 这里要把 WriteCellData的样式清空, 不然后面还有一个拦截器 FillStyleCellWriteHandler 默认会将 WriteCellStyle 设置到// cell里面去 会导致自己设置的不一样context.getFirstCellData().setWriteCellStyle(null);}}}}
4.3 下面是全部内容数据都设置成同一种颜色,或者表头都设置成同一种颜色
@Override
public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {.......
}@Override
public void afterCellDispose(CellWriteHandlerContext context) {.......
}public static HorizontalCellStyleStrategy getStyleStrategy() {// 头的策略WriteCellStyle headWriteCellStyle = new WriteCellStyle();// 设置对齐//headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.LEFT);// 背景色, 设置为绿色,也是默认颜色headWriteCellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());// 字体//WriteFont headWriteFont = new WriteFont();//headWriteFont.setFontHeightInPoints((short) 12);//headWriteCellStyle.setWriteFont(headWriteFont);// 内容的策略WriteCellStyle contentWriteCellStyle = new WriteCellStyle();// 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定// contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);// 背景绿色contentWriteCellStyle.setFillForegroundColor(IndexedColors.GREEN.getIndex());// 字体策略WriteFont contentWriteFont = new WriteFont();//contentWriteFont.setFontHeightInPoints((short) 12);contentWriteCellStyle.setWriteFont(contentWriteFont);//设置 自动换行contentWriteCellStyle.setWrapped(true);//设置 垂直居中contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);//设置 水平居中contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);//设置边框样式contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);contentWriteCellStyle.setBorderTop(BorderStyle.THIN);contentWriteCellStyle.setBorderRight(BorderStyle.THIN);contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);// 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);return horizontalCellStyleStrategy;}
当然不要忘了,这里也要加上
EasyExcel.write(desktopPath, ExcelDemo.class).inMemory(true) // 富文本.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 字体居中显示.registerWriteHandler(new CustomCellWriteHandler()) // 自定义的样式.registerWriteHandler(TestHandler.getStyleStrategy()) // 自定义全表的样式.sheet("导出信息").doWrite(list);
自此,就本次踩坑之旅就结束了,但是要再继续深入的学习源码,多去理解别人写的东西,这些应该基本满足我们项目中的需求了,以后如果有新的需求再继续更新本文,如有不足,请各位大佬指教。
感谢以下博客:
写excel · 语雀EasyExcel写Excel的示例https://www.yuque.com/easyexcel/doc/write