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