Suche
Kaffee in Zellen

MS-Office-Dokumente mit Apache POI erzeugen – so geht’s!

Andreas Monschau

© Shutterstock / Peerayot

Allen Alternativen zum Trotz werden in der großen und weiten Unternehmenswelt Daten, Dokumente und Dateien mit Microsoft Office erstellt, gespeichert, bearbeitet und ausgetauscht. Seien es nun lange Texte und Analysen als Word-Dokument, PowerPoint-Präsentationen oder ver-Excelte Zahlen und Datenkolonnen. Gerade Excel dient oft als Quelle für weitere Analysen oder Statistik. Apache POI ist eine Java-Bibliothek, die dem Entwickler hilft, Daten in MS-Office-Dokumente zu schreiben, Dokumente zu bearbeiten oder auszulesen.

Ein kurzer Meinungsaustausch im Kollegenkreis während einer internen Weiterbildung ergab, dass Apache POI eine scheinbar eher ungeliebte Bibliothek ist. Ist das wirklich der Fall, oder ist es an der Zeit, eine Lanze dafür zu brechen? Bei Apache POI handelt es sich um ein Apache-Top-Level-Projekt. Auf der Projektseite wird das Missionsziel der Bibliothek passend beschrieben mit der Bereitstellung eines Java APIs zwecks Manipulation verschiedener, auf dem Office-Open-XML-Standard (OOXML) und OLE2 von Microsoft basierender Dateien. Manipulation meint hier das Lesen, Verändern und Anlegen dieser Dateien. OLE2 umfasst die meisten Office-Dateiformate wie .xls, .doc oder .ppt. Der Office-Open-XML-Standard (Kasten: „Office Open XML (OOXML)“) enthält jene Formate, die ab Microsoft Office 2007 und 2008 verwendet werden, namentlich .xlsx, .docx oder .pptx. Apache POI liefert für jede Office-Anwendung eine Komponente, die sowohl für OOXML als auch für OLE2 ein API bereitstellt.

Office Open XML (OOXML)
Office Open XML ist ein XML-basiertes Format für Office-Dokumente. Dieses Format ist eine von Microsoft entwickelte Spezifikation und wurde von ECMA International 2006 erstmalig standardisiert. Hierbei sei jedoch der Hinweis gestattet, dass Office Open XML nicht mit Open Office bzw. dem Open-Document-Format zu verwechseln ist. Der Standard enthält ebenfalls die von Microsoft definierten Auszeichnungssprachen WordprocessingML und PresentationML.

Mit Microsoft Office erstellte und bearbeitete Dokumente stellen gefühlt immer noch den Großteil aller Unternehmensdokumentation dar, allen Installationen von Confluence oder MediaWiki zum Trotz. Manager wünschen sich ihre Leistungskennzahlen im Excel-Format, Architekten präsentieren ihre Arbeiten mit PowerPoint, ganze Projekte werden mit Office-Produkten gar geplant und durchgeführt – im schlimmsten Fall eben auch mit MS Excel: Im Umfeld der Softwaretests haben wir sehr häufig Testpläne und Testdurchführungsdokumentationen live in Zellen und Spalten erleben dürfen. In der .NET-Welt ist die Arbeit mit Office-Komponenten sehr einfach, es existieren viele Tutorials und Beispiele, um mit C# oder vb.net Excel-Dateien zu manipulieren. Dieser Artikel zeigt, ob das mit Java und Apache POI ebenso einfach geht.

Die Projektseite von Apache POI listet einige Case Studies auf. Sie zeigt auf, dass sich Apache POI vielfältig einsetzen lässt. Interessant ist die dieses Jahr veröffentlichte Studie. Sie bescheinigt, dass die Bibliothek bei der Deutschen Bahn eingesetzt wurde, um komplexe Spezifikationen weiter nutzen zu können, die in alten Dokumentbeständen vorlagen. Man hat die Komponente HWPF eingesetzt.

