Replacing text with a Bookmark

Hi Team,

I have a specific requirement to search for a text/character in word document file and replace it with a Bookmark. Can you help me a sample code if possible?

Thanks.

@ottap

To replace a specific text or character in a Word document with a bookmark using Aspose.Words, you can follow the example code below. This code demonstrates how to search for a text string and replace it with a bookmark.

Sample Code

import com.aspose.words.*;

public class ReplaceTextWithBookmark {
    public static void main(String[] args) throws Exception {
        // Load the document
        Document doc = new Document("path/to/your/document.docx");
        DocumentBuilder builder = new DocumentBuilder(doc);

        // Define the text to search for
        String textToFind = "YourTextToFind";
        
        // Check if the text exists in the document
        if (doc.getRange().getText().contains(textToFind)) {
            // Move to the text to find
            builder.moveToDocumentStart();
            builder.getCurrentParagraph().getRange().replace(textToFind, "", new FindReplaceOptions(FindReplaceDirection.FORWARD));

            // Insert a bookmark at the position where the text was found
            builder.startBookmark("MyBookmark");
            builder.writeln("This is the text that was replaced by a bookmark.");
            builder.endBookmark("MyBookmark");
        }

        // Save the modified document
        doc.save("path/to/your/modified_document.docx");
    }
}

Explanation

  1. Load the Document: The document is loaded from a specified path.
  2. Search for Text: The code checks if the specified text exists in the document.
  3. Replace Text: If the text is found, it is replaced with an empty string.
  4. Insert Bookmark: A bookmark is created at the position where the text was found, and you can insert any content you want within the bookmark.
  5. Save the Document: Finally, the modified document is saved to a new file.

Make sure to adjust the paths and the text you want to find and replace as per your requirements. This approach allows you to effectively replace text with a bookmark in a Word document using Aspose.Words.

For more details on working with bookmarks, you can refer to the official documentation on Working with Bookmarks.

Sources:
[1]: Working with Bookmarks in C#|Aspose.Words for .NET

@ottap If you need to find and wrap some particular text into a bookmark, you can achieve this using IReplacingCallback.
For example see the following code:

Document doc = new Document(@"C:\Temp\in.docx");

ReplacingCallbackWrapWithBookmark callback = new ReplacingCallbackWrapWithBookmark();
FindReplaceOptions opt = new FindReplaceOptions(FindReplaceDirection.Backward);
opt.ReplacingCallback = callback;
doc.Range.Replace("test", "", opt);

doc.Save(@"C:\Temp\out.docx");
public class ReplacingCallbackWrapWithBookmark : ReplacingCallabackBase, IReplacingCallback
{
    public ReplaceAction Replacing(ReplacingArgs args)
    {
        Document doc = (Document)args.MatchNode.Document;
        List<Run> matchedRuns = GetMatchedRuns(args);

        // Generate an unique bookmakr name. Another approach can be used.
        // If bookmark starts with undescore it is hidden in MS Word. 
        string bookmarkName = "_" + Guid.NewGuid().ToString();
        while (doc.Range.Bookmarks[bookmarkName] != null)
            bookmarkName += "_" + Guid.NewGuid().ToString();

        // Insert a bookmark around the matched text
        matchedRuns.First().ParentNode.InsertBefore(new BookmarkStart(doc, bookmarkName), matchedRuns[0]);
        matchedRuns.Last().ParentNode.InsertAfter(new BookmarkEnd(doc, bookmarkName), matchedRuns.Last());

        Bookmarks.Add(bookmarkName);

        // Signal to the replace engine to do nothing because we have already done all what we wanted.
        return ReplaceAction.Skip;
    }

    protected static List<Run> GetMatchedRuns(ReplacingArgs args)
    {
        // This is a Run node that contains either the beginning or the complete match.
        Node currentNode = args.MatchNode;

        // The first (and may be the only) run can contain text before the match, 
        // in this case it is necessary to split the run.
        if (args.MatchOffset > 0)
            currentNode = SplitRun((Run)currentNode, args.MatchOffset);

        // This array is used to store all nodes of the match for further deleting.
        List<Run> runs = new List<Run>();

        // Find all runs that contain parts of the match string.
        int remainingLength = args.Match.Value.Length;
        while (
            remainingLength > 0 &&
            currentNode != null &&
            currentNode.GetText().Length <= remainingLength)
        {
            runs.Add((Run)currentNode);
            remainingLength -= currentNode.GetText().Length;

            // Select the next Run node.
            // Have to loop because there could be other nodes such as BookmarkStart etc.
            do
            {
                currentNode = currentNode.NextSibling;
            } while (currentNode != null && currentNode.NodeType != NodeType.Run);
        }

        // Split the last run that contains the match if there is any text left.
        if (currentNode != null && remainingLength > 0)
        {
            SplitRun((Run)currentNode, remainingLength);
            runs.Add((Run)currentNode);
        }

        return runs;
    }

    private static Run SplitRun(Run run, int position)
    {
        Run afterRun = (Run)run.Clone(true);
        run.ParentNode.InsertAfter(afterRun, run);
        afterRun.Text = run.Text.Substring(position);
        run.Text = run.Text.Substring((0), (0) + (position));
        return afterRun;
    }

    public List<string> Bookmarks
    {
        get { return mBookmarks; }
    }

    private List<string> mBookmarks = new List<string>();
}