- Thema
- Beispiel Code
- SDK-Mitglieder
- ActualDeliveryDate_102 AddPaymentMeans() AddProduct_Comfort() AddTradePaymentTerms() AddTradeTax() BuyerAddressLine1 BuyerCity BuyerCountry BuyerName BuyerPostCode
- Business Terms
- BT-1 Rechnungsnummer BT-2 Rechnungsdatum BT-3 Code für den Rechnungstyp BT-5 Code für die Rechnungswährung BT-31 Umsatzsteuer-Identifikationsnummer des Verkäufers BT-72 Tatsächliches Lieferdatum BG-25 Rechnungsposition BG-23 Umsatzsteueraufschlüsselung
- Codebeispiele
- Kommandozeile, Delphi
- Veröffentlicht
Kurz: Delphi-Anwendungen – auch ältere mit Delphi 5 oder Delphi 7 – erzeugen E-Rechnungen nach EN 16931 (ZUGFeRD 2.x, Factur-X, XRechnung) über die COM-Schnittstelle des Aloaha ZUGFeRD SDK. Eine Umstellung der Delphi-Version ist nicht nötig. Es gibt zwei Wege: Late Binding mit CreateOleObject('Aloaha_ZUGFeRD.XML') ohne Import, oder Early Binding über die mitgelieferte Typbibliothek Aloaha_ZUGFeRD.tlb. Ihr Programm erzeugt die PDF-Rechnung wie bisher; das SDK schreibt das XML und bettet es in das PDF ein (hybride ZUGFeRD-Rechnung, PDF/A-3).
Late oder Early Binding?
| Late Binding | Early Binding | |
|---|---|---|
| Objekt anlegen | CreateOleObject('Aloaha_ZUGFeRD.XML') | CoXML.Create aus der importierten Unit |
| Typbibliothek importieren | nein | ja, einmalig (Aloaha_ZUGFeRD.tlb) |
| Codevervollständigung in der IDE | nein | ja |
| Prüfung von Namen und Parametern | zur Laufzeit | beim Kompilieren |
| Optionale Parameter | am Ende weglassen | in Delphi 5 alle angeben |
| Registrierung der DLL | in beiden Fällen nötig – übernimmt das SDK-Setup | |
Für den schnellen Einstieg und für kleine Anpassungen bestehender Programme ist Late Binding der einfachere Weg. Wer viel mit dem SDK programmiert, profitiert von Early Binding.
Voraussetzungen
- Windows mit .NET Framework 4.7.2 oder neuer.
- Aloaha ZUGFeRD SDK von der Download-Seite. Das SDK-Setup (MSI) registriert die COM-Schnittstelle für 32 und 64 Bit.
- Manuelle Verteilung ohne Setup: die DLL mit dem Regasm passender Bitbreite registrieren, als Administrator. Delphi 5 bis Delphi XE erzeugen 32-Bit-Programme; dafür gilt der Regasm aus
C:\Windows\Microsoft.NET\Framework\v4.0.30319\(nichtFramework64):
Welche Dateien dazugehören, beschreibt Bibliotheken für Delphi registrieren.regasm /codebase Aloaha_ZUGFeRD.dll - COM-Selbsttest: Das Paket
zugferdbinaries.zipenthält das Skriptzugferd_com_test.vbs. Es prüft Registrierung und Bitbreite und legt das Objekt testweise an; für den 32-Bit-Test auf 64-Bit-Windows mitC:\Windows\SysWOW64\cscript.exestarten. - Lizenzschlüssel: Eine kostenlose Testlizenz mit vollem Funktionsumfang erhalten Sie per Mail an info@aloaha.com.
Schritt für Schritt
- SDK installieren (oder die DLL registrieren, siehe oben).
- Objekt anlegen, Lizenzschlüssel und Profil setzen.
- Rechnungskopf, Verkäufer, Käufer und Zahlungsangaben setzen.
- Positionen in einer Schleife hinzufügen (
AddProduct_Comfort). - Umsatzsteuer-Aufschlüsselung je Steuersatz (
AddTradeTax) und Summen (WriteTotals) setzen. - XML speichern (
SaveXML) und in die vorhandene PDF-Rechnung einbetten (MergeXMLIntoPDF). - Die erste Rechnung mit einem Validator prüfen – siehe Wie prüfe ich meine XRechnung vor dem Versand?
Beträge immer mit Dezimalpunkt
Das SDK erwartet Beträge als Text mit Punkt als Dezimaltrennzeichen (59.50). Bei deutscher Windows-Einstellung würde Delphi ein Komma schreiben. Diese Hilfsfunktion nutzen beide Beispiele:
// Delphi 5 bis 2010
function Betrag(Wert: Double): string;
begin
Result := StringReplace(FormatFloat('0.00', Wert), DecimalSeparator, '.', []);
end;
Variante 1: Late Binding mit CreateOleObject
uses ComObj;
procedure ErzeugeERechnung_LateBinding;
var
alo: OleVariant;
begin
alo := CreateOleObject('Aloaha_ZUGFeRD.XML');
alo.Licensekey := 'IHR-LIZENZSCHLUESSEL';
alo.ZUGFeRD_Profile := 1; // 0 = BASIC, 1 = EN 16931 (COMFORT), 2 = EXTENDED
// Rechnungskopf: Nummer (BT-1), Text, Datum (BT-2), Datumsformat, Name, Sprache, Währung (BT-5)
alo.CreateInvoiceObject('RE-2027-0001', 'Rechnung gemäß Bestellung',
'20270104', '102', '', 'DE', 'EUR');
alo.Document_TypeINT := 380; // BT-3: 380 = Rechnung, 381 = Gutschrift
alo.ActualDeliveryDate_102 := '20270104'; // BT-72: Leistungsdatum
// Verkäufer mit USt-ID (BT-31)
alo.WriteSeller('Muster GmbH', '20095', 'Hamburg', 'Hauptstr. 1', '', 'DE', 'DE123456789');
// Käufer
alo.BuyerName := 'Kunde AG';
alo.BuyerAddressLine1 := 'Marktplatz 5';
alo.BuyerPostCode := '80331';
alo.BuyerCity := 'München';
alo.BuyerCountry := 'DE';
// Zahlung: 58 = SEPA-Überweisung (BT-81)
alo.AddPaymentMeans(58, 'SEPA-Überweisung', 'DE02120300000000202051',
'Muster GmbH', '', 'BYLADEM1001');
alo.AddTradePaymentTerms('Zahlbar innerhalb 30 Tagen netto');
// Position (BG-25): 10 Stück à 5,00 EUR, 19 %
alo.AddProduct_Comfort(1, '', 'ART-100', '10.00', 'C62', 'Papier A4', '500 Blatt',
'', 'EUR', '', 'C62', False, '', '', '', Betrag(5.00), 'EUR', '1.00',
'C62', 'VAT', 'S', '19.00', '', Betrag(50.00), 'EUR', '', '');
// Umsatzsteuer-Aufschlüsselung (BG-23): Steuer, Währung, Basis, Währung, Art, Kategorie, Satz
alo.AddTradeTax(Betrag(9.50), 'EUR', Betrag(50.00), 'EUR', 'VAT', 'S', '19.00');
// Summen (BG-22): Positionen, Brutto, Zahlbetrag, Netto, Steuer
alo.WriteTotals(Betrag(50.00), Betrag(59.50), Betrag(59.50), Betrag(50.00), Betrag(9.50));
// XML speichern und in die vorhandene PDF-Rechnung einbetten
if alo.SaveXML('C:\Rechnungen\RE-2027-0001.xml') then
alo.MergeXMLIntoPDF('C:\Rechnungen\RE-2027-0001.xml',
'C:\Rechnungen\RE-2027-0001.pdf',
'C:\Rechnungen\RE-2027-0001_zugferd.pdf',
True, '', 'IHR-LIZENZSCHLUESSEL')
else
ShowMessage(alo.Last_Error);
end;
In der Praxis ersetzen Sie die festen Werte durch die Felder Ihrer Rechnungstabelle und rufen AddProduct_Comfort in einer Schleife über die Positionen auf. Für eine XRechnung an Behörden setzen Sie zusätzlich alo.isKOSIT := True und alo.LeitwegID.
Variante 2: Early Binding über die Typbibliothek
Die Typbibliothek Aloaha_ZUGFeRD.tlb liegt dem SDK bei. Sie müssen sie nicht selbst erzeugen; bei Bedarf geht das mit regasm /codebase Aloaha_ZUGFeRD.dll /tlb:Aloaha_ZUGFeRD.tlb.
- In Delphi 5: Projekt > Typbibliothek importieren > „Aloaha ZUGFeRD Toolkit“ wählen > Unit anlegen. Delphi erzeugt
Aloaha_ZUGFeRD_TLB.pasund zusätzlichmscorlib_TLB.pas. - Meldet der Compiler in der erzeugten Unit Fehler zu
_SetIUnknownProp, löschen Sie diese Zeilen. - Die Unit in die
uses-Klausel aufnehmen. Die Rechnungsklasse heißtXML, ihre Schnittstelle_XML; angelegt wird sie mitCoXML.Create. Prüfen Sie die Namen bitte in der erzeugten Unit.
Delphi 5 übernimmt die Standardwerte optionaler Parameter aus der Typbibliothek nicht zuverlässig. Geben Sie deshalb alle Parameter an:
uses ComObj, Aloaha_ZUGFeRD_TLB;
procedure ErzeugeERechnung_EarlyBinding;
var
alo: _XML;
Standard: TOleEnum;
begin
alo := CoXML.Create;
alo.Licensekey := 'IHR-LIZENZSCHLUESSEL';
alo.ZUGFeRD_Profile := 1; // 1 = EN 16931 (COMFORT)
alo.CreateInvoiceObject('RE-2027-0001', 'Rechnung gemäß Bestellung',
'20270104', '102', '', 'DE', 'EUR');
alo.Document_TypeINT := 380;
alo.ActualDeliveryDate_102 := '20270104';
// Verkäufer: Name, PLZ, Ort, Straße, Straße 2, Land, USt-ID, Straße 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';
// Zahlung: Art, Text, IBAN, Kontoinhaber, Konto-ID, BIC, BLZ, Bank,
// Lastschrift, Mandat, Gläubiger-ID
alo.AddPaymentMeans(58, 'SEPA-Überweisung', 'DE02120300000000202051',
'Muster GmbH', '', 'BYLADEM1001', '', '', False, '', '');
alo.AddTradePaymentTerms('Zahlbar innerhalb 30 Tagen netto', '', '', '', '', '', '', '', '');
alo.AddProduct_Comfort(1, '', 'ART-100', '10.00', 'C62', 'Papier A4', '500 Blatt',
'', 'EUR', '', 'C62', False, '', '', '', Betrag(5.00), 'EUR', '1.00',
'C62', 'VAT', 'S', '19.00', '', Betrag(50.00), 'EUR', '', '');
// 7 Pflicht- und 5 optionale Parameter
alo.AddTradeTax(Betrag(9.50), 'EUR', Betrag(50.00), 'EUR', 'VAT', 'S', '19.00',
'', '', '', '', '');
// Positionen, Brutto, Zahlbetrag, Netto, Steuer, Rabatte, gezahlt, Rundung, Zuschläge
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:\Rechnungen\RE-2027-0001.xml', 'IHR-LIZENZSCHLUESSEL', Standard) then
alo.MergeXMLIntoPDF('C:\Rechnungen\RE-2027-0001.xml',
'C:\Rechnungen\RE-2027-0001.pdf',
'C:\Rechnungen\RE-2027-0001_zugferd.pdf',
True, '', 'IHR-LIZENZSCHLUESSEL', '', '', '', '')
else
ShowMessage(alo.Last_Error);
end;
Die Reihenfolge der Methoden in der COM-Schnittstelle bleibt seit Version 10 unverändert; neue Funktionen kommen nur am Ende hinzu. Eine einmal importierte Unit funktioniert daher auch mit neueren SDK-Versionen weiter.
Überladene Methoden heißen in COM anders
COM kennt keine Überladungen. Gibt es eine Methode in .NET mehrfach, erhält die zweite Variante in Delphi das Suffix _2. Für Delphi wichtig:
| Name in Delphi | Parameter |
|---|---|
WriteTotals | Beträge als Text ('59.50') |
WriteTotals_2 | Beträge als Double |
AddProduct_Comfort | Positionsnummer als Zahl |
AddProduct_Comfort_2 | Positionsnummer als Text (z. B. '1.1') |
AddPaymentMeans | Zahlungsart als Zahl (UNTDID 4461, z. B. 58) |
AddPaymentMeans_2 | Zahlungsart als Text ('58') |
Aufzählungen wie das Profil oder die Zahlungsart übergeben Sie in Delphi als Zahl. Für die Rechnungsart (BT-3) gibt es dafür eigens Document_TypeINT, siehe Rechnung anlegen und Rechnungstyp (BT-3).
Neuere Delphi-Versionen
- Delphi 2009 und neuer:
stringist Unicode; Umlaute gehen ohne Umweg an das SDK. Der Code bleibt gleich. - Ab Delphi XE: Die globale Variable
DecimalSeparatorist veraltet. Nutzen SieTFormatSettings:function Betrag(Wert: Double): string; var FS: TFormatSettings; begin FS := TFormatSettings.Create; FS.DecimalSeparator := '.'; Result := FormatFloat('0.00', Wert, FS); end; - 64-Bit-Programme (ab Delphi XE2): Die DLL muss auch für 64 Bit registriert sein. Das SDK-Setup erledigt beides; bei manueller Registrierung den Regasm aus
Framework64verwenden.
Typische Fehler
| Meldung | Ursache | Lösung |
|---|---|---|
| „Ungültige Klassenzeichenfolge“ | Die COM-Klasse ist nicht registriert. | SDK-Setup ausführen oder regasm /codebase als Administrator. |
| „Klasse nicht registriert“ | Registriert nur für die andere Bitbreite, z. B. 64 Bit für ein 32-Bit-Programm. | Mit dem passenden Regasm registrieren (Framework für 32 Bit). |
| „Unbekannter Name“ | Tippfehler oder die überladene Variante heißt anders (_2). | Namen prüfen; Early Binding zeigt solche Fehler schon beim Kompilieren. |
| „Typenkonflikt“ | Text, wo das SDK eine Zahl erwartet (oder umgekehrt). | Parametertyp der Variante prüfen, siehe Tabelle oben. |
| Validator: BR-CO-10, BR-S-08, BR-CO-17 | Summen passen nicht zu den Positionen oder zur Steuerbasis. | Steuerbasis = Netto nach Rabatt, siehe BR-S-08, BR-S-09 und BR-CO-17. |
Liefert SaveXML False, steht der Grund in Last_Error.
Alternative ohne COM: zugcmd
Soll der Delphi-Code möglichst unverändert bleiben, schreibt Ihr Programm die Rechnungsdaten als CSV-Datei und ruft das Kommandozeilenwerkzeug zugcmd auf, zum Beispiel per ShellExecute. zugcmd erzeugt daraus ZUGFeRD, Factur-X oder XRechnung und bettet das XML in Ihr PDF ein.
Schritt für Schritt mit getesteten Beispieldateien, Aufruf aus der eigenen Anwendung und Dateinamen: E-Rechnungen per CSV und zugcmd aus der eigenen Anwendung erstellen.
Alle Aufrufe im Detail mit Rabatten und mehreren Steuersätzen: Schnellstart mit VB.NET – die Methoden und Parameter sind in Delphi dieselben. Dieselbe Anleitung für Visual Basic: ZUGFeRD und XRechnung mit VB6, VB5 und VBA erstellen.
Häufige Fragen
Kann ich ZUGFeRD-Rechnungen mit Delphi 5 erstellen?
Ja. Das Aloaha ZUGFeRD SDK hat eine COM-Schnittstelle, die Delphi 5 per CreateOleObject('Aloaha_ZUGFeRD.XML') oder über die mitgelieferte Typbibliothek nutzt. Eine neuere Delphi-Version ist nicht nötig.
Brauche ich einen Import der Typbibliothek?
Nein, nicht für Late Binding. Der Import (Early Binding) bringt Codevervollständigung und Prüfung beim Kompilieren. Registriert werden muss die DLL in beiden Fällen; das übernimmt das SDK-Setup.
Funktioniert das auch mit Delphi 7, XE oder Delphi 12?
Ja, der Weg über COM ist derselbe. Ab Delphi XE nutzen Sie für den Dezimalpunkt TFormatSettings, und 64-Bit-Programme brauchen die 64-Bit-Registrierung.
Kann ich meine bestehende PDF-Rechnung aus Delphi weiter verwenden?
Ja. MergeXMLIntoPDF bettet das XML in Ihre vorhandene PDF-Rechnung ein und erzeugt daraus eine hybride ZUGFeRD-Rechnung (PDF/A-3).
Kann ich mit Delphi auch eine reine XRechnung erzeugen?
Ja. Setzen Sie isKOSIT := True und die Leitweg-ID und speichern Sie nur das XML mit SaveXML.
Warum heißt eine Methode in Delphi plötzlich WriteTotals_2?
COM kennt keine Überladungen. Die zweite .NET-Variante einer Methode erhält das Suffix _2. WriteTotals erwartet Beträge als Text, WriteTotals_2 als Double.
Business Terms in diesem Artikel: 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