spreadsheet
typeScript/javascript spreadsheet parser, with formulas.
git clone https://git.vogt.world/spreadsheet.git
Log | Files | README.md
← Commit log
commit
message
[ISNA] formula added and tested (pending correct calling from Parser/Sheet)
author
Ben Vogt <[email protected]>
date
2017-07-09 21:15:49
stats
8 file(s) changed, 94 insertions(+), 5 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 59e6060..f8177dc 100644
  3--- a/DOCS.md
  4+++ b/DOCS.md
  5@@ -656,6 +656,15 @@
  6 @returns {boolean} 
  7 @constructor TODO: This formula needs to be called from inside a try-catch-block in the SheetParser, like ERROR.TYPE.
  8 ```
  9+
 10+### ISNA 
 11+
 12+```
 13+  Returns TRUE if a cell contains the #NA (value not available) error value. If an error occurs, the function returns a logical or numerical value. 
 14+@param value - The value or expression to be tested. 
 15+@returns {boolean} 
 16+@constructor TODO: This formula needs to be called from inside a try-catch-block in the SheetParser, like ERROR.TYPE.
 17+```
 18 ## Logical
 19 
 20 
 21diff --git a/TODO.md b/TODO.md
 22index f652c0f..638cfab 100644
 23--- a/TODO.md
 24+++ b/TODO.md
 25@@ -39,7 +39,6 @@ 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-* ISNA - Requires changes to Parser/Sheet for similar reasons to ISERR; check reference cell value or error field.
 30 * 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.
 31 * 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.
 32 * IFERROR - similar reasons to ISERR.
 33diff --git a/dist/Formulas/AllFormulas.js b/dist/Formulas/AllFormulas.js
 34index 64c3dc7..53c0b95 100644
 35--- a/dist/Formulas/AllFormulas.js
 36+++ b/dist/Formulas/AllFormulas.js
 37@@ -93,6 +93,7 @@ exports.ERRORTYPE = Info_1.ERRORTYPE;
 38 exports.ISBLANK = Info_1.ISBLANK;
 39 exports.ISERR = Info_1.ISERR;
 40 exports.ISERROR = Info_1.ISERROR;
 41+exports.ISNA = Info_1.ISNA;
 42 var Lookup_1 = require("./Lookup");
 43 exports.CHOOSE = Lookup_1.CHOOSE;
 44 var Logical_1 = require("./Logical");
 45diff --git a/dist/Formulas/Info.js b/dist/Formulas/Info.js
 46index 2a93609..cdf0d9b 100644
 47--- a/dist/Formulas/Info.js
 48+++ b/dist/Formulas/Info.js
 49@@ -238,3 +238,29 @@ var ISERROR = function (value) {
 50     return value instanceof Error;
 51 };
 52 exports.ISERROR = ISERROR;
 53+/**
 54+ * Returns TRUE if a cell contains the #N/A (value not available) error value. If an error occurs, the function returns
 55+ * a logical or numerical value.
 56+ * @param value - The value or expression to be tested.
 57+ * @returns {boolean}
 58+ * @constructor
 59+ * TODO: This formula needs to be called from inside a try-catch-block in the Sheet/Parser, like ERROR.TYPE.
 60+ */
 61+var ISNA = function (value) {
 62+    try {
 63+        value = TypeConverter_1.TypeConverter.firstValue(value);
 64+    }
 65+    catch (e) {
 66+        return false;
 67+    }
 68+    if (value instanceof Cell_1.Cell) {
 69+        if (value.hasError()) {
 70+            return value.getError().name === Errors_1.NA_ERROR;
 71+        }
 72+    }
 73+    if (value instanceof Error) {
 74+        return value.name === Errors_1.NA_ERROR;
 75+    }
 76+    return false;
 77+};
 78+exports.ISNA = ISNA;
 79diff --git a/src/Formulas/AllFormulas.ts b/src/Formulas/AllFormulas.ts
 80index 32e1b65..ee47e91 100644
 81--- a/src/Formulas/AllFormulas.ts
 82+++ b/src/Formulas/AllFormulas.ts
 83@@ -92,7 +92,8 @@ import {
 84   ERRORTYPE,
 85   ISBLANK,
 86   ISERR,
 87-  ISERROR
 88+  ISERROR,
 89+  ISNA
 90 } from "./Info";
 91 import {
 92   CHOOSE
 93@@ -435,5 +436,6 @@ export {
 94   ERRORTYPE,
 95   ISBLANK,
 96   ISERR,
 97-  ISERROR
 98+  ISERROR,
 99+  ISNA
100 }
101\ No newline at end of file
102diff --git a/src/Formulas/Info.ts b/src/Formulas/Info.ts
103index fe8b4de..9413c3d 100644
104--- a/src/Formulas/Info.ts
105+++ b/src/Formulas/Info.ts
106@@ -255,6 +255,32 @@ var ISERROR = function (value) {
107 };
108 
109 
110+/**
111+ * Returns TRUE if a cell contains the #N/A (value not available) error value. If an error occurs, the function returns
112+ * a logical or numerical value.
113+ * @param value - The value or expression to be tested.
114+ * @returns {boolean}
115+ * @constructor
116+ * TODO: This formula needs to be called from inside a try-catch-block in the Sheet/Parser, like ERROR.TYPE.
117+ */
118+var ISNA = function (value) {
119+  try {
120+    value = TypeConverter.firstValue(value);
121+  } catch (e) {
122+    return false;
123+  }
124+  if (value instanceof Cell) {
125+    if (value.hasError()) {
126+      return value.getError().name === NA_ERROR;
127+    }
128+  }
129+  if (value instanceof Error) {
130+    return value.name === NA_ERROR;
131+  }
132+  return false;
133+};
134+
135+
136 export {
137   NA,
138   ISTEXT,
139@@ -268,5 +294,6 @@ export {
140   ERRORTYPE,
141   ISBLANK,
142   ISERR,
143-  ISERROR
144+  ISERROR,
145+  ISNA
146 }
147\ No newline at end of file
148diff --git a/tests/Formulas/InfoTest.ts b/tests/Formulas/InfoTest.ts
149index 00cf213..0506e2f 100644
150--- a/tests/Formulas/InfoTest.ts
151+++ b/tests/Formulas/InfoTest.ts
152@@ -11,7 +11,8 @@ import {
153   ERRORTYPE,
154   ISBLANK,
155   ISERR,
156-  ISERROR
157+  ISERROR,
158+  ISNA
159 } from "../../src/Formulas/Info";
160 import * as ERRORS from "../../src/Errors";
161 import {
162@@ -195,3 +196,19 @@ test("ISERROR", function(){
163   assertEquals(ISERROR(new NameError("error")), true);
164   assertEquals(ISERROR(new RefError("error")), true);
165 });
166+
167+
168+test("ISNA", function(){
169+  var errorCell = new Cell("A1");
170+  errorCell.setError(new NAError("err"));
171+  assertEquals(ISNA(errorCell), true);
172+  assertEquals(ISNA(Cell.BuildFrom("A1", 10)), false);
173+  assertEquals(ISNA(new Cell("A1")), false);
174+  assertEquals(ISNA("10"), false);
175+  assertEquals(ISNA(10), false);
176+  assertEquals(ISNA([]), false);
177+  assertEquals(ISNA(new NAError("error")), true);
178+  assertEquals(ISNA(new DivZeroError("error")), false);
179+  assertEquals(ISNA(new NameError("error")), false);
180+  assertEquals(ISNA(new RefError("error")), false);
181+});
182diff --git a/tests/SheetFormulaTest.ts b/tests/SheetFormulaTest.ts
183index b87ae5d..7139791 100644
184--- a/tests/SheetFormulaTest.ts
185+++ b/tests/SheetFormulaTest.ts
186@@ -848,6 +848,10 @@ test("Sheet ISERROR", function(){
187   assertFormulaEquals('=ISERROR(10)', false);
188 });
189 
190+test("Sheet ISNA", function(){
191+  assertFormulaEquals('=ISNA(10)', false);
192+});
193+
194 test("Sheet *", function(){
195   assertFormulaEquals('= 10 * 10', 100);
196   assertFormulaEquals('= 10 * 0', 0);