Excel大数据量导出(1亿数据量都可以做到)

直接上代码

/**
     * 1.文件写入流程,调用方法 init 获取初始化对象
     * 2.将调用init获取到的对象存在参数传入循环调用文件写入方法writeExcel(每一次调用该方法的数据集合不得超过65535)
     * 3.调用将输出流(写入文件/http输出流)以及init对象传入writeDataToExcel方法
     */

    /**
     * 初始化
     * @return
     */
    public static SXSSFWorkbook init(){
        SXSSFWorkbook workbook = new SXSSFWorkbook(10);
        workbook.setCompressTempFiles(true);
        return workbook;
    }

    /**
     * excel文件写入
     */
    public static <T> void writeExcel( SXSSFWorkbook workbook
            , String sheetName,  List<T> datas , Class<T> headers) throws Exception {
        long startTime = System.currentTimeMillis();
        // 分批创建sheet,避免一次性创建所有sheet占用内存
        SXSSFSheet sheet = workbook.createSheet(sheetName);
        // 创建表头
        createHeaderRow(workbook,sheet, headers);
        // 分批写入数据到当前sheet
        int sheetIndex = workbook.getSheetIndex(sheet);
        writeDataToSheet(sheet , sheetIndex , datas);
        // 立即刷新当前sheet到磁盘,释放内存
        sheet.flushRows();
        // 定期清理内存
        System.gc();
    }

    private static <T> void writeDataToSheet(SXSSFSheet sheet
            , int sheetIndex , List<T> datas) throws Exception {
        int size = datas.size();
        long startRow = (long) sheetIndex * datas.size();

        // 分批写入,每批1000行
        int batchSize = 1000;
        for (int batchStart = 1; batchStart <= size; batchStart += batchSize) {
            int batchEnd = Math.min(batchStart + batchSize - 1, size);
            writeDataBatch(sheet, startRow, batchStart, batchEnd,datas);

            // 每处理10000行刷新一次
            if (batchStart % 10000 == 0) {
                sheet.flushRows();
            }
        }
    }

    private static <T> void writeDataBatch(SXSSFSheet sheet
            , long startRow, int batchStart, int batchEnd , List<T> datas) throws IllegalAccessException {
        for (int rowNum = batchStart; rowNum <= batchEnd; rowNum++) {
            Row row = sheet.createRow(rowNum);
            T data = datas.get(rowNum - 1);
            long globalRowIndex = startRow + rowNum;

            // Row数据写入
            fillRowData(row, globalRowIndex,data);

//            long processed = processedRows.incrementAndGet();
        }
    }

    private static <T> void fillRowData(Row row, long globalRowIndex , T data) throws IllegalAccessException {
        Class<?> aClass = data.getClass();
        Field[] declaredFields = aClass.getDeclaredFields();
        for (int i = 0; i < declaredFields.length; i++) {
            Field declaredField = declaredFields[i];
            if (declaredField.getModifiers() == 2) {
                declaredField.setAccessible(true);
            }
            Object dataValue = declaredField.get(data);
            row.createCell(i).setCellValue(String.valueOf(dataValue));
        }
    }

    private static <T> void createHeaderRow( SXSSFWorkbook workbook
            , Sheet sheet, Class<T> headers) {
        Row headerRow = sheet.createRow(0);
        Field[] declaredFields = headers.getDeclaredFields();
        List<String> header = new ArrayList<>();
        for (Field declaredField : declaredFields) {
            if (declaredField.getModifiers() == 2) {
                declaredField.setAccessible(true);
            }
            Excel declaredAnnotation = declaredField.getDeclaredAnnotation(Excel.class);
            if (ObjectUtils.isEmpty(declaredAnnotation)) {
                header.add(declaredField.getName());
            }else {
                String value = declaredAnnotation.value();
                if (StringUtils.isNotEmpty(value)) {
                    header.add(value);
                }else {
                    header.add(declaredField.getName());
                }
            }
        }
        for (int i = 0; i < header.size(); i++) {
            Cell cell = headerRow.createCell(i);
            cell.setCellValue(header.get(i));

            // 简单的表头样式
            CellStyle headerStyle = workbook.createCellStyle();
            Font headerFont = workbook.createFont();
            headerFont.setBold(true);
            headerStyle.setFont(headerFont);
            cell.setCellStyle(headerStyle);
        }
    }

    public static void writeDataToExcel(OutputStream outputStream , SXSSFWorkbook workbook) throws Exception {
        workbook.write(outputStream);
    }

使用方式我都写在了最上面,通过泛型和反射进行解析,有需要也可以自己重新在里面改一下,写一套出来,这个功能可以导出1亿的数据都不会出现内存溢出的情况(实际测试)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值