How to highlight text in a sentence using OpenXML?












1















I am using below code to search and highlight text in a MS Word document, it works fine for point 1 but not point 2:



1. John Alter 


I search for Alter or John, it highlights John/Alter - works.



2. I am going to school


I search for going, it highlights going but it changes its order as I am to school going - does not work.



How to fix point 2? Below is my code.



private void HighLightText(Paragraph paragraph, string text)
{
string textOfRun = string.Empty;
var runCollection = paragraph.Descendants<DocumentFormat.OpenXml.Wordprocessing.Run>();
DocumentFormat.OpenXml.Wordprocessing.Run runAfter = null;

//find the run part which contains the characters
foreach (DocumentFormat.OpenXml.Wordprocessing.Run run in runCollection)
{
if (!string.IsNullOrWhiteSpace(paragraph.InnerText) && paragraph.InnerText != "\s")
textOfRun = run.GetFirstChild<DocumentFormat.OpenXml.Wordprocessing.Text>().Text;

if (textOfRun.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0)
{
//remove the character from this run part
run.GetFirstChild<DocumentFormat.OpenXml.Wordprocessing.Text>().Text = Regex.Replace(textOfRun, text, string.Empty, RegexOptions.IgnoreCase);//textOfRun.Replace(text, string.Empty);
runAfter = run;
break;
}
}

//create a new run with your customization font and the character as its text
DocumentFormat.OpenXml.Wordprocessing.Run HighLightRun = new DocumentFormat.OpenXml.Wordprocessing.Run();
DocumentFormat.OpenXml.Wordprocessing.RunProperties runPro = new DocumentFormat.OpenXml.Wordprocessing.RunProperties();
Highlight highlight = new Highlight() { Val = HighlightColorValues.Yellow };
DocumentFormat.OpenXml.Wordprocessing.Text runText = new DocumentFormat.OpenXml.Wordprocessing.Text() { Text = text };

runPro.Append(highlight);
HighLightRun.Append(runPro);
HighLightRun.Append(runText);

//insert the new created run part
paragraph.InsertAfter(HighLightRun, runAfter);
}









share|improve this question

























  • @pfx: Can you check this ?

    – user662285
    Nov 20 '18 at 0:15











  • can you please add the document and also any other code that allows users to easily reproduce your problem?

    – BKSpurgeon
    Nov 26 '18 at 4:50











  • I have already added code with my post and if you need document just add my point 2 to the code - Add, I am going to school to the document and use my above code it will highlight search word but it will make it like - I am school to going , here going is the word to be highlighted

    – user662285
    Nov 26 '18 at 4:54






  • 1





    paragraph.InsertAfter seems a likely culprit. Not that helpful of a comment, I know :) According to msdn.microsoft.com/en-us/library/office/… there is also an InsertAt method that may be useful?

    – Dan Rayson
    Nov 26 '18 at 11:38
















1















I am using below code to search and highlight text in a MS Word document, it works fine for point 1 but not point 2:



1. John Alter 


I search for Alter or John, it highlights John/Alter - works.



2. I am going to school


I search for going, it highlights going but it changes its order as I am to school going - does not work.



How to fix point 2? Below is my code.



private void HighLightText(Paragraph paragraph, string text)
{
string textOfRun = string.Empty;
var runCollection = paragraph.Descendants<DocumentFormat.OpenXml.Wordprocessing.Run>();
DocumentFormat.OpenXml.Wordprocessing.Run runAfter = null;

//find the run part which contains the characters
foreach (DocumentFormat.OpenXml.Wordprocessing.Run run in runCollection)
{
if (!string.IsNullOrWhiteSpace(paragraph.InnerText) && paragraph.InnerText != "\s")
textOfRun = run.GetFirstChild<DocumentFormat.OpenXml.Wordprocessing.Text>().Text;

if (textOfRun.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0)
{
//remove the character from this run part
run.GetFirstChild<DocumentFormat.OpenXml.Wordprocessing.Text>().Text = Regex.Replace(textOfRun, text, string.Empty, RegexOptions.IgnoreCase);//textOfRun.Replace(text, string.Empty);
runAfter = run;
break;
}
}

//create a new run with your customization font and the character as its text
DocumentFormat.OpenXml.Wordprocessing.Run HighLightRun = new DocumentFormat.OpenXml.Wordprocessing.Run();
DocumentFormat.OpenXml.Wordprocessing.RunProperties runPro = new DocumentFormat.OpenXml.Wordprocessing.RunProperties();
Highlight highlight = new Highlight() { Val = HighlightColorValues.Yellow };
DocumentFormat.OpenXml.Wordprocessing.Text runText = new DocumentFormat.OpenXml.Wordprocessing.Text() { Text = text };

runPro.Append(highlight);
HighLightRun.Append(runPro);
HighLightRun.Append(runText);

//insert the new created run part
paragraph.InsertAfter(HighLightRun, runAfter);
}









