一、介绍
Easypoi功能如同名字easy,主打的功能就是容易,让一个没见接触过poi的人员就可以方便的写出Excel导出,Excel模板导出,Excel导入,Word模板导出,通过简单的注解和模板语言(熟悉的表达式语法),完成以前复杂的写法。在项目中添加依赖即可:
<dependency><groupId>cn.afterturn</groupId><artifactId>easypoi-spring-boot-starter</artifactId><version>4.5.0</version></dependency>
二、相关注解
注解有5类分别是:
- @Excel 作用到filed上面,是对Excel一列的一个描述
- @ExcelCollection 表示一个集合,主要针对一对多的导出,比如一个老师对应多个科目,科目就可以用集合表示
- @ExcelEntity 表示一个继续深入导出的实体,但他没有太多的实际意义,只是告诉系统这个对象里面同样有导出的字段
- @ExcelIgnore 和名字一样表示这个字段被忽略跳过这个导导出
- @ExcelTarget 这个是作用于最外层的对象,描述这个对象的id,以便支持一个对象可以针对不同导出做出不同处理
1、@Excel
这个是必须使用的注解,如果需求简单只使用这一个注解也是可以的,涵盖了常用的Excel需求。
属性 | 类型 | 默认值 | 功能 |
name | String | null | 列名 |
needMerge | boolean | fasle | 是否需要纵向合并单元格(用于含有list中,单个的单元格,合并list创建的多个row) |
orderNum | String | "0" | 列的排序 |
replace | String[] | {} | 值得替换,导出是{a_id,b_id} 导入反过来 |
savePath | String | "upload" | 导入文件保存路径,如果是图片可以填写,默认是upload/className/ IconEntity这个类对应的就是upload/Icon/ |
type | int | 1 | 导出类型 1 是文本 2 是图片,3 是函数,10 是数字 默认是文本 |
width | double | 10 | 列宽 |
height | double | 10 | 列高,后期打算统一使用@ExcelTarget的height,这个会被废弃 |
isStatistics | boolean | fasle | 自动统计数据,在追加一行统计,把所有数据都和输出。这个处理会吞没异常,请注意这一点 |
isHyperlink | boolean | false | 超链接,如果是需要实现接口返回对象 |
isImportField | boolean | true | 校验字段,看看这个字段是不是导入的Excel中有,如果没有说明是错误的Excel,读取失败 |
exportFormat | String | "" | 导出的时间格式,以这个是否为空来判断是否需要格式化日期 |
importFormat | String | "" | 导入的时间格式,以这个是否为空来判断是否需要格式化日期 |
format | String | "" | 时间格式,相当于同时设置了exportFormat 和 importFormat |
databaseFormat | String | "yyyyMMddHHmmss" | 导出时间设置,如果字段是Date类型则不需要设置 数据库如果是string 类型,这个需要设置这个数据库格式,用以转换时间格式输出 |
numFormat | String | "" | 数字格式化,参数是Pattern,使用的对象是DecimalFormat |
imageType | int | 1 | 导出类型 1 从file读取 2 是从数据库中读取 默认是文件 同样导入也是一样的 |
suffix | String | "" | 文字后缀,如% 90 变成90% |
isWrap | boolean | true | 是否换行 即支持\n |
mergeRely | int[] | {} | 合并单元格依赖关系,比如第二列合并是基于第一列 则{0}就可以了 |
mergeVertical | boolean | fasle | 纵向合并内容相同的单元格 |
fixedIndex | int | -1 | 对应excel的列,忽略名字 |
isColumnHidden | boolean | false | 导出隐藏列 |
2、@ExcelTarget
限定一个导出实体的注解,以及一些通用设置,作用于最外面的实体。
属性 | 类型 | 默认值 | 功能 |
---|---|---|---|
value | String | null | 定义ID |
height | double | 10 | 设置行高 |
fontSize | short | 11 | 设置文字大小 |
3、@ExcelEntity
标记是不是导出excel 标记为实体类,标记是否继续穿透,可以自定义内部id。
属性 | 类型 | 默认值 | 功能 |
---|---|---|---|
id | String | null | 定义ID |
4、@ExcelCollection
一对多的集合注解,用以标记集合是否被数据以及集合的整体排序
属性 | 类型 | 默认值 | 功能 |
---|---|---|---|
id | String | null | 定义ID |
name | String | null | 定义集合列名 |
orderNum | int | 0 | 排序 |
type | Class<?> | ArrayList.class | 导入时创建对象使用 |
5、@ExcelIgnore
忽略这个属性,多使用需循环引用中。
三、使用案例
编写easypoi工具类
package com.ywz.utils;import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;/*** 类描述 -> EasyPoi工具类** @Author: ywz* @Date: 2024/08/20*/
public class EasyPoiUtil {/*** 方法描述 -> 复杂导出Excel,包括文件名以及表名。创建表头** @param list 导出的实体类* @param title 表头名称* @param sheetName sheet表名* @param pojoClass 映射的实体类* @param fileName 导出的文件名* @param isCreateHeader 是否创建表头* @Author: ywz* @Date: 2024/08/20*/public static void exportExcel(List<?> list, String title, String sheetName, Class<?> pojoClass, String fileName, boolean isCreateHeader, HttpServletResponse response) {ExportParams exportParams = new ExportParams(title, sheetName);exportParams.setCreateHeadRows(isCreateHeader);defaultExport(list, pojoClass, fileName, response, exportParams);}/*** 方法描述 -> 复杂导出Excel,包括文件名以及表名,不创建表头** @param list 导出的实体类* @param title 表头名称* @param sheetName sheet表名* @param pojoClass 映射的实体类* @param fileName 导出的文件名* @Author: ywz* @Date: 2024/08/20*/public static void exportExcel(List<?> list, String title, String sheetName, Class<?> pojoClass, String fileName, HttpServletResponse response) {defaultExport(list, pojoClass, fileName, response, new ExportParams(title, sheetName));}/*** 方法描述 -> Map 集合导出** @param list 实体集合* @param fileName 导出的文件名称* @Author: ywz* @Date: 2024/08/20*/public static void exportExcel(List<Map<String, Object>> list, String fileName, HttpServletResponse response) {defaultExport(list, fileName, response);}/*** 方法描述 -> 默认导出方法** @param list 导出的实体集合* @param pojoClass pojo实体* @param fileName 导出的文件名* @param exportParams ExportParams封装实体* @Author: ywz* @Date: 2024/08/20*/private static void defaultExport(List<?> list, Class<?> pojoClass, String fileName, HttpServletResponse response, ExportParams exportParams) {Workbook workbook = ExcelExportUtil.exportExcel(exportParams, pojoClass, list);if (workbook != null) {downLoadExcel(fileName, response, workbook);}}/*** 方法描述 -> Excel导出** @param fileName 文件名称* @param workbook Excel对象* @Author: ywz* @Date: 2024/08/20*/private static void downLoadExcel(String fileName, HttpServletResponse response, Workbook workbook) {try {response.setCharacterEncoding("UTF-8");response.setHeader("content-Type", "application/vnd.ms-excel");response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));workbook.write(response.getOutputStream());} catch (IOException e) {throw new RuntimeException(e);}}/*** 方法描述 -> 默认导出方法** @param list 导出的实体集合* @param fileName 导出的文件名* @Author: ywz* @Date: 2024/08/20*/private static void defaultExport(List<Map<String, Object>> list, String fileName, HttpServletResponse response) {Workbook workbook = ExcelExportUtil.exportExcel(list, ExcelType.HSSF);if (workbook != null) ;downLoadExcel(fileName, response, workbook);}/*** 方法描述 -> 根据文件路径来导入Excel** @param filePath 文件路径* @param titleRows 表标题的行数* @param headerRows 表头行数* @param pojoClass Excel实体类* @Author: ywz* @Date: 2024/08/20*/public static <T> List<T> importExcel(String filePath, Integer titleRows, Integer headerRows, Class<T> pojoClass) {//判断文件是否存在if (StringUtils.isBlank(filePath)) {return null;}ImportParams params = new ImportParams();params.setTitleRows(titleRows);params.setHeadRows(headerRows);List<T> list = null;try {list = ExcelImportUtil.importExcel(new File(filePath), pojoClass, params);} catch (NoSuchElementException e) {throw new RuntimeException("模板不能为空");} catch (Exception e) {e.printStackTrace();}return list;}/*** 方法描述 -> 根据接收的Excel文件来导入Excel,并封装成实体类** @param file 上传的文件* @param titleRows 表标题的行数* @param headerRows 表头行数* @param pojoClass Excel实体类* @Author: ywz* @Date: 2024/08/20*/public static <T> List<T> importExcel(MultipartFile file, Integer titleRows, Integer headerRows, Class<T> pojoClass) {if (file == null) {return null;}ImportParams params = new ImportParams();params.setTitleRows(titleRows);params.setHeadRows(headerRows);List<T> list = null;try {list = ExcelImportUtil.importExcel(file.getInputStream(), pojoClass, params);} catch (NoSuchElementException e) {throw new RuntimeException("excel文件不能为空");} catch (Exception e) {throw new RuntimeException(e.getMessage());}return list;}}
定义实体类
package com.ywz.entity;import cn.afterturn.easypoi.excel.annotation.Excel;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;import java.time.LocalDateTime;@ApiModel("用户实体类")
@Data
public class User {@ApiModelProperty("用户id")@Excel(name = "用户id", orderNum = "0")private Integer id;@ApiModelProperty("用户名")@Excel(name = "用户名", orderNum = "1")private String name;@ApiModelProperty("密码")@Excel(name = "密码", orderNum = "2")private String password;@ApiModelProperty("年龄")@Excel(name = "年龄", orderNum = "3")private Integer age;@ApiModelProperty("状态")@Excel(name = "状态", orderNum = "6", replace = {"正常_1", "禁用_0"})private Integer status;@ApiModelProperty("创建时间")@Excel(name = "创建时间", orderNum = "4", exportFormat = "yyyy-MM-dd HH:mm:ss")private LocalDateTime createTime;
}
测试
准备个excel文件进行导入:
测试方法:
package com.ywz;import com.ywz.entity.User;
import com.ywz.utils.EasyPoiUtil;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;import java.util.List;@SpringBootTest
public class EasyPoiTest {@Testpublic void importExcel() {String file = "D:\\用户表.xlsx";List<User> users = EasyPoiUtil.importExcel(file, 0, 1, User.class);System.out.println(users);}
}
在控制台查看导入成功: