使用 Open XML SDK 2.0 删除 PowerPoint 2010 文档中所有作者或特定作者所做的注释

Office 可视操作方法

**摘要:**使用 Open XML SDK 2.0 for Microsoft Office 中的强类型类可从 PowerPoint 文档中删除所有作者或特定作者所做的注释,而无需将该文档加载到 PowerPoint 中。

上次修改时间: 2015年3月9日

适用范围: Excel 2010 | Office 2010 | Open XML | PowerPoint 2010 | VBA | Word 2010

**发布时间:**2010 年 10 月

**供稿人:**Ken Getz,MCW Technologies(该链接可能指向英文页面)

概述

虽然可利用 Open XML 文件格式删除 Microsoft Office PowerPoint 2007 和 Microsoft PowerPoint 2010 文档中的注释,但执行此操作需要做一些工作。Open XML SDK 2.0 for Microsoft Office 添加了可简化对 Open XML 文件格式的访问的强类型类;SDK 将简化检索注释列表并删除注释这一任务。此直观操作方法附带的代码示例介绍如何使用 SDK 来实现这个目标。

编码

此直观操作方法中附带的示例包括从 PowerPoint 2007 或 PowerPoint 2010 文档删除一个作者或所有作者所做的注释所需的代码。以下各节详细讨论了该代码。

设置引用

若要使用 Open XML SDK 2.0 中的代码,您必须向您的项目添加几个引用。示例项目已包含这些引用;但是,您需要在您的代码中显式引用以下程序集:

  • WindowsBase - 可能已根据您创建的项目类型为您设置了此引用。

  • DocumentFormat.OpenXml - 由 Open XML SDK 2.0 安装。

此外,将以下 using/Imports 语句添加到代码文件的顶部。

Imports DocumentFormat.OpenXml.Packaging
Imports DocumentFormat.OpenXml.Presentation
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Presentation;

检查过程

PPTDeleteComments 过程接受两个参数:一个指示要修改的演示文稿的名称的参数(字符串)和(可选)一个指示要删除其所做注释的作者的姓名的参数(字符串)。如果您提供作者姓名,则代码将删除指定作者所做的注释;反之,代码将删除所有注释。

Public Sub PPTDeleteComments(
 ByVal fileName As String, Optional ByVal author As String = "")
public static void PPTDeleteComments(
  string fileName, string author = "")

此过程将修改您指定的演示文稿,并删除所有注释或由指定作者所做的注释。若要调用此过程,请传递参数值,如示例代码中所示。在运行示例代码之前,请务必提供一个名为 C:\temp\Comments.pptx 的文档 - 该文档(用于演示)包含至少一条注释。如此处所示,代码将删除所有注释。若要将结果限制为特定作者所做的注释,请将该作者的姓名作为第二个参数添加。

PPTDeleteComments("C:\temp\comments.pptx")
PPTDeleteComments(@"C:\temp\comments.pptx");

访问演示文稿

该代码首先会使用 PresentationDocument.Open 方法打开文档,并指示应打开文档以供读写访问(最后的 True 参数)。代码将立即检索对注释作者部分的引用,如果该引用为 null,则将退出此过程。如果没有注释作者,则不存在要删除的注释。

Using doc As PresentationDocument = 
  PresentationDocument.Open(fileName, True)

  Dim authorsPart As CommentAuthorsPart = 
    doc.PresentationPart.CommentAuthorsPart

  If authorsPart Is Nothing Then
    Return
  End If
  ' Code removed here…
End Using
using (PresentationDocument doc = 
  PresentationDocument.Open(fileName, true))
{
  CommentAuthorsPart authorsPart = 
    doc.PresentationPart.CommentAuthorsPart;

  if (authorsPart == null)
  {
    return;
  }
  // Code removed here…
}

检索作者列表

接下来,代码将从作者部分检索 CommentAuthor 元素的列表。如果您提供了姓名(这样您便能删除由特定作者所做的注释),则代码将进一步限制作者列表,使其只包含您指定的作者。

Dim commentAuthors = authorsPart.
  CommentAuthorList.Elements(Of CommentAuthor)()
If (Not String.IsNullOrEmpty(author)) Then
  commentAuthors = commentAuthors.
    Where(Function(e) e.Name.Value.Equals(author))
End If
var commentAuthors = authorsPart.
  CommentAuthorList.Elements<CommentAuthor>();
if (!string.IsNullOrEmpty(author))
{
  commentAuthors = commentAuthors.
    Where(e => e.Name.Value.Equals(author));
}

循环访问所有作者和幻灯片

