use std::os::raw::c_char;
use crate::{
convert_bool, error::XlsxErrorSource, try_to_vec, CStringHelper, WorksheetCol, WorksheetRow,
XlsxError,
};
use super::{Format, Worksheet};
#[derive(Default)]
pub struct TableColumn {
pub header: Option<String>,
pub formula: Option<String>,
pub total_string: Option<String>,
pub total_function: TableTotalFunction,
pub header_format: Option<Format>,
pub format: Option<Format>,
pub total_value: f64,
}
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default)]
pub enum TableStyleType {
#[default]
Default,
Light,
Medium,
Dark,
}
impl From<TableStyleType> for u8 {
fn from(t: TableStyleType) -> u8 {
(match t {
TableStyleType::Dark => {
libxlsxwriter_sys::lxw_table_style_type_LXW_TABLE_STYLE_TYPE_DARK
}
TableStyleType::Light => {
libxlsxwriter_sys::lxw_table_style_type_LXW_TABLE_STYLE_TYPE_LIGHT
}
TableStyleType::Medium => {
libxlsxwriter_sys::lxw_table_style_type_LXW_TABLE_STYLE_TYPE_MEDIUM
}
TableStyleType::Default => {
libxlsxwriter_sys::lxw_table_style_type_LXW_TABLE_STYLE_TYPE_DEFAULT
}
}) as u8
}
}
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default)]
pub enum TableTotalFunction {
#[default]
None,
Average,
CountNums,
Count,
Max,
Min,
StdDev,
Sum,
Var,
}
impl From<TableTotalFunction> for u8 {
fn from(f: TableTotalFunction) -> u8 {
(match f {
TableTotalFunction::None => 0,
TableTotalFunction::Average => {
libxlsxwriter_sys::lxw_table_total_functions_LXW_TABLE_FUNCTION_AVERAGE
}
TableTotalFunction::CountNums => {
libxlsxwriter_sys::lxw_table_total_functions_LXW_TABLE_FUNCTION_COUNT_NUMS
}
TableTotalFunction::Count => {
libxlsxwriter_sys::lxw_table_total_functions_LXW_TABLE_FUNCTION_COUNT
}
TableTotalFunction::Max => {
libxlsxwriter_sys::lxw_table_total_functions_LXW_TABLE_FUNCTION_MAX
}
TableTotalFunction::Min => {
libxlsxwriter_sys::lxw_table_total_functions_LXW_TABLE_FUNCTION_MIN
}
TableTotalFunction::StdDev => {
libxlsxwriter_sys::lxw_table_total_functions_LXW_TABLE_FUNCTION_STD_DEV
}
TableTotalFunction::Sum => {
libxlsxwriter_sys::lxw_table_total_functions_LXW_TABLE_FUNCTION_SUM
}
TableTotalFunction::Var => {
libxlsxwriter_sys::lxw_table_total_functions_LXW_TABLE_FUNCTION_VAR
}
}) as u8
}
}
#[derive(Default)]
pub struct TableOptions {
pub name: Option<String>,
pub no_header_row: bool,
pub no_autofilter: bool,
pub no_banded_rows: bool,
pub banded_columns: bool,
pub first_column: bool,
pub last_column: bool,
pub style_type: TableStyleType,
pub style_type_number: u8,
pub total_row: bool,
pub columns: Option<Vec<TableColumn>>,
}
impl<'a> Worksheet<'a> {
pub fn add_table(
&mut self,
first_row: WorksheetRow,
first_col: WorksheetCol,
last_row: WorksheetRow,
last_col: WorksheetCol,
options: Option<TableOptions>,
) -> Result<(), XlsxError> {
let mut cstring_helper = CStringHelper::new();
if options
.as_ref()
.and_then(|x| x.columns.as_ref())
.map_or(false, |x| {
x.len() as WorksheetCol != last_col - first_col + 1
})
{
return Err(XlsxError {
source: XlsxErrorSource::NumberOfColumnsIsNotMatched,
});
}
let columns: Option<Vec<_>> = options
.as_ref()
.and_then(|x| x.columns.as_ref())
.map(|x| {
try_to_vec(
x.iter()
.map(
|y| -> Result<libxlsxwriter_sys::lxw_table_column, XlsxError> {
Ok(libxlsxwriter_sys::lxw_table_column {
header: cstring_helper.add_opt(y.header.as_deref())?
as *mut c_char,
formula: cstring_helper.add_opt(y.formula.as_deref())?
as *mut c_char,
total_string: cstring_helper
.add_opt(y.total_string.as_deref())?
as *mut c_char,
total_function: y.total_function.into(),
header_format: self
._workbook
.get_internal_option_format(y.header_format.as_ref())?,
format: self
._workbook
.get_internal_option_format(y.format.as_ref())?,
total_value: y.total_value,
})
},
)
.map(|x| x.map(Box::pin)),
)
})
.transpose()?;
let columns_ptr: Option<Vec<_>> = columns.as_ref().map(|x| {
let mut p: Vec<_> = x
.iter()
.map(|x| x.as_ref().get_ref() as *const libxlsxwriter_sys::lxw_table_column)
.map(|x| x as *mut libxlsxwriter_sys::lxw_table_column)
.collect();
p.push(std::ptr::null_mut());
p
});
let mut options = if let Some(options) = options {
Some(libxlsxwriter_sys::lxw_table_options {
name: cstring_helper.add_opt(options.name.as_deref())? as *mut c_char,
no_header_row: convert_bool(options.no_header_row),
no_autofilter: convert_bool(options.no_autofilter),
no_banded_rows: convert_bool(options.no_banded_rows),
banded_columns: convert_bool(options.banded_columns),
first_column: convert_bool(options.first_column),
last_column: convert_bool(options.last_column),
style_type: options.style_type.into(),
style_type_number: options.style_type_number,
total_row: convert_bool(options.total_row),
columns: columns_ptr.as_ref().map_or_else(std::ptr::null_mut, |x| {
x.as_ptr() as *mut *mut libxlsxwriter_sys::lxw_table_column
}),
})
} else {
None
};
unsafe {
let result = libxlsxwriter_sys::worksheet_add_table(
self.worksheet,
first_row,
first_col,
last_row,
last_col,
options.as_mut().map_or_else(std::ptr::null_mut, |x| {
x as *mut libxlsxwriter_sys::lxw_table_options
}),
);
std::mem::drop(columns_ptr);
std::mem::drop(columns);
std::mem::drop(cstring_helper);
if result == libxlsxwriter_sys::lxw_error_LXW_NO_ERROR {
Ok(())
} else {
Err(XlsxError::new(result))
}
}
}
}