poi大数据量生成excel

    技术2022-08-10  12

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

    最新回复(0)