Привет, я хотел бы вставить XWPFTable между некоторым содержимым. Содержимое файла фиксировано, и файл принимается как входной. Мне нужно, чтобы таблица была вставлена в определенное поле.

Типа того:

Stack Overflow - это частный веб-сайт, флагманский сайт сети Stack Exchange Network, созданный в 2008 году Джеффом Этвудом и Джоэлом Спольски. Вот таблица.

table image

Содержание продолжается. Он был создан как более открытая альтернатива прежним сайтам вопросов и ответов, таким как 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  

Я получаю исключение нулевого указателя при создании строки.

0
Joel George 13 Мар 2018 в 14:27

2 ответа

Лучший ответ

Протестировали сейчас. Мое подозрение было правильным. Курсор оказался не в том месте в вашем коде после XWPFParagraph p = document.insertNewParagraph(cursor);. Таким образом, XWPFTable table = p.getBody().insertNewTbl(cursor); не может быть вставлен, и тогда он был null.

Но есть и другие проблемы. Если текст был найден, мы попадаем в абзац после , после которого должна быть размещена таблица. Итак, нам нужно переместить курсор к следующему абзацу. Но что, если следующего абзаца нет? Затем нужно создать новый абзац. К счастью, XmlCursor.toNextSibling отмечает, что операция прошла успешно.

Примере:

Шаблон:

enter image description here

Код:

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

Результат:

enter image description here

2
Axel Richter 7 Апр 2020 в 17:24

Я не уверен, что какой-либо из методов 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() не относится к содержанию абзаца. Скорее, это относится к родительской части абзаца.

0
jmarkmurphy 13 Мар 2018 в 15:08