xlsx_batch_reader/read/
mod.rs

1use std::{cmp::max, collections::{HashMap, HashSet}, fs::File, io::BufReader, path::Path};
2use anyhow::{anyhow, Result};
3use zip::{ZipArchive, read::ZipFile};
4use chrono::{Duration, NaiveDate, NaiveDateTime, NaiveTime, Timelike};
5use quick_xml::{events::Event, reader::Reader};
6
7use lazy_static::lazy_static;
8use crate::{get_num_from_ord, get_tuple_from_ord, CellValue, ColNum, Date32, MergedRange, RowNum, Timesecond, Timestamp, MAX_COL_NUM};
9
10#[cfg(feature = "cached")]
11use crate::is_merged_cell;
12
13// ooxml: http://www.officeopenxml.com/
14
15macro_rules! get_attr_val {
16    ($e:expr, $tag:expr) => {
17        match $e.try_get_attribute($tag)? {
18            Some(v) => {v.unescape_value()?},
19            None => return Err(anyhow!("attribute {} not exist", $tag))
20        }
21    };
22    ($e:expr, $tag:expr, parse) => {
23        match $e.try_get_attribute($tag)? {
24            Some(v) => {v.unescape_value()?.parse()?},
25            None => return Err(anyhow!("attribute {} not exist", $tag))
26        }
27    };
28    ($e:expr, $tag:expr, to_string) => {
29        match $e.try_get_attribute($tag)? {
30            Some(v) => {v.unescape_value()?.to_string()},
31            None => return Err(anyhow!("attribute {} not exist", $tag))
32        }
33    };
34}
35
36/// check if row is matched
37fn is_matched_row(row: &Vec<CellValue<'_>>, checks: &HashMap<usize, HashSet<String>>, check_by_and: bool) -> (bool, String) {
38    if check_by_and {
39        for (i, v) in checks {
40            if let Some(cell) = row.get(*i) {
41                if let Ok(Some(s)) = cell.get::<String>() {
42                    if !v.contains(&s) {
43                        return (false, format!("{:?}", v));
44                    }
45                } else {
46                    return (false, format!("{:?}", v));
47                }
48            } else {
49                return (false, format!("{:?}", v));
50            }
51        }
52        (true, "".to_string())
53    } else {
54        for (i, v) in checks {
55            if let Some(cell) = row.get(*i) {
56                if let Ok(Some(s)) = cell.get::<String>() {
57                    if v.contains(&s) {
58                        return (true, format!("{:?}", v));
59                    }
60                }
61            }
62        }
63        (false, "".to_string())
64    }
65}
66
67/// xlsx book reader
68pub struct XlsxBook {
69    ini_share: bool,
70    str_share: Vec<String>,
71    shts_hidden: Vec<String>,
72    shts_visible: Vec<String>,
73    map_style: HashMap<u32, u32>,
74    map_sheet: HashMap<String, String>,
75    zip_archive: ZipArchive<BufReader<File>>,
76    datetime_fmts: HashMap<u32, u8>,
77}
78
79impl XlsxBook {
80    /// load_share: if set to false, you should call load_share_strings before reading data. it should usually be true. If you only need to obtain the sheet names, you can set it false to open the file faster.
81    pub fn new<T: AsRef<Path>>(path: T, load_share: bool) -> Result<XlsxBook> {
82        // zip压缩文件
83        let mut zip_archive = {
84            let file = File::open(path)?;
85            let zipreader = BufReader::new(file);
86            ZipArchive::new(zipreader)?
87        };
88
89        let book_refs = {
90            let file = zip_archive.by_name("xl/_rels/workbook.xml.rels")?;
91            
92            let mut buf = Vec::new();
93            let mut refs = HashMap::new();
94            let mut reader =  Reader::from_reader(BufReader::new(file));
95            loop {
96                match reader.read_event_into(&mut buf) {
97                    Ok(Event::Empty(ref e)) => {
98                        if e.name().as_ref() == b"Relationship"{
99                            refs.insert(get_attr_val!(e, "Id", to_string), get_attr_val!(e, "Target", to_string));
100                        };
101                    },
102                    Ok(Event::Start(ref e)) => {   // 解析 <sheet ..></sheet> 模式
103                        if e.name().as_ref() == b"Relationship"{
104                            refs.insert(get_attr_val!(e, "Id", to_string), get_attr_val!(e, "Target", to_string));
105                        };
106                    },
107                    Ok(Event::Eof) => break, // exits the loop when reaching end of file
108                    Err(e) => return Err(anyhow!("workbook.xml.refs broken: {:?}", e)),
109                    _ => ()                  // There are several other `Event`s we do not consider here
110                }
111                buf.clear();
112            };
113            refs
114        };
115
116
117        // 初始化sheet列表
118        let mut shts_hidden = Vec::<String>::new();
119        let mut shts_visible = Vec::<String>::new();
120        let map_sheet = {
121            let file = zip_archive.by_name("xl/workbook.xml")?;
122            let mut reader =  Reader::from_reader(BufReader::new(file));
123            // reader.trim_text(true);
124
125            let mut buf = Vec::new();
126            let mut map_share: HashMap<String, String> = HashMap::new();
127            loop {
128                match reader.read_event_into(&mut buf) {
129                    Ok(Event::Empty(ref e)) => {
130                        if e.name().as_ref() == b"sheet"{
131                            let name = get_attr_val!(e, "name", to_string);
132                            let rid = get_attr_val!(e, "r:id", to_string);
133                            let sheet = if book_refs.contains_key(&rid) {
134                                if book_refs[&rid].starts_with('/') {
135                                    format!("{}", book_refs[&rid].trim_start_matches('/'))
136                                } else {
137                                    format!("xl/{}", book_refs[&rid])
138                                }
139                            } else {
140                                return Err(anyhow!("Relationship of sheet-{rid} not found"))
141                            };
142                            match e.try_get_attribute("state").unwrap_or(None) {
143                                Some(attr) => {
144                                    if attr.unescape_value()?.as_bytes() == b"hidden" {
145                                        shts_hidden.push(name.clone());
146                                    } else {
147                                        shts_visible.push(name.clone());
148                                    };
149                                },
150                                _ => {shts_visible.push(name.clone());}
151                            };
152                            map_share.insert(name, sheet);  // sheet名,对应的真是xml文件
153                        };
154                    },
155                    Ok(Event::Start(ref e)) => {   // 解析 <sheet ..></sheet> 模式
156                        if e.name().as_ref() == b"sheet"{
157                            let name = get_attr_val!(e, "name", to_string);
158                            let rid = get_attr_val!(e, "r:id", to_string);
159                            let sheet = if book_refs.contains_key(&rid) {
160                                if book_refs[&rid].starts_with('/') {
161                                    format!("{}", book_refs[&rid].trim_start_matches('/'))
162                                } else {
163                                    format!("/xl/{}", book_refs[&rid])
164                                }
165                            } else {
166                                return Err(anyhow!("Relationship of sheet-rid not found!"))
167                            };
168                            match e.try_get_attribute("state").unwrap_or(None) {
169                                Some(attr) => {
170                                    if attr.unescape_value()?.as_bytes() != b"hidden" {
171                                        shts_visible.push(name.clone());
172                                    };
173                                },
174                                _ => {shts_visible.push(name.clone());}
175                            };
176                            map_share.insert(name, sheet);  // sheet名,对应的真是xml文件
177                        };
178                    },
179                    Ok(Event::Eof) => break, // exits the loop when reaching end of file
180                    Err(e) => return Err(anyhow!("workbook.xml is broken: {:?}", e)),
181                    _ => ()                  // There are several other `Event`s we do not consider here
182                }
183                buf.clear();
184            };
185            map_share
186        };
187
188        // 初始化单元格格式
189        let mut datetime_fmts = DATETIME_FMTS.clone();
190        let map_style = {
191            match zip_archive.by_name("xl/styles.xml") {
192                Ok(file) => {
193                    let mut reader =  Reader::from_reader(BufReader::new(file));
194                    // reader.trim_text(true);
195
196                    let mut inx: u32 = 0;
197                    let mut act = false;
198                    let mut buf = Vec::new();
199                    let mut map_style: HashMap<u32, u32> = HashMap::new();
200                    loop {
201                        match reader.read_event_into(&mut buf) {
202                            Ok(Event::Start(ref e)) => {
203                                if e.name().as_ref() == b"cellXfs" || e.name().as_ref() == b"numFmts" {
204                                    act = true;
205                                } else if act && (e.name().as_ref() == b"numFmt"){
206                                    let code = get_attr_val!(e, "formatCode", to_string);
207                                    if code.contains("yy") {
208                                        if code.contains("h") || code.contains("ss") {
209                                            datetime_fmts.insert(get_attr_val!(e, "numFmtId", parse), FMT_DATETIME);
210                                        } else {
211                                            datetime_fmts.insert(get_attr_val!(e, "numFmtId", parse), FMT_DATE);
212                                        }
213                                    } else if code.contains("ss") {
214                                        datetime_fmts.insert(get_attr_val!(e, "numFmtId", parse), FMT_TIME);
215                                    };
216                                } else if act && (e.name().as_ref() == b"xf"){
217                                    map_style.insert(inx, get_attr_val!(e, "numFmtId", parse));
218                                    inx += 1;
219                                };
220                            },
221                            Ok(Event::Empty(ref e)) => {
222                                if act && (e.name().as_ref() == b"numFmt"){
223                                    let code = get_attr_val!(e, "formatCode", to_string);
224                                    if code.contains("yy") {
225                                        if code.contains("h") || code.contains("ss") {
226                                            datetime_fmts.insert(get_attr_val!(e, "numFmtId", parse), FMT_DATETIME);
227                                        } else {
228                                            datetime_fmts.insert(get_attr_val!(e, "numFmtId", parse), FMT_DATE);
229                                        }
230                                    } else if code.contains("ss") {
231                                        datetime_fmts.insert(get_attr_val!(e, "numFmtId", parse), FMT_TIME);
232                                    };
233                                } else if act && (e.name().as_ref() == b"xf"){
234                                    map_style.insert(inx, get_attr_val!(e, "numFmtId", parse));
235                                    inx += 1;
236                                };
237                            },
238                            Ok(Event::End(ref e)) => {
239                                if e.name().as_ref() == b"numFmts" {
240                                    act = false;
241                                } else if e.name().as_ref() == b"cellXfs" {
242                                    break;
243                                };
244                            },
245                            Ok(Event::Eof) => break, // exits the loop when reaching end of file
246                            Err(e) => return Err(anyhow!("styles.xml is broken: {:?}", e)),
247                            _ => ()                  // There are several other `Event`s we do not consider here
248                        }
249                        buf.clear();
250                    };
251                    map_style
252                },
253                Err(_) => {
254                    HashMap::new()
255                }
256            }
257        };
258        
259        let mut book = XlsxBook{
260                ini_share: false,
261                str_share: Vec::new(),
262                map_style,
263                map_sheet,
264                shts_hidden,
265                shts_visible,
266                zip_archive,
267                datetime_fmts,
268            };
269        if load_share {
270            book.load_share_strings()?;
271        };
272        Ok(book)
273    }
274    /// get hidden sheets
275    pub fn get_hidden_sheets(&self) -> &Vec<String> {
276        &self.shts_hidden
277    } 
278    /// get visible sheets
279    pub fn get_visible_sheets(&self) -> &Vec<String> {
280        &self.shts_visible
281    }
282    /// if set load_share to false, you should call load_share_strings before reading data
283    pub fn load_share_strings(&mut self) -> Result<()>{
284        if self.ini_share {
285            return Ok(());
286        };
287        let str_share = {
288            match self.zip_archive.by_name("xl/sharedStrings.xml") {
289                Ok(file) => {
290                    let mut reader =  Reader::from_reader(BufReader::new(file));
291                    // reader.trim_text(true);
292
293                    let mut buf = Vec::with_capacity(3069);
294                    let cap = loop {    // 获取ShareString容量
295                        match reader.read_event_into(&mut buf) {
296                            Ok(Event::Start(ref e)) => {
297                                if e.name().as_ref() == b"sst"{
298                                    let cnt: usize =  {
299                                        match e.try_get_attribute("uniqueCount")? {
300                                            Some(a) => {a.unescape_value()?.parse()?},
301                                            None => {get_attr_val!(e, "count", parse)}
302                                        }
303                                    };
304                                    break cnt
305                                }
306                            }
307                            Ok(Event::Eof) => {return Ok(())}, // exits the loop when reaching end of file
308                            Err(e) => return Err(anyhow!("sharedStrings.xml is broken: {:?}", e)),
309                            _ => (),                     // There are several other `Event`s we do not consider here
310                        }
311                    };
312
313                    let mut insert = false;
314                    let mut shstring = String::new(); 
315                    let mut vec_share: Vec<String> = Vec::with_capacity(cap);
316                    loop {
317                        match reader.read_event_into(&mut buf) {
318                            Ok(Event::Start(ref e)) => {
319                                match e.name().as_ref() {
320                                    b"si" => {shstring.clear()},
321                                    b"t" => {insert = true},
322                                    _ => {insert = false},
323                                }
324                            },
325                            Ok(Event::Text(ref t)) => {
326                                if insert {
327                                    shstring += &String::from_utf8(t.to_vec())?;
328                                }
329                            },
330                            Ok(Event::End(ref e)) => {
331                                if e.name().as_ref() == b"si" {
332                                    vec_share.push(shstring.clone());
333                                }
334                            },
335                            Ok(Event::Eof) => break, // exits the loop when reaching end of file
336                            Err(e) => return Err(anyhow!("sharedStrings.xml is broken: {:?}", e)),
337                            _ => ()                  // There are several other `Event`s we do not consider here
338                        }
339                        buf.clear();
340                    };
341                    if cap != vec_share.len() {  
342                        return Err(anyhow!("shareString-lenth check error!!"));
343                    };
344                    vec_share
345                },
346                Err(_) => {
347                    Vec::<String>::new()
348                }
349            }
350        };
351        self.ini_share = true;
352        self.str_share = str_share;
353        Ok(())
354    }
355    /// sht_name: sheet name  
356    /// iter_batch: The number of rows per batch  
357    /// skip_rows: number of skipped rows  
358    /// left_ncol: Starting column (included), with 1 as the starting value  
359    /// right_ncol: Terminate columns (including), MAX-COL_NUM to get non fixed termination columns  
360    pub fn get_sheet_by_name<'a, 'b>(&'a mut self, sht_name: &'b String, iter_batch: usize, skip_rows: u32, left_ncol: ColNum, right_ncol: ColNum, first_row_is_header: bool) -> Result<XlsxSheet<'a>> {
361        for (k, v) in self.map_sheet.clone() {
362            if k.eq(sht_name) {
363                if !self.ini_share {
364                    self.load_share_strings()?;
365                };
366
367                match self.zip_archive.by_name(v.as_str()) {
368                    Ok(file) => {
369                        let reader = Reader::from_reader(BufReader::new(file));
370                        // reader.trim_text(true);
371            
372                        return Ok(XlsxSheet {
373                            reader,
374                            skip_rows,
375                            left_ncol: left_ncol-1,
376                            right_ncol,
377                            iter_batch,
378                            first_row_is_header,
379                            first_row: None,
380                            key: k,
381                            buf: Vec::with_capacity(8*1024),
382                            status: 1,
383                            currow: 0,
384                            str_share: &self.str_share,
385                            map_style: &self.map_style,
386                            datetime_fmts: &self.datetime_fmts,
387                            max_size: None,
388                            merged_rects: None,
389                            skip_until: None,
390                            skip_matched: None,
391                            skip_matched_check_by_and: true,
392                            read_before: None,
393                            header_check: None,
394                            addr_captures: None,
395                            vals_captures: HashMap::new(),
396                        });
397                    },
398                    Err(_) => {
399                        return Err(anyhow!("sheet {} - {} lost!", k.as_str(), v.as_str()));
400                    }
401                };
402            };
403        };
404        Err(anyhow!(format!("{} sheet not found!", sht_name)))
405    }
406    /// get cached sheet by name, all data will be cached in memory when sheet created
407    #[cfg(feature = "cached")]
408    pub fn get_cached_sheet_by_name<'a>(&'a mut self, sht_name: &String, iter_batch: usize, skip_rows: u32, left_ncol: ColNum, right_ncol: ColNum, first_row_is_header: bool) -> Result<CachedSheet<'a>> {
409        Ok(self.get_sheet_by_name(sht_name, iter_batch, skip_rows, left_ncol, right_ncol, first_row_is_header)?.into_cached_sheet()?)
410    }
411    /// get sheet name map
412    pub fn get_sheets_maps(&self) -> &HashMap<String, String> {
413        &self.map_sheet
414    }
415}
416
417/// batch sheet reader
418pub struct XlsxSheet<'a> {
419    key: String,
420    str_share: &'a Vec<String>,
421    map_style: &'a HashMap<u32, u32>,
422    buf: Vec<u8>,
423    status: u8,   // 0-closed; 1-new; 2-active; 3-get_cell; 4-skip_cell; 初始为1
424    currow: RowNum,  //  当前行号
425    reader: Reader<BufReader<ZipFile<'a, BufReader<File>>>>,
426    iter_batch: usize,
427    skip_rows: u32,
428    max_size: Option<(RowNum, ColNum)>,
429    left_ncol: ColNum,
430    right_ncol: ColNum,
431    first_row_is_header: bool,    //  标识是否需要把读取到的第一行作为标题,读取到标题行以后,会被设置为false
432    first_row: Option<(u32, Vec<CellValue<'a>>)>,
433    datetime_fmts: &'a HashMap<u32, u8>,
434    merged_rects: Option<Vec<((RowNum, ColNum), (RowNum, ColNum))>>,
435    skip_until: Option<HashMap<usize, HashSet<String>>>,
436    skip_matched: Option<HashMap<usize, HashSet<String>>>,
437    skip_matched_check_by_and: bool,
438    read_before: Option<HashMap<usize, HashSet<String>>>,
439    header_check: Option<HashMap<usize, HashSet<String>>>,
440    addr_captures: Option<HashSet<String>>,
441    vals_captures: HashMap<String, CellValue<'a>>
442}
443
444impl<'a> XlsxSheet<'a> {
445    /// into cached sheet
446    #[cfg(feature = "cached")]
447    fn into_cached_sheet(mut self) -> Result<CachedSheet<'a>> {
448        let top_nrow = if self.first_row_is_header {self.skip_rows+2} else {self.skip_rows+1};
449        if self.first_row_is_header {
450            self.get_header_row()?;
451        }
452        let (data, bottom_nrow) =  match self.get_next_row() {
453            Ok(Some((r, d))) => {
454                let mut data = if let Some((rn, _)) = self.max_size {
455                    HashMap::with_capacity(rn as usize)
456                } else {
457                    HashMap::new()
458                };
459                data.insert(r, d);
460                let mut last_nrow = r;
461                loop {
462                    match self.get_next_row() {
463                        Ok(Some((r, d))) => {
464                            last_nrow = r;
465                            data.insert(r, d);
466                        },
467                        Ok(None) => {
468                            break;
469                        },
470                        Err(e) => {
471                            return Err(e);
472                        }
473                    };
474                };
475                (data, last_nrow)
476            },
477            Ok(None) => {(HashMap::new(), 0)},
478            Err(e) => {return Err(e);}
479        };
480        let merged_rects = self.get_merged_ranges()?.to_owned();
481        let right_ncol = if self.right_ncol == MAX_COL_NUM {
482            if let Some((_mr, mc)) = self.max_size {
483                mc
484            } else {
485                self.right_ncol
486            }
487        } else {
488            self.right_ncol
489        };
490        let empty = self.is_empty()?;
491        Ok(CachedSheet {
492            data,
493            merged_rects,
494            key: self.key,
495            current: top_nrow,
496            empty,
497            keep_empty: false,
498            iter_batch: self.iter_batch,
499            top_nrow,
500            bottom_nrow,
501            left_ncol: self.left_ncol + 1,
502            right_ncol,
503            header_row: self.first_row,
504        })
505    }
506    /// get sheet name
507    pub fn sheet_name(&self) -> &String {
508        &self.key
509    }
510    /// skip until a row matched,this function should be called before reading(the matched row will be returned)   
511    pub fn with_skip_until(&mut self, checks: &HashMap<String, String>) {
512        let mut maps = HashMap::new();
513        for (c, v) in checks {
514            let col = get_num_from_ord(c.as_bytes()).unwrap_or(0);
515            if col > self.left_ncol && col <= self.right_ncol {
516                maps.insert((col-self.left_ncol-1) as usize, v.split('|').map(|s| s.to_string()).collect());
517            }
518        }
519        if maps.len() > 0 {
520            self.skip_until = Some(maps);
521        } else {
522            self.skip_until = None;
523        }
524    }
525    /// skip the matched row, this function should be called before reading(the matched row will be returned)   
526    /// when check_by_and is true, all check cells should be matched    
527    /// when check_by_and is false, at least one check cell should be matched
528    pub fn with_skip_matched(&mut self, checks: &HashMap<String, String>, check_by_and: bool) {
529        let mut maps = HashMap::new();
530        for (c, v) in checks {
531            let col = get_num_from_ord(c.as_bytes()).unwrap_or(0);
532            if col > self.left_ncol && col <= self.right_ncol {
533                maps.insert((col-self.left_ncol-1) as usize, v.split('|').map(|s| s.to_string()).collect());
534            }
535        }
536        if maps.len() > 0 {
537            self.skip_matched = Some(maps);
538            self.skip_matched_check_by_and = check_by_and;
539        } else {
540            self.skip_matched = None;
541        }
542    }
543    /// read before a row matched,this function should be called before reading(the matched row will not be returned)
544    pub fn with_read_before(&mut self, checks: &HashMap<String, String>) {
545        let mut maps = HashMap::new();
546        for (c, v) in checks {
547            let col = get_num_from_ord(c.as_bytes()).unwrap_or(0);
548            if col > self.left_ncol && col <= self.right_ncol {
549                maps.insert((col-self.left_ncol-1) as usize, v.split('|').map(|s| s.to_string()).collect());
550            }
551        }
552        if maps.len() > 0 {
553            self.read_before = Some(maps);
554        } else {
555            self.read_before = None;
556        }
557    }
558    /// check header row, this function should be called before reading. If the header is not matched, An error will be raised.
559    pub fn with_header_check(&mut self, checks: &HashMap<String, String>) {
560        let mut maps = HashMap::new();
561        for (c, v) in checks {
562            let col = get_num_from_ord(c.as_bytes()).unwrap_or(0);
563            if col > self.left_ncol && col <= self.right_ncol {
564                maps.insert((col-self.left_ncol-1) as usize, v.split('|').map(|s| s.to_string()).collect());
565            }
566        }
567        if maps.len() > 0 {
568            self.header_check = Some(maps);
569        } else {
570            self.header_check = None;
571        }
572    }
573    /// capture values by address
574    pub fn with_capture_vals(&mut self, captures: HashSet<String>) {
575        if captures.len() > 0 {
576            self.addr_captures = Some(captures);
577        } else {
578            self.addr_captures = None;
579        };
580        self.vals_captures = HashMap::new();
581    }
582    /// get cell captured values,  required:   
583    /// 1. with_capture_vals must be called before this function    
584    /// 2. first_row_is_header must be true     
585    /// 3. the captured values must be after skip_rows(excluded, passed to get_sheet_by_name) and before header row(included)
586    pub fn get_captured_vals(&mut self) -> Result<&HashMap<String, CellValue<'a>>> {
587        if self.addr_captures.is_none() {
588            Ok(&self.vals_captures)
589        } else if self.first_row_is_header {
590            self.get_header_row()?;
591            Ok(&self.vals_captures)
592        } else {
593            Err(anyhow!("get_captured_vals error: first_row_is_header must be true"))
594        }
595    }
596    /// check whether the sheet is empty, should be called after at least one row has been read
597    pub fn is_empty(&self) -> Result<bool> {
598        if self.currow > 0 {
599            Ok(false)
600        } else if self.status == 0 {
601            Ok(true)
602        } else {
603            Err(anyhow!("is_empty should be called after at least one row has been read"))
604        }
605    }
606    /// get column range, v0.1.7 the start column number included (start from 1)
607    pub fn column_range(&self) -> (ColNum, ColNum) {
608        (self.left_ncol+1, self.right_ncol)
609    }
610    /// get next row
611    fn get_next_row(&mut self) -> Result<Option<(u32, Vec<CellValue<'a>>)>> {
612        let mut col: ColNum = 0;
613        let mut cell_addr = "".into();
614        let mut cell_type = vec![];
615        let mut prev_head = vec![];
616        let mut col_index: ColNum = 1;    // 当前需增加cell的col_index
617        // let mut row_num: u32 = 0;     //  sheet中增加currow储存当前行号
618        let mut row_value: Vec<CellValue<'_>> = Vec::new();
619        let mut num_fmt_id: u32 = 0;
620        if self.status == 0 {
621            return Ok(None)
622        }  //  已关闭的sheet直接返回None
623        loop {
624            match self.reader.read_event_into(&mut self.buf) {
625                Ok(Event::Start(ref e)) => {
626                    prev_head = e.name().as_ref().to_vec();
627                    if self.status == 0 {
628                        break Ok(None)
629                    } else if self.status == 1 {
630                        if prev_head == b"dimension" {
631                            let attr = get_attr_val!(e, "ref", to_string);
632                            let dim: Vec<&str> = attr.split(':').collect();
633                            if let Some(x) = dim.get(1) {
634                                self.max_size = Some(get_tuple_from_ord(x.as_bytes())?);
635                            };
636                        } else if prev_head == b"sheetData" {
637                            self.status = 2;
638                        } else if prev_head == b"mergeCells" {
639                            let cnt: usize = get_attr_val!(e, "count", parse);
640                            self.process_merged_cells(cnt)?;
641                        }; 
642                    } else {
643                        if prev_head == b"c" {
644                            match e.try_get_attribute("t")? {
645                                Some(attr) => {
646                                    cell_type = attr.unescape_value()?.as_bytes().to_owned();
647                                },
648                                _ => {
649                                    cell_type = b"n".to_vec();
650                                }
651                            };
652                            match e.try_get_attribute("s")? {
653                                Some(attr) => {
654                                    num_fmt_id = self.map_style[&attr.unescape_value()?.parse::<u32>()?];
655                                },
656                                _ => {
657                                    num_fmt_id = 0;
658                                }
659                            };
660                            cell_addr = get_attr_val!(e, "r").to_string();   //  单元格地址
661                            col = get_num_from_ord(cell_addr.as_bytes()).unwrap_or(0);
662                            
663                            if self.currow > self.skip_rows && col > self.left_ncol && col <= self.right_ncol {
664                                self.status = 3;   // 3-get_cell; 4-skip_cell;
665                            } else {
666                                self.status = 4;   // 3-get_cell; 4-skip_cell;
667                            }
668                        } else if prev_head == b"row" {
669                            self.currow = get_attr_val!(e, "r", parse);
670                            let cap = {
671                                if self.right_ncol == MAX_COL_NUM {
672                                    match e.try_get_attribute("spans") {
673                                        Ok(Some(spans)) => {
674                                            if let Some(x) = spans.unescape_value()?.as_ref().split(":").last() {
675                                                x.parse()?
676                                            } else {
677                                                1
678                                            }
679                                        },
680                                        _ => {
681                                            1
682                                        }
683                                    }
684                                    // if let Some(x) = get_attr_val!(e, "spans").as_ref().split(":").last() {
685                                    //     x.parse()?
686                                    // } else {
687                                    //     1
688                                    // }
689                                } else {
690                                    self.right_ncol
691                                }
692                            } - self.left_ncol;
693                            row_value = Vec::with_capacity(cap.into());
694                            col_index = 1;         // 当前需增加cell的col_index
695                            // row_value.push(CellValue::Number(row_num as f64));  // 行号单独返回
696                        }; 
697                    };
698                },
699                Ok(Event::Empty(ref e)) => {
700                    prev_head = e.name().as_ref().to_vec();
701                    if self.status == 1 && prev_head == b"dimension" {
702                        let attr = get_attr_val!(e, "ref", to_string);
703                        let dim: Vec<&str> = attr.split(':').collect();
704                        if let Some(x) = dim.get(1) {
705                            self.max_size = Some(get_tuple_from_ord(x.as_bytes())?);
706                        };
707                    } else if prev_head == b"sheetData" {
708                        self.status = 0;
709                        break Ok(None)
710                    }
711                },
712                Ok(Event::Text(ref t)) => {
713                    // b for boolean
714                    // d for date
715                    // e for error
716                    // inlineStr for an inline string (i.e., not stored in the shared strings part, but directly in the cell)
717                    // n for number
718                    // s for shared string (so stored in the shared strings part and not in the cell)
719                    // str for a formula (a string representing the formula)
720                    if self.status == 3 && (prev_head == b"v" || prev_head == b"t") {
721                        while col_index + self.left_ncol < col {
722                            row_value.push(CellValue::Blank);
723                            col_index += 1;
724                        }
725                        let cel_val = if cell_type == b"inlineStr" && prev_head == b"t" { 
726                            CellValue::String(String::from_utf8(t.to_vec())?)
727                        } else if prev_head == b"v" {
728                            if cell_type == b"s" {
729                                CellValue::Shared(&self.str_share[String::from_utf8(t.to_vec())?.parse::<usize>()?])
730                            } else if cell_type == b"n" {
731                                let fmt = self.datetime_fmts.get(&num_fmt_id).unwrap_or(&FMT_DEFAULT);
732                                if *fmt == FMT_DATE {
733                                    CellValue::Date(String::from_utf8(t.to_vec())?.parse::<f64>()?)
734                                } else if *fmt == FMT_DATETIME {
735                                    CellValue::Datetime(String::from_utf8(t.to_vec())?.parse::<f64>()?)
736                                } else if *fmt == FMT_TIME {
737                                    CellValue::Time(String::from_utf8(t.to_vec())?.parse::<f64>()?)
738                                } else {
739                                    CellValue::Number(String::from_utf8(t.to_vec())?.parse::<f64>()?)
740                                }
741                            } else if cell_type == b"b" {
742                                if String::from_utf8(t.to_vec())?.parse::<usize>() == Ok(1) {
743                                    CellValue::Bool(true)
744                                } else {
745                                    CellValue::Bool(false)
746                                }
747                            } else if cell_type == b"d" {
748                                CellValue::String(String::from_utf8(t.to_vec())?)
749                            } else if cell_type == b"e" {
750                                CellValue::Error(String::from_utf8(t.to_vec())?)
751                            } else if cell_type == b"str" {
752                                CellValue::String(String::from_utf8(t.to_vec())?)
753                            } else{
754                                CellValue::Blank
755                            }
756                        } else {
757                            CellValue::Error("Unknown cell type".into())
758                        };
759                        if let Some(addrs) = &mut self.addr_captures {
760                            if let Some(key) = addrs.take(&cell_addr) {
761                                self.vals_captures.insert(key, cel_val.clone());
762                            }
763                        }
764                        col_index += 1;
765                        row_value.push(cel_val);
766                    }
767                },
768                Ok(Event::End(ref e)) => {
769                    // 0-closed; 1-new; 2-active;
770                    if (e.name().as_ref() == b"row") && self.status > 1 && row_value.len() > 0 {
771                        if let Some(skip_until) = &self.skip_until {
772                            if is_matched_row(&row_value, skip_until, true).0 {
773                                self.skip_until = None;
774                            } else {
775                                // col = 0;   //  reset each cell
776                                // cell_type = Vec::new();   // reset each cell
777                                // num_fmt_id = 0;   // reset each cell
778                                // prev_head = Vec::new();    reset each tag
779                                // col_index = 1;    // 当前需增加cell的col_index  // reset each row
780                                // row_num = 0;       //  reset each row
781                                // row_value = Vec::new();    // reset each row
782                                continue;
783                            }   //  读取到初始行前继续读取
784                        } else if let Some(read_before) = &self.read_before {
785                            if is_matched_row(&row_value, read_before, true).0 {
786                                self.status = 0; 
787                                self.read_before = None;
788                                break Ok(None);
789                            }  //  读取到结尾行后不再继续读取,且抛弃结尾行
790                        };
791                        if self.right_ncol != MAX_COL_NUM {
792                            while row_value.len() < row_value.capacity() {
793                                row_value.push(CellValue::Blank);
794                            };
795                        }
796                        self.addr_captures = None;    //  返回首行时,不再匹配captures
797                        
798                        // 处理标题行
799                        if !self.first_row_is_header {    //  不跳过标题行
800                            if let Some(skip_matched) = &self.skip_matched {
801                                if is_matched_row(&row_value, skip_matched, self.skip_matched_check_by_and).0 {
802                                    continue;    //   如果当前行满足条件,忽略当前行; 
803                                }
804                            } 
805                        };
806                        break Ok(Some((self.currow, row_value)))
807                    }else if e.name().as_ref() == b"sheetData" {
808                        self.status = 0; 
809                        break Ok(None)
810                    }
811                },
812                Ok(Event::Eof) => {
813                    self.status = 0; 
814                    break Ok(None)
815                },   // exits the loop when reaching end of file
816                Err(e) => {
817                    return Err(anyhow!("sheet data is broken: {:?}", e));
818                },
819                _ => ()                  // There are several other `Event`s we do not consider here
820            }
821            self.buf.clear();
822        }
823    }
824    /// get header if first_row_is_header is true
825    pub fn get_header_row(&mut self) -> Result<(u32, Vec<CellValue<'a>>)> {
826        if self.first_row_is_header {
827            match self.get_next_row() {
828                Ok(Some(v)) => {
829                    if let Some(header_check) = &self.header_check {
830                        let matched = is_matched_row(&v.1, header_check, true);
831                        if matched.0 {
832                            self.first_row = Some(v);
833                            self.first_row_is_header = false;
834                        } else {
835                            return Err(anyhow!("header row check failed: {}", matched.1));
836                        }
837                    } else {
838                        self.first_row = Some(v);
839                        self.first_row_is_header = false;
840                    }
841                },
842                Ok(None) => {},
843                Err(e) => {return Err(e)}
844            }
845        }
846        match &self.first_row {
847            Some(v) => Ok(v.clone()),
848            None => Err(anyhow!("no header row!"))
849        }
850    }
851    fn process_merged_cells(&mut self, count: usize) -> Result<()> {
852        if self.status == 1 || self.status == 0 {
853            if self.merged_rects.is_none() {
854                self.merged_rects = Some(vec![]);
855            }
856            loop {
857                match self.reader.read_event_into(&mut self.buf) {
858                    Ok(Event::Start(ref e)) => {
859                        if e.name().as_ref() == b"mergeCell" {
860                            let attr = get_attr_val!(e, "ref", to_string);
861                            let dim: Vec<&str> = attr.split(':').collect();
862                            if let Some(x) = dim.get(0) {
863                                let left_top = get_tuple_from_ord(x.as_bytes())?;
864                                let right_end =  if let Some(x) = dim.get(1) {
865                                    get_tuple_from_ord(x.as_bytes())?
866                                } else {
867                                    return Err(anyhow!("mergeCell error:{}", attr));
868                                };
869                                if let Some(ref mut mgs) = self.merged_rects {
870                                    mgs.push((left_top, right_end))
871                                };
872                            } else {
873                                return Err(anyhow!("mergeCell error:{}", attr));
874                            }; 
875                        }
876                    },
877                    Ok(Event::Empty(ref e)) => {
878                        if e.name().as_ref() == b"mergeCell" {
879                            let attr = get_attr_val!(e, "ref", to_string);
880                            let dim: Vec<&str> = attr.split(':').collect();
881                            if let Some(x) = dim.get(0) {
882                                let left_top = get_tuple_from_ord(x.as_bytes())?;
883                                let right_end =  if let Some(x) = dim.get(1) {
884                                    get_tuple_from_ord(x.as_bytes())?
885                                } else {
886                                    return Err(anyhow!("mergeCell error:{}", attr));
887                                };
888                                if let Some(ref mut mgs) = self.merged_rects {
889                                    mgs.push((left_top, right_end))
890                                };
891                            } else {
892                                return Err(anyhow!("mergeCell error:{}", attr));
893                            }; 
894                        }
895                    },
896                    Ok(Event::End(ref e)) => {
897                        if e.name().as_ref() != b"mergeCells" {
898                            break;
899                        }
900                        else if e.name().as_ref() != b"mergeCell" {
901                            break;
902                        }
903                    },
904                    Ok(Event::Eof) => {
905                        break;
906                    }, // exits the loop when reaching end of file
907                    _ => {}
908                }
909            };
910            if let Some(ref rects) = self.merged_rects {
911                if rects.len() != count {
912                    self.merged_rects = None;
913                    return Err(anyhow!("the number of merged ranges is not equal to the number of rows"));
914                };
915            }
916        }
917        Ok(())
918    }
919    /// get merged ranges, call after all data getched
920    pub fn get_merged_ranges(&mut self) -> Result<&Vec<MergedRange>> {
921        if self.merged_rects.is_none() {
922            if self.status == 0 {  // 已关闭的情况下读取合并单元格
923                loop {
924                    match self.reader.read_event_into(&mut self.buf) {
925                        Ok(Event::Start(ref e)) => {
926                            if e.name().as_ref() == b"mergeCells" {
927                                let cnt: usize = get_attr_val!(e, "count", parse);
928                                self.process_merged_cells(cnt)?;
929                                break;
930                            };
931                        },
932                        _ => {}
933                    }
934                };
935            } else {
936                return Err(anyhow!("finish fetching data first"));
937            }
938        };
939        if let Some(ref rects) = self.merged_rects {
940            Ok(rects)
941        } else {
942            return Err(anyhow!("merged_rects error"));
943        }
944    }
945    /// Get all the remaining data
946    pub fn get_remaining_cells(&mut self) -> Result<Option<(Vec<u32>, Vec<Vec<CellValue<'_>>>)>> {
947        if self.first_row_is_header {
948            self.get_header_row()?;
949        }
950        match self.get_next_row() {
951            Ok(Some((r, d))) => {
952                let (mut rows, mut data) = if let Some((rn, _)) = self.max_size {
953                    (Vec::with_capacity(max(1, rn-r+1) as usize), Vec::with_capacity(rn as usize))
954                } else {
955                    (Vec::new(), Vec::new())
956                };
957                rows.push(r);
958                data.push(d);
959                loop {
960                    match self.get_next_row() {
961                        Ok(Some((r, d))) => {
962                            rows.push(r);
963                            data.push(d);
964                        },
965                        Ok(None) => {
966                            break Ok(Some((rows, data)));
967                        },
968                        Err(e) => {
969                            break Err(e);
970                        }
971                    };
972                }
973            },
974            Ok(None) => {
975                Ok(None)
976            },
977            Err(e) => {Err(e)}
978        }
979    }
980}
981
982impl<'a> Iterator for XlsxSheet<'a> {
983    type Item = Result<(Vec<u32>, Vec<Vec<CellValue<'a>>>)>;
984    fn next(&mut self) -> Option<Self::Item> {
985        let mut nums = Vec::with_capacity(self.iter_batch);
986        let mut data = Vec::with_capacity(self.iter_batch);
987        if self.first_row_is_header {
988            match self.get_header_row() {
989                Ok(_) => {},
990                Err(e) => {
991                    return Some(Err(e));
992                }
993            }
994        }
995        loop {
996            match self.get_next_row() {
997                Ok(Some(v)) => {
998                    nums.push(v.0);
999                    data.push(v.1);
1000                    if nums.len() >= self.iter_batch { 
1001                        break Some(Ok((nums, data)))
1002                    }
1003                },
1004                Ok(None) => {
1005                    if nums.len() > 0 {
1006                        break Some(Ok((nums, data)))
1007                    } else {
1008                        break None
1009                    }
1010                },
1011                Err(e) => {
1012                    break Some(Err(e));
1013                }
1014            }
1015        }
1016        
1017    }
1018}
1019
1020/// cached sheet reader
1021#[cfg(feature = "cached")]
1022pub struct CachedSheet<'a> {
1023    data: HashMap<RowNum, Vec<CellValue<'a>>>,
1024    key: String,
1025    current: RowNum,
1026    empty: bool,
1027    keep_empty: bool,
1028    iter_batch: usize,
1029    top_nrow: RowNum,
1030    bottom_nrow: RowNum,
1031    left_ncol: ColNum,
1032    right_ncol: ColNum,
1033    header_row: Option<(u32, Vec<CellValue<'a>>)>,
1034    merged_rects: Vec<((RowNum, ColNum), (RowNum, ColNum))>
1035}
1036
1037#[cfg(feature = "cached")]
1038impl <'a> CachedSheet<'a> {
1039    /// whether keep empty rows when iter (default: skip empty rows)
1040    pub fn with_empty_rows(mut self, keep_empty: bool) -> Self {
1041        self.keep_empty = keep_empty;
1042        self
1043    }
1044    /// get sheet name
1045    pub fn sheet_name(&self) -> &String {
1046        &self.key
1047    }
1048    /// check whether the sheet is empty
1049    pub fn is_empty(&self) -> bool {
1050        self.empty
1051    }
1052    /// get row range
1053    pub fn row_range(&self) -> (RowNum, RowNum) {
1054        (self.top_nrow, self.bottom_nrow)
1055    }
1056    /// get column range
1057    pub fn column_range(&self) -> (ColNum, ColNum) {
1058        (self.left_ncol, self.right_ncol)
1059    }
1060    /// get header if first_row_is_header is true
1061    pub fn get_header_row(&self) -> Result<(u32, Vec<CellValue<'a>>)> {
1062        match &self.header_row {
1063            Some(v) => Ok(v.clone()),
1064            None => Err(anyhow!("no header row!"))
1065        }
1066    }
1067    /// get merged ranges, call as any time
1068    pub fn get_merged_ranges(&self) -> &Vec<MergedRange> {
1069        &self.merged_rects
1070    }
1071    /// Get all data
1072    pub fn get_all_cells(&self) -> &HashMap<RowNum, Vec<CellValue<'_>>> {
1073        &self.data
1074    }
1075    /// get cell value by address, if the cell is not exist, return &CellValue::Blank
1076    pub fn get_cell_value<A: AsRef<str>>(&self, addr: A) -> Result<&CellValue<'a>> {
1077        let (row, col) = get_tuple_from_ord(addr.as_ref().as_bytes())?;
1078        if row >= self.top_nrow && row <= self.bottom_nrow
1079            && col >= self.left_ncol && col <= self.right_ncol {
1080            if self.data.contains_key(&row) {
1081                Ok(self.data[&row].get((col-1) as usize).unwrap_or(&CellValue::Blank))
1082            } else {
1083                Ok(&CellValue::Blank)
1084            }
1085        } else {
1086            Err(anyhow!("Invalid address - out of range"))
1087        }
1088    }
1089    /// get cell value by address, if the cell is not exist, return &CellValue::Blank
1090    pub fn get_cell_value_with_merge_info<A: AsRef<str>>(&self, addr: A) -> Result<(&CellValue<'a>, (bool, Option<(RowNum, ColNum)>))> {
1091        let (row, col) = get_tuple_from_ord(addr.as_ref().as_bytes())?;
1092        if row >= self.top_nrow && row <= self.bottom_nrow
1093            && col >= self.left_ncol && col <= self.right_ncol {
1094            let (merge, spans) = is_merged_cell(&self.merged_rects, row, col);
1095            if self.data.contains_key(&row) {
1096                Ok((self.data[&row].get((col-1) as usize).unwrap_or(&CellValue::Blank), (merge, spans)))
1097            } else {
1098                Ok((&CellValue::Blank, (merge, spans)))
1099            }
1100        } else {
1101            Err(anyhow!("Invalid address - out of range"))
1102        }
1103    }
1104}
1105
1106#[cfg(feature = "cached")]
1107impl<'a> Iterator for CachedSheet<'a> {
1108    type Item = (Vec<u32>, Vec<Vec<CellValue<'a>>>);
1109    fn next(&mut self) -> Option<Self::Item> {
1110        let mut nrow = Vec::with_capacity(self.iter_batch);
1111        let mut data = Vec::with_capacity(self.iter_batch);
1112        while nrow.len() < self.iter_batch && self.current <= self.bottom_nrow {
1113            if self.data.contains_key(&self.current) {
1114                nrow.push(self.current);
1115                data.push(self.data[&self.current].to_owned());
1116            } else if self.keep_empty {
1117                nrow.push(self.current);
1118                data.push(vec![]);
1119            };
1120            self.current += 1;
1121        }
1122        Some((nrow, data))
1123    }
1124}
1125
1126/// get another type of data from cell value
1127pub trait FromCellValue {
1128    fn try_from_cval(val: &CellValue<'_>) -> Result<Option<Self>> 
1129        where Self: Sized;
1130}
1131
1132impl FromCellValue for String {
1133    fn try_from_cval(val: &CellValue<'_>) -> Result<Option<Self>> {
1134        match val {
1135            CellValue::Number(n) => Ok(Some(n.to_string())),
1136            CellValue::Date(n) => {
1137                Ok(Some((BASE_DATE.clone()+(Duration::try_days(*n as i64).ok_or(anyhow!("invalid date"))?)).to_string()))
1138            },
1139            CellValue::Time(n) => {
1140                Ok(Some(NaiveTime::from_num_seconds_from_midnight_opt(((*n-n.trunc()) * 86400.0) as u32, 0).unwrap().format("%H:%M:%S").to_string()))
1141            }
1142            CellValue::Datetime(n) => {
1143                Ok(Some((BASE_DATETIME.clone()+(Duration::try_days(*n as i64).ok_or(anyhow!("invalid date"))?)+(Duration::try_seconds(((*n-n.trunc()) * 86400.0) as i64).ok_or(anyhow!("invalid date"))?)).to_string()))
1144            },
1145            CellValue::Shared(s) => Ok(Some((**s).to_owned())),
1146            CellValue::String(s) => Ok(Some((*s).to_owned())),
1147            CellValue::Error(s) => Ok(Some((*s).to_string())),
1148            CellValue::Bool(b) => Ok(Some(if *b {"true".to_string()}else{"false".to_string()})),
1149            CellValue::Blank => Ok(Some("".to_string())),
1150        }
1151    }
1152}
1153
1154impl FromCellValue for f64 {
1155    fn try_from_cval(val: &CellValue<'_>) -> Result<Option<Self>> {
1156        match val {
1157            CellValue::Number(n) => Ok(Some(*n)),
1158            CellValue::Date(n) => Ok(Some(*n)),
1159            CellValue::Time(n) => Ok(Some(*n)),
1160            CellValue::Datetime(n) => Ok(Some(*n)),
1161            CellValue::Shared(s) => {
1162                match s.parse::<f64>() {
1163                    Ok(n) => Ok(Some(n)),
1164                    Err(_) => {
1165                        if NULL_STRING.contains(*s) {
1166                            Ok(None)
1167                        } else if let Ok(n) = s.replace(',', "").parse::<f64>() {
1168                            Ok(Some(n))
1169                        } else {
1170                            Err(anyhow!(format!("invalid value-{:?}", val)))
1171                        }
1172                    }
1173                }
1174            },
1175            CellValue::String(s) => {
1176                match s.parse::<f64>() {
1177                    Ok(n) => Ok(Some(n)),
1178                    Err(_) => {
1179                        if NULL_STRING.contains(s) {
1180                            Ok(None)
1181                        } else if let Ok(n) = s.replace(',', "").parse::<f64>() {
1182                            Ok(Some(n))
1183                        } else {
1184                            Err(anyhow!(format!("invalid value-{:?}", val)))
1185                        }
1186                    }
1187                }
1188            },
1189            CellValue::Error(_) => Err(anyhow!(format!("invalid value-{:?}", val))),
1190            CellValue::Bool(b) => Ok(Some(if *b {1.0}else{0.0})),
1191            CellValue::Blank => Ok(None),
1192        }
1193    }
1194}
1195
1196impl FromCellValue for i64 {
1197    fn try_from_cval(val: &CellValue<'_>) -> Result<Option<Self>> {
1198        match val {
1199            CellValue::Number(n) => Ok(Some(*n as i64)),
1200            CellValue::Date(n) => Ok(Some(*n as i64)),
1201            CellValue::Time(n) => Ok(Some(*n as i64)),
1202            CellValue::Datetime(n) => Ok(Some(*n as i64)),
1203            CellValue::Shared(s) => {
1204                match s.parse::<i64>() {
1205                    Ok(n) => Ok(Some(n)),
1206                    Err(_) => {
1207                        if NULL_STRING.contains(*s) {
1208                            Ok(None)
1209                        } else if let Ok(n) = s.replace(',', "").parse::<i64>() {
1210                            Ok(Some(n))
1211                        } else {
1212                            Err(anyhow!(format!("invalid value-{:?}", val)))
1213                        }
1214                    }
1215                }
1216            },
1217            CellValue::String(s) => {
1218                match s.parse::<i64>() {
1219                    Ok(n) => Ok(Some(n)),
1220                    Err(_) => {
1221                        if NULL_STRING.contains(s) {
1222                            Ok(None)
1223                        } else if let Ok(n) = s.replace(',', "").parse::<i64>() {
1224                            Ok(Some(n))
1225                        } else {
1226                            Err(anyhow!(format!("invalid value-{:?}", val)))
1227                        }
1228                    }
1229                }
1230            },
1231            CellValue::Error(_) => Err(anyhow!(format!("invalid value-{:?}", val))),
1232            CellValue::Bool(b) => Ok(Some(if *b {1}else{0})),
1233            CellValue::Blank => Ok(None),
1234        }
1235    }
1236}
1237
1238impl FromCellValue for bool {
1239    fn try_from_cval(val: &CellValue<'_>) -> Result<Option<Self>> {
1240        match val {
1241            CellValue::Number(n) => {if (*n).abs() > 0.009 {Ok(Some(true))} else {Ok(Some(false))}},
1242            CellValue::Date(n) => {if (*n).abs() > 0.009 {Ok(Some(true))} else {Ok(Some(false))}},
1243            CellValue::Time(n) => {if (*n).abs() > 0.009 {Ok(Some(true))} else {Ok(Some(false))}},
1244            CellValue::Datetime(n) => {if (*n).abs() > 0.009 {Ok(Some(true))} else {Ok(Some(false))}},
1245            CellValue::Shared(s) => {
1246                match s.parse::<bool>() {
1247                    Ok(n) => Ok(Some(n)),
1248                    Err(_) => {
1249                        if NULL_STRING.contains(*s) {
1250                            Ok(None)
1251                        } else {
1252                            Err(anyhow!(format!("invalid value-{:?}", val)))
1253                        }
1254                    }
1255                }
1256            },
1257            CellValue::String(s) => {
1258                match s.parse::<bool>() {
1259                    Ok(n) => Ok(Some(n)),
1260                    Err(_) => {
1261                        if NULL_STRING.contains(s) {
1262                            Ok(None)
1263                        } else {
1264                            Err(anyhow!(format!("invalid value-{:?}", val)))
1265                        }
1266                    }
1267                }
1268            },
1269            CellValue::Error(_) => Err(anyhow!(format!("invalid value-{:?}", val))),
1270            CellValue::Bool(b) => Ok(Some(*b)),
1271            CellValue::Blank => Ok(None),
1272        }
1273    }
1274}
1275
1276impl FromCellValue for NaiveDate {
1277    fn try_from_cval(val: &CellValue<'_>) -> Result<Option<Self>> {
1278        match val {
1279            CellValue::Number(n) => Ok(Some(BASE_DATE.clone()+(Duration::try_days(*n as i64).ok_or(anyhow!("invalid datetime"))?))),
1280            CellValue::Date(n) => Ok(Some(BASE_DATE.clone()+(Duration::try_days(*n as i64).ok_or(anyhow!("invalid datetime"))?))),
1281            CellValue::Time(n) => Ok(Some(BASE_DATE.clone()+(Duration::try_days(*n as i64).ok_or(anyhow!("invalid datetime"))?))),
1282            CellValue::Datetime(n) => Ok(Some(BASE_DATE.clone()+(Duration::try_days(*n as i64).ok_or(anyhow!("invalid datetime"))?))),
1283            CellValue::Shared(s) => {
1284                match NaiveDate::parse_from_str(*s, "%Y-%m-%d") {
1285                    Ok(v) => Ok(Some(v)),
1286                    Err(_) => {
1287                        match NaiveDate::parse_from_str(*s, "%Y/%m/%d") {
1288                            Ok(v) => Ok(Some(v)),
1289                            Err(_) => {
1290                                if NULL_STRING.contains(*s) {
1291                                    Ok(None)
1292                                } else {
1293                                    Err(anyhow!(format!("invalid value-{:?}", val)))
1294                                }
1295                            }
1296                        }
1297                    }
1298                }
1299            },
1300            CellValue::String(s) => {
1301                match NaiveDate::parse_from_str(s, "%Y-%m-%d") {
1302                    Ok(v) => Ok(Some(v)),
1303                    Err(_) => {
1304                        match NaiveDate::parse_from_str(s, "%Y/%m/%d") {
1305                            Ok(v) => Ok(Some(v)),
1306                            Err(_) => {
1307                                if NULL_STRING.contains(s) {
1308                                    Ok(None)
1309                                } else {
1310                                    Err(anyhow!(format!("invalid value-{:?}", val)))
1311                                }
1312                            }
1313                        }
1314                    }
1315                }
1316            },
1317            CellValue::Error(_) => Err(anyhow!(format!("invalid datetime{:?}", val))),
1318            CellValue::Bool(_) => Err(anyhow!(format!("invalid datetime{:?}", val))),
1319            CellValue::Blank => Ok(None),
1320        }
1321    }
1322}
1323
1324impl FromCellValue for NaiveDateTime {
1325    fn try_from_cval(val: &CellValue<'_>) -> Result<Option<Self>> {
1326        match val {
1327            CellValue::Number(n) => {
1328                Ok(Some(BASE_DATETIME.clone()+(Duration::try_days(*n as i64).ok_or(anyhow!("invalid date"))?)+(Duration::try_seconds(((*n-n.trunc()) * 86400.0) as i64).ok_or(anyhow!("invalid date"))?)))
1329            },
1330            CellValue::Date(n) => {
1331                Ok(Some(BASE_DATETIME.clone()+(Duration::try_days(*n as i64).ok_or(anyhow!("invalid date"))?)+(Duration::try_seconds(((*n-n.trunc()) * 86400.0) as i64).ok_or(anyhow!("invalid date"))?)))
1332            },
1333            CellValue::Time(n) => {
1334                Ok(Some(BASE_DATETIME.clone()+(Duration::try_days(*n as i64).ok_or(anyhow!("invalid date"))?)+(Duration::try_seconds(((*n-n.trunc()) * 86400.0) as i64).ok_or(anyhow!("invalid date"))?)))
1335            },
1336            CellValue::Datetime(n) => {
1337                Ok(Some(BASE_DATETIME.clone()+(Duration::try_days(*n as i64).ok_or(anyhow!("invalid date"))?)+(Duration::try_seconds(((*n-n.trunc()) * 86400.0) as i64).ok_or(anyhow!("invalid date"))?)))
1338            },
1339            CellValue::Shared(s) => {
1340                match NaiveDateTime::parse_from_str(*s, "%Y-%m-%d %H:%M:%S") {
1341                    Ok(v) => Ok(Some(v)),
1342                    Err(_) => {
1343                        match NaiveDateTime::parse_from_str(*s, "%Y/%m/%d %H:%M:%S") {
1344                            Ok(v) => Ok(Some(v)),
1345                            Err(_) => {
1346                                if NULL_STRING.contains(*s) {
1347                                    Ok(None)
1348                                } else {
1349                                    Err(anyhow!(format!("invalid value-{:?}", val)))
1350                                }
1351                            }
1352                        }
1353                    }
1354                }
1355            },
1356            CellValue::String(s) => {
1357                match NaiveDateTime::parse_from_str(s, "%Y-%m-%d %H:%M:%S") {
1358                    Ok(v) => Ok(Some(v)),
1359                    Err(_) => {
1360                        match NaiveDateTime::parse_from_str(s, "%Y/%m/%d %H:%M:%S") {
1361                            Ok(v) => Ok(Some(v)),
1362                            Err(_) => {
1363                                if NULL_STRING.contains(s) {
1364                                    Ok(None)
1365                                } else {
1366                                    Err(anyhow!(format!("invalid value-{:?}", val)))
1367                                }
1368                            }
1369                        }
1370                    }
1371                }
1372            },
1373            CellValue::Error(_) => Err(anyhow!(format!("invalid datetime{:?}", val))),
1374            CellValue::Bool(_) => Err(anyhow!(format!("invalid datetime{:?}", val))),
1375            CellValue::Blank => Ok(None),
1376        }
1377    }
1378}
1379
1380impl FromCellValue for NaiveTime {
1381    fn try_from_cval(val: &CellValue<'_>) -> Result<Option<Self>> {
1382        match val {
1383            CellValue::Number(n) => {
1384                Ok(Some(NaiveTime::from_num_seconds_from_midnight_opt(((*n-n.trunc()) * 86400.0) as u32, 0).ok_or(anyhow!("invalid time"))?))
1385            },
1386            CellValue::Date(n) => {
1387                Ok(Some(NaiveTime::from_num_seconds_from_midnight_opt(((*n-n.trunc()) * 86400.0) as u32, 0).ok_or(anyhow!("invalid time"))?))
1388            },
1389            CellValue::Time(n) => {
1390                Ok(Some(NaiveTime::from_num_seconds_from_midnight_opt(((*n-n.trunc()) * 86400.0) as u32, 0).ok_or(anyhow!("invalid time"))?))
1391            },
1392            CellValue::Datetime(n) => {
1393                Ok(Some(NaiveTime::from_num_seconds_from_midnight_opt(((*n-n.trunc()) * 86400.0) as u32, 0).ok_or(anyhow!("invalid time"))?))
1394            },
1395            CellValue::Shared(s) => {
1396                match NaiveTime::parse_from_str(*s, "%H:%M:%S") {
1397                    Ok(v) => Ok(Some(v)),
1398                    Err(_) => {
1399                        match NaiveTime::parse_from_str(*s, "%H:%M:%S") {
1400                            Ok(v) => Ok(Some(v)),
1401                            Err(_) => {
1402                                if NULL_STRING.contains(*s) {
1403                                    Ok(None)
1404                                } else {
1405                                    Err(anyhow!(format!("invalid value-{:?}", val)))
1406                                }
1407                            }
1408                        }
1409                    }
1410                }
1411            },
1412            CellValue::String(s) => {
1413                match NaiveTime::parse_from_str(s, "%H:%M:%S") {
1414                    Ok(v) => Ok(Some(v)),
1415                    Err(_) => {
1416                        match NaiveTime::parse_from_str(s, "%H:%M:%S") {
1417                            Ok(v) => Ok(Some(v)),
1418                            Err(_) => {
1419                                if NULL_STRING.contains(s) {
1420                                    Ok(None)
1421                                } else {
1422                                    Err(anyhow!(format!("invalid value-{:?}", val)))
1423                                }
1424                            }
1425                        }
1426                    }
1427                }
1428            },
1429            CellValue::Error(_) => Err(anyhow!(format!("invalid time{:?}", val))),
1430            CellValue::Bool(_) => Err(anyhow!(format!("invalid time{:?}", val))),
1431            CellValue::Blank => Ok(None),
1432        }
1433    }
1434}
1435
1436impl FromCellValue for Date32 {
1437    fn try_from_cval(val: &CellValue<'_>) -> Result<Option<Self>> {
1438        match val {
1439            // 1970-01-01的Excel值为25569
1440            CellValue::Number(n) => Ok(Some((*n as i32)-25569)),
1441            CellValue::Date(n) => Ok(Some((*n as i32)-25569)),
1442            CellValue::Time(n) => Ok(Some((*n as i32)-25569)),
1443            CellValue::Datetime(n) => Ok(Some((*n as i32)-25569)),
1444            CellValue::Shared(s) => {
1445                match NaiveDate::parse_from_str(*s, "%Y-%m-%d") {
1446                    Ok(v) => Ok(Some((v - UNIX_DATE.clone()).num_days() as i32)),
1447                    Err(_) => {
1448                        match NaiveDate::parse_from_str(*s, "%Y/%m/%d") {
1449                            Ok(v) => Ok(Some((v - UNIX_DATE.clone()).num_days() as i32)),
1450                            Err(_) => {
1451                                if NULL_STRING.contains(*s) {
1452                                    Ok(None)
1453                                } else {
1454                                    Err(anyhow!(format!("invalid value-{:?}", val)))
1455                                }
1456                            }
1457                        }
1458                    }
1459                }
1460            },
1461            CellValue::String(s) => {
1462                match NaiveDate::parse_from_str(s, "%Y-%m-%d") {
1463                    Ok(v) => Ok(Some((v - UNIX_DATE.clone()).num_days() as i32)),
1464                    Err(_) => {
1465                        match NaiveDate::parse_from_str(s, "%Y/%m/%d") {
1466                            Ok(v) => Ok(Some((v - UNIX_DATE.clone()).num_days() as i32)),
1467                            Err(_) => {
1468                                if NULL_STRING.contains(s) {
1469                                    Ok(None)
1470                                } else {
1471                                    Err(anyhow!(format!("invalid value-{:?}", val)))
1472                                }
1473                            }
1474                        }
1475                    }
1476                }
1477            },
1478            CellValue::Error(_) => Err(anyhow!(format!("invalid date32-{:?}", val))),
1479            CellValue::Bool(_) => Err(anyhow!(format!("invalid date32-{:?}", val))),
1480            CellValue::Blank => Ok(None),
1481        }
1482    }
1483}
1484
1485impl FromCellValue for Timestamp {
1486    fn try_from_cval(val: &CellValue<'_>) -> Result<Option<Self>> {
1487        match val {
1488            // 1970-01-01的Excel值为25569
1489            CellValue::Number(n) => Ok(Some(((*n - 25569.0) * 86400.0).into())),
1490            CellValue::Date(n) => Ok(Some(((*n - 25569.0) * 86400.0).into())),
1491            CellValue::Time(n) => Ok(Some(((*n - 25569.0) * 86400.0).into())),
1492            CellValue::Datetime(n) => Ok(Some(((*n - 25569.0) * 86400.0).into())),
1493            CellValue::Shared(s) => {
1494                match NaiveDateTime::parse_from_str(*s, "%Y-%m-%d %H:%M:%S") {
1495                    Ok(v) => Ok(Some(v.and_utc().timestamp().into())),
1496                    Err(_) => {
1497                        match NaiveDateTime::parse_from_str(*s, "%Y-%m-%d %H:%M:%S") {
1498                            Ok(v) => Ok(Some(v.and_utc().timestamp().into())),
1499                            Err(_) => {
1500                                if NULL_STRING.contains(*s) {
1501                                    Ok(None)
1502                                } else {
1503                                    Err(anyhow!(format!("invalid value-{:?}", val)))
1504                                }
1505                            }
1506                        }
1507                    }
1508                }
1509            },
1510            CellValue::String(s) => {
1511                match NaiveDateTime::parse_from_str(s, "%Y-%m-%d %H:%M:%S") {
1512                    Ok(v) => Ok(Some(v.and_utc().timestamp().into())),
1513                    Err(_) => {
1514                        match NaiveDateTime::parse_from_str(s, "%Y/%m/%d %H:%M:%S") {
1515                            Ok(v) => Ok(Some(v.and_utc().timestamp().into())),
1516                            Err(_) => {
1517                                if NULL_STRING.contains(s) {
1518                                    Ok(None)
1519                                } else {
1520                                    Err(anyhow!(format!("invalid value-{:?}", val)))
1521                                }
1522                            }
1523                        }
1524                    }
1525                }
1526            },
1527            CellValue::Error(_) => Err(anyhow!(format!("invalid timestamp-{:?}", val))),
1528            CellValue::Bool(_) => Err(anyhow!(format!("invalid timestamp-{:?}", val))),
1529            CellValue::Blank => Ok(None),
1530        }
1531    }
1532}
1533
1534impl FromCellValue for Timesecond {
1535    fn try_from_cval(val: &CellValue<'_>) -> Result<Option<Self>> {
1536        match val {
1537            CellValue::Number(n) => {
1538                Ok(Some((((*n-n.trunc()) * 86400.0) as i32).into()))
1539            },
1540            CellValue::Date(n) => {
1541                Ok(Some((((*n-n.trunc()) * 86400.0) as i32).into()))
1542            },
1543            CellValue::Time(n) => {
1544                Ok(Some((((*n-n.trunc()) * 86400.0) as i32).into()))
1545            },
1546            CellValue::Datetime(n) => {
1547                Ok(Some((((*n-n.trunc()) * 86400.0) as i32).into()))
1548            },
1549            CellValue::Shared(s) => {
1550                match NaiveTime::parse_from_str(*s, "%H:%M:%S") {
1551                    Ok(v) => {Ok(Some((v.num_seconds_from_midnight() as i32).into()))},
1552                    Err(_) => {
1553                        match NaiveTime::parse_from_str(*s, "%H:%M:%S") {
1554                            Ok(v) =>Ok(Some((v.num_seconds_from_midnight() as i32).into())),
1555                            Err(_) => {
1556                                if NULL_STRING.contains(*s) {
1557                                    Ok(None)
1558                                } else {
1559                                    Err(anyhow!(format!("invalid value-{:?}", val)))
1560                                }
1561                            }
1562                        }
1563                    }
1564                }
1565            },
1566            CellValue::String(s) => {
1567                match NaiveTime::parse_from_str(s, "%H:%M:%S") {
1568                    Ok(v) => {Ok(Some((v.num_seconds_from_midnight() as i32).into()))},
1569                    Err(_) => {
1570                        match NaiveTime::parse_from_str(s, "%H:%M:%S") {
1571                            Ok(v) =>Ok(Some((v.num_seconds_from_midnight() as i32).into())),
1572                            Err(_) => {
1573                                if NULL_STRING.contains(s) {
1574                                    Ok(None)
1575                                } else {
1576                                    Err(anyhow!(format!("invalid value-{:?}", val)))
1577                                }
1578                            }
1579                        }
1580                    }
1581                }
1582            },
1583            CellValue::Error(_) => Err(anyhow!(format!("invalid time{:?}", val))),
1584            CellValue::Bool(_) => Err(anyhow!(format!("invalid time{:?}", val))),
1585            CellValue::Blank => Ok(None),
1586        }
1587    }
1588}
1589
1590/// Into CellValue
1591impl Into<CellValue<'_>> for String {
1592    fn into(self) -> CellValue<'static> {
1593        CellValue::String(self)
1594    }
1595}
1596
1597impl Into<CellValue<'_>> for f64 {
1598    fn into(self) -> CellValue<'static> {
1599        CellValue::Number(self)
1600    }
1601}
1602
1603impl Into<CellValue<'_>> for i64 {
1604    fn into(self) -> CellValue<'static> {
1605        CellValue::Number(self as f64)
1606    }
1607}
1608
1609impl Into<CellValue<'_>> for bool {
1610    fn into(self) -> CellValue<'static> {
1611        CellValue::Bool(self)
1612    }
1613}
1614
1615/// make another type of data into cell value
1616pub trait IntoCellValue {
1617    fn try_into_cval(self) -> Result<CellValue<'static>>;
1618}
1619
1620impl IntoCellValue for NaiveDate {
1621    fn try_into_cval(self) -> Result<CellValue<'static>> {
1622        Ok(CellValue::Date((self.signed_duration_since(*BASE_DATE).num_days()) as f64))
1623    }
1624}
1625
1626impl IntoCellValue for NaiveDateTime {
1627    fn try_into_cval(self) -> Result<CellValue<'static>> {
1628        let (dt, tm) = (self.date(), self.time());
1629        Ok(CellValue::Datetime(((dt.signed_duration_since(*BASE_DATE).num_days()) as f64) + ((tm.num_seconds_from_midnight() as f64) / 86400.0)))
1630    }
1631}
1632
1633impl IntoCellValue for NaiveTime {
1634    fn try_into_cval(self) -> Result<CellValue<'static>> {
1635        Ok(CellValue::Time((self.num_seconds_from_midnight() as f64) / 86400.0))
1636    }
1637}
1638
1639impl IntoCellValue for Date32 {
1640    fn try_into_cval(self) -> Result<CellValue<'static>> {
1641        Ok(CellValue::Date((self + 25569) as f64))
1642    }
1643}
1644
1645// utc time-zone only
1646impl IntoCellValue for Timestamp {
1647    fn try_into_cval(self) -> Result<CellValue<'static>> {
1648        if let Some(v) = BASE_DATETIME.checked_add_signed(Duration::seconds(self.0)) {
1649            v.try_into_cval()
1650        } else {
1651            Ok(CellValue::Error(format!("Invalid Timestamp-{}", self.0)))
1652        }
1653    }
1654}
1655
1656impl IntoCellValue for Timesecond {
1657    fn try_into_cval(self) -> Result<CellValue<'static>> {
1658        Ok(CellValue::Time(self.0 as f64 / 86400.0))
1659    }
1660}
1661
1662// datetime sign
1663static FMT_DATE: u8 = 0;
1664static FMT_TIME: u8 = 1;
1665static FMT_DATETIME: u8 = 2;
1666static FMT_DEFAULT: u8 = 255;
1667
1668lazy_static! {
1669    static ref BASE_DATE: NaiveDate = NaiveDate::from_ymd_opt(1899, 12,30).unwrap();
1670    static ref BASE_DATETIME: NaiveDateTime = BASE_DATE.and_hms_opt(0, 0, 0).unwrap();
1671    static ref BASE_TIME: NaiveTime = NaiveTime::from_num_seconds_from_midnight_opt(0, 0).unwrap();
1672    static ref UNIX_DATE: NaiveDate = NaiveDate::from_ymd_opt(1970,  1, 1).unwrap();
1673    static ref NULL_STRING: HashSet<String> = {
1674        let mut v = HashSet::new();
1675        v.insert("".into());
1676        v.insert("-".into());
1677        v.insert("--".into());
1678        v.insert("#N/A".into());
1679        v
1680    };
1681    static ref DATETIME_FMTS: HashMap<u32, u8> = {
1682        let mut v = HashMap::new();
1683        v.extend((14..18).map(|n| (n, FMT_DATE)));
1684        v.extend((27..32).map(|n| (n, FMT_DATE)));
1685        v.extend((34..37).map(|n| (n, FMT_DATE)));
1686        v.extend((50..59).map(|n| (n, FMT_DATE)));  // FMT_DATE - 0
1687        v.extend((18..22).map(|n| (n, FMT_TIME)));
1688        v.extend((32..34).map(|n| (n, FMT_TIME)));
1689        v.extend((45..48).map(|n| (n, FMT_TIME)));  // FMT_TIME - 1
1690        v.insert(22, FMT_DATETIME);                 // FMT_DATETIME - 2
1691        v
1692    };
1693    static ref NUM_FMTS: HashMap<u32, String> = {
1694        let mut map: HashMap<u32, String> = HashMap::new();
1695        // General
1696        map.insert(0, "General".to_string());
1697        map.insert(1, "0".to_string());
1698        map.insert(2, "0.00".to_string());
1699        map.insert(3, "#,##0".to_string());
1700        map.insert(4, "#,##0.00".to_string());
1701
1702        map.insert(9, "0%".to_string());
1703        map.insert(10, "0.00%".to_string());
1704        map.insert(11, "0.00E+00".to_string());
1705        map.insert(12, "# ?/?".to_string());
1706        map.insert(13, "# ??/??".to_string());
1707        map.insert(14, "m/d/yyyy".to_string()); // Despite ECMA 'mm-dd-yy");
1708        map.insert(15, "d-mmm-yy".to_string());
1709        map.insert(16, "d-mmm".to_string());
1710        map.insert(17, "mmm-yy".to_string());
1711        map.insert(18, "h:mm AM/PM".to_string());
1712        map.insert(19, "h:mm:ss AM/PM".to_string());
1713        map.insert(20, "h:mm".to_string());
1714        map.insert(21, "h:mm:ss".to_string());
1715        map.insert(22, "m/d/yyyy h:mm".to_string()); // Despite ECMA 'm/d/yy h:mm");
1716
1717        map.insert(37, "#,##0_);(#,##0)".to_string()); //  Despite ECMA '#,##0 ;(#,##0)");
1718        map.insert(38, "#,##0_);[Red](#,##0)".to_string()); //  Despite ECMA '#,##0 ;[Red](#,##0)");
1719        map.insert(39, "#,##0.00_);(#,##0.00)".to_string()); //  Despite ECMA '#,##0.00;(#,##0.00)");
1720        map.insert(40, "#,##0.00_);[Red](#,##0.00)".to_string()); //  Despite ECMA '#,##0.00;[Red](#,##0.00)");
1721
1722        map.insert(44, r###"_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)"###.to_string());
1723        map.insert(45, "mm:ss".to_string());
1724        map.insert(46, "[h]:mm:ss".to_string());
1725        map.insert(47, "mm:ss.0".to_string()); //  Despite ECMA 'mmss.0");
1726        map.insert(48, "##0.0E+0".to_string());
1727        map.insert(49, "@".to_string());
1728
1729        // CHT
1730        map.insert(27, "[$-404]e/m/d".to_string());
1731        map.insert(30, "m/d/yy".to_string());
1732        map.insert(36, "[$-404]e/m/d".to_string());
1733        map.insert(50, "[$-404]e/m/d".to_string());
1734        map.insert(57, "[$-404]e/m/d".to_string());
1735
1736        // THA
1737        map.insert(59, "t0".to_string());
1738        map.insert(60, "t0.00".to_string());
1739        map.insert(61, "t#,##0".to_string());
1740        map.insert(62, "t#,##0.00".to_string());
1741        map.insert(67, "t0%".to_string());
1742        map.insert(68, "t0.00%".to_string());
1743        map.insert(69, "t# ?/?".to_string());
1744        map.insert(70, "t# ??/??".to_string());
1745
1746        // JPN
1747        map.insert(28, r###"[$-411]ggge"年"m"月"d"日""###.to_string());
1748        map.insert(29, r###"[$-411]ggge"年"m"月"d"日""###.to_string());
1749        map.insert(31, r###"yyyy"年"m"月"d"日""###.to_string());
1750        map.insert(32, r###"h"時"mm"分""###.to_string());
1751        map.insert(33, r###"h"時"mm"分"ss"秒""###.to_string());
1752        map.insert(34, r###"yyyy"年"m"月""###.to_string());
1753        map.insert(35, r###"m"月"d"日""###.to_string());
1754        map.insert(51, r###"[$-411]ggge"年"m"月"d"日""###.to_string());
1755        map.insert(52, r###"yyyy"年"m"月""###.to_string());
1756        map.insert(53, r###"m"月"d"日""###.to_string());
1757        map.insert(54, r###"[$-411]ggge"年"m"月"d"日""###.to_string());
1758        map.insert(55, r###"yyyy"年"m"月""###.to_string());
1759        map.insert(56, r###"m"月"d"日""###.to_string());
1760        map.insert(58, r###"[$-411]ggge"年"m"月"d"日""###.to_string());
1761
1762        map
1763    };
1764    static ref EMP_CELLS: Vec<CellValue<'static>> = vec![];
1765}