use oxidize_pdf::advanced_tables::{
AdvancedTableBuilder, AdvancedTableExt, BorderStyle, CellAlignment, CellStyle, HeaderBuilder,
Padding, TableRenderer,
};
use oxidize_pdf::coordinate_system::CoordinateSystem;
use oxidize_pdf::graphics::Color;
use oxidize_pdf::page::{LayoutManager, Page};
use oxidize_pdf::text::Font;
use oxidize_pdf::Document;
use std::error::Error;
fn main() -> Result<(), Box<dyn Error>> {
println!("Creating advanced tables with adjusted widths example PDF...");
let mut doc = Document::new();
let mut page1 = Page::a4(); let mut layout_manager =
LayoutManager::new(&page1, CoordinateSystem::PdfStandard).with_element_spacing(40.0);
create_financial_table(&mut page1, &mut layout_manager)?;
doc.add_page(page1);
let mut page2 = Page::a4();
let mut layout_manager =
LayoutManager::new(&page2, CoordinateSystem::PdfStandard).with_element_spacing(40.0);
create_inventory_table(&mut page2, &mut layout_manager)?;
doc.add_page(page2);
let mut page3 = Page::a4();
let mut layout_manager =
LayoutManager::new(&page3, CoordinateSystem::PdfStandard).with_element_spacing(40.0);
create_schedule_table(&mut page3, &mut layout_manager)?;
doc.add_page(page3);
let output_path = "examples/results/advanced_tables_adjusted_example.pdf";
doc.save(output_path)?;
println!("PDF saved to: {}", output_path);
println!("Portrait dimensions: 595 x 842 points (451 points usable width)");
Ok(())
}
fn create_financial_table(
page: &mut Page,
layout_manager: &mut LayoutManager,
) -> Result<(), Box<dyn Error>> {
println!("Creating financial report table with adjusted widths...");
let header_style = CellStyle::new()
.background_color(Color::rgb(0.2, 0.4, 0.8))
.text_color(Color::white())
.font(Font::HelveticaBold)
.font_size(12.0)
.alignment(CellAlignment::Center)
.padding(Padding::uniform(8.0))
.border(BorderStyle::Solid, 2.0, Color::rgb(0.1, 0.2, 0.4));
let data_style = CellStyle::new()
.font(Font::Helvetica)
.font_size(10.0)
.padding(Padding::uniform(6.0))
.border(BorderStyle::Solid, 1.0, Color::gray(0.5));
let total_style = CellStyle::new()
.font(Font::HelveticaBold)
.font_size(11.0)
.background_color(Color::rgb(0.95, 0.95, 0.95))
.padding(Padding::uniform(6.0))
.border(BorderStyle::Double, 2.0, Color::black());
let table = AdvancedTableBuilder::new()
.title("Quarterly Financial Report - Q3 2024 (Adjusted)")
.columns(vec![
("Department", 110.0), ("Q1 Revenue", 85.0), ("Q2 Revenue", 85.0), ("Q3 Revenue", 85.0), ("Total", 75.0), ]) .header_style(header_style)
.data_style(data_style)
.zebra_stripes(true, Color::rgb(0.98, 0.98, 0.98))
.add_row(vec![
"Sales",
"$1,250,000",
"$1,380,000",
"$1,520,000",
"$4,150,000",
])
.add_row(vec![
"Marketing",
"$850,000",
"$920,000",
"$980,000",
"$2,750,000",
])
.add_row(vec![
"Engineering",
"$2,100,000",
"$2,200,000",
"$2,350,000",
"$6,650,000",
])
.add_row(vec![
"Support",
"$450,000",
"$480,000",
"$510,000",
"$1,440,000",
])
.add_row(vec![
"Operations",
"$780,000",
"$820,000",
"$890,000",
"$2,490,000",
])
.add_row_with_style(
vec![
"TOTAL",
"$5,430,000",
"$5,800,000",
"$6,250,000",
"$17,480,000",
],
total_style,
)
.build()?;
let renderer = TableRenderer::new();
let table_height = renderer.calculate_table_height(&table);
println!("Financial table width: {} points", table.calculate_width());
if let Some(y_position) = layout_manager.add_element(table_height) {
let x_position = layout_manager.center_x(table.calculate_width());
page.add_advanced_table(&table, x_position, y_position)?;
} else {
return Err("Table does not fit on page".into());
}
Ok(())
}
fn create_inventory_table(
page: &mut Page,
layout_manager: &mut LayoutManager,
) -> Result<(), Box<dyn Error>> {
println!("Creating inventory table with adjusted widths...");
let header_builder = HeaderBuilder::new(7)
.add_level(vec![
("Product Information", 3), ("Stock Levels", 2), ("Pricing", 2), ])
.add_level(vec![
("SKU", 1),
("Name", 1),
("Category", 1),
("In Stock", 1),
("Reserved", 1),
("Cost", 1),
("Retail", 1),
]);
let table = AdvancedTableBuilder::new()
.title("Product Inventory Report (Adjusted)")
.columns(vec![
("SKU", 50.0), ("Name", 90.0), ("Category", 70.0), ("In Stock", 50.0), ("Reserved", 50.0), ("Cost", 65.0), ("Retail", 65.0), ]) .complex_header(header_builder)
.add_row(vec![
"PRD-001",
"Laptop Pro",
"Electronics",
"45",
"12",
"$899",
"$1,299",
])
.add_row(vec![
"PRD-002",
"Wireless Mouse",
"Accessories",
"128",
"15",
"$15",
"$39",
])
.add_row(vec![
"PRD-003",
"USB-C Hub",
"Accessories",
"87",
"8",
"$25",
"$59",
])
.add_row(vec![
"PRD-004",
"Monitor 27\"",
"Electronics",
"23",
"5",
"$180",
"$399",
])
.add_row(vec![
"PRD-005",
"Keyboard Mech",
"Accessories",
"67",
"10",
"$45",
"$129",
])
.build()?;
let renderer = TableRenderer::new();
let table_height = renderer.calculate_table_height(&table);
println!("Inventory table width: {} points", table.calculate_width());
if let Some(y_position) = layout_manager.add_element(table_height) {
let x_position = layout_manager.center_x(table.calculate_width());
page.add_advanced_table(&table, x_position, y_position)?;
} else {
return Err("Table does not fit on page".into());
}
Ok(())
}
fn create_schedule_table(
page: &mut Page,
layout_manager: &mut LayoutManager,
) -> Result<(), Box<dyn Error>> {
println!("Creating schedule table with adjusted widths...");
let time_style = CellStyle::new()
.background_color(Color::rgb(0.3, 0.3, 0.5))
.text_color(Color::white())
.font(Font::HelveticaBold)
.font_size(10.0)
.alignment(CellAlignment::Center);
let event_style = CellStyle::new()
.font(Font::Helvetica)
.font_size(10.0)
.padding(Padding::new(4.0, 8.0, 4.0, 8.0));
let break_style = CellStyle::new()
.background_color(Color::rgb(0.9, 0.95, 0.9))
.font(Font::HelveticaOblique)
.font_size(10.0)
.alignment(CellAlignment::Center);
let table = AdvancedTableBuilder::new()
.title("Conference Schedule - Day 1 (Adjusted)")
.columns(vec![
("Time", 60.0), ("Track A", 127.0), ("Track B", 127.0), ("Track C", 126.0), ]) .add_row_with_mixed_styles(vec![
(time_style.clone(), "9:00 AM"),
(event_style.clone(), "Keynote: Future of Technology"),
(event_style.clone(), "Workshop: Cloud Architecture"),
(event_style.clone(), "Tutorial: Machine Learning"),
])
.add_row_with_mixed_styles(vec![
(time_style.clone(), "10:30 AM"),
(break_style.clone(), "Coffee Break"),
(break_style.clone(), "Coffee Break"),
(break_style.clone(), "Coffee Break"),
])
.add_row_with_mixed_styles(vec![
(time_style.clone(), "11:00 AM"),
(event_style.clone(), "Panel: Industry Trends"),
(event_style.clone(), "Demo: DevOps Tools"),
(event_style.clone(), "Talk: Security Best Practices"),
])
.add_row_with_mixed_styles(vec![
(time_style.clone(), "12:30 PM"),
(break_style.clone(), "Lunch"),
(break_style.clone(), "Lunch"),
(break_style, "Lunch"),
])
.add_row_with_mixed_styles(vec![
(time_style, "2:00 PM"),
(event_style.clone(), "Workshop: Microservices"),
(event_style.clone(), "Case Study: Scaling"),
(event_style, "Hands-on: Kubernetes"),
])
.build()?;
let renderer = TableRenderer::new();
let table_height = renderer.calculate_table_height(&table);
println!("Schedule table width: {} points", table.calculate_width());
if let Some(y_position) = layout_manager.add_element(table_height) {
let x_position = layout_manager.center_x(table.calculate_width());
page.add_advanced_table(&table, x_position, y_position)?;
} else {
return Err("Table does not fit on page".into());
}
Ok(())
}