Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

OpenXML Iterate and Replace

Posted on 2011-03-24
3
Medium Priority
?
3,721 Views
Last Modified: 2012-05-11
How do you iterate through all the content controls?  I have a document with several RichText content controls but the process is not finding all the content controls within the document.  It appears that it is only finding content controls that are on the root and not ones that are within the body text.

Also, once I find a content control how do I replace the text?

This should be easy right?

public static void MyMethod(string docfile)
        {
            using (WordprocessingDocument doc = WordprocessingDocument.Open(docfile, true))
            {
                var docPart = doc.MainDocumentPart;
                // Find the first content control whose Alias property matches the supplied name.
                var sdts = docPart.Document.Descendants<SdtBlock>();
                foreach (var sdt in sdts)
                {
                    //todo it is not finding all content controls, it appeas they can't be with the body text
                    if (sdt.SdtContentBlock.InnerText == "ReplaceMeText")
                    {
                        //todo how to replace text: sdt.SdtContentBlock.InnerText = "MyNewText";

                        System.Diagnostics.Debug.WriteLine("Found" + sdt.SdtContentBlock.InnerText);
                    }

                }
            }
        }

Open in new window

0
Comment
Question by:tampsystems
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
3 Comments
 
LVL 1

Expert Comment

by:nulliusinverba
ID: 35212916
I had this problem too.

I found that some of the content controls were of type "StdBlock", but some others were of type "SdtRun".

Best thing to do it is to firstly check out the Open XML SDK Productivity Tool, which opens your document and reflects the code.  Then you can drill down to where you know the controls are and see what type of element they are.

I also made myself a little console app that analyses a file and tells me how many blocks and runs there are, and what their control name is.  It's real simple.  THere's probably much better ways to do this, but I'm new to this too, and it works for me.  Here's my analysis program:

 
class Program
    {
        static void Main(string[] args)
        {
            // (1) Objects used throughout
            string fileName = @"C:\...\Letter.dotx"; // file to open
            int hb = 0; // for count of StdBlocks in header
            int hr = 0; // for count of SrdRuns in header
            int bb = 0; // for count of StdBlocks in body
            int br = 0; // for count of StdRuns in body
            List<string> hBlocks = new List<string>(); // to hold list of aliases of all blocks in header
            List<string> hRuns = new List<string>(); // to hold list of aliases of all runs in header
            List<string> bBlocks = new List<string>(); // to hold list of aliases of all blocks in body
            List<string> bRuns = new List<string>(); // to hold list of aliases of all runs in body

            // (2) Create the memory stream
            byte[] templateBytes = System.IO.File.ReadAllBytes(fileName);
            using (MemoryStream templateStream = new MemoryStream())
            {
                templateStream.Write(templateBytes, 0, (int)templateBytes.Length);

                // (3) Open the template as a wordprocessing document
                using (WordprocessingDocument outDoc = WordprocessingDocument.Open(templateStream, true))
                {
                    MainDocumentPart mainPart = outDoc.MainDocumentPart;

                    // (4) Analyse the header parts, count the number of runs and blocks, and write the string names to the relevant list
                    var hp = mainPart.HeaderParts;
                    foreach (var hd in hp)
                    {
                        foreach (SdtElement sdt in hd.Header.Descendants<SdtElement>().ToList())
                        {
                            string type = sdt.GetType().Name;
                            SdtAlias alias = sdt.Descendants<SdtAlias>().FirstOrDefault();
                            string sdtTitle = alias.Val.Value;
                            if (alias != null)
                            {
                                if (type == "SdtBlock")
                                {
                                    hb++;
                                    hBlocks.Add(sdtTitle);
                                }
                                else if (type == "SdtRun")
                                {
                                    hr++;
                                    hRuns.Add(sdtTitle);
                                }
                            }
                        }
                    }

                    // (5) Analyse the body parts, count the number of runs and blocks, and write the string names to the relevant list
                    foreach (SdtElement sdt in mainPart.Document.Descendants<SdtElement>().ToList())
                    {
                        string type = sdt.GetType().Name;
                        SdtAlias alias = sdt.Descendants<SdtAlias>().FirstOrDefault();
                        string sdtTitle = alias.Val.Value;

                        if (alias != null)
                        {
                            if (type == "SdtBlock")
                            {
                                bb++;
                                bBlocks.Add(sdtTitle);
                            }
                            else if (type == "SdtRun")
                            {
                                br++;
                                bRuns.Add(sdtTitle);
                            }
                        }
                    }
                                     
                }

            }

            // (6) Write the results of the analysis to the Console
            Console.WriteLine("The header part contains the following.\n\r\t{0} elements are StdRun:", hr.ToString());
            foreach (string x in hRuns)
            {
                Console.WriteLine("\t\t{0}", x);
            }
            Console.WriteLine("\t{0} elements are StdBlock:", hb.ToString());
            foreach (string x in hBlocks)
            {
                Console.WriteLine("\t\t{0}", x);
            }
            Console.WriteLine("\n\rThe body part contains the following.\n\r\t{0} elements are StdRun:", br.ToString());
            foreach (string x in bRuns)
            {
                Console.WriteLine("\t\t{0}", x);
            }
            Console.WriteLine("\t{0} elements are StdBlock:", bb.ToString());
            foreach (string x in bBlocks)
            {
                Console.WriteLine("\t\t{0}", x);
            }
        }
    }

Open in new window


Hope this helps.

Cheers,

Tim.
0
 

Author Comment

by:tampsystems
ID: 35216581
I tried your code but it appears that all of the SdtAlias were null.
                       
SdtAlias alias = sdt.Descendants<SdtAlias>().FirstOrDefault();

if (alias != null) //always null
0
 
LVL 1

Accepted Solution

by:
nulliusinverba earned 2000 total points
ID: 35363182
Sorry mate - wish that had worked for you.

So what's going on is going to be a function of the (your) Word document which is being analysed by the code.

Best you could do is use the productivity tool to drill down to your content controls and see where they fit into the heirarchy of StdElement, SdtBlock, SdtRun, etc...

The productivity tool really is your best friend.
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Browsing the questions asked to the Experts of this forum, you will be amazed to see how many times people are headaching about monster regular expressions (regex) to select that specific part of some HTML or XML file they want to extract. The examp…
This article aims to explain the working of CircularLogArchiver. This tool was designed to solve the buildup of log file in cases where systems do not support circular logging or where circular logging is not enabled
In this video you will find out how to export Office 365 mailboxes using the built in eDiscovery tool. Bear in mind that although this method might be useful in some cases, using PST files as Office 365 backup is troublesome in a long run (more on t…
Please read the paragraph below before following the instructions in the video — there are important caveats in the paragraph that I did not mention in the video. If your PaperPort 12 or PaperPort 14 is failing to start, or crashing, or hanging, …

609 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question