diff options
author | AnotherTest <ali.mpfard@gmail.com> | 2020-09-26 15:29:11 +0330 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-09-28 17:41:48 +0200 |
commit | f159d161fa6c15aa16cdac6967a2b165d0f9fef0 (patch) | |
tree | ae967b4d7bcf1c742c56083c7f03b82bde53f117 /Base/res/js/Spreadsheet/runtime.js | |
parent | 13ce24de135805c250ca64e32b8f911004073a69 (diff) | |
download | serenity-f159d161fa6c15aa16cdac6967a2b165d0f9fef0.zip |
Spreadsheet: Let the cells know their own position in the sheet
Diffstat (limited to 'Base/res/js/Spreadsheet/runtime.js')
-rw-r--r-- | Base/res/js/Spreadsheet/runtime.js | 132 |
1 files changed, 130 insertions, 2 deletions
diff --git a/Base/res/js/Spreadsheet/runtime.js b/Base/res/js/Spreadsheet/runtime.js index df74a37d1c..67e66307e0 100644 --- a/Base/res/js/Spreadsheet/runtime.js +++ b/Base/res/js/Spreadsheet/runtime.js @@ -1,8 +1,82 @@ +// FIXME: Figure out a way to document non-function entities too. +class Position { + constructor(column, row, sheet) { + this.column = column; + this.row = row; + this.sheet = sheet ?? thisSheet; + this.name = `${column}${row}`; + } + + static from_name(name) { + let sheet = thisSheet; + let obj = sheet.parse_cell_name(name); + return new Position(obj.column, obj.row, sheet); + } + + up(how_many) { + how_many = how_many ?? 1; + const row = Math.max(0, this.row - how_many); + return new Position(this.column, row, this.sheet); + } + + down(how_many) { + how_many = how_many ?? 1; + const row = Math.max(0, this.row + how_many); + return new Position(this.column, row, this.sheet); + } + + left(how_many) { + how_many = how_many ?? 1; + const column = Math.min( + "Z".charCodeAt(0), + Math.max("A".charCodeAt(0), this.column.charCodeAt(0) - how_many) + ); + return new Position(String.fromCharCode(column), this.row, this.sheet); + } + + right(how_many) { + how_many = how_many ?? 1; + const column = Math.min( + "Z".charCodeAt(0), + Math.max("A".charCodeAt(0), this.column.charCodeAt(0) + how_many) + ); + return new Position(String.fromCharCode(column), this.row, this.sheet); + } + + with_column(value) { + return new Position(value, this.row, this.sheet); + } + + with_row(value) { + return new Position(this.column, value, this.sheet); + } + + in_sheet(the_sheet) { + return new Position(this.column, this.row, sheet(the_sheet)); + } + + value() { + return this.sheet[this.name]; + } + + valueOf() { + return value(); + } + + toString() { + return `<Cell at ${this.name}>`; + } +} + function range(start, end, columnStep, rowStep) { columnStep = integer(columnStep ?? 1); rowStep = integer(rowStep ?? 1); - start = parse_cell_name(start) ?? { column: "A", row: 0 }; - end = parse_cell_name(end) ?? start; + if (!(start instanceof Position)) { + start = parse_cell_name(start) ?? { column: "A", row: 0 }; + } + if (!(end instanceof Position)) { + end = parse_cell_name(end) ?? start; + } if (end.column.length > 1 || start.column.length > 1) throw new TypeError("Only single-letter column names are allowed (TODO)"); @@ -172,6 +246,21 @@ function stddev(cells) { return Math.sqrt(variance(cells)); } +// Lookup + +function row() { + return thisSheet.current_cell_position().row; +} + +function column() { + return thisSheet.current_cell_position().column; +} + +function here() { + const position = current_cell_position(); + return new Position(position.column, position.row, thisSheet); +} + // Cheat the system and add documentation range.__documentation = JSON.stringify({ name: "range", @@ -382,3 +471,42 @@ stddev.__documentation = JSON.stringify({ 'stddev(range("A0", "C4"))': "Calculate the standard deviation of the values in A0:C4", }, }); + +row.__documentation = JSON.stringify({ + name: "row", + argc: 0, + argnames: [], + doc: "Returns the row number of the current cell", + examples: {}, +}); + +column.__documentation = JSON.stringify({ + name: "column", + argc: 0, + argnames: [], + doc: "Returns the column name of the current cell", + examples: {}, +}); + +here.__documentation = JSON.stringify({ + name: "here", + argc: 0, + argnames: [], + doc: + "Returns an object representing the current cell's position, see `Position` below.\n\n" + + "## Position\na `Position` is an object representing a given cell position in a given sheet.\n" + + "### Methods:\n- `up(count = 1)`: goes up count cells, or returns the top position if at the top\n" + + "- `down(count = 1)`: goes down count cells\n" + + "- `left(count = 1)`: Goes left count cells, or returns the leftmost position if the edge\n" + + "- `right(count = 1)`: Goes right count cells.\n" + + "- `with_row(row)`: Returns a Position with its column being this object's, and its row being the provided the value.\n" + + "- `with_column(column)`: Similar to `with_row()`, but changes the column instead.\n" + + "- `in_sheet(the_sheet)`: Returns a Position with the same column and row as this one, but with its sheet being `the_sheet`.\n" + + "- `value()`: Returns the value at the position which it represents, in the object's sheet (current sheet by default).\n\n" + + "**NOTE**: Currently only supports single-letter column names", + examples: { + "here().up().value()": "Get the value of the cell above this one", + "here().up().with_column('A')": + "Get a Position above this one in column A, for instance, evaluates to A2 if run in B3.", + }, +}); |