Webseiten-Werkzeuge

Benutzer-Werkzeuge


Factur-X 1.0 aka ZUGFeRD 2.2

Das ZUGFeRD-Datenformat basiert auf der Richtlinie 2014/55/EU vom 16. April 2014 über die elektronische Rechnungsstellung bei öffentlichen Aufträgen und auf der am 28. Juni 2017 veröffentlichten Norm EN 16931. Zudem werden die Cross-Industry-Invoice (CII) 1) von UN/CEFACT 2) und die ISO-Norm 19005-3:2012 (PDF/A-3) bei ZUGFeRD 2.2.0 berücksichtigt.

ZUGFeRD 2.2 und Factur-X 1.0 sind vollständig kompatible und technisch identische Formate, die bereits seit dem 24. März 2020 gemeinsam die Kennung Factur-X nutzen. Beide Formate sind grundsätzlich für den Rechnungsaustausch zwischen Unternehmen, der öffentlichen Verwaltung und Verbrauchern geeignet.

In der hybriden Ausprägung beinhaltet das Rechnungsformat ZUGFeRD die strukturierten Rechnungsdaten in einer PDF/A-3 Datei, die die Sichtkomponente der Rechnung bildet. Die strukturierten XML-Rechnungsdaten können vom Rechnungs­empfänger ausgelesen und verarbeitet werden.

Die EU-Richtlinie EN 16931 gibt die Verwendung des strukturierten Datenformats XML für den elektronischen Rechnungs­austausch vor, welches eine automatisierte Rechnungsverarbeitung ermöglicht. Ein standardisiertes semantisches Datenmodell beschreibt die Informationselemente einer Rechnung und deren gegenseitige Beziehung und Datentypen. Die Vorgabe der Syntax stellt eine einheitliche technische Umsetzung der E-Rechnung in der EU sicher.

Insofern ist die im Tip ZUGFeRD vorgestellte Lösung nicht mehr aktuell.

Update auf Factur-X

Die grundlegenden Komponenten der ZUGFeRD-Lösung können für Factur-X übernommen werden. Deshalb setzen die nachfolgenden Ausführungen die Kenntnisse aus dem Tip ZUGFeRD voraus. Insbesondere die dort vorgestellten Hinweise zur Inbetriebnahme einer Lösung sind auch im Falle der Factur-X gültig.

Eine Besonderheit von Factur-X ist, dass es in fünf sogenannten Profilen zur Verfügung steht: Minimum, Basic WL, BASIC, EN16931 und Extended, sowie ein Referenzprofil XRechnung. Da die ersten drei Pofile in Deutschland keine gültige Rechnung darstellen, sondern lediglich eine Buchungshilfe, wurde für die nachfolgenden Ausführungen das Profil EN 16931 als Grundlage gewählt.

Gegenüber der bisherigen Lösung wurde das Beispieldokument um die E-Mail-Adressen von Lieferant und Kunden erweitert.

Die E-Mail-Adresse des Rechnungsem­pfängers befindet sich unterhalb des Adressfelds, die des Rechungsausstellers ganz unten rechts bei den Geschäftsangaben.


Anpassungen

Das hier verwendete Skript macht zur Analyse der Kontrolldatei des print2forms-Gateways ausgiebigen Gebrauch von einer Hilfsdatei, in der eine spezielle Klasse factXrech definiert ist. Diese Klasse reduziert den Aufwand des eigentlichen Skripts für die Factur-X erheblich und abstrahiert auch viele technische Details.

Das eigentliche Skript hat den Name factur-x.php und wird im nachfolgenden schrittweise vorgestellt. Die eben genannte Klasse wird im Rahmen dieses Textes nur insoweit informal beschrieben, als die Methoden und Eigenschaften vom Skript factur-x.php genutzt werden. Eine genaue Beschreibung findet sich im Tip factXrech-class.php.

Ablauf

