Working with ZUGFeRD invoice

17 Jan 202317 minutes to read

The ZUGFeRD invoice is one of the uniformed data format for electronic invoices based on the ISO standard PDF/A-3, which is specifically designed for long term archiving. The ZUGFeRD invoice contains both human-readable invoice and machine-readable structured invoice data (XML).

Generating ZUGFeRD invoice

The Syncfusion .NET PDF library has support to create PDF document with PDF/A-3b conformance, which allow to add external file to the PDF document as attachment. The ZUGFeRD has two versions, ZugferdVersion 1.0 and ZugferdVersion 2.0. The Zugferd 2.0 is an updated version of Zugferd 1.0.

The ZUGFeRD has five conformance levels,

  • Basic: Represents the structured data for simple invoices. Additional information can be included as free text.
  • Comfort: Represents the structured data for fully automated invoice processing.
  • Extended: Represents the additional structured data for exchanging invoice across different industry segments.
  • Minimum: Represents the basic invoice details compatible with the French Standard Factur-X.
  • EN16931: Represents the fully compliant with the EU Standard, though it only defines the core elements of an invoice.

NOTE

  • The ZUGFeRD conformance levels Minimum and EN16931 are only supported in ZugferdVersion2.0.

The ZUGFeRD invoice document can be created by specifying the conformance level as Pdf_A3B through PdfConformanceLevel Enum when creating the new PDF document and set the ZugferdConformanceLevel property as Basic in ZugferdConformanceLevel Enum.

//Create ZUGFeRD invoice PDF document
PdfDocument document = new PdfDocument(PdfConformanceLevel.Pdf_A3B);

//Set ZUGFeRD conformance level
document.ZugferdConformanceLevel = ZugferdConformanceLevel.Basic;
'Create ZUGFeRD invoice PDF document
Dim document As PdfDocument = New PdfDocument(PdfConformanceLevel.Pdf_A3B) 

'Set ZUGFeRD conformance level
document.ZugferdConformanceLevel = ZugferdConformanceLevel.Basic
//Create ZUGFeRD invoice PDF document
PdfDocument document = new PdfDocument(PdfConformanceLevel.Pdf_A3B);

//Set ZUGFeRD conformance level
document.ZugferdConformanceLevel = ZugferdConformanceLevel.Basic;
//Create ZUGFeRD invoice PDF document
PdfDocument document = new PdfDocument(PdfConformanceLevel.Pdf_A3B);

//Set ZUGFeRD conformance level
document.ZugferdConformanceLevel = ZugferdConformanceLevel.Basic;
//Create ZUGFeRD invoice PDF document 
PdfDocument document = new PdfDocument(PdfConformanceLevel.Pdf_A3B);

//Set ZUGFeRD conformance level
document.ZugferdConformanceLevel = ZugferdConformanceLevel.Basic;

Using PDF/A-3b conformance, you can create a ZUGFeRD invoice PDF by specifying the ZugferdVersion property as ZugferdVersion2_0 of ZugferdVersion Enum. By default, ZugferdVersion1.0 used.

//Create ZUGFeRD invoice PDF document
PdfDocument document = new PdfDocument(PdfConformanceLevel.Pdf_A3B);

//Specifies ZUGFeRD version 
document.ZugferdVersion = ZugferdVersion.ZugferdVersion2_0;
'Create ZUGFeRD invoice PDF document
Dim document As PdfDocument = New PdfDocument(PdfConformanceLevel.Pdf_A3B) 

'Specifies ZUGFeRD version 
document.ZugferdVersion = ZugferdVersion.ZugferdVersion2_0
//Create ZUGFeRD invoice PDF document
PdfDocument document = new PdfDocument(PdfConformanceLevel.Pdf_A3B);

//Specifies ZUGFeRD version          
document.ZugferdVersion = ZugferdVersion.ZugferdVersion2_0;
//Create ZUGFeRD invoice PDF document
PdfDocument document = new PdfDocument(PdfConformanceLevel.Pdf_A3B);

//Specifies ZUGFeRD version            
document.ZugferdVersion = ZugferdVersion.ZugferdVersion2_0;
//Create ZUGFeRD invoice PDF document
PdfDocument document = new PdfDocument(PdfConformanceLevel.Pdf_A3B);

//Specifies ZUGFeRD version         
document.ZugferdVersion = ZugferdVersion.ZugferdVersion2_0;

Adding ZUGFeRD structured data as attachment

The PDF/A-3b conformance supports the external files as attachment to the PDF document using PdfAttachment class.

