Skip to content

表格渲染

Table API 提供全面的表格创建系统,支持表头、单元格样式、边框、背景、列对齐、内边距和行间条纹。

绑定覆盖。 底层的 Table / TableStyle / TableCell 构建器 API 仅限 Rust。在 Python、Node、WASM、Go 和 C# 中,表格可以通过以下两种方式生成:(a) 将含有 GFM 或 <table> 块的 Markdown 或 HTML 字符串传给 Pdf.from_markdown / Pdf.from_html / Pdf.from_html_css(v0.3.37+ 的纯 Rust HTML+CSS 流水线支持列宽和边框);或 (b) 通过 FluentPageBuilder 链式调用 textlinerect,直接绘制单元格。

快速示例

Rust

use pdf_oxide::writer::{Table, TableCell, TableStyle};

let table = Table::new(vec![
    vec![TableCell::header("Name"), TableCell::header("Age"), TableCell::header("City")],
    vec![TableCell::text("Alice"), TableCell::number("30"), TableCell::text("New York")],
    vec![TableCell::text("Bob"), TableCell::number("25"), TableCell::text("London")],
    vec![TableCell::text("Carol"), TableCell::number("35"), TableCell::text("Tokyo")],
])
.with_header_row()
.with_width(468.0);  // Page width minus margins

Python

表格渲染通过 Rust API 可用。在 Python 中,使用 Pdf.from_markdown() 的 Markdown 表格:

from pdf_oxide import Pdf

markdown = """
# Employee Directory

| 名称  | Age | City     |
|-------|-----|----------|
| Alice | 30  | New York |
| Bob   | 25  | London   |
| Carol | 35  | Tokyo    |
"""

pdf = Pdf.from_markdown(markdown)
pdf.save("directory.pdf")

WASM

在 JavaScript 中,使用 WasmPdf.fromMarkdown()WasmPdf.fromHtml() 的 Markdown 或 HTML 表格:

import { WasmPdf } from "pdf-oxide-wasm";
import { writeFileSync } from "fs";

const markdown = `# Employee Directory

| 名称  | Age | City     |
|-------|-----|----------|
| Alice | 30  | New York |
| Bob   | 25  | London   |
| Carol | 35  | Tokyo    |
`;

const pdf = WasmPdf.fromMarkdown(markdown);
writeFileSync("directory.pdf", pdf.toBytes());

完整 API 参考

Table – Table Container

构造

use pdf_oxide::writer::{Table, TableCell, TableRow};

// From Vec<Vec<TableCell>>
let table = Table::new(vec![
    vec![TableCell::text("A"), TableCell::text("B")],
    vec![TableCell::text("1"), TableCell::text("2")],
]);

// From TableRow objects
let table = Table::from_rows(vec![
    TableRow::header(vec![TableCell::header("A"), TableCell::header("B")]),
    TableRow::new(vec![TableCell::text("1"), TableCell::text("2")]),
]);

// Empty table with rows added later
let mut table = Table::empty();
table.add_row(TableRow::new(vec![TableCell::text("1"), TableCell::text("2")]));

配置方法

Method 描述
.with_header_row() 将第一行标记为表头
.with_style(style) 设置表格样式
.with_width(width) 设置表格总宽度(磅)
.with_column_widths(widths) 设置列宽规格
.with_column_aligns(aligns) 设置默认列对齐

属性

Method Returns 描述
.num_columns() usize Number of columns
.num_rows() usize Number of rows
.is_empty() bool 表格是否没有行

TableCell – Cell Content

use pdf_oxide::writer::{TableCell, CellAlign, CellVAlign, CellPadding, Borders};

// Basic cells
let cell = TableCell::text("Hello");
let empty = TableCell::empty();

// Semantic cell types
let header = TableCell::header("Column Name");  // Centered + bold
let number = TableCell::number("$1,234.56");    // Right-aligned

// Full configuration
let cell = TableCell::text("Important")
    .colspan(2)                             // Span 2 columns
    .rowspan(3)                             // Span 3 rows
    .align(CellAlign::Center)               // Horizontal alignment
    .valign(CellVAlign::Middle)             // Vertical alignment
    .padding(CellPadding::uniform(8.0))     // Cell padding
    .borders(Borders::all(TableBorderStyle::thick()))
    .background(0.95, 0.95, 1.0)           // Light blue background
    .font("Helvetica-Bold", 14.0)          // Custom font
    .bold()                                 // Bold text
    .italic();                              // Italic text

TableRow – Row Container

use pdf_oxide::writer::{TableRow, TableCell};

// Data row
let row = TableRow::new(vec![
    TableCell::text("Alice"),
    TableCell::number("30"),
]);

// Header row
let header = TableRow::header(vec![
    TableCell::header("Name"),
    TableCell::header("Age"),
]);

// Configured row
let row = TableRow::new(vec![TableCell::text("Total"), TableCell::number("$500")])
    .min_height(30.0)
    .background(0.9, 0.9, 0.9)  // Gray background
    .as_header();

TableStyle – Style Configuration

use pdf_oxide::writer::{
    TableStyle, TableBorderStyle, Borders, CellPadding,
};

// Default style (thin borders, gray header, Helvetica 10pt)
let style = TableStyle::new();

// Custom style
let style = TableStyle::new()
    .cell_padding(CellPadding::symmetric(8.0, 6.0))
    .cell_borders(Borders::all(TableBorderStyle::medium()))
    .outer_border(TableBorderStyle::thick())
    .font("Times-Roman", 11.0)
    .header_background(0.2, 0.4, 0.8)    // Blue header
    .striped(0.95, 0.95, 0.95);           // Light gray stripes

