umya_spreadsheet/structs/
defined_name.rs1use 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 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}