DataTplCultureOut.cs
//
// This code is part of Document Solutions for Word demos.
// Copyright (c) MESCIUS inc. All rights reserved.
//
using System;
using System.IO;
using System.Drawing;
using System.Collections.Generic;
using System.Linq;
using System.Globalization;
using System.Xml;
using GrapeCity.Documents.Word;

namespace DsWordWeb.Demos
{
    // This example shows how to format data from different data sources
    // in a culture-aware way by associating the correct culture with
    // each data source.
    public class DataTplCultureOut
    {
        public GcWordDocument CreateDocx()
        {
            // USD to EUR conversion rate:
            if (ExchangeOperations.ExchangeRateToEuro.TryGetValue("USD", out decimal usd2eur))
            {
                // Define the 'dsEn' data source to contain random amounts in US dollars:
                var dsEn = new List<decimal>();
                var rnd = Util.NewRandom();
                for (int i = 0; i < rnd.Next(5, 15); ++i)
                    dsEn.Add((decimal)(rnd.Next(10, 1000) / 10f));

                // The 'dsFr' data source will contain same amounts converted to EUR:
                var dsFr = new List<decimal>();
                foreach (var d in dsEn)
                    dsFr.Add(d / usd2eur);

                // Create Word document
                var doc = new GcWordDocument();

                // Add the two data sources, associating a proper culture with each data source:
                doc.DataTemplate.DataSources.Add("dsEn", dsEn, CultureInfo.GetCultureInfo("en-US"));
                doc.DataTemplate.DataSources.Add("dsFr", dsFr, CultureInfo.GetCultureInfo("fr-FR"));

                // The template will print two columns of data, the amounts from 'dsEn' in the first column,
                // the corresponding amounts from 'dsFr' in the second one. Because we specified correct
                // cultures for the two data sources, the culture-aware currency format will format
                // the data appropriately:
                doc.Body.Paragraphs.Add("{{#dsEn}:seq(x)}{{#dsFr}:follow(x)}{{dsEn.value}:format(C)} is approximately {{dsFr.value}:format(C)}{{/dsFr}}{{/dsEn}}");

                // Process the template:
                doc.DataTemplate.Process(CultureInfo.GetCultureInfo("en-US"));

                // Done:
                return doc;
            }
            else
            {
                var doc = new GcWordDocument();
                doc.Body.Paragraphs.Add("Could not get exchange rates from www.ecb.int, please try again later.", doc.Styles[BuiltInStyleId.Heading1]);
                return doc;
            }
        }

        // From https://docs.microsoft.com/en-us/answers/questions/785478/api-for-currency-exchange-rate.html:
        internal static class ExchangeOperations
        {
            public static readonly Dictionary<string, decimal> ExchangeRateToEuro = new Dictionary<string, decimal>();
            public static List<string> FromCurrency = new List<string>();
            public static List<string> ToCurrency = new List<string>();

            static ExchangeOperations()
            {
                LoadRates();
            }

            public static void LoadRates()
            {
                try
                {
                    XmlDocument xmlDoc = new XmlDocument();
                    xmlDoc.Load("http://www.ecb.int/stats/eurofxref/eurofxref-daily.xml");

                    foreach (XmlNode node in xmlDoc.DocumentElement.ChildNodes[2].ChildNodes[0].ChildNodes)
                    {
                        ExchangeRateToEuro.Add(node.Attributes["currency"].Value, decimal.Parse(node.Attributes["rate"].Value));
                        FromCurrency.Add(node.Attributes["currency"].Value);
                        ToCurrency.Add(node.Attributes["currency"].Value);
                    }
                }
                catch
                {
                    // Eat errors, ExchangeRateToEuro will stay empty.
                }
            }
        }
    }
}