spreadsheet
typeScript/javascript spreadsheet parser, with formulas.
git clone https://git.vogt.world/spreadsheet.git
Log | Files | README.md
← Commit log
commit
message
Added Formulas.COUNTUNIQUE
author
Ben Vogt <[email protected]>
date
2017-02-18 21:54:54
stats
3 file(s) changed, 62 insertions(+), 3 deletions(-)
files
src/RawFormulas/RawFormulas.ts
src/RawFormulas/Utils.ts
tests/FormulasTest.ts
  1diff --git a/src/RawFormulas/RawFormulas.ts b/src/RawFormulas/RawFormulas.ts
  2index 1e075cb..4343863 100644
  3--- a/src/RawFormulas/RawFormulas.ts
  4+++ b/src/RawFormulas/RawFormulas.ts
  5@@ -85,7 +85,8 @@ import {
  6   CriteriaFunctionFactory,
  7   ArgsChecker,
  8   Filter,
  9-  TypeCaster
 10+  TypeCaster,
 11+  Serializer
 12 } from "./Utils";
 13 import {CellError, NUM_ERROR} from "../Errors"
 14 import * as ERRORS from "../Errors"
 15@@ -95,7 +96,6 @@ var ACCRINT = Formula["ACCRINT"];
 16 var COMBIN = Formula["COMBIN"];
 17 var CONVERT = Formula["CONVERT"];
 18 var CORREL = Formula["CORREL"];
 19-var COUNTUNIQUE = Formula["COUNTUNIQUE"];
 20 var COVARIANCEP = Formula["COVARIANCEP"];
 21 var COVARIANCES = Formula["COVARIANCES"];
 22 var CUMIPMT = Formula["CUMIPMT"];
 23@@ -132,6 +132,42 @@ var SUMX2MY2 = Formula["SUMX2MY2"];
 24 var SUMX2PY2 = Formula["SUMX2PY2"];
 25 var YEARFRAC = Formula["YEARFRAC"];
 26 
 27+
 28+/**
 29+ * Counts the number of unique values in a list of specified values and ranges.
 30+ * @param values The values or ranges to consider for uniqueness. Supports an arbitrary number of arguments for this
 31+ * function.
 32+ * @returns {number} of unique values passed in.
 33+ * @constructor
 34+ */
 35+var COUNTUNIQUE = function (...values) : number {
 36+  ArgsChecker.checkAtLeastLength(values, 1);
 37+
 38+  // Private function that will recursively generate an array of the unique primatives
 39+  var countUniquePrivate = function (values: Array<any>) : Object {
 40+    var uniques = {};
 41+    for (var i = 0; i < values.length; i++) {
 42+      if (Array.isArray(values[i])) {
 43+        // For some reasons an empty range is converted to a range with a single empty string in it.
 44+        if (values[i].length === 0) {
 45+          values[i] = [""];
 46+        }
 47+        var uniquesOfArray = countUniquePrivate(values[i]);
 48+        for (var key in uniquesOfArray) {
 49+          uniques[key] = true;
 50+        }
 51+      } else {
 52+        uniques[Serializer.serialize(values[i])] = true;
 53+      }
 54+    }
 55+    return uniques;
 56+  };
 57+
 58+  var uniques = countUniquePrivate(values);
 59+  return Object.keys(uniques).length;
 60+};
 61+
 62+
 63 /**
 64  * Calculates the sum of the products of corresponding entries in two equal-sized arrays or ranges.
 65  * @param values Arrays or ranges whose entries will be multiplied with corresponding entries in the second such array
 66diff --git a/src/RawFormulas/Utils.ts b/src/RawFormulas/Utils.ts
 67index a135858..003b260 100644
 68--- a/src/RawFormulas/Utils.ts
 69+++ b/src/RawFormulas/Utils.ts
 70@@ -351,12 +351,22 @@ class ArgsChecker {
 71       throw new CellError(ERRORS.NA_ERROR, "Wrong number of arguments to ___. Expected 1 arguments, but got " + args.length + " arguments.");
 72     }
 73   }
 74-  }
 75+}
 76 
 77+/**
 78+ * Class to hold static methods for serialization.
 79+ */
 80+class Serializer {
 81+  static serialize(value: any) : string {
 82+    var t = typeof value;
 83+    return "<" +  t + ": " + value + ">";
 84+  }
 85+}
 86 
 87 export {
 88   ArgsChecker,
 89   CriteriaFunctionFactory,
 90   Filter,
 91+  Serializer,
 92   TypeCaster
 93 }
 94\ No newline at end of file
 95diff --git a/tests/FormulasTest.ts b/tests/FormulasTest.ts
 96index 8a2341a..396d8c2 100644
 97--- a/tests/FormulasTest.ts
 98+++ b/tests/FormulasTest.ts
 99@@ -635,7 +635,19 @@ catchAndAssertEquals(function() {
100   COUNTIFS([1, 5, 10, 20], ">4", [0, 0], "=1");
101 }, ERRORS.VALUE_ERROR);
102 
103+// Test COUNTUNIQUE
104 assertEquals(COUNTUNIQUE([1, 1, 10]), 2);
105+assertEquals(COUNTUNIQUE(["1", 1, 10]), 3);
106+assertEquals(COUNTUNIQUE(["1", 1, 10, ""]), 4);
107+assertEquals(COUNTUNIQUE(["1", 1, 10, "", ""]), 4);
108+assertEquals(COUNTUNIQUE(["1", 1, 10, "", " "]), 5);
109+assertEquals(COUNTUNIQUE(["1", 1, 10, []]), 4);
110+assertEquals(COUNTUNIQUE(["", " ", [""], []]), 2);
111+assertEquals(COUNTUNIQUE([[""], []]), 1);
112+catchAndAssertEquals(function() {
113+  COUNTUNIQUE();
114+}, ERRORS.NA_ERROR);
115+
116 
117 assertEquals(COVARIANCEP([3,2,4,5,6], [9,7,12,15,17]), 5.2);
118