use std::path::Path;
#[cfg(feature = "date")]
use crate::date_util;
use crate::xlsx_util;
use anyhow::{anyhow, Result};
use umya_spreadsheet::{reader, writer, Spreadsheet, Worksheet};
pub enum XlsxLineAdvanceWriterResult {
Break,
Continue,
}
pub type XlsxLineAdvanceWriter<T> =
fn(&mut Worksheet, u32, T) -> Option<XlsxLineAdvanceWriterResult>;
pub type XlsxLineConverter<T> = fn(u32, T) -> Vec<XlsxColValue>;
#[derive(Debug)]
pub struct XlsxColValue {
pub value: String,
pub value_type: XlsxColValueType,
}
impl XlsxColValue {
pub fn new(value: impl ToString, value_type: XlsxColValueType) -> Self {
Self {
value: value.to_string(),
value_type,
}
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum XlsxColValueType {
StringValue,
NumberValue,
}
pub enum XlsxLineWriterModel {
Advance,
Simple,
}
impl XlsxColValue {
pub fn write_line_data_simple(
sheet: &mut Worksheet,
line_index: u32,
line_data: &[XlsxColValue],
) -> Result<()> {
for (col_index, XlsxColValue { value, value_type }) in line_data.iter().enumerate() {
match value_type {
XlsxColValueType::NumberValue => {
let value: f64 = value.parse()?;
xlsx_util::XlsxWriterTool::set_excel_cell_value_number(
sheet,
(col_index + 1) as u32,
line_index,
value,
);
}
XlsxColValueType::StringValue => {
xlsx_util::XlsxWriterTool::set_excel_cell_value_str(
sheet,
(col_index + 1) as u32,
line_index,
value,
)
}
}
}
Ok(())
}
}
pub type GroupMaker<T> = fn(T) -> String;
pub struct OutputXlsxFile {
pub index: u32,
pub excel_book: Spreadsheet,
pub output_file_name: String,
pub id: String,
}
impl OutputXlsxFile {
pub fn save(&self, #[cfg(feature = "encrypt")] passwrod: Option<&str>) -> Result<()> {
writer::xlsx::write(&self.excel_book, Path::new(&self.output_file_name))?;
#[cfg(feature = "encrypt")]
if let Some(passwrod) = passwrod {
msoffice_crypt::encrypt(&self.output_file_name, passwrod, None)?;
}
Ok(())
}
}
pub enum XlsxInitTemplet {
Header(String),
Advanced(XlsxAdvanceTemplate),
}
impl XlsxInitTemplet {
pub fn init_new_xlsx(&self, id: &str, file_name: &str) -> Result<OutputXlsxFile> {
match self {
XlsxInitTemplet::Header(header_str) => {
let mut book = umya_spreadsheet::new_file();
let sheet = book
.get_sheet_mut(&0)
.map_err(|err| anyhow!("读取待写入excel表格失败:{}", err))?;
for (col, value) in header_str.split(',').enumerate() {
xlsx_util::XlsxWriterTool::set_excel_cell_value_str(
sheet,
(col + 1) as u32,
1,
value,
);
}
Ok(OutputXlsxFile {
index: 2,
excel_book: book,
output_file_name: file_name.into(),
id: id.into(),
})
}
XlsxInitTemplet::Advanced(template) => template.new_from_template(id, file_name),
}
}
pub fn new_header(header: &str) -> Self {
Self::Header(header.into())
}
pub fn new_advance(file_path: &str, start_line: u32) -> Self {
Self::Advanced(XlsxAdvanceTemplate {
file_path: file_path.into(),
start_line,
})
}
}
pub struct XlsxAdvanceTemplate {
file_path: String,
start_line: u32,
}
impl XlsxAdvanceTemplate {
pub fn new_from_template(&self, id: &str, file_name: &str) -> Result<OutputXlsxFile> {
let book = reader::xlsx::read(&self.file_path)?;
Ok(OutputXlsxFile {
index: self.start_line,
excel_book: book,
output_file_name: file_name.into(),
id: id.into(),
})
}
}
pub type OutputFileNameAdvanceGetter = fn(&str) -> String;
pub struct OutputFileNameSimpleGetter {
file_name_pref: &'static str,
#[cfg(feature = "date")]
is_append_date: bool,
}
impl OutputFileNameSimpleGetter {
pub const fn new(
file_name_pref: &'static str,
#[cfg(feature = "date")] is_append_date: bool,
) -> Self {
Self {
file_name_pref,
#[cfg(feature = "date")]
is_append_date,
}
}
pub fn get_save_file_name(&self, group_id: &str) -> String {
#[cfg(feature = "date")]
if self.is_append_date {
format!(
"{}-{}-{}.xlsx",
self.file_name_pref,
group_id,
date_util::get_now_date()
)
} else {
format!("{}-{}.xlsx", self.file_name_pref, group_id)
}
#[cfg(not(feature = "date"))]
format!("{}-{}.xlsx", self.file_name_pref, group_id)
}
}
#[derive(Debug)]
pub struct XlsxGroupWriteResp {
pub group_id: String,
pub file_name: String,
}
impl XlsxGroupWriteResp {
pub fn new(group_id: &str, file_name: &str) -> Self {
Self {
file_name: file_name.into(),
group_id: group_id.into(),
}
}
}
impl From<OutputXlsxFile> for XlsxGroupWriteResp {
fn from(output_file: OutputXlsxFile) -> Self {
Self::new(&output_file.id, &output_file.output_file_name)
}
}
impl From<&OutputXlsxFile> for XlsxGroupWriteResp {
fn from(output_file: &OutputXlsxFile) -> Self {
Self::new(&output_file.id, &output_file.output_file_name)
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum XlsxWriteModel {
MergeAndGroup,
GroupOnly,
MergeOnly,
}