Reputation: 571
I am trying to insert a comment as a reply using OpenXml. If it is not possible, I would like to insert a comment right after a selected comment. So far I am able to insert the comment in the place I want but I cannot get the comment to display when I open the document.
Below is the code to insert the comment.
using (WordprocessingDocument document = WordprocessingDocument.Open(path + fileName + ".docx", true)){
// Locate the first paragraph in the document.
//XMLParagraphAlias firstParagraph = document.MainDocumentPart.Document.Descendants<XMLParagraphAlias>().First();
XMLCommentsAlias comments = document.MainDocumentPart.WordprocessingCommentsPart.Comments;
string id = comments.Descendants<DocumentFormat.OpenXml.Wordprocessing.Comment>()
.Where(i => i.Id.Value == reply.CurrentCommentID.ToString())
.Select(e => e.Id.Value)
.First();
// Compose a new Comment and add it to the Comments part.
XMLParagraphAlias p = new XMLParagraphAlias(new Run(new Text(reply.ReplyText)));
string newCommentID = comments.Descendants<DocumentFormat.OpenXml.Wordprocessing.Comment>().Select(e => e.Id.Value).Max();
XMLCommentAlias cmt = new XMLCommentAlias()
{
Id = newCommentID,
Author = reply.CurrentUserName,
Date = DateTime.Now.Date
};
XMLCommentAlias comment = comments.Elements<XMLCommentAlias>()
.Where(n => n.Id.Value == reply.CurrentCommentID.ToString())
.First();
XMLParagraphAlias test2 = comment.Descendants<XMLParagraphAlias>().First();
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.
test2.InsertBefore(new CommentRangeStart() { Id = reply.CurrentCommentID.ToString() }, test2.GetFirstChild<Run>());
// Insert the new CommentRangeEnd after last run of paragraph.
var cmtEnd = test2.InsertAfter(new CommentRangeEnd() { Id = reply.CurrentCommentID.ToString() }, test2.Elements<Run>().Last());
// Compose a run with CommentReference and insert it.
test2.InsertAfter(new Run(new CommentReference() { Id = reply.CurrentCommentID.ToString() }), cmtEnd);
}
I can see that the comment is put into the document using the debugger in VS, but it is not being displayed when I open the document.
After the save command is executed the comment is added to the document, but it doesn't display.
The overall goal here is to insert the comment after a specific comment in the list of comments that are contained in the document. Can someone help me find a solution to this?
Upvotes: 4
Views: 2096
Reputation: 187
I found that the following are needed to create reply comments
The example code below will add comments to an existing word in a document
foreach (var paragraph in document.MainDocumentPart.Document.Descendants<Paragraph>())
{
foreach (var run in paragraph.Elements<Run>())
{
var item = run.Elements<Text>().FirstOrDefault(b => b.Text.Contains("DTT"));
if (item != null)
{
if (document.MainDocumentPart.GetPartsCountOfType<WordprocessingCommentsPart>() > 0)
{
comments = document.MainDocumentPart.WordprocessingCommentsPart.Comments;
commentsEx = document.MainDocumentPart.WordprocessingCommentsExPart.CommentsEx;
if (comments.HasChildren)
{
// Obtain an unused ID.
id = comments.Descendants<Comment>().Select(e => e.Id.Value).Max();
}
}
else
{
// No WordprocessingCommentsPart part exists, so add one to the package.
WordprocessingCommentsPart commentPart = document.MainDocumentPart.AddNewPart<WordprocessingCommentsPart>();
commentPart.Comments = new Comments();
comments = commentPart.Comments;
WordprocessingCommentsExPart commentsExPart = document.MainDocumentPart.AddNewPart<WordprocessingCommentsExPart>();
commentsExPart.CommentsEx = new CommentsEx();
commentsEx = commentsExPart.CommentsEx;
}
Comment comment1 = new Comment() { Initials = "GS", Author = "Tony, Stark", Date = System.Xml.XmlConvert.ToDateTime("2018-11-19T14:54:00Z", System.Xml.XmlDateTimeSerializationMode.RoundtripKind), Id = "1" };
Paragraph paragraph1 = new Paragraph() { ParagraphId = "68DAFED3", TextId = "77777777" };
paragraph1.Append(new Run(new Text("fsdfas")));
comment1.Append(paragraph1);
Comment comment2 = new Comment() { Initials = "GS", Author = "Tony, Stark", Date = System.Xml.XmlConvert.ToDateTime("2018-11-19T14:54:00Z", System.Xml.XmlDateTimeSerializationMode.RoundtripKind), Id = "2" };
Paragraph paragraph2 = new Paragraph() { ParagraphId = "346EE35B", TextId = "77777777" };
paragraph2.Append(new Run(new Text("sadfsad")));
comment2.Append(paragraph2);
comments.Append(comment1);
comments.Append(comment2);
comments.Save();
CommentRangeStart commentRangeStart1 = new CommentRangeStart() { Id = "1" };
CommentRangeStart commentRangeStart2 = new CommentRangeStart() { Id = "2" };
CommentRangeEnd commentRangeEnd1 = new CommentRangeEnd() { Id = "1" };
CommentReference commentReference1 = new CommentReference() { Id = "1" };
CommentRangeEnd commentRangeEnd2 = new CommentRangeEnd() { Id = "2" };
CommentReference commentReference2 = new CommentReference() { Id = "2" };
run.InsertBefore(commentRangeStart1, item);
run.InsertBefore(commentRangeStart2, item);
var cmtEnd = run.InsertAfter(commentRangeEnd1, item);
var cmtEnd2 = run.InsertAfter(commentRangeEnd2, cmtEnd);
run.InsertAfter(new Run(commentReference1), cmtEnd);
run.InsertAfter(new Run(commentReference2), cmtEnd2);
CommentEx commentEx1 = new CommentEx() { ParaId = "68DAFED3", Done = false };
CommentEx commentEx2 = new CommentEx() { ParaId = "346EE35B", ParaIdParent = "68DAFED3", Done = false };
commentsEx.Append(commentEx1);
commentsEx.Append(commentEx2);
commentsEx.Save();
}
}
}
Upvotes: 5
Reputation: 571
After following Meister's advice I was able to solve my problem. The comments that are marked as replies are located in the commentsExtended.xml file. To create a relationship with the comment you will need to create a CommentEX object and link the comment reply you are inserting to the comment you are replying to. The code to implement the comment reply is located below. The ParaIdParent property is the paraId of the comment you are replying to.
private void BuildCommentExtendXML(WordprocessingDocument document, string randomHexBinaryValue, HexBinaryValue commentsParagraphDescendantId)
{
var commentsEx = document.MainDocumentPart.WordprocessingCommentsExPart.CommentsEx;
CommentEx commentEx = new CommentEx()
{
ParaId = randomHexBinaryValue,
ParaIdParent = commentsParagraphDescendantId,
Done = new OnOffValue(false)
};
commentsEx.Append(commentEx);
}
Upvotes: 0