iText: Can I adjust the height of a table cell during rendering?
我正在生成一个PdfPTable并将其添加到章节中,然后将该章节添加到我的文档中。我的表有多个单元格,其中RowSpan> 1,有时这些跨度跨越页面边界,当发生这种情况时,我希望跨度的单元格再次出现。换句话说,如果我的表格如下所示:
1 2 3 4 5 6 7 | +------------------+------------------+ | Cell 1 RowSpan=1 | Cell 2 RowSpan=3 | +------------------+------------------+ | Cell 3 RowSpan=1 | | +------------------+------------------+ | Cell 4 RowSpan=1 | | +------------------+------------------+ |
但是在打印时,第2行和第3行之间有一个分页符,我希望表格看起来像这样:
1 2 3 4 5 6 7 8 9 | +--------+--------+ | Cell 1 | Cell 2 | +--------+ | | Cell 3 | | +--------+--------+ Page Break +--------+--------+ | Cell 4 | Cell 2 | +--------+--------+ |
这要归功于我在这里学到的技巧,我有一个实现IPdfPCellEvent的类,该类实例化并附加到RowSpan> 1的单元格上:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | public class CellEvent : IPdfPCellEvent { Phrase m_phrase; bool m_first = true; public CellEvent(Phrase phrase) { m_phrase = phrase; } void IPdfPCellEvent.CellLayout(PdfPCell cell, Rectangle r, PdfContentByte[] canvases) { if (m_first) m_first = false; else { ColumnText ct = cell.Column; ct.Canvases = canvases; m_phrase.Leading = m_phrase.Font.Size; ct.AddElement(m_phrase); ct.Go(); } } } |
如果CellLayout()被多次调用,则会发生后续调用,因为RowSpan已溢出到新页面上(我在上面描述的确切情况),因此我手动重新绘制了单元格文本。这很好。
除了。
如果我的单元格2比我的单元格1高:
1 2 3 4 5 6 | +------------------+-------------------------+ | Cell 1 RowSpan=1 | Cell 2 Line 1 RowSpan=2 | | | Cell 2 Line 2 | +------------------+-------------------------+ | Cell 3 RowSpan=1 | | +------------------+-------------------------+ |
表在这两行之间中断,我看到的是:
1 2 3 4 5 6 7 8 | +--------+---------------+ | Cell 1 | Cell 2 Line 1 | | | Cell 2 Line 2 | +--------+---------------+ Page Break +--------+---------------+ | Cell 3 | Cell 2 Line 1 | +--------+---------------+ |
因为,当然,该表不知道我要在第2行中绘制两行文本。
我可以将第2行设置为始终足够高以容纳两行,但是如果表恰好以这样的方式掉落,使得第1行和第2行之间没有分页符,则会在行中产生不必要的空白#2:
1 2 3 4 5 6 7 | +--------+---------------+ | Cell 1 | Cell 2 Line 1 | | | Cell 2 Line 2 | +--------| | | Cell 3 | | | | | <- un-necessary space +--------+---------------+ |
我尝试添加一个实现IPdfPTableEvent的类并将其附加到我的文档中,但是看来在执行完所有布局后会调用TableLayout(),因此我没有机会潜入并调整行高。
我想我可以使用PdfPTable.KeepRowsTogether()来防止在行跨度中间出现分页符,但这不是首选格式。
当表格呈现在PDF文档中时,是否有办法"介入"表格的布局,以便我可以调整行的高度?
ps。我刚刚创建了PdfPTable的子类,在其中重写GetRowHeight(idx)并返回所需的行高。它对生成的PDF无效。
我想出的解决方案是非迭代的(请参阅@ChrisHaas的想法),但需要更多代码。 代码有点混乱(反映了我为弄清解决方案而进行的所有迭代),所以我不会全部上传,但是基本要点是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | public class TableRowInfo { public int height; } public class TableEvent : IPdfPTableEventAfterSplit { Dictionary<PdfPRow, TableRowInfo> m_rows = null; public bool LoadSpans(PdfPTable table) { // Fill in m_rows, mapping PdfPRow to information about the height // of cells in that row, keeping row-spanning in mind } void IPdfPTableEventAfterSplit.AfterSplitTable(PdfPTable table, PdfPRow rowToStartNextPage, int startIdx) { TableRowInfo rowInfo = m_rows[rowToStartNextPage]; if (rowInfo.height > rowToStartNextPage.MaxHeights) { PdfPCell[] cells = rowToStartNextPage.GetCells(); foreach (PdfPCell cell in cells) { if (cell != null) cell.MinimumHeight = rowInfo.height; } rowToStartNextPage.MaxHeights = rowInfo.height; } } } PdfPTable table = new PdfPTable(...); // Fill in the rows of the table here table.TableEvent = new TableEvent(); table.TableEvent.LoadSpans(table); |