share|improve this question

























  • @pfx: Can you check this ?

    – user662285
    Nov 20 '18 at 0:15











  • can you please add the document and also any other code that allows users to easily reproduce your problem?

    – BKSpurgeon
    Nov 26 '18 at 4:50











  • I have already added code with my post and if you need document just add my point 2 to the code - Add, I am going to school to the document and use my above code it will highlight search word but it will make it like - I am school to going , here going is the word to be highlighted

    – user662285
    Nov 26 '18 at 4:54






  • 1





    paragraph.InsertAfter seems a likely culprit. Not that helpful of a comment, I know :) According to msdn.microsoft.com/en-us/library/office/… there is also an InsertAt method that may be useful?

    – Dan Rayson
    Nov 26 '18 at 11:38














1












1








1


0






I am using below code to search and highlight text in a MS Word document, it works fine for point 1 but not point 2:



1. John Alter 


I search for Alter or John, it highlights John/Alter - works.



2. I am going to school


I search for going, it highlights going but it changes its order as I am to school going - does not work.



How to fix point 2? Below is my code.



private void HighLightText(Paragraph paragraph, string text)
{
string textOfRun = string.Empty;
var runCollection = paragraph.Descendants<DocumentFormat.OpenXml.Wordprocessing.Run>();
DocumentFormat.OpenXml.Wordprocessing.Run runAfter = null;

//find the run part which contains the characters
foreach (DocumentFormat.OpenXml.Wordprocessing.Run run in runCollection)
{
if (!string.IsNullOrWhiteSpace(paragraph.InnerText) && paragraph.InnerText != "\s")
textOfRun = run.GetFirstChild<DocumentFormat.OpenXml.Wordprocessing.Text>().Text;

if (textOfRun.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0)
{
//remove the character from this run part
run.GetFirstChild<DocumentFormat.OpenXml.Wordprocessing.Text>().Text = Regex.Replace(textOfRun, text, string.Empty, RegexOptions.IgnoreCase);//textOfRun.Replace(text, string.Empty);
runAfter = run;
break;
}
}

//create a new run with your customization font and the character as its text
DocumentFormat.OpenXml.Wordprocessing.Run HighLightRun = new DocumentFormat.OpenXml.Wordprocessing.Run();
DocumentFormat.OpenXml.Wordprocessing.RunProperties runPro = new DocumentFormat.OpenXml.Wordprocessing.RunProperties();
Highlight highlight = new Highlight() { Val = HighlightColorValues.Yellow };
DocumentFormat.OpenXml.Wordprocessing.Text runText = new DocumentFormat.OpenXml.Wordprocessing.Text() { Text = text };

runPro.Append(highlight);
HighLightRun.Append(runPro);
HighLightRun.Append(runText);

//insert the new created run part
paragraph.InsertAfter(HighLightRun, runAfter);
}









share|improve this question
















I am using below code to search and highlight text in a MS Word document, it works fine for point 1 but not point 2:



1. John Alter 


I search for Alter or John, it highlights John/Alter - works.



2. I am going to school


I search for going, it highlights going but it changes its order as I am to school going - does not work.



How to fix point 2? Below is my code.



private void HighLightText(Paragraph paragraph, string text)
{
string textOfRun = string.Empty;
var runCollection = paragraph.Descendants<DocumentFormat.OpenXml.Wordprocessing.Run>();
DocumentFormat.OpenXml.Wordprocessing.Run runAfter = null;

//find the run part which contains the characters
foreach (DocumentFormat.OpenXml.Wordprocessing.Run run in runCollection)
{
if (!string.IsNullOrWhiteSpace(paragraph.InnerText) && paragraph.InnerText != "\s")
textOfRun = run.GetFirstChild<DocumentFormat.OpenXml.Wordprocessing.Text>().Text;

if (textOfRun.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0)
{
//remove the character from this run part
run.GetFirstChild<DocumentFormat.OpenXml.Wordprocessing.Text>().Text = Regex.Replace(textOfRun, text, string.Empty, RegexOptions.IgnoreCase);//textOfRun.Replace(text, string.Empty);
runAfter = run;
break;
}
}

//create a new run with your customization font and the character as its text
DocumentFormat.OpenXml.Wordprocessing.Run HighLightRun = new DocumentFormat.OpenXml.Wordprocessing.Run();
DocumentFormat.OpenXml.Wordprocessing.RunProperties runPro = new DocumentFormat.OpenXml.Wordprocessing.RunProperties();
Highlight highlight = new Highlight() { Val = HighlightColorValues.Yellow };
DocumentFormat.OpenXml.Wordprocessing.Text runText = new DocumentFormat.OpenXml.Wordprocessing.Text() { Text = text };

runPro.Append(highlight);
HighLightRun.Append(runPro);
HighLightRun.Append(runText);

//insert the new created run part
paragraph.InsertAfter(HighLightRun, runAfter);
}






c# openxml wordprocessingml






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 27 '18 at 16:58







user662285

















asked Nov 20 '18 at 0:13









user662285user662285

1,273155684




