前面我们介绍了 SpringBoot 中使用 JeecgBoot 的 Autopoi 导出 Excel,其实 Autopoi 的底层也是 EasyPoi,对于 Excel 的导入/导出也是非常方便的。那 EasyPoi 也是基于 POI 的,如果对这方面想要深究的,可以先看看原生 POI 的导入/导出方式,你会回来选择 EasyPoi 的
一、简介
EasyPoi 功能如同名字 easy,主打的功能就是容易,让一个没见接触过poi的人员就可以方便的写出 Excel 导出,Excel 模板导出,Excel 导入,Word 模板导出,通过简单的注解和模板语言(熟悉的表达式语法),完成以前复杂的写法
如果想了解 JeecgBoot 的 Autopoi,可以参考我的另一篇博客,SpringBoot 中使用 JeecgBoot 的 Autopoi 导出 Excel
https://blog.csdn.net/qq_40065776/article/details/107824221
二、引入 EasyPoi
EasyPoi 在 SpringBoot 中也是做了很好的封装,让我们能够在 SpringBoot 快速地使用 EasyPoi 进行开发
<!-- easypoi -->
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-spring-boot-starter</artifactId>
<version>4.2.0</version>
</dependency>
我们只需要引入这一个依赖即可,这是对 SpringBoot 做了很好的支持
三、源码解读
1、@Excel 源码解读
通过查阅源码,我们不难从 cn.afterturn.easypoi.excel.annotation.Excel 注解中发现
package cn.afterturn.easypoi.excel.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Excel {
public String name();
public String orderNum() default "0";
public String[] replace() default { };
public String dict() default "";
}
以上是 @Excel 注解的代码片段,我们可以看出该注解中支持两种字典替换方式
- 1、replace,该方式支持直接写入注解参数中,如:
@Excel(name = "性别", width = 15, replace = "男_1,女_2")
@TableField("sex")
private Integer sex;
我们用 1 表示 男性,2 表示 女性,这样我们在导出的时候,就能够自动替换掉数据中的魔法值,但是这样我们往往要在注解参数中写入过多的代码,而且我们的字典往往是动态变化的,这样的局限性太大
- 2、dict,字典方式,传入字典参数中,如:
@Excel(name = "性别", width = 15, dict = "sex")
@TableField("sex")
private Integer sex;
这里我们只传入的字典的 key,这样我们在查询出数据的时候,写入 Excel 文件时,在进行动态替换,即可替换掉数据中的魔法值,增加数据的可读性
2、IExcelDictHandler 源码解读
上一步,我们已经知道了在 EasyPoi 中是支持自定义字典查询导出的,那么我们该如何实现它呢?通过阅读 cn.afterturn.easypoi.handler.inter.IExcelDictHandler 接口中的代码,代码如下:
package cn.afterturn.easypoi.handler.inter;
import java.util.List;
import java.util.Map;
public interface IExcelDictHandler {
default public List<Map> getList(String dict) {
return null;
}
public String toName(String dict, Object obj, String name, Object value);
public String toValue(String dict, Object obj, String name, Object value);
}
接口中提供了三个方法:
- 1、getList,通过字典 key 查询该 key 下的所有字典数据,例如:sex 下的 {“1”:“男”, “2”:“女”}
- 2、toName,字典的翻译功能,从值翻译到名称,例如:sex: 1 --> “男”,一般导出的时候使用
- 3、toValue,与 toName 相反,从名称翻译到值,例如:sex: “男” --> 1,一般导入的时候使用
既然我们知道在 EasyPoi 中提供了字典翻译的接口,那我们只需要提供一个实现类,重写接口中的方法即可,IExcelDictHandlerImpl.java 实现 IExcelDictHandler 接口,代码如下:
package com.zyxx.common.excel;
import cn.afterturn.easypoi.handler.inter.IExcelDictHandler;
import com.zyxx.sys.service.SysDictDetailService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Slf4j
@Component
public class IExcelDictHandlerImpl implements IExcelDictHandler {
@Autowired
private SysDictDetailMapper testSysDictDetailMapper;
private static SysDictDetailMapper sysDictDetailMapper;
@PostConstruct
public void init() {
sysDictDetailMapper = this.testSysDictDetailMapper;
}
@Override
public String toName(String dict, Object obj, String name, Object value) {
return sysDictDetailMapper.getTextByDictAndValue(dict, String.valueOf(value));
}
@Override
public String toValue(String dict, Object obj, String name, Object value) {
return null;
}
}
- 1、这里我们导出,只使用了 toName(从值翻译到名称)这个方法,所以,只写了一个方法
- 2、我们需要使用 @Component 注解将它加载到 Spring 容器中
- 3、@PostConstruct 该注解被用来修饰一个非静态的 void() 方法。被 @PostConstruct 修饰的方法会在服务器加载 Servlet 的时候运行,并且只会被服务器执行一次。PostConstruct 在构造函数之后执行,init() 方法之前执行
四、开始导出
1、定义实体类
package com.zyxx.sys.entity;
import cn.afterturn.easypoi.excel.annotation.Excel;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.zyxx.common.annotation.Dict;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("sys_user_info")
@ApiModel(value = "SysUserInfo对象", description = "用户信息表")
public class SysUserInfo extends Model<SysUserInfo> {
@ApiModelProperty(value = "ID")
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@Excel(name = "姓名", width = 15)
@ApiModelProperty(value = "姓名")
@TableField("name")
private String name;
@Excel(name = "电话", width = 15)
@ApiModelProperty(value = "电话")
@TableField("phone")
private String phone;
@Excel(name = "性别", width = 15, dict = "sex")
@TableField("sex")
@Dict(dictCode = "user_sex")
private Integer sex;
@Excel(name = "状态", width = 15, dict = "status")
@TableField("status")
private Integer status;
}
@Excel 注解解释如下:
- name,表头名称
- width,列宽
- dict,字典 key
2、导出 API 接口
controller 层提供导出 API
@ApiOperation(value = "导出用户信息", notes = "导出用户信息")
@GetMapping(value = "/export")
public void exportXls(HttpServletResponse response) {
// 查询数据
List<SysUserInfo> list = sysUserInfoService.list(1, Integer.MAX_VALUE);
// 导出数据,数据,数据类型,文件名称,表名,响应对象
ExportExcelUtil.exportExcel(list, SysUserInfo.class, "用户信息表", "用户信息统计", response);
}
3、导出工具类
public static void exportExcel(List<?> list, Class<?> pojoClass, String fileName, String title, HttpServletResponse response) {
ExportParams exportParams = new ExportParams(title, null);
// 自定义字典查询规则
exportParams.setDictHandler(new IExcelDictHandlerImpl());
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, pojoClass, list);
if (workbook != null) {
try {
response.setCharacterEncoding("UTF-8");
response.setHeader("content-Type", "application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8") + ".xls");
workbook.write(response.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
}
exportParams.setDictHandler(new IExcelDictHandlerImpl());,我们传入了自定义的字典查询规则
五、测试导出
我们调取导出数据的 API 接口,即可导出文件,导出效果如下:
六、总结
可以看出,自定义字典查询导出方式,其实和 JeecgBoot 的 Autopoi 方式都大同小异,后面是发现了 JeecgBoot 的 Autopoi 和 hutool 的读取文件 ExcelReader 有冲突,放弃了 JeecgBoot 的 Autopoi,EasyPoi 确实是一款强大的 Excel 操作产品!!!
如您在阅读中发现不足,欢迎留言!!!