需求背景:
根据查询条件将列表数据导出,并筛选出满足某个条件的数据,将满足条件的数据的背景颜色设置成黄色。
(本文例子如: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);// exporttry {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 {@Overridepublic <T> void exportExcel(List<T> exportData, HttpServletResponse response, Class<T> tClass, String fileName, String sheetName){try{// 使用swagger 会导致各种问题,直接用浏览器或者用postmanresponse.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");response.setCharacterEncoding("utf-8");// fileName encoderString fileNameEncoder = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileNameEncoder + ".xlsx");// write to excelEasyExcelFactory.write(response.getOutputStream(), tClass).autoCloseStream(Boolean.FALSE).sheet(sheetName).doWrite(exportData);}catch (Exception e){log.error("EasyExcelServiceImpl->exportExcel error, message is :{}", e.getMessage());}}@Overridepublic <T> void exportExcelWithBackGround(List<T> exportData, HttpServletResponse response, Class<T> tClass,String fileName, String sheetName, List<Integer> backGroundIndex) throws Exception {// 使用swagger 会导致各种问题,直接用浏览器或者用postmanresponse.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");response.setCharacterEncoding("utf-8");// fileName encoderString 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 excelEasyExcelFactory.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;}@Overridepublic void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {// 源码context中row待优化:支持入参 获取需要字段的出现次数 从而设置背景颜色// to do:(row.getCell(columnIndex)失效)}@Overridepublic void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {// empty}@Overridepublic 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:
👍如果对你有帮助,给博主一个免费的点赞以示鼓励
欢迎各位🔎点赞👍评论收藏⭐️