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 {
@Autowired
private UserService userService;
@GetMapping("download")
public void download(HttpServletResponse response) throws IOException {
// 导出excel如果失败会返回json
try {
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");
// 这里需要设置不关闭流,这样失败了可以返回json
EasyExcel.write(response.getOutputStream(), User.class).autoCloseStream(Boolean.FALSE).sheet("模板")
.doWrite(userService.list());
} catch (Exception e) {
// 重置response
response.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条
@Test
public 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 {
@Autowired
private 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();
}
}