Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 24 additions & 22 deletions src/xlsx/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -714,12 +714,12 @@ impl<RS: Read + Seek> Xlsx<RS> {
Ok(())
}

/// Provide metadata for all pivot tables.
/// Get all Pivot Tables in a workbook.
///
/// # Note
///
/// This function is required before working with Pivot Table Data due to reliance on metadata in `PivotTableRef`.
pub fn read_pivot_table_metadata(&mut self) -> Result<PivotTables, XlsxError>
pub fn pivot_tables(&mut self) -> Result<PivotTables, XlsxError>
where
RS: Read + Seek,
{
Expand Down Expand Up @@ -764,7 +764,7 @@ impl<RS: Read + Seek> Xlsx<RS> {
/// let mut workbook: Xlsx<_> = open_workbook(path)?;
///
/// // Must retrieve necessary metadata before reading Pivot Table data.
/// let pivot_tables = workbook.read_pivot_table_metadata()?;
/// let pivot_tables = workbook.pivot_tables()?;
///
/// // Get the Pivot Table data by referencing the pivot table name and the worksheet it resides.
/// for row in workbook.pivot_table_data(&pivot_tables, "PivotSheet1", "PivotTable1")? {
Expand Down Expand Up @@ -2673,7 +2673,7 @@ impl PivotTables {
/// // Open the workbook.
/// let mut workbook: Xlsx<_> = open_workbook("tests/pivots.xlsx")?;
/// // Must retrieve necessary metadata before reading Pivot Table data.
/// let pivot_tables = workbook.read_pivot_table_metadata()?;
/// let pivot_tables = workbook.pivot_tables()?;
///
/// // "PivotTable1" is found on both sheets: "PivotSheet1" & "PivotSheet3" so
/// // we must include the sheet name in our filter ~ see note on uniqueness.
Expand Down Expand Up @@ -2718,7 +2718,7 @@ impl PivotTables {
/// let mut workbook: Xlsx<_> = open_workbook(path)?;
///
/// // Must retrieve necessary metadata before reading Pivot Table data.
/// let pivot_tables = workbook.read_pivot_table_metadata()?;
/// let pivot_tables = workbook.pivot_tables()?;
///
/// // Get the pivot table names in the workbook for a given sheet.
/// let pivot_table_names = pivot_tables.pivot_tables_by_sheet("PivotSheet1");
Expand Down Expand Up @@ -2894,7 +2894,7 @@ impl<'a, RS: Read + Seek + 'a> PivotCacheIter<'a, RS> {
//
// https://learn.microsoft.com/en-us/dotnet/api/documentformat.openxml.spreadsheet.pivotcacherecord?view=openxml-3.0.1
impl<'a, RS: Read + Seek + 'a> Iterator for PivotCacheIter<'a, RS> {
type Item = Vec<Data>;
type Item = Result<Vec<Data>, XlsxError>;

fn next(&mut self) -> Option<Self::Item> {
let mut row = vec![];
Expand All @@ -2910,12 +2910,17 @@ impl<'a, RS: Read + Seek + 'a> Iterator for PivotCacheIter<'a, RS> {
value,
}) = a
{
let value_position = self
.reader
.decoder()
.decode(value.as_ref())
.map(|val| val.parse::<usize>().unwrap())
.unwrap();
let value_position = match self.reader.decoder().decode(value.as_ref())
{
Ok(val) => match val.parse::<usize>() {
Ok(val) => val,
Err(e) => {
return Some(Err(XlsxError::ParseInt(e)));
}
},
Err(e) => return Some(Err(XlsxError::Encoding(e))),
};

let column_name = &self.field_names[col_number];
row.push(parse_item(
&self.definitions[column_name][value_position],
Expand All @@ -2927,19 +2932,16 @@ impl<'a, RS: Read + Seek + 'a> Iterator for PivotCacheIter<'a, RS> {

col_number += 1;
}
Ok(Event::End(e)) if e.local_name().as_ref() == b"r" => return Some(row),
Ok(Event::End(e)) if e.local_name().as_ref() == b"r" => return Some(Ok(row)),
Ok(Event::Start(e)) if e.local_name().as_ref() == b"pivotCacheRecords" => {
return Some(
self.field_names
.iter()
.map(|fields| Data::String(fields.to_string()))
.collect(),
)
return Some(Ok(self
.field_names
.iter()
.map(|fields| Data::String(fields.to_string()))
.collect()))
}
Ok(Event::Eof) => return None,
Err(e) => {
panic!("{e}")
}
Err(e) => return Some(Err(XlsxError::Xml(e))),
Ok(Event::Start(e)) => {
if let Some(tag) = item_tag(&e) {
if let Ok(value) = item_value(&e) {
Expand Down
12 changes: 8 additions & 4 deletions tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2555,7 +2555,7 @@ fn test_xlsx_empty_shared_string() {
#[test]
fn test_pivot_table_meta_data() {
let mut wb: Xlsx<_> = wb("pivots.xlsx");
let pivot_tables = wb.read_pivot_table_metadata().unwrap();
let pivot_tables = wb.pivot_tables().unwrap();
let mut results = pivot_tables.get_pivot_tables_by_name_and_sheet();
results.sort();
let expected = vec![
Expand All @@ -2570,6 +2570,7 @@ fn test_pivot_table_meta_data() {
let pivot_table_data_pt5: Vec<Vec<Data>> = wb
.pivot_table_data(&pivot_tables, "PivotSheet4", "PivotTable5")
.unwrap()
.map(|val| val.unwrap())
.collect();
for (sheet_name, pt_name) in pivot_tables.get_pivot_tables_by_name_and_sheet() {
if pt_name.eq("PivotTable5") {
Expand All @@ -2578,6 +2579,7 @@ fn test_pivot_table_meta_data() {
let pivot_table_data_other: Vec<Vec<Data>> = wb
.pivot_table_data(&pivot_tables, sheet_name, pt_name)
.unwrap()
.map(|val| val.unwrap())
.collect();
assert_ne!(pivot_table_data_pt5, pivot_table_data_other);
}
Expand Down Expand Up @@ -2720,26 +2722,28 @@ fn test_pivot_cache_data_mapping() {
String("blue".to_string()),
],
];
let pivot_tables = wb.read_pivot_table_metadata().unwrap();
let pivot_tables = wb.pivot_tables().unwrap();
let mut results = wb
.pivot_table_data(&pivot_tables, "PivotSheet1", "PivotTable1")
.unwrap();
for expected_data in expected {
assert_eq!(results.next(), Some(expected_data));
assert_eq!(results.next().map(|m| m.unwrap()), Some(expected_data));
}
}

#[test]
fn test_pivot_table_cache_match() {
let mut wb: Xlsx<_> = wb("pivots.xlsx");
let pivot_tables = wb.read_pivot_table_metadata().unwrap();
let pivot_tables = wb.pivot_tables().unwrap();
let results1 = wb
.pivot_table_data(&pivot_tables, "PivotSheet1", "PivotTable1")
.unwrap()
.map(|val| val.unwrap())
.collect::<Vec<_>>();
let results2 = wb
.pivot_table_data(&pivot_tables, "PivotSheet2", "PivotTable2")
.unwrap()
.map(|val| val.unwrap())
.collect::<Vec<_>>();
assert_eq!(results1, results2);
}