ppt-rs API Guide
September 7, 2026 · View on GitHub
Complete guide to the simplified ppt-rs API for creating PowerPoint presentations.
Table of Contents
- Quick Start
- Presentation Builder
- HTML to PowerPoint
- Shape Helpers
- Color API
- Table API
- Charts
- Images
- Themes & Templates
- Export & Compression
- Editing Existing Decks
- Package Validation
- Extension Methods
- Complete Examples
- API Comparison
Quick Start
use ppt_rs::prelude::*;
fn main() -> Result<()> {
let slides = vec![
SlideContent::new("My First Slide")
.add_shape(
rect(1.0, 2.0, 3.0, 1.5)
.fill(blue().to_color())
.text("Hello World")
),
];
let pptx = create_pptx_with_content("My Presentation", slides)?;
std::fs::write("output.pptx", pptx)?;
Ok(())
}
Presentation Builder
High-level Presentation API for create → save → export workflows:
use ppt_rs::prelude::*;
use ppt_rs::{Presentation, PresentationTheme};
fn main() -> Result<()> {
Presentation::with_title("Q1 Review")
.with_theme(PresentationTheme::corporate())
.add_slide(
SlideContent::new("Highlights")
.add_bullet("Revenue up 15%")
.add_bullet("NPS at 72")
)
.add_slide(
SlideContent::new("Metrics")
.layout(SlideLayout::TitleOnly)
.add_shape(
rect(1.0, 2.0, 3.0, 1.5)
.fill(hex("1565C0"))
.text("KPI")
)
)
.save("q1.pptx")?;
Ok(())
}
Useful methods:
| Method | Purpose |
|---|---|
Presentation::with_title / add_slide | Build deck |
.with_theme(PresentationTheme::…) | Embed brand theme |
.save(path) | Write PPTX |
.from_path(path) | Open existing PPTX |
.save_as_markdown / .save_as_html | Round-trip export |
.compress(path, &options) | Shrink file size |
HTML to PowerPoint
Convert HTML content directly into PowerPoint slides using the html2ppt API. No external dependencies required.
Quick Parse
The simplest way: pass an HTML string to parse_html():
use ppt_rs::generator::create_pptx_with_content;
use ppt_rs::import::parse_html;
let html = r#"
<h1>My Presentation</h1>
<p>This is the first slide.</p>
<ul>
<li>Bullet 1</li>
<li>Bullet 2</li>
</ul>
<h1>Data Slide</h1>
<table>
<tr><th>Name</th><th>Value</th></tr>
<tr><td>Alpha</td><td>100</td></tr>
<tr><td>Beta</td><td>200</td></tr>
</table>
<blockquote>Speaker notes for this slide</blockquote>
"#;
let slides = parse_html(html)?;
let pptx = create_pptx_with_content("From HTML", slides)?;
std::fs::write("output.pptx", pptx)?;
Parse with Options
Control parsing behavior with HtmlParseOptions:
use ppt_rs::import::{Html2Ppt, HtmlParseOptions};
let options = HtmlParseOptions::new()
.max_slides(20) // limit to 20 slides
.max_bullets(8) // max 8 bullets per slide
.include_code(true) // include code blocks
.include_tables(true) // include tables
.include_images(false); // skip image placeholders
let slides = Html2Ppt::with_options(options).parse(html)?;
Parse from File
use ppt_rs::import::Html2Ppt;
let slides = Html2Ppt::new().parse_file("presentation.html")?;
HTML Element Reference
| HTML Element | Creates |
|---|---|
<h1> | New slide with title |
<h2>–<h6> | Bold section headers |
<p> | Bullet points |
<ul> / <ol> | List items |
<table> | Table with styled header |
<pre> / <code> | Code blocks |
<img> | Image placeholder |
<blockquote> | Speaker notes |
<hr> | Slide break |
CLI Usage
# Convert HTML file to PPTX
pptcli html2ppt slides.html presentation.pptx
# With custom title
pptcli html2ppt slides.html --title "My Talk"
# Control content extraction
pptcli html2ppt slides.html --no-tables --no-code --max-slides 30
Shape Helpers
Create shapes with simple, readable functions. All dimensions are in inches.
Rectangle
rect(x, y, width, height)
.fill(color)
.stroke(color, width)
.text("Text")
Example:
rect(1.0, 2.0, 3.0, 1.5)
.fill(blue().to_color())
.stroke(black().to_color(), 2.0)
.text("Rectangle")
Circle
circle(x, y, diameter)
Example:
circle(2.0, 2.0, 1.5)
.fill(red().to_color())
.text("Circle")
Ellipse
ellipse(x, y, width, height)
Example:
ellipse(3.0, 2.0, 2.5, 1.5)
.fill(green().to_color())
Rounded Rectangle
rounded_rect(x, y, width, height)
Example:
rounded_rect(1.0, 3.0, 2.0, 1.0)
.fill(orange().to_color())
.text("Rounded")
Triangle
triangle(x, y, width, height)
Diamond
diamond(x, y, width, height)
Arrow Shapes
shapes::arrow_right(x, y, width, height)
shapes::arrow_left(x, y, width, height)
shapes::arrow_up(x, y, width, height)
shapes::arrow_down(x, y, width, height)
Color API
Color Aliases
Use simple color names instead of hex codes:
// Basic colors
red() green() blue() yellow()
cyan() magenta() white() black()
gray() orange() purple() pink()
brown() navy() teal() olive()
// Material Design colors
material_red() material_blue() material_green()
material_orange() material_purple() material_pink()
material_teal() material_amber() material_brown()
// Corporate colors
corporate_blue() corporate_green() corporate_red()
Example:
rect(1.0, 2.0, 2.0, 1.0)
.fill(material_blue().to_color())
.text("Material Blue")
Color Adjustments
Lighter
Make a color lighter by a percentage (0.0 - 1.0):
let light_blue = blue().lighter(0.3); // 30% lighter
Darker
Make a color darker by a percentage (0.0 - 1.0):
let dark_blue = blue().darker(0.5); // 50% darker
Opacity
Set the opacity (0.0 = transparent, 1.0 = opaque):
let semi_transparent = red().opacity(0.5); // 50% opacity
Transparency
Set transparency as a percentage (0 = opaque, 100 = transparent):
let transparent = blue().transparent(25); // 25% transparent
Color Operations
Mix Colors
Blend two colors together:
let purple = red().mix(&blue(), 0.5); // 50/50 mix
let pink = red().mix(&white(), 0.3); // 30% white, 70% red
Grayscale
Convert to grayscale:
let gray_version = blue().grayscale();
Invert
Invert the color:
let inverted = blue().invert();
RGB Colors
Create colors from RGB values:
ColorValue::rgb(255, 128, 64)
Hex Colors
Create colors from hex strings:
ColorValue::from_hex("#FF8040")
ColorValue::from_hex("FF8040") // # is optional
Complete Color Example
SlideContent::new("Color Showcase")
.add_shape(
rect(1.0, 1.5, 1.5, 0.8)
.fill(blue().to_color())
.text("Base Blue")
)
.add_shape(
rect(3.0, 1.5, 1.5, 0.8)
.fill(blue().lighter(0.3).to_color())
.text("Lighter")
)
.add_shape(
rect(5.0, 1.5, 1.5, 0.8)
.fill(blue().darker(0.3).to_color())
.text("Darker")
)
.add_shape(
rect(2.0, 2.8, 1.5, 0.8)
.fill(red().mix(&blue(), 0.5).to_color())
.text("Purple Mix")
)
Table API
Simple Table
Create a table with equal column widths:
simple_table(rows, cols)
.position(inches(x), inches(y))
.build()
Example:
let table = simple_table(4, 3)
.position(inches(1.0), inches(1.5))
.build();
Table with Custom Widths
Specify column widths in inches:
table_with_widths(&[2.0, 3.0, 2.5])
.position(inches(1.0), inches(1.5))
.build()
Table from Data
Create a table from a 2D array:
let data = vec![
vec!["Name", "Age", "City"],
vec!["Alice", "30", "NYC"],
vec!["Bob", "25", "LA"],
];
let table = table_from_data(&data, None)
.position(inches(1.0), inches(1.5))
.build();
With custom column widths:
let table = table_from_data(&data, Some(vec![2.5, 1.5, 2.0]))
.position(inches(1.0), inches(1.5))
.build();
Table with Header
Create a table with an auto-styled header row:
table_with_header(&["Name", "Role", "Status"], 3)
.position(inches(1.0), inches(1.5))
.build()
QuickTable Builder
The most flexible way to create tables:
QuickTable::new(4)
.header(&["Name", "Role", "Department", "Status"])
.row(&["Alice", "Engineer", "Product", "Active"])
.row(&["Bob", "Designer", "UX", "Active"])
.at(1.0, 1.5)
.build()
With custom column widths:
QuickTable::with_widths(&[2.0, 1.5, 1.5, 2.0])
.header(&["Task", "Priority", "Status", "Owner"])
.row(&["API Work", "High", "Done", "Team A"])
.at(0.8, 1.5)
.build()
Styled Table Cells
Create custom styled cells:
QuickTable::new(3)
.styled_row(vec![
header_cell("Name"),
header_cell("Status"),
header_cell("Priority"),
])
.styled_row(vec![
cell("Task 1"),
highlight_cell("Done", &material_green().to_hex()),
highlight_cell("High", &material_red().to_hex()),
])
.at(1.0, 1.5)
.build()
Cell Helpers
cell("text") // Basic cell
header_cell("Header") // Auto-styled header
highlight_cell("Text", "#FF0000") // Highlighted cell
Charts
Charts embed an Excel workbook so values stay editable in PowerPoint.
use ppt_rs::generator::{ChartSeries, SlideContent, create_pptx_with_content};
use ppt_rs::helpers::bar_chart;
let chart = bar_chart("Quarterly Revenue")
.categories(vec!["Q1", "Q2", "Q3", "Q4"])
.add_series(ChartSeries::new("2025", vec![120.0, 145.0, 160.0, 190.0]))
.add_series(ChartSeries::new("2024", vec![100.0, 110.0, 130.0, 150.0]))
.build();
let slides = vec![
SlideContent::new("Revenue")
.layout(SlideLayout::TitleOnly)
.add_chart(chart),
];
let pptx = create_pptx_with_content("Charts", slides)?;
Helpers: bar_chart, line_chart, pie_chart, area_chart (ppt_rs::helpers).
Or use ChartBuilder::new(title, ChartType::…) for the full type set.
Images
use ppt_rs::prelude::*;
use ppt_rs::generator::ImageBuilder;
// From bytes / file, with effects and accessibility alt text
let photo = std::fs::read("photo.jpg")?;
let img = ImageBuilder::auto(photo)
.at(inches(1.0), inches(1.5))
.size(inches(4.0), inches(3.0))
.shadow()
.build()
.with_alt_text("Team photo at kickoff");
let slides = vec![SlideContent::new("Gallery").add_image(img)];
Prelude shortcuts: image(bytes), image_file(path).
Effects on ImageBuilder: .shadow(), .reflection(), .glow(), .soft_edges(), .blur(), .crop(…).
Themes & Templates
Embedded themes
use ppt_rs::{Presentation, PresentationTheme};
Presentation::with_title("Brand Deck")
.with_theme(PresentationTheme::modern()) // corporate, vibrant, dark, nature, tech, carbon
.add_slide(SlideContent::new("Hello"))
.save("branded.pptx")?;
Clone from an existing deck
use ppt_rs::generator::{create_pptx_with_template, SlideContent};
use ppt_rs::SlideLayout;
let slides = vec![
SlideContent::new("Cover").with_layout(SlideLayout::CenteredTitle),
SlideContent::new("Agenda").with_layout(SlideLayout::TitleAndContent),
];
let pptx = create_pptx_with_template("Review", &slides, "brand.pptx", None)?;
CLI: pptcli create out.pptx --template brand.pptx --title "Review"
Layouts (7 on slide master 1): CenteredTitle, TitleAndContent, TitleOnly, TwoColumn, Blank, and related variants via SlideLayout.
Export & Compression
use ppt_rs::{Presentation, CompressionOptions, MarkdownOptions};
let pres = Presentation::from_path("deck.pptx")?;
// Markdown / HTML
pres.save_as_markdown("deck.md")?;
pres.save_as_markdown_with_options("deck.md", &MarkdownOptions::default())?;
pres.save_as_html("deck.html")?;
// Compress (web preset targets ~5MB)
pres.compress("deck-web.pptx", &CompressionOptions::web())?;
Image export (PNG/JPEG) and PDF require LibreOffice (soffice).
Editing Existing Decks
use ppt_rs::oxml::PresentationEditor;
use ppt_rs::generator::SlideContent;
let mut editor = PresentationEditor::open("deck.pptx")?;
editor.duplicate_slide(0)?; // copy first slide after itself
editor.insert_slide(1, SlideContent::new("Inserted"))?;
editor.reorder_slide(2, 0)?; // move slide to front
editor.save("deck-edited.pptx")?;
Package Validation
Structured checks so decks open in PowerPoint without a repair prompt:
use ppt_rs::core::{validate_package_bytes, ValidationSeverity};
let bytes = std::fs::read("deck.pptx")?;
let report = validate_package_bytes(&bytes);
if !report.is_valid() {
for issue in &report.issues {
if issue.severity == ValidationSeverity::Error {
eprintln!("{:?}: {}", issue.category, issue.message);
}
}
}
CLI: pptcli validate deck.pptx
JSON: pptcli validate deck.pptx --json
Debug builds also debug_assert! every generated package.
Extension Methods
Shorter, more intuitive method names for common operations.
Shape Extensions
Instead of .with_fill(), .with_line(), .with_text():
// Old API
shape.with_fill(ShapeFill::new("4F81BD"))
.with_line(ShapeLine::new("000000", 25400))
.with_text("Hello")
// New API
shape.fill(hex("4F81BD"))
.stroke(hex("000000"), 2.0)
.text("Hello")
Available Extensions
.fill(color)- Set fill color.stroke(color, width)- Set border/stroke.text(text)- Set text content
Complete Examples
Example 1: Colorful Dashboard
use ppt_rs::prelude::*;
fn main() -> Result<()> {
let slides = vec![
SlideContent::new("Q1 Dashboard")
.add_shape(
rect(0.5, 1.5, 2.0, 1.2)
.fill(material_blue().to_color())
.text("Revenue\n\$2.1M")
)
.add_shape(
rect(3.0, 1.5, 2.0, 1.2)
.fill(material_green().to_color())
.text("Customers\n12,450")
)
.add_shape(
rect(5.5, 1.5, 2.0, 1.2)
.fill(material_orange().to_color())
.text("NPS Score\n72")
),
];
let pptx = create_pptx_with_content("Dashboard", slides)?;
std::fs::write("dashboard.pptx", pptx)?;
Ok(())
}
Example 2: Employee Directory Table
use ppt_rs::prelude::*;
fn main() -> Result<()> {
let slides = vec![
SlideContent::new("Employee Directory")
.table(
QuickTable::new(4)
.header(&["Name", "Role", "Department", "Status"])
.row(&["Alice Johnson", "Engineer", "Product", "Active"])
.row(&["Bob Smith", "Designer", "UX", "Active"])
.row(&["Carol White", "Manager", "Operations", "On Leave"])
.row(&["David Brown", "Analyst", "Finance", "Active"])
.at(0.5, 1.5)
.build()
),
];
let pptx = create_pptx_with_content("Directory", slides)?;
std::fs::write("directory.pptx", pptx)?;
Ok(())
}
Example 3: Color Adjustments
use ppt_rs::prelude::*;
fn main() -> Result<()> {
let base_color = material_blue();
let slides = vec![
SlideContent::new("Color Variations")
.add_shape(
rect(1.0, 1.5, 1.5, 0.8)
.fill(base_color.darker(0.4).to_color())
.text("Darker 40%")
)
.add_shape(
rect(3.0, 1.5, 1.5, 0.8)
.fill(base_color.to_color())
.text("Base Color")
)
.add_shape(
rect(5.0, 1.5, 1.5, 0.8)
.fill(base_color.lighter(0.4).to_color())
.text("Lighter 40%")
),
];
let pptx = create_pptx_with_content("Colors", slides)?;
std::fs::write("colors.pptx", pptx)?;
Ok(())
}
Example 4: Task Tracker with Styled Cells
use ppt_rs::prelude::*;
fn main() -> Result<()> {
let slides = vec![
SlideContent::new("Task Tracker")
.table(
QuickTable::with_widths(&[2.5, 1.5, 1.5, 1.5])
.styled_row(vec![
header_cell("Task"),
header_cell("Priority"),
header_cell("Status"),
header_cell("Owner"),
])
.styled_row(vec![
cell("API Simplification"),
highlight_cell("High", &material_red().to_hex()),
highlight_cell("Done", &material_green().to_hex()),
cell("Team A"),
])
.styled_row(vec![
cell("Documentation"),
highlight_cell("Medium", &material_orange().to_hex()),
cell("In Progress"),
cell("Team B"),
])
.at(0.5, 1.5)
.build()
),
];
let pptx = create_pptx_with_content("Tasks", slides)?;
std::fs::write("tasks.pptx", pptx)?;
Ok(())
}
API Comparison
Before (Verbose)
use ppt_rs::generator::{Shape, ShapeType, ShapeFill, ShapeLine};
let shape = Shape::new(ShapeType::Rectangle, 914400, 1828800, 2743200, 1371600)
.with_fill(ShapeFill::new("4F81BD"))
.with_line(ShapeLine::new("000000", 25400))
.with_text("Hello");
After (Simplified)
use ppt_rs::prelude::*;
let shape = rect(1.0, 2.0, 3.0, 1.5)
.fill(blue().to_color())
.stroke(black().to_color(), 2.0)
.text("Hello");
Result: ~60% less code, dramatically more readable!
Tips & Best Practices
- Use color aliases -
red()is clearer thanhex("FF0000") - Adjust colors - Use
.lighter()and.darker()for color variations - QuickTable for flexibility - Most powerful table creation method
- Inches for dimensions - More intuitive than EMUs; use
Dimension::Ratio/percentfor responsive layouts - Chain methods - Use fluent API for cleaner code
- Validate before ship -
validate_package_bytesorpptcli validatecatches packaging gaps - Theme once - Prefer
PresentationTheme/--templateover hand-styling every shape
See Also
- Examples - Working code (
simplified_api,color_and_table_demo,dimension_demo,theme_customization_test) - examples/README.md - Example index
- API Reference - Complete rustdoc
- SPEC.md - Technical specifications
- ARCHITECTURE.md - Module layout
- docs/index.html - Docs landing page