EasyExcel 数值型和最后一列超出文本框问题

528 阅读4分钟

EasyExcel 数值型和最后一列超出文本框问题

Alibaba出品的EasyExcel对比原版excel库POI,极大的简化了开发人员的代码编写工作。EasyExcel使用注解和监听器等简化读写开发,

问题说明

在我的日常工作中,很大一部分的工作都是将数据库的数据整理归纳后导出为Excel,当然会碰到许许多多的问题,比如导出超时(当然这个问题大多数都是SQL执行的问题,日常几十万条数据的excel并不会花费多少时间),字段类型与需求不匹配、文本超出单元格、动态头.....

这里主要记录和说明其中几个问题

  • 字段类型不匹配
  • 最后一列文本内容超出单元格

字段类型不匹配

解决方法可看easyexcel 官方github Issues :github.com/alibaba/eas…

问题展示

如上图所示,当我们设置实体类的属性为字符串型时,默认导出的时候数值型会模糊单元格的格式,所以上方有个三角符号,这时候excel是无法进行数值的求和汇总等运算的。

分析

我们看一下导出excel时的实体类

@Data
public class Student implements Serializable {
​
    @ExcelProperty( "学生编号")
    private String id;
​
    @ExcelProperty( "学生姓名")
    private String name;
​
    @ExcelProperty( "学生生日")
    @DateTimeFormat("yyyy-mm-dd")
    private Date birthday;
​
    @ExcelProperty("学号")
    private String stuNo;
}

注意 private String stuNo;为String类型,这里就是导致导出excel无法确定单元格格式的主要原因。

解决方法

修改方式很简单,将String改为对应的数值型格式即可如

@Data
public class Student implements Serializable {
​
    @ExcelProperty( "学生编号")
    private String id;
​
    @ExcelProperty( "学生姓名")
    private String name;
​
    @ExcelProperty( "学生生日")
    @DateTimeFormat("yyyy-mm-dd")
    private Date birthday;
​
    @ExcelProperty("学号")
    private Integer stuNo;
}

结果

PS: 第一列仍为String类型,所以导出仍有三角符号。

最后一列文本内容超出单元格

这个问题我在issues 中没有找到,可能问题比较简单😂😂😂

先说一下思路,构造出一列空值覆盖前一列内容超出部分,再手动生成标题头

问题

如果最后一列导出为长文本字符型时,很容易超出单元格,观感不佳,现象如下。

分析

我们看一下实体类多加了一个note字段,这个也就是上方长文本的字段。

@Data
public class Student implements Serializable {
​
    @ExcelProperty( "学生编号")
    private String id;
​
    @ExcelProperty( "学生姓名")
    private String name;
​
    @ExcelProperty( "学生生日")
    @DateTimeFormat("yyyy-mm-dd")
    private Date birthday;
​
    @ExcelProperty("学号")
    private Integer stuNo;
​
    @ExcelProperty("备注")
    private String note;
}

解决方法

我们首先看一下导出代码

EasyExcel.write("学生信息表.xlsx", Student.class)
        .sheet()
        .head(Student.class)
        .doWrite(WriteDemo.getData());

注意一下其中的方法和参数write()和head()

write()重载方法入参

  • File file
  • File file,@Nullable Class head
  • String pathName
  • String pathName, @Nullable Class head
  • outputStream outputStream
  • outputStream outputStream, @Nullable Class head

所有的重载方法入参第一个都是确定文件名称(File )和位置(pathName),outputStream 是web上传、下载。我们关注后面一个参数 Class head这里指定了导出文件的head,同head方法功能相似,也就是说,这里我们去到 .head(Student.class)或者.write("学生信息表.xlsx", Student.class)中的Student.class都是正常的。

简单分析一下源代码
write
public class EasyExcelFactory {
    public static ExcelWriterBuilder write(String pathName, Class head) {
        ExcelWriterBuilder excelWriterBuilder = new ExcelWriterBuilder();
        excelWriterBuilder.file(pathName);
        if (head != null) {
            excelWriterBuilder.head(head);
        }
​
        return excelWriterBuilder;
    }
}
​
​
public abstract class AbstractParameterBuilder<T extends AbstractParameterBuilder, C extends BasicParameter> {
 
​
    public T head(Class clazz) {
        this.parameter().setClazz(clazz);
        return this.self();
    }
}

我们可以看到这里给excelWriterBuilder设置了一个head然后调用了AbstractParameterBuilder的head方法

head
public abstract class AbstractParameterBuilder<T extends AbstractParameterBuilder, C extends BasicParameter> {
 /***/
    public T head(Class clazz) {
        this.parameter().setClazz(clazz);
        return this.self();
    }
     /***/
    protected abstract C parameter();
     /***/
}

这里给 this.parameter()设置了类名,这里的this.parameter指的是AbstractParameterBuilder 中的protected abstract C parameter();方法,我们可以看到,这里其实本质上是调用了同一个方法。

head的特别之处

head方法本质上是用来动态生成头文件的,详情可参照官方文档easyexcel.opensource.alibaba.com/docs/curren…

如果我们再write方法上没有指定标题头,则可以手动通过head方法构造,这样我们就可以实现最后一列不出单元格了

具体实现

先修改导出实体类添加一个占位符并赋初始值为空注意,如果没有赋值为空字符串,则不会写入excel进行覆盖前一列

@Data
public class Student implements Serializable {
​
    @ExcelProperty( "学生编号")
    private String id;
​
    @ExcelProperty( "学生姓名")
    private String name;
​
    @ExcelProperty( "学生生日")
    @DateTimeFormat("yyyy-mm-dd")
    private Date birthday;
​
    @ExcelProperty("学号")
    private Integer stuNo;
​
    @ExcelProperty("备注")
    private String note;
​
    // 占位符
    private String palaceHolder = "";
}

手动构造头文件

private List<List<String>> setHead() {
​
    List<String> list = Arrays.asList(
            "学生编号",
            "学生姓名",
            "学生生日",
            "学号",
            "备注"
    );
​
    return list.stream()
            .map(Arrays::asList)
            .collect(Collectors.toList());
​
}

最后生成excel

public void dynamicHeadWrite() {
​
​
    EasyExcel.write("学生信息表.xlsx")
            .sheet()
            .head(setHead())
            .doWrite(WriteDemo.getData());
​
​
}

结果

可以看到,最后一列内容没有超出单元格了。