calamine/lib.rs
1// SPDX-License-Identifier: MIT
2//
3// Copyright 2016-2025, Johann Tuffe.
4
5#![cfg_attr(docsrs, feature(doc_cfg))]
6
7//! Rust Excel/`OpenDocument` reader
8//!
9//! # Status
10//!
11//! **calamine** is a pure Rust library to read Excel and `OpenDocument` Spreadsheet files.
12//!
13//! Read both cell values and vba project.
14//!
15//! # Examples
16//! ```
17//! use calamine::{Reader, open_workbook, Xlsx, Data};
18//!
19//! // opens a new workbook
20//! # let path = format!("{}/tests/issue3.xlsm", env!("CARGO_MANIFEST_DIR"));
21//! let mut workbook: Xlsx<_> = open_workbook(path).expect("Cannot open file");
22//!
23//! // Read whole worksheet data and provide some statistics
24//! if let Ok(range) = workbook.worksheet_range("Sheet1") {
25//! let total_cells = range.get_size().0 * range.get_size().1;
26//! let non_empty_cells: usize = range.used_cells().count();
27//! println!("Found {total_cells} cells in 'Sheet1', including {non_empty_cells} non empty cells");
28//! // alternatively, we can manually filter rows
29//! assert_eq!(non_empty_cells, range.rows()
30//! .flat_map(|r| r.iter().filter(|&c| c != &Data::Empty)).count());
31//! }
32//!
33//! // Check if the workbook has a vba project
34//! if let Ok(Some(vba)) = workbook.vba_project() {
35//! let module1 = vba.get_module("Module 1").unwrap();
36//! println!("Module 1 code:");
37//! println!("{module1}");
38//! for r in vba.get_references() {
39//! if r.is_missing() {
40//! println!("Reference {} is broken or not accessible", r.name);
41//! }
42//! }
43//! }
44//!
45//! // You can also get defined names definition (string representation only)
46//! for name in workbook.defined_names() {
47//! println!("name: {}, formula: {}", name.0, name.1);
48//! }
49//!
50//! // Now get all formula!
51//! let sheets = workbook.sheet_names().to_owned();
52//! for s in sheets {
53//! println!("found {} formula in '{}'",
54//! workbook
55//! .worksheet_formula(&s)
56//! .expect("error while getting formula")
57//! .rows().flat_map(|r| r.iter().filter(|f| !f.is_empty()))
58//! .count(),
59//! s);
60//! }
61//! ```
62//!
63//!
64//! # Crate Features
65//!
66//! The following is a list of the optional features supported by the `calamine`
67//! crate. They are all off by default.
68//!
69//! - `chrono`: Adds support for Chrono date/time types to the API.
70//! - `dates`: A deprecated backwards compatible synonym for the `chrono` feature.
71//! - `picture`: Adds support for reading raw data for pictures in spreadsheets.
72//!
73//! A `calamine` feature can be enabled in your `Cargo.toml` file as follows:
74//!
75//! ```bash
76//! cargo add calamine -F chrono
77//! ```
78
79#[macro_use]
80mod utils;
81
82mod auto;
83mod cfb;
84mod datatype;
85mod formats;
86mod ods;
87mod xls;
88mod xlsb;
89mod xlsx;
90
91mod de;
92mod errors;
93
94pub mod changelog;
95pub mod vba;
96
97use serde::de::{Deserialize, DeserializeOwned, Deserializer};
98use std::cmp::{max, min};
99use std::fmt;
100use std::fs::File;
101use std::io::{BufReader, Read, Seek};
102use std::ops::{Index, IndexMut};
103use std::path::Path;
104
105pub use crate::auto::{open_workbook_auto, open_workbook_auto_from_rs, Sheets};
106pub use crate::datatype::{Data, DataRef, DataType, ExcelDateTime, ExcelDateTimeType};
107pub use crate::de::{DeError, RangeDeserializer, RangeDeserializerBuilder, ToCellDeserializer};
108pub use crate::errors::Error;
109pub use crate::ods::{Ods, OdsError};
110pub use crate::xls::{Xls, XlsError, XlsOptions};
111pub use crate::xlsb::{Xlsb, XlsbError};
112pub use crate::xlsx::{Xlsx, XlsxError};
113
114use crate::vba::VbaProject;
115
116// https://msdn.microsoft.com/en-us/library/office/ff839168.aspx
117/// An enum to represent all different errors that can appear as
118/// a value in a worksheet cell
119#[derive(Debug, Clone, PartialEq)]
120pub enum CellErrorType {
121 /// Division by 0 error
122 Div0,
123 /// Unavailable value error
124 NA,
125 /// Invalid name error
126 Name,
127 /// Null value error
128 Null,
129 /// Number error
130 Num,
131 /// Invalid cell reference error
132 Ref,
133 /// Value error
134 Value,
135 /// Getting data
136 GettingData,
137}
138
139impl fmt::Display for CellErrorType {
140 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
141 match *self {
142 CellErrorType::Div0 => write!(f, "#DIV/0!"),
143 CellErrorType::NA => write!(f, "#N/A"),
144 CellErrorType::Name => write!(f, "#NAME?"),
145 CellErrorType::Null => write!(f, "#NULL!"),
146 CellErrorType::Num => write!(f, "#NUM!"),
147 CellErrorType::Ref => write!(f, "#REF!"),
148 CellErrorType::Value => write!(f, "#VALUE!"),
149 CellErrorType::GettingData => write!(f, "#DATA!"),
150 }
151 }
152}
153
154/// Dimensions info
155#[derive(Debug, Default, PartialEq, Eq, Hash, Ord, PartialOrd, Copy, Clone)]
156pub struct Dimensions {
157 /// start: (row, col)
158 pub start: (u32, u32),
159 /// end: (row, col)
160 pub end: (u32, u32),
161}
162
163#[allow(clippy::len_without_is_empty)]
164impl Dimensions {
165 /// create dimensions info with start position and end position
166 pub fn new(start: (u32, u32), end: (u32, u32)) -> Self {
167 Self { start, end }
168 }
169 /// check if a position is in it
170 pub fn contains(&self, row: u32, col: u32) -> bool {
171 row >= self.start.0 && row <= self.end.0 && col >= self.start.1 && col <= self.end.1
172 }
173 /// len
174 pub fn len(&self) -> u64 {
175 (self.end.0 - self.start.0 + 1) as u64 * (self.end.1 - self.start.1 + 1) as u64
176 }
177}
178
179/// Common file metadata
180///
181/// Depending on file type, some extra information may be stored
182/// in the Reader implementations
183#[derive(Debug, Default)]
184pub struct Metadata {
185 sheets: Vec<Sheet>,
186 /// Map of sheet names/sheet path within zip archive
187 names: Vec<(String, String)>,
188}
189
190/// Type of sheet.
191///
192/// Only Excel formats support this. Default value for ODS is
193/// `SheetType::WorkSheet`.
194///
195/// The property is defined in the following specifications:
196///
197/// - [ECMA-376 Part 1] 12.3.2, 12.3.7 and 12.3.24.
198/// - [MS-XLS `BoundSheet`].
199/// - [MS-XLSB `ST_SheetType`].
200///
201/// [ECMA-376 Part 1]: https://www.ecma-international.org/publications-and-standards/standards/ecma-376/
202/// [MS-XLS `BoundSheet`]: https://learn.microsoft.com/en-us/openspecs/office_file_formats/ms-xls/b9ec509a-235d-424e-871d-f8e721106501
203/// [MS-XLS `BrtBundleSh`]: https://learn.microsoft.com/en-us/openspecs/office_file_formats/ms-xlsb/1edadf56-b5cd-4109-abe7-76651bbe2722
204///
205#[derive(Debug, Clone, Copy, PartialEq)]
206pub enum SheetType {
207 /// A worksheet.
208 WorkSheet,
209 /// A dialog sheet.
210 DialogSheet,
211 /// A macro sheet.
212 MacroSheet,
213 /// A chartsheet.
214 ChartSheet,
215 /// A VBA module.
216 Vba,
217}
218
219/// Type of visible sheet.
220///
221/// The property is defined in the following specifications:
222///
223/// - [ECMA-376 Part 1] 18.18.68 `ST_SheetState` (Sheet Visibility Types).
224/// - [MS-XLS `BoundSheet`].
225/// - [MS-XLSB `ST_SheetState`].
226/// - [OpenDocument v1.2] 19.471 `style:display`.
227///
228/// [ECMA-376 Part 1]: https://www.ecma-international.org/publications-and-standards/standards/ecma-376/
229/// [OpenDocument v1.2]: https://docs.oasis-open.org/office/v1.2/os/OpenDocument-v1.2-os-part1.html#property-table_display
230/// [MS-XLS `BoundSheet`]: https://learn.microsoft.com/en-us/openspecs/office_file_formats/ms-xls/b9ec509a-235d-424e-871d-f8e721106501
231/// [MS-XLSB `ST_SheetState`]: https://learn.microsoft.com/en-us/openspecs/office_file_formats/ms-xlsb/74cb1d22-b931-4bf8-997d-17517e2416e9
232///
233#[derive(Debug, Clone, Copy, PartialEq)]
234pub enum SheetVisible {
235 /// Visible
236 Visible,
237 /// Hidden
238 Hidden,
239 /// The sheet is hidden and cannot be displayed using the user interface. It is supported only by Excel formats.
240 VeryHidden,
241}
242
243/// Metadata of sheet
244#[derive(Debug, Clone, PartialEq)]
245pub struct Sheet {
246 /// Name
247 pub name: String,
248 /// Type
249 /// Only Excel formats support this. Default value for ODS is `SheetType::WorkSheet`.
250 pub typ: SheetType,
251 /// Visible
252 pub visible: SheetVisible,
253}
254
255/// Row to use as header
256/// By default, the first non-empty row is used as header
257#[derive(Debug, Default, Clone, Copy)]
258#[non_exhaustive]
259pub enum HeaderRow {
260 /// First non-empty row
261 #[default]
262 FirstNonEmptyRow,
263 /// Index of the header row
264 Row(u32),
265}
266
267// FIXME `Reader` must only be seek `Seek` for `Xls::xls`. Because of the present API this limits
268// the kinds of readers (other) data in formats can be read from.
269/// A trait to share spreadsheets reader functions across different `FileType`s
270pub trait Reader<RS>: Sized
271where
272 RS: Read + Seek,
273{
274 /// Error specific to file type
275 type Error: std::fmt::Debug + From<std::io::Error>;
276
277 /// Creates a new instance.
278 fn new(reader: RS) -> Result<Self, Self::Error>;
279
280 /// Set header row (i.e. first row to be read)
281 /// If `header_row` is `None`, the first non-empty row will be used as header row
282 fn with_header_row(&mut self, header_row: HeaderRow) -> &mut Self;
283
284 /// Gets `VbaProject`
285 fn vba_project(&mut self) -> Result<Option<VbaProject>, Self::Error>;
286
287 /// Initialize
288 fn metadata(&self) -> &Metadata;
289
290 /// Read worksheet data in corresponding worksheet path
291 fn worksheet_range(&mut self, name: &str) -> Result<Range<Data>, Self::Error>;
292
293 /// Fetch all worksheet data & paths
294 fn worksheets(&mut self) -> Vec<(String, Range<Data>)>;
295
296 /// Read worksheet formula in corresponding worksheet path
297 fn worksheet_formula(&mut self, _: &str) -> Result<Range<String>, Self::Error>;
298
299 /// Get all sheet names of this workbook, in workbook order
300 ///
301 /// # Examples
302 /// ```
303 /// use calamine::{Xlsx, open_workbook, Reader};
304 ///
305 /// # let path = format!("{}/tests/issue3.xlsm", env!("CARGO_MANIFEST_DIR"));
306 /// let mut workbook: Xlsx<_> = open_workbook(path).unwrap();
307 /// println!("Sheets: {:#?}", workbook.sheet_names());
308 /// ```
309 fn sheet_names(&self) -> Vec<String> {
310 self.metadata()
311 .sheets
312 .iter()
313 .map(|s| s.name.to_owned())
314 .collect()
315 }
316
317 /// Fetch all sheets metadata
318 fn sheets_metadata(&self) -> &[Sheet] {
319 &self.metadata().sheets
320 }
321
322 /// Get all defined names (Ranges names etc)
323 fn defined_names(&self) -> &[(String, String)] {
324 &self.metadata().names
325 }
326
327 /// Get the nth worksheet. Shortcut for getting the nth
328 /// worksheet name, then the corresponding worksheet.
329 fn worksheet_range_at(&mut self, n: usize) -> Option<Result<Range<Data>, Self::Error>> {
330 let name = self.sheet_names().get(n)?.to_string();
331 Some(self.worksheet_range(&name))
332 }
333
334 /// Get the raw data of the pictures in a workbook.
335 ///
336 /// Returns a vector of tuples containing the file extension and a buffer of
337 /// the image data.
338 ///
339 /// # Examples
340 ///
341 /// An example of getting the raw data of pictures in an spreadsheet file.
342 ///
343 /// ```
344 /// # use calamine::{open_workbook, Error, Reader, Xlsx};
345 /// #
346 /// # fn main() -> Result<(), Error> {
347 /// # let path = "tests/picture.xlsx";
348 /// #
349 /// // Open the workbook.
350 /// let workbook: Xlsx<_> = open_workbook(path)?;
351 ///
352 /// // Get the data for each picture.
353 /// if let Some(pics) = workbook.pictures() {
354 /// for (ext, data) in pics {
355 /// println!("Type: '{}', Size: {} bytes", ext, data.len());
356 /// }
357 /// }
358 /// #
359 /// # Ok(())
360 /// # }
361 /// #
362 /// ```
363 ///
364 /// Output:
365 ///
366 /// ```text
367 /// Type: 'jpg', Size: 20762 bytes
368 /// Type: 'png', Size: 23453 bytes
369 /// ```
370 ///
371 #[cfg(feature = "picture")]
372 #[cfg_attr(docsrs, doc(cfg(feature = "picture")))]
373 fn pictures(&self) -> Option<Vec<(String, Vec<u8>)>>;
374}
375
376/// A trait to share spreadsheets reader functions across different `FileType`s
377pub trait ReaderRef<RS>: Reader<RS>
378where
379 RS: Read + Seek,
380{
381 /// Get worksheet range where shared string values are only borrowed.
382 ///
383 /// This is implemented only for [`calamine::Xlsx`](crate::Xlsx) and [`calamine::Xlsb`](crate::Xlsb), as Xls and Ods formats
384 /// do not support lazy iteration.
385 fn worksheet_range_ref<'a>(&'a mut self, name: &str)
386 -> Result<Range<DataRef<'a>>, Self::Error>;
387
388 /// Get the nth worksheet range where shared string values are only borrowed. Shortcut for getting the nth
389 /// worksheet name, then the corresponding worksheet.
390 ///
391 /// This is implemented only for [`calamine::Xlsx`](crate::Xlsx) and [`calamine::Xlsb`](crate::Xlsb), as Xls and Ods formats
392 /// do not support lazy iteration.
393 fn worksheet_range_at_ref(
394 &mut self,
395 n: usize,
396 ) -> Option<Result<Range<DataRef<'_>>, Self::Error>> {
397 let name = self.sheet_names().get(n)?.to_string();
398 Some(self.worksheet_range_ref(&name))
399 }
400}
401
402/// Convenient function to open a file with a `BufReader<File>`.
403pub fn open_workbook<R, P>(path: P) -> Result<R, R::Error>
404where
405 R: Reader<BufReader<File>>,
406 P: AsRef<Path>,
407{
408 let file = BufReader::new(File::open(path)?);
409 R::new(file)
410}
411
412/// Convenient function to open a file with a `BufReader<File>`.
413pub fn open_workbook_from_rs<R, RS>(rs: RS) -> Result<R, R::Error>
414where
415 RS: Read + Seek,
416 R: Reader<RS>,
417{
418 R::new(rs)
419}
420
421/// A trait to constrain cells
422pub trait CellType: Default + Clone + PartialEq {}
423
424impl CellType for Data {}
425impl<'a> CellType for DataRef<'a> {}
426impl CellType for String {}
427impl CellType for usize {} // for tests
428
429// -----------------------------------------------------------------------
430// The `Cell` struct.
431// -----------------------------------------------------------------------
432
433/// A struct to hold a cell position and value.
434///
435/// A `Cell` is a fundamental worksheet type that is used to create a [`Range`].
436/// It contains a position and a value.
437///
438/// # Examples
439///
440/// An example of creating a range of `Cell`s and iterating over them.
441///
442/// ```
443/// use calamine::{Cell, Data, Range};
444///
445/// let cells = vec![
446/// Cell::new((1, 1), Data::Int(1)),
447/// Cell::new((1, 2), Data::Int(2)),
448/// Cell::new((3, 1), Data::Int(3)),
449/// ];
450///
451/// // Create a Range from the cells.
452/// let range = Range::from_sparse(cells);
453///
454/// // Iterate over the cells in the range.
455/// for (row, col, data) in range.cells() {
456/// println!("({row}, {col}): {data}");
457/// }
458///
459/// ```
460///
461/// Output:
462///
463/// ```text
464/// (0, 0): 1
465/// (0, 1): 2
466/// (1, 0):
467/// (1, 1):
468/// (2, 0): 3
469/// (2, 1):
470/// ```
471///
472#[derive(Debug, Clone)]
473pub struct Cell<T: CellType> {
474 // The position for the cell (row, column).
475 pos: (u32, u32),
476
477 // The [`CellType`] value of the cell.
478 val: T,
479}
480
481impl<T: CellType> Cell<T> {
482 /// Creates a new `Cell` instance.
483 ///
484 /// # Parameters
485 ///
486 /// - `position`: A tuple representing the cell's position in the form of
487 /// `(row, column)`.
488 /// - `value`: The value of the cell, which must implement the [`CellType`]
489 /// trait.
490 ///
491 /// # Examples
492 ///
493 /// An example of creating a new `Cell` instance.
494 ///
495 /// ```
496 /// use calamine::{Cell, Data};
497 ///
498 /// let cell = Cell::new((1, 2), Data::Int(42));
499 ///
500 /// assert_eq!(&Data::Int(42), cell.get_value());
501 /// ```
502 ///
503 pub fn new(position: (u32, u32), value: T) -> Cell<T> {
504 Cell {
505 pos: position,
506 val: value,
507 }
508 }
509
510 /// Gets `Cell` position.
511 ///
512 /// # Examples
513 ///
514 /// An example of getting a `Cell` position `(row, column)`.
515 ///
516 /// ```
517 /// use calamine::{Cell, Data};
518 ///
519 /// let cell = Cell::new((1, 2), Data::Int(42));
520 ///
521 /// assert_eq!((1, 2), cell.get_position());
522 /// ```
523 ///
524 pub fn get_position(&self) -> (u32, u32) {
525 self.pos
526 }
527
528 /// Gets `Cell` value.
529 ///
530 /// # Examples
531 ///
532 /// An example of getting a `Cell` value.
533 ///
534 /// ```
535 /// use calamine::{Cell, Data};
536 ///
537 /// let cell = Cell::new((1, 2), Data::Int(42));
538 ///
539 /// assert_eq!(&Data::Int(42), cell.get_value());
540 /// ```
541 ///
542 pub fn get_value(&self) -> &T {
543 &self.val
544 }
545}
546
547// -----------------------------------------------------------------------
548// The `Range` struct.
549// -----------------------------------------------------------------------
550
551/// A struct which represents an area of cells and the data within it.
552///
553/// Ranges are used by `calamine` to represent an area of data in a worksheet. A
554/// `Range` is a rectangular area of cells defined by its start and end
555/// positions.
556///
557/// A `Range` is constructed with **absolute positions** in the form of `(row,
558/// column)`. The start position for the absolute positioning is the cell `(0,
559/// 0)` or `A1`. For the example range "B3:C6", shown below, the start position
560/// is `(2, 1)` and the end position is `(5, 2)`. Within the range, the cells
561/// are indexed with **relative positions** where `(0, 0)` is the start cell. In
562/// the example below the relative positions for the start and end cells are
563/// `(0, 0)` and `(3, 1)` respectively.
564///
565/// ```text
566/// ______________________________________________________________________________
567/// | || | | | |
568/// | || A | B | C | D |
569/// |_________||________________|________________|________________|________________|
570/// | 1 || | | | |
571/// |_________||________________|________________|________________|________________|
572/// | 2 || | | | |
573/// |_________||________________|________________|________________|________________|
574/// | 3 || | (2, 1), (0, 0) | | |
575/// |_________||________________|________________|________________|________________|
576/// | 4 || | | | |
577/// |_________||________________|________________|________________|________________|
578/// | 5 || | | | |
579/// |_________||________________|________________|________________|________________|
580/// | 6 || | | (5,2), (3, 1) | |
581/// |_________||________________|________________|________________|________________|
582/// | 7 || | | | |
583/// |_________||________________|________________|________________|________________|
584/// |_ ___________________________________________________________________|
585/// \ Sheet1 /
586/// ------
587/// ```
588///
589/// A `Range` contains a vector of cells of of generic type `T` which implement
590/// the [`CellType`] trait. The values are stored in a row-major order.
591///
592#[derive(Debug, Default, Clone, PartialEq, Eq)]
593pub struct Range<T> {
594 start: (u32, u32),
595 end: (u32, u32),
596 inner: Vec<T>,
597}
598
599impl<T: CellType> Range<T> {
600 /// Creates a new `Range` with default values.
601 ///
602 /// Create a new [`Range`] with the given start and end positions. The
603 /// positions are in worksheet absolute coordinates, i.e. `(0, 0)` is cell `A1`.
604 ///
605 /// The range is populated with default values of type `T`.
606 ///
607 /// When possible, use the more efficient [`Range::from_sparse()`]
608 /// constructor.
609 ///
610 /// # Parameters
611 ///
612 /// - `start`: The zero indexed (row, column) tuple.
613 /// - `end`: The zero indexed (row, column) tuple.
614 ///
615 /// # Panics
616 ///
617 /// Panics if `start` > `end`.
618 ///
619 ///
620 /// # Examples
621 ///
622 /// An example of creating a new calamine `Range`.
623 ///
624 /// ```
625 /// use calamine::{Data, Range};
626 ///
627 /// // Create a 8x1 Range.
628 /// let range: Range<Data> = Range::new((2, 2), (9, 2));
629 ///
630 /// assert_eq!(range.width(), 1);
631 /// assert_eq!(range.height(), 8);
632 /// assert_eq!(range.cells().count(), 8);
633 /// assert_eq!(range.used_cells().count(), 0);
634 /// ```
635 ///
636 ///
637 #[inline]
638 pub fn new(start: (u32, u32), end: (u32, u32)) -> Range<T> {
639 assert!(start <= end, "invalid range bounds");
640 Range {
641 start,
642 end,
643 inner: vec![T::default(); ((end.0 - start.0 + 1) * (end.1 - start.1 + 1)) as usize],
644 }
645 }
646
647 /// Creates a new empty `Range`.
648 ///
649 /// Creates a new [`Range`] with start and end positions both set to `(0,
650 /// 0)` and with an empty inner vector. An empty range can be expanded by
651 /// adding data.
652 ///
653 /// # Examples
654 ///
655 /// An example of creating a new empty calamine `Range`.
656 ///
657 /// ```
658 /// use calamine::{Data, Range};
659 ///
660 /// let range: Range<Data> = Range::empty();
661 ///
662 /// assert!(range.is_empty());
663 /// ```
664 ///
665 #[inline]
666 pub fn empty() -> Range<T> {
667 Range {
668 start: (0, 0),
669 end: (0, 0),
670 inner: Vec::new(),
671 }
672 }
673
674 /// Get top left cell position of a `Range`.
675 ///
676 /// Get the top left cell position of a range in absolute `(row, column)`
677 /// coordinates.
678 ///
679 /// Returns `None` if the range is empty.
680 ///
681 /// # Examples
682 ///
683 /// An example of getting the start position of a calamine `Range`.
684 ///
685 /// ```
686 /// use calamine::{Data, Range};
687 ///
688 /// let range: Range<Data> = Range::new((2, 3), (9, 3));
689 ///
690 /// assert_eq!(range.start(), Some((2, 3)));
691 /// ```
692 ///
693 #[inline]
694 pub fn start(&self) -> Option<(u32, u32)> {
695 if self.is_empty() {
696 None
697 } else {
698 Some(self.start)
699 }
700 }
701
702 /// Get bottom right cell position of a `Range`.
703 ///
704 /// Get the bottom right cell position of a range in absolute `(row,
705 /// column)` coordinates.
706 ///
707 /// Returns `None` if the range is empty.
708 ///
709 /// # Examples
710 ///
711 /// An example of getting the end position of a calamine `Range`.
712 ///
713 /// ```
714 /// use calamine::{Data, Range};
715 ///
716 /// let range: Range<Data> = Range::new((2, 3), (9, 3));
717 ///
718 /// assert_eq!(range.end(), Some((9, 3)));
719 /// ```
720 ///
721 #[inline]
722 pub fn end(&self) -> Option<(u32, u32)> {
723 if self.is_empty() {
724 None
725 } else {
726 Some(self.end)
727 }
728 }
729
730 /// Get the column width of a `Range`.
731 ///
732 /// The width is defined as the number of columns between the start and end
733 /// positions.
734 ///
735 /// # Examples
736 ///
737 /// An example of getting the column width of a calamine `Range`.
738 ///
739 /// ```
740 /// use calamine::{Data, Range};
741 ///
742 /// let range: Range<Data> = Range::new((2, 3), (9, 3));
743 ///
744 /// assert_eq!(range.width(), 1);
745 /// ```
746 ///
747 #[inline]
748 pub fn width(&self) -> usize {
749 if self.is_empty() {
750 0
751 } else {
752 (self.end.1 - self.start.1 + 1) as usize
753 }
754 }
755
756 /// Get the row height of a `Range`.
757 ///
758 /// The height is defined as the number of rows between the start and end
759 /// positions.
760 ///
761 /// # Examples
762 ///
763 /// An example of getting the row height of a calamine `Range`.
764 ///
765 /// ```
766 /// use calamine::{Data, Range};
767 ///
768 /// let range: Range<Data> = Range::new((2, 3), (9, 3));
769 ///
770 /// assert_eq!(range.height(), 8);
771 /// ```
772 ///
773 #[inline]
774 pub fn height(&self) -> usize {
775 if self.is_empty() {
776 0
777 } else {
778 (self.end.0 - self.start.0 + 1) as usize
779 }
780 }
781
782 /// Get size of a `Range` in (height, width) format.
783 ///
784 /// # Examples
785 ///
786 /// An example of getting the (height, width) size of a calamine `Range`.
787 ///
788 /// ```
789 /// use calamine::{Data, Range};
790 ///
791 /// let range: Range<Data> = Range::new((2, 3), (9, 3));
792 ///
793 /// assert_eq!(range.get_size(), (8, 1));
794 /// ```
795 ///
796 #[inline]
797 pub fn get_size(&self) -> (usize, usize) {
798 (self.height(), self.width())
799 }
800
801 /// Check if a `Range` is empty.
802 ///
803 /// # Examples
804 ///
805 /// An example of checking if a calamine `Range` is empty.
806 ///
807 /// ```
808 /// use calamine::{Data, Range};
809 ///
810 /// let range: Range<Data> = Range::empty();
811 ///
812 /// assert!(range.is_empty());
813 /// ```
814 ///
815 #[inline]
816 pub fn is_empty(&self) -> bool {
817 self.inner.is_empty()
818 }
819
820 /// Creates a `Range` from a sparse vector of cells.
821 ///
822 /// The `Range::from_sparse()` constructor can be used to create a Range
823 /// from a vector of [`Cell`] data. This is slightly more efficient than
824 /// creating a range with [`Range::new()`] and then setting the values.
825 ///
826 /// # Parameters
827 ///
828 /// - `cells`: A vector of [`Cell`] elements.
829 ///
830 /// # Examples
831 ///
832 /// An example of creating a new calamine `Range` for a sparse vector of
833 /// Cells.
834 ///
835 /// ```
836 /// use calamine::{Cell, Data, Range};
837 ///
838 /// let cells = vec![
839 /// Cell::new((2, 2), Data::Int(1)),
840 /// Cell::new((5, 2), Data::Int(1)),
841 /// Cell::new((9, 2), Data::Int(1)),
842 /// ];
843 ///
844 /// let range = Range::from_sparse(cells);
845 ///
846 /// assert_eq!(range.width(), 1);
847 /// assert_eq!(range.height(), 8);
848 /// assert_eq!(range.cells().count(), 8);
849 /// assert_eq!(range.used_cells().count(), 3);
850 /// ```
851 ///
852 pub fn from_sparse(cells: Vec<Cell<T>>) -> Range<T> {
853 if cells.is_empty() {
854 return Range::empty();
855 }
856 // cells do not always appear in (row, col) order
857 // search bounds
858 let mut row_start = u32::MAX;
859 let mut row_end = 0;
860 let mut col_start = u32::MAX;
861 let mut col_end = 0;
862 for (r, c) in cells.iter().map(|c| c.pos) {
863 row_start = min(r, row_start);
864 row_end = max(r, row_end);
865 col_start = min(c, col_start);
866 col_end = max(c, col_end);
867 }
868 let cols = (col_end - col_start + 1) as usize;
869 let rows = (row_end - row_start + 1) as usize;
870 let len = cols.saturating_mul(rows);
871 let mut v = vec![T::default(); len];
872 v.shrink_to_fit();
873 for c in cells {
874 let row = (c.pos.0 - row_start) as usize;
875 let col = (c.pos.1 - col_start) as usize;
876 let idx = row.saturating_mul(cols) + col;
877 if let Some(v) = v.get_mut(idx) {
878 *v = c.val;
879 }
880 }
881 Range {
882 start: (row_start, col_start),
883 end: (row_end, col_end),
884 inner: v,
885 }
886 }
887
888 /// Set a value at an absolute position in a `Range`.
889 ///
890 /// This method sets a value in the range at the given absolute position
891 /// (relative to `A1`).
892 ///
893 /// Try to avoid this method as much as possible and prefer initializing the
894 /// `Range` with the [`Range::from_sparse()`] constructor.
895 ///
896 /// # Parameters
897 ///
898 /// - `absolute_position`: The absolute position, relative to `A1`, in the
899 /// form of `(row, column)`. It must be greater than or equal to the start
900 /// position of the range. If the position is greater than the end of the range
901 /// the structure will be resized to accommodate the new end position.
902 ///
903 /// # Panics
904 ///
905 /// If `absolute_position.0 < self.start.0 || absolute_position.1 < self.start.1`
906 ///
907 /// # Examples
908 ///
909 /// An example of setting a value in a calamine `Range`.
910 ///
911 /// ```
912 /// use calamine::{Data, Range};
913 ///
914 /// let mut range = Range::new((0, 0), (5, 2));
915 ///
916 /// // The initial range is empty.
917 /// assert_eq!(range.get_value((2, 1)), Some(&Data::Empty));
918 ///
919 /// // Set a value at a specific position.
920 /// range.set_value((2, 1), Data::Float(1.0));
921 ///
922 /// // The value at the specified position should now be set.
923 /// assert_eq!(range.get_value((2, 1)), Some(&Data::Float(1.0)));
924 /// ```
925 ///
926 pub fn set_value(&mut self, absolute_position: (u32, u32), value: T) {
927 assert!(
928 self.start.0 <= absolute_position.0 && self.start.1 <= absolute_position.1,
929 "absolute_position out of bounds"
930 );
931
932 // check if we need to change range dimension (strangely happens sometimes ...)
933 match (
934 self.end.0 < absolute_position.0,
935 self.end.1 < absolute_position.1,
936 ) {
937 (false, false) => (), // regular case, position within bounds
938 (true, false) => {
939 let len = (absolute_position.0 - self.end.0 + 1) as usize * self.width();
940 self.inner.extend_from_slice(&vec![T::default(); len]);
941 self.end.0 = absolute_position.0;
942 }
943 // missing some rows
944 (e, true) => {
945 let height = if e {
946 (absolute_position.0 - self.start.0 + 1) as usize
947 } else {
948 self.height()
949 };
950 let width = (absolute_position.1 - self.start.1 + 1) as usize;
951 let old_width = self.width();
952 let mut data = Vec::with_capacity(width * height);
953 let empty = vec![T::default(); width - old_width];
954 for sce in self.inner.chunks(old_width) {
955 data.extend_from_slice(sce);
956 data.extend_from_slice(&empty);
957 }
958 data.extend_from_slice(&vec![T::default(); width * (height - self.height())]);
959 if e {
960 self.end = absolute_position;
961 } else {
962 self.end.1 = absolute_position.1;
963 }
964 self.inner = data;
965 } // missing some columns
966 }
967
968 let pos = (
969 absolute_position.0 - self.start.0,
970 absolute_position.1 - self.start.1,
971 );
972 let idx = pos.0 as usize * self.width() + pos.1 as usize;
973 self.inner[idx] = value;
974 }
975
976 /// Get a value at an absolute position in a `Range`.
977 ///
978 /// If the `absolute_position` is out of range, returns `None`, otherwise
979 /// returns the cell value. The coordinate format is `(row, column)`
980 /// relative to `A1`.
981 ///
982 /// For relative positions see the [`Range::get()`] method.
983 ///
984 /// # Parameters
985 ///
986 /// - `absolute_position`: The absolute position, relative to `A1`, in the
987 /// form of `(row, column)`.
988 ///
989 /// # Examples
990 ///
991 /// An example of getting a value in a calamine `Range`.
992 ///
993 /// ```
994 /// use calamine::{Data, Range};
995 ///
996 /// let range = Range::new((1, 1), (5, 5));
997 ///
998 /// // Get the value for a cell in the range.
999 /// assert_eq!(range.get_value((2, 2)), Some(&Data::Empty));
1000 ///
1001 /// // Get the value for a cell outside the range.
1002 /// assert_eq!(range.get_value((0, 0)), None);
1003 /// ```
1004 ///
1005 pub fn get_value(&self, absolute_position: (u32, u32)) -> Option<&T> {
1006 let p = absolute_position;
1007 if p.0 >= self.start.0 && p.0 <= self.end.0 && p.1 >= self.start.1 && p.1 <= self.end.1 {
1008 return self.get((
1009 (absolute_position.0 - self.start.0) as usize,
1010 (absolute_position.1 - self.start.1) as usize,
1011 ));
1012 }
1013 None
1014 }
1015
1016 /// Get a value at a relative position in a `Range`.
1017 ///
1018 /// If the `relative_position` is out of range, returns `None`, otherwise
1019 /// returns the cell value. The coordinate format is `(row, column)`
1020 /// relative to `(0, 0)` in the range.
1021 ///
1022 /// For absolute cell positioning see the [`Range::get_value()`] method.
1023 ///
1024 /// # Parameters
1025 ///
1026 /// - `relative_position`: The position relative to the index `(0, 0)` in
1027 /// the range.
1028 ///
1029 /// # Examples
1030 ///
1031 /// An example of getting a value in a calamine `Range`, using relative
1032 /// positioning.
1033 ///
1034 /// ```
1035 /// use calamine::{Data, Range};
1036 ///
1037 /// let mut range = Range::new((1, 1), (5, 5));
1038 ///
1039 /// // Set a cell value using the cell absolute position.
1040 /// range.set_value((2, 3), Data::Int(123));
1041 ///
1042 /// // Get the value using the range relative position.
1043 /// assert_eq!(range.get((1, 2)), Some(&Data::Int(123)));
1044 /// ```
1045 ///
1046 pub fn get(&self, relative_position: (usize, usize)) -> Option<&T> {
1047 let (row, col) = relative_position;
1048 let (height, width) = self.get_size();
1049 if col >= width || row >= height {
1050 None
1051 } else {
1052 self.inner.get(row * width + col)
1053 }
1054 }
1055
1056 /// Get an iterator over the rows of a `Range`.
1057 ///
1058 /// # Examples
1059 ///
1060 /// An example of using a `Row` iterator with a calamine `Range`.
1061 ///
1062 /// ```
1063 /// use calamine::{Cell, Data, Range};
1064 ///
1065 /// let cells = vec![
1066 /// Cell::new((1, 1), Data::Int(1)),
1067 /// Cell::new((1, 2), Data::Int(2)),
1068 /// Cell::new((3, 1), Data::Int(3)),
1069 /// ];
1070 ///
1071 /// // Create a Range from the cells.
1072 /// let range = Range::from_sparse(cells);
1073 ///
1074 /// // Iterate over the rows of the range.
1075 /// for (row_num, row) in range.rows().enumerate() {
1076 /// for (col_num, data) in row.iter().enumerate() {
1077 /// // Print the data in each cell of the row.
1078 /// println!("({row_num}, {col_num}): {data}");
1079 /// }
1080 /// }
1081 ///
1082 /// ```
1083 ///
1084 /// Output in relative coordinates:
1085 ///
1086 /// ```text
1087 /// (0, 0): 1
1088 /// (0, 1): 2
1089 /// (1, 0):
1090 /// (1, 1):
1091 /// (2, 0): 3
1092 /// (2, 1):
1093 /// ```
1094 ///
1095 pub fn rows(&self) -> Rows<'_, T> {
1096 if self.inner.is_empty() {
1097 Rows { inner: None }
1098 } else {
1099 let width = self.width();
1100 Rows {
1101 inner: Some(self.inner.chunks(width)),
1102 }
1103 }
1104 }
1105
1106 /// Get an iterator over the used cells in a `Range`.
1107 ///
1108 /// This method returns an iterator over the used cells in a range. The
1109 /// "used" cells are defined as the cells that have a value other than the
1110 /// default value for `T`. The iterator returns tuples of `(row, column,
1111 /// value)` for each used cell. The row and column are relative/index values
1112 /// rather than absolute cell positions.
1113 ///
1114 /// # Examples
1115 ///
1116 /// An example of iterating over the used cells in a calamine `Range`.
1117 ///
1118 /// ```
1119 /// use calamine::{Cell, Data, Range};
1120 ///
1121 /// let cells = vec![
1122 /// Cell::new((1, 1), Data::Int(1)),
1123 /// Cell::new((1, 2), Data::Int(2)),
1124 /// Cell::new((3, 1), Data::Int(3)),
1125 /// ];
1126 ///
1127 /// // Create a Range from the cells.
1128 /// let range = Range::from_sparse(cells);
1129 ///
1130 /// // Iterate over the used cells in the range.
1131 /// for (row, col, data) in range.used_cells() {
1132 /// println!("({row}, {col}): {data}");
1133 /// }
1134 /// ```
1135 ///
1136 /// Output:
1137 ///
1138 /// ```text
1139 /// (0, 0): 1
1140 /// (0, 1): 2
1141 /// (2, 0): 3
1142 /// ```
1143 ///
1144 pub fn used_cells(&self) -> UsedCells<'_, T> {
1145 UsedCells {
1146 width: self.width(),
1147 inner: self.inner.iter().enumerate(),
1148 }
1149 }
1150
1151 /// Get an iterator over all the cells in a `Range`.
1152 ///
1153 /// This method returns an iterator over all the cells in a range, including
1154 /// those that are empty. The iterator returns tuples of `(row, column,
1155 /// value)` for each cell. The row and column are relative/index values
1156 /// rather than absolute cell positions.
1157 ///
1158 /// # Examples
1159 ///
1160 /// An example of iterating over the used cells in a calamine `Range`.
1161 ///
1162 /// ```
1163 /// use calamine::{Cell, Data, Range};
1164 ///
1165 /// let cells = vec![
1166 /// Cell::new((1, 1), Data::Int(1)),
1167 /// Cell::new((1, 2), Data::Int(2)),
1168 /// Cell::new((3, 1), Data::Int(3)),
1169 /// ];
1170 ///
1171 /// // Create a Range from the cells.
1172 /// let range = Range::from_sparse(cells);
1173 ///
1174 /// // Iterate over the cells in the range.
1175 /// for (row, col, data) in range.cells() {
1176 /// println!("({row}, {col}): {data}");
1177 /// }
1178 /// ```
1179 ///
1180 /// Output:
1181 ///
1182 /// ```text
1183 /// (0, 0): 1
1184 /// (0, 1): 2
1185 /// (1, 0):
1186 /// (1, 1):
1187 /// (2, 0): 3
1188 /// (2, 1):
1189 /// ```
1190 ///
1191 pub fn cells(&self) -> Cells<'_, T> {
1192 Cells {
1193 width: self.width(),
1194 inner: self.inner.iter().enumerate(),
1195 }
1196 }
1197
1198 /// Build a `RangeDeserializer` for a `Range`.
1199 ///
1200 /// This method returns a [`RangeDeserializer`] that can be used to
1201 /// deserialize the data in the range.
1202 ///
1203 /// # Errors
1204 ///
1205 /// - [`DeError`] if the range cannot be deserialized.
1206 ///
1207 /// # Examples
1208 ///
1209 /// An example of creating a deserializer fora calamine `Range`.
1210 ///
1211 /// The sample Excel file `temperature.xlsx` contains a single sheet named
1212 /// "Sheet1" with the following data:
1213 ///
1214 /// ```text
1215 /// ____________________________________________
1216 /// | || | |
1217 /// | || A | B |
1218 /// |_________||________________|________________|
1219 /// | 1 || label | value |
1220 /// |_________||________________|________________|
1221 /// | 2 || celsius | 22.2222 |
1222 /// |_________||________________|________________|
1223 /// | 3 || fahrenheit | 72 |
1224 /// |_________||________________|________________|
1225 /// |_ _________________________________|
1226 /// \ Sheet1 /
1227 /// ------
1228 /// ```
1229 ///
1230 /// ```
1231 /// use calamine::{open_workbook, Error, Reader, Xlsx};
1232 ///
1233 /// fn main() -> Result<(), Error> {
1234 /// let path = "tests/temperature.xlsx";
1235 ///
1236 /// // Open the workbook.
1237 /// let mut workbook: Xlsx<_> = open_workbook(path)?;
1238 ///
1239 /// // Get the data range from the first sheet.
1240 /// let sheet_range = workbook.worksheet_range("Sheet1")?;
1241 ///
1242 /// // Get an iterator over data in the range.
1243 /// let mut iter = sheet_range.deserialize()?;
1244 ///
1245 /// // Get the next record in the range. The first row is assumed to be the
1246 /// // header.
1247 /// if let Some(result) = iter.next() {
1248 /// let (label, value): (String, f64) = result?;
1249 ///
1250 /// assert_eq!(label, "celsius");
1251 /// assert_eq!(value, 22.2222);
1252 ///
1253 /// Ok(())
1254 /// } else {
1255 /// Err(From::from("Expected at least one record but got none"))
1256 /// }
1257 /// }
1258 /// ```
1259 ///
1260 pub fn deserialize<'a, D>(&'a self) -> Result<RangeDeserializer<'a, T, D>, DeError>
1261 where
1262 T: ToCellDeserializer<'a>,
1263 D: DeserializeOwned,
1264 {
1265 RangeDeserializerBuilder::new().from_range(self)
1266 }
1267
1268 /// Build a new `Range` out of the current range.
1269 ///
1270 /// This method returns a new `Range` with cloned data. In general it is
1271 /// used to get a subset of an existing range. However, if the new range is
1272 /// larger than the existing range the new cells will be filled with default
1273 /// values.
1274 ///
1275 /// # Examples
1276 ///
1277 /// An example of getting a sub range of a calamine `Range`.
1278 ///
1279 /// ```
1280 /// use calamine::{Data, Range};
1281 ///
1282 /// // Create a range with some values.
1283 /// let mut a = Range::new((1, 1), (3, 3));
1284 /// a.set_value((1, 1), Data::Bool(true));
1285 /// a.set_value((2, 2), Data::Bool(true));
1286 /// a.set_value((3, 3), Data::Bool(true));
1287 ///
1288 /// // Get a sub range of the main range.
1289 /// let b = a.range((1, 1), (2, 2));
1290 /// assert_eq!(b.get_value((1, 1)), Some(&Data::Bool(true)));
1291 /// assert_eq!(b.get_value((2, 2)), Some(&Data::Bool(true)));
1292 ///
1293 /// // Get a larger range with default values.
1294 /// let c = a.range((0, 0), (5, 5));
1295 /// assert_eq!(c.get_value((0, 0)), Some(&Data::Empty));
1296 /// assert_eq!(c.get_value((3, 3)), Some(&Data::Bool(true)));
1297 /// assert_eq!(c.get_value((5, 5)), Some(&Data::Empty));
1298 /// ```
1299 ///
1300 pub fn range(&self, start: (u32, u32), end: (u32, u32)) -> Range<T> {
1301 let mut other = Range::new(start, end);
1302 let (self_start_row, self_start_col) = self.start;
1303 let (self_end_row, self_end_col) = self.end;
1304 let (other_start_row, other_start_col) = other.start;
1305 let (other_end_row, other_end_col) = other.end;
1306
1307 // copy data from self to other
1308 let start_row = max(self_start_row, other_start_row);
1309 let end_row = min(self_end_row, other_end_row);
1310 let start_col = max(self_start_col, other_start_col);
1311 let end_col = min(self_end_col, other_end_col);
1312
1313 if start_row > end_row || start_col > end_col {
1314 return other;
1315 }
1316
1317 let self_width = self.width();
1318 let other_width = other.width();
1319
1320 // change referential
1321 //
1322 // we want to copy range: start_row..(end_row + 1)
1323 // In self referential it is (start_row - self_start_row)..(end_row + 1 - self_start_row)
1324 let self_row_start = (start_row - self_start_row) as usize;
1325 let self_row_end = (end_row + 1 - self_start_row) as usize;
1326 let self_col_start = (start_col - self_start_col) as usize;
1327 let self_col_end = (end_col + 1 - self_start_col) as usize;
1328
1329 let other_row_start = (start_row - other_start_row) as usize;
1330 let other_row_end = (end_row + 1 - other_start_row) as usize;
1331 let other_col_start = (start_col - other_start_col) as usize;
1332 let other_col_end = (end_col + 1 - other_start_col) as usize;
1333
1334 {
1335 let self_rows = self
1336 .inner
1337 .chunks(self_width)
1338 .take(self_row_end)
1339 .skip(self_row_start);
1340
1341 let other_rows = other
1342 .inner
1343 .chunks_mut(other_width)
1344 .take(other_row_end)
1345 .skip(other_row_start);
1346
1347 for (self_row, other_row) in self_rows.zip(other_rows) {
1348 let self_cols = &self_row[self_col_start..self_col_end];
1349 let other_cols = &mut other_row[other_col_start..other_col_end];
1350 other_cols.clone_from_slice(self_cols);
1351 }
1352 }
1353
1354 other
1355 }
1356}
1357
1358impl<T: CellType + fmt::Display> Range<T> {
1359 /// Get headers for a `Range`.
1360 ///
1361 /// This method returns the first row of the range as an optional vector of
1362 /// strings. The data type `T` in the range must support the [`ToString`]
1363 /// trait.
1364 ///
1365 /// # Examples
1366 ///
1367 /// An example of getting the header row of a calamine `Range`.
1368 ///
1369 /// ```
1370 /// use calamine::{Data, Range};
1371 ///
1372 /// // Create a range with some values.
1373 /// let mut range = Range::new((0, 0), (5, 2));
1374 /// range.set_value((0, 0), Data::String(String::from("a")));
1375 /// range.set_value((0, 1), Data::Int(1));
1376 /// range.set_value((0, 2), Data::Bool(true));
1377 ///
1378 /// // Get the headers of the range.
1379 /// let headers = range.headers();
1380 ///
1381 /// assert_eq!(
1382 /// headers,
1383 /// Some(vec![
1384 /// String::from("a"),
1385 /// String::from("1"),
1386 /// String::from("true")
1387 /// ])
1388 /// );
1389 /// ```
1390 ///
1391 pub fn headers(&self) -> Option<Vec<String>> {
1392 self.rows()
1393 .next()
1394 .map(|row| row.iter().map(ToString::to_string).collect())
1395 }
1396}
1397
1398/// Implementation of the `Index` trait for `Range` rows.
1399///
1400/// # Examples
1401///
1402/// An example of row indexing for a calamine `Range`.
1403///
1404/// ```
1405/// use calamine::{Data, Range};
1406///
1407/// // Create a range with a value.
1408/// let mut range = Range::new((1, 1), (3, 3));
1409/// range.set_value((2, 2), Data::Int(123));
1410///
1411/// // Get the second row via indexing.
1412/// assert_eq!(range[1], [Data::Empty, Data::Int(123), Data::Empty]);
1413/// ```
1414///
1415impl<T: CellType> Index<usize> for Range<T> {
1416 type Output = [T];
1417 fn index(&self, index: usize) -> &[T] {
1418 let width = self.width();
1419 &self.inner[index * width..(index + 1) * width]
1420 }
1421}
1422
1423/// Implementation of the `Index` trait for `Range` cells.
1424///
1425/// # Examples
1426///
1427/// An example of cell indexing for a calamine `Range`.
1428///
1429/// ```
1430/// use calamine::{Data, Range};
1431///
1432/// // Create a range with a value.
1433/// let mut range = Range::new((1, 1), (3, 3));
1434/// range.set_value((2, 2), Data::Int(123));
1435///
1436/// // Get the value via cell indexing.
1437/// assert_eq!(range[(1, 1)], Data::Int(123));
1438/// ```
1439///
1440impl<T: CellType> Index<(usize, usize)> for Range<T> {
1441 type Output = T;
1442 fn index(&self, index: (usize, usize)) -> &T {
1443 let (height, width) = self.get_size();
1444 assert!(index.1 < width && index.0 < height, "index out of bounds");
1445 &self.inner[index.0 * width + index.1]
1446 }
1447}
1448
1449/// Implementation of the `IndexMut` trait for `Range` rows.
1450impl<T: CellType> IndexMut<usize> for Range<T> {
1451 fn index_mut(&mut self, index: usize) -> &mut [T] {
1452 let width = self.width();
1453 &mut self.inner[index * width..(index + 1) * width]
1454 }
1455}
1456
1457/// Implementation of the `IndexMut` trait for `Range` cells.
1458///
1459/// # Examples
1460///
1461/// An example of mutable cell indexing for a calamine `Range`.
1462///
1463/// ```
1464/// use calamine::{Data, Range};
1465///
1466/// // Create a new empty range.
1467/// let mut range = Range::new((1, 1), (3, 3));
1468///
1469/// // Set a value in the range using cell indexing.
1470/// range[(1, 1)] = Data::Int(123);
1471///
1472/// // Test the value was set correctly.
1473/// assert_eq!(range.get((1, 1)), Some(&Data::Int(123)));
1474/// ```
1475///
1476impl<T: CellType> IndexMut<(usize, usize)> for Range<T> {
1477 fn index_mut(&mut self, index: (usize, usize)) -> &mut T {
1478 let (height, width) = self.get_size();
1479 assert!(index.1 < width && index.0 < height, "index out of bounds");
1480 &mut self.inner[index.0 * width + index.1]
1481 }
1482}
1483
1484// -----------------------------------------------------------------------
1485// Range Iterators.
1486// -----------------------------------------------------------------------
1487
1488/// A struct to iterate over all `Cell`s in a `Range`.
1489///
1490/// # Examples
1491///
1492/// An example iterating over the cells in a calamine range using the `Cells`
1493/// iterator returned by [`Range::cells()`].
1494///
1495/// ```
1496/// use calamine::{Cell, Data, Range};
1497///
1498/// let cells = vec![
1499/// Cell::new((1, 1), Data::Int(1)),
1500/// Cell::new((1, 2), Data::Int(2)),
1501/// Cell::new((3, 1), Data::Int(3)),
1502/// ];
1503///
1504/// // Create a Range from the cells.
1505/// let range = Range::from_sparse(cells);
1506///
1507/// // Use the Cells iterator returned by Range::cells().
1508/// for (row, col, data) in range.cells() {
1509/// println!("({row}, {col}): {data}");
1510/// }
1511///
1512/// ```
1513///
1514/// Output:
1515///
1516/// ```text
1517/// (0, 0): 1
1518/// (0, 1): 2
1519/// (1, 0):
1520/// (1, 1):
1521/// (2, 0): 3
1522/// (2, 1):
1523/// ```
1524///
1525#[derive(Clone, Debug)]
1526pub struct Cells<'a, T: CellType> {
1527 width: usize,
1528 inner: std::iter::Enumerate<std::slice::Iter<'a, T>>,
1529}
1530
1531impl<'a, T: 'a + CellType> Iterator for Cells<'a, T> {
1532 type Item = (usize, usize, &'a T);
1533 fn next(&mut self) -> Option<Self::Item> {
1534 self.inner.next().map(|(i, v)| {
1535 let row = i / self.width;
1536 let col = i % self.width;
1537 (row, col, v)
1538 })
1539 }
1540 fn size_hint(&self) -> (usize, Option<usize>) {
1541 self.inner.size_hint()
1542 }
1543}
1544
1545impl<'a, T: 'a + CellType> DoubleEndedIterator for Cells<'a, T> {
1546 fn next_back(&mut self) -> Option<Self::Item> {
1547 self.inner.next_back().map(|(i, v)| {
1548 let row = i / self.width;
1549 let col = i % self.width;
1550 (row, col, v)
1551 })
1552 }
1553}
1554
1555impl<'a, T: 'a + CellType> ExactSizeIterator for Cells<'a, T> {}
1556
1557/// A struct to iterate over all the used `Cell`s in a `Range`.
1558///
1559/// # Examples
1560///
1561/// An example iterating over the used cells in a calamine range using the
1562/// `UsedCells` iterator returned by [`Range::used_cells()`].
1563///
1564/// ```
1565/// use calamine::{Cell, Data, Range};
1566///
1567/// let cells = vec![
1568/// Cell::new((1, 1), Data::Int(1)),
1569/// Cell::new((1, 2), Data::Int(2)),
1570/// Cell::new((3, 1), Data::Int(3)),
1571/// ];
1572///
1573/// // Create a Range from the cells.
1574/// let range = Range::from_sparse(cells);
1575///
1576/// // Use the UsedCells iterator returned by Range::used_cells().
1577/// for (row, col, data) in range.used_cells() {
1578/// println!("({row}, {col}): {data}");
1579/// }
1580///
1581/// ```
1582///
1583/// Output:
1584///
1585/// ```text
1586/// (0, 0): 1
1587/// (0, 1): 2
1588/// (2, 0): 3
1589/// ```
1590///
1591#[derive(Clone, Debug)]
1592pub struct UsedCells<'a, T: CellType> {
1593 width: usize,
1594 inner: std::iter::Enumerate<std::slice::Iter<'a, T>>,
1595}
1596
1597impl<'a, T: 'a + CellType> Iterator for UsedCells<'a, T> {
1598 type Item = (usize, usize, &'a T);
1599 fn next(&mut self) -> Option<Self::Item> {
1600 self.inner
1601 .by_ref()
1602 .find(|&(_, v)| v != &T::default())
1603 .map(|(i, v)| {
1604 let row = i / self.width;
1605 let col = i % self.width;
1606 (row, col, v)
1607 })
1608 }
1609 fn size_hint(&self) -> (usize, Option<usize>) {
1610 let (_, up) = self.inner.size_hint();
1611 (0, up)
1612 }
1613}
1614
1615impl<'a, T: 'a + CellType> DoubleEndedIterator for UsedCells<'a, T> {
1616 fn next_back(&mut self) -> Option<Self::Item> {
1617 self.inner
1618 .by_ref()
1619 .rfind(|&(_, v)| v != &T::default())
1620 .map(|(i, v)| {
1621 let row = i / self.width;
1622 let col = i % self.width;
1623 (row, col, v)
1624 })
1625 }
1626}
1627
1628/// A struct to iterate over all `Rows`s in a `Range`.
1629///
1630/// # Examples
1631///
1632/// An example iterating over the rows in a calamine range using the `Rows`
1633/// iterator returned by [`Range::rows()`].
1634///
1635/// ```
1636/// use calamine::{Cell, Data, Range};
1637///
1638/// let cells = vec![
1639/// Cell::new((1, 1), Data::Int(1)),
1640/// Cell::new((1, 2), Data::Int(2)),
1641/// Cell::new((3, 1), Data::Int(3)),
1642/// ];
1643///
1644/// // Create a Range from the cells.
1645/// let range = Range::from_sparse(cells);
1646///
1647/// // Use the Rows iterator returned by Range::rows().
1648/// for (row_num, row) in range.rows().enumerate() {
1649/// for (col_num, data) in row.iter().enumerate() {
1650/// // Print the data in each cell of the row.
1651/// println!("({row_num}, {col_num}): {data}");
1652/// }
1653/// }
1654/// ```
1655///
1656/// Output in relative coordinates:
1657///
1658/// ```text
1659/// (0, 0): 1
1660/// (0, 1): 2
1661/// (1, 0):
1662/// (1, 1):
1663/// (2, 0): 3
1664/// (2, 1):
1665/// ```
1666///
1667#[derive(Clone, Debug)]
1668pub struct Rows<'a, T: CellType> {
1669 inner: Option<std::slice::Chunks<'a, T>>,
1670}
1671
1672impl<'a, T: 'a + CellType> Iterator for Rows<'a, T> {
1673 type Item = &'a [T];
1674 fn next(&mut self) -> Option<Self::Item> {
1675 self.inner.as_mut().and_then(std::iter::Iterator::next)
1676 }
1677 fn size_hint(&self) -> (usize, Option<usize>) {
1678 self.inner
1679 .as_ref()
1680 .map_or((0, Some(0)), std::iter::Iterator::size_hint)
1681 }
1682}
1683
1684impl<'a, T: 'a + CellType> DoubleEndedIterator for Rows<'a, T> {
1685 fn next_back(&mut self) -> Option<Self::Item> {
1686 self.inner
1687 .as_mut()
1688 .and_then(std::iter::DoubleEndedIterator::next_back)
1689 }
1690}
1691
1692impl<'a, T: 'a + CellType> ExactSizeIterator for Rows<'a, T> {}
1693
1694// -----------------------------------------------------------------------
1695// The `Table` struct.
1696// -----------------------------------------------------------------------
1697
1698/// The `Table` struct represents an Excel worksheet table.
1699///
1700/// Tables in Excel are a way of grouping a range of cells into a single entity
1701/// that has common formatting or that can be referenced in formulas. In
1702/// `calamine`, tables can be read and converted to a data [`Range`] for further
1703/// processing.
1704///
1705/// Calamine does not automatically load Table data from a workbook to avoid
1706/// unnecessary overhead. Instead you must explicitly load the Table data using
1707/// the [`Xlsx::load_tables()`](crate::Xlsx::load_tables) method. Once the
1708/// tables have been loaded the following methods can be used to extract and
1709/// work with individual tables:
1710///
1711/// - [`Xlsx::table_by_name()`](crate::Xlsx::table_by_name).
1712/// - [`Xlsx::table_by_name_ref()`](crate::Xlsx::table_by_name_ref).
1713/// - [`Xlsx::table_names()`](crate::Xlsx::table_names).
1714/// - [`Xlsx::table_names_in_sheet()`](crate::Xlsx::table_names_in_sheet).
1715///
1716/// Note, these methods are only available for the [`Xlsx`] struct since Tables
1717/// are a feature of the xlsx/xlsb format. They are not currently implemented
1718/// for [`Xlsb`].
1719///
1720/// Once you have a `Table` instance, you can access its properties and data
1721/// using the methods below.
1722///
1723/// # Examples
1724///
1725/// An example of reading the data from an Excel worksheet Table using the
1726/// `calamine` crate.
1727///
1728/// The sample Excel file `inventory-table.xlsx` contains a single sheet named
1729/// "Sheet1" with the following data laid out in a worksheet Table called
1730/// "Table1":
1731///
1732/// ```text
1733/// _____________________________________________________________
1734/// | || | | |
1735/// | || A | B | C |
1736/// |_________||________________|________________|________________|
1737/// | 1 || Item | Type | Quantity |
1738/// |_________||________________|________________|________________|
1739/// | 2 || 1 | Apple | 50 |
1740/// |_________||________________|________________|________________|
1741/// | 3 || 2 | Banana | 200 |
1742/// |_________||________________|________________|________________|
1743/// | 4 || 3 | Orange | 60 |
1744/// |_________||________________|________________|________________|
1745/// | 5 || 4 | Pear | 100 |
1746/// |_________||________________|________________|________________|
1747/// |_ __________________________________________________|
1748/// \ Sheet1 /
1749/// ------
1750/// ```
1751///
1752/// ```
1753/// use calamine::{open_workbook, Error, Xlsx};
1754///
1755/// fn main() -> Result<(), Error> {
1756/// let path = format!("{}/tests/inventory-table.xlsx", env!("CARGO_MANIFEST_DIR"));
1757///
1758/// // Open the workbook.
1759/// let mut workbook: Xlsx<_> = open_workbook(path)?;
1760///
1761/// // Load the tables in the workbook.
1762/// workbook.load_tables()?;
1763///
1764/// // Get the table by name.
1765/// let table = workbook.table_by_name("Table1")?;
1766///
1767/// // Check the table's name.
1768/// let table_name = table.name();
1769/// assert_eq!(table_name, "Table1");
1770///
1771/// // Check that it came from Sheet1.
1772/// let sheet_name = table.sheet_name();
1773/// assert_eq!(sheet_name, "Sheet1");
1774///
1775/// // Get the table column headers.
1776/// let columns_headers = table.columns();
1777/// assert_eq!(columns_headers, vec!["Item", "Type", "Quantity"]);
1778///
1779/// // Get the table data range (without the headers).
1780/// let data = table.data();
1781///
1782/// // Iterate over the rows of the data range.
1783/// for (row_num, row) in data.rows().enumerate() {
1784/// for (col_num, data) in row.iter().enumerate() {
1785/// // Print the data in each cell of the row.
1786/// println!("({row_num}, {col_num}): {data}");
1787/// }
1788/// println!();
1789/// }
1790///
1791/// Ok(())
1792/// }
1793/// ```
1794///
1795/// Output in relative coordinates:
1796///
1797/// ```text
1798/// (0, 0): 1
1799/// (0, 1): Apple
1800/// (0, 2): 50
1801///
1802/// (1, 0): 2
1803/// (1, 1): Banana
1804/// (1, 2): 200
1805///
1806/// (2, 0): 3
1807/// (2, 1): Orange
1808/// (2, 2): 60
1809///
1810/// (3, 0): 4
1811/// (3, 1): Pear
1812/// (3, 2): 100
1813/// ```
1814///
1815#[derive(Debug, Clone)]
1816pub struct Table<T> {
1817 pub(crate) name: String,
1818 pub(crate) sheet_name: String,
1819 pub(crate) columns: Vec<String>,
1820 pub(crate) data: Range<T>,
1821}
1822impl<T> Table<T> {
1823 /// Get the name of the table.
1824 ///
1825 /// Tables in Excel have sequentially assigned names like "Table1",
1826 /// "Table2", etc. but can also have used assigned names.
1827 ///
1828 /// # Examples
1829 ///
1830 /// An example of getting the name of an Excel worksheet Table.
1831 ///
1832 /// ```
1833 /// use calamine::{open_workbook, Error, Xlsx};
1834 ///
1835 /// fn main() -> Result<(), Error> {
1836 /// let path = format!("{}/tests/inventory-table.xlsx", env!("CARGO_MANIFEST_DIR"));
1837 ///
1838 /// // Open the workbook.
1839 /// let mut workbook: Xlsx<_> = open_workbook(path)?;
1840 ///
1841 /// // Load the tables in the workbook.
1842 /// workbook.load_tables()?;
1843 ///
1844 /// // Get the table by name.
1845 /// let table = workbook.table_by_name("Table1")?;
1846 ///
1847 /// // Check the table's name.
1848 /// let table_name = table.name();
1849 /// assert_eq!(table_name, "Table1");
1850 ///
1851 /// Ok(())
1852 /// }
1853 /// ```
1854 ///
1855 pub fn name(&self) -> &str {
1856 &self.name
1857 }
1858 /// Get the name of the parent worksheet for a table.
1859 ///
1860 /// This method returns the name of the parent worksheet that contains the
1861 /// table.
1862 ///
1863 /// # Examples
1864 ///
1865 /// An example of getting the parent worksheet name for an Excel worksheet
1866 /// Table.
1867 ///
1868 /// ```
1869 /// use calamine::{open_workbook, Error, Xlsx};
1870 ///
1871 /// fn main() -> Result<(), Error> {
1872 /// let path = format!("{}/tests/inventory-table.xlsx", env!("CARGO_MANIFEST_DIR"));
1873 ///
1874 /// // Open the workbook.
1875 /// let mut workbook: Xlsx<_> = open_workbook(path)?;
1876 ///
1877 /// // Load the tables in the workbook.
1878 /// workbook.load_tables()?;
1879 ///
1880 /// // Get the table by name.
1881 /// let table = workbook.table_by_name("Table1")?;
1882 ///
1883 /// // Check that it came from Sheet1.
1884 /// let sheet_name = table.sheet_name();
1885 /// assert_eq!(sheet_name, "Sheet1");
1886 ///
1887 /// Ok(())
1888 /// }
1889 /// ```
1890 ///
1891 pub fn sheet_name(&self) -> &str {
1892 &self.sheet_name
1893 }
1894
1895 /// Get the header names of the table columns.
1896 ///
1897 /// This method returns a slice of strings representing the names of the
1898 /// column headers in the table.
1899 ///
1900 /// In Excel table headers can be hidden but the table will still have
1901 /// column header names.
1902 ///
1903 /// # Examples
1904 ///
1905 /// An example of getting the column headers for an Excel worksheet Table.
1906 ///
1907 /// ```
1908 /// use calamine::{open_workbook, Error, Xlsx};
1909 ///
1910 /// fn main() -> Result<(), Error> {
1911 /// let path = format!("{}/tests/inventory-table.xlsx", env!("CARGO_MANIFEST_DIR"));
1912 ///
1913 /// // Open the workbook.
1914 /// let mut workbook: Xlsx<_> = open_workbook(path)?;
1915 ///
1916 /// // Load the tables in the workbook.
1917 /// workbook.load_tables()?;
1918 ///
1919 /// // Get the table by name.
1920 /// let table = workbook.table_by_name("Table1")?;
1921 ///
1922 /// // Get the table column headers.
1923 /// let columns_headers = table.columns();
1924 /// assert_eq!(columns_headers, vec!["Item", "Type", "Quantity"]);
1925 ///
1926 /// Ok(())
1927 /// }
1928 /// ```
1929 ///
1930 pub fn columns(&self) -> &[String] {
1931 &self.columns
1932 }
1933
1934 /// Get a range representing the data from the table
1935 ///
1936 /// This method returns a reference to the data [`Range`] of the table,
1937 ///
1938 /// Note that the data range excludes the column headers.
1939 ///
1940 /// # Examples
1941 ///
1942 /// An example of getting the data range of an Excel worksheet Table.
1943 ///
1944 /// ```
1945 /// use calamine::{open_workbook, Data, Error, Xlsx};
1946 ///
1947 /// fn main() -> Result<(), Error> {
1948 /// let path = format!("{}/tests/inventory-table.xlsx", env!("CARGO_MANIFEST_DIR"));
1949 ///
1950 /// // Open the workbook.
1951 /// let mut workbook: Xlsx<_> = open_workbook(path)?;
1952 ///
1953 /// // Load the tables in the workbook.
1954 /// workbook.load_tables()?;
1955 ///
1956 /// // Get the table by name.
1957 /// let table = workbook.table_by_name("Table1")?;
1958 ///
1959 /// // Get the data range of the table.
1960 /// let data_range = table.data();
1961 ///
1962 /// // Check one of the values in the data range. Note the relative
1963 /// // positioning within the range returned by the `get()` method.
1964 /// assert_eq!(
1965 /// data_range.get((0, 1)),
1966 /// Some(&Data::String("Apple".to_string()))
1967 /// );
1968 ///
1969 /// Ok(())
1970 /// }
1971 /// ```
1972 ///
1973 pub fn data(&self) -> &Range<T> {
1974 &self.data
1975 }
1976}
1977
1978/// Convert a `Table<T>` into a `Range<T>`.
1979///
1980/// # Examples
1981///
1982/// An example of getting the data range of an Excel worksheet Table via the
1983/// `From/Into` trait.
1984///
1985/// ```
1986/// use calamine::{open_workbook, Data, Error, Range, Xlsx};
1987///
1988/// fn main() -> Result<(), Error> {
1989/// let path = format!("{}/tests/inventory-table.xlsx", env!("CARGO_MANIFEST_DIR"));
1990///
1991/// // Open the workbook.
1992/// let mut workbook: Xlsx<_> = open_workbook(path)?;
1993///
1994/// // Load the tables in the workbook.
1995/// workbook.load_tables()?;
1996///
1997/// // Get the table by name.
1998/// let table = workbook.table_by_name("Table1")?;
1999///
2000/// // Convert the table into a data range using the `From/Into` trait.
2001/// let data_range: Range<Data> = table.into();
2002///
2003/// // Check one of the values in the data range. Note the relative
2004/// // positioning within the range returned by the `get()` method.
2005/// assert_eq!(
2006/// data_range.get((0, 1)),
2007/// Some(&Data::String("Apple".to_string()))
2008/// );
2009///
2010/// Ok(())
2011/// }
2012/// ```
2013///
2014impl<T: CellType> From<Table<T>> for Range<T> {
2015 fn from(table: Table<T>) -> Range<T> {
2016 table.data
2017 }
2018}
2019
2020/// A helper function to deserialize cell values as `i64`.
2021///
2022/// This is useful when cells may also contain invalid values (i.e. strings). It
2023/// applies the [`as_i64`](crate::datatype::DataType::as_i64) method to the cell
2024/// value, and returns `Ok(Some(value_as_i64))` if successful or `Ok(None)` if
2025/// unsuccessful, therefore never failing.
2026///
2027/// This function is intended to be used with Serde's
2028/// [`deserialize_with`](https://serde.rs/field-attrs.html#deserialize_with)
2029/// field attribute.
2030///
2031pub fn deserialize_as_i64_or_none<'de, D>(deserializer: D) -> Result<Option<i64>, D::Error>
2032where
2033 D: Deserializer<'de>,
2034{
2035 let data = Data::deserialize(deserializer)?;
2036 Ok(data.as_i64())
2037}
2038
2039/// A helper function to deserialize cell values as `i64`.
2040///
2041/// This is useful when cells may also contain invalid values (i.e. strings). It
2042/// applies the [`as_i64`](crate::datatype::DataType::as_i64) method to the cell
2043/// value, and returns `Ok(Ok(value_as_i64))` if successful or
2044/// `Ok(Err(value_to_string))` if unsuccessful, therefore never failing.
2045///
2046/// This function is intended to be used with Serde's
2047/// [`deserialize_with`](https://serde.rs/field-attrs.html#deserialize_with)
2048/// field attribute.
2049///
2050pub fn deserialize_as_i64_or_string<'de, D>(
2051 deserializer: D,
2052) -> Result<Result<i64, String>, D::Error>
2053where
2054 D: Deserializer<'de>,
2055{
2056 let data = Data::deserialize(deserializer)?;
2057 Ok(data.as_i64().ok_or_else(|| data.to_string()))
2058}
2059
2060/// A helper function to deserialize cell values as `f64`.
2061///
2062/// This is useful when cells may also contain invalid values (i.e. strings). It
2063/// applies the [`as_f64`](crate::datatype::DataType::as_f64) method to the cell
2064/// value, and returns `Ok(Some(value_as_f64))` if successful or `Ok(None)` if
2065/// unsuccessful, therefore never failing.
2066///
2067/// This function is intended to be used with Serde's
2068/// [`deserialize_with`](https://serde.rs/field-attrs.html#deserialize_with)
2069/// field attribute.
2070///
2071pub fn deserialize_as_f64_or_none<'de, D>(deserializer: D) -> Result<Option<f64>, D::Error>
2072where
2073 D: Deserializer<'de>,
2074{
2075 let data = Data::deserialize(deserializer)?;
2076 Ok(data.as_f64())
2077}
2078
2079/// A helper function to deserialize cell values as `f64`.
2080///
2081/// This is useful when cells may also contain invalid values (i.e. strings). It
2082/// applies the [`as_f64`](crate::datatype::DataType::as_f64) method to the cell
2083/// value, and returns `Ok(Ok(value_as_f64))` if successful or
2084/// `Ok(Err(value_to_string))` if unsuccessful, therefore never failing.
2085///
2086/// This function is intended to be used with Serde's
2087/// [`deserialize_with`](https://serde.rs/field-attrs.html#deserialize_with)
2088/// field attribute.
2089///
2090pub fn deserialize_as_f64_or_string<'de, D>(
2091 deserializer: D,
2092) -> Result<Result<f64, String>, D::Error>
2093where
2094 D: Deserializer<'de>,
2095{
2096 let data = Data::deserialize(deserializer)?;
2097 Ok(data.as_f64().ok_or_else(|| data.to_string()))
2098}
2099
2100/// A helper function to deserialize cell values as [`chrono::NaiveDate`].
2101///
2102/// This is useful when cells may also contain invalid values (i.e. strings). It
2103/// applies the [`as_date()`](crate::Data::as_date) method to the cell value,
2104/// and returns `Ok(Some(value_as_date))` if successful or `Ok(None)` if
2105/// unsuccessful, therefore never failing.
2106///
2107/// This function is intended to be used with Serde's
2108/// [`deserialize_with`](https://serde.rs/field-attrs.html#deserialize_with)
2109/// field attribute.
2110///
2111/// [`chrono::NaiveDate`]: https://docs.rs/chrono/latest/chrono/naive/struct.NaiveDate.html
2112///
2113#[cfg(feature = "chrono")]
2114#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
2115pub fn deserialize_as_date_or_none<'de, D>(
2116 deserializer: D,
2117) -> Result<Option<chrono::NaiveDate>, D::Error>
2118where
2119 D: Deserializer<'de>,
2120{
2121 let data = Data::deserialize(deserializer)?;
2122 Ok(data.as_date())
2123}
2124
2125/// A helper function to deserialize cell values as [`chrono::NaiveDate`].
2126///
2127/// This is useful when cells may also contain invalid values (i.e. strings). It
2128/// applies the [`as_date()`](crate::Data::as_date) method to the cell value,
2129/// and returns `Ok(Ok(value_as_date))` if successful or
2130/// `Ok(Err(value_to_string))` if unsuccessful, therefore never failing.
2131///
2132/// This function is intended to be used with Serde's
2133/// [`deserialize_with`](https://serde.rs/field-attrs.html#deserialize_with)
2134/// field attribute.
2135///
2136/// [`chrono::NaiveDate`]: https://docs.rs/chrono/latest/chrono/naive/struct.NaiveDate.html
2137///
2138#[cfg(feature = "chrono")]
2139#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
2140pub fn deserialize_as_date_or_string<'de, D>(
2141 deserializer: D,
2142) -> Result<Result<chrono::NaiveDate, String>, D::Error>
2143where
2144 D: Deserializer<'de>,
2145{
2146 let data = Data::deserialize(deserializer)?;
2147 Ok(data.as_date().ok_or_else(|| data.to_string()))
2148}
2149
2150/// A helper function to deserialize cell values as [`chrono::NaiveTime`].
2151///
2152/// This is useful when cells may also contain invalid values (i.e. strings). It
2153/// applies the [`as_time()`](crate::Data::as_time) method to the cell value,
2154/// and returns `Ok(Some(value_as_time))` if successful or `Ok(None)` if
2155/// unsuccessful, therefore never failing.
2156///
2157/// This function is intended to be used with Serde's
2158/// [`deserialize_with`](https://serde.rs/field-attrs.html#deserialize_with)
2159/// field attribute.
2160///
2161/// [`chrono::NaiveTime`]:
2162/// https://docs.rs/chrono/latest/chrono/naive/struct.NaiveTime.html
2163///
2164#[cfg(feature = "chrono")]
2165#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
2166pub fn deserialize_as_time_or_none<'de, D>(
2167 deserializer: D,
2168) -> Result<Option<chrono::NaiveTime>, D::Error>
2169where
2170 D: Deserializer<'de>,
2171{
2172 let data = Data::deserialize(deserializer)?;
2173 Ok(data.as_time())
2174}
2175
2176/// A helper function to deserialize cell values as [`chrono::NaiveTime`].
2177///
2178/// This is useful when cells may also contain invalid values (i.e. strings). It
2179/// applies the [`as_time()`](crate::Data::as_time) method to the cell value,
2180/// and returns `Ok(Ok(value_as_time))` if successful or
2181/// `Ok(Err(value_to_string))` if unsuccessful, therefore never failing.
2182///
2183/// This function is intended to be used with Serde's
2184/// [`deserialize_with`](https://serde.rs/field-attrs.html#deserialize_with)
2185/// field attribute.
2186///
2187/// [`chrono::NaiveTime`]:
2188/// https://docs.rs/chrono/latest/chrono/naive/struct.NaiveTime.html
2189///
2190#[cfg(feature = "chrono")]
2191#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
2192pub fn deserialize_as_time_or_string<'de, D>(
2193 deserializer: D,
2194) -> Result<Result<chrono::NaiveTime, String>, D::Error>
2195where
2196 D: Deserializer<'de>,
2197{
2198 let data = Data::deserialize(deserializer)?;
2199 Ok(data.as_time().ok_or_else(|| data.to_string()))
2200}
2201
2202/// A helper function to deserialize cell values as [`chrono::Duration`].
2203///
2204/// This is useful when cells may also contain invalid values (i.e. strings). It
2205/// applies the [`as_duration()`](crate::Data::as_duration) method to the cell
2206/// value, and returns `Ok(Some(value_as_duration))` if successful or `Ok(None)`
2207/// if unsuccessful, therefore never failing.
2208///
2209/// This function is intended to be used with Serde's
2210/// [`deserialize_with`](https://serde.rs/field-attrs.html#deserialize_with)
2211/// field attribute.
2212///
2213/// [`chrono::Duration`]:
2214/// https://docs.rs/chrono/latest/chrono/struct.Duration.html
2215///
2216#[cfg(feature = "chrono")]
2217#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
2218pub fn deserialize_as_duration_or_none<'de, D>(
2219 deserializer: D,
2220) -> Result<Option<chrono::Duration>, D::Error>
2221where
2222 D: Deserializer<'de>,
2223{
2224 let data = Data::deserialize(deserializer)?;
2225 Ok(data.as_duration())
2226}
2227
2228/// A helper function to deserialize cell values as [`chrono::Duration`].
2229///
2230/// This is useful when cells may also contain invalid values (i.e. strings). It
2231/// applies the [`as_duration()`](crate::Data::as_duration) method to the cell
2232/// value, and returns `Ok(Ok(value_as_duration))` if successful or
2233/// `Ok(Err(value_to_string))` if unsuccessful, therefore never failing.
2234///
2235/// This function is intended to be used with Serde's
2236/// [`deserialize_with`](https://serde.rs/field-attrs.html#deserialize_with)
2237/// field attribute.
2238///
2239/// [`chrono::Duration`]:
2240/// https://docs.rs/chrono/latest/chrono/struct.Duration.html
2241///
2242#[cfg(feature = "chrono")]
2243#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
2244pub fn deserialize_as_duration_or_string<'de, D>(
2245 deserializer: D,
2246) -> Result<Result<chrono::Duration, String>, D::Error>
2247where
2248 D: Deserializer<'de>,
2249{
2250 let data = Data::deserialize(deserializer)?;
2251 Ok(data.as_duration().ok_or_else(|| data.to_string()))
2252}
2253
2254/// A helper function to deserialize cell values as [`chrono::NaiveDateTime`].
2255///
2256/// This is useful when cells may also contain invalid values (i.e. strings). It
2257/// applies the [`as_datetime()`](crate::Data::as_datetime) method to the cell
2258/// value, and returns `Ok(Some(value_as_datetime))` if successful or `Ok(None)`
2259/// if unsuccessful, therefore never failing.
2260///
2261/// This function is intended to be used with Serde's
2262/// [`deserialize_with`](https://serde.rs/field-attrs.html#deserialize_with)
2263/// field attribute.
2264///
2265/// [`chrono::NaiveDateTime`]:
2266/// https://docs.rs/chrono/latest/chrono/naive/struct.NaiveDateTime.html
2267///
2268#[cfg(feature = "chrono")]
2269#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
2270pub fn deserialize_as_datetime_or_none<'de, D>(
2271 deserializer: D,
2272) -> Result<Option<chrono::NaiveDateTime>, D::Error>
2273where
2274 D: Deserializer<'de>,
2275{
2276 let data = Data::deserialize(deserializer)?;
2277 Ok(data.as_datetime())
2278}
2279
2280/// A helper function to deserialize cell values as [`chrono::NaiveDateTime`].
2281///
2282/// This is useful when cells may also contain invalid values (i.e. strings). It
2283/// applies the [`as_datetime()`](crate::Data::as_datetime) method to the cell
2284/// value, and returns `Ok(Ok(value_as_datetime))` if successful or
2285/// `Ok(Err(value_to_string))` if unsuccessful, therefore never failing.
2286///
2287/// This function is intended to be used with Serde's
2288/// [`deserialize_with`](https://serde.rs/field-attrs.html#deserialize_with)
2289/// field attribute.
2290///
2291/// [`chrono::NaiveDateTime`]:
2292/// https://docs.rs/chrono/latest/chrono/naive/struct.NaiveDateTime.html
2293///
2294#[cfg(feature = "chrono")]
2295#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
2296pub fn deserialize_as_datetime_or_string<'de, D>(
2297 deserializer: D,
2298) -> Result<Result<chrono::NaiveDateTime, String>, D::Error>
2299where
2300 D: Deserializer<'de>,
2301{
2302 let data = Data::deserialize(deserializer)?;
2303 Ok(data.as_datetime().ok_or_else(|| data.to_string()))
2304}