1,273155684













  • @pfx: Can you check this ?

    – user662285
    Nov 20 '18 at 0:15











  • can you please add the document and also any other code that allows users to easily reproduce your problem?

    – BKSpurgeon
    Nov 26 '18 at 4:50











  • I have already added code with my post and if you need document just add my point 2 to the code - Add, I am going to school to the document and use my above code it will highlight search word but it will make it like - I am school to going , here going is the word to be highlighted

    – user662285
    Nov 26 '18 at 4:54






  • 1





    paragraph.InsertAfter seems a likely culprit. Not that helpful of a comment, I know :) According to msdn.microsoft.com/en-us/library/office/… there is also an InsertAt method that may be useful?

    – Dan Rayson
    Nov 26 '18 at 11:38



















  • @pfx: Can you check this ?

    – user662285
    Nov 20 '18 at 0:15











  • can you please add the document and also any other code that allows users to easily reproduce your problem?

    – BKSpurgeon
    Nov 26 '18 at 4:50











  • I have already added code with my post and if you need document just add my point 2 to the code - Add, I am going to school to the document and use my above code it will highlight search word but it will make it like - I am school to going , here going is the word to be highlighted

    – user662285
    Nov 26 '18 at 4:54






  • 1





    paragraph.InsertAfter seems a likely culprit. Not that helpful of a comment, I know :) According to msdn.microsoft.com/en-us/library/office/… there is also an InsertAt method that may be useful?

    – Dan Rayson
    Nov 26 '18 at 11:38

















@pfx: Can you check this ?

– user662285
Nov 20 '18 at 0:15





@pfx: Can you check this ?

– user662285
Nov 20 '18 at 0:15













can you please add the document and also any other code that allows users to easily reproduce your problem?

– BKSpurgeon
Nov 26 '18 at 4:50





can you please add the document and also any other code that allows users to easily reproduce your problem?

– BKSpurgeon
Nov 26 '18 at 4:50













I have already added code with my post and if you need document just add my point 2 to the code - Add, I am going to school to the document and use my above code it will highlight search word but it will make it like - I am school to going , here going is the word to be highlighted

– user662285
Nov 26 '18 at 4:54





I have already added code with my post and if you need document just add my point 2 to the code - Add, I am going to school to the document and use my above code it will highlight search word but it will make it like - I am school to going , here going is the word to be highlighted

– user662285
Nov 26 '18 at 4:54




1




1





paragraph.InsertAfter seems a likely culprit. Not that helpful of a comment, I know :) According to msdn.microsoft.com/en-us/library/office/… there is also an InsertAt method that may be useful?

– Dan Rayson
Nov 26 '18 at 11:38





paragraph.InsertAfter seems a likely culprit. Not that helpful of a comment, I know :) According to msdn.microsoft.com/en-us/library/office/… there is also an InsertAt method that may be useful?

– Dan Rayson
Nov 26 '18 at 11:38












1 Answer
1






active

oldest

votes


















1





+100









You need to split-up your Run if you want to highlight some text in the middle of that Run. So replacing the search text with an empty string won't work.



Your original text structure looks like:



<Run>
<Text>
I am going to school
</Text>
</Run>


If you want to highlight the going word, you need to make a more complex structure out of it:



<Run>
<Text>
I am
</Text>
</Run>
<Run>
<Text>
going
</Text>
</Run>
<Run>
<Text>
to school
</Text>
</Run>


Then, the Run in the middle can be set-up for highlighting.



Here is a working code sample. Please note, there's no error handing in this code! It should give you some idea how to solve your task. Implement the proper exception handing for production usage!



Also note that this sample only searches for the first occurrence, as it is in your code. If you need to highlight multiple search matches, you will have to improve this code.



void HighLightText(Paragraph paragraph, string text)
{
// Search for a first occurrence of the text in the text runs
var found = paragraph
.Descendants<Run>()
.Where(r => !string.IsNullOrEmpty(r.InnerText) && r.InnerText != "\s")
.Select(r =>
{
var runText = r.GetFirstChild<Text>();
int index = runText.Text.IndexOf(text, StringComparison.OrdinalIgnoreCase);

// 'Run' is a reference to the text run we found,
// TextNode is a reference to the run's Text object,
// 'TokenIndex` is the index of the search string in run's text
return new { Run = r, TextNode = runText, TokenIndex = index };
})
.FirstOrDefault(o => o.TokenIndex >= 0);

// Nothing found -- escape
if (found == null)
{
return;
}

// Create a node for highlighted text as a clone (to preserve formatting etc)
var highlightRun = found.Run.CloneNode(true);

// Add the highlight node after the found text run and set up the highlighting
paragraph.InsertAfter(highlightRun, found.Run);
highlightRun.GetFirstChild<Text>().Text = text;
RunProperties runPro = new RunProperties();
Highlight highlight = new Highlight { Val = HighlightColorValues.Yellow };

runPro.AppendChild(highlight);
highlightRun.InsertAt(runPro, 0);

// Check if there's some text in the text run *after* the found text
int remainderLength = found.TextNode.Text.Length - found.TokenIndex - text.Length;
if (remainderLength > 0)
{
// There is some text after the highlighted section --
// insert it in a separate text run after the highlighted text run
var remainderRun = found.Run.CloneNode(true);
paragraph.InsertAfter(remainderRun, highlightRun);
var textNode = remainderRun.GetFirstChild<Text>();
textNode.Text = found.TextNode.Text.Substring(found.TokenIndex + text.Length);

// We need to set up this to preserve the spaces between text runs
textNode.Space = new EnumValue<SpaceProcessingModeValues>(SpaceProcessingModeValues.Preserve);
}

// Check if there's some text *before* the found text
if (found.TokenIndex > 0)
{
// Something is left before the highlighted text,
// so make the original text run contain only that portion
found.TextNode.Text = found.TextNode.Text.Remove(found.TokenIndex);

// We need to set up this to preserve the spaces between text runs
found.TextNode.Space = new EnumValue<SpaceProcessingModeValues>(SpaceProcessingModeValues.Preserve);
}
else
{
// There's nothing before the highlighted text -- remove the unneeded text run
paragraph.RemoveChild(found.Run);
}
}


