Springboot使用hutool实现Excel文件导入导出功能
导入依赖
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
<version>5.8.1</version>
</dependency>
Excel文件导入
导入后返回前端的信息实体VO
@Data
public class ImportReturnVO {
@ApiModelProperty(value = "是否所有记录都是有效导入的数据,只有所有数据都为有效数据才视为导入成功")
private Boolean isSuccessImport;
@ApiModelProperty(value = "是否所有记录都成功保存到数据库")
private Boolean isSuccessSave;
@ApiModelProperty(value = "无效导入的数据的数量")
private Integer errCount;
@ApiModelProperty(value = "Map{无效导入的数据行号 : 无效的原因}")
private Map<Integer, String> errItem;
@ApiModelProperty(value = "成功保存到数据库的数据总数")
private Integer count;
}
注:此处的导入是写死的,即每一列固定是表示什么数据
若需其他导入方式可参考
@Transactional(readOnly = false)
public ImportReturnVO importFromExcel(MultipartFile file) throws IOException {
ImportReturnVO returnVO = new ImportReturnVO();
InputStream inputStream = file.getInputStream();
ExcelReader reader = ExcelUtil.getReader(inputStream);
//跳过标题行,直接读取表的内容
List<List<Object>> objectList = reader.read(1);
//导入保存的实体列表
List<Entity> list = new ArrayList<>();
//{无效的数据行号 : 无效的原因}
Map<Integer, String> errItem = new HashMap<>();
for (int i = 0; i < objectList.size(); i++) {
//一行的所有数据
List<Object> row = objectList.get(i);
//若该行有哪列数据格式错误,拼接错误消息
StringBuilder errMsg = new StringBuilder();
//导入后保存到数据库表的实体
//Entity e = new Entity();
//...判断数据合法性及赋值...
//含有非法数据
if (errMsg.length() > 0) {
//行号从2开始,第1行标题不读,[i+2]为当前行号
errItem.put(i + 2, errMsg.toString());
} else {
list.add(entity);
}
}
//导入失败
if (errItem.size() > 0) {
returnVO.setErrItem(errItem);
returnVO.setErrCount(errItem.size());
returnVO.setIsSuccessImport(false);
return returnVO;
} else {
//导入成功
returnVO.setIsSuccessImport(true);
returnVO.setErrCount(0);
}
//将导入的列表保存到数据库
int count = 0;
//...
//保存数据库成功
if (count == list.size()) {
returnVO.setCount(count);
returnVO.setIsSuccessSave(true);
} else {
//保存数据库失败
returnVO.setIsSuccessSave(false);
//手动回滚
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
return returnVO;
}
Excel文件导出
@Data
public class ExportVO {
@ApiModelProperty(value = "要导出的实体id列表")
private List<String> idList;
//添加其余条件查询所需的字段...
}
//在Excel中显示的行数据对象
@Data
public class EntityExcel {
private String title;
private String details;
}
@Transactional(readOnly = true)
public void exportToExcel(ExportVO vo, HttpServletResponse response) {
//默认创建xls格式的(getWriter(true)则创建xlsx格式)
ExcelWriter writer = ExcelUtil.getWriter(true);
//自定义标题别名(Excel的标题行/第一行),根据EntityExcel的属性映射对应的标题名
writer.addHeaderAlias("title", "标题");
writer.addHeaderAlias("details", "详情");
EntityExample example = new EntityExample();
//逻辑删除字段
example.createCriteria().andDelFlagEqualTo(Entity.DEL_FLAG_NORMAL);
List<String> idList = vo.getIdList();
//id列表为空, 则导出所有未被删除的实体
//id列表不为空,则导出id列表对应的实体
if (idList != null && idList.size() > 0) {
example.getOredCriteria().get(0).andIdIn(idList);
}
List<Entity> list = mapper.selectByExample(example);
//Excel行数据,一个EntityExcel对应一行数据
List<EntityExcel> rows = new ArrayList<>();
for (Entity e : list) {
EntityExcel entityExcel = new EntityExcel();
//给EntityExcel行数据赋值
BeanUtils.copyProperties(e, entityExcel);
rows.add(entityExcel);
}
// 一次性写出内容,使用默认样式
writer.write(rows, true);
//response为HttpServletResponse对象
response.setContentType("application/vnd.ms-excel");
ServletOutputStream out = null;
//文件名格式:文件+当前时间,如文件20220617094900
String rawFileName = "文件" + DateUtil.format(new Date(), DatePattern.PURE_DATETIME_PATTERN);
try {
//弹出下载对话框的文件名不能为中文,中文请自行编码
//P.S 这里可以中文命名,但是只能通过URL请求,通过swagger或postman请求还是会乱码,若要测试可以通过Get请求
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(rawFileName, "UTF-8") + ".xlsx");
out = response.getOutputStream();
writer.flush(out, true);
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭writer,释放内存
writer.close();
//此处记得关闭输出Servlet流
IoUtil.close(out);
}
}
本文参考地址
若有误,欢迎评论区指正~