locked
OpenXML replacing text - formatting lost RRS feed

  • Question

  • I am trying to create a method that will replace some text “ABC-DEF” within a paragraph with some new text “My New Text”.  Because there can be multiple runs with text and we can’t change the InnerText property, I had to remove all the runs and create a new run.  Everything works great except that the formatting is being lost.  The text I am replacing contains an underline. I am thinking that each run can have different formatting. 

      

    Is there a way to preserve the formatting?

     

    Or maybe get the first run’s formatting and apply it to my new run?

     

     

    using (WordprocessingDocument doc = WordprocessingDocument.Open(filename, true))

    {

     

        Paragraph par = doc.MainDocumentPart.Document.Descendants<Paragraph>().ElementAt(2); //hardcoded a paragraph index for testing

     

        string modifiedString = par.InnerText.Replace("ABC-DEF", "My New Text");

        par.RemoveAllChildren<Run>();

        Run run = new Run(new Text(modifiedString));

        par.AppendChild<Run>(run);

     

        System.Diagnostics.Debug.WriteLine(par.InnerText);

     

        doc.MainDocumentPart.Document.Save();

    }

     


    Thomas Abruzzo thomas@tampsystems.com
    Thursday, April 21, 2011 2:00 PM

Answers

  • Hi Thomas,

    I knew your problem, below is the code snippet which I have modified:

               using (WordprocessingDocument doc = WordprocessingDocument.Open(docfile, true))
                {
                    Paragraph par = doc.MainDocumentPart.Document.Descendants<Paragraph>().ElementAt(0); //hardcoded a paragraph index for testing
                    //Run r = par.Descendants<Run>().First();
                    //string modifiedString = par.InnerText.Replace("ABC-DEF", "My New Text");
                    //Text t = new Text(modifiedString);
                    //r.RemoveAllChildren<Text>();
                    //r.AppendChild<Text>(t);
                    //System.Diagnostics.Debug.WriteLine(par.InnerText);
     
                    string modifiedString="";
                    // get all runs under the paragraph and convert to be array
                    Run[] runArr = par.Descendants<Run>().ToArray();
                    // foreach each run
                    foreach (Run run in runArr)
                    {
                        modifiedString = run.InnerText.Replace("ABC-DEF""My New Text");
                        // if the InnerText doesn't modify
                        if (modifiedString != run.InnerText)
                        {
                            Text t = new Text(modifiedString);
                            run.RemoveAllChildren<Text>();
                            run.AppendChild<Text>(t);
                        }
                    }
                    doc.MainDocumentPart.Document.Save();
                }

    I hope it can help you and feel free to follow up after you have tried.

    Best Regards,


    Bruce Song [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Proposed as answer by Bruce Song Monday, May 2, 2011 8:15 AM
    • Marked as answer by Bruce Song Monday, May 2, 2011 8:16 AM
    Monday, April 25, 2011 7:42 AM

All replies

  • Hi Thomas,

    I looked into the xml structure of the document in the Open XML SDK Productivity tool and found that the format property is contained under the Run property. So, if we remove run property, the entire format will also be removed. 

    If you want to preserve the format for these runs, I think you can just remove the text from the run and the add the new text to the run, below is the code snippet which I have fixed:

                using (WordprocessingDocument doc = WordprocessingDocument.Open(docfile, true))
                {
                    Paragraph par = doc.MainDocumentPart.Document.Descendants<Paragraph>().ElementAt(0); //hardcoded a paragraph index for testing
                    Run r = par.Descendants<Run>().First();
                    string modifiedString = par.InnerText.Replace("New Text""My New Text");
                    Text t = new Text(modifiedString);
                    r.RemoveAllChildren<Text>();
                    r.AppendChild<Text>(t);
                    System.Diagnostics.Debug.WriteLine(par.InnerText);
                    doc.MainDocumentPart.Document.Save();
                }

    I hope this can help you and just feel free to follow up after you have tried.

    Best Regards,


    Bruce Song [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Friday, April 22, 2011 7:50 AM
  • Thank you for your help.

    Example of the text in paragraph two: (note that ABC-DEF is underlined or any other formatting)

     

    "This document is the ABC-DEF confidential property."

                

    The code below will append the new text with the underline to the end of the paragraph.

    Just need to replace the text ABC-DEF and keep the formatting?

     

     

    using (WordprocessingDocument doc = WordprocessingDocument.Open(filename, true))

    {

        Paragraph par = doc.MainDocumentPart.Document.Descendants<Paragraph>().ElementAt(2); //hardcoded a paragraph index for testing

        Run r = par.Descendants<Run>().First();

        string modifiedString = par.InnerText.Replace("ABC-DEF", "My New Text");

        Text t = new Text(modifiedString);

        r.RemoveAllChildren<Text>();

        r.AppendChild<Text>(t);

        System.Diagnostics.Debug.WriteLine(par.InnerText);

     

        doc.MainDocumentPart.Document.Save();

    }

     

     


    Thomas Abruzzo thomas@tampsystems.com
    Friday, April 22, 2011 4:26 PM
  • Hi Thomas,

    I knew your problem, below is the code snippet which I have modified:

               using (WordprocessingDocument doc = WordprocessingDocument.Open(docfile, true))
                {
                    Paragraph par = doc.MainDocumentPart.Document.Descendants<Paragraph>().ElementAt(0); //hardcoded a paragraph index for testing
                    //Run r = par.Descendants<Run>().First();
                    //string modifiedString = par.InnerText.Replace("ABC-DEF", "My New Text");
                    //Text t = new Text(modifiedString);
                    //r.RemoveAllChildren<Text>();
                    //r.AppendChild<Text>(t);
                    //System.Diagnostics.Debug.WriteLine(par.InnerText);
     
                    string modifiedString="";
                    // get all runs under the paragraph and convert to be array
                    Run[] runArr = par.Descendants<Run>().ToArray();
                    // foreach each run
                    foreach (Run run in runArr)
                    {
                        modifiedString = run.InnerText.Replace("ABC-DEF""My New Text");
                        // if the InnerText doesn't modify
                        if (modifiedString != run.InnerText)
                        {
                            Text t = new Text(modifiedString);
                            run.RemoveAllChildren<Text>();
                            run.AppendChild<Text>(t);
                        }
                    }
                    doc.MainDocumentPart.Document.Save();
                }

    I hope it can help you and feel free to follow up after you have tried.

    Best Regards,


    Bruce Song [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Proposed as answer by Bruce Song Monday, May 2, 2011 8:15 AM
    • Marked as answer by Bruce Song Monday, May 2, 2011 8:16 AM
    Monday, April 25, 2011 7:42 AM
  • Hi Thomas,

    Have you resolved your problem yet, and does the suggestion help you? If you still have any concern on the thread, just feel free to follow up. 

    Best Regards,


    Bruce Song [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Wednesday, April 27, 2011 9:17 AM
  • yes this did help me towards the right direction but i am still working on this issue.  i will let you know when i have a completed solution.
    Thomas Abruzzo thomas@tampsystems.com
    Wednesday, April 27, 2011 12:46 PM
  • Hi Thomas,

    I will temporarily mark the reply as the answer, if you still encounter any issues, just feel free to update.

    Best Regards,


    Bruce Song [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Monday, May 2, 2011 8:16 AM