Programmatically convert Rich Text data from InfoPath to Word DOCX

Applies to: InfoPath 2007

Learn how to use the WindowsBase DLL and the System.IO.Packaging namespace to export the contents of a Rich Text Box field on an InfoPath form to a Word 2007 document.

ADVERTISEMENTS

Problem

You have an InfoPath form with a Rich Text Box control on it. You want to be able to take the contents of the Rich Text Box control and display it in a Word 2007 document (DOCX file).

Solution

Use an altChunk node in the Word 2007 DOCX file to be able to import and display the XHTML contents of an InfoPath Rich Text Box control in a Word 2007 document.

This solution is based on an InfoPath newsgroup thread started by Joe Gannon. Joe researched much of the difficult stuff in this solution hoping to make your life easier, should you want to take the route he took. So I'd hereby like to thank Joe Gannon for his efforts and his contribution to this article and to the InfoPath community.

Discussion

To be able to include an altChunk node for XHTML data in a Word 2007, you must do the following:

  1. Add the following content type to the [Content_Types].xml file in the root folder of the DOCX file:

    <Default Extension="htm" ContentType="application/xhtml+xml"/>

  2. Add an altChunk node to the DOCX file. The altChunk node should look something like the following:

    <w:altChunk r:id="rAltChunkId1"
    xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
    xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
    />

    where rAltChunkId1 is the identifier for the node. This identifier should be referenced in the relationships XML file of the word document.

  3. Add the following relationship to the document.xml.rels file located in the /word/_rels folder:

    <Relationship Id="rAltChunkId1"
    Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/aFChunk"
    Target="/rtfContents.txt"
    TargetMode="Internal"
    />

  4. Add a text file containing the XHTML data in the /word folder in the DOCX file.

Note: If you are unsure how to modify the DOCX file, follow the instructions on how to manually change a DOCX file.

The solution presented in this article programmatically adds an altChunk to a DOCX file, before importing the XHTML contents of the Rich Text Box. If you need to control where the contents of the Rich Text Box should appear in the DOCX file, you will have to add the altChunk manually to the DOCX file and remove the code that adds the altChunk node described in the instructions below.

To achieve this functionality:

  1. In InfoPath, create a new Blank form template.
  2. Add a Rich Text Box control and Button control to the InfoPath form template.
  3. Name the Rich Text Box control rtfField.
  4. Double-click the Button control to open its Properties dialog box.
  5. On the Button Properties dialog box, click Edit Form Code.
  6. In Microsoft Visual Studio Tools for Applications, go to the Project Explorer window, click the References node, select Add Reference from the context menu, and add a reference to the WindowsBase DLL that comes with the Microsoft .NET Framework 3.0.
  7. Add the following namespaces to the InfoPath form's code file:

    using System.IO;
    using System.IO.Packaging;
    using System.Diagnostics;

  8. Add the following C# code to the Clicked event handler for the button:

    // Define the location of the template Word document
    // and the new Word document to be created
    string wordTemplateFilePath = @"C:\Template.docx";
    string wordPrintFilePath = @"C:\MyNewWordDocument.docx";

    // Define the Open Xml schemas
    string mainSchema =
    "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
    string relSchema =
    "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
    string aFChunkSchema =
    "http://schemas.openxmlformats.org/officeDocument/2006/relationships/aFChunk";

    // Copy the template to create a new docx file
    File.Copy(wordTemplateFilePath, wordPrintFilePath, true);

    // Crack open the package
    Package packWordPrint =
    Package.Open(wordPrintFilePath,
    FileMode.Open, FileAccess.ReadWrite);

    Uri uri = new Uri("/word/document.xml", UriKind.Relative);
    PackagePart documentPart = packWordPrint.GetPart(uri);

    // Retrieve the XML for document.xml
    XmlDocument wordDoc = new XmlDocument();
    using (Stream s = documentPart.GetStream())
    wordDoc.Load(s);

    // Create an XmlNamespaceManager for XPath queries
    XmlNamespaceManager nsMgr =
    new XmlNamespaceManager(wordDoc.NameTable);
    nsMgr.AddNamespace("w", mainSchema);

    // Find the w:body tag and add an altChunk node to it
    string altChunkId = "rAltChunkId1";
    XmlNode bodyNode = wordDoc.SelectSingleNode("//w:body", nsMgr);
    XmlNode altNode = wordDoc.CreateElement("w:altChunk", mainSchema);
    XmlAttribute attr = wordDoc.CreateAttribute("r:id", relSchema);
    attr.Value = altChunkId;
    altNode.Attributes.Append(attr);
    bodyNode.AppendChild(altNode);

    using (StreamWriter sw = new StreamWriter(
    documentPart.GetStream(FileMode.Create, FileAccess.Write)))
    {
    wordDoc.Save(sw);
    sw.Close();
    packWordPrint.Flush();
    }

    // Retrieve XHTML data from the RTF control
    XPathNavigator nav = MainDataSource.CreateNavigator();
    string rtfValue =
    nav.SelectSingleNode("//my:rtfField", NamespaceManager).InnerXml;

    // Add HTML tags to the RTF
    rtfValue = "<html>" + rtfValue + "</html>";

    // Create the aFChunk text file
    Uri rtfUri = new Uri("/word/rtfContents.htm", UriKind.Relative);

    // Add the content type for the RTF data to [Content_Types].xml
    // in the package
    PackagePart altChunkpart =
    packWordPrint.CreatePart(rtfUri, "application/xhtml+xml");

    // Write the RTF contents to the text file
    using (Stream fs = altChunkpart.GetStream())
    {
    using (StreamWriter sw = new StreamWriter(fs))
    {
    sw.WriteLine(rtfValue);
    sw.Close();
    }
    fs.Close();
    }

    // Add the aFChunk relationship to the word part, located
    // in /word/_rels/document.xml.rels
    documentPart.CreateRelationship(
    rtfUri, TargetMode.Internal, aFChunkSchema, altChunkId);

    // Write changes to the package
    packWordPrint.Flush();

    // Close the package
    packWordPrint.Close();

    // Open the new docx file in Word 2007
    Process proc = new Process();
    proc.EnableRaisingEvents = false;
    proc.StartInfo.FileName = "winword";
    proc.StartInfo.Arguments = wordPrintFilePath;
    proc.Start();

  9. Give the InfoPath form template full trust and sign it with a digital certificate.

You should now have a fully functional InfoPath form so that when type text into the Rich Text Box field and then click the button, the XHTML contents of the Rich Text field will be exported and displayed in a Word 2007 document.

 


Related InfoPath Articles:

 

Copyright: This article may not be used on web sites (whether personal or otherwise), copied, disseminated, altered, printed, published, broadcasted, or reproduced in any way without an expressed written consent. The techniques demonstrated in this article may be used within any Microsoft InfoPath project. This article is provided without any warranties. Copyright for this article is non-transferrable and remains with the author.

InfoPath 2013 Cookbook: 121 Codeless Recipes for Beginners

InfoPath 2013 Cookbook 2: 121 Codeless Recipes for SharePoint 2013

InfoPath 2010 Cookbook: 101 Codeless Recipes for Beginners

InfoPath 2010 Cookbook 2: 101 Codeless Recipes for SharePoint 2010

InfoPath 2010 Cookbook 3: 101 Code Recipes for C# Developers

InfoPath 2010 Cookbook 4: 101 Code Recipes for VB Developers

InfoPath 2010 Cookbook 5: Integrating InfoPath with Excel and Excel Services