簡體   English   中英

VSTO OpenXml C# - 在運行時編輯 PowerPoint

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

我已經閱讀了很多關於使用 OpenXml 編輯 pptx 文件的內容,例如

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

但是如何在運行時修改幻燈片/演示文稿的 XML 數據? 特別是當我運行一個新的演示文稿時,女巫不會被保存。

我正在開發 C# VSTO 插件,我想以某種方式修改我的幻燈片/xml,Microsoft.Office.Interop 不支持這種方式。

不幸的是,Microsoft Word 是唯一提供用於讀取甚至寫入 Open XML 標記的互操作 API 的 Office 應用程序,在這種情況下,對於給定的Range對象(它也可以是代表整個主要文檔部分的Range )。 Excel 和 PowerPoint 都沒有提供這種功能。

但是,即使 Microsoft Word 也不會給您完整的標記,這意味着您無法通過閱讀或更改 Open XML 標記來閱讀或更改打開文檔的每個方面。 因此,根據您希望對文檔執行的操作,您甚至必須關閉和重新打開 Word 文檔才能訪問和處理完整的 Open XML 標記。

執行此操作的次優但功能性方法是使用剪貼板往返。 復制到剪貼板的幻燈片實際上被打包為 ppt 數據(這只是一個 zip)。 而且您可以控制剪貼板並插入等幻燈片。 所以基本上:

  1. 使用 PP API 以編程方式選擇要編輯的內容並將其復制到剪貼板。
  2. 將剪貼板數據的“PowerPoint 14.0 幻燈片包”部分讀入內存流。
  3. 使用 Open XML 傳遞/編輯內存流。
  4. 將內存流復制回剪貼板。
  5. 根據需要粘貼回 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;
                }
            }            
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM