使用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)); } } }