# xlsx-Datei mit Apache POI einlesen



## reutila (3. Mai 2018)

Hallo liebe Community,

ich möchte gerne eine xlsx-Datei in Java einlesen.
Für jede Zeile soll ein neues Objekt "Schueler" angelegt werden,
wobei die einzelnen Zellen als Attribute diesem Objekt zugeodnert werden soll.
Alle Schueler Objekte sollen schließlich in einer Liste gespeichert werden.

Die Exceltabelle ist wie folgt aufgebaut:
1   |  Klasse 1 | Musterfrau | Eva
2   |  Klasse 2 | Mustermann | Max
Die erste Spalte ist hierbei eine Id.
Die erste Spalte ist in der xlsx-Datei als Standard formatiert.
Wenn ich diese Spalte in Java als Double einlesen möchte, dann funktioniert dies auch.
Allerdings funktioniert es nicht, wenn ich sie als Integer einlesen möchte.

Kann mir jemand von euch sagen was ich falsch mache und es mir bitte richtig programmieren?

Mein Code für die Klasse Schueler

```
package calc;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.*;

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;

public class Schueler {

    private double id;
    private String name;
    private String vorname;
    private String klasse;

    public double getId() {
        return id;
    }

    public void setId(double d) {
        this.id = d;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getVorname() {
        return vorname;
    }

    public void setVorname(String vorname) {
        this.vorname = vorname;
    }

    public String getKlasse() {
        return klasse;
    }

    public void setKlasse(String klasse) {
        this.klasse = klasse;
    }

    public Date getGeburtstag() {
        return geburtstag;
    }

    public void setGeburtstag(Date geburtstag) {
        this.geburtstag = geburtstag;
    }

    public String getBerechtigt() {
        return berechtigt;
    }

    public void setBerechtigt(String berechtigt) {
        this.berechtigt = berechtigt;
    }

    public Schueler(int id, String name, String vorname) {
        super();
        this.id = id;
        this.name = name;
        this.vorname = vorname;
        //this.geburtstag = geburtstag;
        //this.berechtigt = berechtigt;
    }

    public Schueler() {
        super();
    }

    public String toString() {
        return "Schueler [id=" + id + ", name=" + name + ", vorname=" + vorname + "]";
    }

    private Object getCellValue(Cell cell) {
        switch (cell.getCellType()) {
        case Cell.CELL_TYPE_STRING:
            return cell.getStringCellValue();

        case Cell.CELL_TYPE_BOOLEAN:
            return cell.getBooleanCellValue();

        case Cell.CELL_TYPE_NUMERIC:
            return cell.getNumericCellValue();
        }

        return null;
    }

    public List<Schueler> readSchuelersFromExcelFile(String excelFilePath) throws IOException {
        List<Schueler> listSchuelers = new ArrayList<>();
        FileInputStream inputStream = new FileInputStream(new File(excelFilePath));

        Workbook workSchueler = new XSSFWorkbook(inputStream);
        Sheet firstSheet = workSchueler.getSheetAt(0);
        Iterator<Row> iterator = firstSheet.iterator();

        while (iterator.hasNext()) {
            Row nextRow = iterator.next();
            Iterator<Cell> cellIterator = nextRow.cellIterator();
            Schueler aSchueler = new Schueler();

            while (cellIterator.hasNext()) {
                Cell nextCell = cellIterator.next();
                int columnIndex = nextCell.getColumnIndex();

                switch (columnIndex) {
                case 0:
                    aSchueler.setId((double) getCellValue(nextCell));
                    break;
                case 1:
                    aSchueler.setKlasse((String) getCellValue(nextCell));
                case 2:
                    aSchueler.setName((String) getCellValue(nextCell));
                    break;
                case 3:
                    aSchueler.setVorname((String) getCellValue(nextCell));
                    break;
                }

            }
            listSchuelers.add(aSchueler);
        }

        workSchueler.close();
        inputStream.close();

        return listSchuelers;
    }

}
```

Meine Testklasse hat folgenden Code:

```
package gui;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.*;

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;

import calc.Schueler;

public class Test {

    public static void main(String[] args) throws IOException{
        String excelFilePath = "A://SchuelerListeTest.xlsx";
        Schueler reader = new Schueler();
        List<Schueler> listBooks = reader.readSchuelersFromExcelFile(excelFilePath);
        System.out.println(listBooks);

    }

}
```

