Find Keywords in Word Document and Highlight Text with Special Characters using C# .NET Code

Hello Team

in one of my requirement i have to find a word in word doc and highlight that word. Now the problem is that it works fine for word which does not have apostrophe in it but word with apostrophe is not recognized and not highlighted. Eg
I have word “Trust” and “Trust’s”. when i use the Find and highlight code as suggested in

it highlight only “Trust” in both word not complete “Trust’s”


After an initial test with the licensed latest (20.10) version of Aspose.Words for .NET, we were unable to reproduce this issue on our end. We used the following simple code for testing on our end:

C# Code:

Document doc = new Document("C:\\temp\\find and highlight test.docx");

FindReplaceOptions options = new FindReplaceOptions();
options.ReplacingCallback = new ReplaceEvaluatorFindAndHighlight();
options.Direction = FindReplaceDirection.Backward;

Regex regex = new Regex("“Trust”", RegexOptions.IgnoreCase);
doc.Range.Replace(regex, "", options);

regex = new Regex("“Trust’s”", RegexOptions.IgnoreCase);
doc.Range.Replace(regex, "", options);


We suggest you to please upgrade to the latest version of Aspose.Words. In case the problem still remains, then please provide your simplified Word document (you are getting this problem with) here for testing. We will then investigate the issue further on our end and provide you more information.

Thanks awais, for looking into my issue.
I had 20.6 version of aspose which i updated to 20.10 as suggested by you. but issue still persist. And i don’t have any specific doc, i tried with doc shared by you in attachement over there also i didn’t worked. can you share the ReplaceEvaluatorFindAndHighlight callback class you used. May be there is some difference


Please check the following code that I copied from How to Find and Highlight Text section:

private class ReplaceEvaluatorFindAndHighlight : IReplacingCallback
    /// <summary>
    /// This method is called by the Aspose.Words find and replace engine for each match.
    /// This method highlights the match string, even if it spans multiple runs.
    /// </summary>
    ReplaceAction IReplacingCallback.Replacing(ReplacingArgs e)
        // This is a Run node that contains either the beginning or the complete match.
        Node currentNode = e.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 (e.MatchOffset > 0)
            currentNode = SplitRun((Run)currentNode, e.MatchOffset);

        // This array is used to store all nodes of the match for further highlighting.
        ArrayList runs = new ArrayList();

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

            // Select the next Run node. 
            // Have to loop because there could be other nodes such as BookmarkStart etc.
                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);

        // Now highlight all runs in the sequence.
        foreach (Run run in runs)
            run.Font.HighlightColor = Color.Yellow;

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

    /// <summary>
    /// Splits text of the specified run into two runs.
    /// Inserts the new run just after the specified run.
    /// </summary>
    private static Run SplitRun(Run run, int position)
        Run afterRun = (Run)run.Clone(true);
        afterRun.Text = run.Text.Substring(position);
        run.Text = run.Text.Substring(0, position);
        run.ParentNode.InsertAfter(afterRun, run);
        return afterRun;