Open Source Dokumentenmanagement
Dokumentation

Durchsuchbare Dokumentation aufrufen | Zurück zur Dokumentationsübersicht

Navigation: Dokumentationen agorum core > agorum core JavaScript-API


JavaScript-Bibliothek office/fill-template

Diese Bibliothek erlaubt es, Platzhalter in Office-Dokumenten zu befüllen. Sie ist äquivalent zu templates.fill.

Unterstützte Dateitypen


Folgende Dateitypen werden unterstützt und können befüllt werden:

Platzhalter formatieren


Ein Platzhalter wird nach dem Muster ${name} aufgebaut. Hierbei kann es sich etwa um Metadaten handeln (Rechnungsnummer usw.). Ein solches Metadatum muss existieren, bevor Sie es einsetzen können.

Möchten Sie Formatierungen verwenden, können Sie diese direkt auf den Platzhalter anwenden. Hierbei ist lediglich die Formatierung des $-Zeichens ausschlaggebend für die Formatierung des Platzhalters.


Beispiel
Sie möchten das Erstelldatum kursiv, die Rechnungsnummer fett und die Kundennummer unterstrichen formatieren. Formatieren Sie die Platzhalter im Office-Dokument wie folgt:

Platzhalter formatieren


Ergebnis
Die Platzhalter werden im Dokument anhand der Formatierungen formatiert.

Ergebnis der Formatierung

Alternativ können Sie auch den gesamten Platzhalter formatieren.

Verwendung


let office = require('office/fill-template');

Funktionen


fill

Befüllt Platzhalter in einem Office-Dokument. Das Office-Dokument (Zieldatei) muss zu diesem Zeitpunkt bereits angelegt worden sein.

office.fill(template, outputFile, data, clearEmpty, fileCallback);

Die zu ersetzende Datei wird anhand ihrer Dateiendung automatisch erkannt.​​​​​

Parameter Beschreibung
template Definiert die Datei, die als Vorlage für das Befüllen der Platzhalter dient.
  • Die Datei liegt in der Konfiguration oder im Workspace.
  • Die Datei wird nicht verändert.
outputFile Definiert die Datei, deren Inhalt nach dem Ausführen von fill überschrieben wird.

Das Format der Datei sollte das gleiche sein wie das Format der Datei im Parameter template.
data Definiert den Inhalt, mit dem die Platzhalter befüllt werden sollen.
clearEmpty (optional) Definiert, ob Platzhalter, deren Werte nicht definiert sind, entfernt werden.

Sind Platzhalter in anderen Platzhaltern enthalten / verschachtelt, werden diese ebenfalls entfernt:

${paymentInfo:start}Zahlungskonditionen
${elements:start}${elements}
${elements:end}${paymentInfo:end}

Wenn im Platzhalter ${elements} keine Daten vorhanden sind, wird der komplette Block mit den Zahlungskonditionen nicht angezeigt.

Mögliche Werte

true
Platzhalter werden entfernt.

false
Platzhalter werden nicht entfernt.

Standard
false
fileCallback (optional) Definiert, welche Funktion zum Befüllen des Dokuments verwendet werden soll.

Mögliche Werte
office.simpleFill (für Dokumente aus Kopfdaten -> keine Positionen)
office.domFill​​​​​​ (für Dokumente, die etwa mit Positionen arbeiten)

Standard:
simpleFill

Hinweis: Bei optionalen Parametern muss für den Fall, dass der Parameter nicht belegt ist, null übergeben werden.


Beispiel

let md = metadata().load(objects[0], /^ac_/).data();

office.fill(templateFile, outFile, {
  ac_user_name: sc.loginUser.fullName,
  ac_counter: '32.',
  projectNumber: md.demo_projectNumber
}, true, office.domFill);
Ansicht einer Vorlage in Word


Ergebnis
Der Platzhalter ${ac_user_name} im Dokument wird durch den Namen des angemeldeten Benutzers gefüllt.

Ergebnis in Word

fillRegex

Hinweis: Diese Funktion kann nur verwendet werden, wenn Sie den Wert office.simpleFill im Parameter callFileback verwenden.

Sie können mit fillRegex ganze Bereiche durch einen Platzhalter austauschen lassen, um etwa eine Tabellenzeile zu ersetzen. Dazu definieren Sie in data Folgendes:

