JakartaPOI - Java meets Office

Die Seite wird erstellt Ulrich Groß
 
WEITER LESEN
JakartaPOI - Java meets Office
Seminarbericht:

JakartaPOI – Java meets Office
Fachhochschule Nordwestschweiz FHA
University of Applied Sciences Aargau

Autor:                   Strittmatter Reto
                         r.strittmatter@stud.fh-aargau.ch

Studiengang              Informatik
Vertiefung               Enterprise Computing
Dozent                   Prof. Dr. Dominik Gruntz

Windisch, 7. Juli 2004
JakartaPOI - Java meets Office
JakartaPOI

Abstract

Das JakartaPOI Projekt stellt mehrere freie in Java implementierte Bibliotheken zur
Verfügung, mit denen Dokumente, welche in dem Microsoft proprietären „OLE-2
Compound Document“ Format gespeichert sind, gelesen und erstellt werden können. In
diesem Format sind auch die MS Word und Excel Dokumente gespeichert. Dieser
Seminarbericht soll einen Überblick über diese Bibliotheken geben und ihre Verwendung
an einfachen Beispielen demonstrieren. Insbesondere soll der Verwendung von POI im
Bereich Webservices Beachtung geschenkt werden.

R. Strittmatter, FH-Aargau                                                   Seite 2/28
JakartaPOI

Inhaltsverzeichnis
1 Wie kann man Office Dokumente mit Java bearbeiten..................................................... 4
2 Was ist JakartaPOI........................................................................................................... 4
3 Elemente von JakartaPOI................................................................................................. 5
   3.1 POIFS – Implementation des OLE2 Compound Document Format ......................... 5
   3.2 HSSF - Java API um MS Excel Dokumente anzusprechen....................................... 6
   3.3 HWPF - Java API um MS Word Dokumente zu bearbeiten.......................................7
   3.4 HPSF – Java API um Dokument Eigenschaften zu manipulieren..............................7
4 Einblick in das Arbeiten mit HSSF..................................................................................... 8
   4.1 Elemente eines Excel Dokument............................................................................... 8
   4.2 Erstellen eines einfachen Excel Dokument................................................................ 9
   4.3 Lesen eines Excel Dokument................................................................................... 11
   4.4 Weitere HSSF Aspekte im Detail............................................................................. 11
      4.4.1 HSSF Cells....................................................................................................... 11
      4.4.2 Zellen Formatierung.......................................................................................... 12
      4.4.2.1 Ausrichtung Optionen.................................................................................... 13
      4.4.2.2 Zellen Ränder................................................................................................ 14
      4.4.2.3 Füllungen und Farben.................................................................................... 14
      4.4.2.4 Arbeiten mit Schriften.................................................................................... 15
      4.4.2.6 Zeichnen von Figuren.................................................................................... 17
      4.4.2.7 Arbeiten mit Formeln..................................................................................... 18
5 JakartaPOI in Webanwendungen................................................................................... 19
6 Fazit................................................................................................................................. 21
A) Literaturverzeichnis und Quellenangaben..................................................................... 22
B) Servlet Quellcode.......................................................................................................... 23
C) POIFS Beispiel.............................................................................................................. 27
D) HPSF Beispiel............................................................................................................... 27

R. Strittmatter, FH-Aargau                                                                                                    Seite 3/28
JakartaPOI                                   Wie kann man Office Dokumente mit Java bearbeiten

1 Wie kann man Office Dokumente mit Java bearbeiten

Um mit Java MS Office Dateien erzeugen und bearbeiten zu können, gibt es grundsätzlich
zwei verschiedene Ansätze. Ein möglicher Ansatz wäre eine MS Office Anwendung fern
zu steuern, dies geschieht mittels der COM/DCOM Schnittstelle. Jede MS Office
Anwendung ist, wenn sie korrekt installiert wurde, gleichzeitig auch ein COM/DCOM
Server. Während das Schreiben eines DCOM Client in Visual Basic oder C++ kein
Problem darstellt, ist dies mit Java nicht ohne weiteres möglich.
Der Grund weshalb das Ansprechen des DCOM Servers nicht so einfach realisierbar ist,
liegt in der Plattformunabhängigkeit von Java. Als Lösung könnte man einen Client in
einer nativen Programmiersprache schreiben, der dann über das Java Native Interface
(JNI) in die Java Umgebung eingebunden wird. Dies ist eine komplexe Vorgehensweise
mit mehreren Nachteilen. Zum einen ist das Java-Produkt dazu nicht mehr plattform-
unabhängig, hat hohe Performance Einbussen, da eine Methodenaufruf über mehrere
Schichten geht, und eine MS Office Anwendung wird bloss ferngesteuert, was bei einer
Webapplikationsanwendung weitere Einschränkungen zur Folge hätte.

Ein zweiter weit flexibler Ansatz ist die komplette Erzeugung eines MS Office Format
direkt in Java. Mit anderen Worten, es wird eine MS Excel bzw. Word Dateien erzeugt, als
ob diese von einer MS Office Anwendung stammen würde.
Diesen Ansatz verfolgt das JakartaPOI Projekt, welches ich in diesem Seminarbericht
vorstellen möchte.

2 Was ist JakartaPOI

Das JakartaPOI Projekt besteht aus mehreren Java APIs, die es einer/em Entwickler/in
erlauben, Dateien zu erstellen und zu bearbeiten, welche auf dem Microsoft proprietären
Dateiformat „OLE-2 Compound Document Format“ beruhen. Alle MS Office Anwendungen
ab der Version 95 bis XP benutzen dieses Datei Format, wenn auch in einer leicht
abweichender Form.
POI steht dabei für “Poor Obfuscation Implementation“ (Schlechte, verschleiernde
Implementierung). Diesen abschätzigen Projektname haben die Entwickler gewählt, da sie
finden, dass das Datei Format (OLE2CDF), welches die Office Komponenten benutzen,
von Microsoft nicht richtig durchdacht worden ist. Diese Ansicht wiederspiegelt sich auch
in der Namensgebung der einzelnen Teile des Projektes, auf die ich nun genauer
eingehen möchte.

R. Strittmatter, FH-Aargau                                                          Seite 4/28
JakartaPOI                                                           Elemente von JakartaPOI

3 Elemente von JakartaPOI

Wie im vorherigen Kapitel bereits erwähnt, besteht das JakartaPOI Projekt aus mehreren
Einzelprojekten. Diese sind unterschiedlich weit fortgeschritten in ihrer Entwicklung. Ich
möchte im Folgenden auf jedes einzelne Projekt eingehen und die wichtigsten Aspekte
ein wenig erläutern.

3.1 POIFS – Implementation des OLE2 Compound Document Format

