How to Create ZUGFeRD-compliant PDF Invoices in C#

Electronic invoicing, or e-invoicing, is exchanging an electronic invoice document, transmitting, receiving, and processing it electronically. It is digital throughout its entire life cycle. Hence, it offers cost savings and increased efficiencies in a business-to-business (B2B) environment, and that value extends to both buyers and sellers.

In an era driven by computer and communication technology, as millions of companies move forward to take advantage of the benefits offered by e-invoices, standards are needed to ensure complete interoperability of e-invoices so that once generated, any software can read them.

Out of the many data formats for e-invoices, the ZUGFeRD standard has become increasingly established in German-speaking and EU countries. Hence, GrapeCity Documents API for PDF (GcPdf) can now be used (with the help of the ZUGFeRD-csharp package) to create or load ZUGFeRD-compliant invoices (in c#).

In this blog, we will learn what the ZUGFeRD standard is, how to create ZUGFeRD-compliant PDF invoices, and how to extract ZUGFeRD information from PDF invoices using GcPdf.

How to Create ZUGFeRD-compliant PDF Invoices in C#

What is ZUGFeRD?

ZUGFeRD "Zentraler User Guide des Forums Elektronische Rechnung Deutschland," is a German e-invoicing standard developed by FeRD - "Forum Elektronische Rechnung Deutschland" as a uniform data format for exchanging data structurally in public and private sectors.

ZUGFeRD format is based on PDF/A-3 and contains structured data in XML. The hybrid approach enables the PDF to be used as a "container" and present the invoice data in a fixed-layout PDF that can be processed by ZUGFeRD-compliant applications. PDF/A-3 is an ISO standard for long-term archiving. Because the ZUGFeRD XML format is based on the international standard UN CEFACT, it is compatible across the EU and internationally.

How to Create ZUGFeRD-compliant PDF Invoices in C

GcPdf enables creating ZUGFeRD-compliant PDFs by building the invoice in HTML and then converting it to a PDF using GcHtml. The structured XML file containing the invoice information is added to the PDF through the 'EmbeddedFiles' collection of the 'GcPdfDocument' class.

To understand how GcPdf performs these actions, let's generate a sample invoice using data from the GcNWind database. The whole process of creating a ZUGFeRD-compliant PDF invoice consists of the following phases:

  1. Fetching data
  2. Building ZUGFeRD-compliant XML
  3. Building an invoice as HTML
  4. Converting an HTML invoice to PDF
  5. Creating a PDF/3-A compliant PDF and attaching an XML invoice

Fetching Data for the ZUGFeRD-compliant Invoice

Invoices are order specific documents, so we need first to access the order details corresponding to the particular Order ID. For this, we'll use the 'Suppliers', 'OrdersCustomersEmployees,' and 'EmployeesProductsOrders' tables from the GcNwind.xml database and extract the details of a random order.

var orderDetails = dtOrdersDetails.Select()
                  .Select(it => new
                        OrderID = Convert.ToInt32(it["OrderID"]),
                        ItemDescription = it["ProductName"].ToString(),
                        Rate = Convert.ToDecimal(it["UnitPrice"]),
                        Quantity = Convert.ToDecimal(it["Quantity"])
                  .Where(it => it.OrderID == order.OrderID)
                  .OrderBy(it => it.ItemDescription).ToList();

The above code fetches the 'orderDetails' of an order whose OrderID matches the OrderID of the 'order' for which the invoice is being generated.

Building ZUGFeRD-compliant XML

As mentioned earlier, the ZUGFeRD standard calls for adding a structured XML to a PDF. To build ZUGFeRD-compliant XML, we'll use the ZUGFeRD-csharp package and add invoice information to it.

var zugferdDesc = InvoiceDescriptor.CreateInvoice( order.OrderID.ToString(),
                  order.OrderDate, CurrencyCodes.USD);

// Fill the invoice buyer info:
zugferdDesc.SetBuyer( order.ShipName, order.ShipPostalCode,
                  order.ShipCity, order.ShipAddress,
                  GetCountryCode(order.ShipCountry), order.CompanyName);
zugferdDesc.SetBuyerContact($"{order.FirstName} {order.LastName}");

The above code builds ZUGFeRD-compliant XML and adds buyer information. Similarly, data for the seller, delivery date, due date, etc., can also be added.

After building ZUGFeRD-compliant XML, we can save it to a temporary stream, add it as an attachment to the PDF invoice later, and set the standard to Version1. At this time, only 1.x version is adequately supported.

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

Creating Invoices as HTML

Note: We use HTML as an intermediate state only to simplify formatting. Building HTML is not related to ZUGFeRD, so you can use GcPdfGraphics to draw the invoice instead.

To ease the HTML creation, we'll create HTML templates for the invoice sections, where the templates will have data placeholders and can be re-used. For instance, we can make the following data row an HTML template and use it for each invoice record:

const string c_dataRowFmt = @"
            <td class='no'>{0}</td>
            <td class='desc'><h3>{1}</h3></td>
            <td class='unit'>{2}</td>
            <td class='qty'>{3}</td>
            <td class='total'>{4}</td>

Similarly, we can create HTML templates for other invoice sections like header, body, styles, etc. This blog will use HTML templates for invoice tables, rows/records, and styles. Creating an HTML template is out of scope for this blog, so refer to the attached application for code.

Once the HTML templates are ready, we can build an HTML invoice by adding data to these templates.

var html = string.Format(c_tableTpl, detailsHtml.ToString(),
           $"{supplier.Address}, {supplier.Region} {supplier.PostalCode}, {supplier.City} {supplier.Country}",
           $"{order.FirstName} {order.LastName} {order.CompanyName}",
           $"{order.ShipAddress}, {order.ShipRegion} {order.ShipPostalCode}, {order.ShipCity} {order.ShipCountry}",
           orderSubTotal.ToString("C", culture),
           orderTax.ToString("C", culture),
           (orderSubTotal + orderTax).ToString("C", culture), c_tableStyles);

This action will build the invoice in HTML format, which will later convert to PDF.

Converting HTML Invoices to PDF

To convert the HTML build in the previous step, we'll use the GcHtmlRenderer class with the bound HTML template string as its parameter.

However, to use the GcHtmlRenderer class, we first need to import the following namespace:

using GrapeCity.Documents.Html;

GcHtmlRenderer exposes the 'RenderToPdf' method that converts the HTML string and creates a corresponding PDF file. With the help of this method, we will convert the bound HTML to PDF format.

// Render the bound HTML
using (var re = new GcHtmlRenderer(boundTemplate))

While creating the PDF file, we can customize it. Margins, header, and footer can all be added to the PDF file while converting the HTML template with GcHtmlRenderer.

var tmpPdf = Path.GetTempFileName();
using (var re = new GcHtmlRenderer(html))
    // Set up HTML headers, margins etc (see HtmlSettings)
    var pdfSettings = new PdfSettings()
        Margins = new Margins(0.2f, 1, 0.2f, 1),
        IgnoreCSSPageSize = true,
        DisplayHeaderFooter = true,
        HeaderTemplate = "<div style='color:#1a5276; font-size:12px; width:1000px; margin-left:0.2in; margin-right:0.2in'>" +
                         "<span style='float:left;'>Invoice</span>" +
                         "<span style='float:right'>Page <span class='pageNumber'></span> of <span class='totalPages'></span></span>" +
        FooterTemplate = "<div style='color: #1a5276; font-size:12em; width:1000px; margin-left:0.2in; margin-right:0.2in;'>" +
                         "<span>(c) GrapeCity, Inc. All Rights Reserved.</span>" +
                         "<span style='float:right'>Generated on <span class='date'></span></span></div>"
    // Render the source Web page to the temporary file:

Creating PDF/3-A-compliant PDF and Attaching an XML Invoice

Finally, we'll use the PDF created above and build a PDF/A-3-compliant document with the ZUGFeRD XML attachment. To generate the PDF, we'll use the 'GcPdfDocument' class, set ConformanceLevel to PdfA3a, and use the EmbeddedFiles collection to add the XML invoice as an attachment:

var doc = new GcPdfDocument();
var tmpZugferd = Path.GetTempFileName();
using (var fs = File.OpenRead(tmpPdf))
     doc.ConformanceLevel = PdfAConformanceLevel.PdfA3a;
     var ef1 = EmbeddedFileStream.FromBytes(doc, ms.ToArray());
     ef1.ModificationDate = DateTime.Now;
     ef1.MimeType = "text/xml";

     // According to the ZUGFeRD 1.x standard naming, the filename should be ZUGFeRD-invoice.xml:
     var fspec = FileSpecification.FromEmbeddedStream("ZUGFeRD-invoice.xml", ef1);
     fspec.Relationship = AFRelationship.Alternative;
     fspec.UnicodeFile.FileName = fspec.File.FileName;

     // The attachment dictionary key can be anything:
     doc.EmbeddedFiles.Add("ZUGfERD-Attachment", fspec);

How to Create ZUGFeRD-compliant PDF Invoices in C#

Extracting ZUGFeRD Information in C

Besides creating a ZUGFeRD-compliant PDF, GcPdf also allows extracting ZUGFeRD information from the PDF invoice.

To extract the ZUGFeRD information, GcPdf accesses the structured XML attached to the PDF and stores the invoice information in an instance of the Invoice Descriptor class provided by the ZUGFeRD-csharp package.

var doc = new GcPdfDocument();
using (FileStream fs = File.OpenRead(invoicePdf))
    // Load the ZUGFeRD compliant invoice PDF:
    var invoice = new GcPdfDocument();

    // Get the ZUGFeRD attachment from the invoice by the ZUGFeRD 1.x standard file name:
    var attachment = invoice.EmbeddedFiles.Values.FirstOrDefault(it => it.File.FileName == "ZUGFeRD-invoice.xml");
    if (attachment != null)
        using (var xmlstream = attachment.GetStream())
            // Load the invoice descriptor:
            var descriptor = InvoiceDescriptor.Load(xmlstream);

The InvoiceDescriptor object 'descriptor' will store all invoice information of the loaded PDF. We can use this information as necessary and even render the extracted invoice information in a new PDF using GcPdfDocument API.

How to Create ZUGFeRD-compliant PDF Invoices in C#

Viewing ZUGFeRD Invoice Attachment in GcPdfViewer

Using GrapeCity's Documents for PDF, we don't even need to rely on a browser to open the PDF. GrapeCity's Documents API for PDF provides a cross-platform PDF viewer, 'GcPdfViewer,' which we can use to view the ZUGFeRD compliant PDFs on the web, along with the structured XML.

How to Create ZUGFeRD-compliant PDF Invoices in C#

Visit the Demo section to find sample applications with complete code, to learn more about working with ZUGFeRD format PDFs using GcPdf.

Ruchir Agarwal

comments powered by Disqus