前言:
Excel 导入是一个非常常见的功能,项目开发中随处可见,市面上也有各种处理 Excel 的 API,本文简单分享一下 alibaba.excel 的导入功能。
引入依赖:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.2.1</version>
</dependency>
定义实体类:
@Data
public class ImportVO {
@ExcelProperty(index = 0, value = {"手机号"})
private String phoneNo;
@ExcelProperty(index = 1, value = {"用户姓名"})
private String userName;
@ApiModelProperty("分值")
@ExcelProperty(index = 1, value = {"分值"})
private BigDecimal score;
@ApiModelProperty("部门")
@ExcelProperty(index = 3, value = {"部门"})
private String department;
}
创建监听器:
需要注意的是监听器不能被 Spring 管理,每次使用时需要 new 来创建对象,需要用到 Spring 对象的时候,可以通过构造方法传进去,或者使用 getBean 方法来获取。
@Data
@EqualsAndHashCode(callSuper = true)
@Slf4j
public class ImportListener extends AnalysisEventListener<SatisfactionEvaluationImportVO> {
private AService aService;
private BService bService;
//构造方法
public ImportListener(AService aService, BService bService) {
this.aService = aService;
this.bService = bService;
}
//getBean
private CService cService = SpringContextHolder.getBean("cServiceImpl");
/**
* 返回结果
*/
private List<ImportVO> importDataList = new ArrayList<>();
/**
* @param headMap: key 表头索引 value 为名称
* @param context:
* @author author
* @date 2024/6/13 15:16
* @description 表头校验
*/
@Override
public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
int count = 0;
// 获取数据实体的字段列表
Field[] fields = ImportVO.class.getDeclaredFields();
// 遍历字段进行判断
for (Field field : fields) {
// 获取当前字段上的ExcelProperty注解信息
ExcelProperty fieldAnnotation = field.getAnnotation(ExcelProperty.class);
// 判断当前字段上是否存在ExcelProperty注解
if (fieldAnnotation != null) {
++count;
// 存在ExcelProperty注解则根据注解的index索引到表头中获取对应的表头名
String headName = headMap.get(fieldAnnotation.index());
// 判断表头是否为空或是否和当前字段设置的表头名不相同
if (StringUtils.isEmpty(headName) || !headName.equals(fieldAnnotation.value()[0])) {
// 如果为空或不相同,则抛出异常不再往下执行
throw new RuntimeException("请使用正确的导入模板!");
}
}
}
// 判断用户导入表格的标题头是否完全符合模板
if (count != headMap.size()) {
throw new RuntimeException("请使用正确的导入模板!");
}
}
/**
* @param importVO:
* @param analysisContext:
* @author author
* @date 2024/6/13 15:16
* @description 每解析一行数据都会调用 invoke 方法
*/
@Override
public void invoke(ImportVO importVO, AnalysisContext analysisContext) {
int rowIndex = analysisContext.readRowHolder().getRowIndex() + 1;
//数据校验--根据自己的业务需求
//处理数据--根据自己的业务需求
//加入结果集
importDataList.add(importVO);
}
/**
* @param analysisContext:
* @author author
* @date 2024/6/13 15:19
* @description 所有数据解析完了会来调用
*/
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
}
}
Controller 层导入方法使用:
@PostMapping("/import")
@ApiOperation(httpMethod = "POST", value = "导入测试", notes = "导入测试")
public RetVo<Void> satisfactionImport(@RequestParam("file") MultipartFile file) throws IOException {
ImportSatisfactionEvaluationListener listener = new ImportSatisfactionEvaluationListener();
try {
//getbean 方式 获取bean
EasyExcel.read(file.getInputStream(), ImportVO.class, new ImportListener()).sheet(0).headRowNumber(1).doRead();
//构造方法获取 bean
EasyExcel.read(file.getInputStream(), ImportVO.class, ImportListener(aService, bService)).sheet(0).headRowNumber(1).doRead();
List<ImportVO> excelDataList = listener.getImportDataList();
if (CollectionUtils.isEmpty(excelDataList)) {
throw new BizException("数据为空");
}
List<ImportDO> satisfactionEvaluationList= BeanUtil.copyListProperties(excelDataList, ImportDO.class);
//入库处理
} catch (ExcelDataConvertException e) {
throw new BizException(MessageFormat.format(UserInfoConstants.FORMAT_ERROR, (e.getRowIndex() + 1), (e.getColumnIndex() + 1)));
}
return RetVo.success();
}
总结:本文简单分享使用 alibaba EasyExcel 导入 Excel 的简单使用,只是简单的分享了主要流程及要点,具体的业务实现是根据业务来的,希望可以帮助到有需要的小伙伴。
欢迎提出建议及对错误的地方指出纠正。