E-Rechnung aus einer alten VB6-Anwendung: COM oder CSV und zugcmd?

Thema
VB6
SDK-Mitglieder
BuyerName CreateInvoiceObject() Licensekey SaveXML() WriteSeller() ZUGFeRD_Profile
Business Terms
BT-1 Rechnungsnummer BT-2 Rechnungsdatum BT-3 Code für den Rechnungstyp BT-5 Code für die Rechnungswährung BT-10 Referenz des Käufers BT-106 Summe der Nettobeträge aller Rechnungspositionen BT-109 Rechnungsgesamtbetrag ohne Umsatzsteuer BT-112 Rechnungsgesamtbetrag einschließlich Umsatzsteuer
Codebeispiele
VB6 / VBScript (COM), VB.NET
Veröffentlicht

Kurz: Eine ältere Anwendung in Visual Basic 6 muss für die E-Rechnungspflicht nicht neu geschrieben oder nach .NET migriert werden. Mit dem Aloaha ZUGFeRD SDK gibt es zwei Wege zu ZUGFeRD und XRechnung (EN 16931): Weg 1 ruft das SDK direkt über die COM-Schnittstelle auf. Weg 2 schreibt die Rechnungsdaten in CSV-Dateien und startet das Kommandozeilen-Tool zugcmd. Weg 2 braucht in VB6 nur Dateiausgabe und einen Programmaufruf und ist deshalb ideal, wenn Sie lange nicht mehr in VB6 programmiert haben. In beiden Fällen erzeugt Ihr Programm die PDF-Rechnung wie bisher; heraus kommt eine hybride ZUGFeRD-Rechnung (PDF/A-3 mit eingebettetem XML).

Ihre Anwendung ist in Visual FoxPro geschrieben? Dafür gibt es eine eigene Anleitung: ZUGFeRD und XRechnung mit Visual FoxPro 9 erstellen.

Welcher Weg passt zu Ihnen?

Weg 1: COM-SchnittstelleWeg 2: CSV-Dateien + zugcmd
Was Ihre VB6-Anwendung tutlegt ein SDK-Objekt an und setzt Kopf, Parteien, Positionen, Steuer und Summen über Methodenschreibt vier Textdateien und startet zugcmd
Benötigte VB6-KenntnisseObjekte, Methodenaufrufe, FehlerbehandlungOpen … For Output, Print # und ein Programmaufruf
Verweis im VB6-Projektnicht nötig (Late Binding mit CreateObject), optional für IntelliSensenicht nötig
Fehler erkennenRückgabewerte der Methoden, z. B. SaveXMLRückgabewert von zugcmd (0 = Erfolg)
Testen ohne VB6neinja – zugcmd lässt sich mit den CSV-Dateien von Hand aufrufen
Funktionsumfangalle Felder des SDKalle gängigen Felder (Positionen, Rabatte, mehrere Steuersätze, Lieferanschrift, Leitweg-ID …)
Ausführliche AnleitungZUGFeRD und XRechnung mit VB6, VB5 und VBA erstellenE-Rechnungen per CSV und zugcmd erstellen

Unsere Empfehlung: Wer lange nicht mehr in VB6 programmiert hat, beginnt mit Weg 2. Die Daten liegen dann als lesbare Textdateien vor, Fehler lassen sich ohne Debugger finden, und ein späterer Wechsel zu Weg 1 ist jederzeit möglich – das XML ist in beiden Fällen dasselbe.

Voraussetzungen

  • Windows mit .NET Framework 4.7.2 oder neuer (in Windows 10 ab Version 1803 und in Windows 11 bereits enthalten). Ihre VB6-Anwendung selbst bleibt unverändert eine VB6-Anwendung.
  • Für Weg 1 das SDK-Setup von der Download-Seite; es registriert die COM-Schnittstelle. VB6-Programme sind immer 32 Bit – die 32-Bit-Registrierung ist im Setup enthalten.
  • Für Weg 2 das Paket zugcmd.zip von der Download-Seite, mit Beispiel-CSV-Dateien und readme.txt.
  • Ein Lizenzschlüssel. Eine kostenlose Testlizenz mit vollem Funktionsumfang erhalten Sie per E-Mail an info@aloaha.com.

Für beide Wege: Beträge mit Dezimalpunkt

Das SDK und zugcmd erwarten Beträge mit Punkt als Dezimaltrennzeichen (59.50). Format$ schreibt bei deutscher Windows-Einstellung ein Komma. Diese Hilfsfunktion löst das in VB6 (und VB5):

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

Weg 1: das SDK direkt über COM aufrufen

Nach der Installation legt Ihre Anwendung das Objekt mit CreateObject an – ohne Verweis im Projekt. Das Gerüst einer Rechnung:

Dim alo As Object
Set alo = CreateObject("Aloaha_ZUGFeRD.XML")
alo.Licensekey = "IHR-LIZENZSCHLUESSEL"
alo.ZUGFeRD_Profile = 1                       ' 1 = EN 16931 (COMFORT)

