Java POI 大數據生成Excel

POI 提供了 好幾種生成Excel的方式,查看官方的API可以發現

第一種:HSSFWorkbook 

針對是 EXCEL2003 版本,擴展名爲 .xls;所以 此種的侷限就是 導出的行數 至多爲 65535 行,此種 因爲行數不足七萬行 所以 一般不會發生 內存不足的情況(OOM)

第二種:XSSFWorkbook 

這種形式的出現 是由於 第一種HSSFWorkbook 的侷限性而產生的,因爲其所導出的行數比較少,所以 XSSFWookbook應運而生 其 對應的是EXCEL2007+(1048576行,16384列)擴展名 .xlsx,最多可以 導出 104 萬行,不過 這樣 就伴隨着一個問題---OOM 內存溢出,原因是 你所 創建的 book sheet row cell 等 此時是存在 內存的 並沒有 持久化,那麼 隨着 數據量增大  內存的需求量也就增大,那麼很大可能就是要 OOM了,那麼 怎麼解決呢?

第三種:SXSSFWorkbook  poi.jar 3.8+

第二種遇到的問題該如何解決呢? 因爲數據量過大 導致內存吃不消 那麼 可以 讓內存 到量持久化 嗎? 

答案是 肯定的,

此種的情況 就是 設置 最大 內存條數 比如  設置 最大內存量爲5000 rows  --new SXSSFWookbook(5000),此時 當 行數 達到 5000 時,把 內存 持久化 寫到 文件中,以此 逐步 寫入  避免OOM,那麼這樣 就完美解決了 大數據下 導出 的問題;


明顯發現最後一種是處理大數據的最好方式:

//創建Excel的workbook 對象
SXSSFWorkbook workbook = new SXSSFWorkbook(1000);
//循環生成多個Sheet 頁  如果需要
			for(Map<String, Object> sheetTempMap : sheetList){
                創建sheet 頁名字
				Sheet sheet = createSheetName(workbook, sheetTempMap);
				//get column map 獲取列頭和列屬性的Map 這部分的數據可以放到數據庫裏面,也可以寫道js 文件上,方便靈活的生成列頭,線上也可直接修改。
				Map<String, String> columnMap = getColumnMap(sheetTempMap,outputVO);
				if(CollectionUtils.isEmpty(columnMap)){
					m_Logger.error("Column Map is empty,please setup.");
					return outputVO; 
				}
				//create header
				createHeader(columnMap, workbook, sheet,0);
				//create line and write data 
                //這裏使用Mybatis返回Map 的數據類型,這樣就可通過上面的columnMap直接獲取數據
				List<Map<String, Object>> resultMap = getResultListMap(sheetTempMap);
				createLine(columnMap, resultMap, workbook, sheet);
			}
			List<File> files = new ArrayList<File>();
			writeExcel(workbook,params,files);


/**
	 * create Header
	 * @param workbook
	 * @param sheetTempMap
	 * @return
	 */
private void createHeader(Map<String, String> columnMap,SXSSFWorkbook workbook, Sheet sheet,int currentRow) {
		CellStyle columnTopStyle = getColumnTopStyle(workbook);
		Row rowRowName = sheet.createRow(currentRow);
		int columnTemp = 0;
		for (Map.Entry<String, String> headerMap : columnMap.entrySet()) {
			Cell cellRowName = rowRowName.createCell(columnTemp);
			cellRowName.setCellType(1);
			XSSFRichTextString text = new XSSFRichTextString((String) headerMap.getKey());
			cellRowName.setCellValue(text);
			cellRowName.setCellStyle(columnTopStyle);
			sheet.autoSizeColumn(columnTemp);
			columnTemp++;
		}
	}

private void createLine(Map<String, String> columnMap,List<Map<String, Object>> resultMap, SXSSFWorkbook workbook,Sheet sheet) {
		CellStyle columnStyle = getStyle(workbook);
		int rowCount = 1;
		for (Map<String, Object> dataMap : resultMap) {
			int rowColunmCount = 0;
			Row row = sheet.createRow(rowCount);
			for (Map.Entry<String, String> rowMap : columnMap.entrySet()) {
				Cell cell = row.createCell(rowColunmCount);
				cell.setCellType(1);
				String currentValue = String.valueOf(dataMap.get(rowMap.getValue()));
				XSSFRichTextString text = new XSSFRichTextString(currentValue);
				if (String.valueOf(text).trim().equals("null".trim())) {
					text = new XSSFRichTextString("");
				}
				cell.setCellValue(text);
				cell.setCellStyle(columnStyle);
				sheet.autoSizeColumn(rowColunmCount);
				rowColunmCount++;
			}
			rowCount++;
		}
	}

/**
	 * create sheet name 
	 * default vale is sheet1
	 * @param workbook
	 * @param sheetTempMap
	 * @return
	 */
	private Sheet createSheetName(SXSSFWorkbook workbook,Map<String, Object> sheetTempMap) {
		String sheetName = "sheet1";
		if(sheetTempMap.containsKey("sheetName")){
			sheetName = String.valueOf(sheetTempMap.get("sheetName"));
		}
		Sheet sheet = workbook.createSheet(sheetName);
		return sheet;
	}


private Map<String,String> getColumnMap (){
    //這裏使用了一個LinkedHashMap 使得數據有序化。
    Map<String,String> columnMap = new LinkedHashMap<String, String>();
    columnMap.put("列頭","列屬性");
    return columnMap ;
}

//以下是header 和 row data 的style 可以參考下
public CellStyle getColumnTopStyle(SXSSFWorkbook workbook) {
		Font font = workbook.createFont();
		font.setFontHeightInPoints((short) 11);
		font.setBoldweight((short) 700);
		font.setFontName("Courier New");
		CellStyle style = workbook.createCellStyle();
		style.setBorderBottom((short) 1);
		style.setBottomBorderColor((short) 10);
		style.setBorderLeft((short) 1);
		style.setLeftBorderColor((short) 8);
		style.setBorderRight((short) 1);
		style.setRightBorderColor((short) 8);
		style.setBorderTop((short) 1);
		style.setTopBorderColor((short) 8);
		style.setFont(font);
		style.setWrapText(false);
		style.setAlignment(CellStyle.ALIGN_CENTER);
		style.setVerticalAlignment((short) 1);
		style.setFillForegroundColor((short) 10);
		style.setFillPattern((short) 1);
		return style;
	}

	public CellStyle getStyle(SXSSFWorkbook workbook) {
		Font font = workbook.createFont();
		font.setFontName("Courier New");
		CellStyle style = workbook.createCellStyle();
		style.setBorderBottom((short) 1);
		style.setBottomBorderColor((short) 8);
		style.setBorderLeft((short) 1);
		style.setLeftBorderColor((short) 1);
		style.setBorderRight((short) 1);
		style.setRightBorderColor((short) 8);
		style.setBorderTop((short) 1);
		style.setTopBorderColor((short) 8);
		style.setFont(font);
		style.setWrapText(false);
		style.setAlignment(CellStyle.ALIGN_CENTER);
		style.setVerticalAlignment((short) 1);
		return style;
	}

 

最終導出的樣子

結語:

一切實現在於自己,路人只留下腳印。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章