@borgar/fx 2.1.1 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +139 -24
- package/References.md +39 -0
- package/dist/fx.js +1 -1
- package/lib/a1.js +152 -87
- package/lib/a1.spec.js +264 -0
- package/lib/addMeta.js +72 -13
- package/lib/{addMeta-test.js → addMeta.spec.js} +39 -6
- package/lib/constants.js +7 -89
- package/lib/fixRanges.js +41 -0
- package/lib/fixRanges.spec.js +111 -0
- package/lib/index.js +9 -6
- package/lib/isType.js +18 -0
- package/lib/lexer.js +99 -70
- package/lib/{lexer-test.js → lexer.spec.js} +445 -142
- package/lib/lexerParts.js +153 -0
- package/lib/mergeRefTokens.js +77 -0
- package/lib/mergeRefTokens.spec.js +118 -0
- package/lib/parseRef.js +44 -40
- package/lib/rc.js +154 -49
- package/lib/rc.spec.js +220 -0
- package/lib/stringifyPrefix.js +21 -0
- package/lib/{translate-toA1-test.js → translate-toA1.spec.js} +20 -2
- package/lib/{translate-toRC-test.js → translate-toRC.spec.js} +18 -1
- package/lib/translate.js +20 -32
- package/package.json +12 -10
- package/lib/a1-test.js +0 -158
- package/lib/quickVerify.js +0 -35
- package/lib/rc-test.js +0 -111
package/lib/translate.js
CHANGED
|
@@ -1,48 +1,36 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { MAX_ROWS, MAX_COLS } from './constants.js';
|
|
2
2
|
import { fromA1, toA1 } from './a1.js';
|
|
3
3
|
import { fromRC, toRC } from './rc.js';
|
|
4
4
|
import { tokenize } from './lexer.js';
|
|
5
|
+
import { isRange } from './isType.js';
|
|
6
|
+
|
|
7
|
+
const calc = (abs, vX, aX) => {
|
|
8
|
+
if (vX == null) {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
return abs ? vX : vX - aX;
|
|
12
|
+
};
|
|
5
13
|
|
|
6
14
|
export function translateToRC (fx, anchorCell) {
|
|
7
15
|
const { top, left } = fromA1(anchorCell);
|
|
8
16
|
const isString = typeof fx === 'string';
|
|
9
17
|
|
|
10
18
|
const tokens = isString
|
|
11
|
-
? tokenize(fx, { emitRanges: false, mergeRanges: false, r1c2: false })
|
|
19
|
+
? tokenize(fx, { emitRanges: false, mergeRanges: false, allowTernary: true, r1c2: false })
|
|
12
20
|
: fx;
|
|
13
21
|
|
|
14
22
|
tokens.forEach(token => {
|
|
15
|
-
if (token
|
|
16
|
-
const range = {};
|
|
17
|
-
const d = fromA1(token.value);
|
|
18
|
-
|
|
19
|
-
range.r0 = d.$top ? d.top : d.top - top;
|
|
20
|
-
range.$r0 = d.$top;
|
|
21
|
-
range.r1 = d.$bottom ? d.bottom : d.bottom - top;
|
|
22
|
-
range.$r1 = d.$bottom;
|
|
23
|
-
|
|
24
|
-
range.c0 = d.$left ? d.left : d.left - left;
|
|
25
|
-
range.$c0 = d.$left;
|
|
26
|
-
range.c1 = d.$right ? d.right : d.right - left;
|
|
27
|
-
range.$c1 = d.$right;
|
|
28
|
-
|
|
29
|
-
// console.error(token.value, d, range, [ top, left ]);
|
|
30
|
-
token.value = toRC(range);
|
|
31
|
-
}
|
|
32
|
-
else if (token.type === RANGE_BEAM) {
|
|
23
|
+
if (isRange(token)) {
|
|
33
24
|
const range = {};
|
|
34
25
|
const d = fromA1(token.value);
|
|
35
|
-
|
|
36
|
-
range.r0 = d.$top ? d.top : d.top - top;
|
|
26
|
+
range.r0 = calc(d.$top, d.top, top);
|
|
37
27
|
range.$r0 = d.$top;
|
|
38
|
-
range.r1 = d.$bottom
|
|
28
|
+
range.r1 = calc(d.$bottom, d.bottom, top);
|
|
39
29
|
range.$r1 = d.$bottom;
|
|
40
|
-
|
|
41
|
-
range.c0 = d.$left ? d.left : d.left - left;
|
|
30
|
+
range.c0 = calc(d.$left, d.left, left);
|
|
42
31
|
range.$c0 = d.$left;
|
|
43
|
-
range.c1 = d.$right
|
|
32
|
+
range.c1 = calc(d.$right, d.right, left);
|
|
44
33
|
range.$c1 = d.$right;
|
|
45
|
-
|
|
46
34
|
token.value = toRC(range);
|
|
47
35
|
}
|
|
48
36
|
});
|
|
@@ -54,11 +42,11 @@ export function translateToRC (fx, anchorCell) {
|
|
|
54
42
|
|
|
55
43
|
function toFixed (val, abs, base, max) {
|
|
56
44
|
let v = val;
|
|
57
|
-
if (!abs) {
|
|
45
|
+
if (v != null && !abs) {
|
|
58
46
|
v = base + val;
|
|
59
47
|
// Excel "wraps around" when value goes out of lower bounds.
|
|
60
|
-
// It's a bit quirky on entry as Excel
|
|
61
|
-
// references but behaviour is consistent with INDIRECT:
|
|
48
|
+
// It's a bit quirky on entry as Excel _really wants_ to re-rewite the
|
|
49
|
+
// references but the behaviour is consistent with INDIRECT:
|
|
62
50
|
// ... In A1: RC[-1] => R1C[16383].
|
|
63
51
|
if (v < 0) {
|
|
64
52
|
v = max + v + 1;
|
|
@@ -76,11 +64,11 @@ export function translateToA1 (fx, anchorCell) {
|
|
|
76
64
|
const isString = typeof fx === 'string';
|
|
77
65
|
|
|
78
66
|
const tokens = isString
|
|
79
|
-
? tokenize(fx, { emitRanges: false, mergeRanges: false, r1c1: true })
|
|
67
|
+
? tokenize(fx, { emitRanges: false, mergeRanges: false, allowTernary: true, r1c1: true })
|
|
80
68
|
: fx;
|
|
81
69
|
|
|
82
70
|
tokens.forEach(token => {
|
|
83
|
-
if (token
|
|
71
|
+
if (isRange(token)) {
|
|
84
72
|
const range = {};
|
|
85
73
|
const d = fromRC(token.value);
|
|
86
74
|
const r0 = toFixed(d.r0, d.$r0, anchor.top, MAX_ROWS);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@borgar/fx",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "Utilities for working with Excel formulas",
|
|
5
5
|
"main": "dist/fx.js",
|
|
6
6
|
"module": "lib/index.js",
|
|
@@ -11,8 +11,10 @@
|
|
|
11
11
|
}
|
|
12
12
|
},
|
|
13
13
|
"scripts": {
|
|
14
|
-
"
|
|
15
|
-
"
|
|
14
|
+
"preversion": "npm test && npm run lint",
|
|
15
|
+
"version": "npm run build",
|
|
16
|
+
"lint": "eslint lib/*.js",
|
|
17
|
+
"test": "tape lib/*.spec.js | tap-min",
|
|
16
18
|
"build": "NODE_ENV=production rollup -c"
|
|
17
19
|
},
|
|
18
20
|
"repository": {
|
|
@@ -36,16 +38,16 @@
|
|
|
36
38
|
"author": "Borgar Þorsteinsson <borgar@borgar.net> (http://borgar.net/)",
|
|
37
39
|
"license": "MIT",
|
|
38
40
|
"devDependencies": {
|
|
39
|
-
"@babel/core": "~7.
|
|
41
|
+
"@babel/core": "~7.21.0",
|
|
40
42
|
"@babel/eslint-parser": "~7.19.1",
|
|
41
|
-
"@babel/preset-env": "~7.
|
|
42
|
-
"@borgar/eslint-config": "~
|
|
43
|
-
"@rollup/plugin-babel": "~6.0.
|
|
43
|
+
"@babel/preset-env": "~7.20.2",
|
|
44
|
+
"@borgar/eslint-config": "~3.0.0",
|
|
45
|
+
"@rollup/plugin-babel": "~6.0.3",
|
|
44
46
|
"babel-eslint": "~10.1.0",
|
|
45
|
-
"eslint": "~8.
|
|
46
|
-
"rollup": "~3.2
|
|
47
|
+
"eslint": "~8.34.0",
|
|
48
|
+
"rollup": "~3.17.2",
|
|
47
49
|
"rollup-plugin-minification": "~0.2.0",
|
|
48
50
|
"tap-min": "~2.0.0",
|
|
49
|
-
"tape": "~5.6.
|
|
51
|
+
"tape": "~5.6.3"
|
|
50
52
|
}
|
|
51
53
|
}
|
package/lib/a1-test.js
DELETED
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
/* eslint-disable object-property-newline, object-curly-newline */
|
|
2
|
-
import { test, Test } from 'tape';
|
|
3
|
-
import {
|
|
4
|
-
fromCol,
|
|
5
|
-
toCol,
|
|
6
|
-
fromRow,
|
|
7
|
-
toRow,
|
|
8
|
-
toRelative,
|
|
9
|
-
toAbsolute,
|
|
10
|
-
parseA1Ref
|
|
11
|
-
} from './a1.js';
|
|
12
|
-
|
|
13
|
-
Test.prototype.isA1Equal = function isTokens (expr, result, opts) {
|
|
14
|
-
if (result) {
|
|
15
|
-
result = {
|
|
16
|
-
sheetName: '',
|
|
17
|
-
workbookName: '',
|
|
18
|
-
range: null,
|
|
19
|
-
name: '',
|
|
20
|
-
...result
|
|
21
|
-
};
|
|
22
|
-
if (result.range && typeof result.range === 'object') {
|
|
23
|
-
// mix in some defaults so we don't have to write things out in full
|
|
24
|
-
result.range = {
|
|
25
|
-
top: null, left: null, bottom: null, right: null,
|
|
26
|
-
$top: false, $left: false, $bottom: false, $right: false,
|
|
27
|
-
...result.range
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
this.deepEqual(parseA1Ref(expr, opts), result, expr);
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
// What happens when B2:A1 -> should work!
|
|
35
|
-
test('convert to and from column and row ids', t => {
|
|
36
|
-
t.is(fromCol('a'), 0);
|
|
37
|
-
t.is(fromCol('A'), 0);
|
|
38
|
-
t.is(fromCol('AA'), 26);
|
|
39
|
-
t.is(fromCol('zz'), 701);
|
|
40
|
-
t.is(fromCol('ZZZ'), 18277);
|
|
41
|
-
t.is(toCol(0), 'A');
|
|
42
|
-
t.is(toCol(26), 'AA');
|
|
43
|
-
t.is(toCol(701), 'ZZ');
|
|
44
|
-
t.is(toCol(18277), 'ZZZ');
|
|
45
|
-
t.is(fromRow('11'), 10);
|
|
46
|
-
t.is(fromRow('1'), 0);
|
|
47
|
-
t.is(toRow(12), '13');
|
|
48
|
-
t.is(toRow(77), '78');
|
|
49
|
-
t.end();
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
test('parse A1 references', t => {
|
|
53
|
-
t.isA1Equal('A1', { range: { top: 0, left: 0, bottom: 0, right: 0 } });
|
|
54
|
-
t.isA1Equal('A1:B2', { range: { top: 0, left: 0, bottom: 1, right: 1 } });
|
|
55
|
-
|
|
56
|
-
t.isA1Equal('$A1:B2', { range: { top: 0, left: 0, bottom: 1, right: 1, $left: true } });
|
|
57
|
-
t.isA1Equal('A$1:B2', { range: { top: 0, left: 0, bottom: 1, right: 1, $top: true } });
|
|
58
|
-
t.isA1Equal('A1:$B2', { range: { top: 0, left: 0, bottom: 1, right: 1, $right: true } });
|
|
59
|
-
t.isA1Equal('A1:B$2', { range: { top: 0, left: 0, bottom: 1, right: 1, $bottom: true } });
|
|
60
|
-
|
|
61
|
-
t.isA1Equal('A:A', { range: { top: 0, left: 0, bottom: 1048575, right: 0, $top: true, $bottom: true } });
|
|
62
|
-
t.isA1Equal('C:C', { range: { top: 0, left: 2, bottom: 1048575, right: 2, $top: true, $bottom: true } });
|
|
63
|
-
t.isA1Equal('C:$C', { range: { top: 0, left: 2, bottom: 1048575, right: 2, $right: true, $top: true, $bottom: true } });
|
|
64
|
-
t.isA1Equal('$C:C', { range: { top: 0, left: 2, bottom: 1048575, right: 2, $left: true, $top: true, $bottom: true } });
|
|
65
|
-
t.isA1Equal('$C:$C', { range: { top: 0, left: 2, bottom: 1048575, right: 2, $left: true, $right: true, $top: true, $bottom: true } });
|
|
66
|
-
|
|
67
|
-
t.isA1Equal('1:1', { range: { top: 0, left: 0, bottom: 0, right: 16383, $left: true, $right: true } });
|
|
68
|
-
t.isA1Equal('10:10', { range: { top: 9, left: 0, bottom: 9, right: 16383, $left: true, $right: true } });
|
|
69
|
-
t.isA1Equal('10:$10', { range: { top: 9, left: 0, bottom: 9, right: 16383, $bottom: true, $left: true, $right: true } });
|
|
70
|
-
t.isA1Equal('$10:10', { range: { top: 9, left: 0, bottom: 9, right: 16383, $top: true, $left: true, $right: true } });
|
|
71
|
-
t.isA1Equal('$10:$10', { range: { top: 9, left: 0, bottom: 9, right: 16383, $top: true, $bottom: true, $left: true, $right: true } });
|
|
72
|
-
|
|
73
|
-
t.isA1Equal('XFD1048576', { range: { top: 1048575, left: 16383, bottom: 1048575, right: 16383 } });
|
|
74
|
-
|
|
75
|
-
t.isA1Equal('Sheet1!A1', {
|
|
76
|
-
sheetName: 'Sheet1',
|
|
77
|
-
range: { top: 0, left: 0, bottom: 0, right: 0 }
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
t.isA1Equal('\'Sheet1\'!A1', {
|
|
81
|
-
sheetName: 'Sheet1',
|
|
82
|
-
range: { top: 0, left: 0, bottom: 0, right: 0 }
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
t.isA1Equal('\'Sheet1\'\'s\'!A1', {
|
|
86
|
-
sheetName: 'Sheet1\'s',
|
|
87
|
-
range: { top: 0, left: 0, bottom: 0, right: 0 }
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
t.isA1Equal('[Workbook.xlsx]Sheet1!A1', {
|
|
91
|
-
sheetName: 'Sheet1',
|
|
92
|
-
workbookName: 'Workbook.xlsx',
|
|
93
|
-
range: { top: 0, left: 0, bottom: 0, right: 0 }
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
t.isA1Equal("'[Workbook.xlsx]Sheet1'!A1", {
|
|
97
|
-
sheetName: 'Sheet1',
|
|
98
|
-
workbookName: 'Workbook.xlsx',
|
|
99
|
-
range: { top: 0, left: 0, bottom: 0, right: 0 }
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
t.isA1Equal("'[Workbook.xlsx]Sheet1'!A1", {
|
|
103
|
-
sheetName: 'Sheet1',
|
|
104
|
-
workbookName: 'Workbook.xlsx',
|
|
105
|
-
range: { top: 0, left: 0, bottom: 0, right: 0 }
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
t.isA1Equal("='[Workbook.xlsx]Sheet1'!A1", {
|
|
109
|
-
sheetName: 'Sheet1',
|
|
110
|
-
workbookName: 'Workbook.xlsx',
|
|
111
|
-
range: { top: 0, left: 0, bottom: 0, right: 0 }
|
|
112
|
-
});
|
|
113
|
-
t.isA1Equal('0123456789abcdefghijklmnopqrstuvwxyz!A1', null);
|
|
114
|
-
|
|
115
|
-
t.isA1Equal('[Workbook.xlsx]!A1', null);
|
|
116
|
-
t.isA1Equal('[Workbook.xlsx]!A1:B2', null);
|
|
117
|
-
t.isA1Equal('[Workbook.xlsx]!A:A', null);
|
|
118
|
-
t.isA1Equal('[Workbook.xlsx]!1:1', null);
|
|
119
|
-
t.isA1Equal('[]Sheet1!A1', null);
|
|
120
|
-
t.isA1Equal('namedrange', { name: 'namedrange' });
|
|
121
|
-
|
|
122
|
-
t.isA1Equal('Workbook.xlsx!namedrange', {
|
|
123
|
-
workbookName: 'Workbook.xlsx',
|
|
124
|
-
name: 'namedrange'
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
t.isA1Equal("'Workbook.xlsx'!namedrange", {
|
|
128
|
-
workbookName: 'Workbook.xlsx',
|
|
129
|
-
name: 'namedrange'
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
t.isA1Equal('[Workbook.xlsx]!namedrange', null);
|
|
133
|
-
t.isA1Equal('pensioneligibilitypartner1', { name: 'pensioneligibilitypartner1' });
|
|
134
|
-
t.isA1Equal('XFE1048577', { name: 'XFE1048577' });
|
|
135
|
-
|
|
136
|
-
// with named ranges disallowed
|
|
137
|
-
t.isA1Equal('namedrange', null, false);
|
|
138
|
-
t.isA1Equal('Workbook.xlsx!namedrange', null, false);
|
|
139
|
-
t.isA1Equal('pensioneligibilitypartner1', null, false);
|
|
140
|
-
t.isA1Equal('XFE1048577', null, false);
|
|
141
|
-
|
|
142
|
-
t.end();
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
test('A1 utilities', t => {
|
|
146
|
-
const relA1Range = {
|
|
147
|
-
top: 0, left: 0, bottom: 0, right: 0,
|
|
148
|
-
$top: false, $left: false, $bottom: false, $right: false
|
|
149
|
-
};
|
|
150
|
-
const absA1Range = {
|
|
151
|
-
top: 0, left: 0, bottom: 0, right: 0,
|
|
152
|
-
$top: true, $left: true, $bottom: true, $right: true
|
|
153
|
-
};
|
|
154
|
-
t.deepEqual(toAbsolute(relA1Range), absA1Range);
|
|
155
|
-
t.deepEqual(toRelative(absA1Range), relA1Range);
|
|
156
|
-
t.end();
|
|
157
|
-
});
|
|
158
|
-
|
package/lib/quickVerify.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
export function quickVerifyRangeA1 (tokenValue) {
|
|
2
|
-
// Quickly determine if range valus are out of bounds: Split the string into
|
|
3
|
-
// numeric, alphabetical, and "other" chunks and parse them as base 36 numbers.
|
|
4
|
-
// Both rows and cols can be represented in base 36 and we can decide which we
|
|
5
|
-
// hold by checking if the chunk was already a finite number. So we can simply
|
|
6
|
-
// compare against the base 36 parsed versions of XFD and 1048576.
|
|
7
|
-
return tokenValue.split(/(\d+|[a-zA-Z]+)/).every(d => {
|
|
8
|
-
const n = parseInt(d, 36);
|
|
9
|
-
if (!isNaN(n)) {
|
|
10
|
-
return isFinite(d)
|
|
11
|
-
? n <= 2183880786 // max rows
|
|
12
|
-
: n <= 43321; // max cols
|
|
13
|
-
}
|
|
14
|
-
return true;
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const bounds = {
|
|
19
|
-
'R': 1048577,
|
|
20
|
-
'R[': 1048576,
|
|
21
|
-
'C': 16385,
|
|
22
|
-
'C[': 16384
|
|
23
|
-
};
|
|
24
|
-
export function quickVerifyRangeRC (tokenValue) {
|
|
25
|
-
const reNums = /([RC]\[?)(-?\d+)/gi;
|
|
26
|
-
let m;
|
|
27
|
-
while ((m = reNums.exec(tokenValue)) !== null) {
|
|
28
|
-
const x = bounds[m[1]];
|
|
29
|
-
const val = parseInt(m[2], 10);
|
|
30
|
-
if (val >= x || val <= -x) {
|
|
31
|
-
return false;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
return true;
|
|
35
|
-
}
|
package/lib/rc-test.js
DELETED
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
/* eslint-disable object-property-newline, object-curly-newline */
|
|
2
|
-
import { test, Test } from 'tape';
|
|
3
|
-
import { MAX_COLS, MAX_ROWS } from './constants.js';
|
|
4
|
-
import { parseRCRef } from './rc.js';
|
|
5
|
-
|
|
6
|
-
Test.prototype.isRCEqual = function isTokens (expr, result, opts) {
|
|
7
|
-
if (result) {
|
|
8
|
-
result = {
|
|
9
|
-
sheetName: '',
|
|
10
|
-
workbookName: '',
|
|
11
|
-
name: '',
|
|
12
|
-
range: null,
|
|
13
|
-
...result
|
|
14
|
-
};
|
|
15
|
-
if (result.range && typeof result.range === 'object') {
|
|
16
|
-
// mix in some defaults so we don't have to write things out in full
|
|
17
|
-
result.range = {
|
|
18
|
-
r0: null, c0: null, r1: null, c1: null,
|
|
19
|
-
$r0: false, $c0: false, $r1: false, $c1: false,
|
|
20
|
-
...result.range
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
this.deepEqual(parseRCRef(expr, opts), result, expr);
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
test('parse single R1C1 references', t => {
|
|
28
|
-
// current row
|
|
29
|
-
t.isRCEqual('R', { range: { r0: 0, c0: 0, r1: 0, c1: MAX_COLS, $c0: true, $c1: true } });
|
|
30
|
-
t.isRCEqual('R[0]', { range: { r0: 0, c0: 0, r1: 0, c1: MAX_COLS, $c0: true, $c1: true } });
|
|
31
|
-
// row N (equivalent to 1:1)
|
|
32
|
-
t.isRCEqual('R0', { name: 'R0' });
|
|
33
|
-
t.isRCEqual('R1', { range: { r0: 0, c0: 0, r1: 0, c1: MAX_COLS, $r0: true, $r1: true, $c0: true, $c1: true } });
|
|
34
|
-
t.isRCEqual('R10', { range: { r0: 9, c0: 0, r1: 9, c1: MAX_COLS, $r0: true, $r1: true, $c0: true, $c1: true } });
|
|
35
|
-
// row following current
|
|
36
|
-
t.isRCEqual('R[1]', { range: { r0: 1, c0: 0, r1: 1, c1: MAX_COLS, $c0: true, $c1: true } });
|
|
37
|
-
// row preceding current
|
|
38
|
-
t.isRCEqual('R[-1]', { range: { r0: -1, c0: 0, r1: -1, c1: MAX_COLS, $c0: true, $c1: true } });
|
|
39
|
-
// current column
|
|
40
|
-
t.isRCEqual('C', { range: { r0: 0, c0: 0, r1: MAX_ROWS, c1: 0, $r0: true, $r1: true } });
|
|
41
|
-
t.isRCEqual('C[0]', { range: { r0: 0, c0: 0, r1: MAX_ROWS, c1: 0, $r0: true, $r1: true } });
|
|
42
|
-
// column N (equivalent to A:A)
|
|
43
|
-
t.isRCEqual('C0', { name: 'C0' });
|
|
44
|
-
t.isRCEqual('C1', { range: { r0: 0, c0: 0, r1: MAX_ROWS, c1: 0, $c0: true, $c1: true, $r0: true, $r1: true } });
|
|
45
|
-
t.isRCEqual('C10', { range: { r0: 0, c0: 9, r1: MAX_ROWS, c1: 9, $c0: true, $c1: true, $r0: true, $r1: true } });
|
|
46
|
-
// column following current
|
|
47
|
-
t.isRCEqual('C[1]', { range: { r0: 0, c0: 1, r1: MAX_ROWS, c1: 1, $r0: true, $r1: true } });
|
|
48
|
-
// column preceding current
|
|
49
|
-
t.isRCEqual('C[-1]', { range: { r0: 0, c0: -1, r1: MAX_ROWS, c1: -1, $r0: true, $r1: true } });
|
|
50
|
-
// current cell
|
|
51
|
-
t.isRCEqual('RC', { range: { r0: 0, c0: 0, r1: 0, c1: 0 } });
|
|
52
|
-
t.isRCEqual('R0C0', { name: 'R0C0' });
|
|
53
|
-
// fixed cell
|
|
54
|
-
t.isRCEqual('R1C1', { range: { r0: 0, c0: 0, r1: 0, c1: 0, $c0: true, $c1: true, $r0: true, $r1: true } });
|
|
55
|
-
t.isRCEqual('R10C8', { range: { r0: 9, c0: 7, r1: 9, c1: 7, $c0: true, $c1: true, $r0: true, $r1: true } });
|
|
56
|
-
t.isRCEqual('R-10C-8', null);
|
|
57
|
-
// relative parts
|
|
58
|
-
t.isRCEqual('R[2]C', { range: { r0: 2, c0: 0, r1: 2, c1: 0 } });
|
|
59
|
-
t.isRCEqual('R[-2]C', { range: { r0: -2, c0: 0, r1: -2, c1: 0 } });
|
|
60
|
-
t.isRCEqual('RC[3]', { range: { r0: 0, c0: 3, r1: 0, c1: 3 } });
|
|
61
|
-
t.isRCEqual('RC[-3]', { range: { r0: 0, c0: -3, r1: 0, c1: -3 } });
|
|
62
|
-
t.isRCEqual('R[2]C[4]', { range: { r0: 2, c0: 4, r1: 2, c1: 4 } });
|
|
63
|
-
t.isRCEqual('R[-2]C[-4]', { range: { r0: -2, c0: -4, r1: -2, c1: -4 } });
|
|
64
|
-
// mixed fixed and relative
|
|
65
|
-
t.isRCEqual('R[9]C9', { range: { r0: 9, c0: 8, r1: 9, c1: 8, $c0: true, $c1: true } });
|
|
66
|
-
t.isRCEqual('R9C[9]', { range: { r0: 8, c0: 9, r1: 8, c1: 9, $r0: true, $r1: true } });
|
|
67
|
-
|
|
68
|
-
// out of bounds
|
|
69
|
-
t.isRCEqual('R1048577', { name: 'R1048577' });
|
|
70
|
-
t.isRCEqual('R[1048576]', null);
|
|
71
|
-
t.isRCEqual('C16385', { name: 'C16385' });
|
|
72
|
-
t.isRCEqual('C[16384]', null);
|
|
73
|
-
|
|
74
|
-
t.end();
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
test('parse joined R1C1 references', t => {
|
|
78
|
-
// all "mirrored" refs are equivalent of the non mirrored counterparts...
|
|
79
|
-
t.isRCEqual('R:R', { range: { r0: 0, c0: 0, r1: 0, c1: MAX_COLS, $c0: true, $c1: true } });
|
|
80
|
-
t.isRCEqual('R[0]:R[0]', { range: { r0: 0, c0: 0, r1: 0, c1: MAX_COLS, $c0: true, $c1: true } });
|
|
81
|
-
t.isRCEqual('R1:R1', { range: { r0: 0, c0: 0, r1: 0, c1: MAX_COLS, $r0: true, $r1: true, $c0: true, $c1: true } });
|
|
82
|
-
t.isRCEqual('R10:R10', { range: { r0: 9, c0: 0, r1: 9, c1: MAX_COLS, $r0: true, $r1: true, $c0: true, $c1: true } });
|
|
83
|
-
t.isRCEqual('R[1]:R[1]', { range: { r0: 1, c0: 0, r1: 1, c1: MAX_COLS, $c0: true, $c1: true } });
|
|
84
|
-
t.isRCEqual('R[-1]:R[-1]', { range: { r0: -1, c0: 0, r1: -1, c1: MAX_COLS, $c0: true, $c1: true } });
|
|
85
|
-
t.isRCEqual('C:C', { range: { r0: 0, c0: 0, r1: MAX_ROWS, c1: 0, $r0: true, $r1: true } });
|
|
86
|
-
t.isRCEqual('C[0]:C[0]', { range: { r0: 0, c0: 0, r1: MAX_ROWS, c1: 0, $r0: true, $r1: true } });
|
|
87
|
-
t.isRCEqual('C1:C1', { range: { r0: 0, c0: 0, r1: MAX_ROWS, c1: 0, $c0: true, $c1: true, $r0: true, $r1: true } });
|
|
88
|
-
t.isRCEqual('C10:C10', { range: { r0: 0, c0: 9, r1: MAX_ROWS, c1: 9, $c0: true, $c1: true, $r0: true, $r1: true } });
|
|
89
|
-
t.isRCEqual('C[1]:C[1]', { range: { r0: 0, c0: 1, r1: MAX_ROWS, c1: 1, $r0: true, $r1: true } });
|
|
90
|
-
t.isRCEqual('C[-1]:C[-1]', { range: { r0: 0, c0: -1, r1: MAX_ROWS, c1: -1, $r0: true, $r1: true } });
|
|
91
|
-
t.isRCEqual('R0:R0', null);
|
|
92
|
-
t.isRCEqual('C0:C0', null);
|
|
93
|
-
t.isRCEqual('R[9]C9:R[9]C9', { range: { r0: 9, c0: 8, r1: 9, c1: 8, $c0: true, $c1: true } });
|
|
94
|
-
t.isRCEqual('R9C[9]:R9C[9]', { range: { r0: 8, c0: 9, r1: 8, c1: 9, $r0: true, $r1: true } });
|
|
95
|
-
t.isRCEqual('R[1]C[1]:R1C1', { range: { r0: 1, c0: 1, r1: 0, c1: 0, $c1: true, $r1: true } });
|
|
96
|
-
t.isRCEqual('R[1]C[1]:R1C1', { range: { r0: 1, c0: 1, r1: 0, c1: 0, $c1: true, $r1: true } });
|
|
97
|
-
t.isRCEqual('R1C1:R2C2', { range: { r0: 0, c0: 0, r1: 1, c1: 1, $c0: true, $c1: true, $r0: true, $r1: true } });
|
|
98
|
-
t.isRCEqual('R2C2:R1C1', { range: { r0: 1, c0: 1, r1: 0, c1: 0, $c0: true, $c1: true, $r0: true, $r1: true } });
|
|
99
|
-
// single thing
|
|
100
|
-
t.isRCEqual('C1:C3', { range: { r0: 0, c0: 0, r1: MAX_ROWS, c1: 2, $c0: true, $c1: true, $r0: true, $r1: true } });
|
|
101
|
-
t.isRCEqual('R[1]:R3', { range: { r0: 1, c0: 0, r1: 2, c1: MAX_COLS, $c0: true, $c1: true, $r0: false, $r1: true } });
|
|
102
|
-
t.isRCEqual('R[1]C1:R1C[-1]', { range: { r0: 1, c0: 0, r1: 0, c1: -1, $r0: false, $c0: true, $r1: true, $c1: false } });
|
|
103
|
-
// many things
|
|
104
|
-
t.isRCEqual('R:C', null);
|
|
105
|
-
t.isRCEqual('R:RC', null);
|
|
106
|
-
t.isRCEqual('RC:R', null);
|
|
107
|
-
t.isRCEqual('RC:C', null);
|
|
108
|
-
t.isRCEqual('C:R', null);
|
|
109
|
-
t.isRCEqual('C:RC', null);
|
|
110
|
-
t.end();
|
|
111
|
-
});
|