1use super::*;
5use crate::error::{ OfficeError, Result, XlsxError };
6use crate::xlsx::cell::{ CellReference, CellValue };
7use std::collections::HashMap;
8
9impl FormulaCalculator {
10 pub fn new(cell_provider: Box<dyn CellProvider>) -> Self {
12 let mut calculator = Self {
13 cell_provider,
14 function_library: FunctionLibrary::new(),
15 cache: HashMap::new(),
16 };
17
18 calculator.register_builtin_functions();
20 calculator
21 }
22
23 pub fn evaluate(&mut self, expr: &FormulaExpression) -> Result<FormulaValue> {
25 match expr {
26 FormulaExpression::Constant(value) => Ok(value.clone()),
27
28 FormulaExpression::CellRef(cell_ref) => {
29 let cell_value = self.cell_provider.get_cell_value(cell_ref)?;
30 Ok(self.cell_value_to_formula_value(cell_value))
31 }
32
33 FormulaExpression::RangeRef(start, end) => {
34 let values = self.cell_provider.get_range_values(start, end)?;
35 let formula_values = values
36 .into_iter()
37 .map(|row| {
38 row.into_iter()
39 .map(|cell| self.cell_value_to_formula_value(cell))
40 .collect()
41 })
42 .collect();
43 Ok(FormulaValue::Array(formula_values))
44 }
45
46 FormulaExpression::Function { name, args } => self.evaluate_function(name, args),
47
48 FormulaExpression::BinaryOp { op, left, right } => {
49 let left_val = self.evaluate(left)?;
50 let right_val = self.evaluate(right)?;
51 self.evaluate_binary_op(op, &left_val, &right_val)
52 }
53
54 FormulaExpression::UnaryOp { op, operand } => {
55 let operand_val = self.evaluate(operand)?;
56 self.evaluate_unary_op(op, &operand_val)
57 }
58 }
59 }
60
61 fn cell_value_to_formula_value(&self, cell_value: CellValue) -> FormulaValue {
63 match cell_value {
64 CellValue::Empty => FormulaValue::Number(0.0),
65 CellValue::Number(n) => FormulaValue::Number(n),
66 CellValue::Text(s) => FormulaValue::Text(s),
67 CellValue::Boolean(b) => FormulaValue::Boolean(b),
68 CellValue::DateTime(d) => FormulaValue::Number(d),
69 CellValue::Formula(_) => FormulaValue::Error(FormulaError::ReferenceError),
70 CellValue::Error(e) => FormulaValue::Error(FormulaError::ValueError),
71 }
72 }
73
74 fn evaluate_binary_op(
76 &self,
77 op: &BinaryOperator,
78 left: &FormulaValue,
79 right: &FormulaValue
80 ) -> Result<FormulaValue> {
81 if left.is_error() {
83 return Ok(left.clone());
84 }
85 if right.is_error() {
86 return Ok(right.clone());
87 }
88
89 match op {
90 BinaryOperator::Add => {
91 let left_num = left.as_number()?;
92 let right_num = right.as_number()?;
93 Ok(FormulaValue::Number(left_num + right_num))
94 }
95
96 BinaryOperator::Subtract => {
97 let left_num = left.as_number()?;
98 let right_num = right.as_number()?;
99 Ok(FormulaValue::Number(left_num - right_num))
100 }
101
102 BinaryOperator::Multiply => {
103 let left_num = left.as_number()?;
104 let right_num = right.as_number()?;
105 Ok(FormulaValue::Number(left_num * right_num))
106 }
107
108 BinaryOperator::Divide => {
109 let left_num = left.as_number()?;
110 let right_num = right.as_number()?;
111
112 if right_num == 0.0 {
113 Ok(FormulaValue::Error(FormulaError::DivisionByZero))
114 } else {
115 Ok(FormulaValue::Number(left_num / right_num))
116 }
117 }
118
119 BinaryOperator::Power => {
120 let left_num = left.as_number()?;
121 let right_num = right.as_number()?;
122 Ok(FormulaValue::Number(left_num.powf(right_num)))
123 }
124
125 BinaryOperator::Equal => Ok(FormulaValue::Boolean(self.values_equal(left, right))),
126
127 BinaryOperator::NotEqual => Ok(FormulaValue::Boolean(!self.values_equal(left, right))),
128
129 BinaryOperator::LessThan => {
130 let result = self.compare_values(left, right)?;
131 Ok(FormulaValue::Boolean(result < 0))
132 }
133
134 BinaryOperator::LessThanOrEqual => {
135 let result = self.compare_values(left, right)?;
136 Ok(FormulaValue::Boolean(result <= 0))
137 }
138
139 BinaryOperator::GreaterThan => {
140 let result = self.compare_values(left, right)?;
141 Ok(FormulaValue::Boolean(result > 0))
142 }
143
144 BinaryOperator::GreaterThanOrEqual => {
145 let result = self.compare_values(left, right)?;
146 Ok(FormulaValue::Boolean(result >= 0))
147 }
148
149 BinaryOperator::Concatenate => {
150 let left_text = left.as_text();
151 let right_text = right.as_text();
152 Ok(FormulaValue::Text(format!("{}{}", left_text, right_text)))
153 }
154
155 BinaryOperator::LogicalOr => {
156 let left_bool = left.as_boolean()?;
157 let right_bool = right.as_boolean()?;
158 Ok(FormulaValue::Boolean(left_bool || right_bool))
159 }
160
161 BinaryOperator::LogicalAnd => {
162 let left_bool = left.as_boolean()?;
163 let right_bool = right.as_boolean()?;
164 Ok(FormulaValue::Boolean(left_bool && right_bool))
165 }
166 }
167 }
168
169 fn evaluate_unary_op(
171 &self,
172 op: &UnaryOperator,
173 operand: &FormulaValue
174 ) -> Result<FormulaValue> {
175 if operand.is_error() {
176 return Ok(operand.clone());
177 }
178
179 match op {
180 UnaryOperator::Plus => {
181 let num = operand.as_number()?;
182 Ok(FormulaValue::Number(num))
183 }
184 UnaryOperator::Minus => {
185 let num = operand.as_number()?;
186 Ok(FormulaValue::Number(-num))
187 }
188 UnaryOperator::Percent => {
189 let num = operand.as_number()?;
190 Ok(FormulaValue::Number(num / 100.0))
191 }
192 UnaryOperator::Factorial => {
193 let num = operand.as_number()?;
194 if num < 0.0 || num.fract() != 0.0 {
195 return Ok(FormulaValue::Error(FormulaError::ValueError));
196 }
197 let mut result = 1.0;
198 for i in 1..=num as u64 {
199 result *= i as f64;
200 }
201 Ok(FormulaValue::Number(result))
202 }
203 }
204 }
205
206 fn values_equal(&self, left: &FormulaValue, right: &FormulaValue) -> bool {
208 match (left, right) {
209 (FormulaValue::Number(a), FormulaValue::Number(b)) => (a - b).abs() < f64::EPSILON,
210 (FormulaValue::Text(a), FormulaValue::Text(b)) => a == b,
211 (FormulaValue::Boolean(a), FormulaValue::Boolean(b)) => a == b,
212 (FormulaValue::Error(a), FormulaValue::Error(b)) => a == b,
213 _ => false,
214 }
215 }
216
217 fn compare_values(&self, left: &FormulaValue, right: &FormulaValue) -> Result<i32> {
219 match (left, right) {
220 (FormulaValue::Number(a), FormulaValue::Number(b)) => {
221 Ok(a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal) as i32)
222 }
223 (FormulaValue::Text(a), FormulaValue::Text(b)) => Ok(a.cmp(b) as i32),
224 (FormulaValue::Boolean(a), FormulaValue::Boolean(b)) => Ok(a.cmp(b) as i32),
225 _ =>
226 Err(
227 OfficeError::Xlsx(XlsxError::InvalidFormula {
228 formula: "Cannot compare different types".to_string(),
229 })
230 ),
231 }
232 }
233
234 fn evaluate_function(
236 &mut self,
237 name: &str,
238 args: &[FormulaExpression]
239 ) -> Result<FormulaValue> {
240 let mut arg_values = Vec::new();
242 for arg in args {
243 arg_values.push(self.evaluate(arg)?);
244 }
245
246 self.function_library.call_function(name, &arg_values)
248 }
249
250 fn register_builtin_functions(&mut self) {
252 self.function_library.register(Box::new(SumFunction));
254 self.function_library.register(Box::new(AverageFunction));
255 self.function_library.register(Box::new(MaxFunction));
256 self.function_library.register(Box::new(MinFunction));
257 self.function_library.register(Box::new(CountFunction));
258 self.function_library.register(Box::new(RoundFunction));
259 self.function_library.register(Box::new(AbsFunction));
260 self.function_library.register(Box::new(SqrtFunction));
261
262 self.function_library.register(Box::new(IfFunction));
264 self.function_library.register(Box::new(AndFunction));
265 self.function_library.register(Box::new(OrFunction));
266 self.function_library.register(Box::new(NotFunction));
267
268 self.function_library.register(Box::new(ConcatenateFunction));
270 self.function_library.register(Box::new(LeftFunction));
271 self.function_library.register(Box::new(RightFunction));
272 self.function_library.register(Box::new(MidFunction));
273 self.function_library.register(Box::new(LenFunction));
274 self.function_library.register(Box::new(UpperFunction));
275 self.function_library.register(Box::new(LowerFunction));
276 }
277}
278
279impl FunctionLibrary {
280 pub fn new() -> Self {
282 Self {
283 functions: HashMap::new(),
284 }
285 }
286
287 pub fn register(&mut self, function: Box<dyn FormulaFunction>) {
289 self.functions.insert(function.name().to_uppercase(), function);
290 }
291
292 pub fn call_function(&self, name: &str, args: &[FormulaValue]) -> Result<FormulaValue> {
294 let function = self.functions.get(&name.to_uppercase()).ok_or_else(|| {
295 OfficeError::Xlsx(XlsxError::InvalidFormula {
296 formula: format!("Unknown function: {}", name),
297 })
298 })?;
299
300 if args.len() < function.min_args() {
302 return Err(
303 OfficeError::Xlsx(XlsxError::InvalidFormula {
304 formula: format!(
305 "Function {} requires at least {} arguments",
306 name,
307 function.min_args()
308 ),
309 })
310 );
311 }
312
313 if let Some(max_args) = function.max_args() {
314 if args.len() > max_args {
315 return Err(
316 OfficeError::Xlsx(XlsxError::InvalidFormula {
317 formula: format!(
318 "Function {} accepts at most {} arguments",
319 name,
320 max_args
321 ),
322 })
323 );
324 }
325 }
326
327 function.execute(args)
328 }
329}
330
331struct SumFunction;
335
336impl FormulaFunction for SumFunction {
337 fn name(&self) -> &str {
338 "SUM"
339 }
340 fn min_args(&self) -> usize {
341 1
342 }
343 fn max_args(&self) -> Option<usize> {
344 None
345 }
346
347 fn execute(&self, args: &[FormulaValue]) -> Result<FormulaValue> {
348 let mut sum = 0.0;
349
350 for arg in args {
351 match arg {
352 FormulaValue::Number(n) => {
353 sum += n;
354 }
355 FormulaValue::Boolean(b) => {
356 sum += if *b { 1.0 } else { 0.0 };
357 }
358 FormulaValue::Array(arr) => {
359 for row in arr {
360 for cell in row {
361 if let FormulaValue::Number(n) = cell {
362 sum += n;
363 }
364 }
365 }
366 }
367 FormulaValue::Error(e) => {
368 return Ok(FormulaValue::Error(e.clone()));
369 }
370 _ => {} }
372 }
373
374 Ok(FormulaValue::Number(sum))
375 }
376}
377
378struct AverageFunction;
380
381impl FormulaFunction for AverageFunction {
382 fn name(&self) -> &str {
383 "AVERAGE"
384 }
385 fn min_args(&self) -> usize {
386 1
387 }
388 fn max_args(&self) -> Option<usize> {
389 None
390 }
391
392 fn execute(&self, args: &[FormulaValue]) -> Result<FormulaValue> {
393 let mut sum = 0.0;
394 let mut count = 0;
395
396 for arg in args {
397 match arg {
398 FormulaValue::Number(n) => {
399 sum += n;
400 count += 1;
401 }
402 FormulaValue::Boolean(b) => {
403 sum += if *b { 1.0 } else { 0.0 };
404 count += 1;
405 }
406 FormulaValue::Array(arr) => {
407 for row in arr {
408 for cell in row {
409 if let FormulaValue::Number(n) = cell {
410 sum += n;
411 count += 1;
412 }
413 }
414 }
415 }
416 FormulaValue::Error(e) => {
417 return Ok(FormulaValue::Error(e.clone()));
418 }
419 _ => {} }
421 }
422
423 if count == 0 {
424 Ok(FormulaValue::Error(FormulaError::DivisionByZero))
425 } else {
426 Ok(FormulaValue::Number(sum / (count as f64)))
427 }
428 }
429}
430
431struct MaxFunction;
433
434impl FormulaFunction for MaxFunction {
435 fn name(&self) -> &str {
436 "MAX"
437 }
438 fn min_args(&self) -> usize {
439 1
440 }
441 fn max_args(&self) -> Option<usize> {
442 None
443 }
444
445 fn execute(&self, args: &[FormulaValue]) -> Result<FormulaValue> {
446 let mut max_val = f64::NEG_INFINITY;
447 let mut has_number = false;
448
449 for arg in args {
450 match arg {
451 FormulaValue::Number(n) => {
452 max_val = max_val.max(*n);
453 has_number = true;
454 }
455 FormulaValue::Array(arr) => {
456 for row in arr {
457 for cell in row {
458 if let FormulaValue::Number(n) = cell {
459 max_val = max_val.max(*n);
460 has_number = true;
461 }
462 }
463 }
464 }
465 FormulaValue::Error(e) => {
466 return Ok(FormulaValue::Error(e.clone()));
467 }
468 _ => {} }
470 }
471
472 if has_number {
473 Ok(FormulaValue::Number(max_val))
474 } else {
475 Ok(FormulaValue::Number(0.0))
476 }
477 }
478}
479
480struct MinFunction;
482
483impl FormulaFunction for MinFunction {
484 fn name(&self) -> &str {
485 "MIN"
486 }
487 fn min_args(&self) -> usize {
488 1
489 }
490 fn max_args(&self) -> Option<usize> {
491 None
492 }
493
494 fn execute(&self, args: &[FormulaValue]) -> Result<FormulaValue> {
495 let mut min_val = f64::INFINITY;
496 let mut has_number = false;
497
498 for arg in args {
499 match arg {
500 FormulaValue::Number(n) => {
501 min_val = min_val.min(*n);
502 has_number = true;
503 }
504 FormulaValue::Array(arr) => {
505 for row in arr {
506 for cell in row {
507 if let FormulaValue::Number(n) = cell {
508 min_val = min_val.min(*n);
509 has_number = true;
510 }
511 }
512 }
513 }
514 FormulaValue::Error(e) => {
515 return Ok(FormulaValue::Error(e.clone()));
516 }
517 _ => {} }
519 }
520
521 if has_number {
522 Ok(FormulaValue::Number(min_val))
523 } else {
524 Ok(FormulaValue::Number(0.0))
525 }
526 }
527}
528
529struct CountFunction;
531
532impl FormulaFunction for CountFunction {
533 fn name(&self) -> &str {
534 "COUNT"
535 }
536 fn min_args(&self) -> usize {
537 1
538 }
539 fn max_args(&self) -> Option<usize> {
540 None
541 }
542
543 fn execute(&self, args: &[FormulaValue]) -> Result<FormulaValue> {
544 let mut count = 0;
545
546 for arg in args {
547 match arg {
548 FormulaValue::Number(_) => {
549 count += 1;
550 }
551 FormulaValue::Array(arr) => {
552 for row in arr {
553 for cell in row {
554 if let FormulaValue::Number(_) = cell {
555 count += 1;
556 }
557 }
558 }
559 }
560 FormulaValue::Error(e) => {
561 return Ok(FormulaValue::Error(e.clone()));
562 }
563 _ => {} }
565 }
566
567 Ok(FormulaValue::Number(count as f64))
568 }
569}
570
571struct RoundFunction;
573
574impl FormulaFunction for RoundFunction {
575 fn name(&self) -> &str {
576 "ROUND"
577 }
578 fn min_args(&self) -> usize {
579 2
580 }
581 fn max_args(&self) -> Option<usize> {
582 Some(2)
583 }
584
585 fn execute(&self, args: &[FormulaValue]) -> Result<FormulaValue> {
586 let number = args[0].as_number()?;
587 let digits = args[1].as_number()? as i32;
588
589 let multiplier = (10.0_f64).powi(digits);
590 let rounded = (number * multiplier).round() / multiplier;
591
592 Ok(FormulaValue::Number(rounded))
593 }
594}
595
596struct AbsFunction;
598
599impl FormulaFunction for AbsFunction {
600 fn name(&self) -> &str {
601 "ABS"
602 }
603 fn min_args(&self) -> usize {
604 1
605 }
606 fn max_args(&self) -> Option<usize> {
607 Some(1)
608 }
609
610 fn execute(&self, args: &[FormulaValue]) -> Result<FormulaValue> {
611 let number = args[0].as_number()?;
612 Ok(FormulaValue::Number(number.abs()))
613 }
614}
615
616struct SqrtFunction;
618
619impl FormulaFunction for SqrtFunction {
620 fn name(&self) -> &str {
621 "SQRT"
622 }
623 fn min_args(&self) -> usize {
624 1
625 }
626 fn max_args(&self) -> Option<usize> {
627 Some(1)
628 }
629
630 fn execute(&self, args: &[FormulaValue]) -> Result<FormulaValue> {
631 let number = args[0].as_number()?;
632
633 if number < 0.0 {
634 Ok(FormulaValue::Error(FormulaError::NumError))
635 } else {
636 Ok(FormulaValue::Number(number.sqrt()))
637 }
638 }
639}
640
641struct IfFunction;
643
644impl FormulaFunction for IfFunction {
645 fn name(&self) -> &str {
646 "IF"
647 }
648 fn min_args(&self) -> usize {
649 2
650 }
651 fn max_args(&self) -> Option<usize> {
652 Some(3)
653 }
654
655 fn execute(&self, args: &[FormulaValue]) -> Result<FormulaValue> {
656 let condition = args[0].as_boolean()?;
657
658 if condition {
659 Ok(args[1].clone())
660 } else if args.len() > 2 {
661 Ok(args[2].clone())
662 } else {
663 Ok(FormulaValue::Boolean(false))
664 }
665 }
666}
667
668struct AndFunction;
670
671impl FormulaFunction for AndFunction {
672 fn name(&self) -> &str {
673 "AND"
674 }
675 fn min_args(&self) -> usize {
676 1
677 }
678 fn max_args(&self) -> Option<usize> {
679 None
680 }
681
682 fn execute(&self, args: &[FormulaValue]) -> Result<FormulaValue> {
683 for arg in args {
684 if !arg.as_boolean()? {
685 return Ok(FormulaValue::Boolean(false));
686 }
687 }
688 Ok(FormulaValue::Boolean(true))
689 }
690}
691
692struct OrFunction;
694
695impl FormulaFunction for OrFunction {
696 fn name(&self) -> &str {
697 "OR"
698 }
699 fn min_args(&self) -> usize {
700 1
701 }
702 fn max_args(&self) -> Option<usize> {
703 None
704 }
705
706 fn execute(&self, args: &[FormulaValue]) -> Result<FormulaValue> {
707 for arg in args {
708 if arg.as_boolean()? {
709 return Ok(FormulaValue::Boolean(true));
710 }
711 }
712 Ok(FormulaValue::Boolean(false))
713 }
714}
715
716struct NotFunction;
718
719impl FormulaFunction for NotFunction {
720 fn name(&self) -> &str {
721 "NOT"
722 }
723 fn min_args(&self) -> usize {
724 1
725 }
726 fn max_args(&self) -> Option<usize> {
727 Some(1)
728 }
729
730 fn execute(&self, args: &[FormulaValue]) -> Result<FormulaValue> {
731 let value = args[0].as_boolean()?;
732 Ok(FormulaValue::Boolean(!value))
733 }
734}
735
736struct ConcatenateFunction;
738
739impl FormulaFunction for ConcatenateFunction {
740 fn name(&self) -> &str {
741 "CONCATENATE"
742 }
743 fn min_args(&self) -> usize {
744 1
745 }
746 fn max_args(&self) -> Option<usize> {
747 None
748 }
749
750 fn execute(&self, args: &[FormulaValue]) -> Result<FormulaValue> {
751 let mut result = String::new();
752
753 for arg in args {
754 result.push_str(&arg.as_text());
755 }
756
757 Ok(FormulaValue::Text(result))
758 }
759}
760
761struct LeftFunction;
763
764impl FormulaFunction for LeftFunction {
765 fn name(&self) -> &str {
766 "LEFT"
767 }
768 fn min_args(&self) -> usize {
769 1
770 }
771 fn max_args(&self) -> Option<usize> {
772 Some(2)
773 }
774
775 fn execute(&self, args: &[FormulaValue]) -> Result<FormulaValue> {
776 let text = args[0].as_text();
777 let num_chars = if args.len() > 1 { args[1].as_number()? as usize } else { 1 };
778
779 let result = text.chars().take(num_chars).collect::<String>();
780 Ok(FormulaValue::Text(result))
781 }
782}
783
784struct RightFunction;
786
787impl FormulaFunction for RightFunction {
788 fn name(&self) -> &str {
789 "RIGHT"
790 }
791 fn min_args(&self) -> usize {
792 1
793 }
794 fn max_args(&self) -> Option<usize> {
795 Some(2)
796 }
797
798 fn execute(&self, args: &[FormulaValue]) -> Result<FormulaValue> {
799 let text = args[0].as_text();
800 let num_chars = if args.len() > 1 { args[1].as_number()? as usize } else { 1 };
801
802 let chars: Vec<char> = text.chars().collect();
803 let start = chars.len().saturating_sub(num_chars);
804 let result = chars[start..].iter().collect::<String>();
805
806 Ok(FormulaValue::Text(result))
807 }
808}
809
810struct MidFunction;
812
813impl FormulaFunction for MidFunction {
814 fn name(&self) -> &str {
815 "MID"
816 }
817 fn min_args(&self) -> usize {
818 3
819 }
820 fn max_args(&self) -> Option<usize> {
821 Some(3)
822 }
823
824 fn execute(&self, args: &[FormulaValue]) -> Result<FormulaValue> {
825 let text = args[0].as_text();
826 let start = (args[1].as_number()? as usize).saturating_sub(1); let length = args[2].as_number()? as usize;
828
829 let chars: Vec<char> = text.chars().collect();
830 let end = (start + length).min(chars.len());
831
832 if start >= chars.len() {
833 Ok(FormulaValue::Text(String::new()))
834 } else {
835 let result = chars[start..end].iter().collect::<String>();
836 Ok(FormulaValue::Text(result))
837 }
838 }
839}
840
841struct LenFunction;
843
844impl FormulaFunction for LenFunction {
845 fn name(&self) -> &str {
846 "LEN"
847 }
848 fn min_args(&self) -> usize {
849 1
850 }
851 fn max_args(&self) -> Option<usize> {
852 Some(1)
853 }
854
855 fn execute(&self, args: &[FormulaValue]) -> Result<FormulaValue> {
856 let text = args[0].as_text();
857 Ok(FormulaValue::Number(text.chars().count() as f64))
858 }
859}
860
861struct UpperFunction;
863
864impl FormulaFunction for UpperFunction {
865 fn name(&self) -> &str {
866 "UPPER"
867 }
868 fn min_args(&self) -> usize {
869 1
870 }
871 fn max_args(&self) -> Option<usize> {
872 Some(1)
873 }
874
875 fn execute(&self, args: &[FormulaValue]) -> Result<FormulaValue> {
876 let text = args[0].as_text();
877 Ok(FormulaValue::Text(text.to_uppercase()))
878 }
879}
880
881struct LowerFunction;
883
884impl FormulaFunction for LowerFunction {
885 fn name(&self) -> &str {
886 "LOWER"
887 }
888 fn min_args(&self) -> usize {
889 1
890 }
891 fn max_args(&self) -> Option<usize> {
892 Some(1)
893 }
894
895 fn execute(&self, args: &[FormulaValue]) -> Result<FormulaValue> {
896 let text = args[0].as_text();
897 Ok(FormulaValue::Text(text.to_lowercase()))
898 }
899}
900
901#[cfg(test)]
902mod tests {
903 use super::*;
904 use crate::xlsx::cell::CellValue;
905
906 struct MockCellProvider {
907 cells: HashMap<String, CellValue>,
908 }
909
910 impl MockCellProvider {
911 fn new() -> Self {
912 let mut cells = HashMap::new();
913 cells.insert("A1".to_string(), CellValue::Number(10.0));
914 cells.insert("A2".to_string(), CellValue::Number(20.0));
915 cells.insert("A3".to_string(), CellValue::Number(30.0));
916
917 Self { cells }
918 }
919 }
920
921 impl CellProvider for MockCellProvider {
922 fn get_cell_value(&self, reference: &CellReference) -> Result<CellValue> {
923 let key = reference.to_a1();
924 Ok(self.cells.get(&key).cloned().unwrap_or(CellValue::Empty))
925 }
926
927 fn get_range_values(
928 &self,
929 start: &CellReference,
930 end: &CellReference
931 ) -> Result<Vec<Vec<CellValue>>> {
932 let mut result = Vec::new();
933
934 for row in start.row..=end.row {
935 let mut row_values = Vec::new();
936 for col in start.column..=end.column {
937 let ref_key = CellReference::new(col, row).to_a1();
938 row_values.push(self.cells.get(&ref_key).cloned().unwrap_or(CellValue::Empty));
939 }
940 result.push(row_values);
941 }
942
943 Ok(result)
944 }
945 }
946
947 #[test]
948 fn test_sum_function() {
949 let provider = Box::new(MockCellProvider::new());
950 let mut calculator = FormulaCalculator::new(provider);
951
952 let args = vec![
953 FormulaValue::Number(1.0),
954 FormulaValue::Number(2.0),
955 FormulaValue::Number(3.0)
956 ];
957
958 let result = calculator.function_library.call_function("SUM", &args).unwrap();
959 assert_eq!(result, FormulaValue::Number(6.0));
960 }
961
962 #[test]
963 fn test_if_function() {
964 let provider = Box::new(MockCellProvider::new());
965 let mut calculator = FormulaCalculator::new(provider);
966
967 let args = vec![
968 FormulaValue::Boolean(true),
969 FormulaValue::Text("Yes".to_string()),
970 FormulaValue::Text("No".to_string())
971 ];
972
973 let result = calculator.function_library.call_function("IF", &args).unwrap();
974 assert_eq!(result, FormulaValue::Text("Yes".to_string()));
975 }
976
977 #[test]
978 fn test_binary_operations() {
979 let provider = Box::new(MockCellProvider::new());
980 let mut calculator = FormulaCalculator::new(provider);
981
982 let left = FormulaValue::Number(10.0);
983 let right = FormulaValue::Number(3.0);
984
985 let result = calculator.evaluate_binary_op(&BinaryOperator::Add, &left, &right).unwrap();
986 assert_eq!(result, FormulaValue::Number(13.0));
987
988 let result = calculator.evaluate_binary_op(&BinaryOperator::Divide, &left, &right).unwrap();
989 assert_eq!(result, FormulaValue::Number(10.0 / 3.0));
990 }
991
992 #[test]
993 fn test_factorial() {
994 let provider = Box::new(MockCellProvider::new());
995 let calculator = FormulaCalculator::new(provider);
996
997 let result = calculator
999 .evaluate_unary_op(&UnaryOperator::Factorial, &FormulaValue::Number(5.0))
1000 .unwrap();
1001 assert_eq!(result, FormulaValue::Number(120.0)); let result = calculator
1004 .evaluate_unary_op(&UnaryOperator::Factorial, &FormulaValue::Number(0.0))
1005 .unwrap();
1006 assert_eq!(result, FormulaValue::Number(1.0)); let result = calculator
1010 .evaluate_unary_op(&UnaryOperator::Factorial, &FormulaValue::Number(-3.0))
1011 .unwrap();
1012 assert_eq!(result, FormulaValue::Error(FormulaError::ValueError));
1013
1014 let result = calculator
1016 .evaluate_unary_op(&UnaryOperator::Factorial, &FormulaValue::Number(3.5))
1017 .unwrap();
1018 assert_eq!(result, FormulaValue::Error(FormulaError::ValueError));
1019
1020 let result = calculator
1022 .evaluate_unary_op(&UnaryOperator::Factorial, &FormulaValue::Number(10.0))
1023 .unwrap();
1024 assert_eq!(result, FormulaValue::Number(3628800.0)); }
1026}