POIFS ist eine reine Java Implementation des „OLE 2 Compound Document Format“
(OLE2CDF). Eine Datei, die im OLE2CD Format abgespeichert ist, beinhaltet ein
Dateisystem, welches aus verschachtelten Verzeichniseinträgen sowie normalen
Einträgen, also Dateien besteht. Man kann sich das ganze auch gut als ein ZIP-Archive
vorstellen.
Mit der POIFS API können solche Dateien einfach gelesen und geschrieben werden.
POIFS stellt die Grundfunktionen für das Arbeiten mit OLE2CDF Dateien zur Verfügung
und wird von allen anderen POI Komponenten verwendet. Alle weiteren POI-
Komponenten wie HSSF oder HWPF verstecken die POIFS API vor dem Benutzer, es
wird mit ihnen auf einer abstrakteren Schicht gearbeitet. Es gibt aber Anwendungsfälle bei
denen ein/e Entwickler/inn nicht darum herum kommt, direkt mit der POIFS API zu
arbeiten.

Darum möchte ich kurz eine grobe Übersicht über die Verwendung der POIFS API geben.
Weitere Details wie man mit der POIFS API arbeitet, sind im Anhang unter
„Weiterführende Links„ unter [1] zu finden.

Ein OLE2CDF Datei kann mit der POIFS API auf zwei Arten gelesen werden.

       1. Herkömmliches Lesen:
          Dabei wird die OLE2CDF Datei wie ein normales Dateisystem gelesen, man
          kann die Einträge in beliebiger Reihenfolge anspringen und lesen.
          Der grösste Nachteil dieser Methode besteht darin, dass sich alle
          Dateien/Einträge der Datei im Speicher befinden, egal, ob sie die Anwendung
          braucht oder nicht.

R. Strittmatter, FH-Aargau                                                        Seite 5/28
JakartaPOI                       POIFS – Implementation des OLE2 Compound Document Format

       2. Event gesteuertes Lesen:
          Diese Art zu lesen ist effizienter als das herkömmliche Lesen. Es wird das
          Reactor Pattern benutzt, um ein Dokument einzulesen (Vergleichbar mit einem
          SAX Parser bei einer XML Datei). Es reduziert den Speicherverbrauch einer
          Anwendung und ist schneller als das herkömmliche Lesen, da nur noch das
          gelesen wird, was auch wirklich gebraucht wird.
          Die Nachteile dieser Lesevariante liegen in der komplizierteren Handhabung,
          sowie der genauen Kenntnis im Vorfeld, was genau gelesen werden muss.
          Ausserdem hat man keine Kontrolle über die Reihenfolge wie ein Dokument
          eingelesen wird.

Das Schreiben einer OLE2CDF Datei kann ebenfalls auf mehrere Arten geschehen.
Man kann ein existierendes Dateisystem in den Speicher laden und modifizieren (Dateien
hinzufügen, löschen oder umbenennen) und anschliessend abspeichern oder man kann
eine neue leere OLE2CDF Datei kreieren und mit dieser weiter arbeiten.

Als Beispiel für das Arbeiten mit dem POIFS möchte ich zeigen, wie man mit der POIFS
API die Elemente eines OLE2CDF Filesystems auslesen kann. Der Quellcode dieses
Beispiels ist im Anhang dieses Dokumentes unter C zu finden.

3.2 HSSF - Java API um MS Excel Dokumente anzusprechen

HSSF ist ein API um Microsofts Excel'97 (-2002) Dateien (XLS) manipulieren zu können.
Auch diese API ist in reinem Java implementiert und benutzt im Hintergrund das POIFS
API. HSSF steht für „Horrible Spread Sheet Format“ was wiederum die Meinung der
Entwickler über das Excel Format wiedergibt.
Auf die Einzelheiten und die Verwendung der HSSF API wird im Laufe dieses Berichts
näher eingegangen.

R. Strittmatter, FH-Aargau                                                      Seite 6/28
JakartaPOI                               HWPF - Java API um MS Word Dokumente zu bearbeiten

3.3 HWPF - Java API um MS Word Dokumente zu bearbeiten

HWPF ist eine Java – API, die es einer/em Entwickler/in erlaubt, MS Word Dokumente zu
bearbeiten. Dieser Teil des POI Projektes steckt immer noch im frühen Anfangsstadium
der Entwicklung und ist noch nicht so weit fortgeschritten, wie die des HSSF Teils.
Ausser ein paar einfachen Beispielen im Entwickler-Zweig des Projektes und der JavaDoc
Dokumentation der API findet man wenig Informationen wie mit HWPF gearbeitet werden
soll. Dies wird sich sicherlich im Laufe der Entwicklung dieses Projektzweiges ändern und
sollte deshalb von allen Interessierten mit Spannung verfolgt werden.

Die frühe Entwicklungsphase des HWPF-Projektes nehme ich zum Anlass, an dieser
Stelle nicht weiter darauf einzugehen.

3.4 HPSF – Java API um Dokument Eigenschaften zu manipulieren

Microsoft Anwendungen ermöglichen es, dass ein Benutzer einem erstellten Dokument
gewisse Eigenschaften wie Titel, Kategorie, etc. zuweisen kann. Die Anwendung selbst
speichert den letzten Autor, das Erstellungsdatum und andere Informationen automatisch
in der entsprechenden OLE2CDF Datei ab. Diese Eigenschaften werden in einem
Eigenschaftenstream in der internen Datenstruktur der Datei abgelegt. Mit der HPSF API,
(Horrible Property Set Streams API) welche als Grundlage die POIFS API benutzt, kann
man auf diesen Eigenschaftstream der OLE2CDF Dateien zugreifen und diese
Eigenschaften manipulieren.
Dabei unterstützt HPSF OLE2 Eigenschaftstream im Allgemeinen und ist nicht limitiert auf
die weiter oben beschriebenen MS Office Anwendungen.

In diesem Abschnitt möchte ich aufzeigen, wie man die wichtigsten Eigenschaften eines
Dokumentes lesen kann. Die Unterstützung, um die Eigenschaften schreiben zu können,
ist zum Zeitpunkt der Erstellung dieses Seminarberichtes nur rudimentär vorhanden und
wird daher nicht weiter verfolgt.

Im Anhang D des Dokuments ist das Listing des Quellcode abgedruckt, der den
SummaryInformation- Strom eines Dokumentes einliest und ein paar Eigenschafts-
Informationen auf der Konsole ausgibt. Das Dokument wird mit der Event Methode
eingelesen, welche im POIFS Teil schon kurz erwähnt wurde.

R. Strittmatter, FH-Aargau                                                        Seite 7/28
JakartaPOI                                                     Einblick in das Arbeiten mit HSSF

4 Einblick in das Arbeiten mit HSSF