//Creates an attachment
FileStream invoiceStream = new FileStream("../../Data/ZUGFeRD-invoice.xml", FileMode.Open, FileAccess.Read);
PdfAttachment attachment = new PdfAttachment("ZUGFeRD-invoice.xml",invoiceStream);
attachment.Relationship = PdfAttachmentRelationship.Alternative;
attachment.ModificationDate = DateTime.Now;
attachment.Description = "ZUGFeRD-invoice";
attachment.MimeType = "application/xml";
//Add attachment to PDF document
document.Attachments.Add(attachment);
'Creates an attachment
Dim invoiceStream As FileStream = New FileStream("../../Data/ZUGFeRD-invoice.xml", FileMode.Open, FileAccess.Read)
Dim attachment As PdfAttachment = New PdfAttachment("ZUGFeRD-invoice.xml", invoiceStream)
attachment.Relationship = PdfAttachmentRelationship.Alternative
attachment.ModificationDate = DateTime.Now
attachment.Description = "ZUGFeRD-invoice"
attachment.MimeType = "application/xml"
//Add attachment to PDF document 
document.Attachments.Add(attachment)
//Creates an attachment
Stream invoiceStream = typeof(MainPage).GetTypeInfo().Assembly.GetManifestResourceStream("Sample.Assets.Data.ZUGFeRD-invoice.xml");
PdfAttachment attachment = new PdfAttachment("ZUGFeRD-invoice.xml",invoiceStream);
attachment.Relationship = PdfAttachmentRelationship.Alternative;
attachment.ModificationDate = DateTime.Now;
attachment.Description = "ZUGFeRD-invoice";
attachment.MimeType = "application/xml";
//Add attachment to PDF document
document.Attachments.Add(attachment);
//Creates an attachment
FileStream fontStream = new FileStream("../../Data/ZUGFeRD-invoice.xml", FileMode.Open, FileAccess.Read);
PdfAttachment attachment = new PdfAttachment("ZUGFeRD-invoice.xml",invoiceStream);
attachment.Relationship = PdfAttachmentRelationship.Alternative;
attachment.ModificationDate = DateTime.Now;
attachment.Description = "ZUGFeRD-invoice";
attachment.MimeType = "application/xml";
//Add attachment to PDF document
document.Attachments.Add(attachment);
//Creates an attachment
Stream invoiceStream = typeof(MainPage).GetTypeInfo().Assembly.GetManifestResourceStream("Sample.Assets.Data.ZUGFeRD-invoice.xml");
PdfAttachment attachment = new PdfAttachment("ZUGFeRD-invoice.xml",invoiceStream);
attachment.Relationship = PdfAttachmentRelationship.Alternative;
attachment.ModificationDate = DateTime.Now;
attachment.Description = "ZUGFeRD-invoice";
attachment.MimeType = "application/xml";
//Add attachment to PDF document
document.Attachments.Add(attachment);

NOTE

*As per the ZUGFeRD standard guidelines, the XML name must be ZUGFeRD-invoice.xml.

Complete code

The complete code to create ZUGFeRD invoice PDF document as follows.

//Create ZUGFeRD invoice PDF document
PdfDocument document = new PdfDocument(PdfConformanceLevel.Pdf_A3B);
//Set ZUGFeRD conformance level 
document.ZugferdConformanceLevel = ZugferdConformanceLevel.Basic;

//Creates an attachment 
FileStream invoiceStream = new FileStream("../../ Data / ZUGFeRD - invoice.xml", FileMode.Open, FileAccess.Read)
PdfAttachment attachment = new PdfAttachment("ZUGFeRD-invoice.xml",invoiceStream);
attachment.Relationship = PdfAttachmentRelationship.Alternative;
attachment.ModificationDate = DateTime.Now;
attachment.Description = "ZUGFeRD-invoice";
attachment.MimeType = "application/xml";
//Add attachment to PDF document
document.Attachments.Add(attachment);

//Save and close the document
document.Save("Zugferd.pdf");
document.Close(true);
'Create ZUGFeRD invoice PDF document
Dim document As PdfDocument = New PdfDocument(PdfConformanceLevel.Pdf_A3B)
'Set ZUGFeRD conformance level 
document.ZugferdConformanceLevel = ZugferdConformanceLevel.Basic

'Creates an attachment
Dim invoiceStream As FileStream = New FileStream("../../ Data / ZUGFeRD - invoice.xml", FileMode.Open, FileAccess.Read)
Dim attachment As PdfAttachment = New PdfAttachment("ZUGFeRD-invoice.xml",invoiceStream)
attachment.Relationship = PdfAttachmentRelationship.Alternative
attachment.ModificationDate = DateTime.Now
attachment.Description = "ZUGFeRD-invoice"
attachment.MimeType = "application/xml"
//Add attachment to PDF document
document.Attachments.Add(attachment)

