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);
        }
    }
相关推荐
小道士写程序17 分钟前
Windows Rust 环境安装指导
开发语言·windows·rust
传奇开心果编程19 分钟前
【Compose Multiplatform 跨端开发学与练】第4课 导航与路由
android·windows·学习·ui·ios·kotlin·composer
Tisfy30 分钟前
两台旧电脑修复 —— 绕过WinXP密码登录、备份和恢复Win7数据、安装Win10
windows·数据恢复·系统重装
传奇开心果编程38 分钟前
【Compose Multiplatform 跨端开发学与练】第2课 Compose 基础语法
android·windows·学习·ui·ios·kotlin·composer
supabc1231 小时前
Celium:连接 Windows、Mac、Linux 与 Android,让远程访问和设备管理更简单
android·linux·windows·macos·远程访问·网络管理·celium
2401_872418781 小时前
Windows服务器:错误 403 - 禁止访问:本地 FTP 上传文件到网站服务器后提示无访问权限
运维·服务器·windows
YCOSA202513 小时前
Windows11_InsiderPreview_EnterpriseVL_x64_zh-cn_29680_1000.iso 官方直链
windows
怎么没有名字注册了啊15 小时前
Windows Server 2008 R2 如何开启Aero
windows
lingchen190616 小时前
Windows CMD 的 `cd`(change directory,切换目录)命令
windows·命令模式
ITHAOGE1517 小时前
下载 | Win11 26H2 正式版发布!(ISO映像、2026年度版本、26300.9457、Windows 11)
windows·科技·微软·电脑