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);