In der angefügten zip-Datei findet ihr die xlsx-Datei, die Klasse Schueler und eine Test-Main-Klasse.  Das Attribut id ist in der Klasse Schueler noch als double deklariert.
Die einzelnen jar files kann man auf der Apache Webseite downloaden.

P.S.: die beiden Attribute geburtstag und berechtigt in der Klasse Schueler sollen erst später umgesetzt werden.


----------



## VfL_Freak (3. Mai 2018)

Moin,


reutila hat gesagt.:


> Wenn ich diese Spalte in Java als Double einlesen möchte, dann funktioniert dies auch.
> Allerdings funktioniert es nicht, wenn ich sie als Integer einlesen möchte.


was heißt das konkret?
Fehlermeldung? StackTrace?

VG Klaus


----------



## reutila (3. Mai 2018)

Hallo Klaus,

danke für deine Nachricht.
Erstens:
ich habe einen Denkfehler gemacht.
Die Id ist mir egal, da jedes Schueler-Objekt in der Liste über .get() angesprochen werden kann.

nun habe ich aber ein anderes Problem:
Ich habe in der xlsx-Datei eine weitere Spalte mit Geburtstagsdatum stehen,
diese sollen auch über die POI eingelesen werden.

Der Code für die Klasse schueler sieht nun wie folgt aus:

```
package calc;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;

public class Schueler2 {

    private String name;
    private String vorname;
    private String klasse;
    private Date geburtstag;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getVorname() {
        return vorname;
    }

    public void setVorname(String vorname) {
        this.vorname = vorname;
    }

    public String getKlasse() {
        return klasse;
    }

    public void setKlasse(String klasse) {
        this.klasse = klasse;
    }

    public Date getGeburtstag() {
        return geburtstag;
    }

    public void setGeburtstag(Date geburtstag) {
        this.geburtstag = geburtstag;
    }

    public Schueler2(String name, String vorname, String klasse, Date geburtstag) {
        super();
        this.name = name;
        this.vorname = vorname;
        this.klasse = klasse;
        this.geburtstag = geburtstag;
    }

    public Schueler2() {
        super();
    }

    public String toString() {
        return "Schueler [klasse=" + klasse + ", name=" + name + ", vorname=" + vorname + ", geb=" + geburtstag + "]";
    }

    private Object getCellValue(Cell cell) {
        switch (cell.getCellType()) {
        case Cell.CELL_TYPE_STRING:
            return cell.getStringCellValue();

        case Cell.CELL_TYPE_BOOLEAN:
            return cell.getBooleanCellValue();

        case Cell.CELL_TYPE_NUMERIC:
            if (DateUtil.isCellDateFormatted(cell)) {
                SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
                cell.getDateCellValue();
            } else {
                return cell.getNumericCellValue();
            }
        }

        return null;
    }

    public List<Schueler2> readSchuelersFromExcelFile(String excelFilePath) throws IOException {
        List<Schueler2> listSchueler2 = new ArrayList<>();
        FileInputStream inputStream = new FileInputStream(new File(excelFilePath));

        Workbook workSchueler = new XSSFWorkbook(inputStream);
        Sheet firstSheet = workSchueler.getSheetAt(0);
        Iterator<Row> iterator = firstSheet.iterator();

        while (iterator.hasNext()) {
            Row nextRow = iterator.next();
            Iterator<Cell> cellIterator = nextRow.cellIterator();
            Schueler2 aSchueler = new Schueler2();

            while (cellIterator.hasNext()) {
                Cell nextCell = cellIterator.next();
                int columnIndex = nextCell.getColumnIndex();

                switch (columnIndex) {
                case 0:
                    aSchueler.setKlasse((String) getCellValue(nextCell));
                case 1:
                    aSchueler.setName((String) getCellValue(nextCell));
                    break;
                case 2:
                    aSchueler.setVorname((String) getCellValue(nextCell));
                    break;
                case 3:
                    aSchueler.setGeburtstag((Date) getCellValue(nextCell));
                    break;
                }

            }
            listSchueler2.add(aSchueler);
        }

        workSchueler.close();
        inputStream.close();

        return listSchueler2;
    }

}
```

und meine Testklasse wie folgt:

