Search code examples
c#ms-wordopenxmlopenxml-sdk

using C# OpenXml SDK apply strike through for all bullets in MS Word


I need to apply styles to bullets in a MS Word document. I am able to read full docx using OpenXML then apply styles for Paragraphs using Run nodes

enter image description here

This is how I am applying styles at other areas based up on the condition

private void StrikeAndUnderline(Run run)
        {
            if (run.RunProperties == null)
            {
                run.RunProperties = new RunProperties();
            }
            run.RunProperties.Strike = new Strike();
            run.RunProperties.Strike.Val = true;
            run.RunProperties.Underline = new Underline();
            run.RunProperties.Underline.Val = UnderlineValues.Single;
        }

But I don't get a Run property for bullets

enter image description here

<w:p>
  <w:pPr>
    <w:pStyle w:val="ListParagraph"/>
    <w:numPr>
      <w:ilvl w:val="0"/>
      <w:numId w:val="1"/>
    </w:numPr>
  </w:pPr>
  <w:r>
    <w:t>Paragraph one.</w:t>
  </w:r>
</w:p>

Solution

  • Based on the explanation @Shelest provided, here is the quick & dirty implementation of striking bullets using OpenXML SDK

    public static void ReadAndStrikeBulletsWithOpenXml()
            {
                var sourcePath = @"C:\temp\test.docx";
                var destinationPath = @"C:\temp\new-test.docx";
                File.Copy(sourcePath, destinationPath);
                using (var document = WordprocessingDocument.Open(destinationPath, true))
                {
                    Numbering numbering = document.MainDocumentPart.NumberingDefinitionsPart.Numbering;
                    var abstractNum = numbering.ChildElements.FirstOrDefault(x => x.LocalName.Equals("abstractNum"));
                    if (abstractNum?.ChildElements != null)
                    {
                        foreach (var child in abstractNum.ChildElements)
                        {
                            if (child.OuterXml.Contains("<w:lvl"))
                            {
                                XmlDocument levelXml = new XmlDocument();
                                levelXml.LoadXml(child.OuterXml);
    
                                XmlNamespaceManager namespaceManager = new XmlNamespaceManager(levelXml.NameTable);
                                namespaceManager.AddNamespace("w",
                                    "http://schemas.openxmlformats.org/wordprocessingml/2006/main");
    
                                XmlNode runProperty = levelXml.SelectSingleNode("w:lvl/w:rPr", namespaceManager);
                                if (runProperty == null)
                                {
                                    // Need to uncomment this if you prefer to strike all bullets at all levels
                                    //child.InnerXml = child.InnerXml +
                                    //                 "<w:rPr><w:strike w:val\"1\"/></w:rPr>";
                                }
                                else if (runProperty.InnerXml.Contains("w:strike"))
                                {
                                    XmlDocument runXml = new XmlDocument();
                                    runXml.LoadXml(runProperty.OuterXml);
    
                                    XmlNamespaceManager runNamespaceManager = new XmlNamespaceManager(runXml.NameTable);
                                    runNamespaceManager.AddNamespace("w",
                                        "http://schemas.openxmlformats.org/wordprocessingml/2006/main");
    
                                    XmlNode strikeNode = runXml.SelectSingleNode("w:rPr/w:strike", namespaceManager);
                                    if (strikeNode?.Attributes != null)
                                    {
                                        if (strikeNode.Attributes["w:val"] == null)
                                        {
                                            // do nothing
                                        }
                                        else if (strikeNode.Attributes["w:val"].Value == "0")
                                        {
                                            child.InnerXml = child.InnerXml.Replace("w:strike w:val=\"0\"", "w:strike w:val=\"1\"");
                                        }
                                    }
                                }
                            }
                        }
                    }
                    document.MainDocumentPart.Document.Save();
                    document.Close();
                }
            }