本主题演示如何使用 Open XML SDK for Office 中的类以编程方式将音频文件添加到演示文稿中的最后一张幻灯片。
获取 Presentation 对象
在 Open XML SDK 中 PresentationDocument , 类表示演示文稿文档包。 若要处理演示文稿文档,请先创建 类的 PresentationDocument 实例,然后使用该实例。 若要从文档创建类实例, Open 请调用使用文件路径的方法,并使用布尔值作为第二个参数来指定文档是否可编辑。 若要打开文档进行读/写,请指定此参数的值 true ,如以下 using 语句所示。 在该代码中,file 参数是一个字符串,表示要从中打开该文档的文件的路径。
using (PresentationDocument presentationDocument = PresentationDocument.Open(filePath, true))
在 v3.0.0+ 中, Close() 已删除 方法,转而依赖于 using 语句。
这可确保在 Dispose() 到达右大括号时自动调用 方法。 语句后面的 using 块为在 语句中创建 using 或命名的对象建立作用域,在本例 ppt中为 。
来自文件的音频的结构
PresentationML 文档由多个部分组成,其中包括 Picture (<pic/>) 元素。
ISO/IEC 29500 规范中的以下文本介绍了包的整体PresentationML形式。
音频文件 (<audioFile/>) 指定存在音频文件。 此元素在 对象的非可视属性中指定。 音频应附加到对象,因为这就是它在文档中的表示方式。 但是,音频的实际播放是在计时元素下指定的计时节点列表中完成的。
请考虑以下 Picture 对象,该对象附加了一个音频文件。
<p:pic>
<p:nvPicPr>
<p:cNvPr id="7" name="Rectangle 6">
<a:hlinkClick r:id="" action="ppaction://media"/>
</p:cNvPr>
<p:cNvPicPr>
<a:picLocks noRot="1"/>
</p:cNvPicPr>
<p:nvPr>
<a:audioFile r:link="rId1"/>
</p:nvPr>
</p:nvPicPr>
</p:pic>
在上面的示例中,我们看到有一个 audioFile 元素附加到此图片。 此图片与普通图片或形状一样放置在文档中。 此图片的 ID(在本例中为 7)用于从计时节点列表中引用此 audioFile 元素。 链接关系 ID 用于检索实际音频文件以进行播放。
© ISO/IEC 29500:2016
以下 XML 架构片段定义 audioFile 的内容。
<xsd:complexType name="CT_TLMediaNodeAudio">
<xsd:sequence>
<xsd:element name="cMediaNode" type="CT_TLCommonMediaNodeData" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="isNarration" type="xsd:boolean" use="optional" default="false"/>
</xsd:complexType>
示例代码的工作方式
在 语句中 using 打开演示文稿文件进行读/写访问后,代码将从演示文稿文档中获取演示文稿部件。 然后,它获取最后一张幻灯片的关系 ID,并从关系 ID 获取幻灯片部件。
//Get presentation part
PresentationPart presentationPart = presentationDocument.PresentationPart;
//Get slides ids.
OpenXmlElementList slidesIds = presentationPart.Presentation.SlideIdList.ChildElements;
//Get relationsipId of the last slide
string? audioSlidePartRelationshipId = ((SlideId)slidesIds[slidesIds.ToArray().Length - 1]).RelationshipId;
if (audioSlidePartRelationshipId == null)
{
throw new NullReferenceException("Slide id not found");
}
//Get slide part by relationshipID
SlidePart? slidePart = (SlidePart)presentationPart.GetPartById(audioSlidePartRelationshipId);
代码首先为要添加的音频文件创建媒体数据部分。 打开音频文件流后,它将馈送媒体数据部件对象。 接下来,使用提供的 embedId 将音频和媒体关系引用添加到幻灯片,以便将来引用音频文件,并使用 mediaEmbedId 进行媒体引用。
然后添加一个图像部件,其中包含要用作音频占位符的示例图片。 使用各种元素(如非可视绘图属性 (<cNvPr/>) )创建图片对象,这些元素指定非可视画布属性。 这允许其他信息不会影响要存储的图片的外观。
<audioFile/>上面介绍的 元素也包括在内。 HyperLinkOnClick (<hlinkClick/>) 元素指定要应用于文本或图像运行的点击超链接信息。 单击超链接文本或图像时,将提取链接。 非视觉对象图片绘图属性 (<cNvPicPr/>) 指定图片画布的非视觉属性。 有关所用元素的详细说明,请参阅 ISO/IEC 29500
// Create audio Media Data Part (content type, extension)
MediaDataPart mediaDataPart = presentationDocument.CreateMediaDataPart("audio/mp3", ".mp3");
//Get the audio file and feed the stream
using (Stream mediaDataPartStream = File.OpenRead(audioFilePath))
{
mediaDataPart.FeedData(mediaDataPartStream);
}
//Adds a AudioReferenceRelationship to the MainDocumentPart
slidePart.AddAudioReferenceRelationship(mediaDataPart, embedId);
//Adds a MediaReferenceRelationship to the SlideLayoutPart
slidePart.AddMediaReferenceRelationship(mediaDataPart, mediaEmbedId);
NonVisualDrawingProperties nonVisualDrawingProperties = new NonVisualDrawingProperties() { Id = shapeId, Name = "audio" };
A.AudioFromFile audioFromFile = new A.AudioFromFile() { Link = embedId };
ApplicationNonVisualDrawingProperties appNonVisualDrawingProperties = new ApplicationNonVisualDrawingProperties();
appNonVisualDrawingProperties.Append(audioFromFile);
//adds sample image to the slide with id to be used as reference in blip
ImagePart imagePart = slidePart.AddImagePart(ImagePartType.Png, imgEmbedId);
using (Stream data = File.OpenRead(coverPicPath))
{
imagePart.FeedData(data);
}
if (slidePart!.Slide!.CommonSlideData!.ShapeTree == null)
{
throw new NullReferenceException("Presentation shape tree is empty");
}
//Getting existing shape tree element from PowerPoint
ShapeTree shapeTree = slidePart.Slide.CommonSlideData.ShapeTree;
// specifies the existence of a picture within a presentation.
// It can have non-visual properties, a picture fill as well as shape properties attached to it.
Picture picture = new Picture();
NonVisualPictureProperties nonVisualPictureProperties = new NonVisualPictureProperties();
A.HyperlinkOnClick hyperlinkOnClick = new A.HyperlinkOnClick() { Id = "", Action = "ppaction://media" };
nonVisualDrawingProperties.Append(hyperlinkOnClick);
NonVisualPictureDrawingProperties nonVisualPictureDrawingProperties = new NonVisualPictureDrawingProperties();
A.PictureLocks pictureLocks = new A.PictureLocks() { NoChangeAspect = true };
nonVisualPictureDrawingProperties.Append(pictureLocks);
ApplicationNonVisualDrawingPropertiesExtensionList appNonVisualDrawingPropertiesExtensionList = new ApplicationNonVisualDrawingPropertiesExtensionList();
ApplicationNonVisualDrawingPropertiesExtension appNonVisualDrawingPropertiesExtension = new ApplicationNonVisualDrawingPropertiesExtension() { Uri = "{DAA4B4D4-6D71-4841-9C94-3DE7FCFB9230}" };
接下来,使用以前引用的 mediaEmbedId (嵌入式图片引用) 创建 Media (CT_Media) 元素。 还添加了 Blip 元素;此元素指定存在 (二进制大图像或图片) 的图像,并包含对图像数据的引用。 Blip 的 Embed 属性用于指定之前创建的图像部件中的占位符图像。
P14.Media media = new() { Embed = mediaEmbedId };
media.AddNamespaceDeclaration("p14", "http://schemas.microsoft.com/office/powerpoint/2010/main");
appNonVisualDrawingPropertiesExtension.Append(media);
appNonVisualDrawingPropertiesExtensionList.Append(appNonVisualDrawingPropertiesExtension);
appNonVisualDrawingProperties.Append(appNonVisualDrawingPropertiesExtensionList);
nonVisualPictureProperties.Append(nonVisualDrawingProperties);
nonVisualPictureProperties.Append(nonVisualPictureDrawingProperties);
nonVisualPictureProperties.Append(appNonVisualDrawingProperties);
//Prepare shape properties to display picture
BlipFill blipFill = new BlipFill();
A.Blip blip = new A.Blip() { Embed = imgEmbedId };
所有其他元素(如 Offset (<off/>) 、Stretch (<stretch/>) 、fillRectangle (<fillRect/>) )将追加到 ShapeProperties (<spPr/>) 和 ShapeProperties 将追加到 Picture 元素 (<pic/>) 。 最后,将包含音频的图片元素添加到幻灯片的 ShapeTree (<sp/>) 。
下面是可用于将音频添加到幻灯片的完整示例代码。
示例代码
AddAudio(args[0], args[1], args[2]);
static void AddAudio(string filePath, string audioFilePath, string coverPicPath)
{
string imgEmbedId = "rId4", embedId = "rId3", mediaEmbedId = "rId2";
UInt32Value shapeId = 5;
using (PresentationDocument presentationDocument = PresentationDocument.Open(filePath, true))
{
if (presentationDocument.PresentationPart == null || presentationDocument.PresentationPart.Presentation.SlideIdList == null)
{
throw new NullReferenceException("Presentation Part is empty or there are no slides in it");
}
//Get presentation part
PresentationPart presentationPart = presentationDocument.PresentationPart;
//Get slides ids.
OpenXmlElementList slidesIds = presentationPart.Presentation.SlideIdList.ChildElements;
//Get relationsipId of the last slide
string? audioSlidePartRelationshipId = ((SlideId)slidesIds[slidesIds.ToArray().Length - 1]).RelationshipId;
if (audioSlidePartRelationshipId == null)
{
throw new NullReferenceException("Slide id not found");
}
//Get slide part by relationshipID
SlidePart? slidePart = (SlidePart)presentationPart.GetPartById(audioSlidePartRelationshipId);
// Create audio Media Data Part (content type, extension)
MediaDataPart mediaDataPart = presentationDocument.CreateMediaDataPart("audio/mp3", ".mp3");
//Get the audio file and feed the stream
using (Stream mediaDataPartStream = File.OpenRead(audioFilePath))
{
mediaDataPart.FeedData(mediaDataPartStream);
}
//Adds a AudioReferenceRelationship to the MainDocumentPart
slidePart.AddAudioReferenceRelationship(mediaDataPart, embedId);
//Adds a MediaReferenceRelationship to the SlideLayoutPart
slidePart.AddMediaReferenceRelationship(mediaDataPart, mediaEmbedId);
NonVisualDrawingProperties nonVisualDrawingProperties = new NonVisualDrawingProperties() { Id = shapeId, Name = "audio" };
A.AudioFromFile audioFromFile = new A.AudioFromFile() { Link = embedId };
ApplicationNonVisualDrawingProperties appNonVisualDrawingProperties = new ApplicationNonVisualDrawingProperties();
appNonVisualDrawingProperties.Append(audioFromFile);
//adds sample image to the slide with id to be used as reference in blip
ImagePart imagePart = slidePart.AddImagePart(ImagePartType.Png, imgEmbedId);
using (Stream data = File.OpenRead(coverPicPath))
{
imagePart.FeedData(data);
}
if (slidePart!.Slide!.CommonSlideData!.ShapeTree == null)
{
throw new NullReferenceException("Presentation shape tree is empty");
}
//Getting existing shape tree element from PowerPoint
ShapeTree shapeTree = slidePart.Slide.CommonSlideData.ShapeTree;
// specifies the existence of a picture within a presentation.
// It can have non-visual properties, a picture fill as well as shape properties attached to it.
Picture picture = new Picture();
NonVisualPictureProperties nonVisualPictureProperties = new NonVisualPictureProperties();
A.HyperlinkOnClick hyperlinkOnClick = new A.HyperlinkOnClick() { Id = "", Action = "ppaction://media" };
nonVisualDrawingProperties.Append(hyperlinkOnClick);
NonVisualPictureDrawingProperties nonVisualPictureDrawingProperties = new NonVisualPictureDrawingProperties();
A.PictureLocks pictureLocks = new A.PictureLocks() { NoChangeAspect = true };
nonVisualPictureDrawingProperties.Append(pictureLocks);
ApplicationNonVisualDrawingPropertiesExtensionList appNonVisualDrawingPropertiesExtensionList = new ApplicationNonVisualDrawingPropertiesExtensionList();
ApplicationNonVisualDrawingPropertiesExtension appNonVisualDrawingPropertiesExtension = new ApplicationNonVisualDrawingPropertiesExtension() { Uri = "{DAA4B4D4-6D71-4841-9C94-3DE7FCFB9230}" };
P14.Media media = new() { Embed = mediaEmbedId };
media.AddNamespaceDeclaration("p14", "http://schemas.microsoft.com/office/powerpoint/2010/main");
appNonVisualDrawingPropertiesExtension.Append(media);
appNonVisualDrawingPropertiesExtensionList.Append(appNonVisualDrawingPropertiesExtension);
appNonVisualDrawingProperties.Append(appNonVisualDrawingPropertiesExtensionList);
nonVisualPictureProperties.Append(nonVisualDrawingProperties);
nonVisualPictureProperties.Append(nonVisualPictureDrawingProperties);
nonVisualPictureProperties.Append(appNonVisualDrawingProperties);
//Prepare shape properties to display picture
BlipFill blipFill = new BlipFill();
A.Blip blip = new A.Blip() { Embed = imgEmbedId };
A.Stretch stretch = new A.Stretch();
A.FillRectangle fillRectangle = new A.FillRectangle();
A.Transform2D transform2D = new A.Transform2D();
A.Offset offset = new A.Offset() { X = 1524000L, Y = 857250L };
A.Extents extents = new A.Extents() { Cx = 9144000L, Cy = 5143500L };
A.PresetGeometry presetGeometry = new A.PresetGeometry() { Preset = A.ShapeTypeValues.Rectangle };
A.AdjustValueList adjValueList = new A.AdjustValueList();
stretch.Append(fillRectangle);
blipFill.Append(blip);
blipFill.Append(stretch);
transform2D.Append(offset);
transform2D.Append(extents);
presetGeometry.Append(adjValueList);
ShapeProperties shapeProperties = new ShapeProperties();
shapeProperties.Append(transform2D);
shapeProperties.Append(presetGeometry);
//adds all elements to the slide's shape tree
picture.Append(nonVisualPictureProperties);
picture.Append(blipFill);
picture.Append(shapeProperties);
shapeTree.Append(picture);
}
}