行业知识
easypoi实现Excel模板导入(包含文档下载的与前端交互回显)
实战使用easypoi完成Excel模板导入,且包含一对多的导入,模板文件的下载 和 下载成功后浏览器页面的回显功能。
目录
1、后端代码
2、前端代码
3、导入文件的坑
3.1无法读取某列的数据
3.2一对多的导入注意事项
模板文件的样例:
导入成功后的提示:
1、后端代码
依赖:
使用easypoi依赖和hutool包
cn.afterturn easypoi-base 4.3.0 cn.afterturn easypoi-web 4.3.0 cn.afterturn easypoi-annotation 4.3.0 cn.hutool hutool-core 5.3.8 cn.hutool hutool-crypto 5.3.8 cn.hutool hutool-extra 5.3.8 cn.hutool hutool-http 5.3.8
接口:
@Autowiredprivate ImportExpertListExcelUtil importExpertListExcelUtil;/** * 通过excel导入数据 */@PostMapping(value = "/importExcel")public Result importExcel(HttpServletRequest request, HttpServletResponse response) { return importExpertListExcelUtil.importExcel(request, response, ExpertInformation.class);} 实体类:
@Data@TableName("expert_information")public class ExpertInformation implements Serializable { private static final long serialVersionUID = 1L; /** * id */ @TableId(type = IdType.ASSIGN_ID) private java.lang.String id; /** * 姓名 */ @NotNull(message = "姓名不能为空") @Excel(name = "姓名", needMerge = true, width = 15) private java.lang.String name; /** * 国家/地区 */ @Excel(name = "国家/地区", needMerge = true, width = 15) private java.lang.String country; /** * 证件类型 */ @Excel(name = "证件类型", needMerge = true, width = 15) private java.lang.String credentialType; /** * 证件号码 */ @NotNull(message = "证件号码不能为空") @Excel(name = "证件号码", needMerge = true, width = 30) private java.lang.String credentialNumber; /** * 毕业学校 */ @Excel(name = "毕业学校", needMerge = true, width = 30) private java.lang.String graduationSchool; /** * 学历 */ @Excel(name = "学历", needMerge = true, width = 15) private java.lang.String degree; /** * 联系电话 */ @NotNull(message = "联系电话不能为空") @Excel(name = "联系电话", needMerge = true, width = 15) private java.lang.String phone; /** * 邮箱 */ @Excel(name = "邮箱", needMerge = true, width = 15) @NotNull(message = "邮箱不能为空") private java.lang.String mail; /** * 开户银行名称 */ @Excel(name = "开户银行名称", needMerge = true, width = 30) private java.lang.String openedBankName; /** * 其开户银行名称 */ @Excel(name = "其开户银行名称(选择 其他 时展示)", width = 30) @TableField(updateStrategy = FieldStrategy.IGNORED) //更新操作时,无论字段是否为 空字符串,都会进行更新 private java.lang.String otherOpenedBankName; /** * 银行账户 */ @Excel(name = "银行账户", needMerge = true, width = 30) private java.lang.String bankAccount; /** * 评审范围 */ @Excel(name = "评审范围", width = 15) @TableField(updateStrategy = FieldStrategy.IGNORED) //更新操作时,无论字段是否为 空字符串,都会进行更新 private java.lang.String scopeAssessment; @TableField(exist = false) private List checkedList; /** * 单位-列表 */ @TableField(exist = false) @ExcelCollection(name = "工作经历") private List unit; /** * 单位名称 */ @TableField(exist = false) private String companyName;} @Data@TableName("expert_work_experience")public class ExpertWorkExperience implements Serializable { private static final long serialVersionUID = 1L; /** * id */ @TableId(type = IdType.ASSIGN_ID) private java.lang.String id; /** * 专家主键id */ private java.lang.String expertInformationId; /** * 单位名称 */ @Excel(name = "单位名称", width = 30) private java.lang.String companyName; /** * 职位 */ @Excel(name = "职位", width = 15) private java.lang.String post;} 工具类方法:
@Slf4j@Componentpublic class ImportExpertListExcelUtil {/** * 通过excel导入数据 */ public Result importExcel(HttpServletRequest request, HttpServletResponse response, Class clazz) { MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; Map fileMap = multipartRequest.getFileMap(); //错误集合 List errorMsg = new ArrayList(); List totalExpertWorkExperienceList = new LinkedList(); for (Map.Entry entity : fileMap.entrySet()) { MultipartFile file = entity.getValue();// 获取上传文件对象 ImportParams params = new ImportParams(); params.setTitleRows(2); params.setHeadRows(1); params.setNeedSave(true); try { long start = System.currentTimeMillis(); //导入Excel格式校验,看匹配的字段文本概率 Boolean t = ExcelImportCheckUtil.check(file.getInputStream(), ExpertInformation.class, params); if (!t) { throw new RuntimeException("导入Excel校验失败 !"); } List expertInformationList = ExcelImportUtil.importExcel(file.getInputStream(), clazz, params); log.info("消耗时间" + (System.currentTimeMillis() - start) + "毫秒"); return Result.ok(String.format("文件导入成功:%s 行", expertInformationList.size()); } catch (Exception e) { log.error(e.getMessage(), e); return Result.error("文件导入失败:" + e.getMessage()); } finally { try { file.getInputStream().close(); } catch (Exception e) { e.printStackTrace(); } } } return Result.error("文件导入失败!"); }} List expertInformationList = ExcelImportUtil.importExcel(file.getInputStream(), clazz, params);
在这行代码导入Excel后,返回的数据可以根据自己的业务做一些校验,我这里当时对它的证件号码和手机号、邮箱这些字段做一些正则校验,这个代码我就省略了,只是demo演示一下导入Excel。
2、前端代码
导入按钮的功能:
这里有一对多的导入,这个导入按钮的代码就省略了,每个项目的前端使用框架不一样,封装的组件和方法也不一样,根据自身情况去官方开发文档查看即可。
--我这里前端框架使用的是ant-design的vue2版本,如果和我情况一样,可以评论问我,无偿分享这里的前端代码。
模板下载:
这里让用户把模板下载出来,再去填写数据,避免因为导入的Excel字段和实体类使用注解的name不一致。导致无法读取该列的数据。
@Excel(name = "单位名称", width = 30) private String companyName;
这个代码在这文章中t提供了文件下载,前端下载成功弹窗回显 和 注意事项,需要的可以去这个文章参考代码。
模板下载https://blog.csdn.net/RYH6817/article/details/136240011
3、导入文件的坑
3.1无法读取某列的数据
这里一定要注意使用注解中的name值,必须和Excel列的名字要一致,不然无法识别,就默认这列数据为null。
导入的Excel字段和实体类使用注解的name不一致。导致无法读取该列的数据。
@Excel(name = "单位名称", width = 30) private String companyName;
3.2一对多的导入注意事项
- 首先就是在父表ExpertInformation中有子表字段,
例如:在ExpertInformation中添加一个子表的list集合。
/** * 单位-列表 */ @TableField(exist = false) @ExcelCollection(name = "工作经历") private List unit;
这里需要使用注解 @ExcelCollection(name = "工作经历") ,而且也必须和页面的列名一致。不然也是无法识别子表的数据。
- 还有就是这个列名 “工作经历” 必须合并单元格,包含其子表需要导入的字段。我这里子表只导入:”单位名称“和”职位“两个字段。
完整的一对多模板表格如图:
- 子表 ExpertWorkExperience 的字段,也需要使用注解 @Excel(name = "单位名称", width = 30)
- 还有就是这个列名 “工作经历” 必须合并单元格,包含其子表需要导入的字段。我这里子表只导入:”单位名称“和”职位“两个字段。
上一篇:如何下载并保存微信聊天记录
下一篇:Git相关配置的指令