使用POI導出百萬級數據到excel的解決方案

1.HSSFWorkbook 和SXSSFWorkbook區別

HSSFWorkbook:是操做Excel2003之前(包括2003)的版本,擴展名是.xls,一張表最大支持65536行數據,256列,也就是說一個sheet頁,最多導出6w多條數據html

XSSFWorkbook:是操做Excel2007-2010的版本,擴展名是.xlsx對於不一樣版本的EXCEL文檔要使用不一樣的工具類,若是使用錯了,
會提示以下錯誤信息。apache

org.apache.poi.openxml4j.exceptions.InvalidOperationException    api

org.apache.poi.poifs.filesystem.OfficeXmlFileExceptionxss

它的一張表最大支持1048576行,16384列,關於二者介紹,對下面導出百萬數據很重要,不要使用錯了!工具

 

2.使用SXSSFWorkbook對象,導出百萬數據

SXSSFWorkbook使用方法和 HSSFWorkbook差很少,若是你以前和我同樣用的HSSFWorkbook,如今想要修改,則只須要將HSSFWorkbook改爲SXSSFWorkbook便可,下面有我介紹,具體使用也可參考API測試

因項目業務,須要導出百萬級數據到excel,在研究了各類方案後,最終肯定了用POI的SXSSFWorkbook。

SXSSFWorkbook是POI3.8以上新增的,excel2007後每一個sheet支持104萬行數據。字體

3.如何將百萬數據分紅多個sheet頁,導出到excel

導出百萬數據到excel,很簡單,只須要將原來的HSSFWorkbook修改爲SXSSFWorkbook,或者直接使用SXSSFWorkbook對象,它是直接用來導出大數據用的,官方文檔 有介紹,可是若是有300w條數據,一下導入一個excel的sheet頁中,想一想打開excel也須要一段時間吧,慢的話有可能致使程序沒法加載,或者直接結束進程的狀況發生大數據

4.先看導出後的效果

因爲百萬數據太長了,這裏只截取尾部效果圖this

 

5.下面是Java代碼部分

