Convert File to PDF/Factur-X (ZUGFeRD) within C# and .NET

  1. Add SautinSoft.Document from Nuget.
  2. Load an input document.
  3. Save to a PDF format.

Document .Net can help your application to convert any file document into a new one in PDF: Factur-X (Order-X, ZUGFeRD) format for electronic Invoices.

Factur-X is a Franco-German e-invoicing standard which complies with the European e-invoicing standard EN 16931. The Factur-X specifications are available on the FNFE-MPE website in English and French. The Factur-X standard is also called ZUGFeRD 2.2 in Germany.

Facture X is at the same time a full readable invoice in a PDF A/3 format, containing all information useful for its treatment, especially in case of discrepancy or absence of automatic matching with orders and / or receptions, and a set of invoice data presented in an XML structured file conformant to EN16931 (syntax CII D16B), complete or not, allowing invoice process automation. Order-X is the equivalent of Factur-X for purchase orders.

The main feature of this Document .Net library is to generate Factur-X invoices and Order-X orders from a regular PDF document and a FacturX or OrderX compliant XML file.

ZUGFeRD 2.2 and Factur-X 1.0 are fully compatible and technically identical formats that have been using the FacturX identifier together since March 24, 2020. Both formats are basically suitable for the exchange of invoices between companies, public administration and consumers.

Document .Net provides additional features:

  • Generate PDF documents of Factur-X v.1.0, ZUGFeRD v.1.0 - v.2.2
  • Convert RTF file to Factur-X v.1.0, ZUGFeRD v.1.0 - v.2.2
  • Convert DOCX file to Factur-X v.1.0, ZUGFeRD v.1.0 - v.2.2
  • Convert PDF file to Factur-X v.1.0, ZUGFeRD v.1.0 - v.2.2
  • Convert HTML file to Factur-X v.1.0, ZUGFeRD v.1.0 - v.2.2
  • Extract PDF/FactureX to Word, Excel, HTML, XML
  • Check a Factur-X or Order-X XML file against the official XML Schema Definition


             
 /// Convert file to PDF/ Factur-X format (file to file).
 /// Read more information about Factur-X: https://fnfe-mpe.org/factur-x/
 
 static void ConvertFromFile()
 {
     string inpFile = @"..\..\..\Factur.rtf";
     string outFile = @"..\..\..\Factur.pdf";
     string xmlInfo = File.ReadAllText(@"..\..\..\Factur.xml");

     DocumentCore dc = DocumentCore.Load(inpFile);

     PdfSaveOptions pdfSO = new PdfSaveOptions()
     {
         // Factur-X is at the same time a full readable invoice in a PDF A/3 format,
         // containing all information useful for its treatment, especially in case of discrepancy or absence of automatic matching with orders and / or receptions,
         // and a set of invoice data presented in an XML structured file conformant to EN16931 (syntax CII D16B), complete or not, allowing invoice process automation.
         FacturXXML = xmlInfo
     };

     dc.Save(outFile, pdfSO);

     // Open the result for demonstration purposes.
     System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo(outFile) { UseShellExecute = true });
 }

About ZUGFeRD 1, ZUGFeRD 2 and Factur-X

The ZUGFeRD 1.0 specification has been published in June 2014. The ZUGFeRD 1.0 info package (available only in German language) contains specifications, XML schemas, XSLT style sheets as well as a dozen of sample PDF invoices. The PDF-specific requirements of the ZUGFeRD format are summarized below.

ZUGFeRD 2.0 has been published in March 2019. It is based on European Norm EN 16931 from June 2017, conforms to the XRechnung standard and is mostly compatible with the corresponding French standard Factur-X.

ZUGFeRD 2.1 has been published in March 2020. It makes the standard fully compatible with Factur-X 1.0.05.

ZUGFeRD 1 und 2 apply the same principles regarding embedding in PDF/A. Minor differences between the versions are mentioned in the description below.

About XML Part of a ZUGFeRD Invoice

While we will focus on the PDF aspects of ZUGFeRD on the remainder of this page, here is a brief overview of the embedded invoice XML. ZUGFeRD does not introduce a new XML format for invoices, but instead is based on the existing standard »Core Cross Industry Invoice« (CII) developed by UN/CEFACT. The CII provides a large framework with more than 2000 elements. The framework is modelled around business processes and relationships. Customarily the CII framework is restricted for particular applications because usually not all elements are required.

