LuckyOx

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

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 List dataCheck(MultipartFile[] files) {
    // 构建结果集
    List results = new ArrayList<>();
    //遍历文件
    for (MultipartFile file : files) {
    //检查文件类型
    if (!Objects.requireNonNull(file.getOriginalFilename()).endsWith(".xlsx")) {
    throw new RuntimeException("请上传Excel文件");
    }
    //初始化结果集(通过校验与未通过的结果list)
    List passList = 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();
    // 获取所有行数据
    List allList = 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(List results, MultipartFile file,
    List allList, List passList,
    List failList) {
    // 结果对象
    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, List list,
    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 List list) {
    bamsRenterService.importExcel(list);
    return R.ok();
    }
    /
    *
  • 批量导入租客
  • @param list 导入数据
    */
    @Transactional(rollbackFor = Exception.class)
    public void importExcel(List list) {
    // 数据导入成功后需清理的ossIds
    List ossIds = 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();
    // 所有行
    List passList = 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());
}

}

posted on 2026-01-30 22:15  lucky_ox  阅读(0)  评论(0)    收藏  举报