This code works for highlighting the I, going, or school words in the I am going to school sentence.






share|improve this answer
























  • Thanks,Your code is working with some changes. However same approach does not work for presentation(.pptx) documents..I have updated the code above for same..it corrupts the file and ask to repair while opening pptx and after opening it highlights the word but it does not preserves the formatting..can you help on same ?

    – user662285
    Nov 26 '18 at 22:31











  • @user662285 changing the scope of a question like that (moving the goal post) is never cool. Especially as the provided answer would have been originally crafted based on the original request targeting word documents.

    – Nkosi
    Nov 26 '18 at 23:16













  • my above question does not mean i will not give bounty points, irrespective of whether it is answered for pptx or not, i am just curious to understand why it does not work for pptx as both uses run and text...My intention is not to change the scope of the question

    – user662285
    Nov 26 '18 at 23:19













  • @user662285 noted and understood.

    – Nkosi
    Nov 26 '18 at 23:39






  • 1





    This code only works for Wordprocessing.Paragraph. I am pretty sure it will not work for OpenXmlDrawing.Paragraph. For PowerPoint, you should ask another question because the XML structure of the PowerPoint documents is different.

    – dymanoid
    Nov 27 '18 at 16:41











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53384447%2fhow-to-highlight-text-in-a-sentence-using-openxml%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









1





+100









You need to split-up your Run if you want to highlight some text in the middle of that Run. So replacing the search text with an empty string won't work.



Your original text structure looks like:



<Run>
<Text>
I am going to school
</Text>
</Run>


If you want to highlight the going word, you need to make a more complex structure out of it:



<Run>
<Text>
I am
</Text>
</Run>
<Run>
<Text>
going
</Text>
</Run>
<Run>
<Text>
to school
</Text>
</Run>


Then, the Run in the middle can be set-up for highlighting.



Here is a working code sample. Please note, there's no error handing in this code! It should give you some idea how to solve your task. Implement the proper exception handing for production usage!



Also note that this sample only searches for the first occurrence, as it is in your code. If you need to highlight multiple search matches, you will have to improve this code.



void HighLightText(Paragraph paragraph, string text)
{
// Search for a first occurrence of the text in the text runs
var found = paragraph
.Descendants<Run>()
.Where(r => !string.IsNullOrEmpty(r.InnerText) && r.InnerText != "\s")
.Select(r =>
{
var runText = r.GetFirstChild<Text>();
int index = runText.Text.IndexOf(text, StringComparison.OrdinalIgnoreCase);

// 'Run' is a reference to the text run we found,
// TextNode is a reference to the run's Text object,
// 'TokenIndex` is the index of the search string in run's text
return new { Run = r, TextNode = runText, TokenIndex = index };
})
.FirstOrDefault(o => o.TokenIndex >= 0);

// Nothing found -- escape
if (found == null)
{
return;
}

// Create a node for highlighted text as a clone (to preserve formatting etc)
var highlightRun = found.Run.CloneNode(true);

// Add the highlight node after the found text run and set up the highlighting
paragraph.InsertAfter(highlightRun, found.Run);
highlightRun.GetFirstChild<Text>().Text = text;
RunProperties runPro = new RunProperties();
Highlight highlight = new Highlight { Val = HighlightColorValues.Yellow };

runPro.AppendChild(highlight);
highlightRun.InsertAt(runPro, 0);

// Check if there's some text in the text run *after* the found text
int remainderLength = found.TextNode.Text.Length - found.TokenIndex - text.Length;
if (remainderLength > 0)
{
// There is some text after the highlighted section --
// insert it in a separate text run after the highlighted text run
var remainderRun = found.Run.CloneNode(true);
paragraph.InsertAfter(remainderRun, highlightRun);
var textNode = remainderRun.GetFirstChild<Text>();
textNode.Text = found.TextNode.Text.Substring(found.TokenIndex + text.Length);

// We need to set up this to preserve the spaces between text runs
textNode.Space = new EnumValue<SpaceProcessingModeValues>(SpaceProcessingModeValues.Preserve);
}

// Check if there's some text *before* the found text
if (found.TokenIndex > 0)
{
// Something is left before the highlighted text,
// so make the original text run contain only that portion
found.TextNode.Text = found.TextNode.Text.Remove(found.TokenIndex);

// We need to set up this to preserve the spaces between text runs
found.TextNode.Space = new EnumValue<SpaceProcessingModeValues>(SpaceProcessingModeValues.Preserve);
}
else
{
// There's nothing before the highlighted text -- remove the unneeded text run
paragraph.RemoveChild(found.Run);
}
}


This code works for highlighting the I, going, or school words in the I am going to school sentence.






