spreadsheet
typeScript/javascript spreadsheet parser, with formulas.
git clone https://git.vogt.world/spreadsheet.git
Log | Files | README.md
← Commit log
commit
message
Simplifying Formulas.ts
author
Ben Vogt <[email protected]>
date
2017-01-15 18:10:11
stats
1 file(s) changed, 0 insertions(+), 200 deletions(-)
files
src/Formulas.ts
  1diff --git a/src/Formulas.ts b/src/Formulas.ts
  2index 59561de..82a5211 100644
  3--- a/src/Formulas.ts
  4+++ b/src/Formulas.ts
  5@@ -1,5 +1,3 @@
  6-/// <reference path="../node_modules/moment/moment.d.ts"/>
  7-import * as moment from "moment";
  8 import * as Formula from "formulajs"
  9 import * as RawFormulas from "./RawFormulas";
 10 
 11@@ -22,209 +20,21 @@ const SUPPORTED_FORMULAS = [
 12   'XOR'
 13 ];
 14 
 15-const CustomFormulas = {
 16-  "F.DIST": Formula["FDIST"],
 17-  "F.INV": Formula["FINV"],
 18-  ATAN2: function (x, y) {
 19-    return Math.atan2(y, x);
 20-  },
 21-  DATEVALUE: function (dateString: string) : Date {
 22-    return new Date(dateString);
 23-  },
 24-  EDATE: function (start_date: Date, months) {
 25-    return moment(start_date).add(months, 'months').toDate();
 26-  },
 27-  EOMONTH: function (start_date, months) {
 28-    var edate = moment(start_date).add(months, 'months');
 29-    return new Date(edate.year(), edate.month(), edate.daysInMonth());
 30-  },
 31-  SIN: function (rad) {
 32-    return rad === Math.PI ? 0 : Math.sin(rad);
 33-  },
 34-  TAN: function (rad) {
 35-    return rad === Math.PI ? 0 : Math.tan(rad);
 36-  },
 37-  ACCRINT: function (issue, first, settlement, rate, par, frequency, basis) {
 38-    // Return error if either date is invalid
 39-    if (!moment(issue).isValid() || !moment(first).isValid() || !moment(settlement).isValid()) {
 40-      return '#VALUE!';
 41-    }
 42-
 43-    // Set default values
 44-    par = (typeof par === 'undefined') ? 0 : par;
 45-    basis = (typeof basis === 'undefined') ? 0 : basis;
 46-
 47-    // Return error if either rate or par are lower than or equal to zero
 48-    if (rate <= 0 || par <= 0) {
 49-      return '#NUM!';
 50-    }
 51-
 52-    // Return error if frequency is neither 1, 2, or 4
 53-    if ([1, 2, 4].indexOf(frequency) === -1) {
 54-      return '#NUM!';
 55-    }
 56-
 57-    // Return error if basis is neither 0, 1, 2, 3, or 4
 58-    if ([0, 1, 2, 3, 4].indexOf(basis) === -1) {
 59-      return '#NUM!';
 60-    }
 61-
 62-    // Return error if issue greater than or equal to settlement
 63-    if (moment(issue).diff(moment(settlement)) >= 0) {
 64-      return '#NUM!';
 65-    }
 66-
 67-    // Compute accrued interest
 68-    var factor : any = 0;
 69-    switch (basis) {
 70-      case 0:
 71-        // US (NASD) 30/360
 72-        factor = CustomFormulas.YEARFRAC(issue, settlement, basis);
 73-        break;
 74-      case 1:
 75-        // Actual/actual
 76-        factor = CustomFormulas.YEARFRAC(issue, settlement, basis);
 77-        break;
 78-      case 2:
 79-        // Actual/360
 80-        factor = CustomFormulas.YEARFRAC(issue, settlement, basis);
 81-        break;
 82-      case 3:
 83-        // Actual/365
 84-        factor = CustomFormulas.YEARFRAC(issue, settlement, basis);
 85-        break;
 86-      case 4:
 87-        // European 30/360
 88-        factor = CustomFormulas.YEARFRAC(issue, settlement, basis);
 89-        break;
 90-    }
 91-    return par * rate * factor;
 92-  },
 93-  YEARFRAC: function (start_date, end_date, basis) : any {
 94-    basis = (typeof basis === 'undefined') ? 0 : basis;
 95-    var sdate = moment(new Date(start_date));
 96-    var edate = moment(new Date(end_date));
 97-
 98-    // Return error if either date is invalid
 99-    if (!sdate.isValid() || !edate.isValid()) {
100-      return '#VALUE!';
101-    }
102-
103-    // Return error if basis is neither 0, 1, 2, 3, or 4
104-    if ([0, 1, 2, 3, 4].indexOf(basis) === -1) {
105-      return '#NUM!';
106-    }
107-
108-    // Return zero if start_date and end_date are the same
109-    if (sdate === edate) {
110-      return 0;
111-    }
112-
113-    // Swap dates if start_date is later than end_date
114-    if (sdate.diff(edate) > 0) {
115-      edate = moment(new Date(start_date));
116-      sdate = moment(new Date(end_date));
117-    }
118-
119-    // Lookup years, months, and days
120-    var syear = sdate.year();
121-    var smonth = sdate.month();
122-    var sday = sdate.date();
123-    var eyear = edate.year();
124-    var emonth = edate.month();
125-    var eday = edate.date();
126-
127-    switch (basis) {
128-      case 0:
129-        // US (NASD) 30/360
130-        // Note: if eday == 31, it stays 31 if sday < 30
131-        if (sday === 31 && eday === 31) {
132-          sday = 30;
133-          eday = 30;
134-        } else if (sday === 31) {
135-          sday = 30;
136-        } else if (sday === 30 && eday === 31) {
137-          eday = 30;
138-        } else if (smonth === 1 && emonth === 1 && sdate.daysInMonth() === sday && edate.daysInMonth() === eday) {
139-          sday = 30;
140-          eday = 30;
141-        } else if (smonth === 1 && sdate.daysInMonth() === sday) {
142-          sday = 30;
143-        }
144-        return ((eday + emonth * 30 + eyear * 360) - (sday + smonth * 30 + syear * 360)) / 360;
145-
146-      case 1:
147-        // Actual/actual
148-        var feb29Between = function (date1, date2) {
149-          // Requires year2 == (year1 + 1) or year2 == year1
150-          // Returns TRUE if February 29 is between the two dates (date1 may be February 29), with two possibilities:
151-          // year1 is a leap year and date1 <= Februay 29 of year1
152-          // year2 is a leap year and date2 > Februay 29 of year2
153-
154-          var mar1year1 = moment(new Date(date1.year(), 2, 1));
155-          if (moment([date1.year()]).isLeapYear() && date1.diff(mar1year1) < 0 && date2.diff(mar1year1) >= 0) {
156-            return true;
157-          }
158-          var mar1year2 = moment(new Date(date2.year(), 2, 1));
159-          if (moment([date2.year()]).isLeapYear() && date2.diff(mar1year2) >= 0 && date1.diff(mar1year2) < 0) {
160-            return true;
161-          }
162-          return false;
163-        };
164-        var ylength = 365;
165-        if (syear === eyear || ((syear + 1) === eyear) && ((smonth > emonth) || ((smonth === emonth) && (sday >= eday)))) {
166-          if (syear === eyear && moment([syear]).isLeapYear()) {
167-            ylength = 366;
168-          } else if (feb29Between(sdate, edate) || (emonth === 1 && eday === 29)) {
169-            ylength = 366;
170-          }
171-          return edate.diff(sdate, 'days') / ylength;
172-        } else {
173-          var years = (eyear - syear) + 1;
174-          var days = moment(new Date(eyear + 1, 0, 1)).diff(moment(new Date(syear, 0, 1)), 'days');
175-          var average = days / years;
176-          return edate.diff(sdate, 'days') / average;
177-        }
178-
179-      case 2:
180-        // Actual/360
181-        return edate.diff(sdate, 'days') / 360;
182-
183-      case 3:
184-        // Actual/365
185-        return edate.diff(sdate, 'days') / 365;
186-
187-      case 4:
188-        // European 30/360
189-        if (sday === 31) {
190-          sday = 30;
191-        }
192-
193-        if (eday === 31) {
194-          eday = 30;
195-        }
196-        // Remarkably, do NOT change February 28 or February 29 at ALL
197-        return ((eday + emonth * 30 + eyear * 360) - (sday + smonth * 30 + syear * 360)) / 360;
198-    }
199-  }
200-};
201-
202 var Formulas = {
203   exists: function(fn: string) {
204-    return ((fn in CustomFormulas) || SUPPORTED_FORMULAS.indexOf(fn) > -1 || (fn in RawFormulas));
205+    return (SUPPORTED_FORMULAS.indexOf(fn) > -1 || (fn in RawFormulas) || (fn in RawFormulas.__COMPLEX));
206   },
207   get: function(fn: string) {
208     if (fn in RawFormulas) {
209       return RawFormulas[fn];
210     }
211-    if (fn in CustomFormulas) {
212-      return CustomFormulas[fn];
213+    if (fn in RawFormulas.__COMPLEX) {
214+      return RawFormulas.__COMPLEX[fn];
215     }
216     return Formula[fn];
217   }
218 };
219 
220 export {
221-  Formulas,
222-  CustomFormulas
223+  Formulas
224 }
225\ No newline at end of file