【问题标题】:VSTO OpenXml C# - Edit PowerPoint on RuntimeVSTO OpenXml C# - 在运行时编辑 PowerPoint
【发布时间】:2019-12-11 20:00:12
【问题描述】:

我读过很多关于用 OpenXml 编辑 pptx 文件的文章

PresentationDocument presentationDocument = PresentationDocument.Open("C:\\Users\\beggers\\Desktop\\Test.pptx", true)

但是如何在运行时修改幻灯片/演示文稿的 XML 数据?特别是当我运行一个新的演示文稿时,女巫没有保存。

我正在开发 C# VSTO 插件,我想以某种方式修改我的幻灯片/xml,这是 Microsoft.Office.Interop 不支持的。

【问题讨论】:

  • 如果您在项目中添加对 Open XML SDK 的引用,您的外接程序将有权访问演示文稿的 XML 以对其进行修改。
  • 正如 John Korchok 所评论的,您需要参考 Open XML SDK,但是,您需要关闭并重新打开该文档,VSTO 才能看到更改。
  • 您好,谢谢您的意见.... 不幸的是,重新打开不是我们案例的解决方案。我正在寻找运行时解决方案。目前,我们正在尝试找出是否可以使用 COM 构建自定义解决方案。
  • 您是否能够使用 COM 构建自定义解决方案?
  • 只有在 c++ 级别的内存操作才有可能。例如,Thinkcell 就是这样做的……但我没有找到任何解决方案

标签: c# xml vsto powerpoint openxml


【解决方案1】:

不幸的是,Microsoft Word 是唯一提供用于读取甚至写入 Open XML 标记的互操作 API 的 Office 应用程序,在这种情况下,给定的 Range 对象(也可以是代表整个主文档的 Range部分)。 Excel 和 PowerPoint 都没有提供这种功能。

不过,即使 Microsoft Word 也不会为您提供完整的标记,这意味着您无法通过阅读或更改 Open XML 标记来阅读或更改已打开文档的各个方面。因此,根据您希望对文档执行的操作,您甚至必须关闭并重新打开 Word 文档才能访问和处理完整的 Open XML 标记。

