umya_spreadsheet/structs/
merge_cells.rs

1// mergeCell
2use super::Range;
3
4use crate::reader::driver::*;
5use crate::writer::driver::*;
6use quick_xml::events::{BytesStart, Event};
7use quick_xml::Reader;
8use quick_xml::Writer;
9use std::io::Cursor;
10use thin_vec::ThinVec;
11
12#[derive(Clone, Default, Debug)]
13pub(crate) struct MergeCells {
14    range: ThinVec<Range>,
15}
16
17impl MergeCells {
18    #[inline]
19    pub(crate) fn get_range_collection(&self) -> &[Range] {
20        &self.range
21    }
22
23    #[inline]
24    pub(crate) fn get_range_collection_mut(&mut self) -> &mut ThinVec<Range> {
25        &mut self.range
26    }
27
28    #[inline]
29    pub(crate) fn add_range<S: Into<String>>(&mut self, range: S) -> &mut Self {
30        let mut obj = Range::default();
31        obj.set_range(range);
32        self.range.push(obj);
33        self
34    }
35
36    pub(crate) fn _has_vertical(&self, row_num: &u32) -> bool {
37        self.get_range_collection().iter().any(|range| {
38            let start_num = range
39                .get_coordinate_start_row()
40                .map_or(true, |v| v.get_num() <= row_num);
41            let end_num = range
42                .get_coordinate_end_row()
43                .map_or(true, |v| v.get_num() >= row_num);
44            start_num && end_num && start_num != end_num
45        })
46    }
47
48    pub(crate) fn has_horizontal(&self, col_num: &u32) -> bool {
49        self.get_range_collection().iter().any(|range| {
50            let start_num = range
51                .get_coordinate_start_col()
52                .map_or(true, |v| v.get_num() <= col_num);
53            let end_num = range
54                .get_coordinate_end_col()
55                .map_or(true, |v| v.get_num() >= col_num);
56            start_num && end_num && start_num != end_num
57        })
58    }
59
60    pub(crate) fn set_attributes<R: std::io::BufRead>(
61        &mut self,
62        reader: &mut Reader<R>,
63        _e: &BytesStart,
64    ) {
65        xml_read_loop!(
66            reader,
67            Event::Empty(ref e) => {
68                if e.name().into_inner() == b"mergeCell" {
69                    self.add_range(get_attribute(e, b"ref").unwrap());
70                }
71            },
72            Event::End(ref e) => {
73                if e.name().into_inner() == b"mergeCells" {
74                    return
75                }
76            },
77            Event::Eof => panic!("Error: Could not find {} end element", "mergeCells")
78        );
79    }
80
81    pub(crate) fn write_to(&self, writer: &mut Writer<Cursor<Vec<u8>>>) {
82        if !self.get_range_collection().is_empty() {
83            // mergeCells
84            write_start_tag(
85                writer,
86                "mergeCells",
87                vec![("count", &self.get_range_collection().len().to_string())],
88                false,
89            );
90
91            // mergeCell
92            for merge_cell in self.get_range_collection() {
93                write_start_tag(
94                    writer,
95                    "mergeCell",
96                    vec![("ref", &merge_cell.get_range())],
97                    true,
98                );
99            }
100
101            write_end_tag(writer, "mergeCells");
102        }
103    }
104}