现状
在日常Java开发中,有时会遇到基于现有的查询结果来导出Excel文件的业务需求,一般会想到使用开源的POI库,大多数人应该会先从网上找几个例子,再复制粘贴到项目中,基于需求来set对应的单元格内容,代码中会存在许多定制化代码,如下图所示:
对应的单元格赋值
设计
抽象表头信息ExcelHeader类一般导出的Excel第一行都是表头信息,从第二行开始是需要导出的数据。我们可以使用一个Model类来定义Excel表头及所处列的信息。
// 实现Comparable接口是为了根据order字段排序,确定这个表头的标题放在列的位置顺序@Data@Builder@NoArgsConstructor@AllArgsConstructorpublic class ExcelHeader implements Comparable {// 表头的标题名称privateStringtitle;// 表头的标题所在列的顺序privateintorder;// 单元格的宽度privateintwidth;// 对应字段privateStringfieldName; @OverridepublicintcompareTo(ExcelHeader o) {returnInteger.compare(order, o.order); } }抽象数据模型注解导出的数据在后端是基于某个Model类的List集合,我们可以定义一个注解来标识此Model的需要导出的字段,从而实现通用的导出。
// 用来在导出对象的field上加入的注解,通过该annotation说明某个属性所对应的标题@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.FIELD})@Documentedpublic@interfaceExcelResources {// 导出字段的标题名称,用于构造ExcelHeader对象的titleStringtitle();// 导出字段在excel的顺序,用于构造ExcelHeader对象的orderintorder()default9999;// 导出字段列的宽度,用于构造ExcelHeader对象的widthintwidth()default150; }实现1、先定义工具类通用的静态导出方法
/** *@paramobjs 导出的数据集合,一般为后端DB查询结果 *@paramclz 导出的Excel内容Model类,其导出属性上需要加@ExcelResources*@paramsheetName 导出的Excel的Sheet页名称 *@parampageSize 导出的Excel的每个Sheet页的数据量,若objs.size()>pageSize,会写入到(objs.size()/pageSize+1)个Sheet页中 *@paramfileName 导出的Excel文件名,会加上_yyyyMMddHHmmss避免重名 *@paramresponse HttpServletResponse */publicstaticvoid exportExcel(List