Die HSSF API besteht aus den folgenden Hauptpaketen:

                 Package                                 Beschreibung
org.apache.poi.hssf.              Liefert eine abstrakte Sicht von gängigen   Spreadsheet
usermodel                         Elementen wie Workbook, Sheet, Row, Cell, Font, Cell Style,
                                  Color Palette, Data Format, etc.
org.apache.poi.hssf.record        Beinhaltet Klassen, welche eine binäre XLS Struktur
                                  repräsentieren.
org.apache.poi.hssf.record.       Beinhaltet Klassen, die es erlauben mehrere Records als
aggregates                        einen Record zu bearbeiten.
org.apache.poi.hssf.record.       In diesem Paket sind die Klassen angesiedelt, welche es
formula                           erlauben mit Formeln in einem Excel Dokument zu arbeiten.
org.apache.poi.hssf.              Event basierte API um HSSF Dateien zu lesen.
eventusermodel
org.apache.poi.hssf.dev           Beinhaltet Beispiele und Werkzeuge um Excel Dateien zu
                                  erstellen und validieren.

4.1 Elemente eines Excel Dokument

Aus der Sicht von HSSF ist ein Excel Dokument ein Workbook, welches ein oder mehrere
Worksheets beinhaltet. Ein Worksheet besteht wiederum aus Reihen, welche mehrere
Zellen beinhalten können. Zu den jeweiligen Zellen können verschiedene Anzeigeattribute
und Formelfunktionen zugewiesen sein.

Die folgende Graphik soll diesen Zusammenhang verdeutlichen.

                                  Workbook

             Worksheet 1         Worksheet ...              Worksheet n

                                                                     Attributes
                                  Row (1...n)                           color
                                                                        width
                                  Cell (1...n)                          height
                                                                         ...

R. Strittmatter, FH-Aargau                                                            Seite 8/28
JakartaPOI                                              Erstellen eines einfachen Excel Dokument

4.2 Erstellen eines einfachen Excel Dokument

Diese Schritte sind nötig, um ein einfaches Excel Dokument zu erstellen.

      1. Erstellen eines HSSFWorkbook Objektes.

      2. Erstellen eines HSSFWorksheet Objektes von dem HSSFWorkbook Objekt.
         Dies ist der einzige Weg, um eine Referenz auf ein Worksheet Objekt zu
         bekommen, da in Excel kein Worksheet ausserhalb eines Workbook existieren
         kann.

      3. Analog zur Erstellung eines Woorksheets erhält man HSSFRow Objekte von
         einem Worksheet und HSSFCell Objekte von einem Row Objekt.

      4. Um einen Header zu kreieren, muss man mehrere Zellen/Reihen
         zusammenfassen, dies ist möglich via dem org.apache.poi.hssf.util.Region
         Objektes. Die Nummerierung der Reihen und Zellen beginnt bei null.

      5. Um Daten in eine Zelle einzufügen, verwendet man die HSSFCell Methode
         setCellValue. Zellen unterstützen alle Nativen Java Typen wie String, int, boolean,
         etc. Das API unterstützt zudem noch andere gängige Typen wie Date und
         Calendar.

      6. Als letztes muss das Excel Dokument im physikalischen Dateisystem erstellt
         werden. Dazu wird ein OutputStream Objekt der HSSFWorkbook Methode write
         übergeben, welche dann das Dokument in den entsprechenden Stream schreibt.
         Danach muss der Stream unbedingt geschossen werden, da die HSSF API dies
         nicht automatisch macht.

R. Strittmatter, FH-Aargau                                                            Seite 9/28
JakartaPOI                                             Erstellen eines einfachen Excel Dokument

Dieses „Hello Excel“ Beispiel soll die oben aufgeführten Schritte wiedergeben:

 // Schritt 1:
            HSSFWorkbook wb = new HSSFWorkbook();

 // Schritt 2:
            HSSFSheet sheet              = wb.createSheet("Hello");

 // Schritt 3:
            HSSFRow          headerRow   = sheet.createRow(1);

 // Schritt 4:
            // Header von Reihe 2 bis 3 und Zellen 2 bis 11
            //               Region(RowFrom ,CellFrom ,RowTo ,CellTo    )
            Region reg = new Region(1    ,(short)1 , 2    ,(short)10 );
            sheet.addMergedRegion(reg);

                 HSSFCell headerCell = headerRow.createCell((short)1);

 // Schritt 5:
            headerCell.setCellValue( "Hallo Excel" );

 // Schritt 6:
            FileOutputStream fileOut = new FileOutputStream
                                                     ("HelloExcel.xls");
            wb.write(fileOut);
            fileOut.close();

R. Strittmatter, FH-Aargau                                                          Seite 10/28
JakartaPOI                                                      Lesen eines Excel Dokument

4.3 Lesen eines Excel Dokument

Das Einlesen eines Excel Dokumentes aus einer Datei ist genau so einfach wie das
Erstellen. Als erstes muss ein POIFSFileSystem Objekt erzeugt werden und dieses dann
als Konstruktorargument dem HSSFWorkbook Objekt mitgegeben werden. Mit Hilfe der
HSSFWorbook Methode getSheetAt( int ) kann man nun auf die einzelnen Worksheet
zugreifen. Die Nummerierung beginnt hier wie bei den Feldern ebenfalls bei null.

  POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(“wb.xls“));
  HSSFWorkbook wb = new HSSFWorkbook( fs );
  HSSFSheet sheet = wb.getSheetAt(0);

4.4 Weitere HSSF Aspekte im Detail

Nach der kurzen Einführung wie man eine Excel Datei erstellt bzw. liest, möchte ich nun
auf ein paar wichtige Aspekte von HSSF näher eingehen. Eine detailliertere Anleitung wie
man mit der HSSF API arbeitet, ist im Anhang bei den Quellenangaben unter Punkt [2] zu
finden. Ausserdem soll an dieser Stelle auf die JavaDoc [3] Dokumentation des Projektes
verwiesen werden.

4.4.1 HSSF Cells

Zellen können von einem der folgenden Typen sein:

       •   CELL_TYPE_NUMERIC    Diese Zellen dürfen nur Zahlen beinhalten.
       •   CELL_TYPE_STRING     Diese Zellen können nur Strings beinhalten keine
                                Zahlen.
       •   CELL_TYPE_BLANK      Ein leere Zelle.
       •   CELL_TYPE_BOOLEAN    Diese Zellen können nur Ja(1)/Nein(0) beinhalten.
       •   CELL_TYPE_ERROR
       •   CELL_TYPE_FORMULA    Diese Zellen beinhalten eine Zeichenkette, die
                                aber als Formel interpretiert wird.
                                (Das Gleichheitszeichen wird nicht benötigt)

