Как выделить текст в предложении, используя OpenXML? - PullRequest
0 голосов
/ 20 ноября 2018

Я использую приведенный ниже код для поиска и выделения текста в документе MS Word, он отлично работает для пункта 1, но не для пункта 2:

1. John Alter 

Я ищу Alter или John, он выделяет John / Alter - работает.

2. I am going to school

Я ищу going, он выделяет going, но меняет свой порядок на I am to school going - не работает.

Как исправить точку 2? Ниже мой код.

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

1 Ответ

0 голосов
/ 26 ноября 2018

Вам нужно разделить ваш Run, если вы хотите выделить какой-то текст в середине этого Run.Поэтому замена текста поиска на пустую строку не будет работать.

Ваша исходная структура текста выглядит следующим образом:

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

Если вы хотите выделить слово going, вам нужносделайте из него более сложную структуру:

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

Затем можно выделить Run в середине для выделения.

Вот пример рабочего кода.Обратите внимание, в этом коде нет ошибок при передаче !Это должно дать вам представление о том, как решить вашу задачу.Реализуйте правильную обработку исключений для производственного использования!

Также обратите внимание, что этот пример ищет только первое вхождение, как в вашем коде.Если вам нужно выделить несколько поисковых запросов, вам нужно будет улучшить этот код.

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, going или school в I am going to schoolпредложение.

...