Apache POI - Excel-Datei einlesen
Aus Byte-Welt Wiki
Mit dem Java-Framework Apache POI kann man recht komfortabel Microsoft Excel-Dateien auslesen und erzeugen (schreiben).
Hier ein vollständiges Beispiel zum Auslesen des Tabelleninhaltes einer beliebigen Excel-Datei. Das heißt, wir mit diesem Code das binäre Format (.xls) sowie das auf XML basierende Format .xslx einlesen.
Diese Klasse wurde mit der Apache License 2.0 veröffentlicht:
Excel-Datei einlesen
/*
* ExcelFileReader.java
*
* Copyright (c) 2019 Gernot Segieth - wiki.byte-welt.net
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.FormulaEvaluator;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.WorkbookUtil;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
/**
* ExcelFileProxy liest die Excel-Datei ein und erzeugt ein tabellarisches
* Abbild der Arbeitsmappe in Form von verschachtelten Listen.
*
* @author Gernot Segieth
*/
public class ExcelFileProxy {
private File excelFile;
private Workbook workbook;
private FormulaEvaluator evaluator;
private boolean isEmptyRow;
/**
* Erzeugt einen neuen Excel-Datei-Stellvertreter. ExcelFileProxy liest die
* ihm übergebene Excel-Datei ein und erzeugt ein tabellarisches Abbild
* davon.
*
* @param excelFile Die einzulesene Excel-Datei
* @throws java.lang.ClassNotFoundException wenn eine Klasse nicht gefunden
* wurde
* @throws java.io.IOException wenn die Datei nicht eingelesen werde konnte
* @throws org.apache.poi.openxml4j.exceptions.InvalidFormatException wenn
* es Probleme mit dem Format der Datei oder der Verschlüsselung gibt
*/
public ExcelFileProxy(File excelFile) throws ClassNotFoundException, IOException, InvalidFormatException {
this.excelFile = excelFile;
createWorkbook(excelFile);
}
/**
* Gibt den Inhalt des übergebenen Tabellenblattes in einer geschachtelten
* Liste zurück.
*
* @param sheetIndex der Index des Tabellenblattes
* @return eine Liste aus Listen (Zeilen mit Spalten)
*/
public List<List<?>> getSheetContent(int sheetIndex) {
evaluator = workbook.getCreationHelper().createFormulaEvaluator();
return getSheetContent(sheetIndex, 0, 0, 0, 0);
}
/**
* Gibt den Inhalt des übergebenen Tabellenblattes in einer geschachtelten
* Liste zurück.
*
* @param sheetIndex der Index des Tabellenblattes
* @param firstRow in dieser Zeile mit dem Auslesen beginnen
* @param firstCol in dieser Spalte mit dem Auslesen beginnen
* @param lastRow letzte auszulesene Zeile
* @param lastCol letzte auszulesene Spalte
* @return eine Liste aus Listen (Zeilen mit Spalten)
*/
public List<List<?>> getSheetContent(int sheetIndex, int firstRow, int firstCol, int lastRow, int lastCol) {
evaluator = workbook.getCreationHelper().createFormulaEvaluator();
Sheet sheet = workbook.getSheetAt(sheetIndex);
List<List<?>> sheetData = new ArrayList<>();
// Range festlegen (bei Übergabe 0 - ermitteln, sonst Range verarbeiten
int lastRowNum;
if (lastRow < 1) {
lastRowNum = sheet.getLastRowNum();
} else {
lastRowNum = lastRow;
}
for (int actuallyRow = firstRow; actuallyRow <= lastRowNum; actuallyRow++) {
Row row = sheet.getRow(actuallyRow); //leere Zeile kann NPE auslösen!
if (row != null) { //leere Zeile abfangen
List<Object> rowData = new ArrayList<>();
isEmptyRow = true; //Zeile erstmal als leer ansehen
int lastColNum;
if (lastCol < 1) {
lastColNum = row.getLastCellNum();
} else {
lastColNum = lastCol;
}
for (int actuallyCol = firstCol; actuallyCol < lastColNum; actuallyCol++) {
Cell cell = row.getCell(actuallyCol);
rowData.add(getData(cell));
}
if (!isEmptyRow) { //leere Zeilen nicht aufnehmen
sheetData.add(rowData);
}
}
}
return sheetData;
}
/**
* Schreibt Daten einer tabellenartig aufgebauten Liste in das Arbeitsblatt.
*
* @param sheetData die Daten aus der Liste, die in das Tabellenblatt
* geschrieben werden sollen
* @param sheetName Name des Tabellenblattes
*/
public void setSheetContent(List<List<?>> sheetData, String sheetName) {
String safeName = WorkbookUtil.createSafeSheetName(sheetName);
CreationHelper createHelper = workbook.getCreationHelper();
Sheet sheet = workbook.createSheet(safeName);
for (int i = 0, j = sheetData.size(); i < j; i++) {
Row row = sheet.createRow(i); //Zeile erzeugen
List<?> rowList = sheetData.get(i); //Zeile holen
for (int x = 0, y = rowList.size(); x < y; x++) {
Cell cell = row.createCell(x); //Zelle erzeugen
Object cellValue = rowList.get(x);
if (cellValue instanceof Number) {
cell.setCellValue((Double) cellValue);
} else if (cellValue instanceof Date) {
cell.setCellValue((Date) cellValue);
} else if (cellValue instanceof Boolean) {
cell.setCellValue((Boolean) cellValue);
} else if (cellValue instanceof String) {
cell.setCellValue(createHelper.createRichTextString(cellValue.toString()));
}
}
}
}
/**
* Gibt die Namen aller Tabellenblätter zurück.
*
* @return die Namen der Tabellenblätter
*/
public String[] getSheetNames() {
String[] sheetNames = new String[getNumberOfSheets()];
for (int i = 0; i < sheetNames.length; i++) {
sheetNames[i] = getSheetName(i);
}
return sheetNames;
}
/**
* Gibt die Anzahl der Tabellenblätter in der Excel-Datei zurück.
*
* @return die Anzahl
*/
public int getNumberOfSheets() {
return workbook.getNumberOfSheets();
}
/**
* Gibt den Namen des Tabellenblattes am übergebenen Index zurück.
*
* @param sheetIndex der Index
* @return das Tabelleenblatt
*/
public String getSheetName(int sheetIndex) {
return workbook.getSheetName(sheetIndex);
}
/**
* Setzt den Namen des Tabellenblattes am übergebenen Index.
*
* @param index der Index des Tabellenblattes in der Arbeitsmappe
* @param sheetName der Name des Tabellenblattes
*/
public void setSheetName(int index, String sheetName) {
workbook.setSheetName(index, sheetName);
}
/**
* Gibt den Index des aktiven Tabellenblattes zurück.
*
* @return der Index des aktiven Tabellenblattes
*/
public int getActiveSheetIndex() {
return workbook.getActiveSheetIndex();
}
/**
* Setzt das aktive Tabellenblatt.
*
* @param index der Index des aktiven Tabellenblattes in der Arbeitsmappe
*/
public void setActiveSheet(int index) {
workbook.setActiveSheet(index);
}
/**
* Gibt das Datum der letzten Änderung der Excel-Datei zurück.
*
* @return
*/
public long lastModified() {
return excelFile.lastModified();
}
/**
* Gibt den genauen (einzigen) Pfad zur geladenen Excel-Datei zurück.
*
* @return Der Pfad zur geladenen Excel-Datei. //@throws java.io.IOException
*/
public String getPath() /*throws IOException*/ {
return excelFile.getAbsolutePath();
}
/**
* Setzt den Pfad zur Excel-Datei und erzeugt ein Abbild des Workbooks (alle
* Tabellenblätter).
*
* @param excelFile
* @throws java.lang.ClassNotFoundException
* @throws java.io.IOException
* @throws org.apache.poi.openxml4j.exceptions.InvalidFormatException
*/
public void setPath(File excelFile) throws ClassNotFoundException, IOException, InvalidFormatException {
this.excelFile = excelFile;
update();
}
/**
* Liest das Workbook der Excel-Datei neu ein.
*
* @throws java.lang.ClassNotFoundException
* @throws java.io.IOException
* @throws org.apache.poi.openxml4j.exceptions.InvalidFormatException
*/
public synchronized void update() throws ClassNotFoundException, IOException, InvalidFormatException {
createWorkbook(excelFile);
}
public void createWorkbook(Map<String, List<List<?>>> sheetData) throws IOException {
Set<String> keys = sheetData.keySet();
Iterator<String> it = keys.iterator();
while (it.hasNext()) {
String key = it.next();
this.setSheetContent(sheetData.get(key), key);
}
createExcelFile(excelFile);
}
//erzeugt ein Workbook aus der übergebenen Excel-Datei
private void createWorkbook(File file) throws ClassNotFoundException, IOException, InvalidFormatException {
String filename = file.getName().toLowerCase();
try {
if (filename.endsWith(".xls")) {
readHSSFWorkbook(file);
//workbook = WorkbookFactory.create(file);
} else if (filename.endsWith(".xlsx")) {
readXSSFWorkbook(file);
} else {
throw new IllegalArgumentException("Ausnahmefehler: Die übergebene Datei " + file.getName() + " ist keine valide Microsoft Excel-Datei (*.xls bzw. *.xlsx)!");
}
} catch (IOException ioe) {
Logger.getLogger(ExcelFileProxy.class.getName()).log(Level.SEVERE, null, ioe);
throw new IOException("Ausnahmefehler: Die Datei " + file.getName() + " konnte nicht eingelesen werden!");
} catch (EncryptedDocumentException ede) {
Logger.getLogger(ExcelFileProxy.class.getName()).log(Level.SEVERE, null, ede);
throw new EncryptedDocumentException("Ausnahmefehler: Die Datei " + file.getName() + " ist mit einem Passwort geschützt und kann daher nicht geöffnet werden!");
} catch (NoClassDefFoundError err) {
System.err.println(err.toString());
throw new ClassNotFoundException("Schwerer Ausnahmefehler: Klassendefinition nicht gefunden!\nPrüfen Sie die Programmdateien und externen Bibliotheken auf Vollständigkeit!");
}
}
private void readHSSFWorkbook(File file) throws IOException {
POIFSFileSystem fs = new POIFSFileSystem(file);
workbook = new HSSFWorkbook(fs.getRoot(), true);
fs.close();
}
private void readXSSFWorkbook(File file) throws InvalidFormatException, IOException {
OPCPackage pkg = OPCPackage.open(file);
workbook = new XSSFWorkbook(pkg);
pkg.close();
}
//Schreibt eine Arbeitsmappe in eine Exceldatei
private void createExcelFile(File file) throws FileNotFoundException, IOException {
try (FileOutputStream fileOut = new FileOutputStream(file)) {
workbook.write(fileOut);
} catch (FileNotFoundException fnfe) {
throw new IOException("Ausnahmefehler: Die Datei " + file.getName() + " konnte nicht erzeugt werden!");
} catch (IOException ioe) {
throw new IOException("Ausnahmefehler: Die Datei " + file.getName() + " konnte nicht erzeugt werden!");
}
}
//Liest die Daten aus einer Zelle und gibt sie zurück.
private Object getData(Cell cell) {
if (cell != null) {
switch (cell.getCellType()) {
case STRING:
String string = cell.getRichStringCellValue().getString();
if (string.isEmpty()) {
return null;
} else {
isEmptyRow = false;
return string.trim();
}
case NUMERIC:
if (DateUtil.isCellDateFormatted(cell)) {
Date date = cell.getDateCellValue();
if (date.toString().isEmpty()) {
return null;
} else {
isEmptyRow = false;
return date;
}
} else {
Number number = cell.getNumericCellValue();
if (number.toString().isEmpty()) {
return null;
} else {
isEmptyRow = false;
return number;
}
}
case BOOLEAN:
Boolean bool = (cell.getBooleanCellValue());
if (bool.toString().isEmpty()) {
return null;
} else {
isEmptyRow = false;
return bool;
}
case _NONE:
case FORMULA:
case BLANK:
case ERROR:
default:
return null;
}
} else {
return null;
}
}
}
Beispiel-Code für die Benutzung dieser Klasse
Erläuterungen zum Code
![]() |
Dieser Beitrag wird derzeit noch bearbeitet. Der Text ist deshalb unvollständig und kann Fehler oder ungeprüfte Aussagen enthalten. |

