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