use crate::packaging::element::*;
use crate::packaging::namespace::Namespaces;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename = "numFmt")]
pub struct NumberFormat {
#[serde(rename = "numFmtId")]
id: usize,
#[serde(rename = "formatCode")]
pub code: String,
}
impl OpenXmlElementInfo for NumberFormat {
fn tag_name() -> &'static str {
"numFmt"
}
fn element_type() -> OpenXmlElementType {
OpenXmlElementType::Node
}
}
impl OpenXmlDeserializeDefault for NumberFormat {}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename = "numFmts")]
pub struct NumberFormats {
#[serde(rename = "numFmt")]
num_fmt: Vec<NumberFormat>,
}
impl OpenXmlDeserializeDefault for NumberFormats {}
pub(crate) mod font {
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename = "sz")]
pub struct FontSize {
val: usize,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename = "name")]
pub struct FontName {
val: String,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename = "charset")]
pub struct FontCharset {
val: String,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename = "scheme")]
pub struct FontScheme {
val: String,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename = "color")]
pub struct FontColor {
theme: Option<usize>,
rbg: Option<String>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename = "b")]
pub struct FontBlack;
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename = "numFmt")]
pub struct Font {
black: Option<FontBlack>,
#[serde(rename = "sz")]
size: Option<FontSize>,
color: Option<FontColor>,
name: String,
charset: Option<String>,
scheme: Option<String>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename = "fonts")]
pub struct Fonts {
#[serde(rename = "font")]
pub(crate) fonts: Vec<Font>,
}
}
pub use font::*;
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename = "fgColor")]
#[serde(rename_all = "camelCase")]
pub struct PatternFill {
pattern_type: Option<String>,
bg_color: Option<BgColor>,
fg_color: Option<FgColor>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename = "fgColor")]
#[serde(rename_all = "camelCase")]
pub struct FgColor {
theme: Option<usize>,
tint: Option<f64>,
indexed: Option<usize>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename = "bgColor")]
#[serde(rename_all = "camelCase")]
pub struct BgColor {
theme: Option<usize>,
tint: Option<f64>,
indexed: Option<usize>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename = "fill")]
#[serde(rename_all = "camelCase")]
pub struct Fill {
pattern_fill: Option<PatternFill>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename = "fills")]
pub struct Fills {
count: usize,
#[serde(rename = "fill")]
pub(crate) fills: Vec<Fill>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename = "borderStyle")]
pub struct BorderStyle {
style: Option<String>,
color: Option<usize>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename = "border")]
pub struct Diagonal {}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename = "border")]
pub struct Border {
diagonal: Diagonal,
left: Option<BorderStyle>,
right: Option<BorderStyle>,
top: Option<BorderStyle>,
bottom: Option<BorderStyle>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename = "borders")]
pub struct Borders {
#[serde(rename = "border")]
borders: Vec<Border>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Alignment {
vertical: Option<String>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Xf {
num_fmt_id: usize,
font_id: usize,
fill_id: usize,
border_id: usize,
apply_number_format: Option<bool>,
apply_fill: Option<bool>,
apply_alignment: Option<bool>,
apply_protection: Option<bool>,
alignment: Option<Alignment>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CellStyleXfs {
count: usize,
xf: Vec<Xf>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CellXfs {
count: usize,
xf: Vec<Xf>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CellStyle {
name: String,
xf_id: usize,
builtin_id: usize,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CellStylesPart {
count: usize,
cell_style: Vec<CellStyle>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TableStyles {
count: usize,
default_table_style: String,
default_pilot_style: String,
styles: Vec<TableStyle>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TableStyle {}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ExtLst {
uri: String,
namespaces: Namespaces,
slicer_styles: Vec<SlicerStyle>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", rename = "x14:slicerStyles")]
pub struct SlicerStyle {
default: String,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename = "styleSheet", rename_all = "camelCase")]
pub struct StylesPart {
num_fmts: Option<NumberFormats>,
fonts: Option<Fonts>,
fills: Option<Fills>,
cell_style_xfs: Option<CellStyleXfs>,
cell_xfs: Option<CellXfs>,
cell_styles: Option<CellStylesPart>,
#[serde(flatten)]
namespaces: Namespaces,
}
#[derive(Debug)]
pub struct CellFormatComponent<'a> {
styles: &'a StylesPart,
xf: &'a Xf,
}
impl<'a> CellFormatComponent<'a> {
pub fn number_format(&self) -> Option<&NumberFormat> {
self.styles.get_number_format(self.xf.num_fmt_id)
}
pub fn font(&self) -> Option<&Font> {
self.styles.get_font(self.xf.font_id)
}
pub fn fill(&self) -> Option<&Fill> {
self.styles.get_fill(self.xf.fill_id)
}
pub fn apply_number_format(&self) -> bool {
self.xf.apply_alignment.unwrap_or_default()
}
}
#[derive(Debug)]
pub struct CellStyleComponent<'a> {
styles: &'a StylesPart,
cell_style: &'a CellStyle,
}
impl<'a> CellStyleComponent<'a> {
pub fn number_format(&self) -> Option<&NumberFormat> {
self.xf()
.and_then(|xf| self.styles.get_number_format(xf.num_fmt_id))
}
pub fn xf(&self) -> Option<&Xf> {
self.styles.get_cell_style_xf(self.cell_style.xf_id)
}
pub fn font(&self) -> Option<&Font> {
self.font_id()
.and_then(|font_id| self.styles.get_font(font_id))
}
pub fn fill(&self) -> Option<&Fill> {
self.xf()
.map(|xf| xf.fill_id)
.and_then(|id| self.styles.get_fill(id))
}
pub fn apply_number_format(&self) -> bool {
self.xf()
.and_then(|xf| xf.apply_alignment)
.unwrap_or_default()
}
pub fn font_id(&self) -> Option<usize> {
self.xf().map(|xf| xf.font_id)
}
}
impl StylesPart {
pub fn default_spreadsheet_styles() -> StylesPart {
let namespaces =
Namespaces::new("http://schemas.openxmlformats.org/spreadsheetml/2006/main");
let _num_fmts = NumberFormats::default();
Self {
namespaces,
..Default::default()
}
}
pub fn get_cell_format_component<'a>(&'a self, id: usize) -> Option<CellFormatComponent<'a>> {
let xf = self.get_cell_xf(id);
xf.map(|xf| CellFormatComponent {
styles: self,
xf,
})
}
pub fn get_cell_style_component<'a>(&'a self, id: usize) -> Option<CellStyleComponent<'a>> {
let cell_style = self.get_cell_style(id);
cell_style.map(|cell_style| CellStyleComponent {
styles: self,
cell_style,
})
}
pub fn get_cell_style(&self, id: usize) -> Option<&CellStyle> {
self.cell_styles
.as_ref()
.and_then(|cs| cs.cell_style.get(id))
}
pub fn get_cell_style_xf(&self, id: usize) -> Option<&Xf> {
self.cell_style_xfs.as_ref().and_then(|xf| {
let xf1 = dbg!(xf.xf.get(id));
xf1
})
}
pub fn get_cell_xf(&self, id: usize) -> Option<&Xf> {
self.cell_xfs.as_ref().and_then(|xf| {
let xf1 = xf.xf.get(id);
xf1
})
}
pub fn get_number_format(&self, id: usize) -> Option<&NumberFormat> {
self.num_fmts
.as_ref()
.and_then(|inner| inner.num_fmt.iter().find(|nf| nf.id == id))
}
pub fn get_font(&self, id: usize) -> Option<&Font> {
self.fonts.as_ref().and_then(|fonts| fonts.fonts.get(id))
}
pub fn get_fill(&self, id: usize) -> Option<&Fill> {
self.fills.as_ref().and_then(|fills| fills.fills.get(id))
}
}
impl OpenXmlElementInfo for StylesPart {
fn tag_name() -> &'static str {
"styleSheet"
}
}
impl OpenXmlDeserializeDefault for StylesPart {}
#[test]
fn test_de() {
let value = StylesPart::from_xml_file("examples/simple-spreadsheet/xl/styles.xml").unwrap();
println!("{:?}", value);
}