use chrono::{DateTime, Utc};
#[derive(Clone, Debug)]
pub enum CellData {
Text(String),
Number(f64),
NumberWithFormat(f64, String),
Date(DateTime<Utc>),
DateWithFormat(i64, String),
Bool(bool),
Blank,
Error(CellError),
}
#[derive(Clone, Debug)]
pub enum CellError {
Div0, Value, Ref, Name, Num, Na,
}
impl CellData {
pub fn text(s: impl Into<String>) -> Self { CellData::Text(s.into()) }
pub fn number(n: f64) -> Self { CellData::Number(n) }
pub fn number_with_format(n: f64, format_code: impl Into<String>) -> Self {
CellData::NumberWithFormat(n, format_code.into())
}
pub fn date(d: DateTime<Utc>) -> Self { CellData::Date(d) }
pub fn date_from_timestamp(timestamp: i64) -> Self {
CellData::DateWithFormat(timestamp, "m/d/yy h:mm".to_string())
}
pub fn date_with_format(timestamp: i64, format_code: impl Into<String>) -> Self {
CellData::DateWithFormat(timestamp, format_code.into())
}
pub fn bool(b: bool) -> Self { CellData::Bool(b) }
pub fn blank() -> Self { CellData::Blank }
pub fn percentage(value: f64) -> Self {
CellData::NumberWithFormat(value, "0.00%".to_string())
}
pub fn percentage_with_decimals(value: f64, decimals: usize) -> Self {
let format = if decimals == 0 {
"0%".to_string()
} else {
let zeros = "0".repeat(decimals);
format!("0.{}%", zeros)
};
CellData::NumberWithFormat(value, format)
}
pub fn time(timestamp: i64) -> Self {
CellData::DateWithFormat(timestamp, "h:mm:ss".to_string())
}
pub fn time_with_format(timestamp: i64, format_code: impl Into<String>) -> Self {
CellData::DateWithFormat(timestamp, format_code.into())
}
pub fn number_negative_red(value: f64) -> Self {
CellData::NumberWithFormat(value, "#,##0.00;[Red]-#,##0.00".to_string())
}
pub fn number_with_comma(value: f64) -> Self {
CellData::NumberWithFormat(value, "#,##0.00".to_string())
}
pub fn number_with_comma_and_decimals(value: f64, decimals: usize) -> Self {
let format = if decimals == 0 {
"#,##0".to_string()
} else {
let zeros = "0".repeat(decimals);
format!("#,##0.{}", zeros)
};
CellData::NumberWithFormat(value, format)
}
pub fn currency(value: f64) -> Self {
CellData::NumberWithFormat(value, "¥#,##0.00".to_string())
}
pub fn currency_with_symbol(value: f64, symbol: impl Into<String>) -> Self {
let format = format!("{}#,##0.00", symbol.into());
CellData::NumberWithFormat(value, format)
}
pub fn get_format_code(&self) -> Option<&str> {
match self {
CellData::NumberWithFormat(_, format) => Some(format),
CellData::DateWithFormat(_, format) => Some(format),
_ => None,
}
}
pub fn has_format(&self) -> bool {
matches!(self, CellData::NumberWithFormat(_, _) | CellData::DateWithFormat(_, _))
}
}
pub trait CellSupplier {
fn get_cell(&self, row: usize, col: usize) -> CellData;
}
impl<F: Fn(usize, usize) -> CellData> CellSupplier for F {
fn get_cell(&self, row: usize, col: usize) -> CellData { self(row, col) }
}
pub trait RowHandler {
fn on_row(&mut self, row_idx: usize, cells: &[CellData]);
}
impl<F: FnMut(usize, &[CellData])> RowHandler for F {
fn on_row(&mut self, row_idx: usize, cells: &[CellData]) { self(row_idx, cells) }
}