cell_sheet_core/formula/
functions.rs1use crate::model::{CellError, CellValue};
2
3fn collect_numbers(values: &[CellValue]) -> Result<Vec<f64>, CellError> {
4 let mut nums = Vec::new();
5 for v in values {
6 match v {
7 CellValue::Number(n) => nums.push(*n),
8 CellValue::Error(e) => return Err(e.clone()),
9 CellValue::Empty => {}
10 CellValue::Text(_) => {}
11 CellValue::Bool(_) => {}
12 }
13 }
14 Ok(nums)
15}
16
17pub fn fn_sum(values: &[CellValue]) -> CellValue {
18 match collect_numbers(values) {
19 Ok(nums) => CellValue::Number(nums.iter().sum()),
20 Err(e) => CellValue::Error(e),
21 }
22}
23
24pub fn fn_average(values: &[CellValue]) -> CellValue {
25 match collect_numbers(values) {
26 Ok(nums) if nums.is_empty() => CellValue::Error(CellError::DivZero),
27 Ok(nums) => {
28 let count = nums.len() as f64;
29 CellValue::Number(nums.iter().sum::<f64>() / count)
30 }
31 Err(e) => CellValue::Error(e),
32 }
33}
34
35pub fn fn_count(values: &[CellValue]) -> CellValue {
36 match collect_numbers(values) {
37 Ok(nums) => CellValue::Number(nums.len() as f64),
38 Err(e) => CellValue::Error(e),
39 }
40}
41
42pub fn fn_min(values: &[CellValue]) -> CellValue {
43 match collect_numbers(values) {
44 Ok(nums) if nums.is_empty() => CellValue::Number(0.0),
45 Ok(nums) => CellValue::Number(nums.iter().cloned().fold(f64::INFINITY, f64::min)),
46 Err(e) => CellValue::Error(e),
47 }
48}
49
50pub fn fn_max(values: &[CellValue]) -> CellValue {
51 match collect_numbers(values) {
52 Ok(nums) if nums.is_empty() => CellValue::Number(0.0),
53 Ok(nums) => CellValue::Number(nums.iter().cloned().fold(f64::NEG_INFINITY, f64::max)),
54 Err(e) => CellValue::Error(e),
55 }
56}
57
58pub fn fn_if(args: &[CellValue]) -> CellValue {
59 if args.len() != 3 {
60 return CellValue::Error(CellError::Value);
61 }
62 match &args[0] {
63 CellValue::Bool(true) => args[1].clone(),
64 CellValue::Bool(false) => args[2].clone(),
65 CellValue::Number(n) => {
66 if *n != 0.0 {
67 args[1].clone()
68 } else {
69 args[2].clone()
70 }
71 }
72 CellValue::Error(e) => CellValue::Error(e.clone()),
73 _ => CellValue::Error(CellError::Value),
74 }
75}