代码之家  ›  专栏  ›  技术社区  ›  Bokambo

使用OpenXML突出显示power point演示文稿中的文本?

  •  2
  • Bokambo  · 技术社区  · 6 年前

    我使用下面的代码使用openxml突出显示power point演示文稿(.pptx)中的文本,但下面的代码用于pptx-打开pptx时会损坏文件并要求修复,打开pptx后会突出显示单词,但不会保留格式。所以总共有两个问题:

    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,但它显示了两次:

    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 回复  |  直到 6 年前
        1
  •  2
  •   dymanoid    6 年前

    a:rPr 元素( RunProperties )在 a:r 元素( Run )而只有一个是允许的。

    因此,您应该首先检查是否已经存在 运行特性 中的元素 在插入新的之前。如果 运行特性 元素已经存在,您应该重新使用它。

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