該頁面可以包含自動翻譯的文字。
Table 容器
使用 Table 容器來佈局最複雜的資料。表格在 PDF 文件中發揮著 至關重要的作用,可以提高文件的清晰度和有效性。
表格提供了用於呈現資料的結構化格式。它們使您能夠以簡潔且具有視覺吸引力的方式呈現複雜的細節。您可以 使用表格來簡潔地呈現事實、數據和趨勢,而不是冗長的段落。
精心設計的表格可以增強可讀性。透過對齊列和行,您可以建立引導讀者視線的結構。您可以使用背景、邊框和 字體樣式來強調特定的儲存格或標題。
透過呼叫 LayoutContainer.Table 方法來取得一 個表格容器。然後您必須在容器中定義至少一列。在最簡單的情況下,您可以透過多次呼叫 Cell 方法來填入所有列和行。
請繼續閱讀以了解如何定義列、為表格新增頁首和/或頁尾。該文字還描述了 Table 容器的所有其他功能。
本文是用於 PDF 產生的 Layout API 的系列文章的一部分。 如果您是 API 新手,請先閱讀 Layout API 入 門 部分。
9.5.17548-dev 9.5.17548-dev14,726 已通過 NuGet 總下載量 4,514,921
列和行
每個表格必須至少定義一列。使用 Table.Columns 方法來
定義列。此方法接受類型為
Action
<TableColumnContainer> 的委託。在委
託代碼中,透過呼叫所提供物件的方法將列新增至表中。
ConstantColumn 方法增加一列, 其寬度等於精確的點數。
RelativeColumn 方法會新增具有
相對寬度的欄位。此方法接受列應佔據的部分數。部分總數是該表中所有 RelativeColumn
呼叫中所有數字的
總和。大多數情況下,此方法的運作方式與 Row 容器 的 RelativeItem
相同。請閱讀連結
以獲取詳細說明。
無需顯式定義行。行數取決於列和單元格屬性。儲存格數量也會影響行數。表的高度可以大於其所有行高度的總 和。行的儲存格數量可以少於列的數量。且列的單元格數可能少於行數。
PdfDocumentBuilder.Create().Generate("table-basic.pdf", doc =>
{
doc.Pages(page =>
{
page.Size(300, 100);
page.Content()
.Padding(10)
//.MinimalBox()
.Border(b => b.Thickness(1).Color(new PdfRgbColor(250, 123, 5)))
.Table(table =>
{
table.Columns(columns =>
{
columns.ConstantColumn(100);
columns.RelativeColumn(1);
columns.RelativeColumn(3);
});
for (int i = 0; i < 10; i++)
{
table.Cell()
.Border(b => b.Thickness(0.1))
.AlignCenter()
.Text($"Cell {i + 1}");
}
});
});
});
您可以在 table-basic.pdf 中看到程式碼的結果。
在產生的 PDF 中,表格佔據了所有父容器空間。即使沒有足夠的細胞來覆蓋該區域。取消註解 MinimalBox 呼叫以將表高度限制為其行高 度之和。
此程式碼定義了三列並在表中新增了 10 個儲存格。表格將儲存格一個接一個地放置,並在需要時新增一行。一 行只有一個單元格是完全可以的。
如果目前頁面沒有足夠的空間,表格會將儲存格放置在下一頁。您可以透過增加添加的細胞數量來觀察這一點。
細胞
讓我解釋一下 Layout API 為處理表格單元格提供了什麼。
位置
建立表格儲存格有兩種方法:
- 沒有明確的位置訊息
- 至少部分指定位置
我在上一節的程式碼中使用了第一種方式。您呼叫不接受參數的 Cell 方法重載。此方法將一個新單元格新增至列中最後新增 的儲存格之後。如果右側沒有空間,則儲存格將進入下一行。在 RTL 模式下,此方法檢查最後新增的單元格左側 的空間。
如果您知道新儲存格的確切位置,請使用 Cell
方法的其他重載。接受
Action
<TableCell> 類型的委託。在委託程式碼中,透過呼
叫所提供物件的 RowIndex 和
ColumnIndex 方法來指定單元格行和索引。
可以為新單元格僅指定行或列索引。當僅指定行索引時,列索引為 0。反之亦然。
建立儲存格時,您可以按任意順序混合呼叫這兩個 Cell
重載。
我將在本文接下來的程式碼範例中使用以下擴展方法。這將使範例更加簡潔且易於閱讀。
static class LayoutHelpers
{
public static TextSpan BoxWithText(this LayoutContainer cell, string caption)
=> cell.Border(b => b.Thickness(0.5))
.Background(new PdfGrayColor(75))
.ShowOnce()
.MinWidth(50)
.MinHeight(50)
.Padding(10)
.AlignCenter()
.AlignMiddle()
.Text(caption);
}
下面是一個建立包含明確和隱式放置單元格的表格的範例。我使用擴展方法將樣式和文字應用到單元格。單元格 中的數字反映了單元格的建立順序。
PdfDocumentBuilder.Create().Generate("table-cells.pdf", doc =>
{
doc.Pages(page =>
{
page.Size(300, 200);
page.Content()
.Padding(10)
.MinimalBox()
.Border(b => b.Thickness(0.1))
.Table(table =>
{
table.Columns(columns =>
{
for (int i = 0; i < 4; i++)
columns.RelativeColumn();
});
table.Cell().BoxWithText("1");
table.Cell(c => c.RowIndex(1).ColumnIndex(1)).BoxWithText("2");
table.Cell().BoxWithText("3");
table.Cell(c => c.RowIndex(2).ColumnIndex(2)).BoxWithText("4");
table.Cell(c => c.RowIndex(0).ColumnIndex(3)).BoxWithText("5");
});
});
});
您可以在 table-cells.pdf 中看到程式碼的結果。
行和列跨度
單元格可以跨越多行和/或多列。使用接受委託的 Cell 重載 來指定儲存格跨越的行數和列數。
PdfDocumentBuilder.Create().Generate("table-cellspans.pdf", doc =>
{
doc.Pages(page =>
{
page.Size(300, 150);
page.Content()
.Padding(10)
.MinimalBox()
.Border(b => b.Thickness(0.1))
.Table(table =>
{
table.Columns(columns =>
{
for (int i = 0; i < 4; i++)
columns.RelativeColumn();
});
table.Cell(c => c.RowSpan(2).ColumnSpan(2)).BoxWithText("1");
table.Cell(c => c.ColumnSpan(2)).BoxWithText("2");
table.Cell().BoxWithText("3");
table.Cell().BoxWithText("4");
});
});
});
您可以在 table-cellspans.pdf 中看到程式碼的結果。
重疊
細胞之間有可能相互覆蓋。當這種情況發生時,建立的順序決定了哪個單元將位於另一個單元之上。
當儲存格跨越一列或多行時,您可能會得到一些重疊的儲存格。或當您明確和隱式定位儲存格時。
PdfDocumentBuilder.Create().Generate("table-overlapping.pdf", doc =>
{
doc.Pages(page =>
{
page.Size(300, 300);
page.Content()
.Padding(10)
.MinimalBox()
.Border(b => b.Thickness(0.1))
.Table(table =>
{
table.Columns(columns =>
{
for (int i = 0; i < 4; i++)
columns.RelativeColumn();
});
for (int i = 0; i < 16; i++)
table.Cell().BoxWithText($"{i + 1}");
table.Cell(c => c.RowIndex(2).ColumnIndex(1).ColumnSpan(3))
.Background(new PdfRgbColor(250, 123, 5), 50);
});
});
});
您可以在 table-overlapping.pdf 中看到程式碼的結 果。
延伸至底部
如果表格的佈局很複雜,分頁機制可能會導致某些欄位的底部出現空白。如果您想消除空白,請使用 ExtendCellsToBottom 方法。此方法擴展每 列中的最後一個單元格,以便單元格結束於表格的底部。
在以下範例中,第一頁顯示預設行為。第二頁顯示了 ExtendCellsToBottom
呼叫如何影響列。
PdfDocumentBuilder.Create().Generate("table-extendcells.pdf", doc =>
{
for (int take = 0; take < 2; take++)
{
doc.Pages(page =>
{
page.Size(300, 200);
page.Content()
.Padding(10)
.MinimalBox()
.Border(b => b.Thickness(0.1))
.Table(table =>
{
if (take != 0)
table.ExtendCellsToBottom();
table.Columns(columns =>
{
for (int i = 0; i < 4; i++)
columns.RelativeColumn();
});
table.Cell(c => c.RowIndex(0).ColumnIndex(0)).BoxWithText("1");
table.Cell(c => c.RowIndex(2).ColumnIndex(0)).BoxWithText("2");
table.Cell(c => c.RowIndex(1).ColumnIndex(1)).BoxWithText("3");
table.Cell(c => c.RowIndex(2).ColumnIndex(2)).BoxWithText("4");
table.Cell(c => c.RowIndex(1).ColumnIndex(3)).BoxWithText("5");
});
});
}
});
您可以在 table-extendcells.pdf 中看到程式碼的結 果。
頁首和頁尾
表格可以有頁首和頁尾。使用 Header 和 Footer 方法來存取和設定對應的 TableCellContainer。容器提供了 Cell 方法來建立單元格。這些方法的工作原理 與主表內容的方法完全相同。
頁首、頁尾和主表格儲存格使用相同的列定義。但三個細胞集合都是獨立的,互不影響。
當表格無法容納在一頁上時,頁首和頁尾將在表格佔用的每一頁上重複。
我在前面的範例中使用了 BoxWithText
擴充方法。我還在下一個程式碼中使用了 WhiteBoxWithText
擴充方
法。
static class LayoutHelpers
{
public static TextSpan WhiteBoxWithText(
this LayoutContainer cell, string caption, bool center = true)
{
return cell.Border(b => b.Thickness(0.5))
.ShowOnce()
.MinWidth(50)
.MinHeight(50)
.Padding(10)
.Container(l => center ? l.AlignCenter() : l)
.AlignMiddle()
.Text(caption);
}
}
以下範例顯示如何建立帶有標題的表格。我使用一張包含五種基本化學元素的表格。每種元素都有名稱和熔點 (以攝氏度和開氏度為單位)。
var elements = new (string Name, double Celsius, double Kelvin)[] {
("Oxygen", -218.79, 54.36),
("Carbon", double.NaN, double.NaN),
("Hydrogen", -259.16, 13.99),
("Nitrogen", -209.86, 63.23),
("Sulfur", 115.21, 388.36),
};
static string formatDouble(double val)
{
return double.IsNaN(val)
? string.Empty
: val.ToString(CultureInfo.InvariantCulture);
}
PdfDocumentBuilder.Create().Generate("table-header.pdf", doc =>
{
doc.Pages(page =>
{
page.Size(400, 500);
page.Content()
.Padding(10)
.MinimalBox()
.Border(b => b.Thickness(0.1))
.Table(table =>
{
table.Columns(columns =>
{
columns.RelativeColumn();
columns.ConstantColumn(100);
columns.ConstantColumn(100);
});
table.Header(header =>
{
header.Cell(c => c.RowSpan(2)).BoxWithText("Chemical element");
header.Cell(c => c.ColumnSpan(2)).BoxWithText("Melting point");
header.Cell().BoxWithText("Celsius");
header.Cell().BoxWithText("Kelvin");
});
foreach (var (Name, Celsius, Kelvin) in elements)
{
table.Cell().WhiteBoxWithText(Name, false);
table.Cell().WhiteBoxWithText(formatDouble(Celsius));
table.Cell().WhiteBoxWithText(formatDouble(Kelvin));
}
});
});
});
您可以在 table-header.pdf 中看到程式碼的結果。
範例程式碼
請花一些時間檢查 將表格新增至 PDF 文件 範例。它還展示瞭如何建立帶有標題的表,但不使用任何擴展方 法。還有一個 VB.NET 版本。