/**
     * 使用 SXSSFWorkbook 對象實現excel導出
     * (通常是導出百萬級數據的excel)
     */
    public void exportBigDataExcel() {
        long  startTime = System.currentTimeMillis();    //開始時間
        System.out.println("start execute time: " + startTime);
        
        // 1.建立工做簿
        // 閾值,內存中的對象數量最大值,超過這個值會生成一個臨時文件存放到硬盤中
        SXSSFWorkbook wb = new SXSSFWorkbook(1000);
        
        //2.在Workbook中添加一個sheet,對應Excel文件中的sheet
        Sheet sheet = wb.createSheet();
        
        //3.設置樣式以及字體樣式
        CellStyle titleCellStyle = createTitleCellStyle(wb);
        CellStyle headCellStyle = createHeadCellStyle(wb);
        CellStyle cellStyle = createCellStyle(wb);
        
        //4.建立標題、表頭,內容和合並單元格等操做
        int rowNum = 0;// 行號
        // 建立第一行,索引從0開始
        Row row0 = sheet.createRow(rowNum++);
        row0.setHeight((short) 800);// 設置行高
        
        String title = "這裏是標題標題標題";
        Cell c00 = row0.createCell(0);
        c00.setCellValue(title);
        c00.setCellStyle(titleCellStyle);
        // 合併單元格,參數依次爲起始行,結束行,起始列,結束列 (索引0開始)
        sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 6));//標題合併單元格操做,6爲總列數
        
        // 第二行
        Row row1 = sheet.createRow(rowNum++);
        row1.setHeight((short) 500);
        String[] row_first = {"填表單位:", "", "", "", "", " xxxx年第x季度 ", ""};
        for (int i = 0; i < row_first.length; i++) {
            Cell tempCell = row1.createCell(i);
            tempCell.setCellStyle(headCellStyle);
            if (i == 0) {
                tempCell.setCellValue(row_first[i] + "測試單位");
            } else if (i == 5) {
                tempCell.setCellStyle(headCellStyle);
                tempCell.setCellValue(row_first[i]);
            } else {
                tempCell.setCellValue(row_first[i]);
            }
        }
        
        // 合併
        sheet.addMergedRegion(new CellRangeAddress(1, 1, 0, 4));
        sheet.addMergedRegion(new CellRangeAddress(1, 1, 5, 6));
        
        //第三行
        Row row2 = sheet.createRow(rowNum++);
        row2.setHeight((short) 700);
        String[] row_second = {"名稱", "採集狀況", "", "", "登記狀況", "", "備註"};
        for (int i = 0; i < row_second.length; i++) {
            Cell tempCell = row2.createCell(i);
            tempCell.setCellValue(row_second[i]);
            tempCell.setCellStyle(headCellStyle);
        }
        
        // 合併
        sheet.addMergedRegion(new CellRangeAddress(2, 3, 0, 0));//名稱
        sheet.addMergedRegion(new CellRangeAddress(2, 2, 1, 3));//人數狀況
        sheet.addMergedRegion(new CellRangeAddress(2, 2, 4, 5));//登記狀況
        sheet.addMergedRegion(new CellRangeAddress(2, 3, 6, 6));//備註
        
        //第三行
        Row row3 = sheet.createRow(rowNum++);
        row3.setHeight((short) 700);
        String[] row_third = {"", "登記數(人)", "辦證總數(人)", "辦證率(%)", "登記戶數(戶)", "登記時間", ""};
        for (int i = 0; i < row_third.length; i++) {
            Cell tempCell = row3.createCell(i);
            tempCell.setCellValue(row_third[i]);
            tempCell.setCellStyle(headCellStyle);
        }
        
        // 數據處理(建立100萬條測試數據)
        List<Map<String, Object>> dataList = new ArrayList<Map<String, Object>>();
        for (int i = 0; i < 999999; i++) {
            Map<String,Object> map = new HashMap<String,Object>();
            map.put("name", "測試名稱" + i);
            map.put("r1", "111");
            map.put("r2", "222");
            map.put("r3", "333");
            map.put("r4", "444");
            map.put("addTime", new DateTime());
            map.put("r6", "這裏是備註"+i);
            dataList.add(map);
        }
        
        for (Map<String, Object> excelData : dataList) {
            Row tempRow = sheet.createRow(rowNum++);
            tempRow.setHeight((short) 500);
            // 循環單元格填入數據
            for (int j = 0; j < 7; j++) {
                Cell tempCell = tempRow.createCell(j);
                tempCell.setCellStyle(cellStyle);
                String tempValue;
                if (j == 0) {
                    // 鄉鎮、街道名稱
                    tempValue = excelData.get("name").toString();
                } else if (j == 1) {
                    // 登記數(人)
                    tempValue = excelData.get("r1").toString();
                } else if (j == 2) {
                    // 辦證總數(人)
                    tempValue = excelData.get("r2").toString();
                } else if (j == 3) {
                    // 辦證率(%)
                    tempValue = excelData.get("r3").toString();
                } else if (j == 4) {
                    // 登記戶數(戶)
                    tempValue = excelData.get("r4").toString();
                } else if (j == 5) {
                    // 登記日期
                    tempValue = excelData.get("addTime").toString();
                } else {
                    // 備註
                    tempValue = excelData.get("r6").toString();
                }
                tempCell.setCellValue(tempValue);
               
//                sheet.autoSizeColumn(j);// 根據內容自動調整列寬,
            }
        }
        //設置列寬,必須在單元格設值之後進行
        sheet.setColumnWidth(0, 4000);//名稱
        sheet.setColumnWidth(1, 3000);//登記數(人)
        sheet.setColumnWidth(2, 3000);//辦證總數(人)
        sheet.setColumnWidth(3, 3000);//辦證率(%)
        sheet.setColumnWidth(4, 3000);//登記戶數(戶)
        sheet.setColumnWidth(5, 6000);//登記時間
        sheet.setColumnWidth(6, 4000);//備註
        
        // 註釋行
        Row remark = sheet.createRow(rowNum++);
        remark.setHeight((short) 500);
        String[] row_remark = {"注:表中的「辦證率=辦證總數÷登記數×100%」", "", "", "", "", "", ""};
        for (int i = 0; i < row_remark.length; i++) {
            Cell tempCell = remark.createCell(i);
            if (i == 0) {
                tempCell.setCellStyle(headCellStyle);
            } else {
                tempCell.setCellStyle(cellStyle);
            }
            tempCell.setCellValue(row_remark[i]);
        }
        int remarkRowNum = dataList.size() + 4;
        sheet.addMergedRegion(new CellRangeAddress(remarkRowNum, remarkRowNum, 0, 6));//註釋行合併單元格
         
        // 尾行
        Row foot = sheet.createRow(rowNum++);
        foot.setHeight((short) 500);
        String[] row_foot = {"審覈人:", "", "填表人:", "", "填表時間:", "", ""};
        for (int i = 0; i < row_foot.length; i++) {
            Cell tempCell = foot.createCell(i);
            tempCell.setCellStyle(cellStyle);
            if (i == 0) {
                tempCell.setCellValue(row_foot[i] + "張三");
            } else if (i == 2) {
                tempCell.setCellValue(row_foot[i] + "李四");
            } else if (i == 4) {
                tempCell.setCellValue(row_foot[i] + "xxxx");
            } else {
                tempCell.setCellValue(row_foot[i]);
            }
        }
        int footRowNum = dataList.size() + 5;
        //
        sheet.addMergedRegion(new CellRangeAddress(footRowNum, footRowNum, 0, 1));
        sheet.addMergedRegion(new CellRangeAddress(footRowNum, footRowNum, 2, 3));
        sheet.addMergedRegion(new CellRangeAddress(footRowNum, footRowNum, 4, 6));
        
        
        long finishedTime = System.currentTimeMillis();    //處理完成時間
        System.out.println("finished execute  time: " + (finishedTime - startTime)/1000 + "m");
        
        //導出
        HttpServletResponse response = this.getResponse();
        String fileName = "報表文件名稱.xlsx";
        try {
            fileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
            response.setHeader("Content-disposition", "attachment;filename=\"" + fileName + "\"");
            OutputStream stream = response.getOutputStream();
            if (null != wb && null != stream) {
                wb.write(stream);// 將數據寫出去  
                wb.close();
                stream.close();
                
                long stopTime = System.currentTimeMillis();        //寫文件時間
                System.out.println("write xlsx file time: " + (stopTime - startTime)/1000 + "m");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        
    }
    

 

CellStyle標題,表頭,內容樣式代碼:spa

private static CellStyle createTitleCellStyle(Workbook workbook) {
        CellStyle cellStyle = workbook.createCellStyle();
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);

        cellStyle.setBorderBottom(BorderStyle.THIN);
        cellStyle.setBottomBorderColor(IndexedColors.BLACK.index);
        cellStyle.setBorderLeft(BorderStyle.THIN);
        cellStyle.setLeftBorderColor(IndexedColors.BLACK.index);
        cellStyle.setBorderRight(BorderStyle.THIN);
        cellStyle.setRightBorderColor(IndexedColors.BLACK.index);
        cellStyle.setBorderTop(BorderStyle.THIN);
        cellStyle.setTopBorderColor(IndexedColors.BLACK.index);

        cellStyle.setFillForegroundColor(IndexedColors.GREY_40_PERCENT.index);
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);

        return cellStyle;
    }

 

