Products Technologies Demo Docs Blog Support Company

Creating 100% Compliant ZUGFeRD and Factur-X Invoices using MailMerge in C#

The ZUGFeRD and Factur-X standards are hybrid electronic invoice formats regulated and required by some European governments. This article shows how to create a valid ZUGFeRD compliant invoice PDF document from scratch.

Creating 100% Compliant ZUGFeRD and Factur-X Invoices using MailMerge in C#

The ZUGFeRD / Factur-X standard is a hybrid electronic invoice format that consists of two parts:

  • A PDF visual, human-readable representation of the invoice.
  • An XML file that contains invoice data in a structured form that can be processed automatically.

This article shows how to use the MailMerge class to merge invoice data into a template and how to embed the generated ZUGFeRD XML to the final PDF document.

ZUGFeRD-csharp

In this sample, we utilize the GitHub project ZUGFeRD-csharp that is also available as a NuGet package.

ZUGFeRD-csharp GitHub repository

ZUGFeRD-csharp NuGet package

The Template

The following screenshot shows a very simple invoice template with fields according to the following Order data structure. You can see the merge fields for the Buyer and the merge block highlighted in red to repeat the LineItems.

Invoice template

The Data Source

The class Order contains all data required for an invoice generation process including address data for the buyer, the seller and the sold line items. Some properties such as LineTotalAmount and TaxTotalAmount are calculated automatically based on the added line items.

public class Order {
  public int Id { get; set; }
  public DateTime OrderDate { get; set; }
  public ContractParty Buyer { get; set; }
  public ContractParty Seller { get; set; }
  public Decimal Allowance { get; set; }
  public Decimal Vat { get; set; } = 6.5M;
  public List<LineItem> LineItems { get; set; } = new List<LineItem>();
  
  public Decimal LineTotalAmount {
    get {
      return this.LineItems.Sum(item => item.GrossPrice * item.Quantity);
    }
  }

  public Decimal TaxTotalAmount {
    get {
      return (this.LineTotalAmount / 100) * this.Vat;
    }
  }

  public Decimal GrandTotalAmount {
    get {
      return this.LineTotalAmount + this.TaxTotalAmount;
    }
  }

  public class LineItem {
    public string Name { get; set; }
    public string Description { get; set; }
    public QuantityCodes QuantityCode { get; set; } = QuantityCodes.H87;
    public int Quantity { get; set; }
    public decimal GrossPrice { get; set; }
  }

  public class Seller : ContractParty { }
  public class Buyer : ContractParty { }

  public class ContractParty {
    public int Id { get; set; }
    public string Name { get; set; }
    public string PostalCode { get; set; }
    public string City { get; set; }
    public string Address { get; set; }
    public CountryCodes CountryCodes { get; set; }
    public ContractPartyContact BuyerContact { get; set; }
  }

  public class ContractPartyContact {
    public string FirstName { get; set; }
    public string LastName { get; set; }
  }
  
}

Additionally, the class Order contains a property that generates the required ZUGFeRD XML. The property get method is basically matching the data source to the required properties of the InvoiceDescriptor that generates the XML.

public byte[] ZugferdXML {
  get {
    var invoice = InvoiceDescriptor.CreateInvoice(this.Id.ToString(),
        this.OrderDate, CurrencyCodes.USD);

    invoice.SetBuyer(this.Buyer.Name,
      this.Buyer.PostalCode,
      this.Buyer.City,
      this.Buyer.Address,
      this.Buyer.CountryCodes,
      this.Buyer.Id.ToString());

    invoice.SetSeller(this.Seller.Name,
      this.Seller.PostalCode,
      this.Seller.City,
      this.Seller.Address,
      this.Seller.CountryCodes,
      this.Seller.Id.ToString());

    invoice.SetSellerContact($"{this.Seller.BuyerContact.FirstName} {this.Seller.BuyerContact.LastName}");

    foreach (LineItem lineItem in this.LineItems) {
      invoice.AddTradeLineItem(lineItem.Name, lineItem.Description, lineItem.QuantityCode, lineItem.Quantity, lineItem.GrossPrice, lineItem.GrossPrice, lineItem.Quantity);
    }

    invoice.LineTotalAmount = LineTotalAmount;
    invoice.ChargeTotalAmount = invoice.LineTotalAmount;
    invoice.AllowanceTotalAmount = Allowance;
    invoice.TaxBasisAmount = invoice.ChargeTotalAmount;
    invoice.TaxTotalAmount = TaxTotalAmount;
    invoice.GrandTotalAmount = GrandTotalAmount;

    MemoryStream ms = new MemoryStream();

    invoice.Save(ms, ZUGFeRDVersion.Version1, Profile.Basic);

    return ms.ToArray();
  }
}

Creating the Invoice

The static method Create of the Invoice class is doing the actual merging work and embeds the generated XML into the created PDF. The method uses the MailMerge class to merge the data into the template and embeds the ZUGFeRD XML into a PDF/A-3b document.

