spreadsheet
typeScript/javascript spreadsheet parser, with formulas.
git clone https://git.vogt.world/spreadsheet.git
Log | Files | README.md
← Commit log
commit
message
[WORKDAY] work-in-progress on formula and tests, adding TODO for NETWORKDAYS$INTL
author
Ben Vogt <[email protected]>
date
2017-04-29 01:10:22
stats
4 file(s) changed, 69 insertions(+), 19 deletions(-)
files
src/Cell.ts
src/RawFormulas/Date.ts
src/RawFormulas/RawFormulas.ts
tests/DateFormulasTest.ts
  1diff --git a/src/Cell.ts b/src/Cell.ts
  2index 4de3544..92baf9c 100644
  3--- a/src/Cell.ts
  4+++ b/src/Cell.ts
  5@@ -121,21 +121,9 @@ class Cell {
  6     return this.error;
  7   }
  8 
  9-  /**
 10-   * Get the renderable value for this cell, meaning the value that is the most meaningful to the user. If the error is
 11-   * null, we return the error. If we don't have an error, return the value.
 12-   * @returns {string} renderable string value to return.
 13-   */
 14-  getRenderedValue() : string {
 15-    if (this.error !== null) {
 16-      return this.value;
 17-    }
 18-    return this.error;
 19-  }
 20-
 21   /**
 22    * Returns the human-readable string representation of this cell, omitting some obvious fields.
 23-   * @returns {string} to return
 24+   * @returns {string}
 25    */
 26   toString() : string {
 27     return "id=" + this.id + ", value=" + this.value + ", formula=" + this.formula + ", error=" + this.error;
 28diff --git a/src/RawFormulas/Date.ts b/src/RawFormulas/Date.ts
 29index 568c76d..463f08c 100644
 30--- a/src/RawFormulas/Date.ts
 31+++ b/src/RawFormulas/Date.ts
 32@@ -725,7 +725,9 @@ var NETWORKDAYS$INTL = function (...values) : number {
 33           + "' cannot be coerced to a number.")
 34     }
 35   } else {
 36-    weekendDays = [1, 6];
 37+    // TODO: This had the wrong number of default weekend values and was still passing. Add a test that fails with
 38+    // TODO:     weekendDays = [1, 6] but not with [2, 6].
 39+    weekendDays = [0, 6];
 40   }
 41   var hasHolidays = values.length === 4;
 42   var holidays = [];
 43@@ -815,9 +817,56 @@ var TIME = function (...values) : ExcelTime {
 44 };
 45 
 46 
 47+/**
 48+ * Calculates the end date after a specified number of working days.
 49+ * @param values[0] start_date - The date from which to begin counting.
 50+ * @param values[1] num_days - The number of working days to advance from start_date. If negative, counts backwards. If
 51+ * not an integer, truncate.
 52+ * @param values[2] holidays - [ OPTIONAL ] - A range or array constant containing the dates to consider holidays. The
 53+ * values provided within an array for holidays must be date serial number values, as returned by N or date values, as
 54+ * returned by DATE, DATEVALUE or TO_DATE. Values specified by a range should be standard date values or date serial
 55+ * numbers.
 56+ * @returns {ExcelDate} end date after a specified number of working days.
 57+ * @constructor
 58+ */
 59+var WORKDAY = function (...values) {
 60+  ArgsChecker.checkLengthWithin(values, 2, 3);
 61+  var start = TypeCaster.firstValueAsExcelDate(values[0], true);
 62+  var days = TypeCaster.firstValueAsNumber(values[1]);
 63+  var hasHolidays = values.length === 3;
 64+  var holidays = [];
 65+  if (hasHolidays) {
 66+    if (values[2].length === 0) {
 67+      throw new RefError("Reference does not exist.");
 68+    }
 69+    for (var holidayDateValue of values[2]) {
 70+      if (holidayDateValue instanceof ExcelDate) {
 71+        holidays.push(holidayDateValue.toNumber());
 72+      } else if (typeof holidayDateValue === "number") {
 73+        holidays.push(holidayDateValue);
 74+      } else {
 75+        throw new ValueError("WORKDAY expects number values. But '" + holidayDateValue + "' is a " +
 76+          (typeof holidayDateValue) + " and cannot be coerced to a number.")
 77+      }
 78+    }
 79+  }
 80+
 81+  var weekend_days = [0, 6];
 82+  var cd = moment.utc(start.toMoment());
 83+  var j = 0;
 84+  while (j < days) {
 85+    cd.add(1, 'days');
 86+    if (weekend_days.indexOf(cd.day()) < 0 && holidays.indexOf(new ExcelDate(cd).toNumber()) < 0) {
 87+      j++;
 88+    }
 89+  }
 90+  return new ExcelDate(cd);
 91+};
 92+
 93+
 94+
 95 // Functions unimplemented.
 96 var WORKDAY$INTL;
 97-var WORKDAY;
 98 
 99 export {
100   DATE,
101@@ -841,5 +890,6 @@ export {
102   NETWORKDAYS$INTL,
103   NOW,
104   TODAY,
105-  TIME
106+  TIME,
107+  WORKDAY
108 }
109\ No newline at end of file
110diff --git a/src/RawFormulas/RawFormulas.ts b/src/RawFormulas/RawFormulas.ts
111index f2a7682..af7c60e 100644
112--- a/src/RawFormulas/RawFormulas.ts
113+++ b/src/RawFormulas/RawFormulas.ts
114@@ -130,7 +130,8 @@ import {
115   NETWORKDAYS$INTL,
116   NOW,
117   TODAY,
118-  TIME
119+  TIME,
120+  WORKDAY
121 } from "./Date"
122 
123 var ACCRINT = Formula["ACCRINT"];
124@@ -264,5 +265,6 @@ export {
125   NETWORKDAYS$INTL,
126   NOW,
127   TODAY,
128-  TIME
129+  TIME,
130+  WORKDAY
131 }
132\ No newline at end of file
133diff --git a/tests/DateFormulasTest.ts b/tests/DateFormulasTest.ts
134index 443accc..ea33e4a 100644
135--- a/tests/DateFormulasTest.ts
136+++ b/tests/DateFormulasTest.ts
137@@ -19,7 +19,8 @@ import {
138   SECOND,
139   NETWORKDAYS,
140   NETWORKDAYS$INTL,
141-  TIME
142+  TIME,
143+  WORKDAY
144 } from "../src/RawFormulas/RawFormulas"
145 import * as ERRORS from "../src/Errors"
146 import {
147@@ -28,6 +29,13 @@ import {
148 } from "./utils/Asserts"
149 import moment = require("moment");
150 
151+
152+// Test WORKDAY
153+assertEquals(WORKDAY(DATE(1999, 2, 2), 10), DATE(1999, 2, 16));
154+assertEquals(WORKDAY(DATE(1999, 10, 10), 100), DATE(2000, 2, 25));
155+
156+
157+
158 // Test TIME
159 assertEquals(TIME(10, 10, 10).toNumber(), 0.4237268518518518);
160 assertEquals(TIME(34, 10, 10).toNumber(), 0.4237268518518518);