问题
I am using open XML(Microsoft Word - .docx) as a file template to automatically generate other documents. In the template document I have defined content controls, and I have written code to replace content in these content controls.
The content is replaced and the documents are generated, but I am struggling with keeping the style. In Word, when inspecting properties of the content control, I have checked the checbox for "Use a style to format text into the empty control: style", and also checked for "Remove content controls when content are edited". This doesn't seem to have any impact when documents are generated by code.

private static void ReplaceTags(MainDocumentPart mainPart, string tagName, string tagValue)
{
//grab all the tag fields
var tagFields = mainPart.Document.Body.Descendants<SdtBlock>().Where
(r => r.SdtProperties.GetFirstChild<Tag>().Val == tagName);
foreach (var field in tagFields)
{
//remove all paragraphs from the content block
field.SdtContentBlock.RemoveAllChildren<DocumentFormat.OpenXml.Wordprocessing.Paragraph>();
//create a new paragraph containing a run and a text element
var newParagraph = new DocumentFormat.OpenXml.Wordprocessing.Paragraph();
var newRun = new DocumentFormat.OpenXml.Wordprocessing.Run();
var newText = new DocumentFormat.OpenXml.Wordprocessing.Text(tagValue);
newRun.Append(newText);
newParagraph.Append(newRun);
//add the new paragraph to the content block
field.SdtContentBlock.Append(newParagraph);
}
}
回答1:
When you assign a style to the content control a new RunProperties
element is added under the SdtProperties
. For example, if I assign a new style called Style1
I can see the following XML is generated:
<w:sdt>
<w:sdtPr>
<w:rPr>
<w:rStyle w:val="Style1" />
</w:rPr>
<w:alias w:val="LastName" />
<w:tag w:val="LastName" />
....
You need to grab this value and assign it to the new Paragraph
you are creating, add the Paragraph
at the same level as the SdtBlock
and then remove the SdtBlock
which is what Word does when you select the "Remove content control when contents are edited" option. The RunProperties
are the <w:rPr>
element. The following should do what you're after.
private static void ReplaceTags(MainDocumentPart mainPart, string tagName, string tagValue)
{
//grab all the tag fields
IEnumerable<SdtBlock> tagFields = mainPart.Document.Body.Descendants<SdtBlock>().Where
(r => r.SdtProperties.GetFirstChild<Tag>().Val == tagName);
foreach (var field in tagFields)
{
//grab the RunProperties from the SdtBlcok
RunProperties runProp = field.SdtProperties.GetFirstChild<RunProperties>();
//create a new paragraph containing a run and a text element
Paragraph newParagraph = new Paragraph();
Run newRun = new Run();
if (runProp != null)
{
//assign the RunProperties to our new run
newRun.Append(runProp.CloneNode(true));
}
Text newText = new Text(tagValue);
newRun.Append(newText);
newParagraph.Append(newRun);
//insert the new paragraph before the field we're going to remove
field.Parent.InsertBefore(newParagraph, field);
//remove the SdtBlock to mimic the Remove content control when contents are edited option
field.Remove();
}
}
来源:https://stackoverflow.com/questions/29092858/how-to-keep-style-on-open-xml-documents