use std::fmt::Debug;
pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
#[derive(Debug, Clone, PartialEq)]
pub enum CellValue {
Empty,
Bool(bool),
Int(i64),
Float(f64),
String(String),
DateTime(f64),
Error(String),
}
pub trait Cell {
fn row(&self) -> u32;
fn column(&self) -> u32;
fn coordinate(&self) -> String;
fn value(&self) -> &CellValue;
fn is_empty(&self) -> bool {
matches!(self.value(), CellValue::Empty)
}
fn is_formula(&self) -> bool {
false }
fn is_date(&self) -> bool {
matches!(self.value(), CellValue::DateTime(_))
}
}
pub trait CellIterator<'a> {
fn next(&mut self) -> Option<Result<Box<dyn Cell + 'a>>>;
}
pub trait RowIterator<'a> {
fn next(&mut self) -> Option<Result<Vec<CellValue>>>;
}
pub trait Worksheet {
fn name(&self) -> &str;
fn row_count(&self) -> usize;
fn column_count(&self) -> usize;
fn dimensions(&self) -> Option<(u32, u32, u32, u32)>;
fn cell(&self, row: u32, column: u32) -> Result<Box<dyn Cell + '_>>;
fn cell_by_coordinate(&self, coordinate: &str) -> Result<Box<dyn Cell + '_>>;
fn cells(&self) -> Box<dyn CellIterator<'_> + '_>;
fn rows(&self) -> Box<dyn RowIterator<'_> + '_>;
fn row(&self, row_idx: usize) -> Result<Vec<CellValue>>;
fn cell_value(&self, row: u32, column: u32) -> Result<CellValue>;
}
pub trait WorksheetIterator<'a> {
fn next(&mut self) -> Option<Result<Box<dyn Worksheet + 'a>>>;
}
pub trait Workbook {
fn active_worksheet(&self) -> Result<Box<dyn Worksheet + '_>>;
fn worksheet_names(&self) -> Vec<String>;
fn worksheet_by_name(&self, name: &str) -> Result<Box<dyn Worksheet + '_>>;
fn worksheet_by_index(&self, index: usize) -> Result<Box<dyn Worksheet + '_>>;
fn worksheets(&self) -> Box<dyn WorksheetIterator<'_> + '_>;
fn worksheet_count(&self) -> usize;
fn active_sheet_index(&self) -> usize;
}
#[cfg(feature = "ooxml")]
pub fn open_workbook<P: AsRef<std::path::Path>>(path: P) -> Result<Box<dyn Workbook>> {
let package = crate::ooxml::opc::OpcPackage::open(path)?;
let workbook = crate::ooxml::xlsx::Workbook::new(package)?;
Ok(Box::new(workbook))
}
#[cfg(feature = "ooxml")]
pub fn open_workbook_from_bytes(bytes: &[u8]) -> Result<Box<dyn Workbook>> {
use std::io::Cursor;
let cursor = Cursor::new(bytes);
let package = crate::ooxml::opc::OpcPackage::from_reader(cursor)?;
let workbook = crate::ooxml::xlsx::Workbook::new(package)?;
Ok(Box::new(workbook))
}
#[cfg(feature = "ole")]
pub fn open_xls_workbook<P: AsRef<std::path::Path>>(path: P) -> Result<crate::ole::xls::XlsWorkbook<std::fs::File>> {
use std::fs::File;
let file = File::open(path)?;
let workbook = crate::ole::xls::XlsWorkbook::new(file)?;
Ok(workbook)
}
#[cfg(feature = "ole")]
pub fn open_xls_workbook_from_bytes(bytes: &[u8]) -> Result<crate::ole::xls::XlsWorkbook<std::io::Cursor<&[u8]>>> {
use std::io::Cursor;
let cursor = Cursor::new(bytes);
let workbook = crate::ole::xls::XlsWorkbook::new(cursor)?;
Ok(workbook)
}
#[cfg(feature = "ole")]
pub fn open_xls_workbook_dyn<P: AsRef<std::path::Path>>(path: P) -> Result<Box<dyn Workbook>> {
let workbook = open_xls_workbook(path)?;
Ok(Box::new(workbook))
}
#[cfg(feature = "ole")]
pub fn open_xls_workbook_from_bytes_dyn(bytes: &[u8]) -> Result<Box<dyn Workbook>> {
use std::io::Cursor;
let cursor = Cursor::new(bytes.to_vec());
let workbook = crate::ole::xls::XlsWorkbook::new(cursor)?;
Ok(Box::new(workbook))
}
#[cfg(feature = "ooxml")]
pub fn open_xlsb_workbook<P: AsRef<std::path::Path>>(path: P) -> Result<crate::ooxml::xlsb::XlsbWorkbook> {
use std::fs::File;
let file = File::open(path)?;
let workbook = crate::ooxml::xlsb::XlsbWorkbook::new(file)?;
Ok(workbook)
}
#[cfg(feature = "ooxml")]
pub fn open_xlsb_workbook_from_bytes(bytes: &[u8]) -> Result<crate::ooxml::xlsb::XlsbWorkbook> {
use std::io::Cursor;
let cursor = Cursor::new(bytes);
let workbook = crate::ooxml::xlsb::XlsbWorkbook::new(cursor)?;
Ok(workbook)
}
#[cfg(feature = "ooxml")]
pub fn open_xlsb_workbook_dyn<P: AsRef<std::path::Path>>(path: P) -> Result<Box<dyn Workbook>> {
let workbook = open_xlsb_workbook(path)?;
Ok(Box::new(workbook))
}
#[cfg(feature = "ooxml")]
pub fn open_xlsb_workbook_from_bytes_dyn(bytes: &[u8]) -> Result<Box<dyn Workbook>> {
use std::io::Cursor;
let cursor = Cursor::new(bytes.to_vec());
let workbook = crate::ooxml::xlsb::XlsbWorkbook::new(cursor)?;
Ok(Box::new(workbook))
}
pub mod text;
pub fn open_csv_workbook<P: AsRef<std::path::Path>>(path: P) -> Result<Box<dyn Workbook>> {
let workbook = crate::sheet::text::TextWorkbook::open(path)?;
Ok(Box::new(workbook))
}
pub fn open_csv_workbook_from_bytes(bytes: &[u8]) -> Result<Box<dyn Workbook>> {
let workbook = crate::sheet::text::TextWorkbook::from_bytes(bytes, crate::sheet::text::TextConfig::default())?;
Ok(Box::new(workbook))
}
pub fn open_tsv_workbook<P: AsRef<std::path::Path>>(path: P) -> Result<Box<dyn Workbook>> {
let config = crate::sheet::text::TextConfig::tsv();
let workbook = crate::sheet::text::TextWorkbook::from_path_with_config(path, config)?;
Ok(Box::new(workbook))
}
pub fn open_tsv_workbook_from_bytes(bytes: &[u8]) -> Result<Box<dyn Workbook>> {
let config = crate::sheet::text::TextConfig::tsv();
let workbook = crate::sheet::text::TextWorkbook::from_bytes(bytes, config)?;
Ok(Box::new(workbook))
}
pub fn open_prn_workbook<P: AsRef<std::path::Path>>(path: P) -> Result<Box<dyn Workbook>> {
let config = crate::sheet::text::TextConfig::prn();
let workbook = crate::sheet::text::TextWorkbook::from_path_with_config(path, config)?;
Ok(Box::new(workbook))
}
pub fn open_prn_workbook_from_bytes(bytes: &[u8]) -> Result<Box<dyn Workbook>> {
let config = crate::sheet::text::TextConfig::prn();
let workbook = crate::sheet::text::TextWorkbook::from_bytes(bytes, config)?;
Ok(Box::new(workbook))
}
pub fn open_text_workbook_with_config<P: AsRef<std::path::Path>>(
path: P,
config: crate::sheet::text::TextConfig
) -> Result<Box<dyn Workbook>> {
let workbook = crate::sheet::text::TextWorkbook::from_path_with_config(path, config)?;
Ok(Box::new(workbook))
}
pub fn open_text_workbook_from_bytes_with_config(
bytes: &[u8],
config: crate::sheet::text::TextConfig
) -> Result<Box<dyn Workbook>> {
let workbook = crate::sheet::text::TextWorkbook::from_bytes(bytes, config)?;
Ok(Box::new(workbook))
}