Oregami
Repositories/oxedyne/fe2o3

oxedyne/fe2o3/fe2o3_file/examples/make_xlsx.rs

2.7 KiB, 5 runs

created by r1870400018:22738, which is this file's identity for as long as the history lasts, whatever it is later renamed to

download · who wrote it · its history

1//! Writes a `.xlsx` holding one of everything, so an external reader can be asked what it makes of it.
2//!
3//! A spreadsheet is the format where reading your own output proves least, because the interesting
4//! cases -- a shared string, a date that is really a number, a formula whose cached value is what
5//! everyone sees -- are all conventions rather than structure. A file that satisfies this crate's own
6//! reader may still open in Excel as five columns of five-digit integers.
7//!
8//! ```text
9//! cargo run -p oxedyne_fe2o3_file --example make_xlsx -- out.xlsx
10//! soffice --headless --convert-to csv out.xlsx
11//! ```
12//!
13//! `dev/xlsx_oracle.sh` does that and prints what came back.
14//!
15//! [Written with AI entirely](https://need2know.ai/entirely-ai/code)\
16//! Anthropic Claude
17
18use oxedyne_fe2o3_core::prelude::*;
19use oxedyne_fe2o3_file::office::sheet::{
20 Book,
21 Cell,
22 Sheet,
23 Value,
24};
25use oxedyne_fe2o3_file::office::xlsx;
26
27fn main() -> Outcome<()> {
28 let args: Vec<String> = std::env::args().collect();
29 if args.len() != 2 {
30 return Err(err!("Usage: make_xlsx <xlsx out>"; Invalid, Input));
31 }
32 let mut sales = Sheet::new("Sales");
33 sales.rows.push(vec![
34 Cell::text("Region"), Cell::text("Units"), Cell::text("Price"), Cell::text("Total"),
35 Cell::text("Booked"), Cell::text("Active"),
36 ]);
37 // A formula and the value the last calculation left beside it. Both are written; a formula with
38 // no cached value shows as blank in every reader that does not calculate.
39 sales.rows.push(vec![
40 Cell::text("North"), Cell::number(120.0), Cell::number(3.4),
41 Cell::formula("B2*C2", Value::Number(408.0)),
42 Cell { value: Value::Date("2026-03-14".to_string()), formula: None },
43 Cell::bool(true),
44 ]);
45 sales.rows.push(vec![
46 Cell::text("South"), Cell::number(85.0), Cell::number(11.0),
47 Cell::formula("B3*C3", Value::Number(935.0)),
48 Cell { value: Value::Date("2026-04-01".to_string()), formula: None },
49 Cell::bool(false),
50 ]);
51 // A gap, then a total: the sparse case, which is where a reader that counts positions instead of
52 // reading addresses puts everything one column out.
53 sales.rows.push(Vec::new());
54 sales.rows.push(vec![
55 Cell::text("Total"), Cell::empty(), Cell::empty(),
56 Cell::formula("SUM(D2:D3)", Value::Number(1343.0)),
57 ]);
58 // A string that is only spaces, and one with markup in it: both are text and neither is markup.
59 let mut notes = Sheet::new("Notes");
60 notes.rows.push(vec![Cell::text(" "), Cell::text("a < b & c"), Cell::text("3.40")]);
61
62 let book = Book { sheets: vec![sales, notes] };
63 let bytes = res!(xlsx::write(&book));
64 res!(std::fs::write(&args[1], &bytes), IO, File);
65 println!("{}: {} bytes, {} sheets", args[1], bytes.len(), book.sheets.len());
66 Ok(())
67}