Say I have a document that contains the following line:
{star}This is the entire line I want to be highlighted{/star}
In the document you can see I have html like code that designates a start and stop point of text I would like to have highlighted, “{star}”.
Unlike most solutions I’ve seen, I do not know what the text is beforehand to do a find and highlight. Several different instances of this may occur in the document, so I would want it to do a “find” and highlight of each {star} span if you will.
Is this possible?
Hi
Thanks for your request. You can use Regular Expressions to find text in your document. I think the following article could be useful for you:
https://docs.aspose.com/words/net/find-and-replace/
Best regards.
I’ve used your example before posting, and that is great for finding and replacing words that you know you are looking for.
In my example, you don’t know. Of course you know the “tags”, but how do you highlight ALL the text between them?
wt.Range.Replace(regex1, regex2);
Basically I would want a method that would allow for 2 regex expressions to be passed and highlight the text between them when it finds a match. This can be more than once of course.
I am digging through the documentation to see if I can figure this out myself, but any help would be greatly appreciated.
Hopefully I am making sense.
Hi
Thanks for your request. Actually, you can do this using only one regex. Using regular expressions you can find any text. For example the following regex will match any word between tags:
Regex regex = new Regex("(?<=\\{mytag\\})\\S*(?=\\{mytag\\})", RegexOptions.IgnoreCase);
See also attached input and output documents.
You can learn more about regexes here:
https://www.codeproject.com/Articles/9099/The-30-Minute-Regex-Tutorial
Best regards.
While waiting for your replay I came up with the following. It works so far, but sure not as elegant as what your solution provides.
private static Aspose.Words.ReplaceAction ReplaceWithHtmlEvaluator(object sender, Aspose.Words.ReplaceEvaluatorArgs e)
{
int index = (e.MatchNode as Run).Text.IndexOf("{star}");
int index2 = (e.MatchNode as Run).Text.IndexOf("{/star}");
//Get MatchNode
Run runner = (Run)e.MatchNode;
if (index != -1 && index2 != -1)
{
runner.Text = runner.Text.Substring(index + 6, index2 - index - 6);
runner.Font.StrikeThrough = true;
//(e.MatchNode as Run).ParentParagraph.InsertBefore(runner, e.MatchNode);
(e.MatchNode as Run).ParentParagraph.InsertBefore(runner, e.MatchNode);
}
return ReplaceAction.Skip;
}
Follow up question.
I am using a modified regular expression of what you recommended above. It works great if only one pair of the star tags are present, but chokes if more than one exists. I’m leaning at this point it is more my regular expression, but have run out of ideas on what it could be. I would hate to think it was a bug in aspose holding me up.
I have attached 4 documents (in 1 zip) that shows the behavior I am seeing.
In1Tag.doc —> Out1Tag.doc Shows the text between the items properly struck through and that only 1 tag exists
In2Tag.doc —> Out2Tag.doc Shows what happens if a 2nd set of tags exists, screwing up the match process.
Thanks for your time.
System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex("(?<=\{star\}).*(?=\{star\})", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
wt.Range.Replace(regex, new Aspose.Words.ReplaceEvaluator(ReplaceWithCrossOut), true);
private static Aspose.Words.ReplaceAction ReplaceWithCrossOut(object sender, Aspose.Words.ReplaceEvaluatorArgs 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))
{
runs.Add(currentNode);
remainingLength = 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(currentNode);
}
// Now highlight all runs in the sequence.
foreach (Run run in runs)
{
// run.Font.HighlightColor = Color.Yellow;
run.Font.StrikeThrough = true;
}
// Signal to the replace engine to do nothing because we have already done all what we wanted.
return ReplaceAction.Skip;
}
Hi
Thanks for your request. The problem occurs because your regular expression is incorrect a bit. Please try using this expression:
Regex regex = new Regex("(?<=\\{star\\})[ \\S]*(?=\\{star\\})", RegexOptions.IgnoreCase);
Hope this helps.
Best regards.