easyexcel 给单元格设置格式,通过自定义注解方式实现对每一列格式的精确控制

easyexcel官方文档中可以设置表头单元格格式及内容的单元格格式,其中单元格格式策略类中有两个构造函数

public HorizontalCellStyleStrategy(WriteCellStyle headWriteCellStyle,
    List<WriteCellStyle> contentWriteCellStyleList) {
    this.headWriteCellStyle = headWriteCellStyle;
    this.contentWriteCellStyleList = contentWriteCellStyleList;
}

public HorizontalCellStyleStrategy(WriteCellStyle headWriteCellStyle, WriteCellStyle contentWriteCellStyle) {
    this.headWriteCellStyle = headWriteCellStyle;
    contentWriteCellStyleList = new ArrayList<WriteCellStyle>();
    contentWriteCellStyleList.add(contentWriteCellStyle);
}

两者的不同之处在于:第一个构造函数给内容设置单元格格式参数为一个集合,通过下方源码可以看到,

HorizontalCellStyleStrategy类中给内容设置单元格格式的代码如下:
@Override
protected void setContentCellStyle(Cell cell, Head head, Integer relativeRowIndex) {
    if (contentCellStyleList == null || contentCellStyleList.isEmpty()) {
        return;
    }
    cell.setCellStyle(contentCellStyleList.get(relativeRowIndex % contentCellStyleList.size()));
}

可以看出contentCellStyleList就是构造函数中内容单元格格式集合,该集合作用其实是给excel隔行换样式,比如你给了2种不同的样式,则1,3,5行为一个样式,2,4,6行为另一种样式,比如你给了3种不同的样式,则1,4,7行为一个样式,2,5,8行为另一种样式,3,6,9行为一种样式,通过cell.setCellStyle(contentCellStyleList.get(relativeRowIndex % contentCellStyleList.size()))这句代码就可以看出。

通过上述代码我们发现虽然easyexcel是通过给行设置样式,即同一行中,不同列样式是一样的,但一行中的每一列都会执行上述代码setContentCellStyle方法,这就是我们可以重写的地方,我们可以通过重写该方法,实现自己对单元格格式的精准控制

实现方式如下:

通过调试发现,该方法中的head参数是可以拿到单元格对应的实体类的参数名,即field的name,如下方的remark参数

@ExcelProperty("备注")
private String remark;

既然可以取到field的name,那么就可以自由发挥了。

我第一版实现是通过field的name中有特定字符串,然后设置单独样式,比如下面就是如果field的name中以amount结尾,就执行我设置的单元格格式,其它的执行公共的内容单元格格式。


private static final String AMOUNT = "amount";

@Override
protected void setContentCellStyle(Cell cell, Head head, Integer relativeRowIndex) {
    if (head.getFieldName().toLowerCase().endsWith(AMOUNT)) {
        Workbook wb = cell.getSheet().getWorkbook();
        CellStyle cellStyle = wb.createCellStyle();
        Font font = wb.createFont();
        font.setFontName("宋体");
        font.setFontHeightInPoints((short) 13);
        cellStyle.setFont(font);
        cellStyle.setAlignment(HorizontalAlignment.RIGHT);
        cell.setCellStyle(cellStyle);

    }else {
        super.setContentCellStyle(cell,head,relativeRowIndex);
    }
}

上述实现有一个最大的局限就是,如果同一行中,有各种各样的格式,则使用起来特别麻烦。所以就有了第二种方式:通过自定义注解的方式实现。

因为我们可以获取到field的name,那么就会想到反射,只要给到field的name的class,就可以获取到Field。通过反射获取到field上的注解,给field设置单元格格式,实现代码如下:

@Slf4j
public class ExcelStyleAnnotationCellWriteHandler extends HorizontalCellStyleStrategy {

    private Class c;
    ExcelStyleAnnotationCellWriteHandler(Class c, WriteCellStyle headWriteCellStyle, WriteCellStyle contentWriteCellStyle) {
        super(headWriteCellStyle, contentWriteCellStyle);
        this.c = c;
    }

    @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();
                Font font = wb.createFont();
                font.setFontName(annotation.fontName());
                font.setFontHeightInPoints(annotation.fontHeightInPoints());
                cellStyle.setFont(font);
                cellStyle.setAlignment(annotation.horizontalAlignment());
                cellStyle.setVerticalAlignment(annotation.verticalAlignment());
                cell.setCellStyle(cellStyle);
            }else {
                super.setContentCellStyle(cell,head,relativeRowIndex);
            }
        } catch (NoSuchFieldException e) {
            log.error("ExcelStyleAnnotationCellWriteHandler error{0}",e);
        }

    }
}

自定义注解如下,写的不全,大家可以自行补充


@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;
}
注解使用方式如下

@ExcelProperty("账号")
@ColumnWidth(28)
@ExcelStyle(fontName = "宋体",horizontalAlignment = HorizontalAlignment.LEFT)
private String account;

通过重写setContentCellStyle方法,读取到field上的注解,给单元格设置格式,没有注解的,走通用的样式。

使用多行表头时遇到的一点问题:https://github.com/alibaba/easyexcel/issues/990,大家可以看下,避免坑到自己

 

 

 

  • 8
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值