Creating ZUGFeRD descriptors with C# / .net

November 4, 2013, with 5 comments
by admin

I recently came across a nice initiative from German government and other (semi-)state organizations for developing a standard for electronic invoices. It uses PDF/A-3 as a basis. In the PDF file, an XML file is embedded which serves as a descriptor of the PDF file. It contains information about buyer, seller, invoice header information as well as line items.

The descriptor uses existing mechanisms from e.g. UN/CEFACT. It is still developing, e.g. there are plans to extend it to Europe.

You can find more information here:

The ZUGFeRD initiative delivers a set of sample files along with schema files and schema documentation. Unfortunately, there is no source code for creating ZUGFeRD compliant invoices.

So I decided to create such a library as a C# .net assembly:

This component is writting in C# but allows you to create ZUGFeRD compliant XML files using any .net language.

Update (2013-11-17):
ZUGFeRD library is now also available on nuget for plugging it in easily into your .net projects:

It is not yet complete as it does not support the following yet (in order of my personal priority):

  • some enums are still passed as strings
  • parse (load) existing ZUGFeRD file
  • support the three ZUGFeRD profiles
  • write line items

Please feel free to fork the code and issue pull requests.

The actual usage is not dead simple as a generic invoice structure itself is somewhat complicated. The library comes with a sample application which creates the same invoice file as shipping with the ZUGFeRD information package found on the initiative’s website:

InvoiceDescriptor desc = InvoiceDescriptor.CreateInvoice("471102", new DateTime(2013, 6, 5), CurrencyCodes.EUR, "GE2020211-471102");
desc.Profile = Profile.Comfort;
desc.ReferenceOrderNo = "AB-312";
desc.AddNote("Rechnung gemäß Bestellung Nr. 2013-471331 vom 01.03.2013.");
desc.AddNote("Es bestehen Rabatt- und Bonusvereinbarungen.", "AAK");
desc.SetBuyer("Kunden Mitte AG", "69876", "Frankfurt", "Kundenstraße", "15", "DE", "88", "4000001987658");
desc.AddBuyerTaxRegistration("DE234567890", "VA");
desc.SetBuyerContact("Hans Muster");
desc.SetSeller("Lieferant GmbH", "80333", "München", "Lieferantenstraße", "20", "DE", "88", "4000001123452");
desc.AddSellerTaxRegistration("201/113/40209", "FC");
desc.AddSellerTaxRegistration("DE123456789", "VA");
desc.SetBuyerOrderReferenceDocument("2013-471331", new DateTime(2013, 03, 01));
desc.SetDeliveryNoteReferenceDocument("2013-51111", new DateTime(2013, 6, 3));
desc.ActualDeliveryDate = new DateTime(2013, 6, 3);
desc.SetTotals(202.76m, 5.80m, 14.73m, 193.83m, 21.31m, 215.14m, 50.0m, 165.14m);
desc.AddApplicableTradeTax(9.06m, 129.37m, 7m, "VAT", "S");
desc.AddApplicableTradeTax(12.25m, 64.46m, 19m, "VAT", "S");
desc.SetLogisticsServiceCharge(5.80m, "Versandkosten", "VAT", "S", 7m);
desc.setTradePaymentTerms("Zahlbar innerhalb 30 Tagen netto bis 04.07.2013, 3% Skonto innerhalb 10 Tagen bis 15.06.2013", new DateTime(2013, 07, 04));


Please also see for an update of the library here.

Aktualisiert am December 15, 2013

Keine Kommentare

  1. Great work!

  2. Great work, but is this library still maintained?

  3. Hallo Stephan!
    Super Arbeit!
    Planen Sie irgendwann ZUGFERD-Dateien oder XML einzulesen (parsen)?

  4. Gute Lösung für V. 1.0 !
    Gibt es einen Zeitplan für Implementation von ZUGFeRD 2.0 mit Unterstützung für Profil EN16931 ?
    Für die Abwicklung öffentlicher Aufträge reicht ab November 2020 anscheinend ZUGFeRD 1.0 nicht mehr aus, sondern es wird das og. 2.0-Profil (oder XRechnung) benötigt.

Schreibe einen Kommentar

Kommentar absenden >>