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