实战使用easypoi完成Excel模板导入,且包含一对多的导入,模板文件的下载 和 下载成功后浏览器页面的回显功能。
目录
1、后端代码
2、前端代码
3、导入文件的坑
3.1无法读取某列的数据
3.2一对多的导入注意事项
模板文件的样例:
导入成功后的提示:
1、后端代码
依赖:
使用easypoi依赖和hutool包
<dependency>
<groupId>***.afterturn</groupId>
<artifactId>easypoi-base</artifactId>
<version>4.3.0</version>
</dependency>
<dependency>
<groupId>***.afterturn</groupId>
<artifactId>easypoi-web</artifactId>
<version>4.3.0</version>
</dependency>
<dependency>
<groupId>***.afterturn</groupId>
<artifactId>easypoi-annotation</artifactId>
<version>4.3.0</version>
</dependency>
<!-- hutool工具类 版本:<hutool.version>5.3.8</hutool.version> -->
<dependency>
<groupId>***.hutool</groupId>
<artifactId>hutool-core</artifactId>
<version>5.3.8</version>
</dependency>
<dependency>
<groupId>***.hutool</groupId>
<artifactId>hutool-crypto</artifactId>
<version>5.3.8</version>
</dependency>
<dependency>
<groupId>***.hutool</groupId>
<artifactId>hutool-extra</artifactId>
<version>5.3.8</version>
</dependency>
<dependency>
<groupId>***.hutool</groupId>
<artifactId>hutool-http</artifactId>
<version>5.3.8</version>
</dependency>
接口:
java">@Autowired
private 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 bankA***ount;
/**
* 评审范围
*/
@Excel(name = "评审范围", width = 15)
@TableField(updateStrategy = FieldStrategy.IGNORED) //更新操作时,无论字段是否为 空字符串,都会进行更新
private java.lang.String scopeAssessment;
@TableField(exist = false)
private List<String> checkedList;
/**
* 单位-列表
*/
@TableField(exist = false)
@ExcelCollection(name = "工作经历")
private List<ExpertWorkExperience> unit;
/**
* 单位名称
*/
@TableField(exist = false)
private String ***panyName;
}
@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 ***panyName;
/**
* 职位
*/
@Excel(name = "职位", width = 15)
private java.lang.String post;
}
工具类方法:
@Slf4j
@***ponent
public class ImportExpertListExcelUtil {
/**
* 通过excel导入数据
*/
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response, Class<ExpertInformation> clazz) {
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
//错误集合
List<String> errorMsg = new ArrayList<>();
List<ExpertWorkExperience> totalExpertWorkExperienceList = new LinkedList<>();
for (Map.Entry<String, MultipartFile> 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<ExpertInformation> 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<ExpertInformation> expertInformationList = ExcelImportUtil.importExcel(file.getInputStream(), clazz, params);
在这行代码导入Excel后,返回的数据可以根据自己的业务做一些校验,我这里当时对它的证件号码和手机号、邮箱这些字段做一些正则校验,这个代码我就省略了,只是demo演示一下导入Excel。
2、前端代码
导入按钮的功能:
这里有一对多的导入,这个导入按钮的代码就省略了,每个项目的前端使用框架不一样,封装的组件和方法也不一样,根据自身情况去官方开发文档查看即可。
--我这里前端框架使用的是ant-design的vue2版本,如果和我情况一样,可以评论问我,无偿分享这里的前端代码。
模板下载:
这里让用户把模板下载出来,再去填写数据,避免因为导入的Excel字段和实体类使用注解的name不一致。导致无法读取该列的数据。
@Excel(name = "单位名称", width = 30) private String ***panyName;
这个代码在这文章中t提供了文件下载,前端下载成功弹窗回显 和 注意事项,需要的可以去这个文章参考代码。
模板下载https://blog.csdn.***/RYH6817/article/details/136240011
3、导入文件的坑
3.1无法读取某列的数据
这里一定要注意使用注解中的name值,必须和Excel列的名字要一致,不然无法识别,就默认这列数据为null。
导入的Excel字段和实体类使用注解的name不一致。导致无法读取该列的数据。
@Excel(name = "单位名称", width = 30) private String ***panyName;
3.2一对多的导入注意事项
- 首先就是在父表ExpertInformation中有子表字段,
例如:在ExpertInformation中添加一个子表的list集合。
/**
* 单位-列表
*/
@TableField(exist = false)
@ExcelCollection(name = "工作经历")
private List<ExpertWorkExperience> unit;
这里需要使用注解 @ExcelCollection(name = "工作经历") ,而且也必须和页面的列名一致。不然也是无法识别子表的数据。
- 还有就是这个列名 “工作经历” 必须合并单元格,包含其子表需要导入的字段。我这里子表只导入:”单位名称“和”职位“两个字段。
完整的一对多模板表格如图:
- 子表 ExpertWorkExperience 的字段,也需要使用注解 @Excel(name = "单位名称", width = 30)