上片文章easyexcel基于注解的可回调的更精细的单元格格式设置(一)中只能根据本字段的值的情况设置不同样式,但如果该字段单元格样式受到其它字段值影响,则无法实现。于是衍生出了该方案。
该方案也有方案一中两个Consumer,且多了一个richTextConsumer用于设置富文本,CommonCallBackData只是对于字体和单元格样式类等的封装而已。多了一个List<T> dataList,该dataList也包含在CommonCallBackData中,在回调时会将该集合会作为方法参数传过去,同时会传入relativeRowIndex字段,这样根据这两个字段,就可以获取到某一行的数据,也就可以实现上述需求。代码1处为富文本回调。为了支持富文本,注解也添加了字段是否为富文本,哪个字段需要支持富文本,只需将注解的richText设置为true。若有多个字段都需要支持富文本,则需要根据回调中传过去的Field做判断。
@ExcelProperty("名称")
@ColumnWidth(45)
@ExcelStyle(richText = true)
private String name;
@Target({ElementType.FIELD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExcelStyle {
String fontName() default "宋体";
short fontHeightInPoints() default 12;
HorizontalAlignment horizontalAlignment() default HorizontalAlignment.LEFT;
VerticalAlignment verticalAlignment() default VerticalAlignment.CENTER;
boolean wrapText() default false;
boolean richText() default false;
}
package com.tzxx.common.domain.logic.excel;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.tzxx.common.annotation.ExcelStyle;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.Workbook;
import java.lang.reflect.Field;
import java.util.List;
import java.util.function.Consumer;
@Slf4j
public class ExcelStyleAnnotationAndContainsCommonCallBackCellWriteHandler<T> extends HorizontalCellStyleStrategy {
private Class<?> c;
private List<T> dataList;
private Consumer<CommonCallBackData<T>> fontConsumer;
private Consumer<CommonCallBackData<T>> cellStyleConsumer;
private Consumer<CommonCallBackData<T>> richTextConsumer;
public ExcelStyleAnnotationAndContainsCommonCallBackCellWriteHandler(Class<?> c, WriteCellStyle headWriteCellStyle,
WriteCellStyle contentWriteCellStyle,
List<T> dataList,
Consumer<CommonCallBackData<T>> fontConsumer,
Consumer<CommonCallBackData<T>> cellStyleConsumer,
Consumer<CommonCallBackData<T>> richTextConsumer) {
super(headWriteCellStyle, contentWriteCellStyle);
this.c = c;
this.fontConsumer = fontConsumer;
this.cellStyleConsumer = cellStyleConsumer;
this.richTextConsumer = richTextConsumer;
this.dataList = dataList;
}
@Override
protected void setContentCellStyle(Cell cell, Head head, Integer relativeRowIndex) {
try {
Field declaredField = c.getDeclaredField(head.getFieldName());
ExcelStyle annotation = declaredField.getAnnotation(ExcelStyle.class);
if (annotation != null) {
Workbook wb = cell.getSheet().getWorkbook();
CellStyle cellStyle = wb.createCellStyle();
cell.setCellStyle(cellStyle);
Font font = wb.createFont();
CommonCallBackData<T> callBackData = create(font,cellStyle,relativeRowIndex,cell,wb,annotation,declaredField);
font.setFontName(annotation.fontName());
font.setFontHeightInPoints(annotation.fontHeightInPoints());
if (fontConsumer != null) {
fontConsumer.accept(callBackData);
}
cellStyle.setFont(font);
cellStyle.setAlignment(annotation.horizontalAlignment());
cellStyle.setVerticalAlignment(annotation.verticalAlignment());
cellStyle.setWrapText(annotation.wrapText());
if (cellStyleConsumer != null) {
cellStyleConsumer.accept(callBackData);
}
//1
boolean richText = annotation.richText();
if (richText && richTextConsumer != null) {
richTextConsumer.accept(callBackData);
}
}else {
super.setContentCellStyle(cell,head,relativeRowIndex);
}
} catch (NoSuchFieldException e) {
log.error("ExcelStyleAnnotationCellWriteHandler error{0}",e);
}
}
private CommonCallBackData<T> create(Font font, CellStyle cellStyle, Integer relativeRowIndex,Cell cell,Workbook wb,ExcelStyle annotation, Field field){
CommonCallBackData<T> callBackData = new CommonCallBackData<>();
callBackData.setFont(font);
callBackData.setCellStyle(cellStyle);
callBackData.setRelativeRowIndex(relativeRowIndex);
callBackData.setDataList(this.dataList);
callBackData.setCell(cell);
callBackData.setWorkbook(wb);
callBackData.setAnnotation(annotation);
callBackData.setField(field);
return callBackData;
}
}
@Data
public class CommonCallBackData<T> {
private Font font;
private CellStyle cellStyle;
private List<T> dataList;
private Integer relativeRowIndex;
private Cell cell;
private Workbook workbook;
private Field field;
private ExcelStyle annotation;
}
Consumer示例:
public static void richTextConsumer(CommonCallBackData<XX> callBackData){
Integer relativeRowIndex = callBackData.getRelativeRowIndex();
List<XX> dataList = callBackData.getDataList();
XX dto = dataList.get(relativeRowIndex);
if (Boolean.TRUE.equals(dto.getXx))) {
Workbook workbook = callBackData.getWorkbook();
Cell cell = callBackData.getCell();
Font font = workbook.createFont();
font.setColor(Font.COLOR_RED);
String big = "富文本";
String value = cell.getStringCellValue() + big;
int index = value.lastIndexOf(big);
//将富文本三个字设置为红色字体
RichTextString richTextString = new XSSFRichTextString(value);
richTextString.applyFont(index,index+3,font);
cell.setCellValue(richTextString);
}
}
public static void cellStyleTextConsumer(CommonCallBackData<XX> callBackData){
Integer relativeRowIndex = callBackData.getRelativeRowIndex();
List<XX> dataList = callBackData.getDataList();
XX dto = dataList.get(relativeRowIndex);
if (Boolean.TRUE.equals(dto.getXx())) {
CellStyle cellStyle = callBackData.getCellStyle();
cellStyle.setAlignment(HorizontalAlignment.CENTER);
}
}
调用:为了支持富文本,需要将inMemory设置为true,该设置是将默认的SXSSF替换为XSSF,SXSSF不支持富文本。
EasyExcelFactory.write(httpServletResponse.getOutputStream(), XX.class)
.inMemory(true)
.registerWriteHandler(EasyExcelUtil.getStyleForCustomAnnotationAndContainsCommonCallBack(
XX.class,exportList,null,
XX::cellStyleTextConsumer,XX::richTextConsumer
))
.sheet("xxxxx表").doWrite(list);
//EasyExcelUtil
public static <T> ExcelStyleAnnotationAndContainsCommonCallBackCellWriteHandler getStyleForCustomAnnotationAndContainsCommonCallBack(Class<?> c,
List<T> dataList,
Consumer<CommonCallBackData<T>> fontConsumer,
Consumer<CommonCallBackData<T>> cellStyleConsumer, Consumer<CommonCallBackData<T>> richTextConsumer) {
return new ExcelStyleAnnotationAndContainsCommonCallBackCellWriteHandler(c,getHeadWriteCellStyle(), getContentWriteCellStyle(),dataList,fontConsumer,cellStyleConsumer,richTextConsumer);
}
private static WriteCellStyle getHeadWriteCellStyle(){
// 头的策略
WriteCellStyle headWriteCellStyle = new WriteCellStyle();
WriteFont headWriteFont = new WriteFont();
headWriteFont.setFontHeightInPoints((short)14);
headWriteFont.setFontName("宋体");
headWriteCellStyle.setWriteFont(headWriteFont);
return headWriteCellStyle;
}
private static WriteCellStyle getContentWriteCellStyle(){
// 内容的策略
WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
WriteFont contentWriteFont = new WriteFont();
contentWriteFont.setFontName("宋体");
contentWriteFont.setFontHeightInPoints((short)13);
contentWriteCellStyle.setWriteFont(contentWriteFont);
return contentWriteCellStyle;
}