将行添加到 table 后,无法更改 .docx 文件中的行文本
Can't change row text in .docx file once row is added to table
我遇到以下代码的问题:
XWPFTable table = <get table somehow>;
CTRow firstRow = table.getRow(0).getCtRow();
for (int i = 0; i < data.getRowCount(); i++) {
CTRow ctRow = (CTRow) firstRow.copy();
XWPFTableRow row = new XWPFTableRow(ctRow, table);
XWPFRun[] cellRuns = row.getTableCells()
.stream()
.map(c -> c.getParagraphs().get(0))
.map(p -> p.getRuns().isEmpty() ? p.createRun() : p.getRuns().get(0))
.toArray(XWPFRun[]::new);
for (int j = 0; j < cellRuns.length; j++) {
cellRuns[j].setText(data.getValueAt(i, j).toString(), 0);
}
table.addRow(row);
}
table.getRow(1).getTableCells()
.get(0).getParagraphs()
.get(0).getRuns()
.get(0).setText("FooBar", 0); //change text in some added row
此代码多次复制 table 的第一行,然后从 data
复制值。工作得很好(文本样式除外),除了最后一个运算符,它应该更改某些添加的 table 行中的文本。此外,"FooBar" 字符串甚至没有出现在创建的 WORD 文档的 document.xml 中。我没有从调试中看到任何线索,因为 table.addRow(row);
运算符似乎只是将 row
指针复制到它的内部行列表。此外,我在更改现有行方面没有问题。那么您知道为什么会发生这种情况吗?
要重现问题,请让 source.docx
的第一个 table 至少有两行。
然后执行 运行 以下代码:
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();
}
}
此代码创建第二行的副本并将其作为第三行插入 table。然后它确实改变了新的第三行中的某些内容。
问题是,更改确实出现在行本身的低级别 CTRow
中,但没有出现在 table 的低级别 CTTbl
中。对我来说,这不符合逻辑,我无法理解其中的原因。看起来新的 CTRow
元素根本不是 CTTbl
的一部分。但是它们是使用 XWPFTable.addRow 中的 ctTbl.setTrArray
添加到其中的。所以我怀疑org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl
中的setTrArray
有问题。似乎正确地更新了 XML
,但丢失了 CTTbl
中 CTRow
的数组(或列表)中的对象关系。但这很难确定,因为 org.openxmlformats.schemas
类 的编程类型。至少我做不到。也许这里的另一位专业和狂热的程序员可以?
我使用相同的方法插入与给定源行具有相同样式的行。但是在完成此操作后,我将设置 boolean weMustCommitTableRows = true;
,然后在写出文档之前设置 if (weMustCommitTableRows) commitTableRows(table);
。然后将提交所有更改。
我遇到以下代码的问题:
XWPFTable table = <get table somehow>;
CTRow firstRow = table.getRow(0).getCtRow();
for (int i = 0; i < data.getRowCount(); i++) {
CTRow ctRow = (CTRow) firstRow.copy();
XWPFTableRow row = new XWPFTableRow(ctRow, table);
XWPFRun[] cellRuns = row.getTableCells()
.stream()
.map(c -> c.getParagraphs().get(0))
.map(p -> p.getRuns().isEmpty() ? p.createRun() : p.getRuns().get(0))
.toArray(XWPFRun[]::new);
for (int j = 0; j < cellRuns.length; j++) {
cellRuns[j].setText(data.getValueAt(i, j).toString(), 0);
}
table.addRow(row);
}
table.getRow(1).getTableCells()
.get(0).getParagraphs()
.get(0).getRuns()
.get(0).setText("FooBar", 0); //change text in some added row
此代码多次复制 table 的第一行,然后从 data
复制值。工作得很好(文本样式除外),除了最后一个运算符,它应该更改某些添加的 table 行中的文本。此外,"FooBar" 字符串甚至没有出现在创建的 WORD 文档的 document.xml 中。我没有从调试中看到任何线索,因为 table.addRow(row);
运算符似乎只是将 row
指针复制到它的内部行列表。此外,我在更改现有行方面没有问题。那么您知道为什么会发生这种情况吗?
要重现问题,请让 source.docx
的第一个 table 至少有两行。
然后执行 运行 以下代码:
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();
}
}
此代码创建第二行的副本并将其作为第三行插入 table。然后它确实改变了新的第三行中的某些内容。
问题是,更改确实出现在行本身的低级别 CTRow
中,但没有出现在 table 的低级别 CTTbl
中。对我来说,这不符合逻辑,我无法理解其中的原因。看起来新的 CTRow
元素根本不是 CTTbl
的一部分。但是它们是使用 XWPFTable.addRow 中的 ctTbl.setTrArray
添加到其中的。所以我怀疑org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl
中的setTrArray
有问题。似乎正确地更新了 XML
,但丢失了 CTTbl
中 CTRow
的数组(或列表)中的对象关系。但这很难确定,因为 org.openxmlformats.schemas
类 的编程类型。至少我做不到。也许这里的另一位专业和狂热的程序员可以?
我使用相同的方法插入与给定源行具有相同样式的行。但是在完成此操作后,我将设置 boolean weMustCommitTableRows = true;
,然后在写出文档之前设置 if (weMustCommitTableRows) commitTableRows(table);
。然后将提交所有更改。