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
//! Word page layout: page size/orientation/margins/columns, and default vs.
//! first-page vs. even-page headers and footers. Page setup applies to the
//! whole document, so this example still spans several pages (via manual
//! page breaks) to show the header/footer alternation in Word's own page
//! view.
//!
//! Run with: `cargo run -p office-toolkit --example docx_page_layout`

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

use office_toolkit::SaveToFile;
use office_toolkit::prelude::*;
use office_toolkit::word::{HeaderFooter, Orientation, PageSetup, Run};

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

    let page_setup = PageSetup::new()
        .with_size_twips(16_838, 11_906) // A4 landscape, in twentieths of a point
        .with_orientation(Orientation::Landscape)
        .with_margins_twips(1_440, 1_440, 1_800, 1_800) // top, bottom, left, right
        .with_header_footer_margins_twips(720, 720)
        .with_gutter_twips(0)
        .with_columns(2);

    let default_header =
        HeaderFooter::new().with_paragraph(Paragraph::with_text("Default header — every page"));
    let default_footer =
        HeaderFooter::new().with_paragraph(Paragraph::with_text("Default footer — every page"));
    let first_header = HeaderFooter::new()
        .with_paragraph(Paragraph::with_text("First-page header — cover page only"));
    let even_header = HeaderFooter::new().with_paragraph(Paragraph::with_text("Even-page header"));

    let document = Document::new()
        .with_page_setup(page_setup)
        .with_header(default_header)
        .with_footer(default_footer)
        .with_header_first(first_header)
        .with_header_even(even_header)
        .with_paragraph(heading("Page setup: A4 landscape, custom margins, two columns", false))
        .with_paragraph(Paragraph::with_text(
            "This document is landscape A4, with wider left/right margins than top/bottom, and its body text \
             flows in two columns. Look at the page in Word's Layout view to see the effect.",
        ))
        .with_paragraph(heading("Headers and footers", true))
        .with_paragraph(Paragraph::with_text(
            "Page 1 (this page) uses the first-page header, since \"different first page\" headers are set. \
             Every other page uses the default header shown above, and every page uses the default footer.",
        ))
        .with_paragraph(heading("A third page, to see the default header again", true))
        .with_paragraph(Paragraph::with_text(
            "If Word is configured to show even/odd pages differently, this page alternates between the \
             default and even-page header depending on whether it lands on an even or odd page number.",
        ));

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

fn heading(text: &str, new_page: bool) -> Paragraph {
    Paragraph::new()
        .with_run(Run::new(text).with_bold(true).with_font_size(28))
        .with_page_break_before(new_page)
}

/// 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)
}