'Save and close the document
document.Save("Zugferd.pdf")
document.Close(True)
//Create ZUGFeRD invoice PDF document
PdfDocument document = new PdfDocument(PdfConformanceLevel.Pdf_A3B);
//Set ZUGFeRD conformance level 
document.ZugferdConformanceLevel = ZugferdConformanceLevel.Basic;

//Creates an attachment 
Stream invoiceStream = typeof(MainPage).GetTypeInfo().Assembly.GetManifestResourceStream("Sample.Assets.Data.ZUGFeRD-invoice.xml");
PdfAttachment attachment = new PdfAttachment("ZUGFeRD-invoice.xml",invoiceStream);
attachment.Relationship = PdfAttachmentRelationship.Alternative;
attachment.ModificationDate = DateTime.Now;
attachment.Description = "ZUGFeRD-invoice";
attachment.MimeType = "application/xml";
//Add attachment to PDF document
document.Attachments.Add(attachment);

//Close the document
document.Close(true);
//Save the stream as PDF document file in local machine. Refer to the PDF/UWP section for respected code samples
Save(stream, "Zugferd.pdf");
//Create ZUGFeRD invoice PDF document
PdfDocument document = new PdfDocument(PdfConformanceLevel.Pdf_A3B);
//Set ZUGFeRD conformance level 
document.ZugferdConformanceLevel = ZugferdConformanceLevel.Basic;

//Creates an attachment 
FileStream fontStream = new FileStream("../../ Data / ZUGFeRD - invoice.xml", FileMode.Open, FileAccess.Read);
PdfAttachment attachment = new PdfAttachment("ZUGFeRD-invoice.xml",invoiceStream);
attachment.Relationship = PdfAttachmentRelationship.Alternative;
attachment.ModificationDate = DateTime.Now;
attachment.Description = "ZUGFeRD-invoice";
attachment.MimeType = "application/xml";
//Add attachment to PDF document
document.Attachments.Add(attachment);

//Creating the stream object
MemoryStream stream = new MemoryStream();
//Save the document into memory stream
document.Save(stream);
//If the position is not set to '0', then the PDF will be empty
stream.Position = 0;
//Close the document
document.Close(true);
//Defining the ContentType for PDF file
string contentType = "application/pdf";
//Define the file name
string fileName = "Zugferd.pdf";
//Creates a FileContentResult object by using the file contents, content type, and file name
return File(stream, contentType, fileName);
//Create ZUGFeRD invoice PDF document
PdfDocument document = new PdfDocument(PdfConformanceLevel.Pdf_A3B);
//Set ZUGFeRD conformance level
document.ZugferdConformanceLevel = ZugferdConformanceLevel.Basic;

//Creates an attachment 
Stream invoiceStream = typeof(MainPage).GetTypeInfo().Assembly.GetManifestResourceStream("Sample.Assets.Data.ZUGFeRD-invoice.xml");
PdfAttachment attachment = new PdfAttachment("ZUGFeRD-invoice.xml",invoiceStream);
attachment.Relationship = PdfAttachmentRelationship.Alternative;
attachment.ModificationDate = DateTime.Now;
attachment.Description = "ZUGFeRD-invoice";
attachment.MimeType = "application/xml";
//Add attachment to PDF document
document.Attachments.Add(attachment);

//Save the document into memory stream
MemoryStream stream = new MemoryStream();
document.Save(stream);
//Close the document
document.Close(true);
//Save the stream into PDF file
//The operation in Save under Xamarin varies between Windows Phone, Android, and iOS platforms. Refer to the PDF/Xamarin section for respective code samples
if (Device.RuntimePlatform == Device.UWP)
{
    Xamarin.Forms.DependencyService.Get<ISaveWindowsPhone>().Save("Zugferd.pdf", "application/pdf", stream);
}
else
{
    Xamarin.Forms.DependencyService.Get<ISave>().Save("Zugferd.pdf", "application/pdf", stream);
}

You can download a complete working sample from GitHub.

Extract ZUGFeRD invoice from PDF

You can extract the ZUGFeRD invoice using PdfAttachment class.

//Loads the PDF document
PdfLoadedDocument document = new PdfLoadedDocument("Sample.pdf");

//Iterates the attachments
foreach (PdfAttachment attachment in document.Attachments)
{
//Extracts the ZUGFeRD invoice attachment and saves it to the disk
FileStream s = new FileStream(attachment.FileName, FileMode.Create);
s.Write(attachment.Data, 0, attachment.Data.Length);
s.Dispose();
}