下一步是循环访问所有注释作者,并从所有幻灯片中删除特定作者所做的注释。(作者列表将包含您在参数中指定的单个作者或所有作者。)代码将循环访问所有注释作者并存储作者 ID,然后循环访问幻灯片部分的列表。对于每个幻灯片,代码将检索对相应的注释部分的引用,并且该引用可为 null(如果当前幻灯片没有注释)。您在下一节中将看到处理每个注释的代码,并且循环将以从注释作者列表中删除当前注释的作者作为结束。

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.SlideParts
    ' Iterate through the slide parts and find the 
    ' slide comment part.
    Dim slideCommentsPart = Slide.SlideCommentsPart
    If slideCommentsPart IsNot Nothing Then
      ' Code removed here…
    End If
  Next slide
  commentAuthor.Remove()
Next commentAuthor
foreach (var commentAuthor in commentAuthors)
{
  var authorId = commentAuthor.Id;

  // Iterate through all the slides and get the slide parts.
  foreach (var slide in doc.PresentationPart.SlideParts)
  {
    // Iterate through the slide parts and find the slide comment part.
    var slideCommentsPart = slide.SlideCommentsPart;
    if (slideCommentsPart != null)
    {
      // Code removed here.
    }
  }
  commentAuthor.Remove();
}

处理注释

对于给定的幻灯片及其注释,代码将检索所有注释元素的列表。对于注释列表中由特定作者所做的每个注释(转换为数组,并强制执行 LINQ 查询),代码将删除当前注释。

Dim commentList = 
  slideCommentsPart.CommentList.Elements(Of Comment)(). 
  Where(Function(e) e.AuthorId.Value = authorId.Value)
For Each comment In commentList.ToArray()
  ' Delete all the comments by the specified author.
  comment.Remove()
Next comment
var commentList = slideCommentsPart.CommentList.
  Elements<Comment>().Where(e => e.AuthorId.Value == authorId.Value);

foreach (var comment in commentList.ToArray())
{
  // Delete all the comments by the specified author.
  comment.Remove();
}

在循环访问所有注释并删除指定作者所做的每个注释后,代码将确定是必须删除注释部分还是保存注释部分。如果未保留任何注释,则代码将删除注释部分;否则,代码将保存注释部分。

If slideCommentsPart.CommentList.Count() = 0 Then
  slide.DeletePart(slideCommentsPart)
Else
  slideCommentsPart.CommentList.Save()
End If
if (slideCommentsPart.CommentList.Count() == 0)
{
  slide.DeletePart(slideCommentsPart);
}
else
{
  slideCommentsPart.CommentList.Save();
}

删除或保存注释作者部分

完成所有删除操作后,注释作者列表将包含零个作者(如果您删除了所有注释或删除了最后的作者)或一个或多个作者(如果您指定了要删除的作者,并且演示文稿中包含来自多个作者的注释)。如果再也没有作者,则代码将删除注释作者部分;否则,代码将保存已修改的部分。

If authorsPart.CommentAuthorList.Count = 0 Then
  ' No authors left, so delete the part.
  doc.PresentationPart.DeletePart(authorsPart)
Else
  ' Save the comment authors part.
  authorsPart.CommentAuthorList.Save()
if (authorsPart.CommentAuthorList.Count() == 0)
{
  // No authors left, so delete the part.
  doc.PresentationPart.DeletePart(authorsPart);
}
else
{
  // Save the comment authors part.
  authorsPart.CommentAuthorList.Save();
}

示例过程

下面的代码演示了整个示例过程。

Public Sub PPTDeleteComments(ByVal fileName As String,
                             Optional ByVal author As String = "")

  Using doc As PresentationDocument = 
    PresentationDocument.Open(fileName, True)
    ' Get the authors part.
    Dim authorsPart As CommentAuthorsPart = 
      doc.PresentationPart.CommentAuthorsPart

    If authorsPart Is Nothing Then
      ' There is no authors part, so just
      ' fail. If no authors, there cannot be any comments.
      Return
    End If

    ' Get the comment authors, or the specified author if supplied:
    Dim commentAuthors = authorsPart.
      CommentAuthorList.Elements(Of CommentAuthor)()
    If (Not String.IsNullOrEmpty(author)) Then
      commentAuthors = commentAuthors.
        Where(Function(e) e.Name.Value.Equals(author))
    End If

    Dim changed As Boolean = False
    ' The commentAuthors list contains either all the authors, 
    ' or one author.
    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.SlideParts
        ' Iterate through the slide parts and find the 
        ' slide comment part.
        Dim slideCommentsPart = slide.SlideCommentsPart
        If slideCommentsPart IsNot Nothing Then

          ' Get the list of comments.
          Dim commentList = slideCommentsPart.CommentList.
            Elements(Of Comment)().
            Where(Function(e) e.AuthorId.Value = authorId.Value)
          For Each comment In commentList.ToArray()
            ' Delete all the comments by the specified author.
            comment.Remove()
          Next comment

          ' No comments left? Delete the comments part 
          ' for this slide.
          If slideCommentsPart.CommentList.Count() = 0 Then
            slide.DeletePart(slideCommentsPart)
          Else
            ' Save the slide comments part.
            slideCommentsPart.CommentList.Save()
          End If
        End If

      Next slide

      ' Delete the comment author from the comment authors part.
      commentAuthor.Remove()
    Next commentAuthor

    If authorsPart.CommentAuthorList.Count = 0 Then
      ' No authors left, so delete the part.
      doc.PresentationPart.DeletePart(authorsPart)
    Else
      ' Save the comment authors part.
      authorsPart.CommentAuthorList.Save()
    End If
  End Using
