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