ZUGFeRD 2.0 and Factur-X are based on UN/CEFACT Cross Industry Invoice Stand D16B version 100, uncoupled set of schemas (CII). Since ZUGFeRD 1.0 uses a custom XML flavor, the invoice XML slightly differs between both versions. For example, the root element in ZUGFeRD 1.0 is CrossIndustryDocument, but CrossIndustryInvoice in ZUGFeRD 2.0/Factur-X.

ZUGFeRD 1.0 and 2.x/Factur-X support multiple application profiles:

  • ZUGFeRD 2.x only: the »Minimum« and »Basic WL« profiles have been included in ZUGFeRD 2.x for compatibility with the French standard Factur-X. They don't contain all invoicing information required in Germany and should therefore not be used in Germany.
  • The »Basic« profile carries structured data for simple invoices. Additional information can be included as free text. It covers only a subset of EN 16931-1 and is suitable for simple invoices.
  • The »Comfort« profile adds structured data for fully automated invoice processing. It completely covers EN 16931-1.
  • The »Extended« profile adds still more structured data for exchanging invoice across different industry segments.
    At a minimum, applications must support the »Basic« profile, but they may add more CII elements provided these don’t interfere with the »Extended« profile. Since additional elements are outside the scope of ZUGFeRD they require prior arrangements between the exchanging parties.

Document .Net and PDF Requirements for ZUGFeRD Invoices

The ZUGFeRD format specification spells out the following requirements:

(1) The PDF part of a ZUGFeRD invoice must conform to the PDF/A-3 standard (ISO 19005-3). All PDF/A-3 conformance levels are allowed, i.e. PDF/A-3a, PDF/A-3b, and PDF/A-3u. It simultaneously serves as container for the XML part. While only a single XML invoice attachment is allowed in ZUGFeRD, additional attachments for other purposes may also be embedded. For example, spreadsheets, CAD drawings, images or other files can be embedded which are related to the invoice or may be relevant for invoice verification.

While only PDF/A-3 allows embedded file attachments, the three PDF/A levels are upwards compatible regarding the use of PDF elements. This implies the following combinations for creating ZUGFeRD invoices by attaching XML to PDF/A invoices:

PDF/A-1a and PDF/A-2a can serve as basis for PDF/A-3a, PDF/A-3b or PDF/A-3u;
PDF/A-1b and PDF/A-2b can serve as basis for PDF/A-3b;
PDF/A-2u can serve as basis for PDF/A-3b or PDF/A-3u;
(2) The XML part of the invoice must be associated with the document level of the PDF/A document (as opposed to some part of it, e.g. a page). In PDF/A-3 this is expressed with the /AF (associated files) key in the document catalog. It is required to use a fixed file name for the XML attachment; however, the standards require slightly different file names:

ZUGFeRD 1.0: file name »ZUGFeRD-invoice.xml«
ZUGFeRD 2.0: file name »zugferd-invoice.xml«
ZUGFeRD 2.1 and Factur-X: file name »factur-x.xml«
The relationship of attachment and document must be »Alternative« in ZUGFeRD 1.0 and ZUGFeRD 2.0 to signal that the PDF and XML representations are equivalent. In PDF/A-3 this is expressed with the /AFRelationship key.

ZUGFeRD 2.1 changes the required value of the /AFRelationship key from »Alternative« to »Source« for the BASIC, EN 16931 and EXTENDED profiles if the invoice recipient is located outside Germany and if the PDF document is the result of transforming the XML data. Note that the ZUGFeRD 2.1 samples contain a wrong /AFRelationship key (»Data« instead of the required »Alternative« or »Source«).

(3) The XML file must additionally be declared as regular PDF attachment so that it can be processed with tools which don’t support associated files according to PDF/A-3). This is achieved by including the attachment in the PDF 1.7 standard data structure /EmbeddedFiles in the document catalog.

