spreadsheet
typeScript/javascript spreadsheet parser, with formulas.
git clone https://git.vogt.world/spreadsheet.git
Log | Files | README.md
← Commit log
commit
message
Refactoring formulas into files
author
Ben Vogt <[email protected]>
date
2017-02-16 01:29:57
stats
2 file(s) changed, 342 insertions(+), 419 deletions(-)
files
src/RawFormulas/Math.ts
src/RawFormulas/RawFormulas.ts
  1diff --git a/src/RawFormulas/Math.ts b/src/RawFormulas/Math.ts
  2index 7785894..2ae9e1e 100644
  3--- a/src/RawFormulas/Math.ts
  4+++ b/src/RawFormulas/Math.ts
  5@@ -1,5 +1,5 @@
  6 import { checkArgumentsLength, checkArgumentsAtLeastLength, valueToNumber, filterOutStringValues, flatten,
  7-    stringValuesToZeros, firstValueAsNumber, valueToBoolean} from "./Utils"
  8+    stringValuesToZeros, firstValueAsNumber, valueToBoolean, checkArgumentsAtWithin, CriteriaFunctionFactory, valueCanCoerceToNumber} from "./Utils"
  9 import { CellError } from "../Errors"
 10 import * as ERRORS from "../Errors"
 11 
 12@@ -711,6 +711,326 @@ var TANH = function (...values) : number {
 13   return Math["tanh"](rad);
 14 };
 15 
 16+/**
 17+ * Returns the average of a range depending on criteria.
 18+ * @param values[0] criteria_range - The range to check against criterion.
 19+ * @param values[1] criterion - The pattern or test to apply to criteria_range.
 20+ * @param values[2] average_range - [optional] The range to average. If not included, criteria_range is used for the
 21+ * average instead.
 22+ * @returns {number}
 23+ * @constructor
 24+ * TODO: This needs to take nested range values.
 25+ * TODO: This needs to also accept a third parameter "average_range"
 26+ */
 27+var AVERAGEIF = function (...values) {
 28+  checkArgumentsLength(values, 2);
 29+  var range = values[0];
 30+  var criteriaEvaluation = CriteriaFunctionFactory.createCriteriaFunction(values[1]);
 31+
 32+  var result = 0;
 33+  var count = 0;
 34+  for (var i = 0; i < range.length; i++) {
 35+    var val = valueToNumber(range[i]);
 36+    if (criteriaEvaluation(val)) {
 37+      result = result + val;
 38+      count++;
 39+    }
 40+  }
 41+  if (count === 0) {
 42+    throw new CellError(ERRORS.DIV_ZERO_ERROR, "Evaluation of function AVERAGEIF caused a divide by zero error.");
 43+  }
 44+  return result / count;
 45+};
 46+
 47+/**
 48+ * Rounds a number up to the nearest integer multiple of specified significance.
 49+ * @param values[0] The value to round up to the nearest integer multiple of factor.
 50+ * @param values[1] The number to whose multiples value will be rounded.
 51+ * @returns {number}
 52+ * @constructor
 53+ */
 54+var CEILING = function (...values) : number {
 55+  checkArgumentsAtWithin(values, 1, 2);
 56+  var num = firstValueAsNumber(values[0]);
 57+  if (values.length === 1) {
 58+    return Math.ceil(num);
 59+  }
 60+  var significance = firstValueAsNumber(values[1]);
 61+  if (significance === 0) {
 62+    throw new CellError(ERRORS.DIV_ZERO_ERROR, "Function CEILING parameter 2 cannot be zero.");
 63+  }
 64+  var precision = -Math.floor(Math.log(significance) / Math.log(10));
 65+  if (num >= 0) {
 66+    return ROUND(Math.ceil(num / significance) * significance, precision);
 67+  } else {
 68+    return -ROUND(Math.floor(Math.abs(num) / significance) * significance, precision);
 69+  }
 70+};
 71+
 72+/**
 73+ * Rounds a number down to the nearest integer multiple of specified significance.
 74+ * @param values[0] The value to round down to the nearest integer multiple of factor.
 75+ * @param values[1] The number to whose multiples value will be rounded.
 76+ * @returns {number}
 77+ * @constructor
 78+ */
 79+var FLOOR = function (...values) : number {
 80+  checkArgumentsAtWithin(values, 1, 2);
 81+  var num = firstValueAsNumber(values[0]);
 82+  if (values.length === 1) {
 83+    return Math.floor(num);
 84+  }
 85+  var significance = firstValueAsNumber(values[1]);
 86+  if (significance === 0) {
 87+    throw new CellError(ERRORS.DIV_ZERO_ERROR, "Function FLOOR parameter 2 cannot be zero.");
 88+  }
 89+  significance = significance ? Math.abs(significance) : 1;
 90+  var precision = -Math.floor(Math.log(significance) / Math.log(10));
 91+  if (num >= 0) {
 92+    return ROUND(Math.floor(num / significance) * significance, precision);
 93+  }
 94+  return -ROUND(Math.floor(Math.abs(num) / significance) * significance, precision);
 95+};
 96+
 97+/**
 98+ * Returns one value if a logical expression is TRUE and another if it is FALSE.
 99+ * @param values[0] An expression or reference to a cell containing an expression that represents some logical value, i.e. TRUE or FALSE.
100+ * @param values[1] The value the function returns if logical_expression is TRUE
101+ * @param values[2] The value the function returns if logical_expression is FALSE.
102+ * @returns one value if a logical expression is TRUE and another if it is FALSE.
103+ * @constructor
104+ */
105+var IF = function (...values) : any {
106+  checkArgumentsLength(values, 3);
107+  if (values[0] instanceof Array) {
108+    if (values[0].length === 0) {
109+      throw new CellError(ERRORS.REF_ERROR, "Reference does not exist.");
110+    }
111+    return IF(values[0][0], values[1], values[2]);
112+  } else if (values[0] === "") {
113+    return values[2];
114+  }
115+  return (valueToBoolean(values[0])) ? values[1] : values[2];
116+};
117+
118+/**
119+ * Returns the a count of the number of numeric values in a dataset.
120+ * @param values The values or ranges to consider when counting.
121+ * @returns {number} number of numeric values in a dataset.
122+ * @constructor
123+ */
124+var COUNT = function (...values) : number {
125+  checkArgumentsAtLeastLength(values, 1);
126+  var count = 0;
127+  for (var i = 0; i < values.length; i++) {
128+    if (values[i] instanceof Array) {
129+      if (values[i].length > 0) {
130+        count += COUNT.apply(this, values[i]);
131+      }
132+    } else if (valueCanCoerceToNumber(values[i])) {
133+      count++;
134+    }
135+  }
136+  return count;
137+};
138+
139+/**
140+ * Returns a conditional count across a range.
141+ * @param values[0] range - The range that is tested against criterion., value[1];
142+ * @param values[1] criterion - The pattern or test to apply to range. If the range to check against contains text, this must be a
143+ * string. It can be a comparison based string (e.g. "=1", "<1", ">=1") or it can be a wild-card string, in which *
144+ * matches any number of characters, and ? matches the next character. Both ? and * can be escaped by placing a ~ in
145+ * front of them. If it is neither, it will compared with values in the range using equality comparison.
146+ * @returns {number}
147+ * @constructor
148+ * TODO: This needs to take nested range values.
149+ */
150+var COUNTIF = function (...values) {
151+  checkArgumentsLength(values, 2);
152+  var range = values[0];
153+  var criteria = values[1];
154+
155+  var criteriaEvaluation = CriteriaFunctionFactory.createCriteriaFunction(criteria);
156+
157+  var count = 0;
158+  for (var i = 0; i < range.length; i++) {
159+    var x = range[i];
160+    if (criteriaEvaluation(x)) {
161+      count++;
162+    }
163+  }
164+  return count;
165+};
166+
167+/**
168+ * Returns the count of a range depending on multiple criteria.
169+ * @param values[0] criteria_range1 - The range to check against criterion1.
170+ * @param values[1] criterion1 - The pattern or test to apply to criteria_range1.
171+ * @param values[2...N] Repeated sets of ranges and criterion to check.
172+ * @returns {number} count
173+ * @constructor
174+ * TODO: This needs to take nested range values.
175+ */
176+var COUNTIFS = function (...values) {
177+  checkArgumentsAtLeastLength(values, 2);
178+  var criteriaEvaluationFunctions = values.map(function (criteria, index) {
179+    if (index % 2 === 1) {
180+      return CriteriaFunctionFactory.createCriteriaFunction(criteria);
181+    } else {
182+      return function () {return false;}
183+    }
184+  });
185+
186+  var count = 0;
187+  // For every value in the range
188+  for (var i = 0; i < values[0].length; i++) {
189+    // check for criteria eval for other ranges and other criteria pairs
190+    var otherCriteriaEvaluationSuccessfulSoFar = true;
191+    for (var x = 0; x < values.length; x += 2) {
192+      if (values[x].length < values[0].length) {
193+        throw new CellError(ERRORS.VALUE_ERROR, "Array arguments to COUNTIFS are of different size.");
194+      }
195+      var criteriaEvaluation = criteriaEvaluationFunctions[x+1];
196+      if (otherCriteriaEvaluationSuccessfulSoFar) {
197+        if (!criteriaEvaluation(values[x][i])) { // evaluate THIS value with x+1 index, which is criteria
198+          otherCriteriaEvaluationSuccessfulSoFar = false;
199+        }
200+      }
201+    }
202+    if (otherCriteriaEvaluationSuccessfulSoFar) {
203+      count++;
204+    }
205+  }
206+  return count;
207+};
208+
209+/**
210+ * Returns the a count of the number of values in a dataset.
211+ * @param values The values or ranges to consider when counting.
212+ * @returns {number} number of values in a dataset.
213+ * @constructor
214+ */
215+var COUNTA = function (...values) : number {
216+  checkArgumentsAtLeastLength(values, 1);
217+  var count = 0;
218+  for (var i = 0; i < values.length; i++) {
219+    if (values[i] instanceof Array) {
220+      if (values[i].length > 0) {
221+        count += COUNTA.apply(this, values[i]);
222+      } else {
223+        count++;
224+      }
225+    } else {
226+      count++;
227+    }
228+  }
229+  return count;
230+};
231+
232+/**
233+ * Compare two numeric values, returning 1 if they're equal.
234+ * @param values[0] The first number to compare.
235+ * @param values[1] The second number to compare.
236+ * @returns {number} 1 if they're equal, 0 if they're not equal.
237+ * @constructor
238+ */
239+var DELTA = function (...values) : number {
240+  checkArgumentsAtWithin(values, 1, 2);
241+  if (values.length === 1) {
242+    return valueToNumber(values[0]) === 0 ? 1 : 0;
243+  }
244+  return valueToNumber(values[0]) === valueToNumber(values[1]) ? 1 : 0;
245+};
246+
247+/**
248+ * Rounds a number to a certain number of decimal places according to standard rules.
249+ * @param values[0] The value to round to places number of places.
250+ * @param values[1] The number of decimal places to which to round.
251+ * @returns {number}
252+ * @constructor
253+ */
254+var ROUND = function (...values) {
255+  checkArgumentsAtWithin(values, 1, 2);
256+  var n = firstValueAsNumber(values[0]);
257+  if (values.length === 1) {
258+    return Math.round(n);
259+  }
260+  var d = firstValueAsNumber(values[1]);
261+  return Math.round(n * Math.pow(10, d)) / Math.pow(10, d);
262+};
263+
264+/**
265+ * Rounds a number to a certain number of decimal places, always rounding down to the next valid increment.
266+ * @param values[0] The value to round to places number of places, always rounding down.
267+ * @param values[1] (optional) The number of decimal places to which to round.
268+ * @returns {number}
269+ * @constructor
270+ */
271+var ROUNDDOWN = function (...values) {
272+  checkArgumentsAtWithin(values, 1, 2);
273+  var n = firstValueAsNumber(values[0]);
274+  if (values.length === 1) {
275+    return Math.floor(n);
276+  }
277+  var d = firstValueAsNumber(values[1]);
278+  return Math.floor(n * Math.pow(10, d)) / Math.pow(10, d);
279+};
280+
281+/**
282+ * Rounds a number to a certain number of decimal places, always rounding up to the next valid increment.
283+ * @param values[0] The value to round to places number of places, always rounding up.
284+ * @param values[1] (optional) The number of decimal places to which to round.
285+ * @returns {number}
286+ * @constructor
287+ */
288+var ROUNDUP = function (...values) {
289+  checkArgumentsAtWithin(values, 1, 2);
290+  var n = firstValueAsNumber(values[0]);
291+  if (values.length === 1) {
292+    return Math.ceil(n);
293+  }
294+  var d = firstValueAsNumber(values[1]);
295+  return Math.ceil(n * Math.pow(10, d)) / Math.pow(10, d);
296+};
297+
298+/**
299+ * Returns a conditional sum across a range.
300+ * @param values[0] The range which is tested against criterion.
301+ * @param values[1] The pattern or test to apply to range. If the range to check against contains text, this must be a
302+ * string. It can be a comparison based string (e.g. "=1", "<1", ">=1") or it can be a wild-card string, in which *
303+ * matches any number of characters, and ? matches the next character. Both ? and * can be escaped by placing a ~ in
304+ * front of them.
305+ * @param values[2] (optional) The range to be summed, if different from range.
306+ * @returns {number}
307+ * @constructor
308+ * TODO: This needs to take nested range values.
309+ */
310+var SUMIF = function (...values) {
311+  checkArgumentsAtWithin(values, 2, 3);
312+  var range = values[0];
313+  var criteria = values[1];
314+  var sumRange = null;
315+  if (values.length === 3) {
316+    sumRange = values[2];
317+  }
318+
319+  var criteriaEvaluation = CriteriaFunctionFactory.createCriteriaFunction(criteria);
320+
321+  var sum = 0;
322+  for (var i = 0; i < range.length; i++) {
323+    var x = range[i];
324+    if (sumRange && i > sumRange.length-1) {
325+      continue;
326+    }
327+    if (values.length === 2 && valueCanCoerceToNumber(x) && criteriaEvaluation(x)) {
328+      sum = sum + x;
329+    } else if (values.length === 3 && valueCanCoerceToNumber(sumRange[i]) && criteriaEvaluation(x)) {
330+      sum = sum + sumRange[i];
331+    }
332+  }
333+  return sum;
334+};
335+
336 export {
337   ABS,
338   ACOS,
339@@ -750,5 +1070,18 @@ export {
340   LOG10,
341   LN,
342   TAN,
343-  TANH
344+  TANH,
345+  AVERAGEIF,
346+  ROUND,
347+  ROUNDDOWN,
348+  ROUNDUP,
349+  SUMIF,
350+  FLOOR,
351+  IF,
352+  DELTA,
353+  COUNT,
354+  COUNTA,
355+  COUNTIF,
356+  COUNTIFS,
357+  CEILING
358 }
359\ No newline at end of file
360diff --git a/src/RawFormulas/RawFormulas.ts b/src/RawFormulas/RawFormulas.ts
361index 37dccd7..9cfaa95 100644
362--- a/src/RawFormulas/RawFormulas.ts
363+++ b/src/RawFormulas/RawFormulas.ts
364@@ -40,7 +40,20 @@ import {
365   LOG10,
366   LN,
367   TAN,
368-  TANH
369+  TANH,
370+  AVERAGEIF,
371+  ROUND,
372+  ROUNDDOWN,
373+  ROUNDUP,
374+  SUMIF,
375+  FLOOR,
376+  IF,
377+  DELTA,
378+  COUNT,
379+  COUNTA,
380+  COUNTIF,
381+  COUNTIFS,
382+  CEILING
383 } from "./Math";
384 import {
385   AND,
386@@ -129,326 +142,6 @@ var SUMX2PY2 = Formula["SUMX2PY2"];
387 var TRUNC = Formula["TRUNC"];
388 var YEARFRAC = Formula["YEARFRAC"];
389 
390-/**
391- * Returns the average of a range depending on criteria.
392- * @param values[0] criteria_range - The range to check against criterion.
393- * @param values[1] criterion - The pattern or test to apply to criteria_range.
394- * @param values[2] average_range - [optional] The range to average. If not included, criteria_range is used for the
395- * average instead.
396- * @returns {number}
397- * @constructor
398- * TODO: This needs to take nested range values.
399- * TODO: This needs to also accept a third parameter "average_range"
400- */
401-var AVERAGEIF = function (...values) {
402-  checkArgumentsLength(values, 2);
403-  var range = values[0];
404-  var criteriaEvaluation = CriteriaFunctionFactory.createCriteriaFunction(values[1]);
405-
406-  var result = 0;
407-  var count = 0;
408-  for (var i = 0; i < range.length; i++) {
409-    var val = valueToNumber(range[i]);
410-    if (criteriaEvaluation(val)) {
411-      result = result + val;
412-      count++;
413-    }
414-  }
415-  if (count === 0) {
416-    throw new CellError(ERRORS.DIV_ZERO_ERROR, "Evaluation of function AVERAGEIF caused a divide by zero error.");
417-  }
418-  return result / count;
419-};
420-
421-/**
422- * Rounds a number up to the nearest integer multiple of specified significance.
423- * @param values[0] The value to round up to the nearest integer multiple of factor.
424- * @param values[1] The number to whose multiples value will be rounded.
425- * @returns {number}
426- * @constructor
427- */
428-var CEILING = function (...values) : number {
429-  checkArgumentsAtWithin(values, 1, 2);
430-  var num = firstValueAsNumber(values[0]);
431-  if (values.length === 1) {
432-    return Math.ceil(num);
433-  }
434-  var significance = firstValueAsNumber(values[1]);
435-  if (significance === 0) {
436-    throw new CellError(ERRORS.DIV_ZERO_ERROR, "Function CEILING parameter 2 cannot be zero.");
437-  }
438-  var precision = -Math.floor(Math.log(significance) / Math.log(10));
439-  if (num >= 0) {
440-    return ROUND(Math.ceil(num / significance) * significance, precision);
441-  } else {
442-    return -ROUND(Math.floor(Math.abs(num) / significance) * significance, precision);
443-  }
444-};
445-
446-/**
447- * Rounds a number down to the nearest integer multiple of specified significance.
448- * @param values[0] The value to round down to the nearest integer multiple of factor.
449- * @param values[1] The number to whose multiples value will be rounded.
450- * @returns {number}
451- * @constructor
452- */
453-var FLOOR = function (...values) : number {
454-  checkArgumentsAtWithin(values, 1, 2);
455-  var num = firstValueAsNumber(values[0]);
456-  if (values.length === 1) {
457-    return Math.floor(num);
458-  }
459-  var significance = firstValueAsNumber(values[1]);
460-  if (significance === 0) {
461-    throw new CellError(ERRORS.DIV_ZERO_ERROR, "Function FLOOR parameter 2 cannot be zero.");
462-  }
463-  significance = significance ? Math.abs(significance) : 1;
464-  var precision = -Math.floor(Math.log(significance) / Math.log(10));
465-  if (num >= 0) {
466-    return ROUND(Math.floor(num / significance) * significance, precision);
467-  }
468-  return -ROUND(Math.floor(Math.abs(num) / significance) * significance, precision);
469-};
470-
471-/**
472- * Returns one value if a logical expression is TRUE and another if it is FALSE.
473- * @param values[0] An expression or reference to a cell containing an expression that represents some logical value, i.e. TRUE or FALSE.
474- * @param values[1] The value the function returns if logical_expression is TRUE
475- * @param values[2] The value the function returns if logical_expression is FALSE.
476- * @returns one value if a logical expression is TRUE and another if it is FALSE.
477- * @constructor
478- */
479-var IF = function (...values) : any {
480-  checkArgumentsLength(values, 3);
481-  if (values[0] instanceof Array) {
482-    if (values[0].length === 0) {
483-      throw new CellError(ERRORS.REF_ERROR, "Reference does not exist.");
484-    }
485-    return IF(values[0][0], values[1], values[2]);
486-  } else if (values[0] === "") {
487-    return values[2];
488-  }
489-  return (valueToBoolean(values[0])) ? values[1] : values[2];
490-};
491-
492-/**
493- * Returns the a count of the number of numeric values in a dataset.
494- * @param values The values or ranges to consider when counting.
495- * @returns {number} number of numeric values in a dataset.
496- * @constructor
497- */
498-var COUNT = function (...values) : number {
499-  checkArgumentsAtLeastLength(values, 1);
500-  var count = 0;
501-  for (var i = 0; i < values.length; i++) {
502-    if (values[i] instanceof Array) {
503-      if (values[i].length > 0) {
504-        count += COUNT.apply(this, values[i]);
505-      }
506-    } else if (valueCanCoerceToNumber(values[i])) {
507-      count++;
508-    }
509-  }
510-  return count;
511-};
512-
513-/**
514- * Returns a conditional count across a range.
515- * @param values[0] range - The range that is tested against criterion., value[1];
516- * @param values[1] criterion - The pattern or test to apply to range. If the range to check against contains text, this must be a
517- * string. It can be a comparison based string (e.g. "=1", "<1", ">=1") or it can be a wild-card string, in which *
518- * matches any number of characters, and ? matches the next character. Both ? and * can be escaped by placing a ~ in
519- * front of them. If it is neither, it will compared with values in the range using equality comparison.
520- * @returns {number}
521- * @constructor
522- * TODO: This needs to take nested range values.
523- */
524-var COUNTIF = function (...values) {
525-  checkArgumentsLength(values, 2);
526-  var range = values[0];
527-  var criteria = values[1];
528-
529-  var criteriaEvaluation = CriteriaFunctionFactory.createCriteriaFunction(criteria);
530-
531-  var count = 0;
532-  for (var i = 0; i < range.length; i++) {
533-    var x = range[i];
534-    if (criteriaEvaluation(x)) {
535-      count++;
536-    }
537-  }
538-  return count;
539-};
540-
541-/**
542- * Returns the count of a range depending on multiple criteria.
543- * @param values[0] criteria_range1 - The range to check against criterion1.
544- * @param values[1] criterion1 - The pattern or test to apply to criteria_range1.
545- * @param values[2...N] Repeated sets of ranges and criterion to check.
546- * @returns {number} count
547- * @constructor
548- * TODO: This needs to take nested range values.
549- */
550-var COUNTIFS = function (...values) {
551-  checkArgumentsAtLeastLength(values, 2);
552-  var criteriaEvaluationFunctions = values.map(function (criteria, index) {
553-    if (index % 2 === 1) {
554-      return CriteriaFunctionFactory.createCriteriaFunction(criteria);
555-    } else {
556-      return function () {return false;}
557-    }
558-  });
559-
560-  var count = 0;
561-  // For every value in the range
562-  for (var i = 0; i < values[0].length; i++) {
563-    // check for criteria eval for other ranges and other criteria pairs
564-    var otherCriteriaEvaluationSuccessfulSoFar = true;
565-    for (var x = 0; x < values.length; x += 2) {
566-      if (values[x].length < values[0].length) {
567-        throw new CellError(ERRORS.VALUE_ERROR, "Array arguments to COUNTIFS are of different size.");
568-      }
569-      var criteriaEvaluation = criteriaEvaluationFunctions[x+1];
570-      if (otherCriteriaEvaluationSuccessfulSoFar) {
571-        if (!criteriaEvaluation(values[x][i])) { // evaluate THIS value with x+1 index, which is criteria
572-          otherCriteriaEvaluationSuccessfulSoFar = false;
573-        }
574-      }
575-    }
576-    if (otherCriteriaEvaluationSuccessfulSoFar) {
577-      count++;
578-    }
579-  }
580-  return count;
581-};
582-
583-/**
584- * Returns the a count of the number of values in a dataset.
585- * @param values The values or ranges to consider when counting.
586- * @returns {number} number of values in a dataset.
587- * @constructor
588- */
589-var COUNTA = function (...values) : number {
590-  checkArgumentsAtLeastLength(values, 1);
591-  var count = 0;
592-  for (var i = 0; i < values.length; i++) {
593-    if (values[i] instanceof Array) {
594-      if (values[i].length > 0) {
595-        count += COUNTA.apply(this, values[i]);
596-      } else {
597-        count++;
598-      }
599-    } else {
600-      count++;
601-    }
602-  }
603-  return count;
604-};
605-
606-/**
607- * Compare two numeric values, returning 1 if they're equal.
608- * @param values[0] The first number to compare.
609- * @param values[1] The second number to compare.
610- * @returns {number} 1 if they're equal, 0 if they're not equal.
611- * @constructor
612- */
613-var DELTA = function (...values) : number {
614-  checkArgumentsAtWithin(values, 1, 2);
615-  if (values.length === 1) {
616-    return valueToNumber(values[0]) === 0 ? 1 : 0;
617-  }
618-  return valueToNumber(values[0]) === valueToNumber(values[1]) ? 1 : 0;
619-};
620-
621-/**
622- * Rounds a number to a certain number of decimal places according to standard rules.
623- * @param values[0] The value to round to places number of places.
624- * @param values[1] The number of decimal places to which to round.
625- * @returns {number}
626- * @constructor
627- */
628-var ROUND = function (...values) {
629-  checkArgumentsAtWithin(values, 1, 2);
630-  var n = firstValueAsNumber(values[0]);
631-  if (values.length === 1) {
632-    return Math.round(n);
633-  }
634-  var d = firstValueAsNumber(values[1]);
635-  return Math.round(n * Math.pow(10, d)) / Math.pow(10, d);
636-};
637-
638-/**
639- * Rounds a number to a certain number of decimal places, always rounding down to the next valid increment.
640- * @param values[0] The value to round to places number of places, always rounding down.
641- * @param values[1] (optional) The number of decimal places to which to round.
642- * @returns {number}
643- * @constructor
644- */
645-var ROUNDDOWN = function (...values) {
646-  checkArgumentsAtWithin(values, 1, 2);
647-  var n = firstValueAsNumber(values[0]);
648-  if (values.length === 1) {
649-    return Math.floor(n);
650-  }
651-  var d = firstValueAsNumber(values[1]);
652-  return Math.floor(n * Math.pow(10, d)) / Math.pow(10, d);
653-};
654-
655-/**
656- * Rounds a number to a certain number of decimal places, always rounding up to the next valid increment.
657- * @param values[0] The value to round to places number of places, always rounding up.
658- * @param values[1] (optional) The number of decimal places to which to round.
659- * @returns {number}
660- * @constructor
661- */
662-var ROUNDUP = function (...values) {
663-  checkArgumentsAtWithin(values, 1, 2);
664-  var n = firstValueAsNumber(values[0]);
665-  if (values.length === 1) {
666-    return Math.ceil(n);
667-  }
668-  var d = firstValueAsNumber(values[1]);
669-  return Math.ceil(n * Math.pow(10, d)) / Math.pow(10, d);
670-};
671-
672-/**
673- * Returns a conditional sum across a range.
674- * @param values[0] The range which is tested against criterion.
675- * @param values[1] The pattern or test to apply to range. If the range to check against contains text, this must be a
676- * string. It can be a comparison based string (e.g. "=1", "<1", ">=1") or it can be a wild-card string, in which *
677- * matches any number of characters, and ? matches the next character. Both ? and * can be escaped by placing a ~ in
678- * front of them.
679- * @param values[2] (optional) The range to be summed, if different from range.
680- * @returns {number}
681- * @constructor
682- * TODO: This needs to take nested range values.
683- */
684-var SUMIF = function (...values) {
685-  checkArgumentsAtWithin(values, 2, 3);
686-  var range = values[0];
687-  var criteria = values[1];
688-  var sumRange = null;
689-  if (values.length === 3) {
690-    sumRange = values[2];
691-  }
692-
693-  var criteriaEvaluation = CriteriaFunctionFactory.createCriteriaFunction(criteria);
694-
695-  var sum = 0;
696-  for (var i = 0; i < range.length; i++) {
697-    var x = range[i];
698-    if (sumRange && i > sumRange.length-1) {
699-      continue;
700-    }
701-    if (values.length === 2 && valueCanCoerceToNumber(x) && criteriaEvaluation(x)) {
702-      sum = sum + x;
703-    } else if (values.length === 3 && valueCanCoerceToNumber(sumRange[i]) && criteriaEvaluation(x)) {
704-      sum = sum + sumRange[i];
705-    }
706-  }
707-  return sum;
708-};
709-
710 export {
711   __COMPLEX,
712