Partager via


Supprimer les commentaires de tous les auteurs ou d’un auteur spécifique dans un document de traitement de texte

Cette rubrique montre comment utiliser les classes du Kit de développement logiciel (SDK) Open XML pour Office pour supprimer par programmation les commentaires de tout ou d’un auteur spécifique dans un document de traitement de texte, sans avoir à charger le document dans Microsoft Word. Il contient un exemple DeleteComments de méthode pour illustrer cette tâche.


Méthode DeleteComments

Vous pouvez utiliser la DeleteComments méthode pour supprimer tous les commentaires d’un document de traitement de texte, ou uniquement ceux écrits par un auteur spécifique. Comme le montre le code suivant, la méthode accepte deux paramètres pour indiquer le nom du document à modifier (chaîne) et, facultativement, le nom de l'auteur dont vous souhaitez supprimer les commentaires (chaîne). Si vous fournissez un nom d'auteur, le code supprime les commentaires écrits par l'auteur spécifié. Si vous ne fournissez pas de nom d'auteur, le code supprime tous les commentaires du document.

// 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 = "")

Appel de la méthode DeleteComments

Pour appeler la DeleteComments méthode, fournissez les paramètres requis comme indiqué dans le code suivant.

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

Fonctionnement du code

Le code suivant commence par ouvrir le document, en utilisant la WordprocessingDocument.Open méthode et en indiquant que le document doit être ouvert pour l’accès en lecture/écriture (la valeur du paramètre final true ). Ensuite, le code récupère une référence au composant commentaires, à l’aide de la WordprocessingCommentsPart propriété du composant de document main, après avoir récupéré une référence au composant de document main à partir de la MainDocumentPart propriété du document de traitement de texte. Si la partie des commentaires est absente, il n'y a pas lieu de continuer, car il n'y a pas de commentaire à supprimer.

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

Création de la liste de commentaires

Le code effectue ensuite deux tâches : la création d’une liste de tous les commentaires à supprimer et la création d’une liste d’ID de commentaire qui correspondent aux commentaires à supprimer. Compte tenu de ces listes, le code peut supprimer les commentaires de la partie commentaires qui contient les commentaires et supprimer les références aux commentaires du composant de document. Le code suivant commence par récupérer une liste d’éléments Comment . Pour récupérer la liste, il convertit la Elements() collection exposée par la commentPart variable en liste d’objets Comment .

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

Jusqu'ici, la liste des commentaires contient tous les commentaires. Si le paramètre author n’est pas une chaîne vide, le code suivant limite la liste aux seuls commentaires dont la Author propriété correspond au paramètre que vous avez fourni.

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

Avant de supprimer des commentaires, le code récupère une liste de valeurs d'ID de commentaires, afin qu'il puisse ultérieurement supprimer les éléments correspondants de la partie document. L’appel à la Select méthode projette efficacement la liste des commentaires, en récupérant un IEnumerable<T> de chaînes qui contiennent toutes les valeurs d’ID de commentaire.

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

Suppression des commentaires et enregistrement de la partie

Étant donné la commentsToDelete collection, le code suivant effectue une boucle dans tous les commentaires qui nécessitent la suppression et effectue la suppression.

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

Suppression des références de commentaires dans le document

Bien que le code ait effectué la suppression de tous les commentaires à ce stade, cela ne suffit pas. Il doit également supprimer les références aux commentaires de la partie document. Cette action nécessite trois étapes, car la référence de commentaire inclut les CommentRangeStartéléments , CommentRangeEndet CommentReference , et le code doit supprimer les trois pour chaque commentaire. Avant d'exécuter des suppressions, le code récupère d'abord une référence à l'élément racine de la partie principale du document, comme le montre le code suivant.

    Document doc = document.MainDocumentPart.Document;

Disposant d'une référence à l'élément de document, le code suivant effectue trois boucles, une boucle pour chacun des éléments qu'il doit supprimer. Dans chaque cas, le code recherche tous les descendants du type correct (CommentRangeStart, , CommentRangeEndou CommentReference) et limite la liste à ceux dont Id la valeur de propriété est contenue dans la liste des ID de commentaire à supprimer. En s'appuyant sur la liste des éléments à supprimer, le code supprime chaque élément à tour de rôle. Enfin, le code se termine en enregistrant le 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();
}

Exemple de code

Voici l’exemple de code complet en C# et en 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();
        }
    }
}

Voir aussi