share|improve this answer
























  • Thanks,Your code is working with some changes. However same approach does not work for presentation(.pptx) documents..I have updated the code above for same..it corrupts the file and ask to repair while opening pptx and after opening it highlights the word but it does not preserves the formatting..can you help on same ?

    – user662285
    Nov 26 '18 at 22:31











  • @user662285 changing the scope of a question like that (moving the goal post) is never cool. Especially as the provided answer would have been originally crafted based on the original request targeting word documents.

    – Nkosi
    Nov 26 '18 at 23:16













  • my above question does not mean i will not give bounty points, irrespective of whether it is answered for pptx or not, i am just curious to understand why it does not work for pptx as both uses run and text...My intention is not to change the scope of the question

    – user662285
    Nov 26 '18 at 23:19













  • @user662285 noted and understood.

    – Nkosi
    Nov 26 '18 at 23:39






  • 1





    This code only works for Wordprocessing.Paragraph. I am pretty sure it will not work for OpenXmlDrawing.Paragraph. For PowerPoint, you should ask another question because the XML structure of the PowerPoint documents is different.

    – dymanoid
    Nov 27 '18 at 16:41
















1





+100









You need to split-up your Run if you want to highlight some text in the middle of that Run. So replacing the search text with an empty string won't work.



Your original text structure looks like:



<Run>
<Text>
I am going to school
</Text>
</Run>


If you want to highlight the going word, you need to make a more complex structure out of it:



<Run>
<Text>
I am
</Text>
</Run>
<Run>
<Text>
going
</Text>
</Run>
<Run>
<Text>
to school
</Text>
</Run>


Then, the Run in the middle can be set-up for highlighting.



Here is a working code sample. Please note, there's no error handing in this code! It should give you some idea how to solve your task. Implement the proper exception handing for production usage!



Also note that this sample only searches for the first occurrence, as it is in your code. If you need to highlight multiple search matches, you will have to improve this code.



void HighLightText(Paragraph paragraph, string text)
{
// Search for a first occurrence of the text in the text runs
var found = paragraph
.Descendants<Run>()
.Where(r => !string.IsNullOrEmpty(r.InnerText) && r.InnerText != "\s")
.Select(r =>
{
var runText = r.GetFirstChild<Text>();
int index = runText.Text.IndexOf(text, StringComparison.OrdinalIgnoreCase);

// 'Run' is a reference to the text run we found,
// TextNode is a reference to the run's Text object,
// 'TokenIndex` is the index of the search string in run's text
return new { Run = r, TextNode = runText, TokenIndex = index };
})
.FirstOrDefault(o => o.TokenIndex >= 0);

// Nothing found -- escape
if (found == null)
{
return;
}

// Create a node for highlighted text as a clone (to preserve formatting etc)
var highlightRun = found.Run.CloneNode(true);

// Add the highlight node after the found text run and set up the highlighting
paragraph.InsertAfter(highlightRun, found.Run);
highlightRun.GetFirstChild<Text>().Text = text;
RunProperties runPro = new RunProperties();
Highlight highlight = new Highlight { Val = HighlightColorValues.Yellow };

runPro.AppendChild(highlight);
highlightRun.InsertAt(runPro, 0);

// Check if there's some text in the text run *after* the found text
int remainderLength = found.TextNode.Text.Length - found.TokenIndex - text.Length;
if (remainderLength > 0)
{
// There is some text after the highlighted section --
// insert it in a separate text run after the highlighted text run
var remainderRun = found.Run.CloneNode(true);
paragraph.InsertAfter(remainderRun, highlightRun);
var textNode = remainderRun.GetFirstChild<Text>();
textNode.Text = found.TextNode.Text.Substring(found.TokenIndex + text.Length);

// We need to set up this to preserve the spaces between text runs
textNode.Space = new EnumValue<SpaceProcessingModeValues>(SpaceProcessingModeValues.Preserve);
}

// Check if there's some text *before* the found text
if (found.TokenIndex > 0)
{
// Something is left before the highlighted text,
// so make the original text run contain only that portion
found.TextNode.Text = found.TextNode.Text.Remove(found.TokenIndex);

// We need to set up this to preserve the spaces between text runs
found.TextNode.Space = new EnumValue<SpaceProcessingModeValues>(SpaceProcessingModeValues.Preserve);
}
else
{
// There's nothing before the highlighted text -- remove the unneeded text run
paragraph.RemoveChild(found.Run);
}
}


This code works for highlighting the I, going, or school words in the I am going to school sentence.






share|improve this answer
























  • Thanks,Your code is working with some changes. However same approach does not work for presentation(.pptx) documents..I have updated the code above for same..it corrupts the file and ask to repair while opening pptx and after opening it highlights the word but it does not preserves the formatting..can you help on same ?

    – user662285
    Nov 26 '18 at 22:31











  • @user662285 changing the scope of a question like that (moving the goal post) is never cool. Especially as the provided answer would have been originally crafted based on the original request targeting word documents.

    – Nkosi
    Nov 26 '18 at 23:16













  • my above question does not mean i will not give bounty points, irrespective of whether it is answered for pptx or not, i am just curious to understand why it does not work for pptx as both uses run and text...My intention is not to change the scope of the question

    – user662285
    Nov 26 '18 at 23:19













  • @user662285 noted and understood.

    – Nkosi
    Nov 26 '18 at 23:39






  • 1





    This code only works for Wordprocessing.Paragraph. I am pretty sure it will not work for OpenXmlDrawing.Paragraph. For PowerPoint, you should ask another question because the XML structure of the PowerPoint documents is different.

    – dymanoid
    Nov 27 '18 at 16:41














