背景说明
最近做excel的导入,第一个想到的就是esaypoi。
达成目的
数据导入成功,失败的数据说明,是多少行错误,错误原因等
解决方式
esaypoi官方文档:http://doc.wupaas.com/docs/easypoi/easypoi-1c0u6ksp2r091
或者http://easypoi.mydoc.io/
找到一篇博客,可以参考,这个老哥写的很棒。easypoi导入Excel最佳实践
easypoi的导入用法很简单,就是加上注释,然后就可以使用了。
@Data
@Getter
@Setter
@ExcelTarget("exportVO")
public class ExportVO implements IExcelDataModel, IExcelModel {
/**
* 行号
*/
private int rowNum;
/**
* 错误消息
*/
private String errorMsg;
/**
* 编号
*/
private Integer id;
/**
* 姓名
*/
@Excel(name = "姓名")
@NotBlank(message = "[姓名]不能为空")
private String name;
/**
* 密码
*/
private String password;
/**
* 手机号
*/
@Excel(name = "手机号")
@NotBlank(message = "[手机号]不能为空")
@Pattern(regexp = "/^(([0+]d{2,3}-)?(0d{2,3})-)(d{7,8})(-(d{3,}))?$/", message = "[状态]错误,只能为0否,或者1是")
private String phone;
/**
* 身份证号码
*/
@Excel(name = "身份证号码")
@NotBlank(message = "[身份证号码]不能为空")
private String idCard;
/**
* 学院id
*/
@Excel(name = "学院")
private String collegeId;
/**
* 状态 0=未激活 1激活
*/
@Excel(name = "状态")
@Pattern(regexp = "[01]", message = "[状态]错误,只能为0否,或者1是")
private String status;
/**
* 创建人
*/
private String createUser;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新人
*/
private String updateUser;
/**
* 更新时间
*/
private Date updateTime;
}
如果直接导入的话,这些代码就够了。
ImportParams params = new ImportParams();
// 表格标题行数,默认0(我没有大标题,故是0)
params.setTitleRows(0);
// 表头行数,默认1(我的字段在第一行,占了一行)
params.setHeadRows(1);
List<exportVO> result = ExcelImportUtil.importExcel(multipartFile.getInputStream(), exportVO.class, params);
那要是有问题呢?
public List<ExportErrorMsg> uploadFileToExport(MultipartFile file, HttpServletResponse response) {
ImportParams params = new ImportParams();
params.setTitleRows(0);
params.setHeadRows(1);
//开启easypoi校验
params.setNeedVerfiy(true);
try {
//List<exportVO> result = ExcelImportUtil.importExcel(file.getInputStream(), exportVO.class, params);
// 复杂的数据校验
ExcelImportResult<ExportVO> result = ExcelImportUtil.importExcelMore(file.getInputStream(), ExportVO.class, params);
// System.out.println("是否校验失败: " + result.isVerfiyFail());
// System.out.println("校验失败的集合:" + JSONObject.toJSONString(result.getFailList()));
// System.out.println("校验通过的集合:" + JSONObject.toJSONString(result.getList()));
ArrayList<ExportErrorMsg> errorMsgList = new ArrayList<>();
//记录错误的数据信息
for (ExportVO entity : result.getFailList()) {
errorMsgList.add(new ExportErrorMsg(entity.getRowNum(), entity.getErrorMsg()));
}
//转换成安全的list
List<ExportErrorMsg> lists = Collections.synchronizedList(errorMsgList);
//并行流操作
result.getList().parallelStream().forEach( u ->{
String idCard = u.getIdCard();
// 查询数据是是否重复
User dataUser = this.userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getIdCard, idCard).or().eq(User::getPhone, u.getPhone()));
// 没有重复就入库
if (dataUser == null){
User user = new User();
BeanUtils.copyProperties(u, user);
user.setCreateTime(new Date());
user.setPassword(idCard.substring(idCard.length()-6, idCard.length()));
this.userMapper.insert(user);
} else {
// 有重复就报错信息
lists.add(new ExportErrorMsg(u.getRowNum(), "数据重复或者数据已经存在"));
}
});
// 排序所需信息的行号
List<ExportErrorMsg> collectList = lists.stream().sorted(Comparator.comparing(ExportErrorMsg::getRowNum)).collect(Collectors.toList());
// 返回
return collectList;
} catch (Exception e) {
log.error("数据导出失败!", e);
throw new RuntimeException("数据导入失败", e);
}
}
就是每一步记录一下数据情况,然后能入库的入库,不能入库的记录错误信息。
评论区