使用poi生成excel,当遇到大数据量时,会有几个问题:
1. 目前office2003 excle每个sheet最大支持行数为65536,当数据超过65536行时,会报异常
2. 当列为17列左右,数据行数达到50w条左右时,会包OOM错误
Exception in thread "15124183@qtp-16902686-1" java.lang.OutOfMemoryError: Java heap space
Exception in thread "Thread-13" java.lang.OutOfMemoryError: Java heap space
at org.apache.poi.hssf.usermodel.HSSFRow.createCell(HSSFRow.java:141)
at org.apache.poi.hssf.usermodel.HSSFRow.createCell(HSSFRow.java:119)
问题1比较好解决,每次写入数据时,都获取sheet最后一行,在最后一行后继续写入数据,判断当最大行数大于65536或再小些,生成新的sheet,就能解决此问题。
具体代码片段
int sheetLastSize = sheet.getLastRowNum();
// 如果数据是最大写入数的整数倍(Constants.EXCEL_SHEET_DATASIZE为最大行数)
if (sheetLastSize >= Constants.EXCEL_SHEET_DATASIZE) {
sheet = workbook.createSheet();
sheetLastSize = sheet.getLastRowNum();
log.info("sheetLast Size:=========" + sheetLastSize);
mapInfo.put("sheet", sheet);
// 处理标题头
processExcelTitle(dataset, workbook, sheet);
}
问题2 目前没有较好的解决办法。由于每行都要生成多个cell对象,当数据量大时,java GC还没来得及回收,导致最后没有内存创建cell对象。现在正测试一种方法(只是暂时缓解,不是最好的办法),每次写入数据后,把row赋值null,定时调用System.GC();没有别的好办法,只能暂时测试下。
还是不行,仍然溢出!
/**
* 传入已存在的workbook和数据源,向excel中追加数据,每个sheet大于指定行数时,创建新的sheet
*
* @param workbook
* 已存在的工作薄
* @param dataset
* 写入数据集合
* @param mapInfo
* 准备数据map
*/
@SuppressWarnings("unchecked")
private void dynamicExcel(HSSFWorkbook workbook, Map<String, Object> dataset, Map<Object, Object> mapInfo) {
Map<String, String> headers = (Map<String, String>) dataset.get("1");
Iterator<Entry<String, String>> titleIter = headers.entrySet().iterator();
// 取得所有行的数据
List<Map<String, String>> valueList = (List<Map<String, String>>) dataset.get("2");
wroteRecodeSize += valueList.size();
log.info("this times size is:------------------------------------------------------" + valueList.size());
log.info("total wrote recode size is:------------------------------------------------" + wroteRecodeSize);
HSSFSheet sheet = (HSSFSheet) mapInfo.get("sheet");
for (int i = 0; i < valueList.size(); i++) {
int sheetLastSize = sheet.getLastRowNum();
// 如果数据是最大写入数的整数倍
if (sheetLastSize >= Constants.EXCEL_SHEET_DATASIZE) {
sheet = workbook.createSheet();
sheetLastSize = sheet.getLastRowNum();
log.info("sheetLast Size:=========" + sheetLastSize);
mapInfo.put("sheet", sheet);
// 处理标题头
processExcelTitle(dataset, workbook, sheet);
}
// 追加行
HSSFRow row = sheet.createRow(sheetLastSize + 1);
sheet.setDefaultColumnWidth(25);
// 取得一行所有记录的所有值
int dataIndex = 0;
Map<String, String> values = valueList.get(i);
titleIter = headers.entrySet().iterator();
while (titleIter.hasNext()) {
Map.Entry<String, String> entry = (Map.Entry<String, String>) titleIter.next();
String key = entry.getKey();
HSSFCell cell = row.createCell(dataIndex++);
// String v = values.get(key);
cell.setCellValue(values.get(key));
}
}
}