public static class Invoice {
  public static byte[] Create(Order order) {

    TXTextControl.SaveSettings saveSettings = new TXTextControl.SaveSettings();

    var metaData = System.IO.File.ReadAllText("metadata.xml");

    // create a new embedded file
    var zugferdInvoice = new TXTextControl.EmbeddedFile(
      "ZUGFeRD-invoice.xml",
      order.ZugferdXML,
      metaData);

    zugferdInvoice.Description = "ZUGFeRD-invoice";
    zugferdInvoice.Relationship = "Alternative";
    zugferdInvoice.MIMEType = "application/xml";
    zugferdInvoice.LastModificationDate = DateTime.Now;

    // set the embedded files
    saveSettings.EmbeddedFiles = new TXTextControl.EmbeddedFile[] { zugferdInvoice };

    byte[] document;

    using (TXTextControl.ServerTextControl tx = new ServerTextControl()) {
      tx.Create();

      tx.Load("template.tx", StreamType.InternalUnicodeFormat);

      using (MailMerge mailMerge = new MailMerge()) {
        mailMerge.TextComponent = tx;
        mailMerge.MergeObject(order);
      }

      // export the PDF
      tx.Save(out document, TXTextControl.BinaryStreamType.AdobePDFA, saveSettings);

      return document;
    }
  }
}

The Sample

The console application creates a new Order and calls the above Invoice.Create method and writes the created PDF document to a file.

using s2industries.ZUGFeRD;
using TXTextControl.DocumentServer.PDF.Zugferd;

Console.WriteLine("Creating ZUGFeRD Invoice...");

Order order = new Order() {
        Buyer = new ContractParty() {
                Address = "123 Street Dr.",
                CountryCodes = CountryCodes.US,
                BuyerContact = new ContractPartyContact() {
                        FirstName = "Jack",
                        LastName = "Sparrow"
                },
                City = "Charlotte",
                Id = 123,
                Name = "Company, LLC",
                PostalCode = "NC 28209"
        },
        Seller = new ContractParty() {
                Address = "333 Ave Dr.",
                CountryCodes = CountryCodes.US,
                BuyerContact = new ContractPartyContact() {
                        FirstName = "Peter",
                        LastName = "Jackson"
                },
                City = "Charlotte",
                Id = 123,
                Name = "Microogle, LLC",
                PostalCode = "NC 28210"
        },
        Id = 1,
        OrderDate = DateTime.Now,
        Allowance = 0,
        Vat = 6.5M,
        LineItems = new List<LineItem> {
                                        new LineItem() {
                                                Name = "Product A",
                                                Description = "Description A",
                                                Quantity = 5,
                                                QuantityCode = QuantityCodes.H87,
                                                GrossPrice = 432.00M
                                        },
                                        new LineItem() {
                                                Name = "Product B",
                                                Description = "Description B",
                                                Quantity = 2,
                                                QuantityCode = QuantityCodes.H87,
                                                GrossPrice = 5232.00M
                                        },
                                }
};

File.WriteAllBytes("result.pdf", Invoice.Create(order));

Console.WriteLine("ZUGFeRD Invoice created successfully!");

After opening the PDF in Acrobat Reader, you can see the created visual representation and the embedded XML in the Attachments pane.

Invoice PDF

When loading this document into a ZUGFeRD validator (ZF/FX Validation), the results show a valid ZUGFeRD PDF.

Invoice PDF

You can download the sample from our GitHub repository to test this on your own.

Stay in the loop!

Subscribe to the newsletter to receive the latest updates.

GitHub

Download and Fork This Sample on GitHub

We proudly host our sample code on github.com/TextControl.

Please fork and contribute.

Download ZIP

Open on GitHub

Open in Visual Studio

Requirements for this sample

  • TX Text Control .NET Server 31.0
  • Visual Studio 2022

ASP.NET

Integrate document processing into your applications to create documents such as PDFs and MS Word documents, including client-side document editing, viewing, and electronic signatures.

ASP.NET Core
Angular
Blazor
JavaScript
React
  • Angular
  • Blazor
  • React
  • JavaScript
  • ASP.NET MVC, ASP.NET Core, and WebForms

Learn more Trial token Download trial

Related Posts

ASP.NETASP.NET CoreFactur-X

Visualize and Preview XRechnung, ZUGFeRD, and Factur-X Documents in .NET C#

This article shows how to visualize and preview ZUGFeRD, XRechnung, and Factur-X documents in .NET C#. It uses TX Text Control .NET Server to render the documents from the XML data.


ASP.NETASP.NET CoreFactur-X

Creating ZUGFeRD 2.3 (XRechnung, Factur-X) Documents with .NET C#

This article shows how to create ZUGFeRD 2.3 compliant invoices using TX Text Control .NET Server. ZUGFeRD 2.3 is the latest version of the ZUGFeRD data model and complies with the European…


ASP.NETASP.NET CoreXRechnung

Using XRechnung / ZUGFeRD XML to Create PDF/A-3b Invoices with ASP.NET Core C#

This article shows how to create invoices with XRechnung and ZUGFeRD XML files using ASP.NET Core C# and the MailMerge class of TX Text Control .NET Server. The MailMerge class is used to merge…


ASP.NETASP.NET CoreElectronic Invoicing

Generating a ZUGFeRD PDF with Existing XML Data using .NET C#

This article shows how to generate a ZUGFeRD invoice with existing XML data using .NET C#. A valid PDF/A-3b file is created with a ZUGFeRD XML attachment using TX Text Control .NET Server.


ASP.NETWindows FormsWPF

Electronic Invoicing will Become Mandatory in Germany in 2025

The German government has decided to make the ability to receive electronic invoices mandatory for all B2B transactions. This article explains what this means for you and how you can prepare for…