Skip to main content

temporal_style_fixture/
temporal_style_fixture.rs

1//! Shared component-preserving temporal assignment across existing number formats.
2use crabxl::{
3    Alignment, Border, BorderLine, BorderSide, Cell, CellAddress, CellStyle, CellValue, Color,
4    ColorKind, ExcelDateTime, Fill, FillPattern, Font, PatternFill, Row, RowIndex, SheetId,
5    StyleId, Workbook, WorkbookLimits, WorkbookWriter, WriteOptions,
6};
7// One stack-owned fixture sink; boxing would add a mode-only allocation.
8#[allow(clippy::large_enum_variant)]
9enum Output {
10    Streaming(WorkbookWriter),
11    Owned {
12        book: Workbook,
13        sheet: Option<SheetId>,
14    },
15}
16impl Output {
17    fn register_style(&mut self, style: CellStyle) -> crabxl::Result<StyleId> {
18        match self {
19            Self::Streaming(writer) => writer.register_style(style),
20            Self::Owned { book, .. } => book.register_style(style),
21        }
22    }
23    fn start_sheet(&mut self) -> crabxl::Result<()> {
24        match self {
25            Self::Streaming(writer) => writer.start_sheet("Sheet"),
26            Self::Owned { book, sheet } => {
27                *sheet = Some(book.create_sheet("Sheet")?);
28                Ok(())
29            }
30        }
31    }
32    fn write_row(&mut self, row: &mut Row) -> crabxl::Result<()> {
33        match self {
34            Self::Streaming(writer) => writer.write_row(row),
35            Self::Owned { book, sheet } => {
36                let id = sheet.ok_or_else(|| {
37                    crabxl::Error::new(crabxl::ErrorKind::InvalidState, "Missing fixture sheet")
38                })?;
39                let mut editor = book.sheet_mut(id)?;
40                for cell in row.cells.drain(..) {
41                    editor.set(cell)?;
42                }
43                Ok(())
44            }
45        }
46    }
47    fn finish(self, path: String) -> crabxl::Result<()> {
48        let writer = match self {
49            Self::Streaming(mut writer) => {
50                writer.close_sheet()?;
51                writer
52            }
53            Self::Owned { book, .. } => {
54                eprintln!("BANK_BYTES {}", book.charged_bytes());
55                WorkbookWriter::from_workbook(WriteOptions::default(), book)?
56            }
57        };
58        eprintln!("STYLE_BYTES {}", writer.style_memory_bytes());
59        eprintln!("TEMP_BYTES {}", writer.stats().peak_temp_bytes);
60        writer.finish(std::fs::File::create(path).map_err(|error| {
61            crabxl::Error::caused_by(crabxl::ErrorKind::Io, "Cannot create fixture", error)
62        })?)?;
63        Ok(())
64    }
65}
66fn main() -> Result<(), Box<dyn std::error::Error>> {
67    let mut arguments = std::env::args().skip(1);
68    let path = arguments.next().ok_or("Missing output")?;
69    let rows: u32 = arguments.next().as_deref().unwrap_or("4").parse()?;
70    if rows == 0 || rows > 1_048_576 {
71        return Err("Invalid row count".into());
72    }
73    let mut writer = match arguments.next().as_deref() {
74        None => Output::Streaming(WorkbookWriter::new(WriteOptions::default())?),
75        Some("owned") => Output::Owned {
76            book: Workbook::new(WorkbookLimits::default())?,
77            sheet: None,
78        },
79        Some(_) => return Err("Unknown fixture mode".into()),
80    };
81    let mut identities = Vec::<StyleId>::new();
82    identities.try_reserve_exact(5)?;
83    for code in ["General", "0.00", "yyyy-mm-dd", "hh:mm:ss", "[h]:mm:ss"] {
84        identities.push(writer.register_style(CellStyle {
85            number_format: code.into(),
86            font: Font {
87                name: Some("Public temporal font".into()),
88                size: Some(14.0),
89                bold: Some(true),
90                color: Some(Color {
91                    kind: ColorKind::Argb(0xff112233),
92                    tint: None,
93                }),
94                ..Default::default()
95            },
96            fill: Fill::Pattern(PatternFill {
97                pattern: Some(FillPattern::Solid),
98                foreground: Some(Color {
99                    kind: ColorKind::Argb(0xff445566),
100                    tint: None,
101                }),
102                ..Default::default()
103            }),
104            borders: {
105                let mut border = Border::default();
106                border.sides[0] = Some(BorderSide {
107                    line: Some(BorderLine::Thin),
108                    color: Some(Color {
109                        kind: ColorKind::Argb(0xff778899),
110                        tint: None,
111                    }),
112                });
113                border
114            },
115            alignment: Alignment {
116                indent: Some(2.5),
117                wrap_text: Some(true),
118                ..Default::default()
119            },
120            ..Default::default()
121        })?);
122    }
123    let dates = [
124        ExcelDateTime::from_ymd(2024, 1, 2)?,
125        ExcelDateTime::from_ymd_hms_micro(2024, 1, 2, 3, 4, 5, 678900)?,
126        ExcelDateTime::from_hms_micro(3, 4, 5, 678900)?,
127        ExcelDateTime::from_duration_parts(2, 3, 678900)?,
128    ];
129    writer.start_sheet()?;
130    let mut row = Row::new(RowIndex::new(0)?);
131    row.cells.try_reserve_exact(5)?;
132    for index in 0..rows {
133        row.index = RowIndex::new(index)?;
134        row.cells.clear();
135        for (column, id) in identities.iter().enumerate() {
136            row.cells.push(Cell {
137                address: CellAddress::new(index, column as u32)?,
138                value: CellValue::DateTime(Box::new(dates[index as usize % dates.len()])),
139                style: *id,
140            });
141        }
142        writer.write_row(&mut row)?;
143    }
144    writer.finish(path)?;
145    println!("{}", rows * 5);
146    Ok(())
147}