umya_spreadsheet/structs/
defined_name.rs

1use super::Address;
2use super::BooleanValue;
3use super::StringValue;
4use super::UInt32Value;
5use crate::helper::address::*;
6use crate::reader::driver::*;
7use crate::traits::AdjustmentCoordinateWithSheet;
8use crate::writer::driver::*;
9use quick_xml::events::{BytesStart, Event};
10use quick_xml::Reader;
11use quick_xml::Writer;
12use std::io::Cursor;
13use thin_vec::ThinVec;
14
15#[derive(Clone, Default, Debug)]
16pub struct DefinedName {
17    name: StringValue,
18    address: ThinVec<Address>,
19    string_value: StringValue,
20    local_sheet_id: UInt32Value,
21    hidden: BooleanValue,
22}
23impl DefinedName {
24    #[inline]
25    pub fn get_name(&self) -> &str {
26        &self.name.get_value_str()
27    }
28
29    #[inline]
30    pub(crate) fn set_name<S: Into<String>>(&mut self, value: S) -> &mut Self {
31        self.name.set_value(value);
32        self
33    }
34
35    pub fn get_address(&self) -> String {
36        if self.string_value.has_value() {
37            return self.string_value.get_value_str().to_string();
38        }
39        let mut result: Vec<String> = Vec::with_capacity(self.address.len());
40        for row in &self.address {
41            result.push(row.get_address_ptn2());
42        }
43        result.join(",")
44    }
45
46    pub fn set_address<S: Into<String>>(&mut self, value: S) -> &mut Self {
47        let list = self.split_str(value);
48        for v in &list {
49            if is_address(&v) {
50                self.add_address(v);
51            } else {
52                self.set_string_value(v);
53            }
54        }
55        self
56    }
57
58    pub fn add_address<S: Into<String>>(&mut self, value: S) -> &mut Self {
59        let mut obj = Address::default();
60        obj.set_address(value.into().replace("''", "'"));
61        self.address.push(obj);
62        self
63    }
64
65    pub(crate) fn get_sheet_name_crate(&self) -> String {
66        if self.string_value.has_value() {
67            return String::new();
68        }
69        self.address
70            .first()
71            .unwrap_or(&Address::default())
72            .get_sheet_name()
73            .to_string()
74    }
75
76    #[inline]
77    pub(crate) fn get_address_obj(&self) -> &[Address] {
78        &self.address
79    }
80
81    #[inline]
82    pub(crate) fn get_address_obj_mut(&mut self) -> &mut ThinVec<Address> {
83        &mut self.address
84    }
85
86    #[inline]
87    pub(crate) fn set_string_value<S: Into<String>>(&mut self, value: S) -> &mut Self {
88        self.address.clear();
89        self.string_value.set_value(value);
90        self
91    }
92
93    #[inline]
94    pub fn has_local_sheet_id(&self) -> bool {
95        self.local_sheet_id.has_value()
96    }
97
98    #[inline]
99    pub fn get_local_sheet_id(&self) -> &u32 {
100        &self.local_sheet_id.get_value()
101    }
102
103    #[inline]
104    pub fn set_local_sheet_id(&mut self, value: u32) {
105        self.local_sheet_id.set_value(value);
106    }
107
108    #[inline]
109    pub fn get_hidden(&self) -> &bool {
110        &self.hidden.get_value()
111    }
112
113    #[inline]
114    pub fn set_hidden(&mut self, value: bool) {
115        self.hidden.set_value(value);
116    }
117
118    fn split_str<S: Into<String>>(&self, value: S) -> Vec<String> {
119        let value = value.into();
120        let char_list: Vec<char> = value.chars().collect::<Vec<char>>();
121        let mut is_pass_s = false;
122        let mut is_pass_d = false;
123        let mut is_pass_b = 0;
124        let mut result: Vec<String> = Vec::new();
125        let mut string = String::new();
126        for c in &char_list {
127            match c {
128                '(' => {
129                    is_pass_b += 1;
130                    string.push(*c);
131                }
132                ')' => {
133                    is_pass_b -= 1;
134                    string.push(*c);
135                }
136                '\'' => {
137                    is_pass_s = !is_pass_s;
138                    string.push(*c);
139                }
140                '"' => {
141                    is_pass_d = !is_pass_d;
142                    if is_pass_s || is_pass_b != 0 {
143                        string.push(*c);
144                    }
145                }
146                ',' => {
147                    if !is_pass_s && !is_pass_d && is_pass_b == 0 {
148                        result.push(std::mem::take(&mut string));
149                    } else {
150                        string.push(*c);
151                    }
152                }
153                _ => {
154                    string.push(*c);
155                }
156            }
157        }
158        if !string.is_empty() {
159            result.push(string);
160        }
161        result
162    }
163
164    pub(crate) fn set_sheet_name<S: Into<String>>(&mut self, value: S) -> &mut Self {
165        let value = value.into();
166        for address in &mut self.address {
167            address.set_sheet_name(value.clone());
168        }
169        self
170    }
171
172    pub(crate) fn set_attributes<R: std::io::BufRead>(
173        &mut self,
174        reader: &mut Reader<R>,
175        e: &BytesStart,
176    ) {
177        set_string_from_xml!(self, e, name, "name");
178        set_string_from_xml!(self, e, local_sheet_id, "localSheetId");
179        set_string_from_xml!(self, e, hidden, "hidden");
180
181        let mut value: String = String::new();
182        xml_read_loop!(
183            reader,
184                Event::Text(e) => {
185                    value = e.unescape().unwrap().to_string();
186                },
187                Event::End(ref e) => {
188                    if e.name().into_inner() == b"definedName" {
189                        self.set_address(value);
190                        return
191                    }
192                },
193                Event::Eof => panic!("Error: Could not find {} end element", "definedName")
194        );
195    }
196
197    pub(crate) fn write_to(&self, writer: &mut Writer<Cursor<Vec<u8>>>) {
198        // definedName
199        let mut attributes: Vec<(&str, &str)> = Vec::new();
200        attributes.push(("name", self.get_name()));
201        let local_sheet_id_str = self.local_sheet_id.get_value_string();
202        if self.local_sheet_id.has_value() {
203            attributes.push(("localSheetId", &local_sheet_id_str));
204        }
205        let hidden_str = self.hidden.get_value_string();
206        if self.hidden.has_value() {
207            attributes.push(("hidden", &hidden_str));
208        }
209        write_start_tag(writer, "definedName", attributes, false);
210        write_text_node_conversion(writer, self.get_address());
211        write_end_tag(writer, "definedName");
212    }
213}
214impl AdjustmentCoordinateWithSheet for DefinedName {
215    fn adjustment_insert_coordinate_with_sheet(
216        &mut self,
217        sheet_name: &str,
218        root_col_num: &u32,
219        offset_col_num: &u32,
220        root_row_num: &u32,
221        offset_row_num: &u32,
222    ) {
223        for address in &mut self.address {
224            address.adjustment_insert_coordinate_with_sheet(
225                sheet_name,
226                root_col_num,
227                offset_col_num,
228                root_row_num,
229                offset_row_num,
230            );
231        }
232    }
233
234    fn adjustment_remove_coordinate_with_sheet(
235        &mut self,
236        sheet_name: &str,
237        root_col_num: &u32,
238        offset_col_num: &u32,
239        root_row_num: &u32,
240        offset_row_num: &u32,
241    ) {
242        self.address.retain(|x| {
243            !(x.is_remove_coordinate_with_sheet(
244                sheet_name,
245                root_col_num,
246                offset_col_num,
247                root_row_num,
248                offset_row_num,
249            ))
250        });
251        for address in &mut self.address {
252            address.adjustment_remove_coordinate_with_sheet(
253                sheet_name,
254                root_col_num,
255                offset_col_num,
256                root_row_num,
257                offset_row_num,
258            );
259        }
260    }
261
262    #[inline]
263    fn is_remove_coordinate_with_sheet(
264        &self,
265        sheet_name: &str,
266        root_col_num: &u32,
267        offset_col_num: &u32,
268        root_row_num: &u32,
269        offset_row_num: &u32,
270    ) -> bool {
271        if self.string_value.has_value() {
272            return false;
273        }
274        if self.address.is_empty() {
275            return true;
276        }
277        false
278    }
279}