前言
项目开发中,我们经常会遇到使用Excel实现导入导出的需求,推荐一款性能比较好的Excel导入导出工具EasyExcel,简单记录一下使用的步骤,希望对大家有所帮助!提示:以下是本篇文章正文内容,下面案例可供参考
一、EasyExcel简介
EasyExcel是一款阿里开源的Excel导入导出工具,具有处理快速、占用内存小、使用方便的特点,在Github上已有22k+Star,可见其非常流行。
EasyExcel读取75M(46W行25列)的Excel,仅需使用64M内存,耗时20s,极速模式还可以更快!
官方网站:https://yuque.com/easyexcel
github地址:https://github.com/alibaba/easyexcel
二、使用步骤
EasyExcel和EasyPoi的使用非常类似,都是通过注解来控制导入导出。接下来我们以用户信息的导入导出为例,分别实现下简单的单表导入导出
1.引入库
我这里选择的easyexcel版本是2.2.6
代码如下:
<!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.6</version>
</dependency>
2.创建用户信息对象,自定义转换器
EasyExcel的核心注解:
@ExcelProperty:核心注解,value属性可用来设置表头名称,converter属性可以用来设置类型转换器;
@ColumnWidth:用于设置表格列的宽度;
@DateTimeFormat:用于设置日期转换格式
首先创建一个用户信息对象ExportUserInfoDTO ,封装需要导出的用户信息
代码如下:
/**
* @Description : Excel导出用户信息对象
* @Author : 冰雪伯爵
* @Date : 2022/1/9
* <p>
* EasyExcel的核心注解:
* @ExcelProperty:核心注解,value属性可用来设置表头名称,converter属性可以用来设置类型转换器;
* @ColumnWidth:用于设置表格列的宽度;
* @DateTimeFormat:用于设置日期转换格式
**/
@Data
public class ExportUserInfoDTO {
@ExcelProperty("ID")
@ColumnWidth(20)
private Long id;
@ExcelProperty("用户名")
@ColumnWidth(20)
private String username;
@ExcelProperty("邮箱")
@ColumnWidth(20)
private String email;
@ExcelProperty("手机号")
@ColumnWidth(20)
private String mobile;
@ExcelProperty(value = "账号状态", converter = StatusConverter.class)
@ColumnWidth(20)
private Integer status;
@ExcelProperty("备注")
@ColumnWidth(20)
private String remark;
@ExcelProperty("创建时间")
@ColumnWidth(20)
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
private Date createTime;
}
然后自定义状态转换器,在EasyExcel中,如果想要实现枚举类型到字符串的转换,比如Status属性中,0->正常,1->停用,2->删除,需要自定义转换器,下面为自定义的StatusConverter代码实现;
代码如下:
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
/**
* @Description : 自定义转换器 状态
* @Author : 冰雪伯爵
* @Date : 2022/1/9
* <p>
* 在EasyExcel中,如果你想实现枚举类型到字符串的转换(比如Status属性中,0->正常,1->停用,2->删除),需要自定义转换器
**/
public class StatusConverter implements Converter<Integer> {
@Override
public Class supportJavaTypeKey() {
//对象属性类型(即:0,1,2... 对应的数据类型)
return Integer.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
//CellData属性类型
return CellDataTypeEnum.STRING;
}
/**
* CellData转对象属性
*
* @param cellData
* @param excelContentProperty
* @param globalConfiguration
* @return
* @throws Exception
* 正常->0,停用->1,删除->2
*/
@Override
public Integer convertToJavaData(CellData cellData, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
String value = cellData.getStringValue();
if (StringUtils.isEmpty(value)) {
return null;
}
if ("正常".equals(value)) {
return 0;
} else if ("停用".equals(value)) {
return 1;
} else if ("删除".equals(value)) {
return 2;
} else {
return null;
}
}
/**
* 对象属性转CellData
*
* @param value
* @param excelContentProperty
* @param globalConfiguration
* @return
* @throws Exception
* 0->正常,1->停用,2->删除
*/
@Override
public CellData convertToExcelData(Integer value, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
if (value== null) {
return new CellData<>("");
}
if (value == 0) {
return new CellData<>("正常");
} else if (value == 1) {
return new CellData<>("停用");
} else if (value == 2) {
return new CellData<>("删除");
} else {
return new CellData<>("");
}
}
}
3.在Controller中实现接口
最后在Controller中添加导入导出,用于导出用户信息列表到Excel,还需给响应头设置下载excel的属性,具体代码如下;
另外测试代码功能,建议直接用浏览器或者用postman,如果使用swagger 会导致各种莫名其妙的问题
代码如下:
/**
* @Description : EasyExcel导入导出Controller
* @Author : 冰雪伯爵
* @Date : 2022/1/9
**/
@Api(value = "EasyExcel导入导出Controller", tags = "EasyExcel导入导出Controller")
@RestController
@RequestMapping("/easyExcel")
public class EasyExcelController {
private static final Logger log = LoggerFactory.getLogger(EasyExcelController.class);
@Autowired
private SysUserService userService;
/**
* 【导出下载方式一】
* @param response
*/
@ApiOperation("导出用户信息列表Excel")
@RequestMapping(value = "/exportList", method = RequestMethod.GET)
public void exportList(HttpServletResponse response) {
log.info("easyExcel,导出用户信息列表Excel---------->>>>>start ");
List<ExportUserInfoDTO> userList = userService.exportList();
try {
setExcelRespProp(response, "用户信息表");
// 这里需要设置不关闭流
EasyExcel.write(response.getOutputStream())
.head(ExportUserInfoDTO.class)
.excelType(ExcelTypeEnum.XLSX)
.sheet("用户信息sheet")
.doWrite(userList);
} catch (Exception e) {
e.printStackTrace();
log.error("导出用户信息列表Excel 失败")
}
log.info("easyExcel,导出用户信息列表Excel---------->>>>>end ");
}
/**
* 【导出下载方式二】
* 文件下载并且失败的时候返回json(默认失败了会返回一个有部分数据的Excel)
* 使用swagger 会导致各种问题,请直接用浏览器或者用postman
*
* @param response
* @throws IOException
*/
@ApiOperation("文件下载并且失败的时候返回json")
@RequestMapping(value = "/downloadFailedUsingJson", method = RequestMethod.GET)
public void downloadFailedUsingJson(HttpServletResponse response) throws IOException {
List<ExportUserInfoDTO> userList = userService.exportList();
try {
setExcelRespProp(response, "用户信息表");
// 这里需要设置不关闭流
EasyExcel.write(response.getOutputStream(), ExportUserInfoDTO.class)
.autoCloseStream(Boolean.FALSE)
.sheet("模板")
.doWrite(userList);
} catch (Exception e) {
// 重置response
response.reset();
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
Map<String, String> map = new HashMap();
map.put("status", "failure");
map.put("message", "下载文件失败" + e.getMessage());
response.getWriter().println(JSON.toJSONString(map));
}
}
@ApiOperation("从Excel导入用户信息列表")
@RequestMapping(value = "/importList", method = RequestMethod.POST)
@ResponseBody
public RestResponceBody importList(@RequestPart("file") MultipartFile file) {
log.info("easyExcel,导入用户信息列表Excel---------->>>>>start ");
try {
List<ExportUserInfoDTO> userList = EasyExcel.read(file.getInputStream())
.head(ExportUserInfoDTO.class)
.sheet()
.doReadSync();
log.info("easyExcel,导入用户信息列表Excel---------->>>>>end ");
return new RestResponceBody<>(userList);
} catch (IOException e) {
e.printStackTrace();
log.error("导入用户信息列表Excel 失败")
}
}
/**
* 设置excel下载响应头属性
*
* @param response
* @param rawFileName 文件名
* @throws UnsupportedEncodingException
*/
private void setExcelRespProp(HttpServletResponse response, String rawFileName) throws UnsupportedEncodingException {
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
//这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
String fileName = URLEncoder.encode(rawFileName, "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
}
}
4.运行项目,测试导入导出
1、运行项目,使用postman测试接口,测试导出下载文件
下载完成后,查看导出下载好的Excel文件
2、运行项目,使用postman测试接口,测试导入Excel文件
至此,使用EasyExcel导入导出功能已完成