- Membres du SDK
- ActualDeliveryDate_102 AddPaymentMeans() AddProduct_Comfort() AddTradePaymentTerms() AddTradeTax() BuyerAddressLine1 BuyerCity BuyerCountry BuyerName BuyerPostCode
- Termes métier
- BT-1 Invoice number BT-2 Invoice issue date BT-3 Invoice type code BT-5 Invoice currency code BT-31 Seller VAT identifier BT-72 Actual delivery date BG-25 Invoice line BG-23 VAT breakdown
- Exemples de code
- Ligne de commande, Delphi
- Publié le
En bref : les applications Delphi – y compris les plus anciennes écrites en Delphi 5 ou Delphi 7 – créent des factures électroniques conformes à la EN 16931 (ZUGFeRD 2.x, Factur-X, XRechnung) via l'interface COM du SDK Aloaha ZUGFeRD. Il n'est pas nécessaire de changer de version de Delphi. Deux voies sont possibles : la liaison tardive avec CreateOleObject('Aloaha_ZUGFeRD.XML'), sans importation, ou la liaison anticipée via la bibliothèque de types fournie Aloaha_ZUGFeRD.tlb. Votre programme crée la facture PDF comme auparavant ; le SDK écrit le XML et l'intègre dans le PDF (facture ZUGFeRD hybride, PDF/A-3).
Liaison tardive ou anticipée ?
| Liaison tardive | Liaison anticipée | |
|---|---|---|
| Créer l'objet | CreateOleObject('Aloaha_ZUGFeRD.XML') | CoXML.Create depuis l'unité importée |
| Importer la bibliothèque de types | non | oui, une fois (Aloaha_ZUGFeRD.tlb) |
| Complétion de code dans l'IDE | non | oui |
| Contrôle des noms et des paramètres | à l'exécution | à la compilation |
| Paramètres facultatifs | les omettre en fin de liste | sous Delphi 5, tous les transmettre |
| Enregistrement de la DLL | nécessaire dans les deux cas – effectué par le programme d'installation du SDK | |
Pour un démarrage rapide et pour de petites modifications de programmes existants, la liaison tardive est la voie la plus simple. Si vous programmez beaucoup avec le SDK, la liaison anticipée est rentable.
Prérequis
- Windows avec .NET Framework 4.7.2 ou ultérieur.
- SDK Aloaha ZUGFeRD depuis la page de téléchargement. Le programme d'installation du SDK (MSI) enregistre l'interface COM pour 32 et 64 bits.
- Distribution manuelle sans programme d'installation : enregistrez la DLL avec le Regasm de l'architecture correspondante, en tant qu'administrateur. Delphi 5 à Delphi XE produisent des programmes 32 bits ; utilisez pour ceux-ci le Regasm de
C:\Windows\Microsoft.NET\Framework\v4.0.30319\(et nonFramework64) :
Les fichiers nécessaires sont décrits dans Register libraries for Delphi.regasm /codebase Aloaha_ZUGFeRD.dll - Autotest COM : le paquet
zugferdbinaries.zipcontient le scriptzugferd_com_test.vbs. Il vérifie l'enregistrement et l'architecture et crée l'objet à titre de test ; pour le test 32 bits sur un Windows 64 bits, lancez-le avecC:\Windows\SysWOW64\cscript.exe. - Clé de licence : vous obtenez une licence d'essai gratuite et complète par e-mail à info@aloaha.com.
Étape par étape
- Installer le SDK (ou enregistrer la DLL, voir ci-dessus).
- Créer l'objet, définir la clé de licence et le profil.
- Renseigner l'en-tête de facture, le vendeur, l'acheteur et les données de paiement.
- Ajouter les lignes dans une boucle (
AddProduct_Comfort). - Définir la ventilation de la TVA par taux (
AddTradeTax) et les totaux (WriteTotals). - Enregistrer le XML (
SaveXML) et l'intégrer dans la facture PDF existante (MergeXMLIntoPDF). - Contrôler la première facture avec un validateur – voir Comment contrôler ma XRechnung avant l'envoi ?
Toujours transmettre les montants avec un point décimal
Le SDK attend des montants sous forme de texte avec un point comme séparateur décimal (59.50). Avec des paramètres régionaux Windows français ou allemands, Delphi écrirait une virgule. Les deux exemples utilisent cette fonction d'aide (Betrag = montant) :
// Delphi 5 à 2010
function Betrag(Wert: Double): string;
begin
Result := StringReplace(FormatFloat('0.00', Wert), DecimalSeparator, '.', []);
end;
Variante 1 : liaison tardive avec CreateOleObject
uses ComObj;
procedure ErzeugeERechnung_LateBinding;
var
alo: OleVariant;
begin
alo := CreateOleObject('Aloaha_ZUGFeRD.XML');
alo.Licensekey := 'VOTRE-CLE-DE-LICENCE';
alo.ZUGFeRD_Profile := 1; // 0 = BASIC, 1 = EN 16931 (COMFORT), 2 = EXTENDED
// en-tête : numéro (BT-1), texte, date (BT-2), format de date, nom, langue, devise (BT-5)
alo.CreateInvoiceObject('RE-2027-0001', 'Invoice as per order',
'20270104', '102', '', 'DE', 'EUR');
alo.Document_TypeINT := 380; // BT-3 : 380 = facture, 381 = avoir
alo.ActualDeliveryDate_102 := '20270104'; // BT-72 : date de livraison
// vendeur avec numéro de TVA (BT-31)
alo.WriteSeller('Muster GmbH', '20095', 'Hamburg', 'Hauptstr. 1', '', 'DE', 'DE123456789');
// acheteur
alo.BuyerName := 'Kunde AG';
alo.BuyerAddressLine1 := 'Marktplatz 5';
alo.BuyerPostCode := '80331';
alo.BuyerCity := 'München';
alo.BuyerCountry := 'DE';
// paiement : 58 = virement SEPA (BT-81)
alo.AddPaymentMeans(58, 'SEPA credit transfer', 'DE02120300000000202051',
'Muster GmbH', '', 'BYLADEM1001');
alo.AddTradePaymentTerms('Payable within 30 days net');
// ligne (BG-25) : 10 pièces à 5,00 EUR, 19 %
alo.AddProduct_Comfort(1, '', 'ART-100', '10.00', 'C62', 'Paper A4', '500 sheets',
'', 'EUR', '', 'C62', False, '', '', '', Betrag(5.00), 'EUR', '1.00',
'C62', 'VAT', 'S', '19.00', '', Betrag(50.00), 'EUR', '', '');
// ventilation TVA (BG-23) : taxe, devise, base, devise, type, catégorie, taux
alo.AddTradeTax(Betrag(9.50), 'EUR', Betrag(50.00), 'EUR', 'VAT', 'S', '19.00');
// totaux (BG-22) : lignes, total TTC, montant dû, net, taxe
alo.WriteTotals(Betrag(50.00), Betrag(59.50), Betrag(59.50), Betrag(50.00), Betrag(9.50));
// enregistrer le XML et l'intégrer dans la facture PDF existante
if alo.SaveXML('C:\Invoices\RE-2027-0001.xml') then
alo.MergeXMLIntoPDF('C:\Invoices\RE-2027-0001.xml',
'C:\Invoices\RE-2027-0001.pdf',
'C:\Invoices\RE-2027-0001_zugferd.pdf',
True, '', 'VOTRE-CLE-DE-LICENCE')
else
ShowMessage(alo.Last_Error);
end;
En pratique, remplacez les valeurs fixes par les champs de votre table de factures et appelez AddProduct_Comfort dans une boucle sur les lignes. Pour une XRechnung destinée aux administrations allemandes, définissez en outre alo.isKOSIT := True et alo.LeitwegID.
Variante 2 : liaison anticipée via la bibliothèque de types
La bibliothèque de types Aloaha_ZUGFeRD.tlb est fournie avec le SDK. Vous n'avez pas à la créer vous-même ; si nécessaire, utilisez regasm /codebase Aloaha_ZUGFeRD.dll /tlb:Aloaha_ZUGFeRD.tlb.
- Sous Delphi 5 : Project > Import Type Library > choisir « Aloaha ZUGFeRD Toolkit » > Create Unit. Delphi crée
Aloaha_ZUGFeRD_TLB.pasainsi quemscorlib_TLB.pas. - Si le compilateur signale des erreurs concernant
_SetIUnknownPropdans l'unité générée, supprimez ces lignes. - Ajoutez l'unité à la clause
uses. La classe de facture s'appelleXML, son interface_XML; elle est créée avecCoXML.Create. Vérifiez les noms dans l'unité générée.
Delphi 5 ne reprend pas de manière fiable les valeurs par défaut des paramètres facultatifs depuis la bibliothèque de types. Transmettez donc tous les paramètres :
uses ComObj, Aloaha_ZUGFeRD_TLB;
procedure ErzeugeERechnung_EarlyBinding;
var
alo: _XML;
Standard: TOleEnum;
begin
alo := CoXML.Create;
alo.Licensekey := 'VOTRE-CLE-DE-LICENCE';
alo.ZUGFeRD_Profile := 1; // 1 = EN 16931 (COMFORT)
alo.CreateInvoiceObject('RE-2027-0001', 'Invoice as per order',
'20270104', '102', '', 'DE', 'EUR');
alo.Document_TypeINT := 380;
alo.ActualDeliveryDate_102 := '20270104';
// vendeur : nom, code postal, ville, rue, rue 2, pays, n° TVA, rue 3
alo.WriteSeller('Muster GmbH', '20095', 'Hamburg', 'Hauptstr. 1', '', 'DE', 'DE123456789', '');
alo.BuyerName := 'Kunde AG';
alo.BuyerAddressLine1 := 'Marktplatz 5';
alo.BuyerPostCode := '80331';
alo.BuyerCity := 'München';
alo.BuyerCountry := 'DE';
// paiement : type, texte, IBAN, titulaire, ID de compte, BIC, code banque, banque,
// prélèvement, mandat, ID créancier
alo.AddPaymentMeans(58, 'SEPA credit transfer', 'DE02120300000000202051',
'Muster GmbH', '', 'BYLADEM1001', '', '', False, '', '');
alo.AddTradePaymentTerms('Payable within 30 days net', '', '', '', '', '', '', '', '');
alo.AddProduct_Comfort(1, '', 'ART-100', '10.00', 'C62', 'Paper A4', '500 sheets',
'', 'EUR', '', 'C62', False, '', '', '', Betrag(5.00), 'EUR', '1.00',
'C62', 'VAT', 'S', '19.00', '', Betrag(50.00), 'EUR', '', '');
// 7 paramètres obligatoires et 5 facultatifs
alo.AddTradeTax(Betrag(9.50), 'EUR', Betrag(50.00), 'EUR', 'VAT', 'S', '19.00',
'', '', '', '', '');
// lignes, total TTC, montant dû, net, taxe, remises, payé, arrondi, frais
alo.WriteTotals(Betrag(50.00), Betrag(59.50), Betrag(59.50), Betrag(50.00), Betrag(9.50),
'0.00', '0.00', '0.00', '0.00');
Standard := 2; // 2 = ZUGFeRD 2.x / Factur-X / XRechnung
if alo.SaveXML('C:\Invoices\RE-2027-0001.xml', 'VOTRE-CLE-DE-LICENCE', Standard) then
alo.MergeXMLIntoPDF('C:\Invoices\RE-2027-0001.xml',
'C:\Invoices\RE-2027-0001.pdf',
'C:\Invoices\RE-2027-0001_zugferd.pdf',
True, '', 'VOTRE-CLE-DE-LICENCE', '', '', '', '')
else
ShowMessage(alo.Last_Error);
end;
L'ordre des méthodes dans l'interface COM n'a pas changé depuis la version 10 ; les nouvelles fonctions ne sont ajoutées qu'à la fin. Une unité importée une fois continue donc de fonctionner avec les versions plus récentes du SDK.
Les méthodes surchargées portent d'autres noms en COM
COM ne connaît pas la surcharge. Si une méthode existe plusieurs fois en .NET, la deuxième variante reçoit le suffixe _2 dans Delphi. Points importants pour Delphi :
| Nom dans Delphi | Paramètres |
|---|---|
WriteTotals | montants sous forme de texte ('59.50') |
WriteTotals_2 | montants en Double |
AddProduct_Comfort | numéro de ligne sous forme de nombre |
AddProduct_Comfort_2 | numéro de ligne sous forme de texte (p. ex. '1.1') |
AddPaymentMeans | moyen de paiement sous forme de nombre (UNTDID 4461, p. ex. 58) |
AddPaymentMeans_2 | moyen de paiement sous forme de texte ('58') |
Dans Delphi, transmettez les énumérations comme le profil ou le moyen de paiement sous forme de nombres. Pour le type de facture (BT-3), il existe une propriété dédiée Document_TypeINT, voir Créer une facture et le type de facture (BT-3) (en allemand).
Versions plus récentes de Delphi
- Delphi 2009 et ultérieur :
stringest en Unicode ; les caractères accentués parviennent au SDK sans détour. Le code reste identique. - À partir de Delphi XE : la variable globale
DecimalSeparatorest obsolète. UtilisezTFormatSettings:function Betrag(Wert: Double): string; var FS: TFormatSettings; begin FS := TFormatSettings.Create; FS.DecimalSeparator := '.'; Result := FormatFloat('0.00', Wert, FS); end; - Programmes 64 bits (à partir de Delphi XE2) : la DLL doit aussi être enregistrée pour 64 bits. Le programme d'installation du SDK fait les deux ; pour un enregistrement manuel, utilisez le Regasm de
Framework64.
Erreurs fréquentes
| Message | Cause | Solution |
|---|---|---|
| « Invalid class string » | La classe COM n'est pas enregistrée. | Exécuter le programme d'installation du SDK ou regasm /codebase en tant qu'administrateur. |
| « Class not registered » | Enregistrée uniquement pour l'autre architecture, p. ex. 64 bits pour un programme 32 bits. | Enregistrer avec le Regasm correspondant (Framework pour 32 bits). |
| « Unknown name » | Faute de frappe, ou la variante surchargée porte un autre nom (_2). | Vérifier le nom ; la liaison anticipée signale ces erreurs dès la compilation. |
| « Type mismatch » | Du texte là où le SDK attend un nombre (ou inversement). | Vérifier le type de paramètre de la variante, voir le tableau ci-dessus. |
| Validateur : BR-CO-10, BR-S-08, BR-CO-17 | Les totaux ne correspondent pas aux lignes ou à la base d'imposition. | Base d'imposition = net après remises, voir BR-S-08, BR-S-09 et BR-CO-17. |
Si SaveXML renvoie False, la cause figure dans Last_Error.
Alternative sans COM : zugcmd
Si le code Delphi doit rester aussi inchangé que possible, votre programme écrit les données de facture dans des fichiers CSV et appelle l'outil en ligne de commande zugcmd, par exemple via ShellExecute. zugcmd en produit une facture ZUGFeRD, Factur-X ou XRechnung et intègre le XML dans votre PDF.
Étape par étape, avec des fichiers d'exemple testés, l'appel depuis votre propre application et les noms de fichiers : Créer des factures électroniques via CSV et zugcmd depuis votre application.
Tous les appels en détail, avec remises et plusieurs taux de TVA : démarrage rapide avec VB.NET – les méthodes et paramètres sont les mêmes en Delphi. Le même guide pour Visual Basic : Créer ZUGFeRD et XRechnung avec VB6, VB5 et VBA.
Questions fréquentes
Puis-je créer des factures ZUGFeRD avec Delphi 5 ?
Oui. Le SDK Aloaha ZUGFeRD dispose d'une interface COM que Delphi 5 utilise via CreateOleObject('Aloaha_ZUGFeRD.XML') ou via la bibliothèque de types fournie. Une version plus récente de Delphi n'est pas nécessaire.
Dois-je importer la bibliothèque de types ?
Non, pas pour la liaison tardive. L'importation (liaison anticipée) apporte la complétion de code et des contrôles à la compilation. La DLL doit être enregistrée dans les deux cas ; le programme d'installation du SDK s'en charge.
Cela fonctionne-t-il aussi avec Delphi 7, XE ou Delphi 12 ?
Oui, la voie COM est la même. À partir de Delphi XE, utilisez TFormatSettings pour le point décimal ; les programmes 64 bits nécessitent l'enregistrement 64 bits.
Puis-je continuer à utiliser ma facture PDF existante produite par Delphi ?
Oui. MergeXMLIntoPDF intègre le XML dans votre facture PDF existante et en fait une facture ZUGFeRD hybride (PDF/A-3).
Puis-je aussi créer une XRechnung pure avec Delphi ?
Oui. Définissez isKOSIT := True et le Leitweg-ID, puis enregistrez uniquement le XML avec SaveXML.
Pourquoi une méthode s'appelle-t-elle soudain WriteTotals_2 dans Delphi ?
COM ne connaît pas la surcharge. La deuxième variante .NET d'une méthode reçoit le suffixe _2. WriteTotals attend les montants sous forme de texte, WriteTotals_2 en Double.
Termes métier dans cet article : BT-1 BT-2 BT-3 BT-5 BT-31 BT-72 BG-25 BG-23 BG-22 BT-81 BT-106 BT-109 BT-110 BT-112 BT-115 BT-116