how to add comment to a table of word by apache poi

gt y

I want to write a comment to a existing word document programmatically using apache poi. I have successfully added comments to the paragraph by the method mentioned here, but when adding comments to the table, I don't know how to associate it with real comments

BigInteger cId = BigInteger.ZERO;

 ctComment = comments.addNewComment();
 ctComment.setAuthor("Axel Ríchter");
 ctComment.setDate(new GregorianCalendar(Locale.US));
 ctComment.addNewP().addNewR().addNewT().setStringValue("The first comment.");

 paragraph = document.createParagraph();

 run = paragraph.createRun();
 run.setText("Paragraph with the first comment.");



in paragraph, we can use paragraph.getCTP().addNewR().addNewCommentReference().setId() to link a comment, but there seems no similar method in table. what should i do? I am a beginner to apache poi, any suggestions are greatly appreciated.

Axel Richter

The short answer to your question how to comment a whole table is: You get the first paragraph in first cell of that table to set the CommentRangeStart as the first element in that paragraph. Then you get the last paragraph in last cell of that table to set the CommentRangeEnd as the last element in that paragraph.

But if you wants changing a already present Word document, then much more needs to be taken into account. What if there are comment already? My example you are linking is for creating a new Word document from scratch. So there cannot be comments already before. I have provided also How to manipulate content of a comment with Apache POI. But this rely on already present comments. Now we have to use a combination of both. This needs to take into account already present comments as well as a not already present comments document which then needs to be new created.

Additional there is difficulty to to set the CommentRangeStart as the first element in a already present paragraph. There are no methods for this. So we need using very low level XML manipulating to achieve this.

The following example needs a WordDocument.docx having at least one table. This whole table gets commented then.


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

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

