@rowsncolumns/utils 9.3.0 → 9.4.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/dist/cjs/index.d.ts +3 -0
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +3 -0
- package/dist/cjs/sparkline-groups.d.ts +102 -0
- package/dist/cjs/sparkline-groups.d.ts.map +1 -0
- package/dist/cjs/sparkline-groups.js +452 -0
- package/dist/cjs/string.d.ts +15 -0
- package/dist/cjs/string.d.ts.map +1 -1
- package/dist/cjs/string.js +46 -1
- package/dist/cjs/table-names.d.ts +55 -0
- package/dist/cjs/table-names.d.ts.map +1 -0
- package/dist/cjs/table-names.js +189 -0
- package/dist/cjs/table-styles.d.ts +9 -0
- package/dist/cjs/table-styles.d.ts.map +1 -1
- package/dist/cjs/table-styles.js +53 -1
- package/dist/cjs/table-totals.d.ts +31 -0
- package/dist/cjs/table-totals.d.ts.map +1 -0
- package/dist/cjs/table-totals.js +84 -0
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/index.d.ts +3 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +3 -0
- package/dist/esm/sparkline-groups.d.ts +102 -0
- package/dist/esm/sparkline-groups.d.ts.map +1 -0
- package/dist/esm/sparkline-groups.js +387 -0
- package/dist/esm/string.d.ts +15 -0
- package/dist/esm/string.d.ts.map +1 -1
- package/dist/esm/string.js +43 -0
- package/dist/esm/table-names.d.ts +55 -0
- package/dist/esm/table-names.d.ts.map +1 -0
- package/dist/esm/table-names.js +129 -0
- package/dist/esm/table-styles.d.ts +9 -0
- package/dist/esm/table-styles.d.ts.map +1 -1
- package/dist/esm/table-styles.js +34 -1
- package/dist/esm/table-totals.d.ts +31 -0
- package/dist/esm/table-totals.d.ts.map +1 -0
- package/dist/esm/table-totals.js +68 -0
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/package.json +5 -3
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Excel's rules for a table name (Table Design → Table Name / "Rename an Excel table"):
|
|
3
|
+
*
|
|
4
|
+
* - starts with a letter, an underscore (`_`) or a backslash (`\`);
|
|
5
|
+
* - the rest is letters, digits, periods (`.`) and underscores — no spaces;
|
|
6
|
+
* - is not a cell reference (`A1`, `R1C1`, `XFD1048576`) and not the lone `C` / `R` shortcuts;
|
|
7
|
+
* - is at most 255 characters;
|
|
8
|
+
* - is unique across the workbook, compared case-insensitively — against the other tables AND the
|
|
9
|
+
* defined names (Excel refuses a table named like an existing defined name, and a defined name
|
|
10
|
+
* spelled like an existing table).
|
|
11
|
+
*
|
|
12
|
+
* Both engines create and rename tables through these checks (the rnc store mirrors them in Rust and
|
|
13
|
+
* surfaces the same messages through its `rejections` channel), and the table editor's validation
|
|
14
|
+
* schema shows the same text under the name field.
|
|
15
|
+
*/
|
|
16
|
+
export const TABLE_NAME_MAX_LENGTH = 255;
|
|
17
|
+
// Built with `RegExp` (not literals) so the `u` flag survives the CJS build's ES5 target.
|
|
18
|
+
const LEADING_CHAR = new RegExp("^[\\p{L}_\\\\]", "u");
|
|
19
|
+
const BODY_CHARS = new RegExp("^[\\p{L}\\p{N}._]*$", "u");
|
|
20
|
+
/** `A1`-style — up to three ASCII column letters then a row number. */
|
|
21
|
+
const A1_REFERENCE = /^[A-Za-z]{1,3}\d+$/;
|
|
22
|
+
/** `R1C1`-style — `R`/`C` each followed by an optional index (`RC`, `R1C`, `R1C1`). */
|
|
23
|
+
const R1C1_REFERENCE = /^[Rr]\d*[Cc]\d*$/;
|
|
24
|
+
/** `C` and `R` alone select the active cell's column / row in the Name Box. */
|
|
25
|
+
const RESERVED_SHORTCUT = /^[CcRr]$/;
|
|
26
|
+
export const TABLE_NAME_REQUIRED_MESSAGE = "Enter a table name.";
|
|
27
|
+
export const TABLE_NAME_TOO_LONG_MESSAGE = `Table names can't be longer than ${TABLE_NAME_MAX_LENGTH} characters.`;
|
|
28
|
+
export const TABLE_NAME_SPACES_MESSAGE = "Table names can't contain spaces.";
|
|
29
|
+
export const TABLE_NAME_LEADING_CHAR_MESSAGE = "Table names must start with a letter, an underscore (_) or a backslash (\\).";
|
|
30
|
+
export const TABLE_NAME_INVALID_CHAR_MESSAGE = "Table names can only contain letters, numbers, periods (.) and underscores (_).";
|
|
31
|
+
export const TABLE_NAME_CELL_REFERENCE_MESSAGE = "Table names can't be a cell reference such as A1 or R1C1.";
|
|
32
|
+
export const tableNameDuplicateMessage = (existing) => `A table named "${existing}" already exists in this workbook. Table names must be unique.`;
|
|
33
|
+
export const tableNameDefinedNameMessage = (existing) => `A defined name "${existing}" already exists in this workbook. Table names and defined names must be unique.`;
|
|
34
|
+
/** `create-table` with an `id` an existing table already holds is refused on both engines (#668 T-56). */
|
|
35
|
+
export const tableIdDuplicateMessage = (id) => `A table with the id "${id}" already exists in this workbook.`;
|
|
36
|
+
export const definedNameTableNameMessage = (existing) => `A table named "${existing}" already exists in this workbook. Table names and defined names must be unique.`;
|
|
37
|
+
/** The entry of `names` that equals `name` case-insensitively, the way Excel compares names. */
|
|
38
|
+
const findNameCollision = (name, names) => {
|
|
39
|
+
if (!names) {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
const lower = name.toLowerCase();
|
|
43
|
+
for (const existing of names) {
|
|
44
|
+
if (existing.toLowerCase() === lower) {
|
|
45
|
+
return existing;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return undefined;
|
|
49
|
+
};
|
|
50
|
+
/** True when `name` reads as a cell reference in either A1 or R1C1 notation. */
|
|
51
|
+
export const isCellReferenceLikeName = (name) => A1_REFERENCE.test(name) ||
|
|
52
|
+
R1C1_REFERENCE.test(name) ||
|
|
53
|
+
RESERVED_SHORTCUT.test(name);
|
|
54
|
+
/**
|
|
55
|
+
* The reason `name` is not an acceptable table name, or `undefined` when it is. `existingNames` are
|
|
56
|
+
* the OTHER tables' names in the workbook (leave the table being renamed out of it) and
|
|
57
|
+
* `existingDefinedNames` the workbook's defined names; duplicates against either are detected
|
|
58
|
+
* case-insensitively, the way Excel compares names.
|
|
59
|
+
*/
|
|
60
|
+
export const validateTableName = (name, existingNames, existingDefinedNames) => {
|
|
61
|
+
if (!name) {
|
|
62
|
+
return TABLE_NAME_REQUIRED_MESSAGE;
|
|
63
|
+
}
|
|
64
|
+
if (name.length > TABLE_NAME_MAX_LENGTH) {
|
|
65
|
+
return TABLE_NAME_TOO_LONG_MESSAGE;
|
|
66
|
+
}
|
|
67
|
+
if (/\s/.test(name)) {
|
|
68
|
+
return TABLE_NAME_SPACES_MESSAGE;
|
|
69
|
+
}
|
|
70
|
+
if (!LEADING_CHAR.test(name)) {
|
|
71
|
+
return TABLE_NAME_LEADING_CHAR_MESSAGE;
|
|
72
|
+
}
|
|
73
|
+
if (!BODY_CHARS.test(name.slice(1))) {
|
|
74
|
+
return TABLE_NAME_INVALID_CHAR_MESSAGE;
|
|
75
|
+
}
|
|
76
|
+
if (isCellReferenceLikeName(name)) {
|
|
77
|
+
return TABLE_NAME_CELL_REFERENCE_MESSAGE;
|
|
78
|
+
}
|
|
79
|
+
const duplicate = findNameCollision(name, existingNames);
|
|
80
|
+
if (duplicate !== undefined) {
|
|
81
|
+
return tableNameDuplicateMessage(duplicate);
|
|
82
|
+
}
|
|
83
|
+
const definedName = findNameCollision(name, existingDefinedNames);
|
|
84
|
+
if (definedName !== undefined) {
|
|
85
|
+
return tableNameDefinedNameMessage(definedName);
|
|
86
|
+
}
|
|
87
|
+
return undefined;
|
|
88
|
+
};
|
|
89
|
+
export const isValidTableName = (name, existingNames, existingDefinedNames) => validateTableName(name, existingNames, existingDefinedNames) === undefined;
|
|
90
|
+
/**
|
|
91
|
+
* The reason a defined name `name` cannot be created or renamed to — it is spelled like one of
|
|
92
|
+
* `tableNames` (case-insensitive) — or `undefined` when no table holds it. Excel keeps tables and
|
|
93
|
+
* defined names in one namespace.
|
|
94
|
+
*/
|
|
95
|
+
export const validateDefinedNameAgainstTables = (name, tableNames) => {
|
|
96
|
+
const table = findNameCollision(name, tableNames);
|
|
97
|
+
return table === undefined ? undefined : definedNameTableNameMessage(table);
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* The default name for a new table: `Table1`, `Table2`, … — the LOWEST number no existing table
|
|
101
|
+
* uses (case-insensitive), so a deleted table's number is reissued and the result never collides.
|
|
102
|
+
* `format` localises the pattern (`(n) => \`Tabelle${n}\``).
|
|
103
|
+
*/
|
|
104
|
+
export const getNextTableName = (existingNames, format = (index) => `Table${index}`) => {
|
|
105
|
+
const taken = new Set();
|
|
106
|
+
for (const name of existingNames) {
|
|
107
|
+
taken.add(name.toLowerCase());
|
|
108
|
+
}
|
|
109
|
+
let index = 1;
|
|
110
|
+
while (taken.has(format(index).toLowerCase())) {
|
|
111
|
+
index++;
|
|
112
|
+
}
|
|
113
|
+
return format(index);
|
|
114
|
+
};
|
|
115
|
+
/**
|
|
116
|
+
* The name for a copy of table `base`: `Sales2`, `Sales3`, … — the LOWEST number no existing table
|
|
117
|
+
* uses (case-insensitive), the way Excel names the table on a duplicated sheet.
|
|
118
|
+
*/
|
|
119
|
+
export const getNextTableCopyName = (base, existingNames) => {
|
|
120
|
+
const taken = new Set();
|
|
121
|
+
for (const name of existingNames) {
|
|
122
|
+
taken.add(name.toLowerCase());
|
|
123
|
+
}
|
|
124
|
+
let index = 2;
|
|
125
|
+
while (taken.has(`${base}${index}`.toLowerCase())) {
|
|
126
|
+
index++;
|
|
127
|
+
}
|
|
128
|
+
return `${base}${index}`;
|
|
129
|
+
};
|
|
@@ -32,6 +32,15 @@ export type BandingProperties = {
|
|
|
32
32
|
secondBandBorder?: Maybe<Borders>;
|
|
33
33
|
totalRowColor?: Maybe<Color>;
|
|
34
34
|
totalRowBorder?: Maybe<Borders>;
|
|
35
|
+
/**
|
|
36
|
+
* Fill of the table's first / last column when the table shows them (`TableView.showFirstColumn`
|
|
37
|
+
* / `showLastColumn` — Excel's Table Design → First Column / Last Column). Every built-in style
|
|
38
|
+
* emphasises those columns in bold; only the Dark styles add a fill.
|
|
39
|
+
*/
|
|
40
|
+
firstColumnColor?: Maybe<Color>;
|
|
41
|
+
lastColumnColor?: Maybe<Color>;
|
|
42
|
+
/** Excel's `totalRow` style element bolds the totals row. */
|
|
43
|
+
totalRowBold?: Maybe<boolean>;
|
|
35
44
|
};
|
|
36
45
|
export type BandedDefinition = {
|
|
37
46
|
rowProperties?: Maybe<BandingProperties>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"table-styles.d.ts","sourceRoot":"","sources":["../../table-styles.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAE7D,MAAM,MAAM,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC;AAG5C,MAAM,MAAM,UAAU,GAAG;IACvB,KAAK,EAAE,UAAU,CAAC;IAClB,IAAI,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG,MAAM,GAAG,UAAU,CAAC;AAExC,MAAM,MAAM,WAAW,GACnB,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,MAAM,GACN,cAAc,GACd,aAAa,GACb,QAAQ,CAAC;AAGb,MAAM,MAAM,MAAM,GAAG;IACnB,KAAK,EAAE,WAAW,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,GAAG,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACpB,MAAM,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACvB,IAAI,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACrB,KAAK,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,WAAW,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IAC3B,WAAW,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IAC3B,cAAc,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IAC9B,eAAe,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IAC/B,YAAY,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAC9B,YAAY,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAC9B,eAAe,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IACjC,gBAAgB,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAClC,aAAa,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IAC7B,cAAc,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"table-styles.d.ts","sourceRoot":"","sources":["../../table-styles.ts"],"names":[],"mappings":"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"}
|
package/dist/esm/table-styles.js
CHANGED
|
@@ -11,7 +11,7 @@ export const getTableBorderStyles = (showRowStripes, showColumnStripes) => {
|
|
|
11
11
|
let runningLightIndex = 1;
|
|
12
12
|
let runningMediumIndex = 1;
|
|
13
13
|
let runningDarkIndex = 1;
|
|
14
|
-
|
|
14
|
+
const styles = new Map([
|
|
15
15
|
[
|
|
16
16
|
"Light",
|
|
17
17
|
[
|
|
@@ -285,6 +285,10 @@ export const getTableBorderStyles = (showRowStripes, showColumnStripes) => {
|
|
|
285
285
|
...colorIndexes.map((value) => {
|
|
286
286
|
const firstTint = value - 1 === 0 ? 0.25 : -0.25;
|
|
287
287
|
const secondTint = value - 1 === 0 ? 0.5 : 0;
|
|
288
|
+
const edgeColumnColor = {
|
|
289
|
+
theme: value,
|
|
290
|
+
tint: value - 1 === 0 ? 0.15 : -0.5,
|
|
291
|
+
};
|
|
288
292
|
return [
|
|
289
293
|
("TableStyleDark" + runningDarkIndex++),
|
|
290
294
|
firstTint,
|
|
@@ -300,6 +304,8 @@ export const getTableBorderStyles = (showRowStripes, showColumnStripes) => {
|
|
|
300
304
|
theme: value,
|
|
301
305
|
tint: secondTint,
|
|
302
306
|
},
|
|
307
|
+
firstColumnColor: edgeColumnColor,
|
|
308
|
+
lastColumnColor: edgeColumnColor,
|
|
303
309
|
},
|
|
304
310
|
columnProperties: showColumnStripes
|
|
305
311
|
? {
|
|
@@ -315,6 +321,10 @@ export const getTableBorderStyles = (showRowStripes, showColumnStripes) => {
|
|
|
315
321
|
...[1, 5, 7, 9].map((value) => {
|
|
316
322
|
const firstTint = value - 1 === 0 ? -0.35 : 0.6;
|
|
317
323
|
const secondTint = value - 1 === 0 ? -0.15 : 0.8;
|
|
324
|
+
const edgeColumnColor = {
|
|
325
|
+
theme: value - 1,
|
|
326
|
+
tint: value - 1 === 0 ? -0.5 : 0.4,
|
|
327
|
+
};
|
|
318
328
|
return [
|
|
319
329
|
("TableStyleDark" + runningDarkIndex++),
|
|
320
330
|
firstTint,
|
|
@@ -330,6 +340,8 @@ export const getTableBorderStyles = (showRowStripes, showColumnStripes) => {
|
|
|
330
340
|
theme: value - 1,
|
|
331
341
|
tint: secondTint,
|
|
332
342
|
},
|
|
343
|
+
firstColumnColor: edgeColumnColor,
|
|
344
|
+
lastColumnColor: edgeColumnColor,
|
|
333
345
|
},
|
|
334
346
|
columnProperties: showColumnStripes
|
|
335
347
|
? {
|
|
@@ -345,6 +357,27 @@ export const getTableBorderStyles = (showRowStripes, showColumnStripes) => {
|
|
|
345
357
|
],
|
|
346
358
|
],
|
|
347
359
|
]);
|
|
360
|
+
// Excel's built-in table styles bold the totals row and rule it with a double top border in
|
|
361
|
+
// the style's accent colour — the header border's colour, else the header fill's, else the
|
|
362
|
+
// stripe border's.
|
|
363
|
+
for (const entries of styles.values()) {
|
|
364
|
+
for (const [, , , bandDefinition] of entries) {
|
|
365
|
+
const rows = bandDefinition?.rowProperties;
|
|
366
|
+
if (!rows)
|
|
367
|
+
continue;
|
|
368
|
+
rows.totalRowBold = true;
|
|
369
|
+
const accent = rows.headerBorder?.top?.color ??
|
|
370
|
+
rows.headerBorder?.bottom?.color ??
|
|
371
|
+
rows.headerColor ??
|
|
372
|
+
rows.firstBandBorder?.bottom?.color;
|
|
373
|
+
if (accent && !rows.totalRowBorder) {
|
|
374
|
+
rows.totalRowBorder = {
|
|
375
|
+
top: { width: 1, style: "double", color: accent },
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
return styles;
|
|
348
381
|
};
|
|
349
382
|
/**
|
|
350
383
|
* Find the banded definition for a given table theme
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Excel's table totals row: the `totalsRowFunction` values a `<tableColumn>` carries
|
|
3
|
+
* (ECMA-376 `ST_TotalsRowFunction`), the hidden-row-aware `SUBTOTAL` number each one
|
|
4
|
+
* writes into the totals cell, and the structured-reference formula for it.
|
|
5
|
+
*/
|
|
6
|
+
export declare const TOTALS_ROW_FUNCTIONS: readonly ["none", "average", "count", "countNums", "max", "min", "sum", "stdDev", "var", "custom"];
|
|
7
|
+
export type TotalsRowFunction = (typeof TOTALS_ROW_FUNCTIONS)[number];
|
|
8
|
+
/**
|
|
9
|
+
* `SUBTOTAL` function numbers of the 101–111 family (ignore rows hidden by a filter),
|
|
10
|
+
* as Excel writes them into a totals-row cell. `none` and `custom` have none.
|
|
11
|
+
*/
|
|
12
|
+
export declare const TOTALS_ROW_FUNCTION_SUBTOTAL: Readonly<Partial<Record<TotalsRowFunction, number>>>;
|
|
13
|
+
export declare const isTotalsRowFunction: (value: unknown) => value is TotalsRowFunction;
|
|
14
|
+
/**
|
|
15
|
+
* Escape a column name for use inside a structured reference: `[`, `]`, `#`
|
|
16
|
+
* and `'` are prefixed with `'`, as Excel does (`Sales[Amount '[est']]`).
|
|
17
|
+
*/
|
|
18
|
+
export declare const escapeStructuredColumnName: (name: string) => string;
|
|
19
|
+
/**
|
|
20
|
+
* The totals-row formula for `fn` over a table column, qualified with the table
|
|
21
|
+
* name so it evaluates from any engine and matches what Excel writes:
|
|
22
|
+
* `=SUBTOTAL(109,Sales[Amount])`. `undefined` for `none` / `custom`.
|
|
23
|
+
*/
|
|
24
|
+
export declare const getTotalsRowFormula: (fn: TotalsRowFunction, tableName: string, columnName: string) => string | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* Recognise the aggregation a totals-row formula uses. Both the hidden-row-aware
|
|
27
|
+
* (1xx) and plain (1–11) `SUBTOTAL` numbers map to the same function; anything
|
|
28
|
+
* else is `none`.
|
|
29
|
+
*/
|
|
30
|
+
export declare const getTotalsRowFunctionFromFormula: (formula: string | null | undefined) => TotalsRowFunction;
|
|
31
|
+
//# sourceMappingURL=table-totals.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table-totals.d.ts","sourceRoot":"","sources":["../../table-totals.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,oGAWvB,CAAC;AAEX,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtE;;;GAGG;AACH,eAAO,MAAM,4BAA4B,EAAE,QAAQ,CACjD,OAAO,CAAC,MAAM,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC,CAU3C,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAC9B,OAAO,OAAO,KACb,KAAK,IAAI,iBAEiD,CAAC;AAE9D;;;GAGG;AACH,eAAO,MAAM,0BAA0B,GAAI,MAAM,MAAM,WACnB,CAAC;AAErC;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAC9B,IAAI,iBAAiB,EACrB,WAAW,MAAM,EACjB,YAAY,MAAM,KACjB,MAAM,GAAG,SAQX,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,+BAA+B,GAC1C,SAAS,MAAM,GAAG,IAAI,GAAG,SAAS,KACjC,iBAcF,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Excel's table totals row: the `totalsRowFunction` values a `<tableColumn>` carries
|
|
3
|
+
* (ECMA-376 `ST_TotalsRowFunction`), the hidden-row-aware `SUBTOTAL` number each one
|
|
4
|
+
* writes into the totals cell, and the structured-reference formula for it.
|
|
5
|
+
*/
|
|
6
|
+
export const TOTALS_ROW_FUNCTIONS = [
|
|
7
|
+
"none",
|
|
8
|
+
"average",
|
|
9
|
+
"count",
|
|
10
|
+
"countNums",
|
|
11
|
+
"max",
|
|
12
|
+
"min",
|
|
13
|
+
"sum",
|
|
14
|
+
"stdDev",
|
|
15
|
+
"var",
|
|
16
|
+
"custom",
|
|
17
|
+
];
|
|
18
|
+
/**
|
|
19
|
+
* `SUBTOTAL` function numbers of the 101–111 family (ignore rows hidden by a filter),
|
|
20
|
+
* as Excel writes them into a totals-row cell. `none` and `custom` have none.
|
|
21
|
+
*/
|
|
22
|
+
export const TOTALS_ROW_FUNCTION_SUBTOTAL = {
|
|
23
|
+
average: 101,
|
|
24
|
+
countNums: 102,
|
|
25
|
+
count: 103,
|
|
26
|
+
max: 104,
|
|
27
|
+
min: 105,
|
|
28
|
+
stdDev: 107,
|
|
29
|
+
sum: 109,
|
|
30
|
+
var: 110,
|
|
31
|
+
};
|
|
32
|
+
export const isTotalsRowFunction = (value) => typeof value === "string" &&
|
|
33
|
+
TOTALS_ROW_FUNCTIONS.includes(value);
|
|
34
|
+
/**
|
|
35
|
+
* Escape a column name for use inside a structured reference: `[`, `]`, `#`
|
|
36
|
+
* and `'` are prefixed with `'`, as Excel does (`Sales[Amount '[est']]`).
|
|
37
|
+
*/
|
|
38
|
+
export const escapeStructuredColumnName = (name) => name.replace(/(['\[\]#])/g, "'$1");
|
|
39
|
+
/**
|
|
40
|
+
* The totals-row formula for `fn` over a table column, qualified with the table
|
|
41
|
+
* name so it evaluates from any engine and matches what Excel writes:
|
|
42
|
+
* `=SUBTOTAL(109,Sales[Amount])`. `undefined` for `none` / `custom`.
|
|
43
|
+
*/
|
|
44
|
+
export const getTotalsRowFormula = (fn, tableName, columnName) => {
|
|
45
|
+
const subtotal = TOTALS_ROW_FUNCTION_SUBTOTAL[fn];
|
|
46
|
+
if (subtotal === undefined) {
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
return `=SUBTOTAL(${subtotal},${tableName}[${escapeStructuredColumnName(columnName)}])`;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Recognise the aggregation a totals-row formula uses. Both the hidden-row-aware
|
|
53
|
+
* (1xx) and plain (1–11) `SUBTOTAL` numbers map to the same function; anything
|
|
54
|
+
* else is `none`.
|
|
55
|
+
*/
|
|
56
|
+
export const getTotalsRowFunctionFromFormula = (formula) => {
|
|
57
|
+
if (!formula) {
|
|
58
|
+
return "none";
|
|
59
|
+
}
|
|
60
|
+
const match = /^\s*=\s*SUBTOTAL\s*\(\s*(\d{1,3})\s*,/i.exec(formula);
|
|
61
|
+
if (!match) {
|
|
62
|
+
return "none";
|
|
63
|
+
}
|
|
64
|
+
const number = Number(match[1]);
|
|
65
|
+
const normalized = number > 100 ? number - 100 : number;
|
|
66
|
+
const found = Object.entries(TOTALS_ROW_FUNCTION_SUBTOTAL).find(([, subtotal]) => subtotal - 100 === normalized);
|
|
67
|
+
return found?.[0] ?? "none";
|
|
68
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["../../array.ts","../../cell-data-helpers.ts","../../color.ts","../../colors.ts","../../conditional-format.ts","../../content-hash.ts","../../data-validation.ts","../../date.ts","../../dom.ts","../../excel-number-format.ts","../../formatter.ts","../../formula-locale.ts","../../formula-refs.ts","../../formula.ts","../../index.ts","../../keyboard.ts","../../locale.ts","../../log.ts","../../memoize.ts","../../numbers.ts","../../selection.ts","../../shared-string-canonical.ts","../../sheet-span.ts","../../sort.ts","../../string.ts","../../table-styles.ts","../../typeguards.ts","../../uuid.ts","../../vitest.config.ts","../../formula-locale/formula-locale-data.generated.ts"],"version":"5.8.3"}
|
|
1
|
+
{"root":["../../array.ts","../../cell-data-helpers.ts","../../color.ts","../../colors.ts","../../conditional-format.ts","../../content-hash.ts","../../data-validation.ts","../../date.ts","../../dom.ts","../../excel-number-format.ts","../../formatter.ts","../../formula-locale.ts","../../formula-refs.ts","../../formula.ts","../../index.ts","../../keyboard.ts","../../locale.ts","../../log.ts","../../memoize.ts","../../numbers.ts","../../selection.ts","../../shared-string-canonical.ts","../../sheet-span.ts","../../sort.ts","../../sparkline-groups.ts","../../string.ts","../../table-names.ts","../../table-styles.ts","../../table-totals.ts","../../typeguards.ts","../../uuid.ts","../../vitest.config.ts","../../formula-locale/formula-locale-data.generated.ts"],"version":"5.8.3"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rowsncolumns/utils",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.4.0",
|
|
4
4
|
"author": "Vinay M",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
6
6
|
"main": "./dist/cjs/index.js",
|
|
@@ -28,7 +28,9 @@
|
|
|
28
28
|
"clean": "rimraf dist",
|
|
29
29
|
"build:watch": "tsc -p ./tsconfig.esm.json --watch",
|
|
30
30
|
"test": "vitest --run",
|
|
31
|
-
"types": "tsc -p . --noEmit"
|
|
31
|
+
"types": "tsc -p . --noEmit",
|
|
32
|
+
"types:specs": "node ../../scripts/typecheck-specs.mjs",
|
|
33
|
+
"types:specs:update": "node ../../scripts/typecheck-specs.mjs --update"
|
|
32
34
|
},
|
|
33
35
|
"files": [
|
|
34
36
|
"dist"
|
|
@@ -42,7 +44,7 @@
|
|
|
42
44
|
},
|
|
43
45
|
"dependencies": {
|
|
44
46
|
"numfmt": "^3.2.2",
|
|
45
|
-
"@rowsncolumns/common-types": ">=5.2.
|
|
47
|
+
"@rowsncolumns/common-types": ">=5.2.34"
|
|
46
48
|
},
|
|
47
49
|
"devDependencies": {},
|
|
48
50
|
"peerDependencies": {}
|