let data = {
  positions: {
    replaceRegex: /(<table:table-row\ .*\$\{positions\}.+?<\/table:table-row>)/,
    raw: true, // da wir hier XML einfügen wollen, wird der raw Modus aktiviert
    value: '...XML für Tabellenzeilen'
  }
};

Für ein Beispiel, wie Sie mit LibreOffice eine Tabellenzeile erzeugen, siehe Skript.

fillWord

Äquivalent zu fill, erzwingt zusätzlich das Lesen / Schreiben in Word.

office.fillWord(template, outputFile, data)

fillExcel

Äquivalent zu fill, erzwingt zusätzlich das Lesen / Schreiben in Excel.

office.fillExcel(template, outputFile, data)

fillPowerpoint

Äquivalent zu fill, erzwingt zusätzlich das Lesen / Schreiben in PowerPoint.

office.fillPowerpoint(template, outputFile, data)

fillOdt

Äquivalent zu fill, erzwingt zusätzlich das Lesen / Schreiben eines Textdokuments in OpenOffice /LibreOffice.

office.fillOdt(template, outputFile, data)

fillOds

Äquivalent zu fill, erzwingt zusätzlich das Lesen / Schreiben eines Tabellendokuments in OpenOffice /LibreOffice.

office.fillOds(template, outputFile, data)

fillOdp

Äquivalent zu fill, erzwingt zusätzlich das Lesen / Schreiben eines Präsentationsdokuments in OpenOffice /LibreOffice.

office.fillOdp(template, outputFile, data)

readFile

Liest den Text einer Datei und gibt ihn zurück.

​​​​​office.readFile(template, type)
Parameter Beschreibung
template Definiert die Datei, deren Text geholt werden soll.
type (optional) Definiert den Typ und wie die Datei gelesen werden soll.

Wird der Typ nicht gesetzt, wird die Dateiendung verwendet.

Sie können folgende Werte übergeben (je nachdem werden verschiedene Dateien gelesen, die für den jeweiligen Dokumententyp relevant sind): 

  • docx
  • word
  • xlsx
  • excel
  • pptx
  • powerpoint
  • odt
return Liefert ein Array von Objekten zurück.

Die Objekte enthalten im Key name den Namen der Quell-Datei und im Key text den zugehörigen Inhalt.
[
  {
    "name": "styles.xml",
    "text": "// Inhalt der Datei \\"
  },
  {
    "name": "content.xml",
    "text": "// Inhalt der Datei \\"
  }
]

Vorgehen (office.simpleFill)


Das folgende Vorgehen gilt für den Fall, dass Sie den Wert office.simpleFill beim Parameter fileCallback angeben.

Eine Vorlage erstellen

Existiert noch keine Vorlage, erstellen Sie diese mit folgendem Skript:

 let outFile= objects.tryFind('/agorum/roi/Files/output_file.docx');  
  if (!outFile) {
    outFile = objects.create('file', {
      name: 'output_file.docx',          //hier können Sie auch andere Dateiformate angeben, z. B. .odt usw.
      path: '/agorum/roi/Files/'
    });
  }

Die Vorlage soll meistens nicht überschrieben werden, sondern immer gleich bleiben. Legen Sie deshalb diese Vorlage etwa in den Workspace-Ordner. Das hat den Zweck, dass die Vorlage von Bibliotheken nicht „angefasst“ und überschrieben werden kann.

Positionsdaten erzeugen (Beispiel)

Nachdem Sie die Vorlage erstellt haben, befüllen Sie sie, damit Sie anschließend eine Datei aus der Vorlage erzeugen können. Im Beispiel unten wird eine LibreOffice-Vorlage erzeugt und Positionsdaten in einer Tabelle dynamisch eingefügt.

Auch die Tabelle erzeugen Sie wie gewünscht und erstellen eine Zeile mit einem Platzhalter:

 

Nachdem Sie Ihr Dokument erstellt haben, laden Sie es in agorum core hoch und können es verwenden. 

Nun wird der Platzhalter ${positions} programmatisch ausgetauscht. Sie müssen dazu die erstellte ODT-Datei in eine ZIP-Datei umbenennen und diese entpacken. Darin finden Sie die Datei content.xml.

