spreadsheet
typeScript/javascript spreadsheet parser, with formulas.
git clone https://git.vogt.world/spreadsheet.git
Log | Files | README.md
← Commit log
commit
message
I could be wrong, but I think I'm getting close!
author
Ben Vogt <[email protected]>
date
2016-12-27 03:24:21
stats
2 file(s) changed, 145 insertions(+), 139 deletions(-)
files
ts/sheet.js
ts/sheet.ts
  1diff --git a/ts/sheet.js b/ts/sheet.js
  2index 961152f..621e0fa 100644
  3--- a/ts/sheet.js
  4+++ b/ts/sheet.js
  5@@ -35,11 +35,34 @@ function numberToLetters(num) {
  6     var mod = num % 26, pow = num / 26 | 0, out = mod ? String.fromCharCode(64 + mod) : (--pow, 'Z');
  7     return pow ? numberToLetters(pow) + out : out;
  8 }
  9+var Cell = (function () {
 10+    function Cell(formula, id) {
 11+        this.formula = formula;
 12+        this.value = "";
 13+        this.dependencies = [];
 14+        this.error = null;
 15+        this.id = id;
 16+    }
 17+    Cell.prototype.updateDependencies = function (dependencies) {
 18+        for (var index in dependencies) {
 19+            if (this.dependencies.indexOf(dependencies[index]) === -1) {
 20+                this.dependencies.push(dependencies[index]);
 21+            }
 22+        }
 23+    };
 24+    Cell.prototype.setValue = function (value) {
 25+        this.value = value;
 26+    };
 27+    Cell.prototype.setError = function (error) {
 28+        this.error = error;
 29+    };
 30+    return Cell;
 31+}());
 32 var mine = (function () {
 33     'use strict';
 34     var instance = this;
 35     var parser = {
 36-        setObj: function (thing) {
 37+        setObj: function (obj) {
 38         },
 39         parse: function (thing) {
 40         }
 41@@ -99,51 +122,24 @@ var mine = (function () {
 42                 return item.id === key.toString();
 43             })[0];
 44         };
 45-        this.updateItem = function (cell, props) {
 46-            if (instance.utils.isString(cell)) {
 47-                cell = instance.matrix.getItem(new A1CellKey(cell));
 48-            }
 49-            if (cell && props) {
 50-                for (var p in props) {
 51-                    if (cell[p] && instance.utils.isArray(cell[p])) {
 52-                        if (instance.utils.isArray(props[p])) {
 53-                            props[p].forEach(function (i) {
 54-                                if (cell[p].indexOf(i) === -1) {
 55-                                    cell[p].push(i);
 56-                                }
 57-                            });
 58-                        }
 59-                        else {
 60-                            if (cell[p].indexOf(props[p]) === -1) {
 61-                                cell[p].push(props[p]);
 62-                            }
 63-                        }
 64-                    }
 65-                    else {
 66-                        cell[p] = props[p];
 67-                    }
 68-                }
 69-            }
 70-        };
 71-        this.addItem = function (item) {
 72-            var cellId = item.id, coords = instance.utils.cellCoords(cellId);
 73-            item.row = coords.row;
 74-            item.col = coords.col;
 75-            var cellExist = instance.matrix.data.filter(function (cell) {
 76+        this.addItem = function (cell) {
 77+            var cellId = cell.id, coords = instance.utils.cellCoords(cellId);
 78+            cell.row = coords.row;
 79+            cell.col = coords.col;
 80+            var existingCell = instance.matrix.data.filter(function (cell) {
 81                 return cell.id === cellId;
 82             })[0];
 83-            if (!cellExist) {
 84-                instance.matrix.data.push(item);
 85+            if (!existingCell) {
 86+                instance.matrix.data.push(cell);
 87             }
 88             else {
 89-                instance.matrix.updateItem(cellExist, item);
 90+                // instance.matrix.updateItem(cellExist, item);
 91+                instance.matrix.getItem(cellId).updateDependencies(cell.dependencies);
 92+                instance.matrix.getItem(cellId).setValue(cell.value);
 93+                instance.matrix.getItem(cellId).setError(cell.error);
 94             }
 95             return instance.matrix.getItem(new A1CellKey(cellId));
 96         };
 97-        this.updateCellItem = function (key, props) {
 98-            var item = instance.matrix.getItem(key);
 99-            instance.matrix.updateItem(item, props);
100-        };
101         this.getDependencies = function (id) {
102             var getDependencies = function (id) {
103                 var filtered = instance.matrix.data.filter(function (cell) {
104@@ -185,19 +181,22 @@ var mine = (function () {
105             allDependencies.forEach(function (refId) {
106                 var currentCell = instance.matrix.getItem(new A1CellKey(refId));
107                 if (currentCell && currentCell.formula) {
108-                    calculateCellFormula(currentCell.formula, currentCell.id);
109+                    calculateCellFormula(currentCell);
110                 }
111             });
112         };
113-        var calculateCellFormula = function (formula, id) {
114+        var calculateCellFormula = function (cell) {
115             // to avoid double translate formulas, update item data in parser
116-            var parsed = parse(formula, id), value = parsed.result, error = parsed.error;
117-            instance.matrix.updateCellItem(new A1CellKey(id), { value: value, error: error });
118+            var parsed = parse(cell.formula, cell.id);
119+            var key = new A1CellKey(cell.id);
120+            // instance.matrix.updateCellItem(key, {value: value, error: error});
121+            instance.matrix.getItem(key).setValue(parsed.result);
122+            instance.matrix.getItem(key).setError(parsed.error);
123             return parsed;
124         };
125         var registerCellInMatrix = function (cell) {
126             instance.matrix.addItem(cell);
127-            calculateCellFormula(cell.formula, cell.id);
128+            calculateCellFormula(cell);
129         };
130         this.scan = function () {
131             var input = [
132@@ -215,8 +214,9 @@ var mine = (function () {
133                         id: id,
134                         formula: input[y][x].toString()
135                     };
136-                    registerCellInMatrix(cell);
137-                    recalculateCellDependencies(cell);
138+                    var trueCell = new Cell(input[y][x].toString(), id);
139+                    registerCellInMatrix(trueCell);
140+                    recalculateCellDependencies(trueCell);
141                 }
142             }
143             console.log(this.data);
144@@ -477,7 +477,8 @@ var mine = (function () {
145             // get value
146             value = item ? item.value : "0"; // TODO: fix this, it's sloppy.
147             //update dependencies
148-            instance.matrix.updateCellItem(new A1CellKey(origin), { deps: [cell] });
149+            // instance.matrix.updateCellItem(new A1CellKey(origin), {deps: [cell]});
150+            instance.matrix.getItem(new A1CellKey(origin)).updateDependencies([cell]);
151             // check references error
152             if (item && item.deps) {
153                 if (item.deps.indexOf(cell) !== -1) {
154@@ -501,7 +502,8 @@ var mine = (function () {
155             // iterate cells to get values and indexes
156             var cells = instance.utils.iterateCells.call(this, coordsStart, coordsEnd), result = [];
157             //update dependencies
158-            instance.matrix.updateCellItem(new A1CellKey(origin), { deps: cells.index });
159+            // instance.matrix.updateCellItem(new A1CellKey(origin), {deps: cells.index});
160+            instance.matrix.getItem(new A1CellKey(origin)).updateDependencies([cells.index]);
161             result.push(cells.value);
162             return result;
163         },
164@@ -516,16 +518,18 @@ var mine = (function () {
165         }
166     };
167     var parse = function (formula, key) {
168-        var result = null, error = null;
169+        var result = null;
170+        var error = null;
171         try {
172             parser.setObj(key);
173             result = parser.parse(formula);
174-            var id = key;
175-            var deps = instance.matrix.getDependencies(id);
176-            if (deps.indexOf(id) !== -1) {
177+            var deps = instance.matrix.getDependencies(key);
178+            if (deps.indexOf(key) !== -1) {
179                 result = null;
180                 deps.forEach(function (id) {
181-                    instance.matrix.updateItem(id, { value: null, error: Exception.get('REF') });
182+                    // instance.matrix.updateItem(id, {value: null, error: Exception.get('REF')});
183+                    instance.matrix.getItem(new A1CellKey(id)).setError(Exception.get('REF'));
184+                    instance.matrix.getItem(new A1CellKey(id)).setValue(null);
185                 });
186                 throw Error('REF');
187             }
188diff --git a/ts/sheet.ts b/ts/sheet.ts
189index 9bd51cf..ea73c1a 100644
190--- a/ts/sheet.ts
191+++ b/ts/sheet.ts
192@@ -65,6 +65,38 @@ function numberToLetters(num: number): string {
193 
194 
195 
196+class Cell {
197+  public formula: string;
198+  public value: string;
199+  public dependencies: Array<string>;
200+  public error: any;
201+  public id: string;
202+  public row: number;
203+  public col: number;
204+  constructor(formula: string, id: string) {
205+    this.formula = formula;
206+    this.value = "";
207+    this.dependencies = [];
208+    this.error = null;
209+    this.id = id;
210+  }
211+  updateDependencies(dependencies: Array<string>) {
212+    for (var index in dependencies) {
213+      if (this.dependencies.indexOf(dependencies[index]) === -1) {
214+        this.dependencies.push(dependencies[index]);
215+      }
216+    }
217+  }
218+  setValue(value: string) {
219+    this.value = value;
220+  }
221+  setError(error: any) {
222+    this.error = error;
223+  }
224+}
225+
226+
227+
228 
229 
230 
231@@ -76,7 +108,7 @@ var mine = (function () {
232   var instance = this;
233 
234   var parser = {
235-    setObj: function (thing: any) {
236+    setObj: function (obj: string) {
237 
238     },
239     parse: function (thing: any) {
240@@ -95,7 +127,7 @@ var mine = (function () {
241 
242     formulaParser.prototype = Parser;
243     var newParser = new formulaParser;
244-    newParser.setObj = function(obj) {
245+    newParser.setObj = function(obj: string) {
246       newParser.yy.obj = obj;
247     };
248 
249@@ -151,60 +183,29 @@ var mine = (function () {
250       })[0];
251     };
252 
253-    this.updateItem = function (cell, props) {
254-      if (instance.utils.isString(cell)) {
255-        cell = instance.matrix.getItem(new A1CellKey(cell));
256-      }
257-
258-      if (cell && props) {
259-        for (var p in props) {
260-          if (cell[p] && instance.utils.isArray(cell[p])) {
261-            if (instance.utils.isArray(props[p])) {
262-              props[p].forEach(function (i) {
263-                if (cell[p].indexOf(i) === -1) {
264-                  cell[p].push(i);
265-                }
266-              });
267-            } else {
268-
269-              if (cell[p].indexOf(props[p]) === -1) {
270-                cell[p].push(props[p]);
271-              }
272-            }
273-          } else {
274-            cell[p] = props[p];
275-          }
276-        }
277-      }
278-    };
279-
280-    this.addItem = function (item) {
281-      var cellId = item.id,
282+    this.addItem = function (cell: Cell) {
283+      var cellId = cell.id,
284         coords = instance.utils.cellCoords(cellId);
285 
286-      item.row = coords.row;
287-      item.col = coords.col;
288+      cell.row = coords.row;
289+      cell.col = coords.col;
290 
291-      var cellExist = instance.matrix.data.filter(function (cell) {
292+      var existingCell = instance.matrix.data.filter(function (cell) {
293         return cell.id === cellId;
294       })[0];
295 
296-      if (!cellExist) {
297-        instance.matrix.data.push(item);
298+      if (!existingCell) {
299+        instance.matrix.data.push(cell);
300       } else {
301-        instance.matrix.updateItem(cellExist, item);
302+        // instance.matrix.updateItem(cellExist, item);
303+        instance.matrix.getItem(cellId).updateDependencies(cell.dependencies);
304+        instance.matrix.getItem(cellId).setValue(cell.value);
305+        instance.matrix.getItem(cellId).setError(cell.error);
306       }
307 
308       return instance.matrix.getItem(new A1CellKey(cellId));
309     };
310 
311-
312-    this.updateCellItem = function (key: A1CellKey, props) {
313-      var item = instance.matrix.getItem(key);
314-
315-      instance.matrix.updateItem(item, props);
316-    };
317-
318     this.getDependencies = function (id: string) {
319       var getDependencies = function (id: string) {
320         var filtered = instance.matrix.data.filter(function (cell) {
321@@ -247,35 +248,36 @@ var mine = (function () {
322       return allDependencies;
323     };
324 
325-    this.getCellDependencies = function (cell) {
326+    this.getCellDependencies = function (cell: Cell) {
327       return instance.matrix.getDependencies(cell.id);
328     };
329 
330-    var recalculateCellDependencies = function (cell) {
331+    var recalculateCellDependencies = function (cell: Cell) {
332       var allDependencies = instance.matrix.getCellDependencies(cell);
333 
334       allDependencies.forEach(function (refId) {
335         var currentCell = instance.matrix.getItem(new A1CellKey(refId));
336         if (currentCell && currentCell.formula) {
337-          calculateCellFormula(currentCell.formula, currentCell.id);
338+          calculateCellFormula(currentCell);
339         }
340       });
341     };
342 
343-    var calculateCellFormula = function (formula: string, id: string) {
344+    var calculateCellFormula = function (cell: Cell) {
345       // to avoid double translate formulas, update item data in parser
346-      var parsed = parse(formula, id),
347-        value = parsed.result,
348-        error = parsed.error;
349+      var parsed = parse(cell.formula, cell.id);
350+      var key =  new A1CellKey(cell.id);
351 
352-      instance.matrix.updateCellItem(new A1CellKey(id), {value: value, error: error});
353+      // instance.matrix.updateCellItem(key, {value: value, error: error});
354+      instance.matrix.getItem(key).setValue(parsed.result);
355+      instance.matrix.getItem(key).setError(parsed.error);
356 
357       return parsed;
358     };
359 
360-    var registerCellInMatrix = function (cell) {
361+    var registerCellInMatrix = function (cell: Cell) {
362       instance.matrix.addItem(cell);
363-      calculateCellFormula(cell.formula, cell.id);
364+      calculateCellFormula(cell);
365     };
366 
367     this.scan = function () {
368@@ -294,8 +296,9 @@ var mine = (function () {
369             id: id,
370             formula: input[y][x].toString()
371           };
372-          registerCellInMatrix(cell);
373-          recalculateCellDependencies(cell);
374+          var trueCell = new Cell(input[y][x].toString(), id);
375+          registerCellInMatrix(trueCell);
376+          recalculateCellDependencies(trueCell);
377         }
378       }
379       console.log(this.data);
380@@ -616,7 +619,8 @@ var mine = (function () {
381       // get value
382       value = item ? item.value : "0"; // TODO: fix this, it's sloppy.
383       //update dependencies
384-      instance.matrix.updateCellItem(new A1CellKey(origin), {deps: [cell]});
385+      // instance.matrix.updateCellItem(new A1CellKey(origin), {deps: [cell]});
386+      instance.matrix.getItem(new A1CellKey(origin)).updateDependencies([cell]);
387       // check references error
388       if (item && item.deps) {
389         if (item.deps.indexOf(cell) !== -1) {
390@@ -649,7 +653,8 @@ var mine = (function () {
391       var cells = instance.utils.iterateCells.call(this, coordsStart, coordsEnd),
392         result = [];
393       //update dependencies
394-      instance.matrix.updateCellItem(new A1CellKey(origin), {deps: cells.index});
395+      // instance.matrix.updateCellItem(new A1CellKey(origin), {deps: cells.index});
396+      instance.matrix.getItem(new A1CellKey(origin)).updateDependencies([cells.index]);
397 
398       result.push(cells.value);
399       return result;
400@@ -669,33 +674,25 @@ var mine = (function () {
401   };
402 
403   var parse = function (formula, key) {
404-    var result = null,
405-      error = null;
406+    var result = null;
407+    var error = null;
408 
409     try {
410-
411       parser.setObj(key);
412       result = parser.parse(formula);
413+      var deps = instance.matrix.getDependencies(key);
414 
415-      var id = key;
416-
417-
418-      var deps = instance.matrix.getDependencies(id);
419-
420-      if (deps.indexOf(id) !== -1) {
421+      if (deps.indexOf(key) !== -1) {
422         result = null;
423-
424         deps.forEach(function (id) {
425-          instance.matrix.updateItem(id, {value: null, error: Exception.get('REF')});
426+          // instance.matrix.updateItem(id, {value: null, error: Exception.get('REF')});
427+          instance.matrix.getItem(new A1CellKey(id)).setError(Exception.get('REF'));
428+          instance.matrix.getItem(new A1CellKey(id)).setValue(null);
429         });
430-
431         throw Error('REF');
432       }
433-
434     } catch (ex) {
435-
436       var message = Exception.get(ex.message);
437-
438       if (message) {
439         error = message;
440       } else {