业务场景:由于公司发展需要,现有大量的导入导出工作,一直都是用的apache-poi,现在部门领导要求使用EasyExcel(版本为 2.1.3),听说性能更好!EasyExcel重写了poi对Excel文件的解析逻辑,基本不会出现大文件解析导致的内存溢出。
于是我就上手了,但是!!!
因为公司强烈使用LocalDateTime
(注意EasyExcel是支持Date类型的,可以直接导入导出!)
所以我在做导入导出的时候就遇到问题了,报错如下:
Can not find 'Converter' support class LocalDateTime.
可是百度了一大堆,Google了一大堆都没有解决方案。。。如果不懂EasyExcel建议先去官网了解一下,很详细,好啦我就默认你已经了解过EasyExcel了,不多逼逼,上代码!
新建User类,然后在类上添加EasyExcel的注解
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
@ExcelProperty(value = "姓名", index = 0)
private String name;
@ExcelProperty(value = "年龄", index = 1)
private Integer age;
@ExcelProperty(value = "性别", index = 2)
private Integer sex;
@ExcelProperty(value = "创建时间", index = 3)
private LocalDateTime createTime;
}
新建Controller用于测试
@Slf4j
@RestController
public class ExcelController {
@PostMapping("/importData")
public void importData(@RequestParam("file") MultipartFile file) throws IOException {
if (file == null) return;
ArrayList<Object> list = new ArrayList<>();
AnalysisEventListener listener = new AnalysisEventListener() {
@Override
public void invoke(Object data, AnalysisContext context) {
list.add(data);
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
log.info("导入数据完毕");
}
};
try {
EasyExcel.read(file.getInputStream(), User.class, listener).sheet(0).doRead();
} catch (IOException e) {
log.error("导入出错:{}", e.getMessage());
}
list.forEach(System.out::println);
}
@PostMapping("/exportData")
public void exportData(HttpServletResponse response) {
List<User> list = getList();
try {
response.setContentType("application/vnd.ms-excel; charset=utf-8");
response.setCharacterEncoding("utf-8");
String fileName = "三好学生表";
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "utf-8") + ".xlsx");
EasyExcel.write(response.getOutputStream(), User.class).sheet("test").doWrite(list);
} catch (Exception e) {
log.error("下载报表异常:{}", e.getMessage());
throw new RuntimeException("下载报表异常");
}
}
private List<User> getList() {
List<User> list = new ArrayList<>();
LocalDateTime now = LocalDateTime.now();
User xd = new User("熊大", 10, 1, now);
User ne = new User("牛二", 20, 0, now);
User zs = new User("张三", 30, 1, now);
User ls = new User("李四", 40, 1, now);
User ww = new User("王五", 50, 0, now);
list.add(xd);
list.add(ne);
list.add(zs);
list.add(ls);
list.add(ww);
return list;
}
}
访问exportData接口即会报如上的错,那么怎么解决呢?首先我可以告诉你解决方案!就是自定义转换器,因为我们要转换LocalDateTime,所以编写如下转换器!注意要实现的是com.alibaba.excel.converters.Converter
接口,别引用错包了!
public class LocalDateTimeConverter implements Converter<LocalDateTime> {
@Override
public Class<LocalDateTime> supportJavaTypeKey() {
return LocalDateTime.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
@Override
public LocalDateTime convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
return LocalDateTime.parse(cellData.getStringValue(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
}
@Override
public CellData<String> convertToExcelData(LocalDateTime value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
return new CellData<>(value.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
}
}
ExcelWriterBuilders
是支持对单次的操作添加converter的,那样就不需要为需要转换的字段单独添加converter了
定义全局Converter加载器以及Converter使用总结
以上三种方式只需使用一种!修改代码完毕之后再重启就可以了,不管是导入还是导出都没问题!时间已经可以正常写入Excel啦!赶快试试吧!
加油!