Die ersten paar Zeilen des Skripts factur-x.php bereiten die eigentliche Arbeit vor. Als allererstes wird das zweite Skript einkopiert (inkludiert), sodass die dort gemachte Definition der Klasse factXrech zur Verfügung steht. Anschliessend wird das aktuelle Arbeitsverzeichnis auf das Skriptverzeichnis gesetzt, damit zur Vereinfachung im weiteren auch relative Pfadangaben benutzt werden können.

Es wird geprüft, ob das Skript mit einem Parameter aufgerufen wurde, wobei das der Pfad und Namen der zu bearbeitenden Datei ist. 3) Evenuelle Fehlermeldungen werden in einer Datei factxrech.log gesammelt, die sich im gleichen Verzeichnis wie das Skript befindet. 4)

<?php
 
/* Factur-X Support Version 3.0     (c) 2024 SPE Systemhaus GmbH */
 
require "factXrech-class.php";
 
chdir (dirname(__FILE__));
 
if ($argc < 2)
  factXrech::error ("started without required param", 1);
 
$document = $argv [1];             /* base name (no extension) including path */


Die nächsten Zeilen starten jetzt das Aufsammeln der Rechnungsdaten, die für die Factur-X XML-Datei benötigt werden. Dazu wird als erstes ein Objekt $fxr angelegt. Der Konstruktor (new) des Objekts bekommt als Parameter ein Kennzeichen für die Factur-X 5), eine Zeitzone und den Namen der Indexdatei. Der Konstruktor wird dann die Indexdatei lesen und für einen schnellen Zugriff in einer internen Struktur abspeichern.

Die Information zur Zeitzone wird benötigt, um beim eventuellen Einbetten des XML-Dokuments in ein PDF eine korrekte Zeitinformation der Einbettung zu erzeugen. Ausserdem sorgt die korrekte Zeitzone für korrekte Zeitstempel in der Log-Datei.

Die Rechnungsinformationen selbst werden in einem Feld (Array) mit dem Namen $vars gesammelt. Als initialen Inhalt wird lediglich der Platzhalter ITEMS 6) definiert und mit einer leeren Zeichenkette vorbesetzt.

Die Methode fetch holt vom angegebenen Index unter Verwendung des angegebenen regulären Ausdrucks den Wert für den als letztes notierten Platzhalter und speichert ihn in der Variablen $vars. Der reguläre Ausdruck wird verwendet, um aus der Indexdatei nur die Daten zu lesen, die wirklich gebraucht werden. Gleich beim ersten Platzhalter (die Währung) wird nur ein Teil der Indexinformation ausgewertet. Konkret wird aus der Tabellenüberschrift der letzten Spalte das 'EUR' geholt.

Mit dem Namen des Dokuments und des Identifikationsnummer wird ganz ähnlich verfahren.

/* Create instance and init, collect data for Factur-X template */
 
$fxr = new factXrech (factXrech::FACTURX, "Europe/Berlin", "$document.CTL");
 
$vars = array ("ITEMS" => "");                 /* start with no items present */
 
$fxr->fetch ("0105D20985", $vars, "in ([A-Z]+)", "currencyID");
$fxr->fetch ("0100E200C6", $vars, "(.*)", "HeaderExchangedDocumentName");
$fxr->fetch ("01012D0846", $vars, "(.*)", "DocumentID");


Die nächsten Zeilen holen die restlichen Rechnungsinformationen. Neu ist hier, dass als fünfter, offensichtlich optionaler Parameter für die Methode fetch eine Konstante aus der Klasse übergeben wird. Damit wird die Formatierung der Information gesteuert. Wie der Name bereits suggeriert, sorgt factXrech::DATE_FIELD dafür, dass eine Zeichenkette der Form '04.03.2019' in der Variable $vars als '20190304' (YYYYMMDD) landet. Entsprechend macht factXrech::CURRENCY_FIELD das mit Währungsinformationen, die im Factur-X-Standard mit einem Dezimalpunkt und zwei Nachkommastellen erwartet werden.

