spreadsheet
typeScript/javascript spreadsheet parser, with formulas.
git clone https://git.vogt.world/spreadsheet.git
Log | Files | README.md
← Commit log
commit
message
Added Formulas.BIN2HEX
author
Ben Vogt <[email protected]>
date
2017-02-18 05:37:44
stats
4 file(s) changed, 107 insertions(+), 25 deletions(-)
files
src/RawFormulas/RawFormulas.ts
src/RawFormulas/Utils.ts
tests/FormulasTest.ts
tests/SheetFormulaTest.ts
  1diff --git a/src/RawFormulas/RawFormulas.ts b/src/RawFormulas/RawFormulas.ts
  2index de62157..6da8d24 100644
  3--- a/src/RawFormulas/RawFormulas.ts
  4+++ b/src/RawFormulas/RawFormulas.ts
  5@@ -83,7 +83,6 @@ import * as ERRORS from "../Errors"
  6 import {Cell} from "../Cell";
  7 
  8 var ACCRINT = Formula["ACCRINT"];
  9-var BIN2HEX = Formula["BIN2HEX"];
 10 var BIN2OCT = Formula["BIN2OCT"];
 11 var DECIMAL = Formula["DECIMAL"];
 12 var COMBIN = Formula["COMBIN"];
 13@@ -140,8 +139,11 @@ var YEARFRAC = Formula["YEARFRAC"];
 14  * @returns {number}
 15  * @constructor
 16  */
 17-var BIN2DEC = function (...values) {
 18+var BIN2DEC = function (...values) : number {
 19   ArgsChecker.checkLength(values, 1);
 20+  if (typeof TypeCaster.firstValue(values[0]) === "boolean") {
 21+    throw new CellError(ERRORS.VALUE_ERROR, "Function BIN2DEC parameter 1 expects text values. But '" + values[0] + "' is a boolean and cannot be coerced to a text.");
 22+  }
 23   var n = TypeCaster.firstValueAsString(values[0]);
 24   if (!(/^[01]{1,10}$/).test(n)) {
 25     throw new CellError(ERRORS.NUM_ERROR, "Input for BIN2DEC ('"+n+"') is not a valid binary representation.");
 26@@ -149,12 +151,56 @@ var BIN2DEC = function (...values) {
 27 
 28   if (n.length === 10 && n.substring(0, 1) === '1') {
 29     return parseInt(n.substring(1), 2) - 512;
 30-  } else {
 31-    return parseInt(n, 2);
 32   }
 33+  return parseInt(n, 2);
 34+};
 35+
 36+
 37+/**
 38+ * Converts a signed binary number to signed hexadecimal format.
 39+ * @param values[0] signed_binary_number - The signed 10-bit binary value to be converted to signed hexadecimal,
 40+ * provided as a string. The most significant bit of signed_binary_number is the sign bit; that is, negative numbers are
 41+ * represented in two's complement format.
 42+ * @param values[1] significant_digits - [ OPTIONAL ] - The number of significant digits to ensure in the result.
 43+ * @returns {string} string representation of a signed hexadecimal
 44+ * @constructor
 45+ */
 46+var BIN2HEX = function (...values) : string {
 47+  ArgsChecker.checkLengthWithin(values, 1, 2);
 48+  if (typeof TypeCaster.firstValue(values[0]) === "boolean") {
 49+    throw new CellError(ERRORS.VALUE_ERROR, "Function BIN2HEX parameter 1 expects text values. But '" + values[0] + "' is a boolean and cannot be coerced to a text.");
 50+  }
 51+  var n = TypeCaster.firstValueAsString(values[0]);
 52+  var p = 10;
 53+  if (values.length === 2) {
 54+    p = TypeCaster.firstValueAsNumber(values[1]);
 55+  }
 56+  if (!(/^[01]{1,10}$/).test(n)) {
 57+    throw new CellError(ERRORS.NUM_ERROR, "Input for BIN2HEX ('"+n+"') is not a valid binary representation.");
 58+  }
 59+
 60+  if (n.length === 10 && n.substring(0, 1) === '1') {
 61+    return (1099511627264 + parseInt(n.substring(1), 2)).toString(16).toUpperCase();
 62+  }
 63+
 64+  if (p < 1 || p > 10) {
 65+    throw new CellError(ERRORS.NUM_ERROR, "Function BIN2HEX parameter 2 value is " + p + ". Valid values are between 1 and 10 inclusive.");
 66+  }
 67+  p = Math.floor(p);
 68+  // Convert decimal number to hexadecimal
 69+  var result = parseInt(n.toString(), 2).toString(16).toUpperCase();
 70+  if (p === 10) {
 71+    return result;
 72+  }
 73+  var str = "";
 74+  for (var i = 0; i < p - result.length; i++) {
 75+    str += "0";
 76+  }
 77+  return str + result;
 78 };
 79 
 80 
 81+
 82 /**
 83  * Converts an angle value in degrees to radians.
 84  * @param values[0] angle - The angle to convert from degrees to radians.
 85@@ -219,16 +265,12 @@ var DEC2OCT = function (...values) : string {
 86   var result = parseInt(n.toString(), 10).toString(8).toUpperCase();
 87   if (!placesPresent) {
 88     return result;
 89-  } else {
 90-    if (p >= result.length) {
 91-      // Throw NUM error?
 92-    }
 93-    var str = "";
 94-    for (var i = 0; i < p - result.length; i++) {
 95-      str += "0";
 96-    }
 97-    return str + result.toUpperCase();
 98   }
 99+  var str = "";
100+  for (var i = 0; i < p - result.length; i++) {
101+    str += "0";
102+  }
103+  return str + result.toUpperCase();
104 };
105 
106 
107@@ -272,16 +314,12 @@ var DEC2HEX = function (...values) : string {
108   var result = parseInt(n.toString(), 10).toString(16).toUpperCase();
109   if (!placesPresent) {
110     return result;
111-  } else {
112-    if (p >= result.length) {
113-      // Throw NUM error?
114-    }
115-    var str = "";
116-    for (var i = 0; i < p - result.length; i++) {
117-      str += "0";
118-    }
119-    return str + result.toUpperCase();
120   }
121+  var str = "";
122+  for (var i = 0; i < p - result.length; i++) {
123+    str += "0";
124+  }
125+  return str + result;
126 };
127 
128 /**
129diff --git a/src/RawFormulas/Utils.ts b/src/RawFormulas/Utils.ts
130index 7042ea5..447d62a 100644
131--- a/src/RawFormulas/Utils.ts
132+++ b/src/RawFormulas/Utils.ts
133@@ -197,6 +197,16 @@ class TypeCaster {
134     return TypeCaster.valueToString(input);
135   }
136 
137+  static firstValue(input: any) : any {
138+    if (input instanceof Array) {
139+      if (input.length === 0) {
140+        throw new CellError(ERRORS.REF_ERROR, "Reference does not exist.");
141+      }
142+      return TypeCaster.firstValue(input[0]);
143+    }
144+    return input;
145+  }
146+
147   /**
148    * Takes any input type and will throw a REF_ERROR or coerce it into a string.
149    * @param input to attempt to coerce into a string
150diff --git a/tests/FormulasTest.ts b/tests/FormulasTest.ts
151index 7305733..bcfaca4 100644
152--- a/tests/FormulasTest.ts
153+++ b/tests/FormulasTest.ts
154@@ -289,6 +289,9 @@ catchAndAssertEquals(function() {
155 assertEquals(BIN2DEC("1010101010"), -342);
156 assertEquals(BIN2DEC("10"), 2);
157 assertEquals(BIN2DEC(["10", "str"]), 2);
158+catchAndAssertEquals(function() {
159+  BIN2DEC(false);
160+}, ERRORS.VALUE_ERROR);
161 catchAndAssertEquals(function() {
162   BIN2DEC("str");
163 }, ERRORS.NUM_ERROR);
164@@ -300,7 +303,31 @@ catchAndAssertEquals(function() {
165 }, ERRORS.NA_ERROR);
166 
167 
168-assertEquals(BIN2HEX(1010101010), "fffffffeaa");
169+// Test BIN2HEX
170+assertEquals(BIN2HEX("1010101010"), "FFFFFFFEAA");
171+assertEquals(BIN2HEX("10"), "2");
172+assertEquals(BIN2HEX("10101010"), "AA");
173+assertEquals(BIN2HEX("10101010", 4), "00AA");
174+assertEquals(BIN2HEX(["10101010"], [4]), "00AA");
175+catchAndAssertEquals(function() {
176+  BIN2HEX("10101010", 22);
177+}, ERRORS.NUM_ERROR);
178+catchAndAssertEquals(function() {
179+  BIN2HEX(false);
180+}, ERRORS.VALUE_ERROR);
181+catchAndAssertEquals(function() {
182+  BIN2HEX("10101010", 0);
183+}, ERRORS.NUM_ERROR);
184+catchAndAssertEquals(function() {
185+  BIN2DEC("str");
186+}, ERRORS.NUM_ERROR);
187+catchAndAssertEquals(function() {
188+  BIN2DEC();
189+}, ERRORS.NA_ERROR);
190+catchAndAssertEquals(function() {
191+  BIN2DEC("10", 4, 4);
192+}, ERRORS.NA_ERROR);
193+
194 
195 assertEquals(BIN2OCT(1010101010), "7777777252");
196 
197diff --git a/tests/SheetFormulaTest.ts b/tests/SheetFormulaTest.ts
198index 35d4d5c..ded4855 100644
199--- a/tests/SheetFormulaTest.ts
200+++ b/tests/SheetFormulaTest.ts
201@@ -88,7 +88,7 @@ testFormula("=BIN2DEC('1010101010')", -342);
202 // testFormula('=BINOMINV(6, 0.5, 0.75)', 4);
203 
204 // Test BIN2HEX
205-testFormula("=BIN2HEX(1010101010)", "fffffffeaa");
206+testFormula("=BIN2HEX(1010101010)", "FFFFFFFEAA");
207 
208 // Test BIN2OCT
209 testFormula("=BIN2OCT(1010101010)", "7777777252");