End Sub
public static void PPTDeleteComments(string fileName, string author = "")
{

  using (PresentationDocument doc = PresentationDocument.Open(fileName, true))
  {
    // Get the authors part.
    CommentAuthorsPart authorsPart = doc.PresentationPart.CommentAuthorsPart;

    if (authorsPart == null)
    {
      // There is no authors part, so just
      // fail. If no authors, there cannot be any comments.
      return;
    }

    // Get the comment authors, or the specified author if supplied:
    var commentAuthors = authorsPart.
      CommentAuthorList.Elements<CommentAuthor>();
    if (!string.IsNullOrEmpty(author))
    {
      commentAuthors = commentAuthors.
        Where(e => e.Name.Value.Equals(author));
    }

    foreach (var commentAuthor in commentAuthors)
    {
      var authorId = commentAuthor.Id;

      // Iterate through all the slides and get the slide parts.
      foreach (var slide in doc.PresentationPart.SlideParts)
      {
        // Iterate through the slide parts and find the slide comment part.
        var slideCommentsPart = slide.SlideCommentsPart;
        if (slideCommentsPart != null)
        {
            // Get the list of comments.
            var commentList = slideCommentsPart.CommentList.
              Elements<Comment>().Where(e => e.AuthorId.Value == authorId.Value);

            foreach (var comment in commentList.ToArray())
            {
              // Delete all the comments by the specified author.
              comment.Remove();
            }

          // No comments left? Delete the comments part for this slide.
          if (slideCommentsPart.CommentList.Count() == 0)
          {
            slide.DeletePart(slideCommentsPart);
          }
          else
          {
            // Save the slide comments part.
            slideCommentsPart.CommentList.Save();
          }
        }
      }

      // Delete the comment author from the comment authors part.
      commentAuthor.Remove();
    }

    if (authorsPart.CommentAuthorList.Count() == 0)
    {
      // No authors left, so delete the part.
      doc.PresentationPart.DeletePart(authorsPart);
    }
    else
    {
      // Save the comment authors part.
      authorsPart.CommentAuthorList.Save();
    }
  }
}
读取

此直观操作方法附带的示例演示了将删除 PowerPoint 演示文稿中的注释的代码。若要使用该示例,必须安装 Open XML SDK 2.0(可通过"浏览"一节中列出的链接获得)。该示例还将使用作为 Open XML SDK 2.0 代码示例集的一部分包含的修改后的代码。"浏览"一节还包括指向完整代码段集的链接,但您无需下载并安装代码段即可使用该示例。

示例应用程序仅演示了在修改演示文稿的结构时可与之交互的由 Open XML SDK 2.0 提供的几个可用属性和方法。有关详细信息,请参阅 Open XML SDK 2.0 Productivity Tool 附带的文档(单击应用程序窗口左下角的"Open XML SDK 文档"选项卡,并搜索要研究的类)。尽管该文档当前不包含代码示例,但借助此处所示的示例和文档,您应能成功修改示例应用程序。

观看

观看视频

观看视频(该链接可能指向英文页面) | 时长:20:29

单击以获取代码

获取代码(该链接可能指向英文页面)

浏览

关于作者
Ken Getz 是 MCW Technologies 的高级顾问。他是 ASP.NET Developers Jumpstart(《ASP.NET 开发人员入门》,Addison-Wesley,2002)、Access Developer's Handbook(《Access 开发人员手册》,Sybex,2001)和 VBA Developer's Handbook, 2nd Edition(《VBA 开发人员手册第 2 版》,Sybex,2001)的合著者。