Aber wofür steht nun dieses mysteriöse POI? Der Name stand ursprünglich als Abkürzung für Poor Obfuscation Implementation – das könnte man in etwa mit „verschleiernde, dürftige Implementierung“ übersetzen. Der Name scheint noch aus den Anfangstagen des Projekts zu kommen und wurde aus scheinbar ironischen Gründen beibehalten. Die Komponenten folgen teilweise einer ähnlich humorvollen Namensgebung, z. B. POIFS, das Poor Obfuscation File System, oder HSSF, das Horrible Spreadsheet Format. HSSF dient dem Lesen und Schreiben von .xls-Dokumenten.

Komponente Beschreibung
POIFS Der älteste und stabilste Teil von Apache POI. Hierauf basieren alle Komponenten von Apache POI, die nicht auf XML-basierte Office-Dokumente zugreifen.
HSSF Implementierung für Dokumente im Excel-97-2007-Dateiformat.
XSSF Implementierung für Dokumente im Excel-2007-OOXML-Dateiformat.
HWPF Implementierung für Dokumente im Word-97-2007-Dateiformat
XWPF Implementierung für Dokumente im Word-2007-OOXML-Dateiformat. Aktuell (Frühjahr 2016) wird an einer Umsetzung von WordprocessingML gearbeitet.
HSLF Implementierung für Dokumente im PowerPoint-97-2007-Dateiformat
XSLF Implementierung für Dokumente im PowerPoint-2007-OOXML-Dateiformat. Aktuell (Frühjahr 2016) wird an einer Umsetzung von PresentationML gearbeitet.
HSPF Implementierung für die Manipulation von OLE-2-Attributen eines Dokuments (Titel oder Autor).
HDGF Rudimentäre Implementierung für Dokumente im Visio-97-2003-Dateiformat.
PBF Rudimentäre Implementierung für Dokumente im Publisher-97-2003-Dateiformat.
HMEF Implementierung für das TNEF (Transport Neutral Encoding Format) Dateiformat.
HSMF Rudimentäre Implementierung des Office-Nachrichtenformats.

Tabelle 1 bietet eine kurze Übersicht über die Bestandteile von Apache POI. Dieser Artikel beschäftigt sich ausschließlich mit XSSF – wobei das wiederum die Abkürzung für das eher weniger amüsante XML-Spreadsheet-Format darstellt. Die Version 1.0.0 von Apache POI wurde Ende Dezember 2001 vorgestellt, am 3. Oktober dieses Jahres feierte das Projekt auch sein fünfzehnjähriges Bestehen. Seit September 2016 befindet es sich in Version 3.15. Listing 1 zeigt die in Maven einzubindenden Dependencies: Zum einen den Kern von Apache POI, womit bereits Dokumente im Office-97-2007-Format bearbeitet werden können, und zum anderen eine weitere Dependency auf poi-ooxml, um auch das OOXML-Dateiformat zu verwenden.

Grundsätzlich ist ein Excel-Dokument ein so genanntes Workbook. Ein Workbook besteht aus mehreren Spreadsheets. Das sind die einzelnen Tabellen eines Excel-Dokuments. Jedes Spreadsheet besteht aus Zellen, die über die Zeile und die Spalte identifiziert werden können. In einer Zelle sind darzustellende Daten oder Formeln. Eine Zelle kann spezifisch formatiert werden (Kasten: „Formatierung von Zellen mit Apache POI“ und Listing 6).

Formatierung von Zellen mit Apache POI
Apache POI erlaubt vielfältige Formatierung von Zellen – sei es die Anpassung der Cell Border, Füllen von Zellen mit Farben, das Zusammenfügen (Merging) von Zellen oder für jede Zelle ein individueller Font. Der Fantasie sind hier so gut wie keine Grenzen gesetzt. Listing 6 zeigt ein Beispiel für eine formatierte Zelle. Über eine CellRange wird ein Bereich, der gemerget werden soll, festgelegt, und anschließend ein Font und eine Farbe für die Zelle gewählt. Abbildung 5 zeigt das Ergebnis. Die Möglichkeiten zur Formatierung stellen einen weiteren Vorteil gegenüber der CSV-Export-Variante dar. Wichtige Inhalte werden hervorgehoben, Zusammenhänge werden schnell klar.
 
