Tejana

Using Microsoft Word in LightSwitch C#

Posted in .net, LightSwitch, Microsoft, Software, Visual Studio by tejana on April 25, 2011

C# version of Beth Massi’s Sharing the goodness that is VB.

The time span between blog posts represents a ground zero reinstallation of Windows. It does a body good. My boot drive is solid state. For something to post I have a translation of Beth Massi’s visual basic for those of us that like C#. This is a case where automated translation is no help. The following is a class added to a C# lightswitch project in the Client project under UserCode, named PrintClass.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices.Automation;
using System.Xml.Linq;

namespace LightSwitchApplication

{
    public class PrintClass
    {
        public static readonly PrintClass globalMethods = new PrintClass();

        private PrintClass()
        { Initialize(); }

        public void Initialize()
        { }

        public void RunCustomerReportFixedTemplate(Customer customer)
        {
            try
            {
                if (AutomationFactory.IsAvailable)
                {
                    //create xml element customer: xmlTree 
                    XElement xmlTree = new XElement("customer");
                    foreach (Microsoft.LightSwitch.Details.IProperty prop in customer.Details.Properties.All())
                    {
                        xmlTree.Add(new XElement(prop.Name.ToLower(), prop.Value));
                    }
                    //Load CustomerDetails.docx and replace existing xml node "customer[1]"
                    //with xml element customer: xmlTree, above
                    using (dynamic word = AutomationFactory.CreateObject("Word.Application"))
                    {
                        System.Windows.Resources.StreamResourceInfo resourceInfo = System.Windows.Application.GetResourceStream(new Uri("CustomerDetails.docx", UriKind.Relative));
                        string fileName = CopyStreamToTempFile(resourceInfo.Stream, ".docx");
                        dynamic doc = word.Documents.Open(fileName);
                        //here we get existing part from document, it must exist in document
                        //RunCustomerReportDynamicTemplate() below creates a new part in document
                        dynamic customXMLPart = doc.CustomXMLParts("urn:microsoft:ordermanager:customer");
                        //select top node
                        dynamic all = customXMLPart.SelectSingleNode("//*");
                        //select target
                        dynamic replaceNode = customXMLPart.SelectSingleNode(@"/ns0:root[1]/customer[1]");
                        //insert
                        all.ReplaceChildSubTree(xmlTree.ToString(), replaceNode);
                        //show
                        word.Visible = true;
                    }
                }
            }

            catch (Exception ex)
            {
                throw new InvalidOperationException("Failed to create customer report,", ex);
            }
        }

        public void RunCustomerReportDynamicTemplate(Customer cust)
        {
            try
            {
                if (AutomationFactory.IsAvailable)
                {
                    //load template for word
                    dynamic templateFile = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) +
                        @"\Reports\CustomerDetails.docx";

                    //with name space ns0
                    XNamespace ns0 = "urn:microsoft:ordermanager:customer";

                    //create "customer" node in xmlTree
                    XElement xmlTree = new XElement("customer");
                    foreach (Microsoft.LightSwitch.Details.IProperty prop in cust.Details.Properties.All())
                    {
                        xmlTree.Add(new XElement(prop.Name.ToLower(), prop.Value));
                    }

                    //create "root", with sub node xmlTree, "customer"
                    XElement root = new XElement(
                        ns0 + "root", new XAttribute(XNamespace.Xmlns + "ns0", "urn:microsoft:ordermanager:customer"), xmlTree);

                   //copy template to temp, open temp, insert "root",
                    using (dynamic word = AutomationFactory.CreateObject("Word.Application"))
                    {
                        string tempFile = GetTempFileName(".docx");
                        System.IO.File.Copy(templateFile, tempFile);
                        dynamic doc = word.Documents.Open(tempFile);
                        dynamic customXMLPart = doc.CustomXMLParts.Add(root.ToString());
                        //set bindings
                        for (int i = 1; i < doc.ContentControls.Count + 1; i++)
                        {
                            dynamic ctrl = doc.ContentControls[i];
                            if (!ctrl.XMLMApping.IsMapped)
                            {
                                ctrl.XMLMapping.SetMapping("/ns0:root[1]/customer[1]/" + ctrl.Title.ToLower(),
                                    @"xmlns:ns0=""urn:microsoft:ordermanager:customer""", customXMLPart);
                            }
                        }
                        //show
                        word.Visible = true;
                    }
                }
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException("Failed to create customer report,", ex);
            }          
        }

        private string CopyStreamToTempFile(System.IO.Stream stream, string ext)
        {
            string path = GetTempFileName(ext);
            dynamic file = System.IO.File.Create(path);
            file.Close();
            System.IO.FileStream  fileStream = System.IO.File.Open(path,
                                                    System.IO.FileMode.OpenOrCreate,
                                                System.IO.FileAccess.Write,
                                                    System.IO.FileShare.None);
           byte[] buffer = new byte[stream.Length];
           stream.Read(buffer, 0, (int)stream.Length);
           fileStream.Write(buffer, 0, buffer.Length);
           fileStream.Close();
                return path;
        }

        private string GetTempFileName(string ext)
        {
            string path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Reports";
            if (!System.IO.Directory.Exists(path))
            {
                System.IO.Directory.CreateDirectory(path);
            }
            string filename = Guid.NewGuid().ToString() + ext;
            path = System.IO.Path.Combine(path, filename);
            return path;
        }
    }
}

 

The calling program includes:

partial void Print_Execute()
       {
           // Write your code here.
           //PrintClass.globalMethods.RunCustomerReportFixedTemplate(this.Customer);
           PrintClass.globalMethods.RunCustomerReportDynamicTemplate(this.Customer);
       }

The debug mode of visual studio 2010 is less helpful with the C# than the Visual Basic. The Word Content Control Toolkit is essential. Place a “CustomerDetails.docx” containing a Custom XML part,  in the Client project as content, copy newer and a “CustomerDetails.docx” without a Custom XML part in MyDocuments\Reports. Beth Massi put the former in ClientGenerated project directory, the latter in the project directory LightSwitchReportSample.  To understand this post, or download VB code  …  See Beth’s:

Using Microsoft Word to Create Reports For LightSwitch (or Silverlight)
Advertisements

One Response

Subscribe to comments with RSS.

  1. cZac said, on June 23, 2011 at 2:20 am

    how can you, once the user selects the print button, create a modal to read multiple files in a folder, display to the user as a checkboxlist to select only the documents to populate and print?


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: