123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- 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 (end.column.length > 1 || start.column.length > 1)
- throw new TypeError("Only single-letter column names are allowed (TODO)");
- const cells = [];
- for (
- let col = Math.min(start.column.charCodeAt(0), end.column.charCodeAt(0));
- col <= Math.max(start.column.charCodeAt(0), end.column.charCodeAt(0));
- col += columnStep
- ) {
- for (
- let row = Math.min(start.row, end.row);
- row <= Math.max(start.row, end.row);
- row += rowStep
- ) {
- cells.push(String.fromCharCode(col) + row);
- }
- }
- return cells;
- }
- // FIXME: Remove this and use String.split() eventually
- function split(str, sep) {
- const parts = [];
- let splitIndex = -1;
- for (;;) {
- splitIndex = str.indexOf(sep);
- if (splitIndex == -1) {
- if (str.length) parts.push(str);
- return parts;
- }
- parts.push(str.substring(0, splitIndex));
- str = str.slice(splitIndex + sep.length);
- }
- }
- function R(fmt, ...args) {
- if (args.length !== 0) throw new TypeError("R`` format must be literal");
- fmt = fmt[0];
- return range(...split(fmt, ":"));
- }
- function select(criteria, t, f) {
- if (criteria) return t;
- return f;
- }
- function sumIf(condition, cells) {
- let sum = null;
- for (let name of cells) {
- let cell = thisSheet[name];
- if (condition(cell)) sum = sum === null ? cell : sum + cell;
- }
- return sum;
- }
- function countIf(condition, cells) {
- let count = 0;
- for (let name of cells) {
- let cell = thisSheet[name];
- if (condition(cell)) count++;
- }
- return count;
- }
- function now() {
- return new Date();
- }
- function repeat(count, str) {
- return Array(count + 1).join(str);
- }
- function randRange(min, max) {
- return Math.random() * (max - min) + min;
- }
- function integer(value) {
- return value | 0;
- }
- function sheet(name) {
- return workbook.sheet(name);
- }
- // Cheat the system and add documentation
- range.__documentation = JSON.stringify({
- name: "range",
- argc: 2,
- argnames: ["start", "end", "column step", "row step"],
- doc:
- "Generates a list of cell names in a rectangle defined by two " +
- "_top left_ and _bottom right_ cells `start` and `end`, spaced" +
- " `column step` columns, and `row step` rows apart.",
- examples: {
- 'range("A1", "C4")': "Generate a range A1:C4",
- 'range("A1", "C4", 2)': "Generate a range A1:C4, skipping every other column",
- },
- });
- select.__documentation = JSON.stringify({
- name: "select",
- argc: 3,
- argnames: ["criteria", "true value", "false value"],
- doc: "Selects between the two `true` and `false` values based on the value of `criteria`",
- examples: {
- "select(A1, A2, A3)": "Evaluates to A2 if A1 is true, A3 otherwise",
- },
- });
- sumIf.__documentation = JSON.stringify({
- name: "sumIf",
- argc: 2,
- argnames: ["condition", "cell names"],
- doc:
- "Calculates the sum of cells the value of which evaluates to true when passed to `condition`",
- examples: {
- 'sumIf(x => x instanceof Number, range("A1", "C4"))':
- "Calculates the sum of all numbers within A1:C4",
- },
- });
- countIf.__documentation = JSON.stringify({
- name: "countIf",
- argc: 2,
- argnames: ["condition", "cell names"],
- doc: "Counts cells the value of which evaluates to true when passed to `condition`",
- examples: {
- 'countIf(x => x instanceof Number, range("A1", "C4"))':
- "Counts the number of cells which have numbers within A1:C4",
- },
- });
- now.__documentation = JSON.stringify({
- name: "now",
- argc: 0,
- argnames: [],
- doc: "Returns a Date instance for the current moment",
- examples: {},
- });
- repeat.__documentation = JSON.stringify({
- name: "repeat",
- argc: 2,
- argnames: ["string", "count"],
- doc: "Returns a string equivalent to `string` repeated `count` times",
- examples: {
- 'repeat("a", 10)': 'Generates the string "aaaaaaaaaa"',
- },
- });
- randRange.__documentation = JSON.stringify({
- name: "randRange",
- argc: 2,
- argnames: ["start", "end"],
- doc: "Returns a random number in the range (`start`, `end`)",
- examples: {},
- });
- integer.__documentation = JSON.stringify({
- name: "integer",
- argc: 1,
- argnames: ["value"],
- doc: "Returns the integer value of `value`",
- examples: {
- "A1 = integer(A0)": "Sets the value of the cell A1 to the integer value of the cell A0",
- },
- });
- sheet.__documentation = JSON.stringify({
- name: "sheet",
- argc: 1,
- argnames: ["name or index"],
- doc: "Returns a reference to another sheet, identified by _name_ or _index_",
- examples: {
- "sheet('Sheet 1').A4": "Read the value of the cell A4 in a sheet named 'Sheet 1'",
- "sheet(0).A0 = 123": "Set the value of the cell A0 in the first sheet to 123",
- },
- });
|