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

Я использую приведенный ниже код для выделения текста в презентации Power Point (.pptx), используя openxml, но ниже код для pptx - он повреждает файл и просит исправить при открытии pptx и после открытия выделяет слово, но это не сохраняетформатирование.Итак, всего 2 проблемы:

1. File gets corrupted
2. Formatting is not preserved
But it highlights the text which i want (but it does not preserve formatting)

I have debuged my code line by line and problem is at below line, but i am not able to figure out what is the problem.

    highlightRun.InsertAt(runPro, 0);

Я использовал инструмент производительности openxml для сравнения двух файлов pptx один с выделением одного без выделения: я вижу разницу, как показано ниже: я не использую два раза RunProperties, но этопоказывает 2 раза:

Поврежденный файл:

public Run GenerateRun()
        {
            Run run1 = new Run();

            RunProperties runProperties1 = new RunProperties(){ Language = "en-US", Dirty = false };
            runProperties1.SetAttribute(new OpenXmlAttribute("", "smtClean", "", "0"));

            SolidFill solidFill1 = new SolidFill();
            RgbColorModelHex rgbColorModelHex1 = new RgbColorModelHex(){ Val = "FFF000" };

            solidFill1.Append(rgbColorModelHex1);

            runProperties1.Append(solidFill1);

            RunProperties runProperties2 = new RunProperties(){ Language = "en-US", Dirty = false };
            runProperties2.SetAttribute(new OpenXmlAttribute("", "smtClean", "", "0"));

            SolidFill solidFill2 = new SolidFill();
            RgbColorModelHex rgbColorModelHex2 = new RgbColorModelHex(){ Val = "FFFF00" };

            solidFill2.Append(rgbColorModelHex2);

            runProperties2.Append(solidFill2);
            Text text1 = new Text();
            text1.Text = "gaits";

            run1.Append(runProperties1);
            run1.Append(runProperties2);
            run1.Append(text1);
            return run1;

}

<a:r xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
  <a:rPr lang="en-US" dirty="0" smtClean="0">
    <a:solidFill>
      <a:srgbClr val="FFF000" />
    </a:solidFill>
  </a:rPr>
  <a:rPr lang="en-US" dirty="0" smtClean="0">
    <a:solidFill>
      <a:srgbClr val="FFFF00" />
    </a:solidFill>
  </a:rPr>
  <a:t>gaits</a:t>
</a:r>

Правильный файл:

    public class GeneratedClass
    {
        // Creates an Run instance and adds its children.
        public Run GenerateRun()
        {
            Run run1 = new Run();

            RunProperties runProperties1 = new RunProperties(){ Language = "en-US", Dirty = false };
            runProperties1.SetAttribute(new OpenXmlAttribute("", "smtClean", "", "0"));

            SolidFill solidFill1 = new SolidFill();
            RgbColorModelHex rgbColorModelHex1 = new RgbColorModelHex(){ Val = "FFFF00" };

            solidFill1.Append(rgbColorModelHex1);

            runProperties1.Append(solidFill1);
            Text text1 = new Text();
            text1.Text = "gaits";

            run1.Append(runProperties1);
            run1.Append(text1);
            return run1;
        }

<a:r xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
  <a:rPr lang="en-US" dirty="0" smtClean="0">
    <a:solidFill>
      <a:srgbClr val="FFFF00" />
    </a:solidFill>
  </a:rPr>
  <a:t>gaits</a:t>
</a:r>

Чего мне не хватает?Мой полный код приведен ниже:

using OpenXmlDrawing = DocumentFormat.OpenXml.Drawing;
      private void HighLightTextPresentation(OpenXmlDrawing.Paragraph paragraph, string text)
            {           

                var found = paragraph
                    .Descendants<OpenXmlDrawing.Run>()
                    .Where(r => !string.IsNullOrEmpty(r.InnerText) && r.InnerText != "\\s")
                    .Select(r =>
                    {
                        var runText = r.GetFirstChild<OpenXmlDrawing.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<OpenXmlDrawing.Text>().Text = text;

                DocumentFormat.OpenXml.Drawing.RunProperties runPro = new DocumentFormat.OpenXml.Drawing.RunProperties() { Language = "en-US", Dirty = false };
                runPro.SetAttribute(new OpenXmlAttribute("", "smtClean", "", "0"));

                //Apply color to searched text
                DocumentFormat.OpenXml.Drawing.SolidFill solidFill1 = new DocumentFormat.OpenXml.Drawing.SolidFill();
                DocumentFormat.OpenXml.Drawing.RgbColorModelHex rgbColorModelHex1 = new DocumentFormat.OpenXml.Drawing.RgbColorModelHex() { Val = "FFF000" };//Set Font-Color to Green (Hex "00B050").
                solidFill1.Append(rgbColorModelHex1);

                runPro.Append(solidFill1);
                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);
                    OpenXmlDrawing.Text textNode = remainderRun.GetFirstChild<OpenXmlDrawing.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);
                }
            }

1 Ответ

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

Как отмечается в комментариях, причина «повреждения» заключается в том, что вы делаете структуру XML недействительной, создавая дополнительный элемент a:rPr (RunProperties) в элементе a:r (Run), в то время как толькодопускается один.

Поэтому прежде чем вставлять новый, вы должны сначала проверить, есть ли уже элемент RunProperties в Run.Если элемент RunProperties уже существует, вам следует использовать его повторно.

// Either reuse an existing RunProperties element,
// or create a new one if there's none
RunProperties runPro = highlightRun.Descendants<RunProperties>().FirstOrDefault() ??
    new RunProperties { Language = "en-US", Dirty = false };

// only add the element if it's really new, don't add existing one
if (runPro.Parent == null)
{
    highlightRun.InsertAt(runPro, 0);
}
...