Skip to content

Commit

Permalink
add formula reading for xlsb cells_reader
Browse files Browse the repository at this point in the history
  • Loading branch information
tafia committed Nov 1, 2023
1 parent 63a5f9e commit 0c87903
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 258 deletions.
10 changes: 5 additions & 5 deletions src/auto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,12 +115,12 @@ where
}

/// Read worksheet formula in corresponding worksheet path
fn worksheet_formula(&mut self, name: &str) -> Option<Result<Range<String>, Self::Error>> {
fn worksheet_formula(&mut self, name: &str) -> Result<Range<String>, Self::Error> {
match *self {
Sheets::Xls(ref mut e) => e.worksheet_formula(name).map(|r| r.map_err(Error::Xls)),
Sheets::Xlsx(ref mut e) => e.worksheet_formula(name).map(|r| r.map_err(Error::Xlsx)),
Sheets::Xlsb(ref mut e) => e.worksheet_formula(name).map(|r| r.map_err(Error::Xlsb)),
Sheets::Ods(ref mut e) => e.worksheet_formula(name).map(|r| r.map_err(Error::Ods)),
Sheets::Xls(ref mut e) => e.worksheet_formula(name).map_err(Error::Xls),
Sheets::Xlsx(ref mut e) => e.worksheet_formula(name).map_err(Error::Xlsx),
Sheets::Xlsb(ref mut e) => e.worksheet_formula(name).map_err(Error::Xlsb),
Sheets::Ods(ref mut e) => e.worksheet_formula(name).map_err(Error::Ods),
}
}

Expand Down
3 changes: 1 addition & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@
//! println!("found {} formula in '{}'",
//! workbook
//! .worksheet_formula(&s)
//! .expect("sheet not found")
//! .expect("error while getting formula")
//! .rows().flat_map(|r| r.iter().filter(|f| !f.is_empty()))
//! .count(),
Expand Down Expand Up @@ -230,7 +229,7 @@ where
fn worksheets(&mut self) -> Vec<(String, Range<DataType>)>;

/// Read worksheet formula in corresponding worksheet path
fn worksheet_formula(&mut self, _: &str) -> Option<Result<Range<String>, Self::Error>>;
fn worksheet_formula(&mut self, _: &str) -> Result<Range<String>, Self::Error>;

/// Get all sheet names of this workbook, in workbook order
///
Expand Down
7 changes: 5 additions & 2 deletions src/ods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,11 @@ where
}

/// Read worksheet data in corresponding worksheet path
fn worksheet_formula(&mut self, name: &str) -> Option<Result<Range<String>, OdsError>> {
self.sheets.get(name).map(|r| Ok(r.1.to_owned()))
fn worksheet_formula(&mut self, name: &str) -> Result<Range<String>, OdsError> {
self.sheets
.get(name)
.ok_or_else(|| OdsError::WorksheetNotFound(name.into()))
.map(|r| r.1.to_owned())
}

#[cfg(feature = "picture")]
Expand Down
7 changes: 5 additions & 2 deletions src/xls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,8 +236,11 @@ impl<RS: Read + Seek> Reader<RS> for Xls<RS> {
.collect()
}

fn worksheet_formula(&mut self, name: &str) -> Option<Result<Range<String>, XlsError>> {
self.sheets.get(name).map(|r| Ok(r.1.clone()))
fn worksheet_formula(&mut self, name: &str) -> Result<Range<String>, XlsError> {
self.sheets
.get(name)
.ok_or_else(|| XlsError::WorksheetNotFound(name.into()))
.map(|r| r.1.clone())
}

#[cfg(feature = "picture")]
Expand Down
54 changes: 53 additions & 1 deletion src/xlsb/cells_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ use crate::{
Cell, CellErrorType, Dimensions, XlsbError,
};

use super::{cell_format, wide_str, RecordIter};
use super::{cell_format, parse_formula, wide_str, RecordIter};

/// A cells reader for xlsb files
pub struct XlsbCellsReader<'a> {
iter: RecordIter<'a>,
formats: &'a [CellFormat],
strings: &'a [String],
extern_sheets: &'a [String],
metadata_names: &'a [(String, String)],
typ: u16,
row: u32,
is_1904: bool,
Expand All @@ -24,6 +26,8 @@ impl<'a> XlsbCellsReader<'a> {
mut iter: RecordIter<'a>,
formats: &'a [CellFormat],
strings: &'a [String],
extern_sheets: &'a [String],
metadata_names: &'a [(String, String)],
is_1904: bool,
) -> Result<Self, XlsbError> {
let mut buf = Vec::with_capacity(1024);
Expand Down Expand Up @@ -55,6 +59,8 @@ impl<'a> XlsbCellsReader<'a> {
formats,
is_1904,
strings,
extern_sheets,
metadata_names,
dimensions,
typ: 0,
row: 0,
Expand Down Expand Up @@ -144,6 +150,52 @@ impl<'a> XlsbCellsReader<'a> {
let col = read_u32(&self.buf);
Ok(Some(Cell::new((self.row, col), value)))
}

pub fn next_formula(&mut self) -> Result<Option<Cell<String>>, XlsbError> {
let value = loop {
self.typ = self.iter.read_type()?;
let _ = self.iter.fill_buffer(&mut self.buf)?;

let value = match self.typ {
// 0x0001 => continue, // DataType::Empty, // BrtCellBlank
0x0008 => {
// BrtFmlaString
let cch = read_u32(&self.buf[8..]) as usize;
let formula = &self.buf[14 + cch * 2..];
let cce = read_u32(formula) as usize;
let rgce = &formula[4..4 + cce];
parse_formula(rgce, &self.extern_sheets, &self.metadata_names)?
}
0x0009 => {
// BrtFmlaNum
let formula = &self.buf[18..];
let cce = read_u32(formula) as usize;
let rgce = &formula[4..4 + cce];
parse_formula(rgce, &self.extern_sheets, &self.metadata_names)?
}
0x000A | 0x000B => {
// BrtFmlaBool | BrtFmlaError
let formula = &self.buf[11..];
let cce = read_u32(formula) as usize;
let rgce = &formula[4..4 + cce];
parse_formula(rgce, &self.extern_sheets, &self.metadata_names)?
}
0x0000 => {
// BrtRowHdr
self.row = read_u32(&self.buf);
if self.row > 0x0010_0000 {
return Ok(None); // invalid row
}
continue;
}
0x0092 => return Ok(None), // BrtEndSheetData
_ => continue, // anything else, ignore and try next, without changing idx
};
break value;
};
let col = read_u32(&self.buf);
Ok(Some(Cell::new((self.row, col), value)))
}
}

fn parse_dimensions(buf: &[u8]) -> Dimensions {
Expand Down
Loading

0 comments on commit 0c87903

Please sign in to comment.