如何使用 Apache POI 操作评论内容 [英] How to manipulate content of a comment with Apache POI

查看:35
本文介绍了如何使用 Apache POI 操作评论内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在 Docx 文档中找到评论(不知何故,按作者或 ID...),然后创建新内容.在此答案的帮助下,我能够创建评论,但在操纵方面没有运气.

解决方案

正如我在您的问题中链接的答案中所说,到目前为止,XWPFdocument 在创建时只会读取该包部分.既没有写访问权限,也没有创建该包部分的可能性.这在 XWPFDocument.java - protected void onDocumentRead(): code line 210: "//TODO根据XWPFComment类创建,扩展POIXMLDocumentPart".

所以我们需要自己做这件事,直到现在.我们需要为注释提供扩展 POIXMLDocumentPart 的类,并注册这个关系,而不是仅仅与简单的 POIXMLDocumentPart 的关系.这样就可以进行在编写 XWPFDocument 时提交的更改.

示例:

import java.io.*;导入 org.apache.poi.*;导入 org.apache.poi.openxml4j.opc.*;导入 org.apache.xmlbeans.*;导入 org.apache.poi.xwpf.usermodel.*;导入静态 org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;导入 org.openxmlformats.schemas.wordprocessingml.x2006.main.*;导入 javax.xml.namespace.QName;导入 java.math.BigInteger;导入 java.util.GregorianCalendar;导入 java.util.Locale;公共类 WordChangeComments {public static void main(String[] args) 抛出异常 {XWPFDocument 文档 = new XWPFDocument(new FileInputStream("WordDocumentHavingComments.docx"));for (POIXMLDocumentPart.RelationPart rpart : document.getRelationParts()) {字符串关系 = rpart.getRelationship().getRelationshipType();如果(relation.equals(XWPFRelation.COMMENT.getRelation())){POIXMLDocumentPart 部分 = rpart.getDocumentPart();//这只是POIXMLDocumentPart,不是扩展POIXMLDocumentPart的高级类//为注释提供扩展POIXMLDocumentPart的类MyXWPFCommentsDocument myXWPFCommentsDocument = new MyXWPFCommentsDocument(part.getPackagePart());//并注册此关系而不是仅与POIXMLDocumentPart的关系String rId = document.getRelationId(part);document.addRelation(rId, XWPFRelation.COMMENT, myXWPFCommentsDocument);//现在可以从新的 MyXWPFCommentsDocument 获得评论for (CTComment ctComment : myXWPFCommentsDocument.getComments().getCommentArray()) {System.out.print("评论:Id:" + ctComment.getId());System.out.print(", 作者:" + ctComment.getAuthor());System.out.print(", 日期:" + ctComment.getDate());System.out.print(", 文本:");for (CTP ctp : ctComment.getPArray()) {System.out.print(ctp.newCursor().getTextValue());}System.out.println();//并且可以进行更改,这些更改是在编写 XWPFDocument 时提交的if (BigInteger.ONE.equals(ctComment.getId())) {//第二条评论(Id 0 = first)ctComment.setAuthor("新作者");ctComment.setInitials("NA");ctComment.setDate(new GregorianCalendar(Locale.US));CTP newCTP = CTP.Factory.newInstance();newCTP.addNewR().addNewT().setStringValue("ID 为 1 的新的评论文本.");ctComment.setPArray(new CTP[]{newCTP });}}}}document.write(new FileOutputStream("WordDocumentHavingComments.docx"));文档.close();}//*.docx ZIP 存档中 CommentsDocument/word/comments.xml 的包装类私有静态类 MyXWPFCommentsDocument 扩展 POIXMLDocumentPart {私人 CTComments 评论;私有 MyXWPFCommentsDocument(PackagePart part) 抛出异常 {超级(部分);评论 = CommentsDocument.Factory.parse(part.getInputStream(), DEFAULT_XML_OPTIONS).getComments();}私人 CTComments getComments() {回复评论;}@覆盖protected void commit() 抛出 IOException {System.out.println("============MyXWPFCommentsDocument 已提交================);XmlOptions xmlOptions = 新 XmlOptions(DEFAULT_XML_OPTIONS);xmlOptions.setSaveSyntheticDocumentElement(new QName(CTComments.type.getName().getNamespaceURI(), "comments"));PackagePart 部分 = getPackagePart();OutputStream out = part.getOutputStream();评论.save(out, xmlOptions);关闭();}}}

<小时>

这适用于 apache poi 3.17.从 apache poi 4.0.0 开始,ooxml 部分是分开的.所以一定有:

<预><代码>...导入 org.apache.poi.ooxml.*;...导入静态 org.apache.poi.ooxml.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;...

I would like to find a comment in Docx document (somehow, by author or ID...), then create new content. I was able to create a comment, with the help of this answer, but had no luck with manipulation.

解决方案

As said in my answer linked in your question, until now the XWPFdocument will only read that package part while creating. There is neither write access nor a possibility to create that package part. This is mentioned in XWPFDocument.java - protected void onDocumentRead(): code line 210: "// TODO Create according XWPFComment class, extending POIXMLDocumentPart".

So we need doing this ourself until now. We need providing class extending POIXMLDocumentPart for comments and registering this relation instead of only relation to the simple POIXMLDocumentPart. So that and changings can be made which were committed while writing the XWPFDocument.

Example:

import java.io.*;

import org.apache.poi.*;
import org.apache.poi.openxml4j.opc.*;
import org.apache.xmlbeans.*;

import org.apache.poi.xwpf.usermodel.*;

import static org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;

import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;

import javax.xml.namespace.QName;

import java.math.BigInteger;
import java.util.GregorianCalendar;
import java.util.Locale;

public class WordChangeComments {

 public static void main(String[] args) throws Exception {

  XWPFDocument document = new XWPFDocument(new FileInputStream("WordDocumentHavingComments.docx"));

  for (POIXMLDocumentPart.RelationPart rpart : document.getRelationParts()) {
   String relation = rpart.getRelationship().getRelationshipType();
   if (relation.equals(XWPFRelation.COMMENT.getRelation())) {
    POIXMLDocumentPart part = rpart.getDocumentPart(); //this is only POIXMLDocumentPart, not a high level class extending POIXMLDocumentPart
    //provide class extending POIXMLDocumentPart for comments 
    MyXWPFCommentsDocument myXWPFCommentsDocument = new MyXWPFCommentsDocument(part.getPackagePart());
    //and registering this relation instead of only relation to POIXMLDocumentPart
    String rId = document.getRelationId(part);
    document.addRelation(rId, XWPFRelation.COMMENT, myXWPFCommentsDocument);

    //now the comments are available from the new MyXWPFCommentsDocument 
    for (CTComment ctComment : myXWPFCommentsDocument.getComments().getCommentArray()) {

     System.out.print("Comment: Id: " + ctComment.getId());
     System.out.print(", Author: " + ctComment.getAuthor());
     System.out.print(", Date: " + ctComment.getDate());
     System.out.print(", Text: ");
     for (CTP ctp : ctComment.getPArray()) {
      System.out.print(ctp.newCursor().getTextValue());
     }
     System.out.println();

     //and changings can be made which were committed while writing the XWPFDocument
     if (BigInteger.ONE.equals(ctComment.getId())) { //the second comment (Id 0 = first)
      ctComment.setAuthor("New Author");
      ctComment.setInitials("NA");
      ctComment.setDate(new GregorianCalendar(Locale.US));
      CTP newCTP = CTP.Factory.newInstance();
      newCTP.addNewR().addNewT().setStringValue("The new Text for Comment with Id 1.");
      ctComment.setPArray(new CTP[]{newCTP });
     }
    }
   }
  }

  document.write(new FileOutputStream("WordDocumentHavingComments.docx"));

  document.close();
 }

//a wrapper class for the CommentsDocument /word/comments.xml in the *.docx ZIP archive
 private static class MyXWPFCommentsDocument extends POIXMLDocumentPart {

  private CTComments comments;

  private MyXWPFCommentsDocument(PackagePart part) throws Exception {
   super(part);
   comments = CommentsDocument.Factory.parse(part.getInputStream(), DEFAULT_XML_OPTIONS).getComments();
  }

  private CTComments getComments() {
   return comments;
  }

  @Override
  protected void commit() throws IOException {

System.out.println("============MyXWPFCommentsDocument is committed=================");

   XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS);
   xmlOptions.setSaveSyntheticDocumentElement(new QName(CTComments.type.getName().getNamespaceURI(), "comments"));
   PackagePart part = getPackagePart();
   OutputStream out = part.getOutputStream();
   comments.save(out, xmlOptions);
   out.close();
  }

 }

}


This works for apache poi 3.17. Since apache poi 4.0.0 the ooxml part is separated. So there must be:

...
import org.apache.poi.ooxml.*;
...
import static org.apache.poi.ooxml.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;
...

这篇关于如何使用 Apache POI 操作评论内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