R. Strittmatter, FH-Aargau                                                     Seite 11/28
JakartaPOI                                                     Weitere HSSF Aspekte im Detail

Der Zellentyp wird implizit gesetzt, wenn man der Zellen entsprechende Werte mittels der
Methode setCellValue(...) zuweist.

       Bsp: cell.setCellValue( 1.1 ) weiss der Zelle automatisch den Typ „Numeric“ zu.

Explizit kann man den Typ der Zelle auch mit der HSSFCell Methode setCellType
( HSSFCell.Celltype ) setzen, wobei Celltype einer der oberen Werte annehmen muss.

Ist der Typ einer Zelle einmal gesetzt, kann man die Zelle mit Hilfe der entsprechenden
typbezogenen Getter/Setter Methoden lesen bzw. Schreiben.

               cell.get/setBooleanCellValue()   für Zellen vom Typ Boolean
               cell.get/setCellFormula()        für Zellen vom Typ Formula
               cell.get/setErrorCellValue()     für Zellen vom Typ Error
               cell.get/setNumericCellValue()   für Zellen vom Typ Numeric
               cell.get/setStringCellValue()    für Zellen vom Typ String

Wird auf eine Zelle eine Getter/Setter Methode eines anderen Zellentyps aufgerufen, so
wird eine Exception geworfen.

4.4.2 Zellen Formatierung

Jeder einzelnen Zelle kann ein HSSFCellStyle Objekt zugewiesen werden. Die
HSSFCellStyle Klasse legt Anzeigeattribute wie Farbe, Schrift, Höhe, Breite ,etc für die
jeweilige Zelle fest. Für komplexere Attribute wie Schrift und Farbe bietet die HSSF API,
die zusätzlichen Klassen HSSFFont und HSSFColor, welche die Arbeit ein wenig
vereinfachen.

Es ist zu beachten, dass man eine neuse HSSFCellStyle Objekt immer, von einem
HSSFWorkbook Objekt mittels der Methode createCellSytle() kreieren sollte.

R. Strittmatter, FH-Aargau                                                        Seite 12/28
JakartaPOI                                                       Weitere HSSF Aspekte im Detail

4.4.2.1 Ausrichtung Optionen

Für die Ausrichtung des Textes bzw. Wertes einer Zelle stehen folgende Möglichkeiten
zur Verfügung:

               HSSFCellStyle.ALIGN_CENTER
               HSSFCellStyle.ALIGN_CENTER_SELECTION
               HSSFCellStyle.ALIGN_FILL
               HSSFCellStyle.ALIGN_GENERAL
               HSSFCellStyle.ALIGN_JUSTIFY
               HSSFCellStyle.ALIGN_RIGHT
               HSSFCellStyle.ALIGN_LEFT

Um einer Zelle einen Stil zuweisen zu können, muss man von einem Workbook Objekt ein
Objekt von Typ HSSFCellStyle anfordern, dies geschieht mit dem Aufruf
workbook.createStyle(). Das so erhaltene HSSFCellStyle Objekt kann man dann mit der
Methode setAlignment( HSSFCellSytle.ALIGN_X ) einen Stil zuweisen. Hat man nun ein
HSSFCellStyle Objekt nach Wunsch kreiert, kann man es mit der HSSFCell Methode
setCellStyle(...) einer Zelle zuweisen.

Einen Zellen-Text kann man auch vertikal ausrichten, dies ist mit der Methode
setVerticalAlignment(...) eines HSSFCellSytle Objekt möglich. Auch für diese Methode
sind statische Konstanten definiert, mit welchen man die Ausrichtung bestimmen kann
(Bsp: HSSFCellStyle.VERTICAL_CENTER).

    HSSFCellStyle style = workbook.createCellStyle();
    style.setAlignment(HSSFCellStyle.ALIGN_LEFT);
    style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
    cell.setCellStyle(style);

R. Strittmatter, FH-Aargau                                                          Seite 13/28
JakartaPOI                                                    Weitere HSSF Aspekte im Detail

4.4.2.2 Zellen Ränder

Ähnlich wie das bei dem Ausrichtungsstil einer Zelle geschieht, können auch die Ränder
einer Zelle durch ein HSSFCellStyle Objekt festgelegt werden. Dafür stellt die
HSSFCellStyle Klasse die folgenden Methoden zur Verfügung.

       •   setBorderBottom(...)
       •   setBorderLeft(...)
       •   setBorderRight(...)
       •   setBorderTop(...)

Auch hierfür sind in der HSSF-API Konstanten definiert, welche man als Parameter für die
einzelnen Methoden setzen kann. Mit den Zuweisungs- Methoden setBorderXXXColor(...)
kann man den einzelnen Rändern auch noch eine Farbe geben.

4.4.2.3 Füllungen und Farben

Um einer Zelle eine Farbe zuzuweisen, müssen zwei Schritte gemacht werden, erstens
muss einem HSSFCellStyle Objekt eine Farbe zugewiesen werden, dies geschieht mit
setFillBackgroundColor(...) oder setFillForegroundColor(...), anschliessend muss jeweils
noch ein Füllmuster mit setFillPatern(...) gesetzt werden.

Die Werte der Füllmuster sind als statische Attribute in der Klasse HSSFCellStyle
definiert, als Beispiel sollen hier SOLID_FOREGROUND, SPARSE_DOTS oder
SQUARES dienen, weitere Attribute können aus der API Dokumentation des Projekts
entnommen werden.

Um die Farben zu definieren, gibt es im Paket ...hssf.util die Klasse HSSFColor, wo eine
Palette von Farben schon vordefiniert ist. Die Folgenden paar Codezeilen sollen die
Handhabung aufzeigen.

     HSSFCellStyle style = workbook.createCellStyle();
     style.setFillForegroundColor( HSSFColor.RED.index );
     style.setFillPatern( HSSFCellStyle.SOLID_FOREGROUND );
     cell.setCellStyle( style );

R. Strittmatter, FH-Aargau                                                       Seite 14/28
JakartaPOI                                                    Weitere HSSF Aspekte im Detail

4.4.2.4 Arbeiten mit Schriften

Um mit unterschiedlichen Schriften arbeiten zu können, haben die Entwickler ebenfalls
eine spezielle Klasse HSSFFont zu Verfügung gestellt, welche bei der Arbeit mit den
Schriften unterstützt soll.
Als Beispiel soll die Schrift einer Zelle mit einer 14 Punkt Courier New Schrift mit Stil
kursiv und fett versehen werden.

   HSSFFont font = workbook.createFont();
   font.setFontHeightInPoints( (short) 14 );
   font.setFontName( “Courier New“ );
   font.setItalic(true);
   font.setBoldWight(HSSFFont.BOLDWEIGHT_BOLD ); //oder BOLDWEIGHT_NORMAL
   HSSFCellStyle style = workbook.createCellSytle();
   style.setFont(font);
   cell.setText( “Font Text“ );
   cell.setCellStyle(style);

