Skip to main content

cell_sheet_core/formula/
functions.rs

1use 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}