spreadsheet_ods/
sheet_.rs

1//!
2//! One sheet of the spreadsheet.
3//!
4
5use get_size2::GetSize;
6use std::collections::{BTreeMap, Bound};
7use std::fmt::{Debug, Display, Formatter};
8use std::iter::FusedIterator;
9use std::ops::RangeBounds;
10use std::{fmt, mem};
11
12use crate::cell_::{CellContent, CellContentRef, CellData};
13use crate::draw::{Annotation, DrawFrame};
14use crate::style::{ColStyleRef, RowStyleRef, TableStyleRef};
15use crate::validation::ValidationRef;
16use crate::value_::Value;
17use crate::xmltree::XmlTag;
18use crate::{CellRange, CellStyleRef, Length, OdsError};
19
20#[cfg(test)]
21mod tests;
22
23/// Visibility of a column or row.
24#[derive(Debug, Clone, Copy, Eq, PartialEq, Default, GetSize)]
25#[allow(missing_docs)]
26pub enum Visibility {
27    #[default]
28    Visible,
29    Collapsed,
30    Filtered,
31}
32
33impl Display for Visibility {
34    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
35        match self {
36            Visibility::Visible => write!(f, "visible"),
37            Visibility::Collapsed => write!(f, "collapse"),
38            Visibility::Filtered => write!(f, "filter"),
39        }
40    }
41}
42
43/// Row data
44#[derive(Debug, Clone, GetSize)]
45pub(crate) struct RowHeader {
46    pub(crate) style: Option<RowStyleRef>,
47    pub(crate) cellstyle: Option<CellStyleRef>,
48    pub(crate) visible: Visibility,
49    /// Value of the table:number-rows-repeated.
50    ///
51    /// This value is moved to span if use_repeat_for_cells is not set.
52    /// This way a programmatic set_repeat() is possible without cloning
53    /// all the row-data. When writing the necessary data is found via
54    /// the range row..row+span and doesn't interfere with any calculated
55    /// repeat-values.
56    pub(crate) repeat: u32,
57    /// Logical valid range for all the header values. Avoids duplication
58    /// on reading.
59    pub(crate) span: u32,
60    pub(crate) height: Length,
61}
62
63impl Default for RowHeader {
64    fn default() -> Self {
65        Self {
66            style: None,
67            cellstyle: None,
68            visible: Default::default(),
69            repeat: 1,
70            span: 1,
71            height: Default::default(),
72        }
73    }
74}
75
76/// Column data
77#[derive(Debug, Clone, GetSize)]
78pub(crate) struct ColHeader {
79    pub(crate) style: Option<ColStyleRef>,
80    pub(crate) cellstyle: Option<CellStyleRef>,
81    pub(crate) visible: Visibility,
82    pub(crate) width: Length,
83    /// Logical valid range for all the header values. Avoids duplication
84    /// on reading.
85    pub(crate) span: u32,
86}
87
88impl Default for ColHeader {
89    fn default() -> Self {
90        Self {
91            style: None,
92            cellstyle: None,
93            visible: Default::default(),
94            width: Default::default(),
95            span: 1,
96        }
97    }
98}
99
100/// One sheet of the spreadsheet.
101///
102/// Contains the data and the style-references. The can also be
103/// styles on the whole sheet, columns and rows. The more complicated
104/// grouping tags are not covered.
105#[derive(Clone, Default, GetSize)]
106pub struct Sheet {
107    pub(crate) name: String,
108    pub(crate) style: Option<TableStyleRef>,
109
110    pub(crate) data: BTreeMap<(u32, u32), CellData>,
111
112    pub(crate) col_header: BTreeMap<u32, ColHeader>,
113    pub(crate) row_header: BTreeMap<u32, RowHeader>,
114
115    pub(crate) display: bool,
116    pub(crate) print: bool,
117
118    pub(crate) header_rows: Option<Header>,
119    pub(crate) header_cols: Option<Header>,
120    pub(crate) print_ranges: Option<Vec<CellRange>>,
121
122    pub(crate) group_rows: Vec<Grouped>,
123    pub(crate) group_cols: Vec<Grouped>,
124
125    pub(crate) sheet_config: SheetConfig,
126
127    pub(crate) extra: Vec<XmlTag>,
128}
129
130impl<'a> IntoIterator for &'a Sheet {
131    type Item = ((u32, u32), CellContentRef<'a>);
132    type IntoIter = CellIter<'a>;
133
134    fn into_iter(self) -> Self::IntoIter {
135        CellIter {
136            iter: self.data.iter(),
137            k_data: None,
138            v_data: None,
139        }
140    }
141}
142
143/// Iterator over cells.
144#[derive(Debug)]
145pub(crate) struct CellDataIter<'a> {
146    iter: std::collections::btree_map::Range<'a, (u32, u32), CellData>,
147    k_data: Option<&'a (u32, u32)>,
148    v_data: Option<&'a CellData>,
149}
150
151impl<'a> CellDataIter<'a> {
152    pub(crate) fn new(iter: std::collections::btree_map::Range<'a, (u32, u32), CellData>) -> Self {
153        Self {
154            iter,
155            k_data: None,
156            v_data: None,
157        }
158    }
159
160    /// Returns the (row,col) of the next cell.
161    #[allow(dead_code)]
162    pub(crate) fn peek_cell(&mut self) -> Option<(u32, u32)> {
163        self.k_data.copied()
164    }
165
166    fn load_next_data(&mut self) {
167        if let Some((k, v)) = self.iter.next() {
168            self.k_data = Some(k);
169            self.v_data = Some(v);
170        } else {
171            self.k_data = None;
172            self.v_data = None;
173        }
174    }
175}
176
177impl FusedIterator for CellDataIter<'_> {}
178
179impl<'a> Iterator for CellDataIter<'a> {
180    type Item = ((u32, u32), &'a CellData);
181
182    fn next(&mut self) -> Option<Self::Item> {
183        if self.k_data.is_none() {
184            self.load_next_data();
185        }
186
187        if let Some(k_data) = self.k_data {
188            if let Some(v_data) = self.v_data {
189                let r = Some((*k_data, v_data));
190                self.load_next_data();
191                r
192            } else {
193                None
194            }
195        } else {
196            None
197        }
198    }
199
200    fn size_hint(&self) -> (usize, Option<usize>) {
201        self.iter.size_hint()
202    }
203}
204
205/// Iterator over cells.
206#[derive(Debug)]
207pub(crate) struct CellDataIterMut<'a> {
208    iter: std::collections::btree_map::RangeMut<'a, (u32, u32), CellData>,
209    k_data: Option<&'a (u32, u32)>,
210    v_data: Option<&'a mut CellData>,
211}
212
213impl<'a> CellDataIterMut<'a> {
214    pub(crate) fn new(
215        iter: std::collections::btree_map::RangeMut<'a, (u32, u32), CellData>,
216    ) -> Self {
217        Self {
218            iter,
219            k_data: None,
220            v_data: None,
221        }
222    }
223
224    /// Returns the (row,col) of the next cell.
225    pub(crate) fn peek_cell(&mut self) -> Option<(u32, u32)> {
226        self.k_data.copied()
227    }
228
229    fn load_next_data(&mut self) {
230        if let Some((k, v)) = self.iter.next() {
231            self.k_data = Some(k);
232            self.v_data = Some(v);
233        } else {
234            self.k_data = None;
235            self.v_data = None;
236        }
237    }
238}
239
240impl FusedIterator for CellDataIterMut<'_> {}
241
242impl<'a> Iterator for CellDataIterMut<'a> {
243    type Item = ((u32, u32), &'a mut CellData);
244
245    fn next(&mut self) -> Option<Self::Item> {
246        if self.k_data.is_none() {
247            self.load_next_data();
248        }
249
250        if let Some(k_data) = self.k_data {
251            if let Some(v_data) = self.v_data.take() {
252                let r = Some((*k_data, v_data));
253                self.load_next_data();
254                r
255            } else {
256                None
257            }
258        } else {
259            None
260        }
261    }
262
263    fn size_hint(&self) -> (usize, Option<usize>) {
264        self.iter.size_hint()
265    }
266}
267
268/// Iterator over cells.
269#[derive(Clone, Debug)]
270pub struct CellIter<'a> {
271    iter: std::collections::btree_map::Iter<'a, (u32, u32), CellData>,
272    k_data: Option<&'a (u32, u32)>,
273    v_data: Option<&'a CellData>,
274}
275
276impl CellIter<'_> {
277    /// Returns the (row,col) of the next cell.
278    pub fn peek_cell(&mut self) -> Option<(u32, u32)> {
279        self.k_data.copied()
280    }
281
282    fn load_next_data(&mut self) {
283        if let Some((k, v)) = self.iter.next() {
284            self.k_data = Some(k);
285            self.v_data = Some(v);
286        } else {
287            self.k_data = None;
288            self.v_data = None;
289        }
290    }
291}
292
293impl FusedIterator for CellIter<'_> {}
294
295impl<'a> Iterator for CellIter<'a> {
296    type Item = ((u32, u32), CellContentRef<'a>);
297
298    fn next(&mut self) -> Option<Self::Item> {
299        if self.k_data.is_none() {
300            self.load_next_data();
301        }
302
303        if let Some(k_data) = self.k_data {
304            if let Some(v_data) = self.v_data {
305                let r = Some((*k_data, v_data.cell_content_ref()));
306                self.load_next_data();
307                r
308            } else {
309                None
310            }
311        } else {
312            None
313        }
314    }
315
316    fn size_hint(&self) -> (usize, Option<usize>) {
317        self.iter.size_hint()
318    }
319}
320
321struct IterRows<'a> {
322    iter: std::collections::btree_map::Range<'a, (u32, u32), CellData>,
323    start: (u32, u32),
324    end: (u32, u32),
325    hint: usize,
326}
327
328impl<'a> IterRows<'a> {
329    fn new<R: RangeBounds<(u32, u32)>>(sheet: &'a Sheet, range: R) -> Self {
330        let start = match range.start_bound() {
331            Bound::Included((r, c)) => (*r, *c),
332            Bound::Excluded((r, c)) => (r + 1, c + 1),
333            Bound::Unbounded => (0, 0),
334        };
335        let end = match range.end_bound() {
336            Bound::Included((r, c)) => (r + 1, c + 1),
337            Bound::Excluded((r, c)) => (*r, *c),
338            Bound::Unbounded => sheet.used_grid_size(),
339        };
340
341        Self {
342            iter: sheet.data.range(range),
343            start,
344            end,
345            hint: (end.0 - start.0) as usize * (end.1 * start.1) as usize,
346        }
347    }
348}
349
350impl FusedIterator for IterRows<'_> {}
351
352impl<'a> Iterator for IterRows<'a> {
353    type Item = ((u32, u32), CellContentRef<'a>);
354
355    fn next(&mut self) -> Option<Self::Item> {
356        loop {
357            if let Some(((r, c), d)) = self.iter.next() {
358                if *r < self.end.0 && *c >= self.start.1 && *c < self.end.1 {
359                    return Some(((*r, *c), d.cell_content_ref()));
360                }
361            } else {
362                return None;
363            }
364        }
365    }
366
367    fn size_hint(&self) -> (usize, Option<usize>) {
368        (0, Some(self.hint))
369    }
370}
371
372struct IterCols<'a> {
373    sheet: &'a Sheet,
374    start: (u32, u32),
375    end: (u32, u32),
376    cell: (u32, u32),
377}
378
379impl Debug for IterCols<'_> {
380    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
381        f.debug_struct("IterCols")
382            .field("start", &self.start)
383            .field("end", &self.end)
384            .field("cell", &self.cell)
385            .finish()
386    }
387}
388
389impl FusedIterator for IterCols<'_> {}
390
391impl<'a> IterCols<'a> {
392    fn new<R: RangeBounds<(u32, u32)>>(sheet: &'a Sheet, range: R) -> Self {
393        let start = match range.start_bound() {
394            Bound::Included((r, c)) => (*r, *c),
395            Bound::Excluded((r, c)) => (r + 1, c + 1),
396            Bound::Unbounded => (0, 0),
397        };
398        let end = match range.end_bound() {
399            Bound::Included((r, c)) => (r + 1, c + 1),
400            Bound::Excluded((r, c)) => (*r, *c),
401            Bound::Unbounded => sheet.used_grid_size(),
402        };
403
404        Self {
405            sheet,
406            start,
407            end,
408            cell: start,
409        }
410    }
411}
412
413impl<'a> Iterator for IterCols<'a> {
414    type Item = ((u32, u32), CellContentRef<'a>);
415
416    #[allow(clippy::comparison_chain)]
417    fn next(&mut self) -> Option<Self::Item> {
418        if self.cell.0 == self.end.0 && self.cell.1 == self.end.1 {
419            return None;
420        }
421
422        loop {
423            let r = self.cell.0;
424            let c = self.cell.1;
425            let d = self.sheet.cell_ref(self.cell.0, self.cell.1);
426
427            if self.cell.0 + 1 < self.end.0 {
428                self.cell.0 += 1;
429            } else if self.cell.0 + 1 == self.end.0 {
430                if self.cell.1 + 1 < self.end.1 {
431                    self.cell.0 = self.start.0;
432                    self.cell.1 += 1;
433                } else if self.cell.1 + 1 == self.end.1 {
434                    self.cell.0 += 1;
435                    self.cell.1 += 1;
436                } else {
437                    assert_eq!(self.cell, self.end);
438                }
439            } else {
440                assert_eq!(self.cell, self.end);
441            }
442
443            if let Some(d) = d {
444                return Some(((r, c), d));
445            }
446        }
447    }
448
449    fn size_hint(&self) -> (usize, Option<usize>) {
450        (
451            0,
452            Some((self.end.0 - self.start.0) as usize * (self.end.1 - self.start.1) as usize),
453        )
454    }
455}
456
457/// Range iterator.
458#[derive(Clone, Debug)]
459pub struct Range<'a> {
460    range: std::collections::btree_map::Range<'a, (u32, u32), CellData>,
461}
462
463impl FusedIterator for Range<'_> {}
464
465impl<'a> Iterator for Range<'a> {
466    type Item = ((u32, u32), CellContentRef<'a>);
467
468    fn next(&mut self) -> Option<Self::Item> {
469        if let Some((k, v)) = self.range.next() {
470            Some((*k, v.cell_content_ref()))
471        } else {
472            None
473        }
474    }
475
476    fn size_hint(&self) -> (usize, Option<usize>) {
477        self.range.size_hint()
478    }
479}
480
481impl DoubleEndedIterator for Range<'_> {
482    fn next_back(&mut self) -> Option<Self::Item> {
483        if let Some((k, v)) = self.range.next_back() {
484            Some((*k, v.cell_content_ref()))
485        } else {
486            None
487        }
488    }
489}
490
491impl ExactSizeIterator for Range<'_> {}
492
493impl Debug for Sheet {
494    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
495        writeln!(f, "name {:?} style {:?}", self.name, self.style)?;
496        for (k, v) in self.data.iter() {
497            writeln!(f, "  data {:?} {:?}", k, v)?;
498        }
499        for (k, v) in &self.col_header {
500            writeln!(f, "{:?} {:?}", k, v)?;
501        }
502        for (k, v) in &self.row_header {
503            writeln!(f, "{:?} {:?}", k, v)?;
504        }
505        if let Some(header_rows) = &self.header_rows {
506            writeln!(f, "header rows {:?}", header_rows)?;
507        }
508        if let Some(header_cols) = &self.header_cols {
509            writeln!(f, "header cols {:?}", header_cols)?;
510        }
511        for v in &self.group_cols {
512            writeln!(f, "group cols {:?}", v)?;
513        }
514        for v in &self.group_rows {
515            writeln!(f, "group rows {:?}", v)?;
516        }
517        for xtr in &self.extra {
518            writeln!(f, "extras {:?}", xtr)?;
519        }
520        Ok(())
521    }
522}
523
524impl Sheet {
525    /// Create an empty sheet.
526    #[deprecated]
527    pub fn new_with_name<S: Into<String>>(name: S) -> Self {
528        Self::new(name)
529    }
530
531    /// Create an empty sheet.
532    ///
533    /// The name is shown as the tab-title, but also as a reference for
534    /// this sheet in formulas and sheet-metadata. Giving an empty string
535    /// here is allowed and a name will be generated, when the document is
536    /// opened. But any metadata will not be applied.
537    ///
538    /// Renaming the sheet works for metadata, but formulas will not be fixed.  
539    ///
540    pub fn new<S: Into<String>>(name: S) -> Self {
541        Sheet {
542            name: name.into(),
543            data: BTreeMap::new(),
544            col_header: Default::default(),
545            style: None,
546            header_rows: None,
547            header_cols: None,
548            print_ranges: None,
549            group_rows: Default::default(),
550            group_cols: Default::default(),
551            sheet_config: Default::default(),
552            extra: vec![],
553            row_header: Default::default(),
554            display: true,
555            print: true,
556        }
557    }
558
559    /// Copy all the attributes but not the actual data.
560    pub fn clone_no_data(&self) -> Self {
561        Self {
562            name: self.name.clone(),
563            style: self.style.clone(),
564            data: Default::default(),
565            col_header: self.col_header.clone(),
566            row_header: self.row_header.clone(),
567            display: self.display,
568            print: self.print,
569            header_rows: self.header_rows,
570            header_cols: self.header_cols,
571            print_ranges: self.print_ranges.clone(),
572            group_rows: self.group_rows.clone(),
573            group_cols: self.group_cols.clone(),
574            sheet_config: Default::default(),
575            extra: self.extra.clone(),
576        }
577    }
578
579    /// Iterate all cells.
580    pub fn iter(&self) -> CellIter<'_> {
581        self.into_iter()
582    }
583
584    /// Count all cells with any data.
585    pub fn cell_count(&self) -> usize {
586        self.data.len()
587    }
588
589    /// Iterate the range row-wise.
590    ///
591    /// If there is no upper bound this uses used_grid_size(), which
592    /// does an extra full iteration to find the bounds.
593    pub fn iter_rows<R: RangeBounds<(u32, u32)>>(
594        &self,
595        range: R,
596    ) -> impl Iterator<Item = ((u32, u32), CellContentRef<'_>)> {
597        IterRows::new(self, range)
598    }
599
600    /// Iterate the range column-wise.
601    ///
602    /// If there is no upper bound this uses used_grid_size(), which
603    /// does an extra full iteration to find the bounds.
604    pub fn iter_cols<R: RangeBounds<(u32, u32)>>(
605        &self,
606        range: R,
607    ) -> impl Iterator<Item = ((u32, u32), CellContentRef<'_>)> {
608        IterCols::new(self, range)
609    }
610
611    /// Iterate a range of cells in lexical order.
612    pub fn range<R: RangeBounds<(u32, u32)>>(
613        &self,
614        range: R,
615    ) -> impl Iterator<Item = ((u32, u32), CellContentRef<'_>)> {
616        Range {
617            range: self.data.range(range),
618        }
619    }
620
621    /// Sheet name.
622    pub fn set_name<V: Into<String>>(&mut self, name: V) {
623        self.name = name.into();
624    }
625
626    /// Sheet name.
627    pub fn name(&self) -> &String {
628        &self.name
629    }
630
631    /// Configuration for the sheet.
632    pub fn config(&self) -> &SheetConfig {
633        &self.sheet_config
634    }
635
636    /// Configuration for the sheet.
637    pub fn config_mut(&mut self) -> &mut SheetConfig {
638        &mut self.sheet_config
639    }
640
641    /// Sets the table-style
642    pub fn set_style(&mut self, style: &TableStyleRef) {
643        self.style = Some(style.clone())
644    }
645
646    /// Returns the table-style.
647    pub fn style(&self) -> Option<&TableStyleRef> {
648        self.style.as_ref()
649    }
650
651    // find the col-header with the correct data.
652    pub(crate) fn valid_col_header(&self, col: u32) -> Option<&ColHeader> {
653        if let Some((base_col, col_header)) = self.col_header.range(..=col).last() {
654            if (*base_col..*base_col + col_header.span).contains(&col) {
655                Some(col_header)
656            } else {
657                None
658            }
659        } else {
660            None
661        }
662    }
663
664    // find the col-header with the correct data and do a three-way-split
665    // to allow setting a value for a single col.
666    // Create the col-header if necessary.
667    #[allow(clippy::comparison_chain)]
668    fn create_split_col_header(&mut self, col: u32) -> &mut ColHeader {
669        // not already split up.
670        if self.col_header.get(&col).filter(|v| v.span == 1).is_none() {
671            let mut col_col = None;
672            let mut left_hdr = None;
673            let mut split_hdr = None;
674            let mut right_hdr = None;
675
676            for (base_col, col_header) in &self.col_header {
677                if col >= *base_col && col < base_col + col_header.span {
678                    // correct one.
679                    col_col = Some(*base_col);
680
681                    // now split three-ways: base_col..col | col | col + 1..base_col+base_span
682                    let left_span = col - *base_col;
683                    if left_span > 0 {
684                        let mut tmp = col_header.clone();
685                        tmp.span = left_span;
686                        left_hdr = Some((*base_col, tmp));
687                    }
688
689                    split_hdr = Some((col, col_header.clone()));
690
691                    let right_span = (*base_col + col_header.span) - (col + 1);
692                    if right_span > 0 {
693                        let mut tmp = col_header.clone();
694                        tmp.span = right_span;
695                        right_hdr = Some((col + 1, tmp));
696                    }
697
698                    break;
699                }
700            }
701
702            if let Some(col_col) = col_col {
703                // found
704                self.col_header.remove(&col_col);
705
706                if let Some(left_hdr) = left_hdr {
707                    self.col_header.insert(left_hdr.0, left_hdr.1);
708                }
709                if let Some(split_hdr) = split_hdr {
710                    self.col_header.insert(split_hdr.0, split_hdr.1);
711                }
712                if let Some(right_hdr) = right_hdr {
713                    self.col_header.insert(right_hdr.0, right_hdr.1);
714                }
715            } else {
716                // not found
717                self.col_header.insert(col, ColHeader::default());
718            }
719        } else {
720            // found with span==1
721        }
722
723        self.col_header.get_mut(&col).expect("col-header")
724    }
725
726    /// Column style.
727    pub fn set_colstyle(&mut self, col: u32, style: &ColStyleRef) {
728        self.create_split_col_header(col).style = Some(style.clone());
729    }
730
731    /// Remove the style.
732    pub fn clear_colstyle(&mut self, col: u32) {
733        self.create_split_col_header(col).style = None;
734    }
735
736    /// Returns the column style.
737    pub fn colstyle(&self, col: u32) -> Option<&ColStyleRef> {
738        if let Some(col_header) = self.valid_col_header(col) {
739            col_header.style.as_ref()
740        } else {
741            None
742        }
743    }
744
745    /// Default cell style for this column.
746    pub fn set_col_cellstyle(&mut self, col: u32, style: &CellStyleRef) {
747        self.create_split_col_header(col).cellstyle = Some(style.clone());
748    }
749
750    /// Remove the style.
751    pub fn clear_col_cellstyle(&mut self, col: u32) {
752        self.create_split_col_header(col).cellstyle = None;
753    }
754
755    /// Returns the default cell style for this column.
756    pub fn col_cellstyle(&self, col: u32) -> Option<&CellStyleRef> {
757        if let Some(col_header) = self.valid_col_header(col) {
758            col_header.cellstyle.as_ref()
759        } else {
760            None
761        }
762    }
763
764    /// Visibility of the column
765    pub fn set_col_visible(&mut self, col: u32, visible: Visibility) {
766        self.create_split_col_header(col).visible = visible;
767    }
768
769    /// Returns the default cell style for this column.
770    pub fn col_visible(&self, col: u32) -> Visibility {
771        if let Some(col_header) = self.valid_col_header(col) {
772            col_header.visible
773        } else {
774            Default::default()
775        }
776    }
777
778    /// unstable internal method
779    pub fn _set_col_header_span(&mut self, col: u32, span: u32) {
780        self.create_split_col_header(col).span = span
781    }
782
783    /// unstable internal method
784    pub fn _col_header_span(&self, col: u32) -> u32 {
785        if let Some(col_header) = self.valid_col_header(col) {
786            col_header.span
787        } else {
788            Default::default()
789        }
790    }
791
792    /// Sets the column width for this column.
793    pub fn set_col_width(&mut self, col: u32, width: Length) {
794        self.create_split_col_header(col).width = width;
795    }
796
797    /// Returns the column-width.
798    pub fn col_width(&self, col: u32) -> Length {
799        if let Some(ch) = self.valid_col_header(col) {
800            ch.width
801        } else {
802            Length::Default
803        }
804    }
805
806    // find the row-header with the correct data.
807    pub(crate) fn valid_row_header(&self, row: u32) -> Option<&RowHeader> {
808        if let Some((base_row, row_header)) = self.row_header.range(..=row).last() {
809            if (*base_row..*base_row + row_header.span).contains(&row) {
810                Some(row_header)
811            } else {
812                None
813            }
814        } else {
815            None
816        }
817    }
818
819    // find the row-header with the correct data and do a three-way-split
820    // to allow setting a value for a single row.
821    // Create the row-header if necessary.
822    #[allow(clippy::comparison_chain)]
823    fn create_split_row_header(&mut self, row: u32) -> &mut RowHeader {
824        let mut cloned = Vec::new();
825
826        if let Some((base_row, row_header)) = self.row_header.range_mut(..=row).last() {
827            if (*base_row..*base_row + row_header.span).contains(&row) {
828                let base_span = row_header.span;
829
830                // three-way split:
831                //      base_row .. row
832                //      row
833                //      row +1 .. base_row+span
834
835                // front + target
836                if *base_row < row {
837                    row_header.span = row - *base_row;
838
839                    let mut clone = row_header.clone();
840                    clone.span = 1;
841                    cloned.push((row, clone));
842                } else if *base_row == row {
843                    row_header.span = 1;
844                } else {
845                    unreachable!();
846                }
847
848                // back
849                if *base_row + base_span > row {
850                    let mut clone = row_header.clone();
851                    clone.span = *base_row + base_span - (row + 1);
852                    cloned.push((row + 1, clone));
853                } else if *base_row + base_span == row {
854                    // noop
855                } else {
856                    unreachable!();
857                }
858            } else {
859                self.row_header.insert(row, RowHeader::default());
860            }
861        } else {
862            self.row_header.insert(row, RowHeader::default());
863        }
864
865        for (r, rh) in cloned {
866            self.row_header.insert(r, rh);
867        }
868
869        self.row_header.get_mut(&row).expect("row-header")
870    }
871
872    /// unstable internal method.
873    pub fn _row_header_span(&self, row: u32) -> Option<u32> {
874        self.row_header.get(&row).map(|v| v.span)
875    }
876
877    /// unstable internal method.
878    pub fn _set_row_header_span(&mut self, row: u32, span: u32) {
879        if let Some(row_header) = self.row_header.get_mut(&row) {
880            row_header.span = span;
881        }
882    }
883
884    /// Row style.
885    pub fn set_rowstyle(&mut self, row: u32, style: &RowStyleRef) {
886        self.create_split_row_header(row).style = Some(style.clone());
887    }
888
889    /// Remove the style.
890    pub fn clear_rowstyle(&mut self, row: u32) {
891        self.create_split_row_header(row).style = None;
892    }
893
894    /// Returns the row style.
895    pub fn rowstyle(&self, row: u32) -> Option<&RowStyleRef> {
896        if let Some(row_header) = self.valid_row_header(row) {
897            row_header.style.as_ref()
898        } else {
899            None
900        }
901    }
902
903    /// Default cell style for this row.
904    pub fn set_row_cellstyle(&mut self, row: u32, style: &CellStyleRef) {
905        self.create_split_row_header(row).cellstyle = Some(style.clone());
906    }
907
908    /// Remove the style.
909    pub fn clear_row_cellstyle(&mut self, row: u32) {
910        self.create_split_row_header(row).cellstyle = None;
911    }
912
913    /// Returns the default cell style for this row.
914    pub fn row_cellstyle(&self, row: u32) -> Option<&CellStyleRef> {
915        if let Some(row_header) = self.valid_row_header(row) {
916            row_header.cellstyle.as_ref()
917        } else {
918            None
919        }
920    }
921
922    /// Visibility of the row
923    pub fn set_row_visible(&mut self, row: u32, visible: Visibility) {
924        self.create_split_row_header(row).visible = visible;
925    }
926
927    /// Returns the default cell style for this row.
928    pub fn row_visible(&self, row: u32) -> Visibility {
929        if let Some(row_header) = self.valid_row_header(row) {
930            row_header.visible
931        } else {
932            Default::default()
933        }
934    }
935
936    /// Sets the repeat count for this row. Usually this is the last row
937    /// with data in a sheet. Setting the repeat count will not change
938    /// the row number of following rows. But they will be changed after
939    /// writing to an ODS file and reading it again.
940    ///
941    /// Panics
942    ///
943    /// Panics if the repeat is 0.
944    pub fn set_row_repeat(&mut self, row: u32, repeat: u32) {
945        assert!(repeat > 0);
946        self.create_split_row_header(row).repeat = repeat
947    }
948
949    /// Returns the repeat count for this row.
950    pub fn row_repeat(&self, row: u32) -> u32 {
951        if let Some(row_header) = self.valid_row_header(row) {
952            row_header.repeat
953        } else {
954            Default::default()
955        }
956    }
957
958    /// Sets the row-height.
959    pub fn set_row_height(&mut self, row: u32, height: Length) {
960        self.create_split_row_header(row).height = height;
961    }
962
963    /// Returns the row-height
964    pub fn row_height(&self, row: u32) -> Length {
965        if let Some(rh) = self.valid_row_header(row) {
966            rh.height
967        } else {
968            Length::Default
969        }
970    }
971
972    /// Returns the maximum used column in the column header.
973    pub fn _col_header_len(&self) -> usize {
974        self.col_header.len()
975    }
976
977    /// Returns the maximum used row in the row header.
978    pub fn _row_header_len(&self) -> usize {
979        self.row_header.len()
980    }
981
982    /// Returns the maximum used column in the column header.
983    pub fn col_header_max(&self) -> u32 {
984        *self.col_header.keys().max().unwrap_or(&0)
985    }
986
987    /// Returns the maximum used row in the row header.
988    pub fn row_header_max(&self) -> u32 {
989        *self.row_header.keys().max().unwrap_or(&0)
990    }
991
992    /// Returns a tuple of (max(row)+1, max(col)+1)
993    pub fn used_grid_size(&self) -> (u32, u32) {
994        let max = self.data.keys().fold((0, 0), |mut max, (r, c)| {
995            max.0 = u32::max(max.0, *r);
996            max.1 = u32::max(max.1, *c);
997            max
998        });
999
1000        (max.0 + 1, max.1 + 1)
1001    }
1002
1003    /// Is the sheet displayed?
1004    pub fn set_display(&mut self, display: bool) {
1005        self.display = display;
1006    }
1007
1008    /// Is the sheet displayed?
1009    pub fn display(&self) -> bool {
1010        self.display
1011    }
1012
1013    /// Is the sheet printed?
1014    pub fn set_print(&mut self, print: bool) {
1015        self.print = print;
1016    }
1017
1018    /// Is the sheet printed?
1019    pub fn print(&self) -> bool {
1020        self.print
1021    }
1022
1023    /// Returns true if there is no SCell at the given position.
1024    pub fn is_empty(&self, row: u32, col: u32) -> bool {
1025        !self.data.contains_key(&(row, col))
1026    }
1027
1028    /// Returns a clone of the cell content.
1029    pub fn cell(&self, row: u32, col: u32) -> Option<CellContent> {
1030        self.data
1031            .get(&(row, col))
1032            .map(CellData::cloned_cell_content)
1033    }
1034
1035    /// Returns references to the cell data.
1036    pub fn cell_ref(&self, row: u32, col: u32) -> Option<CellContentRef<'_>> {
1037        self.data.get(&(row, col)).map(CellData::cell_content_ref)
1038    }
1039
1040    /// Consumes the CellContent and sets the values.
1041    pub fn add_cell(&mut self, row: u32, col: u32, cell: CellContent) {
1042        self.add_cell_data(row, col, cell.into_celldata());
1043    }
1044
1045    /// Removes the cell and returns the values as CellContent.
1046    pub fn remove_cell(&mut self, row: u32, col: u32) -> Option<CellContent> {
1047        self.data
1048            .remove(&(row, col))
1049            .map(CellData::into_cell_content)
1050    }
1051
1052    /// Add a new cell. Main use is for reading the spreadsheet.
1053    pub(crate) fn add_cell_data(&mut self, row: u32, col: u32, cell: CellData) {
1054        self.data.insert((row, col), cell);
1055    }
1056
1057    /// Sets a value for the specified cell and provides a style at the same time.
1058    #[inline]
1059    pub fn set_styled<V: Into<Value>>(
1060        &mut self,
1061        row: u32,
1062        col: u32,
1063        value: V,
1064        style: &CellStyleRef,
1065    ) {
1066        self.set_styled_value(row, col, value, style)
1067    }
1068
1069    /// Sets a value for the specified cell. Creates a new cell if necessary.
1070    pub fn set_styled_value<V: Into<Value>>(
1071        &mut self,
1072        row: u32,
1073        col: u32,
1074        value: V,
1075        style: &CellStyleRef,
1076    ) {
1077        let cell = self.data.entry((row, col)).or_default();
1078        cell.value = value.into();
1079        cell.style = Some(style.clone());
1080    }
1081
1082    /// Sets a value for the specified cell. Creates a new cell if necessary.
1083    pub fn set_value<V: Into<Value>>(&mut self, row: u32, col: u32, value: V) {
1084        let cell = self.data.entry((row, col)).or_default();
1085        cell.value = value.into();
1086    }
1087
1088    /// Returns a value
1089    pub fn value(&self, row: u32, col: u32) -> &Value {
1090        if let Some(cell) = self.data.get(&(row, col)) {
1091            &cell.value
1092        } else {
1093            &Value::Empty
1094        }
1095    }
1096
1097    /// Sets a formula for the specified cell. Creates a new cell if necessary.
1098    pub fn set_formula<V: Into<String>>(&mut self, row: u32, col: u32, formula: V) {
1099        let cell = self.data.entry((row, col)).or_default();
1100        cell.formula = Some(formula.into());
1101    }
1102
1103    /// Removes the formula.
1104    pub fn clear_formula(&mut self, row: u32, col: u32) {
1105        if let Some(cell) = self.data.get_mut(&(row, col)) {
1106            cell.formula = None;
1107        }
1108    }
1109
1110    /// Returns a value
1111    pub fn formula(&self, row: u32, col: u32) -> Option<&String> {
1112        if let Some(c) = self.data.get(&(row, col)) {
1113            c.formula.as_ref()
1114        } else {
1115            None
1116        }
1117    }
1118
1119    /// Sets a repeat counter for the cell.
1120    pub fn set_cell_repeat(&mut self, row: u32, col: u32, repeat: u32) {
1121        let cell = self.data.entry((row, col)).or_default();
1122        cell.repeat = repeat;
1123    }
1124
1125    /// Returns the repeat counter for the cell within one row.
1126    pub fn cell_repeat(&self, row: u32, col: u32) -> u32 {
1127        if let Some(c) = self.data.get(&(row, col)) {
1128            c.repeat
1129        } else {
1130            1
1131        }
1132    }
1133
1134    /// Sets the cell-style for the specified cell. Creates a new cell if necessary.
1135    pub fn set_cellstyle(&mut self, row: u32, col: u32, style: &CellStyleRef) {
1136        let cell = self.data.entry((row, col)).or_default();
1137        cell.style = Some(style.clone());
1138    }
1139
1140    /// Removes the cell-style.
1141    pub fn clear_cellstyle(&mut self, row: u32, col: u32) {
1142        if let Some(cell) = self.data.get_mut(&(row, col)) {
1143            cell.style = None;
1144        }
1145    }
1146
1147    /// Returns a value
1148    pub fn cellstyle(&self, row: u32, col: u32) -> Option<&CellStyleRef> {
1149        if let Some(c) = self.data.get(&(row, col)) {
1150            c.style.as_ref()
1151        } else {
1152            None
1153        }
1154    }
1155
1156    /// Sets a content-validation for this cell.
1157    pub fn set_validation(&mut self, row: u32, col: u32, validation: &ValidationRef) {
1158        let cell = self.data.entry((row, col)).or_default();
1159        cell.extra_mut().validation_name = Some(validation.clone());
1160    }
1161
1162    /// Removes the cell-style.
1163    pub fn clear_validation(&mut self, row: u32, col: u32) {
1164        if let Some(cell) = self.data.get_mut(&(row, col)) {
1165            cell.extra_mut().validation_name = None;
1166        }
1167    }
1168
1169    /// Returns a content-validation name for this cell.
1170    pub fn validation(&self, row: u32, col: u32) -> Option<&ValidationRef> {
1171        if let Some(CellData { extra: Some(c), .. }) = self.data.get(&(row, col)) {
1172            c.validation_name.as_ref()
1173        } else {
1174            None
1175        }
1176    }
1177
1178    /// Sets the rowspan of the cell. Must be greater than 0.
1179    pub fn set_row_span(&mut self, row: u32, col: u32, span: u32) {
1180        let cell = self.data.entry((row, col)).or_default();
1181        cell.extra_mut().span.set_row_span(span);
1182    }
1183
1184    /// Rowspan of the cell.
1185    pub fn row_span(&self, row: u32, col: u32) -> u32 {
1186        if let Some(CellData { extra: Some(c), .. }) = self.data.get(&(row, col)) {
1187            c.span.row_span()
1188        } else {
1189            1
1190        }
1191    }
1192
1193    /// Sets the colspan of the cell. Must be greater than 0.
1194    pub fn set_col_span(&mut self, row: u32, col: u32, span: u32) {
1195        assert!(span > 0);
1196        let cell = self.data.entry((row, col)).or_default();
1197        cell.extra_mut().span.set_col_span(span);
1198    }
1199
1200    /// Colspan of the cell.
1201    pub fn col_span(&self, row: u32, col: u32) -> u32 {
1202        if let Some(CellData { extra: Some(c), .. }) = self.data.get(&(row, col)) {
1203            c.span.col_span()
1204        } else {
1205            1
1206        }
1207    }
1208
1209    /// Sets the rowspan of the cell. Must be greater than 0.
1210    pub fn set_matrix_row_span(&mut self, row: u32, col: u32, span: u32) {
1211        let cell = self.data.entry((row, col)).or_default();
1212        cell.extra_mut().matrix_span.set_row_span(span);
1213    }
1214
1215    /// Rowspan of the cell.
1216    pub fn matrix_row_span(&self, row: u32, col: u32) -> u32 {
1217        if let Some(CellData { extra: Some(c), .. }) = self.data.get(&(row, col)) {
1218            c.matrix_span.row_span()
1219        } else {
1220            1
1221        }
1222    }
1223
1224    /// Sets the colspan of the cell. Must be greater than 0.
1225    pub fn set_matrix_col_span(&mut self, row: u32, col: u32, span: u32) {
1226        let cell = self.data.entry((row, col)).or_default();
1227        cell.extra_mut().matrix_span.set_col_span(span);
1228    }
1229
1230    /// Colspan of the cell.
1231    pub fn matrix_col_span(&self, row: u32, col: u32) -> u32 {
1232        if let Some(CellData { extra: Some(c), .. }) = self.data.get(&(row, col)) {
1233            c.matrix_span.col_span()
1234        } else {
1235            1
1236        }
1237    }
1238
1239    /// Sets a annotation for this cell.
1240    pub fn set_annotation(&mut self, row: u32, col: u32, annotation: Annotation) {
1241        let cell = self.data.entry((row, col)).or_default();
1242        cell.extra_mut().annotation = Some(Box::new(annotation));
1243    }
1244
1245    /// Removes the annotation.
1246    pub fn clear_annotation(&mut self, row: u32, col: u32) {
1247        if let Some(cell) = self.data.get_mut(&(row, col)) {
1248            cell.extra_mut().annotation = None;
1249        }
1250    }
1251
1252    /// Returns a content-validation name for this cell.
1253    pub fn annotation(&self, row: u32, col: u32) -> Option<&Annotation> {
1254        if let Some(CellData { extra: Some(c), .. }) = self.data.get(&(row, col)) {
1255            c.annotation.as_ref().map(|v| v.as_ref())
1256        } else {
1257            None
1258        }
1259    }
1260
1261    /// Returns a content-validation name for this cell.
1262    pub fn annotation_mut(&mut self, row: u32, col: u32) -> Option<&mut Annotation> {
1263        if let Some(CellData { extra: Some(c), .. }) = self.data.get_mut(&(row, col)) {
1264            c.annotation.as_mut().map(|v| v.as_mut())
1265        } else {
1266            None
1267        }
1268    }
1269
1270    /// Add a drawframe to a specific cell.
1271    pub fn add_draw_frame(&mut self, row: u32, col: u32, draw_frame: DrawFrame) {
1272        let cell = self.data.entry((row, col)).or_default();
1273        cell.extra_mut().draw_frames.push(draw_frame);
1274    }
1275
1276    /// Removes all drawframes.
1277    pub fn clear_draw_frames(&mut self, row: u32, col: u32) {
1278        if let Some(cell) = self.data.get_mut(&(row, col)) {
1279            cell.extra_mut().draw_frames = Vec::new();
1280        }
1281    }
1282
1283    /// Returns the draw-frames.
1284    pub fn draw_frames(&self, row: u32, col: u32) -> Option<&Vec<DrawFrame>> {
1285        if let Some(CellData { extra: Some(c), .. }) = self.data.get(&(row, col)) {
1286            Some(c.draw_frames.as_ref())
1287        } else {
1288            None
1289        }
1290    }
1291
1292    /// Returns a content-validation name for this cell.
1293    pub fn draw_frames_mut(&mut self, row: u32, col: u32) -> Option<&mut Vec<DrawFrame>> {
1294        if let Some(CellData { extra: Some(c), .. }) = self.data.get_mut(&(row, col)) {
1295            Some(c.draw_frames.as_mut())
1296        } else {
1297            None
1298        }
1299    }
1300
1301    /// Defines a range of rows as header rows.
1302    /// These rows are repeated when printing on multiple pages.
1303    pub fn set_header_rows(&mut self, row_start: u32, row_end: u32) {
1304        self.header_rows = Some(Header {
1305            from: row_start,
1306            to: row_end,
1307        });
1308    }
1309
1310    /// Clears the header-rows definition.
1311    pub fn clear_header_rows(&mut self) {
1312        self.header_rows = None;
1313    }
1314
1315    /// Returns the header rows.
1316    /// These rows are repeated when printing on multiple pages.
1317    pub fn header_rows(&self) -> Option<Header> {
1318        self.header_rows
1319    }
1320
1321    /// Defines a range of columns as header columns.
1322    /// These columns are repeated when printing on multiple pages.
1323    pub fn set_header_cols(&mut self, col_start: u32, col_end: u32) {
1324        self.header_cols = Some(Header {
1325            from: col_start,
1326            to: col_end,
1327        });
1328    }
1329
1330    /// Clears the header-columns definition.
1331    pub fn clear_header_cols(&mut self) {
1332        self.header_cols = None;
1333    }
1334
1335    /// Returns the header columns.
1336    /// These columns are repeated when printing on multiple pages.
1337    pub fn header_cols(&self) -> Option<Header> {
1338        self.header_cols
1339    }
1340
1341    /// Print ranges.
1342    pub fn add_print_range(&mut self, range: CellRange) {
1343        self.print_ranges.get_or_insert_with(Vec::new).push(range);
1344    }
1345
1346    /// Remove print ranges.
1347    pub fn clear_print_ranges(&mut self) {
1348        self.print_ranges = None;
1349    }
1350
1351    /// Return the print ranges.
1352    pub fn print_ranges(&self) -> Option<&Vec<CellRange>> {
1353        self.print_ranges.as_ref()
1354    }
1355
1356    /// Split horizontally on a cell boundary. The splitting is fixed in
1357    /// position.
1358    pub fn split_col_header(&mut self, col: u32) {
1359        self.config_mut().hor_split_mode = SplitMode::Heading;
1360        self.config_mut().hor_split_pos = col + 1;
1361        self.config_mut().position_right = col + 1;
1362        self.config_mut().cursor_x = col + 1;
1363    }
1364
1365    /// Split vertically on a cell boundary. The splitting is fixed in
1366    /// position.
1367    pub fn split_row_header(&mut self, row: u32) {
1368        self.config_mut().vert_split_mode = SplitMode::Heading;
1369        self.config_mut().vert_split_pos = row + 1;
1370        self.config_mut().position_bottom = row + 1;
1371        self.config_mut().cursor_y = row + 1;
1372    }
1373
1374    /// Split horizontally with a pixel width. The split can be moved around.
1375    /// For more control look at SheetConfig.
1376    pub fn split_horizontal(&mut self, col: u32) {
1377        self.config_mut().hor_split_mode = SplitMode::Split;
1378        self.config_mut().hor_split_pos = col;
1379    }
1380
1381    /// Split vertically with a pixel width. The split can be moved around.
1382    /// For more control look at SheetConfig.
1383    pub fn split_vertical(&mut self, col: u32) {
1384        self.config_mut().vert_split_mode = SplitMode::Split;
1385        self.config_mut().vert_split_pos = col;
1386    }
1387
1388    /// Add a column group.
1389    ///
1390    /// Panic
1391    ///
1392    /// Column groups can be contained within another, but they can't overlap.
1393    /// From must be less than or equal to.
1394    pub fn add_col_group(&mut self, from: u32, to: u32) {
1395        assert!(from <= to);
1396        let grp = Grouped::new(from, to, true);
1397        for v in &self.group_cols {
1398            assert!(grp.contains(v) || v.contains(&grp) || grp.disjunct(v));
1399        }
1400        self.group_cols.push(grp);
1401    }
1402
1403    /// Remove a column group.
1404    pub fn remove_col_group(&mut self, from: u32, to: u32) {
1405        if let Some(idx) = self
1406            .group_cols
1407            .iter()
1408            .position(|v| v.from == from && v.to == to)
1409        {
1410            self.group_cols.remove(idx);
1411        }
1412    }
1413
1414    /// Change the expansion/collapse of a col group.
1415    ///
1416    /// Does nothing if no such group exists.
1417    pub fn set_col_group_displayed(&mut self, from: u32, to: u32, display: bool) {
1418        if let Some(idx) = self
1419            .group_cols
1420            .iter()
1421            .position(|v| v.from == from && v.to == to)
1422        {
1423            self.group_cols[idx].display = display;
1424
1425            for r in from..=to {
1426                self.set_col_visible(
1427                    r,
1428                    if display {
1429                        Visibility::Visible
1430                    } else {
1431                        Visibility::Collapsed
1432                    },
1433                );
1434            }
1435        }
1436    }
1437
1438    /// Count of column groups.
1439    pub fn col_group_count(&self) -> usize {
1440        self.group_cols.len()
1441    }
1442
1443    /// Returns the nth column group.
1444    pub fn col_group(&self, idx: usize) -> Option<&Grouped> {
1445        self.group_cols.get(idx)
1446    }
1447
1448    /// Returns the nth column group.
1449    pub fn col_group_mut(&mut self, idx: usize) -> Option<&mut Grouped> {
1450        self.group_cols.get_mut(idx)
1451    }
1452
1453    /// Iterate the column groups.
1454    pub fn col_group_iter(&self) -> impl Iterator<Item = &Grouped> {
1455        self.group_cols.iter()
1456    }
1457
1458    /// Add a row group.
1459    ///
1460    /// Panic
1461    ///
1462    /// Row groups can be contained within another, but they can't overlap.
1463    /// From must be less than or equal to.
1464    pub fn add_row_group(&mut self, from: u32, to: u32) {
1465        assert!(from <= to);
1466        let grp = Grouped::new(from, to, true);
1467        for v in &self.group_rows {
1468            assert!(grp.contains(v) || v.contains(&grp) || grp.disjunct(v));
1469        }
1470        self.group_rows.push(grp);
1471    }
1472
1473    /// Remove a row group.
1474    pub fn remove_row_group(&mut self, from: u32, to: u32) {
1475        if let Some(idx) = self
1476            .group_rows
1477            .iter()
1478            .position(|v| v.from == from && v.to == to)
1479        {
1480            self.group_rows.remove(idx);
1481        }
1482    }
1483
1484    /// Change the expansion/collapse of a row group.
1485    ///
1486    /// Does nothing if no such group exists.
1487    pub fn set_row_group_displayed(&mut self, from: u32, to: u32, display: bool) {
1488        if let Some(idx) = self
1489            .group_rows
1490            .iter()
1491            .position(|v| v.from == from && v.to == to)
1492        {
1493            self.group_rows[idx].display = display;
1494
1495            for r in from..=to {
1496                self.set_row_visible(
1497                    r,
1498                    if display {
1499                        Visibility::Visible
1500                    } else {
1501                        Visibility::Collapsed
1502                    },
1503                );
1504            }
1505        }
1506    }
1507
1508    /// Count of row groups.
1509    pub fn row_group_count(&self) -> usize {
1510        self.group_rows.len()
1511    }
1512
1513    /// Returns the nth row group.
1514    pub fn row_group(&self, idx: usize) -> Option<&Grouped> {
1515        self.group_rows.get(idx)
1516    }
1517
1518    /// Iterate row groups.
1519    pub fn row_group_iter(&self) -> impl Iterator<Item = &Grouped> {
1520        self.group_rows.iter()
1521    }
1522}
1523
1524/// Describes header rows/columns.
1525#[derive(Debug, Copy, Clone, Default, GetSize)]
1526pub struct Header {
1527    pub from: u32,
1528    pub to: u32,
1529}
1530
1531impl From<Header> for (u32, u32) {
1532    fn from(value: Header) -> Self {
1533        (value.from, value.to)
1534    }
1535}
1536
1537/// Describes a row/column group.
1538#[derive(Debug, PartialEq, Clone, Copy, GetSize)]
1539pub struct Grouped {
1540    /// Inclusive from row/col.
1541    pub from: u32,
1542    /// Inclusive to row/col.
1543    pub to: u32,
1544    /// Visible/Collapsed state.
1545    pub display: bool,
1546}
1547
1548impl Grouped {
1549    /// New group.
1550    pub fn new(from: u32, to: u32, display: bool) -> Self {
1551        Self { from, to, display }
1552    }
1553
1554    /// Inclusive start.
1555    pub fn from(&self) -> u32 {
1556        self.from
1557    }
1558
1559    /// Inclusive start.
1560    pub fn set_from(&mut self, from: u32) {
1561        self.from = from;
1562    }
1563
1564    /// Inclusive end.
1565    pub fn to(&self) -> u32 {
1566        self.to
1567    }
1568
1569    /// Inclusive end.
1570    pub fn set_to(&mut self, to: u32) {
1571        self.to = to
1572    }
1573
1574    /// Group is displayed?
1575    pub fn display(&self) -> bool {
1576        self.display
1577    }
1578
1579    /// Change the display state for the group.
1580    ///
1581    /// Note: Changing this does not change the visibility of the rows/columns.
1582    /// Use Sheet::set_display_col_group() and Sheet::set_display_row_group() to make
1583    /// all necessary changes.
1584    pub fn set_display(&mut self, display: bool) {
1585        self.display = display;
1586    }
1587
1588    /// Contains the other group.
1589    pub fn contains(&self, other: &Grouped) -> bool {
1590        self.from <= other.from && self.to >= other.to
1591    }
1592
1593    /// The two groups are disjunct.
1594    pub fn disjunct(&self, other: &Grouped) -> bool {
1595        self.from < other.from && self.to < other.from || self.from > other.to && self.to > other.to
1596    }
1597}
1598
1599/// There are two ways a sheet can be split. There are fixed column/row header
1600/// like splits, and there is a moveable split.
1601///
1602#[derive(Clone, Copy, Debug, GetSize)]
1603#[allow(missing_docs)]
1604pub enum SplitMode {
1605    None = 0,
1606    Split = 1,
1607    Heading = 2,
1608}
1609
1610impl TryFrom<i16> for SplitMode {
1611    type Error = OdsError;
1612
1613    fn try_from(n: i16) -> Result<Self, Self::Error> {
1614        match n {
1615            0 => Ok(SplitMode::None),
1616            1 => Ok(SplitMode::Split),
1617            2 => Ok(SplitMode::Heading),
1618            _ => Err(OdsError::Ods(format!("Invalid split mode {}", n))),
1619        }
1620    }
1621}
1622
1623/// Per sheet configurations.
1624#[derive(Clone, Debug, GetSize)]
1625pub struct SheetConfig {
1626    /// Active column.
1627    pub cursor_x: u32,
1628    /// Active row.
1629    pub cursor_y: u32,
1630    /// Splitting the table.
1631    pub hor_split_mode: SplitMode,
1632    /// Splitting the table.
1633    pub vert_split_mode: SplitMode,
1634    /// Position of the split.
1635    pub hor_split_pos: u32,
1636    /// Position of the split.
1637    pub vert_split_pos: u32,
1638    /// SplitMode is Pixel
1639    /// - 0-4 indicates the quadrant where the focus is.
1640    ///
1641    /// SplitMode is Cell
1642    /// - No real function.
1643    pub active_split_range: i16,
1644    /// SplitMode is Pixel
1645    /// - First visible column in the left quadrant.
1646    ///
1647    /// SplitMode is Cell
1648    /// - The first visible column in the left quadrant.
1649    ///   AND every column left of this one is simply invisible.
1650    pub position_left: u32,
1651    /// SplitMode is Pixel
1652    /// - First visible column in the right quadrant.
1653    ///
1654    /// SplitMode is Cell
1655    /// - The first visible column in the right quadrant.
1656    pub position_right: u32,
1657    /// SplitMode is Pixel
1658    /// - First visible row in the top quadrant.
1659    ///
1660    /// SplitMode is Cell
1661    /// - The first visible row in the top quadrant.
1662    ///   AND every row up from this one is simply invisible.
1663    pub position_top: u32,
1664    /// SplitMode is Pixel
1665    /// - The first visible row in teh right quadrant.
1666    ///
1667    /// SplitMode is Cell
1668    /// - The first visible row in the bottom quadrant.
1669    pub position_bottom: u32,
1670    /// If 0 then zoom_value denotes a percentage.
1671    /// If 2 then zoom_value is 50%???
1672    pub zoom_type: i16,
1673    /// Value of zoom.
1674    pub zoom_value: i32,
1675    /// Value of pageview zoom.
1676    pub page_view_zoom_value: i32,
1677    /// Grid is showing.
1678    pub show_grid: bool,
1679}
1680
1681impl Default for SheetConfig {
1682    fn default() -> Self {
1683        Self {
1684            cursor_x: 0,
1685            cursor_y: 0,
1686            hor_split_mode: SplitMode::None,
1687            vert_split_mode: SplitMode::None,
1688            hor_split_pos: 0,
1689            vert_split_pos: 0,
1690            active_split_range: 2,
1691            position_left: 0,
1692            position_right: 0,
1693            position_top: 0,
1694            position_bottom: 0,
1695            zoom_type: 0,
1696            zoom_value: 100,
1697            page_view_zoom_value: 60,
1698            show_grid: true,
1699        }
1700    }
1701}
1702
1703/// Cleanup repeat col-data.
1704pub(crate) fn dedup_colheader(sheet: &mut Sheet) -> Result<(), OdsError> {
1705    fn limited_eq(ch1: &ColHeader, ch2: &ColHeader) -> bool {
1706        ch1.style == ch2.style
1707            && ch1.cellstyle == ch2.cellstyle
1708            && ch1.visible == ch2.visible
1709            && ch1.width == ch2.width
1710    }
1711
1712    let col_header = mem::take(&mut sheet.col_header);
1713
1714    let mut new_col_header = BTreeMap::new();
1715    let mut new = None;
1716    for (col, header) in col_header {
1717        match new.as_mut() {
1718            None => {
1719                new = Some((col, header));
1720            }
1721            Some((new_col, new_header)) => {
1722                if limited_eq(new_header, &header) {
1723                    new_header.span += header.span;
1724                } else {
1725                    new_col_header
1726                        .insert(mem::replace(new_col, col), mem::replace(new_header, header));
1727                }
1728            }
1729        }
1730    }
1731    if let Some((new_col, new_header)) = new {
1732        new_col_header.insert(new_col, new_header);
1733    }
1734
1735    sheet.col_header = new_col_header;
1736
1737    Ok(())
1738}