简体   繁体   English

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

[英]VSTO OpenXml C# - Edit PowerPoint on Runtime

I've read a lot about editing pptx files with OpenXml like我已经阅读了很多关于使用 OpenXml 编辑 pptx 文件的内容,例如

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

But how can I modify the XML data of my slides/presentation on runtime?但是如何在运行时修改幻灯片/演示文稿的 XML 数据? Specialy when I run a new presentation witch is not saved.特别是当我运行一个新的演示文稿时,女巫不会被保存。

I am working on a C# VSTO Add-in and I want to modify my slide/xml in a way, which is not supportet by Microsoft.Office.Interop.我正在开发 C# VSTO 插件,我想以某种方式修改我的幻灯片/xml,Microsoft.Office.Interop 不支持这种方式。

Unfortunately, Microsoft Word is the only Office application that offers an Interop API for reading and even writing Open XML markup, in that case of a given Range object (which can also be the Range representing the whole main document part).不幸的是,Microsoft Word 是唯一提供用于读取甚至写入 Open XML 标记的互操作 API 的 Office 应用程序,在这种情况下,对于给定的Range对象(它也可以是代表整个主要文档部分的Range )。 Neither Excel nor PowerPoint provides that capability. Excel 和 PowerPoint 都没有提供这种功能。

Even Microsoft Word does not give you the full markup, though, meaning you can't read or change every aspect of the opened document by reading or making changes to the Open XML markup.但是,即使 Microsoft Word 也不会给您完整的标记,这意味着您无法通过阅读或更改 Open XML 标记来阅读或更改打开文档的每个方面。 Thus, depending on what you would like to do with your document, you will have to close and reopen even Word documents to access and process the full Open XML markup.因此,根据您希望对文档执行的操作,您甚至必须关闭和重新打开 Word 文档才能访问和处理完整的 Open XML 标记。

A sub-optimal yet functional way to do this is round trip using the clipboard.执行此操作的次优但功能性方法是使用剪贴板往返。 Slide(s) copied to the clipboard are actually packaged up as ppt data (which is just a zip).复制到剪贴板的幻灯片实际上被打包为 ppt 数据(这只是一个 zip)。 And you have control over the clipboard and inserting etc slides.而且您可以控制剪贴板并插入等幻灯片。 So basically:所以基本上:

  1. Programmatically select and copy the content you want to edit to the clipboard using PP APIs.使用 PP API 以编程方式选择要编辑的内容并将其复制到剪贴板。
  2. Read "PowerPoint 14.0 Slides Package" part of clipboard data into memory stream.将剪贴板数据的“PowerPoint 14.0 幻灯片包”部分读入内存流。
  3. Pass/edit memory stream with Open XML.使用 Open XML 传递/编辑内存流。
  4. Copy memory stream back to clipboard.将内存流复制回剪贴板。
  5. paste back into PP as needed.根据需要粘贴回 PP。

Here's an example of steps 2-3 working using this Open XML example as a base that write all text in the first slide in the clipboard to the console:以下是第 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;
                }
            }            
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM