Issue
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 XWPFRun
are 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.
Solution
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
}
}
Answered By - Axel Richter
Answer Checked By - Clifford M. (JavaFixing Volunteer)