rs_x2jsonl/
lib.rs

1use std::error::Error;
2use std::io::Write;
3use std::path::Path;
4
5use calamine::{Reader, Xlsx, open_workbook};
6use serde_json::json;
7
8pub fn excel_to_jsonl<P: AsRef<Path>, W: Write>(
9    path: P,
10    sheet: &str,
11    mut writer: W,
12) -> Result<(), Box<dyn Error>> {
13    let mut excel: Xlsx<_> =
14        open_workbook(path).map_err(|e| format!("Failed to open excel file: {e}"))?;
15
16    let range = excel
17        .worksheet_range(sheet)
18        .map_err(|e| format!("Failed to get sheet or range: {e}"))?;
19
20    let mut rows = range.rows();
21    let header = rows
22        .next()
23        .ok_or_else(|| "Failed to get header row from the sheet".to_string())?;
24
25    for row in rows {
26        let mut json_row = json!({});
27        for (i, cell) in row.iter().enumerate() {
28            let key = header.get(i).map(|c| c.to_string()).unwrap_or_default();
29            let value = match cell {
30                calamine::Data::Int(v) => json!(v),
31                calamine::Data::Float(v) => json!(v),
32                calamine::Data::String(v) => json!(v),
33                calamine::Data::Bool(v) => json!(v),
34                calamine::Data::DateTime(v) => json!(v.to_string()),
35                calamine::Data::DateTimeIso(v) => json!(v),
36                calamine::Data::DurationIso(v) => json!(v),
37                calamine::Data::Error(v) => json!(v.to_string()),
38                calamine::Data::Empty => json!(null),
39            };
40            json_row[key] = value;
41        }
42        serde_json::to_writer(&mut writer, &json_row)?;
43        writeln!(writer)?;
44    }
45
46    Ok(())
47}