Apache POI - Excel-Datei einlesen

Aus Byte-Welt Wiki
Zur Navigation springenZur Suche springen

Mit dem Java-Framework Apache POI kann man recht komfortabel Excel-Dateien auslesen und erzeugen (schreiben).

Hier ein Beispiel zum Auslesen einer beliebigen Excel-Datei. Das heißt, wir verarbeiten das binäre Format (.xls) sowie das auf XML basierende Format .xslx .

Excel-Datei einlesen

Wir schreiben uns zunächst eine Klasse, die zwei private Methoden implementiert, die die beiden Dateitypen separat verarbeiten:

 1 import org.apache.poi.EncryptedDocumentException;
 2 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
 3 import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
 4 import org.apache.poi.openxml4j.opc.OPCPackage;
 5 import org.apache.poi.poifs.filesystem.POIFSFileSystem;
 6 import org.apache.poi.ss.usermodel.Cell;
 7 import org.apache.poi.ss.usermodel.CreationHelper;
 8 import org.apache.poi.ss.usermodel.DateUtil;
 9 import org.apache.poi.ss.usermodel.FormulaEvaluator;
10 import org.apache.poi.ss.usermodel.Row;
11 import org.apache.poi.ss.usermodel.Sheet;
12 import org.apache.poi.ss.usermodel.Workbook;
13 import org.apache.poi.ss.util.WorkbookUtil;
14 import org.apache.poi.xssf.usermodel.XSSFWorkbook;
15 
16 /**
17  * ExcelFileProxy liest die Excel-Datei ein und erzeugt ein tabellarisches
18  * Abbild der Arbeitsmappe in Form von verschachtelten Listen.
19  *
20  * @author Gernot Segieth
21  */
22 public class ExcelFileReader {
23     private Workbook workbook
24 
25     /**
26      * Liest die ihm übergebene Excel-Datei ein und erzeugt ein tabellarisches Abbild
27      * davon.
28      *
29      * @param excelFile Die einzulesene Excel-Datei
30      * @throws java.lang.ClassNotFoundException wenn eine Klasse nicht gefunden
31      * wurde
32      * @throws java.io.IOException wenn die Datei nicht eingelesen werde konnte
33      * @throws org.apache.poi.openxml4j.exceptions.InvalidFormatException wenn
34      * es Probleme mit dem Format der Datei oder der Verschlüsselung gibt
35      */
36     public ExcelFileReader(File excelFile) throws ClassNotFoundException, IOException, InvalidFormatException {
37         createWorkbook(excelFile);
38     }
39 
40     private void readHSSFWorkbook(File file) throws IOException {
41         POIFSFileSystem fs = new POIFSFileSystem(file);
42         workbook = new HSSFWorkbook(fs.getRoot(), true);
43         fs.close();
44     }
45 
46     private void readXSSFWorkbook(File file) throws InvalidFormatException, IOException {
47         OPCPackage pkg = OPCPackage.open(file);
48         workbook = new XSSFWorkbook(pkg);
49         pkg.close();
50     }
51 
52 }

