Das Demo-Paket enthält alles, um csv2zugferd ohne Konfigurationsaufwand auszuprobieren: eine fertige Windows-Exe, zwei Beispiel-Rechnungen und eine vollständige YAML-Konfiguration.
Demo-Paket auf GitHub herunterladenPaketinhalt#
| Datei | Beschreibung |
|---|---|
csv2zugferd-win-x64.exe | Windows-64-bit-Exe, self-contained |
config_demo.yml | Fertige YAML-Konfiguration für die Demo-CSV |
demo-2026-0001.csv | Beispiel-Rechnung 1 (Softwarelizenzen mit Rabatt) |
demo-2026-0001.pdf | PDF-Vorlage zu Rechnung 1 |
demo-2026-0002.csv | Beispiel-Rechnung 2 (Lizenzen, Service, Schulung) |
demo-2026-0002.pdf | PDF-Vorlage zu Rechnung 2 |
create-zugferd-demo.cmd | Startskript für Windows |
Schnellstart#
- ZIP-Archiv aus den GitHub Releases herunterladen.
- Alle Dateien in einen gemeinsamen Ordner entpacken.
create-zugferd-demo.cmdper Doppelklick oder in der Eingabeaufforderung starten.
Die erzeugten ZUGFeRD-Dateien liegen danach im Unterordner output\.
Die zwei Demo-Rechnungen#
DEMO-2026-0001 — Softwarelizenzen mit Rabatt#
Käufer: Beispiel Nord GmbH
| Pos | Produkt | Menge | Einzelpreis | Rabatt | Einheitencode |
|---|---|---|---|---|---|
| 0 | Demo Software 9 Light Einzelplatz-Lizenz | 2 | 357,00 € | 10 % | C62 (Stück) |
| 1 | Demo Software 9 Standard Einzelplatz-Lizenz | 1 | 579,00 € | — | C62 (Stück) |
Netto: 1.221,60 € · MwSt 19 %: 232,10 € · Brutto: 1.453,70 €
DEMO-2026-0002 — Lizenzen, Service und Schulung#
Käufer: Beispiel West GmbH
| Pos | Produkt | Menge | Einzelpreis | Rabatt | Einheitencode |
|---|---|---|---|---|---|
| 0 | Demo Software 9 Enterprise Floating-Lizenz | 5 | 1.839,00 € | 10 % | C62 (Stück) |
| 1 | Software Service Vertrag Enterprise | 5 | 275,85 € | — | ANN (Jahr) — per Regex aus Produktcode 002xx |
| 2 | Vor-Ort-Schulungen | 2 | 1.500,00 € | — | DAY (Tag) — per Regex aus Produktname Schulung |
Netto: 12.654,75 € · MwSt 19 %: 2.404,40 € · Brutto: 15.059,15 €
config_demo.yml im Detail#
Die YAML-Konfiguration verbindet die CSV-Spalten mit den ZUGFeRD-Feldern. Jeder Abschnitt ist unabhängig konfigurierbar.
CSV-Einstellungen#
csv:
separator: ","
encoding: "UTF-8"
hasHeader: true
decimalSeparator: "."
dateFormat: "dd.MM.yyyy"Die Demo-CSV verwendet Komma als Trennzeichen und Punkt als Dezimalzeichen — typisch für CRM-Exporte. Datumsfelder stehen im Format 24.05.2026.
ZUGFeRD-Ausgabe#
zugferd:
version: "2.3"
profile: "Extended"
format: "CII"Profil Extended erlaubt alle Pflicht- und optionalen Felder der ZUGFeRD-2.3-Spezifikation. CII ist das XML-Format nach UN/CEFACT Cross Industry Invoice.
Rechnungskopf#
mapping:
invoice:
invoiceNumber:
column: "INVOICE_NO"
invoiceDate:
column: "INVOICE_DUEDATE"
currency:
value: "EUR"
orderReferenceId:
column: "SALESORDER_ID"
referenceOrderNo:
column: "SALESORDER_ID"INVOICE_DUEDATE wird hier bewusst als Rechnungsdatum verwendet, weil die Demo-CSV kein separates Ausstellungsdatum enthält. SALESORDER_ID erscheint zweimal: als orderReferenceId beim Erstellen des InvoiceDescriptor und als referenceOrderNo für die Bestellreferenz im Rechnungskopf.
Käuferdaten — aus der CSV#
buyer:
name:
column: "ACCOUNT_NAME"
postalCode:
column: "INVOICE_BILL_CODE"
city:
column: "INVOICE_BILL_CITY"
street:
column: "INVOICE_BILL_STREET"
country:
value: "DE"
contact:
column: "CONTACT_LASTNAME"Adressdaten kommen direkt aus der CSV. country ist fest auf DE gesetzt, weil die Demo-Rechnungen alle deutschen Käufern gehören. CONTACT_LASTNAME liefert den Ansprechpartner.
Verkäuferdaten — fest in der YAML#
seller:
name:
value: "Demo Software GmbH"
postalCode:
value: "10115"
city:
value: "Musterstadt"
street:
value: "Demostrasse 1"
country:
value: "DE"
taxRegistrations:
- value: "Demo"
scheme: "FC"
- value: "DE000000000"
scheme: "VA"Verkäuferdaten sind für alle Rechnungen identisch und stehen deshalb als feste Werte in der YAML. Das ist die empfohlene Vorgehensweise für eigene Konfigurationen: Stammdaten einmal in der YAML hinterlegen, nicht in jeder CSV-Zeile wiederholen. FC steht für Steuernummer, VA für Umsatzsteuer-ID.
Lieferung und Bestellreferenz#
delivery:
actualDeliveryDate:
column: "SALESORDER_DUEDATE"
orderReference:
orderNumber:
column: "SALESORDER_ID"actualDeliveryDate setzt das Lieferdatum (BT-72). Hier wird das Fälligkeitsdatum der Bestellung als Lieferdatum verwendet. orderNumber entspricht BT-13 (Bestellnummer des Käufers).
Rechnungspositionen — columns-Modus#
lineItems:
mode: "columns"
columnPattern:
style: "suffix"
separator: "_"
startIndex: 0
zeroPadding: 0Im columns-Modus steht die gesamte Rechnung in einer CSV-Zeile. Positionen werden über nummerierte Spaltensuffixe erkannt: PRODUCT_NAME_0, PRODUCT_NAME_1 usw. Die Iteration stoppt, sobald PRODUCT_NAME_N leer ist.
Positionsfelder#
fields:
name:
column: "PRODUCT_NAME"
sellerAssignedId:
column: "PRODUCT_CODE"
netUnitPrice:
column: "PRODUCT_PRICE"
billedQuantity:
column: "PRODUCT_QUANTITY"
taxPercent:
column: "INVOICE_TAX"
discountPercent:
column: "PRODUCT_DISCOUNT"| Feld | CSV-Spalte | Besonderheit |
|---|---|---|
name | PRODUCT_NAME_N | Positionsbezeichnung, Pflichtfeld |
sellerAssignedId | PRODUCT_CODE_N | Interne Artikelnummer, positionsbezogen |
netUnitPrice | PRODUCT_PRICE_N | Netto-Einzelpreis vor Rabatt |
billedQuantity | PRODUCT_QUANTITY_N | Menge |
taxPercent | INVOICE_TAX | Globale Spalte — einmal pro Rechnung, gilt für alle Positionen |
discountPercent | PRODUCT_DISCOUNT_N | Positionsbezogener Rabatt, akzeptiert 10, 10.00 oder 10% |
INVOICE_TAX ist eine globale Spalte: der Wert 19.00 steht einmal in der CSV und wird auf jede erzeugte Position angewendet. PRODUCT_DISCOUNT_N ist dagegen positionsbezogen — Position 0 liest PRODUCT_DISCOUNT_0, Position 1 liest PRODUCT_DISCOUNT_1.
Einheitencodes per Regex — fixedFields#
fixedFields:
unitCode:
default: "C62"
rules:
- when:
column: "PRODUCT_CODE"
regex: "^002"
value: "ANN"
- when:
column: "PRODUCT_CODE"
regex: "^003"
value: "DAY"
- when:
column: "PRODUCT_NAME"
regex: "(?i)vor-ort-schulung|schulung"
value: "DAY"
taxType:
value: "VAT"
taxCategoryCode:
value: "S"fixedFields enthält Positionsfelder, die meistens konstant sind, aber FieldMapping mit rules unterstützen.
Der Einheitencode unitCode wird per Regex aus dem Produktcode oder Produktnamen abgeleitet:
| Bedingung | Regex | Ergebnis | Bedeutung |
|---|---|---|---|
PRODUCT_CODE_N beginnt mit 002 | ^002 | ANN | Jahr (Jahreslizenzen, Serviceverträge) |
PRODUCT_CODE_N beginnt mit 003 | ^003 | DAY | Tag (Tagessätze) |
PRODUCT_NAME_N enthält „Schulung" | (?i)vor-ort-schulung|schulung | DAY | Tag (Schulungen) |
| sonst | — | C62 | Stück (Standardfall) |
Im columns-Modus werden Regelspalten positionsbezogen aufgelöst: bei Position 1 prüft die Regel PRODUCT_CODE_1, bei Position 2 PRODUCT_CODE_2 usw.
Summen#
totals:
mode: "auto"auto berechnet alle Summen aus den Positionsdaten: Zeilennetto, Rabatte, Steuerbasis, MwSt-Gruppen und Gesamtbetrag. Keine manuelle CSV-Spalte nötig.
Zahlungsbedingungen#
paymentTerms:
description:
value: "Zahlbar ohne Abzug bis zum Faelligkeitsdatum"
dueDate:
column: "INVOICE_DUEDATE"Die Zahlungsbeschreibung ist fest in der YAML. Das Fälligkeitsdatum kommt aus INVOICE_DUEDATE — derselben Spalte, die auch als Rechnungsdatum dient.
Nächster Schritt#
Sie haben das Demo-Paket erfolgreich ausprobiert. Im nächsten Schritt erstellen Sie Ihre eigene config.yml für Ihre CSV-Datei und erzeugen daraus Ihre erste ZUGFeRD-PDF.
Ausgabe prüfen#
Die erzeugten PDF-Dateien im Ordner output\ sind valide ZUGFeRD-2.3-Rechnungen im Profil Extended. Für die Prüfung siehe ZUGFeRD-Validierung →.