Replacing Content Controls in OpenXML

2019-03-09 12:39发布

问题:

I need something as a placeholder. I at first looked to Content Control as a solution but I'm having some problems with it.

I then looked into adding CustomXML to the .docx but turned away from that because of the i4i lawsuit.

Then I decided I would just plain change the text of the Content Control through OpenXML SDK 2.0 but even if it's so marked the Content Control doesn't go away. I guess that it doesn't know that the text changed unless it happens inside word.

I could perhaps just remove the CC and place text instead but I'm afraid of problems with format and styles it could bring and also it would kind of defy the purpose of the Content Control.

Then I started wondering if I could define my own placeholders that Word could recognize. Through Building blocks perhaps. It doesn't have to do anything except be easy to find using OpenXML and somehow taggable so I know what to replace it with. I'm not really sure what can be done with Building Blocks but I'm hoping it's do-able.

Not sure what solution would be best for me but what I need is:

a)Something that's easy to place in the template, perhaps predefined Content Control placeholders that you can place where you wan't and style as you like.

b)When the data has been added it removes all placeholders, it won't be modified again. It keeps the style/format defined in the placeholder.

TO RECAP, I need answer to either

How can I edit Content Controls in OpenXML SDK so they will be removed after text is added.

-OR-

Can I define my own custom OpenXML tag for a Word Document that I could then replace?

回答1:

Perhaps this can help you,

private void DeleteSdtBlockAndKeepContent(MainDocumentPart mainDocumentPart, string sdtBlockTag)
    {
        List<SdtBlock> sdtList = mainDocumentPart.Document.Descendants<SdtBlock>().ToList();
        SdtBlock sdtA = null;

        foreach (SdtBlock sdt in sdtList)
        {
            if (sdt.SdtProperties.GetFirstChild<Tag>().Val.Value == sdtBlockTag)
            {
                sdtA = sdt;
                break;
            }
        }


        OpenXmlElement sdtc = sdtA.GetFirstChild<SdtContentBlock>();
        OpenXmlElement parent = sdtA.Parent;

        OpenXmlElementList elements = sdtc.ChildElements;

        var mySdtc = new SdtContentBlock(sdtc.OuterXml);

        foreach (OpenXmlElement elem in elements)
        {

            string text = parent.FirstChild.InnerText;
            parent.Append((OpenXmlElement)elem.Clone());
        }

        sdtA.Remove();
    }


回答2:

Take a look at using a Field. The mail merge fields are designed for exactly this purpose.



回答3:

I don't understand from your question if you are only interested in a solution that automatically removes the ContentControl/SDT when you modify it using the OpenXML SDK, or whether you want it to disappear after the content is modifed programmatically or by a user.

If the former, I think you'll have to remove it yourself as Bilel suggested. If the latter, you should look at this property: ContentControl.Temporary ("the ContentControl is automatically deleted when the user types in the control, or when the text in the control is changed programmatically. When the ContentControl is automatically deleted from the document, the text in the control remains in the document.")