factXrech::COUNTRY_FIELD ist deutlich komplexer, weil es zum Beispiel 'Deutschland' in 'DE' übersetzen muss. Das regelt die Klasse unter Zuhilfenahme von entsprechenden Tabellen, die als externe Dateien im Hintergrund automatisch bereitgestellt werden.

Das neue Format factXrech::MAIL_FIELD stellt sicher, dass es sich bei dem zu prüfenden Wert um eine gültige E-Mail-Adresse handelt. 7)

$fxr->fetch ("0101720846", $vars, "(.*)", "IssueDate", factXrech::DATE_FIELD);
$fxr->fetch ("0101B70846", $vars, "(.*)", "ActualDeliveryDate", factXrech::DATE_FIELD);
$fxr->fetch ("0101FC0846", $vars, "(.*)", "PaymentReference");
$fxr->fetch ("0102860846", $vars, "(.*)", "BuyerReference");
$fxr->fetch ("0102410846", $vars, "(.*)", "CustomerID");
$fxr->fetch ("01036C00C6", $vars, "(.*)", "BuyerRegistrationName");
$fxr->fetch ("0103B100C6", $vars, "(.*)", "BuyerStreetName");
$fxr->fetch ("0103F600C6", $vars, "[A-Za-z]*-?([0-9]+) .*", "BuyerPostcodeCode");
$fxr->fetch ("0103F600C6", $vars, "[A-Za-z]*-?[0-9]+ (.*)", "BuyerCityName");
$fxr->fetch ("01043B00C6", $vars, "(.*)", "CountryIC", factXrech::COUNTRY_FIELD);
$fxr->fetch ("010D1A0889", $vars, "([0-9,]+) .*", "TaxableAmount", factXrech::CURRENCY_FIELD);
$fxr->fetch ("010D5F0889", $vars, "([0-9,]+) .*", "TaxAmount", factXrech::CURRENCY_FIELD);
$fxr->fetch ("010DA40889", $vars, "([0-9,]+) .*", "PayableAmount", factXrech::CURRENCY_FIELD);
$fxr->fetch ("010D5F00C6", $vars, ".+ ([0-9,]+)% .*", "TaxPercent");
$fxr->fetch ("01050A0229", $vars, "(.*)", "BuyerEndpointID", factXrech::MAIL_FIELD);


Was jetzt noch fehlt, ist die Information zu der gewünschten Zahlungsweise.

Hier kommt es nun zu einer Situation, in der der Windows-Druckertreiber eine längere Zeile durch eine Neupositionierung teilt. 8) Hier zur Verdeutlichung der Besonderheit der entsprechende Ausschnitt aus der Indexdatei:

...
[010E7300C6]innerhalb 30 Tag
[010E730281]en netto bis 04.07.2018, innerhalb 14 Tagen 2% Skonto bis 19.06.2018
...

Für diesen Anwendungsfall gibt es eine Methode getLine, die alle Texte aufsammelt, die über eine Zeile verstreut sind. Das wird anhand der Ziffern eins bis sechs des Indexes erkannt.

Nachdem die Zeile zur Verfügung steht, wird aus ihr das Datum für den Ablauf der Zahlungsfrist extrahiert, und direkt in das Feld $vars eingetragen. Da für ein Datum in Factur-X ein bestimmtes Format vorgeschrieben ist, muss vorher noch die Methode formatDate direkt aufgerufen werden. Neben formatDate (entspricht factXrech::DATE_FIELD) gibt es noch die Methoden formatQuantity (entspricht factXrech::QUANTITY_FIELD) und formatCurrency (entspricht factXrech::CURRENCY_FIELD), die für eigene Konvertierungen aufgerufen werden können, wenn, so wie hier, die Methode fetch nicht zum Einsatz kommen kann.

/* Handling of payment is identical for all items */
 
$vars ["PaymentTerms"] = $fxr->getLine ("010E7300C6");
$vars ["DueDate"] = $fxr->formatDate (substr ($vars ["PaymentTerms"], 29, 10));


