pub struct Workbook {
pub sheets: Vec<Sheet>,
pub defined_names: Vec<DefinedName>,
pub properties: DocumentProperties,
pub protection: Option<WorkbookProtection>,
pub write_protection: Option<WriteProtection>,
pub active_tab: Option<usize>,
pub external_links: Vec<ExternalWorkbookLink>,
pub vba_project: Option<Vec<u8>>,
pub calculation: Option<CalculationProperties>,
pub table_styles: Vec<TableStyle>,
pub named_cell_styles: Vec<NamedCellStyle>,
}Expand description
A .xlsx workbook: a sequence of sheets, in the order they appear in Excel’s own sheet tabs.
Fields§
§sheets: Vec<Sheet>The sheets that make up this workbook, in order.
defined_names: Vec<DefinedName>Named ranges/formulas/constants defined on this workbook (<definedNames>/<definedName>,
CT_DefinedNames/CT_DefinedName), in order. Unlike a sheet, this lives at the workbook
level even for a name scoped to a single sheet (see DefinedName::local_sheet_id).
properties: DocumentPropertiesDocument metadata (docProps/core.xml/docProps/app.xml). Both parts are always written by
this crate (they’re required for a strictly valid package), but before this point every
field in them was left empty/boilerplate.
protection: Option<WorkbookProtection>Workbook structure protection (<workbookProtection>, CT_WorkbookProtection). Distinct
from Sheet::protection: this locks whether sheets can be
added/renamed/hidden/reordered/deleted, not cell editing within a sheet.
write_protection: Option<WriteProtection>Write-protection / “read-only recommended” (<fileSharing>, CT_FileSharing). Distinct
from protection (<workbookProtection>, point 26, which locks
structure): this instead controls the “This file should be opened as read-only” prompt
Excel shows when opening the file, and/or the legacy 16-bit write-reservation password some
older workflows still use. Confirmed via sml.xsd: CT_Workbook’s sequence puts
fileSharing? before workbookPr?/ workbookProtection?/bookViews?, i.e. as the very
first possible child of <workbook>.
active_tab: Option<usize>The 0-based index into sheets of the sheet shown as active/selected
when the workbook is opened (<bookViews><workbookView activeTab="..">). None leaves
Excel’s own default (the first sheet).
external_links: Vec<ExternalWorkbookLink>References to other workbooks used by this workbook’s formulas (<externalReferences> + one
xl/externalLinks/externalLinkN.xml part per entry, CT_ExternalReference). Storage only,
same posture as this crate’s own formula text: nothing here resolves or evaluates a
reference into the other workbook’s actual values.
vba_project: Option<Vec<u8>>A VBA project’s raw compiled bytes (xl/vbaProject.bin), if this workbook carries macros.
Preserved opaquely: this crate can round-trip an existing macro-enabled workbook’s
vbaProject.bin unchanged but cannot create, parse, or modify VBA source from scratch; the
OLE2/ CFB container format vbaProject.bin is internally structured in isn’t decoded at
all. When Some, Workbook::write_to switches the workbook part’s content type to the
macro-enabled variant (..sheet.macroEnabled.main+xml) — the caller is still responsible
for using a .xlsm file name, this crate has no notion of file extensions.
calculation: Option<CalculationProperties>Workbook-wide calculation properties (<calcPr>, CT_CalcPr). None leaves Excel’s own
default (automatic recalculation, no iterative calculation).
table_styles: Vec<TableStyle>Custom table style definitions (xl/styles.xml’s <tableStyles>), referenced by name from
any sheet’s ExcelTable::table_style_name. Workbook-wide (styles.xml is a single shared
part), same posture as defined_names living here rather than per-sheet even for a
sheet-scoped name.
named_cell_styles: Vec<NamedCellStyle>Named cell styles (xl/styles.xml’s <cellStyles>/<cellStyleXfs>,
CT_CellStyles/CT_CellStyleXfs): the “Cell Styles” gallery Excel’s Home ribbon shows
(Good/ Bad/Neutral, Heading 1-4, Input/Output/Calculation,
Currency/Percent/Comma..). Before this point every cellXfs entry this crate wrote
implicitly pointed at a single, hardcoded "Normal" cellStyleXfs entry (xfId="0") — a
cell format that set CellFormat::named_style had no way to actually link back to one of
these named entries, so the association was silently lost on write. A CellFormat used
anywhere in this workbook (cell, row/column default..) that sets named_style to a name
found here gets that entry’s index written as its cellXfs xfId, instead of the default
0; a name not found here silently falls back to 0 ("Normal"), same “best-effort, not
validated” posture as ExcelTable::table_style_name referencing a name not in this same
list. Workbook-wide (styles.xml is a single shared part), same posture as
table_styles/defined_names living here rather than per-sheet.
Implementations§
Source§impl Workbook
impl Workbook
Sourcepub fn new() -> Workbook
pub fn new() -> Workbook
Creates an empty workbook (no sheets).
Examples found in repository?
13fn main() -> office_toolkit::Result<()> {
14 let path = output_path("hello_world.xlsx");
15
16 // `Workbook` and `Row` both come from `office_toolkit::prelude`.
17 // `Row::with_text` puts a single text cell in column A.
18 let workbook = Workbook::new()
19 .with_sheet(Sheet::new("Sheet1").with_row(Row::new().with_text("Hello, world!")));
20 workbook.save_to_file(&path)?;
21 println!("Wrote {}", path.display());
22
23 // Read the file back to confirm it is a valid .xlsx.
24 let reopened = Workbook::open_file(&path)?;
25 let cell_a1 = &reopened.sheets[0].rows[0].cells[0].value;
26 println!("Read back A1: {cell_a1:?}");
27 assert!(matches!(cell_a1, CellValue::Text(text) if text == "Hello, world!"));
28
29 Ok(())
30}More examples
21fn main() -> office_toolkit::Result<()> {
22 let path = output_path("xlsx_images_and_charts.xlsx");
23 let image_bytes = std::fs::read(image_fixture_path())?;
24
25 let picture = SheetPicture::new(image_bytes, PictureFormat::Png).with_name("Test image");
26 let picture_sheet = Sheet::new("Picture")
27 .with_row(Row::new().with_text("The picture is anchored to cell A1:"))
28 .with_drawing(SheetDrawing::new().with_anchor(DrawingAnchor::new(
29 CellAnchorPoint::new(0, 1),
30 CellAnchorPoint::new(2, 6),
31 DrawingObject::Picture(Box::new(picture)),
32 )));
33
34 let chart = SheetChart::new(sample_chart_space()).with_name("Quarterly revenue");
35 let chart_sheet = Sheet::new("Chart")
36 .with_row(Row::new().with_text("A bar chart is anchored below:"))
37 .with_drawing(SheetDrawing::new().with_anchor(DrawingAnchor::new(
38 CellAnchorPoint::new(0, 1),
39 CellAnchorPoint::new(6, 16),
40 DrawingObject::Chart(Box::new(chart)),
41 )));
42
43 let workbook = Workbook::new()
44 .with_sheet(picture_sheet)
45 .with_sheet(chart_sheet);
46 workbook.save_to_file(&path)?;
47 println!("Wrote {}", path.display());
48 Ok(())
49}16fn main() -> office_toolkit::Result<()> {
17 let path = output_path("xlsx_protection.xlsx");
18
19 let sheet_protection_sheet = Sheet::new("Sheet protection")
20 .with_row(Row::new().with_text("Locked: this sheet is protected with a password."))
21 .with_protection(SheetProtection::with_password("secret"));
22
23 let protected_range_sheet = Sheet::new("Protected range")
24 .with_row(
25 Row::new()
26 .with_text("A1 is protected; B1 stays editable via a named unprotected range."),
27 )
28 .with_protection(SheetProtection::locked())
29 .with_protected_range(ProtectedRange::new("EditableArea", "B1:B1").with_password("secret"));
30
31 let workbook = Workbook::new()
32 .with_write_protection(
33 WriteProtection::recommended()
34 .with_user_name("Author")
35 .with_password("secret"),
36 )
37 .with_sheet(sheet_protection_sheet)
38 .with_sheet(protected_range_sheet);
39
40 // `Workbook.protection` (structure protection: locking sheet
41 // add/rename/hide/reorder/delete) has no `with_*` builder — it's set
42 // directly, like any other public field.
43 let workbook = Workbook {
44 protection: Some(WorkbookProtection::locked().with_lock_windows(true)),
45 ..workbook
46 };
47
48 workbook.save_to_file(&path)?;
49 println!("Wrote {}", path.display());
50 Ok(())
51}14fn main() -> office_toolkit::Result<()> {
15 let path = output_path("xlsx_print_and_views.xlsx");
16
17 let print_setup_sheet = Sheet::new("Print setup")
18 .with_row(Row::new().with_text("Header").with_text("Header"))
19 .with_row(Row::new().with_text("Data").with_number(1.0))
20 .with_print_settings(
21 PrintSettings::new()
22 .with_print_area("A1:B2")
23 .with_repeat_rows("1:1")
24 .with_fit_to_width(1)
25 .with_fit_to_height(0)
26 .with_scale(100)
27 .with_orientation(PageOrientation::Landscape)
28 .with_header("&CCompany Report")
29 .with_footer("&LPage &P of &N"),
30 );
31
32 let view_options_sheet = Sheet::new("View options")
33 .with_row(Row::new().with_text("Zoomed, colored tab, no gridlines"))
34 .with_zoom_scale(150)
35 .with_tab_color("FFC00000")
36 .with_show_grid_lines(false)
37 .with_show_row_col_headers(false)
38 .with_show_zeros(false)
39 .with_right_to_left(false)
40 .with_active_cell("A1")
41 .with_default_column_width(12.0)
42 .with_default_row_height(18.0);
43
44 let hidden_sheet = Sheet::new("Hidden sheet")
45 .with_row(Row::new().with_text("Not shown in the tab bar unless unhidden."))
46 .with_visibility(SheetVisibility::Hidden);
47
48 let workbook = Workbook::new()
49 .with_sheet(print_setup_sheet)
50 .with_sheet(view_options_sheet)
51 .with_sheet(hidden_sheet);
52
53 workbook.save_to_file(&path)?;
54 println!("Wrote {}", path.display());
55 Ok(())
56}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}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}Sourcepub fn with_sheet(self, sheet: Sheet) -> Workbook
pub fn with_sheet(self, sheet: Sheet) -> Workbook
Appends a sheet and returns the workbook for chaining.
Examples found in repository?
13fn main() -> office_toolkit::Result<()> {
14 let path = output_path("hello_world.xlsx");
15
16 // `Workbook` and `Row` both come from `office_toolkit::prelude`.
17 // `Row::with_text` puts a single text cell in column A.
18 let workbook = Workbook::new()
19 .with_sheet(Sheet::new("Sheet1").with_row(Row::new().with_text("Hello, world!")));
20 workbook.save_to_file(&path)?;
21 println!("Wrote {}", path.display());
22
23 // Read the file back to confirm it is a valid .xlsx.
24 let reopened = Workbook::open_file(&path)?;
25 let cell_a1 = &reopened.sheets[0].rows[0].cells[0].value;
26 println!("Read back A1: {cell_a1:?}");
27 assert!(matches!(cell_a1, CellValue::Text(text) if text == "Hello, world!"));
28
29 Ok(())
30}More examples
21fn main() -> office_toolkit::Result<()> {
22 let path = output_path("xlsx_images_and_charts.xlsx");
23 let image_bytes = std::fs::read(image_fixture_path())?;
24
25 let picture = SheetPicture::new(image_bytes, PictureFormat::Png).with_name("Test image");
26 let picture_sheet = Sheet::new("Picture")
27 .with_row(Row::new().with_text("The picture is anchored to cell A1:"))
28 .with_drawing(SheetDrawing::new().with_anchor(DrawingAnchor::new(
29 CellAnchorPoint::new(0, 1),
30 CellAnchorPoint::new(2, 6),
31 DrawingObject::Picture(Box::new(picture)),
32 )));
33
34 let chart = SheetChart::new(sample_chart_space()).with_name("Quarterly revenue");
35 let chart_sheet = Sheet::new("Chart")
36 .with_row(Row::new().with_text("A bar chart is anchored below:"))
37 .with_drawing(SheetDrawing::new().with_anchor(DrawingAnchor::new(
38 CellAnchorPoint::new(0, 1),
39 CellAnchorPoint::new(6, 16),
40 DrawingObject::Chart(Box::new(chart)),
41 )));
42
43 let workbook = Workbook::new()
44 .with_sheet(picture_sheet)
45 .with_sheet(chart_sheet);
46 workbook.save_to_file(&path)?;
47 println!("Wrote {}", path.display());
48 Ok(())
49}16fn main() -> office_toolkit::Result<()> {
17 let path = output_path("xlsx_protection.xlsx");
18
19 let sheet_protection_sheet = Sheet::new("Sheet protection")
20 .with_row(Row::new().with_text("Locked: this sheet is protected with a password."))
21 .with_protection(SheetProtection::with_password("secret"));
22
23 let protected_range_sheet = Sheet::new("Protected range")
24 .with_row(
25 Row::new()
26 .with_text("A1 is protected; B1 stays editable via a named unprotected range."),
27 )
28 .with_protection(SheetProtection::locked())
29 .with_protected_range(ProtectedRange::new("EditableArea", "B1:B1").with_password("secret"));
30
31 let workbook = Workbook::new()
32 .with_write_protection(
33 WriteProtection::recommended()
34 .with_user_name("Author")
35 .with_password("secret"),
36 )
37 .with_sheet(sheet_protection_sheet)
38 .with_sheet(protected_range_sheet);
39
40 // `Workbook.protection` (structure protection: locking sheet
41 // add/rename/hide/reorder/delete) has no `with_*` builder — it's set
42 // directly, like any other public field.
43 let workbook = Workbook {
44 protection: Some(WorkbookProtection::locked().with_lock_windows(true)),
45 ..workbook
46 };
47
48 workbook.save_to_file(&path)?;
49 println!("Wrote {}", path.display());
50 Ok(())
51}14fn main() -> office_toolkit::Result<()> {
15 let path = output_path("xlsx_print_and_views.xlsx");
16
17 let print_setup_sheet = Sheet::new("Print setup")
18 .with_row(Row::new().with_text("Header").with_text("Header"))
19 .with_row(Row::new().with_text("Data").with_number(1.0))
20 .with_print_settings(
21 PrintSettings::new()
22 .with_print_area("A1:B2")
23 .with_repeat_rows("1:1")
24 .with_fit_to_width(1)
25 .with_fit_to_height(0)
26 .with_scale(100)
27 .with_orientation(PageOrientation::Landscape)
28 .with_header("&CCompany Report")
29 .with_footer("&LPage &P of &N"),
30 );
31
32 let view_options_sheet = Sheet::new("View options")
33 .with_row(Row::new().with_text("Zoomed, colored tab, no gridlines"))
34 .with_zoom_scale(150)
35 .with_tab_color("FFC00000")
36 .with_show_grid_lines(false)
37 .with_show_row_col_headers(false)
38 .with_show_zeros(false)
39 .with_right_to_left(false)
40 .with_active_cell("A1")
41 .with_default_column_width(12.0)
42 .with_default_row_height(18.0);
43
44 let hidden_sheet = Sheet::new("Hidden sheet")
45 .with_row(Row::new().with_text("Not shown in the tab bar unless unhidden."))
46 .with_visibility(SheetVisibility::Hidden);
47
48 let workbook = Workbook::new()
49 .with_sheet(print_setup_sheet)
50 .with_sheet(view_options_sheet)
51 .with_sheet(hidden_sheet);
52
53 workbook.save_to_file(&path)?;
54 println!("Wrote {}", path.display());
55 Ok(())
56}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}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}Sourcepub fn add_sheet(&mut self, name: impl Into<String>) -> &mut Sheet
pub fn add_sheet(&mut self, name: impl Into<String>) -> &mut Sheet
Appends an empty sheet with the given name and returns a mutable reference to it, to build
it up in place (e.g. workbook.add_sheet("Feuil1").write_cell(1, 1, Cell::text("Hi"))). A
&mut self counterpart to Self::with_sheet, for building a workbook sheet-by-sheet in a
loop without the consuming builder’s workbook = workbook.with_sheet(..) reassignment on
every iteration.
Sourcepub fn with_defined_name(self, defined_name: DefinedName) -> Workbook
pub fn with_defined_name(self, defined_name: DefinedName) -> Workbook
Appends a defined name and returns the workbook for chaining.
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}Sourcepub fn with_calculation(self, calculation: CalculationProperties) -> Workbook
pub fn with_calculation(self, calculation: CalculationProperties) -> Workbook
Sets this workbook’s calculation properties and returns it for chaining.
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}Sourcepub fn with_table_style(self, table_style: TableStyle) -> Workbook
pub fn with_table_style(self, table_style: TableStyle) -> Workbook
Appends a custom table style definition and returns the workbook for chaining. See
ExcelTable::table_style_name’s doc comment for how a table references one of these by
name.
Examples found in repository?
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}Sourcepub fn with_write_protection(
self,
write_protection: WriteProtection,
) -> Workbook
pub fn with_write_protection( self, write_protection: WriteProtection, ) -> Workbook
Sets this workbook’s write-protection and returns it for chaining.
Examples found in repository?
16fn main() -> office_toolkit::Result<()> {
17 let path = output_path("xlsx_protection.xlsx");
18
19 let sheet_protection_sheet = Sheet::new("Sheet protection")
20 .with_row(Row::new().with_text("Locked: this sheet is protected with a password."))
21 .with_protection(SheetProtection::with_password("secret"));
22
23 let protected_range_sheet = Sheet::new("Protected range")
24 .with_row(
25 Row::new()
26 .with_text("A1 is protected; B1 stays editable via a named unprotected range."),
27 )
28 .with_protection(SheetProtection::locked())
29 .with_protected_range(ProtectedRange::new("EditableArea", "B1:B1").with_password("secret"));
30
31 let workbook = Workbook::new()
32 .with_write_protection(
33 WriteProtection::recommended()
34 .with_user_name("Author")
35 .with_password("secret"),
36 )
37 .with_sheet(sheet_protection_sheet)
38 .with_sheet(protected_range_sheet);
39
40 // `Workbook.protection` (structure protection: locking sheet
41 // add/rename/hide/reorder/delete) has no `with_*` builder — it's set
42 // directly, like any other public field.
43 let workbook = Workbook {
44 protection: Some(WorkbookProtection::locked().with_lock_windows(true)),
45 ..workbook
46 };
47
48 workbook.save_to_file(&path)?;
49 println!("Wrote {}", path.display());
50 Ok(())
51}Sourcepub fn with_named_cell_style(self, named_cell_style: NamedCellStyle) -> Workbook
pub fn with_named_cell_style(self, named_cell_style: NamedCellStyle) -> Workbook
Appends a named cell style definition and returns the workbook for chaining. See
CellFormat::named_style’s doc comment for how a format references one of these by name.
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}Source§impl Workbook
impl Workbook
Sourcepub fn write_to<W>(&self, writer: W) -> Result<W, Error>
pub fn write_to<W>(&self, writer: W) -> Result<W, Error>
Writes this workbook out as a valid .xlsx package.
Writes [Content_Types].xml, _rels/.rels, xl/workbook.xml,
xl/_rels/workbook.xml.rels, one xl/worksheets/sheetN.xml per sheet, xl/styles.xml,
xl/sharedStrings.xml, docProps/core.xml, docProps/app.xml, and xl/theme/theme1.xml
(always the fixed default “Office” theme —; this crate has no notion of a customizable theme
model, unlike word-ooxml’s Theme). xl/calcChain.xml is still never written — it only
matters for formula dependency ordering, which this crate leaves to Excel to recompute on
open. xl/vbaProject.bin and xl/externalLinks/externalLinkN.xml are written only when
Workbook::vba_project/Workbook::external_links are non-empty.
Trait Implementations§
Source§impl SaveToFile for Workbook
Available on crate feature excel only.
impl SaveToFile for Workbook
excel only.