#![allow(dead_code)]
use rust_xlsxwriter::{Formula, Workbook};
pub fn wb_strings(cells: &[(u32, u16, &str)]) -> Vec<u8> {
let mut wb = Workbook::new();
let ws = wb.add_worksheet();
for (row, col, val) in cells {
ws.write_string(*row, *col, *val).unwrap();
}
wb.save_to_buffer().unwrap()
}
pub fn wb_numbers(cells: &[(u32, u16, f64)]) -> Vec<u8> {
let mut wb = Workbook::new();
let ws = wb.add_worksheet();
for (row, col, val) in cells {
ws.write_number(*row, *col, *val).unwrap();
}
wb.save_to_buffer().unwrap()
}
pub fn wb_bools(cells: &[(u32, u16, bool)]) -> Vec<u8> {
let mut wb = Workbook::new();
let ws = wb.add_worksheet();
for (row, col, val) in cells {
ws.write_boolean(*row, *col, *val).unwrap();
}
wb.save_to_buffer().unwrap()
}
pub fn wb_with_formula(
value_row: u32,
value_col: u16,
value: &str,
formula_row: u32,
formula_col: u16,
formula: &str,
) -> Vec<u8> {
let mut wb = Workbook::new();
let ws = wb.add_worksheet();
ws.write_string(value_row, value_col, value).unwrap();
ws.write_formula(formula_row, formula_col, Formula::new(formula))
.unwrap();
wb.save_to_buffer().unwrap()
}
pub fn wb_empty() -> Vec<u8> {
let mut wb = Workbook::new();
wb.add_worksheet();
wb.save_to_buffer().unwrap()
}
pub type SheetSpec<'a> = (&'a str, &'a [(u32, u16, &'a str)]);
pub fn wb_sheets(sheets: &[SheetSpec]) -> Vec<u8> {
let mut wb = Workbook::new();
for (name, cells) in sheets {
let ws = wb.add_worksheet();
ws.set_name(*name).unwrap();
for (row, col, val) in *cells {
ws.write_string(*row, *col, *val).unwrap();
}
}
wb.save_to_buffer().unwrap()
}
pub fn wb_wide_column(row: u32, col: u16, value: &str) -> Vec<u8> {
let mut wb = Workbook::new();
let ws = wb.add_worksheet();
ws.write_string(row, col, value).unwrap();
wb.save_to_buffer().unwrap()
}
pub fn wb_sparse(cells: &[(u32, u16, &str)]) -> Vec<u8> {
wb_strings(cells)
}
pub fn wb_large(rows: u32, cols: u16, prefix: &str) -> Vec<u8> {
let mut wb = Workbook::new();
let ws = wb.add_worksheet();
for r in 0..rows {
for c in 0..cols {
ws.write_string(r, c, format!("{prefix}_{r}_{c}")).unwrap();
}
}
wb.save_to_buffer().unwrap()
}
pub fn patch_xlsx_xml(
xlsx_bytes: &[u8],
entry_path: &str,
patch: impl Fn(String) -> String,
) -> Vec<u8> {
let mut archive = zip::ZipArchive::new(std::io::Cursor::new(xlsx_bytes)).unwrap();
let mut out_buf = Vec::new();
let mut writer = zip::ZipWriter::new(std::io::Cursor::new(&mut out_buf));
let mut patched = false;
for i in 0..archive.len() {
let mut entry = archive.by_index(i).unwrap();
let name = entry.name().to_string();
let mut contents = Vec::new();
std::io::Read::read_to_end(&mut entry, &mut contents).unwrap();
let options: zip::write::FileOptions<()> = zip::write::FileOptions::default();
writer.start_file(&name, options).unwrap();
if name == entry_path {
let text = String::from_utf8(contents).unwrap();
let patched_text = patch(text);
std::io::Write::write_all(&mut writer, patched_text.as_bytes()).unwrap();
patched = true;
} else {
std::io::Write::write_all(&mut writer, &contents).unwrap();
}
}
writer.finish().unwrap();
assert!(patched, "entry {entry_path} not found in xlsx archive");
out_buf
}