' Rechnungskopf: Nummer (BT-1), Hinweis, Datum (BT-2), Datumsformat, Name, Sprache, Währung (BT-5)
Call alo.CreateInvoiceObject("RE-2027-0001", "", "20270104", "102", "", "DE", "EUR")
alo.WriteSeller "Muster GmbH", "20095", "Hamburg", "Hauptstr. 1", "", "DE", "DE123456789"
alo.BuyerName = "Kunde AG"
' ... Käufer, Zahlungsangaben (AddPaymentMeans), je Position AddProduct_Comfort,
'     Steuer (AddTradeTax) und Summen (WriteTotals)

If alo.SaveXML("C:\Rechnungen\RE-2027-0001.xml") Then
    ' XML in die vorhandene PDF-Rechnung einbetten (MergeXMLIntoPDF)
End If

Das vollständige, getestete Beispiel mit allen Parametern, Early Binding und den typischen Fehlern steht in ZUGFeRD und XRechnung mit VB6, VB5 und VBA erstellen. Wichtig: Die Rechnungsart (BT-3, z. B. 875 für eine Abschlagsrechnung Bau) setzen Sie nach dem Anlegen der Rechnung, bei Late Binding mit alo.Document_TypeINT = 875 – nicht im Hinweis-Parameter.

Weg 2: CSV-Dateien schreiben und zugcmd starten

Ihre Anwendung schreibt pro Rechnung drei kleine Dateien (buyer.csv, items.csv, totals.csv); die Verkäuferdaten (seller.csv) legen Sie einmal als Stammdatei ab. Die erste Zeile enthält die Spaltennamen, darunter folgen die Daten – in items.csv eine Zeile je Position. Die Spalten werden über ihren Namen zugeordnet; die Reihenfolge spielt keine Rolle.

Schritt 1: Hilfsroutinen

' Wert in Anführungszeichen setzen, wenn er das Trennzeichen (Komma) enthält
Public Function Feld(ByVal Wert As String) As String
    If InStr(Wert, ",") > 0 Then Feld = """" & Wert & """" Else Feld = Wert
End Function

' Kopfzeile und Datenzeile(n) in eine Datei schreiben (VB6 schreibt Windows-ANSI)
Public Sub SchreibeCSV(ByVal Datei As String, ByVal Kopf As String, ByVal Daten As String)
    Dim f As Integer
    f = FreeFile
    Open Datei For Output As #f
    Print #f, Kopf
    Print #f, Daten
    Close #f
End Sub

' zugcmd ohne Fenster starten, warten und den Rückgabewert liefern (0 = Erfolg)
Public Function StarteZugcmd(ByVal Parameter As String) As Long
    Dim sh As Object
    Set sh = CreateObject("WScript.Shell")
    StarteZugcmd = sh.Run("""C:\zugcmd\zugcmd_wnd.exe"" " & Parameter, 0, True)
End Function

Der VB6-Befehl Shell wartet nicht und liefert den Rückgabewert von zugcmd nicht. WScript.Shell.Run mit dem dritten Parameter True wartet, bis zugcmd fertig ist, und gibt dessen Rückgabewert zurück – ohne API-Deklarationen.

Schritt 2: Rechnung schreiben und umwandeln

Das Beispiel erzeugt genau die Dateien des getesteten Minimalbeispiels (10 × 5,00 € netto zu 19 %, vom KoSIT-Validator ohne Fehler und Warnungen angenommen). In Ihrer Anwendung kommen die Werte aus der Datenbank; mehrere Positionen verbinden Sie mit vbCrLf.

Public Function ERechnungPerCSV() As Boolean
    Dim d As String, nr As String, pos As String, rc As Long
    nr = "RE-2027-0001"
    d = "C:\ERechnung\" & nr & "\"            ' eigener Ordner je Rechnung, PDF liegt bereits dort

    SchreibeCSV d & "buyer.csv", "id,Name,Street1,city,email,country,postcode", _
        "K-1001," & Feld("Kunde AG") & ",Marktplatz 5,München,einkauf@kunde.example,DE,80331"

    pos = "ART-100,Papier A4,500 Blatt,10,C62," & Betrag(5) & ",1,C62,19,VAT,S," & Betrag(50)
    ' weitere Position: pos = pos & vbCrLf & "ART-200,..."
    SchreibeCSV d & "items.csv", "AssignedID,productname,description,quantity,unit,netprice," & _
        "netbasisquantity,netbasisunit,taxpercent,taxtypecode,taxcategorycode,totalamount", pos

    SchreibeCSV d & "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," & nr & ",20270104,20270104,K-1001," & Betrag(50) & ",0.00,0.00," & Betrag(50) & "," & _
        Betrag(9.5) & "," & Betrag(59.5) & ",0.00," & Betrag(59.5) & ",Zahlbar innerhalb 30 Tagen netto,20270203," & _
        Betrag(9.5) & ",VAT," & Betrag(50) & ",S,19"

    rc = StarteZugcmd("-s ""C:\ERechnung\stamm\seller.csv""" & _
        " -b """ & d & "buyer.csv"" -p """ & d & "items.csv"" -t """ & d & "totals.csv""" & _
        " -i """ & d & nr & ".pdf"" -x """ & d & nr & ".xml"" -o """ & d & nr & "_zugferd.pdf""" & _
        " -y "","" -c ansi -l IHR-LIZENZSCHLUESSEL")

    If rc <> 0 Then MsgBox "zugcmd meldet Fehler " & rc, vbExclamation
    ERechnungPerCSV = (rc = 0)