【讨论】:

    【解决方案2】:

    一种次优但实用的方法是使用剪贴板进行往返。复制到剪贴板的幻灯片实际上被打包为 ppt 数据(只是一个 zip)。你可以控制剪贴板和插入等幻灯片。所以基本上:

    1. 使用 PP API 以编程方式选择要编辑的内容并将其复制到剪贴板。
    2. 将剪贴板数据的“PowerPoint 14.0 Slides Package”部分读入内存流。
    3. 使用 Open XML 传递/编辑内存流。
    4. 将内存流复制回剪贴板。
    5. 根据需要粘贴回 PP。

    以下是步骤 2-3 的示例,使用 this Open XML 示例作为基础,将剪贴板中第一张幻灯片中的所有文本写入控制台:

    using System;
    using System.IO; 
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    
    using DocumentFormat.OpenXml;
    using DocumentFormat.OpenXml.Drawing;
    using DocumentFormat.OpenXml.Packaging;
    using DocumentFormat.OpenXml.Presentation;
    using P = DocumentFormat.OpenXml.Presentation;
    using D = DocumentFormat.OpenXml.Drawing;
    using DocumentFormat.OpenXml.Office2016.Drawing.ChartDrawing;
    
    namespace PPClipboardTest
    {    
        class Program
        {
            public static string format = "PowerPoint 14.0 Slides Package";
    
    
            // Get all the text in a slide.
            public static string[] GetAllTextInSlide(string presentationFile, int slideIndex)
            {
                // Open the presentation as read-only.
                using (PresentationDocument presentationDocument = PresentationDocument.Open(presentationFile, false))
                {
                    // Pass the presentation and the slide index
                    // to the next GetAllTextInSlide method, and
                    // then return the array of strings it returns. 
                    return GetAllTextInSlide(presentationDocument, slideIndex);
                }
            }
    
            public static string[] GetAllTextInSlide(PresentationDocument presentationDocument, int slideIndex)
            {
                // Verify that the presentation document exists.
                if (presentationDocument == null)
                {
                    throw new ArgumentNullException("presentationDocument");
                }
    
                // Verify that the slide index is not out of range.
                if (slideIndex < 0)
                {
                    throw new ArgumentOutOfRangeException("slideIndex");
                }
    
                // Get the presentation part of the presentation document.
                PresentationPart presentationPart = presentationDocument.PresentationPart;
    
                // Verify that the presentation part and presentation exist.
                if (presentationPart != null && presentationPart.Presentation != null)
                {
                    // Get the Presentation object from the presentation part.
                    Presentation presentation = presentationPart.Presentation;
    
                    // Verify that the slide ID list exists.
                    if (presentation.SlideIdList != null)
                    {
                        // Get the collection of slide IDs from the slide ID list.
                        DocumentFormat.OpenXml.OpenXmlElementList slideIds =
                            presentation.SlideIdList.ChildElements;
    
                        // If the slide ID is in range...
                        if (slideIndex < slideIds.Count)
                        {
                            // Get the relationship ID of the slide.
                            string slidePartRelationshipId = (slideIds[slideIndex] as SlideId).RelationshipId;
    
                            // Get the specified slide part from the relationship ID.
                            SlidePart slidePart =
                                (SlidePart)presentationPart.GetPartById(slidePartRelationshipId);
    
                            // Pass the slide part to the next method, and
                            // then return the array of strings that method
                            // returns to the previous method.
                            return GetAllTextInSlide(slidePart);
                        }
                    }
                }
    
                // Else, return null.
                return null;
            }
    
            public static string[] GetAllTextInSlide(SlidePart slidePart)
            {
                // Verify that the slide part exists.
                if (slidePart == null)
                {
                    throw new ArgumentNullException("slidePart");
                }
    
                // Create a new linked list of strings.
                LinkedList<string> texts = new LinkedList<string>();
    
                // If the slide exists...
                if (slidePart.Slide != null)
                {
                    // Iterate through all the paragraphs in the slide.
                    foreach (DocumentFormat.OpenXml.Drawing.Paragraph paragraph in
                        slidePart.Slide.Descendants<DocumentFormat.OpenXml.Drawing.Paragraph>())
                    {
                        // Create a new string builder.                    
                        StringBuilder paragraphText = new StringBuilder();
    
                        // Iterate through the lines of the paragraph.
                        foreach (DocumentFormat.OpenXml.Drawing.Text text in
                            paragraph.Descendants<DocumentFormat.OpenXml.Drawing.Text>())
                        {
                            // Append each line to the previous lines.
                            paragraphText.Append(text.Text);
                        }
    
                        if (paragraphText.Length > 0)
                        {
                            // Add each paragraph to the linked list.
                            texts.AddLast(paragraphText.ToString());
                        }
                    }
                }
    
                if (texts.Count > 0)
                {
                    // Return an array of strings.
                    return texts.ToArray();
                }
                else
                {
                    return null;
                }
            }
    
    
    
            [STAThread]
            static void Main(string[] args)
            {
                IDataObject iData = new DataObject();
    
                iData = Clipboard.GetDataObject();
                string[] formats = iData.GetFormats();
    
                foreach(string f in formats)
                {
                    if(f == format)
                    {
                        MemoryStream ms = iData.GetData(format) as MemoryStream;
    
                        using (PresentationDocument pres = PresentationDocument.Open(ms, true))
                        {
                            string[] allText = GetAllTextInSlide(pres, 0);
                            Console.Write("Text in first slide copied to clipboard:\n");
                            foreach (string txt in allText)
                            {
                                
                                Console.Write(txt + "\n");
                            }
                        }
    
                        /*
                        // Write to file
                        using (FileStream file = new FileStream("file.ppt", FileMode.Create, System.IO.FileAccess.Write)) // Bin chunk from clipboard is just a zip file
                        {
                            byte[] bytes = new byte[ms.Length];
                            ms.Read(bytes, 0, (int)ms.Length);
                            file.Write(bytes, 0, bytes.Length);
                            ms.Close();
                        }
                        */
    
    
                        break;
                    }
                }            
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-04-16
      • 1970-01-01
      • 2020-04-20
      • 1970-01-01
      • 1970-01-01
      • 2011-12-24
      • 1970-01-01
      相关资源
      最近更新 更多