spreadsheet
typeScript/javascript spreadsheet parser, with formulas.
git clone https://git.vogt.world/spreadsheet.git
Log | Files | README.md
← Commit log
commit
message
[CHOOSE] formula added and tested, mostly, see TODO.md for more information
author
Ben Vogt <[email protected]>
date
2017-05-30 00:15:40
stats
9 file(s) changed, 118 insertions(+), 5 deletions(-)
files
DOCS.md
TODO.md
dist/Formulas/AllFormulas.js
dist/Formulas/Lookup.js
src/Formulas/AllFormulas.ts
src/Formulas/Info.ts
src/Formulas/Lookup.ts
tests/Formulas/LookupTest.ts
tests/SheetFormulaTest.ts
  1diff --git a/DOCS.md b/DOCS.md
  2index 43c43fe..6ac27ce 100644
  3--- a/DOCS.md
  4+++ b/DOCS.md
  5@@ -511,6 +511,17 @@
  6 @returns {boolean} returns true if only one input is considered logically true. 
  7 @constructor
  8 ```
  9+## Lookup
 10+
 11+
 12+### CHOOSE 
 13+
 14+```
 15+  Returns an element from a list of choices based on index. 
 16+@param index - Which choice to return. 
 17+@param values -  Array of potential value to return. Required. May be a reference to a cell or an individual value. 
 18+@constructor TODO: This does not currently work with the parser. See TODO.md for more information.
 19+```
 20 ## Math
 21 
 22 
 23diff --git a/TODO.md b/TODO.md
 24index cb52986..20859ba 100644
 25--- a/TODO.md
 26+++ b/TODO.md
 27@@ -5,6 +5,14 @@
 28 Instead of having non-primitives, (i.e. Date, DateTime, Time, Dollar), cells should have formats based on the highest-order type that was used during the compilation and execution of a cell's dependency. For example, `DATE` might return a number, but the cell that called `DATE` would be aware of it calling a formula that returns an non-primitive type, and would display the returned number as a Date. If you're using `DATE` in conjunction with `DOLLAR` it would still display the returned value as a Date. The hierarchy would look like: [Date, DateTime, Time, Dollar, number, boolean, string]. Advantages to this would include not having to cast down when using primitive operators, and flexibility in display. It would also simplify the types themselves, by having types be constants and just having helpers to convert, display, and do normal operations with them.
 29 
 30 
 31+### Sheet should automatically parse some values, unless told otherwises.
 32+When entering raw values into cells, if the value is a string, the Sheet should automatically attempt to convert to a number. For example, `= 10e2` should be be evaluated with a RegEx and converted to a number. See `Sheet.helper.number`.
 33+
 34+
 35+### Parser should be able to detect arrays following numbers when passing in arguments.
 36+For example the CHOOSE formula can't be parsed: `=CHOOSE(2, [1, 2, 3])`.
 37+
 38+
 39 ### Cell.rawFormulaText does not get reset when updating a cell for the second time.
 40 
 41 
 42@@ -32,7 +40,6 @@ For example 64 tbs to a qt.
 43 * CELL
 44 * IFERROR
 45 * ADDRESS
 46-* CHOOSE
 47 * COLUMN
 48 * COLUMNS
 49 * HLOOKUP
 50diff --git a/dist/Formulas/AllFormulas.js b/dist/Formulas/AllFormulas.js
 51index 94e934d..0992648 100644
 52--- a/dist/Formulas/AllFormulas.js
 53+++ b/dist/Formulas/AllFormulas.js
 54@@ -66,6 +66,8 @@ exports.LTE = Math_1.LTE;
 55 exports.NE = Math_1.NE;
 56 var Info_1 = require("./Info");
 57 exports.NA = Info_1.NA;
 58+var Lookup_1 = require("./Lookup");
 59+exports.CHOOSE = Lookup_1.CHOOSE;
 60 var Logical_1 = require("./Logical");
 61 exports.AND = Logical_1.AND;
 62 exports.EXACT = Logical_1.EXACT;
 63diff --git a/dist/Formulas/Lookup.js b/dist/Formulas/Lookup.js
 64new file mode 100644
 65index 0000000..ee3cfb9
 66--- /dev/null
 67+++ b/dist/Formulas/Lookup.js
 68@@ -0,0 +1,26 @@
 69+"use strict";
 70+exports.__esModule = true;
 71+var ArgsChecker_1 = require("../Utilities/ArgsChecker");
 72+var Errors_1 = require("../Errors");
 73+var TypeConverter_1 = require("../Utilities/TypeConverter");
 74+/**
 75+ * Returns an element from a list of choices based on index.
 76+ * @param index - Which choice to return.
 77+ * @param values -  Array of potential value to return. Required. May be a reference to a cell or an individual value.
 78+ * @constructor
 79+ * TODO: This does not currently work with the parser. See TODO.md for more information.
 80+ */
 81+var CHOOSE = function (index) {
 82+    var values = [];
 83+    for (var _i = 1; _i < arguments.length; _i++) {
 84+        values[_i - 1] = arguments[_i];
 85+    }
 86+    ArgsChecker_1.ArgsChecker.checkAtLeastLength(arguments, 2, "NA");
 87+    var i = Math.floor(TypeConverter_1.TypeConverter.firstValueAsNumber(index));
 88+    if (i < 1 || i > values.length) {
 89+        throw new Errors_1.NumError("Function CHOOSE parameter 1 value is " + i + ". Valid values are between 1 and "
 90+            + (values.length) + " inclusive.");
 91+    }
 92+    return values[i - 1];
 93+};
 94+exports.CHOOSE = CHOOSE;
 95diff --git a/src/Formulas/AllFormulas.ts b/src/Formulas/AllFormulas.ts
 96index bc2e10c..f35efc1 100644
 97--- a/src/Formulas/AllFormulas.ts
 98+++ b/src/Formulas/AllFormulas.ts
 99@@ -66,6 +66,9 @@ import {
100 import {
101   NA
102 } from "./Info";
103+import {
104+  CHOOSE
105+} from "./Lookup";
106 import {
107   AND,
108   EXACT,
109@@ -295,5 +298,6 @@ export {
110   LT,
111   LTE,
112   NE,
113-  NA
114+  NA,
115+  CHOOSE
116 }
117\ No newline at end of file
118diff --git a/src/Formulas/Info.ts b/src/Formulas/Info.ts
119index d03c506..3ea5bbc 100644
120--- a/src/Formulas/Info.ts
121+++ b/src/Formulas/Info.ts
122@@ -2,10 +2,6 @@ import {
123   ArgsChecker
124 } from "../Utilities/ArgsChecker";
125 import {
126-  NumError,
127-  DivZeroError,
128-  RefError,
129-  ValueError,
130   NAError
131 } from "../Errors";
132 
133diff --git a/src/Formulas/Lookup.ts b/src/Formulas/Lookup.ts
134new file mode 100644
135index 0000000..683ed9e
136--- /dev/null
137+++ b/src/Formulas/Lookup.ts
138@@ -0,0 +1,32 @@
139+import {
140+  ArgsChecker
141+} from "../Utilities/ArgsChecker";
142+import {
143+  NumError
144+} from "../Errors";
145+import {
146+  TypeConverter
147+} from "../Utilities/TypeConverter";
148+
149+
150+/**
151+ * Returns an element from a list of choices based on index.
152+ * @param index - Which choice to return.
153+ * @param values -  Array of potential value to return. Required. May be a reference to a cell or an individual value.
154+ * @constructor
155+ * TODO: This does not currently work with the parser. See TODO.md for more information.
156+ */
157+var CHOOSE = function (index, ...values) {
158+  ArgsChecker.checkAtLeastLength(arguments, 2, "NA");
159+  var i = Math.floor(TypeConverter.firstValueAsNumber(index));
160+  if (i < 1 || i > values.length) {
161+    throw new NumError("Function CHOOSE parameter 1 value is " + i + ". Valid values are between 1 and "
162+        + (values.length) + " inclusive.");
163+  }
164+  return values[i-1];
165+};
166+
167+
168+export {
169+  CHOOSE
170+}
171\ No newline at end of file
172diff --git a/tests/Formulas/LookupTest.ts b/tests/Formulas/LookupTest.ts
173new file mode 100644
174index 0000000..cd62bfb
175--- /dev/null
176+++ b/tests/Formulas/LookupTest.ts
177@@ -0,0 +1,27 @@
178+import {
179+  CHOOSE
180+} from "../../src/Formulas/Lookup";
181+import * as ERRORS from "../../src/Errors";
182+import {
183+  catchAndAssertEquals,
184+  test,
185+  assertEquals
186+} from "../Utils/Asserts";
187+
188+
189+test("CHOOSE", function(){
190+  assertEquals(CHOOSE.apply(this, [1, 1, 2, 3]), 1);
191+  assertEquals(CHOOSE.apply(this, [2, 1, 2, 3]), 2);
192+  catchAndAssertEquals(function() {
193+    CHOOSE.apply(this, []);
194+  }, ERRORS.NA_ERROR);
195+  catchAndAssertEquals(function() {
196+    CHOOSE.apply(this, [1]);
197+  }, ERRORS.NA_ERROR);
198+  catchAndAssertEquals(function() {
199+    CHOOSE.apply(this, [4, 1, 2, 3]);
200+  }, ERRORS.NUM_ERROR);
201+  catchAndAssertEquals(function() {
202+    CHOOSE.apply(this, [0, 1, 2, 3]);
203+  }, ERRORS.NUM_ERROR);
204+});
205diff --git a/tests/SheetFormulaTest.ts b/tests/SheetFormulaTest.ts
206index 7d56ccf..c845bb1 100644
207--- a/tests/SheetFormulaTest.ts
208+++ b/tests/SheetFormulaTest.ts
209@@ -154,6 +154,11 @@ test("Sheet CORREL", function(){
210   assertFormulaEquals('=CORREL([9, 5],[10, 4])', 1);
211 });
212 
213+// TODO: Formula will not parse because lexer does not expect array values to occur after a comma
214+// test("Sheet CHOOSE", function(){
215+//   assertFormulaEquals('=CHOOSE(2, [1, 2, 3])', 2);
216+// });
217+
218 test("Sheet COS", function(){
219   assertFormulaEquals("=COS(PI())", -1);
220 });