如何使用Apache POI操纵注释的内容

我想在Docx文档中找到一条评论(不知何故,通过作者或ID …),然后创建新内容。 在这个答案的帮助下,我能够创建一个评论 ,但没有操纵的运气。

正如我在你的问题中链接的回答中所述,到目前为止, XWPFdocument只会在创建时读取该包部分。 既没有写访问权,也没有创建该包部分的可能性。 这在XWPFDocument.java中提到- 受保护的void onDocumentRead() : 代码行210 :“// TODO根据XWPFComment类创建,扩展POIXMLDocumentPart”。

所以我们现在需要自己做这件事。 我们需要提供扩展POIXMLDocumentPart的类以用于注释并注册此关系,而不是仅关注简单的POIXMLDocumentPart。 因此,可以在编写XWPFDocument时进行更改。

例:

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