alibaba / easyexcel

快速、简洁、解决大文件内存溢出的java处理Excel工具
https://easyexcel.opensource.alibaba.com
Apache License 2.0
32.09k stars 7.5k forks source link

使用easyexcel时 导出50个字段大概300行数据 需要40秒左右 是否太过慢了 #3991

Open zdd874133 opened 2 weeks ago

zdd874133 commented 2 weeks ago

`String filePath = ""; //导出的文件名 String exportFileName = encodingFilename(fileName); //文件在服务器的路径 String localFilePath = getAbsoluteFile(exportFileName);

    //构建 writer
    ExcelWriter writer = EasyExcel.write(localFilePath, clazz)
        // 自动适配
        .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
        .registerWriteHandler(new ImageCellWriteHandler())
        .registerWriteHandler(new CommonStyleStrategy())
        .excelType(ExcelTypeEnum.XLSX)
        .includeColumnFieldNames(Arrays.asList(query.getExports().split(CommonConstants.STR_COMMA)))
        // 大数值自动转换 防止失真
        .registerConverter(new ExcelBigNumberConvert())
        .build();
    WriteSheet sheet = EasyExcel.writerSheet(fileName).build();

    List<T> entityList = new ArrayList<>();
    baseMapper.selectExportList(lqw, new ResultHandler<T>() {
        int count = 0;

        @Override
        public void handleResult(ResultContext<? extends T> resultContext) {
            T resultObject = resultContext.getResultObject();
            entityList.add(resultObject);
            count++;
            if (entityList.size() >= batchSize) {
                //处理数据
                List<V> convert = entity2DtoFunction.apply(entityList, clazz);
                writer.write(convert, sheet);
                entityList.clear();

                if (Objects.nonNull(taskId)) {
                    ExportMessageDto messageDto = new ExportMessageDto();
                    messageDto.setTopic(WebSocketConstants.EXPORT_PROCESS_TOPIC);
                    messageDto.setProcessStatus(AsyncTaskStatus.PROCESSING.getCode());
                    messageDto.setTaskId(taskId);
                    messageDto.setProcessRate(BigDecimal.valueOf(count).divide(BigDecimal.valueOf(totalCount), 4, RoundingMode.HALF_UP));
                    WebSocketUtils.sendMessage(LoginHelper.getUserId(), JSONUtil.toJsonStr(messageDto));
                    System.out.println(JSONUtil.toJsonStr(messageDto));
                }
            }
        }
    });
    if (!entityList.isEmpty()) {
        //处理数据
        List<V> convert = entity2DtoFunction.apply(entityList, clazz);
        writer.write(convert, sheet);
        entityList.clear();
    }
    try {
        writer.close();
    } catch (Exception e) {
        System.err.println("excelWrite关闭失败: " + e.getMessage());
    }
    //上传文件到oss
    filePath = SpringUtils.getBean(OssService.class).uploadExcel(new File(localFilePath), "export");
    try {
        boolean delete = Files.deleteIfExists(Paths.get(localFilePath));
        if (!delete) {
            System.err.println("文件删除失败: " + localFilePath);
        }
    } catch (Exception e) {
        System.err.println("删除文件时发生错误: " + e.getMessage());
    }
    return filePath;`

目前已经定位到writer.write(convert, sheet);这个方法耗时占比90%以上, 是我的用法错误吗, 已经排除了是几个样式处理器的问题, 去掉样式处理器一样很慢, 而且不考虑多次写入, 单次也如一样很慢