Не удается прочитать файл Excel 2010 с Apache POI. Номер первой строки -1

1

Я пытаюсь использовать этот тестовый файл с API Apache POI (текущая версия 3 -1 0-FINAL). Следующий тестовый код

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 (а существующие строки возвращаются как null). Тестовый файл был создан в Excel 2010 (у меня нет контроля над этой частью) и может быть прочитан с помощью Excel без предупреждений или проблем. Если я открою и сохраню файл с моей версией Excel (2013), он может быть прочитан отлично, как и ожидалось.

Любые намеки на то, почему я не могу прочитать исходный файл или как могу, очень ценятся.

  • 0
    Это определенно не старый формат, который требовал бы структуры HSSF. Я надеялся найти кого-нибудь, кто сможет сказать мне, что не так с файлом (потому что файлы 2010 года определенно могут быть прочитаны фреймворком)
  • 0
    Вы уверены, что ваши данные не в листе 1 или листе 2?
Показать ещё 1 комментарий
Теги:
excel
excel-2010
apache-poi
xssf

1 ответ

5
Лучший ответ

Файл 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.CTWorksheet, org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetData, org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRow. Которые являются частью бинарного дистрибутива POI Apache 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 напрямую, поскольку он имеет защищенный доступ.

  • 1
    Просто для подробного описания пропуска SpreadsheetGear необязательного атрибута r, см. Stackoverflow.com/questions/26634736/… . Существует возможность сказать SpreadsheetGear включить этот атрибут. Он не включен по умолчанию, потому что (кроме того факта, что он является технически необязательным, и у Excel нет проблем с чтением в таких файлах) его пропуск может значительно улучшить степень сжатия zip и, следовательно, уменьшить размер файла, а также время на его обработку, особенно для больших файлов рабочих книг.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню