Мне нужно прочитать файл XLSX Excel 2007 в приложении Java. Кто-нибудь знает о хорошем API для выполнения этой задачи?
Чтение файла XLSX в Java
Ответ 1
AFAIK пока нет доступных xlsx-библиотек. Но есть некоторые для старых xls:
Одна библиотека jxls, которая внутренне использует уже упомянутый POI.
2 другие ссылки: обрабатывать файлы Excel, библиотеки Java для читать и записывать файлы документов Excel XLS.
Ответ 2
Apache POI 3.5 добавили поддержку всем OOXML (docx, xlsx и т.д.)
Смотрите подпроект XSSF
Ответ 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);
}