1





+100







1





+100



1




+100





You need to split-up your Run if you want to highlight some text in the middle of that Run. So replacing the search text with an empty string won't work.



Your original text structure looks like:



<Run>
<Text>
I am going to school
</Text>
</Run>


If you want to highlight the going word, you need to make a more complex structure out of it:



<Run>
<Text>
I am
</Text>
</Run>
<Run>
<Text>
going
</Text>
</Run>
<Run>
<Text>
to school
</Text>
</Run>


Then, the Run in the middle can be set-up for highlighting.



Here is a working code sample. Please note, there's no error handing in this code! It should give you some idea how to solve your task. Implement the proper exception handing for production usage!



Also note that this sample only searches for the first occurrence, as it is in your code. If you need to highlight multiple search matches, you will have to improve this code.



void HighLightText(Paragraph paragraph, string text)
{
// Search for a first occurrence of the text in the text runs
var found = paragraph
.Descendants<Run>()
.Where(r => !string.IsNullOrEmpty(r.InnerText) && r.InnerText != "\s")
.Select(r =>
{
var runText = r.GetFirstChild<Text>();
int index = runText.Text.IndexOf(text, StringComparison.OrdinalIgnoreCase);

// 'Run' is a reference to the text run we found,
// TextNode is a reference to the run's Text object,
// 'TokenIndex` is the index of the search string in run's text
return new { Run = r, TextNode = runText, TokenIndex = index };
})
.FirstOrDefault(o => o.TokenIndex >= 0);

// Nothing found -- escape
if (found == null)
{
return;
}

// Create a node for highlighted text as a clone (to preserve formatting etc)
var highlightRun = found.Run.CloneNode(true);

// Add the highlight node after the found text run and set up the highlighting
paragraph.InsertAfter(highlightRun, found.Run);
highlightRun.GetFirstChild<Text>().Text = text;
RunProperties runPro = new RunProperties();
Highlight highlight = new Highlight { Val = HighlightColorValues.Yellow };

runPro.AppendChild(highlight);
highlightRun.InsertAt(runPro, 0);

// Check if there's some text in the text run *after* the found text
int remainderLength = found.TextNode.Text.Length - found.TokenIndex - text.Length;
if (remainderLength > 0)
{
// There is some text after the highlighted section --
// insert it in a separate text run after the highlighted text run
var remainderRun = found.Run.CloneNode(true);
paragraph.InsertAfter(remainderRun, highlightRun);
var textNode = remainderRun.GetFirstChild<Text>();
textNode.Text = found.TextNode.Text.Substring(found.TokenIndex + text.Length);

// We need to set up this to preserve the spaces between text runs
textNode.Space = new EnumValue<SpaceProcessingModeValues>(SpaceProcessingModeValues.Preserve);
}

// Check if there's some text *before* the found text
if (found.TokenIndex > 0)
{
// Something is left before the highlighted text,
// so make the original text run contain only that portion
found.TextNode.Text = found.TextNode.Text.Remove(found.TokenIndex);

// We need to set up this to preserve the spaces between text runs
found.TextNode.Space = new EnumValue<SpaceProcessingModeValues>(SpaceProcessingModeValues.Preserve);
}
else
{
// There's nothing before the highlighted text -- remove the unneeded text run
paragraph.RemoveChild(found.Run);
}
}


This code works for highlighting the I, going, or school words in the I am going to school sentence.






share|improve this answer













You need to split-up your Run if you want to highlight some text in the middle of that Run. So replacing the search text with an empty string won't work.



Your original text structure looks like:



<Run>
<Text>
I am going to school
</Text>
</Run>


If you want to highlight the going word, you need to make a more complex structure out of it:



<Run>
<Text>
I am
</Text>
</Run>
<Run>
<Text>
going
</Text>
</Run>
<Run>
<Text>
to school
</Text>
</Run>


Then, the Run in the middle can be set-up for highlighting.



Here is a working code sample. Please note, there's no error handing in this code! It should give you some idea how to solve your task. Implement the proper exception handing for production usage!



Also note that this sample only searches for the first occurrence, as it is in your code. If you need to highlight multiple search matches, you will have to improve this code.