(4) The XMP document metadata must include four entries from the ZUGFeRD schema. These entries describe the document type (always INVOICE); the file name of the embedded XML representation which must match the name under which the XML is actually attached in the PDF document; the version of the corresponding XML schema; and the name of the applicable ZUGFeRD profile (BASIC, COMFORT, or EXTENDED). PDF/A requires that custom metadata properties like those defined by ZUGFeRD are accompanied by the corresponding schema description or extension schema; see here for details. The requirements for XMP extension schema descriptions are identical in PDF/A-1, PDF/A-2 and PDF/A-3. Templates for the XMP metadata properties for ZUGFeRD 1.0, 2.0, 2.1 and Factur-X including the required PDF/A extension schema description can be found at the end of this page. The templates for the three standards are slightly different because different file names are required for the XML attachments (see (2) above) and different XML namespaces and prefixes are used.

 

Document .Net supports these formats:

PDF DOCX RTF HTML Text Image
Create/Read/Write Create/Read/Write Create/Read/Write Create/Read/Write Create/Read/Write Create/Read(OCR)/Write

We've also prepared the video for you: How to convert file to PDF/Factur-X in Linux:

Complete code

using System.IO;
using SautinSoft.Document;

namespace Example
{
    class Program
    {
        static void Main(string[] args)
        {
            ConvertFromFile();
            ConvertFromStream();
        }

        /// <summary>
        /// Convert RTF file to PDF/ Factur-X format (file to file).
        /// Read more information about Factur-X: https://fnfe-mpe.org/factur-x/
        /// </summary>
		/// <remarks>
        /// Details: https://www.sautinsoft.com/products/document/help/net/developer-guide/convert-file-to-pdf-factur-x-in-csharp-vb.php
        /// </remarks>
        static void ConvertFromFile()
        {
            string inpFile = @"..\..\..\Factur.rtf";
            string outFile = @"..\..\..\Factur.pdf";
            string xmlInfo = File.ReadAllText(@"..\..\..\Factur\Facture.xml");

            DocumentCore dc = DocumentCore.Load(inpFile);

            PdfSaveOptions pdfSO = new PdfSaveOptions()
            {
                // Factur-X is at the same time a full readable invoice in a PDF A/3 format,
                // containing all information useful for its treatment, especially in case of discrepancy or absence of automatic matching with orders and / or receptions,
                // and a set of invoice data presented in an XML structured file conformant to EN16931 (syntax CII D16B), complete or not, allowing invoice process automation.
                FacturXXML = xmlInfo
            };

            dc.Save(outFile, pdfSO);

            // Open the result for demonstration purposes.
            System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo(outFile) { UseShellExecute = true });
        }

        /// <summary>
        /// Convert PDF file to PDF/ Factur-X format (using Stream).
        /// Read more information about Factur-X: https://fnfe-mpe.org/factur-x/
        /// </summary>
        /// <remarks>
        /// Details: https://www.sautinsoft.com/products/document/help/net/developer-guide/convert-file-to-pdf-factur-x-in-csharp-vb.php
        /// </remarks>
        static void ConvertFromStream()
        {

            // We need files only for demonstration purposes.
            // The conversion process will be done completely in memory.
            string inpFile = @"..\..\..\Sample.pdf";
            string outFile = @"..\..\..\Factur.pdf";
            string xmlInfo = File.ReadAllText(@"..\..\..\Factur\Facture.xml");
            byte[] inpData = File.ReadAllBytes(inpFile);
            byte[] outData = null;

            using (MemoryStream msInp = new MemoryStream(inpData))
            {
                // Specifying PdfLoadOptions we explicitly set that a loadable document is PDF.
                PdfLoadOptions pdfLO = new PdfLoadOptions()
                {
                    // 'false' - means to load vector graphics as is. Don't transform it to raster images.
                    RasterizeVectorGraphics = false,

                    // The PDF format doesn't have real tables, in fact it's a set of orthogonal graphic lines.
                    // In case of 'true' the component will detect and recreate tables from graphic lines.
                    DetectTables = false,
                    // 'Disabled' - Never load embedded fonts in PDF. Use the fonts with the same name installed at the system or similar by font metrics.
                    // 'Enabled' - Always load embedded fonts in PDF.
                    // 'Auto' - Load only embedded fonts missing in the system. In other case, use the system fonts.					
                    PreserveEmbeddedFonts = PropertyState.Auto
                };

                // Load a document.
                DocumentCore dc = DocumentCore.Load(msInp, pdfLO);

                // Save the document to PDF/A format.
                PdfSaveOptions pdfSO = new PdfSaveOptions()
                {
                    // Factur-X is at the same time a full readable invoice in a PDF A/3 format,
                    // containing all information useful for its treatment, especially in case of discrepancy or absence of automatic matching with orders and / or receptions,
                    // and a set of invoice data presented in an XML structured file conformant to EN16931 (syntax CII D16B), complete or not, allowing invoice process automation.
                    FacturXXML = xmlInfo
                };

                using (MemoryStream outMs = new MemoryStream())
                {
                    dc.Save(outMs, pdfSO);
                    outData = outMs.ToArray();
                }
                // Show the result for demonstration purposes.
                if (outData != null)
                {
                    File.WriteAllBytes(outFile, outData);
                    System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo(outFile) { UseShellExecute = true });
                }
            }
        }
    }
}