private static CellStyle createHeadCellStyle(Workbook workbook) {
        CellStyle cellStyle = workbook.createCellStyle();
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);

        cellStyle.setBorderBottom(BorderStyle.THIN);
        cellStyle.setBottomBorderColor(IndexedColors.BLACK.index);
        cellStyle.setBorderLeft(BorderStyle.THIN);
        cellStyle.setLeftBorderColor(IndexedColors.BLACK.index);
        cellStyle.setBorderRight(BorderStyle.THIN);
        cellStyle.setRightBorderColor(IndexedColors.BLACK.index);
        cellStyle.setBorderTop(BorderStyle.THIN);
        cellStyle.setTopBorderColor(IndexedColors.BLACK.index);

        cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.index);
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);

        return cellStyle;
    }

 

    private static CellStyle createCellStyle(Workbook workbook) {
        CellStyle cellStyle = workbook.createCellStyle();
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);

        cellStyle.setBorderBottom(BorderStyle.THIN);
        cellStyle.setBottomBorderColor(IndexedColors.BLACK.index);
        cellStyle.setBorderLeft(BorderStyle.THIN);
        cellStyle.setLeftBorderColor(IndexedColors.BLACK.index);
        cellStyle.setBorderRight(BorderStyle.THIN);
        cellStyle.setRightBorderColor(IndexedColors.BLACK.index);
        cellStyle.setBorderTop(BorderStyle.THIN);
        cellStyle.setTopBorderColor(IndexedColors.BLACK.index);

        return cellStyle;
    }
    

 

完畢!good luck!

相關文章
相關標籤/搜索