Als nächstes erfolgt die Bearbeitung der Tabelle mit den einzelnen Rechnungsposten.

Dazu werden zwei weitere Methoden benötigt getIndex und setIndex. Innerhalb der Klasse wird ein Zeiger innerhalb der Indexdatei verwaltet, der mit den beiden Methoden abgefragt oder gesetzt werden kann. Wichtig zu wissen ist auch, dass die Methode fetch mit diesem Zeiger arbeitet und ihn immer weiter schiebt, wenn sie ohne einen Index aufgerufen wird.

Im folgenden wird also erst der Zeiger auf die erste Zeile der Indexdatei mit Tabelleninformationen gesetzt. In unserem Fall ist dies die erste Positionsnummer in der Tabelle mit dem Index 01063100FD. Um das Ende der Tabelle zu finden, wird in der Schleife auf die erste Zeile getestet, die nicht mehr zur Tabelle gehört - am Index 010D1A00C6 steht 'Rechnungssumme Netto (exkl. USt.)'.

Für jeden Rechnungsposten wird ein eigenes Feld $itemvars für die ausgelesenen Informationen angelegt. Das Feld wird mit der Währungsbezeichnung und dem Umsatzsteuersatz der Rechnung fest vorbesetzt. Für jede der acht Tabellenspalten wird jetzt einmal die Methode fetch mit einem leeren Index aufgerufen, und so das Feld $itemvars Schritt für Schritt gefüllt.

Am Ende jeder Tabellenzeile werden die ausgelesenen Daten aus dem Feld $itemvars in die Vorlage für Rechnungspositionen an Stelle der dort hinterlegten Platzhalter eingetragen. Dazu dient die Methode substitute, die als Parameter die Kennung der Vorlage (eine vordefinierte Konstante der Klasse) und die Variable mit den Daten erwartet. Die Methode gibt die resultierende XML-Zeichenkette zurück, die einfach an den aktuellen Wert des Platzhalters ITEMS in den Rechnungsinformationen angehängt wird.

Am Ende der Schleife steht in $vars für den Platzhalter ITEMS der gesamte XML-Text für die vorgefundenen Rechnungs­positionen.

$fxr->setIndex ("01063100FD");           /* position to start with item table */
 
while ($fxr->getIndex () != "010D1A00C6")       /* loop through list of items */
  {
    /* Process list of invoice items, all items have fix VAT and currency */
 
    $itemvars = array ("currencyID" => $vars ["currencyID"],
                       "TaxPercent" => $vars ["TaxPercent"]);
 
    $fxr->fetch ("", $itemvars, "(.*)", "LineID");
    $fxr->fetch ("", $itemvars, "(.*)", "SellerAssignedID");
    $fxr->fetch ("", $itemvars, "(.*)", "BuyerAssignedID");
    $fxr->fetch ("", $itemvars, "(.*)", "Name");
    $fxr->fetch ("", $itemvars, "(.*)", "PriceAmount", factXrech::CURRENCY_FIELD);
    $fxr->fetch ("", $itemvars, "(.*)", "UnitCode", factXrech::UNIT_FIELD);
    $fxr->fetch ("", $itemvars, "(.*)", "InvoicedQuantity", factXrech::QUANTITY_FIELD);
    $fxr->fetch ("", $itemvars, "(.*)", "LineExtensionAmount", factXrech::CURRENCY_FIELD);
 
    $vars ["ITEMS"] .= $fxr->substitute (factXrech::ITEM_TEMPLATE, $itemvars);
  }


Jetzt sind alle Informationen für Factur-X in $vars verfügbar.

Jetzt werden durch erneuten Aufruf der Methode substitute diese Daten ihrerseits in die Vorlage für die eigentliche Rechnung eingesetzt. Die resultierende Zeichenkette wird in eine temporäre XML-Datei geschrieben.

