office-toolkit 1.0.0

A Rust library to create, read, and modify Microsoft Office documents (Word/Excel/PowerPoint) in the modern Open XML (OOXML) format.
Documentation
//! PowerPoint speaker notes and reviewer comments. One slide per feature.
//!
//! Run with: `cargo run -p office-toolkit --example pptx_notes_and_comments`

use std::path::{Path, PathBuf};

use office_toolkit::SaveToFile;
use office_toolkit::drawing::{ShapeProperties, TextBody, TextParagraph, TextRun, Transform2D};
use office_toolkit::powerpoint::{AutoShape, Shape, SlideComment};
use office_toolkit::prelude::*;

fn main() -> office_toolkit::Result<()> {
    let path = output_path("pptx_notes_and_comments.pptx");

    let title = |text: &str| {
        AutoShape::new(2, "Title")
            .with_properties(
                ShapeProperties::new().with_transform(
                    Transform2D::new()
                        .with_offset(838_200, 838_200)
                        .with_extent(8_000_000, 1_000_000),
                ),
            )
            .with_text_body(
                TextBody::new().with_paragraph(TextParagraph::new().with_run(TextRun::text(text))),
            )
    };

    let notes_slide = Slide::new()
        .with_shape(Shape::AutoShape(title("A slide with speaker notes")))
        .with_notes(
            TextBody::new().with_paragraph(
                TextParagraph::new()
                    .with_run(TextRun::text("Remember to mention the Q3 numbers here.")),
            ),
        );

    let commented_slide = Slide::new()
        .with_shape(Shape::AutoShape(title("A slide with reviewer comments")))
        .with_comment(
            SlideComment::new(
                "Reviewer",
                "RV",
                "2026-07-21T10:00:00",
                "This claim needs a source.",
            )
            .with_position(1_000_000, 2_000_000),
        )
        .with_comment(
            SlideComment::new(
                "Editor",
                "ED",
                "2026-07-21T11:30:00",
                "Looks good otherwise.",
            )
            .with_position(3_000_000, 2_000_000),
        );

    let presentation = Presentation::new()
        .with_slide(notes_slide)
        .with_slide(commented_slide);

    presentation.save_to_file(&path)?;
    println!("Wrote {}", path.display());
    Ok(())
}

/// Every example in this directory writes its output under
/// `tests-data/output/`, resolved relative to this crate's own manifest so
/// it works no matter what directory `cargo run` was invoked from.
fn output_path(filename: &str) -> PathBuf {
    Path::new(env!("CARGO_MANIFEST_DIR"))
        .join("../../tests-data/output")
        .join(filename)
}