Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you change the content of a content control in Word 2007 with OpenXml SDK 2.0?

About to go mad with this problem. I'm sure it's so simple I'm just missing it, but I cannot for the life of me find out how to change the content of a content control in Word 2007 with the OpenXml SDK v2.0 in C#.

I have created a Word document with a plain text content control. The tag for this control is "FirstName". In code, I'd like to open up the Word document, find this content control, and change the content without losing the formatting.

The solution I finally got to work involved finding the content control, inserting a run after it, then removing the content control as such:

using (WordprocessingDocument wordProcessingDocument = WordprocessingDocument.Open(filePath, true)) {
MainDocumentPart mainDocumentPart = wordProcessingDocument.MainDocumentPart;
SdtRun sdtRun = mainDocumentPart.Document.Descendants<SdtRun>()
 .Where(run => run.SdtProperties.GetFirstChild<Tag>().Val == "FirstName").Single();

if (sdtRun != null) {
 sdtRun.Parent.InsertAfter(new Run(new Text("John")), sdtRun);
 sdtRun.Remove();
}

This does change the text, but I lose all formatting. Does anyone know how I can do this?

like image 398
Jason Avatar asked Jan 15 '10 23:01

Jason


People also ask

How do you do content control in Word?

View the Developer tab to add or change content controlsTo add a control, click in the document where you want to add it, and then click the control you want to add on the Design tab. To set properties on a control or change an existing control, on the Developer tab, in the Controls group, click Properties.

How do I use rich text content control in Word?

Under Insert controls, click Rich Text Box. To specify the type of rich text that users can enter, double-click the rich text box that was inserted on the form template, click the Display tab, and then select or clear the check boxes under Available formatting.

What is a rich text content control?

Rich Text. A rich text control can contain custom formatted text or other items, such as tables, pictures, or other content controls. Before Word 2013, rich text controls cannot be bound to an XML data node. Plain Text. A plain text content control is limited to plain text in a single or multiple paragraphs.


2 Answers

I found a better way to do the above using http://wiki.threewill.com/display/enterprise/SharePoint+and+Open+XML#SharePointandOpenXML-UsingWord2007ContentControls as a reference. Your results may vary but I think this will get you off to a good start:

using (WordprocessingDocument wordprocessingDocument = WordprocessingDocument.Open(filePath, true)) {
    var sdtRuns = mainDocumentPart.Document.Descendants<SdtRun>()
        .Where(run => run.SdtProperties.GetFirstChild<Tag>().Val.Value == contentControlTagValue);

    foreach (SdtRun sdtRun in sdtRuns) {
        sdtRun.Descendants<Text>().First().Text = replacementText;
    }

    wordprocessingDocument.MainDocumentPart.Document.Save();
}

I think the above will only work for Plain Text content controls. Unfortunately, it doesn't get rid of the content control in the final document. If I get that working I'll post it.

http://msdn.microsoft.com/en-us/library/cc197932.aspx is also a good reference if you want to find a rich text content control. This one talks about adding rows to a table that was placed in a rich text content control.

like image 95
Jason Avatar answered Nov 12 '22 04:11

Jason


Your first approach to remove the sdtRun and adding a new one will obviously remove the formatting because you are only adding a Run but not the RunStyle. To preserve the formatting you should create run elements like

new Run( new RunProperties(new RunStyle(){ Val = "MyStyle" }),
                            new Text("Replacement Text"));

Your second approach to replace all Decendants<Text> will work for Plain Text Content Control only because a Rich Text Content Control does not have SdtRun element. Rich Text Content Control is SdtBlock with SdtContent elements. A rich text content control can have multiple paragraphs, multiple Runs and multiple Texts. So your code, sdtRun.Descendants<Text>().First().Text = replacementText, will be flawed for a Rich Text Content Control. There is no one line code to replace the entire text of a rich content control and yet preserve all the formatting.

I did not understand what you mean by "it doesn't get rid of the content control in the final document"? I thought your requirement here is to change the text (content) only by preserving the content control and the formatting.

like image 45
Bijay Kusle Avatar answered Nov 12 '22 03:11

Bijay Kusle