Einem Font kann man auch, wie wir das in dem letzten Kapitel gesehen haben, durch die
Methode font.setColor(...) eine Farbe zuweisen. Allerdings muss man hier kein Füllmuster
zuweisen.

R. Strittmatter, FH-Aargau                                                       Seite 15/28
JakartaPOI                                                             Weitere HSSF Aspekte im Detail

4.4.2.5 Zellen verbinden

Um zwei Zellen miteinander zu verbinden, wird aus dem Package ...hssf.util die
Hilfsklasse Region (Achtung nicht HSSFRegion) verwendet.

                   // Region(RowFrom, CellFrom , RowTo , CellTo   )
    Region reg = new Region(1       , (short) 1, 2     , (short)2 );
    sheet.addMergedRegion( reg );
    HSSFRow row = sheet.createRow(1);
    row.createCell((short)1).setCellValue( "Hallo Excel" );
    // Dieser Zelltext ist von der Region verdeckt:
    row.createCell((short)2).setCellValue( "Hidden" );

In dem Beispiel wird von Reihe eins, Zelle eins bis Reihe zwei; Zelle zwei verbunden (die
short Werte spezifizieren die Zeilennummern). Nicht zu vergessen ist hier, dass die
Nummerierung der Zellen und Reihen bei null beginnt.
Möchte man nun einen Wert in die definierte Region setzen, so muss dieser in die erste
Zelle, welche aus der ersten Reihe, die die Region definiert, erstellt worden ist, gesetzt
werden (also in die Reihe und Zelle oben links der definierten Region). Ansonsten wird der
Wert von der definierten Region überdeckt.

Das folgende Bild zeigt die verbundene Region welche mit dem vorhergehenden Code-
Beispiel erzeugt wurde.

R. Strittmatter, FH-Aargau                                                                Seite 16/28
JakartaPOI                                                            Weitere HSSF Aspekte im Detail

4.4.2.6 Zeichnen von Figuren

POI unterstützt das Zeichnen von Figuren in einem Excel Dokument, die in einer
hierarchischen Ordnung von Gruppen und Figuren organisiert sind. Das Element, auf dem
alle Figuren gezeichnet werden, wird „Patriarch“ genannt. Der Patriarch ist nicht auf dem
Excelsheet sichtbar und es kann pro Sheet nur einen Patriarchen geben. (Man kann sich
den Patriarchen als Glasplatte über dem Dokument vorstellen, auf der gezeichnet wird.)
Mit dem Aufruf der Methode createDrawingPatriarch() auf einem HSSFSheet Objekt wird
ein neuer Patriarch erstellt. Falls schon ein anderer Patriarch vorhanden ist, werden alle
Zeichnungsobjekte mit diesem gelöscht.

Um Zeichnungsobjekte zu erstellen sind folgende Schritte notwendig:

       •   Erstellen eines Patriarchen
       •   Erstellen eines Ankers, um die Zeichnung auf dem Blatt zu positionieren
       •   Informieren des Patriarchen, dass dieser ein Zeichnungobjekt erstellen soll.
       •   Zuweisen eins Stils (line, oval, rectangle, etc) an das Zeichnungsobjekt
       •   Setzen von weiteren Stil Eigenschaften für die Figur.

    HSSFPatriarch patriarch = sheet_mita.createDrawingPatriarch();
    HSSFClientAnchor a = new HSSFClientAnchor(0, 100, 0, 100, (short)1, 5, (short)6, 5 );
    HSSFSimpleShape shape = patriarch.createSimpleShape(a);
    shape.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE);

Ein HSSFClientAnchor Objekt definiert ein Rechteck, in dem eine Figur platziert und
verankert werden kann. Dem Konstruktor werden dabei folgende Werte übergeben.

       HSSFClientAnchor( x1, y1, x2, y2, col1, row1, col2, row2 )

               •   col1, row1 :      Zelle oben links
               •   col2, row2 :      Zelle unten rechts
               •   x1, y1     :      Offset von der rechten oberen Zellenecke aus
                                     (Für die Zelle oben links)
               •   x2, y2     :      Offset von der rechten oberen Zellenecke aus
                                     (Für die Zelle unten rechts)

R. Strittmatter, FH-Aargau                                                                  Seite 17/28
JakartaPOI                                                     Weitere HSSF Aspekte im Detail

4.4.2.7 Arbeiten mit Formeln

Das HSSF Projekt ist bestrebt, eine möglichst vollständige Formel Unterstützung
nachzubilden. Bis jetzt werden folgende Features unterstützt (Auszug der wichtigsten
Punkte).

               •   Zellen Referenzen
               •   Zeichenketten, Integer und Fliesskommazahlen Literale
               •   Relative und absolute Referenzen
               •   Arithmetische und logische Operationen
               •   Formeln Rückgabewerte (Nummern oder Zeichenketten)

Formeln kann man einer Zelle mit der Methode setCellFormula( “formelString“ ) zuweisen
oder mit dem Pendant getCellFormula() abfragen. Die übergebene Formelzeichenkette
wird von einem Parser in Token zerlegt welche nach der umgekehrt polnischen Notation
gespeichert, werden. Diese Notation ist nämlich die Art, wie MS Excel die Formeln zur
Weiterverarbeitung abspeichert.

                String formel = "SUM(E7:E10)";
                cell.setCellFormula(formel);

R. Strittmatter, FH-Aargau                                                        Seite 18/28
JakartaPOI                                                   JakartaPOI in Webanwendungen

5 JakartaPOI in Webanwendungen

Für das Versenden von Daten an den Client von einer Webanwendung aus, werden
Formate benötigt, welche die gängigsten Applikationen die in der Industrie eingesetzt
werden, verarbeiten können. Zu diesen Anwendungen gehören ohne Zweifel die MS
Office Produkte Word und Excel.

Um eine Daten im Excel- Format an den Client zu senden, gibt es zwei verschiedenen
Möglichkeiten. Man könnte dem Client lediglich eine CSV-Datei (Comma Separated Value
File Format) oder eine HTML-Tabelle senden. Durch das Setzen des Dokumententyps
application/vnd.ms-excel im HTTP Response Header wird der Browser vom
Server beauftragt, diese Daten mit MS Excel einzulesen und zu verarbeiten.

Excel ist in der Lage, das erhaltene Format zu erkennen und in sein eigenes zu
konvertieren. Wird eine HTML Tabelle gesendet, übernimmt Excel sogar die
Zellengrössen und Farben. Ein Nachteil dieser Variante ist, dass nicht davon
ausgegangen werden kann, dass auf allen Client-Systemen MS Excel installiert ist.

