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.

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 Mail
ZUGFeRD-csharp
In this sample, we utilize the GitHub project ZUGFeRD-csharp that is also available as a 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.
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 Mail
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.
When loading this document into a ZUGFeRD validator (ZF/FX Validation), the results show a valid ZUGFeRD PDF.
You can download the sample from our GitHub repository to test this on your own.
Download and Fork This Sample on GitHub
We proudly host our sample code on github.com/TextControl.
Please fork and contribute.
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.
- Angular
- Blazor
- React
- JavaScript
- ASP.NET MVC, ASP.NET Core, and WebForms
Related Posts
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.
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…
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.
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…