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 classe WordprocessingDocument comme indiqué dans l'instruction using suivante. Dans la même instruction, ouvrez le fichier de traitement de texte au chemin d’accès spécifié à l’aide de la méthode Open(String, Boolean), avec le paramètre booléen défini sur true pour permettre la modification dans le document.
using (WordprocessingDocument document =
WordprocessingDocument.Open(filepath, true))
{
// Insert other code here.
}
L'instruction using offre une alternative recommandée pour la séquence .Open, .Save, .Close standard. Elle permet de garantir que la méthode Dispose (méthode interne utilisée par le kit de développement logiciel Open XML pour nettoyer les ressources) 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, dans le cas présent document.
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 de document de type Paragraph. La méthode First est membre de la classe System.Linq.Enumerable . La classe System.Linq.Enumerable fournit des méthodes d’extension pour les objets qui implémentent l’interface System.Collections.Generic.IEnumerable .
Paragraph firstParagraph = document.MainDocumentPart.Document.Descendants<Paragraph>().First();
Comments comments = null;
string id = "0";
Le code détermine d’abord si un composant WordprocessingCommentsPart existe. Pour ce faire, appelez la méthode générique MainDocumentPart , GetPartsCountOfType, et spécifiez un type de WordprocessingCommentsPart.
S’il existe un composant WordprocessingCommentsPart , le code obtient une nouvelle valeur Id pour l’objet Comment qu’il ajoutera à l’objet de collection WordprocessingCommentsPartComments existant. Pour ce faire, il recherche la valeur d’attribut Id la plus élevée donnée à un Commentaire dans l’objet de collection Comments , incrémente la valeur d’un, puis la stocke en tant que valeur Id . Si aucun composant WordprocessingCommentsPart n’existe, le code en crée un à l’aide de la méthode AddNewPart<T>() de l’objet MainDocumentPart , puis y ajoute un objet de collection Comments .
if (document.MainDocumentPart.GetPartsCountOfType<WordprocessingCommentsPart>() > 0)
{
comments =
document.MainDocumentPart.WordprocessingCommentsPart.Comments;
if (comments.HasChildren)
{
id = (comments.Descendants<Comment>().Select(e => int.Parse(e.Id.Value)).Max() + 1).ToString();
}
}
else
{
WordprocessingCommentsPart commentPart =
document.MainDocumentPart.AddNewPart<WordprocessingCommentsPart>();
commentPart.Comments = new Comments();
comments = commentPart.Comments;
}
Les objets Comment et Comments représentent respectivement des éléments comment et comments dans le schéma Open XML Wordprocessing. Un Comment doit être ajouté à un objet Comments de sorte que le code instancie d’abord un objet Comments (à l’aide des arguments de type chaîne author, initials et comments, qui ont été passés à la méthode AddCommentOnFirstParagraph).
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 et enregistre les modifications. Cela crée l’arborescence DOM (Document Model Object) XML requise en mémoire, qui est constituée d’un élément parent comments avec des éléments enfants comment au-dessous.
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);
comments.AppendChild(cmt);
comments.Save();
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>
Avec l’objet Comment instancié, le code associe le Comment à une plage de texte dans le document Wordprocessing. Les objets CommentRangeStart et CommentRangeEnd correspondent aux éléments commentRangeStart et commentRangeEnd dans le schéma Wordprocessing Open XML. Un objet CommentRangeStart est donné comme argument à la méthode InsertBefore<T>(T, OpenXmlElement) de l’objet Paragraph et un objet CommentRangeEnd est passé à la méthode InsertAfter<T>(T, OpenXmlElement). 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 objet CommentReference représente un élément commentReference dans le schéma Wordprocessing Open XML. Un commentReference établit une liaison entre un commentaire spécifique dans le composant WordprocessingCommentsPart (le fichier Comments.xml dans le package Wordprocessing) et un emplacement spécifique dans le corps du document (le composant MainDocumentPart contenu dans le fichier Document.xml dans le package Wordprocessing). L’attribut id du commentaire, commentRangeStart, commentRangeEnd et commentReference étant identiques pour un commentaire donné, l’attribut id de commentReference doit par conséquent correspondre à la valeur de l’attribut id du commentaire auquel il est lié. Dans l’exemple, le code ajoute un élément commentReference à l’aide de l’API et instancie un objet CommentReference , en spécifiant la valeur Id , puis l’ajoute à un objet Run .
firstParagraph.InsertBefore(new CommentRangeStart()
{ Id = id }, firstParagraph.GetFirstChild<Run>());
var cmtEnd = firstParagraph.InsertAfter(new CommentRangeEnd()
{ Id = id }, firstParagraph.Elements<Run>().Last());
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 d’accès du document, votre nom, vos initiales et le texte de commentaire. Par exemple, l’appel suivant à la méthode AddCommentOnFirstParagraph écrit le commentaire « This is my comment. » dans le fichier « Word8.docx ».
AddCommentOnFirstParagraph(@"C:\Users\Public\Documents\Word8.docx",
author, initials, "This is my comment.");
Voici un exemple de code complet en C# et Visual Basic.
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using System;
using System.Linq;
AddCommentOnFirstParagraph(args[0], args[1], args[2], args[3]);
// 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/* || document.MainDocumentPart.WordprocessingCommentsPart 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);
wordprocessingCommentsPart.Comments.Save();
// 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
Language Integrated Query (LINQ)