pub struct Cell {
pub value: CellValue,
pub format: Option<CellFormat>,
}Expand description
A single cell (<c>, CT_Cell): a value plus an optional style.
Fields§
§value: CellValueThis cell’s value.
format: Option<CellFormat>This cell’s style, if any. None means the cell uses Excel’s own default style
(xl/styles.xml’s cellXfs index 0, the “Normal” style) — this crate never writes a
<c>’s s attribute for a cell with no format, matching how real Excel omits s="0" too
(it’s the implicit default). Distinct CellFormats across a workbook are deduplicated into
shared cellXfs entries by the writer, exactly like CellValue::Text’s shared-strings
deduplication — see writer.rs::collect_cell_formats.
Implementations§
Source§impl Cell
impl Cell
Sourcepub fn text(text: impl Into<String>) -> Cell
pub fn text(text: impl Into<String>) -> Cell
Creates a text cell.
Examples found in repository?
13fn main() -> office_toolkit::Result<()> {
14 let path = output_path("xlsx_structure_and_layout.xlsx");
15
16 let merged_sheet = Sheet::new("Merged cells")
17 .with_row(Row::new().with_text("This title spans three columns"))
18 .with_merged_range("A1:C1");
19
20 let columns_sheet = Sheet::new("Columns")
21 .with_row(
22 Row::new()
23 .with_cell(Cell::text("Wide"))
24 .with_cell(Cell::text("Hidden"))
25 .with_cell(Cell::text("Grouped")),
26 )
27 .with_column_setting(ColumnSetting::new(0).with_width(30.0))
28 .with_column_setting(ColumnSetting::new(1).with_hidden(true))
29 .with_column_setting(
30 ColumnSetting::new(2)
31 .with_outline_level(1)
32 .with_collapsed(false),
33 );
34
35 let rows_sheet = Sheet::new("Rows")
36 .with_row(Row::new().with_text("Normal row"))
37 .with_row(Row::new().with_text("Taller row").with_height(30.0))
38 .with_row(Row::new().with_text("Hidden row").with_hidden(true))
39 .with_row(
40 Row::new()
41 .with_text("Grouped detail row")
42 .with_outline_level(1),
43 );
44
45 let frozen_panes_sheet = Sheet::new("Frozen panes")
46 .with_row(
47 Row::new()
48 .with_cell(Cell::text("Frozen header"))
49 .with_cell(Cell::text("Frozen header")),
50 )
51 .with_row(
52 Row::new()
53 .with_cell(Cell::text("Scrolling data"))
54 .with_cell(Cell::number(1.0)),
55 )
56 .with_freeze_panes(FreezePane::new(1, 1));
57
58 let page_breaks_sheet = Sheet::new("Page breaks")
59 .with_row(Row::new().with_text("Above this row: page break"))
60 .with_row(Row::new().with_text("Below the break"))
61 .with_row_break(1)
62 .with_column_break(0)
63 .with_outline_summary_below(false)
64 .with_outline_summary_right(false);
65
66 let workbook = Workbook::new()
67 .with_sheet(merged_sheet)
68 .with_sheet(columns_sheet)
69 .with_sheet(rows_sheet)
70 .with_sheet(frozen_panes_sheet)
71 .with_sheet(page_breaks_sheet);
72
73 workbook.save_to_file(&path)?;
74 println!("Wrote {}", path.display());
75 Ok(())
76}More examples
16fn main() -> office_toolkit::Result<()> {
17 let path = output_path("xlsx_tables.xlsx");
18
19 let plain_sheet = Sheet::new("Plain table")
20 .with_row(Row::new().with_text("Name").with_text("Score"))
21 .with_row(Row::new().with_text("Alice").with_number(92.0))
22 .with_row(Row::new().with_text("Bob").with_number(87.0))
23 .with_table(ExcelTable::new(
24 "ScoresTable",
25 "A1:B3",
26 vec!["Name", "Score"],
27 ));
28
29 let calculated_sheet = Sheet::new("Calculated and totals")
30 .with_row(
31 Row::new()
32 .with_text("Item")
33 .with_text("Qty")
34 .with_text("Unit price")
35 .with_text("Line total"),
36 )
37 .with_row(
38 Row::new()
39 .with_text("Widget")
40 .with_number(3.0)
41 .with_number(9.99)
42 .with_cell(Cell::formula("B2*C2").with_cached_value(29.97)),
43 )
44 .with_row(
45 Row::new()
46 .with_text("Gadget")
47 .with_number(2.0)
48 .with_number(19.99)
49 .with_cell(Cell::formula("B3*C3").with_cached_value(39.98)),
50 )
51 .with_row(Row::new().with_cell(Cell::text("Total")))
52 .with_table(
53 ExcelTable::with_columns(
54 "OrdersTable",
55 "A1:D4",
56 vec![
57 TableColumn::new("Item"),
58 TableColumn::new("Qty").with_totals_row_function(TotalsRowFunction::Sum),
59 TableColumn::new("Unit price"),
60 TableColumn::new("Line total")
61 .with_calculated_formula(
62 "OrdersTable[[#This Row],[Qty]]*OrdersTable[[#This Row],[Unit price]]",
63 )
64 .with_totals_row_function(TotalsRowFunction::Sum),
65 ],
66 )
67 .with_totals_row(true),
68 );
69
70 let styled_sheet = Sheet::new("Custom style and sort")
71 .with_row(Row::new().with_text("City").with_text("Population"))
72 .with_row(Row::new().with_text("Springfield").with_number(120_000.0))
73 .with_row(Row::new().with_text("Shelbyville").with_number(95_000.0))
74 .with_table(
75 ExcelTable::new("CitiesTable", "A1:B3", vec!["City", "Population"])
76 .with_table_style_name("CustomTableStyle")
77 .with_sort_state(
78 SortState::new("A2:B3")
79 .with_condition(SortCondition::new("B2:B3").with_descending(true)),
80 ),
81 );
82
83 let workbook = Workbook::new()
84 .with_table_style(
85 TableStyle::new("CustomTableStyle")
86 .with_element(TableStyleElement::new(
87 TableStyleElementType::HeaderRow,
88 CellFormat::new()
89 .with_bold(true)
90 .with_fill_color("FF2E74B5")
91 .with_font_color("FFFFFFFF"),
92 ))
93 .with_element(TableStyleElement::new(
94 TableStyleElementType::FirstRowStripe,
95 CellFormat::new().with_fill_color("FFF2F2F2"),
96 )),
97 )
98 .with_sheet(plain_sheet)
99 .with_sheet(calculated_sheet)
100 .with_sheet(styled_sheet);
101
102 workbook.save_to_file(&path)?;
103 println!("Wrote {}", path.display());
104 Ok(())
105}15fn main() -> office_toolkit::Result<()> {
16 let path = output_path("xlsx_cell_formatting.xlsx");
17
18 let borders_sheet =
19 Sheet::new("Borders").with_row(
20 Row::new()
21 .with_cell(Cell::text("Thin all around").with_format(
22 CellFormat::new().with_border(Border::all(BorderStyle::Thin, "FF000000")),
23 ))
24 .with_cell(Cell::text("Thick bottom only").with_format(
25 CellFormat::new().with_border(
26 Border::new().with_bottom(
27 BorderEdge::new(BorderStyle::Thick).with_color("FFC00000"),
28 ),
29 ),
30 )),
31 );
32
33 let fills_sheet = Sheet::new("Fills")
34 .with_row(Row::new().with_cell(
35 Cell::text("Solid fill").with_format(CellFormat::new().with_fill_color("FFFFF2CC")),
36 ))
37 .with_row(
38 Row::new().with_cell(
39 Cell::text("Pattern fill").with_format(
40 CellFormat::new().with_pattern_fill(
41 PatternFill::new(PatternType::LightGray)
42 .with_fg_color("FF4472C4")
43 .with_bg_color("FFFFFFFF"),
44 ),
45 ),
46 ),
47 )
48 .with_row(
49 Row::new().with_cell(Cell::text("Gradient fill").with_format(
50 CellFormat::new().with_gradient_fill(GradientFill::new(
51 90.0,
52 vec![
53 GradientStop::new(0.0, "FFFFFFFF"),
54 GradientStop::new(1.0, "FF4472C4"),
55 ],
56 )),
57 )),
58 );
59
60 let fonts_and_alignment_sheet =
61 Sheet::new("Fonts and alignment")
62 .with_row(
63 Row::new().with_cell(
64 Cell::text("Bold, red, 14pt").with_format(
65 CellFormat::new()
66 .with_bold(true)
67 .with_font_size(14.0)
68 .with_font_color("FFC00000"),
69 ),
70 ),
71 )
72 .with_row(
73 Row::new().with_cell(
74 Cell::text("Centered both ways").with_format(
75 CellFormat::new()
76 .with_horizontal_alignment(HorizontalAlignment::Center)
77 .with_vertical_alignment(VerticalAlignment::Center),
78 ),
79 ),
80 )
81 .with_row(Row::new().with_cell(
82 Cell::text("Indented text").with_format(CellFormat::new().with_indent(2)),
83 ));
84
85 let number_formats_sheet = Sheet::new("Number formats")
86 .with_row(Row::new().with_cell(
87 Cell::number(1234.5).with_format(CellFormat::new().with_number_format("#,##0.00")),
88 ))
89 .with_row(Row::new().with_cell(
90 Cell::number(0.0825).with_format(CellFormat::new().with_number_format("0.00%")),
91 ))
92 .with_row(Row::new().with_cell(
93 Cell::number(1234.5).with_format(CellFormat::new().with_number_format("$#,##0.00")),
94 ));
95
96 let named_styles_sheet = Sheet::new("Named styles").with_row(
97 Row::new().with_cell(
98 Cell::text("Uses a named style")
99 .with_format(CellFormat::new().with_named_style("Emphasis")),
100 ),
101 );
102
103 let workbook = Workbook::new()
104 .with_named_cell_style(NamedCellStyle::new(
105 "Emphasis",
106 CellFormat::new()
107 .with_bold(true)
108 .with_font_color("FF4472C4"),
109 ))
110 .with_sheet(borders_sheet)
111 .with_sheet(fills_sheet)
112 .with_sheet(fonts_and_alignment_sheet)
113 .with_sheet(number_formats_sheet)
114 .with_sheet(named_styles_sheet);
115
116 workbook.save_to_file(&path)?;
117 println!("Wrote {}", path.display());
118 Ok(())
119}Sourcepub fn number(number: f64) -> Cell
pub fn number(number: f64) -> Cell
Creates a numeric cell.
Examples found in repository?
13fn main() -> office_toolkit::Result<()> {
14 let path = output_path("xlsx_structure_and_layout.xlsx");
15
16 let merged_sheet = Sheet::new("Merged cells")
17 .with_row(Row::new().with_text("This title spans three columns"))
18 .with_merged_range("A1:C1");
19
20 let columns_sheet = Sheet::new("Columns")
21 .with_row(
22 Row::new()
23 .with_cell(Cell::text("Wide"))
24 .with_cell(Cell::text("Hidden"))
25 .with_cell(Cell::text("Grouped")),
26 )
27 .with_column_setting(ColumnSetting::new(0).with_width(30.0))
28 .with_column_setting(ColumnSetting::new(1).with_hidden(true))
29 .with_column_setting(
30 ColumnSetting::new(2)
31 .with_outline_level(1)
32 .with_collapsed(false),
33 );
34
35 let rows_sheet = Sheet::new("Rows")
36 .with_row(Row::new().with_text("Normal row"))
37 .with_row(Row::new().with_text("Taller row").with_height(30.0))
38 .with_row(Row::new().with_text("Hidden row").with_hidden(true))
39 .with_row(
40 Row::new()
41 .with_text("Grouped detail row")
42 .with_outline_level(1),
43 );
44
45 let frozen_panes_sheet = Sheet::new("Frozen panes")
46 .with_row(
47 Row::new()
48 .with_cell(Cell::text("Frozen header"))
49 .with_cell(Cell::text("Frozen header")),
50 )
51 .with_row(
52 Row::new()
53 .with_cell(Cell::text("Scrolling data"))
54 .with_cell(Cell::number(1.0)),
55 )
56 .with_freeze_panes(FreezePane::new(1, 1));
57
58 let page_breaks_sheet = Sheet::new("Page breaks")
59 .with_row(Row::new().with_text("Above this row: page break"))
60 .with_row(Row::new().with_text("Below the break"))
61 .with_row_break(1)
62 .with_column_break(0)
63 .with_outline_summary_below(false)
64 .with_outline_summary_right(false);
65
66 let workbook = Workbook::new()
67 .with_sheet(merged_sheet)
68 .with_sheet(columns_sheet)
69 .with_sheet(rows_sheet)
70 .with_sheet(frozen_panes_sheet)
71 .with_sheet(page_breaks_sheet);
72
73 workbook.save_to_file(&path)?;
74 println!("Wrote {}", path.display());
75 Ok(())
76}More examples
13fn main() -> office_toolkit::Result<()> {
14 let path = output_path("xlsx_rich_data.xlsx");
15
16 let dates_and_booleans_sheet = Sheet::new("Dates and booleans")
17 .with_row(Row::new().with_cell(Cell::date(ExcelDateTime::date(2026, 7, 21))))
18 .with_row(Row::new().with_cell(Cell::date(
19 ExcelDateTime::date(2026, 7, 21).with_time(14, 30, 0),
20 )))
21 .with_row(
22 Row::new()
23 .with_cell(Cell::boolean(true))
24 .with_cell(Cell::boolean(false)),
25 );
26
27 // An array/shared formula's `ref` must be a range whose top-left cell
28 // is the cell the `<f t="array"|"shared">` element actually sits in —
29 // `with_cell` fills a row left-to-right starting at column A, so each
30 // formula cell below is positioned to land exactly on its own `ref`'s
31 // first cell, with plain cached-value cells (no `<f>`) filling out the
32 // rest of the declared range, matching how Excel itself writes a
33 // multi-cell array/shared formula. The previous version declared
34 // ranges like "D1:D3"/"E1:E3" while the formula cells actually landed
35 // in column A — a real cell/range mismatch Excel refuses to open
36 // without repairing.
37 let formulas_sheet = Sheet::new("Formulas")
38 .with_row(
39 Row::new()
40 .with_cell(Cell::number(10.0))
41 .with_cell(Cell::number(20.0))
42 .with_cell(Cell::formula("A1+B1").with_cached_value(30.0)),
43 )
44 .with_row(
45 Row::new()
46 .with_cell(Cell::array_formula("A1:A3*2", "A2:C2").with_cached_value(20.0))
47 .with_cell(Cell::number(40.0))
48 .with_cell(Cell::number(60.0)),
49 )
50 .with_row(
51 Row::new()
52 .with_cell(Cell::shared_formula("A1+1", 0, "A3:C3").with_cached_value(11.0))
53 .with_cell(Cell::shared_formula_follower(0).with_cached_value(21.0))
54 .with_cell(Cell::shared_formula_follower(0).with_cached_value(31.0)),
55 );
56
57 let rich_text_sheet =
58 Sheet::new("Rich text").with_row(Row::new().with_cell(Cell::rich_text(vec![
59 RichTextRun::new("Bold red, ").with_bold(true).with_font_color("FFC00000"),
60 RichTextRun::new("then italic blue.").with_italic(true).with_font_color("FF2E74B5"),
61 ])));
62
63 let hyperlinks_sheet = Sheet::new("Hyperlinks")
64 .with_row(
65 Row::new()
66 .with_text("Visit Rust")
67 .with_text("Jump to C1")
68 .with_text("You've arrived"),
69 )
70 .with_hyperlink(
71 CellHyperlink::external("A1", "https://www.rust-lang.org")
72 .with_tooltip("Opens in your browser"),
73 )
74 .with_hyperlink(CellHyperlink::internal("B1", "'Hyperlinks'!C1"));
75
76 let comments_sheet = Sheet::new("Comments")
77 .with_row(
78 Row::new()
79 .with_text("Hover B1 for a comment")
80 .with_text("Reviewed"),
81 )
82 .with_comment(CellComment::new(
83 "A1",
84 "Reviewer",
85 "Double-check this figure before publishing.",
86 ))
87 .with_comment(
88 CellComment::new("B1", "Reviewer", "Looks correct.")
89 .with_rich_text(vec![RichTextRun::new("Looks correct.").with_bold(true)]),
90 );
91
92 let workbook = Workbook::new()
93 .with_sheet(dates_and_booleans_sheet)
94 .with_sheet(formulas_sheet)
95 .with_sheet(rich_text_sheet)
96 .with_sheet(hyperlinks_sheet)
97 .with_sheet(comments_sheet);
98
99 workbook.save_to_file(&path)?;
100 println!("Wrote {}", path.display());
101 Ok(())
102}15fn main() -> office_toolkit::Result<()> {
16 let path = output_path("xlsx_cell_formatting.xlsx");
17
18 let borders_sheet =
19 Sheet::new("Borders").with_row(
20 Row::new()
21 .with_cell(Cell::text("Thin all around").with_format(
22 CellFormat::new().with_border(Border::all(BorderStyle::Thin, "FF000000")),
23 ))
24 .with_cell(Cell::text("Thick bottom only").with_format(
25 CellFormat::new().with_border(
26 Border::new().with_bottom(
27 BorderEdge::new(BorderStyle::Thick).with_color("FFC00000"),
28 ),
29 ),
30 )),
31 );
32
33 let fills_sheet = Sheet::new("Fills")
34 .with_row(Row::new().with_cell(
35 Cell::text("Solid fill").with_format(CellFormat::new().with_fill_color("FFFFF2CC")),
36 ))
37 .with_row(
38 Row::new().with_cell(
39 Cell::text("Pattern fill").with_format(
40 CellFormat::new().with_pattern_fill(
41 PatternFill::new(PatternType::LightGray)
42 .with_fg_color("FF4472C4")
43 .with_bg_color("FFFFFFFF"),
44 ),
45 ),
46 ),
47 )
48 .with_row(
49 Row::new().with_cell(Cell::text("Gradient fill").with_format(
50 CellFormat::new().with_gradient_fill(GradientFill::new(
51 90.0,
52 vec![
53 GradientStop::new(0.0, "FFFFFFFF"),
54 GradientStop::new(1.0, "FF4472C4"),
55 ],
56 )),
57 )),
58 );
59
60 let fonts_and_alignment_sheet =
61 Sheet::new("Fonts and alignment")
62 .with_row(
63 Row::new().with_cell(
64 Cell::text("Bold, red, 14pt").with_format(
65 CellFormat::new()
66 .with_bold(true)
67 .with_font_size(14.0)
68 .with_font_color("FFC00000"),
69 ),
70 ),
71 )
72 .with_row(
73 Row::new().with_cell(
74 Cell::text("Centered both ways").with_format(
75 CellFormat::new()
76 .with_horizontal_alignment(HorizontalAlignment::Center)
77 .with_vertical_alignment(VerticalAlignment::Center),
78 ),
79 ),
80 )
81 .with_row(Row::new().with_cell(
82 Cell::text("Indented text").with_format(CellFormat::new().with_indent(2)),
83 ));
84
85 let number_formats_sheet = Sheet::new("Number formats")
86 .with_row(Row::new().with_cell(
87 Cell::number(1234.5).with_format(CellFormat::new().with_number_format("#,##0.00")),
88 ))
89 .with_row(Row::new().with_cell(
90 Cell::number(0.0825).with_format(CellFormat::new().with_number_format("0.00%")),
91 ))
92 .with_row(Row::new().with_cell(
93 Cell::number(1234.5).with_format(CellFormat::new().with_number_format("$#,##0.00")),
94 ));
95
96 let named_styles_sheet = Sheet::new("Named styles").with_row(
97 Row::new().with_cell(
98 Cell::text("Uses a named style")
99 .with_format(CellFormat::new().with_named_style("Emphasis")),
100 ),
101 );
102
103 let workbook = Workbook::new()
104 .with_named_cell_style(NamedCellStyle::new(
105 "Emphasis",
106 CellFormat::new()
107 .with_bold(true)
108 .with_font_color("FF4472C4"),
109 ))
110 .with_sheet(borders_sheet)
111 .with_sheet(fills_sheet)
112 .with_sheet(fonts_and_alignment_sheet)
113 .with_sheet(number_formats_sheet)
114 .with_sheet(named_styles_sheet);
115
116 workbook.save_to_file(&path)?;
117 println!("Wrote {}", path.display());
118 Ok(())
119}Sourcepub fn formula(formula: impl Into<String>) -> Cell
pub fn formula(formula: impl Into<String>) -> Cell
Creates a formula cell holding the given formula text (without a leading =) and no cached
value yet — see Cell::with_cached_value to attach one. A formula with no cached value is
still schema-valid (Excel simply recomputes it the next time the file is opened, its
standard behavior for any formula it considers “dirty”).
Examples found in repository?
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}More examples
16fn main() -> office_toolkit::Result<()> {
17 let path = output_path("xlsx_tables.xlsx");
18
19 let plain_sheet = Sheet::new("Plain table")
20 .with_row(Row::new().with_text("Name").with_text("Score"))
21 .with_row(Row::new().with_text("Alice").with_number(92.0))
22 .with_row(Row::new().with_text("Bob").with_number(87.0))
23 .with_table(ExcelTable::new(
24 "ScoresTable",
25 "A1:B3",
26 vec!["Name", "Score"],
27 ));
28
29 let calculated_sheet = Sheet::new("Calculated and totals")
30 .with_row(
31 Row::new()
32 .with_text("Item")
33 .with_text("Qty")
34 .with_text("Unit price")
35 .with_text("Line total"),
36 )
37 .with_row(
38 Row::new()
39 .with_text("Widget")
40 .with_number(3.0)
41 .with_number(9.99)
42 .with_cell(Cell::formula("B2*C2").with_cached_value(29.97)),
43 )
44 .with_row(
45 Row::new()
46 .with_text("Gadget")
47 .with_number(2.0)
48 .with_number(19.99)
49 .with_cell(Cell::formula("B3*C3").with_cached_value(39.98)),
50 )
51 .with_row(Row::new().with_cell(Cell::text("Total")))
52 .with_table(
53 ExcelTable::with_columns(
54 "OrdersTable",
55 "A1:D4",
56 vec![
57 TableColumn::new("Item"),
58 TableColumn::new("Qty").with_totals_row_function(TotalsRowFunction::Sum),
59 TableColumn::new("Unit price"),
60 TableColumn::new("Line total")
61 .with_calculated_formula(
62 "OrdersTable[[#This Row],[Qty]]*OrdersTable[[#This Row],[Unit price]]",
63 )
64 .with_totals_row_function(TotalsRowFunction::Sum),
65 ],
66 )
67 .with_totals_row(true),
68 );
69
70 let styled_sheet = Sheet::new("Custom style and sort")
71 .with_row(Row::new().with_text("City").with_text("Population"))
72 .with_row(Row::new().with_text("Springfield").with_number(120_000.0))
73 .with_row(Row::new().with_text("Shelbyville").with_number(95_000.0))
74 .with_table(
75 ExcelTable::new("CitiesTable", "A1:B3", vec!["City", "Population"])
76 .with_table_style_name("CustomTableStyle")
77 .with_sort_state(
78 SortState::new("A2:B3")
79 .with_condition(SortCondition::new("B2:B3").with_descending(true)),
80 ),
81 );
82
83 let workbook = Workbook::new()
84 .with_table_style(
85 TableStyle::new("CustomTableStyle")
86 .with_element(TableStyleElement::new(
87 TableStyleElementType::HeaderRow,
88 CellFormat::new()
89 .with_bold(true)
90 .with_fill_color("FF2E74B5")
91 .with_font_color("FFFFFFFF"),
92 ))
93 .with_element(TableStyleElement::new(
94 TableStyleElementType::FirstRowStripe,
95 CellFormat::new().with_fill_color("FFF2F2F2"),
96 )),
97 )
98 .with_sheet(plain_sheet)
99 .with_sheet(calculated_sheet)
100 .with_sheet(styled_sheet);
101
102 workbook.save_to_file(&path)?;
103 println!("Wrote {}", path.display());
104 Ok(())
105}13fn main() -> office_toolkit::Result<()> {
14 let path = output_path("xlsx_rich_data.xlsx");
15
16 let dates_and_booleans_sheet = Sheet::new("Dates and booleans")
17 .with_row(Row::new().with_cell(Cell::date(ExcelDateTime::date(2026, 7, 21))))
18 .with_row(Row::new().with_cell(Cell::date(
19 ExcelDateTime::date(2026, 7, 21).with_time(14, 30, 0),
20 )))
21 .with_row(
22 Row::new()
23 .with_cell(Cell::boolean(true))
24 .with_cell(Cell::boolean(false)),
25 );
26
27 // An array/shared formula's `ref` must be a range whose top-left cell
28 // is the cell the `<f t="array"|"shared">` element actually sits in —
29 // `with_cell` fills a row left-to-right starting at column A, so each
30 // formula cell below is positioned to land exactly on its own `ref`'s
31 // first cell, with plain cached-value cells (no `<f>`) filling out the
32 // rest of the declared range, matching how Excel itself writes a
33 // multi-cell array/shared formula. The previous version declared
34 // ranges like "D1:D3"/"E1:E3" while the formula cells actually landed
35 // in column A — a real cell/range mismatch Excel refuses to open
36 // without repairing.
37 let formulas_sheet = Sheet::new("Formulas")
38 .with_row(
39 Row::new()
40 .with_cell(Cell::number(10.0))
41 .with_cell(Cell::number(20.0))
42 .with_cell(Cell::formula("A1+B1").with_cached_value(30.0)),
43 )
44 .with_row(
45 Row::new()
46 .with_cell(Cell::array_formula("A1:A3*2", "A2:C2").with_cached_value(20.0))
47 .with_cell(Cell::number(40.0))
48 .with_cell(Cell::number(60.0)),
49 )
50 .with_row(
51 Row::new()
52 .with_cell(Cell::shared_formula("A1+1", 0, "A3:C3").with_cached_value(11.0))
53 .with_cell(Cell::shared_formula_follower(0).with_cached_value(21.0))
54 .with_cell(Cell::shared_formula_follower(0).with_cached_value(31.0)),
55 );
56
57 let rich_text_sheet =
58 Sheet::new("Rich text").with_row(Row::new().with_cell(Cell::rich_text(vec![
59 RichTextRun::new("Bold red, ").with_bold(true).with_font_color("FFC00000"),
60 RichTextRun::new("then italic blue.").with_italic(true).with_font_color("FF2E74B5"),
61 ])));
62
63 let hyperlinks_sheet = Sheet::new("Hyperlinks")
64 .with_row(
65 Row::new()
66 .with_text("Visit Rust")
67 .with_text("Jump to C1")
68 .with_text("You've arrived"),
69 )
70 .with_hyperlink(
71 CellHyperlink::external("A1", "https://www.rust-lang.org")
72 .with_tooltip("Opens in your browser"),
73 )
74 .with_hyperlink(CellHyperlink::internal("B1", "'Hyperlinks'!C1"));
75
76 let comments_sheet = Sheet::new("Comments")
77 .with_row(
78 Row::new()
79 .with_text("Hover B1 for a comment")
80 .with_text("Reviewed"),
81 )
82 .with_comment(CellComment::new(
83 "A1",
84 "Reviewer",
85 "Double-check this figure before publishing.",
86 ))
87 .with_comment(
88 CellComment::new("B1", "Reviewer", "Looks correct.")
89 .with_rich_text(vec![RichTextRun::new("Looks correct.").with_bold(true)]),
90 );
91
92 let workbook = Workbook::new()
93 .with_sheet(dates_and_booleans_sheet)
94 .with_sheet(formulas_sheet)
95 .with_sheet(rich_text_sheet)
96 .with_sheet(hyperlinks_sheet)
97 .with_sheet(comments_sheet);
98
99 workbook.save_to_file(&path)?;
100 println!("Wrote {}", path.display());
101 Ok(())
102}Sourcepub fn boolean(value: bool) -> Cell
pub fn boolean(value: bool) -> Cell
Creates a boolean cell.
Examples found in repository?
13fn main() -> office_toolkit::Result<()> {
14 let path = output_path("xlsx_rich_data.xlsx");
15
16 let dates_and_booleans_sheet = Sheet::new("Dates and booleans")
17 .with_row(Row::new().with_cell(Cell::date(ExcelDateTime::date(2026, 7, 21))))
18 .with_row(Row::new().with_cell(Cell::date(
19 ExcelDateTime::date(2026, 7, 21).with_time(14, 30, 0),
20 )))
21 .with_row(
22 Row::new()
23 .with_cell(Cell::boolean(true))
24 .with_cell(Cell::boolean(false)),
25 );
26
27 // An array/shared formula's `ref` must be a range whose top-left cell
28 // is the cell the `<f t="array"|"shared">` element actually sits in —
29 // `with_cell` fills a row left-to-right starting at column A, so each
30 // formula cell below is positioned to land exactly on its own `ref`'s
31 // first cell, with plain cached-value cells (no `<f>`) filling out the
32 // rest of the declared range, matching how Excel itself writes a
33 // multi-cell array/shared formula. The previous version declared
34 // ranges like "D1:D3"/"E1:E3" while the formula cells actually landed
35 // in column A — a real cell/range mismatch Excel refuses to open
36 // without repairing.
37 let formulas_sheet = Sheet::new("Formulas")
38 .with_row(
39 Row::new()
40 .with_cell(Cell::number(10.0))
41 .with_cell(Cell::number(20.0))
42 .with_cell(Cell::formula("A1+B1").with_cached_value(30.0)),
43 )
44 .with_row(
45 Row::new()
46 .with_cell(Cell::array_formula("A1:A3*2", "A2:C2").with_cached_value(20.0))
47 .with_cell(Cell::number(40.0))
48 .with_cell(Cell::number(60.0)),
49 )
50 .with_row(
51 Row::new()
52 .with_cell(Cell::shared_formula("A1+1", 0, "A3:C3").with_cached_value(11.0))
53 .with_cell(Cell::shared_formula_follower(0).with_cached_value(21.0))
54 .with_cell(Cell::shared_formula_follower(0).with_cached_value(31.0)),
55 );
56
57 let rich_text_sheet =
58 Sheet::new("Rich text").with_row(Row::new().with_cell(Cell::rich_text(vec![
59 RichTextRun::new("Bold red, ").with_bold(true).with_font_color("FFC00000"),
60 RichTextRun::new("then italic blue.").with_italic(true).with_font_color("FF2E74B5"),
61 ])));
62
63 let hyperlinks_sheet = Sheet::new("Hyperlinks")
64 .with_row(
65 Row::new()
66 .with_text("Visit Rust")
67 .with_text("Jump to C1")
68 .with_text("You've arrived"),
69 )
70 .with_hyperlink(
71 CellHyperlink::external("A1", "https://www.rust-lang.org")
72 .with_tooltip("Opens in your browser"),
73 )
74 .with_hyperlink(CellHyperlink::internal("B1", "'Hyperlinks'!C1"));
75
76 let comments_sheet = Sheet::new("Comments")
77 .with_row(
78 Row::new()
79 .with_text("Hover B1 for a comment")
80 .with_text("Reviewed"),
81 )
82 .with_comment(CellComment::new(
83 "A1",
84 "Reviewer",
85 "Double-check this figure before publishing.",
86 ))
87 .with_comment(
88 CellComment::new("B1", "Reviewer", "Looks correct.")
89 .with_rich_text(vec![RichTextRun::new("Looks correct.").with_bold(true)]),
90 );
91
92 let workbook = Workbook::new()
93 .with_sheet(dates_and_booleans_sheet)
94 .with_sheet(formulas_sheet)
95 .with_sheet(rich_text_sheet)
96 .with_sheet(hyperlinks_sheet)
97 .with_sheet(comments_sheet);
98
99 workbook.save_to_file(&path)?;
100 println!("Wrote {}", path.display());
101 Ok(())
102}Sourcepub fn date(date: ExcelDateTime) -> Cell
pub fn date(date: ExcelDateTime) -> Cell
Creates a date cell from an ExcelDateTime — see CellValue::Date’s doc comment: pair
this with a .with_format(CellFormat::new().with_number_format("dd/mm/yyyy")) (or any other
date-shaped format code) for Excel to actually display it as a date; without one, Excel
shows the raw serial number.
Examples found in repository?
13fn main() -> office_toolkit::Result<()> {
14 let path = output_path("xlsx_rich_data.xlsx");
15
16 let dates_and_booleans_sheet = Sheet::new("Dates and booleans")
17 .with_row(Row::new().with_cell(Cell::date(ExcelDateTime::date(2026, 7, 21))))
18 .with_row(Row::new().with_cell(Cell::date(
19 ExcelDateTime::date(2026, 7, 21).with_time(14, 30, 0),
20 )))
21 .with_row(
22 Row::new()
23 .with_cell(Cell::boolean(true))
24 .with_cell(Cell::boolean(false)),
25 );
26
27 // An array/shared formula's `ref` must be a range whose top-left cell
28 // is the cell the `<f t="array"|"shared">` element actually sits in —
29 // `with_cell` fills a row left-to-right starting at column A, so each
30 // formula cell below is positioned to land exactly on its own `ref`'s
31 // first cell, with plain cached-value cells (no `<f>`) filling out the
32 // rest of the declared range, matching how Excel itself writes a
33 // multi-cell array/shared formula. The previous version declared
34 // ranges like "D1:D3"/"E1:E3" while the formula cells actually landed
35 // in column A — a real cell/range mismatch Excel refuses to open
36 // without repairing.
37 let formulas_sheet = Sheet::new("Formulas")
38 .with_row(
39 Row::new()
40 .with_cell(Cell::number(10.0))
41 .with_cell(Cell::number(20.0))
42 .with_cell(Cell::formula("A1+B1").with_cached_value(30.0)),
43 )
44 .with_row(
45 Row::new()
46 .with_cell(Cell::array_formula("A1:A3*2", "A2:C2").with_cached_value(20.0))
47 .with_cell(Cell::number(40.0))
48 .with_cell(Cell::number(60.0)),
49 )
50 .with_row(
51 Row::new()
52 .with_cell(Cell::shared_formula("A1+1", 0, "A3:C3").with_cached_value(11.0))
53 .with_cell(Cell::shared_formula_follower(0).with_cached_value(21.0))
54 .with_cell(Cell::shared_formula_follower(0).with_cached_value(31.0)),
55 );
56
57 let rich_text_sheet =
58 Sheet::new("Rich text").with_row(Row::new().with_cell(Cell::rich_text(vec![
59 RichTextRun::new("Bold red, ").with_bold(true).with_font_color("FFC00000"),
60 RichTextRun::new("then italic blue.").with_italic(true).with_font_color("FF2E74B5"),
61 ])));
62
63 let hyperlinks_sheet = Sheet::new("Hyperlinks")
64 .with_row(
65 Row::new()
66 .with_text("Visit Rust")
67 .with_text("Jump to C1")
68 .with_text("You've arrived"),
69 )
70 .with_hyperlink(
71 CellHyperlink::external("A1", "https://www.rust-lang.org")
72 .with_tooltip("Opens in your browser"),
73 )
74 .with_hyperlink(CellHyperlink::internal("B1", "'Hyperlinks'!C1"));
75
76 let comments_sheet = Sheet::new("Comments")
77 .with_row(
78 Row::new()
79 .with_text("Hover B1 for a comment")
80 .with_text("Reviewed"),
81 )
82 .with_comment(CellComment::new(
83 "A1",
84 "Reviewer",
85 "Double-check this figure before publishing.",
86 ))
87 .with_comment(
88 CellComment::new("B1", "Reviewer", "Looks correct.")
89 .with_rich_text(vec![RichTextRun::new("Looks correct.").with_bold(true)]),
90 );
91
92 let workbook = Workbook::new()
93 .with_sheet(dates_and_booleans_sheet)
94 .with_sheet(formulas_sheet)
95 .with_sheet(rich_text_sheet)
96 .with_sheet(hyperlinks_sheet)
97 .with_sheet(comments_sheet);
98
99 workbook.save_to_file(&path)?;
100 println!("Wrote {}", path.display());
101 Ok(())
102}Sourcepub fn rich_text(runs: Vec<RichTextRun>) -> Cell
pub fn rich_text(runs: Vec<RichTextRun>) -> Cell
Creates a rich-text cell (a text value with per-run character formatting).
Examples found in repository?
13fn main() -> office_toolkit::Result<()> {
14 let path = output_path("xlsx_rich_data.xlsx");
15
16 let dates_and_booleans_sheet = Sheet::new("Dates and booleans")
17 .with_row(Row::new().with_cell(Cell::date(ExcelDateTime::date(2026, 7, 21))))
18 .with_row(Row::new().with_cell(Cell::date(
19 ExcelDateTime::date(2026, 7, 21).with_time(14, 30, 0),
20 )))
21 .with_row(
22 Row::new()
23 .with_cell(Cell::boolean(true))
24 .with_cell(Cell::boolean(false)),
25 );
26
27 // An array/shared formula's `ref` must be a range whose top-left cell
28 // is the cell the `<f t="array"|"shared">` element actually sits in —
29 // `with_cell` fills a row left-to-right starting at column A, so each
30 // formula cell below is positioned to land exactly on its own `ref`'s
31 // first cell, with plain cached-value cells (no `<f>`) filling out the
32 // rest of the declared range, matching how Excel itself writes a
33 // multi-cell array/shared formula. The previous version declared
34 // ranges like "D1:D3"/"E1:E3" while the formula cells actually landed
35 // in column A — a real cell/range mismatch Excel refuses to open
36 // without repairing.
37 let formulas_sheet = Sheet::new("Formulas")
38 .with_row(
39 Row::new()
40 .with_cell(Cell::number(10.0))
41 .with_cell(Cell::number(20.0))
42 .with_cell(Cell::formula("A1+B1").with_cached_value(30.0)),
43 )
44 .with_row(
45 Row::new()
46 .with_cell(Cell::array_formula("A1:A3*2", "A2:C2").with_cached_value(20.0))
47 .with_cell(Cell::number(40.0))
48 .with_cell(Cell::number(60.0)),
49 )
50 .with_row(
51 Row::new()
52 .with_cell(Cell::shared_formula("A1+1", 0, "A3:C3").with_cached_value(11.0))
53 .with_cell(Cell::shared_formula_follower(0).with_cached_value(21.0))
54 .with_cell(Cell::shared_formula_follower(0).with_cached_value(31.0)),
55 );
56
57 let rich_text_sheet =
58 Sheet::new("Rich text").with_row(Row::new().with_cell(Cell::rich_text(vec![
59 RichTextRun::new("Bold red, ").with_bold(true).with_font_color("FFC00000"),
60 RichTextRun::new("then italic blue.").with_italic(true).with_font_color("FF2E74B5"),
61 ])));
62
63 let hyperlinks_sheet = Sheet::new("Hyperlinks")
64 .with_row(
65 Row::new()
66 .with_text("Visit Rust")
67 .with_text("Jump to C1")
68 .with_text("You've arrived"),
69 )
70 .with_hyperlink(
71 CellHyperlink::external("A1", "https://www.rust-lang.org")
72 .with_tooltip("Opens in your browser"),
73 )
74 .with_hyperlink(CellHyperlink::internal("B1", "'Hyperlinks'!C1"));
75
76 let comments_sheet = Sheet::new("Comments")
77 .with_row(
78 Row::new()
79 .with_text("Hover B1 for a comment")
80 .with_text("Reviewed"),
81 )
82 .with_comment(CellComment::new(
83 "A1",
84 "Reviewer",
85 "Double-check this figure before publishing.",
86 ))
87 .with_comment(
88 CellComment::new("B1", "Reviewer", "Looks correct.")
89 .with_rich_text(vec![RichTextRun::new("Looks correct.").with_bold(true)]),
90 );
91
92 let workbook = Workbook::new()
93 .with_sheet(dates_and_booleans_sheet)
94 .with_sheet(formulas_sheet)
95 .with_sheet(rich_text_sheet)
96 .with_sheet(hyperlinks_sheet)
97 .with_sheet(comments_sheet);
98
99 workbook.save_to_file(&path)?;
100 println!("Wrote {}", path.display());
101 Ok(())
102}Sourcepub fn array_formula(
formula: impl Into<String>,
range: impl Into<String>,
) -> Cell
pub fn array_formula( formula: impl Into<String>, range: impl Into<String>, ) -> Cell
Creates an array (CSE) formula cell holding the given formula text (without a leading =)
and range, and no cached value yet — see Cell::with_cached_value to attach one. This
cell should be placed at the array range’s top-left (anchor) position — see
CellValue::ArrayFormula’s doc comment.
Examples found in repository?
13fn main() -> office_toolkit::Result<()> {
14 let path = output_path("xlsx_rich_data.xlsx");
15
16 let dates_and_booleans_sheet = Sheet::new("Dates and booleans")
17 .with_row(Row::new().with_cell(Cell::date(ExcelDateTime::date(2026, 7, 21))))
18 .with_row(Row::new().with_cell(Cell::date(
19 ExcelDateTime::date(2026, 7, 21).with_time(14, 30, 0),
20 )))
21 .with_row(
22 Row::new()
23 .with_cell(Cell::boolean(true))
24 .with_cell(Cell::boolean(false)),
25 );
26
27 // An array/shared formula's `ref` must be a range whose top-left cell
28 // is the cell the `<f t="array"|"shared">` element actually sits in —
29 // `with_cell` fills a row left-to-right starting at column A, so each
30 // formula cell below is positioned to land exactly on its own `ref`'s
31 // first cell, with plain cached-value cells (no `<f>`) filling out the
32 // rest of the declared range, matching how Excel itself writes a
33 // multi-cell array/shared formula. The previous version declared
34 // ranges like "D1:D3"/"E1:E3" while the formula cells actually landed
35 // in column A — a real cell/range mismatch Excel refuses to open
36 // without repairing.
37 let formulas_sheet = Sheet::new("Formulas")
38 .with_row(
39 Row::new()
40 .with_cell(Cell::number(10.0))
41 .with_cell(Cell::number(20.0))
42 .with_cell(Cell::formula("A1+B1").with_cached_value(30.0)),
43 )
44 .with_row(
45 Row::new()
46 .with_cell(Cell::array_formula("A1:A3*2", "A2:C2").with_cached_value(20.0))
47 .with_cell(Cell::number(40.0))
48 .with_cell(Cell::number(60.0)),
49 )
50 .with_row(
51 Row::new()
52 .with_cell(Cell::shared_formula("A1+1", 0, "A3:C3").with_cached_value(11.0))
53 .with_cell(Cell::shared_formula_follower(0).with_cached_value(21.0))
54 .with_cell(Cell::shared_formula_follower(0).with_cached_value(31.0)),
55 );
56
57 let rich_text_sheet =
58 Sheet::new("Rich text").with_row(Row::new().with_cell(Cell::rich_text(vec![
59 RichTextRun::new("Bold red, ").with_bold(true).with_font_color("FFC00000"),
60 RichTextRun::new("then italic blue.").with_italic(true).with_font_color("FF2E74B5"),
61 ])));
62
63 let hyperlinks_sheet = Sheet::new("Hyperlinks")
64 .with_row(
65 Row::new()
66 .with_text("Visit Rust")
67 .with_text("Jump to C1")
68 .with_text("You've arrived"),
69 )
70 .with_hyperlink(
71 CellHyperlink::external("A1", "https://www.rust-lang.org")
72 .with_tooltip("Opens in your browser"),
73 )
74 .with_hyperlink(CellHyperlink::internal("B1", "'Hyperlinks'!C1"));
75
76 let comments_sheet = Sheet::new("Comments")
77 .with_row(
78 Row::new()
79 .with_text("Hover B1 for a comment")
80 .with_text("Reviewed"),
81 )
82 .with_comment(CellComment::new(
83 "A1",
84 "Reviewer",
85 "Double-check this figure before publishing.",
86 ))
87 .with_comment(
88 CellComment::new("B1", "Reviewer", "Looks correct.")
89 .with_rich_text(vec![RichTextRun::new("Looks correct.").with_bold(true)]),
90 );
91
92 let workbook = Workbook::new()
93 .with_sheet(dates_and_booleans_sheet)
94 .with_sheet(formulas_sheet)
95 .with_sheet(rich_text_sheet)
96 .with_sheet(hyperlinks_sheet)
97 .with_sheet(comments_sheet);
98
99 workbook.save_to_file(&path)?;
100 println!("Wrote {}", path.display());
101 Ok(())
102}Creates a shared-formula group’s master cell — the one carrying the group’s actual
formula text and its full range — and no cached value yet — see
Cell::with_cached_value to attach one. Pair with Cell::shared_formula_follower for
the group’s other cells, using the same group_index. See CellValue::SharedFormula’s
doc comment: this crate does not compute each follower’s own shifted formula text.
Examples found in repository?
13fn main() -> office_toolkit::Result<()> {
14 let path = output_path("xlsx_rich_data.xlsx");
15
16 let dates_and_booleans_sheet = Sheet::new("Dates and booleans")
17 .with_row(Row::new().with_cell(Cell::date(ExcelDateTime::date(2026, 7, 21))))
18 .with_row(Row::new().with_cell(Cell::date(
19 ExcelDateTime::date(2026, 7, 21).with_time(14, 30, 0),
20 )))
21 .with_row(
22 Row::new()
23 .with_cell(Cell::boolean(true))
24 .with_cell(Cell::boolean(false)),
25 );
26
27 // An array/shared formula's `ref` must be a range whose top-left cell
28 // is the cell the `<f t="array"|"shared">` element actually sits in —
29 // `with_cell` fills a row left-to-right starting at column A, so each
30 // formula cell below is positioned to land exactly on its own `ref`'s
31 // first cell, with plain cached-value cells (no `<f>`) filling out the
32 // rest of the declared range, matching how Excel itself writes a
33 // multi-cell array/shared formula. The previous version declared
34 // ranges like "D1:D3"/"E1:E3" while the formula cells actually landed
35 // in column A — a real cell/range mismatch Excel refuses to open
36 // without repairing.
37 let formulas_sheet = Sheet::new("Formulas")
38 .with_row(
39 Row::new()
40 .with_cell(Cell::number(10.0))
41 .with_cell(Cell::number(20.0))
42 .with_cell(Cell::formula("A1+B1").with_cached_value(30.0)),
43 )
44 .with_row(
45 Row::new()
46 .with_cell(Cell::array_formula("A1:A3*2", "A2:C2").with_cached_value(20.0))
47 .with_cell(Cell::number(40.0))
48 .with_cell(Cell::number(60.0)),
49 )
50 .with_row(
51 Row::new()
52 .with_cell(Cell::shared_formula("A1+1", 0, "A3:C3").with_cached_value(11.0))
53 .with_cell(Cell::shared_formula_follower(0).with_cached_value(21.0))
54 .with_cell(Cell::shared_formula_follower(0).with_cached_value(31.0)),
55 );
56
57 let rich_text_sheet =
58 Sheet::new("Rich text").with_row(Row::new().with_cell(Cell::rich_text(vec![
59 RichTextRun::new("Bold red, ").with_bold(true).with_font_color("FFC00000"),
60 RichTextRun::new("then italic blue.").with_italic(true).with_font_color("FF2E74B5"),
61 ])));
62
63 let hyperlinks_sheet = Sheet::new("Hyperlinks")
64 .with_row(
65 Row::new()
66 .with_text("Visit Rust")
67 .with_text("Jump to C1")
68 .with_text("You've arrived"),
69 )
70 .with_hyperlink(
71 CellHyperlink::external("A1", "https://www.rust-lang.org")
72 .with_tooltip("Opens in your browser"),
73 )
74 .with_hyperlink(CellHyperlink::internal("B1", "'Hyperlinks'!C1"));
75
76 let comments_sheet = Sheet::new("Comments")
77 .with_row(
78 Row::new()
79 .with_text("Hover B1 for a comment")
80 .with_text("Reviewed"),
81 )
82 .with_comment(CellComment::new(
83 "A1",
84 "Reviewer",
85 "Double-check this figure before publishing.",
86 ))
87 .with_comment(
88 CellComment::new("B1", "Reviewer", "Looks correct.")
89 .with_rich_text(vec![RichTextRun::new("Looks correct.").with_bold(true)]),
90 );
91
92 let workbook = Workbook::new()
93 .with_sheet(dates_and_booleans_sheet)
94 .with_sheet(formulas_sheet)
95 .with_sheet(rich_text_sheet)
96 .with_sheet(hyperlinks_sheet)
97 .with_sheet(comments_sheet);
98
99 workbook.save_to_file(&path)?;
100 println!("Wrote {}", path.display());
101 Ok(())
102}Creates a shared-formula group’s follower cell — no formula text and no range
(matching what real Excel itself writes for a follower, just t="shared" si=".."), only the
group’s shared group_index. See Cell::shared_formula for the group’s master cell.
Examples found in repository?
13fn main() -> office_toolkit::Result<()> {
14 let path = output_path("xlsx_rich_data.xlsx");
15
16 let dates_and_booleans_sheet = Sheet::new("Dates and booleans")
17 .with_row(Row::new().with_cell(Cell::date(ExcelDateTime::date(2026, 7, 21))))
18 .with_row(Row::new().with_cell(Cell::date(
19 ExcelDateTime::date(2026, 7, 21).with_time(14, 30, 0),
20 )))
21 .with_row(
22 Row::new()
23 .with_cell(Cell::boolean(true))
24 .with_cell(Cell::boolean(false)),
25 );
26
27 // An array/shared formula's `ref` must be a range whose top-left cell
28 // is the cell the `<f t="array"|"shared">` element actually sits in —
29 // `with_cell` fills a row left-to-right starting at column A, so each
30 // formula cell below is positioned to land exactly on its own `ref`'s
31 // first cell, with plain cached-value cells (no `<f>`) filling out the
32 // rest of the declared range, matching how Excel itself writes a
33 // multi-cell array/shared formula. The previous version declared
34 // ranges like "D1:D3"/"E1:E3" while the formula cells actually landed
35 // in column A — a real cell/range mismatch Excel refuses to open
36 // without repairing.
37 let formulas_sheet = Sheet::new("Formulas")
38 .with_row(
39 Row::new()
40 .with_cell(Cell::number(10.0))
41 .with_cell(Cell::number(20.0))
42 .with_cell(Cell::formula("A1+B1").with_cached_value(30.0)),
43 )
44 .with_row(
45 Row::new()
46 .with_cell(Cell::array_formula("A1:A3*2", "A2:C2").with_cached_value(20.0))
47 .with_cell(Cell::number(40.0))
48 .with_cell(Cell::number(60.0)),
49 )
50 .with_row(
51 Row::new()
52 .with_cell(Cell::shared_formula("A1+1", 0, "A3:C3").with_cached_value(11.0))
53 .with_cell(Cell::shared_formula_follower(0).with_cached_value(21.0))
54 .with_cell(Cell::shared_formula_follower(0).with_cached_value(31.0)),
55 );
56
57 let rich_text_sheet =
58 Sheet::new("Rich text").with_row(Row::new().with_cell(Cell::rich_text(vec![
59 RichTextRun::new("Bold red, ").with_bold(true).with_font_color("FFC00000"),
60 RichTextRun::new("then italic blue.").with_italic(true).with_font_color("FF2E74B5"),
61 ])));
62
63 let hyperlinks_sheet = Sheet::new("Hyperlinks")
64 .with_row(
65 Row::new()
66 .with_text("Visit Rust")
67 .with_text("Jump to C1")
68 .with_text("You've arrived"),
69 )
70 .with_hyperlink(
71 CellHyperlink::external("A1", "https://www.rust-lang.org")
72 .with_tooltip("Opens in your browser"),
73 )
74 .with_hyperlink(CellHyperlink::internal("B1", "'Hyperlinks'!C1"));
75
76 let comments_sheet = Sheet::new("Comments")
77 .with_row(
78 Row::new()
79 .with_text("Hover B1 for a comment")
80 .with_text("Reviewed"),
81 )
82 .with_comment(CellComment::new(
83 "A1",
84 "Reviewer",
85 "Double-check this figure before publishing.",
86 ))
87 .with_comment(
88 CellComment::new("B1", "Reviewer", "Looks correct.")
89 .with_rich_text(vec![RichTextRun::new("Looks correct.").with_bold(true)]),
90 );
91
92 let workbook = Workbook::new()
93 .with_sheet(dates_and_booleans_sheet)
94 .with_sheet(formulas_sheet)
95 .with_sheet(rich_text_sheet)
96 .with_sheet(hyperlinks_sheet)
97 .with_sheet(comments_sheet);
98
99 workbook.save_to_file(&path)?;
100 println!("Wrote {}", path.display());
101 Ok(())
102}Sourcepub fn with_cached_value(self, value: f64) -> Cell
pub fn with_cached_value(self, value: f64) -> Cell
Attaches a cached result value to a formula cell and returns the cell for chaining. A no-op
if this cell doesn’t hold
CellValue::Formula/CellValue::ArrayFormula/CellValue::SharedFormula (e.g. called on a
Cell::number).
Examples found in repository?
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}More examples
16fn main() -> office_toolkit::Result<()> {
17 let path = output_path("xlsx_tables.xlsx");
18
19 let plain_sheet = Sheet::new("Plain table")
20 .with_row(Row::new().with_text("Name").with_text("Score"))
21 .with_row(Row::new().with_text("Alice").with_number(92.0))
22 .with_row(Row::new().with_text("Bob").with_number(87.0))
23 .with_table(ExcelTable::new(
24 "ScoresTable",
25 "A1:B3",
26 vec!["Name", "Score"],
27 ));
28
29 let calculated_sheet = Sheet::new("Calculated and totals")
30 .with_row(
31 Row::new()
32 .with_text("Item")
33 .with_text("Qty")
34 .with_text("Unit price")
35 .with_text("Line total"),
36 )
37 .with_row(
38 Row::new()
39 .with_text("Widget")
40 .with_number(3.0)
41 .with_number(9.99)
42 .with_cell(Cell::formula("B2*C2").with_cached_value(29.97)),
43 )
44 .with_row(
45 Row::new()
46 .with_text("Gadget")
47 .with_number(2.0)
48 .with_number(19.99)
49 .with_cell(Cell::formula("B3*C3").with_cached_value(39.98)),
50 )
51 .with_row(Row::new().with_cell(Cell::text("Total")))
52 .with_table(
53 ExcelTable::with_columns(
54 "OrdersTable",
55 "A1:D4",
56 vec![
57 TableColumn::new("Item"),
58 TableColumn::new("Qty").with_totals_row_function(TotalsRowFunction::Sum),
59 TableColumn::new("Unit price"),
60 TableColumn::new("Line total")
61 .with_calculated_formula(
62 "OrdersTable[[#This Row],[Qty]]*OrdersTable[[#This Row],[Unit price]]",
63 )
64 .with_totals_row_function(TotalsRowFunction::Sum),
65 ],
66 )
67 .with_totals_row(true),
68 );
69
70 let styled_sheet = Sheet::new("Custom style and sort")
71 .with_row(Row::new().with_text("City").with_text("Population"))
72 .with_row(Row::new().with_text("Springfield").with_number(120_000.0))
73 .with_row(Row::new().with_text("Shelbyville").with_number(95_000.0))
74 .with_table(
75 ExcelTable::new("CitiesTable", "A1:B3", vec!["City", "Population"])
76 .with_table_style_name("CustomTableStyle")
77 .with_sort_state(
78 SortState::new("A2:B3")
79 .with_condition(SortCondition::new("B2:B3").with_descending(true)),
80 ),
81 );
82
83 let workbook = Workbook::new()
84 .with_table_style(
85 TableStyle::new("CustomTableStyle")
86 .with_element(TableStyleElement::new(
87 TableStyleElementType::HeaderRow,
88 CellFormat::new()
89 .with_bold(true)
90 .with_fill_color("FF2E74B5")
91 .with_font_color("FFFFFFFF"),
92 ))
93 .with_element(TableStyleElement::new(
94 TableStyleElementType::FirstRowStripe,
95 CellFormat::new().with_fill_color("FFF2F2F2"),
96 )),
97 )
98 .with_sheet(plain_sheet)
99 .with_sheet(calculated_sheet)
100 .with_sheet(styled_sheet);
101
102 workbook.save_to_file(&path)?;
103 println!("Wrote {}", path.display());
104 Ok(())
105}13fn main() -> office_toolkit::Result<()> {
14 let path = output_path("xlsx_rich_data.xlsx");
15
16 let dates_and_booleans_sheet = Sheet::new("Dates and booleans")
17 .with_row(Row::new().with_cell(Cell::date(ExcelDateTime::date(2026, 7, 21))))
18 .with_row(Row::new().with_cell(Cell::date(
19 ExcelDateTime::date(2026, 7, 21).with_time(14, 30, 0),
20 )))
21 .with_row(
22 Row::new()
23 .with_cell(Cell::boolean(true))
24 .with_cell(Cell::boolean(false)),
25 );
26
27 // An array/shared formula's `ref` must be a range whose top-left cell
28 // is the cell the `<f t="array"|"shared">` element actually sits in —
29 // `with_cell` fills a row left-to-right starting at column A, so each
30 // formula cell below is positioned to land exactly on its own `ref`'s
31 // first cell, with plain cached-value cells (no `<f>`) filling out the
32 // rest of the declared range, matching how Excel itself writes a
33 // multi-cell array/shared formula. The previous version declared
34 // ranges like "D1:D3"/"E1:E3" while the formula cells actually landed
35 // in column A — a real cell/range mismatch Excel refuses to open
36 // without repairing.
37 let formulas_sheet = Sheet::new("Formulas")
38 .with_row(
39 Row::new()
40 .with_cell(Cell::number(10.0))
41 .with_cell(Cell::number(20.0))
42 .with_cell(Cell::formula("A1+B1").with_cached_value(30.0)),
43 )
44 .with_row(
45 Row::new()
46 .with_cell(Cell::array_formula("A1:A3*2", "A2:C2").with_cached_value(20.0))
47 .with_cell(Cell::number(40.0))
48 .with_cell(Cell::number(60.0)),
49 )
50 .with_row(
51 Row::new()
52 .with_cell(Cell::shared_formula("A1+1", 0, "A3:C3").with_cached_value(11.0))
53 .with_cell(Cell::shared_formula_follower(0).with_cached_value(21.0))
54 .with_cell(Cell::shared_formula_follower(0).with_cached_value(31.0)),
55 );
56
57 let rich_text_sheet =
58 Sheet::new("Rich text").with_row(Row::new().with_cell(Cell::rich_text(vec![
59 RichTextRun::new("Bold red, ").with_bold(true).with_font_color("FFC00000"),
60 RichTextRun::new("then italic blue.").with_italic(true).with_font_color("FF2E74B5"),
61 ])));
62
63 let hyperlinks_sheet = Sheet::new("Hyperlinks")
64 .with_row(
65 Row::new()
66 .with_text("Visit Rust")
67 .with_text("Jump to C1")
68 .with_text("You've arrived"),
69 )
70 .with_hyperlink(
71 CellHyperlink::external("A1", "https://www.rust-lang.org")
72 .with_tooltip("Opens in your browser"),
73 )
74 .with_hyperlink(CellHyperlink::internal("B1", "'Hyperlinks'!C1"));
75
76 let comments_sheet = Sheet::new("Comments")
77 .with_row(
78 Row::new()
79 .with_text("Hover B1 for a comment")
80 .with_text("Reviewed"),
81 )
82 .with_comment(CellComment::new(
83 "A1",
84 "Reviewer",
85 "Double-check this figure before publishing.",
86 ))
87 .with_comment(
88 CellComment::new("B1", "Reviewer", "Looks correct.")
89 .with_rich_text(vec![RichTextRun::new("Looks correct.").with_bold(true)]),
90 );
91
92 let workbook = Workbook::new()
93 .with_sheet(dates_and_booleans_sheet)
94 .with_sheet(formulas_sheet)
95 .with_sheet(rich_text_sheet)
96 .with_sheet(hyperlinks_sheet)
97 .with_sheet(comments_sheet);
98
99 workbook.save_to_file(&path)?;
100 println!("Wrote {}", path.display());
101 Ok(())
102}Sourcepub fn with_format(self, format: CellFormat) -> Cell
pub fn with_format(self, format: CellFormat) -> Cell
Attaches a cell style and returns the cell for chaining.
Examples found in repository?
15fn main() -> office_toolkit::Result<()> {
16 let path = output_path("xlsx_cell_formatting.xlsx");
17
18 let borders_sheet =
19 Sheet::new("Borders").with_row(
20 Row::new()
21 .with_cell(Cell::text("Thin all around").with_format(
22 CellFormat::new().with_border(Border::all(BorderStyle::Thin, "FF000000")),
23 ))
24 .with_cell(Cell::text("Thick bottom only").with_format(
25 CellFormat::new().with_border(
26 Border::new().with_bottom(
27 BorderEdge::new(BorderStyle::Thick).with_color("FFC00000"),
28 ),
29 ),
30 )),
31 );
32
33 let fills_sheet = Sheet::new("Fills")
34 .with_row(Row::new().with_cell(
35 Cell::text("Solid fill").with_format(CellFormat::new().with_fill_color("FFFFF2CC")),
36 ))
37 .with_row(
38 Row::new().with_cell(
39 Cell::text("Pattern fill").with_format(
40 CellFormat::new().with_pattern_fill(
41 PatternFill::new(PatternType::LightGray)
42 .with_fg_color("FF4472C4")
43 .with_bg_color("FFFFFFFF"),
44 ),
45 ),
46 ),
47 )
48 .with_row(
49 Row::new().with_cell(Cell::text("Gradient fill").with_format(
50 CellFormat::new().with_gradient_fill(GradientFill::new(
51 90.0,
52 vec![
53 GradientStop::new(0.0, "FFFFFFFF"),
54 GradientStop::new(1.0, "FF4472C4"),
55 ],
56 )),
57 )),
58 );
59
60 let fonts_and_alignment_sheet =
61 Sheet::new("Fonts and alignment")
62 .with_row(
63 Row::new().with_cell(
64 Cell::text("Bold, red, 14pt").with_format(
65 CellFormat::new()
66 .with_bold(true)
67 .with_font_size(14.0)
68 .with_font_color("FFC00000"),
69 ),
70 ),
71 )
72 .with_row(
73 Row::new().with_cell(
74 Cell::text("Centered both ways").with_format(
75 CellFormat::new()
76 .with_horizontal_alignment(HorizontalAlignment::Center)
77 .with_vertical_alignment(VerticalAlignment::Center),
78 ),
79 ),
80 )
81 .with_row(Row::new().with_cell(
82 Cell::text("Indented text").with_format(CellFormat::new().with_indent(2)),
83 ));
84
85 let number_formats_sheet = Sheet::new("Number formats")
86 .with_row(Row::new().with_cell(
87 Cell::number(1234.5).with_format(CellFormat::new().with_number_format("#,##0.00")),
88 ))
89 .with_row(Row::new().with_cell(
90 Cell::number(0.0825).with_format(CellFormat::new().with_number_format("0.00%")),
91 ))
92 .with_row(Row::new().with_cell(
93 Cell::number(1234.5).with_format(CellFormat::new().with_number_format("$#,##0.00")),
94 ));
95
96 let named_styles_sheet = Sheet::new("Named styles").with_row(
97 Row::new().with_cell(
98 Cell::text("Uses a named style")
99 .with_format(CellFormat::new().with_named_style("Emphasis")),
100 ),
101 );
102
103 let workbook = Workbook::new()
104 .with_named_cell_style(NamedCellStyle::new(
105 "Emphasis",
106 CellFormat::new()
107 .with_bold(true)
108 .with_font_color("FF4472C4"),
109 ))
110 .with_sheet(borders_sheet)
111 .with_sheet(fills_sheet)
112 .with_sheet(fonts_and_alignment_sheet)
113 .with_sheet(number_formats_sheet)
114 .with_sheet(named_styles_sheet);
115
116 workbook.save_to_file(&path)?;
117 println!("Wrote {}", path.display());
118 Ok(())
119}Trait Implementations§
Source§impl From<&str> for Cell
Lets Sheet::write_cell accept a raw string directly (sheet.write_cell(1, 1, "Bonjour"))
instead of requiring Cell::text("Bonjour") — same rationale as the f64/bool impls below;
see Sheet::write_cell’s doc comment.
impl From<&str> for Cell
Lets Sheet::write_cell accept a raw string directly (sheet.write_cell(1, 1, "Bonjour"))
instead of requiring Cell::text("Bonjour") — same rationale as the f64/bool impls below;
see Sheet::write_cell’s doc comment.
Source§impl From<bool> for Cell
Lets Sheet::write_cell accept a raw bool directly (sheet.write_cell(1, 1, true)) instead
of requiring Cell::boolean(true).
impl From<bool> for Cell
Lets Sheet::write_cell accept a raw bool directly (sheet.write_cell(1, 1, true)) instead
of requiring Cell::boolean(true).
Source§impl From<f64> for Cell
Lets Sheet::write_cell accept a raw f64 directly (sheet.write_cell(1, 1, 42.0)) instead
of requiring Cell::number(42.0).
impl From<f64> for Cell
Lets Sheet::write_cell accept a raw f64 directly (sheet.write_cell(1, 1, 42.0)) instead
of requiring Cell::number(42.0).