Home > Net >  Apache poi: insert text in a paragraph and view track changes in a word document
Apache poi: insert text in a paragraph and view track changes in a word document

Time:04-21

I´m using Apache poi library with java 11. I´m trying to see the track changes after to add a new text into a paragraph in a word document:

 private void setSectionRun(XWPFParagraph paragraph){
    // insert xml node
    paragraph.getCTP().addNewIns().setAuthor("Kane");

    XWPFRun newRun = paragraph.createRun();
    newRun.setText(". Hello world");
    paragraph.addRun(newRun);
}

And I get the following output in document.xml. In this case the track changes is not working:

<w:ins w:author="Kane"/>
<w:r>
    <w:t>. Hello world</w:t>
</w:r>

In any case, if I manually edit the document I can see the track changes and accept or reject the insertion with the following result:

<w:ins w:id="0" w:author="Kane" w:date="2022-04-20T15:33:00Z">
    <w:r w:rsidR="00B00A22">
        <w:t>. Hello world</w:t>
    </w:r>
</w:ins>

The problem is that I can't activate the track changes when I insert a new text in a paragraph with Apache poi.

On the other hand, with newRun.getCTR().getRPr().addNewRPrChange().setAuthor("Kane") the format changes of a XWPFRunare detected and I can see the change control correctly, but not the new text insertions at the paragraph level.

Is there a way to enable the track change on new text inserts?

Thanks in advance.

CodePudding user response:

Apache POI does not support tracking changes up to now.

As you see in your XML, your code places an empty w:ins element above the w:r element. But Microsoft Word wraps the w:r element with the w:ins element. The w:r element is a child element of the w:ins element.

One possibility to code that would be having a class XWPFInsRun which extends XWPFRun and a method to create such XWPFInsRun in a XWPFParagraph. Doing this one has all options of XWPFRun extended by the options of CTRunTrackChange - author and date for example.

Complete example:

import java.io.FileOutputStream;

import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;

public class CreateWordInsRun {
    
 static XWPFInsRun createInsRun(XWPFParagraph paragraph, String author, java.util.Calendar date) {
  CTRunTrackChange trackChange = paragraph.getCTP().addNewIns();
  trackChange.setAuthor(author);
  trackChange.setDate(date);
  trackChange.addNewR();
  return new XWPFInsRun(
    trackChange,
    trackChange.getRArray(0),
    paragraph
   );
 }

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

  XWPFDocument doc = new XWPFDocument();

  XWPFParagraph paragraph = doc.createParagraph();
  XWPFRun run = paragraph.createRun();
  run.setText("Paragraph 1");

  paragraph = doc.createParagraph();
  XWPFInsRun insRun = createInsRun(paragraph, "Kane", new java.util.GregorianCalendar());
  insRun.setText("Paragraph 2 inserted by Kane");
  System.out.println(insRun.getAuthor());
  System.out.println(insRun.getDate());
  
  paragraph = doc.createParagraph();
  run = paragraph.createRun();
  run.setText("Paragraph 3");
    
  FileOutputStream out = new FileOutputStream("./WordDocument.docx");
  doc.write(out);
  out.close();
  doc.close();    
 }
 
 static class XWPFInsRun extends XWPFRun {
  private CTRunTrackChange trackChange;
  public XWPFInsRun(CTRunTrackChange trackChange, CTR run, IRunBody p) {
   super(run, p);
   this.trackChange = trackChange;
  }
  public String getAuthor() {
   return this.trackChange.getAuthor();   
  }
  public void setAuthor(String author) {
   this.trackChange.setAuthor(author);   
  }
  public java.util.Calendar getDate() {
   return this.trackChange.getDate();   
  }
  public void setDate(java.util.Calendar date) {
   this.trackChange.setDate(date);   
  }
  //... further methods
 }
}
  • Related