By shannon on June 03, 2010
Recently, I was asked about doing a find and replace for Word documents in code. We had sections that needed to be conditionally shown, based on specific criteria. This meant that the Word document template contained 2 different sections, but after the code ran, only one of them should remain. Since I had never done this, I did a little searching. I found a large number of posts on various ways to do this, but none of them seemed to do exactly what I wanted, and in many cases they didn't seem to work as I was expecting.

I knew the logic, that would work, but it was a matter of figuring out how to actually find and replace the pieces using the Word interop objects. We added Tags to the document to mark the beginning and ending of the sections that we needed to work with.

First I got it working to delete the section of content that I wanted to "hide". Then, I had to remove just the tags for the section we were going to leave. This left me with just the section of text we wanted.

So just say we started with a very simple Word document that looked something like this:

Here is the start of our document.
[FirstTagToFindStart]This is our first section.[FirstTagToFindEnd][SecondTagToFindStart]This is our second section.[SecondTagToFindEnd]
Here is the end of our document

At the end, we want the document to look like this:

Here is the start of our document.
This is our second section.
Here is the end of our document.

Here is the code that seemed to do the trick:
Word.Application word = new Word.Application();
Document doc = new Document();
// Set our missing object as we are required to pass it for any param that we are not setting below
object missing = System.Type.Missing;

// Open our word document
object fileName = @"c:\wordtest\template.doc";
doc = word.Documents.Open(ref fileName, ref missing, ref missing, ref missing, ref missing, 
    ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, 
    ref missing, ref missing, ref missing);
doc.Activate();

try
{
    // set our search range to the entire document
    Word.Range beginSearchRange = doc.Content;

    beginSearchRange.Find.Text = "[FirstTagToFindStart]";
    beginSearchRange.Find.Execute(ref missing, ref missing, ref missing, ref missing, ref missing, ref missing,
                      ref missing, ref missing, ref missing, ref missing, ref missing, ref missing,
                      ref missing, ref missing, ref missing);

    object sectionStart = beginSearchRange.Start;

    Word.Range endSearchRange = doc.Content;

    endSearchRange.Find.Text = "[FirstTagToFindEnd]";
    endSearchRange.Find.Execute(ref missing, ref missing, ref missing, ref missing, ref missing, ref missing,
                      ref missing, ref missing, ref missing, ref missing, ref missing, ref missing,
                      ref missing, ref missing, ref missing);

    object sectionEnd = endSearchRange.End;

    Word.Range deleteRange = doc.Range(ref sectionStart, ref sectionEnd);

    // Check to make sure we don't just delete the whole document if not found
    if (deleteRange.Start != doc.Content.Start && deleteRange.End != doc.Content.End)
    {
        deleteRange.Delete(ref missing, ref missing);
    }

    // Need to also delete the tags for the section we are going to keep in the document
    Word.Range removeStartTagRange = doc.Content;
    removeStartTagRange.Find.Text = "[SecondTagToFindStart]";

    removeStartTagRange.Find.Execute(ref missing, ref missing, ref missing, ref missing, ref missing, ref missing,
                      ref missing, ref missing, ref missing, ref missing, ref missing, ref missing,
                      ref missing, ref missing, ref missing);

    // Can get both start and end from this one range
    // Check to be sure we don't delete the whole document
    if (removeStartTagRange.Start != doc.Content.Start && removeStartTagRange.End != doc.Content.End)
    {
        removeStartTagRange.Delete(ref missing, ref missing);
    }

    // Now do the same thing for the Ending alternate tag
    Word.Range removeEndTagRange = doc.Content;
    removeEndTagRange.Find.Text = "[SecondTagToFindEnd]";

    removeEndTagRange.Find.Execute(ref missing, ref missing, ref missing, ref missing, ref missing, ref missing,
                      ref missing, ref missing, ref missing, ref missing, ref missing, ref missing,
                      ref missing, ref missing, ref missing);

    // Can get both start and end from this one range
    if (removeEndTagRange.Start != doc.Content.Start && removeEndTagRange.End != doc.Content.End)
    {
        removeEndTagRange.Delete(ref missing, ref missing);
    }
}
catch (Exception ex)
{
    MessageBox.Show(ex.Message);
}
finally
{
    doc.Close(ref missing, ref missing, ref missing);
    word.Quit(ref missing, ref missing, ref missing);
    System.Runtime.InteropServices.Marshal.ReleaseComObject(word);
}