use anyhow::bail;
use quick_xml::events::{BytesStart, Event};
use std::io::Read;
use crate::{
excel::XmlReader,
helper::{string_to_bool, string_to_unsignedint},
};
use super::{alignment::XlsxAlignment, protection::XlsxCellProtection};
#[derive(Debug, Clone, PartialEq)]
pub struct XlsxCellFormat {
pub alignment: Option<XlsxAlignment>,
pub protection: Option<XlsxCellProtection>,
pub apply_alignment: Option<bool>,
pub apply_border: Option<bool>,
pub apply_fill: Option<bool>,
pub apply_font: Option<bool>,
pub apply_number_format: Option<bool>,
pub apply_protection: Option<bool>,
pub border_id: Option<u64>,
pub fill_id: Option<u64>,
pub font_id: Option<u64>,
pub num_fmt_id: Option<u64>,
pub pivot_button: Option<bool>,
pub quote_prefix: Option<bool>,
pub xf_id: Option<u64>,
}
impl XlsxCellFormat {
pub(crate) fn load(reader: &mut XmlReader<impl Read>, e: &BytesStart) -> anyhow::Result<Self> {
let attributes = e.attributes();
let mut format = Self {
alignment: None,
protection: None,
apply_alignment: None,
apply_border: None,
apply_fill: None,
apply_font: None,
apply_number_format: None,
apply_protection: None,
border_id: None,
fill_id: None,
font_id: None,
num_fmt_id: None,
pivot_button: None,
quote_prefix: None,
xf_id: None,
};
for a in attributes {
match a {
Ok(a) => {
let string_value = String::from_utf8(a.value.to_vec())?;
match a.key.local_name().as_ref() {
b"applyAlignment" => {
format.apply_alignment = string_to_bool(&string_value);
}
b"applyBorder" => {
format.apply_border = string_to_bool(&string_value);
}
b"applyFill" => {
format.apply_fill = string_to_bool(&string_value);
}
b"applyFont" => {
format.apply_font = string_to_bool(&string_value);
}
b"applyNumberFormat" => {
format.apply_number_format = string_to_bool(&string_value);
}
b"applyProtection" => {
format.apply_protection = string_to_bool(&string_value);
}
b"borderId" => {
format.border_id = string_to_unsignedint(&string_value);
}
b"fillId" => {
format.fill_id = string_to_unsignedint(&string_value);
}
b"fontId" => {
format.font_id = string_to_unsignedint(&string_value);
}
b"numFmtId" => {
format.num_fmt_id = string_to_unsignedint(&string_value);
}
b"pivotButton" => {
format.pivot_button = string_to_bool(&string_value);
}
b"quotePrefix" => {
format.quote_prefix = string_to_bool(&string_value);
}
b"xfId" => {
format.xf_id = string_to_unsignedint(&string_value);
}
_ => {}
}
}
Err(error) => {
bail!(error.to_string())
}
}
}
let mut buf = Vec::new();
loop {
buf.clear();
match reader.read_event_into(&mut buf) {
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"extLst" => {
let _ = reader.read_to_end_into(e.to_end().to_owned().name(), &mut Vec::new());
}
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"alignment" => {
let alignment = XlsxAlignment::load(e)?;
format.alignment = Some(alignment)
}
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"protection" => {
let protection = XlsxCellProtection::load(e)?;
format.protection = Some(protection)
}
Ok(Event::End(ref e)) if e.local_name().as_ref() == b"xf" => break,
Ok(Event::Eof) => bail!("unexpected end of file."),
Err(e) => bail!(e.to_string()),
_ => (),
}
}
Ok(format)
}
}