VSTO OpenXml C#-在运行时编辑PowerPoint

VSTO OpenXml C#-在运行时编辑PowerPoint,c#,xml,vsto,powerpoint,openxml,C#,Xml,Vsto,Powerpoint,Openxml,我读过很多关于用OpenXml编辑pptx文件的书,比如 PresentationDocument presentationDocument = PresentationDocument.Open("C:\\Users\\beggers\\Desktop\\Test.pptx", true) 但是如何在运行时修改幻灯片/演示文稿的XML数据呢?特别是当我运行一个新的演示时,它不会被保存 我正在开发一个C#VSTO插件,我想以Microsoft.Office.Interop不支持的方式修改幻灯片

我读过很多关于用OpenXml编辑pptx文件的书,比如

PresentationDocument presentationDocument = PresentationDocument.Open("C:\\Users\\beggers\\Desktop\\Test.pptx", true)
但是如何在运行时修改幻灯片/演示文稿的XML数据呢?特别是当我运行一个新的演示时,它不会被保存


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

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


但是,即使是Microsoft Word也不提供完整的标记,这意味着您无法通过读取或更改打开的XML标记来读取或更改打开的文档的各个方面。因此,根据您对文档的处理方式,您甚至必须关闭或重新打开Word文档才能访问和处理完全打开的XML标记rkup.

实现这一点的次优但实用的方法是使用剪贴板往返。复制到剪贴板的幻灯片实际上打包为ppt数据(仅为zip)。您可以控制剪贴板和插入etc幻灯片。因此基本上:

  • 使用PP API以编程方式选择要编辑的内容并将其复制到剪贴板
  • 将剪贴板数据的“PowerPoint 14.0幻灯片包”部分读取到内存流中
  • 使用打开的XML传递/编辑内存流
  • 将内存流复制回剪贴板
  • 根据需要将其粘贴回PP中
  • 下面是步骤2-3的示例,使用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;
                    }
                }            
            }
        }
    }
    
    使用系统;
    使用System.IO;
    使用System.Collections.Generic;
    使用System.Linq;
    使用系统文本;
    使用System.Windows;
    使用DocumentFormat.OpenXml;
    使用DocumentFormat.OpenXml.Drawing;
    使用DocumentFormat.OpenXml.Packaging;
    使用DocumentFormat.OpenXml.Presentation;
    使用P=DocumentFormat.OpenXml.Presentation;
    使用D=DocumentFormat.OpenXml.Drawing;
    使用DocumentFormat.OpenXml.Office2016.Drawing.ChartDrawing;
    命名空间PPClipboardTest
    {    
    班级计划
    {
    公共静态字符串格式=“PowerPoint 14.0幻灯片包”;
    //在幻灯片中获取所有文本。
    公共静态字符串[]GetAllTextInSlide(字符串表示文件,int slideIndex)
    {
    //以只读方式打开演示文稿。
    使用(PresentationDocument PresentationDocument=PresentationDocument.Open(presentationFile,false))
    {
    //传递演示文稿和幻灯片索引
    //到下一个GetAllTextInSlide方法,以及
    //然后返回它返回的字符串数组。
    返回GetAllTextInSlide(显示文档、slideIndex);
    }
    }
    公共静态字符串[]GetAllTextInSlide(PresentationDocument PresentationDocument,int slideIndex)
    {
    //验证演示文稿文档是否存在。
    如果(presentationDocument==null)
    {
    抛出新ArgumentNullException(“presentationDocument”);
    }
    //确认幻灯片索引未超出范围。
    如果(滑动索引<0)
    {
    抛出新ArgumentOutOfRangeException(“slideIndex”);
    }
    //获取演示文稿文档的演示文稿部分。
    PresentationPart PresentationPart=presentationDocument.PresentationPart;
    //验证演示文稿部分和演示文稿是否存在。
    if(presentationPart!=null&&presentationPart.Presentation!=null)
    {
    //从演示文稿部分获取演示文稿对象。
    演示文稿=演示文稿部分。演示文稿;
    //验证幻灯片ID列表是否存在。
    如果(presentation.SlideIdList!=null)
    {
    //从幻灯片ID列表中获取幻灯片ID的集合。
    DocumentFormat.OpenXml.OpenXmlElementList幻灯片ID=
    presentation.slidedlist.ChildElements;
    //如果幻灯片ID在范围内。。。
    if(slideIndex