End Function

Die Stammdatei C:\ERechnung\stamm\seller.csv mit Name, Anschrift, Kontakt, USt-ID und Bankverbindung des Verkäufers legen Sie einmal an – Vorlage und Spalten stehen im CSV-Artikel und in zugcmd.zip.

Worauf es ankommt

  • -c ansi: VB6 schreibt mit Print # im Windows-ANSI-Zeichensatz. Ohne diesen Parameter erwartet zugcmd UTF-8, und Umlaute wie in „München“ kommen falsch an.
  • Vollständige Pfade mit Laufwerk und Ordner angeben (oder mit -d ein Basisverzeichnis setzen).
  • Summen berechnet Ihre Anwendung; zugcmd übernimmt sie so, wie sie in totals.csv stehen. Die Spalten und ihre Business Terms (BT-106 Positionssumme, BT-109 Netto, BT-110 Steuer, BT-112 Brutto, BT-115 Zahlbetrag) beschreibt der CSV-Artikel.
  • Für eine XRechnung an öffentliche Auftraggeber gehört die Leitweg-ID in die Spalte leitwegid (BT-10).
  • Rückgabewerte: 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.

Testen ohne VB6

Den Aufruf aus Schritt 2 können Sie zuerst in einer Eingabeaufforderung mit zugcmd.exe und den Beispieldateien aus zugcmd.zip ausprobieren – Fehlermeldungen erscheinen dann direkt auf der Konsole. Umgekehrt zerlegt zugcmd -r rechnung.xml eine vorhandene E-Rechnung in genau diese CSV-Dateien; so sehen Sie an einem echten Beispiel, welches Feld in welche Spalte gehört. Die erste erzeugte Rechnung prüfen Sie mit einem Validator – siehe Wie prüfe ich meine XRechnung vor dem Versand?

Häufige Fragen

Muss ich meine VB6-Anwendung für die E-Rechnung nach .NET migrieren?

Nein. Das Aloaha ZUGFeRD SDK ist über COM aus VB6 aufrufbar, und das Kommandozeilen-Tool zugcmd lässt sich aus jeder Anwendung starten. Die VB6-Anwendung bleibt, wie sie ist; auf dem Rechner wird nur das .NET Framework 4.7.2 benötigt.

Welcher Weg ist einfacher, wenn ich lange nicht mehr in VB6 programmiert habe?

Der Weg über CSV-Dateien und zugcmd. In VB6 brauchen Sie dafür nur Dateiausgabe mit Open und Print sowie einen Programmaufruf. Die Dateien sind lesbar und lassen sich ohne VB6 testen.

Wie erhalte ich in VB6 den Rückgabewert von zugcmd?

Mit CreateObject("WScript.Shell").Run(Befehl, 0, True). Der dritte Parameter True wartet, bis zugcmd fertig ist, und liefert dessen Rückgabewert; 0 bedeutet Erfolg. Der VB6-Befehl Shell wartet nicht und liefert den Rückgabewert nicht.

Warum stehen Umlaute falsch in der E-Rechnung?

VB6 schreibt Textdateien im Windows-ANSI-Zeichensatz, zugcmd erwartet ohne Angabe UTF-8. Rufen Sie zugcmd mit -c ansi auf.

Funktioniert das auch mit VB5, Access oder Excel (VBA)?

Ja. Beide Wege funktionieren mit VB5 und VBA genauso. Bei VBA ist für den COM-Weg die Bitbreite von Office entscheidend; ein 64-Bit-Office braucht die 64-Bit-Registrierung, die das SDK-Setup mitbringt.

Kann ich das SDK vor dem Kauf testen?

Ja. Eine kostenlose Testlizenz mit vollem Funktionsumfang erhalten Sie per E-Mail an info@aloaha.com. Preise und Lizenzen stehen auf der Seite Lizenzen und Preise.

Business Terms in diesem Artikel: BT-1 BT-2 BT-3 BT-5 BT-10 BT-106 BT-109 BT-112 BT-9 BT-20 BT-72 BT-110 BT-115 BT-131 BT-146