From 550969199f0ab61c9dfdb8f88db9ab7dc393ff12 Mon Sep 17 00:00:00 2001 From: Eric Jolibois Date: Sun, 20 Oct 2024 16:50:00 +0200 Subject: [PATCH 1/3] test: add unit test that explains the bug assertion `left == right` failed: Mismatch at position (1, 0) left: Float(-8.086931554011838e18) right: String("-8086931554011838357") --- tests/string-ref.xlsx | Bin 0 -> 10031 bytes tests/test.rs | 13 +++++++++++++ 2 files changed, 13 insertions(+) create mode 100644 tests/string-ref.xlsx diff --git a/tests/string-ref.xlsx b/tests/string-ref.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..780d83cc208f25422a99b8f621ca50c01bdfab1b GIT binary patch literal 10031 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 = wb("string-ref.xlsx"); + let expected_range = [ + [String("col1".to_string())], + [String("-8086931554011838357".to_string())], + ]; + // first sheet + range_eq!(xlsx.worksheet_range_at(0).unwrap().unwrap(), expected_range); + // second sheet is the same with a cell reference to the first sheet + range_eq!(xlsx.worksheet_range_at(1).unwrap().unwrap(), expected_range); +} From c9c78e950b3fd67b84e889da6682f2dd76a433e1 Mon Sep 17 00:00:00 2001 From: Eric Jolibois Date: Sun, 20 Oct 2024 16:50:43 +0200 Subject: [PATCH 2/3] fix: always parse a string cell as string --- src/xlsx/cells_reader.rs | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/xlsx/cells_reader.rs b/src/xlsx/cells_reader.rs index 53d80a0..4c907ff 100644 --- a/src/xlsx/cells_reader.rs +++ b/src/xlsx/cells_reader.rs @@ -359,17 +359,8 @@ fn read_v<'s>( Ok(DataRef::DateTimeIso(v)) } Some(b"str") => { - // see http://officeopenxml.com/SScontentOverview.php - // str - refers to formula cells - // * indicates calculated value (this case) - // * to the formula string (ignored case - // TODO: Fully support a Data::Formula representing both Formula string & - // last calculated value? - // - // NB: the result of a formula may not be a numeric value (=A3&" "&A4). - // We do try an initial parse as Float for utility, but fall back to a string - // representation if that fails - v.parse().map(DataRef::Float).or(Ok(DataRef::String(v))) + // string + Ok(DataRef::String(v)) } Some(b"n") => { // n - number From 0acc969a1a858f3eeebe8060e20f3111dfaa5646 Mon Sep 17 00:00:00 2001 From: Eric Jolibois Date: Sun, 20 Oct 2024 16:51:53 +0200 Subject: [PATCH 3/3] chore: make cargo clippy happy --- src/lib.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 4ec74eb..9a0e527 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -217,21 +217,16 @@ pub struct Sheet { /// Row to use as header /// By default, the first non-empty row is used as header -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Default, Clone, Copy)] #[non_exhaustive] pub enum HeaderRow { /// First non-empty row + #[default] FirstNonEmptyRow, /// Index of the header row Row(u32), } -impl Default for HeaderRow { - fn default() -> Self { - HeaderRow::FirstNonEmptyRow - } -} - // FIXME `Reader` must only be seek `Seek` for `Xls::xls`. Because of the present API this limits // the kinds of readers (other) data in formats can be read from. /// A trait to share spreadsheets reader functions across different `FileType`s