Я создаю текстовый документ с таблицей, используя Java и Apache POI.
Я могу достаточно легко создать таблицу, установить каждый столбец с разной шириной, а затем объединить ячейки для создания желаемый эффект (см. изображения ниже), однако, когда я открываю текстовый документ, некоторые ячейки были скорректированы так, что их края соединяются вместе. Я обнаружил, что добавление дополнительной строки в начало таблицы и оставление всех ячеек несвязанными сохраняет остальные строки нетронутыми, но удаление этой строки позже с помощью table.removeRow (0); влияет на остальные строки. Если я открою текстовый документ и вручную удалю строку, ячейки останутся на месте. Могу ли я что-нибудь сделать, чтобы сохранить расположение ячеек?
правильный макет с дополнительной неслитой верхней строкой
результат после удаления верхней строки
Это функция, которая создает слово do c и таблицу:
public static void createWord() {
// Blank Document
XWPFDocument document = new XWPFDocument();
CTSectPr sectPr = document.getDocument().getBody().addNewSectPr();
CTPageMar pageMar = sectPr.addNewPgMar();
pageMar.setLeft(BigInteger.valueOf(300L));
pageMar.setTop(BigInteger.valueOf(300L));
pageMar.setRight(BigInteger.valueOf(300L));
pageMar.setBottom(BigInteger.valueOf(300L));
XWPFParagraph paragraph = document.createParagraph();
paragraph.setSpacingBefore(0);
paragraph.setSpacingAfter(0);
// determine the number of rows and columns required
int rows = 3;
int cols = 6;
// create table
XWPFTable table = document.createTable(rows+1, cols);
CTTblPr tblPr = table.getCTTbl().getTblPr();
if (null == tblPr) {
tblPr = table.getCTTbl().addNewTblPr();
}
// set table width
CTTblWidth width = table.getCTTbl().addNewTblPr().addNewTblW();
width.setType(STTblWidth.PCT);
width.setW(BigInteger.valueOf(5000)); // 5000 * 1/50 = 100%
//set row height
for(XWPFTableRow row:table.getRows()) {
row.setHeight(22);
}
// set width of each column
for (int row = 0; row <= rows; row++) {
setCellWidthPercentage(table, row, 0, 0.188);
setCellWidthPercentage(table, row, 1, 0.125);
setCellWidthPercentage(table, row, 2, 0.063);
setCellWidthPercentage(table, row, 3, 0.25);
setCellWidthPercentage(table, row, 4, 0.25);
setCellWidthPercentage(table, row, 5, 0.125);
}
mergeCellHorizontally(table, 1, 0, 2);
mergeCellHorizontally(table, 2, 0, 1);
mergeCellHorizontally(table, 2, 2, 4);
mergeCellHorizontally(table, 3, 1, 3);
// remove first row (comment out this line to see issue)
table.removeRow(0);
// Write the Document in file system
try {
File docFile = new File("C:\\doc.docx");
docFile.createNewFile();
FileOutputStream out = new FileOutputStream(docFile, false);
document.write(out);
out.close();
document.close();
} catch(Exception ex) {
ex.printStackTrace();
}
}
Я использую приведенный ниже код для объединения ячеек по горизонтали:
static void mergeCellHorizontally(XWPFTable table, int row, int fromCol, int toCol) {
for(int colIndex = fromCol; colIndex <= toCol; colIndex++){
XWPFTableCell cell = table.getRow(row).getCell(colIndex);
CTHMerge hmerge = CTHMerge.Factory.newInstance();
if(colIndex == fromCol) {
// The first merged cell is set with RESTART merge value
hmerge.setVal(STMerge.RESTART);
} else {
// Cells which join (merge) the first one, are set with CONTINUE
hmerge.setVal(STMerge.CONTINUE);
}
// Try getting the TcPr. Not simply setting an new one every time.
CTTcPr tcPr = cell.getCTTc().getTcPr();
if (tcPr != null) {
tcPr.setHMerge(hmerge);
} else {
// only set an new TcPr if there is not one already
tcPr = CTTcPr.Factory.newInstance();
tcPr.setHMerge(hmerge);
cell.getCTTc().setTcPr(tcPr);
}
}
}
и эта функция для присвоения значений ширины столбцам перед объединением:
private static void setCellWidthPercentage(XWPFTable table, int row, int col, double width) {
// prevent out of bounds exception
if (row < 0 || row >= table.getRows().size()) return;
if (col < 0 || col >= table.getRow(row).getTableCells().size()) return;
// assign widths in units of 1/50 of a percentage
CTTblWidth tblW = table.getRow(row).getCell(col).getCTTc().addNewTcPr().addNewTcW();
tblW.setType(STTblWidth.PCT);
tblW.setW(BigInteger.valueOf(Math.round(width * 50)));
}
Заранее спасибо!