public void CanCreateComment() { // Let's say we have a document called Comments.docx with a single // paragraph saying "Hello World!". using WordprocessingDocument wordDocument = WordprocessingDocument.Create( "Comments.docx", WordprocessingDocumentType.Document); MainDocumentPart mainDocumentPart = wordDocument.AddMainDocumentPart(); mainDocumentPart.Document = new Document( new Body( new Paragraph( new Run( new Text("Hello World!"))))); // We can add a WordprocessingCommentsPart to the MainDocumentPart // and make sure it has a w:comments root element. var commentsPart = mainDocumentPart.AddNewPart <WordprocessingCommentsPart>(); commentsPart.Comments = new Comments(); // Now, say we want to comment on the whole paragraph. As a first // step, we create a comment and add it to the w:comments element. var comment = new Comment(new Paragraph(new Run(new Text("This is my comment.")))) { Id = "1", Author = "Thomas Barnekow" }; commentsPart.Comments.AppendChild(comment); // Then, we need to add w:commentRangeStart and w:commentRangeEnd // elements to the text on which we want to comment. In this example, // we are getting "some" w:p element and some first and last w:r // elements and insert the w:commentRangeStart before the first and // the w:commentRangeEnd after the last w:r. Paragraph p = mainDocumentPart.Document.Descendants <Paragraph>().First(); Run firstRun = p.Elements <Run>().First(); Run lastRun = p.Elements <Run>().Last(); firstRun.InsertBeforeSelf(new CommentRangeStart { Id = "1" }); CommentRangeEnd commentRangeEnd = lastRun.InsertAfterSelf(new CommentRangeEnd { Id = "1" }); commentRangeEnd.InsertAfterSelf(new Run(new CommentReference { Id = "1" })); }
public static void AddCommentNearElement(this WordprocessingDocument document, OpenXmlElement element, Author author, string comment, string fontName = "Times New Roman", string fontSize = "28") { Comments comments = null; int id = 0; //var lastRun = paragraph.Descendants<Run>().ToList().LastOrDefault(); if (document.MainDocumentPart.GetPartsOfType <WordprocessingCommentsPart>().Any()) { comments = document.MainDocumentPart.WordprocessingCommentsPart.Comments; if (comments.HasChildren) { // Obtain an unused ID. id = comments.Descendants <Comment>().Select(e => Int32.Parse(e.Id.Value)).Max(); id++; } } else { WordprocessingCommentsPart commentPart = document.MainDocumentPart.AddNewPart <WordprocessingCommentsPart>(); commentPart.Comments = new Comments(); comments = commentPart.Comments; } // Compose a new Comment and add it to the Comments part. Paragraph p = new Paragraph(new Run(new Text($"{comment} ID: {id}"), new RunProperties() { FontSize = new FontSize() { Val = fontSize }, RunFonts = new RunFonts() { Ascii = fontName } })); Comment cmt = new Comment() { Id = id.ToString(), Author = author.Name, Initials = author.Initials, Date = DateTime.Now }; cmt.AppendChild(p); comments.AppendChild(cmt); comments.Save(); // Specify the text range for the Comment. // Insert the new CommentRangeStart before the first run of paragraph. element.InsertBeforeSelf(new CommentRangeStart() { Id = id.ToString() }); var commentEnd = new CommentRangeEnd() { Id = id.ToString() }; // Insert the new CommentRangeEnd after last run of paragraph. var cmtEnd = element.InsertAfterSelf(commentEnd); // Compose a run with CommentReference and insert it. commentEnd.InsertAfterSelf(new Run(new CommentReference() { Id = id.ToString() })); }