|
Java und XLS-Dateien (MS Excel Spreadsheets) Es existieren unterschiedliche Möglichkeiten, auf XLS-Dateien von Java aus zuzugreifen. Eine davon wäre die Nutzung von JDBC-ODBC-Bridge. Nachteil ist hier, dass die Tabelle in einer datenbankgerechten Form vorliegen muss. Außerdem muß auf der Zielplattform sowohl ODBC als auch der entsprechende ODBC Treiber zur Verfügung stehen.Eine andere Möglichkeit bieten Komponenten, die man von Drittanbietern kaufen kann. Open Source Löungen existieren natürlich auch. Eine existiert innerhalb des Apache Jakarta POI Projektes, und zwar in dem HSSF (Horrible Spreadsheet Format), welches das Excel 97 Dateiformat in Java implementiert. Dabei kann sowohl lesend, als auch schreibend auf die Datei zugegriffen werden. Vorteil ist die Verfügbarkeit auch unter Linux, Nachteil ist die sehr begrenzte Unterstützung von Formeln und Formel-Evaluierung. In vielen Fällen dürften die Funktionen aber ausreichend sein. Mögliche Anwendungen sind Bereitstellung von Reportings für z.B. statistische Auswertungen oder Datenexport zu Weiterverarbeitung durch Office-Anwender. 1. Einrichten eines Eclipse Projektes Die benötigten Class-Dateien sind in einer JAR Datei zusammengefasst, in diesem Fall (versionsabhängig) ist das poi-3.0-alpha3-20061212.jar. Die von der Jakarta Seite herunter zu ladende gepackte Datei enthält noch zwei weitere JAR-Dateien, unter anderem das Scratchpad, worin die POI - Entwickler all jene Klassen packten, die noch nicht so 100%ig nach ihren Vorstellungen funktionieren. Neben den HSSF-Klassen sind auch Klassen für weitere Office Formate enthalten, unter anderem Word. Von der Jakarta Seite kann man sich dann am besten auch gleich den Quelltext herunterladen. Entpackt habe ich in diesem Fall die Dateien nach D:\Projekte\Java\poi, und zwar die class-Dateien in einen Unterordner bin und die Quelltexte in einen Ordner src. Grundsätzlich vermeide ich es so gut ich kann, Java Dateien über Festplatten und Verzeichnisse zu verteilen, da man für verschiedene Projekte schnell Resourcen doppelt und dreifach auf der Harddisk hat. Nun startet man Eclipse und geht wie folgt vor: a) Man wählt File/New/Project b) Man wählt Java Project c) Als Projektname wurde "HSSFExaample" vergeben. d) "Create seperate source and output folders" aktivereren 
e) "Next" klicken f) Den Reiter "Libraries" wählen. g) Mit "Add External JARs" die Datei poi-3.0-alpha3-20061212.jar hinzufügen. h) "Finish" klicken Der Package Explorer sollte jetzt einen Eintrag "HSSFExample" haben, der etwas so aussieht: 
Das Beispiel soll folgende Situation wiedergeben: Es soll der Firmenname eines Kunden und der jeweilige Umsatz der ersten beide Quartale ermittelt und in einen XLS-Datei geschrieben werden. Zusätzlich wird noch eine Formel zum addieren der beiden Umsätze geschrieben. Da aber keine Datenbank entwickelt werden sollt, wurde eine Klasse entwickelt, die diese Daten für drei Kunden bereitstellt. Für den Zugriff liefert diese Klasse "SalesData" die Methoden: public String getCostumername(int number) public double getSales1(int number) public double getSales2(int number) Die Implementierung dieser Klasse ist maximal simpel und wird hier nicht besprochen. Im Package Explorer wird ein Rechtsklick auf "HSSFExample" gemacht und mit "New/Package" ein neues Package angelegt, welches "xlsCustomerSales" genannt wird. Mit einem Rechtsklick auf das neue Package fügen wird nun eine neue Klasse "SalesData". Auf dem gleichen Weg wird die Klasse "CustomerSales" erzeugt. Diese Klasse soll auch eine main()-Methode enthalten. 
In dieser Klassen importiert man nun das nötige Package: import org.apache.poi.hssf.usermodel.*; Innerhalb der main()-Methode wird nun der Stream für die entsprechende xls-Datei deklariert, eine neue Arbeitsmappe und in dieser eine neue Tabelle erzeugt: Innerhalb der main()-Methode wird nun der Stream für die entsprechende xls-Datei deklariert, eine neue Arbeitsmappe und in dieser eine neue Tabelle erzeugt: Innerhalb der main()-Methode wird nun der Stream für die entsprechende xls-Datei deklariert, eine neue Arbeitsmappe und in dieser eine neue Tabelle erzeugt: FileOutputStream out = null; HSSFWorkbook wb = new HSSFWorkbook(); // HSSFSheet s = wb.createSheet(); Es wird nun ein Objekt der Daten liefernden Klasse erzeugt: SalesData myData = new SalesData(); //Daten aus Objekt, keine Datenbank für Tests In einem try-Block wird der Datei-Stream erzeugt: out = new FileOutputStream("C:/sales..xls"); Als Nächstes gibt man den Namen der Tabelle an. Dabei wird als erster Parameter die Nummer der zu bezeichnenden Tabelle angegeben, beginnend mit 0. Als Nächstes gibt man den Namen der Tabelle an. Dabei wird als erster Parameter die Nummer der zu bezeichnenden Tabelle angegeben, beginnend mit 0. wb.setSheetName(0, "Sales"); Der Zugriff auf einzelne Zellen der Tabelle geschieht über Referenzen der Zeilen und Spalten innerhalb einer Zeile. Konkret ist das Vorgehen hier so, das eine neues Spalten-Objekt erzeugt wird, mit dessen Hilfe dann wiederum die Zellen erzeugt werden. Um dies tun zu können, deklariert man nun Referenzvariablen der entsprechenden Typen: HSSFRow r = null; HSSFCell c = null; Die erste Zeile und die erste Zelle werden erzeugt: r = s.createRow((short) 0); c = r.createCell((short) 0) Die Klasse HSSFCell enthält diverse Methoden zur Manipulation der Zelle, wobei die setCellValue() sicherlich die wichtigste (neben Methoden zur Formatierung) ist. Sie ist vielfach überladen, so dass unterschiedlichste Typen übergeben werden können. Das Übergeben eines einfachen Java Strings wurde leider aus der aktuellen POI Version entfernt, allerdings gibt es die Klasse HSSFRichTextString, die übergeben werden kann. Ein HSSFRichTextString_Objekt wird nun erzeugt und der dem Zellen-Objekt übergeben: HSSFRichTextString str1 = new HSSFRichTextString("UMSÄTZE"); c.setCellValue(str1); Im Beispiel werden auch double-Werte per setCellValue übergeben, ansonsten ist hier nur noch das Setzen von Formeln wirklich interessant. Leider fehlt die Unterstützung von Array-Formeln, so dass die Lösung im Beispiel wenig elegant ist. Ob Formelprogrammierung überhaupt Sinn macht, wenn man doch eh von einer mächtigen Programmiersprache wie Java aus zugreift, ist allerdings im Einzelfall die Frage. Hier nun das Beispiel: String formula; ... formula = "B3+C3"; ... c.setCellFormula(formula); Im Beispiel erkennt man, dass dies besser zu lösen gewesen wäre, wenn man statt der Referenzierung über r und c gleich ein sinnvolles Array Konstrukt verwendet hätte. Zum Abschluß wird dieArbeitsmappe in die Datei geschrieben und der Stream geschlossen. wb.write(out); out.close(); Nachdem das Programm ausgeführt wurde, kann man sich das Ergebnis anschauen (hier in Open Office): Zum Schluss noch der komplette Quelltext: package xlsCustomerSales; import java.io.FileOutputStream; import java.io.IOException; import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFRichTextString; import org.apache.poi.hssf.usermodel.HSSFRow; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; public class CustomerSales { public static void main(String[] args) { FileOutputStream out = null; HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet s = wb.createSheet(); //Daten aus Objekt, keine Datenbank für Tests SalesData myData = new SalesData(); try{ out = new FileOutputStream("C:/sales.xls"); } catch(IOException e){ System.out.println("Error while creating workbook."); } wb.setSheetName(0, "Sales"); // Tabellenname HSSFRow r = null; // Zeilenreferenz HSSFCell c = null; // Zellenreferenz // Zeile 1 r = s.createRow((short) 0); //Kopfzeile c = r.createCell((short) 0);// 1. Zelle HSSFRichTextString str1 = new HSSFRichTextString("UMSÄTZE"); c.setCellValue(str1); // Zeile 2 r = s.createRow((short) 1); //Überschriftenzeile c = r.createCell((short) 0);//1. Zelle: Kunde HSSFRichTextString str2 = new HSSFRichTextString("Kunde"); c.setCellValue(str2); c = r.createCell((short) 1);//2. Zelle Umsatz 1. Quartal HSSFRichTextString str3 = new HSSFRichTextString("Umsatz 1. Quartal"); c.setCellValue(str3); c = r.createCell((short) 2);//3. Zelle Umsatz 2. Quartal HSSFRichTextString str4 = new HSSFRichTextString("Umsatz 2. Quartal"); c.setCellValue(str4); c = r.createCell((short) 3); //Summe HSSFRichTextString str5 = new HSSFRichTextString("Summe 1. Halbjahr"); c.setCellValue(str5); for (short i = 0; i <= 2; i++) { r = s.createRow( i+2 ); c = r.createCell((short) 0); HSSFRichTextString str6 = new HSSFRichTextString(myData.getCostumername((int) i)); c.setCellValue(str6); c = r.createCell((short) 1); c.setCellValue(myData.getSales1((int) i ) ); c = r.createCell((short) 2); c.setCellValue(myData.getSales2((int) i ) ); String formula; switch(i){ case 0: formula = "B3+C3"; //Array Formeln werden nicht unterstützt (12.03.2007) break; case 1: formula = "B4+C4"; break; case 2: formula = "B5+C5"; break; default: formula = ""; } c = r.createCell((short) 3); c.setCellFormula(formula); } try{ wb.write(out); out.close(); } catch(IOException e){ System.out.println("Error while writing XLS-File"); System.exit(1); } System.out.println("Finished"); } }
|