Freigeben über


Löschen der Kommentare eines oder aller Autoren aus einem Textverarbeitungsdokument

In diesem Thema wird gezeigt, wie Sie die Klassen im Open XML SDK für Office verwenden, um Kommentare von allen oder einem bestimmten Autor in einem Textverarbeitungsdokument programmgesteuert zu löschen, ohne das Dokument in Microsoft Word laden zu müssen. Sie enthält eine Beispielmethode DeleteComments zur Veranschaulichung dieser Aufgabe.


DeleteComments-Methode

Sie können die DeleteComments -Methode verwenden, um alle Kommentare aus einem Textverarbeitungsdokument oder nur die Kommentare eines bestimmten Autors zu löschen. Wie der folgende Code zeigt, akzeptiert die Methode zwei Parameter, die den Namen des zu ändernden Dokuments (Zeichenfolge) und optional den Namen des Autors angeben, dessen Kommentare Sie löschen möchten (Zeichenfolge). Wenn Sie einen Autorennamen angeben, löscht der Code Kommentare dieses Autors. Wenn Sie keinen Autorennamen angeben, löscht der Code alle Kommentare.

// Delete comments by a specific author. Pass an empty string for the 
// author to delete all comments, by all authors.
static void DeleteComments(string fileName, string author = "")

Aufrufen der DeleteComments-Methode

Um die DeleteComments -Methode aufzurufen, geben Sie die erforderlichen Parameter an, wie im folgenden Code gezeigt.

if (args is [{ } fileName, { } author])
{
    DeleteComments(fileName, author);
}
else if (args is [{ } fileName2])
{
    DeleteComments(fileName2);
}

Funktionsweise des Codes

Der folgende Code beginnt mit dem Öffnen des Dokuments mit der WordprocessingDocument.Open -Methode und gibt an, dass das Dokument für Lese-/Schreibzugriff geöffnet sein soll (der endgültige true Parameterwert). Als Nächstes ruft der Code mithilfe der WordprocessingCommentsPart -Eigenschaft des Standard Dokumentteils einen Verweis auf den Kommentarteil ab, nachdem ein Verweis auf das Standard Dokumentteil aus der MainDocumentPart -Eigenschaft des Textverarbeitungsdokuments abgerufen wurde. Wenn der Kommentarteil fehlt, muss der Vorgang nicht fortgesetzt werden, da es keine zu löschenden Kommentare gibt.

