Search code examples
javaapache-poixwpf

Inserting XWPFTable in between contents


HI I would like to insert a XWPFTable in between some contents. The file is content is fixed and file is taken as input. I need the table to be inserted in the specific field.

like this:

Stack Overflow is a privately held website, the flagship site of the Stack Exchange Network, created in 2008 by Jeff Atwood and Joel Spolsky. Here is the table.

table image

The contents continue.It was created to be a more open alternative to earlier question and answer sites such as Experts-Exchange.

Thanks

The code i have written

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  

I am getting null pointer exception on creating the row.


Solution

  • Have tested now. My suspicion was right. The cursor was on the wrong place in your code after XWPFParagraph p = document.insertNewParagraph(cursor);. So the XWPFTable table = p.getBody().insertNewTbl(cursor); could not be inserted and was null then.

    But there are further problems. If the text was found, we are in the paragraph after which the table shall be placed. So we need moving the cursor to the next paragraph. But what if there is not a next paragraph? Then a new paragraph needs to be created. Fortunately the XmlCursor.toNextSibling flags if it was successful.

    Example:

    Template:

    enter image description here

    Code:

    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);
        if (cell.getParagraphs().size() > 0 ) paragraph = cell.getParagraphs().get(0); else paragraph = cell.addParagraph();
        run = paragraph.createRun();
        run.setText("Table Cell " + i);
       }
      }
    
      FileOutputStream out = new FileOutputStream("WordTableExampleNew.docx");
      document.write(out);
      out.close();
      document.close();
     }
    }
    

    Result:

    enter image description here