Darum eignet sich die zweite Variante besser, bei der auf dem Server eine Excel Datei
erzeugt und diese mittels Bytestrom an den Client gesendet wird. (Der Dokumententyp im
HTTP Header muss auch hier auf application/vnd.ms-excel gesetzt werden.) Denn
es kann davon ausgegangen werden, dass die meisten professionellen Anwendungen auf
dem Markt eine korrekt erstellten Excel Datei importieren können und somit in der Lage
sind, die Daten weiter zu verarbeiten. Dies ist mit CSV-Dateien oder HTML Tabellen nicht
gewährleistet. Also ein guter Grund um mit dem JakartaPOI Projekt in Java Anwendungen
zu arbeiten.

In meinem Servlet Beispiel (der Quellcode ist im Anhang zu finden), soll eine einfache
Excel Datei eingelesen werden, die Daten sollen mittels der HSSF API neu formatiert
und als neue Excel Datei an den Client gesendet werden. Dabei sollen ein paar der im
HSSF Teil präsentierte Aspekte genutzt werden.

Hat man das Excel Dokument mittels HSSF erstellt und wunschgemäss formatiert im
Speicher, hat man aus einer Webanwendung wiederum zwei Möglichkeiten, es dem Client
verfügbar zumachen.

R. Strittmatter, FH-Aargau                                                     Seite 19/28
JakartaPOI                                                   JakartaPOI in Webanwendungen

Man könnte das Dokument mittels einem FileOutputStream in eine temporäre Datei
schreiben und einen Link an den Client schicken, unter dem er die Datei abholen kann.
Dies bringt allerdings den Nachteil mit, dass nicht mehr gebrauchte Dateien von einem
Dienst regelmässig gelöscht werden müssen, zudem kann dies ein Sicherheitsrisiko
bedeuten, da entsprechende Lese-Rechte bei den einzelnen Dateien gesetzt sein
müssen, was leider nicht so trivial ist.

Die bessere Alternative ist den Outputstream des HSSFWorkbook Objektes direkt mittels
dem HttpServletResponse an Client zu senden, hierzu muss folgenden Punkten
Beachtung geschenkt werden.

       •   Als Dokumenttyp im HTTP Header muss application/vnd.ms-excel
           gesetzt sein.

       •   Des weiteren ist zu beachten, dass bei einem Client der zwei generierte
           Dokumente gleichzeitig bearbeiten möchte, die Dateinamen unterschiedlich sein
           müssen, da Excel zwei Dateien mit gleichem Namen nicht gleichzeitig öffnen
           kann. Ein eindeutiger Dateiname kann im Servlet Response Header durch die
           Methode setHeader("Content-Disposition", "filename=" + filename)
           gesetzt werden.

       •   Wie aus den Newsgroups zum Thema POI zu erfahren ist, ist das Arbeiten mit
           POI auf dem Server sehr Rechen- und Speicherintensiv. Mann sollte daher
           versuchen, die Grösse der Dokumente, die zu generieren sind, einzuschränken.
           Anregungen zur Performance- Optimierung sind in [6] zu finden.

R. Strittmatter, FH-Aargau                                                     Seite 20/28
JakartaPOI                                                                          Fazit

6 Fazit

Das Jakarta POI ist sicherlich ein sehr ambitioniertes Projekt, auf das viele
Entwickler/innen in der Java Welt, welche ihre Daten auf irgend eine Weise für die
Microsoft Office Tools zur Verfügung stellen wollen, gewartet haben.
Dies zeigt sich ebenfalls darin, dass die POI APIs in andere Projekten wie dem Reporting
Projekt JasperReports oder dem Cocoon Projekt , für das es ebenfalls HSSF Serializer
gibt, verwendet werden um MS Excel Dokumente generieren zu können.

Obwohl noch nicht alle Subprojekte von POI reif genug für die kommerzielle Entwicklung
sind, lohnt sich ein Blick insbesondere auf HSSF trotzdem. Ebenfalls sollte man die
weitere Entwicklung der andere Teile im Auge behalten, denn die Entwickler arbeiten
ständig daran, ihre Projekte zu verbessern und weiter zu treiben.

Besonders wird in der letzten Zeit intensiv daran gearbeitet, das Performance und
Speicherverbrauch-Problem von POI zu minimieren.

R. Strittmatter, FH-Aargau                                                    Seite 21/28
JakartaPOI                                                         Literaturverzeichnis und Quellenangaben

A) Literaturverzeichnis und Quellenangaben

       [1]     How To Use the POIFS APIs: http://jakarta.apache.org/poi/poifs/how-to.html
               Geprüft im Mai 2004

       [2]     Busy Developers Guide: http://jakarta.apache.org/poi/hssf/quick-guide.html
               Geprüft im Mai 2004

       [3]     JakartaPOI Project Page: http://jakarta.apache.org/poi/index.html
               Geprüft im Mai 2004

       [4]     Read and Write MS Excel Spreadsheets using Jakarta POI,
               von Shantosh Shanbhag: http://www.ociweb.com/jnbMar2004.html
               Geprüft im Mai 2004

       [5]     Reading and Writing Excel Files with POI
               von A. Sengupta, A. Oliver and R. Klute:
               http://www.onjava.com/pub/a/onjava/2003/04/16/poi_excel.html
               Geprüft im Mai 2004

       [6]     POI Performance Tuning Examples: http://www.codebits.com
               Geprüft im Mai 2004

       [7]     It's POI-fect   von Tony Sintes:
               http://javaworld.com/javaga/2002-05/01-ga-0503-excel3_p.html
               Geprüft im Mai 2004

       [8]     Learn to Read and Write Microsoft Excel Documents with Jakarta's POI
               von Samudra Gupta http://www.devx.com/Java/Article/17301
               Geprüft im Mai 2004

       [9]     Java Magazin Artikel - Java meets Office
               von Bernhard Scherm und Jürgen Stöckel

R. Strittmatter, FH-Aargau                                                                     Seite 22/28
JakartaPOI                                                                            Servlet Quellcode

B) Servlet Quellcode

Dieses Servlet liest Daten aus einer Excel Datei ein und stellt diese in einem neuen, durch
HSSF generiertem Excel Dokument dar. Dieses Dokument wird per Stream an den
Browser gesendet.

import   java.io.FileInputStream;
import   java.io.IOException;
import   java.io.OutputStream;
import   java.util.Collection;
import   java.util.LinkedList;
import   java.util.Iterator;

