commit
message
[TYPE] formula added and tested
author
Ben Vogt <[email protected]>
date
2017-07-10 01:02:27
stats
8 file(s) changed,
117 insertions(+),
6 deletions(-)
files
DOCS.md
TODO.md
dist/Formulas/AllFormulas.js
dist/Formulas/Info.js
src/Formulas/AllFormulas.ts
src/Formulas/Info.ts
tests/Formulas/InfoTest.ts
tests/SheetFormulaTest.ts
1diff --git a/DOCS.md b/DOCS.md
2index e370f67..40f2d0f 100644
3--- a/DOCS.md
4+++ b/DOCS.md
5@@ -675,6 +675,15 @@
6 @returns {any}
7 @constructor TODO: This formula needs to be called from inside a try-catch-block in the SheetParser, like ERROR.TYPE.
8 ```
9+
10+### TYPE
11+
12+```
13+ Returns a number corresponding to the type of data passed into the function. 1 = number, 2 = text, 4 = boolean, 16 = error, 64 = arrayrange, 128 = any other type of cell.
14+@param value - Value for which the type will be determined.
15+@returns {number}
16+@constructor
17+```
18 ## Logical
19
20
21diff --git a/TODO.md b/TODO.md
22index e59ed99..a1323f1 100644
23--- a/TODO.md
24+++ b/TODO.md
25@@ -39,9 +39,8 @@ See documentation for ERROR.TYPE for more information.
26 Many of these formulas can be written by allowing the Sheet and Parser to return Cell objects in addition to primitive types. There are some memory issues with doing this. If a user calls something like `ISNA(A1:A99999)` we really only need the first cell. So we should return cell objects in some cases, but it would be easier in most cases to have context aware formulas, so if they need a cell, or a reference, we simply skip looking up a reference, and instead return a reference, or just a single cell. One way to do this would be to have formula functions, and then on the side have formula args. So before we lookup a large range of cells, we can check to see if it needs all of them, or if it just cares about the first one. So for `ISNA` we could look at `FormulaArgs.ISNA[0]` to get `Value` so we know that it needs only a single argument that is not an array, so if we call it with `ISNA(A1:A99999)`, it would really only lookup `A1`. This might be premature optimization however.
27
28 * ISFORMULA - Requires changes to Parser/Sheet to fetch a cell, and check the formula field to see if it contains a formula.
29-* TYPE - Requires changes to Parser/Sheet to allow for values or cells to be returned to the function. If it's a value, return the value type. If it's a cell, return the value or error inside it.
30 * CELL - Requires changes to Parser/Sheet so that the raw cell is returned to the function. The raw cell should contain all information necessary for returning specified info.
31-* ADDRESS
32+* ADDRESS - In order to implement this, cells need to be aware of their sheet.
33 * COLUMN
34 * COLUMNS
35 * HLOOKUP
36diff --git a/dist/Formulas/AllFormulas.js b/dist/Formulas/AllFormulas.js
37index 33b01f3..c172082 100644
38--- a/dist/Formulas/AllFormulas.js
39+++ b/dist/Formulas/AllFormulas.js
40@@ -95,6 +95,7 @@ exports.ISERR = Info_1.ISERR;
41 exports.ISERROR = Info_1.ISERROR;
42 exports.ISNA = Info_1.ISNA;
43 exports.IFERROR = Info_1.IFERROR;
44+exports.TYPE = Info_1.TYPE;
45 var Lookup_1 = require("./Lookup");
46 exports.CHOOSE = Lookup_1.CHOOSE;
47 var Logical_1 = require("./Logical");
48diff --git a/dist/Formulas/Info.js b/dist/Formulas/Info.js
49index d0d5466..c3120fd 100644
50--- a/dist/Formulas/Info.js
51+++ b/dist/Formulas/Info.js
52@@ -284,3 +284,39 @@ var IFERROR = function (value, valueIfError) {
53 return ISERROR(value) ? valueIfError : value;
54 };
55 exports.IFERROR = IFERROR;
56+/**
57+ * Returns a number corresponding to the type of data passed into the function. 1 = number, 2 = text, 4 = boolean,
58+ * 16 = error, 64 = array/range, 128 = any other type of cell.
59+ * @param value - Value for which the type will be determined.
60+ * @returns {number}
61+ * @constructor
62+ */
63+var TYPE = function (value) {
64+ ArgsChecker_1.ArgsChecker.checkLengthWithin(arguments, 1, 2, "TYPE");
65+ if (value instanceof Cell_1.Cell) {
66+ if (value.hasError()) {
67+ return 16;
68+ }
69+ value = value.getValue();
70+ }
71+ if (value === null) {
72+ return 1;
73+ }
74+ if (typeof value === "number") {
75+ return 1;
76+ }
77+ if (typeof value === "string") {
78+ return 2;
79+ }
80+ if (typeof value === "boolean") {
81+ return 4;
82+ }
83+ if (value instanceof Error) {
84+ return 16;
85+ }
86+ if (value instanceof Array) {
87+ return 64;
88+ }
89+ return 128;
90+};
91+exports.TYPE = TYPE;
92diff --git a/src/Formulas/AllFormulas.ts b/src/Formulas/AllFormulas.ts
93index 6747737..c1a7e50 100644
94--- a/src/Formulas/AllFormulas.ts
95+++ b/src/Formulas/AllFormulas.ts
96@@ -94,7 +94,8 @@ import {
97 ISERR,
98 ISERROR,
99 ISNA,
100- IFERROR
101+ IFERROR,
102+ TYPE
103 } from "./Info";
104 import {
105 CHOOSE
106@@ -439,5 +440,6 @@ export {
107 ISERR,
108 ISERROR,
109 ISNA,
110- IFERROR
111+ IFERROR,
112+ TYPE
113 }
114\ No newline at end of file
115diff --git a/src/Formulas/Info.ts b/src/Formulas/Info.ts
116index d5fffc0..8984e43 100644
117--- a/src/Formulas/Info.ts
118+++ b/src/Formulas/Info.ts
119@@ -302,6 +302,43 @@ var IFERROR = function (value, valueIfError?) {
120 };
121
122
123+/**
124+ * Returns a number corresponding to the type of data passed into the function. 1 = number, 2 = text, 4 = boolean,
125+ * 16 = error, 64 = array/range, 128 = any other type of cell.
126+ * @param value - Value for which the type will be determined.
127+ * @returns {number}
128+ * @constructor
129+ */
130+var TYPE = function (value) {
131+ ArgsChecker.checkLengthWithin(arguments, 1, 2, "TYPE");
132+ if (value instanceof Cell) {
133+ if (value.hasError()) {
134+ return 16;
135+ }
136+ value = value.getValue();
137+ }
138+ if (value === null) {
139+ return 1;
140+ }
141+ if (typeof value === "number") {
142+ return 1;
143+ }
144+ if (typeof value === "string") {
145+ return 2;
146+ }
147+ if (typeof value === "boolean") {
148+ return 4;
149+ }
150+ if (value instanceof Error) {
151+ return 16;
152+ }
153+ if (value instanceof Array) {
154+ return 64;
155+ }
156+ return 128;
157+};
158+
159+
160 export {
161 NA,
162 ISTEXT,
163@@ -317,5 +354,6 @@ export {
164 ISERR,
165 ISERROR,
166 ISNA,
167- IFERROR
168+ IFERROR,
169+ TYPE
170 }
171\ No newline at end of file
172diff --git a/tests/Formulas/InfoTest.ts b/tests/Formulas/InfoTest.ts
173index 3508e90..b0ffd2d 100644
174--- a/tests/Formulas/InfoTest.ts
175+++ b/tests/Formulas/InfoTest.ts
176@@ -13,7 +13,8 @@ import {
177 ISERR,
178 ISERROR,
179 ISNA,
180- IFERROR
181+ IFERROR,
182+ TYPE
183 } from "../../src/Formulas/Info";
184 import * as ERRORS from "../../src/Errors";
185 import {
186@@ -235,3 +236,22 @@ test("IFERROR", function(){
187 IFERROR.apply(this, [])
188 }, ERRORS.NA_ERROR);
189 });
190+
191+
192+test("TYPE", function(){
193+ assertEquals(TYPE(44), 1);
194+ assertEquals(TYPE("str"), 2);
195+ assertEquals(TYPE(false), 4);
196+ assertEquals(TYPE(new NAError("err")), 16);
197+ assertEquals(TYPE([1, 2, 3]), 64);
198+ var errorCell = new Cell("A1");
199+ errorCell.setError(new NAError("err"));
200+ assertEquals(TYPE(errorCell), 16);
201+ assertEquals(TYPE(Cell.BuildFrom("A1", 1)), 1);
202+ assertEquals(TYPE(Cell.BuildFrom("A1", "string")), 2);
203+ assertEquals(TYPE(Cell.BuildFrom("A1", false)), 4);
204+ assertEquals(TYPE(new Cell("A1")), 1);
205+ catchAndAssertEquals(function() {
206+ TYPE.apply(this, [])
207+ }, ERRORS.NA_ERROR);
208+});
209diff --git a/tests/SheetFormulaTest.ts b/tests/SheetFormulaTest.ts
210index 238cbe5..bca685a 100644
211--- a/tests/SheetFormulaTest.ts
212+++ b/tests/SheetFormulaTest.ts
213@@ -856,6 +856,10 @@ test("Sheet IFERROR", function(){
214 assertFormulaEquals('=IFERROR(10)', 10);
215 });
216
217+test("Sheet TYPE", function(){
218+ assertFormulaEquals('=TYPE(10)', 1);
219+});
220+
221 test("Sheet *", function(){
222 assertFormulaEquals('= 10 * 10', 100);
223 assertFormulaEquals('= 10 * 0', 0);