Привет, я хотел бы вставить XWPFTable между некоторым содержимым. Содержимое файла фиксировано, и файл принимается как входной. Мне нужно, чтобы таблица была вставлена в определенное поле.
Типа того:
Stack Overflow - это частный веб-сайт, флагманский сайт сети Stack Exchange Network, созданный в 2008 году Джеффом Этвудом и Джоэлом Спольски. Вот таблица.
Содержание продолжается. Он был создан как более открытая альтернатива прежним сайтам вопросов и ответов, таким как Experts-Exchange.
Благодарность
Код, который я написал
public static void main(String[] args) throws IOException {
XWPFDocument document = new XWPFDocument(new FileInputStream(new File("input.docx")));
FileOutputStream out = new FileOutputStream(new File("output.docx"));
XmlCursor cursor = null;
List<IBodyElement> elements = document.getBodyElements();
for (int n = 0; n < elements.size(); n++) {
IBodyElement element = elements.get(n);
if (element instanceof XWPFParagraph) {
XWPFParagraph p1 = (XWPFParagraph) element;
List<XWPFRun> runList = p1.getRuns();
StringBuilder sb = new StringBuilder();
for (XWPFRun run : runList)
sb.append(run.getText(0));
if (sb.toString().contains("Text after which table should be created")) {
cursor= p1.getCTP().newCursor();
break;
}
}
}
XWPFParagraph p = document.insertNewParagraph(cursor);
XWPFTable table = p.getBody().insertNewTbl(cursor);
XWPFTableRow tableRowOne = table.createRow();
//other codes for generating the table
Я получаю исключение нулевого указателя при создании строки.
2 ответа
Протестировали сейчас. Мое подозрение было правильным. Курсор оказался не в том месте в вашем коде после XWPFParagraph p = document.insertNewParagraph(cursor);
. Таким образом, XWPFTable table = p.getBody().insertNewTbl(cursor);
не может быть вставлен, и тогда он был null
.
Но есть и другие проблемы. Если текст был найден, мы попадаем в абзац после , после которого должна быть размещена таблица. Итак, нам нужно переместить курсор к следующему абзацу. Но что, если следующего абзаца нет? Затем нужно создать новый абзац. К счастью, XmlCursor.toNextSibling отмечает, что операция прошла успешно.
Примере:
Шаблон:
Код:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblWidth;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTblWidth;
import org.apache.xmlbeans.XmlCursor;
import java.math.BigInteger;
public class WordInsertTableInBody {
public static void main(String[] args) throws Exception {
XWPFDocument document = new XWPFDocument(new FileInputStream("WordTableExample.docx"));
XmlCursor cursor = null;
XWPFParagraph paragraph = null;
XWPFRun run = null;
boolean foundTablePosition = false;
boolean thereWasParagraphAfter = false;
for (IBodyElement element : document.getBodyElements()) {
if (element instanceof XWPFParagraph) {
paragraph = (XWPFParagraph) element;
StringBuilder sb = new StringBuilder();
for (XWPFRun irun : paragraph.getRuns()) {
sb.append(irun.getText(0));
System.out.println(sb);
if (sb.toString().contains("Text after which table should be created")) {
cursor= paragraph.getCTP().newCursor();
thereWasParagraphAfter = cursor.toNextSibling(); // move cursor to next paragraph
//because the table shall be **after** that paragraph
//thereWasParagraphAfter is true if there is a next paragraph, else false
foundTablePosition = true;
}
}
}
if (foundTablePosition) break;
}
if (cursor != null) {
if (thereWasParagraphAfter) {
paragraph = document.insertNewParagraph(cursor);
} else {
paragraph = document.createParagraph();
}
cursor = paragraph.getCTP().newCursor();
XWPFTable table = document.insertNewTbl(cursor);
XWPFTableRow row = table.getRow(0); if (row == null) row = table.createRow();
int twipsPerInch = 1440;
table.getCTTbl().addNewTblGrid().addNewGridCol().setW(BigInteger.valueOf(1*1440));
for (int col = 1 ; col < 4; col++) {
table.getCTTbl().getTblGrid().addNewGridCol().setW(BigInteger.valueOf(1*1440));
}
for (int i = 0; i < 4; i++) {
XWPFTableCell cell = row.getCell(i); if (cell == null) cell = row.createCell();
CTTblWidth tblWidth = cell.getCTTc().addNewTcPr().addNewTcW();
tblWidth.setW(BigInteger.valueOf(1 * twipsPerInch));
tblWidth.setType(STTblWidth.DXA);
paragraph = cell.getParagraphs().get(0);
run = paragraph.createRun();
run.setText("Table Cell " + i);
}
}
FileOutputStream out = new FileOutputStream("WordTableExampleNew.docx");
document.write(out);
out.close();
document.close();
}
}
Результат:
Я не уверен, что какой-либо из методов XWPFDocument.insertTable()
работает правильно. Я заметил одну вещь: у вас есть:
XWPFParagraph p = document.insertNewParagraph(cursor);
XWPFTable table = p.getBody().insertNewTbl(cursor);
Что эквивалентно:
XWPFParagraph p = document.insertNewParagraph(cursor);
XWPFTable table = document.insertNewTbl(cursor);
Это заставляет меня задуматься, есть ли у вас некоторая путаница относительно того, где таблица помещается внутри документа. Абзацы и таблицы являются родными братьями. Абзацы не содержат таблиц, хотя таблицы могут содержать абзацы (и другие таблицы) в ячейках таблицы.
Тело абзаца - это фактически часть, содержащая абзац. Это может быть часть документа, или часть верхнего / нижнего колонтитула, или часть комментария и т. Д. Но XWPFParagraph.getBody()
не относится к содержанию абзаца. Скорее, это относится к родительской части абзаца.
Похожие вопросы
Новые вопросы
java
Java - это язык программирования высокого уровня. Используйте этот тег, если у вас возникли проблемы с использованием или пониманием самого языка. Этот тег редко используется отдельно и чаще всего используется вместе с [spring], [spring-boot], [jakarta-ee], [android], [javafx], [hadoop], [gradle] и [maven].