<dependency>
  <groupId>org.apache.poi</groupId>
  <artifactId>poi</artifactId>
  <version>3.15</version>
</dependency>
<dependency>
  <groupId>org.apache.poi</groupId>
  <artifactId>poi-ooxml</artifactId>
  <version>3.15</version>
</dependency>

Ein Beispiel aus dem wahren Leben

Das gezeigte Beispiel stammt aus dem realen Projektleben: Ein Kunde setzt eine individuelle Bestandssoftware ein, um bestimmte Testreihen durchzuführen – diese eingesetzte Software ist übrigens das Ergebnis des Anti-Patterns „Todesmarsch“. Diese Testreihen enthalten Testsuiten, vom Kunden auch Testpools genannt, die wiederum einzelne Testfälle enthalten (Abb. 1). Jeder Testpool umfasst eine bestimmte, fachlich zugeschnittene Menge an Testfällen. Testpools und Testfälle sind für jeden Testlauf inhaltlich identisch. Somit liegt nach jedem Testlauf für alle Testfälle eines Testpools ein Ergebnis vor. So weit, so unspektakulär. Mehr Informationen liefert das System jedoch auf einen schnellen Blick nicht, und wenn man einen Managementreport erstellen will, müssen die Daten umständlich über die Oberfläche der Software oder aus der darunterliegenden Datenbank per Hand oder SQL-Skript zusammengesucht werden. Alle Informationen werden zwar fein säuberlich und vollständig in der Datenbank persistiert, aber managementgerecht aufbereiten lassen sie sich nur mit Mühe.

Abb. 1: Testreihen, Testpools, Testfälle

Der Aufwand wurde den Stakeholdern durch die Nutzer, die bisher diese Daten mühselig erhoben haben, sehr ausführlich dargelegt. So gestand man sich schließlich ein, dass Abhilfe geschaffen werden muss. Die Stakeholder beschrieben ihre Anforderungen an die Auswertung zunächst anhand einer kleinen Skizze (Abb. 2). Auf einer ersten Übersichtsseite soll der zeitliche Verlauf der Testläufe inklusive der erfolgreich sowie der nicht erfolgreich durchgeführten Testfälle dargestellt werden. Darüber hinaus sollte für jeden Testlauf eine spezifische Seite mit tiefergehenden Informationen bezüglich der Testergebnisse hinzugefügt werden. Beim Kunden waren wir ursprünglich im Rahmen eines anderen Projekts tätig, wurden jedoch aufgrund der guten Zusammenarbeit dann zusätzlich mit der Umsetzung beauftragt. Wir sahen schnell, dass eine konventionelle Lösung – CSV-Export und Öffnen des Dokuments in Excel – hier nicht helfen würde. Eine Lösung mit .NET-Mitteln war für uns ebenfalls nicht möglich. Da wir uns beim Kunden in der Java-Welt befanden, entschieden wir uns für eine Umsetzung mit Apache POI, da der Umfang der Bibliothek eine Erfüllung der Anforderungen versprach – trotz anfänglicher Zweifel. Dieser Artikel zeigt eine vereinfachte Version des Produktivcodes.

Abb. 2: So wünschten sich die Stakeholder die Auswertung
Erstellung einer Übersicht

Listing 2 zeigt die grundsätzliche Methode generateReport(), die als Argument eine Liste aller Test-Runs erhält. Wenn man mit Apache POI ein neues Excel-Dokument erstellen will, erzeugt man grundsätzlich eine Instanz des Typs XSSFWorkbook, wobei hier die OOXML-Implementierung verwendet wird (Abschnitt GenerateReport_1 in Listing 2).

 