//Saves and closes the document
document.Save("Output.pdf");
document.Close(true);
'Loads the PDF document
Dim document As New PdfLoadedDocument("Sample.pdf")

'Iterates the attachments
For Each attachment As PdfAttachment In document.Attachments
'Extracts the attachment and saves it to the disk
Dim s As New FileStream(attachment.FileName, FileMode.Create)
s.Write(attachment.Data, 0, attachment.Data.Length)
s.Dispose()
Next

'Saves and closes the document
document.Save("Output.pdf")
document.Close(True)
//Create the file open picker
var picker = new FileOpenPicker();
picker.FileTypeFilter.Add(".pdf");
//Browse and chose the file
StorageFile file = await picker.PickSingleFileAsync();
//Creates an empty PDF loaded document instance
PdfLoadedDocument loadedDocument = new PdfLoadedDocument();
//Loads or opens an existing PDF document through Open method of PdfLoadedDocument class
await loadedDocument.OpenAsync(file);

//Iterates the attachments
foreach (PdfAttachment attachment in loadedDocument.Attachments)
{
//Extracts the ZUGFeRD invoice attachment and saves it to the disk
FileStream s = new FileStream(attachment.FileName, FileMode.Create);
s.Write(attachment.Data, 0, attachment.Data.Length);
s.Dispose();
}

//Save the PDF document to stream
MemoryStream stream = new MemoryStream();
await loadedDocument.SaveAsync(stream);
//Close the document
loadedDocument.Close(true);
//Save the stream as PDF document file in local machine. Refer to PDF/UWP section for respected code samples
Save(stream, "output.pdf");
//Load the PDF document
FileStream docStream = new FileStream("input.pdf", FileMode.Open, FileAccess.Read);
PdfLoadedDocument loadedDocument = new PdfLoadedDocument(docStream);

//Iterates the attachments
foreach (PdfAttachment attachment in loadedDocument.Attachments)
{
//Extracts the ZUGFeRD invoice attachment and saves it to the disk
FileStream s = new FileStream(attachment.FileName, FileMode.Create);
s.Write(attachment.Data, 0, attachment.Data.Length);
s.Dispose();
}

//Save the document into stream
MemoryStream stream = new MemoryStream();
loadedDocument.Save(stream);
stream.Position = 0;
//Closes the document
loadedDocument.Close(true);
//Defining the ContentType for pdf file
string contentType = "application/pdf";
//Define the file name
string fileName = "output.pdf";
//Creates a FileContentResult object by using the file contents, content type, and file name
return File(stream, contentType, fileName);
//Load the file as stream
Stream docStream = typeof(App).GetTypeInfo().Assembly.GetManifestResourceStream("Sample.Assets.input.pdf");
PdfLoadedDocument loadedDocument = new PdfLoadedDocument(docStream);

//Iterates the attachments
foreach (PdfAttachment attachment in loadedDocument.Attachments)
{
//Extracts the ZUGFeRD invoice attachment and saves it to the disk
FileStream s = new FileStream(attachment.FileName, FileMode.Create);
s.Write(attachment.Data, 0, attachment.Data.Length);
s.Dispose();
}

//Save the document into stream.
MemoryStream stream = new MemoryStream();
loadedDocument.Save(stream);
//Close the document.
loadedDocument.Close(true);
//Save the stream into pdf file
//The operation in Save under Xamarin varies between Windows Phone, Android and iOS platforms. Please refer PDF/Xamarin section for respective code samples
if (Device.OS == TargetPlatform.WinPhone || Device.OS == TargetPlatform.Windows)
{
    Xamarin.Forms.DependencyService.Get<ISaveWindowsPhone>().Save("output.pdf", "application/pdf", stream);
}
else
{
    Xamarin.Forms.DependencyService.Get<ISave>().Save("output.pdf", "application/pdf", stream);
}

You can download a complete working sample from GitHub.

Validating ZUGFeRD invoices using Adobe Acrobat

The ZUGFeRD invoices can be validated as follows:

  1. Conformance to the PDF/A-3b standard can be checked with Preflight function in Adobe acrobat.

    • Open the PDF and choose Tools > Print Production > Preflight in the right pane.

    • Select the PDF/A-3b profile and click the Analyze button.

PDF/A-3b Preflight Check image

* Check the result

PDF/A-3b Preflight Results image

  1. Conformance to the ZUGFeRD invoice can be checked as follows:

    • Open the PDF and choose Tools > Print Production > Preflight in the right pane.

    • Select the ZUGFeRD profile and click the Analyze button.

PDF ZUGFeRD Preflight Check image

* Check the result

PDF ZUGFeRD Preflight Results image