Skip to content

DOCX-Template-Beispiele

Diese Seite zeigt typische Muster, wie ein Word-Template für flexiDok aufgebaut wird. flexiDok nutzt intern die Bibliothek docx-templates — die Befehlssyntax dieser Seite folgt ihrer Konvention.

Die Referenz aller Hilfsfunktionen (getComponentListForAllSectionsByChapterName, createImage, formatDate, …) finden Sie unter DOCX-Template-Funktionen.


Befehle im Überblick

flexiDok verwendet +++ als Befehls-Trennzeichen. Jeder Befehl steht zwischen zwei +++.

Befehl Bedeutung
+++INS ausdruck+++ Ergebnis eines Ausdrucks an der Stelle einfügen
+++EXEC code+++ JavaScript ausführen, nichts einfügen (für Variablendefinitionen, Vorverarbeitung)
+++FOR x IN liste++++++END-FOR x+++ Über eine Liste iterieren
+++IF bedingung++++++END-IF+++ Abschnitt nur bei erfüllter Bedingung einfügen
+++IMAGE bildobjekt+++ Bild einfügen
+++LINK ({url, label})+++ Hyperlink einfügen

Schleifenvariable mit $

Innerhalb einer FOR-Schleife muss der Name der Schleifenvariable mit $ präfixiert werden, z.B. +++INS $eintrag.name.value+++. Der zusätzliche Index des innersten Loops steht in $idx (0-basiert).


Typischer Aufbau eines Templates

Ein Report wird in der Regel so strukturiert:

  1. Vorbereitungsblock am Anfang: Listen aufbauen, Konstanten setzen, Hilfsfunktionen definieren (ein bis mehrere EXEC-Befehle)
  2. Inhaltsteil: Text mit INS, Tabellen mit FOR, bedingte Passagen mit IF

1. Vorbereitungsblock — Listen und Kennzeichen aufbauen

Am Anfang des Dokuments werden oft mehrere EXEC-Blöcke platziert, in denen Listen aus den Dokumentdaten gefiltert und kombiniert werden. Die Ergebnisse stehen danach im gesamten Template zur Verfügung.

+++EXEC
LISTE_A = getListFromChapterAndChapterType(`eintraege`, `TypA`);
LISTE_B1 = getListFromChapterAndChapterType(`eintraege`, `TypB`);
LISTE_B2 = getListFromChapterAndChapterType(`eintraege`, `TypB Variante`);
LISTE_B3 = getListFromChapterAndChapterType(`eintraege`, `TypB Variante Kombi`);

GESAMT_OHNE_KOMBI = [].concat(LISTE_B1, LISTE_B2);
GESAMT_ALLE      = [].concat(LISTE_B1, LISTE_B2, LISTE_B3);

IS_B1     = LISTE_B1.length > 0;
IS_B2     = LISTE_B2.length > 0;
IS_GESAMT = GESAMT_ALLE.length > 0;

SHOW_BLOCK = true;
if (LISTE_A.length == 0 && LISTE_B1.length == 0) {
  SHOW_BLOCK = false;
}
+++

Benennung von Variablen

In unseren Templates nutzen wir für diese Template-weiten Variablen meist GROSSBUCHSTABEN — das macht sie im Text gut erkennbar und vermeidet Namenskollisionen mit Feldern aus dem Dokument.

2. Tabellendaten aus mehreren Listen zusammensetzen

Ein häufiges Muster: Aus mehreren gefilterten Listen wird eine gemeinsame Tabelle aufgebaut, in der jede Zeile zusätzlich ein Kürzel und eine Beschreibung bekommt.

+++EXEC
TABELLE = [];

A_COUNT = 1;
for (let eintrag of LISTE_A) {
  let OBJ = {};
  OBJ[`KUERZEL`]    = ``;
  OBJ[`BESCHREIBUNG`] = ``;
  if (eintrag.ChapterTypes.length > 0 && eintrag.ChapterTypes[0] == `TypA`) {
    OBJ[`KUERZEL`]      = `A ` + A_COUNT;
    OBJ[`BESCHREIBUNG`] = `Beschreibung Typ A`;
    A_COUNT++;
    OBJ[`NUMMER`]    = eintrag.uebersicht.nummer.value + ` ` + eintrag.uebersicht.bezeichnung.value[0];
    OBJ[`KENNUNG`]   = eintrag.uebersicht.kennung.value;
    OBJ[`ZUSATZ`]    = eintrag.uebersicht.zusatz.value;
    TABELLE.push(OBJ);
  }
}

