spreadsheet
typeScript/javascript spreadsheet parser, with formulas.
git clone https://git.vogt.world/spreadsheet.git
Log | Files | README.md
← Commit log
commit
message
Adding Formula.SQRT, fixing tests for others
author
Ben Vogt <[email protected]>
date
2017-02-04 17:54:35
stats
3 file(s) changed, 68 insertions(+), 14 deletions(-)
files
src/RawFormulas/Math.ts
src/RawFormulas/RawFormulas.ts
tests/FormulasTest.ts
  1diff --git a/src/RawFormulas/Math.ts b/src/RawFormulas/Math.ts
  2index 47f91e9..4846433 100644
  3--- a/src/RawFormulas/Math.ts
  4+++ b/src/RawFormulas/Math.ts
  5@@ -5,14 +5,14 @@ import * as ERRORS from "../Errors"
  6 
  7 /**
  8  * Returns the absolute value of a number.
  9- * @param value to get the absolute value of.
 10+ * @param values[0] to get the absolute value of.
 11  * @returns {number} absolute value
 12  * @constructor
 13  */
 14-var ABS = function (value?) {
 15-  checkArgumentsLength(arguments, 1);
 16-  value = valueToNumber(value);
 17-  return Math.abs(value);
 18+var ABS = function (...values) {
 19+  checkArgumentsLength(values, 1);
 20+  var v = valueToNumber(values[0]);
 21+  return Math.abs(v);
 22 };
 23 
 24 /**
 25@@ -335,9 +335,6 @@ var MAXA = function (...values) : number {
 26  */
 27 var MEDIAN = function (...values) : number {
 28   checkArgumentsAtLeastLength(values, 1);
 29-  if (values.length === 1) {
 30-    return valueToNumber(values[0]);
 31-  }
 32   var sortedArray = [];
 33   values.forEach(function (currentValue) {
 34     if (currentValue instanceof Array) {
 35@@ -355,6 +352,12 @@ var MEDIAN = function (...values) : number {
 36     var bN = valueToNumber(b);
 37     return aN - bN;
 38   });
 39+  if (sortedArray.length === 1) {
 40+    return valueToNumber(sortedArray[0]);
 41+  }
 42+  if (sortedArray.length === 0) {
 43+    throw new CellError(ERRORS.NUM_ERROR, "MEDIAN has no valid input data.");
 44+  }
 45   // even number of values
 46   if (sortedArray.length % 2 === 0) {
 47     if (sortedArray.length === 2) {
 48@@ -455,6 +458,9 @@ var SUM = function (...values) : number {
 49     if (values[i] instanceof Array) {
 50       result = result + SUM.apply(this, values[i]);
 51     } else {
 52+      if (values[i] === "") {
 53+        throw new CellError(ERRORS.VALUE_ERROR, "Function SUM parameter "+i+" expects number values. But '"+values[i]+"' is a text and cannot be coerced to a number.");
 54+      }
 55       result = result + valueToNumber(values[i]);
 56     }
 57   }
 58diff --git a/src/RawFormulas/RawFormulas.ts b/src/RawFormulas/RawFormulas.ts
 59index a9a5034..e993bf5 100644
 60--- a/src/RawFormulas/RawFormulas.ts
 61+++ b/src/RawFormulas/RawFormulas.ts
 62@@ -68,6 +68,9 @@ var CEILINGPRECISE = Formula["CEILINGPRECISE"];
 63 var CHAR = function (...values) : string {
 64   checkArgumentsLength(values, 1);
 65   var n = firstValueAsNumber(values[0]);
 66+  if (n < 1 || n > 1114112) { //limit
 67+    throw new CellError(ERRORS.NUM_ERROR, "Function CHAR parameter 1 value " + n + " is out of range.");
 68+  }
 69   return String.fromCharCode(n);
 70 };
 71 
 72@@ -80,6 +83,9 @@ var CHAR = function (...values) : string {
 73 var CODE = function (...values) : number {
 74   checkArgumentsLength(values, 1);
 75   var text = firstValueAsString(values[0]);
 76+  if (text === "") {
 77+    throw new CellError(ERRORS.VALUE_ERROR, "Function CODE parameter 1 value should be non-empty.");
 78+  }
 79   return text.charCodeAt(0);
 80 };
 81 var COMBIN = Formula["COMBIN"];
 82@@ -217,7 +223,7 @@ var INT = function (...values) : number {
 83 var ISEVEN = function (...values) : boolean {
 84   checkArgumentsLength(values, 1);
 85   if (values[0] === "") {
 86-    throw new CellError(ERRORS.VALUE_ERROR, "Function ISEVEN parameter 1 expects boolean values. But '" + values[0] + "' is a text and cannot be coerced to a boolean.")
 87+    throw new CellError(ERRORS.VALUE_ERROR, "Function ISEVEN parameter 1 expects boolean values. But '" + values[0] + "' is a text and cannot be coerced to a boolean.");
 88   }
 89   var x = firstValueAsNumber(values[0]);
 90   return Math.floor(x) % 2 === 0;
 91@@ -233,7 +239,7 @@ var ISEVEN = function (...values) : boolean {
 92 var ISODD = function (...values) : boolean {
 93   checkArgumentsLength(values, 1);
 94   if (values[0] === "") {
 95-    throw new CellError(ERRORS.VALUE_ERROR, "Function ISODD parameter 1 expects boolean values. But '" + values[0] + "' is a text and cannot be coerced to a boolean.")
 96+    throw new CellError(ERRORS.VALUE_ERROR, "Function ISODD parameter 1 expects boolean values. But '" + values[0] + "' is a text and cannot be coerced to a boolean.");
 97   }
 98   var x = firstValueAsNumber(values[0]);
 99   return Math.floor(x) % 2 === 1;
100@@ -275,7 +281,23 @@ var SINH = function (...values) : number {
101 
102 
103 var SPLIT = Formula["SPLIT"];
104-var SQRT = Formula["SQRT"];
105+
106+
107+/**
108+ * Returns the positive square root of a positive number.
109+ * @param values[0] The number for which to calculate the positive square root.
110+ * @returns {number} square root
111+ * @constructor
112+ */
113+var SQRT = function (...values) : number {
114+  checkArgumentsLength(values, 1);
115+  var x = firstValueAsNumber(values[0]);
116+  if (x < 0) {
117+    throw new CellError(ERRORS.VALUE_ERROR, "Function SQRT parameter 1 expects number values. But '" + values[0] + "' is a text and cannot be coerced to a number.");
118+  }
119+  return Math.sqrt(x);
120+};
121+
122 var SQRTPI = Formula["SQRTPI"];
123 var SUMIF = Formula["SUMIF"];
124 var SUMPRODUCT = Formula["SUMPRODUCT"];
125diff --git a/tests/FormulasTest.ts b/tests/FormulasTest.ts
126index 2bcd2e8..e98a0f0 100644
127--- a/tests/FormulasTest.ts
128+++ b/tests/FormulasTest.ts
129@@ -14,13 +14,18 @@ import {assertEquals, assertEqualsDates, assertArrayEquals} from "./utils/Assert
130 import {firstValueAsNumber} from "../src/RawFormulas/Utils";
131 
132 function catchAndAssertEquals(toExecute, expected) {
133+  var toThrow = null;
134   try {
135     toExecute();
136+    toThrow = true;
137   } catch (actualError) {
138     if (actualError.message != expected) {
139       console.log(expected, "not equal to", actualError.message);
140     }
141   }
142+  if (toThrow) {
143+    throw new Error("expected error: " + expected);
144+  }
145 }
146 
147 // Test ABS
148@@ -207,7 +212,7 @@ catchAndAssertEquals(function() {
149   AVEDEV(10, 10, "str");
150 }, ERRORS.VALUE_ERROR);
151 catchAndAssertEquals(function() {
152-  AVEDEV(10, 10, {});
153+  AVEDEV(10, 10, []);
154 }, ERRORS.REF_ERROR);
155 
156 
157@@ -675,9 +680,6 @@ catchAndAssertEquals(function() {
158 }, ERRORS.VALUE_ERROR);
159 assertEquals(MEDIAN(1, 1, 2, [5, "mmm", 6, 6, 9]), 5);
160 assertEquals(MEDIAN(1, 1, 2, ["mm"]), 1);
161-catchAndAssertEquals(function() {
162-  MEDIAN(1, 1, 2, ["mm"]);
163-}, ERRORS.REF_ERROR);
164 assertEquals(MEDIAN(100, 22, 1, 14), 18);
165 assertEquals(MEDIAN(100, 22, 1, 1), 11.5);
166 assertEquals(MEDIAN(100, 22, 1), 22);
167@@ -857,7 +859,27 @@ assertEquals(SINH([[10, "str"]]), 11013.232874703393);
168 
169 assertArrayEquals(SPLIT("1,2,3", ",", true), [ '1', '2', '3' ]);
170 
171+
172+// Test SQRT
173 assertEquals(SQRT(9), 3);
174+assertEquals(SQRT("9"), 3);
175+assertEquals(SQRT(4), 2);
176+assertEquals(SQRT(false), 0);
177+assertEquals(SQRT(true), 1);
178+assertEquals(SQRT(""), 0);
179+catchAndAssertEquals(function() {
180+  SQRT("str");
181+}, ERRORS.VALUE_ERROR);
182+catchAndAssertEquals(function() {
183+  SQRT(-9);
184+}, ERRORS.VALUE_ERROR);
185+catchAndAssertEquals(function() {
186+  SQRT();
187+}, ERRORS.NA_ERROR);
188+catchAndAssertEquals(function() {
189+  SQRT(4, 4);
190+}, ERRORS.NA_ERROR);
191+
192 
193 assertEquals(SQRTPI(9), 5.317361552716548);
194