Excel files
Read the sheets of .xlsx, .xls and .ods files, and write .xlsx reports with a bold header and fitted columns.
Version 1.0.0 · 3 functions · 2 crates
Functions
What use spreadsheet.qwer gives a program, with the types Quillo sees. To take only some, or under other names: use sheet_names, read_sheet from spreadsheet (Quillo 0.6).
sheet_names(path: str) → listor an errorThe names of a workbook's sheets.
read_sheet(path: str, sheet: str) → listor an errorThe rows of a sheet (the first one when sheet is empty), as lists of cells: numbers (whole ones as ints), text, booleans, dates as text, empty cells as null.
write_xlsx(path: str, sheet: str, rows: list) → nullor an errorWrites rows (lists of cells) to a new .xlsx file at path, in a sheet named sheet, its first row bold and the columns sized to fit.
Get it
$ quillo install spreadsheet # spreadsheet.qwer into this folder$ quillo install spreadsheet --example # and its example, spreadsheet.qweOr with curl:
$ curl -O https://quillolang.org/plugins/files/spreadsheet.qwer$ curl -O https://quillolang.org/plugins/files/spreadsheet.qweThen, in your program, all of it or only what you call:
use spreadsheet.qweruse sheet_names, read_sheet from spreadsheet // Quillo 0.6: only theseIt uses these crates, which cargo fetches the first time the plugin is built:
calamine = { version = "0.31", features = ["dates"] }rust_xlsxwriter = "0.79"Example
// A sales report as an Excel download, and the file read back.//// quillo run spreadsheet.qwe then open http://localhost:8080/report.xlsxuse "spreadsheet.qwer"let sales = [["Region", "Orders", "Revenue"], ["North", 412, 18250.5], ["South", 380, 16410], ["East", 129, 5120.25]]route GET /report.xlsx { write_xlsx("report.xlsx", "Sales", sales)? file("report.xlsx")}route GET /read { write_xlsx("report.xlsx", "Sales", sales)? { sheets: sheet_names("report.xlsx")?, rows: read_sheet("report.xlsx", "")? }}$ quillo run spreadsheet.qwe$ curl 'localhost:8080/read'Source
//! Excel files: read the sheets of .xlsx, .xls and .ods files, and write .xlsx reports with a bold header.//! version: 1.0.0//!//! [dependencies]//! calamine = { version = "0.31", features = ["dates"] }//! rust_xlsxwriter = "0.79"use calamine::{open_workbook_auto, Data, DataType, Reader};use rust_xlsxwriter::{Format, Workbook};use serde_json::Value;/// The names of a workbook's sheets.pub fn sheet_names(path: &str) -> Result<Vec<String>, String> { Ok(open_workbook_auto(path).map_err(|e| format!("{}: {}", path, e))?.sheet_names())}/// The rows of a sheet (the first one when `sheet` is empty), as lists of cells: numbers (whole ones as ints), text, booleans, dates as text, empty cells as null.pub fn read_sheet(path: &str, sheet: &str) -> Result<Vec<Vec<Value>>, String> { let mut wb = open_workbook_auto(path).map_err(|e| format!("{}: {}", path, e))?; let name = if sheet.is_empty() { wb.sheet_names().first().cloned().ok_or("the workbook has no sheets")? } else { sheet.to_string() }; let range = wb.worksheet_range(&name).map_err(|e| format!("sheet `{}`: {}", name, e))?; Ok(range.rows().map(|row| row.iter().map(|c| match c { Data::Int(i) => Value::from(*i), // Excel keeps every number as a float: whole ones come back as ints. Data::Float(f) if f.fract() == 0.0 && f.abs() < 9.0e15 => Value::from(*f as i64), Data::Float(f) => Value::from(*f), Data::String(s) => Value::String(s.clone()), Data::Bool(b) => Value::Bool(*b), Data::DateTime(_) | Data::DateTimeIso(_) => c.as_datetime().map(|d| Value::String(d.to_string())).unwrap_or(Value::Null), Data::DurationIso(s) => Value::String(s.clone()), Data::Error(e) => Value::String(format!("#{:?}", e)), Data::Empty => Value::Null, }).collect()).collect())}/// Writes `rows` (lists of cells) to a new .xlsx file at `path`, in a sheet named `sheet`, its first row bold and the columns sized to fit.pub fn write_xlsx(path: &str, sheet: &str, rows: Vec<Vec<serde_json::Value>>) -> Result<(), String> { let mut wb = Workbook::new(); let ws = wb.add_worksheet(); ws.set_name(if sheet.is_empty() { "Sheet1" } else { sheet }).map_err(|e| e.to_string())?; let bold = Format::new().set_bold(); for (r, row) in rows.iter().enumerate() { for (c, v) in row.iter().enumerate() { let (r, c) = (r as u32, c as u16); let res = match (v, r == 0) { (Value::Null, _) => Ok(ws as &mut _), (Value::Number(n), false) => ws.write_number(r, c, n.as_f64().unwrap_or(0.0)), (Value::Bool(b), false) => ws.write_boolean(r, c, *b), (Value::String(s), false) => ws.write_string(r, c, s), (v, false) => ws.write_string(r, c, v.to_string()), (Value::String(s), true) => ws.write_string_with_format(r, c, s, &bold), (v, true) => ws.write_string_with_format(r, c, v.to_string(), &bold), }; res.map_err(|e| e.to_string())?; } } ws.autofit(); wb.save(path).map_err(|e| e.to_string())}Related
odf_text.qwer · 1.0.0The text of LibreOffice files (.odt, .ods, .odp): paragraphs with headings and lists, sheets as rows of typed cells, slides with their notes, and the title and author.7 views · 9 downloadsCSV csv.qwer · 1.0.0CSV in and out: rows as maps keyed by the header, with quotes, commas and line breaks in cells handled.8 views · 8 downloadsCSV sniffer csv_sniff.qwer · 1.0.0Guess how an uploaded CSV is written before importing it: delimiter, quote, header row, decimal commas and line endings.9 views · 7 downloads7-Zip sevenz.qwer · 1.0.07-Zip archives listed, one file read, opened safely into a folder, and made from a folder.7 views · 7 downloadsImages to PDF images_pdf.qwer · 1.0.0Pictures put into a PDF, one per page, fitted and centred, with captions if you like: photo reports, scans and receipts.7 views · 7 downloadsMailboxes mbox.qwer · 1.0.0Mailboxes in the mbox format read message by message: lists, search, one message in full with its attachments, each saved as .eml, and messages appended.7 views · 9 downloadsThread 0 posts
On Excel files: questions, tips, corrections, and code that uses it.
No posts yet. The first one opens the thread.