Partager via


Insérer un commentaire 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 afin d’ajouter par programmation un commentaire au premier paragraphe d’un document de traitement de texte.


Ouvrir le document existant en mode édition

Pour ouvrir un document existant, instanciez la WordprocessingDocument classe comme indiqué dans l’instruction suivante using . Dans la même instruction, ouvrez le fichier de traitement de texte au chemin d’accès de fichier spécifié à l’aide de la Open(String, Boolean) méthode , avec le paramètre booléen défini sur true pour permettre la modification dans le document.

using (WordprocessingDocument document = WordprocessingDocument.Open(fileName, true))

Avec v3.0.0+ la Close() méthode a été supprimée au profit de l’instruction using. Il garantit que la Dispose() méthode est automatiquement appelée lorsque l’accolade fermante est atteinte. Le bloc qui suit l’instruction using établit une étendue pour l’objet créé ou nommé dans l’instruction using. Étant donné que la WordprocessingDocument classe du Kit de développement logiciel (SDK) Open XML enregistre et ferme automatiquement l’objet dans le cadre de son IDisposable implémentation, et que Dispose() est appelée automatiquement lorsque vous quittez le bloc, vous n’avez pas à appeler Save() explicitement ou Dispose() tant que vous utilisez une using instruction.


Fonctionnement de l’exemple de code

Après ouverture du document, vous pouvez rechercher le premier paragraphe pour y joindre un commentaire. Le code recherche le premier paragraphe en appelant la méthode d’extension First sur tous les éléments descendants de l’élément document qui sont de type Paragraph. La First méthode est membre de la Enumerable classe . La System.Linq.Enumerable classe fournit des méthodes d’extension pour les objets qui implémentent l’interface IEnumerable<T> .

Paragraph firstParagraph = document.MainDocumentPart.Document.Descendants<Paragraph>().First();
wordprocessingCommentsPart.Comments ??= new Comments();
string id = "0";

Le code détermine d’abord si un WordprocessingCommentsPart composant existe. Pour ce faire, appelez la MainDocumentPart méthode générique , GetPartsCountOfTypeet spécifiez un type de WordprocessingCommentsPart.

S’il existe un WordprocessingCommentsPart composant, le code obtient une nouvelle Id valeur pour l’objet Comment qu’il ajoutera à l’objet de collection existant WordprocessingCommentsPartComments . Pour ce faire, il recherche la valeur d’attribut la plus élevée Id donnée à un Comment dans l’objet Comments de collection, incrémente la valeur d’un, puis la stocke comme Id valeur. S’il n’existe aucun WordprocessingCommentsPart composant, le code en crée un à l’aide de la AddNewPart méthode de l’objet MainDocumentPart , puis y ajoute un Comments objet de collection.

if (document.MainDocumentPart.GetPartsOfType<WordprocessingCommentsPart>().Count() > 0)
{
    if (wordprocessingCommentsPart.Comments.HasChildren)
    {
        // Obtain an unused ID.
        id = (wordprocessingCommentsPart.Comments.Descendants<Comment>().Select(e =>
        {
            if (e.Id is not null && e.Id.Value is not null)
            {
                return int.Parse(e.Id.Value);
            }
            else
            {
                throw new ArgumentNullException("Comment id and/or value are null.");
            }
        })
            .Max() + 1).ToString();
    }
}

Les Comment objets et Comments représentent les éléments commentaires et commentaires, respectivement, dans le schéma Wordprocessing Open XML. Un Comment doit être ajouté à un Comments objet afin que le code instancie d’abord un Comments objet (à l’aide des arguments authorde chaîne , initialset comments qui ont été passés à la AddCommentOnFirstParagraph méthode ).

Le commentaire est représenté par l’exemple de code WordprocessingML suivant. .

    <w:comment w:id="1" w:initials="User">
      ...
    </w:comment>

Le code ajoute ensuite le Comment à l’objet Comments . Cela crée l’arborescence DOM (Document Object Model) XML requise en mémoire, qui se compose d’un comments élément parent avec comment des éléments enfants sous celui-ci.

Paragraph p = new Paragraph(new Run(new Text(comment)));
Comment cmt =
    new Comment()
    {
        Id = id,
        Author = author,
        Initials = initials,
        Date = DateTime.Now
    };
cmt.AppendChild(p);
wordprocessingCommentsPart.Comments.AppendChild(cmt);

L’exemple de code WordprocessingML suivant représente le contenu d’un composant commentaires dans un document WordprocessingML.

    <w:comments>
      <w:comment … >
        …
      </w:comment>
    </w:comments>

Une fois l’objet Comment instancié, le code associe le Comment à une plage dans le document Wordprocessing. CommentRangeStart Les objets et CommentRangeEnd correspondent aux commentRangeStart éléments et commentRangeEnd dans le schéma Wordprocessing Open XML. Un CommentRangeStart objet est donné comme argument à la InsertBefore méthode de l’objet Paragraph et un CommentRangeEnd objet est passé à la InsertAfter méthode . Cela crée une plage de commentaires dont l’étendue commence juste avant le premier caractère du premier paragraphe dans le document Wordprocessing et se termine juste après le dernier caractère du premier paragraphe.

Un CommentReference objet représente un commentReference élément dans le schéma Wordprocessing Open XML. Un objet commentReference lie un commentaire spécifique dans la WordprocessingCommentsPart partie (fichier Comments.xml dans le package Wordprocessing) à un emplacement spécifique dans le corps du document (partie MainDocumentPart contenue dans le fichier Document.xml dans le package Wordprocessing). L’attribut id du comment, commentRangeStart, commentRangeEnd et commentReference étant le même pour un commentaire donné, l’attribut commentReference id doit correspondre à la valeur de l’attribut comment id auquel il est lié. Dans l’exemple, le code ajoute un commentReference élément à l’aide de l’API et instancie un CommentReference objet, en spécifiant la Id valeur, puis l’ajoute à un Run objet .

firstParagraph.InsertBefore(new CommentRangeStart()
{ Id = id }, firstParagraph.GetFirstChild<Run>());

// Insert the new CommentRangeEnd after last run of paragraph.
var cmtEnd = firstParagraph.InsertAfter(new CommentRangeEnd()
{ Id = id }, firstParagraph.Elements<Run>().Last());

// Compose a run with CommentReference and insert it.
firstParagraph.InsertAfter(new Run(new CommentReference() { Id = id }), cmtEnd);

Exemple de code

L’exemple de code suivant montre comment créer un commentaire et l’associer à une plage dans un document de traitement de texte. Pour appeler la méthode AddCommentOnFirstParagraph , passez le chemin du document, votre nom, vos initiales et le texte du commentaire.

string fileName = args[0];
string author = args[1];
string initials = args[2];
string comment = args[3];

AddCommentOnFirstParagraph(fileName, author, initials, comment);

Voici un exemple de code complet en C# et Visual Basic.

// Insert a comment on the first paragraph.
static void AddCommentOnFirstParagraph(string fileName, string author, string initials, string comment)
{
    // Use the file name and path passed in as an 
    // argument to open an existing Wordprocessing document. 
    using (WordprocessingDocument document = WordprocessingDocument.Open(fileName, true))
    {
        if (document.MainDocumentPart is null)
        {
            throw new ArgumentNullException("MainDocumentPart and/or Body is null.");
        }

        WordprocessingCommentsPart wordprocessingCommentsPart = document.MainDocumentPart.WordprocessingCommentsPart ?? document.MainDocumentPart.AddNewPart<WordprocessingCommentsPart>();

        // Locate the first paragraph in the document.
        Paragraph firstParagraph = document.MainDocumentPart.Document.Descendants<Paragraph>().First();
        wordprocessingCommentsPart.Comments ??= new Comments();
        string id = "0";

        // Verify that the document contains a 
        // WordProcessingCommentsPart part; if not, add a new one.
        if (document.MainDocumentPart.GetPartsOfType<WordprocessingCommentsPart>().Count() > 0)
        {
            if (wordprocessingCommentsPart.Comments.HasChildren)
            {
                // Obtain an unused ID.
                id = (wordprocessingCommentsPart.Comments.Descendants<Comment>().Select(e =>
                {
                    if (e.Id is not null && e.Id.Value is not null)
                    {
                        return int.Parse(e.Id.Value);
                    }
                    else
                    {
                        throw new ArgumentNullException("Comment id and/or value are null.");
                    }
                })
                    .Max() + 1).ToString();
            }
        }

        // Compose a new Comment and add it to the Comments part.
        Paragraph p = new Paragraph(new Run(new Text(comment)));
        Comment cmt =
            new Comment()
            {
                Id = id,
                Author = author,
                Initials = initials,
                Date = DateTime.Now
            };
        cmt.AppendChild(p);
        wordprocessingCommentsPart.Comments.AppendChild(cmt);

        // Specify the text range for the Comment. 
        // Insert the new CommentRangeStart before the first run of paragraph.
        firstParagraph.InsertBefore(new CommentRangeStart()
        { Id = id }, firstParagraph.GetFirstChild<Run>());

        // Insert the new CommentRangeEnd after last run of paragraph.
        var cmtEnd = firstParagraph.InsertAfter(new CommentRangeEnd()
        { Id = id }, firstParagraph.Elements<Run>().Last());

        // Compose a run with CommentReference and insert it.
        firstParagraph.InsertAfter(new Run(new CommentReference() { Id = id }), cmtEnd);
    }
}

Voir aussi