import   javax.servlet.ServletConfig;
import   javax.servlet.ServletException;
import   javax.servlet.http.HttpServlet;
import   javax.servlet.http.HttpServletRequest;
import   javax.servlet.http.HttpServletResponse;

import   org.apache.poi.hssf.usermodel.HSSFCellStyle;
import   org.apache.poi.hssf.usermodel.HSSFClientAnchor;
import   org.apache.poi.hssf.usermodel.HSSFFont;
import   org.apache.poi.hssf.usermodel.HSSFPatriarch;
import   org.apache.poi.hssf.usermodel.HSSFSheet;
import   org.apache.poi.hssf.usermodel.HSSFRow;
import   org.apache.poi.hssf.usermodel.HSSFSimpleShape;
import   org.apache.poi.hssf.usermodel.HSSFWorkbook;
import   org.apache.poi.hssf.usermodel.HSSFCell;
import   org.apache.poi.poifs.filesystem.POIFSFileSystem;
import   org.apache.poi.hssf.util.HSSFColor;
import   org.apache.poi.hssf.util.Region;

public class HSSFServlet extends HttpServlet {

         private String inputFileName = null;

         public void init( ServletConfig config ) throws    ServletException {
                super.init(config);

                inputFileName = "Servlet_Input.xls";
         }

         public void destroy() {}

         protected void doGet( HttpServletRequest req, HttpServletResponse resp ) throws
                                                              ServletException, IOException {
                this.processRequest(req,resp);
         }

         protected void doPost( HttpServletRequest req, HttpServletResponse resp ) throws
                                                              ServletException, IOException {
                this.processRequest(req,resp);
         }

R. Strittmatter, FH-Aargau                                                                  Seite 23/28
JakartaPOI                                                                           Servlet Quellcode

       protected void processRequest( HttpServletRequest req, HttpServletResponse resp ) throws
                                                                ServletException, IOException {

                 String filename = "newExcel.xls";

                 resp.setContentType("application/vnd.ms-excel");
                 resp.setHeader("Content-Disposition", "filename=" + filename);

                 OutputStream out = resp.getOutputStream();
                 generateExcelFile(out);
                 out.close();
       }

       private    void generateExcelFile( OutputStream out ) throws IOException {

                 Collection mbCol = this.readExcelFile();

                 // Erstelle eine neue Arbeitsmappe mit einem Sheet:
                 HSSFWorkbook workbook = new HSSFWorkbook();
                 HSSFSheet sheet_mita = workbook.createSheet("Neue Mitarbeiter Liste");

                 // Setze einen Titel:
                 Region regTitel = new Region( 0, (short) 0, 1, (short) 3);
                 sheet_mita.addMergedRegion(regTitel);
                 HSSFCell titel = sheet_mita.createRow(0).createCell((short)0);
                 titel.setCellValue("HSSF Generierte Mitarbeiter Liste");

                 HSSFCellStyle titleStyle = workbook.createCellStyle();
                 titleStyle.setAlignment(HSSFCellStyle.ALIGN_LEFT);
                 titleStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);

                 HSSFFont titleFont = workbook.createFont();
                 titleFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
                 titleFont.setFontHeightInPoints((short)16);
                 titleFont.setFontName("Times New Roman");

                 titleStyle.setFont(titleFont);
                 titel.setCellStyle(titleStyle);

                 // Setze eine Kopfzeile:
                 HSSFFont         headFont = workbook.createFont();
                 HSSFCellStyle headStyle = workbook.createCellStyle();
                 HSSFRow          headRow      = sheet_mita.createRow(4);

                 headRow.setHeightInPoints(25);
                 sheet_mita.setColumnWidth((short)1, (short)4000 );
                 sheet_mita.setColumnWidth((short)2, (short)4000 );
                 sheet_mita.setColumnWidth((short)3, (short)3500 );

                 headStyle.setFillForegroundColor( HSSFColor.PALE_BLUE.index );
                 headStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
                 headStyle.setBorderBottom(HSSFCellStyle.BORDER_MEDIUM);
                 headStyle.setBorderLeft(HSSFCellStyle.BORDER_HAIR);
                 headStyle.setBorderRight(HSSFCellStyle.BORDER_HAIR);
                 headStyle.setBorderTop(HSSFCellStyle.BORDER_HAIR);

                 headFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);

R. Strittmatter, FH-Aargau                                                                 Seite 24/28
JakartaPOI                                                                                Servlet Quellcode

               headStyle.setFont(headFont);

               headRow.createCell((short)1).setCellValue("Name");
               headRow.createCell((short)2).setCellValue("Vorname");
               headRow.createCell((short)3).setCellValue("Geburtsdatum");
               headRow.createCell((short)4).setCellValue("Gehalt");
               headRow.createCell((short)5).setCellValue("Abteilung");

               for(int i = 1; i < 6; i++ ) headRow.getCell((short)i).setCellStyle(headStyle);

               // Daten aus Bean einfügen:
               Iterator iter = mbCol.iterator();
               int startRow = headRow.getRowNum() + 2;
               while( iter.hasNext() ) {
                      MitarbeiterBean mb = (MitarbeiterBean)iter.next();

                        HSSFRow row = sheet_mita.createRow(startRow);

                        row.createCell((short)1).setCellValue(     mb.getName()      );
                        row.createCell((short)2).setCellValue(     mb.getVorname()   );
                        row.createCell((short)3).setCellValue(     mb.getGebDate()   );
                        row.createCell((short)4).setCellValue(     mb.getGehalt()    );
                        row.createCell((short)5).setCellValue(     mb.getAbtNr()     );

                        startRow++;
               }

               // Zeichne eine Line:
               HSSFPatriarch   patriarch = sheet_mita.createDrawingPatriarch();
               HSSFClientAnchor a = new HSSFClientAnchor(0, 100, 0, 100, (short)1, startRow,
                                                                         (short)6, startRow );
               HSSFSimpleShape shape = patriarch.createSimpleShape(a);
               shape.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE);

               // Gesamt Summe der Gehälter berechnen:
               sheet_mita.createRow(startRow+1).createCell((short)4).setCellValue( "Gesammt" );
               String formel = "SUMME(E7:E" + (startRow) + ")";
               sheet_mita.createRow(startRow+2).createCell((short)4).setCellFormula(formel);

               workbook.write(out);
       }

       private Collection readExcelFile() throws IOException{

               Collection col = new LinkedList();

               POIFSFileSystem fs      = new POIFSFileSystem(
                                                      new FileInputStream(this.inputFileName));
               HSSFWorkbook    wb      = new HSSFWorkbook( fs );
               HSSFSheet       sheet   = wb.getSheet("Mitarbeiter");

               int     lastRowNumber           =   sheet.getLastRowNum();
               int     headerRowNumber         =   sheet.getFirstRowNum();
               short   headerFristCellNumber   =   sheet.getRow(headerRowNumber).getFirstCellNum();
               short   headerLastCellnumber    =   sheet.getRow(headerRowNumber).getLastCellNum();

R. Strittmatter, FH-Aargau                                                                      Seite 25/28
JakartaPOI                                                                                 Servlet Quellcode

               System.out.println(   "HeaderRow        :"   +   headerRowNumber );
               System.out.println(   "HeaderFirsCell   :"   +   headerFristCellNumber );
               System.out.println(   "HeaderLastCell   :"   +   headerLastCellnumber );
               System.out.println(   "LastRow          :"   +   lastRowNumber );

               // Lese die einzelnen Zeilen ein. (Achtung: Zellen Mapping auf Bean muss stimmen.)
               // Erste Zeile wird als Header betrachtet und nicht eingelesen.
               try {
                 for( int i = 1; i  0
                          && !(sheet.getRow(i).getPhysicalNumberOfCells() < 5 )) {
                              MitarbeiterBean mbean = new MitarbeiterBean();
                              mbean.setName   ( sheet.getRow(i).getCell((short) 0).
                                                                   getStringCellValue() );
                              mbean.setVorname( sheet.getRow(i).getCell((short) 1).
                                                                   getStringCellValue() );
                              mbean.setGebDate( sheet.getRow(i).getCell((short) 2).
                                                                   getDateCellValue()    );
                              mbean.setAbtNr ( (int) sheet.getRow(i).getCell((short) 3).
                                                                   getNumericCellValue() );
                              mbean.setGehalt ( sheet.getRow(i).getCell((short) 4).
                                                                   getNumericCellValue() );
                              col.add(mbean);
                      }
                      // else skip the row -> it's empty
                 }
               }catch(Exception e){
                      System.err.println("Read-Error" + e.getMessage());
               }

               return col;
       }

       public String getServeltInfo() {
              return "HSSF Servlet Example";
       }
}

