Print extended ZUGFeRD info from a ZUGFeRD compliant invoice

PDF TIFF SVG JPG C# VB
ZugferdInfoExt.cs
  1. //
  2. // This code is part of Document Solutions for PDF demos.
  3. // Copyright (c) MESCIUS inc. All rights reserved.
  4. //
  5. using System;
  6. using System.IO;
  7. using System.Drawing;
  8. using System.Reflection;
  9. using System.Collections.Generic;
  10. using System.Linq;
  11. using System.Globalization;
  12. using GrapeCity.Documents.Pdf;
  13. using GrapeCity.Documents.Text;
  14. using s2industries.ZUGFeRD;
  15. using GCTEXT = GrapeCity.Documents.Text;
  16. using GCDRAW = GrapeCity.Documents.Drawing;
  17.  
  18. namespace DsPdfWeb.Demos
  19. {
  20. // This sample demonstrates how to retrieve invoice data from a ZUGFeRD compliant XML attachment.
  21. // All ZUGFeRD data is printed to the PDF generated by this sample.
  22. // See ZugferdInfo for a similar sample that prints selected portions of the ZUGFeRD data.
  23.  
  24. // The sample PDF invoice containing ZUGFeRD data which this sample uses as input
  25. // was generated by ZugferdInvoice.
  26. //
  27. // ZUGFeRD is a German e-invoicing standard based around PDF and XML file formats.
  28. // Its poised to change the way invoices are handled and can be used by any sort of business.
  29. // It will make invoice processing more efficient for senders and customers.
  30. // For details please see What is ZUGFeRD?.
  31. //
  32. // This sample uses the ZUGFeRD-csharp package
  33. // to parse the ZUGFeRD-compatible XML that is attached to the invoice.
  34. public class ZugferdInfoExt
  35. {
  36. public void CreatePDF(Stream stream)
  37. {
  38. // The sample invoice with ZUGFeRD data:
  39. var invoicePdf = Path.Combine("Resources", "PDFs", "zugferd-invoice.pdf");
  40.  
  41. // Output document:
  42. var doc = new GcPdfDocument();
  43. using (FileStream fs = File.OpenRead(invoicePdf))
  44. {
  45. // Load the ZUGFeRD compliant invoice PDF:
  46. var invoice = new GcPdfDocument();
  47. invoice.Load(fs);
  48.  
  49. // Get the ZUGFeRD attachment from the invoice by the ZUGFeRD 1.x standard file name:
  50. var attachment = invoice.EmbeddedFiles.Values.FirstOrDefault(it => it.File.FileName == "ZUGFeRD-invoice.xml");
  51. if (attachment != null)
  52. {
  53. using (var xmlstream = attachment.GetStream())
  54. {
  55. // Load the invoice descriptor:
  56. var descriptor = InvoiceDescriptor.Load(xmlstream);
  57.  
  58. var tl = new TextLayout(72);
  59. tl.MaxWidth = doc.PageSize.Width;
  60. tl.MaxHeight = doc.PageSize.Height;
  61. tl.MarginAll = tl.Resolution;
  62. tl.DefaultTabStops = 24;
  63.  
  64. // Recursively render all InvoiceDescriptor properties to text layout:
  65. tl.AppendLine($"{nameof(InvoiceDescriptor)}:", _tfStrong);
  66. RenderProperties(descriptor, tl, 1);
  67.  
  68. // Write text layout to output PDF
  69. tl.PerformLayout(true);
  70. var to = new TextSplitOptions(tl);
  71. while (true)
  72. {
  73. var splitResult = tl.Split(to, out TextLayout rest);
  74. doc.Pages.Add().Graphics.DrawTextLayout(tl, PointF.Empty);
  75. if (splitResult != SplitResult.Split)
  76. break;
  77. tl = rest;
  78. }
  79. // Done:
  80. doc.Save(stream);
  81. }
  82. }
  83. }
  84. }
  85.  
  86. // Recursively print all source's properties to text layout:
  87. private static void RenderProperties(object source, TextLayout tl, int level)
  88. {
  89. if (source == null)
  90. return;
  91.  
  92. var props = source.GetType().GetProperties();
  93. foreach (var prop in props)
  94. RenderProperty(prop, source, tl, level);
  95. }
  96.  
  97. // Text formats for output:
  98. private static readonly TextFormat _tfData = new TextFormat() {
  99. Font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "segoeui.ttf")),
  100. FontSize = 12
  101. };
  102. private static readonly TextFormat _tfStrong = new TextFormat(_tfData) {
  103. Font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "segoeuib.ttf"))
  104. };
  105. private static readonly TextFormat _tfLabels = new TextFormat(_tfData) {
  106. Font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "segoeuii.ttf")),
  107. FontSize = 11
  108. };
  109.  
  110. // Print a property:
  111. private static void RenderProperty(PropertyInfo property, object parent, TextLayout tl, int level)
  112. {
  113. var space = string.Empty;
  114. for (int i = 0; i < level; ++i)
  115. space += "\t";
  116. var name = property.Name;
  117. var value = property.GetValue(parent, null);
  118. if (value == null)
  119. {
  120. tl.Append(space, _tfLabels);
  121. tl.AppendLine($"{name}:", _tfLabels);
  122. }
  123. else if (value.GetType().IsValueType || value is string)
  124. {
  125. tl.Append(space, _tfLabels);
  126. tl.Append($"{name}: ", _tfLabels);
  127. tl.AppendLine(string.Format(CultureInfo.GetCultureInfo("en-US"), "{0}", value), _tfData);
  128. }
  129. else
  130. {
  131. if (value is IEnumerable<object> collection)
  132. {
  133. var index = 0;
  134. foreach (var item in collection)
  135. {
  136. tl.Append(space, _tfLabels);
  137. tl.AppendLine($"Collection item {name} [{index++}]:", _tfStrong);
  138. RenderProperties(item, tl, level + 1);
  139. }
  140. }
  141. else
  142. {
  143. tl.Append(space, _tfLabels);
  144. tl.AppendLine($"Container {name}:", _tfStrong);
  145. RenderProperties(value, tl, level + 1);
  146. }
  147. }
  148. }
  149. }
  150. }
  151.