B_COUNT = 1;
for (let eintrag of LISTE_B1) {
  let OBJ = {};
  OBJ[`KUERZEL`]      = `B ` + B_COUNT;
  OBJ[`BESCHREIBUNG`] = `Beschreibung Typ B`;
  B_COUNT++;
  OBJ[`NUMMER`]    = eintrag.uebersicht.nummer.value + ` ` + eintrag.uebersicht.bezeichnung.value[0];
  OBJ[`KENNUNG`]   = eintrag.uebersicht.kennung.value;
  OBJ[`ZUSATZ`]    = eintrag.uebersicht.zusatz.value;
  TABELLE.push(OBJ);
}
+++

Diese TABELLE kann später im Template mit einer einzigen FOR-Schleife in eine Word-Tabelle geschrieben werden.

3. Hilfsfunktionen inline definieren

Für kleine, wiederverwendbare Logik lassen sich JavaScript-Funktionen direkt im Template definieren:

+++EXEC
ABSCHNITTE = getComponentListForAllSectionsByChapterName(`kapitelname`);

getAbschnittsbezeichnung = (arr) => {
  for (let tmp of arr) {
    if (tmp.Name === `uebersicht`) {
      return tmp.nummer.value + ` ` + tmp.bezeichnung.value;
    }
  }
}
+++

Die Funktion getAbschnittsbezeichnung(...) kann anschließend überall im Template aufgerufen werden.

4. Konstanten und Textbausteine

Feste Texte, die an mehreren Stellen vorkommen, werden einmal definiert und wiederverwendet:

+++EXEC
OK_TEXT      = `bestanden`;
NOK_TEXT     = `nicht bestanden (siehe Punkt 2)`;
IO_TEXT      = `in Ordnung`;
NIO_TEXT     = `nicht in Ordnung (siehe Punkt 2)`;
MINUS_TEXT   = `-`;
HINWEIS_TEXT = `nach Herstellerangaben`;
+++

5. Statusflag anhand einer Liste setzen

EXEC lässt sich auch in einer FOR-Schleife verwenden, um z.B. ein einziges Statusflag zu setzen, wenn in einer Liste mindestens ein bestimmtes Kriterium zutrifft:

+++EXEC
NOTIZEN    = getComponentListForAllSectionsByChapterName(`notizen`);
ZEIGE_ERFOLG = true;
+++

+++FOR notiz IN NOTIZEN+++
+++EXEC
if ($notiz.anzeigen.value) {
  ZEIGE_ERFOLG = false;
}
+++
+++END-FOR notiz+++

Nach diesem Block steht ZEIGE_ERFOLG für den Rest des Templates als Flag zur Verfügung.


Inhaltsmuster im Fließtext

Bedingter Text mit IF

Typischer Aufbau für "Alles ok" vs. "Abweichungen":

+++IF ZEIGE_ERFOLG+++
Die +++INS allgemein.prozessdaten.dokumenttyp.value+++ war erfolgreich, es wurden keine Abweichungen festgestellt.
+++END-IF+++

+++IF !ZEIGE_ERFOLG+++
Die +++INS allgemein.prozessdaten.dokumenttyp.value+++ war erfolgreich, es wurden aber Abweichungen festgestellt. Die Prüfung gilt erst als abgeschlossen, wenn dokumentierte Nachweise zu deren Behebung vorliegen. Folgende Abweichungen wurden festgestellt:

+++FOR notiz IN NOTIZEN+++
+++IF $notiz.anzeigen.value+++
•    +++INS $notiz.titel.value+++
+++END-IF+++
+++END-FOR notiz+++

Detaillierte Beschreibungen befinden sich unter Punkt 2.
+++END-IF+++

! vor dem Ausdruck

+++IF !ZEIGE_ERFOLG+++ funktioniert wie in JavaScript: der Block wird eingeschlossen, wenn ZEIGE_ERFOLG falsch/leer ist.

Varianten nach Feldwert

Unterschiedlicher Text je nach Wert eines Dokumentfelds:

+++IF allgemein.prozessdaten.dokumenttyp.value === `Variante1`+++
Erläuterungstext für Variante 1.
+++END-IF+++

+++IF allgemein.prozessdaten.dokumenttyp.value !== `Variante1`+++
Erläuterungstext für alle anderen Varianten.
+++END-IF+++

Vergleichsstrings in Backticks

