Установка ширины столбца таблицы в XWPFTableCell (docx)

Я генерирую файл DOCX с Apache-Poi. В wordfile я добавляю таблицы, столбцы которых имеют ширину, которую я хотел бы видеть фиксированной.

В настоящее время я использую технику, описанную здесь: http://apache-poi.1045710.n5.nabble.com/Is-there-a-way-to-set-the-width-of-a-column-in-XWPFTableCell -td5711491.html

В основном это влечет за собой установку

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

на каждой ячейке этого столбца.

Проблема в том, что, хотя файл прекрасно открывается в MS Word, open office по-разному интерпретирует значения, установленные для ширины столбца. Принимая во внимание, что MS Word, по-видимому, принимает 20-ю точку в качестве единиц, при открытии офиса кажется, что вместо них используются точки, и поэтому все столбцы становятся в 20 раз шире, когда я открываю сгенерированный документ в ОО.

Обычно, когда я вижу что-то странное в сгенерированном выводе, я распаковываю файл docx, вижу значение и меняю свой код. Но кажется, что open office не может сохранить в docx, поэтому я не могу изменить значение в OO, сохранить его обратно и посмотреть, правильно ли Word интерпретирует документ, чтобы найти решение для нескольких приложений.

Любая идея, как я устанавливаю ширину столбца таблицы, чтобы и OO, и MS Wordt интерпретировали это одинаково?

Ответ 1

Ответ извлечен из вопроса:

Недавно мне было указано, что LibreOffice может сэкономить до docx. Меняя сгенерированный файл и сохраняя его обратно и декомпилируя результат, я смог решить проблему.

Ключ должен сначала ввести явную ширину в таблицу. Word, похоже, не заботится о его присутствии, и OpenOffice/LibreOffice могут правильно отображать таблицу.

Итак, после создания таблицы я сделал следующее:

CTTblWidth width = table.getCTTbl().addNewTblPr().addNewTblW();
width.setType(STTblWidth.DXA);
width.setW(BigInteger.valueOf(9072));

Ответ 2

Не касайтесь отдельных ячеек. Добавить 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");

Сетка устанавливает ширину для целых столбцов. Вам не нужно делать какие-либо циклы, чтобы установить ширину для каждой ячейки. Он работает в LibreOffice и GoogleDocs.

Чтобы просмотреть установленную ширину в MS Word, вы можете установить ширину ячеек в первой строке:

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

Ответ 3

После создания таблицы макет по умолчанию устанавливается на "авто", поэтому ширина ячейки всегда увеличивается, чтобы соответствовать длине строки. По разметке OpenXML это выглядит так: w:tblPr w:tblLayout w:type="auto"
решение состоит в том, чтобы установить макет на fixed и задать отдельную длину столбца w:tblPr w:tblLayout w:type="fixed"

Здесь код poi для настройки макета таблицы:

XWPFTable table = document.createTable();
CTTblLayoutType type = table.getCTTbl().getTblPr().addNewTblLayout();
type.setType(STTblLayoutType.FIXED);

Здесь, как установить индивидуальную ширину:

 int[] cols = {
    4896,
    1872,
    4032,
    1728,
    1440
};

for (int i = 0; i < table.getNumberOfRows(); i++) {
    XWPFTableRow row = table.getRow(i);
    int numCells = row.getTableCells().size();
    for (int j = 0; j < numCells; j++) {
        XWPFTableCell cell = row.getCell(j);
        CTTblWidth cellWidth = cell.getCTTc().addNewTcPr().addNewTcW();
        CTTcPr pr = cell.getCTTc().addNewTcPr();
        pr.addNewNoWrap();
        cellWidth.setW(BigInteger.valueOf(cols[j]));
    }
}
Длина столбцов

равна двадцатым точкам (dxa) или 1/1440 дюйма.

Ответ 4

Это важный и очень сложный элемент. Я решил это, используя этот собственный общий метод установки ширины ячейки таблицы.

private static void setTableColumnWidths(XWPFTable table) {
    table.getCTTbl().addNewTblGrid().addNewGridCol().setW(BigInteger.valueOf(2000));
    table.getCTTbl().getTblGrid().addNewGridCol().setW(BigInteger.valueOf(3200));
    table.getCTTbl().getTblGrid().addNewGridCol().setW(BigInteger.valueOf(1000));
    table.getCTTbl().getTblGrid().addNewGridCol().setW(BigInteger.valueOf(1000));
    table.getCTTbl().getTblGrid().addNewGridCol().setW(BigInteger.valueOf(1105));
    table.getCTTbl().getTblGrid().addNewGridCol().setW(BigInteger.valueOf(1105));
}

Ответ 5

На основании других ответов...

  public static void setTableColumnsWidth(XWPFTable table, long... widths) {
    CTTblGrid grid = table.getCTTbl().addNewTblGrid();
    for (long w : widths) {
      grid.addNewGridCol().setW(BigInteger.valueOf(w));
    }    
  }

Использование:

setTableColumnsWidth(table, 1440, 2700, 3000, 1440);