Подтвердить что ты не робот

Чтение файла XLSX в Java

Мне нужно прочитать файл XLSX Excel 2007 в приложении Java. Кто-нибудь знает о хорошем API для выполнения этой задачи?

4b9b3361

Ответ 3

Я должен был сделать это в .NET, и я не мог найти API там. Мое решение состояло в том, чтобы разархивировать .xlsx и погрузиться прямо в управление XML. Это не так уж плохо, если вы создадите свои вспомогательные классы и т.д.

Есть некоторые "gotchas", как и все узлы, все они должны сортироваться в соответствии с тем, как их ожидает excel, чего я не нашел в официальных документах. Excel имеет свою собственную временную метку даты, поэтому вам нужно будет сделать формулу преобразования.

Ответ 4

Возможно, немного поздно, но бета-версия POI теперь поддерживает xlsx.

Ответ 5

Попробуйте следующее:

  • Разархивировать файл XLSX
  • Чтение файлов XML
  • Составление и использование данных

Пример кода:

    public Workbook getTemplateData(String xlsxFile) {
    Workbook workbook = new Workbook();
    parseSharedStrings(xlsxFile);
    parseWorkesheet(xlsxFile, workbook);
    parseComments(xlsxFile, workbook);
    for (Worksheet worksheet : workbook.sheets) {
        worksheet.dimension = manager.getDimension(worksheet);
    }

    return workbook;
}

