poi导出大量数据到Excel

使用SXSSFWorkbook导出

案例

java 复制代码
@Override
    public void getUserExport(UserExportDTO dto) {

        // 开始时间
        LocalDateTime time = LocalDateTime.now();

        // 准备后续查询需要使用的id集合
        List<Integer> userList = testMapper.getUserGetId();

        // 创建线程池(根据第二步查询的耗时情况调整大小)
//        ExecutorService executor = Executors.newFixedThreadPool(10);
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                5,// 线程数量
                10,// 最大线程数量
                1,// 线程存活时间
                TimeUnit.MINUTES,// 存活时间单位
//                new ArrayBlockingQueue<>(600),// 任务队列
                new LinkedBlockingQueue<>(),// 任务队列 -无界队列 (容易内存溢出)
                Executors.defaultThreadFactory()// 线程工厂
        );

        // 使用线程安全的集合存储最终结果
        List<UserVO> voList = Collections.synchronizedList(new ArrayList<>());
        // 创建任务列表
        List<CompletableFuture<Void>> futures = new ArrayList<>();

        if (userList != null && userList.size() > 0){
            for (Integer id : userList) {
                CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                    // 查询用户信息
                    UserVO userVO = testMapper.getUserFindByIdGetUserVO(id);
                    // 查询用户详情
                    List<UserDetails> userDetailsList = testMapper.getUserDetailsByUserId(id);
                    userVO.setUserDetailsList(userDetailsList);
                    voList.add(userVO);
                }, executor);

                // 收集任务
                futures.add(future);
            }
        }

        // 等待所有任务完成
        CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
        // 关闭线程池
        executor.shutdown();

        // 查询结果赋值
        List<UserVO> voList2 = voList;
        // 处理最终结果排序问题
        voList2 = voList2.stream()
                .sorted(Comparator.comparing(UserVO::getId))
                .collect(Collectors.toList());

        // 数据处理完成时间
        LocalDateTime time2 = LocalDateTime.now();

        // ============================================

        try {
            // 创建一个新的工作簿
//            Workbook workbook = new XSSFWorkbook();
            // 创建SXSSFWorkbook,设置行访问窗口为100(内存中保留的行数)
            SXSSFWorkbook workbook = new SXSSFWorkbook(500);
            // 自动刷新临时文件
            workbook.setCompressTempFiles(true);

            // 创建一个新的工作表
            Sheet sheet = workbook.createSheet("Sheet1");

            // 设置标题
            Row row = sheet.createRow(0);
            String[] headers = {"id","姓名","性别","年龄","电话","地址"};
            for (int i = 0; i < headers.length; i++) {
                Cell cell = row.createCell(i);
                cell.setCellValue(headers[i]);
                // 设置列宽
                sheet.setColumnWidth(i,30 * 256);
            }
            // 设置行高
            row.setHeightInPoints(30);

            // 从第一行开始,第零行是标题
            int lineNumber = 1;
            // 设置每行数据
            for (int i = 0; i < voList2.size(); i++) {
                UserVO userVO = voList2.get(i);
                List<UserDetails> userDetailsList = userVO.getUserDetailsList();
                // id合并
                sheet.addMergedRegion(new CellRangeAddress(lineNumber,lineNumber + userDetailsList.size() - 1,0,0));
                // 姓名合并
                sheet.addMergedRegion(new CellRangeAddress(lineNumber,lineNumber + userDetailsList.size() - 1,1,1));
                // 性别合并
                sheet.addMergedRegion(new CellRangeAddress(lineNumber,lineNumber + userDetailsList.size() - 1,2,2));
                // 年龄
                sheet.addMergedRegion(new CellRangeAddress(lineNumber,lineNumber + userDetailsList.size() - 1,3,3));
                // 电话
                sheet.addMergedRegion(new CellRangeAddress(lineNumber,lineNumber + userDetailsList.size() - 1,4,4));

                for (UserDetails userDetails : userDetailsList) {
                    // 创建一行
                    row = sheet.createRow(lineNumber);

                    // 设置行高
                    row.setHeightInPoints(60);

                    // id
                    Cell cell = row.createCell(0);
                    cell.setCellValue(userVO.getId());

                    // 姓名
                    cell = row.createCell(1);
                    cell.setCellValue(userVO.getName());

                    // 性别
                    cell = row.createCell(2);
                    cell.setCellValue(userVO.getSex());

                    // 年龄
                    cell = row.createCell(3);
                    cell.setCellValue(userVO.getAge());

                    // 电话
                    cell = row.createCell(4);
                    cell.setCellValue(userDetails.getTel());

                    // 地址
                    cell = row.createCell(5);
                    cell.setCellValue(userDetails.getAddress());

                    // 增加一行
                    lineNumber = lineNumber + 1;
                }
            }

            // 请求头(这两种请求头二选一,具体不同点在于前端下载方式可能不同,二选一即可,可以都试试)
                response.setCharacterEncoding("UTF-8");
                response.addHeader("content-Type", "application/vnd.ms-excel");
                response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
                response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("用户导出.xlsx", "UTF-8"));

            ServletOutputStream outputStream = response.getOutputStream();
            workbook.write(outputStream);
            // 清理临时文件
            workbook.dispose();

            //关闭资源
            outputStream.flush();
            workbook.close();
            outputStream.close();

            // 数据导出完成时间
            LocalDateTime time3 = LocalDateTime.now();

            Duration duration = Duration.between(time, time2);
            Duration duration2 = Duration.between(time2, time3);

            System.out.println("数据处理时间:" + duration.toMillis());
            System.out.println("数据导出时间:" + duration2.toMillis());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
相关推荐
AI袋鼠帝6 小时前
Claude4.5+Gemini3 接管电脑桌面,这回是真无敌了..
人工智能·windows·aigc
獨枭7 小时前
Windows 下安装与使用 Miniconda 完整指南
windows
CodeToGym7 小时前
【Java 办公自动化】Apache POI 入门:手把手教你实现 Excel 导入与导出
java·apache·excel
命里有定数8 小时前
保姆级教程:在 Windows (WSL2) 下本地部署 Qwen3-ASR
windows
lucky670711 小时前
Windows 上彻底卸载 Node.js
windows·node.js
编程小白202612 小时前
从 C++ 基础到效率翻倍:Qt 开发环境搭建与Windows 神级快捷键指南
开发语言·c++·windows·qt·学习
凯子坚持 c14 小时前
CANN 性能剖析实战:从原始事件到交互式火焰图
windows·microsoft
开开心心就好14 小时前
发票合并打印工具,多页布局设置实时预览
linux·运维·服务器·windows·pdf·harmonyos·1024程序员节
獨枭14 小时前
PyCharm 跑通 SAM 全流程实战
windows
仙剑魔尊重楼15 小时前
音乐制作电子软件FL Studio2025.2.4.5242中文版新功能介绍
windows·音频·录屏·音乐·fl studio