Search code examples
c#ms-wordopenxml-sdkword-contentcontrolwordprocessingml

Remove repeating section controls and text content controls from Word document with C#


A Word document with repeating section content controls and text content controls is dynamically populated with content. After the document has been created, all controls need to be removed to make the document easier to edit (the content should be retained). I have created a basic framework for the code, how can this be extended so that only the controls are deleted and the content is retained?

using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;

using (WordprocessingDocument doc = WordprocessingDocument.Open(@"C:\Temp\Test\Weekly Marketing Dashboard.docx", true))
{

    MainDocumentPart mainPart = doc.MainDocumentPart;

    var sdtElements = mainPart.Document.Descendants<SdtElement>().ToList();

    foreach (var sdtElement in sdtElements)
    {
        sdtElement.Remove();
    }

    mainPart.Document.Save();
}

Solution

  • Finally I found a solution myself, using OpenXML:

        static void RemoveContentControls(OpenXmlElement element)
    {
        // Replace SdtCells
        var sdtCells = element.Descendants<SdtCell>().ToList();
        foreach (var sdtCell in sdtCells)
        {
            // Clone and paste each child element
            foreach (OpenXmlElement child in sdtCell.SdtContentCell.ChildElements)
            {
                sdtCell.InsertBeforeSelf(child.CloneNode(true));
            }
            sdtCell.Remove();
        }
    
        // Replace SdtRuns
        var sdtRuns = element.Descendants<SdtRun>().ToList();
        foreach (var sdtRun in sdtRuns)
        {
            // Clone and paste each child element
            foreach (OpenXmlElement child in sdtRun.SdtContentRun.ChildElements)
            {
                sdtRun.InsertBeforeSelf(child.CloneNode(true));
            }
            sdtRun.Remove();
        }
    
        // Process childs recursive
        foreach (var child in element.ChildElements.ToArray()) // Use ToArray for save modification during iteration
        {
            RemoveContentControls(child);
        }
    }