Search code examples
javaapache-poidocxxwpf

Copying and mutating row in a .docx table


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!


Solution

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