spreadsheet
typeScript/javascript spreadsheet parser, with formulas.
git clone https://git.vogt.world/spreadsheet.git
Log | Files | README.md
← Commit log
commit
message
[ArgsChecker] passing formula names into ArgsChecker functions to format NAErrors
author
Ben Vogt <[email protected]>
date
2017-05-13 20:31:52
stats
10 file(s) changed, 198 insertions(+), 146 deletions(-)
files
README.md
src/Formulas/Date.ts
src/Formulas/Engineering.ts
src/Formulas/Financial.ts
src/Formulas/Logical.ts
src/Formulas/Math.ts
src/Formulas/Statistical.ts
src/Formulas/Text.ts
src/Utilities/ArgsChecker.ts
tests/Utilities/ArgsCheckerTest.ts
   1diff --git a/README.md b/README.md
   2index fc59014..a7688b3 100644
   3--- a/README.md
   4+++ b/README.md
   5@@ -25,10 +25,6 @@ http://stackoverflow.com/questions/3446170/escape-string-for-use-in-javascript-r
   6 e.g. "SUM expects number values...", or "This function expects number values..."
   7 
   8 
   9-### Error formatting
  10-Pass name of calling formula into all functions that throw user-facing errors, or have some sort of error mapper.
  11-
  12-
  13 ### Cells should have `formatAs` fields.
  14 Instead of having non-primitives, (i.e. Date, DateTime, Time, Dollar), cells should have formats based on the
  15 highest-order type that was used during the compilation and execution of a cell's dependency. For example, `DATE` might
  16@@ -69,6 +65,13 @@ TypeConverter.
  17 ### Test CriteriaFunctionFactory
  18 
  19 
  20+### Use `arguments` instead of `...values` for performance reasons.
  21+And use `.call()` when testing with weird param numbers.
  22+
  23+
  24+### Pull static functions outside of formulas, declare once.
  25+
  26+
  27 ### CONVERT could offer more accurate conversions for units in the same system
  28 For example 64 tbs to a qt.
  29 
  30diff --git a/src/Formulas/Date.ts b/src/Formulas/Date.ts
  31index b09d4ed..2835662 100644
  32--- a/src/Formulas/Date.ts
  33+++ b/src/Formulas/Date.ts
  34@@ -22,7 +22,7 @@ import {
  35  */
  36 var DATE = function (...values) : number {
  37   const FIRST_YEAR = 1900;
  38-  ArgsChecker.checkLength(values, 3);
  39+  ArgsChecker.checkLength(values, 3, "DATE");
  40   var year = Math.abs(Math.floor(TypeConverter.firstValueAsNumber(values[0]))); // No negative values for year
  41   var month = Math.floor(TypeConverter.firstValueAsNumber(values[1])) - 1; // Months are between 0 and 11.
  42   var day = Math.floor(TypeConverter.firstValueAsNumber(values[2])) - 1; // Days are also zero-indexed.
  43@@ -48,7 +48,7 @@ var DATE = function (...values) : number {
  44  * @constructor
  45  */
  46 var DATEVALUE = function (...values) : number {
  47-  ArgsChecker.checkLength(values, 1);
  48+  ArgsChecker.checkLength(values, 1, "DATEVALUE");
  49   var dateString = TypeConverter.firstValueAsString(values[0]);
  50   var dateAsNumber;
  51   try {
  52@@ -70,7 +70,7 @@ var DATEVALUE = function (...values) : number {
  53  * @constructor
  54  */
  55 var EDATE = function (...values) : number {
  56-  ArgsChecker.checkLength(values, 2);
  57+  ArgsChecker.checkLength(values, 2, "EDATE");
  58   var startDateNumber = TypeConverter.firstValueAsDateNumber(values[0], true); // tell firstValueAsDateNumber to coerce boolean
  59   if (startDateNumber < 0) {
  60     throw new NumError("Function EDATE parameter 1 value is " + startDateNumber+ ". It should be greater than or equal to 0.");
  61@@ -92,7 +92,7 @@ var EDATE = function (...values) : number {
  62  * @constructor
  63  */
  64 var EOMONTH = function (...values) : number {
  65-  ArgsChecker.checkLength(values, 2);
  66+  ArgsChecker.checkLength(values, 2, "EOMONTH");
  67   var startDateNumber = TypeConverter.firstValueAsDateNumber(values[0], true); // tell firstValueAsDateNumber to coerce boolean
  68   if (startDateNumber < 0) {
  69     throw new NumError("Function EOMONTH parameter 1 value is " + startDateNumber + ". It should be greater than or equal to 0.");
  70@@ -113,7 +113,7 @@ var EOMONTH = function (...values) : number {
  71  * @constructor
  72  */
  73 var DAY = function (...values) : number {
  74-  ArgsChecker.checkLength(values, 1);
  75+  ArgsChecker.checkLength(values, 1, "DAY");
  76   var dateNumber = TypeConverter.firstValueAsDateNumber(values[0], true); // tell firstValueAsDateNumber to coerce boolean
  77   if (dateNumber < 0) {
  78     throw new NumError("Function DAY parameter 1 value is " + dateNumber + ". It should be greater than or equal to 0.");
  79@@ -130,7 +130,7 @@ var DAY = function (...values) : number {
  80  * @constructor
  81  */
  82 var DAYS = function (...values) : number {
  83-  ArgsChecker.checkLength(values, 2);
  84+  ArgsChecker.checkLength(values, 2, "DAYS");
  85   var end = TypeConverter.firstValueAsDateNumber(values[0], true); // tell firstValueAsDateNumber to coerce boolean
  86   var start = TypeConverter.firstValueAsDateNumber(values[1], true); // tell firstValueAsDateNumber to coerce boolean
  87   return end - start;
  88@@ -154,7 +154,7 @@ var DAYS = function (...values) : number {
  89  * @constructor
  90  */
  91 var DAYS360 = function (...values) : number {
  92-  ArgsChecker.checkLengthWithin(values, 2, 3);
  93+  ArgsChecker.checkLengthWithin(values, 2, 3, "DAYS360");
  94   var start = TypeConverter.numberToMoment(TypeConverter.firstValueAsDateNumber(values[0], true)); // tell firstValueAsDateNumber to coerce boolean
  95   var end = TypeConverter.numberToMoment(TypeConverter.firstValueAsDateNumber(values[1], true)); // tell firstValueAsDateNumber to coerce boolean
  96   var methodToUse = false;
  97@@ -193,7 +193,7 @@ var DAYS360 = function (...values) : number {
  98  * @constructor
  99  */
 100 var MONTH = function (...values) : number {
 101-  ArgsChecker.checkLength(values, 1);
 102+  ArgsChecker.checkLength(values, 1, "MONTH");
 103   var date = TypeConverter.firstValueAsDateNumber(values[0], true); // tell firstValueAsDateNumber to coerce boolean
 104   if (date < 0) {
 105     throw new NumError("Function MONTH parameter 1 value is " + date + ". It should be greater than or equal to 0.");
 106@@ -210,7 +210,7 @@ var MONTH = function (...values) : number {
 107  * @constructor
 108  */
 109 var YEAR = function (...values) : number {
 110-  ArgsChecker.checkLength(values, 1);
 111+  ArgsChecker.checkLength(values, 1, "YEAR");
 112   var date = TypeConverter.firstValueAsDateNumber(values[0], true); // tell firstValueAsDateNumber to coerce boolean
 113   if (date < 0) {
 114     throw new NumError("Function YEAR parameter 1 value is " + date + ". It should be greater than or equal to 0.");
 115@@ -232,7 +232,7 @@ var YEAR = function (...values) : number {
 116  * @constructor
 117  */
 118 var WEEKDAY = function (...values) : number {
 119-  ArgsChecker.checkLengthWithin(values, 1, 2);
 120+  ArgsChecker.checkLengthWithin(values, 1, 2, "WEEKDAY");
 121   var date = TypeConverter.firstValueAsDateNumber(values[0], true); // tell firstValueAsDateNumber to coerce boolean
 122   var offsetType = values.length === 2 ? TypeConverter.firstValueAsNumber(values[1]) : 1;
 123   if (date < 0) {
 124@@ -291,7 +291,7 @@ function calculateWeekNum(dm : moment.Moment, shifterArray : Array<number>) : nu
 125  * @constructor
 126  */
 127 var WEEKNUM = function (...values) : number {
 128-  ArgsChecker.checkLengthWithin(values, 1, 2);
 129+  ArgsChecker.checkLengthWithin(values, 1, 2, "WEEKNUM");
 130   var date = TypeConverter.firstValueAsDateNumber(values[0], true); // tell firstValueAsDateNumber to coerce boolean
 131   var shiftType = values.length === 2 ? TypeConverter.firstValueAsNumber(values[1]) : 1;
 132   if (date < 0) {
 133@@ -363,7 +363,7 @@ var WEEKNUM = function (...values) : number {
 134  * @constructor
 135  */
 136 var DATEDIF = function (...values) : number {
 137-  ArgsChecker.checkLength(values, 3);
 138+  ArgsChecker.checkLength(values, 3, "DATEDIF");
 139   var start = TypeConverter.firstValueAsDateNumber(values[0], true);
 140   var end = TypeConverter.firstValueAsDateNumber(values[1], true);
 141   var unit = TypeConverter.firstValueAsString(values[2]);
 142@@ -432,7 +432,7 @@ var DATEDIF = function (...values) : number {
 143  * @constructor
 144  */
 145 var YEARFRAC = function (...values) : number {
 146-  ArgsChecker.checkLengthWithin(values, 2, 3);
 147+  ArgsChecker.checkLengthWithin(values, 2, 3, "YEARFRAC");
 148   var start = TypeConverter.firstValueAsDateNumber(values[0], true);
 149   var end = TypeConverter.firstValueAsDateNumber(values[1], true);
 150   var basis = values.length === 2 ? 0 : TypeConverter.firstValueAsNumber(values[2]);
 151@@ -527,7 +527,7 @@ var YEARFRAC = function (...values) : number {
 152  * @constructor
 153  */
 154 var TIMEVALUE = function (...values) : number {
 155-  ArgsChecker.checkLength(values, 1);
 156+  ArgsChecker.checkLength(values, 1, "TIMEVALUE");
 157   var timeString = TypeConverter.firstValueAsString(values[0]);
 158   try {
 159     return TypeConverter.stringToTimeNumber(timeString);
 160@@ -546,7 +546,7 @@ const MILLISECONDS_IN_DAY = 86400000;
 161  * @constructor
 162  */
 163 var HOUR = function (...values) : number {
 164-  ArgsChecker.checkLength(values, 1);
 165+  ArgsChecker.checkLength(values, 1, "HOUR");
 166   var time = TypeConverter.firstValueAsTimestampNumber(values[0]);
 167   if (time % 1 === 0) {
 168     return 0;
 169@@ -564,7 +564,7 @@ var HOUR = function (...values) : number {
 170  * @constructor
 171  */
 172 var MINUTE = function (...values) : number {
 173-  ArgsChecker.checkLength(values, 1);
 174+  ArgsChecker.checkLength(values, 1, "MINUTE");
 175   var time = TypeConverter.firstValueAsTimestampNumber(values[0]);
 176   if (time % 1 === 0) {
 177     return 0;
 178@@ -581,7 +581,7 @@ var MINUTE = function (...values) : number {
 179  * @constructor
 180  */
 181 var SECOND = function (...values) : number {
 182-  ArgsChecker.checkLength(values, 1);
 183+  ArgsChecker.checkLength(values, 1, "SECOND");
 184   var time = TypeConverter.firstValueAsTimestampNumber(values[0]);
 185   if (time % 1 === 0) {
 186     return 0;
 187@@ -603,7 +603,7 @@ var SECOND = function (...values) : number {
 188  * @constructor
 189  */
 190 var NETWORKDAYS = function (...values) : number {
 191-  ArgsChecker.checkLengthWithin(values, 2, 3);
 192+  ArgsChecker.checkLengthWithin(values, 2, 3, "NETWORKDAYS");
 193   var start = TypeConverter.firstValueAsDateNumber(values[0], true);
 194   var end = TypeConverter.firstValueAsDateNumber(values[1], true);
 195   var hasHolidays = values.length === 3;
 196@@ -669,7 +669,7 @@ var NETWORKDAYS = function (...values) : number {
 197  * @constructor
 198  */
 199 var NETWORKDAYS$INTL = function (...values) : number {
 200-  ArgsChecker.checkLengthWithin(values, 2, 4);
 201+  ArgsChecker.checkLengthWithin(values, 2, 4, "NETWORKDAYS$INTL");
 202   var start = TypeConverter.firstValueAsDateNumber(values[0], true);
 203   var end = TypeConverter.firstValueAsDateNumber(values[1], true);
 204   var weekendDays = [];
 205@@ -768,7 +768,7 @@ var NETWORKDAYS$INTL = function (...values) : number {
 206  * @constructor
 207  */
 208 var NOW = function (...values) : number {
 209-  ArgsChecker.checkLength(values, 0);
 210+  ArgsChecker.checkLength(values, 0, "NOW");
 211   return TypeConverter.momentToNumber(moment.utc());
 212 };
 213 
 214@@ -778,7 +778,7 @@ var NOW = function (...values) : number {
 215  * @constructor
 216  */
 217 var TODAY = function (...values) : number {
 218-  ArgsChecker.checkLength(values, 0);
 219+  ArgsChecker.checkLength(values, 0, "TODAY");
 220   return TypeConverter.momentToNumber(moment.utc().startOf("day"));
 221 };
 222 
 223@@ -793,7 +793,7 @@ var TODAY = function (...values) : number {
 224  * @constructor
 225  */
 226 var TIME = function (...values) : number {
 227-  ArgsChecker.checkLength(values, 3);
 228+  ArgsChecker.checkLength(values, 3, "TIME");
 229   var hours = Math.floor(TypeConverter.firstValueAsNumber(values[0]));
 230   var minutes = Math.floor(TypeConverter.firstValueAsNumber(values[1]));
 231   var seconds = Math.floor(TypeConverter.firstValueAsNumber(values[2]));
 232@@ -818,7 +818,7 @@ var TIME = function (...values) : number {
 233  * @constructor
 234  */
 235 var WORKDAY = function (...values) : number {
 236-  ArgsChecker.checkLengthWithin(values, 2, 3);
 237+  ArgsChecker.checkLengthWithin(values, 2, 3, "WORKDAY");
 238   var start = TypeConverter.firstValueAsDateNumber(values[0], true);
 239   var days = TypeConverter.firstValueAsNumber(values[1]);
 240   var hasHolidays = values.length === 3;
 241@@ -870,7 +870,7 @@ var WORKDAY = function (...values) : number {
 242  * @constructor
 243  */
 244 var WORKDAY$INTL = function (...values) : number {
 245-  ArgsChecker.checkLengthWithin(values, 2, 3);
 246+  ArgsChecker.checkLengthWithin(values, 2, 3, "WORKDAY$INTL");
 247   var start = TypeConverter.firstValueAsDateNumber(values[0], true);
 248   var days = TypeConverter.firstValueAsNumber(values[1]);
 249   var weekendDays = [];
 250diff --git a/src/Formulas/Engineering.ts b/src/Formulas/Engineering.ts
 251index d78e0fa..b7e52d8 100644
 252--- a/src/Formulas/Engineering.ts
 253+++ b/src/Formulas/Engineering.ts
 254@@ -18,7 +18,7 @@ import {
 255  * @constructor
 256  */
 257 var BIN2DEC = function (...values) : number {
 258-  ArgsChecker.checkLength(values, 1);
 259+  ArgsChecker.checkLength(values, 1, "BIN2DEC");
 260   if (typeof TypeConverter.firstValue(values[0]) === "boolean") {
 261     throw new ValueError("Function BIN2DEC parameter 1 expects text values. But '" + values[0] + "' is a boolean and cannot be coerced to a text.");
 262   }
 263@@ -44,7 +44,7 @@ var BIN2DEC = function (...values) : number {
 264  * @constructor
 265  */
 266 var BIN2HEX = function (...values) : string {
 267-  ArgsChecker.checkLengthWithin(values, 1, 2);
 268+  ArgsChecker.checkLengthWithin(values, 1, 2, "BIN2HEX");
 269   if (typeof TypeConverter.firstValue(values[0]) === "boolean") {
 270     throw new ValueError("Function BIN2HEX parameter 1 expects text values. But '" + values[0] + "' is a boolean and cannot be coerced to a text.");
 271   }
 272@@ -90,7 +90,7 @@ var BIN2HEX = function (...values) : string {
 273  * @constructor
 274  */
 275 var BIN2OCT = function (...values) : string {
 276-  ArgsChecker.checkLengthWithin(values, 1, 2);
 277+  ArgsChecker.checkLengthWithin(values, 1, 2, "BIN2OCT");
 278   if (typeof TypeConverter.firstValue(values[0]) === "boolean") {
 279     throw new ValueError("Function BIN2OCT parameter 1 expects text values. But '" + values[0] + "' is a boolean and cannot be coerced to a text.");
 280   }
 281@@ -135,7 +135,7 @@ var BIN2OCT = function (...values) : string {
 282  * @constructor
 283  */
 284 var DEC2OCT = function (...values) : string {
 285-  ArgsChecker.checkLengthWithin(values, 1, 2);
 286+  ArgsChecker.checkLengthWithin(values, 1, 2, "DEC2OCT");
 287   var n = TypeConverter.firstValueAsNumber(values[0]);
 288   if (n < 0) {
 289     n = Math.ceil(n);
 290@@ -183,7 +183,7 @@ var DEC2OCT = function (...values) : string {
 291  * @constructor
 292  */
 293 var DEC2HEX = function (...values) : string {
 294-  ArgsChecker.checkLengthWithin(values, 1, 2);
 295+  ArgsChecker.checkLengthWithin(values, 1, 2, "DEC2HEX");
 296   var n = TypeConverter.firstValueAsNumber(values[0]);
 297   if (n < 0) {
 298     n = Math.ceil(n);
 299@@ -231,7 +231,7 @@ var DEC2HEX = function (...values) : string {
 300  * @constructor
 301  */
 302 var DEC2BIN = function (...values) : string {
 303-  ArgsChecker.checkLengthWithin(values, 1, 2);
 304+  ArgsChecker.checkLengthWithin(values, 1, 2, "DEC2BIN");
 305   var n = TypeConverter.firstValueAsNumber(values[0]);
 306   if (n < 0) {
 307     n = Math.ceil(n);
 308@@ -299,7 +299,7 @@ var DEC2BIN = function (...values) : string {
 309  * @constructor
 310  */
 311 var DELTA = function (...values) : number {
 312-  ArgsChecker.checkLengthWithin(values, 1, 2);
 313+  ArgsChecker.checkLengthWithin(values, 1, 2, "DELTA");
 314   if (values.length === 1) {
 315     return TypeConverter.valueToNumber(values[0]) === 0 ? 1 : 0;
 316   }
 317diff --git a/src/Formulas/Financial.ts b/src/Formulas/Financial.ts
 318index ed4cc64..1c2f28c 100644
 319--- a/src/Formulas/Financial.ts
 320+++ b/src/Formulas/Financial.ts
 321@@ -25,7 +25,7 @@ import {
 322  * @constructor
 323  */
 324 var DDB = function (...values) : number {
 325-  ArgsChecker.checkLengthWithin(values, 4, 5);
 326+  ArgsChecker.checkLengthWithin(values, 4, 5, "DDB");
 327   var cost = TypeConverter.firstValueAsNumber(values[0]);
 328   var salvage = TypeConverter.firstValueAsNumber(values[1]);
 329   var life = TypeConverter.firstValueAsNumber(values[2]);
 330@@ -77,7 +77,7 @@ var DDB = function (...values) : number {
 331  * @constructor
 332  */
 333 var DB = function (...values) : number {
 334-  ArgsChecker.checkLengthWithin(values, 4, 5);
 335+  ArgsChecker.checkLengthWithin(values, 4, 5, "DB");
 336   var cost = TypeConverter.firstValueAsNumber(values[0]);
 337   var salvage = TypeConverter.firstValueAsNumber(values[1]);
 338   var life = TypeConverter.firstValueAsNumber(values[2]);
 339@@ -140,7 +140,7 @@ var DB = function (...values) : number {
 340  * @constructor
 341  */
 342 var DOLLAR = function (...values) : number {
 343-  ArgsChecker.checkLengthWithin(values, 1, 2);
 344+  ArgsChecker.checkLengthWithin(values, 1, 2, "DOLLAR");
 345   var v = TypeConverter.firstValueAsNumber(values[0]);
 346   var places = values.length === 2 ? TypeConverter.firstValueAsNumber(values[1]) : 2;
 347   var sign = (v > 0) ? 1 : -1;
 348@@ -161,7 +161,7 @@ var DOLLAR = function (...values) : number {
 349  * @constructor
 350  */
 351 var DOLLARDE = function (...values) : number {
 352-  ArgsChecker.checkLength(values, 2);
 353+  ArgsChecker.checkLength(values, 2, "DOLLARDE");
 354   var dollar = TypeConverter.firstValueAsNumber(values[0]);
 355   var fraction = Math.floor(TypeConverter.firstValueAsNumber(values[1]));
 356   if (fraction === 0) {
 357@@ -186,7 +186,7 @@ var DOLLARDE = function (...values) : number {
 358  * @constructor
 359  */
 360 var DOLLARFR = function (...values) : number {
 361-  ArgsChecker.checkLength(values, 2);
 362+  ArgsChecker.checkLength(values, 2, "DOLLARFR");
 363   var dollar = TypeConverter.firstValueAsNumber(values[0]);
 364   var unit = Math.floor(TypeConverter.firstValueAsNumber(values[1]));
 365   if (unit === 0) {
 366@@ -206,7 +206,7 @@ var DOLLARFR = function (...values) : number {
 367  * @constructor
 368  */
 369 var EFFECT = function (...values) : number {
 370-  ArgsChecker.checkLength(values, 2);
 371+  ArgsChecker.checkLength(values, 2, "EFFECT");
 372   var rate = TypeConverter.firstValueAsNumber(values[0]);
 373   var periods = TypeConverter.firstValueAsNumber(values[1]);
 374   if (rate <= 0) {
 375@@ -266,7 +266,7 @@ function fv(rate, periods, payment, value, type) {
 376  * @constructor
 377  */
 378 var CUMPRINC = function (...values) : number {
 379-  ArgsChecker.checkLength(values, 6);
 380+  ArgsChecker.checkLength(values, 6, "CUMPRINC");
 381   var rate = TypeConverter.firstValueAsNumber(values[0]);
 382   var periods = TypeConverter.firstValueAsNumber(values[1]);
 383   var value = TypeConverter.firstValueAsNumber(values[2]);
 384@@ -318,7 +318,7 @@ var CUMPRINC = function (...values) : number {
 385  * @constructor
 386  */
 387 var CUMIPMT = function (...values) : number {
 388-  ArgsChecker.checkLength(values, 6);
 389+  ArgsChecker.checkLength(values, 6, "CUMIPMT");
 390   var rate = TypeConverter.firstValueAsNumber(values[0]);
 391   var periods = TypeConverter.firstValueAsNumber(values[1]);
 392   var value = TypeConverter.firstValueAsNumber(values[2]);
 393@@ -386,7 +386,7 @@ var CUMIPMT = function (...values) : number {
 394  * TODO:     second version that is closer to what MSExcel does and is named something like `ACCRINT.MS`.
 395  */
 396 var ACCRINT = function (...values) {
 397-  ArgsChecker.checkLengthWithin(values, 6, 7);
 398+  ArgsChecker.checkLengthWithin(values, 6, 7, "ACCRINT");
 399   var issue = TypeConverter.firstValueAsDateNumber(values[0]);
 400   // "firstPayment" param is only here to check for errors for GS implementation.
 401   // In MSE, there is a 7th (zero-indexed-6th) param that indicates the calculation-method to use, which indicates
 402diff --git a/src/Formulas/Logical.ts b/src/Formulas/Logical.ts
 403index 8381d5a..0c89672 100644
 404--- a/src/Formulas/Logical.ts
 405+++ b/src/Formulas/Logical.ts
 406@@ -18,7 +18,7 @@ import {
 407  * @constructor
 408  */
 409 var AND = function (...values) {
 410-  ArgsChecker.checkAtLeastLength(values, 1);
 411+  ArgsChecker.checkAtLeastLength(values, 1, "AND");
 412   var result = true;
 413   for (var i = 0; i < values.length; i++) {
 414     if (typeof values[i] === "string") {
 415@@ -45,7 +45,7 @@ var AND = function (...values) {
 416  * @constructor
 417  */
 418 var EXACT = function (...values) {
 419-  ArgsChecker.checkLength(values, 2);
 420+  ArgsChecker.checkLength(values, 2, "EXACT");
 421   var one = TypeConverter.firstValue(values[0]);
 422   var two = TypeConverter.firstValue(values[1]);
 423   return one.toString() === two.toString();
 424@@ -55,6 +55,7 @@ var EXACT = function (...values) {
 425  * Returns true.
 426  * @returns {boolean} true boolean
 427  * @constructor
 428+ * TODO: Should throw NA error if param passed in.
 429  */
 430 var TRUE = function () : boolean {
 431   return true;
 432@@ -64,6 +65,7 @@ var TRUE = function () : boolean {
 433  * Returns false.
 434  * @returns {boolean} false boolean
 435  * @constructor
 436+ * TODO: Should throw NA error if param passed in.
 437  */
 438 var FALSE = function () : boolean {
 439   return false;
 440@@ -76,7 +78,7 @@ var FALSE = function () : boolean {
 441  * @constructor
 442  */
 443 var NOT = function (...values) : boolean {
 444-  ArgsChecker.checkLength(values, 1);
 445+  ArgsChecker.checkLength(values, 1, "NOT");
 446   var X = values[0];
 447   if (typeof(X) === "boolean") {
 448     return !X;
 449@@ -108,7 +110,7 @@ var NOT = function (...values) : boolean {
 450  * @constructor
 451  */
 452 var OR = function (...values) {
 453-  ArgsChecker.checkAtLeastLength(values, 1);
 454+  ArgsChecker.checkAtLeastLength(values, 1, "OR");
 455   for (var i = 0; i < values.length; i++) {
 456     if (values[i] instanceof Array) {
 457       if (values[i].length === 0) {
 458@@ -131,7 +133,7 @@ var OR = function (...values) {
 459  * @constructor
 460  */
 461 var XOR = function (...values) {
 462-  ArgsChecker.checkAtLeastLength(values, 1);
 463+  ArgsChecker.checkAtLeastLength(values, 1, "XOR");
 464   var alreadyTruthy = false;
 465   for (var i = 0; i < values.length; i++) {
 466     if (values[i] instanceof Array) {
 467diff --git a/src/Formulas/Math.ts b/src/Formulas/Math.ts
 468index 7080ecb..91deaaf 100644
 469--- a/src/Formulas/Math.ts
 470+++ b/src/Formulas/Math.ts
 471@@ -28,7 +28,7 @@ import {
 472  * @constructor
 473  */
 474 var ABS = function (...values) {
 475-  ArgsChecker.checkLength(values, 1);
 476+  ArgsChecker.checkLength(values, 1, "ABS");
 477   var v = TypeConverter.valueToNumber(values[0]);
 478   return Math.abs(v);
 479 };
 480@@ -40,7 +40,7 @@ var ABS = function (...values) {
 481  * @constructor
 482  */
 483 var ACOS = function (value?) {
 484-  ArgsChecker.checkLength(arguments, 1);
 485+  ArgsChecker.checkLength(arguments, 1, "ACOS");
 486   value = TypeConverter.valueToNumber(value);
 487   if (value === -1) {
 488     return Math.PI;
 489@@ -57,7 +57,7 @@ var ACOS = function (value?) {
 490  * @constructor
 491  */
 492 var ACOSH = function (value?) {
 493-  ArgsChecker.checkLength(arguments, 1);
 494+  ArgsChecker.checkLength(arguments, 1, "ACOSH");
 495   value = TypeConverter.valueToNumber(value);
 496   if (value < 1) {
 497     throw new NumError("Function ACOSH parameter 1 value is " + value + ". It should be greater than or equal to 1.");
 498@@ -72,7 +72,7 @@ var ACOSH = function (value?) {
 499  * @constructor
 500  */
 501 var ACOTH = function (value?) {
 502-  ArgsChecker.checkLength(arguments, 1);
 503+  ArgsChecker.checkLength(arguments, 1, "ACOTH");
 504   value = TypeConverter.valueToNumber(value);
 505   if (value <= 1 && value >= -1) {
 506     throw new NumError("Function ACOTH parameter 1 value is " + value + ". Valid values cannot be between -1 and 1 inclusive.")
 507@@ -87,7 +87,7 @@ var ACOTH = function (value?) {
 508  * @constructor
 509  */
 510 var ASIN = function (value?) {
 511-  ArgsChecker.checkLength(arguments, 1);
 512+  ArgsChecker.checkLength(arguments, 1, "ASIN");
 513   value = TypeConverter.valueToNumber(value);
 514   if (value === -1) {
 515     return Math.PI;
 516@@ -104,7 +104,7 @@ var ASIN = function (value?) {
 517  * @constructor
 518  */
 519 var ASINH = function (value?) {
 520-  ArgsChecker.checkLength(arguments, 1);
 521+  ArgsChecker.checkLength(arguments, 1, "ASINH");
 522   value = TypeConverter.valueToNumber(value);
 523   return Math.log(value + Math.sqrt(value * value + 1));
 524 };
 525@@ -117,7 +117,7 @@ var ASINH = function (value?) {
 526  * @constructor
 527  */
 528 var ATAN = function (value?) {
 529-  ArgsChecker.checkLength(arguments, 1);
 530+  ArgsChecker.checkLength(arguments, 1, "ATAN");
 531   value = TypeConverter.valueToNumber(value);
 532   if (value === -1) {
 533     return Math.PI;
 534@@ -136,7 +136,7 @@ var ATAN = function (value?) {
 535  * @constructor
 536  */
 537 var ATAN2 = function (x, y) {
 538-  ArgsChecker.checkLength(arguments, 2);
 539+  ArgsChecker.checkLength(arguments, 2, "ATAN2");
 540   x = TypeConverter.valueToNumber(x);
 541   y = TypeConverter.valueToNumber(y);
 542   if (x === 0 && y === 0) {
 543@@ -153,7 +153,7 @@ var ATAN2 = function (x, y) {
 544  * @constructor
 545  */
 546 var ATANH = function (value?) : number {
 547-  ArgsChecker.checkLength(arguments, 1);
 548+  ArgsChecker.checkLength(arguments, 1, "ATANH");
 549   value = TypeConverter.valueToNumber(value);
 550   if (value >= 1 || value <= -1) {
 551     throw new NumError("Function ATANH parameter 1 value is " + value + ". Valid values are between -1 and 1 exclusive.");
 552@@ -171,7 +171,7 @@ var ATANH = function (value?) : number {
 553  * @constructor
 554  */
 555 var EVEN = function (...values) : number {
 556-  ArgsChecker.checkLength(values, 1);
 557+  ArgsChecker.checkLength(values, 1, "EVEN");
 558   if (values[0] instanceof Array) {
 559     if (values[0].length === 0) {
 560       throw new RefError("Reference does not exist.");
 561@@ -190,7 +190,7 @@ var EVEN = function (...values) : number {
 562  * @constructor
 563  */
 564 var MOD = function (...values) : number {
 565-  ArgsChecker.checkLength(values, 2);
 566+  ArgsChecker.checkLength(values, 2, "MOD");
 567   var oneN = TypeConverter.valueToNumber(values[0]);
 568   var twoN =  TypeConverter.valueToNumber(values[1]);
 569   if (twoN === 0) {
 570@@ -207,7 +207,7 @@ var MOD = function (...values) : number {
 571  * @constructor
 572  */
 573 var ODD = function (...values) : number {
 574-  ArgsChecker.checkLength(values, 1);
 575+  ArgsChecker.checkLength(values, 1, "ODD");
 576   if (values[0] instanceof Array) {
 577     if (values[0].length === 0) {
 578       throw new RefError("Reference does not exist.");
 579@@ -226,7 +226,7 @@ var ODD = function (...values) : number {
 580  * @constructor
 581  */
 582 var POWER = function (...values) : number {
 583-  ArgsChecker.checkLength(values, 2);
 584+  ArgsChecker.checkLength(values, 2, "POWER");
 585   var n = TypeConverter.firstValueAsNumber(values[0]);
 586   var p = TypeConverter.firstValueAsNumber(values[1]);
 587   return Math.pow(n, p);
 588@@ -239,7 +239,7 @@ var POWER = function (...values) : number {
 589  * @constructor
 590  */
 591 var SUM = function (...values) : number {
 592-  ArgsChecker.checkAtLeastLength(values, 1);
 593+  ArgsChecker.checkAtLeastLength(values, 1, "SUM");
 594   var result = 0;
 595   for (var i = 0; i < values.length; i++) {
 596     if (values[i] instanceof Array) {
 597@@ -261,7 +261,7 @@ var SUM = function (...values) : number {
 598  * @constructor
 599  */
 600 var SQRT = function (...values) : number {
 601-  ArgsChecker.checkLength(values, 1);
 602+  ArgsChecker.checkLength(values, 1, "SQRT");
 603   var x = TypeConverter.firstValueAsNumber(values[0]);
 604   if (x < 0) {
 605     throw new ValueError("Function SQRT parameter 1 expects number values. But '" + values[0] + "' is a text and cannot be coerced to a number.");
 606@@ -276,7 +276,7 @@ var SQRT = function (...values) : number {
 607  * @constructor
 608  */
 609 var SQRTPI = function (...values) : number{
 610-  ArgsChecker.checkLength(values, 1);
 611+  ArgsChecker.checkLength(values, 1, "SQRTPI");
 612   var n = TypeConverter.firstValueAsNumber(values[0]);
 613   if (n < 0) {
 614     throw new NumError("Function SQRTPI parameter 1 value is " + n + ". It should be greater than or equal to 0.");
 615@@ -291,7 +291,7 @@ var SQRTPI = function (...values) : number{
 616  * @constructor
 617  */
 618 var COS = function (...values) : number {
 619-  ArgsChecker.checkLength(values, 1);
 620+  ArgsChecker.checkLength(values, 1, "COS");
 621   var r = TypeConverter.firstValueAsNumber(values[0]);
 622   return Math.cos(r);
 623 };
 624@@ -303,7 +303,7 @@ var COS = function (...values) : number {
 625  * @constructor
 626  */
 627 var COSH = function (...values) : number {
 628-  ArgsChecker.checkLength(values, 1);
 629+  ArgsChecker.checkLength(values, 1, "COSH");
 630   var r = TypeConverter.firstValueAsNumber(values[0]);
 631   return Math["cosh"](r);
 632 };
 633@@ -315,7 +315,7 @@ var COSH = function (...values) : number {
 634  * @constructor
 635  */
 636 var COT = function (...values) : number {
 637-  ArgsChecker.checkLength(values, 1);
 638+  ArgsChecker.checkLength(values, 1, "COT");
 639   var x = TypeConverter.firstValueAsNumber(values[0]);
 640   if (x === 0) {
 641     throw new DivZeroError("Evaluation of function COT caused a divide by zero error.");
 642@@ -330,7 +330,7 @@ var COT = function (...values) : number {
 643  * @constructor
 644  */
 645 var COTH = function (...values) : number {
 646-  ArgsChecker.checkLength(values, 1);
 647+  ArgsChecker.checkLength(values, 1, "COTH");
 648   var x = TypeConverter.firstValueAsNumber(values[0]);
 649   if (x === 0) {
 650     throw new DivZeroError("Evaluation of function COTH caused a divide by zero error.");
 651@@ -345,7 +345,7 @@ var COTH = function (...values) : number {
 652  * @constructor
 653  */
 654 var INT = function (...values) : number {
 655-  ArgsChecker.checkLength(values, 1);
 656+  ArgsChecker.checkLength(values, 1, "INT");
 657   var x = TypeConverter.firstValueAsNumber(values[0]);
 658   return Math.floor(x);
 659 };
 660@@ -358,7 +358,7 @@ var INT = function (...values) : number {
 661  * @constructor
 662  */
 663 var ISEVEN = function (...values) : boolean {
 664-  ArgsChecker.checkLength(values, 1);
 665+  ArgsChecker.checkLength(values, 1, "ISEVEN");
 666   if (values[0] === "") {
 667     throw new ValueError("Function ISEVEN parameter 1 expects boolean values. But '" + values[0] + "' is a text and cannot be coerced to a boolean.");
 668   }
 669@@ -374,7 +374,7 @@ var ISEVEN = function (...values) : boolean {
 670  * @constructor
 671  */
 672 var ISODD = function (...values) : boolean {
 673-  ArgsChecker.checkLength(values, 1);
 674+  ArgsChecker.checkLength(values, 1, "ISODD");
 675   if (values[0] === "") {
 676     throw new ValueError("Function ISODD parameter 1 expects boolean values. But '" + values[0] + "' is a text and cannot be coerced to a boolean.");
 677   }
 678@@ -389,7 +389,7 @@ var ISODD = function (...values) : boolean {
 679  * @constructor
 680  */
 681 var SIN = function (...values) {
 682-  ArgsChecker.checkLength(values, 1);
 683+  ArgsChecker.checkLength(values, 1, "SIN");
 684   var rad = TypeConverter.firstValueAsNumber(values[0]);
 685   return rad === Math.PI ? 0 : Math.sin(rad);
 686 };
 687@@ -401,7 +401,7 @@ var SIN = function (...values) {
 688  * @constructor
 689  */
 690 var SINH = function (...values) : number {
 691-  ArgsChecker.checkLength(values, 1);
 692+  ArgsChecker.checkLength(values, 1, "SINH");
 693   var rad = TypeConverter.firstValueAsNumber(values[0]);
 694   return Math["sinh"](rad);
 695 };
 696@@ -412,6 +412,7 @@ var SINH = function (...values) : number {
 697  * @constructor
 698  */
 699 var PI = function () {
 700+  ArgsChecker.checkLength(arguments, 0, "SINH");
 701   return Math.PI;
 702 };
 703 
 704@@ -422,7 +423,7 @@ var PI = function () {
 705  * @constructor
 706  */
 707 var LOG10 = function (...values) : number {
 708-  ArgsChecker.checkLength(values, 1);
 709+  ArgsChecker.checkLength(values, 1, "LOG10");
 710   var n = TypeConverter.firstValueAsNumber(values[0]);
 711   if (n < 1) {
 712     throw new NumError("Function LOG10 parameter 1 value is " + n + ". It should be greater than 0.");
 713@@ -440,7 +441,7 @@ var LOG10 = function (...values) : number {
 714  * @constructor
 715  */
 716 var LOG = function (...values) : number {
 717-  ArgsChecker.checkAtLeastLength(values, 1);
 718+  ArgsChecker.checkAtLeastLength(values, 1, "LOG");
 719   var n = TypeConverter.firstValueAsNumber(values[0]);
 720   var b = 10;
 721   if (values.length > 1) {
 722@@ -467,7 +468,7 @@ var LOG = function (...values) : number {
 723  * @constructor
 724  */
 725 var LN = function (...values) : number {
 726-  ArgsChecker.checkLength(values, 1);
 727+  ArgsChecker.checkLength(values, 1, "LN");
 728   var n = TypeConverter.firstValueAsNumber(values[0]);
 729   if (n < 1) {
 730     throw new NumError("Function LN parameter 1 value is " + n + ". It should be greater than 0.");
 731@@ -482,7 +483,7 @@ var LN = function (...values) : number {
 732  * @constructor
 733  */
 734 var TAN = function (...values) : number {
 735-  ArgsChecker.checkLength(values, 1);
 736+  ArgsChecker.checkLength(values, 1, "TAN");
 737   var rad = TypeConverter.firstValueAsNumber(values[0]);
 738   return rad === Math.PI ? 0 : Math.tan(rad);
 739 };
 740@@ -494,7 +495,7 @@ var TAN = function (...values) : number {
 741  * @constructor
 742  */
 743 var TANH = function (...values) : number {
 744-  ArgsChecker.checkLength(values, 1);
 745+  ArgsChecker.checkLength(values, 1, "TANH");
 746   var rad = TypeConverter.firstValueAsNumber(values[0]);
 747   return Math["tanh"](rad);
 748 };
 749@@ -507,7 +508,7 @@ var TANH = function (...values) : number {
 750  * @constructor
 751  */
 752 var CEILING = function (...values) : number {
 753-  ArgsChecker.checkLengthWithin(values, 1, 2);
 754+  ArgsChecker.checkLengthWithin(values, 1, 2, "CEILING");
 755   var num = TypeConverter.firstValueAsNumber(values[0]);
 756   if (values.length === 1) {
 757     return Math.ceil(num);
 758@@ -532,7 +533,7 @@ var CEILING = function (...values) : number {
 759  * @constructor
 760  */
 761 var FLOOR = function (...values) : number {
 762-  ArgsChecker.checkLengthWithin(values, 1, 2);
 763+  ArgsChecker.checkLengthWithin(values, 1, 2, "FLOOR");
 764   var num = TypeConverter.firstValueAsNumber(values[0]);
 765   if (values.length === 1) {
 766     return Math.floor(num);
 767@@ -558,7 +559,7 @@ var FLOOR = function (...values) : number {
 768  * @constructor
 769  */
 770 var IF = function (...values) : any {
 771-  ArgsChecker.checkLength(values, 3);
 772+  ArgsChecker.checkLength(values, 3, "IF");
 773   if (values[0] instanceof Array) {
 774     if (values[0].length === 0) {
 775       throw new RefError("Reference does not exist.");
 776@@ -582,7 +583,7 @@ var IF = function (...values) : any {
 777  * @constructor
 778  */
 779 var COUNTIF = function (...values) {
 780-  ArgsChecker.checkLength(values, 2);
 781+  ArgsChecker.checkLength(values, 2, "COUNTIF");
 782   var range = values[0];
 783   if (!(range instanceof Array)) {
 784     range = [range];
 785@@ -611,7 +612,7 @@ var COUNTIF = function (...values) {
 786  * @constructor
 787  */
 788 var COUNTIFS = function (...values) {
 789-  ArgsChecker.checkAtLeastLength(values, 2);
 790+  ArgsChecker.checkAtLeastLength(values, 2, "COUNTIFS");
 791   var criteriaEvaluationFunctions = values.map(function (criteria, index) {
 792     if (index % 2 === 1) {
 793       return CriteriaFunctionFactory.createCriteriaFunction(criteria);
 794@@ -661,7 +662,7 @@ var COUNTIFS = function (...values) {
 795  * @constructor
 796  */
 797 var ROUND = function (...values) {
 798-  ArgsChecker.checkLengthWithin(values, 1, 2);
 799+  ArgsChecker.checkLengthWithin(values, 1, 2, "ROUND");
 800   var n = TypeConverter.firstValueAsNumber(values[0]);
 801   if (values.length === 1) {
 802     return Math.round(n);
 803@@ -678,7 +679,7 @@ var ROUND = function (...values) {
 804  * @constructor
 805  */
 806 var ROUNDDOWN = function (...values) {
 807-  ArgsChecker.checkLengthWithin(values, 1, 2);
 808+  ArgsChecker.checkLengthWithin(values, 1, 2, "ROUNDDOWN");
 809   var n = TypeConverter.firstValueAsNumber(values[0]);
 810   if (values.length === 1) {
 811     return Math.floor(n);
 812@@ -695,7 +696,7 @@ var ROUNDDOWN = function (...values) {
 813  * @constructor
 814  */
 815 var ROUNDUP = function (...values) {
 816-  ArgsChecker.checkLengthWithin(values, 1, 2);
 817+  ArgsChecker.checkLengthWithin(values, 1, 2, "ROUNDUP");
 818   var n = TypeConverter.firstValueAsNumber(values[0]);
 819   if (values.length === 1) {
 820     return Math.ceil(n);
 821@@ -716,7 +717,7 @@ var ROUNDUP = function (...values) {
 822  * @constructor
 823  */
 824 var SUMIF = function (...values) {
 825-  ArgsChecker.checkLengthWithin(values, 2, 3);
 826+  ArgsChecker.checkLengthWithin(values, 2, 3, "SUMIF");
 827   var range = values[0];
 828   var criteria = values[1];
 829   var sumRange = null;
 830@@ -752,7 +753,7 @@ var SUMIF = function (...values) {
 831  * @constructor
 832  */
 833 var SUMSQ = function (...values) {
 834-  ArgsChecker.checkAtLeastLength(values, 1);
 835+  ArgsChecker.checkAtLeastLength(values, 1, "SUMSQ");
 836   var result = 0;
 837   for (var i = 0; i < values.length; i++) {
 838     if (values[i] instanceof Array) {
 839@@ -781,7 +782,7 @@ var SUMSQ = function (...values) {
 840  * @constructor
 841  */
 842 var TRUNC = function (...values) : number {
 843-  ArgsChecker.checkLengthWithin(values, 1, 2);
 844+  ArgsChecker.checkLengthWithin(values, 1, 2, "TRUNC");
 845   var n = TypeConverter.firstValueAsNumber(values[0]);
 846   var digits = 0;
 847   if (values.length === 2) {
 848@@ -799,7 +800,7 @@ var TRUNC = function (...values) : number {
 849  * @constructor
 850  */
 851 var RADIANS = function (...values) {
 852-  ArgsChecker.checkLength(values, 1);
 853+  ArgsChecker.checkLength(values, 1, "RADIANS");
 854   var d = TypeConverter.firstValueAsNumber(values[0]);
 855   return d * Math.PI / 180;
 856 };
 857@@ -811,7 +812,7 @@ var RADIANS = function (...values) {
 858  * @constructor
 859  */
 860 var DEGREES = function (...values) {
 861-  ArgsChecker.checkLength(values, 1);
 862+  ArgsChecker.checkLength(values, 1, "DEGREES");
 863   var r = TypeConverter.firstValueAsNumber(values[0]);
 864   return r * 180 / Math.PI;
 865 };
 866@@ -824,7 +825,7 @@ var DEGREES = function (...values) {
 867  * @constructor
 868  */
 869 var ERFC = function (...values) {
 870-  ArgsChecker.checkLength(values, 1);
 871+  ArgsChecker.checkLength(values, 1, "ERFC");
 872   var v = TypeConverter.firstValueAsNumber(values[0]);
 873   return v === 0 ? 1 : 1 - erf(v);
 874 };
 875@@ -839,7 +840,7 @@ var ERFC = function (...values) {
 876  * @constructor
 877  */
 878 var ERF = function (...values) : number {
 879-  ArgsChecker.checkLengthWithin(values, 1, 2);
 880+  ArgsChecker.checkLengthWithin(values, 1, 2, "ERF");
 881   var lower = TypeConverter.firstValueAsNumber(values[0]);
 882   var upper = values.length === 2 ? TypeConverter.firstValueAsNumber(values[1]) : 0;
 883   return values.length === 1 ? erf(lower) : erf(upper) - erf(lower);
 884@@ -902,7 +903,7 @@ function erf(x) {
 885  * @constructor
 886  */
 887 var SUMX2PY2 = function (...values) : number {
 888-  ArgsChecker.checkLength(values, 2);
 889+  ArgsChecker.checkLength(values, 2, "SUMX2PY2");
 890   var arrOne = Filter.flattenAndThrow(values[0]);
 891   var arrTwo = Filter.flattenAndThrow(values[1]);
 892   if (arrOne.length !== arrTwo.length) {
 893@@ -928,7 +929,7 @@ var SUMX2PY2 = function (...values) : number {
 894  * @constructor
 895  */
 896 var SUMX2MY2 = function (...values) : number {
 897-  ArgsChecker.checkLength(values, 2);
 898+  ArgsChecker.checkLength(values, 2, "SUMX2MY2");
 899   var arrOne = Filter.flattenAndThrow(values[0]);
 900   var arrTwo = Filter.flattenAndThrow(values[1]);
 901   if (arrOne.length !== arrTwo.length) {
 902@@ -953,7 +954,7 @@ var SUMX2MY2 = function (...values) : number {
 903  * @constructor
 904  */
 905 var COUNTUNIQUE = function (...values) : number {
 906-  ArgsChecker.checkAtLeastLength(values, 1);
 907+  ArgsChecker.checkAtLeastLength(values, 1, "COUNTUNIQUE");
 908 
 909   // Private function that will recursively generate an array of the unique primitives
 910   var countUniquePrivate = function (values: Array<any>) : Object {
 911@@ -988,7 +989,7 @@ var COUNTUNIQUE = function (...values) : number {
 912  * @constructor
 913  */
 914 var SUMPRODUCT = function (...values) : number {
 915-  ArgsChecker.checkAtLeastLength(values, 1);
 916+  ArgsChecker.checkAtLeastLength(values, 1, "SUMPRODUCT");
 917   // Ensuring that all values are array values
 918   for (var x = 0; x < values.length; x++) {
 919     if (!Array.isArray(values[x])) {
 920@@ -1027,6 +1028,8 @@ var SUMPRODUCT = function (...values) : number {
 921  * @constructor
 922  */
 923 var COMBIN = function (...values) : number {
 924+  ArgsChecker.checkLength(values, 2, "COMBIN");
 925+
 926   var MEMOIZED_FACT = [];
 927   function fact(number) {
 928     var n = Math.floor(number);
 929@@ -1039,7 +1042,6 @@ var COMBIN = function (...values) : number {
 930       return MEMOIZED_FACT[n];
 931     }
 932   }
 933-  ArgsChecker.checkLength(values, 2);
 934   var n = TypeConverter.firstValueAsNumber(values[0]);
 935   var c = TypeConverter.firstValueAsNumber(values[1]);
 936   if (n < c) {
 937diff --git a/src/Formulas/Statistical.ts b/src/Formulas/Statistical.ts
 938index c9a3ce3..840d42b 100644
 939--- a/src/Formulas/Statistical.ts
 940+++ b/src/Formulas/Statistical.ts
 941@@ -26,7 +26,7 @@ import {
 942  * @constructor
 943  */
 944 var DEVSQ = function (...values) : number {
 945-  ArgsChecker.checkAtLeastLength(values, 1);
 946+  ArgsChecker.checkAtLeastLength(values, 1, "DEVSQ");
 947   var range = Filter.flattenAndThrow(values);
 948   var result = 0;
 949   var count = 0;
 950@@ -49,7 +49,7 @@ var DEVSQ = function (...values) : number {
 951  * @constructor
 952  */
 953 var MEDIAN = function (...values) : number {
 954-  ArgsChecker.checkAtLeastLength(values, 1);
 955+  ArgsChecker.checkAtLeastLength(values, 1, "MEDIAN");
 956   var sortedArray = [];
 957   values.forEach(function (currentValue) {
 958     if (currentValue instanceof Array) {
 959@@ -94,7 +94,7 @@ var MEDIAN = function (...values) : number {
 960  * @constructor
 961  */
 962 var AVERAGE = function (...values) : number {
 963-  ArgsChecker.checkAtLeastLength(values, 1);
 964+  ArgsChecker.checkAtLeastLength(values, 1, "AVERAGE");
 965   var result = 0;
 966   var count = 0;
 967   for (var i = 0; i < values.length; i++) {
 968@@ -120,7 +120,7 @@ var AVERAGE = function (...values) : number {
 969  * @constructor
 970  */
 971 var AVEDEV = function (...values) {
 972-  ArgsChecker.checkAtLeastLength(values, 1);
 973+  ArgsChecker.checkAtLeastLength(values, 1, "AVEDEV");
 974 
 975   // Sort to array-values, and non-array-values
 976   var arrayValues = [];
 977@@ -167,7 +167,7 @@ var AVEDEV = function (...values) {
 978  * @constructor
 979  */
 980 var AVERAGEA = function (...values) {
 981-  ArgsChecker.checkAtLeastLength(values, 1);
 982+  ArgsChecker.checkAtLeastLength(values, 1, "AVERAGEA");
 983   var result = 0;
 984   var count = 0;
 985   for (var i = 0; i < values.length; i++) {
 986@@ -272,7 +272,7 @@ var CORREL = function (...values) : number {
 987     }
 988     return sum(sq_dev) / (arr1Len - 1);
 989   }
 990-  ArgsChecker.checkLength(values, 2);
 991+  ArgsChecker.checkLength(values, 2, "CORREL");
 992   if (!Array.isArray(values[0])) {
 993     values[0] = [values[0]];
 994   }
 995@@ -301,6 +301,7 @@ var CORREL = function (...values) : number {
 996  * @constructor
 997  */
 998 var PEARSON = function (...values) {
 999+  ArgsChecker.checkLength(values, 2, "PEARSON");
1000   return CORREL.apply(this, values);
1001 };
1002 
1003@@ -314,13 +315,13 @@ var PEARSON = function (...values) {
1004  * @constructor
1005  */
1006 var EXPONDIST = function (...values) : number {
1007+  ArgsChecker.checkLength(values, 3, "EXPONDIST");
1008   function cdf(x, rate) {
1009     return x < 0 ? 0 : 1 - Math.exp(-rate * x);
1010   }
1011   function pdf(x, rate) {
1012     return x < 0 ? 0 : rate * Math.exp(-rate * x);
1013   }
1014-  ArgsChecker.checkLength(values, 3);
1015   var x = TypeConverter.firstValueAsNumber(values[0]);
1016   var lambda = TypeConverter.firstValueAsNumber(values[1]);
1017   var cumulative = TypeConverter.firstValueAsBoolean(values[2]);
1018@@ -341,6 +342,7 @@ var EXPONDIST = function (...values) : number {
1019  * TODO: This function should be stricter in its return type.
1020  */
1021 var FDIST$LEFTTAILED = function (...values) : number|undefined|boolean {
1022+  ArgsChecker.checkLength(values, 4, "FDIST$LEFTTAILED");
1023   /**
1024    * Returns the Log-Gamma function evaluated at x. See http://jstat.github.io/special-functions.html#gammaln for more
1025    * information.
1026@@ -513,7 +515,6 @@ var FDIST$LEFTTAILED = function (...values) : number|undefined|boolean {
1027     // make sure x + y doesn't exceed the upper limit of usable values
1028     return (x + y > 170) ? Math.exp(betaln(x, y)) : gammafn(x) * gammafn(y) / gammafn(x + y);
1029   }
1030-  ArgsChecker.checkLength(values, 4);
1031   var x = TypeConverter.firstValueAsNumber(values[0]);
1032   if (x < 0) {
1033     throw new NumError("Function F.DIST parameter 1 value is " + x + ". It should be greater than or equal to 0.");
1034@@ -534,6 +535,7 @@ var FDIST$LEFTTAILED = function (...values) : number|undefined|boolean {
1035  * @constructor
1036  */
1037 var FINV = function (...values) : number {
1038+  ArgsChecker.checkLength(values, 3, "FINV");
1039   /**
1040    * Returns the continued fraction for the incomplete Beta function with parameters a and b modified by Lentz's method
1041    * evaluated at x. For more information see http://jstat.github.io/special-functions.html#betacf
1042@@ -684,7 +686,6 @@ var FINV = function (...values) : number {
1043   function inv(x, df1, df2) {
1044     return df2 / (df1 * (1 / ibetainv(x, df1 / 2, df2 / 2) - 1));
1045   }
1046-  ArgsChecker.checkLength(values, 3);
1047   var probability = TypeConverter.firstValueAsNumber(values[0]);
1048   if (probability <= 0.0 || probability > 1.0) {
1049     throw new NumError("Function FINV parameter 1 value is " + probability
1050@@ -702,7 +703,7 @@ var FINV = function (...values) : number {
1051  * @constructor
1052  */
1053 var FISHER = function (...values) : number {
1054-  ArgsChecker.checkLength(values, 1);
1055+  ArgsChecker.checkLength(values, 1, "FISHER");
1056   var x = TypeConverter.firstValueAsNumber(values[0]);
1057   if (x <= -1 || x >= 1) {
1058     throw new NumError("Function FISHER parameter 1 value is " + x + ". Valid values are between -1 and 1 exclusive.");
1059@@ -717,7 +718,7 @@ var FISHER = function (...values) : number {
1060  * @constructor
1061  */
1062 var FISHERINV = function (...values) : number {
1063-  ArgsChecker.checkLength(values, 1);
1064+  ArgsChecker.checkLength(values, 1, "FISHERINV");
1065   var y = TypeConverter.firstValueAsNumber(values[0]);
1066   var e2y = Math.exp(2 * y);
1067   return (e2y - 1) / (e2y + 1);
1068@@ -730,7 +731,7 @@ var FISHERINV = function (...values) : number {
1069  * @constructor
1070  */
1071 var MAX = function (...values) {
1072-  ArgsChecker.checkAtLeastLength(values, 1);
1073+  ArgsChecker.checkAtLeastLength(values, 1, "MAX");
1074   var maxSoFar = -Infinity;
1075   for (var i = 0; i < values.length; i++) {
1076     if (values[i] instanceof Array) {
1077@@ -755,6 +756,7 @@ var MAX = function (...values) {
1078  * @constructor
1079  */
1080 var MAXA = function (...values) : number {
1081+  ArgsChecker.checkAtLeastLength(values, 1, "MAXA");
1082   return MAX.apply(this, values);
1083 };
1084 
1085@@ -766,7 +768,7 @@ var MAXA = function (...values) : number {
1086  * @constructor
1087  */
1088 var MIN = function (...values) {
1089-  ArgsChecker.checkAtLeastLength(values, 1);
1090+  ArgsChecker.checkAtLeastLength(values, 1, "MIN");
1091   var minSoFar = Infinity;
1092   for (var i = 0; i < values.length; i++) {
1093     if (values[i] instanceof Array) {
1094@@ -792,6 +794,7 @@ var MIN = function (...values) {
1095  * @constructor
1096  */
1097 var MINA = function (...values) : number {
1098+  ArgsChecker.checkAtLeastLength(values, 1, "MINA");
1099   return MIN.apply(this, values);
1100 };
1101 
1102@@ -807,7 +810,7 @@ var MINA = function (...values) : number {
1103  * TODO: This needs to also accept a third parameter "average_range"
1104  */
1105 var AVERAGEIF = function (...values) {
1106-  ArgsChecker.checkLength(values, 2);
1107+  ArgsChecker.checkLength(values, 2, "AVERAGEIF");
1108   var range = Filter.flatten(values[0]);
1109   var criteriaEvaluation = CriteriaFunctionFactory.createCriteriaFunction(values[1]);
1110 
1111@@ -834,7 +837,7 @@ var AVERAGEIF = function (...values) {
1112  * @constructor
1113  */
1114 var COUNT = function (...values) : number {
1115-  ArgsChecker.checkAtLeastLength(values, 1);
1116+  ArgsChecker.checkAtLeastLength(values, 1, "COUNT");
1117   var count = 0;
1118   for (var i = 0; i < values.length; i++) {
1119     if (values[i] instanceof Array) {
1120@@ -855,7 +858,7 @@ var COUNT = function (...values) : number {
1121  * @constructor
1122  */
1123 var COUNTA = function (...values) : number {
1124-  ArgsChecker.checkAtLeastLength(values, 1);
1125+  ArgsChecker.checkAtLeastLength(values, 1, "COUNTA");
1126   var count = 0;
1127   for (var i = 0; i < values.length; i++) {
1128     if (values[i] instanceof Array) {
1129diff --git a/src/Formulas/Text.ts b/src/Formulas/Text.ts
1130index ca8dffb..01f99f6 100644
1131--- a/src/Formulas/Text.ts
1132+++ b/src/Formulas/Text.ts
1133@@ -18,7 +18,7 @@ import {
1134  * @constructor
1135  */
1136 var ARABIC = function (text?) {
1137-  ArgsChecker.checkLength(arguments, 1);
1138+  ArgsChecker.checkLength(arguments, 1, "ARABIC");
1139   if (typeof text !== "string") {
1140     throw new ValueError('Invalid roman numeral in ARABIC evaluation.');
1141   }
1142@@ -48,7 +48,7 @@ var ARABIC = function (text?) {
1143  * @constructor
1144  */
1145 var CHAR = function (...values) : string {
1146-  ArgsChecker.checkLength(values, 1);
1147+  ArgsChecker.checkLength(values, 1, "CHAR");
1148   var n = TypeConverter.firstValueAsNumber(values[0]);
1149   if (n < 1 || n > 1114112) { //limit
1150     throw new NumError("Function CHAR parameter 1 value " + n + " is out of range.");
1151@@ -63,7 +63,7 @@ var CHAR = function (...values) : string {
1152  * @constructor
1153  */
1154 var CODE = function (...values) : number {
1155-  ArgsChecker.checkLength(values, 1);
1156+  ArgsChecker.checkLength(values, 1, "CODE");
1157   var text = TypeConverter.firstValueAsString(values[0]);
1158   if (text === "") {
1159     throw new ValueError("Function CODE parameter 1 value should be non-empty.");
1160@@ -82,7 +82,7 @@ var CODE = function (...values) : number {
1161  * TODO: At some point this needs to return a more complex type than Array. Needs to return a type that has a dimension.
1162  */
1163 var SPLIT = function (...values) : Array<string> {
1164-  ArgsChecker.checkLengthWithin(values, 2, 3);
1165+  ArgsChecker.checkLengthWithin(values, 2, 3, "SPLIT");
1166   var text = TypeConverter.firstValueAsString(values[0]);
1167   var delimiter = TypeConverter.firstValueAsString(values[1]);
1168   var splitByEach = false;
1169@@ -114,7 +114,7 @@ var SPLIT = function (...values) : Array<string> {
1170  * @constructor
1171  */
1172 var CONCATENATE = function (...values) : string {
1173-  ArgsChecker.checkAtLeastLength(values, 1);
1174+  ArgsChecker.checkAtLeastLength(values, 1, "CONCATENATE");
1175   var string = '';
1176   for (var i = 0; i < values.length; i++) {
1177     if (values[i] instanceof Array) {
1178@@ -139,7 +139,7 @@ var CONCATENATE = function (...values) : string {
1179  * TODO: Looking up units is not efficient at all. We should use an object instead of iterating through an array.
1180  */
1181 var CONVERT = function (...values) {
1182-  ArgsChecker.checkLength(values, 3);
1183+  ArgsChecker.checkLength(values, 3, "CONVERT");
1184   var n = TypeConverter.firstValueAsNumber(values[0]);
1185   var fromUnit = TypeConverter.firstValueAsString(values[1]);
1186   var toUnit = TypeConverter.firstValueAsString(values[2]);
1187diff --git a/src/Utilities/ArgsChecker.ts b/src/Utilities/ArgsChecker.ts
1188index d8c6c0d..cc85633 100644
1189--- a/src/Utilities/ArgsChecker.ts
1190+++ b/src/Utilities/ArgsChecker.ts
1191@@ -10,10 +10,13 @@ class ArgsChecker {
1192    * Checks to see if the arguments are of the correct length.
1193    * @param args to check length of
1194    * @param length expected length
1195+   * @param caller name of the function calling this function, for use in error message formatting
1196    */
1197-  static checkLength(args: Array<any> | IArguments, length: number) {
1198+  static checkLength(args: Array<any> | IArguments, length: number, caller?: string) {
1199     if (args.length !== length) {
1200-      throw new NAError("Wrong number of arguments to ___. Expected 1 arguments, but got " + args.length + " arguments.");
1201+      var functionName = caller !== undefined ? " to " + caller : "";
1202+      throw new NAError("Wrong number of arguments" + functionName + ". Expected " + length
1203+          + " arguments, but got " + args.length + " arguments.");
1204     }
1205   }
1206 
1207@@ -21,10 +24,13 @@ class ArgsChecker {
1208    * Checks to see if the arguments are at least a certain length.
1209    * @param args to check length of
1210    * @param length expected length
1211+   * @param caller name of the function calling this function, for use in error message formatting
1212    */
1213-  static checkAtLeastLength(args: any, length: number) {
1214+  static checkAtLeastLength(args: any, length: number, caller?: string) {
1215     if (args.length < length) {
1216-      throw new NAError("Wrong number of arguments to ___. Expected " + length + " arguments, but got " + args.length + " arguments.");
1217+      var functionName = caller !== undefined ? " to " + caller : "";
1218+      throw new NAError("Wrong number of arguments" + functionName + ". Expected " + length
1219+        + " arguments, but got " + args.length + " arguments.");
1220     }
1221   }
1222 
1223@@ -33,10 +39,13 @@ class ArgsChecker {
1224    * @param args to check length of
1225    * @param low least number of arguments
1226    * @param high max number of arguments
1227+   * @param caller name of the function calling this function, for use in error message formatting
1228    */
1229-  static checkLengthWithin(args: any, low: number, high: number) {
1230+  static checkLengthWithin(args: any, low: number, high: number, caller?: string) {
1231     if (args.length > high || args.length < low) {
1232-      throw new NAError("Wrong number of arguments to ___. Expected 1 arguments, but got " + args.length + " arguments.");
1233+      var functionName = caller !== undefined ? " to " + caller : "";
1234+      throw new NAError("Wrong number of arguments" + functionName + ". Expected between" + low
1235+        + "and " + high + " arguments, but got " + args.length + " arguments.");
1236     }
1237   }
1238 }
1239diff --git a/tests/Utilities/ArgsCheckerTest.ts b/tests/Utilities/ArgsCheckerTest.ts
1240index 9c66105..8a1be62 100644
1241--- a/tests/Utilities/ArgsCheckerTest.ts
1242+++ b/tests/Utilities/ArgsCheckerTest.ts
1243@@ -9,13 +9,31 @@ import {
1244 import {NA_ERROR} from "../../src/Errors";
1245 
1246 
1247+function catchAndAssertErrorFormatting(toExecute : Function, errorString: string, nameToMatch: string) {
1248+  var toThrow = null;
1249+  try {
1250+    toExecute();
1251+    toThrow = true;
1252+  } catch (actualError) {
1253+    if (actualError.name !== errorString || actualError.message.indexOf(nameToMatch) === -1) {
1254+      console.log("expected:", errorString, " actual:", actualError.name, actualError.message);
1255+      console.trace();
1256+    }
1257+  }
1258+  if (toThrow) {
1259+    console.log("expected error: " + errorString, "and function name in error: ", nameToMatch);
1260+    console.trace();
1261+  }
1262+}
1263+
1264+const FORMULA_NAME = "FROMTEST";
1265 test("ArgsChecker.checkLength", function () {
1266   assertEquals(ArgsChecker.checkLength(["A", "B"], 2), undefined);
1267   assertEquals(ArgsChecker.checkLength(["A"], 1), undefined);
1268   assertEquals(ArgsChecker.checkLength([], 0), undefined);
1269-  catchAndAssertEquals(function () {
1270-    ArgsChecker.checkLength(["A", "B"], 100);
1271-  }, NA_ERROR);
1272+  catchAndAssertErrorFormatting(function () {
1273+    ArgsChecker.checkLength(["A", "B"], 100, FORMULA_NAME);
1274+  }, NA_ERROR, FORMULA_NAME);
1275 });
1276 
1277 
1278@@ -25,9 +43,9 @@ test("ArgsChecker.checkAtLeastLength", function () {
1279   assertEquals(ArgsChecker.checkAtLeastLength(["A"], 1), undefined);
1280   assertEquals(ArgsChecker.checkAtLeastLength(["A"], 0), undefined);
1281   assertEquals(ArgsChecker.checkAtLeastLength([], 0), undefined);
1282-  catchAndAssertEquals(function () {
1283-    ArgsChecker.checkAtLeastLength(["A", "B"], 3);
1284-  }, NA_ERROR);
1285+  catchAndAssertErrorFormatting(function () {
1286+    ArgsChecker.checkAtLeastLength(["A", "B"], 3, FORMULA_NAME);
1287+  }, NA_ERROR, FORMULA_NAME);
1288 });
1289 
1290 
1291@@ -36,9 +54,13 @@ test("ArgsChecker.checkLengthWithin", function () {
1292   assertEquals(ArgsChecker.checkLengthWithin(["A", "B"], 1, 4), undefined);
1293   assertEquals(ArgsChecker.checkLengthWithin(["A", "B", "C", "D"], 1, 4), undefined);
1294   assertEquals(ArgsChecker.checkLengthWithin(["A", "B", "C", "D"], 1, 6), undefined);
1295-  catchAndAssertEquals(function () {
1296-    ArgsChecker.checkLengthWithin(["A", "B"], 3, 10);
1297-    ArgsChecker.checkLengthWithin(["A", "B"], 5, 10);
1298-    ArgsChecker.checkLengthWithin(["A", "B", "C", "D"], 5, 6);
1299-  }, NA_ERROR);
1300+  catchAndAssertErrorFormatting(function () {
1301+    ArgsChecker.checkLengthWithin(["A", "B"], 3, 10, FORMULA_NAME);
1302+  }, NA_ERROR, FORMULA_NAME);
1303+  catchAndAssertErrorFormatting(function () {
1304+    ArgsChecker.checkLengthWithin(["A", "B"], 5, 10, FORMULA_NAME);
1305+  }, NA_ERROR, FORMULA_NAME);
1306+  catchAndAssertErrorFormatting(function () {
1307+    ArgsChecker.checkLengthWithin(["A", "B", "C", "D"], 5, 6, FORMULA_NAME);
1308+  }, NA_ERROR, FORMULA_NAME);
1309 });