umya_spreadsheet/structs/
numbering_format.rs1use crate::reader::driver::*;
2use crate::writer::driver::*;
3use md5::Digest;
4use quick_xml::escape;
5use quick_xml::events::BytesStart;
6use quick_xml::Reader;
7use quick_xml::Writer;
8use std::collections::HashMap;
9use std::io::Cursor;
10
11#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
12pub struct NumberingFormat {
13 number_format_id: u32,
14 format_code: Box<str>,
15 is_build_in: bool,
16}
17
18impl Default for NumberingFormat {
19 #[inline]
20 fn default() -> Self {
21 Self {
22 number_format_id: 0,
23 format_code: NumberingFormat::FORMAT_GENERAL.into(),
24 is_build_in: true,
25 }
26 }
27}
28
29impl NumberingFormat {
30 pub const FORMAT_GENERAL: &'static str = "General";
32
33 pub const FORMAT_TEXT: &'static str = "@";
34
35 pub const FORMAT_NUMBER: &'static str = "0";
36 pub const FORMAT_NUMBER_00: &'static str = "0.00";
37 pub const FORMAT_NUMBER_COMMA_SEPARATED1: &'static str = "#,##0.00";
38 pub const FORMAT_NUMBER_COMMA_SEPARATED2: &'static str = "#,##0.00_-";
39
40 pub const FORMAT_PERCENTAGE: &'static str = "0%";
41 pub const FORMAT_PERCENTAGE_00: &'static str = "0.00%";
42
43 pub const FORMAT_DATE_YYYYMMDD2: &'static str = "yyyy-mm-dd";
44 pub const FORMAT_DATE_YYYYMMDD: &'static str = "yyyy-mm-dd";
45 pub const FORMAT_DATE_DDMMYYYY: &'static str = "dd-mm-yyyy";
46 pub const FORMAT_DATE_DDMMYYYYSLASH: &'static str = "dd/mm/yyyy";
47 pub const FORMAT_DATE_DMYSLASH: &'static str = "d/m/yy";
48 pub const FORMAT_DATE_DMYMINUS: &'static str = "d-m-yy";
49 pub const FORMAT_DATE_DMMINUS: &'static str = "d-m";
50 pub const FORMAT_DATE_MYMINUS: &'static str = "m-yy";
51 pub const FORMAT_DATE_XLSX14: &'static str = "mm-dd-yy";
52 pub const FORMAT_DATE_XLSX15: &'static str = "d-mmm-yy";
53 pub const FORMAT_DATE_XLSX16: &'static str = "d-mmm";
54 pub const FORMAT_DATE_XLSX17: &'static str = "mmm-yy";
55 pub const FORMAT_DATE_XLSX22: &'static str = "m/d/yy h:mm";
56 pub const FORMAT_DATE_DATETIME: &'static str = "d/m/yy h:mm";
57 pub const FORMAT_DATE_TIME1: &'static str = "h:mm AM/PM";
58 pub const FORMAT_DATE_TIME2: &'static str = "h:mm:ss AM/PM";
59 pub const FORMAT_DATE_TIME3: &'static str = "h:mm";
60 pub const FORMAT_DATE_TIME4: &'static str = "h:mm:ss";
61 pub const FORMAT_DATE_TIME5: &'static str = "mm:ss";
62 pub const FORMAT_DATE_TIME6: &'static str = "h:mm:ss";
63 pub const FORMAT_DATE_TIME8: &'static str = "h:mm:ss;@";
64 pub const FORMAT_DATE_YYYYMMDDSLASH: &'static str = "yyyy/mm/dd;@";
65
66 pub const FORMAT_CURRENCY_USD_SIMPLE: &'static str = r##""$"#,##0.00_-"##;
67 pub const FORMAT_CURRENCY_USD: &'static str = r###"$#,##0_-"###;
68 pub const FORMAT_CURRENCY_EUR_SIMPLE: &'static str = r#"#,##0.00_-"€""#;
69 pub const FORMAT_CURRENCY_EUR: &'static str = r#"#,##0_-"€""#;
70 pub const FORMAT_ACCOUNTING_USD: &'static str =
71 r#"_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)"#;
72 pub const FORMAT_ACCOUNTING_EUR: &'static str =
73 r#"_("€"* #,##0.00_);_("€"* \(#,##0.00\);_("€"* "-"??_);_(@_)"#;
74
75 #[inline]
76 pub fn get_number_format_id(&self) -> &u32 {
77 &self.number_format_id
78 }
79
80 pub fn set_number_format_id(&mut self, value: u32) -> &mut Self {
81 let format_code_result = FILL_BUILT_IN_FORMAT_CODES.iter().find_map(|(key, val)| {
82 if key == &value {
83 Some(val.clone())
84 } else {
85 None
86 }
87 });
88
89 self.format_code = format_code_result
90 .expect("Not Found NumberFormatId.")
91 .into_boxed_str();
92 self.number_format_id = value;
93 self.is_build_in = true;
94 self
95 }
96
97 #[inline]
98 pub(crate) fn set_number_format_id_crate(&mut self, value: u32) -> &mut Self {
99 self.number_format_id = value;
100 self
101 }
102
103 pub fn set_format_code<S: Into<String>>(&mut self, value: S) -> &mut Self {
115 self.format_code = value.into().into_boxed_str();
116 for (index, format) in FILL_BUILT_IN_FORMAT_CODES.iter() {
117 if &*self.format_code == format {
118 self.number_format_id = *index;
119 self.is_build_in = true;
120 return self;
121 }
122 }
123 self.number_format_id = 999999;
124 self.is_build_in = false;
125 self
126 }
127
128 #[inline]
129 pub(crate) fn set_format_code_crate<S: Into<String>>(&mut self, value: S) -> &mut Self {
130 self.format_code = value.into().into_boxed_str();
131 self
132 }
133
134 #[inline]
135 pub fn get_format_code(&self) -> &str {
136 &self.format_code
137 }
138
139 #[inline]
140 pub(crate) fn get_is_build_in(&self) -> &bool {
141 &self.is_build_in
142 }
143
144 #[inline]
145 pub(crate) fn get_hash_code(&self) -> String {
146 format!("{:x}", md5::Md5::digest(&*self.format_code))
147 }
148
149 pub(crate) fn set_attributes<R: std::io::BufRead>(
150 &mut self,
151 _reader: &mut Reader<R>,
152 e: &BytesStart,
153 ) {
154 self.number_format_id = get_attribute(e, b"numFmtId")
155 .unwrap()
156 .parse::<u32>()
157 .unwrap();
158 self.format_code = escape::unescape(get_attribute(e, b"formatCode").unwrap().as_str())
159 .unwrap()
160 .to_string()
161 .into_boxed_str();
162 self.is_build_in = false;
163 }
164
165 pub(crate) fn write_to(&self, writer: &mut Writer<Cursor<Vec<u8>>>, number_format_id: &u32) {
166 write_start_tag(
168 writer,
169 "numFmt",
170 vec![
171 ("numFmtId", &number_format_id.to_string()),
172 ("formatCode", &self.format_code),
173 ],
174 true,
175 );
176 }
177}
178
179lazy_static! {
180 pub(crate) static ref FILL_BUILT_IN_FORMAT_CODES: HashMap<u32, String> = {
181 let mut map:HashMap<u32, String> = HashMap::new();
182 map.insert(0, NumberingFormat::FORMAT_GENERAL.to_string());
184 map.insert(1, "0".to_string());
185 map.insert(2, "0.00".to_string());
186 map.insert(3, "#,##0".to_string());
187 map.insert(4, "#,##0.00".to_string());
188
189 map.insert(9, "0%".to_string());
190 map.insert(10, "0.00%".to_string());
191 map.insert(11, "0.00E+00".to_string());
192 map.insert(12, "# ?/?".to_string());
193 map.insert(13, "# ??/??".to_string());
194 map.insert(14, "m/d/yyyy".to_string()); map.insert(15, "d-mmm-yy".to_string());
196 map.insert(16, "d-mmm".to_string());
197 map.insert(17, "mmm-yy".to_string());
198 map.insert(18, "h:mm AM/PM".to_string());
199 map.insert(19, "h:mm:ss AM/PM".to_string());
200 map.insert(20, "h:mm".to_string());
201 map.insert(21, "h:mm:ss".to_string());
202 map.insert(22, "m/d/yyyy h:mm".to_string()); map.insert(37, "#,##0_);(#,##0)".to_string()); map.insert(38, "#,##0_);[Red](#,##0)".to_string()); map.insert(39, "#,##0.00_);(#,##0.00)".to_string()); map.insert(40, "#,##0.00_);[Red](#,##0.00)".to_string()); map.insert(44, r#"_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)"#.to_string());
210 map.insert(45, "mm:ss".to_string());
211 map.insert(46, "[h]:mm:ss".to_string());
212 map.insert(47, "mm:ss.0".to_string()); map.insert(48, "##0.0E+0".to_string());
214 map.insert(49, "@".to_string());
215
216 map.insert(27, "[$-404]e/m/d".to_string());
218 map.insert(30, "m/d/yy".to_string());
219 map.insert(36, "[$-404]e/m/d".to_string());
220 map.insert(50, "[$-404]e/m/d".to_string());
221 map.insert(57, "[$-404]e/m/d".to_string());
222
223 map.insert(59, "t0".to_string());
225 map.insert(60, "t0.00".to_string());
226 map.insert(61, "t#,##0".to_string());
227 map.insert(62, "t#,##0.00".to_string());
228 map.insert(67, "t0%".to_string());
229 map.insert(68, "t0.00%".to_string());
230 map.insert(69, "t# ?/?".to_string());
231 map.insert(70, "t# ??/??".to_string());
232
233 map.insert(28, r#"[$-411]ggge"年"m"月"d"日""#.to_string());
235 map.insert(29, r#"[$-411]ggge"年"m"月"d"日""#.to_string());
236 map.insert(31, r#"yyyy"年"m"月"d"日""#.to_string());
237 map.insert(32, r#"h"時"mm"分""#.to_string());
238 map.insert(33, r#"h"時"mm"分"ss"秒""#.to_string());
239 map.insert(34, r#"yyyy"年"m"月""#.to_string());
240 map.insert(35, r#"m"月"d"日""#.to_string());
241 map.insert(51, r#"[$-411]ggge"年"m"月"d"日""#.to_string());
242 map.insert(52, r#"yyyy"年"m"月""#.to_string());
243 map.insert(53, r#"m"月"d"日""#.to_string());
244 map.insert(54, r#"[$-411]ggge"年"m"月"d"日""#.to_string());
245 map.insert(55, r#"yyyy"年"m"月""#.to_string());
246 map.insert(56, r#"m"月"d"日""#.to_string());
247 map.insert(58, r#"[$-411]ggge"年"m"月"d"日""#.to_string());
248
249 map
250 };
251}
252
253#[cfg(test)]
254mod tests {
255 use super::*;
256
257 #[test]
258 fn set_number_format_id() {
259 let mut obj = NumberingFormat::default();
260
261 obj.set_number_format_id(0);
262 assert_eq!(obj.get_format_code(), "General");
263
264 obj.set_number_format_id(1);
265 assert_eq!(obj.get_format_code(), "0");
266 }
267}