Skip to main content

oca_data_entry/format/
xlsx.rs

1use std::path::Path;
2
3use umya_spreadsheet::{
4    new_file,
5    writer::xlsx::{write, XlsxError},
6};
7
8use crate::model::EntrySchema;
9
10pub struct XlsxOptions {
11    pub include_metadata_row: bool,
12    pub label_lang: Option<String>,
13    pub metadata_lang: Option<String>,
14}
15
16pub fn write_xlsx(schema: &EntrySchema, path: &Path, opts: &XlsxOptions) -> Result<(), XlsxError> {
17    let mut book = new_file();
18    let sheet = book.get_sheet_by_name_mut("Sheet1").unwrap();
19
20    // Header row
21    for (idx, attr) in schema.attributes.iter().enumerate() {
22        let col = column_name(idx + 1);
23        let header = if opts.label_lang.is_some() {
24            attr.label.clone().unwrap_or_else(|| attr.name.clone())
25        } else {
26            attr.name.clone()
27        };
28        let cell = format!("{}1", col);
29        sheet.get_cell_mut(cell.as_str()).set_value(header);
30    }
31
32    if opts.include_metadata_row {
33        let meta_name = "meta";
34        let _ = book.new_sheet(meta_name);
35        let meta_sheet = book.get_sheet_by_name_mut(meta_name).unwrap();
36
37        meta_sheet.get_cell_mut("A1").set_value("oca_bundle_said");
38        meta_sheet.get_cell_mut("B1").set_value(schema.said.clone());
39
40        meta_sheet.get_cell_mut("A3").set_value("attribute");
41        meta_sheet.get_cell_mut("B3").set_value("label");
42        meta_sheet.get_cell_mut("C3").set_value("type");
43
44        let mut row_meta = 4u32;
45        for attr in schema.attributes.iter() {
46            let cell = format!("A{}", row_meta);
47            meta_sheet
48                .get_cell_mut(cell.as_str())
49                .set_value(attr.name.clone());
50            if let Some(label) = &attr.label {
51                let cell = format!("B{}", row_meta);
52                meta_sheet
53                    .get_cell_mut(cell.as_str())
54                    .set_value(label.clone());
55            }
56            if let Some(t) = &attr.attr_type {
57                let cell = format!("C{}", row_meta);
58                meta_sheet.get_cell_mut(cell.as_str()).set_value(t.clone());
59            }
60            row_meta += 1;
61        }
62    }
63
64    write(&book, path)?;
65    Ok(())
66}
67
68fn column_name(mut idx: usize) -> String {
69    let mut name = String::new();
70    while idx > 0 {
71        let rem = (idx - 1) % 26;
72        name.insert(0, (b'A' + rem as u8) as char);
73        idx = (idx - 1) / 26;
74    }
75    name
76}