Apache POI - Excel-Datei einlesen: Unterschied zwischen den Versionen

Aus Byte-Welt Wiki
KKeine Bearbeitungszusammenfassung
Keine Bearbeitungszusammenfassung
Zeile 2: Zeile 2:
Mit dem Java-[[Framework]] Apache POI kann man recht komfortabel Microsoft Excel-Dateien auslesen und erzeugen (schreiben).
Mit dem Java-[[Framework]] Apache POI kann man recht komfortabel Microsoft 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 .
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:
 
*[https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 (Original)]
*[https://www.moo.com/de/about/fonts/apache-licence Apache License 2.0 (Deutsche Übersetzung)]


==Excel-Datei einlesen==
==Excel-Datei einlesen==
Wir schreiben uns zunächst eine [[Klasse]], die zwei private [[Methoden]] implementiert, die die beiden Dateitypen separat verarbeiten:
 
<syntaxhighlight lang="java" line="true">
<syntaxhighlight lang="java" line="true">
/*
* 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.EncryptedDocumentException;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
Zeile 23: Zeile 67:


/**
/**
  * ExcelFileReader liest die Excel-Datei ein und erzeugt ein tabellarisches
  * ExcelFileProxy liest die Excel-Datei ein und erzeugt ein tabellarisches
  * Abbild der Arbeitsmappe in Form von verschachtelten Listen.
  * Abbild der Arbeitsmappe in Form von verschachtelten Listen.
  *
  *
  * @author Gernot Segieth
  * @author Gernot Segieth
  */
  */
public class ExcelFileReader {
public class ExcelFileProxy {
     private Workbook workbook
 
    private File excelFile;
     private Workbook workbook;
    private FormulaEvaluator evaluator;
    private boolean isEmptyRow;


     /**
     /**
     * Liest die ihm übergebene Excel-Datei ein und erzeugt ein tabellarisches Abbild
     * Erzeugt einen neuen Excel-Datei-Stellvertreter. ExcelFileProxy liest die
    * ihm übergebene Excel-Datei ein und erzeugt ein tabellarisches Abbild
     * davon.
     * davon.
     *
     *
Zeile 42: Zeile 91:
     * es Probleme mit dem Format der Datei oder der Verschlüsselung gibt
     * es Probleme mit dem Format der Datei oder der Verschlüsselung gibt
     */
     */
     public ExcelFileReader(File excelFile) throws ClassNotFoundException, IOException, InvalidFormatException {
     public ExcelFileProxy(File excelFile) throws ClassNotFoundException, IOException, InvalidFormatException {
        this.excelFile = excelFile;
         createWorkbook(excelFile);
         createWorkbook(excelFile);
     }
     }


     private void readHSSFWorkbook(File file) throws IOException {
     /**
         POIFSFileSystem fs = new POIFSFileSystem(file);
    * Gibt den Inhalt des übergebenen Tabellenblattes in einer geschachtelten
         workbook = new HSSFWorkbook(fs.getRoot(), true);
    * Liste zurück.
         fs.close();
    *
    * @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();
     }
     }


     private void readXSSFWorkbook(File file) throws InvalidFormatException, IOException {
     /**
         OPCPackage pkg = OPCPackage.open(file);
    * Liest das Workbook der Excel-Datei neu ein.
        workbook = new XSSFWorkbook(pkg);
    *
        pkg.close();
    * @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 {
</syntaxhighlight>
        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);
    }


Anschließend fügen wir die bereits im Konstruktor aufgerufene [[Methode]], die die Dateitypen unterscheidet, unsere eben erstellten Methoden aufruft und damit das <code>Workbook</code> aus der übergebenen Datei ({{JAPI|File}} erzeugt, ein.
    //erzeugt ein Workbook aus der übergebenen Excel-Datei
<syntaxhighlight lang="java" line="true">
     private void createWorkbook(File file) throws ClassNotFoundException, IOException, InvalidFormatException {
     private void createWorkbook(File file) throws ClassNotFoundException, IOException, InvalidFormatException {
         String filename = file.getName().toLowerCase();
         String filename = file.getName().toLowerCase();
Zeile 68: Zeile 311:
             if (filename.endsWith(".xls")) {
             if (filename.endsWith(".xls")) {
                 readHSSFWorkbook(file);
                 readHSSFWorkbook(file);
                //workbook = WorkbookFactory.create(file);
             } else if (filename.endsWith(".xlsx")) {
             } else if (filename.endsWith(".xlsx")) {
                 readXSSFWorkbook(file);
                 readXSSFWorkbook(file);
Zeile 74: Zeile 318:
             }
             }
         } catch (IOException ioe) {
         } catch (IOException ioe) {
             System.err.println(getClass().getName() + ": " + ioe);
             Logger.getLogger(ExcelFileProxy.class.getName()).log(Level.SEVERE, null, ioe);
             throw new IOException("Ausnahmefehler: Die Datei " + file.getName() + " konnte nicht eingelesen werden!");
             throw new IOException("Ausnahmefehler: Die Datei " + file.getName() + " konnte nicht eingelesen werden!");
         } catch (EncryptedDocumentException ede) {
         } catch (EncryptedDocumentException ede) {
             System.err.println(getClass().getName() + ": " + 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!");
             throw new EncryptedDocumentException("Ausnahmefehler: Die Datei " + file.getName() + " ist mit einem Passwort geschützt und kann daher nicht geöffnet werden!");
         } catch (NoClassDefFoundError err) {
         } catch (NoClassDefFoundError err) {
             System.err.println(getClass().getName() + ": " + err.toString());
             System.err.println(err.toString());
             throw new ClassNotFoundException("Schwerer Ausnahmefehler: Klassendefinition nicht gefunden!\nPrüfen Sie die Programmdateien und externen Bibliotheken auf Vollständigkeit!");
             throw new ClassNotFoundException("Schwerer Ausnahmefehler: Klassendefinition nicht gefunden!\nPrüfen Sie die Programmdateien und externen Bibliotheken auf Vollständigkeit!");
         }
         }
     }
     }
</syntaxhighlight>


Damit haben wir den Code zum Öffnen und Einlesen von Excel-Dateien schon geschrieben.
    private void readHSSFWorkbook(File file) throws IOException {
        POIFSFileSystem fs = new POIFSFileSystem(file);
        workbook = new HSSFWorkbook(fs.getRoot(), true);
        fs.close();
    }


==Workbook auslesen==
    private void readXSSFWorkbook(File file) throws InvalidFormatException, IOException {
Eine Excel-Datei wird als <code>Workbook</code> bezeichnet und besteht aus mindestens einem Arbeitsblatt. Wir sprechen hier vom [[Interface]] <code>Sheet</code>. Ein Arbeitsblatt enthält wiederum Zellen, die in POI als Spalten in Zeilen organisiert sind und mit dem Interface <code>Cell</code> repräsentiert werden. Eine Zelle kann verschiedene Zelltypen haben, die in der Enumeration <code>CellType</code> aufgelistet sind.
        OPCPackage pkg = OPCPackage.open(file);
        workbook = new XSSFWorkbook(pkg);
        pkg.close();
    }


Ein Arbeitsblatt besteht also aus Zeilen, über die in einer Schleife iteriert werden kann.
    //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!");
        }
    }


===Workbook vollständig auslesen===
     //Liest die Daten aus einer Zelle und gibt sie zurück.
In diesem Abschnitt schreiben wir uns den Code zum vollständigen Auslesen '''eines''' Arbeitsblattes einer Excel-Datei.
     private Object getData(Cell cell) {
<syntaxhighlight lang="java" line="true">
         if (cell != null) {
     /**
    * Gibt den Inhalt des übergebenen Tabellenblattes in einer Liste
    * die Listen mit Objekten speichert, 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();
        Sheet sheet = workbook.getSheetAt(sheetIndex);
        List<List<?>> sheetData = new ArrayList<>();


        for (Row row : sheet) {
            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;
                        }
                    }


            if (row != null) {
                 case BOOLEAN:
                List<Object> rowData = new ArrayList<>();
                    Boolean bool = (cell.getBooleanCellValue());
                boolean isEmptyRow = true; //Zeile erstmal als leer ansehen
                    if (bool.toString().isEmpty()) {
 
                        return null;
                 for (Cell cell : row) {
 
                    if (cell != null) {
 
                        switch (cell.getCellType()) {
                            case STRING:
                                String string = cell.getRichStringCellValue().getString();
                                if (string.isEmpty()) {
                                    rowData.add(null);
                                } else {
                                    rowData.add(string.trim());
                                    isEmptyRow = false;
                                }
                                break;
                            case NUMERIC:
                                if (DateUtil.isCellDateFormatted(cell)) {
                                    Date date = cell.getDateCellValue();
                                    if (date.toString().isEmpty()) {
                                        rowData.add(null);
                                    } else {
                                        rowData.add(date);
                                        isEmptyRow = false;
                                    }
                                } else {
                                    Number number = cell.getNumericCellValue();
                                    if (number.toString().isEmpty()) {
                                        rowData.add(null);
                                    } else {
                                        rowData.add(number);
                                        isEmptyRow = false;
                                    }
                                }
                                break;
                            case BOOLEAN:
                                Boolean bool = (cell.getBooleanCellValue());
                                if (bool.toString().isEmpty()) {
                                    rowData.add(null);
                                } else {
                                    rowData.add(bool);
                                    isEmptyRow = false;
                                }
                                break;
                            case _NONE:
                            case FORMULA:
                            case BLANK:
                            case ERROR:
                            default:
                                rowData.add(null);
                                break;
                        }
                     } else {
                     } else {
                         rowData.add(null);
                         isEmptyRow = false;
                        return bool;
                     }
                     }
                 }
 
                 if (!isEmptyRow) { //leere Zeilen nicht aufnehmen
                 case _NONE:
                     sheetData.add(rowData);
                 case FORMULA:
                }
                case BLANK:
                case ERROR:
                default:
                     return null;
             }
             }
        } else {
            return null;
         }
         }
        return sheetData;
     }
     }
}
</syntaxhighlight>
</syntaxhighlight>


===Workbook teilweise auslesen===
==Beispiel-Code für die Benutzung dieser Klasse==
 
==Erläuterungen zum Code==


{{In Arbeit}}
{{In Arbeit}}

Version vom 25. Juni 2019, 14:49 Uhr

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.