spreadsheet
typeScript/javascript spreadsheet parser, with formulas.
git clone https://git.vogt.world/spreadsheet.git
Log | Files | README.md
← Commit log
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);