Anschließend eine fügen wir die bereits im Konstruktor aufgerufene Methode, die die Dateitypen unterscheidet, unsere eben erstellten Methoden aufruft und damit das Workbook aus der übergebenen Datei (File erzeugt, ein.

 1     private void createWorkbook(File file) throws ClassNotFoundException, IOException, InvalidFormatException {
 2         String filename = file.getName().toLowerCase();
 3         try {
 4             if (filename.endsWith(".xls")) {
 5                 readHSSFWorkbook(file);
 6             } else if (filename.endsWith(".xlsx")) {
 7                 readXSSFWorkbook(file);
 8             } else {
 9                 throw new IllegalArgumentException("Ausnahmefehler: Die übergebene Datei " + file.getName() + " ist keine valide Microsoft Excel-Datei (*.xls bzw. *.xlsx)!");
10             }
11         } catch (IOException ioe) {
12             System.err.println(getClass().getName() + ": " + ioe);
13             throw new IOException("Ausnahmefehler: Die Datei " + file.getName() + " konnte nicht eingelesen werden!");
14         } catch (EncryptedDocumentException ede) {
15             System.err.println(getClass().getName() + ": " + ede);
16             throw new EncryptedDocumentException("Ausnahmefehler: Die Datei " + file.getName() + " ist mit einem Passwort geschützt und kann daher nicht geöffnet werden!");
17         } catch (NoClassDefFoundError err) {
18             System.err.println(getClass().getName() + ": " + err.toString());
19             throw new ClassNotFoundException("Schwerer Ausnahmefehler: Klassendefinition nicht gefunden!\nPrüfen Sie die Programmdateien und externen Bibliotheken auf Vollständigkeit!");
20         }
21     }

Damit haben wir den Code zum Öffnen und Einlesen von Excel-Dateien schon geschrieben.

Workbook auslesen

Eine Excel-Datei wird als Workbook bezeichnet und besteht aus mindestens einem Arbeitsblatt. Wir sprechen hier vom Interface Sheet. Ein Arbeitsblatt enthält wiederum Zellen, die in POI als Spalten in Zeilen organisiert sind und mit dem Interface Cell repräsentiert werden. Eine Zelle kann verschiedene Zelltypen haben, die in der Enumeration CellType aufgelistet sind.

Ein Arbeitsblatt besteht also aus Zeilen, über die in einer Schleife iteriert werden kann.

Workbook vollständig auslesen

In diesem Abschnitt schreiben wir uns den Code zum vollständigen Auslesen eines Arbeitsblattes einer Excel-Datei.

 1     /**
 2      * Gibt den Inhalt des übergebenen Tabellenblattes in einer Liste
 3      * die Listen mit Objekten speichert, zurück.
 4      *
 5      * @param sheetIndex der Index des Tabellenblattes
 6      * @return eine Liste aus Listen (Zeilen mit Spalten)
 7      */
 8     public List<List<?>> getSheetContent(int sheetIndex) {
 9         evaluator = workbook.getCreationHelper().createFormulaEvaluator();
10         Sheet sheet = workbook.getSheetAt(sheetIndex);
11         List<List<?>> sheetData = new ArrayList<>();
12 
13         for (Row row : sheet) {
14 
15             if (row != null) {
16                 List<Object> rowData = new ArrayList<>();
17                 boolean isEmptyRow = true; //Zeile erstmal als leer ansehen
18 
19                 for (Cell cell : row) {
20 
21                     if (cell != null) {
22 
23                         switch (cell.getCellType()) {
24                             case STRING:
25                                 String string = cell.getRichStringCellValue().getString();
26                                 if (string.isEmpty()) {
27                                     rowData.add(null);
28                                 } else {
29                                     rowData.add(string.trim());
30                                     isEmptyRow = false;
31                                 }
32                                 break;
33                             case NUMERIC:
34                                 if (DateUtil.isCellDateFormatted(cell)) {
35                                     Date date = cell.getDateCellValue();
36                                     if (date.toString().isEmpty()) {
37                                         rowData.add(null);
38                                     } else {
39                                         rowData.add(date);
40                                         isEmptyRow = false;
41                                     }
42                                 } else {
43                                     Number number = cell.getNumericCellValue();
44                                     if (number.toString().isEmpty()) {
45                                         rowData.add(null);
46                                     } else {
47                                         rowData.add(number);
48                                         isEmptyRow = false;
49                                     }
50                                 }
51                                 break;
52                             case BOOLEAN:
53                                 Boolean bool = (cell.getBooleanCellValue());
54                                 if (bool.toString().isEmpty()) {
55                                     rowData.add(null);
56                                 } else {
57                                     rowData.add(bool);
58                                     isEmptyRow = false;
59                                 }
60                                 break;
61                             case _NONE:
62                             case FORMULA:
63                             case BLANK:
64                             case ERROR:
65                             default:
66                                 rowData.add(null);
67                                 break;
68                         }
69                     } else {
70                         rowData.add(null);
71                     }
72                 }
73                 if (!isEmptyRow) { //leere Zeilen nicht aufnehmen
74                     sheetData.add(rowData);
75                 }
76             }
77         }
78         return sheetData;
79     }

Workbook teilweise auslesen

Baustelle.png Dieser Beitrag wird derzeit noch bearbeitet. Der Text ist deshalb unvollständig und kann Fehler oder ungeprüfte Aussagen enthalten.