spreadsheet
typeScript/javascript spreadsheet parser, with formulas.
git clone https://git.vogt.world/spreadsheet.git
Log | Files | README.md
← Commit log
commit
message
Added documentation for Sheet.ts
author
Ben Vogt <[email protected]>
date
2017-01-01 21:29:39
stats
2 file(s) changed, 104 insertions(+), 27 deletions(-)
files
README.md
src/Sheet.ts
  1diff --git a/README.md b/README.md
  2index db16d81..5ecc9a2 100644
  3--- a/README.md
  4+++ b/README.md
  5@@ -3,7 +3,3 @@ TypeScript implementation of a spreadsheet.
  6 
  7 ## TODO
  8 Things I should do.
  9-
 10-### Write documentation for Sheet
 11-
 12-### Write documentation for Matrix
 13diff --git a/src/Sheet.ts b/src/Sheet.ts
 14index 8827971..b0630bf 100644
 15--- a/src/Sheet.ts
 16+++ b/src/Sheet.ts
 17@@ -5,6 +5,10 @@ import { Cell } from "./Cell"
 18 import { Errors } from "./Errors"
 19 import * as Formula from "formulajs"
 20 
 21+/**
 22+ * Model representing a spreadsheet. When values/cells are added, dependencies recalculated, and true-values of those
 23+ * cells will be updated.
 24+ */
 25 var Sheet = (function () {
 26   var instance = this;
 27 
 28@@ -14,6 +18,14 @@ var Sheet = (function () {
 29     parse: function (formula: string) {}
 30   };
 31 
 32+  /**
 33+   * Creates a new FormulaParser, which parses formulas, and does minimal error handling.
 34+   *
 35+   * @param handler should be this instance. Needs access to helper.fixedCellValue, helper.cellValue,
 36+   * helper.cellRangeValue, and helper.fixedCellRangeValue
 37+   * @returns formula parser instance for use with parser.js
 38+   * @constructor
 39+   */
 40   var FormulaParser = function(handler) {
 41     var formulaLexer = function () {};
 42     formulaLexer.prototype = Parser.lexer;
 43@@ -42,14 +54,32 @@ var Sheet = (function () {
 44     return newParser;
 45   };
 46 
 47+  /**
 48+   * Holds cell values, and allows for the updating and manipulation of those cells.
 49+   */
 50   class Matrix {
 51+    /**
 52+     * Holds cells inside an object for quick access.
 53+     */
 54     public data: Object;
 55     constructor() {
 56       this.data = {};
 57     }
 58-    getCell(key: string) {
 59+
 60+    /**
 61+     * Gets the cell corresponding to the key. If the value is not defined, will return undefined.
 62+     * @param key to look up cell
 63+     * @returns {Cell} to return, if it exists. Returns undefined if key not in matrix.
 64+     */
 65+    getCell(key: string) : Cell {
 66       return this.data[key];
 67     }
 68+
 69+    /**
 70+     * Add cell to matrix. If it exists, update the necessary values. If it doesn't exist add it.
 71+     * @param cell to add to matrix.
 72+     * @returns {Cell} Returns the cell after it has been added.
 73+     */
 74     addCell(cell: Cell) {
 75       var cellId = cell.getId();
 76 
 77@@ -63,6 +93,12 @@ var Sheet = (function () {
 78 
 79       return this.getCell(cellId);
 80     }
 81+
 82+    /**
 83+     * Get all dependencies for a specific cell.
 84+     * @param id of cell
 85+     * @returns {Array} of A1-format cell ID dependencies, in no particular oder.
 86+     */
 87     getDependencies(id: string) {
 88       var getDependencies = function (id: string) {
 89         var filtered = [];
 90@@ -94,7 +130,7 @@ var Sheet = (function () {
 91               allDependencies.push(refId);
 92 
 93               var cell = this.getCell(refId);
 94-              if (cell.dependencies.length) {
 95+              if (cell.getDependencies().length) {
 96                 getTotalDependencies(refId);
 97               }
 98             }
 99@@ -104,11 +140,14 @@ var Sheet = (function () {
100       getTotalDependencies(id);
101       return allDependencies;
102     }
103-    getCellDependencies(cell: Cell) {
104-      return this.getDependencies(cell.getId());
105-    }
106-    setCell(cellKeyString: string, formula: string) {
107-      var cell = new Cell(cellKeyString);
108+
109+    /**
110+     * Set a cell in this matrix. Could update an existing cell, or add a new one.
111+     * @param id to of cell to create of update
112+     * @param formula of cell to create or update
113+     */
114+    setCell(id: string, formula: string) {
115+      var cell = new Cell(id);
116       if (formula.charAt(0) === "=") {
117         cell.setFormula(formula.substr(1));
118       } else {
119@@ -119,18 +158,26 @@ var Sheet = (function () {
120     }
121   }
122 
123-
124+  /**
125+   * Recalculate a cell's dependencies. Involves recalculating cell formulas for ALL dependencies.
126+   * @param cell to recalculate dependencies
127+   */
128   var recalculateCellDependencies = function (cell: Cell) {
129-    var allDependencies = instance.matrix.getCellDependencies(cell);
130+    var allDependencies = instance.matrix.getDependencies(cell.getId());
131 
132     allDependencies.forEach(function (refId) {
133       var currentCell = instance.matrix.getCell(refId);
134-      if (currentCell && currentCell.formula) {
135+      if (currentCell && currentCell.getFormula()) {
136         calculateCellFormula(currentCell);
137       }
138     });
139   };
140 
141+  /**
142+   * Calculate a cell's formula by parsing it, and updating it's value and error fields.
143+   * @param cell to calculate
144+   * @returns {{error: null, result: null}} parsed result
145+   */
146   var calculateCellFormula = function (cell: Cell) {
147     // to avoid double translate formulas, update cell data in parser
148     var parsed = parse(cell.getFormula(), cell.getId());
149@@ -141,6 +188,10 @@ var Sheet = (function () {
150     return parsed;
151   };
152 
153+  /**
154+   * Register a cell in the matrix, and calculate its formula if it has one.
155+   * @param cell to register
156+   */
157   var registerCellInMatrix = function (cell: Cell) {
158     instance.matrix.addCell(cell);
159     if (cell.getFormula() !== null) {
160@@ -427,19 +478,19 @@ var Sheet = (function () {
161         cell = instance.matrix.getCell(cellId);
162 
163       // get value
164-      value = cell ? cell.value : "0"; // TODO: fix this, it's sloppy.
165+      value = cell ? cell.getValue() : "0"; // TODO: fix this, it's sloppy.
166       //update dependencies
167       instance.matrix.getCell(origin).updateDependencies([cellId]);
168       // check references error
169-      if (cell && cell.dependencies) {
170-        if (cell.dependencies.indexOf(cellId) !== -1) {
171+      if (cell && cell.getDependencies()) {
172+        if (cell.getDependencies().indexOf(cellId) !== -1) {
173           throw Error('REF');
174         }
175       }
176 
177       // check if any error occurs
178-      if (cell && cell.error) {
179-        throw Error(cell.error);
180+      if (cell && cell.getError()) {
181+        throw Error(cell.getError());
182       }
183 
184       // return value if is set
185@@ -481,16 +532,22 @@ var Sheet = (function () {
186     }
187   };
188 
189-  var parse = function (formula, key) {
190+  /**
191+   * Parse a formula for a particular cell. Involves calculating all dependencies and potentially updating them as well.
192+   * @param formula to parse
193+   * @param cellId necessary for dependency access
194+   * @returns {{error: null, result: null}} a parsed value including an error, and potential resulting value
195+   */
196+  var parse = function (formula, cellId) {
197     var result = null;
198     var error = null;
199 
200     try {
201-      parser.setObj(key);
202+      parser.setObj(cellId);
203       result = parser.parse(formula);
204-      var deps = instance.matrix.getDependencies(key);
205+      var deps = instance.matrix.getDependencies(cellId);
206 
207-      if (deps.indexOf(key) !== -1) {
208+      if (deps.indexOf(cellId) !== -1) {
209         result = null;
210         deps.forEach(function (id) {
211           instance.matrix.getCell(id).setError(Errors.get('REF'));
212@@ -513,18 +570,32 @@ var Sheet = (function () {
213     }
214   };
215 
216-  var setCell = function (cellKeyString: string, value: string) {
217-    instance.matrix.setCell(cellKeyString, value.toString());
218+  /**
219+   * Set a cell value by A1-format cell ID
220+   * @param id of cel to set
221+   * @param value raw input to update the cell with
222+   */
223+  var setCell = function (id: string, value: string) {
224+    instance.matrix.setCell(id, value.toString());
225   };
226 
227-  var getCell = function (cellKeyString: string) : Cell {
228-    var cell = instance.matrix.getCell(cellKeyString);
229+  /**
230+   * Get a cell by A1-format cell ID, if it exists in the Sheet. If not return null.
231+   * @param id to lookup the cell
232+   * @returns {Cell} cell found, or null.
233+   */
234+  var getCell = function (id: string) : Cell {
235+    var cell = instance.matrix.getCell(id);
236     if (cell === undefined) {
237       return null;
238     }
239     return cell;
240   };
241 
242+  /**
243+   * Load a matrix into this sheet. Matrix values can be of any type, as long as they have a toString()
244+   * @param input matrix
245+   */
246   this.load = function (input: Array<Array<any>>) {
247     for (var y = 0; y < input.length; y++) {
248       for (var x = 0; x < input[0].length; x++) {
249@@ -535,6 +606,10 @@ var Sheet = (function () {
250     }
251   };
252 
253+  /**
254+   * Render this Sheet as a string in which each row is a cell.
255+   * @returns {string}
256+   */
257   this.toString = function () {
258     var toReturn = "";
259     for (var key in this.matrix.data) {