在内容之间插入XWPFTable

时间:2018-03-13 11:27:43

标签: java apache-poi xwpf

HI我想在某些内容之间插入XWPFTable。文件内容是固定的,文件作为输入。我需要将表插入特定字段。

像这样:

Stack Overflow是一个私营网站,是Stack Exchange Network的旗舰网站,由Jeff Atwood和Joel Spolsky于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  

我在创建行时遇到空指针异常。

2 个答案:

答案 0 :(得分:1)

现已测试过。我的怀疑是对的。在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);
   }
  }

  document.write(new FileOutputStream("WordTableExampleNew.docx"));
  document.close();
 }
}

结果:

enter image description here

答案 1 :(得分:0)

我不确定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()不引用段落的内容。相反,它指的是段落的父部分。