Java POI导出为优于空行将被忽略导入时

我有使用Apache POI库导出/导入Excel文件(.xls)的Java程序(我使用旧的Excel .xls文件的HSSF前缀类)。

我的excel格式是:
第1行:标题
第2行:空
第3行:表头和内容

比方说,我的表有5行,包括头,总共7行。 我正在将数据导出到excel文件,文件大小为6k。 我没有改变任何文件,我正在导入它,而debugging导入时,我意识到,我的行数是6! 这意味着它忽略了空行由于某种原因,我不明白。

接下来的情况下,我导出文件打开它与MS Excel保存它,文件大小更改为24K。 我执行导入和它的工作,行的总大小是7。
导入和导入代码的开始如下:

public static TempFile createExcelFile(String sheetTitle, String title, String headerSummary, List<String> header, List<LinkedHashMap<String, String>> data) { TempFile result = new TempFile(FileKeyFactory.getFileKey(ExcelReporter.class).getFullPathKey()); HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet spreadSheet; DataFormat format = null; int rowIndex = 0; // Get a DataFormat object and use it to create a CellStyle object // with the following format set for the cells @. The @ or ampersand // sets the format so that the cell will hold text. format = wb.createDataFormat(); if (sheetTitle != null) { spreadSheet = wb.createSheet(sheetTitle); } else { spreadSheet = wb.createSheet(); } if (title != null) { // Title HSSFFont titleFont = wb.createFont(); titleFont.setFontHeightInPoints((short) 14); titleFont.setItalic(true); HSSFRow titleRow = spreadSheet.createRow(rowIndex++); HSSFCell cell = titleRow.createCell(0); cell.setCellValue(title); cell.getCellStyle().setFont(titleFont); spreadSheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 100)); } else { spreadSheet = wb.createSheet(); } HSSFCellStyle style = wb.createCellStyle(); style.setDataFormat(format.getFormat("@")); if (headerSummary != null) { HSSFFont headerFont = wb.createFont(); headerFont.setFontHeightInPoints((short) 9); headerFont.setItalic(false); HSSFCellStyle headerCellStyle = wb.createCellStyle(); headerCellStyle.setDataFormat(format.getFormat("@")); headerCellStyle.setFont(headerFont); headerCellStyle.setWrapText(true); HSSFRow headerRow = spreadSheet.createRow(rowIndex++); HSSFCell headerCell = headerRow.createCell(0); headerCell.setCellValue(headerSummary); headerCell.setCellStyle(headerCellStyle); //increase row height to accommodate two lines of text headerRow.setHeightInPoints((9 * spreadSheet.getDefaultRowHeightInPoints())); //adjust column width to fit the content spreadSheet.autoSizeColumn((short) 1); spreadSheet.addMergedRegion(new CellRangeAddress(1, 1, 0, 100)); } /* * Data table header */ HSSFRow dateRow = spreadSheet.createRow(rowIndex++); Calendar calendar = Calendar.getInstance(); HSSFCreationHelper createHelper = wb.getCreationHelper(); CellStyle cellStyle = wb.createCellStyle(); cellStyle.setDataFormat(createHelper.createDataFormat().getFormat("m/d/yy h:mm")); HSSFCell cell = dateRow.createCell(0); cell.setCellValue("Created: " + DateParser.toString(calendar, DateParser.MONTH_WORD_DATE_FORMAT)); cell.setCellStyle(cellStyle); HSSFFont headerTableFont = wb.createFont(); headerTableFont.setFontHeightInPoints((short) 10); headerTableFont.setColor(IndexedColors.WHITE.getIndex()); HSSFCellStyle tableHeaderStyle = wb.createCellStyle(); tableHeaderStyle.setDataFormat(format.getFormat("@")); tableHeaderStyle.setBorderRight(HSSFCellStyle.BORDER_MEDIUM); tableHeaderStyle.setBorderTop(HSSFCellStyle.BORDER_MEDIUM); tableHeaderStyle.setBorderLeft(HSSFCellStyle.BORDER_MEDIUM); tableHeaderStyle.setBorderBottom(HSSFCellStyle.BORDER_MEDIUM); tableHeaderStyle.setFillForegroundColor(HSSFColor.LIGHT_BLUE.index); tableHeaderStyle.setFont(headerTableFont); tableHeaderStyle.setFillPattern(CellStyle.SOLID_FOREGROUND); HSSFRow tableHeaderRowRow = spreadSheet.createRow(rowIndex++); for (int i = 0; i < header.size(); i++) { HSSFCell ipHeaderCell = tableHeaderRowRow.createCell(i); ipHeaderCell.setCellStyle(tableHeaderStyle); ipHeaderCell.setCellValue(header.get(i)); spreadSheet.autoSizeColumn(i); } /* * ********************** DATA ******************* */ HSSFCellStyle dataCellStyle = wb.createCellStyle(); dataCellStyle.setDataFormat(format.getFormat("@")); dataCellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN); dataCellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN); dataCellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN); dataCellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN); //spreadSheet.createRow(rowIndex++); for (LinkedHashMap<String, String> row : data) { HSSFRow currentRow = spreadSheet.createRow(rowIndex++); for (int i = 0; i < header.size(); i++) { HSSFCell dataCell = currentRow.createCell(i); dataCell.setCellStyle(dataCellStyle); dataCell.setCellType(Cell.CELL_TYPE_STRING); String celVal = row.get(header.get(i)); dataCell.setCellValue(celVal); } } // Resize columns automatically. for (int i = 0; i < header.size(); i++) { spreadSheet.setDefaultColumnStyle(i, style); spreadSheet.autoSizeColumn(i); } FileOutputStream resultOutStream = null; try { resultOutStream = new FileOutputStream(result); wb.write(resultOutStream); resultOutStream.flush(); } catch (Exception e) { Logger.ERROR("File path: " + result.getAbsolutePath() + File.separator + result.getName(), e); throw new RuntimeException("File path: " + result.getAbsolutePath() + File.separator + result.getName(), e); } finally { try { if (resultOutStream != null) { resultOutStream.close(); } } catch (Exception ignore) { } } return result; } public void import() { ... InputStream input = new BufferedInputStream(new FileInputStream(file)); POIFSFileSystem fs = new POIFSFileSystem(input); HSSFWorkbook wb = new HSSFWorkbook(fs); HSSFSheet sheet = wb.getSheetAt(0); Iterator rows = sheet.rowIterator(); rows.next(); // skip title rows.next(); // skip empty row List<String> header = getLine((HSSFRow) rows.next()); ... } private List<String> getLine(HSSFRow row) { List<String> header = new ArrayList<String>(); Iterator<Cell> cellIterator = row.cellIterator(); while(cellIterator.hasNext()) { HSSFCell cell = (HSSFCell)cellIterator.next(); cell.setCellType(Cell.CELL_TYPE_STRING); header.add(cell.toString()); } return header; } 

任何想法为什么在导出和导入之后,在调用sheet.rowIterator()时,空行会被忽略?

这是预期的行为。 从Javadocs :

返回PHYSICAL行的迭代器。 意思是第三个元素可能不是第三行,如果说例如第二行是未定义的。

如果您在遍历行和单元格的过程中查看Apache POI文档 ,您将看到更详细的描述,以及有关如何强制对范围内的所有行进行迭代的说明(如果这是您真正想要的)。 你的代码将会像(从Apache POI文档中获取的)

 // Decide which rows to process int rowStart = Math.min(15, sheet.getFirstRowNum()); int rowEnd = Math.max(1400, sheet.getLastRowNum()); for (int rowNum = rowStart; rowNum < rowEnd; rowNum++) { Row r = sheet.getRow(rowNum); if (r == null) { // Handle empty row continue; } int lastColumn = Math.max(r.getLastCellNum(), MY_MINIMUM_COLUMN_COUNT); for (int cn = 0; cn < lastColumn; cn++) { Cell c = r.getCell(cn, Row.RETURN_BLANK_AS_NULL); if (c == null) { // The spreadsheet is empty in this cell } else { // Do something useful with the cell's contents } } } 

我从来没有遇到过这个问题,但我使用sheet.getRow(row)而不是rowIterator()。 我想这可能是POI中的rowIterator实现中的错误(您应该向他们报告)。

所以,你可以请尝试更改您的代码:

 Iterator rows = sheet.rowIterator(); rows.next(); // skip title rows.next(); // skip empty row List<String> header = getLine((HSSFRow) rows.next()); 

至:

 int row = 0; ++row; // skip title; ++row; // skip empty row List<String> header = getLine((HSSFRow)sheet.getRow(row)); ++row; 

希望它的作品。

注意:您还应该使用“工作簿”,“工作表”和“行”而不是“HSSFWorkbook”,“HSSFSheet”和“HSSFRow”。 这将节省您一些打字,并且您的代码将准备好,以防您需要一些时间来处理一些XLSX文件!