iText:我可以在渲染过程中调整 table 单元格的高度吗?
iText: Can I adjust the height of a table cell during rendering?
我正在生成一个 PdfPTable 并将其添加到一个章节中,然后将该章节添加到我的文档中。我的 table 有几个 RowSpan > 1 的单元格,有时这些单元格跨越页面边界,当发生这种情况时,我希望跨越的单元格再次出现。换句话说,如果我的 table 看起来像这样:
+------------------+------------------+
| Cell 1 RowSpan=1 | Cell 2 RowSpan=3 |
+------------------+------------------+
| Cell 3 RowSpan=1 | |
+------------------+------------------+
| Cell 4 RowSpan=1 | |
+------------------+------------------+
但是在打印时,第 2 行和第 3 行之间有一个分页符,我希望 table 看起来像这样:
+--------+--------+
| Cell 1 | Cell 2 |
+--------+ |
| Cell 3 | |
+--------+--------+
Page Break
+--------+--------+
| Cell 4 | Cell 2 |
+--------+--------+
这要归功于我在这里学到的一个技巧,我有一个 class 实现了 IPdfPCellEvent,我将其实例化并附加到 RowSpan > 1 的单元格:
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 高:
+------------------+-------------------------+
| Cell 1 RowSpan=1 | Cell 2 Line 1 RowSpan=2 |
| | Cell 2 Line 2 |
+------------------+-------------------------+
| Cell 3 RowSpan=1 | |
+------------------+-------------------------+
并且 table 在这两行之间中断,我看到的是:
+--------+---------------+
| Cell 1 | Cell 2 Line 1 |
| | Cell 2 Line 2 |
+--------+---------------+
Page Break
+--------+---------------+
| Cell 3 | Cell 2 Line 1 |
+--------+---------------+
因为 table 当然不知道我想在第 2 行中绘制两行文本。
我可以将第 2 行设置为始终足够高以容纳两行,但是如果 table 恰好落在第 1 行和第 # 行之间没有分页符的位置2,它在第 2 行生成不必要的白色 space:
+--------+---------------+
| Cell 1 | Cell 2 Line 1 |
| | Cell 2 Line 2 |
+--------| |
| Cell 3 | |
| | | <- un-necessary space
+--------+---------------+
我尝试添加实现 IPdfPTableEvent 的 class 并将其附加到我的文档,但似乎在执行所有布局后调用了 TableLayout(),所以我没有机会潜入并调整行高。
我想我可以使用 PdfPTable.KeepRowsTogether() 来防止在行跨度中间出现分页符,但这不是首选格式。
有没有办法 "get involved" 使用 table 的布局,因为它正在呈现到 PDF 文档中,以便我可以调整行的高度?
p.s。我刚刚创建了 PdfPTable 的子class,我在其中覆盖了 GetRowHeight(idx) 和 return 我想要的行高。它对生成的 PDF 没有影响。
我想出的解决方案是非迭代的(请参阅评论中@ChrisHaas 的想法)但需要更多代码。代码有点乱(反映了我为找出解决方案所做的所有迭代)所以我不打算全部上传,但基本要点是:
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);
我正在生成一个 PdfPTable 并将其添加到一个章节中,然后将该章节添加到我的文档中。我的 table 有几个 RowSpan > 1 的单元格,有时这些单元格跨越页面边界,当发生这种情况时,我希望跨越的单元格再次出现。换句话说,如果我的 table 看起来像这样:
+------------------+------------------+
| Cell 1 RowSpan=1 | Cell 2 RowSpan=3 |
+------------------+------------------+
| Cell 3 RowSpan=1 | |
+------------------+------------------+
| Cell 4 RowSpan=1 | |
+------------------+------------------+
但是在打印时,第 2 行和第 3 行之间有一个分页符,我希望 table 看起来像这样:
+--------+--------+
| Cell 1 | Cell 2 |
+--------+ |
| Cell 3 | |
+--------+--------+
Page Break
+--------+--------+
| Cell 4 | Cell 2 |
+--------+--------+
这要归功于我在这里学到的一个技巧,我有一个 class 实现了 IPdfPCellEvent,我将其实例化并附加到 RowSpan > 1 的单元格:
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 高:
+------------------+-------------------------+
| Cell 1 RowSpan=1 | Cell 2 Line 1 RowSpan=2 |
| | Cell 2 Line 2 |
+------------------+-------------------------+
| Cell 3 RowSpan=1 | |
+------------------+-------------------------+
并且 table 在这两行之间中断,我看到的是:
+--------+---------------+
| Cell 1 | Cell 2 Line 1 |
| | Cell 2 Line 2 |
+--------+---------------+
Page Break
+--------+---------------+
| Cell 3 | Cell 2 Line 1 |
+--------+---------------+
因为 table 当然不知道我想在第 2 行中绘制两行文本。
我可以将第 2 行设置为始终足够高以容纳两行,但是如果 table 恰好落在第 1 行和第 # 行之间没有分页符的位置2,它在第 2 行生成不必要的白色 space:
+--------+---------------+
| Cell 1 | Cell 2 Line 1 |
| | Cell 2 Line 2 |
+--------| |
| Cell 3 | |
| | | <- un-necessary space
+--------+---------------+
我尝试添加实现 IPdfPTableEvent 的 class 并将其附加到我的文档,但似乎在执行所有布局后调用了 TableLayout(),所以我没有机会潜入并调整行高。
我想我可以使用 PdfPTable.KeepRowsTogether() 来防止在行跨度中间出现分页符,但这不是首选格式。
有没有办法 "get involved" 使用 table 的布局,因为它正在呈现到 PDF 文档中,以便我可以调整行的高度?
p.s。我刚刚创建了 PdfPTable 的子class,我在其中覆盖了 GetRowHeight(idx) 和 return 我想要的行高。它对生成的 PDF 没有影响。
我想出的解决方案是非迭代的(请参阅评论中@ChrisHaas 的想法)但需要更多代码。代码有点乱(反映了我为找出解决方案所做的所有迭代)所以我不打算全部上传,但基本要点是:
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);