Falls gewünscht, kann der zweite Parameter der Methode createXML mit dem Wert '1' dafür sorgen, dass die erzeugte XML-Datei gleich validiert wird. 9) Falls die Validierung scheitert, wird intern eine Fehlermeldung in die Log-Datei geschrieben, und die nachfolgende Abfrage auf Fehler verhindert die weitere Bearbeitung. 10)

Als nächstes muss die Einbettung in eine PDF-Datei erfolgen - das Zusammenfassen der PDF-Datei und der XML-Datei zu einer Factur-X konformen PDF/A3-Datei.

Die Methode createPDF benötigt die PCL-Datei des Gateways, einen Firmennamen, einen Titel für die Datei und Schlüsselworte. Diese Informationen werden in die Meta-Daten der PDF-Datei eingebaut und unterstützen so die automatische Weiterverarbeitung der Datei.

Als allerletzte Aufgabe verbleibt, die intern angelegte PDF-Datei mit einem entsprechenden Namen an den gewünschten Zielort zu kopieren wird.

/* create and validate xml file using external kosit validator (java) */
 
$fxr->createXML ($fxr->substitute (factXrech::INVOICE_TEMPLATE, $vars), 1);
 
if ($fxr->errorsfound () == 0)                   /* nothing went wrong so far */
  {
    $invoicedate = substr ($vars ["IssueDate"], 8, 2) . "." .
                   substr ($vars ["IssueDate"], 5, 2) . "." .
                   substr ($vars ["IssueDate"], 0, 4);
 
    $title = "Rechnung {$vars ["DocumentID"]} vom $invoicedate";
    $keywords = "Muster_GmbH; {$vars ["DocumentID"]}; $invoicedate; {$vars ["CustomerID"]}";
 
    $resultfile = $fxr->createPDF ("$document.pcl", "Muster GmbH", $title, $keywords);
 
    /* save and rename just generated pdf file */
 
    copy ($resultfile, "Rechnung_{$vars ["DocumentID"]}_$invoicedate.pdf");
  }
 
//array_map ('unlink', glob ("$document.*"));         /* uncomment after test */
?>



Inbetriebnahme vorbereiten

Gleich vorweg: es ist keine gute Idee, die Factur-X-Lösung ohne die Hilfe einer entsprechenden Entwicklungsumgebung in Betrieb nehmen zu wollen. Das Skript ist nicht ganz trivial, und spätestens, wenn es an die realen Bedingungen einer konkreten Kundeninstallation angepasst werden soll, ist das mit reinem 'Print'-Debugging extrem ineffizient.

Es wird deshalb noch einmal ausdrücklich auf die Tips Visual Studio Code für PHP installieren, Test von PHP-Skripten und PHP-Skript ohne Gateway testen verwiesen. In den nachfolgenden Ausführungen wird davon ausgegangen, dass die Lösung mit Microsoft Visual Studio Code in Betrieb genommen wird.

Alle benötigten Dateien lassen sich hier einfach als Archiv herunterladen, und müssen nicht im Wiki aufgesammelt werden. Das vermeidet auch eventuelle Probleme mit der Kodierung der einzelnen Textdateien. Vorzugsweise sollte das Archiv im Skriptverzeichnis von print2forms entpackt werden - in der Regel C:\Users\Public\Documents\SPE Systemhaus GmbH\print2forms\p2fScript.

Im Archiv sind auch die entsprechenden Konfigurationsdateien für Visual Studio Code enthalten, sodass der jetzt neu erscheinende Ordner p2fFactur-X direkt in der Entwicklungsumgebung geöffnet werden kann. Es sollte sich im Dateiexplorer die rechts abgebildete Struktur ergeben - zunächst aber mit einem unvollständigen Unterordner converter.

Aus lizenzrechtlichen Gründen dürfen die Programme GhostPCL und GhostScript der Firma Artifex nicht mit print2forms zusammen ausgeliefert werden. 11)

