Web中EasyExcel的使用

275 阅读2分钟

EasyExcel

EasyExcel是一个基于Java的、快速、简洁、解决大文件内存溢出的Excel处理工具。

1. 大大减少占用内存的主要原因是在解析Excel时没有将文件数据一次性全部加载到内存中,
   而是从磁盘上一行行读取数据,逐个解析;
2. 采用一行一行的解析模式,并将一行的解析结果以观察者的模式通知处理(AnalysisEventListener)

详细操作见官网:EasyExcel 超详细!!!

Web上传

  1. 上传的excel:

image.png

  1. 创建excel对应实体对象和监听器对象(每解析一行,边将解析结果通知EventListener,执行invoke方法),调用EasyExcel.read读文件:
@Data
public class UploadData {

    @ExcelProperty("用户ID")
    private Long userId;

    @ExcelProperty("内容")
    private String content;

    @ExcelProperty("提交时间")
    private Date submitTime;
}

@Slf4j
@Data
public class UploadExcelListener extends AnalysisEventListener<UploadData> {

    /**
     * Excel定义的表头
     */
    private static final List<String> COMMON_HEADS = new ArrayList(16);

    /**
     * Excel解析出的行数据
     */
    private List<UploadData> datas = new ArrayList<>();

    static {
        COMMON_HEADS.add("用户ID");
        COMMON_HEADS.add("内容");
        COMMON_HEADS.add("提交时间");
    }

    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        log.info("开始解析Excel数据,headMap={}", JsonUtils.serialize(headMap));
        // Excel表头数据校验
        int headSize = headMap.size();
        if (headSize != COMMON_HEADS.size()) {
            throw new RuntimeException("上传的Excel中表头与模板不一致,核实后重新上传!");
        }
        for (int i = 0; i < headSize; i++) {
            if (!COMMON_HEADS.get(i).equals(headMap.get(i))) {
                throw new RuntimeException("上传的Excel中表头与模板不一致,核实后重新上传!");
            }
        }
    }

    @Override
    public void invoke(UploadData data, AnalysisContext context) {
        Integer rowIndex = context.readRowHolder().getRowIndex();
        log.info("开始解析Excel数据,rowIndex={}, data={}", rowIndex, JsonUtils.serialize(data));
        // Excel行数据有效性校验
        Assert.isTrue(data.getUserId() != null && data.getUserId() > 0L,
                String.format("Excel中第%d行:用户ID不能为空且>0!", rowIndex));
        Assert.notBlank(data.getContent(), String.format("Excel中第%d行:内容不能为空!", rowIndex));
        datas.add(data);
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        log.info("Excel解析完成,xxx");
    }
}

// 上传excel文件url
@PostMapping("/upload/url")
public void uploadExcel(@RequestParam String excelFileUrl) {
    File tmpFile = null;
    try {
        // 1.创建临时文件,并下载excel
        tmpFile = FileUtil.createTempFile().toFile();
        boolean downloadSuccess = HttpUtil.downloadFile(excelFileUrl, tmpFile);
        if (!downloadSuccess) {
            log.error("无效的Excel文件地址,excelFileUrl={}", excelFileUrl);
            return;
        }
        // 2.读Excel,并解析
        UploadExcelListener uploadExcelListener = new UploadExcelListener();
        EasyExcel.read(tmpFile, UploadData.class, uploadExcelListener).sheet().doRead();
        List<UploadData> datas = uploadExcelListener.getDatas();
        // 3.进行业务操作 todo
    } catch (IOException e) {
        log.error("Excel上传异常,xxx");
    }
}

// 上传excel文件
@PostMapping("/upload/file")
public void upload(@RequestParam MultipartFile file) {
    try {
        // 1.读Excel,并解析
        UploadExcelListener uploadExcelListener = new UploadExcelListener();
        EasyExcel.read(file.getInputStream(), UploadData.class, uploadExcelListener).sheet().doRead();
        List<UploadData> datas = uploadExcelListener.getDatas();
        // 2.进行业务操作 todo
    } catch (IOException e) {
        log.error("Excel上传异常,xxx");
    }
}
  1. 解析出excel中数据:

image.png

Web下载

  1. 创建excel对应的实体对象,调用EasyExcel.write写文件:
@Data
public class DownloadData {

    @ExcelProperty("用户ID")
    private Long userId;

    @ExcelProperty("内容")
    private String content;

    // 导出excel时忽略此字段
    @ExcelIgnore
    @ExcelProperty("评分")
    private Double score;

    // 导出excel时按照此格式导出日期
    @DateTimeFormat("yyyy-MM-dd")
    @ExcelProperty("评分时间")
    private Date createTime;
}

@PostMapping("/download")
public void download(HttpServletResponse response) {
    // 1.查询业务数据 todo
    List<DownloadData> datas = getBusinessData();
    try {
        // 2.导出Excel
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        String fileName = URLEncoder.encode("下载Excel", "UTF-8");
        response.addHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream(), DownloadData.class).sheet().doWrite(datas);
    } catch (IOException e) {
        log.error("Excel下载异常");
    }
}
  1. 导出的excel:

image.png