Чтобы воспроизвести проблему, нужно иметь source.docx
с первой таблицей, имеющей как минимум две строки.
Затем выполните следующий код:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRow;
public class WordInsertTableRow {
static XWPFTableRow insertNewTableRow(XWPFTableRow sourceTableRow, int pos) throws Exception {
XWPFTable table = sourceTableRow.getTable();
CTRow newCTRrow = CTRow.Factory.parse(sourceTableRow.getCtRow().newInputStream());
XWPFTableRow tableRow = new XWPFTableRow(newCTRrow, table);
table.addRow(tableRow, pos);
return tableRow;
}
static void commitTableRows(XWPFTable table) {
int rowNr = 0;
for (XWPFTableRow tableRow : table.getRows()) {
table.getCTTbl().setTrArray(rowNr++, tableRow.getCtRow());
}
}
public static void main(String[] args) throws Exception {
XWPFDocument doc = new XWPFDocument(new FileInputStream("source.docx"));
boolean weMustCommitTableRows = false;
XWPFTable table = doc.getTableArray(0);
// insert new row, which is a copy of row 2, as new row 3:
XWPFTableRow sourceTableRow = table.getRow(1);
XWPFTableRow newRow3 = insertNewTableRow(sourceTableRow, 2);
// now changing something in that new row:
int i = 1;
for (XWPFTableCell cell : newRow3.getTableCells()) {
for (XWPFParagraph paragraph : cell.getParagraphs()) {
for (XWPFRun run : paragraph.getRuns()) {
run.setText("New row 3 run " + i++, 0);
}
}
}
System.out.println(newRow3.getCtRow()); // was changed
System.out.println(table.getRow(2).getCtRow()); // even this is changed
System.out.println(table.getCTTbl().getTrArray(2)); // but this was not changed, why not?
weMustCommitTableRows = true;
if (weMustCommitTableRows) commitTableRows(table); // now it is changed
FileOutputStream out = new FileOutputStream("result.docx");
doc.write(out);
out.close();
doc.close();
}
}
Этот код создает копию второй строки и вставляет ее как третью строку в таблицу. Затем он что-то меняет в новом третьем ряду.
Проблема заключается в том, что изменения появляются на низком уровне CTRow
самой строки, но не появляются на низком уровне CTTbl
таблицы. Для меня это не логично, и я не могу понять причину этого. Похоже, что новые элементы CTRow
вообще не являются частью CTTbl
. Но они были добавлены к нему с помощью ctTbl.setTrArray
в XWPFTable.addRow . Поэтому я подозреваю, что с setTrArray
в org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl
что-то не так. Кажется, корректно обновляется XML
, но теряются объектные отношения в массиве (или списке) CTRow
s в CTTbl
. Но это очень трудно определить из-за вида программирования классов org.openxmlformats.schemas
. По крайней мере, я не смог этого сделать. Может быть, кто-то из профессиональных и энтузиастов-программистов здесь сможет?
Я использую тот же подход для вставки строк, имеющих тот же стиль, что и заданная исходная строка. Но после того, как я это сделал, я устанавливаю boolean weMustCommitTableRows = true;
, а затем я делаю if (weMustCommitTableRows) commitTableRows(table);
перед тем, как выписать документ. Тогда все изменения будут совершены.