Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set columnwidth of a table in XWPFTableCell (docx)

I'm generating a docx file with apache-poi. In the wordfile, I add tables, whose columns have a width I would like to see fixed.

Currently, I use the technique described here: http://apache-poi.1045710.n5.nabble.com/Is-there-a-way-to-set-the-width-of-a-column-in-XWPFTableCell-td5711491.html

Basically, this entails setting

cell.getCTTc().addNewTcPr().addNewTcW().setW(BigInteger.valueOf(cols[j])); 

on each cell of that column.

The problem is that while the file opens perfectly in MS Word, open office interprets the values I set to the columnwidth differently. Whereas MS Word apparantly assumes 20-th of a point as units, open office seems to use points instead and therefore all columns are 20 times wider when I open the generated document in OO.

Usually when I see something weird in the generated output, I unpack the docx file, see what the value should be and change my code. But open office does not seem to be able to save to docx, so I can't change the value in OO save it back and see if Word still interprets the document correctly in order to find a cross-application solution.

Any idea how I set the width of the table column so that both OO and MS Wordt interprets it the same?

like image 449
Yves V. Avatar asked Nov 18 '13 10:11

Yves V.


2 Answers

Don't touch single cells. Add a GRID:

XWPFDocument doc = new XWPFDocument();
XWPFTable table = doc.createTable(1,2);
table.getCTTbl().addNewTblGrid().addNewGridCol().setW(BigInteger.valueOf(6000));
table.getCTTbl().getTblGrid().addNewGridCol().setW(BigInteger.valueOf(2000));
table.getRow(0).getCell(0).setText("1A");
table.getRow(0).getCell(1).setText("1B");
XWPFTableRow newrow = table.createRow();
newrow.getCell(0).setText("2A");
newrow.getCell(1).setText("2B");

The grid sets widths for entire columns. You don't need to do any cycles to set a width for every cell. It works in LibreOffice and GoogleDocs.

To watch the seted width in MS Word too, you may set widths of cells in the first row:

 widthCellsAcrossRow(table, 0, 0, 4000);
 widthCellsAcrossRow(table, 0, 0, 5000);

private static void widthCellsAcrossRow (XWPFTable table, int rowNum, int colNum, int width) {
        XWPFTableCell cell = table.getRow(rowNum).getCell(colNum);
        if (cell.getCTTc().getTcPr() == null)
            cell.getCTTc().addNewTcPr();
        if (cell.getCTTc().getTcPr().getTcW()==null)
            cell.getCTTc().getTcPr().addNewTcW();
        cell.getCTTc().getTcPr().getTcW().setW(BigInteger.valueOf((long) width));
}
like image 127
nEraquasAr Avatar answered Nov 13 '22 21:11

nEraquasAr


Answer extracted from question:

It was recently pointed out to me that LibreOffice is able to save to docx. By changing the generated file and saving it back and decompiling the result, I have been able to resolve the issue.

Key is to put an explicit width to the table itself first. Word doesn't seem to care about its presence, and OpenOffice/LibreOffice are able to render the table correctly.

So, after creation of the table, I did as follows:

CTTblWidth width = table.getCTTbl().addNewTblPr().addNewTblW();
width.setType(STTblWidth.DXA);
width.setW(BigInteger.valueOf(9072));
like image 11
Deduplicator Avatar answered Nov 13 '22 20:11

Deduplicator