Nachdem die Programme von den hier angegebenen Web-Adressen geladen wurden, müssen für GhostPCL die beiden Dateien gpcl6win64.exe und gpcl6win64.dll (für 64-Bit Systeme, ansonsten gpcl6win32.exe und gpcl6win32.dll für 32-Bit Systeme) in den Ordner converter kopiert werden. Für GhostScript müssen die beiden Dateien gswin64.exe und gsdll64.dll (für 64-Bit Systeme, ansonsten gswin32.exe und gsdll32.dll für 32-Bit Systeme) kopiert werden.

Die beiden Dateien im Unterordner test sind bereits von einem print2forms-Gateway erzeugte Testdaten aus der Beispielrechnung. Durch die Verwendung dieser Dateien wird verhindert, dass das Office Paket auf der Testmaschine die Rechnung abweichend druckt. 12)

Die Dateien im Unterordner mappings dienen der Übersetzung von Länder- und Sprach­bezeichnungen, sowie Masseinheiten in die im Factur-X-Standard vorgegebenen Kodes. Die Dateien im Unterordner validator werden für die eventuell gewünschte Validation der XML-Dateien benötigt. Ansonsten findet sich im Verzeichnis noch die eigentliche Office-Datei mit der Rechnung Formular.odt.

Damit ist alles eingerichtet, und die ersten Funktionstests mit Visual Studio Code können starten.

Eigene Tests mit Gateway

Bisher erfolgte der ganze Test des Skriptes ohne jedes Zutun eines print2forms-Gateways. Soll jetzt Factur-X mit eigenen Dokumenten genutzt werden, ist die Kommandozeile des betreffenden Gateways entsprechend zu konfigurieren.

Das Skript factur-x.php erwartet nur einen Parameter: den Namen des zu bearbeitenden Dokuments. Demzufolge sieht die Kommandozeile in etwa wie folgt aus:

"C:\PHP8\php.exe" "%1/factur-x.php" "%2\%4"

Der Pfad zum Aufruf des PHP-Interpreters ist der gleiche Pfad wie der in der Datei lauch.json.

Weiterverarbeitung

In der Praxis ist das eben entwickelte Beispielskript nur die halbe Miete, weil die erzeugte PDF-Datei noch - möglichst automatisch - weiter an den Rechnungsempfänger übermittelt werden muss. Für den Fall, dass der Rechnungsempfänger die Rechnung über den Upload auf einem speziellen Portal erwartet, ist je nach Portal eine mehr oder minder aufwändige zusätzliche Programmierung notwendig, die weit über den Umfang dieses Wikis hinausgeht.

Für den Fall, dass die Rechnung vom Rechnungsempfänger als E-Mail entgegengenommen wird, kann das Skript jedoch leicht entsprechend erweitert werden. Grundlage dafür liefern die Informationen im Wiki Artikel Dokument via E-Mail in PHP versenden.

Hinweise

  • Das Skript factur-x.php macht natürlich eine ganze Reihe von Annahmen, um den Einstieg in das Thema nicht komplizierter zu machen als unbedingt notwendig. Eine der Annahmen ist, dass die Rechnung einseitig ist. Es ist klar, dass die Schleife zum Auslesen der Rechnungsposten auch für Folgeseiten (eventuell etwas modifiziert) ausgeführt werden muss.
  • Die beiden Dateien im Unterverzeichnis test müssen nicht (!) in das Spool-Verzeichnis von print2forms kopiert werden, weil in der Datei lauch.json das Spool-Verzeichnis für das Projekt so konfiguriert ist, dass das Unter­verzeichnis test benutzt wird.
  • Eine weitere Annahme ist, dass beim Drucken der Rechnungsposten wirklich sequenziell Zeile für Zeile ausgegeben wird. Das ist manchmal nicht der Fall, weil die Anwendung, die die Rechnung erzeugt z.B. spaltenweise vorgeht. Das ist aber durchaus lösbar.
  • Auch zusätzliche Umsatzsteuersätze oder auch die Altteilsteuer werden hier im Rahmen des Wikis vereinfachend ausser Acht gelassen. Wenn solche Anforderungen im Raum stehen, sprechen Sie uns für eine Lösung bitte direkt an.
  • Im Gegensatz zur bisherigen Lösung für ZUGFeRD ist für die hier vorgestellten neuen Skripte keinerlei Lizenzierung notwendig. Ausser den Erstellungskosten für Skriptanpassungen entstehen keine weiteren Kosten.



