15.09.2015
Author: Matija Paunovic

PHPWord-Vorlage

Wie fügt man eine Tabelle in eine PHPWord-Vorlage ein?

Meine Antwort zu dieser Frage ist: "Einfach!".

Z.B., wenn du eine *.DOCX Datei als ein Formular brauchst, z.B. eine Rechnung in einem Shop oder auf deiner Internetseite, dann kannst du hier meine Vorlage nutzen. Es brauchen nur noch die Variablen eingesetzt werden und eine Rechnung ist fertig.

In den letzten Wochen wurde mir dieselbe Frage öfters gestellt: Wie fügt man eine Tabelle in eine PHPWord-Vorlage ein? Es scheint die Antwort kann für viele nützlich sein. Darum schreibe ich diesen Blog-Beitrag. Alle folgenden Beispiele sind in PHP 5.5 und PHPOffice/PHPWord 0.12.0 geschrieben.

PHPWord-Vorlagen

Wie du vielleicht schon weist bietet dir PHPWord "Vorlagen-Verarbeitung" (eng. Template processing) an. Du kannst die Variablen mit dynamisch generiertem Inhalt ersetzen. Als erstes müssen wir den Prozessor instanziieren der dann unsere Vorlage grammatisch analysiert. Danach können wir ganz einfach die Variablen durch unseren Inhalt ersetzen.

$templateProcessor = new 
\PhpOffice\PhpWord\TemplateProcessor('resources/WorkTemplate.docx');
$templateProcessor->setValue($searchPattern, $replaceValue);

Es gibt jedoch eine Begrenzung: du kannst die Variablen nur mit einfachen Datentypen ersetzen. Die Dokumentation sagt folgendes: "Es ist nicht möglich neue OOXML Elemente direkt in die Vorlagendatei einzufügen während sie analysiert wird". :(

PHPWord-Lösung für eine Tabelle mit festgesetzter Spaltenanzahl

Für den Fall, dass du eine festgesetzte Spaltenanzahl hast, bist du im Vorteil, weil PHPWord dir eine transparente Möglichkeit gibt, um dynamische Werte in deiner vordefinierten Tabelle einzufügen.

$templateProcessor->cloneRow('column2', 3);

$templateProcessor->setValue('column2#1', htmlspecialchars('My first row));
$templateProcessor->setValue('column2#2', htmlspecialchars('My second row'));
$templateProcessor->setValue('column2#3', htmlspecialchars('My third row'));

$templateProcessor->setValue('column1#1', htmlspecialchars('My first col1));
$templateProcessor->setValue('column1#2', htmlspecialchars('My second col1'));
$templateProcessor->setValue('column1#3', htmlspecialchars('My third col1'));

Die erste Codezeile durchsucht die Tabellenzellen mit der Variable 'column2'. Falls die Variable existiert, wird PHPWord die Zeile N-mal kopieren (in diesem Fall drei Mal). Falls die Zeile mehrere Variablen enthält werden diese auch kopiert. Nach dem wir die Zeile geklont haben, können wir die Inhalte der Variablen festlegen. Beachte das '#' Zeichen und die Zahl dahinter!

PHPWord-Lösung für eine komplett dynamische Tabelle

Du benötigst eine komplett dynamische Tabelle wenn die Daten aus verschiedenen Datenquellen kommen, welche verschiedenen Spaltendefinitionen beinhalten. Diese Problematik setzt unseren ersten Lösungsweg außer Kraft. Wir müssen eine Alternative finden!

Den XML-Code in das Dokument injizieren

Ist dir aufgefallen, dass das oben genanntes Beispiel die PHP Methode "htmlspecialchars" nutzt (und das aus einem guten Grund). Falls wir ein Sonderzeichen in unserem String einfügen, kann es ein XML-Fehler geben. Es gibt fünf Sonderzeichen bei denen wir aufpassen müssen: ampersand (&), double quote ("), single quote ('), less than (<), and greater than (>).

PHPWord-Objekte zur Rettung

Da wir den Code in die Vorlage injizieren können, müssen wir den einfachsten Weg finden, um eine Tabellenstruktur zu konstruieren damit wir unsere Variable ersetzen können. Deshalb müssen wir wissen, wie PHPWord funktioniert.

PHPWord-Table-Element (Schritt eins - instanziieren des XML-Objektes)

PHPWord hat sehr gut definierte OOXML-Elemente. Eines dieser Elemente ist das Table-Element welches unter dem Namespace \PhpOffice\PhpWord\Element\Table gefunden werden kann. Das Element kann instanziert werden und es hat "addRow"- und "addCell"-Methoden. Leider fehlt eine "toString" Methode. :( Wir müssen herausfinden wie PHPWord Table-Objekte in String-Repräsentation konvertiert.

PHPWord-XMLWriter (Schritt zwei - Umwandlung des XML-Objektes in einen String)

Da wir eine *.DOCX Tabellen-Repräsentation brauchen, müssen wir herausfinden, welcher XMLWriter von PHPWord benutzt wird. Nach einer kurzen Inspektion habe ich herausgefunden, dass ein Word2007-TableWriter unter dem Namespace \PhpOffice\PhpWord\Writer\Word2007\Element\Table existiert.

Es ist an der Zeit zu sehen, ob wir eine String-Repräsentation von dem Table-Element bekommen können:

$table = new \PhpOffice\PhpWord\Element\Table();
/* We need the XMLWriter instance in order to output strings */
$objWriter = new \PhpOffice\PhpWord\Shared\XMLWriter();
$tableWrite = new \PhpOffice\PhpWord\Writer\Word2007\Element\Table($objWriter, $table);
$tableWrite->write();

echo $objWriter->getData();

Es hat funktioniert :)! Die letzte Codezeile gibt uns eine Repräsentation des Table-Elements im XML-Format <w:tbl>...</w:tbl> zurück.

Ich hoffe, der Artikel hat dir geholfen.
Bis zum nächsten mal. :)

Ein Beispiel findest du hier.