- SDK members
- ActualDeliveryDate_102 AddPaymentMeans() AddProduct_Comfort() AddTradePaymentTerms() AddTradeTax() BuyerAddressLine1 BuyerCity BuyerCountry BuyerName BuyerPostCode
- Business terms
- 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
- Code samples
- Command line, VB6 / VBScript (COM)
- Published
In short: Applications in Visual Basic 6, Visual Basic 5 and VBA (Access, Excel, Word) create e-invoices according to EN 16931 (ZUGFeRD 2.x, Factur-X, XRechnung) through the COM interface of the Aloaha ZUGFeRD SDK. A migration to .NET is not needed. There are two ways: late binding with CreateObject("Aloaha_ZUGFeRD.XML") without a reference, or early binding with a reference to the type library "Aloaha ZUGFeRD Toolkit". Your program creates the PDF invoice as before; the SDK writes the XML and embeds it in the PDF (hybrid ZUGFeRD invoice, PDF/A-3).
Late or early binding?
| Late binding | Early binding | |
|---|---|---|
| Create the object | Set alo = CreateObject("Aloaha_ZUGFeRD.XML") | Set alo = New Aloaha_ZUGFeRD.XML |
| Reference in the project | no | yes, "Aloaha ZUGFeRD Toolkit" |
| IntelliSense in the IDE | no | yes |
| Checking of names and parameters | at run time | at compile time |
| Optional parameters | omit them at the end | |
| Registration of the DLL | required in both cases – done by the SDK setup | |
Late binding is robust when you distribute to many computers and works the same way in VBScript. Early binding is more convenient while programming. Both use the same methods.
Requirements
- Windows with .NET Framework 4.7.2 or later.
- Aloaha ZUGFeRD SDK from the download page. The SDK setup (MSI) registers the COM interface for 32 and 64 bit.
- Mind the bitness: VB5 and VB6 programs are always 32 bit. VBA runs with the bitness of Office – a 64-bit Office needs the 64-bit registration.
- Manual distribution without the setup: register the DLL as administrator with the Regasm of the matching bitness – for 32 bit from
C:\Windows\Microsoft.NET\Framework\v4.0.30319\, for 64 bit fromFramework64:
Which files belong to it is described in Register libraries.regasm /codebase Aloaha_ZUGFeRD.dll - COM self-test: the package
zugferdbinaries.zipcontains the scriptzugferd_com_test.vbs. It checks the registration and bitness and creates the object as a test. For the 32-bit test on 64-bit Windows:C:\Windows\SysWOW64\cscript.exe //nologo zugferd_com_test.vbs - Licence key: you get a free, fully functional trial licence by e-mail to info@aloaha.com.
Step by step
- Install the SDK (or register the DLL, see above).
- Create the object, set the licence key and the profile.
- Set the invoice header, seller, buyer and payment details.
- Add the lines in a loop (
AddProduct_Comfort). - Set the VAT breakdown per rate (
AddTradeTax) and the totals (WriteTotals). - Save the XML (
SaveXML) and embed it into the existing PDF invoice (MergeXMLIntoPDF). - Check the first invoice with a validator – see How do I check my XRechnung before sending it?
Always pass amounts with a decimal point
The SDK expects amounts as text with a dot as the decimal separator ("59.50"). With German Windows settings, Format$ writes a comma. This helper function (Betrag = amount) works in VB5, VB6 and VBA (VB5 does not have Replace yet):
Public Function Betrag(ByVal Wert As Double) As String
Dim s As String, p As Integer
s = Format$(Wert, "0.00")
p = InStr(s, ",")
If p > 0 Then Mid$(s, p, 1) = "."
Betrag = s
End Function
Option 1: late binding with CreateObject
Public Sub ErzeugeERechnung_LateBinding()
Dim alo As Object
Set alo = CreateObject("Aloaha_ZUGFeRD.XML")
alo.Licensekey = "YOUR-LICENCE-KEY"
alo.ZUGFeRD_Profile = 1 ' 0 = BASIC, 1 = EN 16931 (COMFORT), 2 = EXTENDED
' invoice header: number (BT-1), text, date (BT-2), date format, name, language, currency (BT-5)
Call alo.CreateInvoiceObject("RE-2027-0001", "Invoice as per order", _
"20270104", "102", "", "DE", "EUR")
alo.Document_TypeINT = 380 ' BT-3: 380 = invoice, 381 = credit note
alo.ActualDeliveryDate_102 = "20270104" ' BT-72: delivery date
' seller with VAT ID (BT-31)
alo.WriteSeller "Muster GmbH", "20095", "Hamburg", "Hauptstr. 1", "", "DE", "DE123456789"
' buyer
alo.BuyerName = "Kunde AG"
alo.BuyerAddressLine1 = "Marktplatz 5"
alo.BuyerPostCode = "80331"
alo.BuyerCity = "München"
alo.BuyerCountry = "DE"
' payment: 58 = SEPA credit transfer (BT-81)
alo.AddPaymentMeans 58, "SEPA credit transfer", "DE02120300000000202051", _
"Muster GmbH", "", "BYLADEM1001"
alo.AddTradePaymentTerms "Payable within 30 days net"
' line (BG-25): 10 pieces at EUR 5.00, 19 %
Call alo.AddProduct_Comfort(1, "", "ART-100", "10.00", "C62", "Paper A4", "500 sheets", _
"", "EUR", "", "C62", False, "", "", "", Betrag(5), "EUR", "1.00", _
"C62", "VAT", "S", "19.00", "", Betrag(50), "EUR", "", "")
' VAT breakdown (BG-23): tax, currency, basis, currency, type, category, rate
alo.AddTradeTax Betrag(9.5), "EUR", Betrag(50), "EUR", "VAT", "S", "19.00"
' totals (BG-22): lines, grand total, amount due, net, tax
alo.WriteTotals Betrag(50), Betrag(59.5), Betrag(59.5), Betrag(50), Betrag(9.5)
' save the XML and embed it into the existing PDF invoice
If alo.SaveXML("C:\Invoices\RE-2027-0001.xml") Then
Call alo.MergeXMLIntoPDF("C:\Invoices\RE-2027-0001.xml", _
"C:\Invoices\RE-2027-0001.pdf", _
"C:\Invoices\RE-2027-0001_zugferd.pdf", _
True, "", "YOUR-LICENCE-KEY")
Else
MsgBox alo.Last_Error
End If
Set alo = Nothing
End Sub
In practice, replace the fixed values with the fields of your recordset and call AddProduct_Comfort in a loop over the lines. For an XRechnung to German public authorities, also set alo.isKOSIT = True and alo.LeitwegID.
Option 2: early binding with a reference
- In VB6: Project > References; in VBA: Tools > References.
- Tick "Aloaha ZUGFeRD Toolkit". If the entry is not in the list, choose the file
Aloaha_ZUGFeRD.tlbvia Browse; it ships with the SDK. - Declare the variable with the class type. The calls stay the same as with late binding:
Dim alo As Aloaha_ZUGFeRD.XML
Set alo = New Aloaha_ZUGFeRD.XML
alo.Licensekey = "YOUR-LICENCE-KEY"
alo.ZUGFeRD_Profile = 1
' ... continue as in option 1
With the reference, the IDE shows all methods and parameters (IntelliSense), and the Object Browser (F2) lists the complete interface. The order of the methods in the COM interface has not changed since version 10; new functions are only added at the end. Compiled programs with a reference therefore keep working with newer SDK versions.
Overloaded methods have different names in COM
COM has no overloads. If a method exists more than once in .NET, the second variant gets the suffix _2 in VB6 and VBA:
| Name in VB6/VBA | Parameters |
|---|---|
WriteTotals | amounts as text ("59.50") |
WriteTotals_2 | amounts as Double |
AddProduct_Comfort | line number as a number |
AddProduct_Comfort_2 | line number as text (e.g. "1.1") |
AddPaymentMeans | payment means as a number (UNTDID 4461, e.g. 58) |
AddPaymentMeans_2 | payment means as text ("58") |
Pass enumerations such as the profile or the payment means as numbers. For the invoice type (BT-3) there is a dedicated Document_TypeINT, see Creating an invoice and the invoice type (BT-3) (German).
VB5, VBA and VBScript
- Visual Basic 5: the code above runs unchanged. The helper function
Betragdeliberately uses only functions that already exist in VB5. - VBA in Access, Excel and Word: the same code in a standard module. With 64-bit Office, the 64-bit registration must be present (the SDK setup does both). Reading invoices and evaluating line values is shown in Reading line values in VBA and Access (German).
- VBScript: declare variables without a type (
Dim alo) and use late binding only; otherwise the same.
Typical errors
| Message | Cause | Solution |
|---|---|---|
| Run-time error 429: "ActiveX component can't create object" | The COM class is not registered, is registered only for the other bitness (e.g. 32 bit with 64-bit Office), or the .NET Framework is missing. | Run the SDK setup or register with the matching Regasm; zugferd_com_test.vbs shows the cause. |
| Run-time error 438: "Object doesn't support this property or method" | Typo, or the overloaded variant has a different name (_2). | Check the name; with a reference, the Object Browser (F2) shows all names. |
| Run-time error 13: "Type mismatch" | Text where the SDK expects a number (or vice versa). | Check the parameter type of the variant, see the table above. |
| Run-time error 450: "Wrong number of arguments" | Too many parameters, or a mandatory parameter is missing. | Compare the parameter list with the API reference. |
| Automation error "File not found" | Registered without /codebase, and the DLL is not in the GAC. | Register again with regasm /codebase. |
| Validator: BR-CO-10, BR-S-08, BR-CO-17 | Totals do not match the lines or the tax basis. | Tax basis = net after allowances, see BR-S-08, BR-S-09 and BR-CO-17. |
If SaveXML returns False, the reason is in Last_Error.
Alternative without COM: zugcmd
If the VB code should stay as unchanged as possible, your program writes the invoice data to CSV files and calls the command-line tool zugcmd, for example via Shell. zugcmd creates ZUGFeRD, Factur-X or XRechnung from them and embeds the XML in your PDF.
Step by step with tested sample files, the call from your own application and file names: Creating e-invoices via CSV and zugcmd from your own application.
All calls in detail: Quick start with VB.NET – the methods and parameters are the same in VB6. There is a separate guide for Delphi: Create ZUGFeRD and XRechnung with Delphi.
Frequently asked questions
Can I create ZUGFeRD invoices and XRechnung with Visual Basic 6?
Yes. The Aloaha ZUGFeRD SDK has a COM interface that VB6 uses via CreateObject("Aloaha_ZUGFeRD.XML") or via a reference to "Aloaha ZUGFeRD Toolkit". A migration to .NET is not needed.
Does this also work with Visual Basic 5?
Yes. VB5 uses the same COM interface. Only functions such as Replace do not exist there yet; the decimal-point helper function in this article does without them.
Does it also work in Access or Excel with VBA?
Yes, with the same code in a standard module. With 64-bit Office, the DLL must also be registered for 64 bit; the SDK setup does that.
Do I need a reference to the type library?
No, not for late binding with CreateObject. The reference (early binding) gives you IntelliSense and checks at compile time. The DLL has to be registered in both cases.
What does run-time error 429 on CreateObject mean?
The COM class is not registered on this computer, or only for the other bitness. Run the SDK setup or register the DLL with the matching Regasm; the script zugferd_com_test.vbs shows the cause.
Why is a method called WriteTotals_2 in VB6?
COM has no overloads. The second .NET variant of a method gets the suffix _2. WriteTotals expects amounts as text, WriteTotals_2 as Double.
Business terms in this 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