File size: 2,290 Bytes
a435638
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
// Mini Excel-like formula engine

export function evaluateFormula(formula, getCell) {
  if (!formula || typeof formula !== "string") return null;
  if (!formula.startsWith("=")) return formula;

  try {
    // Strip "="
    const expr = formula.substring(1).toUpperCase();

    // Handle SUM(A1:A5)
    if (expr.startsWith("SUM(")) return sumFunction(expr, getCell);
    if (expr.startsWith("AVG(")) return avgFunction(expr, getCell);
    if (expr.startsWith("MIN(")) return minFunction(expr, getCell);
    if (expr.startsWith("MAX(")) return maxFunction(expr, getCell);

    // Handle simple arithmetic: A1 + B2 * 3
    const parsed = expr.replace(/[A-Z]+\d+/g, (cellRef) => {
      const v = getCell(cellRef);
      return v !== undefined ? v : 0;
    });

    return eval(parsed);
  } catch (e) {
    return null;
  }
}

// ✅ Extract A1:A5 type ranges
function parseRange(ref) {
  const range = ref.replace(/[A-Z]+\(|\)|/g, "").split(":");
  return range;
}

function getRangeValues(range, getCell) {
  const [start, end] = range;
  const col1 = start.match(/[A-Z]+/)[0];
  const row1 = parseInt(start.match(/\d+/)[0]);
  const col2 = end.match(/[A-Z]+/)[0];
  const row2 = parseInt(end.match(/\d+/)[0]);

  const values = [];

  for (let r = row1; r <= row2; r++) {
    const cellRef = `${col1}${r}`;
    const v = getCell(cellRef);
    if (!isNaN(v)) values.push(Number(v));
  }
  return values;
}

// ✅ SUM
function sumFunction(expr, getCell) {
  const range = parseRange(expr.replace("SUM(", "").replace(")", ""));
  return getRangeValues(range, getCell).reduce((a, b) => a + b, 0);
}

// ✅ AVG
function avgFunction(expr, getCell) {
  const range = parseRange(expr.replace("AVG(", "").replace(")", ""));
  const values = getRangeValues(range, getCell);
  return values.reduce((a, b) => a + b, 0) / values.length;
}

// ✅ MIN
function minFunction(expr, getCell) {
  const values = getRangeValues(
    parseRange(expr.replace("MIN(", "").replace(")", "")),
    getCell
  );
  return Math.min(...values);
}

// ✅ MAX
function maxFunction(expr, getCell) {
  const values = getRangeValues(
    parseRange(expr.replace("MAX(", "").replace(")", "")),
    getCell
  );
  return Math.max(...values);
}