daniel
daniel

Reputation: 35733

Replace bookmarks content without removing the bookmark

I want to replace the text content of bookmarks without loosing the bookmark.

foreach(Bookmark b in document.Bookmarks)
{
    b.Range.Text = "newtext";  // text is set in document but bookmark is gone
}

I tried to set the new Range of the bookmark before the Text setting but I still have the same problem.

I also tried to re-add the bookmark with document.Bookmarks.Add(name, range); but I can't create an instance of range.

Upvotes: 3

Views: 2876

Answers (3)

slacker
slacker

Reputation: 53

With the above approach, you still lose the bookmark before it is added back in. If you really need to preserve the bookmark, I find that you can create an inner bookmark that wraps around the text (a bookmark within bookmark). After having the inner bookmark, you simply need to do:

innerBookmark.Range.Text = newText;

After the text replacing, the inner bookmark is gone and the outer bookmark is preserved. No need to set range.End.

You can create the inner bookmark manually or programmatically depending on your situation.

Upvotes: 1

daniel
daniel

Reputation: 35733

I had to readd the bookmarks and save the range temporarily. I also had to add a list of processed items to evade an endless loop.

List<string> bookmarksProcessed = new List<string>();

foreach (Bookmark b in document.Bookmarks)
{
    if (!bookmarksProcessed.Contains(b.Name))
    {
        string text = getTextFromBookmarkName(b.Name);
        var newend = b.Range.Start + text.Length;
        var name = b.Name;
        Range rng = b.Range;
        b.Range.Text = text;
        rng.End = newend;
        document.Bookmarks.Add(name, rng);
        bookmarksProcessed.Add(name);
    }
}

Upvotes: 3

Ubernator
Ubernator

Reputation: 743

Looks like you solved your problem, but here is a cleaner way to do it:

using Office = Microsoft.Office.Core;
using Microsoft.Office.Tools.Word;
using System.Text.RegularExpressions;
using Word = Microsoft.Office.Interop.Word;

//declare and get the current document 
Document extendedDocument = Globals.Factory.GetVstoObject(Globals.ThisAddIn.Application.ActiveDocument);

List<string> bookmarksProcessed = new List<string>();  

foreach(Word.Bookmark oldBookmark in extendedDocument.Bookmarks)
{
    if(bookmarksProcessed.Contains(oldBookmark.Name))
    {
        string newText = getTextFromBookmarkName(oldBookmark.Name)

        Word.Range newRange = oldBookmark.Range;

        newRange.End = newText.Length;

        Word.Bookmark newBookmark = extendedDocument.Controls.AddBookmark(newRange, oldBookmark.Name);

        newBookmark.Text = newText;

        oldBookmark.Delete();
    }
}

Code isn't tested but should work.

Upvotes: 0

Related Questions