use std::{
fmt::Write,
fs,
io,
path::Path,
};
use crate::structs::{
CsvEncodeValues,
CsvWriterOption,
Workbook,
XlsxError,
};
pub fn write_writer<W: io::Seek + io::Write>(
wb: &Workbook,
writer: &mut W,
option: &CsvWriterOption,
) -> Result<(), XlsxError> {
let worksheet = wb.active_sheet();
let (max_column, max_row) = worksheet.highest_column_and_row();
let mut data = String::new();
for row in 0u32..max_row {
let mut row_vec: Vec<String> = Vec::new();
for column in 0u32..max_column {
let mut value = match worksheet.cell((column + 1, row + 1)) {
Some(cell) => cell.cell_value().value().into(),
None => String::new(),
};
if option.do_trim() {
value = value.trim().to_string();
}
if option.wrap_with_char() != "" {
value = format! {"{}{}{}", option.wrap_with_char(), value, option.wrap_with_char()};
}
row_vec.push(value);
}
write!(data, "{}", row_vec.join(",")).unwrap();
write!(data, "\r\n").unwrap();
}
let data_bytes = match *option.csv_encode_value() {
CsvEncodeValues::ShiftJis => encoding_rs::SHIFT_JIS.encode(&data).0.into_owned(),
CsvEncodeValues::Koi8u => encoding_rs::KOI8_U.encode(&data).0.into_owned(),
CsvEncodeValues::Koi8r => encoding_rs::KOI8_R.encode(&data).0.into_owned(),
CsvEncodeValues::Iso88598i => encoding_rs::ISO_8859_8_I.encode(&data).0.into_owned(),
CsvEncodeValues::Gbk => encoding_rs::GBK.encode(&data).0.into_owned(),
CsvEncodeValues::EucKr => encoding_rs::EUC_KR.encode(&data).0.into_owned(),
CsvEncodeValues::Big5 => encoding_rs::BIG5.encode(&data).0.into_owned(),
CsvEncodeValues::Utf16Le => encoding_rs::UTF_16LE.encode(&data).0.into_owned(),
CsvEncodeValues::Utf16Be => encoding_rs::UTF_16BE.encode(&data).0.into_owned(),
CsvEncodeValues::Utf8 => data.into_bytes(),
};
writer.write_all(&data_bytes).unwrap();
Ok(())
}
pub fn write<P: AsRef<Path>>(
wb: &Workbook,
path: P,
option: Option<&CsvWriterOption>,
) -> Result<(), XlsxError> {
let extension = path.as_ref().extension().unwrap().to_str().unwrap();
let path_tmp = path
.as_ref()
.with_extension(format!("{}{}", extension, "tmp"));
let def_option = CsvWriterOption::default();
let option = match option {
Some(v) => v,
None => &def_option,
};
if let Err(v) = write_writer(
wb,
&mut io::BufWriter::new(fs::File::create::<&Path>(path_tmp.as_ref())?),
option,
) {
fs::remove_file(path_tmp)?;
return Err(v);
}
fs::rename(path_tmp, path)?;
Ok(())
}