private void parseComments(String tmpFile, Workbook workbook) {
    try {
        FileInputStream fin = new FileInputStream(tmpFile);
        final ZipInputStream zin = new ZipInputStream(fin);
        InputStream in = getInputStream(zin);
        while (true) {
            ZipEntry entry = zin.getNextEntry();
            if (entry == null)
                break;

            String name = entry.getName();
            if (name.endsWith(".xml")) { //$NON-NLS-1$
                if (name.contains(COMMENTS)) {
                    parseComments(in, workbook);
                }
            }
            zin.closeEntry();
        }
        in.close();
        zin.close();
        fin.close();
    } catch (FileNotFoundException e) {
        System.out.println(e);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

private void parseComments(InputStream in, Workbook workbook) {
    try {
        DefaultHandler handler = getCommentHandler(workbook);
        SAXParser saxParser = getSAXParser();
        saxParser.parse(in, handler);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private DefaultHandler getCommentHandler(Workbook workbook) {
    final Worksheet ws = workbook.sheets.get(0);
    return new DefaultHandler() {
        String lastTag = "";
        private Cell ccell;

        @Override
        public void startElement(String uri, String localName,
                String qName, Attributes attributes) throws SAXException {
            lastTag = qName;
            if (lastTag.equals("comment")) {
                String cellName = attributes.getValue("ref");
                int r = manager.getRowIndex(cellName);
                int c = manager.getColumnIndex(cellName);
                Row row = ws.rows.get(r);
                if (row == null) {
                    row = new Row();
                    row.index = r;
                    ws.rows.put(r, row);
                }
                ccell = row.cells.get(c);
                if (ccell == null) {
                    ccell = new Cell();
                    ccell.cellName = cellName;
                    row.cells.put(c, ccell);
                }
            }
        }

        @Override
        public void characters(char[] ch, int start, int length)
                throws SAXException {
            String val = "";
            if (ccell != null && lastTag.equals("t")) {
                for (int i = start; i < start + length; i++) {
                    val += ch[i];
                }
                if (ccell.comment == null)
                    ccell.comment = val;
                else {
                    ccell.comment += val;
                }
            }
        }
    };
}

private void parseSharedStrings(String tmpFile) {
    try {
        FileInputStream fin = new FileInputStream(tmpFile);
        final ZipInputStream zin = new ZipInputStream(fin);
        InputStream in = getInputStream(zin);
        while (true) {
            ZipEntry entry = zin.getNextEntry();
            if (entry == null)
                break;
            String name = entry.getName();
            if (name.endsWith(".xml")) { //$NON-NLS-1$
                if (name.startsWith(SHARED_STRINGS)) {
                    parseStrings(in);
                }
            }
            zin.closeEntry();
        }
        in.close();
        zin.close();
        fin.close();
    } catch (FileNotFoundException e) {
        System.out.println(e);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public void parseWorkesheet(String tmpFile, Workbook workbook) {
    try {
        FileInputStream fin = new FileInputStream(tmpFile);
        final ZipInputStream zin = new ZipInputStream(fin);
        InputStream in = getInputStream(zin);
        while (true) {
            ZipEntry entry = zin.getNextEntry();
            if (entry == null)
                break;

            String name = entry.getName();
            if (name.endsWith(".xml")) { //$NON-NLS-1$
                if (name.contains("worksheets")) {
                    Worksheet worksheet = new Worksheet();
                    worksheet.name = name;
                    parseWorksheet(in, worksheet);
                    workbook.sheets.add(worksheet);
                }
            }
            zin.closeEntry();
        }
        in.close();
        zin.close();
        fin.close();
    } catch (FileNotFoundException e) {
        System.out.println(e);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public void parseWorksheet(InputStream in, Worksheet worksheet)
        throws IOException {
    // read sheet1 sharedStrings
    // styles, strings, formulas ...
    try {
        DefaultHandler handler = getDefaultHandler(worksheet);
        SAXParser saxParser = getSAXParser();
        saxParser.parse(in, handler);
    } catch (SAXException e) {
        e.printStackTrace();
    } catch (ParserConfigurationException e) {
        e.printStackTrace();
    }
}

где класс рабочей книги:

public class Workbook {
Integer id = null;
public List<Worksheet> sheets = new ArrayList<Worksheet>();}

и класс Worksheet:

public class Worksheet {
public Integer id = null;
public String name = null;
public String dimension = null;
public Map<Integer, Row> rows = new TreeMap<Integer, Row>();
public Map<Integer, Column> columns = new TreeMap<Integer, Column>();
public List<Span> spans = new ArrayList<Span>();}

и класс Row:

public class Row {
public Integer id = null;
public Integer index = null;
public Row tmpRow = null;
public Style style = null;
public Double height = null;
public Map<Integer,Cell> cells = new TreeMap<Integer, Cell>();
public String spans = null;
public Integer customHeight = null;}

и класс Cell:

public class Cell {
public Integer id = null;
public Integer rowIndex = null;
public Integer colIndex = null;
public String cellName = null;
public String text = null;
public String formula = null;
public String comment = null;
public Style style = null;
public Object value = null;
public Cell tmpCell = null;}

и класс столбца:

public class Column {
    public Integer index = null;
    public Style style = null;
    public String width = null;
    public Column tmpColumn = null;
}

и класс Span:

public class Span {
    Integer id = null;
    String topLeft = null;
    String bottomRight = null;
}

Ответ 6

Этот может работать для вас, он может читать/записывать файл Excel xlsx Excel 2007.   SmartXLS

Ответ 7

Я не очень доволен ни одним из вариантов, поэтому я закончил запрос файла в формате Excel 97. POI отлично подходит для этого. Спасибо всем за помощь.

Ответ 8

Вы просмотрели плохо обфусканный API?

Nevermind:

HSSF - это чистая реализация Java проекта POI Project в формате Excel '97 (-2007). Он не поддерживает новый формат файла Excel.xlsx OOXML, который не основан на OLE2.

Вместо этого вы можете вместо этого использовать JDBC-ODBC bridge.

Ответ 9

Я не знаю, является ли это актуальным для Excel 2007, но для более ранних версий я использую JExcelAPI

Ответ 10

docx4j теперь также охватывает xlsx.

"Зачем вам использовать docx4j для этого", я слышу, что вы спрашиваете, "а не POI, который фокусируется на xlsx и двоичных xls?"

Возможно, потому, что вам нравится JAXB (в отличие от XML Beans), или вы уже используете docx4j для docx или pptx, а также должны иметь возможность делать некоторые вещи с помощью xlsx.

Другая возможная причина заключается в том, что jar XML Beans, генерируемый из схем OpenXML, слишком велик для ваших целей. (Чтобы обойти это, POI предлагает подпрограмму "lite": "большой" ooxml-schemas-1.0.jar - 14,5 МБ! Но если вам нужно поддерживать произвольные электронные таблицы, вам, вероятно, понадобится полная банка). Напротив, весь docx4j/pptx4j/xlsx4j весит примерно так же, как подмножество POI lite.

Если вы обрабатываете только электронные таблицы (т.е. не docx или pptx), а предыдущий абзац не беспокоит вас, тогда вам, вероятно, будет лучше всего использовать POI.

Ответ 11

Aspose.Cells для Java поддерживает формат XLSX. Вы можете найти более подробную информацию и дополнительную помощь в Aspose.Cells для Java-документации. Посмотрите, поможет ли это.

Раскрытие информации: Я работаю евангелистом-разработчиком в Aspose.

Ответ 12

Вы можете использовать Apache Tika для этого:

String parse(File xlsxFile) {
    return new Tika().parseToString(xlsxFile);
}

Tika использует Apache POI для анализа файлов XLSX.

Вот несколько примеров использования для Tiki.

В качестве альтернативы, если вы хотите обрабатывать каждую ячейку таблицы отдельно, здесь один из способов сделать это с помощью POI:

void parse(File xlsx) {
    try (XSSFWorkbook workbook = new XSSFWorkbook(xlsx)) {
        // Handle each cell in each sheet
        workbook.forEach(sheet -> sheet.forEach(row -> row.forEach(this::handle)));
    }
    catch (InvalidFormatException | IOException e) {
        System.out.println("Can't parse file " + xlsx);
    }
}

void handle(Cell cell) {
    final String cellContent;
    switch (cell.getCellType()) {
        case Cell.CELL_TYPE_STRING:
            cellContent = cell.getStringCellValue();
            break;
        case Cell.CELL_TYPE_NUMERIC:
            cellContent = String.valueOf(cell.getNumericCellValue());
            break;
        case Cell.CELL_TYPE_BOOLEAN:
            cellContent = String.valueOf(cell.getBooleanCellValue());
            break;
        default:
            cellContent = "Don't know how to handle cell " + cell;
    }
    System.out.println(cellContent);
}