Comment créer des factures électroniques par CSV et zugcmd depuis mon application ?

Termes métier
BT-1 Invoice number BT-2 Invoice issue date BT-3 Invoice type code BT-10 Buyer reference BT-72 Actual delivery date BT-106 Sum of Invoice line net amount BT-109 Invoice total amount without VAT BT-112 Invoice total amount with VAT
Exemples de code
Ligne de commande, Delphi
Publié le

En bref : votre application – qu'elle soit écrite en Delphi, VB6, Access, COBOL ou tout autre langage – écrit les données de facture dans quatre fichiers CSV et appelle l'outil en ligne de commande zugcmd. zugcmd lit les fichiers, crée le XML de la facture électronique selon EN 16931 (XRechnung 3.0, syntaxe CII) et l'intègre dans votre facture PDF existante. Le résultat est une facture ZUGFeRD hybride (PDF/A-3) que vous envoyez par e-mail comme d'habitude. Aucune programmation avec le SDK n'est nécessaire.

Le déroulement

  1. Votre application crée la facture PDF comme d'habitude.
  2. Elle écrit les données de facture dans les fichiers CSV (voir ci-dessous).
  3. Elle lance zugcmd et évalue le code retour (0 = succès).
  4. zugcmd écrit le XML et le PDF ZUGFeRD avec le XML intégré.
  5. Votre application envoie le PDF ZUGFeRD par e-mail. zugcmd ne l'envoie pas.

Sans PDF existant, zugcmd peut aussi créer le PDF à partir d'un modèle Word (DOCX) ; c'est décrit sur la page zugcmd.

De quels fichiers CSV zugcmd a-t-il besoin ?

FichierContenuParamètreObligatoire
seller.csvVendeur : nom, adresse, contact, numéro de TVA, coordonnées bancaires-soui – change rarement, peut rester en place comme fichier de référence
buyer.csvAcheteur / destinataire de la facture-boui
items.csvLignes de facture, une ligne CSV par ligne de facture-poui
totals.csvEn-tête de facture, totaux et ventilation de la TVA-toui
allowances.csvCharges et remises au niveau du document-zsi nécessaire
deliverto.csv / deliverfrom.csvadresse de livraison ou d'expédition différente-h / -gsi nécessaire

Structure des fichiers CSV

  • Première ligne = noms de colonnes, les données en dessous. items.csv contient une ligne par ligne de facture ; les autres fichiers ont exactement une ligne de données.
  • Correspondance par nom de colonne : majuscules/minuscules et ordre des colonnes n'ont pas d'importance. Omettez simplement les colonnes dont vous n'avez pas besoin.
  • Montants avec un point comme séparateur décimal (59.50), dates au format AAAAMMJJ.
  • Séparateur : indiquez-le avec -y (par ex. , ou ;). Mettez entre guillemets les valeurs qui contiennent le séparateur.
  • Jeu de caractères : indiquez-le avec -c : la valeur par défaut est utf8 ; les programmes qui écrivent en ANSI Windows (par ex. Delphi 5 à 2007, VB6) utilisent -c ansi.
  • Plusieurs taux de TVA : totals.csv accepte jusqu'à 11 taux de TVA – le premier dans les colonnes TAX…, les suivants dans TAX…1 à TAX…10 (par ex. TAXBasisAmount1).

Exemple minimal testé

Une facture de 10 × 5,00 EUR HT à 19 %. Avec ces quatre fichiers, le SDK crée un XML que le validateur KoSIT (XRechnung 3.0.2) accepte sans erreur ni avertissement (vérifié le 16 octobre 2026 avec la fonction ImportCSV, que zugcmd utilise également). Les valeurs d'exemple sont en allemand, comme dans une vraie facture allemande.

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

Les colonnes les plus importantes et leurs termes métier

FichierColonneSignification
totals.csvtypeType de facture, BT-3 (380 facture, 381 avoir, 875 facture partielle de travaux)
totals.csvinvoiceid / invoicedateNuméro de facture BT-1 / date de facture BT-2
totals.csvcurrencyDevise, BT-5
totals.csvDeliveryDateDate de livraison, BT-72
totals.csvleitwegidRéférence acheteur ou Leitweg-ID, BT-10
totals.csvPaymentTerms / duedateConditions de paiement BT-20 / date d'échéance BT-9
totals.csvLineTotalAmountSomme des lignes, BT-106
totals.csvAllowanceTotalAmount / ChargeTotalAmountSomme des remises BT-107 / des charges BT-108
totals.csvTaxBasisTotalAmountMontant HT, BT-109
totals.csvTaxTotalAmountTotal de la TVA, BT-110
totals.csvGrandTotalAmount / DuePayableAmountMontant TTC BT-112 / montant à payer BT-115
totals.csvTAXBasisAmount / TAXCalculatedAmountBase d'imposition BT-116 / montant de TVA BT-117 par taux
totals.csvTAXCategoryCode / TAXRateApplicablePercentCatégorie de TVA BT-118 (S, Z, E, AE, K …) / taux de TVA BT-119
items.csvquantity / unitQuantité BT-129 / unité de mesure BT-130 (par ex. C62 pièce, H87 pièce, KGM kilogramme)
items.csvnetprice / netbasisquantity / netbasisunitPrix net BT-146 par quantité de base BT-149 dans l'unité BT-150
items.csvtotalamountMontant net de la ligne, BT-131