Download

Imports System.IO
Imports SautinSoft.Document

Namespace Example
	Friend Class Program
		Shared Sub Main(ByVal args() As String)
			ConvertFromFile()
			ConvertFromStream()
		End Sub

		''' <summary>
		''' Convert RTF file to PDF/ Factur-X format (file to file).
		''' Read more information about Factur-X: https://fnfe-mpe.org/factur-x/
		''' </summary>
		''' <remarks>
		''' Details: https://www.sautinsoft.com/products/document/help/net/developer-guide/convert-file-to-pdf-factur-x-in-csharp-vb.php
		''' </remarks>
		Private Shared Sub ConvertFromFile()
			Dim inpFile As String = "..\..\..\Factur.rtf"
			Dim outFile As String = "..\..\..\Factur.pdf"
			Dim xmlInfo As String = File.ReadAllText("..\..\..\Factur\Facture.xml")

			Dim dc As DocumentCore = DocumentCore.Load(inpFile)

			Dim pdfSO As New PdfSaveOptions() With {.FacturXXML = xmlInfo}

			dc.Save(outFile, pdfSO)

			' Open the result for demonstration purposes.
			System.Diagnostics.Process.Start(New System.Diagnostics.ProcessStartInfo(outFile) With {.UseShellExecute = True})
		End Sub

		''' <summary>
		''' Convert PDF file to PDF/ Factur-X format (using Stream).
		''' Read more information about Factur-X: https://fnfe-mpe.org/factur-x/
		''' </summary>
		''' <remarks>
		''' Details: https://www.sautinsoft.com/products/document/help/net/developer-guide/convert-file-to-pdf-factur-x-in-csharp-vb.php
		''' </remarks>
		Private Shared Sub ConvertFromStream()

			' We need files only for demonstration purposes.
			' The conversion process will be done completely in memory.
			Dim inpFile As String = "..\..\..\Sample.pdf"
			Dim outFile As String = "..\..\..\Factur.pdf"
			Dim xmlInfo As String = File.ReadAllText("..\..\..\Factur\Facture.xml")
			Dim inpData() As Byte = File.ReadAllBytes(inpFile)
			Dim outData() As Byte = Nothing

			Using msInp As New MemoryStream(inpData)
				' Specifying PdfLoadOptions we explicitly set that a loadable document is PDF.
				Dim pdfLO As New PdfLoadOptions() With {
					.RasterizeVectorGraphics = False,
					.DetectTables = False,
					.PreserveEmbeddedFonts = PropertyState.Auto
				}

				' Load a document.
				Dim dc As DocumentCore = DocumentCore.Load(msInp, pdfLO)

				' Save the document to PDF/A format.
				Dim pdfSO As New PdfSaveOptions() With {.FacturXXML = xmlInfo}

				Using outMs As New MemoryStream()
					dc.Save(outMs, pdfSO)
					outData = outMs.ToArray()
				End Using
				' Show the result for demonstration purposes.
				If outData IsNot Nothing Then
					File.WriteAllBytes(outFile, outData)
					System.Diagnostics.Process.Start(New System.Diagnostics.ProcessStartInfo(outFile) With {.UseShellExecute = True})
				End If
			End Using
		End Sub
	End Class
End Namespace

Download


If you need a new code example or have a question: email us at support@sautinsoft.com or ask at Online Chat (right-bottom corner of this page) or use the Form below:



Questions and suggestions from you are always welcome!

We are developing .Net components since 2002. We know PDF, DOCX, RTF, HTML, XLSX and Images formats. If you need any assistance with creating, modifying or converting documents in various formats, we can help you. We will write any code example for you absolutely free.