Wenn Sie diese Datei mit einem Texteditor betrachten, sehen Sie den XML-Aufbau des Dokuments.

Suchen Sie den Teil, der den Platzhalter ${positions} enthält:

<table:table-row table:style-name="Tabelle1.1">
  <table:table-cell table:style-name="Tabelle1.A2" office:value-type="string">
    <text:p text:style-name="P8">${positions}</text:p>
  </table:table-cell>
  <table:table-cell table:style-name="Tabelle1.A2" office:value-type="string">
    <text:p text:style-name="P7"/>
  </table:table-cell>
  <table:table-cell table:style-name="Tabelle1.A2" office:value-type="string">
    <text:p text:style-name="P7"/>
  </table:table-cell>
  <table:table-cell table:style-name="Tabelle1.A2" office:value-type="string">
    <text:p text:style-name="P11"/>
  </table:table-cell>
</table:table-row>

Kopieren Sie diesen Block wie oben abgebildet.

Dieser XML-Teil entspricht genau einer Zeile in der Tabelle. Damit können Sie jetzt neue Zeilen produzieren. 

Hinweis: Wenn Sie etwas an der Formatierung der Tabelle / Zeile ändern, müssen Sie diesen XML-Teil wieder erneut aus der content.xml heraus holen.

Sobald Sie den XML-Block haben, benötigen Sie die ZIP-Datei nicht mehr.

Wie Sie selbst Zeilen in die Tabelle einfügen, sehen Sie anhand des nachfolgenden Skripts: 

let office = require('office/fill-template');
let objects = require('common/objects');

// load the template
let template = objects.find('home:MyFiles/test-template/invoice-template.odt');

let path = 'home:MyFiles/test-template';
let name = 'invoice-output.odt';

let output = objects.tryFind(path + '/' + name);
if (!output) {
  output = objects.create('file', {
    name: name,
    target: objects.find(path)
  });
}

// create a row
function tableRow(row) {
  let table = '';
  table += '<table:table-row table:style-name="Tabelle1.1">\n';
  table += '<table:table-cell table:style-name="Tabelle1.A2" office:value-type="string">\n';
  table += '<text:p text:style-name="P8">' + row.pos + '</text:p>\n';
  table += '</table:table-cell>\n';
  table += '<table:table-cell table:style-name="Tabelle1.A2" office:value-type="string">\n';
  table += '<text:p text:style-name="P7">' + row.description + '</text:p>\n';
  table += '</table:table-cell>\n';
  table += '<table:table-cell table:style-name="Tabelle1.A2" office:value-type="string">\n';
  table += '<text:p text:style-name="P7">' + row.amount + '</text:p>\n';
  table += '</table:table-cell>\n';
  table += '<table:table-cell table:style-name="Tabelle1.A2" office:value-type="string">\n';
  table += '<text:p text:style-name="P11">' + row.price + '</text:p>\n';
  table += '</table:table-cell>\n';
  table += '</table:table-row>\n';
  return table;
}

function formatNumber(n) {
  n = parseFloat('' + n).toFixed(2).replace('.', ',');
  return n;
}

// build some dummy positions
let sum = 0;
let positions = [];
for (let i = 0; i < 30; i++) {
  positions.push({
    pos: i,
    description: 'Artikel ' + i,
    amount: 1,
    price: formatNumber(10 + i) + ' €'
  });
  
  sum += (10 + i);
}

// convert positions to ODT Table-Rows
let tableRows = positions.map(pos => tableRow(pos)).join('\n');


office.fillOdt(template, output, {
  invoiceDate: '01.01.2020',
  subject: 'Ihre Rechnung',
  invoiceNumber: 'RE123456',
  receiver: {
    value: 'Kunde GmbH<text:line-break/>Teststrasse 21',
    raw: true
  },
  positions: {
    value: tableRows,
    raw: true,
    replaceRegex: /(<table:table-row\ .*\$\{positions\}.+?<\/table:table-row>)/
  },
  sum: formatNumber(sum),
  tax: formatNumber(sum * 0.19),
  completeSum: formatNumber(sum * 1.19)
});

Das Beispiel geht davon aus, dass die ODT-Datei (template) im Verzeichnis Eigene Dateien/test-template liegt und den Namen invoice-template.odt besitzt (siehe Beispiel undefined>invoice-template.odt).