public void generateReport(ArrayList<Testrun> testRuns)
 throws FileNotFoundException, IOException{
  //GenerateReport_1
  XSSFWorkbook wb = new XSSFWorkbook();

  //GenerateReport_2
  XSSFSheet overviewSheet = wb.createSheet("Overview");
  assembleOverviewSheetInfo(overviewSheet, testRuns);

  //GenerateReport_3
  for(Testrun testrun : testRuns){
   XSSFSheet testrunSheet =
    wb.createSheet("Testrun_" + testrun.getTestRunIdentifier());
   assembleTestrunSheetInfo(testrunSheet, testrun);
  }

  //GenerateReport_4
  FileOutputStream fileOut =
   new FileOutputStream("report.xlsx");
  wb.write(fileOut);
  fileOut.close();
}

Alternativ wäre eine Implementierung auch wie folgt machbar, wenn man OOXML nicht verwenden will und sich mit den Dokumenten im Office-97-2007-Dateiformat begnügt. In diesem Fall ist nur die erste in Listing 1 angegebene Dependency notwendig:

Workbook wb = new HSSFWorkbook();

Der Abschnitt GenerateReport_2 beschreibt die Erzeugung des ersten Sheets des Reports. Das geschieht über den Aufruf der Funktion createSheet(). Bedenken muss man an dieser Stelle, dass Excel eine maximale Länge von 31 Zeichen für den Namen eines Spreadsheets erlaubt. Apache POI verkürzt den String still und heimlich, falls der gewünschte Name länger sein sollte. Darüber hinaus muss der Name eines Spreadsheets innerhalb eines Dokuments (Workbooks) eindeutig sein, d. h. ein SpreadSheet mit dem Namen „Testrun 1“ darf nicht mehrfach vorkommen. createSheet() würde den Versuch, einen bereits vorhandenen Namen zu verwenden, mit einer IllegalArgumentException() quittieren. Das nun erzeugte Spreadsheet, das die Übersicht beinhaltet, muss anschließend mit Daten bestückt werden. Beschrieben wird das in Listing 3, das den Quellcode für die selbstgeschriebene Methode assembleOverviewSheetInfo() zeigt.

private void assembleOverviewSheetInfo(XSSFSheet detailSheet, ArrayList<Testrun> testRuns) {
//assembleOverviewSheetInfo_1
XSSFRow testRundIdentifierRow = detailSheet.createRow(5);
XSSFRow testRunDate = detailSheet.createRow(6);
XSSFRow testRunSuccess = detailSheet.createRow(7);
XSSFRow testRunFail = detailSheet.createRow(8);

//assembleOverviewSheetInfo_2
XSSFCell testRundIdentifierRowNameCell =
testRundIdentifierRow.createCell(0);
testRundIdentifierRowNameCell.setCellValue("Testlauf");
XSSFCell testRunDateRowNameCell = testRunDate.createCell(0);
testRunDateRowNameCell.setCellValue("Datum");
XSSFCell testRunSuccessRowNameCell = testRunSuccess.createCell(0);
testRunSuccessRowNameCell.setCellValue("Passed");
XSSFCell testRunFailRowNameCell = testRunFail.createCell(0);
testRunFailRowNameCell.setCellValue("Failed");

//assembleOverviewSheetInfo_3
int cellColumn = 1;
for(Testrun testRun : testRuns){
 XSSFCell testRunIdentifierValue = testRundIdentifierRow.createCell(cellColumn);
testRunIdentifierValue.setCellValue(testRun.getTestRunIdentifier());
 XSSFCell testRunDateValue = testRunDate.createCell(cellColumn);
 testRunDateValue.setCellValue(testRun.getFormattedExecutionDate());
 XSSFCell testRunSuccessValue = testRunSuccess.createCell(cellColumn);
 testRunSuccessValue.setCellValue(testRun.getSuccessCount());
 XSSFCell testRunFailValue = testRunFail.createCell(cellColumn);
 testRunFailValue.setCellValue(testRun.getFailedCount());
 cellColumn++;
}
//assembleOverviewSheetInfo_4
createScatterChart(detailSheet, testRuns.size());
}

