Apache ODF Toolkit, Templates befüllen …

Um z.B. Rechnungen im PDF Format zu erzeugen gibt es in der Java/Scala-Welt verschiedenen Ansätze. Einer ist sicher die Verwendung von iText (Lizenz aber ab 4.2 problematisch) oder JasperReports. Hiermit kann man schicke Sachen machen, aber mal eben so eine Vorlage zu erstellen ist nicht ohne und zumindest für den Laien fast unmöglich.
Da wäre es doch viel besser, wenn man ein Word- oder besser noch OpenOffice-Dokument nehmen könnte, dort Platzhalter definiert, die dann mit Werten gefüllt werden.
Mit Apache ODF Toolkit ist das im Prinzip auch kein Problem. Meine Platzhalter werden von $ eingerahmt, also z.B. $invoice.customer.name$. Folgender Code (Scala) skizziert die Umsetzung:

...
val templateOdt = TextDocument.loadDocument("Template.odt");

val searchItems = new TextNavigation("\\$[a-zA-Z_0-9.%]*\\$", templateOdt);
    
while (searchItems.hasNext()) {
      val placeholder: TextSelection = searchItems.nextSelection() match {
          case x: TextSelection => x
          case _ => null
      }
      val replace = placeholder.getText().replace("$", "") match {
          case "invoice.customer.name" => Some(customer.name)
          ...
          case _ => Some(placeholder.getText() + " not valid.")
      }
      if (replace.isDefined) {
          placeholder.replaceWith(replace.get);
      }
}

So weit so gut. Nun wollte ich die Rechnungsposten in einer Tabelle unterbringen. Das sollte so laufen, dass bei einem Treffer eines Rechnungsposten Platzhalters z.B. $invoice.item.text$ die Zeile als Vorlage für alle Posten genommen wird. Denn die Rechnung kann ja beliebige Posten haben, aber dazu sollte es ausreichen im Template nur eine Zeile zu definieren. Auch das funktionierte. Eine Zeile kann man wie folgt kopieren:

val copiedRow = row.getOdfElement().cloneNode(true)
row.getTable().getOdfElement().insertBefore(copiedRow, row.getOdfElement())

Jetzt fehlte ja nur noch, in der kopierten Zeile die Platzhalter mit einem Rechnungsposten bzw. dessen Attributen zu ersetzen. Auch das funktioniert mit replaceWith. Allerdings waren auf einmal die Formatierungen wie rechtsbündig oder fette Schrift verschwunden. Wie sich nach einigem Ausprobieren herausgestellt hat ist replaceWith ein wenig zerstörerisch, wenn es um eine Tabellenzelle geht. Mit folgendem Code habe ich das Problem umschifft:

if (replace.isDefined) {
    if (placeholder.isInstanceOf[CellSelection]) {
        val nodes = placeholder.asInstanceOf[CellSelection].getCell.getOdfElement().getChildNodes()
        for (i <- 0 to nodes.getLength() - 1) {
            nodes.item(i).setTextContent(nodes.item(i).getTextContent().replace(placeholder.getText(), replace.get))
        }
    } else
        placeholder.replaceWith(replace.get);
}
Dieser Beitrag wurde unter Java, Scala veröffentlicht. Setze ein Lesezeichen auf den Permalink.

Die Kommentarfunktion ist geschlossen.