Toutes les autres colonnes (numéro de commande, projet, contrat, remises par ligne, numéro d'article global …) sont décrites sur les pages de chaque fichier, liées dans le tableau ci-dessus (en allemand).

Pour une XRechnung valide, il vous faut en plus la référence acheteur ou la Leitweg-ID (leitwegid, BT-10), un contact vendeur avec nom, téléphone et e-mail (personname, phone, email) ainsi qu'une adresse e-mail pour les deux parties.

Votre application calcule les totaux

zugcmd reprend les totaux exactement tels qu'ils figurent dans totals.csv. Les erreurs les plus fréquentes :

  • Base d'imposition avec remises : TAXBasisAmount est le montant HT après les remises et charges de ce taux de TVA, et non la somme des lignes – voir BR-S-08, BR-S-09 et BR-CO-17.
  • Lignes arrondies : LineTotalAmount est la somme des montants de ligne arrondis (BR-CO-10).
  • Arrondi uniquement sur le montant à payer : voir BR-CO-15 et BR-CO-16.

Lancer zugcmd depuis votre application

Vous n'avez pas à lancer zugcmd à la main en ligne de commande ; votre application l'appelle elle-même. Outre zugcmd.exe, le paquet contient zugcmd_wnd.exe, qui s'exécute sans fenêtre de console – pratique pour les appels depuis des programmes avec interface graphique. Un appel pour une facture (sur une seule ligne) :

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 VOTRE-CLE-DE-LICENCE

Indiquez toujours des chemins complets (avec lecteur et dossier), ou définissez avec -d un répertoire de base par rapport auquel les noms de fichiers seuls sont résolus. Un nom de fichier seul sans -d n'est pas trouvé.

Le succès se reconnaît au code retour : 0 signifie succès ; exemples d'erreurs : 57 « PDF d'entrée introuvable » ou 59 « le XML n'a pas pu être créé ». La liste complète figure sur la page zugcmd. Des fonctions comme ShellExecute (Delphi) ou Shell (VB6) ne renvoient pas le code retour ; utilisez CreateProcess avec GetExitCodeProcess. Exemple pour Delphi (à partir de la 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);   // attendre la fin de zugcmd
    GetExitCodeProcess(PI.hProcess, Result);      // 0 = succès
    CloseHandle(PI.hThread);
    CloseHandle(PI.hProcess);
  end;
end;

Noms de fichiers et volumes

  • Les noms de fichiers sont définis par votre application avec -x (XML) et -o (PDF), idéalement d'après le numéro de facture. Sans ces paramètres, les fichiers s'appellent OutputXML.xml et OutputPDF.pdf ; il n'y a pas de numérotation automatique.
  • De nombreuses factures (par ex. quelques centaines par jour) ne posent pas de problème : un appel par facture. Placez les fichiers CSV de chaque facture dans un dossier propre ou donnez-leur des noms uniques afin que des appels parallèles ne s'écrasent pas.
  • Les fichiers existants sont écrasés par défaut ; avec -f false, ils sont conservés.

Astuce : examiner la correspondance sur une vraie facture

zugcmd fonctionne aussi dans l'autre sens : -r invoice.xml (ou un PDF ZUGFeRD) décompose une facture électronique existante exactement en ces fichiers CSV. Vous voyez ainsi sur un exemple réel quel champ va dans quelle colonne. Le paquet de téléchargement zugcmd.zip (téléchargements) contient aussi des fichiers CSV d'exemple avec les numéros BT inscrits directement dans les valeurs, deux jeux d'exemple complets (virement, prélèvement) et le readme.txt avec tous les paramètres.

Si vous préférez programmer directement, utilisez le SDK via COM : avec Delphi ou avec VB6, VB5 et VBA.

Questions fréquentes

Faut-il savoir programmer avec le SDK pour utiliser zugcmd ?

Non. Votre application écrit des fichiers CSV et lance zugcmd avec des paramètres. La seule programmation nécessaire est l'écriture des fichiers CSV et l'appel.

Existe-t-il une description des colonnes CSV ?

Oui. Chaque fichier a sa propre page avec toutes les colonnes et tous les termes métier : seller.csv, buyer.csv, items.csv, totals.csv et allowances.csv. Les colonnes sont associées par leur nom ; l'ordre est libre.

Faut-il lancer zugcmd en ligne de commande ?

Non. Toute application peut lancer zugcmd comme processus. zugcmd_wnd.exe s'exécute sans fenêtre de console ; le code retour 0 signifie succès.

Comment les fichiers générés sont-ils nommés ?

Comme votre application les indique avec -x (XML) et -o (PDF), par exemple d'après le numéro de facture. Sans ces paramètres, ils s'appellent OutputXML.xml et OutputPDF.pdf.

zugcmd peut-il traiter 200 factures par jour ?

Oui. Un appel par facture suffit. Il importe seulement que chaque facture ait ses propres fichiers CSV et fichiers de sortie.

zugcmd envoie-t-il aussi la facture par e-mail ?

Non. zugcmd crée le XML et le PDF ZUGFeRD ; l'envoi est assuré par votre application ou votre programme de messagerie.

Termes métier dans cet article : 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