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);
        }
    }
相关推荐
蚰蜒螟3 小时前
深入 Linux 内核同步机制:从 futex 到 spinlock 的完整旅程
linux·windows·microsoft
dllmayday4 小时前
Linux 上用终端连接 WiFi
linux·服务器·windows
JoshRen10 小时前
2026教程:上传Excel,用Gemini 3镜像站多模态一键生成问卷分析图表代码与结论(附国内免费方案)
excel
Curtain_Gin10 小时前
windows nvim lazy
windows
生而为虫12 小时前
Claude Code 最新版安装教程(Windows/Mac/Linux 全平台) 面向普通用户的 Claude Code 安装与模型接入指南
linux·windows·macos
DevilSeagull12 小时前
Windows 批处理 (Batch) 编程: 从入门到入土. (一) 基础概念与环境配置
开发语言·windows·后端·batch·语言
CyL_Cly13 小时前
Parsec(parsec安卓/windows/macos下载)
windows
2601_9583205714 小时前
【小白零基础上手 】钉钉内部机器人接入 OpenClaw 完整流程讲解(含安装包)
人工智能·windows·机器人·钉钉·open claw·open claw安装
love530love15 小时前
f2 项目(多平台的作品下载与接口数据处理)源码部署记录
人工智能·windows·f2
生而为虫15 小时前
在VScode中使用Claude Code agent并配置模型(仅mac电脑实际操作,windows电脑未实际操作如有问题可留言)
windows·vscode·macos