```
package calc;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.*;

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;

import calc.Schueler2;

public class Test2 {

    public static void main(String[] args) throws IOException {
        String excelFilePath = "A://SchuelerListeTest.xlsx";
        Schueler2 reader = new Schueler2();
        List<Schueler2> listSchueler = reader.readSchuelersFromExcelFile(excelFilePath);
        System.out.println(listSchueler);
        System.out.println("Anzahl der Elemente: " + listSchueler.size());
        System.out.println("erste Element aus der liste" + listSchueler.get(0));

        Random r = new Random();
        int i = r.nextInt(listSchueler.size());
        System.out.println("Position " + i + " gehört Schüler: " + listSchueler.get(i));
      
        int j = r.nextInt(listSchueler.size());
        System.out.println("Position " + j + " gehört Schüler: " + listSchueler.get(j));

    }

}
```

Nun wird folgender Fehler ausgegeben:

```
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.apache.poi.openxml4j.util.ZipSecureFile$1 (file:/A:/01%20Schule/Schuljahr%202017_2018/EclipseArbeitsbereich/Programme/Gluecksspiel/lib/poi-ooxml-3.17.jar) to field java.io.FilterInputStream.in
WARNING: Please consider reporting this to the maintainers of org.apache.poi.openxml4j.util.ZipSecureFile$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
Exception in thread "main" java.lang.ClassCastException: java.base/java.lang.String cannot be cast to java.base/java.util.Date
   at calc.Schueler2.readSchuelersFromExcelFile(Schueler2.java:114)
   at calc.Test2.main(Test2.java:18)
```

In Anlage2 findet man die relevanten Dateien dazu.


----------



## VfL_Freak (3. Mai 2018)

Moin,
also ...
Wie da schon steht, ist Dein Fehler, dass Du einen _String _nicht einfach nach _Date _casten kannst!

Die Exception fliegt hier :


> at calc.Schueler2.readSchuelersFromExcelFile(Schueler2.java:114)


ich weiß aber nicht wie dieser Code ausschaut !

BTW: unbekannte Anlagen öffne ich NIE !!
Poste den entsprechenden Code hier!!

VG Klaus


----------



## reutila (3. Mai 2018)

Hallo Klaus, 

der Code habe ich gepostet. s.o.
in Zeile 114 steht folgender Code:

```
aSchueler.setGeburtstag((Date) getCellValue(nextCell));
```

Danke


----------



## VfL_Freak (3. Mai 2018)

Moin,

ok, ich gehe mal davon aus, dass Dir das *getCellValue* einen String liefert, richtig?
Und den versuchst Du dann stumpf zu *Date *zu casten, was aber, wie gesagt nicht geht !!
Du musst Dir dafür vermutlich ein eigene Konvertierungsfunktion schreiben ...

Was genau steht denn in der Zelle?
Eventuell hilft Dir auch der _SimpleDateFormatter _weiter:
https://docs.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html

VG Klaus


----------



## reutila (3. Mai 2018)

Hallo Klaus,

den SimpleDateFormatter habe ich schon verwendet s.o.
hier nochmal die Umsetzung:

```
private Object getCellValue(Cell cell) {
        switch (cell.getCellType()) {
        case Cell.CELL_TYPE_STRING:
            return cell.getStringCellValue();

        case Cell.CELL_TYPE_BOOLEAN:
            return cell.getBooleanCellValue();

        case Cell.CELL_TYPE_NUMERIC:
            if (DateUtil.isCellDateFormatted(cell)) {
                SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
                cell.getDateCellValue();
            } else {
                return cell.getNumericCellValue();
            }
        }

        return null;
    }

    public List<Schueler2> readSchuelersFromExcelFile(String excelFilePath) throws IOException {
        List<Schueler2> listSchueler2 = new ArrayList<>();
        FileInputStream inputStream = new FileInputStream(new File(excelFilePath));

        Workbook workSchueler = new XSSFWorkbook(inputStream);
        Sheet firstSheet = workSchueler.getSheetAt(0);
        Iterator<Row> iterator = firstSheet.iterator();

        while (iterator.hasNext()) {
            Row nextRow = iterator.next();
            Iterator<Cell> cellIterator = nextRow.cellIterator();
            Schueler2 aSchueler = new Schueler2();

            while (cellIterator.hasNext()) {
                Cell nextCell = cellIterator.next();
                int columnIndex = nextCell.getColumnIndex();

                switch (columnIndex) {
                case 0:
                    aSchueler.setKlasse((String) getCellValue(nextCell));
                case 1:
                    aSchueler.setName((String) getCellValue(nextCell));
                    break;
                case 2:
                    aSchueler.setVorname((String) getCellValue(nextCell));
                    break;
                case 3:
                    aSchueler.setGeburtstag((Date) getCellValue(nextCell));
                    break;
                }

            }
            listSchueler2.add(aSchueler);
        }

        workSchueler.close();
        inputStream.close();

        return listSchueler2;
    }
```