Das System erzeugt im selben Verzeichnis eine Datei namens invoice-output.odt.

Vorgehen (office.domFill)


Das folgende Vorgehen gilt für den Fall, dass Sie den Wert office.domFill beim Parameter fileCallback angeben.

Eine leere Zieldatei erstellen

Für das Erzeugen einer leeren Zieldatei siehe Vorgehen (office.simpleFill).

Positionsdaten erzeugen (Beispiel)

Mit Setzen des Werts office.domFill im Parameter fileCallback können Sie zusätzlich ein Start- und ein End-Tag bei Platzhaltern verwenden und ein Template erzeugen. Häufig verwendet werden Start- und End-Tags, etwa bei Positionsdaten, also auf einer Rechnung oder einem Lieferschein, auf denen diverse Artikel aufgelistet werden, die pro Dokument immer verschiedene Werte enthalten.


Aufbau

${name:start}
${weiterePlatzhalter}
${name:end}


Beispiel
Das undefined>Office-Dokument befüllen Sie in der Spalte Position folgendermaßen, um die Positionsdaten zu definieren (items):

Vorlage mit Start- und End-Tags

Hinweis: Möchten Sie ein Datum im Dokument ausgeben, müssen Sie im Platzhalter stets das Datumsformat angeben:

${date:dd-MM-yyy)

Weitere Formatierungen zu den Datumswerten siehe Datumswerte formatieren

Um die Positionsdaten zu befüllen, geben Sie sie im Parameter data mit:

office.fill(templateFile, outFile,
{
  subject: 'Ihre Rechnung #0000000',
  items: [
    { pos: '0001', name: 'Artikel 1', amount: 5, total: 17.25 },
    { pos: '0002', name: 'Artikel 2', amount: 1, total: 300 },
    { pos: '0003', name: 'Artikel 3', amount: 1.5, total: 13.37 }
  ],
  total: {
    net: 330.62,
    vat: 62.82,
    gross: 393.44
  }
}, true, office.domFill);


Ergebnis
Das System befüllt das Office-Dokument folgendermaßen:

Ergebnis mit Start- und End-Tags 

Neben dem Aufbau oben mit start und end existiert ein weiterer Aufbau, der mit startFixed beginnt.
 

Aufbau

${name:startFixed}
${weiterePlatzhalter}
${name:end}

startFixed verwenden Sie, wenn Sie Platzhalter nicht so positionieren können, wie sie eigentlich positioniert werden müssten und wenn dadurch das Layout zerstört werden würde.

Folgendes Skript ist etwa für die Positionen definiert:

{
  subject: 'Ihre Rechnung',
  items: [
   { pos: '0001', name: [ 'Artikel mit mehr-', 'zeiliger Beschreibung' ], amount: 1.0, total: 39.59 } 
  ],
  total: {
    net: 39.59,
    vat: 7.52,
    gross: 47.11
  }
}

Hier enthält die Bezeichnung des Artikels eine mehrzeilige Beschreibung aus zwei Strings, deren Inhalt normalerweise in der Spalte Bezeichnung angezeigt wird.
 

Verhalten ohne „startFixed“
Folgendes ist in der Vorlage definiert. Hier fehlt startFixed bei ${name:start}:

Vorlage samt Platzhalter für die Positionen ohne startFixed


Ergebnis
Fehlt die Angabe startFixed, verschiebt das System den zweiten String in die rechte Tabellenzelle Menge:

Ergebnis ohne startFixed

 

Verhalten mit „startFixed“
Folgendes ist in der Vorlage definiert. Dieses Mal ist startFixed bei ${name:start} angegeben:

Vorlage samt Platzhalter für die Positionen mit startFixed


Ergebnis
Ist die Angabe startFixed enthalten, findet kein Verschieben statt. Stattdessen erzeugt das System für den zweiten String eine neue Zeile und das Layout bleibt erhalten:

Ergebnis mit startFixed

Beispielskript (kompletter Aufruf)

Für das Herunterladen des Templates siehe undefined>template Rechnung - office-fill domFill

let objects = require('common/objects');
let office = require('office/fill-template');

