WPCubed GmbH
Wordprocessing and PDF components 

Create X-Factur (ZUGFeRD) with wPDF

The PDF creator wPDF is widely used to generate PDF invoices with attached XML data in the X-Factur specification.

 

To create the XML data you can use our open source tool WPXOrder.

 

Please note, you can validate the invoice here: https://portal3.gefeg.com/invoice/page/validation

 

To embed the XML code, you can use the code below. In this example, we previously created an invoice in text form using a WPTools TWPRichText Object. At the same time, we created the XML data using WPXOrder and saved it to a blob field. The code uses two variables which are defined by WPXOrder. We copied the value below.

 

Important: Call WPPDFExport1.AddXMPExtra before WPPDFExport1.BeginDoc!

 

procedure TForm1.btnCreatePDFClick(Sender: TObject);
var mem : TMemoryStream;
    lst : TStringList;
    s : string;
begin
   mem := TMemoryStream.Create;
   try
       WPPDFExport1.Info.Producer := 'wPDF - https://www.wpcubed.com';

       if FileExists(PDFName.Text) then
       begin
         if MessageDlg('PDF Datei existiert. ?berschreiben?',mtConfirmation, [mbYes, mbNo],0)=ID_NO then
         begin
           PDFName.SelectAll;
           PDFName.SetFocus;
           exit;
         end;
       end;

       WPPDFExport1.FileName := PDFName.Text;
       WPPDFExport1.AutoLaunch := false;
       WPPDFExport1.CompressStreamMethod := wpCompressFlate;
       WPPDFExport1.Source.ReformatAll(true);
       WPPDFExport1.Source.ReformatAll(true);
       WPPDFExport1.FontMode := wpEmbedCIDFonts;

       OrdersINVOICEXML.SaveToStream(mem);
       mem.Position := 0;

       if mem.Size>0 then
       begin
          WPPDFExport1.PDFAMode :=  wpdfaLevel3B;
          lst := TStringList.Create;
          s :=  Format( pdfa_xfactur_info, [pdfa_xfactur_filename,'EXTENDED'] );
          WPPDFExport1.AddXMPExtra( pdfa_xfactur_schema, s  );
          lst.Free;
       end;
       WPPDFExport1.BeginDoc;
       try
           if mem.Size>0 then
               WPPDFExport1.AddFileAttachment(pdfa_xfactur_filename, pdfa_xfactur_description, mem, 'text/xml', now, [wpDontCompressData])
           else
               ShowMessage('Keine XML Daten fuer X-Factur'' vorhanden, erzeuge regul?res PDF');
       WPPDFExport1.Print;
       finally
         WPPDFExport1.EndDoc;
       end;

       PDFName.SelectAll;
       PDFName.SetFocus;
   finally
     mem.Free;
   end;
end;

 
 

The code uses this constants defined by WPXOrder:

 

pdfa_xfactur_schema =
   '<rdf:li rdf:parseType="Resource">' + #10 +
                  '<pdfaSchema:schema>Factur-X PDFA Extension Schema</pdfaSchema:schema>' + #10 +
                  '<pdfaSchema:namespaceURI>urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0#</pdfaSchema:namespaceURI>' + #10 +
                  '<pdfaSchema:prefix>fx</pdfaSchema:prefix>' + #10 +
                  '<pdfaSchema:property>' + #10 +
                     '<rdf:Seq>' + #10 +
                        '<rdf:li rdf:parseType="Resource">' + #10 +
                           '<pdfaProperty:name>DocumentFileName</pdfaProperty:name>' + #10 +
                           '<pdfaProperty:valueType>Text</pdfaProperty:valueType>' + #10 +
                           '<pdfaProperty:category>external</pdfaProperty:category>' + #10 +
                           '<pdfaProperty:description>name of the embedded XML invoice file</pdfaProperty:description>' + #10 +
                        '</rdf:li>' + #10 +
                        '<rdf:li rdf:parseType="Resource">' + #10 +
                           '<pdfaProperty:name>DocumentType</pdfaProperty:name> ' + #10 +
                           '<pdfaProperty:valueType>Text</pdfaProperty:valueType>' + #10 +
                           '<pdfaProperty:category>external</pdfaProperty:category>' + #10 +
                           '<pdfaProperty:description>INVOICE</pdfaProperty:description>' + #10 +
                        '</rdf:li> ' + #10 +
                        '<rdf:li rdf:parseType="Resource"> ' + #10 +
                           '<pdfaProperty:name>Version</pdfaProperty:name>' + #10 +
                           '<pdfaProperty:valueType>Text</pdfaProperty:valueType>' + #10 +
                           '<pdfaProperty:category>external</pdfaProperty:category>' + #10 +
                           '<pdfaProperty:description>The actual version of the ZUGFeRD data</pdfaProperty:description>' + #10 +
                        '</rdf:li>' + #10 +
                        '<rdf:li rdf:parseType="Resource">' + #10 +
                           '<pdfaProperty:name>ConformanceLevel</pdfaProperty:name>' + #10 +
                           '<pdfaProperty:valueType>Text</pdfaProperty:valueType>' + #10 +
                           '<pdfaProperty:category>external</pdfaProperty:category>' + #10 +
                           '<pdfaProperty:description>The conformance level of the ZUGFeRD data</pdfaProperty:description>' + #10 +
                        '</rdf:li>' + #10 +
                     '</rdf:Seq> ' + #10 +
                  '</pdfaSchema:property>' + #10 +
               '</rdf:li>';


// First %s for filename, second %s for EXTENDED/BASIC
pdfa_xfactur_info =
   '<rdf:Description xmlns:fx="urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0#"' + #32 + 'rdf:about="">' + #10 +
   '<fx:DocumentType>INVOICE</fx:DocumentType>' + #10 +
   '<fx:DocumentFileName>%s</fx:DocumentFileName>' + #10 +
   '<fx:Version>1.0</fx:Version>' + #10 +
   '<fx:ConformanceLevel>%s</fx:ConformanceLevel></rdf:Description>' + #10;
        //      above are real values, should be dynamically created
pdfa_xfactur_LEVEL = 'EXTENDED';
pdfa_xfactur_filename = 'factur-x.xml';
pdfa_xfactur_description = 'Factur-X/ZUGFeRD Rechnung';