I am using Apache POI to process .docx file.
I have .docx with 1 row, 1 column table.
XWPFTable table = document.getTables().get(0);
XWPFTableRow copiedRow = table.getRow(0);
table.addRow(copiedRow);
The above code successfully copies the row, so the table would now have 2 rows.
However, I also want to mutate the copied row.
XWPFTable table = document.getTables().get(0);
XWPFTableRow copiedRow = table.getRow(0);
copiedRow.getTableCells().get(0).setText("SOME MODIFICATION HERE"); // <- setting some data
table.addRow(copiedRow);
The problem is that... the modification affected both rows. Both the original first one, and the second just-to-be-added are affected.
I also tried to explicitly construct new row, like so:
copiedRow.getTableCells().get(0).setText("SOME MODIFICATION");
XWPFTableRow newRow = new XWPFTableRow(copiedRow.getCtRow(), table);
table.addRow(newRow);
...yet the result is still the same: both rows are modified rather than just the second one.
I've tried to make the example as minimal as possible. Thanks for any help!
You're still referencing the same underlying data.
CTRow
does have a copy
method. So use that to create a new XWPFTableRow
:
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRow;
import java.io.*;
import java.nio.file.*;
public class Main {
public static void main(String[] args) throws IOException {
Path documentRoot = Paths.get(System.getProperty("user.home"), "Documents");
try (InputStream inputStream = Files.newInputStream(documentRoot.resolve("Input.docx"))) {
XWPFDocument document = new XWPFDocument(inputStream);
XWPFTable table = document.getTables().get(0);
XWPFTableRow row = table.getRow(0);
XWPFTableRow copiedRow = new XWPFTableRow((CTRow) row.getCtRow().copy(), table);
copiedRow.getTableCells().get(0).setText("SOME MODIFICATION HERE");
table.addRow(copiedRow);
try (OutputStream outputStream = Files.newOutputStream(documentRoot.resolve("Output.docx"))) {
document.write(outputStream);
}
}
}
}