Java POI 大数据生成Excel

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/HZMand1/article/details/84026547

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;
	}

最终导出的样子

结语:

一切实现在于自己,路人只留下脚印。

猜你喜欢

转载自blog.csdn.net/HZMand1/article/details/84026547
今日推荐