Set Result in FieldChar using Open XML SDK

987 views Asked by At

I am working on an application that uses Microsoft Word files as a template to generate documents. I use Merge fields to get data into my documents.

A SimpleField can have its result set fairly easy:

SimpleField f = doc.MainDocumentPart.Document.Body.Descendants<SimpleField>().First();
f.RemoveAllChildren();
f.Append(new Run(new Text("somevalue")));

but, when a field is styled in Word, it is save as a FieldChar, which is a little more complex. The above method doesn't work there, because the result is not a child, but a sibling.

So, basically the question is: how can I set the result of a field (any type) using Open XML SDK ?

1

There are 1 answers

0
Taterhead On

The simplest way to do this is with a string replace. Since you have control over the template, put a unique string in the Merge Field. Regardless if the Merge field is formatted or not, the text you need to replace will be in a Text element.

Then search all Text descendants of the Body of the WordprocessingDocument and do a string replace.

Here is a snip of the Fax Merge Document template. I have changed the Business Phone Merge field to «XXXXBusiness PhoneXXXX» and formatted it differently:

enter image description here

I wrote an extension method for the Body class to do a replace like so:

using System.Linq;
using DocumentFormat.OpenXml.Wordprocessing;
namespace OxmlApp
{

    static class WordprocessingExtensions
    {
        public static void ReplaceTextInTextDescendants(this Body body, string oldText, string newText)
        {
            foreach (var textItem in body.Descendants<Text>().Where(textItem => textItem.Text.Contains(oldText)))
            {
                textItem.Text = textItem.Text.Replace(oldText, newText);
            }
        }
    }
}

Once this is in place, your code is a one-liner after you open the document:

using (var doc = WordprocessingDocument.Open(openFileDialog.FileName, true))
{
    doc.MainDocumentPart.Document.Body.ReplaceTextInTextDescendants("«XXXXBusiness PhoneXXXX»","212-867-5309");
}

The result is seen here:

enter image description here

done!