无法使用Apache POI读取Excel 2010文件。 第一行数是-1

我正在用Apache POI API(当前版本3-10-FINAL)来testing这个testing文件。 以下testing代码

import java.io.FileInputStream; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; public class ExcelTest { public static void main(String[] args) throws Exception { String filename = "testfile.xlsx"; XSSFWorkbook wb = new XSSFWorkbook(new FileInputStream(filename)); XSSFSheet sheet = wb.getSheetAt(0); System.out.println(sheet.getFirstRowNum()); } } 

导致第一行数为-1(现有行返回为空)。 testing文件是由Excel 2010创build的(我无法控制该部分),可以使用Excel进行读取而不出现任何警告或问题。 如果我用我的Excel版本(2013)打开并保存文件,可以按预期完美地读取文件。

任何提示为什么我不能读取原始文件或我怎么能高度赞赏。

testfile.xlsx是使用“SpreadsheetGear 7.1.1.120”创build的。 用一个可以处理ZIP压缩文件的软件打开XLSX文件,并查看/xl/workbook.xml来查看。 在worksheets/sheet?.xml文件中,要注意的是,所有行元素都没有行号。 如果我把行号放在第一行标签里,比如<row r="1">那么apache POI可以读这行。

如果涉及到这个问题,应该指责谁,那么答案肯定是Apache Poi和SpreadsheetGear ;-)。 Apache POI,因为row元素中的属性r是可选的。 但SpreadsheetGear也是因为没有理由不使用r属性,如果Excel本身做它永远。

如果无法以Apache POI直接读取的格式获取testfile.xlsx,则必须使用基础对象。 以下与您的testfile.xlsx一起工作:

 import org.apache.poi.xssf.usermodel.*; import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.util.*; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import java.io.FileNotFoundException; import java.io.IOException; import java.io.FileInputStream; import java.io.InputStream; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetData; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRow; import java.util.List; class Testfile { public static void main(String[] args) { try { InputStream inp = new FileInputStream("testfile.xlsx"); Workbook wb = WorkbookFactory.create(inp); Sheet sheet = wb.getSheetAt(0); System.out.println(sheet.getFirstRowNum()); CTWorksheet ctWorksheet = ((XSSFSheet)sheet).getCTWorksheet(); CTSheetData ctSheetData = ctWorksheet.getSheetData(); List<CTRow> ctRowList = ctSheetData.getRowList(); Row row = null; Cell[] cell = new Cell[2]; for (CTRow ctRow : ctRowList) { row = new MyRow(ctRow, (XSSFSheet)sheet); cell[0] = row.getCell(0); cell[1] = row.getCell(1); if (cell[0] != null && cell[1] != null && cell[0].toString() != "" && cell[1].toString() != "") System.out.println(cell[0].toString()+"\t"+cell[1].toString()); } } catch (InvalidFormatException ifex) { } catch (FileNotFoundException fnfex) { } catch (IOException ioex) { } } } class MyRow extends XSSFRow { MyRow(org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRow row, XSSFSheet sheet) { super(row, sheet); } } 

我已经使用了org.openxmlformats.schemas.spreadsheet.xml.x2006.main.CTWorksheet,org.openxmlformats.schemas.spreadsheet.xml.x2006.main.CTSheetData,org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRow。 哪些是Apache POI二进制发行版poi-bin-3.10.1-20140818的一部分,在poi-ooxml-schemas-3.10.1-20140818.jar

有关文档,请参阅http://grepcode.com/snapshot/repo1.maven.org/maven2/org.apache.poi/ooxml-schemas/1.1/

而且我扩展了XSSFRow,因为我们不能直接使用XSSFRow的构造函数,因为它保护了访问。