//
// 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 What is ZUGFeRD?.
//
// 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", "segoeui.ttf")),
FontSize = 12
};
private static readonly TextFormat _tfStrong = new TextFormat(_tfData) {
Font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "segoeuib.ttf"))
};
private static readonly TextFormat _tfLabels = new TextFormat(_tfData) {
Font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "segoeuii.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);
}
}
}
}
}