Wir verwenden in Template-Ausdrücken durchgehend Backticks (`) für Strings statt einfache oder doppelte Anführungszeichen. Grund: Word ersetzt normale Anführungszeichen gerne durch typografische Smart Quotes („ "), die dann zu Syntaxfehlern führen. Backticks werden von Word nicht autokorrigiert.

Einfache Wertausgabe

Auftragsnummer: +++INS allgemein.kopf.auftragsnummer.value+++
Kunde:          +++INS allgemein.kunde.name.value+++
Erstellt am:    +++INS formatDate(allgemein.dokumentation.datum.value, `dd.MM.yyyy`)+++
Geprüft durch:  +++INS getValidator(true)+++

Tabellenzeile per Schleife

Die FOR-Schleife funktioniert auch über Tabellenzeilen: Der FOR-Befehl steht in der ersten Zeile (als Kommentarzeile), die eigentliche Inhaltszeile folgt, und END-FOR steht in einer abschließenden Zeile.

| Kürzel                    | Nummer                  | Kennung                |
|---------------------------|-------------------------|------------------------|
| +++FOR z IN TABELLE+++    |                         |                        |
| +++INS $z.KUERZEL+++        | +++INS $z.NUMMER+++       | +++INS $z.KENNUNG+++     |
| +++END-FOR z+++           |                         |                        |

Word löscht die Zeilen mit FOR und END-FOR automatisch — übrig bleibt nur die Inhaltszeile, einmal pro Listen-Eintrag.

Bilder einfügen

+++FOR bild IN allgemein.fotos.bilder+++
+++IMAGE createImage($bild, 10, 7, null, true, true)+++
+++END-FOR bild+++

Oder eine PDF-Anlage seitenweise:

+++FOR seite IN createPDFPages(allgemein.anhang.zertifikat)+++
+++IMAGE $seite+++
+++END-FOR seite+++

Vollständiges Miniatur-Beispiel

Ein knappes, komplettes Template mit Vorbereitung, bedingter Ausgabe und Tabelle:

+++EXEC
ABSCHNITTE = getComponentListForAllSectionsByChapterName(`notizen`);
HAT_ABWEICHUNG = false;
+++

+++FOR a IN ABSCHNITTE+++
+++EXEC
if ($a.anzeigen.value) { HAT_ABWEICHUNG = true; }
+++
+++END-FOR a+++

Prüfbericht für +++INS allgemein.kunde.name.value+++
Datum: +++INS formatDate(allgemein.kopf.datum.value, `dd.MM.yyyy`)+++

+++IF !HAT_ABWEICHUNG+++
Keine Abweichungen festgestellt.
+++END-IF+++

+++IF HAT_ABWEICHUNG+++
Folgende Abweichungen wurden festgestellt:
+++FOR a IN ABSCHNITTE+++
+++IF $a.anzeigen.value+++
•    +++INS $a.titel.value+++
+++END-IF+++
+++END-FOR a+++
+++END-IF+++

Geprüft durch: +++INS getValidator(true)+++

Tipps aus der Praxis

  • Backticks statt Anführungszeichen in allen JavaScript-Ausdrücken (siehe Hinweis oben).
  • Template-Variablen in GROSSBUCHSTABEN — leichter lesbar und kollidieren nicht mit Feldnamen.
  • Vorbereitungsblöcke ganz an den Anfang setzen; Inhaltsblöcke sollten sich auf fertige Variablen stützen, nicht mehrere getListFromChapter…-Aufrufe mit denselben Argumenten wiederholen.
  • EXEC-Blöcke erzeugen keine Leerzeilen — aber der umgebende Absatz im Word bleibt. Platzieren Sie EXEC-Blöcke daher in eigenen Absätzen, die später gelöscht werden können, oder inline in bestehende Absätze.
  • Fehlt ein Feld im Dokument, ist der Ausdruck kapitel.abschnitt.feld.value undefined. Wenn das ein Problem ist, prüfen Sie vorher per IF:
+++IF allgemein.kunde.name && allgemein.kunde.name.value+++
Kunde: +++INS allgemein.kunde.name.value+++
+++END-IF+++
  • Smart Quotes in Word deaktivieren für Template-Dateien: Datei → Optionen → Dokumentprüfung → AutoKorrektur-Optionen → AutoFormat während der Eingabe → "Gerade Anführungszeichen" deaktivieren. Andernfalls wandelt Word "foo" in „foo" um — und JavaScript-Ausdrücke brechen.