Im Abschnitt assembleOverviewSheetInfo_1 in Listing 3 werden unspektakulär die einzelnen benötigten Zeilen des Spreadsheets entsprechend den Vorgaben aus Abbildung 2 definiert. Eine Zeile zeigt den Identifier eines Test-Runs, die darunterliegende Zeile das Durchführungsdatum. Anschließend werden Informationen über erfolgreiche und nicht erfolgreiche Testfalldurchführungen über alle Testpools aufsummiert. Als Parameter wird der Methode createRow() des Spreadsheet-Objekts lediglich die entsprechende Zeilennummer übergeben, zur Vereinfachung und Verkürzung des Beispiels werden im Code keine Konstanten o. ä. verwendet.

Im Abschnitt assembleOverviewSheetInfo_2 werden die Zeilenköpfe definiert. Es werden erste Zellen erzeugt. Zellen gehören stets zu einer Zeile (row) und werden mit der Funktion createCell() erstellt. Als Parameter wird hier die ID der entsprechenden Spalte des Spreadsheets angegeben. Und da in diesem Beispiel alle Zeilenköpfe in der ersten Spalte ausgegeben werden sollen, lautet der Parameter 0. Hier kann es unter Umständen zu Verwirrung kommen, da Excel die Spalten eines Sheets stets mit A, B, … beschriftet. Zelle A1 im Excel-Spreadsheet ist demnach in Apache POI die Zelle 0/0. Zu guter Letzt werden jetzt noch die Werte der einzelnen Testläufe in das Spreadsheet übernommen, wie Abschnitt assembleOverviewSheetInfo_3 in Listing 4 beschreibt.

private void createScatterChart(XSSFSheet detailSheet, int
 NUMBER_OF_TESTRUNS) {

 //createScatterChart_1
 XSSFDrawing drawing = detailSheet.createDrawingPatriarch();
 ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 12,
NUMBER_OF_TESTRUNS + 2, 22);

XSSFChart chart = drawing.createChart(anchor);

//createScatterChart_2
XSSFChartLegend legend = chart.getOrCreateLegend();
legend.setPosition(LegendPosition.BOTTOM);

//createScatterChart_3
ChartAxis bottomAxis = chart.getChartAxisFactory().createCategoryAxis(AxisPosition.BOTTOM);
ValueAxis leftAxis = chart.getChartAxisFactory().createValueAxis(AxisPosition.LEFT);
ChartDataSource<String> xs = DataSources.fromStringCellRange(detailSheet, new CellRangeAddress(5, 5, 1, NUMBER_OF_TESTRUNS + 1));
ChartDataSource<Number> ys1 = DataSources.fromNumericCellRange(detailSheet, new CellRangeAddress(7, 7, 1, NUMBER_OF_TESTRUNS + 1));
ChartDataSource<Number> ys2 = DataSources.fromNumericCellRange(detailSheet, new CellRangeAddress(8, 8, 1, NUMBER_OF_TESTRUNS + 1));

//createScatterChart_4
XSSFScatterChartData data = chart.getChartDataFactory().createScatterChartData();
data.addSerie(xs, ys1);
data.addSerie(xs, ys2);

chart.plot(data, bottomAxis, leftAxis);
}

Was Nettes fürs Management: Diagramme

Obwohl das ursprünglich nicht gefordert war, entschlossen wir uns, dem Management noch eine kleine Nettigkeit zu präsentieren: die nackten Zahlen, die im Übersichts-Sheet ausgegeben wurden, sollten auch in Form eines Diagramms visuell greifbarer sein. Wieder etwas, das mithilfe einer reinen CSV-Lösung nicht möglich gewesen wäre. Apache POI liefert das einfach mit. Man darf jedoch nicht verschweigen: Diagramme und Apache POI, insbesondere unter Verwendung von XSSF, sind zwei Dinge, die (derzeit) nur bedingt zusammenpassen. Auf der Projektseite wird auf diese Limitierung auch direkt eingegangen. Im gezeigten Beispiel erzeugt man ein so genanntes ScatterChart, realisiert durch die Methode createScatterChart(). Als zweiter Parameter wird die Anzahl der Test-Runs mitgegeben. Das wird im weiteren Verlauf der Methode genutzt, um die zu verwendenden Zellbereiche bestimmen zu können. Der Abschnitt createScatterChart_1 in Listing 4 zeigt, wie man zunächst einen Bereich für das Diagramm festlegt. Das Diagramm beginnt in Zeile 12 in Spalte 0 und ist so breit wie die Anzahl der Testruns plus zwei Zellen.

