1

我尝试使用创建报告org.apache.poi。我已经创建了带有表格的模板,我想在其中复制行并插入信息。一个单元格包含两个段落和它们之间的小表格。

所以,我有时想删除表格,但XWPFTableCell没有所需的方法。只有removeParagraph(int p1).

如何删除单元格内的表格?

这是细胞克隆方法的代码

public static void cloneCell(XWPFTableCell clone, XWPFTableCell source) {
    CTTcPr cttcPr = clone.getCTTc().isSetTcPr() ? clone.getCTTc().getTcPr() : clone.getCTTc().addNewTcPr();
    cttcPr.set(source.getCTTc().getTcPr());

    int indexParag = 0, indexTable = 0;
    for (IBodyElement iBodyElement : source.getBodyElements()) {
        BodyElementType beType = iBodyElement.getElementType();
        if (beType == BodyElementType.PARAGRAPH) {
            XWPFParagraph sourceParag = (XWPFParagraph)iBodyElement;
            XWPFParagraph cloneParag = indexParag < clone.getParagraphs().size() ? clone.getParagraphs().get(indexParag) : clone.addParagraph();
            cloneParagraph(cloneParag, sourceParag);
            indexParag++;
        } else if (beType == BodyElementType.TABLE) {
            XWPFTable sourceTable = (XWPFTable)iBodyElement;
            XWPFTable cloneTable = indexTable < clone.getTables().size() ? clone.getTables().get(indexTable) : clone.insertNewTbl(sourceTable.getCTTbl().newCursor());
            if (cloneTable == null)
                cloneTable = new XWPFTable(clone.getCTTc().addNewTbl(), clone);

            cloneTable(cloneTable, sourceTable);
            indexTable++;
        }
    }
}
4

1 回答 1

1

我使用这样的代码。有两种非常糟糕的方法可以直接访问单元格的字段。我找不到访问正文元素列表和表格列表的正确方法。

该方法从 startIndex 开始从父元素(文档正文元素或单元格元素)中删除元素,计数显示要删除的元素数量。

注意:表格中的最后一个元素必须是一个段落,所以不要删除最后一个段落元素。使其为空(改为删除运行)。

public void removeElements(IBody parent, int startIndex, int count) {
    if (parent instanceof XWPFTableCell) {
        XWPFTableCell cell = (XWPFTableCell)parent;
        List<IBodyElement> bodyElementsRef = getBodyElementsRef(cell);
        for (int i = 0; i < count; i++) {
            IBodyElement element = bodyElementsRef.get(startIndex);
            if (element instanceof XWPFParagraph) {
                int realParIndex = getParagraphIndex(bodyElementsRef, (XWPFParagraph)element);
                cell.getParagraphs().remove(realParIndex);
                cell.getCTTc().removeP(realParIndex);
            } else if (element instanceof XWPFTable) {
                int realTableIndex = getTableIndex(bodyElementsRef, (XWPFTable) element);
                getTablesRef(cell).remove(realTableIndex);
                cell.getCTTc().removeTbl(realTableIndex);
            }
            bodyElementsRef.remove(startIndex);
        }
    }
    else {
        for (int i = 0; i < count; i++) {
            parent.getXWPFDocument().removeBodyElement(startIndex);
        }
    }
}

private int getParagraphIndex(List<IBodyElement> bodyElementsRef, XWPFParagraph paragraph) {
    int index = -1;
    for(IBodyElement elem : bodyElementsRef) {
        if (elem instanceof XWPFParagraph) {
            index++;
        }
        if (elem == paragraph) {
            return index;
        }
    }
    return -1;
}

private int getTableIndex(List<IBodyElement> bodyElementsRef, XWPFTable table) {
    int index = -1;
    for(IBodyElement elem : bodyElementsRef) {
        if (elem instanceof XWPFTable) {
            index++;
        }
        if (elem == table) {
            return index;
        }
    }
    return -1;
}

/**
 * It's a dirty hack but I cannot find proper way to remove elements from cell's body elements
 * @param cell
 * @return
 */
private List<IBodyElement> getBodyElementsRef(XWPFTableCell cell) {
    try {
        Field beField = cell.getClass().getDeclaredField("bodyElements");
        beField.setAccessible(true);
        return (List<IBodyElement>) beField.get(cell);
    } catch (NoSuchFieldException | IllegalAccessException e) {
        throw new RuntimeException(e);
    }
}
/**
 * It's a dirty hack but I cannot find proper way to remove elements from cell's tables list
 * @param cell
 * @return
 */
private List<XWPFTable> getTablesRef(XWPFTableCell cell) {
    try {
        Field beField = cell.getClass().getDeclaredField("tables");
        beField.setAccessible(true);
        return (List<XWPFTable>) beField.get(cell);
    } catch (NoSuchFieldException | IllegalAccessException e) {
        throw new RuntimeException(e);
    }
}
于 2019-12-03T11:36:28.637 回答