F: Wie erstelle ich ZUGFeRD-Rechnungen und XRechnungen per CSV und zugcmd aus meiner eigenen Anwendung?

Thema
Kommandozeilen-Tools
Business Terms
BT-1 Rechnungsnummer BT-2 Rechnungsdatum BT-3 Code für den Rechnungstyp BT-10 Referenz des Käufers BT-72 Tatsächliches Lieferdatum BT-106 Summe der Nettobeträge aller Rechnungspositionen BT-109 Rechnungsgesamtbetrag ohne Umsatzsteuer BT-112 Rechnungsgesamtbetrag einschließlich Umsatzsteuer
Codebeispiele
Kommandozeile, Delphi
Veröffentlicht

Kurz: Ihre Anwendung – egal ob Delphi, VB6, Access, COBOL oder eine andere Sprache – schreibt die Rechnungsdaten in vier CSV-Dateien und ruft das Kommandozeilenwerkzeug zugcmd auf. zugcmd liest die Dateien, erzeugt das E-Rechnungs-XML nach EN 16931 (XRechnung 3.0, Syntax CII) und bettet es in Ihre vorhandene PDF-Rechnung ein. Heraus kommt eine hybride ZUGFeRD-Rechnung (PDF/A-3), die Sie wie gewohnt per E-Mail versenden. Eine Programmierung gegen das SDK ist dafür nicht nötig.

Der Ablauf

  1. Ihre Anwendung erzeugt die PDF-Rechnung wie bisher.
  2. Sie schreibt die Rechnungsdaten in die CSV-Dateien (siehe unten).
  3. Sie startet zugcmd und wertet den Rückgabewert aus (0 = Erfolg).
  4. zugcmd schreibt das XML und die ZUGFeRD-PDF mit eingebettetem XML.
  5. Ihre Anwendung versendet die ZUGFeRD-PDF per E-Mail. Den Versand übernimmt zugcmd nicht.

Ohne vorhandenes PDF kann zugcmd das PDF auch aus einer Word-Vorlage (DOCX) erzeugen; das beschreibt die zugcmd-Seite.

Welche CSV-Dateien braucht zugcmd?

DateiInhaltParameterPflicht
seller.csvVerkäufer: Name, Anschrift, Kontakt, USt-ID, Bankverbindung-sja – ändert sich kaum, kann als Stammdatei liegen bleiben
buyer.csvKäufer / Rechnungsempfänger-bja
items.csvRechnungspositionen, eine Zeile je Position-pja
totals.csvRechnungskopf, Summen und Umsatzsteuer-Aufschlüsselung-tja
allowances.csvZu- und Abschläge auf Rechnungsebene-znur bei Bedarf
deliverto.csv / deliverfrom.csvabweichende Liefer- bzw. Versandanschrift-h / -gnur bei Bedarf

Aufbau der CSV-Dateien

  • Erste Zeile = Spaltennamen, darunter die Daten. In items.csv folgt eine Zeile je Position, in den anderen Dateien genau eine Datenzeile.
  • Zuordnung über den Spaltennamen: Groß-/Kleinschreibung und Reihenfolge der Spalten spielen keine Rolle. Nicht benötigte Spalten lassen Sie einfach weg.
  • Beträge mit Punkt als Dezimaltrennzeichen (59.50), Datumswerte als JJJJMMTT.
  • Trennzeichen mit -y angeben (z. B. , oder ;). Werte, die das Trennzeichen enthalten, in Anführungszeichen setzen.
  • Zeichensatz mit -c angeben: Standard ist utf8; Programme, die Windows-ANSI schreiben (z. B. Delphi 5 bis 2007, VB6), nutzen -c ansi.
  • Mehrere Steuersätze: In totals.csv stehen bis zu 11 Steuersätze – der erste in den Spalten TAX…, weitere in TAX…1 bis TAX…10 (z. B. TAXBasisAmount1).

Getestetes Minimalbeispiel

Eine Rechnung über 10 × 5,00 € netto zu 19 %. Mit diesen vier Dateien erzeugt das SDK ein XML, das der KoSIT-Validator (XRechnung 3.0.2) ohne Fehler und ohne Warnungen annimmt (geprüft am 16.10.2026 mit der Funktion ImportCSV, die auch zugcmd verwendet).

seller.csv

Name,personname,Street1,city,phone,email,vat,country,postcode,iban,bic,paymentmeans,paymentdescription,accountname
Muster GmbH,Erika Muster,Hauptstr. 1,Hamburg,+49 40 123456,rechnung@muster.example,DE123456789,DE,20095,DE02120300000000202051,BYLADEM1001,58,SEPA-Überweisung,Muster GmbH

buyer.csv

id,Name,Street1,city,email,country,postcode
K-1001,Kunde AG,Marktplatz 5,München,einkauf@kunde.example,DE,80331

items.csv

