【问题标题】:OpenXML insert comment reply into word document C#OpenXML将评论回复插入Word文档C#
【发布时间】:2018-11-20 02:53:00
【问题描述】:

我正在尝试使用 OpenXml 插入评论作为回复。如果不可能,我想在所选评论之后插入评论。到目前为止,我可以在我想要的位置插入评论,但是当我打开文档时我无法显示评论。

下面是插入注释的代码。

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

我可以看到使用VS中的调试器将注释放入文档中,但是当我打开文档时它没有显示出来。

执行保存命令后,注释被添加到文档中,但不显示。

这里的总体目标是在文档中包含的 cmets 列表中的特定注释之后插入注释。有人可以帮我找到解决办法吗?

【问题讨论】:

  • 我建议你创建一个简单的文档,带有一个注释,保存它。现在添加另一个评论(或回复)并将其保存在不同的名称下。在 Open XML Productivity Tool 中打开其中的第一个,然后使用其“比较”功能将其与第二个文档进行比较。该工具将 1) 向您展示底层 XML 的差异和 2) 将第一个文档更改为第二个文档所需的代码。 IOW 它应该向您展示如何添加回复(或其他评论)。

标签: c# ms-word openxml openxml-sdk


【解决方案1】:

我发现创建回复cmets需要以下内容

  • CommentsEx 部分已添加到文档中
  • 回复评论段落链接到其父项
  • CommentRange 和 CommentReference 以正确的顺序添加
  • 回复 cmets 仍需添加到 cmets 部分

下面的示例代码会将 cmets 添加到文档中的现有单词

 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();

       }
    }
}

【讨论】:

    【解决方案2】:

    按照 Meister 的建议后,我能够解决我的问题。标记为回复的 cmets 位于 cmetsExtended.xml 文件中。要创建与评论的关系,您需要创建一个 CommentEX 对象并将您插入的评论回复链接到您正在回复的评论。实现评论回复的代码位于下方。 ParaIdParent 属性是您正在回复的评论的 paraId。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-22
      • 1970-01-01
      • 2014-04-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多