Skip to main content

xlsx_workbook_metadata/
xlsx_workbook_metadata.rs

1//! Excel workbook-level data: document properties and custom properties,
2//! named ranges, calculation settings, what-if scenarios, autofilter
3//! criteria, and suppressed error-checking warnings. One tab per feature.
4//!
5//! Run with: `cargo run -p office-toolkit --example xlsx_workbook_metadata`
6
7use std::path::{Path, PathBuf};
8
9use office_toolkit::SaveToFile;
10use office_toolkit::excel::{
11    AutoFilterColumn, CalculationMode, CalculationProperties, CustomPropertyValue, DefinedName,
12    DocumentProperties, IgnoredError, Scenario, Sheet,
13};
14use office_toolkit::prelude::*;
15
16fn main() -> office_toolkit::Result<()> {
17    let path = output_path("xlsx_workbook_metadata.xlsx");
18
19    let named_ranges_sheet = Sheet::new("Named ranges")
20        .with_row(Row::new().with_text("Tax rate").with_number(0.0825))
21        .with_row(Row::new().with_cell(Cell::formula("TaxRate*100").with_cached_value(8.25)));
22
23    let calculation_sheet = Sheet::new("Calculation").with_row(
24        Row::new().with_text("Set to manual recalculation with iterative calculation enabled."),
25    );
26
27    let scenarios_sheet = Sheet::new("Scenarios")
28        .with_row(Row::new().with_text("Revenue").with_number(100_000.0))
29        .with_row(Row::new().with_text("Cost").with_number(60_000.0))
30        .with_scenario(
31            Scenario::new("Best case")
32                .with_input("B1", "150000")
33                .with_input("B2", "55000")
34                .with_comment("Optimistic projection"),
35        )
36        .with_scenario(
37            Scenario::new("Worst case")
38                .with_input("B1", "70000")
39                .with_input("B2", "65000"),
40        );
41
42    let auto_filter_sheet = Sheet::new("Autofilter criteria")
43        .with_row(Row::new().with_text("Region"))
44        .with_row(Row::new().with_text("North"))
45        .with_row(Row::new().with_text("South"))
46        .with_auto_filter_range("A1:A3")
47        .with_auto_filter_column(AutoFilterColumn::new(0, vec!["North".to_string()]));
48
49    let ignored_errors_sheet = Sheet::new("Ignored errors")
50        .with_row(Row::new().with_text("123")) // a number stored as text — normally flagged by Excel
51        .with_ignored_error(IgnoredError::new("A1:A1").with_number_stored_as_text(true));
52
53    let workbook = Workbook::new()
54        .with_defined_name(DefinedName::new("TaxRate", "'Named ranges'!$B$1"))
55        .with_calculation(
56            CalculationProperties::new()
57                .with_mode(CalculationMode::Manual)
58                .with_iterate(true),
59        )
60        .with_sheet(named_ranges_sheet)
61        .with_sheet(calculation_sheet)
62        .with_sheet(scenarios_sheet)
63        .with_sheet(auto_filter_sheet)
64        .with_sheet(ignored_errors_sheet);
65
66    // `Workbook.properties` has no `with_*` builder — it's set directly,
67    // like any other public field.
68    let properties = DocumentProperties::new()
69        .with_title("Metadata example")
70        .with_author("Example Author")
71        .with_subject("Workbook-level features")
72        .with_custom_property(
73            "ProjectCode",
74            CustomPropertyValue::Text("XLSX-META".to_string()),
75        );
76    let workbook = Workbook {
77        properties,
78        ..workbook
79    };
80
81    workbook.save_to_file(&path)?;
82    println!("Wrote {}", path.display());
83    Ok(())
84}
85
86/// Every example in this directory writes its output under
87/// `tests-data/output/`, resolved relative to this crate's own manifest so
88/// it works no matter what directory `cargo run` was invoked from.
89fn output_path(filename: &str) -> PathBuf {
90    Path::new(env!("CARGO_MANIFEST_DIR"))
91        .join("../../tests-data/output")
92        .join(filename)
93}