// Preset styles
let minimal = TableStyle::minimal();   // No borders
let bordered = TableStyle::bordered(); // Thick outer, medium inner

TableBorderStyle – Border Appearance

use pdf_oxide::writer::TableBorderStyle;

let border = TableBorderStyle::new(0.5);              // Custom width
let border = TableBorderStyle::thin();                 // 0.25pt
let border = TableBorderStyle::medium();               // 0.5pt
let border = TableBorderStyle::thick();                // 1.0pt
let border = TableBorderStyle::none();                 // No border
let border = TableBorderStyle::medium()
    .with_color(0.0, 0.0, 0.8);                       // Blue border

Borders – Four-Side Border Configuration

use pdf_oxide::writer::{Borders, TableBorderStyle};

let borders = Borders::none();
let borders = Borders::all(TableBorderStyle::thin());
let borders = Borders::horizontal(TableBorderStyle::medium());  // Top + bottom
let borders = Borders::vertical(TableBorderStyle::medium());    // Left + right

// Individual sides
let borders = Borders::none()
    .with_top(TableBorderStyle::thick())
    .with_bottom(TableBorderStyle::thick())
    .with_left(TableBorderStyle::thin())
    .with_right(TableBorderStyle::thin());

CellPadding – Padding Configuration

use pdf_oxide::writer::CellPadding;

let padding = CellPadding::uniform(8.0);                // All sides 8pt
let padding = CellPadding::symmetric(10.0, 6.0);        // H=10, V=6
let padding = CellPadding::none();                       // No padding
let padding = CellPadding {
    top: 4.0, right: 8.0, bottom: 4.0, left: 8.0,
};

ColumnWidth – Column Width Specification

use pdf_oxide::writer::ColumnWidth;

let widths = vec![
    ColumnWidth::Auto,           // Automatic sizing
    ColumnWidth::Fixed(150.0),   // Fixed 150pt
    ColumnWidth::Percent(30.0),  // 30% of table width
    ColumnWidth::Weight(2.0),    // Proportional flex weight
];

CellAlign / CellVAlign – Alignment

use pdf_oxide::writer::{CellAlign, CellVAlign};

// Horizontal
let align = CellAlign::Left;
let align = CellAlign::Center;
let align = CellAlign::Right;

// Vertical
let valign = CellVAlign::Top;
let valign = CellVAlign::Middle;
let valign = CellVAlign::Bottom;

高级示例

财务报告表格

use pdf_oxide::writer::{
    Table, TableCell, TableRow, TableStyle, TableBorderStyle,
    Borders, CellPadding, CellAlign, ColumnWidth,
};

let style = TableStyle::new()
    .cell_padding(CellPadding::symmetric(10.0, 6.0))
    .cell_borders(Borders::horizontal(TableBorderStyle::thin()))
    .outer_border(TableBorderStyle::medium())
    .font("Helvetica", 10.0)
    .header_background(0.15, 0.3, 0.55)
    .striped(0.96, 0.96, 0.96);

let table = Table::from_rows(vec![
    TableRow::header(vec![
        TableCell::header("类别"),
        TableCell::header("Q1"),
        TableCell::header("Q2"),
        TableCell::header("Q3"),
        TableCell::header("Q4"),
        TableCell::header("Total"),
    ]),
    TableRow::new(vec![
        TableCell::text("Revenue"),
        TableCell::number("$32M"),
        TableCell::number("$35M"),
        TableCell::number("$38M"),
        TableCell::number("$42M"),
        TableCell::number("$147M").bold(),
    ]),
    TableRow::new(vec![
        TableCell::text("Expenses"),
        TableCell::number("$24M"),
        TableCell::number("$25M"),
        TableCell::number("$27M"),
        TableCell::number("$29M"),
        TableCell::number("$105M").bold(),
    ]),
    TableRow::new(vec![
        TableCell::text("Net Income").bold(),
        TableCell::number("$8M").bold(),
        TableCell::number("$10M").bold(),
        TableCell::number("$11M").bold(),
        TableCell::number("$13M").bold(),
        TableCell::number("$42M").bold(),
    ]).background(0.9, 0.95, 0.9),
])
.with_style(style)
.with_width(468.0)
.with_column_widths(vec![
    ColumnWidth::Fixed(100.0),
    ColumnWidth::Weight(1.0),
    ColumnWidth::Weight(1.0),
    ColumnWidth::Weight(1.0),
    ColumnWidth::Weight(1.0),
    ColumnWidth::Fixed(80.0),
])
.with_column_aligns(vec![
    CellAlign::Left,
    CellAlign::Right,
    CellAlign::Right,
    CellAlign::Right,
    CellAlign::Right,
    CellAlign::Right,
]);

带跨越单元格的表格

use pdf_oxide::writer::{Table, TableCell, TableRow};

let table = Table::from_rows(vec![
    TableRow::header(vec![
        TableCell::header("Product").colspan(2),
        TableCell::header("Sales"),
    ]),
    TableRow::new(vec![
        TableCell::text("类别 A").rowspan(2),
        TableCell::text("Widget X"),
        TableCell::number("1,234"),
    ]),
    TableRow::new(vec![
        // First cell omitted due to rowspan above
        TableCell::text("Widget Y"),
        TableCell::number("567"),
    ]),
])
.with_header_row()
.with_width(400.0);

相关页面