spsheet 0.1.0

A xlsx or ods read and write spreadsheet library
Documentation
use file_common::*;
use std::collections::HashMap;
use std::io::Cursor;
use std::result;
use super::quick_xml::events::{Event, BytesDecl};
use super::quick_xml::writer::Writer;
use super::tempdir::TempDir;
use super::{Book, Value};
use super::XlsxError;

const STYLE_XML: &'static str = "xl/styles.xml";

fn make_num_fmts(writer: &mut Writer<Cursor<Vec<u8>>>, book: &Book) -> Vec<HashMap<String, String>> {
    let mut result = vec![];
    let mut num_fmot_id = 164;
    let mut key_map = HashMap::new();
    for sheet in book.get_sheet_vec() {
        sheet.walk_through(|_, _, cell| {
            match cell.get_value() {
                &Value::Date(_) => {
                    let format = cell.get_style().get_format();
                    if !key_map.contains_key(format) {
                        let mut map = HashMap::new();
                        map.insert(String::from("numFmtId"), num_fmot_id.to_string());
                        map.insert(String::from("format"), format.clone());
                        result.push(map);
                        num_fmot_id = num_fmot_id + 1;
                        key_map.insert(format.clone(), ());
                    }
                },
                _ => {}
            }
        });
    }

    write_start_tag(writer, "numFmts", vec![
        ("count", result.len().to_string().as_str()),
    ], false);

    for map in result.iter() {
        let num_fmt_id = map.get(&String::from("numFmtId")).unwrap();
        let format_code = map.get(&String::from("format")).unwrap();
        write_start_tag(writer, "numFmt", vec![
            ("numFmtId", num_fmt_id.as_str()),
            ("formatCode", format_code.as_str()),
        ], true);
    }

    write_end_tag(writer, "numFmts");
    result
}

fn make_cell_xfs(writer: &mut Writer<Cursor<Vec<u8>>>, num_fmts: &Vec<HashMap<String, String>>) -> HashMap<String, usize> {
    let mut result: HashMap<String, usize> = HashMap::new();
    let count = num_fmts.len() + 1;
    write_start_tag(writer, "cellXfs", vec![("count", count.to_string().as_str()),], false);
    write_start_tag(writer, "xf", vec![
        ("borderId", "0"),
        ("fillId", "0"),
        ("fontId", "0"),
        ("numFmtId", "0"),
        ("xfId", "0"),
        ("applyAlignment", "1"),
        ("applyFont", "1"),
    ], false);
    write_start_tag(writer, "alignment", vec![
        ("readingOrder", "0"),
        ("shrinkToFit", "0"),
        ("vertical", "bottom"),
        ("wrapText", "0"),
    ], true);
    write_end_tag(writer, "xf");

    let mut count = 0;
    for map in num_fmts.iter() {
        count = count + 1;
        let num_fmt_id = map.get(&String::from("numFmtId")).unwrap();
        let format_code = map.get(&String::from("format")).unwrap();
        result.insert(format_code.clone(), count as usize);
        write_start_tag(writer, "xf", vec![
            ("borderId", "0"),
            ("fillId", "0"),
            ("fontId", "1"),
            ("numFmtId", num_fmt_id.to_string().as_str()),
            ("xfId", "0"),
            ("applyAlignment", "1"),
            ("applyFont", "1"),
        ], false);
        write_start_tag(writer, "alignment", vec![
            ("readingOrder", "0"),
        ], true);
        write_end_tag(writer, "xf");
    }

    write_end_tag(writer, "cellXfs");
    result
}

pub fn write(book: &Book, dir: &TempDir) -> result::Result<HashMap<String, usize>, XlsxError> {
    let mut writer = Writer::new(Cursor::new(Vec::new()));
    let _ = writer.write_event(Event::Decl(
        BytesDecl::new(b"1.0", Some(b"UTF-8"), Some(b"yes"))));
    write_text_node(&mut writer, "\n");
    write_start_tag(&mut writer, "styleSheet", vec![("xmlns", "http://schemas.openxmlformats.org/spreadsheetml/2006/main"),("xmlns:x14ac", "http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac"),("xmlns:mc", "http://schemas.openxmlformats.org/markup-compatibility/2006"),], false);
    
    let num_fmts = make_num_fmts(&mut writer, book);
    
    write_start_tag(&mut writer, "fonts", vec![("count", "2"),], false);
    write_start_tag(&mut writer, "font", vec![], false);
    write_start_tag(&mut writer, "sz", vec![("val", "10.0"),], false);
    write_end_tag(&mut writer, "sz");
    write_start_tag(&mut writer, "color", vec![("rgb", "FF000000"),], false);
    write_end_tag(&mut writer, "color");
    write_start_tag(&mut writer, "name", vec![("val", "Arial"),], false);
    write_end_tag(&mut writer, "name");
    write_end_tag(&mut writer, "font");
    write_start_tag(&mut writer, "font", vec![], false);
    write_end_tag(&mut writer, "font");
    write_end_tag(&mut writer, "fonts");
    write_start_tag(&mut writer, "fills", vec![("count", "2"),], false);
    write_start_tag(&mut writer, "fill", vec![], false);
    write_start_tag(&mut writer, "patternFill", vec![("patternType", "none"),], false);
    write_end_tag(&mut writer, "patternFill");
    write_end_tag(&mut writer, "fill");
    write_start_tag(&mut writer, "fill", vec![], false);
    write_start_tag(&mut writer, "patternFill", vec![("patternType", "lightGray"),], false);
    write_end_tag(&mut writer, "patternFill");
    write_end_tag(&mut writer, "fill");
    write_end_tag(&mut writer, "fills");
    write_start_tag(&mut writer, "borders", vec![("count", "1"),], false);
    write_start_tag(&mut writer, "border", vec![], false);
    write_end_tag(&mut writer, "border");
    write_end_tag(&mut writer, "borders");
    write_start_tag(&mut writer, "cellStyleXfs", vec![("count", "1"),], false);
    write_start_tag(&mut writer, "xf", vec![("borderId", "0"),("fillId", "0"),("fontId", "0"),("numFmtId", "0"),("applyAlignment", "1"),("applyFont", "1"),], false);
    write_end_tag(&mut writer, "xf");
    write_end_tag(&mut writer, "cellStyleXfs");

    let result = make_cell_xfs(&mut writer, &num_fmts);

    write_start_tag(&mut writer, "cellStyles", vec![("count", "1"),], false);
    write_start_tag(&mut writer, "cellStyle", vec![("xfId", "0"),("name", "Normal"),("builtinId", "0"),], false);
    write_end_tag(&mut writer, "cellStyle");
    write_end_tag(&mut writer, "cellStyles");
    write_start_tag(&mut writer, "dxfs", vec![("count", "0"),], false);
    write_end_tag(&mut writer, "dxfs");
    write_end_tag(&mut writer, "styleSheet");
    
    let _ = make_file_from_writer(STYLE_XML, dir, writer, Some("xl"))?;
    Ok(result)
}