Excel检查流程(只讲一个Excel的情况,批量类似):先开个passList和failList用来存校验通过的数据和不通过的数据(最后用来分开存通过的Excel和不通过的Excel)先开一个通过监听器获取Excel文件,开个List获取所有的行数据后进行数据校验,校验完了构建返回Vo
/**
- 租客导入数据检查
- @param files Excel文件
- @apiNote 检查上传的Excel文件数据,返回校验结果
*/
@PostMapping("/dataCheck")
public R<List> dataCheck(@RequestParam("files") MultipartFile[] files) {
return R.ok(bamsRenterService.dataCheck(files));
}
/**
- 批量导入数据校验
- @param files 导入文件
- @return 检验结果
/
@Override
public ListdataCheck(MultipartFile[] files) { *
// 构建结果集
Listresults = new ArrayList<>();
//遍历文件
for (MultipartFile file : files) {
//检查文件类型
if (!Objects.requireNonNull(file.getOriginalFilename()).endsWith(".xlsx")) {
throw new RuntimeException("请上传Excel文件");
}
//初始化结果集(通过校验与未通过的结果list)
ListpassList = new ArrayList<>(), failList = new ArrayList<>();
//检查Excel内容
try {
//实例化监听器
RenterImportListener listener = new RenterImportListener();
//读取Excel文件
ExcelReaderBuilder read = EasyExcel.read(file.getInputStream(), RenterImportBo.class, listener);
//以第三行为表头(看情况)
read.headRowNumber(3).sheet().doRead();
// 获取所有行数据
ListallList = listener.getDataList();
//校验数据是否正常 略业务具体逻辑
checkRenterData(allList, passList, failList);
//构建结果集
fillResult(results, file, allList, passList, failList);
} catch (Exception e) {
throw new RuntimeException("数据校验失败", e);
}
}
return results;
}
/ - 构建结果
- @param results 结果集
- @param file 文件
- @param allList 所有数据
- @param passList 通过校验的数据
- @param failList 未通过校验的数据
/
private void fillResult(Listresults, MultipartFile file, *
ListallList, List passList,
ListfailList) {
// 结果对象
UploadResultVo uploadResultVo = new UploadResultVo();
// 当前时间
long time = System.currentTimeMillis();
// 将通过校验与未通过的数据上传到OSS
if (CollectionUtils.isNotEmpty(passList)) {
String passFileName = "excel/pass_" + time + ".xlsx";
doResultOssField(uploadResultVo, passList, passFileName,
"通过数据.xlsx", "校验通过数据", true);
}
if (CollectionUtils.isNotEmpty(failList)) {
String failFileName = "excel/fail_" + time + ".xlsx";
doResultOssField(uploadResultVo, failList, failFileName,
"未通过数据.xlsx", "校验未通过数据", false);
}
//填充结果对象
uploadResultVo.setFileName(file.getOriginalFilename());
uploadResultVo.setTotalCount(allList.size());
uploadResultVo.setPassedCount(passList.size());
uploadResultVo.setFailedCount(failList.size());
//添加到结果集
uploadResultVo.setValid(failList.isEmpty());
results.add(uploadResultVo);
}
/ - 校验后结果数据上传到OSS
- @param vo 结果对象
- @param list 检验后的结果集合
- @param fileName 文件
- @param originalFileName 原文件名
- @param sheetName 表名
/
private void doResultOssField(UploadResultVo vo, Listlist, *
String fileName, String originalFileName, String sheetName, Boolean flag) {
//响应类型
String contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
//文件流写入
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
EasyExcel.write(outputStream, RenterImportBo.class)
.excludeColumnFieldNames(List.of("isRight"))
.sheet(sheetName).doWrite(list);
//上传到oss
byte[] bytes = outputStream.toByteArray();
RemoteFile remoteFile = remoteFileService.upload(fileName, originalFileName, contentType, bytes);
//设置文件路径与ossId
if (flag) {
vo.setPassedExcelUrl(remoteFile.getUrl());
vo.setPassedExcelOssId(remoteFile.getOssId());
} else {
vo.setFailedExcelUrl(remoteFile.getUrl());
vo.setFailedExcelOssId(remoteFile.getOssId());
}
}
/ - 批量导入租客
- @param list 需导入的租客数据集合
- @apiNote 将验证后的数据集合批量导入数据库
/
@PostMapping("/import")
public R<?> importExcel(@RequestBody Listlist) { *
bamsRenterService.importExcel(list);
return R.ok();
}
/ - 批量导入租客
- @param list 导入数据
*/
@Transactional(rollbackFor = Exception.class)
public void importExcel(Listlist) {
// 数据导入成功后需清理的ossIds
ListossIds = new ArrayList<>();
//遍历传入的文件对象集合
for (UploadResultVo uploadResultVo : list) {
//通过校验的文件ossUrl
String passedExcelUrl = uploadResultVo.getPassedExcelUrl();
if (StringUtils.isBlank(passedExcelUrl)) continue;
// 有未通过数据就不导入
if (!uploadResultVo.isValid()) {
continue;
}
//通过校验的文件ossId
Long passOssId = uploadResultVo.getPassedExcelOssId();
if (passOssId != null) {
ossIds.add(passOssId);
}
//未通过校验的文件ossId
Long failedOssId = uploadResultVo.getFailedExcelOssId();
if (failedOssId != null) {
ossIds.add(failedOssId);
}
try {
// 解析ossUrl
URL url = new URL(passedExcelUrl);
// 创建监听器
RenterImportListener listener = new RenterImportListener();
// 读取excel
EasyExcel.read(url.openStream(), RenterImportBo.class, listener)
.headRowNumber(1)
.sheet()
.doRead();
// 所有行
ListpassList = listener.getDataList();
if (CollectionUtils.isEmpty(passList)) {
continue;
}
// 具体业务逻辑
} catch (Exception e) {
log.error("文件解析失败, passOssId={}, passedExcelUrl={}", passOssId, passedExcelUrl, e);
throw new RuntimeException("文件解析失败", e);
}
}
// 清理oss文件
if (CollectionUtils.isNotEmpty(ossIds)) {
remoteFileService.deleteWithValidByIds(ossIds, true);
}
}
// 上传结果Vo
@Data
public class UploadResultVo {
/**
* 文件名称
*/
private String fileName;
/**
* 上传数据条数
*/
private int totalCount;
/**
* 校验通过数据条数
*/
private int passedCount;
/**
* 校验通过数据excel文件地址
*/
private String passedExcelUrl;
/**
* 校验通过数据excel文件ID
*/
private Long passedExcelOssId;
/**
* 校验未通过数据条数
*/
private int failedCount;
/**
* 校验未通过数据excel文件地址
*/
private String failedExcelUrl;
/**
* 校验未通过数据excel文件ID
*/
private Long failedExcelOssId;
/**
* 校验是否通过 True 通过 False 未通过
*/
private boolean valid;
/**
* 校验错误信息
*/
private String errorMessage;
}
package com.shengtu.bams.domain.bo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.shengtu.bams.converter.RenterTypeConverter;
import lombok.Data;
@Data
public class RenterImportBo {
/**
* 租客类型
*/
@ExcelProperty(index = 0, converter = RenterTypeConverter.class)
private Integer renterType;
/**
* 租客名称
*/
@ExcelProperty(index = 1)
private String renterName;
/**
* 联系人姓名
*/
@ExcelProperty(index = 2)
private String contactName;
/**
* 联系人电话
*/
@ExcelProperty(index = 3)
private String contactPhone;
/**
* 校验失败原因
*/
private String failReason;
/**
* 错误数据标识 0 错误 1 正常(默认)
*/
private Integer isRight = 1;
}
@Getter
@Slf4j
public class RenterImportListener extends AnalysisEventListener
private final List<RenterImportBo> dataList = new ArrayList<>();
@Override
public void invoke(RenterImportBo data, AnalysisContext context) {
log.info("读取一行数据:{}", data);
dataList.add(data);
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
log.info("Excel读取完成,共 {} 条记录", dataList.size());
}
}
浙公网安备 33010602011771号