Da ich meine Rechnungen automatisch generiert und als PDF konvertiert haben möchte, habe nach einer Lösung gesucht, wie ich die Rechnungsdaten aus einer Datenquelle in der Template einsetzten kann, und am Ende eine PDF bekomme. Klar sind Report-Generatoren dafür auf der Welt, aber meine Vorlagen möchte ich nicht für Eclipse BIRT oder Jasper schreiben, sondern in Word bzw. OpenOffice. RTF ist relativ leicht zu schreiben und für ein Template meines Erachtens ganz gut. Meine Gedanken kreisten daher einige Zeit um RTF->PDF, doch da gibt es keine freie Lösung. Auch Wege wie RTF->FO->PDF sind möglich, aber dafür gibt es ebenfalls keine leichtgewichtigen freien Lösungen.
Schon für meinen PowerPoint->PDF-Konverter habe ich mit OpenOffice gearbeitet und das klappte ganz gut. Das habe ich für meine Templates nun wieder überlegt — ein recht harter Weg für simple RTFs zwar, aber es funktioniert. Doch anstatt RTF zu nutzen, wollte ich gleich das XML-Format verwenden. Dazu muss man wissen, dass OO ein Zip-Archiv für das OO-Dokument vorsieht und dort in einer XML-Datei den Content ablegt. Mit der großartigen Open-Source-Bibliothek https://truezip.dev.java.net/ ist der Zugriff auf Archive sehr einfach.
Mit TrueZIP ist eine einfache Lösung entstanden, ein OO-Dokument mit Template-Anweisungen wie ${address} zu lesen, Ersetzungen vorzunehmen, und alles wieder zu schreiben. Diesen Text hier zu schreiben hat länger gedauert, als die 90 Zeilen Quellcode. Also los:
import java.io.*;
import java.nio.channels.FileChannel;
import de.schlichtherle.io.ArchiveDetector;
public class OpenOfficeUtils
{
public static void main( String[] args )
{
String source = "S:/Private/Traida/Bills/template.ods";
String destination = "S:/Private/Traida/Bills/bill1.ods";
copyFile( source, destination );
String content = readOpenOfficeContent( source );
content = content.replace( "${addressline1}", "Christian Ullenboom" );
writeOpenOfficeContent( destination, content );
}
public static String readOpenOfficeContent( String filename )
{
Reader is = null;
try
{
de.schlichtherle.io.File file = new de.schlichtherle.io.File( filename + "/content.xml", ArchiveDetector.ALL );
char[] fileContent = new char[ (int) file.length() ];
is = new de.schlichtherle.io.FileReader( file ); // TODO: <?xml version="1.0" encoding="UTF-8"?>
is.read( fileContent );
return new String(fileContent);
}
catch ( IOException e )
{
throw new IllegalArgumentException( e );
}
finally
{
try { is.close(); } catch ( Exception e ) { }
}
}
public static void writeOpenOfficeContent( String filename, String content )
{
Writer os = null;
try
{
de.schlichtherle.io.File file = new de.schlichtherle.io.File( filename + "/content.xml", ArchiveDetector.ALL );
os = new de.schlichtherle.io.FileWriter( file );
os.write( content );
}
catch ( IOException e )
{
throw new IllegalArgumentException( e );
}
finally
{
try { os.close(); } catch ( Exception e ) { }
}
}
public static void copyFile( String in, String out )
{
FileChannel inChannel = null;
FileChannel outChannel = null;
try
{
inChannel = new FileInputStream( new File(in) ).getChannel();
outChannel = new FileOutputStream( new File(out) ).getChannel();
inChannel.transferTo( 0, inChannel.size(), outChannel );
}
catch ( IOException e )
{
throw new IllegalArgumentException( e );
}
finally
{
try { inChannel.close(); } catch ( Exception e ) { }
try { outChannel.close(); } catch ( Exception e ) { }
}
}
}