spreadsheet
typeScript/javascript spreadsheet parser, with formulas.
git clone https://git.vogt.world/spreadsheet.git
Log | Files | README.md
← Commit log
commit
message
[COUNTIFS, README.md] Formula now accepts nested ranges/arrays, adding TODO to README.md
author
Ben Vogt <[email protected]>
date
2017-05-01 23:40:16
stats
3 file(s) changed, 28 insertions(+), 9 deletions(-)
files
README.md
src/Formulas/Math.ts
tests/Formulas/MathTest.ts
 1diff --git a/README.md b/README.md
 2index ba89d27..82e43fd 100644
 3--- a/README.md
 4+++ b/README.md
 5@@ -46,3 +46,6 @@ Right now we're just using the number of days since 1900, but we should check th
 6 ### Ensure all formulas are tested inside of SheetFormulaTest.ts
 7 
 8 ### Test all functions in src/Utilities
 9+
10+### Sheet.ts and parser.js should be able to concatenate strings
11+E.g. `=COUNTIFS(A7:A24, ">6", B7:B24, "<"&DATE(1969,7,20))`
12\ No newline at end of file
13diff --git a/src/Formulas/Math.ts b/src/Formulas/Math.ts
14index 2653a6b..80a582f 100644
15--- a/src/Formulas/Math.ts
16+++ b/src/Formulas/Math.ts
17@@ -609,7 +609,6 @@ var COUNTIF = function (...values) {
18  * @param values[2...N] Repeated sets of ranges and criterion to check.
19  * @returns {number} count
20  * @constructor
21- * TODO: This needs to take nested range values.
22  */
23 var COUNTIFS = function (...values) {
24   ArgsChecker.checkAtLeastLength(values, 2);
25@@ -620,19 +619,28 @@ var COUNTIFS = function (...values) {
26       return function () {return false;}
27     }
28   });
29-
30+  var filteredValues = [];
31+  // Flatten arrays/ranges
32+  for (var x = 0; x < values.length; x++) {
33+    // If this is an array/range parameter
34+    if (x % 2 === 0) {
35+      filteredValues.push(Filter.flatten(values[x]));
36+    } else {
37+      filteredValues.push(values[x]);
38+    }
39+  }
40   var count = 0;
41   // For every value in the range
42-  for (var i = 0; i < values[0].length; i++) {
43-    // check for criteria eval for other ranges and other criteria pairs
44+  for (var i = 0; i < filteredValues[0].length; i++) {
45+    // Check for criteria eval for other ranges and other criteria pairs.
46     var otherCriteriaEvaluationSuccessfulSoFar = true;
47-    for (var x = 0; x < values.length; x += 2) {
48-      if (values[x].length < values[0].length) {
49+    for (var x = 0; x < filteredValues.length; x += 2) {
50+      if (filteredValues[x].length < filteredValues[0].length) {
51         throw new ValueError("Array arguments to COUNTIFS are of different size.");
52       }
53       var criteriaEvaluation = criteriaEvaluationFunctions[x+1];
54       if (otherCriteriaEvaluationSuccessfulSoFar) {
55-        if (!criteriaEvaluation(values[x][i])) { // evaluate THIS value with x+1 index, which is criteria
56+        if (!criteriaEvaluation(filteredValues[x][i])) { // evaluate THIS value with x+1 index, which is criteria.
57           otherCriteriaEvaluationSuccessfulSoFar = false;
58         }
59       }
60diff --git a/tests/Formulas/MathTest.ts b/tests/Formulas/MathTest.ts
61index 65081a0..6ae5f6b 100644
62--- a/tests/Formulas/MathTest.ts
63+++ b/tests/Formulas/MathTest.ts
64@@ -411,6 +411,12 @@ test("COUNTIFS", function(){
65   assertEquals(COUNTIFS(["mom", "pop", "dad", "etc", "mom"], "????"), 0);
66   assertEquals(COUNTIFS(["mom", "pop", "dad", "etc", "mom"], "?"), 0);
67   // Now actually test COUNTIFS
68+  assertEquals(COUNTIFS([1, 5, 5, [5, 5, 5, 5], 10, 5], "= 5"), 7);
69+  assertEquals(COUNTIFS([1, 5, 5, [5, 5, 5, 5], [], 10, 5], "= 5"), 7);
70+  assertEquals(COUNTIFS([1, 5, 5, [5, 5, 5, 5], [], 10, 8], "> 4", [false, false, false, [true, true, true, true], [], false, false], "= true"), 0);
71+  assertEquals(COUNTIFS([1, 5, 5, [5, 5, 5, 5], [], 10, 8], "> 4", [false, false, false, ["A", "A", "A", "A"], [], false, false], "= 'A'"), 0);
72+  assertEquals(COUNTIFS([1, 5, 5, [5, 5, 5, 5], [], 10, 8], "> 4", [1, 5, 5, [5, 5, 5, 5], [], 10, 8], "> 5"), 2);
73+  assertEquals(COUNTIFS([1, 5, 5, [5, 5, "5", "5.000"], [], 10, 5], "= 5"), 7);
74   assertEquals(COUNTIFS([1, 5, 10, 20], ">4", [0, 0, 1, 1], "=1"), 2);
75   assertEquals(COUNTIFS([1, 5, 10, 20], ">4", [0, 0, 1, 1], "=1"), 2);
76   assertEquals(COUNTIFS([1, 5, 10, 20], ">4", [0, 0, 1, 1], "=1", [0, 0, 1, 1], "=1"), 2);