umya_spreadsheet/structs/
cell_value.rs1use super::RichText;
2use super::SharedStringItem;
3use super::Text;
4use crate::helper::formula::*;
5use crate::structs::CellFormula;
6use crate::structs::CellRawValue;
7use crate::traits::AdjustmentCoordinateWith2Sheet;
8use crate::CellErrorType;
9use std::borrow::Cow;
10use std::str::FromStr;
11
12#[derive(Clone, Default, Debug, PartialEq, PartialOrd)]
13pub struct CellValue {
14 pub(crate) raw_value: CellRawValue,
15 pub(crate) formula: Option<Box<CellFormula>>,
16}
17impl CellValue {
18 #[inline]
19 pub fn get_data_type(&self) -> &str {
20 self.raw_value.get_data_type()
21 }
22
23 #[inline]
24 pub fn get_raw_value(&self) -> &CellRawValue {
25 &self.raw_value
26 }
27
28 #[inline]
29 pub(crate) fn get_data_type_crate(&self) -> &str {
30 match &self.formula {
31 Some(_) => "str",
32 None => self.raw_value.get_data_type(),
33 }
34 }
35
36 #[inline]
37 pub fn get_value(&self) -> Cow<'static, str> {
38 self.raw_value.to_string().into()
39 }
40
41 #[inline]
42 pub fn get_value_number(&self) -> Option<f64> {
43 self.raw_value.get_number()
44 }
45
46 #[inline]
47 pub fn get_value_lazy(&mut self) -> Cow<'static, str> {
48 if let CellRawValue::Lazy(v) = &self.raw_value {
49 self.raw_value = Self::guess_typed_data(v);
50 }
51 self.remove_formula();
52 self.raw_value.to_string().into()
53 }
54
55 #[inline]
56 pub(crate) fn get_text(&self) -> Option<Text> {
57 self.raw_value.get_text()
58 }
59
60 #[inline]
61 pub(crate) fn get_rich_text(&self) -> Option<RichText> {
62 self.raw_value.get_rich_text()
63 }
64
65 #[inline]
74 pub fn set_value<S: Into<String>>(&mut self, value: S) -> &mut Self {
75 self.raw_value = Self::guess_typed_data(&value.into());
76 self.remove_formula();
77 self
78 }
79
80 #[inline]
81 pub(crate) fn set_value_crate<S: Into<String>>(&mut self, value: S) -> &mut Self {
82 self.raw_value = Self::guess_typed_data(&value.into());
83 self
84 }
85
86 #[inline]
87 pub fn set_value_lazy<S: Into<String>>(&mut self, value: S) -> &mut Self {
88 self.raw_value = CellRawValue::Lazy(value.into().into_boxed_str());
89 self
90 }
91
92 #[inline]
93 pub fn set_value_string<S: Into<String>>(&mut self, value: S) -> &mut Self {
94 self.raw_value = CellRawValue::String(value.into().into_boxed_str());
95 self.remove_formula();
96 self
97 }
98
99 #[inline]
100 pub(crate) fn set_value_string_crate<S: Into<String>>(&mut self, value: S) -> &mut Self {
101 self.raw_value = CellRawValue::String(value.into().into_boxed_str());
102 self
103 }
104
105 #[inline]
106 pub fn set_value_bool(&mut self, value: bool) -> &mut Self {
107 self.raw_value = CellRawValue::Bool(value);
108 self.remove_formula();
109 self
110 }
111
112 #[inline]
113 pub(crate) fn set_value_bool_crate(&mut self, value: bool) -> &mut Self {
114 self.raw_value = CellRawValue::Bool(value);
115 self
116 }
117
118 #[inline]
119 pub fn set_value_number<T>(&mut self, value: T) -> &mut Self
120 where
121 T: Into<f64>,
122 {
123 self.raw_value = CellRawValue::Numeric(value.into());
124 self.remove_formula();
125 self
126 }
127
128 #[inline]
129 pub fn set_rich_text(&mut self, value: RichText) -> &mut Self {
130 self.raw_value = CellRawValue::RichText(value);
131 self.remove_formula();
132 self
133 }
134
135 #[inline]
136 pub fn set_blank(&mut self) -> &mut Self {
137 self.raw_value = CellRawValue::Empty;
138 self.remove_formula();
139 self
140 }
141
142 #[inline]
143 pub fn is_formula(&self) -> bool {
144 self.formula.is_some()
145 }
146
147 #[inline]
148 pub fn get_formula(&self) -> &str {
149 match &self.formula {
150 Some(v) => v.get_text(),
151 None => "",
152 }
153 }
154
155 #[inline]
156 pub fn get_formula_obj(&self) -> Option<&CellFormula> {
157 self.formula.as_deref()
158 }
159
160 #[inline]
161 pub fn set_formula<S: Into<String>>(&mut self, value: S) -> &mut Self {
162 let mut obj = CellFormula::default();
163 obj.set_text(value.into());
164 self.formula = Some(Box::new(obj));
165 self
166 }
167
168 #[inline]
169 pub fn set_formula_obj(&mut self, value: CellFormula) -> &mut Self {
170 self.formula = Some(Box::new(value));
171 self
172 }
173
174 #[inline]
175 pub fn remove_formula(&mut self) -> &mut Self {
176 self.formula = None;
177 self
178 }
179
180 #[inline]
181 pub fn set_formula_result_default<S: Into<String>>(&mut self, value: S) -> &mut Self {
182 self.set_value_crate(value);
183 self
184 }
185
186 #[inline]
187 pub fn set_error<S: Into<String>>(&mut self, value: S) -> &mut Self {
188 self.set_value_crate(value);
189 self
190 }
191
192 #[inline]
193 pub fn is_error(&self) -> bool {
194 self.raw_value.is_error()
195 }
196
197 #[inline]
198 pub(crate) fn set_shared_string_item(&mut self, value: SharedStringItem) -> &mut Self {
199 if let Some(v) = value.get_text() {
200 self.set_value_string(v.get_value());
201 }
202 if let Some(v) = value.get_rich_text() {
203 self.set_rich_text(v.clone());
204 }
205 self
206 }
207
208 #[inline]
209 pub(crate) fn guess_typed_data(value: &str) -> CellRawValue {
210 let uppercase_value = value.to_uppercase();
211
212 match uppercase_value.as_str() {
213 "" => CellRawValue::Empty,
214 "TRUE" => CellRawValue::Bool(true),
215 "FALSE" => CellRawValue::Bool(false),
216 "NAN" => CellRawValue::String(value.into()),
217 _ => {
218 if let Ok(error_type) = CellErrorType::from_str(&uppercase_value) {
219 CellRawValue::Error(error_type)
220 } else if let Ok(f) = value.parse::<f64>() {
221 CellRawValue::Numeric(f)
222 } else {
223 CellRawValue::String(value.into())
224 }
225 }
226 }
227 }
228
229 #[inline]
230 pub fn is_empty(&self) -> bool {
231 self.is_value_empty() && self.is_formula_empty()
232 }
233
234 #[inline]
235 pub(crate) fn is_value_empty(&self) -> bool {
236 self.raw_value.is_empty()
237 }
238
239 #[inline]
240 pub(crate) fn is_formula_empty(&self) -> bool {
241 !self.is_formula()
242 }
243
244 #[inline]
246 pub(crate) fn is_visually_empty(&self) -> bool {
247 self.get_value() == "" && self.is_formula_empty()
248 }
249}
250impl AdjustmentCoordinateWith2Sheet for CellValue {
251 #[inline]
252 fn adjustment_insert_coordinate_with_2sheet(
253 &mut self,
254 self_sheet_name: &str,
255 sheet_name: &str,
256 root_col_num: &u32,
257 offset_col_num: &u32,
258 root_row_num: &u32,
259 offset_row_num: &u32,
260 ) {
261 if let Some(v) = &mut self.formula {
262 v.adjustment_insert_coordinate_with_2sheet(
263 self_sheet_name,
264 sheet_name,
265 root_col_num,
266 offset_col_num,
267 root_row_num,
268 offset_row_num,
269 );
270 }
271 }
272
273 #[inline]
274 fn adjustment_remove_coordinate_with_2sheet(
275 &mut self,
276 self_sheet_name: &str,
277 sheet_name: &str,
278 root_col_num: &u32,
279 offset_col_num: &u32,
280 root_row_num: &u32,
281 offset_row_num: &u32,
282 ) {
283 if let Some(v) = &mut self.formula {
284 v.adjustment_remove_coordinate_with_2sheet(
285 self_sheet_name,
286 sheet_name,
287 root_col_num,
288 offset_col_num,
289 root_row_num,
290 offset_row_num,
291 );
292 }
293 }
294}
295
296#[cfg(test)]
297mod tests {
298 use super::*;
299
300 #[test]
301 fn set_value() {
302 let mut obj = CellValue::default();
303
304 obj.set_value_string(String::from("TEST"));
305 assert_eq!(obj.get_value(), "TEST");
306 assert!(obj.get_value_number().is_none());
307
308 obj.set_value_string("TEST");
309 assert_eq!(obj.get_value(), "TEST");
310
311 obj.set_value_bool(true);
312 assert_eq!(obj.get_value(), "TRUE");
313
314 obj.set_value_number(1);
315 assert_eq!(obj.get_value(), "1");
316
317 obj.set_blank();
318 assert_eq!(obj.get_value(), "");
319
320 obj.set_error("#NUM!");
321 assert_eq!(obj.get_value(), "#NUM!");
322 }
323
324 #[test]
325 fn error_checking() {
326 let path = std::path::Path::new("./tests/test_files/pr_204.xlsx");
327 let book = crate::reader::xlsx::read(path).unwrap();
328 let sheet = book.get_sheet(&0).unwrap();
329
330 let cell = sheet.get_cell_value("A1");
331 assert!(cell.raw_value.is_error());
332 assert_eq!(cell.raw_value, CellRawValue::Error(CellErrorType::Div0));
333
334 let cell = sheet.get_cell_value("A2");
335 assert!(cell.raw_value.is_error());
336 assert_eq!(cell.raw_value, CellRawValue::Error(CellErrorType::Name));
337
338 let cell = sheet.get_cell_value("A3");
339 assert!(cell.raw_value.is_error());
340 assert_eq!(cell.raw_value, CellRawValue::Error(CellErrorType::Ref));
341
342 let cell = sheet.get_cell_value("A4");
343 assert!(cell.raw_value.is_error());
344 assert_eq!(cell.raw_value, CellRawValue::Error(CellErrorType::Value));
345
346 let cell = sheet.get_cell_value("A5");
347 assert!(cell.raw_value.is_error());
348 assert_eq!(cell.raw_value, CellRawValue::Error(CellErrorType::NA));
349
350 let cell = sheet.get_cell_value("A6");
351 assert!(cell.raw_value.is_error());
352 assert_eq!(cell.raw_value, CellRawValue::Error(CellErrorType::Num));
353
354 let cell = sheet.get_cell_value("A7");
355 assert!(cell.raw_value.is_error());
356 assert_eq!(cell.raw_value, CellRawValue::Error(CellErrorType::Null));
357 }
358}