Diagramme sind stets nur so viel Wert wie die passende Legende. Der Abschnitt createScatterChart_2 beschreibt die Position der Legende. Sie soll unterhalb des Diagramms stehen. Anschließend werden die Diagrammachsen erzeugt und die Datenreihen bestimmt. Es wird sich konkret auf jene Zellbereiche bezogen, welche die Daten für das Diagramm bereitstellen (createScatterChart_3). Der letzte Abschnitt sorgt dafür, dass die Datenreihen den Achsen zugeordnet werden und das Diagramm geplottet wird. Grundsätzlich lassen sich auf diese Art sehr einfach Diagramme erzeugen, aufgrund der genannten Limitierungen ist man jedoch stark eingeschränkt. Eine mögliche Lösung stelle ich am Ende des Artikels vor.

Detailinformationen hinzufügen

Nachdem nun das Sheet mit der Übersicht vollständig ist, muss im nächsten Schritt dem Workbook für jeden Testlauf ein Spreadsheet mit Detailinformationen hinzugefügt werden. Für jeden Testlauf wird ein neues Spreadsheet mit der Methode createSheet() erzeugt, wobei als Argument der eindeutige Identifier des Testlaufs übergeben wird (siehe Abschnitt GenerateReport_3 in Listing 2). Im Anschluss wird die selbstgeschriebene Methode assembleTestrunSheetInfo aufgerufen, um das Spreadsheet zu befüllen. Listing 5 beschreibt die Implementierung dieser Methode. Der dort gezeigt Quellcode verwendet die bereits bekannten Methodenaufrufe, um die Daten in das Detail-Spreadsheet zu schreiben und ist hier nur der Vollständigkeit halber mit beigefügt. Formatierungen habe ich hier aus Gründen der Übersichtlichkeit im Beispiel nicht verwendet, siehe dazu „Formatierung von Zellen mit Apache POI“ und Listing 6.

Nachdem nun alle Spreadsheets gefüllt wurden, ist es an der Zeit, den Report zwecks Weitergabe an die Stakeholder im Dateisystem abzulegen. Das geschieht über einen FileOutputStream. Der Abschnitt GenerateReport_4 in Listing 2 beschreibt das.

Das Ergebnis, also das erzeugte Excel-Dokument, entspricht den durch den Stakeholder verfassten Vorgaben. Abbildung 3 zeigt das Übersichts-Spreadsheet, Abbildung 4 ein Spreadsheet mit einem exemplarischen Testlauf und dazugehörigen Detailinformationen.

Abb. 3: Das Ergebnis-Spreadsheet mit der Übersicht über alle Testläufe sowie Diagramm

Abb. 4: Das Ergebnis-Sheet mit Detailinformationen zu einem Testlauf

 private void assembleTestrunSheetInfo(XSSFSheet testrunSheet, Testrun testrun)
{
  XSSFRow headerRow = testrunSheet.createRow(1);
  XSSFCell dateCell = headerRow.createCell(0);
  dateCell.setCellValue(testrun.getFormattedExecutionDate());
  int rowCounter = 2;
  for(TestPool testPool : testrun.getTestPools()){
   XSSFRow testPoolRow = testrunSheet.createRow(rowCounter);
   XSSFCell testPoolCell = testPoolRow.createCell(0);
   testPoolCell.setCellValue(testPool.getTestPoolName());
   for(Testcase testcase : testPool.getTestCases()){
    XSSFRow testcaseRow = testrunSheet.createRow(rowCounter+1);
    XSSFCell testcaseIdentifierCell = testcaseRow.createCell(1);

   testcaseIdentifierCell.setCellValue(
   testcase.getTestCaseIdentifier());
    XSSFCell testcaseMessageCell = testcaseRow.createCell(2);
    testcaseMessageCell.setCellValue(testcase.getTestCaseMessage());
    rowCounter++;
   }
   rowCounter++;
  }
}
XSSFWorkbook wb = new XSSFWorkbook();
XSSFSheet sheet = wb.createSheet("Format-Test");
sheet.addMergedRegion(new CellRangeAddress(0,0,0,2));
XSSFRow row = sheet.createRow(0);
XSSFCell cell = row.createCell(0);
//Create Font
Font font = wb.createFont();
font.setFontName("Courier New");
font.setFontHeightInPoints((short)36);
font.setBold(true);
//Create Style
XSSFCellStyle style = wb.createCellStyle();
style.setFillForegroundColor(new XSSFColor(java.awt.Color.red));
style.setFillPattern(FillPatternType.FINE_DOTS);
style.setFont(font);

