Thanks to visit codestin.com
Credit goes to pdf.oxide.fyi

Skip to content

Renderizado de Tablas

La API Table ofrece un sistema completo de creación de tablas con soporte para encabezados, estilizado de celdas, bordes, fondos, alineación de columnas, relleno y franjas en filas alternadas.

Cobertura de bindings. La API builder de bajo nivel Table / TableStyle / TableCell es exclusiva de Rust. En Python, Node, WASM, Go y C#, las tablas se generan mediante: (a) una cadena Markdown o HTML con un bloque GFM / <table> pasada a Pdf.from_markdown / Pdf.from_html / Pdf.from_html_css (pipeline puro Rust HTML+CSS v0.3.37+ con anchos de columna y bordes), o (b) encadenando text, line y rect en FluentPageBuilder para pintar celdas directamente.

Ejemplo Rápido

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

El renderizado de tablas está disponible a través de la API Rust. Desde Python, usa tablas Markdown con Pdf.from_markdown():

from pdf_oxide import Pdf

markdown = """
# Employee Directory

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

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

WASM

Desde JavaScript, usa tablas Markdown o HTML con WasmPdf.fromMarkdown() o WasmPdf.fromHtml():

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

const markdown = `# Employee Directory

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

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

Java

Las tablas se renderizan a través de la API Rust. Desde Java, pasa una tabla Markdown a Pdf.fromMarkdown():

import fyi.oxide.pdf.Pdf;
import java.nio.file.Path;

String markdown = """
        # Employee Directory

        | Name  | Age | City     |
        |-------|-----|----------|
        | Alice | 30  | New York |
        | Bob   | 25  | London   |
        | Carol | 35  | Tokyo    |
        """;

try (Pdf pdf = Pdf.fromMarkdown(markdown)) {
    pdf.saveTo(Path.of("directory.pdf"));
}

PHP

<?php
use OxideFyi\Pdf\Pdf;

$markdown = <<<MD
# Employee Directory

| Name  | Age | City     |
|-------|-----|----------|
| Alice | 30  | New York |
| Bob   | 25  | London   |
| Carol | 35  | Tokyo    |
MD;

$pdf = Pdf::fromMarkdown($markdown);
file_put_contents('directory.pdf', $pdf->save());

Ruby

require "pdf_oxide"

markdown = <<~MD
  # Employee Directory

  | Name  | Age | City     |
  |-------|-----|----------|
  | Alice | 30  | New York |
  | Bob   | 25  | London   |
  | Carol | 35  | Tokyo    |
MD

PdfOxide::Pdf.from_markdown(markdown) { |pdf| pdf.save("directory.pdf") }

C++

#include <pdf_oxide/pdf_oxide.hpp>

const char* markdown = R"(# Employee Directory

| Name  | Age | City     |
|-------|-----|----------|
| Alice | 30  | New York |
| Bob   | 25  | London   |
| Carol | 35  | Tokyo    |
)";

auto pdf = pdf_oxide::Pdf::from_markdown(markdown);
pdf.save("directory.pdf");

Swift

import PdfOxide

let markdown = """
# Employee Directory

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

let pdf = try Pdf.fromMarkdown(markdown)
try pdf.save("directory.pdf")

Kotlin

import fyi.oxide.pdf.Pdf

val markdown = """
    # Employee Directory

    | Name  | Age | City     |
    |-------|-----|----------|
    | Alice | 30  | New York |
    | Bob   | 25  | London   |
    | Carol | 35  | Tokyo    |
""".trimIndent()

Pdf.fromMarkdown(markdown).use { it.saveTo(java.nio.file.Path.of("directory.pdf")) }

Dart

import 'package:pdf_oxide/pdf_oxide.dart';

final markdown = '''
# Employee Directory

| Name  | Age | City     |
|-------|-----|----------|
| Alice | 30  | New York |
| Bob   | 25  | London   |
| Carol | 35  | Tokyo    |
''';

final pdf = Pdf.fromMarkdown(markdown);
pdf.save('directory.pdf');

R

library(pdfoxide)

markdown <- "# Employee Directory

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

pdf <- pdf_from_markdown(markdown)
pdf_save(pdf, "directory.pdf")

Julia

using PdfOxide

markdown = """
# Employee Directory

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

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

Zig

const pdf_oxide = @import("pdf_oxide");

const markdown =
    \\# Employee Directory
    \\
    \\| Name  | Age | City     |
    \\|-------|-----|----------|
    \\| Alice | 30  | New York |
    \\| Bob   | 25  | London   |
    \\| Carol | 35  | Tokyo    |
;

var pdf = try pdf_oxide.Pdf.fromMarkdown(markdown);
try pdf.save("directory.pdf");

Scala

import fyi.oxide.pdf.Pdf
import scala.util.Using

val markdown =
  """# Employee Directory
    |
    || Name  | Age | City     |
    ||-------|-----|----------|
    || Alice | 30  | New York |
    || Bob   | 25  | London   |
    || Carol | 35  | Tokyo    |
    |""".stripMargin

Using.resource(Pdf.fromMarkdown(markdown))(_.saveTo(java.nio.file.Path.of("directory.pdf")))

Clojure

(require '[pdf-oxide.core :as pdf])

(def markdown "# Employee Directory

| Name  | Age | City     |
|-------|-----|----------|
| Alice | 30  | New York |
| Bob   | 25  | London   |
| Carol | 35  | Tokyo    |
")

(with-open [p (pdf/from-markdown markdown)]
  (pdf/save p "directory.pdf"))

Objective-C

#import <PdfOxide/PdfOxide.h>

NSError *err = nil;
NSString *markdown = @"# Employee Directory\n\n"
                      "| Name  | Age | City     |\n"
                      "|-------|-----|----------|\n"
                      "| Alice | 30  | New York |\n"
                      "| Bob   | 25  | London   |\n"
                      "| Carol | 35  | Tokyo    |\n";

POXPdf *pdf = [POXPdf fromMarkdown:markdown error:&err];
[pdf saveToPath:@"directory.pdf" error:&err];

Elixir

markdown = """
# Employee Directory

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

{:ok, pdf} = PdfOxide.from_markdown(markdown)
PdfOxide.save(pdf, "directory.pdf")

Referencia Completa de la API

Table – Contenedor de Tabla

Creación

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")]));

Métodos de Configuración

Método Descripción
.with_header_row() Marcar la primera fila como encabezado
.with_style(style) Establecer el estilo de la tabla
.with_width(width) Establecer el ancho total de la tabla en puntos
.with_column_widths(widths) Establecer especificaciones de ancho de columna
.with_column_aligns(aligns) Establecer alineaciones predeterminadas de columna

Propiedades

Método Retorno Descripción
.num_columns() usize Número de columnas
.num_rows() usize Número de filas
.is_empty() bool Si la tabla no tiene filas

TableCell – Contenido de Celda

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 – Contenedor de Fila

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 – Configuración de Estilo

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 – Apariencia de Bordes

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 – Configuración de los Cuatro Lados

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 – Configuración de Relleno

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 – Especificación de Ancho de Columna

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 – Alineación

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;

Ejemplos Avanzados

Tabla de Informe Financiero

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("Category"),
        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,
]);

Tabla con Celdas Fusionadas

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("Category 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);

Páginas Relacionadas