In der Zelle steht ein Datum
habe darauf geachtet, dass das Format auch stimmt, siehe Bild

Hast du noch andere Ideen??


----------



## VfL_Freak (3. Mai 2018)

reutila hat gesagt.:


> Hast du noch andere Ideen??


na ja ... in dem Fall findest Du doch im Web etliche Lösungen 
https://www.google.com/search?q=jav...yyyy+mm+dd&ie=utf-8&oe=utf-8&client=firefox-b

VG Klaus


----------



## reutila (3. Mai 2018)

die Lösungen habe ich auch schon gefunden, bringen mich allerdings leider nicht weiter.
Kannst du mir bitte die nötige Änderung in meinem Quellcode sagen?!

Vielen Dank


----------



## fhoffmann (3. Mai 2018)

Fang doch mal an mit:

```
case 3:
    String geb = (String)getCellValue(nextCell);
    System.out.println(geb);
```


----------



## VfL_Freak (3. Mai 2018)

Moin,
nochmal: Du kannst einen _String _*NICHT* in ein _Date _casten !!!


reutila hat gesagt.:


> aSchueler.setGeburtstag( (Date) getCellValue(nextCell) );


Du musst den Wert dann hier mit einem SimpleDateFormatter entsprechend umwandeln!!
Du hast oben zwar eine deklariert, anwenden tust Du ihn aber nicht!!

Was bringt Dich denn an den Links nicht weiter?
Gleich im ersten Ergebnis von stackoverflow ist es doch hinreichend erklärt!!!


> SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
> Date convertedCurrentDate = sdf.parse("2013-09-18");
> String date=sdf.format(convertedCurrentDate );
> System.out.println(date);


Ein bisschen Eigeninitiative wäre schon nicht schlecht   

VG Klaus


----------



## reutila (3. Mai 2018)

Danke für die Antworten:
mich hat folgendes weiter gebracht:

```
case 3:
                    String geb = (String) getCellValue(nextCell);
                    try {
                        SimpleDateFormat sdf = new SimpleDateFormat("DD.MM.YYYY");
                        Date date1 = sdf.parse(geb);
                        aSchueler.setGeburtstag(date1);
                    } catch (ParseException ex2) {
                        ex2.printStackTrace();
                    }
                    break;
```

Auf der Konsole wird mir nun folgendes als Beispiel ausgegeben:
[klasse=Klasse 1, name=Max, vorname=Köhler, geb=Mon Dec 29 00:00:00 CET 1997]
Was muss ich tun, dass folgendes ausgegeben wird:
[klasse=Klasse 1, name=Max, vorname=Köhler, geb=29.12.1997]


----------



## reutila (3. Mai 2018)

Ich habs....
es lag an meiner toString-Methode

Danke für eure Geduld


----------



## VfL_Freak (3. Mai 2018)

reutila hat gesagt.:


> es lag an meiner toString-Methode


Welche 'toString-Methode' ???

Dann poste bitte auch die Lösung, damit andere User, die vlt. auf diesen thread stossen, etwas davon haben!

Danke und VG
Klaus


----------



## reutila (3. Mai 2018)

In meiner Schueler-Klasse:

```
public String toString() {
        return "Schueler [klasse=" + klasse + ", name=" + name + ", vorname=" + vorname + ", geb="
                + geburtstag.getDate() + "." + geburtstag.getMonth() + "." + geburtstag.getYear() + "]";
    }
```


----------



## reutila (3. Mai 2018)

noch eine Frage:
Warum gibt er mir das Jahr bei der Ausgabe mit 96 (für 1996) oder 103 (für 2003) aus?


----------



## fhoffmann (3. Mai 2018)

reutila hat gesagt.:


> Warum gibt er mir das Jahr bei der Ausgabe mit 96 (für 1996) oder 103 (für 2003) aus?


Gucke doch selbst in die Beschreibung der Klasse java.util.Date
https://docs.oracle.com/javase/8/docs/api/


----------



## reutila (3. Mai 2018)

habe es gefunden...
die ziehen immer 1900 vom Datum ab.
Danke


----------



## mrBrown (3. Mai 2018)

Du kannst dir mal LocalDate-Klasse angucken, die ist dafür deutlich besser geeignet


----------

