iText7 大 table autoLayout()

iText7 large table autoLayout()

根据文档

  public Table(int numColumns,
             boolean largeTable)
Constructs a Table with specified number of columns. The final column widths depend on selected table layout. Since 7.0.2 table layout algorithms were introduced. Auto layout is default, except large tables. For large table fixed layout set implicitly. Since 7.1 table will have undefined column widths, that will be determined during layout. In oder to set equal percent width as column width, use UnitValue.createPercentArray(int)

我使用 https://developers.itextpdf.com/examples/tables/clone-large-tables 渲染了一个大的 table 有没有办法定义自动布局?也许在添加第一行之后,获取单元格宽度并将它们设置在 table 上,但这似乎不可能,因为列宽为空,因为我正在使用具有列数的构造函数。 或者在到达结束页面时添加某种自动布局。 我不想定义列的宽度,因为我们有很多 tables.

首先我想提一下,自动布局需要整个table的内容。计算列宽时使用内容。但是你正在使用大table,这可能意味着你有很多数据并且你不想将所有内容都保存在内存中(如果不是这种情况,那就不要使用大tables ).

因此,您所能做的就是计算给定一些初始单元格的自动列宽的近似值。基本上,可以实现您的第一个想法,但是需要编写一些代码。但是如果你在不同行的单元格中有非常不同的内容(例如图像与内部 tables 与一些文本),那么这种方法可能效果不佳,因为正如我所说,要很好地估计列宽你需要所有内容。

另请记住,这种方法很脏,可能不适用于某些特殊情况。但它确实解决了这个目标,让您无需定义列宽。

为了用几句话来描述解决方案,我们采用几个初始行的单元格,将它们添加到临时 table 并对其进行布局(估计位置等),而不实际将其绘制到任何地方。然后我们从布局步骤信息中提取单元格宽度,并将它们用于大型 table 构造函数。

估算列宽的方法如下所示:

private UnitValue[] estimateWidths(Document document, Cell[][] cells) {
    int numOfColumns = cells[0].length;
    Table table = new Table(numOfColumns);
    for (int i = 0; i < cells.length; i++) {
        for (int j = 0; j < cells[i].length; j++) {
            table.addCell(cells[i][j]);
        }
    }
    LayoutContext context = new LayoutContext(document.getRenderer().getCurrentArea().clone());
    TableRenderer tableRenderer = (TableRenderer)table.createRendererSubTree();
    LayoutResult result = tableRenderer.setParent(document.getRenderer()).layout(context);
    if (result.getStatus() == LayoutResult.PARTIAL) {
        tableRenderer = (TableRenderer) result.getSplitRenderer();
    }
    UnitValue[] widths = new UnitValue[numOfColumns];
    List<IRenderer> subList = tableRenderer.getChildRenderers().subList(0, numOfColumns);
    for (int i = 0; i < subList.size(); i++) {
        IRenderer cell = subList.get(i);
        widths[i] = UnitValue.createPointValue(cell.getOccupiedArea().getBBox().getWidth());
    }
    return widths;
}

因此假设您有一个 Cell[][] cells 单元格数组用于初始几行(也可以是一行,但越多越好),其中 cells[i][j] 指的是行中的单元格i 和列 j,您可以像这样创建大 table:

Table table = new Table(estimateWidths(doc, cells), true);

但不要忘记在添加新内容之前将 cells 数组中的单元格显式添加到大 table 中。