// Get an existing Wordprocessing document.
using (WordprocessingDocument document = WordprocessingDocument.Open(fileName, true))
{

    if (document.MainDocumentPart is null)
    {
        throw new ArgumentNullException("MainDocumentPart is null.");
    }

    // Set commentPart to the document WordprocessingCommentsPart, 
    // if it exists.
    WordprocessingCommentsPart? commentPart = document.MainDocumentPart.WordprocessingCommentsPart;

    // If no WordprocessingCommentsPart exists, there can be no 
    // comments. Stop execution and return from the method.
    if (commentPart is null)
    {
        return;
    }

Erstellen einer Liste der Kommentare

Der Code führt als Nächstes zwei Aufgaben aus: Erstellen einer Liste aller zu löschenden Kommentare und Erstellen einer Liste von Kommentar-IDs, die den zu löschenden Kommentaren entsprechen. Bei diesen Listen kann der Code sowohl die Kommentare aus dem Kommentarteil löschen, der die Kommentare enthält, als auch die Verweise auf die Kommentare aus dem Dokumentteil. Der folgende Code ruft zunächst eine Liste von Comment Elementen ab. Zum Abrufen der Liste wird die von der Elements()commentPart Variablen verfügbar gemachte Auflistung in eine Liste von Comment -Objekten konvertiert.

List<Comment> commentsToDelete = commentPart.Comments.Elements<Comment>().ToList();

Bislang enthält die Liste der Kommentare alle Kommentare. Wenn der parameter author keine leere Zeichenfolge ist, beschränkt der folgende Code die Liste auf die Kommentare, bei denen die Author Eigenschaft mit dem angegebenen Parameter übereinstimmt.

if (!String.IsNullOrEmpty(author))
{
    commentsToDelete = commentsToDelete.Where(c => c.Author == author).ToList();
}

Vor dem Löschen von Kommentaren ruft der Code eine Liste der Kommentar-ID-Werte ab, um später übereinstimmende Elemente aus dem Dokumentteil zu löschen. Der Aufruf der Select -Methode projiziert effektiv die Liste der Kommentare und ruft eine IEnumerable<T> von Zeichenfolgen ab, die alle Kommentar-ID-Werte enthalten.

IEnumerable<string?> commentIds = commentsToDelete.Where(r => r.Id is not null && r.Id.HasValue).Select(r => r.Id?.Value);

Löschen von Kommentaren und Speichern des Teils

In Anbetracht der commentsToDelete Auflistung durchläuft der folgende Code alle Kommentare, die gelöscht werden müssen, und führt den Löschvorgang aus.

// Delete each comment in commentToDelete from the 
// Comments collection.
foreach (Comment c in commentsToDelete)
{
    if (c is not null)
    {
        c.Remove();
    }
}

Löschen von Kommentarverweisen aus dem Dokument

Obgleich der Code an dieser Stelle alle Kommentare erfolgreich entfernt hat, reicht dies noch nicht aus. Der Code muss auch Verweise auf die Kommentare aus dem Dokumentteil entfernen. Diese Aktion erfordert drei Schritte, da der Kommentarverweis die CommentRangeStartElemente , CommentRangeEndund CommentReference enthält, und der Code muss alle drei Für jeden Kommentar entfernen. Vor den Löschvorgängen ruft der Code zunächst einen Verweis auf das Stammelement des Hauptdokumentteils ab (siehe den folgenden Code).

    Document doc = document.MainDocumentPart.Document;

Bei einem Verweis auf das Dokumentelement führt der folgende Code seine Löschschleife dreimal aus, einmal für jedes der verschiedenen Elemente, die es löschen muss. In jedem Fall sucht der Code nach allen Nachfolgern des richtigen Typs (CommentRangeStart, CommentRangeEndoder CommentReference) und beschränkt die Liste auf diejenigen, deren Id Eigenschaftswert in der Liste der zu löschenden Kommentar-IDs enthalten ist. Angesichts der Liste der zu löschenden Elemente entfernt der Code jedes Element nacheinander. Schließlich wird der Code durch Speichern des Dokuments abgeschlossen.

// Delete CommentRangeStart for each
// deleted comment in the main document.
List<CommentRangeStart> commentRangeStartToDelete = doc.Descendants<CommentRangeStart>()
                                                    .Where(c => c.Id is not null && c.Id.HasValue && commentIds.Contains(c.Id.Value))
                                                    .ToList();

foreach (CommentRangeStart c in commentRangeStartToDelete)
{
    c.Remove();
}

// Delete CommentRangeEnd for each deleted comment in the main document.
List<CommentRangeEnd> commentRangeEndToDelete = doc.Descendants<CommentRangeEnd>()
                                                .Where(c => c.Id is not null && c.Id.HasValue && commentIds.Contains(c.Id.Value))
                                                .ToList();

foreach (CommentRangeEnd c in commentRangeEndToDelete)
{
    c.Remove();
}

// Delete CommentReference for each deleted comment in the main document.
List<CommentReference> commentRangeReferenceToDelete = doc.Descendants<CommentReference>()
                                                        .Where(c => c.Id is not null && c.Id.HasValue && commentIds.Contains(c.Id.Value))
                                                        .ToList();

foreach (CommentReference c in commentRangeReferenceToDelete)
{
    c.Remove();
}

Beispielcode

Es folgt der vollständige Beispielcode in C# und Visual Basic.

using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using System;
using System.Collections.Generic;
using System.Linq;


// Delete comments by a specific author. Pass an empty string for the 
// author to delete all comments, by all authors.
static void DeleteComments(string fileName, string author = "")
{
    // Get an existing Wordprocessing document.
    using (WordprocessingDocument document = WordprocessingDocument.Open(fileName, true))
    {

        if (document.MainDocumentPart is null)
        {
            throw new ArgumentNullException("MainDocumentPart is null.");
        }

        // Set commentPart to the document WordprocessingCommentsPart, 
        // if it exists.
        WordprocessingCommentsPart? commentPart = document.MainDocumentPart.WordprocessingCommentsPart;

        // If no WordprocessingCommentsPart exists, there can be no 
        // comments. Stop execution and return from the method.
        if (commentPart is null)
        {
            return;
        }

        // Create a list of comments by the specified author, or
        // if the author name is empty, all authors.
        List<Comment> commentsToDelete = commentPart.Comments.Elements<Comment>().ToList();

        if (!String.IsNullOrEmpty(author))
        {
            commentsToDelete = commentsToDelete.Where(c => c.Author == author).ToList();
        }

        IEnumerable<string?> commentIds = commentsToDelete.Where(r => r.Id is not null && r.Id.HasValue).Select(r => r.Id?.Value);

        // Delete each comment in commentToDelete from the 
        // Comments collection.
        foreach (Comment c in commentsToDelete)
        {
            if (c is not null)
            {
                c.Remove();
            }
        }

        Document doc = document.MainDocumentPart.Document;

        // Delete CommentRangeStart for each
        // deleted comment in the main document.
        List<CommentRangeStart> commentRangeStartToDelete = doc.Descendants<CommentRangeStart>()
                                                            .Where(c => c.Id is not null && c.Id.HasValue && commentIds.Contains(c.Id.Value))
                                                            .ToList();

        foreach (CommentRangeStart c in commentRangeStartToDelete)
        {
            c.Remove();
        }

        // Delete CommentRangeEnd for each deleted comment in the main document.
        List<CommentRangeEnd> commentRangeEndToDelete = doc.Descendants<CommentRangeEnd>()
                                                        .Where(c => c.Id is not null && c.Id.HasValue && commentIds.Contains(c.Id.Value))
                                                        .ToList();

        foreach (CommentRangeEnd c in commentRangeEndToDelete)
        {
            c.Remove();
        }

        // Delete CommentReference for each deleted comment in the main document.
        List<CommentReference> commentRangeReferenceToDelete = doc.Descendants<CommentReference>()
                                                                .Where(c => c.Id is not null && c.Id.HasValue && commentIds.Contains(c.Id.Value))
                                                                .ToList();

        foreach (CommentReference c in commentRangeReferenceToDelete)
        {
            c.Remove();
        }
    }
}

Siehe auch