summaryrefslogtreecommitdiff
path: root/Base/res/js/Spreadsheet/runtime.js
diff options
context:
space:
mode:
authorAnotherTest <ali.mpfard@gmail.com>2020-09-26 15:29:11 +0330
committerAndreas Kling <kling@serenityos.org>2020-09-28 17:41:48 +0200
commitf159d161fa6c15aa16cdac6967a2b165d0f9fef0 (patch)
treeae967b4d7bcf1c742c56083c7f03b82bde53f117 /Base/res/js/Spreadsheet/runtime.js
parent13ce24de135805c250ca64e32b8f911004073a69 (diff)
downloadserenity-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.js132
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.",
+ },
+});