ไม่สามารถอ่านไฟล์ Excel 2010 ด้วย Apache POI หมายเลขแถวแรกคือ -1

ฉันกำลังลองใช้ testfile ด้วย Apache POI API (เวอร์ชันปัจจุบัน 3) -10-สุดท้าย) รหัสทดสอบต่อไปนี้

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 (และแถวที่มีอยู่กลับมาเป็นโมฆะ) ไฟล์ทดสอบสร้างขึ้นโดย Excel 2010 (ฉันไม่สามารถควบคุมส่วนนั้นได้) และสามารถอ่านด้วย Excel โดยไม่มีคำเตือนหรือปัญหา ถ้าฉันเปิดและบันทึกไฟล์ด้วย Excel เวอร์ชันของฉัน (2013) จะสามารถอ่านได้อย่างสมบูรณ์ตามที่คาดไว้

คำแนะนำใด ๆ เกี่ยวกับสาเหตุที่ฉันไม่สามารถอ่านไฟล์ต้นฉบับได้หรือทำอย่างไรจึงจะได้รับการชื่นชมอย่างมาก


person ratatosk    schedule 27.11.2014    source แหล่งที่มา
comment
ไม่ใช่รูปแบบเก่าที่ต้องใช้เฟรมเวิร์ก HSSF แน่นอน ฉันหวังว่าจะพบใครสักคนที่สามารถบอกฉันว่ามีอะไรผิดปกติกับไฟล์ (เพราะเฟรมเวิร์กสามารถอ่านไฟล์ปี 2010 ได้อย่างแน่นอน)   -  person ratatosk    schedule 27.11.2014
comment
คุณแน่ใจหรือไม่ว่าข้อมูลของคุณไม่ได้อยู่ในชีต 1 หรือชีต 2   -  person Gagravarr    schedule 27.11.2014
comment
testfile.xlsx ถูกสร้างขึ้นด้วย SpreadsheetGear 7.1.1.120 เปิดไฟล์ XLSX ด้วยซอฟต์แวร์ที่สามารถจัดการกับไฟล์ ZIP และค้นหาใน /xl/workbook.xml เพื่อดูว่า ในไฟล์ worksheets/sheet?.xml สังเกตว่าองค์ประกอบแถวทั้งหมดไม่มีหมายเลขแถว ถ้าฉันใส่หมายเลขแถวในแท็กแถวแรกเช่น <row r="1"> ดังนั้น apache POI ก็สามารถอ่านแถวนี้ได้   -  person Axel Richter    schedule 27.11.2014


คำตอบ (1)


testfile.xlsx ถูกสร้างขึ้นด้วย "SpreadsheetGear 7.1.1.120" เปิดไฟล์ XLSX ด้วยซอฟต์แวร์ที่สามารถจัดการกับไฟล์ ZIP และตรวจดูใน /xl/workbook.xml เพื่อดูว่า ในไฟล์ worksheets/sheet?.xml จะสังเกตว่าองค์ประกอบแถวทั้งหมดไม่มีหมายเลขแถว ถ้าฉันใส่หมายเลขแถวในแท็กแถวแรกเช่น <row r="1"> apache POI ก็สามารถอ่านแถวนี้ได้

หากพูดถึงคำถามนี้ ใครจะถูกตำหนิ คำตอบก็คือทั้ง Apache Poi และ SpreadsheetGear อย่างแน่นอน ;-) Apache POI เนื่องจากแอตทริบิวต์ r ในองค์ประกอบ row เป็นทางเลือก แต่ SpreadsheetGear ก็เช่นกัน เนื่องจากไม่มีเหตุผลที่จะไม่ใช้แอตทริบิวต์ r หาก Excel เองก็ทำเช่นนั้น

หากคุณไม่สามารถรับ testfile.xlsx ในรูปแบบที่ Apache POI อ่านได้โดยตรง คุณต้องทำงานกับอ็อบเจ็กต์ที่ซ่อนอยู่ ข้อมูลต่อไปนี้ใช้ได้กับ 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.spreadsheetml.x2006.main.CTแผ่นงาน
  • org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetData
  • org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRow

ซึ่งเป็นส่วนหนึ่งของ Apache POI Binary Distribution 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 ได้โดยตรงเนื่องจากมีการป้องกันการเข้าถึง

person Axel Richter    schedule 28.11.2014
comment
เพื่ออธิบายอย่างละเอียดเกี่ยวกับการละเว้นแอตทริบิวต์ r ที่ไม่บังคับของ SpreadsheetGear โปรดดู stackoverflow.com/questions/26634736/ คือ ตัวเลือกในการบอก SpreadsheetGear ให้รวมแอตทริบิวต์นี้ จะไม่รวมไว้ตามค่าเริ่มต้นเพราะ (นอกเหนือจากความจริงที่ว่าเป็นตัวเลือกในทางเทคนิคและ Excel ไม่มีปัญหาในการอ่านไฟล์ดังกล่าว) การละเว้นสามารถปรับปรุงอัตราส่วนการบีบอัด zip ได้อย่างมากและลดขนาดไฟล์ตลอดจนเวลาในการประมวลผล โดยเฉพาะอย่างยิ่งสำหรับไฟล์สมุดงานขนาดใหญ่ - person Tim Andersen; 22.01.2015