如何:按作者从演示文稿中的所有幻灯片中删除注释
上次修改时间: 2010年10月14日
适用范围: Excel 2010 | Office 2010 | PowerPoint 2010 | Word 2010
本文内容
获取 PresentationDocument 对象
基本演示文稿文档结构
Comment 元素的结构
示例代码的工作方式
示例代码
本主题演示如何使用 Open XML SDK 2.0 for Microsoft Office 中的类通过编程方式按特定作者删除演示文稿中的所有注释。
编译本主题中的代码需要使用以下程序集指令。
using System;
using System.Linq;
using System.Collections.Generic;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Presentation;
using DocumentFormat.OpenXml.Packaging;
Imports System
Imports System.Linq
Imports System.Collections.Generic
Imports DocumentFormat.OpenXml
Imports DocumentFormat.OpenXml.Presentation
Imports DocumentFormat.OpenXml.Packaging
获取 PresentationDocument 对象
在 Open XML SDK 中,PresentationDocument 类代表演示文稿文档包。若要使用演示文稿文档,首先创建 PresentationDocument 类的实例,然后使用该实例。若要从文档创建类实例,请调用使用文件路径的 Open(String, Boolean) 方法,并以布尔值作为第二个参数来指定文档是否可编辑。若要打开文档进行读/写,请为此参数指定值 true,如以下的 using 语句所示。在该代码中,fileName 参数是一个字符串,表示要从中打开该文档的文件的路径,author 是"PowerPoint 选项"的"常规"选项卡中显示的用户名。
public static void DeleteCommentsByAuthorInPresentation(string fileName, string author)
{
using (PresentationDocument doc = PresentationDocument.Open(fileName, true))
{
// Insert other code here.
}
Public Shared Sub DeleteCommentsByAuthorInPresentation(ByVal fileName As String, ByVal author As String)
Using doc As PresentationDocument = PresentationDocument.Open(fileName, True)
' Insert other code here.
End Using
using 语句提供典型 .Open, .Save, .Close 序列的建议备选序列。它确保在遇到右大括号时会自动调用 Dispose 方法(Open XML SDK 用于清理资源的内部方法)。using 语句后面的块为 using 语句中创建或指定的对象设定范围,在此示例中这个范围就是 doc。
基本演示文稿文档结构
PresentationML 文档的基本文档结构由包含演示文稿定义的主部件组成。ISO/IEC 29500(该链接可能指向英文页面) 规范中的以下文本介绍了 PresentationML 包的整体形式。
PresentationML 包的主部件以演示文稿根元素开头。该元素包含演示文稿,演示文稿又引用幻灯片 列表、幻灯片母版 列表、备注母版 列表和讲义母版 列表。幻灯片列表指的是演示文稿中的所有幻灯片;幻灯片母版列表指的是演示文稿中使用的全部幻灯片母版;备注母版包含有关备注页格式的信息;讲义母版描述讲义的外观。
讲义 是打印的一组幻灯片,可提供给访问群体 以供他们将来参考。
除了文本和图形,每个幻灯片还可以包含注释 和备注,可以具有布局,并且可以是一个或多个自定义演示文稿 的组成部分。(注释是供维护演示文稿幻灯片平台的人员参考的批注。备注是供演示者或访问群体参考的提醒信息或一段文字。)
PresentationML 文档可以包含的其他功能如下:动画、音频、视频 以及幻灯片之间的切换。
PresentationML 文档不会存储为单个部件中的一个大型正文。而实现某些功能组合的元素会存储在各个部件中。例如,文档中的所有注释都存储在一个注释部件中,而每个幻灯片都有自己的部件。
© ISO/IEC29500: 2008。
以下 XML 代码段代表包含用 ID 267 和 256 表示的两个幻灯片的演示文稿。
<p:presentation xmlns:p="…" … >
<p:sldMasterIdLst>
<p:sldMasterId
xmlns:rel="http://…/relationships" rel:id="rId1"/>
</p:sldMasterIdLst>
<p:notesMasterIdLst>
<p:notesMasterId
xmlns:rel="http://…/relationships" rel:id="rId4"/>
</p:notesMasterIdLst>
<p:handoutMasterIdLst>
<p:handoutMasterId
xmlns:rel="http://…/relationships" rel:id="rId5"/>
</p:handoutMasterIdLst>
<p:sldIdLst>
<p:sldId id="267"
xmlns:rel="http://…/relationships" rel:id="rId2"/>
<p:sldId id="256"
xmlns:rel="http://…/relationships" rel:id="rId3"/>
</p:sldIdLst>
<p:sldSz cx="9144000" cy="6858000"/>
<p:notesSz cx="6858000" cy="9144000"/>
</p:presentation>
使用 Open XML SDK 2.0,您可以利用 PresentationML 元素所对应的强类型类创建文档结构和内容。可以在 DocumentFormat.OpenXml.Presentation 命名空间中找到这些类。下表列出了 sld、sldLayout、sldMaster 和 notesMaster 元素所对应类的类名:
PresentationML 元素 |
Open XML SDK 2.0 类 |
说明 |
---|---|---|
sld |
演示文稿幻灯片。它是 SlidePart 的根元素。 |
|
sldLayout |
幻灯片版式。它是 SlideLayoutPart 的根元素。 |
|
sldMaster |
幻灯片母版。它是 SlideMasterPart 的根元素。 |
|
notesMaster |
备注母版(或讲义母版)。它是 NotesMasterPart 的根元素。 |
Comment 元素的结构
ISO/IEC 29500(该链接可能指向英文页面) 规范中的以下文本介绍了演示文稿包中的注释。
注释是附加到幻灯片的文本备注,主要用途是使演示文稿的读者能够向演示文稿作者提供反馈。每个注释包含无格式文本字符串及有关其作者的信息,并附加到幻灯片上的特定位置。在编辑演示文稿时,注释是可见的,但在播放幻灯片时不会出现。显示幻灯片的应用程序决定何时显示注释并确定其外观。
© ISO/IEC29500: 2008。
以下 XML 元素指定了附加到幻灯片的单个注释。它包含注释文本 (text)、注释在幻灯片上的位置 (pos) 以及引用其作者 (authorId)、日期和时间 (dt) 及注释索引 (idx) 的属性。
<p:cm authorId="0" dt="2006-08-28T17:26:44.129" idx="1">
<p:pos x="10" y="10"/>
<p:text>Add diagram to clarify.</p:text>
</p:cm>
下表列出了 cm(注释)元素的成员和属性的定义。
成员/属性 |
定义 |
---|---|
authorId |
引用文档的注释作者列表中的作者的 ID。 |
dt |
上次修改此注释的日期和时间。 |
idx |
此注释的标识符,在此文档中由此作者创建的所有注释的列表中是唯一的。作者在文档中的第一个注释的索引是 1。 |
pos |
注释在幻灯片表面的放置位置信息。 |
text |
注释的文本内容。 |
extLst |
指定具有修改功能的扩展名列表,该列表中定义了元素类型为 ext 的所有未来扩展名。扩展名列表以及相应的未来扩展名用于扩展 PresentationML 框架的存储功能,从而允许各种新的数据类型以固有的方式存储在该框架内。 |
下面的 XML 架构示例定义了 cm 元素的成员以及必需属性和可选属性。
<complexType name="CT_Comment">
<sequence>
<element name="pos" type="a:CT_Point2D" minOccurs="1" maxOccurs="1"/>
<element name="text" type="xsd:string" minOccurs="1" maxOccurs="1"/>
<element name="extLst" type="CT_ExtensionListModify" minOccurs="0" maxOccurs="1"/>
</sequence>
<attribute name="authorId" type="xsd:unsignedInt" use="required"/>
<attribute name="dt" type="xsd:dateTime" use="optional"/>
<attribute name="idx" type="ST_Index" use="required"/>
</complexType>
示例代码的工作方式
打开要进行读/写访问的演示文稿文档并实例化 PresentationDocument 类之后,代码将从注释作者列表获取指定的注释作者。
// Get the specifed comment author.
IEnumerable<CommentAuthor> commentAuthors =
doc.PresentationPart.CommentAuthorsPart.CommentAuthorList.Elements<CommentAuthor>()
.Where(e => e.Name.Value.Equals(author));
' Get the specifed comment author.
Dim commentAuthors As IEnumerable(Of CommentAuthor) = _
doc.PresentationPart.CommentAuthorsPart.CommentAuthorList.Elements _
(Of CommentAuthor)().Where(Function(e) e.Name.Value.Equals(author))
通过循环访问匹配的作者和演示文稿中的所有幻灯片,代码将获取所有幻灯片部件,并获取每个幻灯片部件的注释部件。之后,代码将获取指定作者创建的注释列表,并删除每个注释。它还确认注释部件不再包含现有注释,然后删除该部件。它还从注释作者部件中删除注释作者。
// Iterate through all the matching authors.
foreach (CommentAuthor commentAuthor in commentAuthors)
{
UInt32Value authorId = commentAuthor.Id;
// Iterate through all the slides and get the slide parts.
foreach (SlidePart slide in doc.PresentationPart.SlideParts)
{
SlideCommentsPart slideCommentsPart = slide.SlideCommentsPart;
// Get the list of comments.
if (slideCommentsPart != null && slide.SlideCommentsPart.CommentList != null)
{
IEnumerable<Comment> commentList =
slideCommentsPart.CommentList.Elements<Comment>().Where(e => e.AuthorId == authorId.Value);
List<Comment> comments = new List<Comment>();
comments = commentList.ToList<Comment>();
foreach (Comment comm in comments)
{
// Delete all the comments by the specified author.
slideCommentsPart.CommentList.RemoveChild<Comment>(comm);
}
// If the commentPart has no existing comment.
if (slideCommentsPart.CommentList.ChildElements.Count == 0)
// Delete this part.
slide.DeletePart(slideCommentsPart);
}
}
// Delete the comment author from the comment authors part.
doc.PresentationPart.CommentAuthorsPart.CommentAuthorList.RemoveChild<CommentAuthor>(commentAuthor);
}
'Iterate through all the matching authors
For Each commentAuthor In commentAuthors
Dim authorId = commentAuthor.Id
' Iterate through all the slides and get the slide parts.
For Each slide In doc.PresentationPart.GetPartsOfType(Of SlidePart)()
' Get the slide comments part of each slide.
For Each slideCommentsPart In slide.GetPartsOfType(Of SlideCommentsPart)()
' Delete all the comments by the specified author.
Dim commentList = slideCommentsPart.CommentList.Elements(Of Comment)(). _
Where(Function(e) e.AuthorId.Value.Equals(authorId.Value))
Dim comments As List(Of Comment) = commentList.ToList()
For Each comm As Comment In comments
slideCommentsPart.CommentList.RemoveChild(Of Comment)(comm)
Next
Next
Next
' Delete the comment author from the comment authors part.
doc.PresentationPart.CommentAuthorsPart.CommentAuthorList.RemoveChild(Of CommentAuthor)(commentAuthor)
Next
示例代码
下面的方法采用源演示文稿文件名和路径以及要删除其注释的注释作者的姓名作为参数。此方法按指定作者在演示文稿中找到所有注释并删除它们。然后,此方法将该注释作者从注释作者的列表中删除。
您可以使用以下示例调用 DeleteCommentsByAuthorInPresentation 方法,以便从演示文稿文件 myppt5.pptx 中删除指定作者的注释。
string fileName = @"C:\Users\Public\Documents\myppt5.pptx";
string author = "Katie Jordan";
DeleteCommentsByAuthorInPresentation(fileName, author);
Dim fileName As String = "C:\Users\Public\Documents\myppt5.pptx"
Dim author As String = "Katie Jordan"
DeleteCommentsByAuthorInPresentation(fileName, author)
备注
若要获取确切的作者名称,请打开演示文稿文件,单击"文件"菜单项,然后单击"选项"。此时将打开"PowerPoint 选项"窗口,显示"通用"选项卡的内容。作者名称必须与此选项卡中的"用户名"相匹配。
以下是使用 C# 和 Visual Basic 编写的完整示例代码。
// Remove all the comments in the slides by a certain author.
public static void DeleteCommentsByAuthorInPresentation(string fileName, string author)
{
if (String.IsNullOrEmpty(fileName) || String.IsNullOrEmpty(author))
throw new ArgumentNullException("File name or author name is NULL!");
using (PresentationDocument doc = PresentationDocument.Open(fileName, true))
{
// Get the specifed comment author.
IEnumerable<CommentAuthor> commentAuthors =
doc.PresentationPart.CommentAuthorsPart.CommentAuthorList.Elements<CommentAuthor>()
.Where(e => e.Name.Value.Equals(author));
// Iterate through all the matching authors.
foreach (CommentAuthor commentAuthor in commentAuthors)
{
UInt32Value authorId = commentAuthor.Id;
// Iterate through all the slides and get the slide parts.
foreach (SlidePart slide in doc.PresentationPart.SlideParts)
{
SlideCommentsPart slideCommentsPart = slide.SlideCommentsPart;
// Get the list of comments.
if (slideCommentsPart != null && slide.SlideCommentsPart.CommentList != null)
{
IEnumerable<Comment> commentList =
slideCommentsPart.CommentList.Elements<Comment>().Where(e => e.AuthorId == authorId.Value);
List<Comment> comments = new List<Comment>();
comments = commentList.ToList<Comment>();
foreach (Comment comm in comments)
{
// Delete all the comments by the specified author.
slideCommentsPart.CommentList.RemoveChild<Comment>(comm);
}
// If the commentPart has no existing comment.
if (slideCommentsPart.CommentList.ChildElements.Count == 0)
// Delete this part.
slide.DeletePart(slideCommentsPart);
}
}
// Delete the comment author from the comment authors part.
doc.PresentationPart.CommentAuthorsPart.CommentAuthorList.RemoveChild<CommentAuthor>(commentAuthor);
}
}
}
' Remove all the comments in the slides by a certain author.
Public Sub DeleteCommentsByAuthorInPresentation(ByVal fileName As String, ByVal author As String)
Dim doc As PresentationDocument = PresentationDocument.Open(fileName, True)
If (String.IsNullOrEmpty(fileName) Or String.IsNullOrEmpty(author)) Then
Throw New ArgumentNullException("File name or author name is NULL!")
End If
Using (doc)
' Get the specifed comment author.
Dim commentAuthors = doc.PresentationPart.CommentAuthorsPart. _
CommentAuthorList.Elements(Of CommentAuthor)().Where(Function(e) _
e.Name.Value.Equals(author))
' Dim changed As Boolean = False
For Each commentAuthor In commentAuthors
Dim authorId = commentAuthor.Id
' Iterate through all the slides and get the slide parts.
For Each slide In doc.PresentationPart.GetPartsOfType(Of SlidePart)()
' Get the slide comments part of each slide.
For Each slideCommentsPart In slide.GetPartsOfType(Of SlideCommentsPart)()
' Delete all the comments by the specified author.
Dim commentList = slideCommentsPart.CommentList.Elements(Of Comment)(). _
Where(Function(e) e.AuthorId.Value.Equals(authorId.Value))
Dim comments As List(Of Comment) = commentList.ToList()
For Each comm As Comment In comments
slideCommentsPart.CommentList.RemoveChild(Of Comment)(comm)
Next
Next
Next
' Delete the comment author from the comment authors part.
doc.PresentationPart.CommentAuthorsPart.CommentAuthorList.RemoveChild(Of CommentAuthor)(commentAuthor)
Next
End Using
End Sub