Таблицы не объединены в таблицу. Обычные таблицы хорошо объединяются. интересно, в чем причина

Правильное изображение введите здесь описание изображения

Таблицы не объединены в таблицу. Обычные таблицы хорошо объединяются. интересно, в чем причина

Таблицы не объединены в таблицу.

Обычные таблицы хорошо объединяются.

Интересно, в чем причина.

public static void main(String[] args) {
    try {
        XWPFDocument doc = new XWPFDocument();

        // create main table
        XWPFTable table = doc.createTable();

        // create rows and cells
        XWPFTableRow row = table.getRow(0);
        row.getCell(0).setText("Main table A1");
        row.addNewTableCell().setText("Main table B1");
        row.addNewTableCell().setText("Main table C1");

        row = table.createRow();
        row.setHeight(2000);
        row.getCell(0).setText("Main table A2");
        row.getCell(1).setText("Main table B2");
        row.getCell(2).setText("Main table C2");

        row = table.createRow();
        row.setHeight(2000);
        row.getCell(0).setText("Main table d2");
        row.getCell(1).setText("Main table d2");
        row.getCell(2).setText("Main table d2");

        // 1
        row = table.getRow(0);
        XWPFTableCell cell = row.getTableCells().get(0);
        XWPFParagraph paragraph = cell.addParagraph();

        // 2
        org.apache.xmlbeans.XmlCursor cursor = paragraph.getCTP().newCursor();

        XWPFTable innerTable = cell.insertNewTbl(cursor);

        // 3
        innerTable.setTopBorder(XWPFTable.XWPFBorderType.SINGLE, 4, 0, "000000");
        innerTable.setRightBorder(XWPFTable.XWPFBorderType.SINGLE, 4, 0, "000000");
        innerTable.setBottomBorder(XWPFTable.XWPFBorderType.SINGLE, 4, 0, "000000");
        innerTable.setLeftBorder(XWPFTable.XWPFBorderType.SINGLE, 4, 0, "000000");
        innerTable.setInsideHBorder(XWPFTable.XWPFBorderType.SINGLE, 4, 0, "000000");
        innerTable.setInsideVBorder(XWPFTable.XWPFBorderType.SINGLE, 4, 0, "000000");

        // 4
        XWPFTableRow rowInInnerTable = innerTable.createRow();
        rowInInnerTable.setHeight(1000);

        XWPFTableCell cellInInnerTable = rowInInnerTable.createCell();
        cellInInnerTable.setColor("FF00FF");
        rowInInnerTable.getCell(0).setWidth("700");
        rowInInnerTable.getCell(0).setVerticalAlignment(XWPFVertAlign.CENTER);
        XWPFParagraph p5 = rowInInnerTable.getCell(0).getParagraphs().get(0);

        p5.setAlignment(ParagraphAlignment.CENTER);
        XWPFRun r5 = p5.createRun();
        r5.setFontSize(10);
        r5.setText("SUB_TAB1");

        cellInInnerTable = rowInInnerTable.createCell();
        rowInInnerTable.getCell(1).setWidth("300"); // ??? ??
        rowInInnerTable.getCell(1).setVerticalAlignment(XWPFVertAlign.CENTER);
        cellInInnerTable.setColor("FF00FF"); // ??
        p5 = rowInInnerTable.getCell(1).getParagraphs().get(0);
        p5.setAlignment(ParagraphAlignment.CENTER);
        r5 = p5.createRun();
        r5.setFontSize(10);
        r5.setText("SUB_TAB3");

        cellInInnerTable = rowInInnerTable.createCell();
        cellInInnerTable.setColor("FF00FF"); // ??
        rowInInnerTable.getCell(2).setWidth("2000"); // ??? ??
        rowInInnerTable.getCell(2).setVerticalAlignment(XWPFVertAlign.CENTER);
        p5 = rowInInnerTable.getCell(2).getParagraphs().get(0);
        p5.setAlignment(ParagraphAlignment.CENTER);
        r5 = p5.createRun();
        r5.setText("SUB_TAB4");

        rowInInnerTable = innerTable.createRow();
        cellInInnerTable = rowInInnerTable.getCell(0);
        p5 = rowInInnerTable.getCell(0).getParagraphs().get(0);
        p5.setAlignment(ParagraphAlignment.CENTER);
        r5 = p5.createRun();
        r5.setText("AA");

        cellInInnerTable = rowInInnerTable.getCell(1);
        p5 = rowInInnerTable.getCell(1).getParagraphs().get(0);
        p5.setAlignment(ParagraphAlignment.CENTER);
        r5 = p5.createRun();
        r5.setText("BB1");

        cellInInnerTable = rowInInnerTable.getCell(2);
        p5 = rowInInnerTable.getCell(2).getParagraphs().get(0);
        p5.setAlignment(ParagraphAlignment.CENTER);
        r5 = p5.createRun();
        r5.setText("CC");

        rowInInnerTable = innerTable.createRow();
        cellInInnerTable = rowInInnerTable.getCell(0);
        p5 = rowInInnerTable.getCell(0).getParagraphs().get(0);
        p5.setAlignment(ParagraphAlignment.CENTER);
        r5 = p5.createRun();
        r5.setText("AA_2");

        setColumnWidth(table, 0, 0, 4500);
        setColumnWidth(table, 0, 1, 2000);
        setColumnWidth(table, 0, 2, 2000);

        mergeCellVertically(table, 1, 1, 2);
        mergeCellVertically(innerTable, 1, 1, 2); // ????????????????????????????

        // save to .docx file
        try (FileOutputStream out = new FileOutputStream("c:\\test\\MAIN_table.docx")) {
            doc.write(out);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public static void setColumnWidth(XWPFTable table, int row, int col, int width) {
    CTTblWidth tblWidth = CTTblWidth.Factory.newInstance();
    tblWidth.setW(BigInteger.valueOf(width));
    tblWidth.setType(STTblWidth.DXA);
    CTTcPr tcPr = table.getRow(row).getCell(col).getCTTc().getTcPr();
    if (tcPr != null) {
        tcPr.setTcW(tblWidth);
    } else {
        tcPr = CTTcPr.Factory.newInstance();
        tcPr.setTcW(tblWidth);
        table.getRow(row).getCell(col).getCTTc().setTcPr(tcPr);
    }
}

static void mergeCellVertically(XWPFTable table, int col, int fromRow, int toRow) {
    for (int rowIndex = fromRow; rowIndex <= toRow; rowIndex++) {
        XWPFTableCell cell = table.getRow(rowIndex).getCell(col);
        CTVMerge vmerge = CTVMerge.Factory.newInstance();
        if (rowIndex == fromRow) {
            vmerge.setVal(STMerge.RESTART);
        } else {
            vmerge.setVal(STMerge.CONTINUE);
            for (int i = cell.getParagraphs().size(); i > 0; i--) {
                cell.removeParagraph(0);
            }
            cell.addParagraph();
        }
        CTTcPr tcPr = cell.getCTTc().getTcPr();
        if (tcPr == null) {
            tcPr = cell.getCTTc().addNewTcPr();
        }
        tcPr.setVMerge(vmerge);
    }
}

Пожалуйста, отредактируйте свой вопрос и правильно отформатируйте код.

MC Emperor 07.01.2023 20:49

гм, простите меня, но я не совсем понимаю, какую часть следует объединять, а какую нет. на картинке изображен ожидаемый результат или проблема?

Bagus Tesa 07.01.2023 21:48

Второй и третий должны слиться.

ych1215 08.01.2023 03:52
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
3
105
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Кажется, что XWPFTable.createRow искажает массив строк таблицы, по крайней мере, для таблиц в таблицах. Моя отладка показала, что XWPFTable.getRow(0) получает вторую строку, когда XWPFTable является таблицей в таблице, а строка была добавлена ​​с помощью XWPFTable.createRow. Тогда XWPFTable.getRow(1) получает третью строку, а первая строка недостижима с помощью XWPFTable.getRow.

Если для добавления строк используется XWPFTable.insertNewTableRow, то XWPFTable.getRow работает корректно.

Полный пример:

import java.io.*;

import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;

public class CreateWordTableInTable2 {
    
public static void main(String[] args) {
    try {
        XWPFDocument doc = new XWPFDocument();

        // create main table
        XWPFTable table = doc.createTable();

        // create rows and cells
        XWPFTableRow row = table.getRow(0);
        row.getCell(0).setText("Main table A1");
        row.addNewTableCell().setText("Main table B1");
        row.addNewTableCell().setText("Main table C1");

        row = table.createRow();
        row.setHeight(2000);
        row.getCell(0).setText("Main table A2");
        row.getCell(1).setText("Main table B2");
        row.getCell(2).setText("Main table C2");

        row = table.createRow();
        row.setHeight(2000);
        row.getCell(0).setText("Main table d2");
        row.getCell(1).setText("Main table d2");
        row.getCell(2).setText("Main table d2");

        // 1
        row = table.getRow(0);
        XWPFTableCell cell = row.getTableCells().get(0);
        XWPFParagraph paragraph = cell.addParagraph();

        // 2
        org.apache.xmlbeans.XmlCursor cursor = paragraph.getCTP().newCursor();

        XWPFTable innerTable = cell.insertNewTbl(cursor);

        // 3
        innerTable.setTopBorder(XWPFTable.XWPFBorderType.SINGLE, 4, 0, "000000");
        innerTable.setRightBorder(XWPFTable.XWPFBorderType.SINGLE, 4, 0, "000000");
        innerTable.setBottomBorder(XWPFTable.XWPFBorderType.SINGLE, 4, 0, "000000");
        innerTable.setLeftBorder(XWPFTable.XWPFBorderType.SINGLE, 4, 0, "000000");
        innerTable.setInsideHBorder(XWPFTable.XWPFBorderType.SINGLE, 4, 0, "000000");
        innerTable.setInsideVBorder(XWPFTable.XWPFBorderType.SINGLE, 4, 0, "000000");

        // 4
        //XWPFTableRow rowInInnerTable = innerTable.createRow();
        XWPFTableRow rowInInnerTable = innerTable.insertNewTableRow(0);
        rowInInnerTable.setHeight(1000);

        XWPFTableCell cellInInnerTable = rowInInnerTable.createCell();
        cellInInnerTable.setColor("FF00FF");
        rowInInnerTable.getCell(0).setWidth("700");
        rowInInnerTable.getCell(0).setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
        XWPFParagraph p5 = rowInInnerTable.getCell(0).getParagraphs().get(0);

        p5.setAlignment(ParagraphAlignment.CENTER);
        XWPFRun r5 = p5.createRun();
        r5.setFontSize(10);
        r5.setText("SUB_TAB1");

        cellInInnerTable = rowInInnerTable.createCell();
        rowInInnerTable.getCell(1).setWidth("300"); // ??? ??
        rowInInnerTable.getCell(1).setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
        cellInInnerTable.setColor("FF00FF"); // ??
        p5 = rowInInnerTable.getCell(1).getParagraphs().get(0);
        p5.setAlignment(ParagraphAlignment.CENTER);
        r5 = p5.createRun();
        r5.setFontSize(10);
        r5.setText("SUB_TAB3");

        cellInInnerTable = rowInInnerTable.createCell();
        cellInInnerTable.setColor("FF00FF"); // ??
        rowInInnerTable.getCell(2).setWidth("2000"); // ??? ??
        rowInInnerTable.getCell(2).setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
        p5 = rowInInnerTable.getCell(2).getParagraphs().get(0);
        p5.setAlignment(ParagraphAlignment.CENTER);
        r5 = p5.createRun();
        r5.setText("SUB_TAB4");

        //rowInInnerTable = innerTable.createRow();
        //cellInInnerTable = rowInInnerTable.getCell(0);
        rowInInnerTable = innerTable.insertNewTableRow(1);
        cellInInnerTable = rowInInnerTable.createCell();
        p5 = rowInInnerTable.getCell(0).getParagraphs().get(0);
        p5.setAlignment(ParagraphAlignment.CENTER);
        r5 = p5.createRun();
        r5.setText("AA");

        //cellInInnerTable = rowInInnerTable.getCell(1);
        cellInInnerTable = rowInInnerTable.createCell();
        p5 = rowInInnerTable.getCell(1).getParagraphs().get(0);
        p5.setAlignment(ParagraphAlignment.CENTER);
        r5 = p5.createRun();
        r5.setText("BB1");

        //cellInInnerTable = rowInInnerTable.getCell(2);
        cellInInnerTable = rowInInnerTable.createCell();
        p5 = rowInInnerTable.getCell(2).getParagraphs().get(0);
        p5.setAlignment(ParagraphAlignment.CENTER);
        r5 = p5.createRun();
        r5.setText("CC");

        //rowInInnerTable = innerTable.createRow();
        //cellInInnerTable = rowInInnerTable.getCell(0);
        rowInInnerTable = innerTable.insertNewTableRow(2);
        cellInInnerTable = rowInInnerTable.createCell();
        p5 = rowInInnerTable.getCell(0).getParagraphs().get(0);
        p5.setAlignment(ParagraphAlignment.CENTER);
        r5 = p5.createRun();
        r5.setText("AA_2");
        
        //cellInInnerTable = rowInInnerTable.getCell(1);
        cellInInnerTable = rowInInnerTable.createCell();

        //cellInInnerTable = rowInInnerTable.getCell(2);
        cellInInnerTable = rowInInnerTable.createCell();

        setColumnWidth(table, 0, 0, 4500);
        setColumnWidth(table, 0, 1, 2000);
        setColumnWidth(table, 0, 2, 2000);

        mergeCellVertically(table, 1, 1, 2);
        mergeCellVertically(innerTable, 1, 1, 2); // ????????????????????????????

        // save to .docx file
        try (FileOutputStream out = new FileOutputStream("./MAIN_table.docx")) {
            doc.write(out);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public static void setColumnWidth(XWPFTable table, int row, int col, int width) {
    CTTblWidth tblWidth = CTTblWidth.Factory.newInstance();
    tblWidth.setW(java.math.BigInteger.valueOf(width));
    tblWidth.setType(STTblWidth.DXA);
    CTTcPr tcPr = table.getRow(row).getCell(col).getCTTc().getTcPr();
    if (tcPr != null) {
        tcPr.setTcW(tblWidth);
    } else {
        tcPr = CTTcPr.Factory.newInstance();
        tcPr.setTcW(tblWidth);
        table.getRow(row).getCell(col).getCTTc().setTcPr(tcPr);
    }
}

static void mergeCellVertically(XWPFTable table, int col, int fromRow, int toRow) {
    for (int rowIndex = fromRow; rowIndex <= toRow; rowIndex++) {
        XWPFTableCell cell = table.getRow(rowIndex).getCell(col);
        //System.out.println(cell.getTableRow().getCtRow()); // wrong row in inner table when XWPFTable.createRow was used
        CTVMerge vmerge = CTVMerge.Factory.newInstance();
        if (rowIndex == fromRow) {
            vmerge.setVal(STMerge.RESTART);
        } else {
            vmerge.setVal(STMerge.CONTINUE);
            for (int i = cell.getParagraphs().size(); i > 0; i--) {
                cell.removeParagraph(0);
            }
            cell.addParagraph();
        }
        CTTcPr tcPr = cell.getCTTc().getTcPr();
        if (tcPr == null) {
            tcPr = cell.getCTTc().addNewTcPr();
        }
        tcPr.setVMerge(vmerge);
    }
}

}

Результат:

Если вопрос, почему так происходит, то подозреваю, что виноват XWPFTable.addColumn. Это основное различие между XWPFTable.createRow и XWPFTable.insertNewTableRow. Первый пытается заполнить новую добавленную строку таким количеством ячеек, сколько столбцов уже есть в таблице. Второй этого не делает и добавляет пустую строку.

Никогда не понимал такого поведения XWPFTable.createRow. Почему необходимо заполнять новую добавленную строку таким количеством ячеек, сколько столбцов уже есть в таблице? Почему бы просто не позволить программисту добавить ячейки в строку?

Большое спасибо. Я долго не мог понять причину. Спасибо.

ych1215 14.01.2023 15:27

Другие вопросы по теме