void HighLightText(Paragraph paragraph, string text)
{
// Search for a first occurrence of the text in the text runs
var found = paragraph
.Descendants<Run>()
.Where(r => !string.IsNullOrEmpty(r.InnerText) && r.InnerText != "\s")
.Select(r =>
{
var runText = r.GetFirstChild<Text>();
int index = runText.Text.IndexOf(text, StringComparison.OrdinalIgnoreCase);

// 'Run' is a reference to the text run we found,
// TextNode is a reference to the run's Text object,
// 'TokenIndex` is the index of the search string in run's text
return new { Run = r, TextNode = runText, TokenIndex = index };
})
.FirstOrDefault(o => o.TokenIndex >= 0);

// Nothing found -- escape
if (found == null)
{
return;
}

// Create a node for highlighted text as a clone (to preserve formatting etc)
var highlightRun = found.Run.CloneNode(true);

// Add the highlight node after the found text run and set up the highlighting
paragraph.InsertAfter(highlightRun, found.Run);
highlightRun.GetFirstChild<Text>().Text = text;
RunProperties runPro = new RunProperties();
Highlight highlight = new Highlight { Val = HighlightColorValues.Yellow };

runPro.AppendChild(highlight);
highlightRun.InsertAt(runPro, 0);

// Check if there's some text in the text run *after* the found text
int remainderLength = found.TextNode.Text.Length - found.TokenIndex - text.Length;
if (remainderLength > 0)
{
// There is some text after the highlighted section --
// insert it in a separate text run after the highlighted text run
var remainderRun = found.Run.CloneNode(true);
paragraph.InsertAfter(remainderRun, highlightRun);
var textNode = remainderRun.GetFirstChild<Text>();
textNode.Text = found.TextNode.Text.Substring(found.TokenIndex + text.Length);

// We need to set up this to preserve the spaces between text runs
textNode.Space = new EnumValue<SpaceProcessingModeValues>(SpaceProcessingModeValues.Preserve);
}

// Check if there's some text *before* the found text
if (found.TokenIndex > 0)
{
// Something is left before the highlighted text,
// so make the original text run contain only that portion
found.TextNode.Text = found.TextNode.Text.Remove(found.TokenIndex);

// We need to set up this to preserve the spaces between text runs
found.TextNode.Space = new EnumValue<SpaceProcessingModeValues>(SpaceProcessingModeValues.Preserve);
}
else
{
// There's nothing before the highlighted text -- remove the unneeded text run
paragraph.RemoveChild(found.Run);
}
}


This code works for highlighting the I, going, or school words in the I am going to school sentence.







share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 26 '18 at 13:50









dymanoiddymanoid

9,26722248




9,26722248













  • Thanks,Your code is working with some changes. However same approach does not work for presentation(.pptx) documents..I have updated the code above for same..it corrupts the file and ask to repair while opening pptx and after opening it highlights the word but it does not preserves the formatting..can you help on same ?

    – user662285
    Nov 26 '18 at 22:31











  • @user662285 changing the scope of a question like that (moving the goal post) is never cool. Especially as the provided answer would have been originally crafted based on the original request targeting word documents.

    – Nkosi
    Nov 26 '18 at 23:16













  • my above question does not mean i will not give bounty points, irrespective of whether it is answered for pptx or not, i am just curious to understand why it does not work for pptx as both uses run and text...My intention is not to change the scope of the question

    – user662285
    Nov 26 '18 at 23:19













  • @user662285 noted and understood.

    – Nkosi
    Nov 26 '18 at 23:39






  • 1





    This code only works for Wordprocessing.Paragraph. I am pretty sure it will not work for OpenXmlDrawing.Paragraph. For PowerPoint, you should ask another question because the XML structure of the PowerPoint documents is different.

    – dymanoid
    Nov 27 '18 at 16:41



















  • Thanks,Your code is working with some changes. However same approach does not work for presentation(.pptx) documents..I have updated the code above for same..it corrupts the file and ask to repair while opening pptx and after opening it highlights the word but it does not preserves the formatting..can you help on same ?

    – user662285
    Nov 26 '18 at 22:31











  • @user662285 changing the scope of a question like that (moving the goal post) is never cool. Especially as the provided answer would have been originally crafted based on the original request targeting word documents.

    – Nkosi
    Nov 26 '18 at 23:16













  • my above question does not mean i will not give bounty points, irrespective of whether it is answered for pptx or not, i am just curious to understand why it does not work for pptx as both uses run and text...My intention is not to change the scope of the question

    – user662285
    Nov 26 '18 at 23:19













  • @user662285 noted and understood.

    – Nkosi
    Nov 26 '18 at 23:39






  • 1





    This code only works for Wordprocessing.Paragraph. I am pretty sure it will not work for OpenXmlDrawing.Paragraph. For PowerPoint, you should ask another question because the XML structure of the PowerPoint documents is different.

    – dymanoid
    Nov 27 '18 at 16:41

















Thanks,Your code is working with some changes. However same approach does not work for presentation(.pptx) documents..I have updated the code above for same..it corrupts the file and ask to repair while opening pptx and after opening it highlights the word but it does not preserves the formatting..can you help on same ?

– user662285
Nov 26 '18 at 22:31





Thanks,Your code is working with some changes. However same approach does not work for presentation(.pptx) documents..I have updated the code above for same..it corrupts the file and ask to repair while opening pptx and after opening it highlights the word but it does not preserves the formatting..can you help on same ?

– user662285
Nov 26 '18 at 22:31













@user662285 changing the scope of a question like that (moving the goal post) is never cool. Especially as the provided answer would have been originally crafted based on the original request targeting word documents.

– Nkosi
Nov 26 '18 at 23:16







@user662285 changing the scope of a question like that (moving the goal post) is never cool. Especially as the provided answer would have been originally crafted based on the original request targeting word documents.

– Nkosi
Nov 26 '18 at 23:16















my above question does not mean i will not give bounty points, irrespective of whether it is answered for pptx or not, i am just curious to understand why it does not work for pptx as both uses run and text...My intention is not to change the scope of the question