AssignedID,productname,description,quantity,unit,netprice,netbasisquantity,netbasisunit,taxpercent,taxtypecode,taxcategorycode,totalamount
ART-100,Papier A4,500 Blatt,10,C62,5.00,1,C62,19,VAT,S,50.00

totals.csv

type,currency,invoiceid,invoicedate,DeliveryDate,leitwegid,LineTotalAmount,ChargeTotalAmount,AllowanceTotalAmount,TaxBasisTotalAmount,TaxTotalAmount,GrandTotalAmount,TotalPrepaidAmount,DuePayableAmount,PaymentTerms,duedate,TAXCalculatedAmount,TAXTypeCode,TAXBasisAmount,TAXCategoryCode,TAXRateApplicablePercent
380,EUR,RE-2027-0001,20270104,20270104,K-1001,50.00,0.00,0.00,50.00,9.50,59.50,0.00,59.50,Zahlbar innerhalb 30 Tagen netto,20270203,9.50,VAT,50.00,S,19

Die wichtigsten Spalten und ihre Business Terms

DateiSpalteBedeutung
totals.csvtypeRechnungsart, BT-3 (380 Rechnung, 381 Gutschrift, 875 Abschlagsrechnung Bau)
totals.csvinvoiceid / invoicedateRechnungsnummer BT-1 / Rechnungsdatum BT-2
totals.csvcurrencyWährung, BT-5
totals.csvDeliveryDateLeistungsdatum, BT-72
totals.csvleitwegidKäuferreferenz bzw. Leitweg-ID, BT-10
totals.csvPaymentTerms / duedateZahlungsbedingungen BT-20 / Fälligkeitsdatum BT-9
totals.csvLineTotalAmountSumme der Positionen, BT-106
totals.csvAllowanceTotalAmount / ChargeTotalAmountSumme Abschläge BT-107 / Zuschläge BT-108
totals.csvTaxBasisTotalAmountNettobetrag, BT-109
totals.csvTaxTotalAmountUmsatzsteuer gesamt, BT-110
totals.csvGrandTotalAmount / DuePayableAmountBruttobetrag BT-112 / Zahlbetrag BT-115
totals.csvTAXBasisAmount / TAXCalculatedAmountSteuerbasis BT-116 / Steuerbetrag BT-117 je Steuersatz
totals.csvTAXCategoryCode / TAXRateApplicablePercentSteuerkategorie BT-118 (S, Z, E, AE, K …) / Steuersatz BT-119
items.csvquantity / unitMenge BT-129 / Mengeneinheit BT-130 (z. B. C62 Stück, H87 Stück, KGM Kilogramm)
items.csvnetprice / netbasisquantity / netbasisunitNettopreis BT-146 je Basismenge BT-149 in Einheit BT-150
items.csvtotalamountNettobetrag der Position, BT-131

Alle weiteren Spalten (Bestellnummer, Projekt, Vertrag, Rabatte je Position, globale Artikelnummer …) beschreiben die Seiten der einzelnen Dateien, verlinkt in der Tabelle oben.

Für eine gültige XRechnung braucht es außerdem die Käuferreferenz bzw. Leitweg-ID (leitwegid, BT-10), beim Verkäufer einen Kontakt mit Name, Telefon und E-Mail (personname, phone, email) und bei beiden Parteien eine E-Mail-Adresse.

Summen berechnet Ihre Anwendung

zugcmd übernimmt die Summen so, wie sie in totals.csv stehen. Die häufigsten Fehler:

  • Steuerbasis bei Rabatten: TAXBasisAmount ist der Nettobetrag nach Abschlägen und Zuschlägen dieses Steuersatzes, nicht die Summe der Positionen – siehe BR-S-08, BR-S-09 und BR-CO-17.
  • Gerundete Positionen: LineTotalAmount ist die Summe der gerundeten Positionsbeträge (BR-CO-10).
  • Rundung nur auf den Zahlbetrag: siehe BR-CO-15 und BR-CO-16.

zugcmd aus der eigenen Anwendung starten

Sie müssen zugcmd nicht von Hand auf der Kommandozeile starten; Ihre Anwendung ruft es selbst auf. Neben zugcmd.exe enthält das Paket zugcmd_wnd.exe, die ohne Konsolenfenster läuft – praktisch für den Aufruf aus Programmen mit Oberfläche. Ein Aufruf für eine Rechnung (in einer Zeile):

zugcmd_wnd.exe -s "C:\ERechnung\stamm\seller.csv" -b "C:\ERechnung\RE-2027-0001\buyer.csv" -p "C:\ERechnung\RE-2027-0001\items.csv" -t "C:\ERechnung\RE-2027-0001\totals.csv" -i "C:\ERechnung\RE-2027-0001\RE-2027-0001.pdf" -x "C:\ERechnung\RE-2027-0001\RE-2027-0001.xml" -o "C:\ERechnung\RE-2027-0001\RE-2027-0001_zugferd.pdf" -y "," -c ansi -l IHR-LIZENZSCHLUESSEL