R. Strittmatter, FH-Aargau                                                                       Seite 26/28
JakartaPOI                                                                                POIFS Beispiel

C) POIFS Beispiel

Listing des Quellcodes der die Verzeichnisstruktur einer OLE2CDF Datei ausgibt und falls
ein Excel Dokument übergeben wird, dessen Workbook-Stream anzeigt.
import   java.io.BufferedInputStream;
import   java.io.FileInputStream;
import   java.io.FileNotFoundException;
import   java.io.IOException;
import   java.io.InputStream;
import   java.util.Iterator;

import   org.apache.poi.poifs.filesystem.DirectoryEntry;
import   org.apache.poi.poifs.filesystem.DocumentEntry;
import   org.apache.poi.poifs.filesystem.DocumentInputStream;
import   org.apache.poi.poifs.filesystem.Entry;
import   org.apache.poi.poifs.filesystem.POIFSFileSystem;

public class POIFSBeispiel {

         public void run( String filename ) throws IOException {

                InputStream is      = new FileInputStream( filename );
                POIFSFileSystem fs = new POIFSFileSystem( new BufferedInputStream( is ) );
                DirectoryEntry dirRoot = fs.getRoot();
                listDir( dirRoot, 0 );

                System.out.println("\n\n-------------Workbook Stream--------------------");

                // Versuche den Workbook-Stream auf der Konsole auszugeben:
                // Nur bei MS Excel Dokumenten möglich.

                try {
                        DocumentEntry doc = (DocumentEntry)dirRoot.getEntry("Workbook");
                        DocumentInputStream dis = new DocumentInputStream( doc );
                        byte[] buffer = new byte[1024];
                        while( dis.read(buffer) > 0 ) {
                               System.out.write(buffer);
                        }
                        dis.close();

                }catch( FileNotFoundException e ) {
                       System.err.println("File has no workbook entry.");
                }
                System.out.flush();
                is.close();
         }

         private void listDir( DirectoryEntry dir, int level ){
                Iterator iter = dir.getEntries();
                while( iter.hasNext() ) {
                        Entry entry = (Entry) iter.next();
                        if( entry.isDirectoryEntry() ) { // DirectoryEntry
                               listDir( (DirectoryEntry) entry, level + 1);
                        }
                        else { // DocumentEntry
                               for( int i = 0; i < level; i++ ) System.out.print("\t");
                               System.out.println(entry.getName());
                        }
                }
         }
}

R. Strittmatter, FH-Aargau                                                                   Seite 27/28
JakartaPOI                                                                              HPSF Beispiel

D)HPSF Beispiel

Im Folgenden ist der Quelltext des Beispiel wiedergegeben, mit dem die
SummaryInformation Eigenschaften einer OLE2CDF Datei ausgeben kann.
import java.io.FileInputStream;
import java.io.IOException;

import   org.apache.poi.hpsf.PropertySetFactory;
import   org.apache.poi.hpsf.SummaryInformation;
import   org.apache.poi.poifs.eventfilesystem.POIFSReader;
import   org.apache.poi.poifs.eventfilesystem.POIFSReaderEvent;
import   org.apache.poi.poifs.eventfilesystem.POIFSReaderListener;

public class HPSFBeispiel implements POIFSReaderListener {

         public void processPOIFSReaderEvent(POIFSReaderEvent event) {

                SummaryInformation si = null;

                try {
                       si = (SummaryInformation)PropertySetFactory.create( event.getStream() );
                }
                catch ( Exception e) {
                       throw new RuntimeException( "Property set stream \"" + event.getPath() +
                                                     event.getName() + "\": " + e );
                }

                System.out.println("Liste der SummaryInformation:");
                System.out.println("-----------------------------");
                System.out.println("");
                System.out.println("ApplicationName:\t" + si.getApplicationName() );
                System.out.println("Author         :\t" + si.getAuthor() );
                System.out.println("LastAuthor     :\t" + si.getLastAuthor() );
                System.out.println("LastSaveDate   :\t" + si.getLastSaveDateTime() );
                System.out.println("PageCount      :\t" + si.getPageCount() );
                System.out.println("Titel          :\t" + si.getTitle() );
                System.out.println("LastPrinted    :\t" + si.getLastPrinted() );
                System.out.flush();

         }

         public static void main(String[] args) throws IOException {

                String filename = args[0];

                // So wird mit der Event-Methode eine Datei eingelesen
                // \005 im unten übergebenen String ist das Mapping
                // auf das Zeichen mit dem Dezimalwert von 5
                POIFSReader reader = new POIFSReader();
                reader.registerListener( new HPSFBeispiel(), "\005SummaryInformation" );
                reader.read( new FileInputStream(filename) );
         }
}

R. Strittmatter, FH-Aargau                                                                 Seite 28/28
Sie können auch lesen