umya_spreadsheet/writer/
csv.rs

1use std::fs;
2use std::io;
3use std::path::Path;
4use std::string::FromUtf8Error;
5
6use crate::structs::CsvEncodeValues;
7use crate::structs::CsvWriterOption;
8use crate::structs::Spreadsheet;
9use crate::structs::XlsxError;
10use std::fmt::Write;
11
12/// write spreadsheet file to arbitrary writer.
13/// # Arguments
14/// * `spreadsheet` - Spreadsheet structs object.
15/// * `writer` - writer to write to.
16/// # Return value
17/// * `Result` - OK is void. Err is error message.
18pub fn write_writer<W: io::Seek + io::Write>(
19    spreadsheet: &Spreadsheet,
20    writer: &mut W,
21    option: &CsvWriterOption,
22) -> Result<(), XlsxError> {
23    // get worksheet.
24    let worksheet = spreadsheet.get_active_sheet();
25
26    // get max column and row.
27    let (max_column, max_row) = worksheet.get_highest_column_and_row();
28
29    let mut data = String::new();
30    for row in 0u32..max_row {
31        let mut row_vec: Vec<String> = Vec::new();
32        for column in 0u32..max_column {
33            // get value.
34            let mut value = match worksheet.get_cell((column + 1, row + 1)) {
35                Some(cell) => cell.get_cell_value().get_value().into(),
36                None => String::new(),
37            };
38            // do trim.
39            if *option.get_do_trim() {
40                value = value.trim().to_string();
41            }
42            // wrap_with_char.
43            if option.get_wrap_with_char() != "" {
44                value = format! {"{}{}{}", option.get_wrap_with_char(), value, option.get_wrap_with_char()};
45            }
46            row_vec.push(value);
47        }
48        write!(data, "{}", row_vec.join(",")).unwrap();
49        write!(data, "\r\n").unwrap();
50    }
51
52    // encoding.
53    let data_bytes = match *option.get_csv_encode_value() {
54        CsvEncodeValues::ShiftJis => encoding_rs::SHIFT_JIS.encode(&data).0.into_owned(),
55        CsvEncodeValues::Koi8u => encoding_rs::KOI8_U.encode(&data).0.into_owned(),
56        CsvEncodeValues::Koi8r => encoding_rs::KOI8_R.encode(&data).0.into_owned(),
57        CsvEncodeValues::Iso88598i => encoding_rs::ISO_8859_8_I.encode(&data).0.into_owned(),
58        CsvEncodeValues::Gbk => encoding_rs::GBK.encode(&data).0.into_owned(),
59        CsvEncodeValues::EucKr => encoding_rs::EUC_KR.encode(&data).0.into_owned(),
60        CsvEncodeValues::Big5 => encoding_rs::BIG5.encode(&data).0.into_owned(),
61        CsvEncodeValues::Utf16Le => encoding_rs::UTF_16LE.encode(&data).0.into_owned(),
62        CsvEncodeValues::Utf16Be => encoding_rs::UTF_16BE.encode(&data).0.into_owned(),
63        _ => data.into_bytes(),
64    };
65
66    // output.
67    writer.write_all(&data_bytes).unwrap();
68    Ok(())
69}
70
71/// write spreadsheet file.
72/// # Arguments
73/// * `spreadsheet` - Spreadsheet structs object.
74/// * `path` - file path to save.
75/// * `option` - options.
76/// # Return value
77/// * `Result` - OK is void. Err is error message.
78/// # Examples
79/// ```
80/// use umya_spreadsheet::*;
81/// let mut book = new_file();
82/// let path = std::path::Path::new("./tests/result_files/zzz.xlsx");
83/// let mut option = structs::CsvWriterOption::default();
84/// option.set_csv_encode_value(structs::CsvEncodeValues::ShiftJis);
85/// option.set_do_trim(true);
86/// option.set_wrap_with_char("\"");
87/// let _ = writer::csv::write(&book, path, Some(&option));
88/// ```
89pub fn write<P: AsRef<Path>>(
90    spreadsheet: &Spreadsheet,
91    path: P,
92    option: Option<&CsvWriterOption>,
93) -> Result<(), XlsxError> {
94    let extension = path.as_ref().extension().unwrap().to_str().unwrap();
95    let path_tmp = path
96        .as_ref()
97        .with_extension(format!("{}{}", extension, "tmp"));
98    let def_option = CsvWriterOption::default();
99    let option = match option {
100        Some(v) => v,
101        None => &def_option,
102    };
103    if let Err(v) = write_writer(
104        spreadsheet,
105        &mut io::BufWriter::new(fs::File::create(path_tmp.as_ref() as &Path)?),
106        option,
107    ) {
108        fs::remove_file(path_tmp)?;
109        return Err(v);
110    }
111    fs::rename(path_tmp, path)?;
112    Ok(())
113}