Java 使用ApachePOI从具有固定位置的模板复制表
我在docx模板中有一个表。 根据对象的数量,我必须复制表的次数与复制对象的次数相同。重复表必须位于模板中的表之后。 我在模板中有几个表的行为应该是这样的 XmlCursor取代模板中的第一个表,并将下一个表放在那里。我想在我自己添加的上一个表之后插入下一个表,但是xmlcursor不返回我添加的表项,而是返回“STARTDOC”Java 使用ApachePOI从具有固定位置的模板复制表,java,apache-poi,docx,xwpf,Java,Apache Poi,Docx,Xwpf,我在docx模板中有一个表。 根据对象的数量,我必须复制表的次数与复制对象的次数相同。重复表必须位于模板中的表之后。 我在模板中有几个表的行为应该是这样的 XmlCursor取代模板中的第一个表,并将下一个表放在那里。我想在我自己添加的上一个表之后插入下一个表,但是xmlcursor不返回我添加的表项,而是返回“STARTDOC” 不清楚使用cursor.toParent()的目的是什么。我也无法重现只有您的小代码片段的问题。但是有一个完整的工作示例可能会对您有所帮助 假设我们有以下模板: 然
不清楚使用
cursor.toParent()的目的是什么代码>。我也无法重现只有您的小代码片段的问题。但是有一个完整的工作示例可能会对您有所帮助
假设我们有以下模板:
然后是以下代码:
import java.io.FileOutputStream;
import java.io.FileInputStream;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlCursor;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl;
public class WordCopyTableAfterTable {
static XmlCursor setCursorToNextStartToken(XmlObject object) {
XmlCursor cursor = object.newCursor();
cursor.toEndToken(); //Now we are at end of the XmlObject.
//There always must be a next start token.
while(cursor.hasNextToken() && cursor.toNextToken() != org.apache.xmlbeans.XmlCursor.TokenType.START);
//Now we are at the next start token and can insert new things here.
return cursor;
}
static void removeCellValues(XWPFTableCell cell) {
for (XWPFParagraph paragraph : cell.getParagraphs()) {
for (int i = paragraph.getRuns().size()-1; i >= 0; i--) {
paragraph.removeRun(i);
}
}
}
public static void main(String[] args) throws Exception {
//The data. Each row a new table.
String[][] data= new String[][] {
new String[] {"John Doe", "5/23/2019", "1234.56"},
new String[] {"Jane Doe", "12/2/2019", "34.56"},
new String[] {"Marie Template", "9/20/2019", "4.56"},
new String[] {"Hans Template", "10/2/2019", "4567.89"}
};
String value;
XWPFDocument document = new XWPFDocument(new FileInputStream("WordTemplate.docx"));
XWPFTable tableTemplate;
CTTbl cTTblTemplate;
XWPFTable tableCopy;
XWPFTable table;
XWPFTableRow row;
XWPFTableCell cell;
XmlCursor cursor;
XWPFParagraph paragraph;
XWPFRun run;
//get first table (the template)
tableTemplate = document.getTableArray(0);
cTTblTemplate = tableTemplate.getCTTbl();
cursor = setCursorToNextStartToken(cTTblTemplate);
//fill in first data in first table (the template)
for (int c = 0; c < data[0].length; c++) {
value = data[0][c];
row = tableTemplate.getRow(1);
cell = row.getCell(c);
removeCellValues(cell);
cell.setText(value);
}
paragraph = document.insertNewParagraph(cursor); //insert new empty paragraph
cursor = setCursorToNextStartToken(paragraph.getCTP());
//fill in next data, each data row in one table
for (int t = 1; t < data.length; t++) {
table = document.insertNewTbl(cursor); //insert new empty table at position t
cursor = setCursorToNextStartToken(table.getCTTbl());
tableCopy = new XWPFTable((CTTbl)cTTblTemplate.copy(), document); //copy the template table
//fill in data in tableCopy
for (int c = 0; c < data[t].length; c++) {
value = data[t][c];
row = tableCopy.getRow(1);
cell = row.getCell(c);
removeCellValues(cell);
cell.setText(value);
}
document.setTable(t, tableCopy); //set tableCopy at position t instead of table
paragraph = document.insertNewParagraph(cursor); //insert new empty paragraph
cursor = setCursorToNextStartToken(paragraph.getCTP());
}
paragraph = document.insertNewParagraph(cursor);
run = paragraph.createRun();
run.setText("Inserted new text below last table.");
cursor = setCursorToNextStartToken(paragraph.getCTP());
FileOutputStream out = new FileOutputStream("WordResult.docx");
document.write(out);
out.close();
document.close();
}
}
import java.io.FileOutputStream;
导入java.io.FileInputStream;
导入org.apache.poi.xwpf.usermodel.*;
导入org.apache.xmlbeans.XmlObject;
导入org.apache.xmlbeans.XmlCursor;
导入org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl;
公共类WordCopyTableAfterTable{
静态XmlCursor setCursorToNextStartToken(XmlObject对象){
XmlCursor=object.newCursor();
cursor.toEndToken();//现在我们到了XmlObject的末尾。
//始终必须有下一个开始令牌。
while(cursor.hasNextToken()&&cursor.toNextToken()!=org.apache.xmlbeans.XmlCursor.TokenType.START);
//现在我们在下一个开始令牌,可以在这里插入新的东西。
返回光标;
}
静态空隙清除单元值(XWPFTableCell){
对于(XWPFParagraph段落:cell.getParagraph()){
对于(int i=段落.getRuns().size()-1;i>=0;i--){
第1(i)段;
}
}
}
公共静态void main(字符串[]args)引发异常{
//数据。每一行都是一个新表。
字符串[][]数据=新字符串[][]{
新字符串[]{“John Doe”、“5/23/2019”、“1234.56”},
新字符串[]{“Jane Doe”,“12/2/2019”,“34.56”},
新字符串[]{“玛丽模板”、“2019年9月20日”、“4.56”},
新字符串[]{“Hans模板”、“2019年2月10日”、“4567.89”}
};
字符串值;
XWPFDocument document=newxwpfdocument(newfileinputstream(“WordTemplate.docx”);
XWPFTable表格模板;
CTTbl cTTblTemplate;
XWPFTable表格副本;
XWPFTable表;
XWPFTableRow行;
XWPFTableCell细胞;
xml光标;
XWPFParagraph段;
XWPFRun;
//获取第一个表(模板)
tableTemplate=document.getTableArray(0);
cTTblTemplate=tableTemplate.getCTTbl();
cursor=setCursorToNextStartToken(cTTblTemplate);
//填写第一个表格中的第一个数据(模板)
对于(int c=0;c
结果如下:
这就是你想要达到的目标吗
请注意我是如何插入附加表的
使用table=document.insertNewTbl(光标)代码>在位置t
插入一个新的空表。此表被放置到文档体中。因此,必须使用此表来调整光标
然后tableCopy=newxwpftable((CTTbl)cTTblTemplate.copy(),document)代码>复制模板表。然后,此副本将填充数据。然后使用document.setTable(t,tableCopy)在t
位置将其设置到文档中代码>
不幸的是,apachepoi
在这里是不完整的XWPFDocument.setable
仅设置内部ArrayList
s,而不设置底层XML
XWPFDocument.insertNewTbl
设置基础XML
,但仅使用空表。因此,我们必须以一种丑陋而复杂的方式来做
import java.io.FileOutputStream;
import java.io.FileInputStream;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlCursor;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl;
public class WordCopyTableAfterTable {
static XmlCursor setCursorToNextStartToken(XmlObject object) {
XmlCursor cursor = object.newCursor();
cursor.toEndToken(); //Now we are at end of the XmlObject.
//There always must be a next start token.
while(cursor.hasNextToken() && cursor.toNextToken() != org.apache.xmlbeans.XmlCursor.TokenType.START);
//Now we are at the next start token and can insert new things here.
return cursor;
}
static void removeCellValues(XWPFTableCell cell) {
for (XWPFParagraph paragraph : cell.getParagraphs()) {
for (int i = paragraph.getRuns().size()-1; i >= 0; i--) {
paragraph.removeRun(i);
}
}
}
public static void main(String[] args) throws Exception {
//The data. Each row a new table.
String[][] data= new String[][] {
new String[] {"John Doe", "5/23/2019", "1234.56"},
new String[] {"Jane Doe", "12/2/2019", "34.56"},
new String[] {"Marie Template", "9/20/2019", "4.56"},
new String[] {"Hans Template", "10/2/2019", "4567.89"}
};
String value;
XWPFDocument document = new XWPFDocument(new FileInputStream("WordTemplate.docx"));
XWPFTable tableTemplate;
CTTbl cTTblTemplate;
XWPFTable tableCopy;
XWPFTable table;
XWPFTableRow row;
XWPFTableCell cell;
XmlCursor cursor;
XWPFParagraph paragraph;
XWPFRun run;
//get first table (the template)
tableTemplate = document.getTableArray(0);
cTTblTemplate = tableTemplate.getCTTbl();
cursor = setCursorToNextStartToken(cTTblTemplate);
//fill in first data in first table (the template)
for (int c = 0; c < data[0].length; c++) {
value = data[0][c];
row = tableTemplate.getRow(1);
cell = row.getCell(c);
removeCellValues(cell);
cell.setText(value);
}
paragraph = document.insertNewParagraph(cursor); //insert new empty paragraph
cursor = setCursorToNextStartToken(paragraph.getCTP());
//fill in next data, each data row in one table
for (int t = 1; t < data.length; t++) {
table = document.insertNewTbl(cursor); //insert new empty table at position t
cursor = setCursorToNextStartToken(table.getCTTbl());
tableCopy = new XWPFTable((CTTbl)cTTblTemplate.copy(), document); //copy the template table
//fill in data in tableCopy
for (int c = 0; c < data[t].length; c++) {
value = data[t][c];
row = tableCopy.getRow(1);
cell = row.getCell(c);
removeCellValues(cell);
cell.setText(value);
}
document.setTable(t, tableCopy); //set tableCopy at position t instead of table
paragraph = document.insertNewParagraph(cursor); //insert new empty paragraph
cursor = setCursorToNextStartToken(paragraph.getCTP());
}
paragraph = document.insertNewParagraph(cursor);
run = paragraph.createRun();
run.setText("Inserted new text below last table.");
cursor = setCursorToNextStartToken(paragraph.getCTP());
FileOutputStream out = new FileOutputStream("WordResult.docx");
document.write(out);
out.close();
document.close();
}
}