1)
Cross Industry Invoice

2)
United Nations Centre for Trade Facilitation and Electronic Business

3)
Der für ZUGFeRD benötigte zweite Parameter mit dem Lizenzschlüssel wird nicht mehr benötigt. Die Factur-X-Lösung ist inzwischen lizenzfrei. Factur-X kommt auch ohne das bisher notwendige Java-Programm aus, weil eine eventuell geforderte Einbettung der XML-Datei in ein PDF-Dokument inzwischen von GhostScript mit Hilfe von etwas PostScript-Code selbst übernommen werden kann - siehe GhostScript ZUGFeRD.

4)
Der Namespace 'factXrech::' vor dem Aufruf der Funktion ist notwendig, weil zu diesem Zeitpunkt noch kein Objekt dieser Klasse instanziiert wurde.

5)
Die Klasse factXrech ist so geschrieben, dass sie sowohl XML-Dateien für den Standard Factur-X erzeugen kann, als auch die für den Standard Factur-X 1.0 (ZUGFeRD 2.2). Deshalb definiert der erste Parameter, welcher Standard genutzt werden soll.

6)
Im Platzhalter ITEMS werden die einzelnen Rechnungspositionen bereits als XML-Daten aufgesammelt. Daher ist es wichtig, dass der Name des Platzhalters in Grossbuchstaben geschrieben wird. Das schützt die Rechnugspositionen vor einer zerstörenden zweiten Umkodierung beim Einbetten in die Vorlage der eigentlichen Rechnung.

7)
Dazu wird eine PHP-Filterfunktion genutzt, die Adressen nach RFC-822 prüft.

8)
Hier im Beispiel wurde die Rechnung nicht (!) durch print2forms aufbereitet. Beim Drucken aus Host-Umgebungen (i5/OS, z/OS, Unix) ist die Ausgangslage meist einfacher, weil meist dicktengleiche Schriften zum Einsatz kommen. Diese bedingen keine Repositionierungen zum Ausgleich von Laufweiten­unterschieden wegen fehlender oder unterschiedlicher Kerning-Tabellen. Wenn die reale Rechnung durch print2forms aus Text- oder XML-Daten aufbereitet wurde, werden ebenfalls keine Neupositionierungen eingebaut.

9)
Dies erfolgt mit dem frei verfügbaren KoSIT Validator. Voraussetzung dafür ist allerdings das Vorhandensein einer Java-Laufzeitumgebung auf dem ausführenden Rechner. Der KoSIT Validator ist lokal installiert, das heisst, die XML-Datei verlässt nicht (!) den lokalen Rechner! Die Ausführungszeiten des Validators bewegen sich im Bereich von vielen Sekunden, weil viele zeitaufwändige Transformationen von XML-Dateien mittels XSLT durchgeführt werden. Das senkt den möglichen Durchsatz des Gateways erheblich!

10)
Das Prüfprotokoll der Validierung steht im Skript-Verzeichnis und hat den Namen 'factur-x-report.html'. Es kann mit jedem Browser zur Anzeige gebracht werden.

11)
Diese beiden Programme werden nur für den Fall benötigt, dass eine PDF-Datei der Rechnung erzeugt werden soll. Geht es nur um die XML-Datei mit der Factur-X, sind die Programme entbehrlich. Die Methode createXPF darf dann allerdings auch nicht aufgerufen werden.

12)
Beispielsweise wenn Microsoft Office statt Open Office verwendet wird. Das führt wegen der Dokumentkonvertierung meist zu einer geringfügig anderen Indexdatei und das Skript müsste somit erst angepasst werden.

print2forms/tips/tip94.txt · Zuletzt geändert: 2024-06-26 17:59 (Externe Bearbeitung)