easypoi大批量导出excel数据

发布时间 2023-12-04 15:11:29作者: 隐琳琥

easypoi导出excel数据

最近,面临了一个新的需求,需要将表中的几百万数据导出到Excel文件中。为了满足这一需求,我决定采用EasyPoi库来实现该功能,并生成压缩包。

<dependency>
      <groupId>cn.afterturn</groupId>
      <artifactId>easypoi-spring-boot-starter</artifactId>
      <version>4.3.0</version>
</dependency>

下面是我封装的工具类

因为easypoi可以使用@Excel注解来生成excel列所以我就不使用模板了。

使用IExcelExportServer将数据分批查询出来,里面的mapper查询这块需要优化,推荐从非关系型数据库中查询。

/**
     * 大批量导出
     * @param name
     * @param bo
     * @param entityClass
     * @param response
     * @param <T>
     */
    public <T> void matterExport(String name, QueryBo bo, Class entityClass, HttpServletResponse response) {
        IExcelExportServer exportServer = new IExcelExportServer() {
            @Override
            public List<Object> selectListForExcelExport(Object queryParams, int page) {
                LambdaQueryWrapper<User> wrapper = iUserService.buildQueryWrapper(bo);
                String lastsql = "LIMIT " + (page - 1) * limit + ", " + limit;
                wrapper.last(lastsql);

                List<User> reslist = userMapper.selectList(wrapper);
                if (null == reslist || reslist.isEmpty()) {
                    return null;
                }
                List<T> list = JSONObject.parseArray(JSON.toJSONString(reslist), entityClass);
                List<Object> objects = new ArrayList<Object>(list);

                if (list.size() == 0) {
                    return null;
                }
                return objects;
            }
        };

        exportBufferExcel(name, entityClass, exportServer, response);
    }

生产workbook后通过文件流的方式导出

 /**
     * 增强导出
     * @param name
     * @param entityClass
     * @param response
     * @param <T>
     */
    public <T> void exportBufferExcel(String name, Class entityClass, IExcelExportServer exportServer, HttpServletResponse response) {
        ExportParams params = new ExportParams(null, name, ExcelType.XSSF);
        params.setCreateHeadRows(true);
        // 生产workbook
        try {
            Workbook  workbook = ExcelExportUtil.exportBigExcel(params, entityClass, exportServer, null);
            downLoadExcel(name, response, workbook);
        } catch (IOException e) {
            e.printStackTrace();
            log.error("导出失败! ===>{}", e.getMessage());
        }

    }

/**
     * 下载
     *
     * @param fileName 文件名称
     * @param response
     * @param workbook excel数据
     */
    private static void downLoadExcel(String fileName, HttpServletResponse response, Workbook workbook) throws IOException {
        try {
            response.setCharacterEncoding("UTF-8");
            response.setHeader("content-Type", "application/vnd.ms-excel");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            workbook.write(response.getOutputStream());
        } catch (Exception e) {
            throw new IOException(e.getMessage());
        }
    }

这样是不是就够了?

本人在用自己的电脑通过本地数据库和jar包测试表数据量达到100w+的时候就有很明显的卡顿了,电脑配置为i7CPU 32G内存。

 

众所周知在Excel中打开超过100万行的数据,可能会导致性能下降和卡顿,部分数据也可能没有及时加载。Excel的最大行数和列数取决于硬件和软件的限制,一般情况下,Excel的行数最大为1048576,列数最大为16384。因此,如果超过了这些限制,Excel可能会出现加载错误。

这个时候单纯的一个excel导出已经不能满足我们的使用需求了。

easypoi多表格大批量导出excel数据

1、对数据进行分片,可以用hutool工具类中ListUtil.partition方法对在数据中查询的数据进行分片

LambdaQueryWrapper<User> wrapper = iUserService.buildQueryWrapper(bo);
List<User> userList = userMapper.selectList(wrapper);
List<List<Map<String, Object>>> partition = ListUtil.partition(userList, partSize);

 

 

 

我们创建一个ThreadPoolExecutor线程池用来提交线程,使用CountDownLatch程序计数器计数,传入线程数,这里也就是我们将要生成的文件个数,然后调用await()方法等待所有线程执行结束。最后关闭线程。