java中操作excel的库是poi,但是poi有很多问题,使用复杂,内存占用大等,阿里开源了一个操作excel的库叫easyexcel,它基于poi做了很多优化,平时读写excel建议使用这个库
文档地址: 关于Easyexcel | Easy Excel 官网
写入excel
在实体类上写excel字段注解,ExcelProperty注解就是导出的列名,ExcelIgnoreUnannotated表示没加ExcelProperty注解的字段不会写入
@ExcelIgnoreUnannotated
@Getter
@Setter
@Schema(name = "User", description = "用户")
public class User implements Serializable {private static final long serialVersionUID = 1L;@TableId(value = "id", type = IdType.AUTO)private Integer id;@ExcelProperty("姓名")@Schema(description = "姓名")private String name;@ExcelProperty("金币数量")@Schema(description = "金币数量")private Integer coinNum;
}
public void testWriteExcel() {String fileName = "d:/aaa.xlsx";List<User> users = new ArrayList<>();User user = new User();user.setName("张三");user.setCoinNum(100);users.add(user);user = new User();user.setName("李四");user.setCoinNum(200);users.add(user);// 写入本地excel文件EasyExcel.write(fileName, User.class).sheet("模板").doWrite(() -> {// 返回写入的数据return users;});}
可以看到,excel数据成功写入了,但是标题换行了,如果想标题不换行可以指定列宽,使用ColumnWidth注解,加在类上面表示所有列宽度都是这个数值,也可以加到指定字段上
导出excel
写法跟写入excel差不多,这里加了个出错返回json,这样出错了前端可以给出提示
@RestController
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserService userService;@GetMapping("download")public void download(HttpServletResponse response) throws IOException {// 导出excel如果失败会返回jsontry {response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");response.setCharacterEncoding("utf-8");// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");// 这里需要设置不关闭流,这样失败了可以返回jsonEasyExcel.write(response.getOutputStream(), User.class).autoCloseStream(Boolean.FALSE).sheet("模板").doWrite(userService.list());} catch (Exception e) {// 重置responseresponse.reset();response.setContentType("application/json");response.setCharacterEncoding("utf-8");Map<String, String> map = MapUtils.newHashMap();map.put("status", "failure");map.put("message", "下载文件失败" + e.getMessage());response.getWriter().println(JSON.toJSONString(map));}}
}
读取excel
这里推荐使用PageRead,默认一次读取100条
@Testpublic void testPageRead() {String fileName = "d:/aaa.xlsx";// 这里默认每次会读取100条数据// 具体需要返回多少行可以在`PageReadListener`的构造函数设置EasyExcel.read(fileName, User.class, new PageReadListener<User>(dataList -> {for (User demoData : dataList) {log.info("读取到一条数据{}", JSON.toJSONString(demoData));}})).sheet().doRead();}
导入excel
导入也跟读取excel类似,使用MultipartFile接收excel文件,使用PageReadListener读取数据
@RestController
@RequestMapping("/user")
public class UserController extends BaseController {@Autowiredprivate UserService userService;@PostMapping("upload")public Result upload(@RequestPart MultipartFile file) throws IOException {EasyExcel.read(file.getInputStream(), User.class, new PageReadListener<User>(users -> {userService.saveBatch(users);})).sheet().doRead();return resultOk();}
}