by Andreas

Microsoft.Office.Interop.Word – replace bookmarks programmatically

Replacing bookmarks in Word documents programmatically is fairly straight forward. The Microsoft.Office.Interop.Word namespace has a set of methods that allows simple access, but there is one short-coming: when replacing the bookmark, the bookmark itself is completely removed. This might be fine in most situations, but in our case we wanted to allow our users to set the bookmark values over and over again, within the same document.

This required a bit of research, but eventually I managed to get it to work (and it turned out to be extremely simple..). The following code should have enough comments to explain the details of what’s going on, but I ended up having to get a reference to the original bookmark in the Word document (god bless the COM..). This bookmark is then replaced with the desired text (e.g. [CompanyName] => “Contoso”). Now, this is where it gets a bit interesting. I re-add the bookmark, as per this article but before that’s done I set the new range values based on the length of the replacement word (“Contoso”). The result is that the bookmark encapsulates your new text, keeps its original name (“CompanyName”) and most importantly: stays within its original StoryType. The StoryType is a read-only property determining which part of a document the bookmark is found, for instance the body, header or footer. Without this, the default is used and you will not be able to support bookmarks anywhere else than within the main body of your Word document.

 

public void BookMarkReplaceInternal(string bookmark, string file, string newText)
{
    Microsoft.Office.Interop.Word.Application _app = null;
    Microsoft.Office.Interop.Word.Document _doc = null;

    try
    {
        // open document
        _app = new Microsoft.Office.Interop.Word.Application();
        _doc = _app.Documents.Open(file, _missing, _missing, _missing, _missing, _missing, _missing, _missing, _missing, _missing);

        // find bookmark
        var bm = _doc.Bookmarks[bookmark];

        // get COM object reference
        object rng = bm.Range;

        // get original bookmark start position and name
        var bmStart = bm.Range.Start;
        var bookmarkName = bm.Name;

        // replace bookmark with new text
        bm.Range.Text = newText;

        // calculate bookmark range (use original bookmark start position, add length of new contents 
        ((Microsoft.Office.Interop.Word.Range)rng).Start = bmStart;
        ((Microsoft.Office.Interop.Word.Range)rng).End = bmStart + newText.Length;

        // re-add bookmark with updated range
        _doc.Bookmarks.Add(bookmarkName, rng);

        _doc.Save();
    }
    finally
    {
        if (_doc != null) _doc.Close(true, _missing, _missing);
        if (_app != null) _app.Quit(true, _missing, _missing);
    }
}
  • Luiz Filipe

    Valeu gostei o artigo, parabéns.

  • selvaa

    Its very helpful to my bottle neck time.
    Thanks lot.

  • dinuka

    i was getting following error “The range cannot be deleted” at line “bm.Range.Text = newText;” ,