如何使用OpenXML高亮显示句子中的文本? [英] How to highlight text in a sentence using OpenXML?

查看:136
本文介绍了如何使用OpenXML高亮显示句子中的文本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用下面的代码搜索并突出显示MS Word文档中的文本,它对第1点有效,但对第2点无效:

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 

我搜索AlterJohn,它突出显示John/Alter-有效.

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

2. I am going to school

我搜索going,它突出显示了going,但是它更改了I am to school going的顺序-不起作用.

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

如何解决第2点?下面是我的代码.

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);    
}

推荐答案

如果要突出显示Run中间的某些文本,则需要拆分Run.因此,用空字符串替换搜索文本将无效.

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>

如果要突出显示going单词,则需要使用它来构建更复杂的结构:

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>

然后,可以设置中间的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);
    }
}

此代码用于突出显示I am going to school句子中的Igoingschool单词.

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

这篇关于如何使用OpenXML高亮显示句子中的文本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