VSTO OpenXml C#-在运行时编辑PowerPoint
我读过很多关于用OpenXml编辑pptx文件的书,比如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不支持的方式修改幻灯片
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