Home ORDIX AG             Dienstleistung             Trainingsshop    Kunden / Referenzen Aktuelles    Kontakt
Home  Pfeil  ORDIX News  Pfeil  1/2008  Pfeil  Java/J2EE/JEE
suche: 
Dieser Artikel richtet sich vorwiegend an Java- Entwickler, die in ihren Projekten Excel-Dateien bearbeiten oder erstellen müssen.

Glossar

API
Application Programming Interface. Ein API ist eine Sammlung von Klassen, welche eine Schnittstelle zu einer Hardware oder Anwendung definieren.
Bibliothek
Archiv mit einer Sammlung von Klassen, die bestimmte Funktionalitäten bereitstellen und in andere Projekte integriert werden können.
Meta-Daten
Daten, die nicht zu den Nutzdaten gehören, sondern Informationen über die eigentlichen Nutzdaten beinhalten.
OOXML
Office Open XML. OOXML ist ein von der Firma Microsoft entwickeltes, auf XML basierendes Dateiformat für Office-Anwendungen.


Excel-Tools unter Java im Vergleich

JExcelAPI und Jakarta POI - David gegen Goliath?

Das Jakarta-Projekt POI ist sicherlich die bekannteste Bibliothek, die in der Lage ist, Dateien von Microsoft Office unter Java zu bearbeiten. Es existieren jedoch eine Reihe weiterer Bibliotheken, die mit Excel-Dateien umgehen können. Für diesen Artikel wurden das POI-Projekt [1] und die Bibliothek JExcelAPI [2] „in den Ring geschickt“, um gegeneinander anzutreten und ihre Unterschiede im Umgang mit Excel-Dateien herauszustellen.

In der rechten Ecke: Das JExcelAPI

Der Herausforderer in Form des JExcelAPI existiert zwar schon einige Jahre, hat aber bis heute noch nicht den Verbreitungsgrad seines Kontrahenten, dem Jakarta-Projekt POI erreicht. Im Gegensatz zum POI-Projekt, das im Zeitraum von 2004 bis 2007 kaum weiterentwickelt wurde, wurde JExcel in dieser Zeit kontinuierlich verbessert und zunehmend ausgereifter.

Mittlerweile bieten einige Projekte, die z. B. für einen Export bisher ausschließlich auf POI gesetzt haben, zusätzliche Schnittstellen für die JExcelAPI an. Als Beispiel sei hier Jasper-Report genannt, dessen Exportfunktion seit einiger Zeit nicht nur durch POI sondern auch durch JExcel realisiert werden kann.

Die Bibliothek steht aktuell in der im Oktober 2007 erschienenen Version 2.6.6 zur Verfügung [2].

In der linken Ecke: Das Jakarta POI-Projekt

Nun schauen wir auf den „Altmeister“ und fragen uns, wie ein Entwicklungsteam auf die Idee kommen kann, sein Projekt „Poor Obfuscation Implementation“ (zu deutsch in etwa „armselige, verwirrende Implementierung“) zu benennen. Der Name ist jedoch nicht auf das Projekt selbst, sondern vielmehr auf das den Office-Dateien zugrunde liegende OLE2-Dateiformat bezogen. POI stellt eine Java-Implementierung dieses von Microsoft definierten Formats dar und besteht aus mehreren Modulen.

Daher ist es mit Hilfe der POI-Bibliothek auch möglich, Microsoft Word-, Powerpoint-, Outlook- und Visio-Dateien zu bearbeiten. Dieser Artikel beschränkt sich jedoch auf das Modul HSSF (Horrible Spreadsheet Format, zu deutsch in etwa „furchtbares Arbeitsblattformat“) für die Bearbeitung von Excel-Dateien. Die aktuellste stabile Version 3.0.1 ist Mitte 2007 erschienen [3].

Funktionen des JExcelAPI

JExcel kann alle Excel-Dateien von der Version 97 bis 2003 interpretieren und Dateien erzeugen, die zu diesen Versionen kompatibel sind. Von Excel 2007 erstellte *.xlsx-Dateien, die auf dem OOXML-Dateiformat basieren, können allerdings von der JExcelAPI nicht interpretiert werden.

Einfache Bestandteile eines Excel-Sheets, wie z. B. Grafiken, Kommentare, viele Formeln, verschiedenen Zellen oder auch Datums- und Nummernformatierung, stellen für JExcel kein Problem dar. Seine Schwächen offenbart das Archiv vor allem beim Auslesen der Meta-Daten des OLE2-Dateiformates, sowie bei der Bearbeitung von Makros. Letztere kann JExcel zwar kopieren bzw. von einem in das andere Workbook-Objekt übertragen, erstellen oder bearbeiten kann es Makros jedoch nicht.

Die Projektseite bietet zwar ein FAQ und ein kleines Tutorial an, es wird dabei aber bei Weitem nicht der ganze Funktionsumfang dieser Bibliothek behandelt.

Im Allgemeinen ist die Verwendung der Funktionen sehr intuitiv, aber bei speziellen Problemen und Fragen, vor allem in der Einarbeitungszeit, ist gelegentlich doch etwas mehr Rechercheaufwand für die Problemlösung erforderlich.

Funktionen des POI

Das Apache-Projekt ist, genau wie JExcel, in der Lage, Dateien der Excel-Versionen 97 bis 2003 zu lesen und zu bearbeiten. Mit dem OOXML-Dateiformat der 2007er Version von Microsoft Excel kann jedoch das Jakarta POI ebenfalls nicht umgehen.

Mit den allermeisten Funktionalitäten aus Excel kommt POI sehr gut zurecht. Neben einfachen Datums-, Nummern- und Fließkommazellen oder auch Grafiken, Charts und Kommentaren unterstützt das Archiv sehr viele Excel-Formeln, ist in der Lage die Meta-Daten der Datei auszulesen und kann auch mit Makros umgehen.

Für einen umfangreichen Zugriff auf einzelne Elemente der Dateistruktur existiert ein Low Level-API, das einen sehr tiefgreifenden Einfluss auf die Datenstruktur erlaubt und vor allem für das Auslesen von Meta-Daten sehr hilfreich sein kann. Die meisten Funktionen des HSSF-Moduls sind sehr gut dokumentiert und die Projektseite der Apache-Group bietet viele Beispiele an. Dies hilft insbesondere in der Einarbeitungszeit, da manche Vorgehensweisen nicht sehr intuitiv sind.

Erstellen von Dateien mit dem JExcelAPI

Für das Erstellen einer Excel-Datei mit dem JExcelAPI wird zunächst ein WritableWorkbook-Objekt erstellt, das eine Excel-Mappe repräsentiert. Einem Workbook wird im Konstruktor das Ausgabe-Objekt (z. B. ein Outputstream oder ein File-Objekt) übergeben. Das WritableWorkbook kann mit Hilfe des WorkbookSettings-Objekts konfiguriert werden (siehe Abbildung 1).

// Erstellen und parametrisieren des Settings-Objektes
WorkbookSettings ws = new WorkbookSettings();
ws.setSuppressWarnings(false);
...
...
// Erstellen des Workbooks und des Sheets
WritableWorkbook workbook = Workbook.createWorkbook(new File(...));
WritableSheet sheet = workbook.createSheet("Name des Sheets", nSheetIndex);
// Erstellen eines Zellenformats
WritableFont fontUeberschrift = new WritableFont(WritableFont.ARIAL, 12, WritableFont.BOLD);
WritableCellFormat formatUeberschrift = new WritableCellFormat (fontUeberschrift);
// Erstellen einer Zelle
sheet.addCell(new Label(0, 0, "Ueberschrift Spalte 1", formatUeberschrift));
...
// Daten rausschreiben
workbook.write();
workbook.close();
Abb. 1: Erzeugen eines neuen Excel-Files mit dem JExcelAPI.

Über eine createSheet-Methode können dann einzelne Arbeitsblätter (Sheets) erzeugt werden. Diesen wiederum kann man dann über die addCell-Methode beliebig viele Zellen hinzufügen. Der addCell-Methode wird hierfür ein Objekt des Interface-Typs WritableCell übergeben, das Angaben über seine Position, seinen Inhalt und seine Formatierung enthält.

Es existieren mehrere Implementierungen des Interfaces WritableCell. Die wichtigsten sind Boolean, Number, Label und DateTime, die in der Lage sind, die entsprechenden Java-Datentypen in einer Excel-Zelle darzustellen und gegebenenfalls Ausgabeformatierungen auf sie anzuwenden. Eine weitere, wichtige Implementierung dieses Interfaces ist die Klasse Formula, die es ermöglicht, eine Formelzelle zu definieren, in der eine Excel-Funktion enthalten ist [z. B. „Summe(A1:A8)“].

Die Formatierung der Zelle wird dabei über ein WritableCellFormat definiert. Da lediglich eine begrenzte Anzahl von Zellenformaten gleichzeitig verwaltet werden kann, kann es zu Problemen kommen, wenn innerhalb eines Dokuments zu viele WritableCellFormat-Objekte erstellt werden. In diesem Falle werden die Zellen, die nach Erreichen der Höchstzahl dargestellt werden, ohne Formatierung ausgegeben.

Erstellen von Dateien mit der Jakarta POI

Genau wie JExcel kennt auch POI Objekt-Repräsentationen einer Excel-Mappe, eines Arbeitsblattes und einer Zelle in Form eines HSSFWorkbook-, eines HSSFSheet- und eines HSSFCell-Objektes (siehe Abbildung 2).

// Erstellen eines neuen Workbooks und eines Sheets
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet("Test-Sheet");
// Erstellen einer neuen Zeile
HSSFRow row = sheet.createRow(0);
// Erstellen eines neuen Zellenformates
HSSFFont fontUeberschrift = workbook.createFont();
fontUeberschrift.setFontName(HSSFFont.FONT_ARIAL);
HSSFCellStyle cellStyleUeberschrift = workbook.createCellStyle();
// Erstellen einer neuen Zelle
Cell cell = row.createCell((short)0);
cell.setCellValue(new HSSFRichTextString("Ueberschrift Spalte 1"));
cell.setCellStyle(cellStyleUeberschrift);
cellStyleUeberschrift.setFont(fontUeberschrift);
// Erstellen des Outputs
FileOutputStream out = new FileOutputStream(new File(....));
// Herausschreiben der Daten
workbook.write(out);
out.close();
Abb. 2: Erzeugen eines neuen Excel-Files mit der POI-Bibliothek.

Im Gegensatz zum JExcelAPI besteht jedoch nicht die Möglichkeit, Zellen direkt einer Position im Sheet zuzuweisen. Für jede Zeile, die über eine oder mehrere Zellen verfügen soll, ist zunächst die Erzeugung eines HSSFRow-Objektes notwendig. Dieses stellt wiederum Methoden bereit, um Zellen an einer bestimmten Spaltenposition der Zeile zu erstellen.

Die Position, der Inhalt und die Formatierung der Zelle werden im Gegensatz zum JExcel API jedoch nicht in einem separaten Objekt gehalten, sondern direkt dem Cell-Objekt übergeben. Die Methode setCellValue kann dabei mit verschiedenen Übergabeparametern, z. B. einem boolean-Wert, einem double-Wert oder einem Date-Objekt aufgerufen werden. Um eine Formelzelle zu erzeugen, stellt das Cell-Objekt die Methode setCellFormula bereit.

Einlesen von Dateien mit dem JExcelAPI

Das Einlesen von bestehenden Excel-Dateien gestaltet sich mit Hilfe des JExcelAPI recht einfach. Neben dem WritableWorkbook stellt das Archiv auch ein einfaches Workbook-Objekt bereit, dessen Konstruktor einer bereits bestehenden Excel-Datei übergeben werden kann. Über entsprechende getter-Methoden kann man dann auf die einzelnen Elemente, bis hin zu den einzelnen Zellen, zugreifen und diese auslesen. Über die getType-Methode des Cell-Objektes lässt sich der Typ des Inhalts bestimmen und anschließend in den spezifischen Cell-Type umwandeln. Dieser stellt dann entsprechende Methoden bereit, um den Zelleninhalt auszulesen.

Das Workbook kann entweder über eine statische Methode direkt erstellt oder über das WorkbookParser-Objekt geholt werden, das neben dem Workbook auch aus dem Dokument ausgelesene Meta-Informationen bereitstellt. Ein einfaches Beispiel für das Einlesen einer Excel-Datei mit Hilfe der JExcelAPI ist in dem Beispielprojekt zu diesem Artikel [5] enthalten.

Einlesen von Dateien mit dem POI-Archiv

Das Lesen oder Bearbeiten von Excel-Dateien kann über das HSSF-Modul ähnlich umgesetzt werden wie mittels JExcel. Das UserAPI bietet auch hier über entsprechende getter-Methoden Zugriff auf die einzelnen Bestandteile, wie Sheets, Rows oder Cells. Diese können entfernt, geändert oder durch andere Objekte ersetzt werden.

Für performanten Nur-Lesezugriff kann jedoch auch die EventAPI verwendet werden. Diese beinhaltet als zentrale Komponenten die HSSFEventFactory und das Interface HSSFListener. Die EventFactory durchläuft das Dokument und die Implementierung des HSSFListener wird während des Parsens über jeden neu gefundenen Eintrag informiert. Die EventFactory kann dann auf die verschiedenen Einträge entsprechend reagieren und sie auslesen. Ein einfaches Beispiel hierzu finden Sie unter [5].

Fazit

Der Funktionsumfang des POI-Projektes ist deutlich größer als der der JExcelAPI. Aber auch die Möglichkeiten der JExcelAPI reichen für die Erstellung einfacher Excel-Mappen und das Auslesen von Daten aus einer Excel-Datei in aller Regel aus. Letztere zeichnet sich dafür zusätzlich durch eine sehr leichte Einarbeitung und eine sehr leicht nachvollziehbare Programmstruktur aus.

Aus Programmierersicht lassen sich viele Anforderungen mit der JExcelAPI einfacher realisieren. Die Handhabung des POI-Projektes wirkt an manchen Stellen etwas altbacken, so z. B. die Verwendung von short- statt int- Werten, was oftmals eine Datentypumwandlung selbst von Konstanten erfordert. Müssen jedoch Meta-Informationen ausgelesen oder sehr spezifische Anforderungen umgesetzt werden, ist man mit der POI-Bibliothek sicherlich besser bedient.

Um einen kleinen Eindruck in die Arbeitsweise und den Umgang mit den beiden Archiven beim Lesen bzw. Schreiben von Excel-Dateien zu erhalten, finden Sie unter [5] ein kleines Beispielprojekt zum Herunterladen. Es steht als Netbeans- und als Eclipse-Projekt zur Verfügung. Es ist in der Lage, eine einfache Excel-Datei zu erzeugen und Daten einer einfachen Excel-Datei auszulesen. Beides wird jeweils mit den beiden vorgestellten Excel-Archiven umgesetzt.

Lesen Sie hierzu auch die übersichtliche Zusammenfassung in unserem Expertencheck!

Alexander Zeller (info@ordix.de).