– user662285
Nov 26 '18 at 23:19







my above question does not mean i will not give bounty points, irrespective of whether it is answered for pptx or not, i am just curious to understand why it does not work for pptx as both uses run and text...My intention is not to change the scope of the question

– user662285
Nov 26 '18 at 23:19















@user662285 noted and understood.

– Nkosi
Nov 26 '18 at 23:39





@user662285 noted and understood.

– Nkosi
Nov 26 '18 at 23:39




1




1





This code only works for Wordprocessing.Paragraph. I am pretty sure it will not work for OpenXmlDrawing.Paragraph. For PowerPoint, you should ask another question because the XML structure of the PowerPoint documents is different.

– dymanoid
Nov 27 '18 at 16:41





This code only works for Wordprocessing.Paragraph. I am pretty sure it will not work for OpenXmlDrawing.Paragraph. For PowerPoint, you should ask another question because the XML structure of the PowerPoint documents is different.

– dymanoid
Nov 27 '18 at 16:41




















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53384447%2fhow-to-highlight-text-in-a-sentence-using-openxml%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

鏡平學校

ꓛꓣだゔៀៅຸ໢ທຮ໕໒ ,ໂ'໥໓າ໼ឨឲ៵៭ៈゎゔit''䖳𥁄卿' ☨₤₨こゎもょの;ꜹꟚꞖꞵꟅꞛေၦေɯ,ɨɡ𛃵𛁹ޝ޳ޠ޾,ޤޒޯ޾𫝒𫠁သ𛅤チョ'サノބޘދ𛁐ᶿᶇᶀᶋᶠ㨑㽹⻮ꧬ꧹؍۩وَؠ㇕㇃㇪ ㇦㇋㇋ṜẰᵡᴠ 軌ᵕ搜۳ٰޗޮ޷ސޯ𫖾𫅀ल, ꙭ꙰ꚅꙁꚊꞻꝔ꟠Ꝭㄤﺟޱސꧨꧼ꧴ꧯꧽ꧲ꧯ'⽹⽭⾁⿞⼳⽋២៩ញណើꩯꩤ꩸ꩮᶻᶺᶧᶂ𫳲𫪭𬸄𫵰𬖩𬫣𬊉ၲ𛅬㕦䬺𫝌𫝼,,𫟖𫞽ហៅ஫㆔ాఆఅꙒꚞꙍ,Ꙟ꙱エ ,ポテ,フࢰࢯ𫟠𫞶 𫝤𫟠ﺕﹱﻜﻣ𪵕𪭸𪻆𪾩𫔷ġ,ŧآꞪ꟥,ꞔꝻ♚☹⛵𛀌ꬷꭞȄƁƪƬșƦǙǗdžƝǯǧⱦⱰꓕꓢႋ神 ဴ၀க௭எ௫ឫោ ' េㇷㇴㇼ神ㇸㇲㇽㇴㇼㇻㇸ'ㇸㇿㇸㇹㇰㆣꓚꓤ₡₧ ㄨㄟ㄂ㄖㄎ໗ツڒذ₶।ऩछएोञयूटक़कयँृी,冬'𛅢𛅥ㇱㇵㇶ𥄥𦒽𠣧𠊓𧢖𥞘𩔋цѰㄠſtʯʭɿʆʗʍʩɷɛ,əʏダヵㄐㄘR{gỚṖḺờṠṫảḙḭᴮᵏᴘᵀᵷᵕᴜᴏᵾq﮲ﲿﴽﭙ軌ﰬﶚﶧ﫲Ҝжюїкӈㇴffצּ﬘﭅﬈軌'ffistfflſtffतभफɳɰʊɲʎ𛁱𛁖𛁮𛀉 𛂯𛀞నఋŀŲ 𫟲𫠖𫞺ຆຆ ໹້໕໗ๆทԊꧢꧠ꧰ꓱ⿝⼑ŎḬẃẖỐẅ ,ờỰỈỗﮊDžȩꭏꭎꬻ꭮ꬿꭖꭥꭅ㇭神 ⾈ꓵꓑ⺄㄄ㄪㄙㄅㄇstA۵䞽ॶ𫞑𫝄㇉㇇゜軌𩜛𩳠Jﻺ‚Üမ႕ႌႊၐၸဓၞၞၡ៸wyvtᶎᶪᶹစဎ꣡꣰꣢꣤ٗ؋لㇳㇾㇻㇱ㆐㆔,,㆟Ⱶヤマފ޼ޝަݿݞݠݷݐ',ݘ,ݪݙݵ𬝉𬜁𫝨𫞘くせぉて¼óû×ó£…𛅑הㄙくԗԀ5606神45,神796'𪤻𫞧ꓐ㄁ㄘɥɺꓵꓲ3''7034׉ⱦⱠˆ“𫝋ȍ,ꩲ軌꩷ꩶꩧꩫఞ۔فڱێظペサ神ナᴦᵑ47 9238їﻂ䐊䔉㠸﬎ffiﬣ,לּᴷᴦᵛᵽ,ᴨᵤ ᵸᵥᴗᵈꚏꚉꚟ⻆rtǟƴ𬎎

Why https connections are so slow when debugging (stepping over) in Java?