cell.setCellStyle(style);
cell.setCellValue("Java Magazin");

Grenzen von Apache POI und Excel

Grenzen hat Apache POI im Umfeld der Diagramme, insbesondere, was XSSF betrifft mehr als die bereits aufgeführten Charts sucht man vergebens. Auch die Arbeit mit Pivot-Tabellen ist sehr limitiert, und Makros lassen sich ebenfalls nicht erzeugen. Aber als Java-Entwickler möchte man das auch nicht so gerne. Darüber hinaus treten bei sehr großen Dokumenten eventuell Speicherprobleme auf, wobei das im beschriebenen Projekt nicht der Fall war. Hier sind die bekannten Limitierungen aufgeführt, auch unter Berücksichtigung von HSSF. Wenn man wirklich komplexe Diagramme mit Leben füllen will, so bleibt einem die Möglichkeit, mit Apache POI die Daten in ein Excel-Dokument zu liefern und schließlich mit Bordmitteln per Hand ein Diagramm zu erstellen.

Dieser Artikel thematisiert ausschließlich das Erzeugen, also Schreiben, von Excel-Dokumenten. Apache POI ist ebenso dafür geeignet, MS Excel-Dateien auszulesen und die Daten weiter aufzubereiten oder in einer richtigen Datenbank zu persistieren. Von als Datenbank missbrauchten Excel-Mappen haben wir gehört. Sie sind uns aber in der freien Wildbahn, vermutlich zu unserem Glück, bisher noch nicht begegnet.

Abb. 5: Eine erfolgreiche Formatierung einer Zelle

Fazit

Hat Apache POI seinen schlechten Ruf in der Java-Welt verdient? Diese Frage lässt sich so einfach nicht mit Ja oder Nein beantworten. Dem einen Entwickler ist das API vielleicht nicht übersichtlich genug, dem anderen Entwickler fehlen wichtige Funktionalitäten – Stichwort Diagramme. Ein ganz anderer Entwickler ist wiederum mit allem zufrieden, was die Bibliothek liefert. Am Ende des Tages hängt die Beantwortung immer von der gestellten Aufgabe ab.

Mit Apache POI lassen sich schnell und ohne großen Aufwand Excel-Dokumente erzeugen, die zudem sinnvoll aufgebaut und formatiert werden können. CSV bietet sich dann natürlich an, wenn man lediglich Datenkolonnen in Excel darstellen möchte, in dem Fall wäre die Nutzung von Apache POI, bzw. HSSF oder XSSF, deutlich übertrieben. Einem Entwickler bietet die Bibliothek umfangreiche Möglichkeiten, Daten für Anwender übersichtlich in einem bei sehr vielen Unternehmen verbreiteten und vom Management geliebten Format darzustellen. Insgesamt sollte der Neid des Java-Entwicklers auf die .NET-Welt aber nicht zu groß sein.

Verwandte Themen:

Geschrieben von
Andreas Monschau
Andreas Monschau
Andreas Monschau ist als IT Consultant mit den Schwerpunkten Java-Softwareentwicklung und Softwaretest (Management, Automatisierung) bei Haeger Consulting in Wachtberg bei Bonn tätig. Seine sonstigen Interessen wechseln stetig, derzeit sind es PHP7, arc42 und Microservices. Nebenher schreibt er Fachartikel und hält Vorträge. Twitter: @andreasmonschau
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.