// functions
let createFile = (path, name) => {
  let doc = objects.tryFind(path + '/' + name);
  if (!doc) {
    doc = objects.create('file', {
      name: name,
      target: objects.find(path)
    });
  }
    
  return doc;
};

let templateFile = objects.find( ... ID or Path ... );
let ouputFile = createFile('/agorum‎/roi‎/Dateien‎/Demo‎', 'output.odt');
let templateData = {
  subject: 'Ihre Rechnung #0000000',
  items: [
    { pos: '0001', name: 'Artikel 1', amount: 5, total: 17.25 },
    { pos: '0002', name: 'Artikel 2', amount: 1, total: 300 },
    { pos: '0003', name: 'Artikel 3', amount: 1.5, total: 13.37 }
  ],
  total: {
    net: 330.62,
    vat: 62.82,
    gross: 393.44
  }
};

// templateFile, ouputFile, templateData, clearEmpty, fillFunction
office.fill(templateFile, ouputFile, templateData, true, office.domFill);

Den RAW-Modus verwenden

Die Funktion domFill unterstützt das direkte Einfügen von XML-Daten.

Hinweis: Die raw-Funktion funktioniert nur, wenn sie in einem Block mit :start und :end im Office-Template eingefasst ist.

Beispiel

${table:start}${table}${table:end}


Beispiel: Tabelle einfügen

let templateData = {
  table: { // Platzhalter, der im Dokument mit den RAW-Daten gefüllt wird.
    raw: 
      "<table:table><table:table-column/><table:table-row><table:table-cell><text:p>Hallo Welt</text:p></table:table-cell></table:table-row></table:table>"
  }
}


Beispiel: Mit Zeilenumbrüchen befüllen

let templateData = {
  table: { // Platzhalter, der im Dokument mit den RAW-Daten gefüllt wird.
    raw: 
      "<w:p><w:r><w:rPr><w:bCs/></w:rPr><w:t>Zeile 1</w:t><w:br/><w:t>Zeile 2</w:t></w:r></w:p>"
  }
}

Vorgehen (office.domFillTemplate)


office.domFillTemplate verhält sich wie office.domFill. Der Unterschied ist, dass dabei auch Office-Vorlagen konvertiert werden.

Wenn etwa eine dotx, potx oder xltx-Datei als Quelle verwendet wird, werden diverse Vorlagen-Parameter modifiziert und das Dokument automatisch in ein entsprechendes Dokument (docx, pptx oder xlsx) gewandelt.

Der Aufruf ist analog zu office.domFill. Dabei können Sie noch weitere Parameter übergeben, die in der Vorlage verändert werden:

let templateFile = objects.find('... eine Vorlage.dotx');
let outFile = createFile('...Ausgabedatei.docx');

office.fill(templateFile, outFile,
{
  subject: 'Ihre Rechnung #0000000',
  items: [
    { pos: '0001', name: 'Artikel 1', amount: 5, total: 17.25 },
    { pos: '0002', name: 'Artikel 2', amount: 1, total: 300 },
    { pos: '0003', name: 'Artikel 3', amount: 1.5, total: 13.37 }
  ],
  total: {
    net: 330.62,
    vat: 62.82,
    gross: 393.44
  },
  _template: {
    creator: 'Ersteller 1',
    modifier: 'Änderer 1',
    created: new Date(),
    modified: new Date(),
    templateName: templateFile.name,
    published: new Date()
  }
}, true, office.domFillTemplate);

Der Parameter _template definiert dabei diverse Parameter, die optional gesetzt werden können und innerhalb der Vorlage bei Konvertierung in das wirkliche Dokument ersetzt werden.

Parameter Beschreibung
creator Ersteller des Dokuments
modifier Letzter Änderer des Dokuments
created Erstelldatum des Dokuments
modified Letztes Änderungsdatum des Dokuments
templateName Name der Vorlagendatei
published Veröffentlichungsdatum des Dokuments

Hinweis: Geänderte Parameter beim Öffnen des Dokuments werden nicht automatisch in Office aktualisiert. Dazu können Sie entweder auf die einzelnen Felder gehen und aktualisieren wählen oder ein Macro in der Vorlage hinterlegen, das die Aktualisierung automatisch übernimmt. Weitere Informationen dazu finden Sie bei Microsoft.