Immer vollständige Pfade angeben (mit Laufwerk und Ordner) oder mit -d ein Basisverzeichnis setzen, gegen das bloße Dateinamen aufgelöst werden. Ein bloßer Dateiname ohne -d wird nicht gefunden.

Den Erfolg erkennen Sie am Rückgabewert (ExitCode): 0 bedeutet Erfolg, z. B. 57 „Eingabe-PDF nicht gefunden“ oder 59 „XML konnte nicht erstellt werden“. Die vollständige Liste steht auf der zugcmd-Seite. Funktionen wie ShellExecute (Delphi) oder Shell (VB6) liefern den Rückgabewert nicht; nutzen Sie CreateProcess mit GetExitCodeProcess. Beispiel für Delphi (ab Version 5):

uses Windows, SysUtils;

function StarteZugcmd(const Parameter: string): DWORD;
var
  SI: TStartupInfo;
  PI: TProcessInformation;
  Cmd: string;
begin
  Result := DWORD(-1);
  Cmd := '"C:\zugcmd\zugcmd_wnd.exe" ' + Parameter;
  FillChar(SI, SizeOf(SI), 0);
  SI.cb := SizeOf(SI);
  if CreateProcess(nil, PChar(Cmd), nil, nil, False, 0, nil, nil, SI, PI) then
  begin
    WaitForSingleObject(PI.hProcess, INFINITE);   // warten, bis zugcmd fertig ist
    GetExitCodeProcess(PI.hProcess, Result);      // 0 = Erfolg
    CloseHandle(PI.hThread);
    CloseHandle(PI.hProcess);
  end;
end;

Dateinamen und Mengen

  • Dateinamen bestimmt Ihre Anwendung mit -x (XML) und -o (PDF), am besten mit der Rechnungsnummer. Ohne Angabe heißen die Dateien OutputXML.xml und OutputPDF.pdf; eine automatische Nummerierung gibt es nicht.
  • Viele Rechnungen (z. B. einige hundert pro Tag) sind kein Problem: ein Aufruf je Rechnung. Legen Sie die CSV-Dateien jeder Rechnung in einen eigenen Ordner oder geben Sie ihnen eindeutige Namen, damit sich parallele Aufrufe nicht gegenseitig überschreiben.
  • Vorhandene Dateien überschreibt zugcmd standardmäßig; mit -f false bleiben sie erhalten.

Tipp: Zuordnung an einer echten Rechnung ansehen

zugcmd arbeitet auch rückwärts: -r rechnung.xml (oder ein ZUGFeRD-PDF) zerlegt eine vorhandene E-Rechnung in genau diese CSV-Dateien. So sehen Sie an einem echten Beispiel, welches Feld in welche Spalte gehört. Das Download-Paket zugcmd.zip (Downloads) enthält außerdem Beispiel-CSV-Dateien, bei denen die BT-Nummern direkt in den Werten stehen, zwei komplette Beispielsätze (Überweisung, Bankeinzug) und die readme.txt mit allen Parametern.

Wer lieber direkt programmiert, nutzt das SDK über COM: mit Delphi oder mit VB6, VB5 und VBA.

Häufige Fragen

Brauche ich Programmierkenntnisse für das SDK, um zugcmd zu nutzen?

Nein. Ihre Anwendung schreibt CSV-Dateien und startet zugcmd mit Parametern. Programmiert wird nur das Schreiben der CSV-Dateien und der Aufruf.

Gibt es eine Beschreibung der CSV-Spalten?

Ja. Jede Datei hat eine eigene Seite mit allen Spalten und Business Terms: seller.csv, buyer.csv, items.csv, totals.csv und allowances.csv. Die Spalten werden über ihren Namen zugeordnet, die Reihenfolge ist beliebig.

Muss zugcmd auf der Kommandozeile gestartet werden?

Nein. Jede Anwendung kann zugcmd als Prozess starten. zugcmd_wnd.exe läuft ohne Konsolenfenster; der Rückgabewert 0 bedeutet Erfolg.

Wie werden die erzeugten Dateien benannt?

So, wie Ihre Anwendung sie mit -x (XML) und -o (PDF) angibt, zum Beispiel nach der Rechnungsnummer. Ohne Angabe heißen sie OutputXML.xml und OutputPDF.pdf.

Schafft zugcmd 200 Rechnungen am Tag?

Ja. Pro Rechnung genügt ein Aufruf. Wichtig ist nur, dass jede Rechnung eigene CSV- und Ausgabedateien hat.

Verschickt zugcmd die Rechnung auch per E-Mail?

Nein. zugcmd erzeugt das XML und die ZUGFeRD-PDF; den Versand übernimmt Ihre Anwendung oder Ihr Mailprogramm.

Business Terms in diesem Artikel: BT-1 BT-2 BT-3 BT-10 BT-72 BT-106 BT-109 BT-112 BT-115 BT-116 BT-117 BT-5 BT-9 BT-20 BT-107 BT-108 BT-110 BT-118 BT-119 BT-129 BT-130 BT-131 BT-146