ZugferdInfoExt.cs
// // This code is part of Document Solutions for PDF demos. // Copyright (c) MESCIUS inc. All rights reserved. // using System; using System.IO; using System.Drawing; using System.Reflection; using System.Collections.Generic; using System.Linq; using System.Globalization; using GrapeCity.Documents.Pdf; using GrapeCity.Documents.Text; using s2industries.ZUGFeRD; using GCTEXT = GrapeCity.Documents.Text; using GCDRAW = GrapeCity.Documents.Drawing; namespace DsPdfWeb.Demos { // This sample demonstrates how to retrieve invoice data from a ZUGFeRD compliant XML attachment. // All ZUGFeRD data is printed to the PDF generated by this sample. // See ZugferdInfo for a similar sample that prints selected portions of the ZUGFeRD data. // The sample PDF invoice containing ZUGFeRD data which this sample uses as input // was generated by ZugferdInvoice. // // ZUGFeRD is a German e-invoicing standard based around PDF and XML file formats. // Its poised to change the way invoices are handled and can be used by any sort of business. // It will make invoice processing more efficient for senders and customers. // For details please see www.ferd-net.de. // // This sample uses the ZUGFeRD-csharp package // to parse the ZUGFeRD-compatible XML that is attached to the invoice. public class ZugferdInfoExt { public void CreatePDF(Stream stream) { // The sample invoice with ZUGFeRD data: var invoicePdf = Path.Combine("Resources", "PDFs", "zugferd-invoice.pdf"); // Output document: var doc = new GcPdfDocument(); using (FileStream fs = File.OpenRead(invoicePdf)) { // Load the ZUGFeRD compliant invoice PDF: var invoice = new GcPdfDocument(); invoice.Load(fs); // 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); var tl = new TextLayout(72); tl.MaxWidth = doc.PageSize.Width; tl.MaxHeight = doc.PageSize.Height; tl.MarginAll = tl.Resolution; tl.DefaultTabStops = 24; // Recursively render all InvoiceDescriptor properties to text layout: tl.AppendLine($"{nameof(InvoiceDescriptor)}:", _tfStrong); RenderProperties(descriptor, tl, 1); // Write text layout to output PDF tl.PerformLayout(true); var to = new TextSplitOptions(tl); while (true) { var splitResult = tl.Split(to, out TextLayout rest); doc.Pages.Add().Graphics.DrawTextLayout(tl, PointF.Empty); if (splitResult != SplitResult.Split) break; tl = rest; } // Done: doc.Save(stream); } } } } // Recursively print all source's properties to text layout: private static void RenderProperties(object source, TextLayout tl, int level) { if (source == null) return; var props = source.GetType().GetProperties(); foreach (var prop in props) RenderProperty(prop, source, tl, level); } // Text formats for output: private static readonly TextFormat _tfData = new TextFormat() { Font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "NotoSans-Regular.ttf")), FontSize = 12 }; private static readonly TextFormat _tfStrong = new TextFormat(_tfData) { Font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "NotoSans-Bold.ttf")) }; private static readonly TextFormat _tfLabels = new TextFormat(_tfData) { Font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "NotoSans-Italic.ttf")), FontSize = 11 }; // Print a property: private static void RenderProperty(PropertyInfo property, object parent, TextLayout tl, int level) { var space = string.Empty; for (int i = 0; i < level; ++i) space += "\t"; var name = property.Name; var value = property.GetValue(parent, null); if (value == null) { tl.Append(space, _tfLabels); tl.AppendLine($"{name}:", _tfLabels); } else if (value.GetType().IsValueType || value is string) { tl.Append(space, _tfLabels); tl.Append($"{name}: ", _tfLabels); tl.AppendLine(string.Format(CultureInfo.GetCultureInfo("en-US"), "{0}", value), _tfData); } else { if (value is IEnumerable<object> collection) { var index = 0; foreach (var item in collection) { tl.Append(space, _tfLabels); tl.AppendLine($"Collection item {name} [{index++}]:", _tfStrong); RenderProperties(item, tl, level + 1); } } else { tl.Append(space, _tfLabels); tl.AppendLine($"Container {name}:", _tfStrong); RenderProperties(value, tl, level + 1); } } } } }