mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 17:58:12 +00:00
Spreadsheet: Let the cells know their own position in the sheet
This commit is contained in:
parent
13ce24de13
commit
f159d161fa
7 changed files with 227 additions and 22 deletions
|
@ -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.",
|
||||
},
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue