需求背景:
根据查询条件将列表数据导出,并筛选出满足某个条件的数据,将满足条件的数据的背景颜色设置成黄色。
(本文例子如:name出现的次数大于等于2,将相关数据背景颜色都设置为黄色)
一、技术选型:
1、easyExcel的自定义写策略处理:CellWriteHandler
2、poi自带的写数据行处理:Workbook
思考选定:
由于目前系统中多处使用的是file插件导出类,是由统一形成的,直接改动,对其它项目引入,从而导出的性能产生一定的影响,所以选择自定义策略实现,故选1。
二、方案设计:(基于实现 CellWriteHandler 接口)
1、在 beforeCellCreate 方法中统计出 每个数据行的 name 出现的次数,在 afterCellDispose 方法中处理满足设置背景颜色数据的背景颜色。
2、直接传入数据行的索引,在 afterCellDispose 方法中处理满足设置背景颜色数据的背景颜色。
note:原本考虑的是选择1,但是在实现的时候,统计name出现次数一直会出现问题,在easeExcel的源码中:beforeCellCreate 操作数据出现问题,待处理。(码友们可自行尝试!!!)故暂选择 方案2 实现当前需求。
三、代码实现:
pom.xml:
<dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>3.3.2</version> </dependency>
API:
@ApiOperation(value = "评论审核导出")
@GetMapping(value = "/export")
public void exportExcel(HttpServletResponse response, TestParam param) throws BaseException {
service.export(response, param);
}
实现层:
public class TestExcelService {
private static final String FILE_NAME = "测试文件名字";
private static final String SHEET_NAME = "测试";
private final IEasyExcelService easyExcelService;
public SeedDemandExcelService(IEasyExcelService easyExcelService) {
this.easyExcelService = easyExcelService;
}
public void export(HttpServletResponse response, TestParam param) throws BaseException{
// 根据查询参数获取查询到的数据(根据自己的查询方法在这里将数据查询出来)
List<TestExcelData> exportData = this.getExportData(param);
// Obtain data rows that require background color settings
// 获取需要设置背景颜色的数据行索引
List<Integer> index = getIndexList(exportData);
// export
try {
easyExcelService.exportExcelWithBackGround(exportData, response, DemoExcelData.class, FILE_NAME, SHEET_NAME, index);
} catch (Exception e) {
throw new Exception(CodeEnum.FAILED, "导出异常,请联系开发人员!异常信息是:" + e.getMessage());
}
}
}
工具类:IEasyExcelService
public interface IEasyExcelService {
/**
* 导出excel方法
* @param exportData 需要导出的数据
* @param response response
* @param tClass 导出excel的字段实体类
* @param fileName 文件名字
* @param sheetName sheet名字
*/
<T> void exportExcel(List<T> exportData, HttpServletResponse response, Class<T> tClass, String fileName, String sheetName);
/**
* 导出excel方法(支持设置背景颜色)
* @param exportData 需要导出的数据
* @param response response
* @param tClass 导出excel的字段实体类
* @param fileName 文件名字
* @param sheetName sheet名字
* @param backGroundIndex 需要设置背景的数据行
* @param <T> t
* @throws Exception Exception
*/
<T> void exportExcelWithBackGround(List<T> exportData, HttpServletResponse response, Class<T> tClass , String fileName, String sheetName, List<Integer> backGroundIndex) throws Exception;
}
工具类:EasyExcelServiceImpl
@Service
@Slf4j
public class EasyExcelServiceImpl implements IEasyExcelService {
@Override
public <T> void exportExcel(List<T> exportData, HttpServletResponse response, Class<T> tClass, String fileName, String sheetName){
try{
// 使用swagger 会导致各种问题,直接用浏览器或者用postman
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
// fileName encoder
String fileNameEncoder = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileNameEncoder + ".xlsx");
// write to excel
EasyExcelFactory.write(response.getOutputStream(), tClass)
.autoCloseStream(Boolean.FALSE)
.sheet(sheetName)
.doWrite(exportData);
}catch (Exception e){
log.error("EasyExcelServiceImpl->exportExcel error, message is :{}", e.getMessage());
}
}
@Override
public <T> void exportExcelWithBackGround(List<T> exportData, HttpServletResponse response, Class<T> tClass,
String fileName, String sheetName, List<Integer> backGroundIndex) throws Exception {
// 使用swagger 会导致各种问题,直接用浏览器或者用postman
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
// fileName encoder
String fileNameEncoder = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileNameEncoder + ".xlsx");
// 自定义策略
Set<Integer> yellowRowsSet = new HashSet<>(backGroundIndex);
SeedDemandCellWriteHandler seedDemandCellWriteHandler = new SeedDemandCellWriteHandler(yellowRowsSet);
// write to excel
EasyExcelFactory.write(response.getOutputStream(), tClass)
// 自定义背景颜色策略
.registerWriteHandler(seedDemandCellWriteHandler)
.inMemory(Boolean.TRUE)
.autoCloseStream(Boolean.FALSE)
.sheet(sheetName)
.doWrite(exportData);
}
}
(其中registerWriteHandler支持扩展多个,可以通过HorizontalCellStyleStrategy策略设置全局的配置,如背景颜色、字体、合并单元格等)
自定义Handle:(自定义设置数据行背景颜色)
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.util.BooleanUtils;
import com.alibaba.excel.write.handler.CellWriteHandler;
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 org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import java.util.Set;
/**
* @author c
*/
public class CustomCellWriteHandler implements CellWriteHandler {
/**
* 标黄行宽集合
*/
private final Set<Integer> yellowRowIndex;
public CustomCellWriteHandler(Set<Integer> yellowRowIndex) {
this.yellowRowIndex = yellowRowIndex;
}
@Override
public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {
// 源码context中row待优化:支持入参 获取需要字段的出现次数 从而设置背景颜色
// to do:(row.getCell(columnIndex)失效)
}
@Override
public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
// empty
}
@Override
public void afterCellDispose(CellWriteHandlerContext context) {
if (BooleanUtils.isNotTrue(context.getHead())) {
// 获取当前行的行号
Integer currentRowIndex = context.getRowIndex();
// 判断当前行是否在yellowRowIndex's中
if (yellowRowIndex.contains(currentRowIndex)) {
// 设置背景颜色,也可以设置字体等其它元素
WriteCellData<?> cellData = context.getFirstCellData();
WriteCellStyle writeCellStyle = cellData.getOrCreateStyle();
writeCellStyle.setFillForegroundColor(IndexedColors.YELLOW.getIndex());
writeCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
}
}
}
}
DemoExcelData:(导出字段实体类)
@Data
@EqualsAndHashCode
public class DemoExcelData{
@ExcelProperty(value = "TaskID", index = 0)
private String name;
@ExcelProperty(value = "taskName", index = 1)
private String sex;
@ExcelProperty(value = "taskName", index = 2)
private String age;
}
End:
👍如果对你有帮助,给博主一个免费的点赞以示鼓励
欢迎各位🔎点赞👍评论收藏⭐️