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