import static org.apache.poi.ooxml.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 WordCommentWholeTable {

 //a method to get or create the CommentsDocument /word/comments.xml in the *.docx ZIP archive  
 private static MyXWPFCommentsDocument createCommentsDocument(XWPFDocument document) throws Exception {
  MyXWPFCommentsDocument myXWPFCommentsDocument = null;

  //trying to get the CommentsDocument
  for (POIXMLDocumentPart.RelationPart rpart : document.getRelationParts()) {
   String relation = rpart.getRelationship().getRelationshipType();
   if (relation.equals(XWPFRelation.COMMENT.getRelation())) {
    POIXMLDocumentPart part = rpart.getDocumentPart();
    myXWPFCommentsDocument = new MyXWPFCommentsDocument(part.getPackagePart());
    String rId = document.getRelationId(part);
    document.addRelation(rId, XWPFRelation.COMMENT, myXWPFCommentsDocument);

  //create a new CommentsDocument if there is not one already
  if (myXWPFCommentsDocument == null) {
   OPCPackage oPCPackage = document.getPackage();
   PackagePartName partName = PackagingURIHelper.createPartName("/word/comments.xml");
   PackagePart part = oPCPackage.createPart(
   myXWPFCommentsDocument = new MyXWPFCommentsDocument(part);
   document.addRelation(null, XWPFRelation.COMMENT, myXWPFCommentsDocument);

  return myXWPFCommentsDocument;

 //a method to get the next comment Id from CTComments
 private static BigInteger getCommentId(CTComments comments) {
  BigInteger cId = BigInteger.ZERO;
  for (CTComment ctComment : comments.getCommentList()) {
   if (ctComment.getId().compareTo(cId) == 1) {
    cId = ctComment.getId();
  cId = cId.add(BigInteger.ONE);
  return cId;

 //method to set CommentRangeStart as first element in paragraph
 private static CTMarkupRange insertCommentRangeStartAsFirstElement(XWPFParagraph paragraph) {
  String uri = CTMarkupRange.type.getName().getNamespaceURI();
  String localPart = "commentRangeStart";
  XmlCursor cursor = paragraph.getCTP().newCursor();
  cursor.beginElement(localPart, uri);
  CTMarkupRange commentRangeStart = (CTMarkupRange)cursor.getObject();
  return commentRangeStart;  

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

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

  MyXWPFCommentsDocument myXWPFCommentsDocument = createCommentsDocument(document);
  CTComments comments = myXWPFCommentsDocument.getComments();

  CTComment ctComment;
  XWPFParagraph paragraph;
  XWPFRun run;

  //comment for the table
  BigInteger cId = getCommentId(comments);
  ctComment = comments.addNewComment();
  ctComment.setAuthor("Axel Ríchter");
  ctComment.setDate(new GregorianCalendar(Locale.US));
  ctComment.addNewP().addNewR().addNewT().setStringValue("This is a comment for whole table.");

  //get first paragraph in first table cell to set CommentRangeStart
  XWPFTable table = document.getTables().get(0);
  XWPFTableRow row = table.getRow(0);
  XWPFTableCell cell = row.getCell(0);
  paragraph = cell.getParagraphArray(0);
  CTMarkupRange commentRangeStart = insertCommentRangeStartAsFirstElement(paragraph);

  //get last paragraph in last table cell to set CommentRangeEnd and CommentReference
  row = table.getRows().get(table.getRows().size()-1);
  cell = row.getTableCells().get(row.getTableCells().size()-1);
  paragraph = cell.getParagraphs().get(cell.getParagraphs().size()-1);

  FileOutputStream out = new FileOutputStream("WordDocumentWithComments.docx");


 //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 {
   try {
    comments = CommentsDocument.Factory.parse(part.getInputStream(), DEFAULT_XML_OPTIONS).getComments();
   } catch (Exception ex) {
    // there was no comments yet
   if (comments == null) comments = CommentsDocument.Factory.newInstance().addNewComments();

  private CTComments getComments() {
   return comments;

  protected void commit() throws IOException {
   XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS);
   xmlOptions.setSaveSyntheticDocumentElement(new QName(CTComments.type.getName().getNamespaceURI(), "comments"));
   PackagePart part = getPackagePart();
   OutputStream out = part.getOutputStream();, xmlOptions);



Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at


Login to comment


How do I ADD bullet points to a word document using Apache POI in Java

Apache POI Word Table Cell not updating color (XWPFTableCell)

How to parse style separated paragraphs of MS Word in Aspose or Apache Poi?

Apache POI library : How to read Excel sheet embedded in Word document

How to add table heading drop-down with Apache Poi

How to partially bold a Paragraph in Apache POI? (Word Documents)

How to set table dimensions and spacing in word using apache poi in java

Java:using apache POI how to convert ms word file to pdf?

Using Apache Poi to parse table within a table in a word document

how to add images in HSSFCell in apache POI?

Hi, how can I restart numbering in java word apache poi?

How to add image with border into table cell in Word with Apache POI?

How to manipulate content of a comment with Apache POI

Apache POI word best way to add text after table

Apache Poi - Java-: How to add text containing blank lines as separate paragraphs to a Word document using Apache POI?

How to decrease default height of a table row in word using apache poi in java

apache poi add table in word document

How to set a font family to an entire Word document in Apache POI XWPF

How to add comment by apache poi

How to add a hyperlink to image in a Word document using Apache POI?

How to set the global font of word file via Apache poi?

Insert table into a word document at a specific position using apache poi

How to change table direction in Apache word poi (XWPF)?

How to insert a table into a cell in poi word?

Apache POI Word XWPF table direction and alignment

How to add superscript text using Apache POI

how to add images side by side word document using apache poi

Line Spacing Inside the Table in Word Using Apache POI

How to put a table inside header of word using java apache poi?

TOP Ranking

  1. 1

    What exactly is memory mapped io and port based io

  2. 2

    How i extract text from a model dialog in selenium?

  3. 3 port in URL

  4. 4

    Selenium browsing with headless isn't working?

  5. 5

    change TabView indicator SwiftUI

  6. 6

    python requests How to send data to a website

  7. 7

    Kubernetes pods not starting, running behind a proxy

  8. 8

    Scaffold-DbContext returns System.ArgumentNullException: Parameter name: proposedIdentifier in EFCore 2.0 when trying to pluralize

  9. 9

    Java POI: How to find an Excel cell with a string value and get its position (row) to use that position to find another cell

  10. 10

    Creating interaction sessions based on timestamps in pandas

  11. 11

    Maven annotation processing processor not found

  12. 12

    Missing field when deserializing using Jackson (Polymorphic)

  13. 13

    Spring Data JPA repository methods don't recognize property names with underscores

  14. 14

    Get all Woocommerce products from current product category term Id in a WP_Query

  15. 15

    How to update if key exists - sequelize

  16. 16

    I got message for error_log file "The stream or file ".../laravel.log" could not be opened: failed to open stream: Permission denied"

  17. 17

    Servlet: HTTP Status 404 - Not Found

  18. 18

    Type 'Moment' is not assignable to type 'Date'. Property 'toDateString' is missing in type 'Moment'

  19. 19

    what is key in CTTelephonyNetworkInfo().serviceSubscriberCellularProviders and CTTelephonyNetworkInfo().serviceCurrentRadioAccessTechnology

  20. 20

    Laravel(ajax) 404 not found

  21. 21

    Error: Cannot write a value to a ko.computed unless you specify a 'write' option. If you wish to read the current value, don't pass any parameters