Deleting Comments By All or Specific Authors in PowerPoint 2010 Documents by Using the Open XML SDK 2.0

Office Visual How To

Summary: Use the strongly typed classes in the Open XML SDK 2.0 for Microsoft Office to delete comments by all or specific authors in a PowerPoint document, without loading the document into PowerPoint.

Applies to: Excel 2010 | Office 2010 | Open XML | PowerPoint 2010 | VBA | Word 2010

Published:  October 2010

Provided by:  Ken Getz, MCW Technologies

Overview

The Open XML file formats make it possible to delete comments in Microsoft Office PowerPoint 2007 and Microsoft PowerPoint 2010 documents, but doing so requires some effort. The Open XML SDK 2.0 for Microsoft Office adds strongly typed classes that simplify access to the Open XML file formats; the SDK simplifies the tasks of retrieving a list of and deleting comments. The code sample included with this Visual How To shows how to the use the SDK to accomplish this goal.

Code It

The sample provided with this Visual How To includes the code necessary to delete comments by one or all authors in a PowerPoint 2007 or PowerPoint 2010 document. The following sections discuss the code in detail.

Setting Up References

To use the code from the Open XML SDK 2.0, you must add a few references to your project. The sample project already includes these references; however, in your own code, you would need to explicitly reference the following assemblies:

  • WindowsBase—This reference may already be set for you, depending on the type of project you create.

  • DocumentFormat.OpenXml—Installed by the Open XML SDK 2.0.

Also, add the following using/Imports statements to the top of your code file.

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

Examining the Procedure

The PPTDeleteComments procedure accepts two parameters, indicating the name of the presentation to modify (string) and, optionally, the name of the author whose comments you want to delete (string). If you supply an author name, the code deletes comments by the specified author; if not, the code deletes all comments.

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

The procedure modifies the presentation you specify, deleting all comments, or comments by a specific author. To call the procedure, pass the parameter values, as shown in the example code. Be sure you provide a document named C:\temp\Comments.pptx—which (for demonstration purposes) contains at least a single comment—before running the sample code. As shown here, the code will remove all comments. To limit the results to comments by a particular author, add the author name as the second parameter.

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

Accessing the Presentation

The code starts by opening the document, using the PresentationDocument.Open method and indicating that the document should be opened for read/write access (the final True parameter). The code immediately retrieves a reference to the comment authors part and, if the reference is null, exits from the procedure. If there are not any comment authors, there cannot be any comments to delete.

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…
}

Retrieving the List of Authors

Next, the code retrieves a list of CommentAuthor elements from the authors part. If you supplied a name (so that you can delete comments by a particular author), the code further restricts the list of authors to include only the one author you specified.

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));
}

Looping Through all Authors and Slides

The next step is to loop through all the comment authors and, for all of the slides, delete comments by the particular author. (The list of authors will contain either the single author you indicated in the parameters, or all the authors.) The code loops through all the comment authors, storing the author ID, and then iterates through the list of slide parts. For each slide, the code retrieves a reference to the corresponding comments part, and the reference can be null (if there are no comments for the current slide). You will see the code that deals with each comment in the next section, and the loop concludes by removing the current comment author from the list of comment 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.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();
}

Handling Comments

For a given slide and its comments, the code retrieves a list of all the comment elements. For each comment in the list of comments for the particular author (converted into an array, forcing the LINQ query to execute), the code deletes the current comment.

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();
}

After looping through all the comments and deleting each for the specified author, the code determines whether it must delete the comments part or save the part. If there are no comments left, the code deletes the part; otherwise, it saves the part.

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();
}

Deleting or Saving the Comment Authors Part

After all the deletion, the comment author list will either contain zero authors (if you deleted all comments, or deleted the final author) or one or more authors (if you specified an author to delete, and there were comments from more than one author in the presentation). If there are no more authors, the code deletes the comment authors part; otherwise, it saves the modified part.

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();
}

Sample Procedure

The following code shows the full sample procedure.

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();
    }
  }
}
Read It

The sample included with this Visual How To demonstrates code that deletes comments from a PowerPoint presentation. To use the sample, you must install the Open XML SDK 2.0, which is available from the link listed in the Explore It section. The sample also uses a modified version of code included as part of a set of code snippets for the Open XML SDK 2.0. The Explore It section also includes a link to the full set of snippets, although you can use the sample without downloading and installing the snippets.

The sample application demonstrates only a handful of the available properties and methods provided by the Open XML SDK 2.0 that you can interact with when modifying a presentation's structure. For more information, see the documentation that comes with the Open XML SDK 2.0 Productivity Tool (click the Open XML SDK Documentation tab in the lower-left corner of the application window, and search for the class you need to study). Although the documentation does not currently include code examples, given the sample shown here and the documentation, you should be able to successfully modify the sample application.

See It

Watch the video

> [!VIDEO https://www.microsoft.com/en-us/videoplayer/embed/2ea3bdb7-75a9-47e8-ace1-be23c0764116]

Length: 00:20:29

Click to grab code

Grab the Code

Explore It

About the Author
Ken Getz is a senior consultant with MCW Technologies. He is coauthor of ASP.NET Developers Jumpstart (Addison-Wesley, 2002), Access Developer's Handbook (Sybex, 2001), and VBA Developer's Handbook, 2nd Edition (Sybex, 2001).