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}