#![deny(missing_docs)]
extern crate byteorder;
extern crate codepage;
extern crate encoding_rs;
extern crate quick_xml;
#[macro_use]
extern crate serde;
extern crate zip;
#[macro_use]
extern crate log;
#[macro_use]
mod utils;
mod auto;
mod cfb;
mod datatype;
mod ods;
mod xls;
mod xlsb;
mod xlsx;
mod de;
mod errors;
pub mod vba;
use serde::de::DeserializeOwned;
use std::borrow::Cow;
use std::cmp::{max, min};
use std::fmt;
use std::fs::File;
use std::io::{BufReader, Read, Seek};
use std::ops::{Index, IndexMut};
use std::path::Path;
pub use auto::{open_workbook_auto, Sheets};
pub use datatype::DataType;
pub use de::{DeError, RangeDeserializer, RangeDeserializerBuilder, ToCellDeserializer};
pub use errors::Error;
pub use ods::{Ods, OdsError};
pub use xls::{Xls, XlsError};
pub use xlsb::{Xlsb, XlsbError};
pub use xlsx::{Xlsx, XlsxError};
use vba::VbaProject;
#[derive(Debug, Clone, PartialEq)]
pub enum CellErrorType {
Div0,
NA,
Name,
Null,
Num,
Ref,
Value,
GettingData,
}
impl fmt::Display for CellErrorType {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self {
CellErrorType::Div0 => write!(f, "#DIV/0!"),
CellErrorType::NA => write!(f, "#N/A"),
CellErrorType::Name => write!(f, "#NAME?"),
CellErrorType::Null => write!(f, "#NULL!"),
CellErrorType::Num => write!(f, "#NUM!"),
CellErrorType::Ref => write!(f, "#REF!"),
CellErrorType::Value => write!(f, "#VALUE!"),
CellErrorType::GettingData => write!(f, "#DATA!"),
}
}
}
#[derive(Debug, Default)]
pub struct Metadata {
sheets: Vec<String>,
names: Vec<(String, String)>,
}
pub trait Reader: Sized {
type RS: Read + Seek;
type Error: ::std::fmt::Debug + From<::std::io::Error>;
fn new(reader: Self::RS) -> Result<Self, Self::Error>;
fn vba_project(&mut self) -> Option<Result<Cow<VbaProject>, Self::Error>>;
fn metadata(&self) -> &Metadata;
fn worksheet_range(&mut self, name: &str) -> Option<Result<Range<DataType>, Self::Error>>;
fn worksheet_formula(&mut self, _: &str) -> Option<Result<Range<String>, Self::Error>>;
fn sheet_names(&self) -> &[String] {
&self.metadata().sheets
}
fn defined_names(&self) -> &[(String, String)] {
&self.metadata().names
}
fn worksheet_range_at(&mut self, n: usize) -> Option<Result<Range<DataType>, Self::Error>> {
let name = if let Some(name) = self.sheet_names().get(n) {
name
} else {
return None;
}
.to_string();
self.worksheet_range(&name)
}
}
pub fn open_workbook<R, P>(path: P) -> Result<R, R::Error>
where
R: Reader<RS = BufReader<File>>,
P: AsRef<Path>,
{
let file = BufReader::new(File::open(path)?);
R::new(file)
}
pub trait CellType: Default + Clone + PartialEq {}
impl<T: Default + Clone + PartialEq> CellType for T {}
#[derive(Debug, Clone)]
pub struct Cell<T: CellType> {
pos: (u32, u32),
val: T,
}
impl<T: CellType> Cell<T> {
pub fn new(position: (u32, u32), value: T) -> Cell<T> {
Cell {
pos: position,
val: value,
}
}
pub fn get_position(&self) -> (u32, u32) {
self.pos
}
pub fn get_value(&self) -> &T {
&self.val
}
}
#[derive(Debug, Default, Clone)]
pub struct Range<T: CellType> {
start: (u32, u32),
end: (u32, u32),
inner: Vec<T>,
}
impl<T: CellType> Range<T> {
#[inline]
pub fn new(start: (u32, u32), end: (u32, u32)) -> Range<T> {
assert!(start <= end, "invalid range bounds");
Range {
start: start,
end: end,
inner: vec![T::default(); ((end.0 - start.0 + 1) * (end.1 - start.1 + 1)) as usize],
}
}
#[inline]
pub fn empty() -> Range<T> {
Range {
start: (0, 0),
end: (0, 0),
inner: Vec::new(),
}
}
#[inline]
pub fn start(&self) -> Option<(u32, u32)> {
if self.is_empty() {
None
} else {
Some(self.start)
}
}
#[inline]
pub fn end(&self) -> Option<(u32, u32)> {
if self.is_empty() {
None
} else {
Some(self.end)
}
}
#[inline]
pub fn width(&self) -> usize {
if self.is_empty() {
0
} else {
(self.end.1 - self.start.1 + 1) as usize
}
}
#[inline]
pub fn height(&self) -> usize {
if self.is_empty() {
0
} else {
(self.end.0 - self.start.0 + 1) as usize
}
}
#[inline]
pub fn get_size(&self) -> (usize, usize) {
(self.height(), self.width())
}
#[inline]
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
pub fn from_sparse(cells: Vec<Cell<T>>) -> Range<T> {
if cells.is_empty() {
Range::empty()
} else {
let row_start = cells.first().unwrap().pos.0;
let row_end = cells.last().unwrap().pos.0;
let mut col_start = ::std::u32::MAX;
let mut col_end = 0;
for c in cells.iter().map(|c| c.pos.1) {
if c < col_start {
col_start = c;
}
if c > col_end {
col_end = c
}
}
let width = col_end - col_start + 1;
let len = ((row_end - row_start + 1) * width) as usize;
let mut v = vec![T::default(); len];
v.shrink_to_fit();
for c in cells {
let idx = ((c.pos.0 - row_start) * width + (c.pos.1 - col_start)) as usize;
v[idx] = c.val;
}
Range {
start: (row_start, col_start),
end: (row_end, col_end),
inner: v,
}
}
}
pub fn set_value(&mut self, absolute_position: (u32, u32), value: T) {
assert!(
self.start.0 <= absolute_position.0 && self.start.1 <= absolute_position.1,
"absolute_position out of bounds"
);
match (
self.end.0 < absolute_position.0,
self.end.1 < absolute_position.1,
) {
(false, false) => (),
(true, false) => {
let len = (absolute_position.0 - self.end.0 + 1) as usize * self.width();
self.inner.extend_from_slice(&vec![T::default(); len]);
self.end.0 = absolute_position.0;
}
(e, true) => {
let height = if e {
(absolute_position.0 - self.start.0 + 1) as usize
} else {
self.height()
};
let width = (absolute_position.1 - self.start.1 + 1) as usize;
let old_width = self.width();
let mut data = Vec::with_capacity(width * height);
let empty = vec![T::default(); width - old_width];
for sce in self.inner.chunks(old_width) {
data.extend_from_slice(sce);
data.extend_from_slice(&empty);
}
data.extend_from_slice(&vec![T::default(); width * (height - self.height())]);
if e {
self.end = absolute_position
} else {
self.end.1 = absolute_position.1
}
self.inner = data;
}
}
let pos = (
absolute_position.0 - self.start.0,
absolute_position.1 - self.start.1,
);
let idx = pos.0 as usize * self.width() + pos.1 as usize;
self.inner[idx] = value;
}
pub fn get_value(&self, absolute_position: (u32, u32)) -> Option<&T> {
let p = absolute_position;
if p.0 >= self.start.0 && p.0 <= self.end.0 && p.1 >= self.start.1 && p.1 <= self.end.1 {
return self.get((
(absolute_position.0 - self.start.0) as usize,
(absolute_position.1 - self.start.1) as usize,
));
}
None
}
pub fn get(&self, relative_position: (usize, usize)) -> Option<&T> {
let (row, col) = relative_position;
self.inner.get(row * self.width() + col)
}
pub fn rows(&self) -> Rows<T> {
if self.inner.is_empty() {
Rows { inner: None }
} else {
let width = self.width();
Rows {
inner: Some(self.inner.chunks(width)),
}
}
}
pub fn used_cells(&self) -> UsedCells<T> {
UsedCells {
width: self.width(),
inner: self.inner.iter().enumerate(),
}
}
pub fn cells(&self) -> Cells<T> {
Cells {
width: self.width(),
inner: self.inner.iter().enumerate(),
}
}
pub fn deserialize<'a, D>(&'a self) -> Result<RangeDeserializer<'a, T, D>, DeError>
where
T: ToCellDeserializer<'a>,
D: DeserializeOwned,
{
RangeDeserializerBuilder::new().from_range(self)
}
pub fn range(&self, start: (u32, u32), end: (u32, u32)) -> Range<T> {
let mut other = Range::new(start, end);
let (self_start_row, self_start_col) = self.start;
let (self_end_row, self_end_col) = self.end;
let (other_start_row, other_start_col) = other.start;
let (other_end_row, other_end_col) = other.end;
let start_row = max(self_start_row, other_start_row);
let end_row = min(self_end_row, other_end_row);
let start_col = max(self_start_col, other_start_col);
let end_col = min(self_end_col, other_end_col);
if start_row > end_row || start_col > end_col {
return other;
}
let self_width = self.width();
let other_width = other.width();
let self_row_start = (start_row - self_start_row) as usize;
let self_row_end = (end_row + 1 - self_start_row) as usize;
let self_col_start = (start_col - self_start_col) as usize;
let self_col_end = (end_col + 1 - self_start_col) as usize;
let other_row_start = (start_row - other_start_row) as usize;
let other_row_end = (end_row + 1 - other_start_row) as usize;
let other_col_start = (start_col - other_start_col) as usize;
let other_col_end = (end_col + 1 - other_start_col) as usize;
{
let self_rows = self
.inner
.chunks(self_width)
.take(self_row_end)
.skip(self_row_start);
let other_rows = other
.inner
.chunks_mut(other_width)
.take(other_row_end)
.skip(other_row_start);
for (self_row, other_row) in self_rows.zip(other_rows) {
let self_cols = &self_row[self_col_start..self_col_end];
let other_cols = &mut other_row[other_col_start..other_col_end];
other_cols.clone_from_slice(self_cols);
}
}
other
}
}
impl<T: CellType> Index<usize> for Range<T> {
type Output = [T];
fn index(&self, index: usize) -> &[T] {
let width = self.width();
&self.inner[index * width..(index + 1) * width]
}
}
impl<T: CellType> Index<(usize, usize)> for Range<T> {
type Output = T;
fn index(&self, index: (usize, usize)) -> &T {
let (height, width) = self.get_size();
assert!(index.1 < width && index.0 < height, "index out of bounds");
&self.inner[index.0 * width + index.1]
}
}
impl<T: CellType> IndexMut<usize> for Range<T> {
fn index_mut(&mut self, index: usize) -> &mut [T] {
let width = self.width();
&mut self.inner[index * width..(index + 1) * width]
}
}
impl<T: CellType> IndexMut<(usize, usize)> for Range<T> {
fn index_mut(&mut self, index: (usize, usize)) -> &mut T {
let (height, width) = self.get_size();
assert!(index.1 < width && index.0 < height, "index out of bounds");
&mut self.inner[index.0 * width + index.1]
}
}
#[derive(Debug)]
pub struct Cells<'a, T: 'a + CellType> {
width: usize,
inner: ::std::iter::Enumerate<::std::slice::Iter<'a, T>>,
}
impl<'a, T: 'a + CellType> Iterator for Cells<'a, T> {
type Item = (usize, usize, &'a T);
fn next(&mut self) -> Option<Self::Item> {
self.inner.next().map(|(i, v)| {
let row = i / self.width;
let col = i % self.width;
(row, col, v)
})
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<'a, T: 'a + CellType> DoubleEndedIterator for Cells<'a, T> {
fn next_back(&mut self) -> Option<Self::Item> {
self.inner.next_back().map(|(i, v)| {
let row = i / self.width;
let col = i % self.width;
(row, col, v)
})
}
}
impl<'a, T: 'a + CellType> ExactSizeIterator for Cells<'a, T> {}
#[derive(Debug)]
pub struct UsedCells<'a, T: 'a + CellType> {
width: usize,
inner: ::std::iter::Enumerate<::std::slice::Iter<'a, T>>,
}
impl<'a, T: 'a + CellType> Iterator for UsedCells<'a, T> {
type Item = (usize, usize, &'a T);
fn next(&mut self) -> Option<Self::Item> {
self.inner
.by_ref()
.find(|&(_, v)| v != &T::default())
.map(|(i, v)| {
let row = i / self.width;
let col = i % self.width;
(row, col, v)
})
}
fn size_hint(&self) -> (usize, Option<usize>) {
let (_, up) = self.inner.size_hint();
(0, up)
}
}
impl<'a, T: 'a + CellType> DoubleEndedIterator for UsedCells<'a, T> {
fn next_back(&mut self) -> Option<Self::Item> {
self.inner
.by_ref()
.rfind(|&(_, v)| v != &T::default())
.map(|(i, v)| {
let row = i / self.width;
let col = i % self.width;
(row, col, v)
})
}
}
#[derive(Debug)]
pub struct Rows<'a, T: 'a + CellType> {
inner: Option<::std::slice::Chunks<'a, T>>,
}
impl<'a, T: 'a + CellType> Iterator for Rows<'a, T> {
type Item = &'a [T];
fn next(&mut self) -> Option<Self::Item> {
self.inner.as_mut().and_then(|c| c.next())
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner
.as_ref()
.map_or((0, Some(0)), |ch| ch.size_hint())
}
}
impl<'a, T: 'a + CellType> DoubleEndedIterator for Rows<'a, T> {
fn next_back(&mut self) -> Option<Self::Item> {
self.inner.as_mut().and_then(|c| c.next_back())
}
}
impl<'a, T: 'a + CellType> ExactSizeIterator for Rows<'a, T> {}