Main problem with your code is that it creates the XWPFParagraph
s in the XWPFDocument
first and then it sets them into the XWPFTableCell
s. But a XWPFTableCell
contains it's own body and is able containing content of a whole document also. So after that the paragraph is in the documents body and in the table cells body. So don't do this. Instead get XWPFParagraph
s from or create XWPFParagraph
s in the XWPFTableCell
s if needed.
In general your requirement "an image on the left and some text on the right" can be fulfilled two ways. It can be fulfilled using a table, as you tried. But it can also be fulfilled using only one paragraph, as you told in your question's title. This paragraph must contain tab stop settings then and the runs must be split by tabulators.
The following code shows both solutions:
import java.io.FileOutputStream;
import java.io.FileInputStream;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.poi.util.Units;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTabStop;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTabJc;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblWidth;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTblWidth;
import java.math.BigInteger;
public class CreateWordTabulatorAndTable {
public static void main(String[] args) throws Exception {
String text = "Text";
String imgFile="Koala.png";
int twipsPerInch = 1440; //measurement unit for table cell width and tab stop pos is twips (twentieth of an inch point)
XWPFDocument document = new XWPFDocument();
XWPFParagraph paragraph = document.createParagraph();
XWPFRun run = paragraph.createRun();
run.setText("Image on the left and text on the right");
paragraph = document.createParagraph();
run = paragraph.createRun();
run.setText("First using a table:");
//create table
XWPFTable table = document.createTable();
table.setWidth(6*twipsPerInch);
//create CTTblGrid for this table with widths of the 2 columns.
//necessary for Libreoffice/Openoffice to accept the column widths.
//first column = 2 inches width
table.getCTTbl().addNewTblGrid().addNewGridCol().setW(BigInteger.valueOf(2*twipsPerInch));
//second column = 4 inches width
table.getCTTbl().getTblGrid().addNewGridCol().setW(BigInteger.valueOf(4*twipsPerInch));
//create first row
XWPFTableRow tableRow = table.getRow(0);
//first cell
XWPFTableCell cell = tableRow.getCell(0);
//set width for first column = 2 inches
CTTblWidth tblWidth = cell.getCTTc().addNewTcPr().addNewTcW();
tblWidth.setW(BigInteger.valueOf(2*twipsPerInch));
//STTblWidth.DXA is used to specify width in twentieths of a point.
tblWidth.setType(STTblWidth.DXA);
//first paragraph in first cell
paragraph = cell.getParagraphArray(0); if (paragraph == null) paragraph = cell.addParagraph();
//first run in paragraph having picture
run = paragraph.createRun();
run.addPicture(new FileInputStream(imgFile), XWPFDocument.PICTURE_TYPE_PNG, imgFile, Units.toEMU(100), Units.toEMU(100));
//second cell
cell = tableRow.addNewTableCell();
cell.setText(text);
paragraph = document.createParagraph();
//---------------------------------------------------------------------------------------------------
paragraph = document.createParagraph();
run = paragraph.createRun();
run.setText("Second using tabulator having tab stops:");
//create tab stop at 2 inches position
paragraph = document.createParagraph();
paragraph.setAlignment(ParagraphAlignment.LEFT);
CTTabStop tabStop = paragraph.getCTP().getPPr().addNewTabs().addNewTab();
tabStop = paragraph.getCTP().getPPr().getTabs().addNewTab();
tabStop.setVal(STTabJc.LEFT);
tabStop.setPos(BigInteger.valueOf(2 * twipsPerInch));
//first run in paragraph having picture
run = paragraph.createRun();
run.addPicture(new FileInputStream(imgFile), XWPFDocument.PICTURE_TYPE_PNG, imgFile, Units.toEMU(100), Units.toEMU(100));
run.addTab();
//second run
run = paragraph.createRun();
run.setText(text);
FileOutputStream out = new FileOutputStream("CreateWordTabulatorAndTable.docx");
document.write(out);
out.close();
document.close();
}
}
Result: