@dou-ui/sheet 0.0.0-stage → 0.1.0-alpha.1
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/LICENSE +21 -0
- package/README.md +10 -2
- package/dist/cell-types.js +20 -0
- package/dist/cell-types.js.map +1 -0
- package/dist/code/code-formula-bar.js +6 -0
- package/dist/code/code-formula-bar.js.map +1 -0
- package/dist/code/code-formula-bar.vue_vue_type_script_setup_true_lang.js +192 -0
- package/dist/code/code-formula-bar.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/code/index.js +12 -0
- package/dist/code/index.js.map +1 -0
- package/dist/code/language.js +51 -0
- package/dist/code/language.js.map +1 -0
- package/dist/code/style.d.ts +1 -0
- package/dist/code/style.js +2 -0
- package/dist/collaboration/anchor.js +143 -0
- package/dist/collaboration/anchor.js.map +1 -0
- package/dist/collaboration/index.js +770 -0
- package/dist/collaboration/index.js.map +1 -0
- package/dist/collaboration/peers.js +87 -0
- package/dist/collaboration/peers.js.map +1 -0
- package/dist/collaboration/shared.js +450 -0
- package/dist/collaboration/shared.js.map +1 -0
- package/dist/components/cell-panel.js +6 -0
- package/dist/components/cell-panel.js.map +1 -0
- package/dist/components/cell-panel.vue_vue_type_script_setup_true_lang.js +70 -0
- package/dist/components/cell-panel.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/cell-renders.js +40 -0
- package/dist/components/cell-renders.js.map +1 -0
- package/dist/components/date-panel.js +6 -0
- package/dist/components/date-panel.js.map +1 -0
- package/dist/components/date-panel.vue_vue_type_script_setup_true_lang.js +48 -0
- package/dist/components/date-panel.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/filter-panel.js +6 -0
- package/dist/components/filter-panel.js.map +1 -0
- package/dist/components/filter-panel.vue_vue_type_script_setup_true_lang.js +259 -0
- package/dist/components/filter-panel.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/format-dialog.js +6 -0
- package/dist/components/format-dialog.js.map +1 -0
- package/dist/components/format-dialog.vue_vue_type_script_setup_true_lang.js +432 -0
- package/dist/components/format-dialog.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/format-list.js +6 -0
- package/dist/components/format-list.js.map +1 -0
- package/dist/components/format-list.vue_vue_type_script_setup_true_lang.js +187 -0
- package/dist/components/format-list.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/format-presets.js +97 -0
- package/dist/components/format-presets.js.map +1 -0
- package/dist/components/option-panel.js +6 -0
- package/dist/components/option-panel.js.map +1 -0
- package/dist/components/option-panel.vue_vue_type_script_setup_true_lang.js +117 -0
- package/dist/components/option-panel.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/sheet-comment.js +6 -0
- package/dist/components/sheet-comment.js.map +1 -0
- package/dist/components/sheet-comment.vue_vue_type_script_setup_true_lang.js +104 -0
- package/dist/components/sheet-comment.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/sheet-formula-bar.js +6 -0
- package/dist/components/sheet-formula-bar.js.map +1 -0
- package/dist/components/sheet-formula-bar.vue_vue_type_script_setup_true_lang.js +124 -0
- package/dist/components/sheet-formula-bar.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/sheet-link.js +6 -0
- package/dist/components/sheet-link.js.map +1 -0
- package/dist/components/sheet-link.vue_vue_type_script_setup_true_lang.js +249 -0
- package/dist/components/sheet-link.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/sheet-menu.js +6 -0
- package/dist/components/sheet-menu.js.map +1 -0
- package/dist/components/sheet-menu.vue_vue_type_script_setup_true_lang.js +115 -0
- package/dist/components/sheet-menu.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/sheet-name-box.js +6 -0
- package/dist/components/sheet-name-box.js.map +1 -0
- package/dist/components/sheet-name-box.vue_vue_type_script_setup_true_lang.js +91 -0
- package/dist/components/sheet-name-box.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/sheet-note.js +6 -0
- package/dist/components/sheet-note.js.map +1 -0
- package/dist/components/sheet-note.vue_vue_type_script_setup_true_lang.js +146 -0
- package/dist/components/sheet-note.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/sheet-outline.js +6 -0
- package/dist/components/sheet-outline.js.map +1 -0
- package/dist/components/sheet-outline.vue_vue_type_script_setup_true_lang.js +237 -0
- package/dist/components/sheet-outline.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/sheet-tabs.js +6 -0
- package/dist/components/sheet-tabs.js.map +1 -0
- package/dist/components/sheet-tabs.vue_vue_type_script_setup_true_lang.js +487 -0
- package/dist/components/sheet-tabs.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/sheet-toolbar.js +6 -0
- package/dist/components/sheet-toolbar.js.map +1 -0
- package/dist/components/sheet-toolbar.vue_vue_type_script_setup_true_lang.js +1562 -0
- package/dist/components/sheet-toolbar.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/validation-dialog.js +6 -0
- package/dist/components/validation-dialog.js.map +1 -0
- package/dist/components/validation-dialog.vue_vue_type_script_setup_true_lang.js +370 -0
- package/dist/components/validation-dialog.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/context.js +12 -0
- package/dist/context.js.map +1 -0
- package/dist/core/address.js +256 -0
- package/dist/core/address.js.map +1 -0
- package/dist/core/axis.js +72 -0
- package/dist/core/axis.js.map +1 -0
- package/dist/core/cell-type.js +30 -0
- package/dist/core/cell-type.js.map +1 -0
- package/dist/core/clipboard.js +141 -0
- package/dist/core/clipboard.js.map +1 -0
- package/dist/core/commands.js +63 -0
- package/dist/core/commands.js.map +1 -0
- package/dist/core/comments.js +74 -0
- package/dist/core/comments.js.map +1 -0
- package/dist/core/conditional.js +362 -0
- package/dist/core/conditional.js.map +1 -0
- package/dist/core/csv.js +191 -0
- package/dist/core/csv.js.map +1 -0
- package/dist/core/data.js +118 -0
- package/dist/core/data.js.map +1 -0
- package/dist/core/document.js +187 -0
- package/dist/core/document.js.map +1 -0
- package/dist/core/extension.js +60 -0
- package/dist/core/extension.js.map +1 -0
- package/dist/core/file.js +336 -0
- package/dist/core/file.js.map +1 -0
- package/dist/core/fill.js +153 -0
- package/dist/core/fill.js.map +1 -0
- package/dist/core/find.js +42 -0
- package/dist/core/find.js.map +1 -0
- package/dist/core/format.js +404 -0
- package/dist/core/format.js.map +1 -0
- package/dist/core/group.js +134 -0
- package/dist/core/group.js.map +1 -0
- package/dist/core/history.js +68 -0
- package/dist/core/history.js.map +1 -0
- package/dist/core/index.js +17 -0
- package/dist/core/link.js +34 -0
- package/dist/core/link.js.map +1 -0
- package/dist/core/merge.js +105 -0
- package/dist/core/merge.js.map +1 -0
- package/dist/core/model.js +48 -0
- package/dist/core/model.js.map +1 -0
- package/dist/core/nav.js +44 -0
- package/dist/core/nav.js.map +1 -0
- package/dist/core/paint.js +106 -0
- package/dist/core/paint.js.map +1 -0
- package/dist/core/plain-cell-types.js +54 -0
- package/dist/core/plain-cell-types.js.map +1 -0
- package/dist/core/protect.js +246 -0
- package/dist/core/protect.js.map +1 -0
- package/dist/core/selection.js +37 -0
- package/dist/core/selection.js.map +1 -0
- package/dist/core/transaction.js +1582 -0
- package/dist/core/transaction.js.map +1 -0
- package/dist/core/validation.js +135 -0
- package/dist/core/validation.js.map +1 -0
- package/dist/core/versions.js +161 -0
- package/dist/core/versions.js.map +1 -0
- package/dist/export/color.js +36 -0
- package/dist/export/color.js.map +1 -0
- package/dist/export/draw.js +316 -0
- package/dist/export/draw.js.map +1 -0
- package/dist/export/index.js +390 -0
- package/dist/export/index.js.map +1 -0
- package/dist/formula/edit.js +210 -0
- package/dist/formula/edit.js.map +1 -0
- package/dist/formula/engine.js +526 -0
- package/dist/formula/engine.js.map +1 -0
- package/dist/formula/error.js +39 -0
- package/dist/formula/error.js.map +1 -0
- package/dist/formula/functions.js +1493 -0
- package/dist/formula/functions.js.map +1 -0
- package/dist/formula/help.js +408 -0
- package/dist/formula/help.js.map +1 -0
- package/dist/formula/index.js +7 -0
- package/dist/formula/parse.js +369 -0
- package/dist/formula/parse.js.map +1 -0
- package/dist/formula/values.js +123 -0
- package/dist/formula/values.js.map +1 -0
- package/dist/formulas.js +30 -0
- package/dist/formulas.js.map +1 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/locale.js +1312 -0
- package/dist/locale.js.map +1 -0
- package/dist/sheet.js +6 -0
- package/dist/sheet.js.map +1 -0
- package/dist/sheet.vue_vue_type_script_setup_true_lang.js +7166 -0
- package/dist/sheet.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/style.css +1 -0
- package/dist/style.d.ts +1 -0
- package/dist/style.js +17 -0
- package/dist/types/cell-types.d.ts +2 -0
- package/dist/types/code/code-formula-bar.vue.d.ts +3 -0
- package/dist/types/code/index.d.ts +12 -0
- package/dist/types/code/language.d.ts +13 -0
- package/dist/types/collaboration/anchor.d.ts +65 -0
- package/dist/types/collaboration/index.d.ts +59 -0
- package/dist/types/collaboration/peers.d.ts +21 -0
- package/dist/types/collaboration/shared.d.ts +75 -0
- package/dist/types/components/cell-panel.vue.d.ts +20 -0
- package/dist/types/components/cell-renders.d.ts +9 -0
- package/dist/types/components/date-panel.vue.d.ts +9 -0
- package/dist/types/components/filter-panel.vue.d.ts +21 -0
- package/dist/types/components/format-dialog.vue.d.ts +24 -0
- package/dist/types/components/format-list.vue.d.ts +25 -0
- package/dist/types/components/format-presets.d.ts +30 -0
- package/dist/types/components/option-panel.vue.d.ts +13 -0
- package/dist/types/components/sheet-comment.vue.d.ts +29 -0
- package/dist/types/components/sheet-formula-bar.vue.d.ts +3 -0
- package/dist/types/components/sheet-link.vue.d.ts +32 -0
- package/dist/types/components/sheet-menu.vue.d.ts +20 -0
- package/dist/types/components/sheet-name-box.vue.d.ts +3 -0
- package/dist/types/components/sheet-note.vue.d.ts +22 -0
- package/dist/types/components/sheet-outline.vue.d.ts +36 -0
- package/dist/types/components/sheet-tabs.vue.d.ts +9 -0
- package/dist/types/components/sheet-toolbar.vue.d.ts +11 -0
- package/dist/types/components/validation-dialog.vue.d.ts +25 -0
- package/dist/types/context.d.ts +189 -0
- package/dist/types/core/address.d.ts +109 -0
- package/dist/types/core/axis.d.ts +23 -0
- package/dist/types/core/cell-type.d.ts +157 -0
- package/dist/types/core/clipboard.d.ts +48 -0
- package/dist/types/core/commands.d.ts +76 -0
- package/dist/types/core/comments.d.ts +22 -0
- package/dist/types/core/conditional.d.ts +114 -0
- package/dist/types/core/csv.d.ts +93 -0
- package/dist/types/core/data.d.ts +26 -0
- package/dist/types/core/document.d.ts +49 -0
- package/dist/types/core/extension.d.ts +177 -0
- package/dist/types/core/file.d.ts +301 -0
- package/dist/types/core/fill.d.ts +23 -0
- package/dist/types/core/find.d.ts +39 -0
- package/dist/types/core/format.d.ts +47 -0
- package/dist/types/core/group.d.ts +76 -0
- package/dist/types/core/history.d.ts +27 -0
- package/dist/types/core/index.d.ts +33 -0
- package/dist/types/core/link.d.ts +14 -0
- package/dist/types/core/merge.d.ts +26 -0
- package/dist/types/core/model.d.ts +363 -0
- package/dist/types/core/nav.d.ts +15 -0
- package/dist/types/core/paint.d.ts +19 -0
- package/dist/types/core/plain-cell-types.d.ts +6 -0
- package/dist/types/core/protect.d.ts +34 -0
- package/dist/types/core/selection.d.ts +25 -0
- package/dist/types/core/transaction.d.ts +470 -0
- package/dist/types/core/validation.d.ts +55 -0
- package/dist/types/core/versions.d.ts +38 -0
- package/dist/types/export/color.d.ts +7 -0
- package/dist/types/export/draw.d.ts +98 -0
- package/dist/types/export/index.d.ts +47 -0
- package/dist/types/formula/edit.d.ts +62 -0
- package/dist/types/formula/engine.d.ts +99 -0
- package/dist/types/formula/error.d.ts +30 -0
- package/dist/types/formula/functions.d.ts +62 -0
- package/dist/types/formula/help.d.ts +12 -0
- package/dist/types/formula/index.d.ts +13 -0
- package/dist/types/formula/parse.d.ts +92 -0
- package/dist/types/formula/values.d.ts +65 -0
- package/dist/types/formulas.d.ts +32 -0
- package/dist/types/index.d.ts +225 -0
- package/dist/types/locale.d.ts +531 -0
- package/dist/types/sheet.vue.d.ts +60 -0
- package/dist/types/types.d.ts +498 -0
- package/dist/types/use-comments.d.ts +47 -0
- package/dist/types/use-messages.d.ts +7 -0
- package/dist/use-comments.js +130 -0
- package/dist/use-comments.js.map +1 -0
- package/dist/use-messages.js +29 -0
- package/dist/use-messages.js.map +1 -0
- package/package.json +93 -4
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
import { splitSheet } from "../core/address.js";
|
|
2
|
+
import { ERROR_CODES } from "./error.js";
|
|
3
|
+
// src/formula/parse.ts
|
|
4
|
+
/** Thrown for text that isn't a formula; it shows as `#ERROR!`. */
|
|
5
|
+
var SheetFormulaSyntaxError = class extends Error {
|
|
6
|
+
at;
|
|
7
|
+
constructor(message, at) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.at = at;
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
var END = "(?![\\p{L}\\p{N}_(!.])";
|
|
13
|
+
var SHEET = "(?:('(?:[^']|'')+'|[\\p{L}_][\\p{L}\\p{N}_.]*)!)?";
|
|
14
|
+
var REF = new RegExp(SHEET + "(?:(\\$?[a-z]{1,3}\\$?[1-9]\\d{0,6})(?::(\\$?[a-z]{1,3}\\$?[1-9]\\d{0,6}))?|(\\$?[a-z]{1,3}):(\\$?[a-z]{1,3})|(\\$?[1-9]\\d{0,6}):(\\$?[1-9]\\d{0,6}))" + END, "iuy");
|
|
15
|
+
var SHEET_ERROR = new RegExp(`${SHEET}#REF!`, "iuy");
|
|
16
|
+
var NUMBER = /(?:\d+(?:\.\d*)?|\.\d+)(?:e[-+]?\d+)?/iy;
|
|
17
|
+
var NAME = /[\p{L}_][\p{L}\p{N}_.]*/uy;
|
|
18
|
+
var NAME_START = /[\p{L}_]/u;
|
|
19
|
+
var OPS = /* @__PURE__ */ new Set([
|
|
20
|
+
"+",
|
|
21
|
+
"-",
|
|
22
|
+
"*",
|
|
23
|
+
"/",
|
|
24
|
+
"^",
|
|
25
|
+
"&",
|
|
26
|
+
"=",
|
|
27
|
+
"<",
|
|
28
|
+
">",
|
|
29
|
+
"%",
|
|
30
|
+
"(",
|
|
31
|
+
")",
|
|
32
|
+
",",
|
|
33
|
+
";"
|
|
34
|
+
]);
|
|
35
|
+
/** One end of a reference, `$B$3`, `B` or `3`, read by hand: this runs for every reference. */
|
|
36
|
+
function readEnd(text) {
|
|
37
|
+
let i = text.charCodeAt(0) === 36 ? 1 : 0;
|
|
38
|
+
let col = -1;
|
|
39
|
+
for (let c = text.charCodeAt(i); (c | 32) >= 97 && (c | 32) <= 122; c = text.charCodeAt(++i)) col = (col + 1) * 26 + (c | 32) - 97;
|
|
40
|
+
if (text.charCodeAt(i) === 36) i++;
|
|
41
|
+
const row = i < text.length ? Number(text.slice(i)) - 1 : -1;
|
|
42
|
+
return {
|
|
43
|
+
col: col === -1 ? void 0 : col,
|
|
44
|
+
row: row === -1 ? void 0 : row
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function readRef(match) {
|
|
48
|
+
const sheet = match[1] ? splitSheet(`${match[1]}!`).sheet : void 0;
|
|
49
|
+
const first = match[2] != null ? 0 : match[4] != null ? 2 : 4;
|
|
50
|
+
const a = readEnd(match[first + 2]);
|
|
51
|
+
const to = match[first + 3];
|
|
52
|
+
const b = to != null ? readEnd(to) : a;
|
|
53
|
+
const node = {
|
|
54
|
+
type: "ref",
|
|
55
|
+
top: Math.min(a.row ?? 0, b.row ?? 0),
|
|
56
|
+
left: Math.min(a.col ?? 0, b.col ?? 0),
|
|
57
|
+
bottom: a.row == null ? Infinity : Math.max(a.row, b.row),
|
|
58
|
+
right: a.col == null ? Infinity : Math.max(a.col, b.col),
|
|
59
|
+
cell: first === 0 && to == null
|
|
60
|
+
};
|
|
61
|
+
if (sheet != null) node.sheet = sheet;
|
|
62
|
+
return node;
|
|
63
|
+
}
|
|
64
|
+
function tokenize(text, loose = false) {
|
|
65
|
+
const tokens = [];
|
|
66
|
+
let i = 0;
|
|
67
|
+
const push = (token, length) => {
|
|
68
|
+
tokens.push({
|
|
69
|
+
...token,
|
|
70
|
+
end: token.at + length
|
|
71
|
+
});
|
|
72
|
+
i = token.at + length;
|
|
73
|
+
};
|
|
74
|
+
const at = (re) => {
|
|
75
|
+
re.lastIndex = i;
|
|
76
|
+
return re.exec(text);
|
|
77
|
+
};
|
|
78
|
+
while (i < text.length) {
|
|
79
|
+
const char = text[i];
|
|
80
|
+
if (char === " " || /\s/.test(char)) {
|
|
81
|
+
i++;
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
if (char === "\"") {
|
|
85
|
+
let value = "";
|
|
86
|
+
let j = i + 1;
|
|
87
|
+
for (;; j++) {
|
|
88
|
+
if (j >= text.length) {
|
|
89
|
+
if (!loose) throw new SheetFormulaSyntaxError("Text without its closing quote", i);
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
if (text[j] === "\"") {
|
|
93
|
+
if (text[j + 1] === "\"") {
|
|
94
|
+
value += "\"";
|
|
95
|
+
j++;
|
|
96
|
+
} else break;
|
|
97
|
+
} else value += text[j];
|
|
98
|
+
}
|
|
99
|
+
push({
|
|
100
|
+
kind: "text",
|
|
101
|
+
value,
|
|
102
|
+
at: i
|
|
103
|
+
}, Math.min(j + 1, text.length) - i);
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
if (char === "#") {
|
|
107
|
+
const code = ERROR_CODES.find((c) => text.startsWith(c, i) || text.toUpperCase().startsWith(c, i));
|
|
108
|
+
if (code) {
|
|
109
|
+
push({
|
|
110
|
+
kind: "error",
|
|
111
|
+
code,
|
|
112
|
+
at: i
|
|
113
|
+
}, code.length);
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
if (!loose) throw new SheetFormulaSyntaxError("Unknown error value", i);
|
|
117
|
+
push({
|
|
118
|
+
kind: "op",
|
|
119
|
+
value: char,
|
|
120
|
+
at: i
|
|
121
|
+
}, 1);
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
const ref = OPS.has(char) ? null : at(REF);
|
|
125
|
+
if (ref) {
|
|
126
|
+
push({
|
|
127
|
+
kind: "ref",
|
|
128
|
+
node: readRef(ref),
|
|
129
|
+
at: i
|
|
130
|
+
}, ref[0].length);
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
const refError = char === "'" || NAME_START.test(char) ? at(SHEET_ERROR) : null;
|
|
134
|
+
if (refError) {
|
|
135
|
+
push({
|
|
136
|
+
kind: "error",
|
|
137
|
+
code: "#REF!",
|
|
138
|
+
at: i
|
|
139
|
+
}, refError[0].length);
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
const number = char >= "0" && char <= "9" || char === "." ? at(NUMBER) : null;
|
|
143
|
+
if (number) {
|
|
144
|
+
push({
|
|
145
|
+
kind: "number",
|
|
146
|
+
value: Number(number[0]),
|
|
147
|
+
at: i
|
|
148
|
+
}, number[0].length);
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
const name = at(NAME);
|
|
152
|
+
if (name) {
|
|
153
|
+
push({
|
|
154
|
+
kind: "name",
|
|
155
|
+
value: name[0],
|
|
156
|
+
at: i
|
|
157
|
+
}, name[0].length);
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
const two = text.slice(i, i + 2);
|
|
161
|
+
const op = two === "<>" || two === "<=" || two === ">=" ? two : OPS.has(char) ? char : void 0;
|
|
162
|
+
if (!op && !loose) throw new SheetFormulaSyntaxError(`Unexpected "${char}"`, i);
|
|
163
|
+
push({
|
|
164
|
+
kind: "op",
|
|
165
|
+
value: op ?? char,
|
|
166
|
+
at: i
|
|
167
|
+
}, (op ?? char).length);
|
|
168
|
+
}
|
|
169
|
+
tokens.push({
|
|
170
|
+
kind: "end",
|
|
171
|
+
at: text.length,
|
|
172
|
+
end: text.length
|
|
173
|
+
});
|
|
174
|
+
return tokens;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* The pieces of a formula, also one being typed and not finished, e.g. for
|
|
178
|
+
* coloring it: numbers, "text", names (of functions), references,
|
|
179
|
+
* operators and brackets, and error values. Spaces are left out.
|
|
180
|
+
*/
|
|
181
|
+
function formulaTokens(formula) {
|
|
182
|
+
const offset = formula.startsWith("=") ? 1 : 0;
|
|
183
|
+
const text = formula.slice(offset);
|
|
184
|
+
const out = [];
|
|
185
|
+
for (const token of tokenize(text, true)) {
|
|
186
|
+
if (token.kind === "end") break;
|
|
187
|
+
const start = token.at + offset;
|
|
188
|
+
const end = token.end + offset;
|
|
189
|
+
const piece = formula.slice(start, end);
|
|
190
|
+
if (token.kind === "ref") out.push({
|
|
191
|
+
kind: "ref",
|
|
192
|
+
start,
|
|
193
|
+
end,
|
|
194
|
+
text: piece,
|
|
195
|
+
ref: token.node
|
|
196
|
+
});
|
|
197
|
+
else out.push({
|
|
198
|
+
kind: token.kind,
|
|
199
|
+
start,
|
|
200
|
+
end,
|
|
201
|
+
text: piece
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
return out;
|
|
205
|
+
}
|
|
206
|
+
var BINARY = {
|
|
207
|
+
"=": [1, "="],
|
|
208
|
+
"<>": [1, "<>"],
|
|
209
|
+
"<": [1, "<"],
|
|
210
|
+
">": [1, ">"],
|
|
211
|
+
"<=": [1, "<="],
|
|
212
|
+
">=": [1, ">="],
|
|
213
|
+
"&": [2, "&"],
|
|
214
|
+
"+": [3, "+"],
|
|
215
|
+
"-": [3, "-"],
|
|
216
|
+
"*": [4, "*"],
|
|
217
|
+
"/": [4, "/"],
|
|
218
|
+
"^": [5, "^"]
|
|
219
|
+
};
|
|
220
|
+
/**
|
|
221
|
+
* Reads a formula, with or without its `=`, into a tree. Throws
|
|
222
|
+
* `SheetFormulaSyntaxError` for text that isn't one.
|
|
223
|
+
*/
|
|
224
|
+
function parseFormula(formula) {
|
|
225
|
+
const tokens = tokenize(formula.startsWith("=") ? formula.slice(1) : formula);
|
|
226
|
+
let pos = 0;
|
|
227
|
+
const peek = () => tokens[pos];
|
|
228
|
+
const isOp = (value) => {
|
|
229
|
+
const t = peek();
|
|
230
|
+
return t.kind === "op" && t.value === value;
|
|
231
|
+
};
|
|
232
|
+
const expect = (value) => {
|
|
233
|
+
if (!isOp(value)) throw new SheetFormulaSyntaxError(`Expected "${value}"`, peek().at);
|
|
234
|
+
pos++;
|
|
235
|
+
};
|
|
236
|
+
function expression(min) {
|
|
237
|
+
let left = prefix();
|
|
238
|
+
for (;;) {
|
|
239
|
+
const t = peek();
|
|
240
|
+
if (t.kind !== "op") break;
|
|
241
|
+
const binary = BINARY[t.value];
|
|
242
|
+
if (!binary || binary[0] < min) break;
|
|
243
|
+
pos++;
|
|
244
|
+
const right = expression(binary[0] + 1);
|
|
245
|
+
left = {
|
|
246
|
+
type: "binary",
|
|
247
|
+
op: binary[1],
|
|
248
|
+
left,
|
|
249
|
+
right
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
return left;
|
|
253
|
+
}
|
|
254
|
+
function prefix() {
|
|
255
|
+
const t = peek();
|
|
256
|
+
if (t.kind === "op" && (t.value === "-" || t.value === "+")) {
|
|
257
|
+
pos++;
|
|
258
|
+
return {
|
|
259
|
+
type: "unary",
|
|
260
|
+
op: t.value,
|
|
261
|
+
arg: prefix()
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
let node = primary();
|
|
265
|
+
while (isOp("%")) {
|
|
266
|
+
pos++;
|
|
267
|
+
node = {
|
|
268
|
+
type: "unary",
|
|
269
|
+
op: "%",
|
|
270
|
+
arg: node
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
return node;
|
|
274
|
+
}
|
|
275
|
+
function primary() {
|
|
276
|
+
const t = peek();
|
|
277
|
+
pos++;
|
|
278
|
+
switch (t.kind) {
|
|
279
|
+
case "number": return {
|
|
280
|
+
type: "number",
|
|
281
|
+
value: t.value
|
|
282
|
+
};
|
|
283
|
+
case "text": return {
|
|
284
|
+
type: "text",
|
|
285
|
+
value: t.value
|
|
286
|
+
};
|
|
287
|
+
case "error": return {
|
|
288
|
+
type: "error",
|
|
289
|
+
code: t.code
|
|
290
|
+
};
|
|
291
|
+
case "ref": return t.node;
|
|
292
|
+
case "name": {
|
|
293
|
+
if (isOp("(")) {
|
|
294
|
+
pos++;
|
|
295
|
+
const args = [];
|
|
296
|
+
if (isOp(")")) pos++;
|
|
297
|
+
else for (;;) {
|
|
298
|
+
const n = peek();
|
|
299
|
+
args.push(n.kind === "op" && (n.value === "," || n.value === ";" || n.value === ")") ? { type: "empty" } : expression(1));
|
|
300
|
+
if (isOp(",") || isOp(";")) pos++;
|
|
301
|
+
else {
|
|
302
|
+
expect(")");
|
|
303
|
+
break;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
return {
|
|
307
|
+
type: "call",
|
|
308
|
+
name: t.value.toUpperCase(),
|
|
309
|
+
args
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
const upper = t.value.toUpperCase();
|
|
313
|
+
if (upper === "TRUE" || upper === "FALSE") return {
|
|
314
|
+
type: "boolean",
|
|
315
|
+
value: upper === "TRUE"
|
|
316
|
+
};
|
|
317
|
+
return {
|
|
318
|
+
type: "error",
|
|
319
|
+
code: "#NAME?"
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
case "op":
|
|
323
|
+
if (t.value === "(") {
|
|
324
|
+
const inner = expression(1);
|
|
325
|
+
expect(")");
|
|
326
|
+
return inner;
|
|
327
|
+
}
|
|
328
|
+
throw new SheetFormulaSyntaxError(`Unexpected "${t.value}"`, t.at);
|
|
329
|
+
default: throw new SheetFormulaSyntaxError("The formula ends too soon", t.at);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
if (peek().kind === "end") throw new SheetFormulaSyntaxError("The formula is empty", 0);
|
|
333
|
+
const node = expression(1);
|
|
334
|
+
if (peek().kind !== "end") throw new SheetFormulaSyntaxError("Unexpected text", peek().at);
|
|
335
|
+
return node;
|
|
336
|
+
}
|
|
337
|
+
/** Every reference in a formula tree. */
|
|
338
|
+
function referencesOf(node, out = []) {
|
|
339
|
+
switch (node.type) {
|
|
340
|
+
case "ref":
|
|
341
|
+
out.push(node);
|
|
342
|
+
break;
|
|
343
|
+
case "call":
|
|
344
|
+
for (const arg of node.args) referencesOf(arg, out);
|
|
345
|
+
break;
|
|
346
|
+
case "unary":
|
|
347
|
+
referencesOf(node.arg, out);
|
|
348
|
+
break;
|
|
349
|
+
case "binary":
|
|
350
|
+
referencesOf(node.left, out);
|
|
351
|
+
referencesOf(node.right, out);
|
|
352
|
+
}
|
|
353
|
+
return out;
|
|
354
|
+
}
|
|
355
|
+
/** The functions a formula calls, in capitals. */
|
|
356
|
+
function functionsOf(node, out = /* @__PURE__ */ new Set()) {
|
|
357
|
+
if (node.type === "call") {
|
|
358
|
+
out.add(node.name);
|
|
359
|
+
for (const arg of node.args) functionsOf(arg, out);
|
|
360
|
+
} else if (node.type === "unary") functionsOf(node.arg, out);
|
|
361
|
+
else if (node.type === "binary") {
|
|
362
|
+
functionsOf(node.left, out);
|
|
363
|
+
functionsOf(node.right, out);
|
|
364
|
+
}
|
|
365
|
+
return out;
|
|
366
|
+
}
|
|
367
|
+
export { SheetFormulaSyntaxError, formulaTokens, functionsOf, parseFormula, referencesOf };
|
|
368
|
+
|
|
369
|
+
//# sourceMappingURL=parse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.js","names":[],"sources":["../../src/formula/parse.ts"],"sourcesContent":["import { splitSheet } from '../core/address'\nimport { ERROR_CODES, type SheetErrorCode } from './error'\n\n/*\n * Formulas as a tree. The text after `=` is read the usual way: numbers,\n * \"text\" (with \"\" for a quote), TRUE / FALSE, error values, references\n * (`A1`, `$A$1`, `A1:B9`, `B:D`, `2:3`, `'表 2'!A1`), function calls,\n * and operators by precedence from loosest to tightest: comparison\n * (= <> < > <= >=), & (joining text), + -, * /, ^, % after a value, and a\n * sign before it. A sign binds tighter than ^, so `-2^2` is 4.\n */\n\nexport type SheetFormulaNode =\n | { type: 'number'; value: number }\n | { type: 'text'; value: string }\n | { type: 'boolean'; value: boolean }\n | { type: 'error'; code: SheetErrorCode }\n /**\n * A reference, with its sheet as written (unquoted); whole columns run\n * from row 0 to `Infinity`, whole rows likewise. `cell` is a single cell.\n */\n | {\n type: 'ref'\n sheet?: string\n top: number\n left: number\n bottom: number\n right: number\n cell: boolean\n }\n /** A function call; `name` in capitals. */\n | { type: 'call'; name: string; args: SheetFormulaNode[] }\n | { type: 'unary'; op: '-' | '+' | '%'; arg: SheetFormulaNode }\n | { type: 'binary'; op: BinaryOp; left: SheetFormulaNode; right: SheetFormulaNode }\n /** An argument left out, as in `IF(A1,,1)`. */\n | { type: 'empty' }\n\nexport type BinaryOp = '+' | '-' | '*' | '/' | '^' | '&' | '=' | '<>' | '<' | '>' | '<=' | '>='\n\n/** Thrown for text that isn't a formula; it shows as `#ERROR!`. */\nexport class SheetFormulaSyntaxError extends Error {\n constructor(\n message: string,\n readonly at: number,\n ) {\n super(message)\n }\n}\n\ntype Token = (\n | { kind: 'number'; value: number }\n | { kind: 'text'; value: string }\n | { kind: 'error'; code: SheetErrorCode }\n | { kind: 'ref'; node: Extract<SheetFormulaNode, { type: 'ref' }> }\n | { kind: 'name'; value: string }\n | { kind: 'op'; value: string }\n | { kind: 'end' }\n) & { at: number; end: number }\n\nconst END = '(?![\\\\p{L}\\\\p{N}_(!.])'\nconst SHEET = \"(?:('(?:[^']|'')+'|[\\\\p{L}_][\\\\p{L}\\\\p{N}_.]*)!)?\"\nconst REF = new RegExp(\n SHEET +\n '(?:(\\\\$?[a-z]{1,3}\\\\$?[1-9]\\\\d{0,6})(?::(\\\\$?[a-z]{1,3}\\\\$?[1-9]\\\\d{0,6}))?' +\n '|(\\\\$?[a-z]{1,3}):(\\\\$?[a-z]{1,3})' +\n '|(\\\\$?[1-9]\\\\d{0,6}):(\\\\$?[1-9]\\\\d{0,6}))' +\n END,\n 'iuy',\n)\nconst SHEET_ERROR = new RegExp(`${SHEET}#REF!`, 'iuy')\nconst NUMBER = /(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:e[-+]?\\d+)?/iy\nconst NAME = /[\\p{L}_][\\p{L}\\p{N}_.]*/uy\nconst NAME_START = /[\\p{L}_]/u\nconst OPS = new Set(['+', '-', '*', '/', '^', '&', '=', '<', '>', '%', '(', ')', ',', ';'])\n\n/** One end of a reference, `$B$3`, `B` or `3`, read by hand: this runs for every reference. */\nfunction readEnd(text: string) {\n let i = text.charCodeAt(0) === 36 ? 1 : 0\n let col = -1\n for (let c = text.charCodeAt(i); (c | 32) >= 97 && (c | 32) <= 122; c = text.charCodeAt(++i))\n col = (col + 1) * 26 + (c | 32) - 97\n if (text.charCodeAt(i) === 36) i++\n const row = i < text.length ? Number(text.slice(i)) - 1 : -1\n return { col: col === -1 ? undefined : col, row: row === -1 ? undefined : row }\n}\n\nfunction readRef(match: RegExpExecArray): Extract<SheetFormulaNode, { type: 'ref' }> {\n const sheet = match[1] ? splitSheet(`${match[1]}!`).sheet : undefined\n const first = match[2] != null ? 0 : match[4] != null ? 2 : 4\n const a = readEnd(match[first + 2]!)\n const to = match[first + 3]\n const b = to != null ? readEnd(to) : a\n const top = Math.min(a.row ?? 0, b.row ?? 0)\n const left = Math.min(a.col ?? 0, b.col ?? 0)\n const bottom = a.row == null ? Infinity : Math.max(a.row, b.row!)\n const right = a.col == null ? Infinity : Math.max(a.col, b.col!)\n const node: Extract<SheetFormulaNode, { type: 'ref' }> = {\n type: 'ref',\n top,\n left,\n bottom,\n right,\n cell: first === 0 && to == null,\n }\n if (sheet != null) node.sheet = sheet\n return node\n}\n\n/** Splits a formula into tokens; `loose` reads what isn't a formula yet too, as while typing. */\n/** A token before its end is known; per kind, so each keeps its own fields. */\ntype WithoutEnd<T> = T extends unknown ? Omit<T, 'end'> : never\n\nfunction tokenize(text: string, loose = false): Token[] {\n const tokens: Token[] = []\n let i = 0\n const push = (token: WithoutEnd<Token>, length: number) => {\n tokens.push({ ...token, end: token.at + length } as Token)\n i = token.at + length\n }\n const at = (re: RegExp) => {\n re.lastIndex = i\n return re.exec(text)\n }\n while (i < text.length) {\n const char = text[i]!\n if (char === ' ' || /\\s/.test(char)) {\n i++\n continue\n }\n if (char === '\"') {\n let value = ''\n let j = i + 1\n for (; ; j++) {\n if (j >= text.length) {\n if (!loose) throw new SheetFormulaSyntaxError('Text without its closing quote', i)\n break\n }\n if (text[j] === '\"') {\n if (text[j + 1] === '\"') {\n value += '\"'\n j++\n } else break\n } else value += text[j]\n }\n push({ kind: 'text', value, at: i }, Math.min(j + 1, text.length) - i)\n continue\n }\n if (char === '#') {\n const code = ERROR_CODES.find(\n (c) => text.startsWith(c, i) || text.toUpperCase().startsWith(c, i),\n )\n if (code) {\n push({ kind: 'error', code, at: i }, code.length)\n continue\n }\n if (!loose) throw new SheetFormulaSyntaxError('Unknown error value', i)\n push({ kind: 'op', value: char, at: i }, 1)\n continue\n }\n // a reference starts with a letter, `$`, a quote, or a digit for rows (`2:3`)\n const ref = OPS.has(char) ? null : at(REF)\n if (ref) {\n push({ kind: 'ref', node: readRef(ref), at: i }, ref[0].length)\n continue\n }\n const refError = char === \"'\" || NAME_START.test(char) ? at(SHEET_ERROR) : null\n if (refError) {\n push({ kind: 'error', code: '#REF!', at: i }, refError[0].length)\n continue\n }\n const number = (char >= '0' && char <= '9') || char === '.' ? at(NUMBER) : null\n if (number) {\n push({ kind: 'number', value: Number(number[0]), at: i }, number[0].length)\n continue\n }\n const name = at(NAME)\n if (name) {\n push({ kind: 'name', value: name[0], at: i }, name[0].length)\n continue\n }\n const two = text.slice(i, i + 2)\n const op = two === '<>' || two === '<=' || two === '>=' ? two : OPS.has(char) ? char : undefined\n if (!op && !loose) throw new SheetFormulaSyntaxError(`Unexpected \"${char}\"`, i)\n push({ kind: 'op', value: op ?? char, at: i }, (op ?? char).length)\n }\n tokens.push({ kind: 'end', at: text.length, end: text.length })\n return tokens\n}\n\n/** A piece of a formula as written, with where it is in the text (counting the `=`). */\nexport type SheetFormulaToken =\n | { kind: 'number' | 'text' | 'name' | 'op' | 'error'; start: number; end: number; text: string }\n | {\n kind: 'ref'\n start: number\n end: number\n text: string\n ref: Extract<SheetFormulaNode, { type: 'ref' }>\n }\n\n/**\n * The pieces of a formula, also one being typed and not finished, e.g. for\n * coloring it: numbers, \"text\", names (of functions), references,\n * operators and brackets, and error values. Spaces are left out.\n */\nexport function formulaTokens(formula: string): SheetFormulaToken[] {\n const offset = formula.startsWith('=') ? 1 : 0\n const text = formula.slice(offset)\n const out: SheetFormulaToken[] = []\n for (const token of tokenize(text, true)) {\n if (token.kind === 'end') break\n const start = token.at + offset\n const end = token.end + offset\n const piece = formula.slice(start, end)\n if (token.kind === 'ref') out.push({ kind: 'ref', start, end, text: piece, ref: token.node })\n else out.push({ kind: token.kind, start, end, text: piece })\n }\n return out\n}\n\nconst BINARY: Record<string, [number, BinaryOp]> = {\n '=': [1, '='],\n '<>': [1, '<>'],\n '<': [1, '<'],\n '>': [1, '>'],\n '<=': [1, '<='],\n '>=': [1, '>='],\n '&': [2, '&'],\n '+': [3, '+'],\n '-': [3, '-'],\n '*': [4, '*'],\n '/': [4, '/'],\n '^': [5, '^'],\n}\n\n/**\n * Reads a formula, with or without its `=`, into a tree. Throws\n * `SheetFormulaSyntaxError` for text that isn't one.\n */\nexport function parseFormula(formula: string): SheetFormulaNode {\n const text = formula.startsWith('=') ? formula.slice(1) : formula\n const tokens = tokenize(text)\n let pos = 0\n const peek = () => tokens[pos]!\n const isOp = (value: string) => {\n const t = peek()\n return t.kind === 'op' && t.value === value\n }\n const expect = (value: string) => {\n if (!isOp(value)) throw new SheetFormulaSyntaxError(`Expected \"${value}\"`, peek().at)\n pos++\n }\n\n function expression(min: number): SheetFormulaNode {\n let left = prefix()\n for (;;) {\n const t = peek()\n if (t.kind !== 'op') break\n const binary = BINARY[t.value]\n if (!binary || binary[0] < min) break\n pos++\n // ^ is left to right too, as spreadsheet programs read `2^3^2`\n const right = expression(binary[0] + 1)\n left = { type: 'binary', op: binary[1], left, right }\n }\n return left\n }\n\n function prefix(): SheetFormulaNode {\n const t = peek()\n if (t.kind === 'op' && (t.value === '-' || t.value === '+')) {\n pos++\n return { type: 'unary', op: t.value, arg: prefix() }\n }\n let node = primary()\n while (isOp('%')) {\n pos++\n node = { type: 'unary', op: '%', arg: node }\n }\n return node\n }\n\n function primary(): SheetFormulaNode {\n const t = peek()\n pos++\n switch (t.kind) {\n case 'number':\n return { type: 'number', value: t.value }\n case 'text':\n return { type: 'text', value: t.value }\n case 'error':\n return { type: 'error', code: t.code }\n case 'ref':\n return t.node\n case 'name': {\n if (isOp('(')) {\n pos++\n const args: SheetFormulaNode[] = []\n if (isOp(')')) pos++\n else\n for (;;) {\n const n = peek()\n args.push(\n n.kind === 'op' && (n.value === ',' || n.value === ';' || n.value === ')')\n ? { type: 'empty' }\n : expression(1),\n )\n if (isOp(',') || isOp(';')) pos++\n else {\n expect(')')\n break\n }\n }\n return { type: 'call', name: t.value.toUpperCase(), args }\n }\n const upper = t.value.toUpperCase()\n if (upper === 'TRUE' || upper === 'FALSE')\n return { type: 'boolean', value: upper === 'TRUE' }\n return { type: 'error', code: '#NAME?' }\n }\n case 'op':\n if (t.value === '(') {\n const inner = expression(1)\n expect(')')\n return inner\n }\n throw new SheetFormulaSyntaxError(`Unexpected \"${t.value}\"`, t.at)\n default:\n throw new SheetFormulaSyntaxError('The formula ends too soon', t.at)\n }\n }\n\n if (peek().kind === 'end') throw new SheetFormulaSyntaxError('The formula is empty', 0)\n const node = expression(1)\n if (peek().kind !== 'end') throw new SheetFormulaSyntaxError('Unexpected text', peek().at)\n return node\n}\n\n/** Every reference in a formula tree. */\nexport function referencesOf(\n node: SheetFormulaNode,\n out: Extract<SheetFormulaNode, { type: 'ref' }>[] = [],\n) {\n switch (node.type) {\n case 'ref':\n out.push(node)\n break\n case 'call':\n for (const arg of node.args) referencesOf(arg, out)\n break\n case 'unary':\n referencesOf(node.arg, out)\n break\n case 'binary':\n referencesOf(node.left, out)\n referencesOf(node.right, out)\n break\n }\n return out\n}\n\n/** The functions a formula calls, in capitals. */\nexport function functionsOf(node: SheetFormulaNode, out = new Set<string>()) {\n if (node.type === 'call') {\n out.add(node.name)\n for (const arg of node.args) functionsOf(arg, out)\n } else if (node.type === 'unary') functionsOf(node.arg, out)\n else if (node.type === 'binary') {\n functionsOf(node.left, out)\n functionsOf(node.right, out)\n }\n return out\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { generalNumber, parseInput } from "../core/format.js";
|
|
2
|
+
import { VALUE, isSheetError } from "./error.js";
|
|
3
|
+
// src/formula/values.ts
|
|
4
|
+
var isRange = (arg) => typeof arg === "object" && arg !== null && arg.kind === "range";
|
|
5
|
+
var DATE = /^(\d{4})-(\d{2})-(\d{2})(?:[ T](\d{2}):(\d{2})(?::(\d{2}))?)?$/;
|
|
6
|
+
var TIME = /^(\d{2}):(\d{2})(?::(\d{2}))?$/;
|
|
7
|
+
var EPOCH = Date.UTC(1899, 11, 30);
|
|
8
|
+
var DAY = 864e5;
|
|
9
|
+
/** Whether a value is a date (or date and time) as cells write them. */
|
|
10
|
+
var isDateText = (value) => typeof value === "string" && DATE.test(value);
|
|
11
|
+
/** Whether a value is a time of day as cells write it, such as `09:30`. */
|
|
12
|
+
var isTimeText = (value) => typeof value === "string" && TIME.test(value);
|
|
13
|
+
/** A date or time written in a cell as a day number (a time as part of a day); `null` when it isn't one. */
|
|
14
|
+
function serialOf(text) {
|
|
15
|
+
const date = DATE.exec(text);
|
|
16
|
+
if (date) {
|
|
17
|
+
const [, y, m, d, h = "0", min = "0", s = "0"] = date;
|
|
18
|
+
return (Date.UTC(+y, +m - 1, +d, +h, +min, +s) - EPOCH) / DAY;
|
|
19
|
+
}
|
|
20
|
+
const time = TIME.exec(text);
|
|
21
|
+
if (time) return (+time[1] * 3600 + +time[2] * 60 + +(time[3] ?? 0)) / 86400;
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
var pad = (n) => String(n).padStart(2, "0");
|
|
25
|
+
/** A day number as a date, with its time when it has a part of a day. */
|
|
26
|
+
function dateText(serial) {
|
|
27
|
+
const ms = Math.round((serial * DAY + EPOCH) / 1e3) * 1e3;
|
|
28
|
+
const d = new Date(ms);
|
|
29
|
+
const day = `${d.getUTCFullYear()}-${pad(d.getUTCMonth() + 1)}-${pad(d.getUTCDate())}`;
|
|
30
|
+
if (!(d.getUTCHours() * 3600 + d.getUTCMinutes() * 60 + d.getUTCSeconds())) return day;
|
|
31
|
+
const time = `${pad(d.getUTCHours())}:${pad(d.getUTCMinutes())}`;
|
|
32
|
+
return d.getUTCSeconds() ? `${day} ${time}:${pad(d.getUTCSeconds())}` : `${day} ${time}`;
|
|
33
|
+
}
|
|
34
|
+
/** A part of a day as `hh:mm`, or `hh:mm:ss` with seconds; a whole day and more wraps round. */
|
|
35
|
+
function timeText(fraction) {
|
|
36
|
+
const seconds = Math.round((fraction % 1 + 1) % 1 * 86400) % 86400;
|
|
37
|
+
const h = Math.floor(seconds / 3600);
|
|
38
|
+
const m = Math.floor(seconds % 3600 / 60);
|
|
39
|
+
const sec = seconds % 60;
|
|
40
|
+
return sec ? `${pad(h)}:${pad(m)}:${pad(sec)}` : `${pad(h)}:${pad(m)}`;
|
|
41
|
+
}
|
|
42
|
+
/** A part of a day as a time; a whole day or more, or below nothing, stays a number of days. */
|
|
43
|
+
var timeOrDays = (days) => days >= 0 && days < 1 ? timeText(days) : days;
|
|
44
|
+
/** The parts of a date, from a date or a day number; `null` when it is neither. */
|
|
45
|
+
function dateParts(value) {
|
|
46
|
+
const serial = typeof value === "number" ? value : typeof value === "string" ? serialOf(value) : null;
|
|
47
|
+
if (serial == null) return null;
|
|
48
|
+
const d = new Date(Math.floor(serial) * DAY + EPOCH);
|
|
49
|
+
return {
|
|
50
|
+
year: d.getUTCFullYear(),
|
|
51
|
+
month: d.getUTCMonth() + 1,
|
|
52
|
+
day: d.getUTCDate(),
|
|
53
|
+
serial
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* A value as a number: `TRUE` is 1, an empty cell 0, text that reads as a
|
|
58
|
+
* number (`12`, `1,280`, `12%`) or a date its number; other text is
|
|
59
|
+
* `#VALUE!`. Errors pass through.
|
|
60
|
+
*/
|
|
61
|
+
function toNumber(value) {
|
|
62
|
+
if (typeof value === "number") return value;
|
|
63
|
+
if (value == null) return 0;
|
|
64
|
+
if (typeof value === "boolean") return value ? 1 : 0;
|
|
65
|
+
if (isSheetError(value)) return value;
|
|
66
|
+
const trimmed = value.trim();
|
|
67
|
+
if (trimmed === "") return VALUE;
|
|
68
|
+
const serial = serialOf(trimmed);
|
|
69
|
+
if (serial != null) return serial;
|
|
70
|
+
const read = parseInput(trimmed).value;
|
|
71
|
+
return typeof read === "number" ? read : VALUE;
|
|
72
|
+
}
|
|
73
|
+
/** A value as text: numbers as a cell shows them without a format, `TRUE` / `FALSE`. */
|
|
74
|
+
function toText(value) {
|
|
75
|
+
if (value == null) return "";
|
|
76
|
+
if (typeof value === "string") return value;
|
|
77
|
+
if (typeof value === "number") return generalNumber(value);
|
|
78
|
+
if (typeof value === "boolean") return value ? "TRUE" : "FALSE";
|
|
79
|
+
return value;
|
|
80
|
+
}
|
|
81
|
+
/** A value as `TRUE` / `FALSE`: numbers are true unless 0; text `TRUE` / `FALSE` reads as such. */
|
|
82
|
+
function toBoolean(value) {
|
|
83
|
+
if (typeof value === "boolean") return value;
|
|
84
|
+
if (value == null) return false;
|
|
85
|
+
if (typeof value === "number") return value !== 0;
|
|
86
|
+
if (isSheetError(value)) return value;
|
|
87
|
+
const upper = value.trim().toUpperCase();
|
|
88
|
+
if (upper === "TRUE") return true;
|
|
89
|
+
if (upper === "FALSE") return false;
|
|
90
|
+
return VALUE;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Compares two values the way formulas do: numbers by size, text by
|
|
94
|
+
* letters ignoring case, `FALSE` before `TRUE`; numbers come before text,
|
|
95
|
+
* and text before `TRUE` / `FALSE`. An empty cell is 0, or "" next to text.
|
|
96
|
+
*/
|
|
97
|
+
function compareValues(a, b) {
|
|
98
|
+
if (a == null) a = typeof b === "string" ? "" : typeof b === "boolean" ? false : 0;
|
|
99
|
+
if (b == null) b = typeof a === "string" ? "" : typeof a === "boolean" ? false : 0;
|
|
100
|
+
const rank = (v) => typeof v === "number" ? 0 : typeof v === "string" ? 1 : 2;
|
|
101
|
+
const ra = rank(a);
|
|
102
|
+
const rb = rank(b);
|
|
103
|
+
if (ra !== rb) return ra - rb;
|
|
104
|
+
if (typeof a === "number") return a - b;
|
|
105
|
+
if (typeof a === "string") {
|
|
106
|
+
const x = a.toLowerCase();
|
|
107
|
+
const y = b.toLowerCase();
|
|
108
|
+
return x < y ? -1 : x > y ? 1 : 0;
|
|
109
|
+
}
|
|
110
|
+
return Number(a) - Number(b);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* A cell's value as it shows: for a formula, its result from `result`
|
|
114
|
+
* (an error as its code, such as `#N/A`), when given.
|
|
115
|
+
*/
|
|
116
|
+
function shownValue(value, result, row, col) {
|
|
117
|
+
if (!result || typeof value !== "string" || !value.startsWith("=")) return value;
|
|
118
|
+
const out = result(row, col);
|
|
119
|
+
return isSheetError(out) ? out.code : out;
|
|
120
|
+
}
|
|
121
|
+
export { compareValues, dateParts, dateText, isDateText, isRange, isTimeText, serialOf, shownValue, timeOrDays, timeText, toBoolean, toNumber, toText };
|
|
122
|
+
|
|
123
|
+
//# sourceMappingURL=values.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"values.js","names":[],"sources":["../../src/formula/values.ts"],"sourcesContent":["import { generalNumber, parseInput } from '../core/format'\nimport type { SheetValue } from '../core/model'\nimport { isSheetError, VALUE, type SheetError } from './error'\n\n/**\n * What a formula gives: a number, text, `TRUE` / `FALSE`, nothing (an\n * empty cell), or an error. Dates are text written `2026-03-05` (or\n * `2026-03-05 09:30`), as cells hold them.\n */\nexport type SheetResult = number | string | boolean | null | SheetError\n\n/** A range a function is given: its cells, as their values or their formulas' results. */\nexport interface SheetRangeArg {\n readonly kind: 'range'\n /** Its size, kept inside the sheet: `A:A` is as tall as the sheet. */\n readonly rows: number\n readonly cols: number\n /** The cell at a row and column counted from the range's top left, from 0. */\n at(row: number, col: number): SheetResult\n /**\n * The cells with something in them, row by row, with where they are.\n * Empty cells are left out, so a whole column costs only its data.\n */\n entries(): Iterable<[row: number, col: number, value: SheetResult]>\n}\n\n/** What a function is given for each argument: a value, or a range for a reference to more than one cell. */\nexport type SheetArg = SheetResult | SheetRangeArg\n\nexport const isRange = (arg: unknown): arg is SheetRangeArg =>\n typeof arg === 'object' && arg !== null && (arg as SheetRangeArg).kind === 'range'\n\n// Dates as day numbers, counted the usual way from 1899-12-30, so date\n// arithmetic and functions agree with other spreadsheet programs.\n\nconst DATE = /^(\\d{4})-(\\d{2})-(\\d{2})(?:[ T](\\d{2}):(\\d{2})(?::(\\d{2}))?)?$/\nconst TIME = /^(\\d{2}):(\\d{2})(?::(\\d{2}))?$/\nconst EPOCH = Date.UTC(1899, 11, 30)\nconst DAY = 86_400_000\n\n/** Whether a value is a date (or date and time) as cells write them. */\nexport const isDateText = (value: unknown): value is string =>\n typeof value === 'string' && DATE.test(value)\n\n/** Whether a value is a time of day as cells write it, such as `09:30`. */\nexport const isTimeText = (value: unknown): value is string =>\n typeof value === 'string' && TIME.test(value)\n\n/** A date or time written in a cell as a day number (a time as part of a day); `null` when it isn't one. */\nexport function serialOf(text: string): number | null {\n const date = DATE.exec(text)\n if (date) {\n const [, y, m, d, h = '0', min = '0', s = '0'] = date\n const ms = Date.UTC(+y!, +m! - 1, +d!, +h, +min, +s)\n return (ms - EPOCH) / DAY\n }\n const time = TIME.exec(text)\n if (time) return (+time[1]! * 3600 + +time[2]! * 60 + +(time[3] ?? 0)) / 86_400\n return null\n}\n\nconst pad = (n: number) => String(n).padStart(2, '0')\n\n/** A day number as a date, with its time when it has a part of a day. */\nexport function dateText(serial: number) {\n const ms = Math.round((serial * DAY + EPOCH) / 1000) * 1000\n const d = new Date(ms)\n const day = `${d.getUTCFullYear()}-${pad(d.getUTCMonth() + 1)}-${pad(d.getUTCDate())}`\n const seconds = d.getUTCHours() * 3600 + d.getUTCMinutes() * 60 + d.getUTCSeconds()\n if (!seconds) return day\n const time = `${pad(d.getUTCHours())}:${pad(d.getUTCMinutes())}`\n return d.getUTCSeconds() ? `${day} ${time}:${pad(d.getUTCSeconds())}` : `${day} ${time}`\n}\n\n/** A part of a day as `hh:mm`, or `hh:mm:ss` with seconds; a whole day and more wraps round. */\nexport function timeText(fraction: number) {\n const seconds = Math.round((((fraction % 1) + 1) % 1) * 86_400) % 86_400\n const h = Math.floor(seconds / 3600)\n const m = Math.floor((seconds % 3600) / 60)\n const sec = seconds % 60\n return sec ? `${pad(h)}:${pad(m)}:${pad(sec)}` : `${pad(h)}:${pad(m)}`\n}\n\n/** A part of a day as a time; a whole day or more, or below nothing, stays a number of days. */\nexport const timeOrDays = (days: number): number | string =>\n days >= 0 && days < 1 ? timeText(days) : days\n\n/** The parts of a date, from a date or a day number; `null` when it is neither. */\nexport function dateParts(value: SheetResult) {\n const serial =\n typeof value === 'number' ? value : typeof value === 'string' ? serialOf(value) : null\n if (serial == null) return null\n const d = new Date(Math.floor(serial) * DAY + EPOCH)\n return { year: d.getUTCFullYear(), month: d.getUTCMonth() + 1, day: d.getUTCDate(), serial }\n}\n\n/**\n * A value as a number: `TRUE` is 1, an empty cell 0, text that reads as a\n * number (`12`, `1,280`, `12%`) or a date its number; other text is\n * `#VALUE!`. Errors pass through.\n */\nexport function toNumber(value: SheetResult): number | SheetError {\n if (typeof value === 'number') return value\n if (value == null) return 0\n if (typeof value === 'boolean') return value ? 1 : 0\n if (isSheetError(value)) return value\n const trimmed = value.trim()\n if (trimmed === '') return VALUE\n const serial = serialOf(trimmed)\n if (serial != null) return serial\n const read = parseInput(trimmed).value\n return typeof read === 'number' ? read : VALUE\n}\n\n/** A value as text: numbers as a cell shows them without a format, `TRUE` / `FALSE`. */\nexport function toText(value: SheetResult): string | SheetError {\n if (value == null) return ''\n if (typeof value === 'string') return value\n if (typeof value === 'number') return generalNumber(value)\n if (typeof value === 'boolean') return value ? 'TRUE' : 'FALSE'\n return value\n}\n\n/** A value as `TRUE` / `FALSE`: numbers are true unless 0; text `TRUE` / `FALSE` reads as such. */\nexport function toBoolean(value: SheetResult): boolean | SheetError {\n if (typeof value === 'boolean') return value\n if (value == null) return false\n if (typeof value === 'number') return value !== 0\n if (isSheetError(value)) return value\n const upper = value.trim().toUpperCase()\n if (upper === 'TRUE') return true\n if (upper === 'FALSE') return false\n return VALUE\n}\n\n/**\n * Compares two values the way formulas do: numbers by size, text by\n * letters ignoring case, `FALSE` before `TRUE`; numbers come before text,\n * and text before `TRUE` / `FALSE`. An empty cell is 0, or \"\" next to text.\n */\nexport function compareValues(a: SheetResult, b: SheetResult): number {\n if (a == null) a = typeof b === 'string' ? '' : typeof b === 'boolean' ? false : 0\n if (b == null) b = typeof a === 'string' ? '' : typeof a === 'boolean' ? false : 0\n const rank = (v: SheetResult) => (typeof v === 'number' ? 0 : typeof v === 'string' ? 1 : 2)\n const ra = rank(a)\n const rb = rank(b)\n if (ra !== rb) return ra - rb\n if (typeof a === 'number') return a - (b as number)\n if (typeof a === 'string') {\n const x = a.toLowerCase()\n const y = (b as string).toLowerCase()\n return x < y ? -1 : x > y ? 1 : 0\n }\n return Number(a) - Number(b)\n}\n\n/**\n * A cell's value as it shows: for a formula, its result from `result`\n * (an error as its code, such as `#N/A`), when given.\n */\nexport function shownValue(\n value: SheetValue,\n result: ((row: number, col: number) => SheetResult) | undefined,\n row: number,\n col: number,\n): SheetValue {\n if (!result || typeof value !== 'string' || !value.startsWith('=')) return value\n const out = result(row, col)\n return isSheetError(out) ? out.code : out\n}\n"],"mappings":"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"}
|
package/dist/formulas.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { SheetFormulaEngine } from "./formula/engine.js";
|
|
2
|
+
import { shallowRef, toRaw, toValue, triggerRef, watch } from "vue";
|
|
3
|
+
// src/formulas.ts
|
|
4
|
+
/**
|
|
5
|
+
* Works out a workbook's formulas outside the grid, such as for totals
|
|
6
|
+
* shown above it. `book` is the workbook bound to the grid's `v-model`.
|
|
7
|
+
*/
|
|
8
|
+
function useSheetFormulas(book, options) {
|
|
9
|
+
const read = () => toRaw(toValue(book));
|
|
10
|
+
const engine = shallowRef(new SheetFormulaEngine(read(), options));
|
|
11
|
+
watch(read, (doc) => {
|
|
12
|
+
if (doc === engine.value.doc) return;
|
|
13
|
+
engine.value.load(doc);
|
|
14
|
+
triggerRef(engine);
|
|
15
|
+
});
|
|
16
|
+
return {
|
|
17
|
+
result: ((sheet, at, col) => typeof at === "number" ? engine.value.result(sheet, at, col) : engine.value.result(sheet, at)),
|
|
18
|
+
evaluate: (formula, sheet) => engine.value.evaluate(formula, sheet),
|
|
19
|
+
update: (change) => {
|
|
20
|
+
engine.value.update(change);
|
|
21
|
+
triggerRef(engine);
|
|
22
|
+
},
|
|
23
|
+
get engine() {
|
|
24
|
+
return engine.value;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export { useSheetFormulas };
|
|
29
|
+
|
|
30
|
+
//# sourceMappingURL=formulas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formulas.js","names":[],"sources":["../src/formulas.ts"],"sourcesContent":["import { shallowRef, toRaw, toValue, triggerRef, watch, type MaybeRefOrGetter } from 'vue'\nimport type { SheetCellTarget } from './core/address'\nimport type { SheetWorkbook } from './core/model'\nimport {\n SheetFormulaEngine,\n type SheetFormulaChange,\n type SheetFormulaEngineOptions,\n} from './formula/engine'\nimport type { SheetResult } from './formula/values'\n\n/** The results of a workbook's formulas, read reactively. */\nexport interface SheetFormulas {\n /**\n * A cell's result, as `SheetFormulaEngine.result` gives it. Read in a\n * `computed` or a template, it is read again when the workbook changes.\n */\n result: {\n (sheet: string | number, cell: SheetCellTarget): SheetResult\n (sheet: string | number, row: number, col: number): SheetResult\n }\n /** Works out a formula without writing it into a cell, reactively too. */\n evaluate: (formula: string, sheet?: string | number) => SheetResult\n /**\n * Catches up with a change of the grid: pass it the `transaction` event\n * (`@transaction=\"formulas.update\"`), and only the formulas the change\n * reaches are worked out again. Without it, every change of the workbook\n * works all of them out again.\n */\n update: (change: SheetFormulaChange) => void\n /** The engine underneath. */\n readonly engine: SheetFormulaEngine\n}\n\n/**\n * Works out a workbook's formulas outside the grid, such as for totals\n * shown above it. `book` is the workbook bound to the grid's `v-model`.\n */\nexport function useSheetFormulas(\n book: MaybeRefOrGetter<SheetWorkbook>,\n options?: SheetFormulaEngineOptions,\n): SheetFormulas {\n // the plain workbook: the grid's transactions start from it, not from a proxy\n const read = () => toRaw(toValue(book))\n const engine = shallowRef(new SheetFormulaEngine(read(), options))\n // a workbook the engine doesn't have yet (replaced from outside, or\n // changed without `update`): start over with it\n watch(read, (doc) => {\n if (doc === engine.value.doc) return\n engine.value.load(doc)\n triggerRef(engine)\n })\n return {\n result: ((sheet: string | number, at: SheetCellTarget | number, col?: number) =>\n typeof at === 'number'\n ? engine.value.result(sheet, at, col!)\n : engine.value.result(sheet, at)) as SheetFormulas['result'],\n evaluate: (formula, sheet) => engine.value.evaluate(formula, sheet),\n update: (change) => {\n engine.value.update(change)\n triggerRef(engine)\n },\n get engine() {\n return engine.value\n },\n }\n}\n"],"mappings":";;;;;;;AAqCA,SAAgB,iBACd,MACA,SACe;CAEf,MAAM,aAAa,MAAM,QAAQ,IAAI,CAAC;CACtC,MAAM,SAAS,WAAW,IAAI,mBAAmB,KAAK,GAAG,OAAO,CAAC;CAGjE,MAAM,OAAO,QAAQ;EACnB,IAAI,QAAQ,OAAO,MAAM,KAAK;EAC9B,OAAO,MAAM,KAAK,GAAG;EACrB,WAAW,MAAM;CACnB,CAAC;CACD,OAAO;EACL,UAAU,OAAwB,IAA8B,QAC9D,OAAO,OAAO,WACV,OAAO,MAAM,OAAO,OAAO,IAAI,GAAI,IACnC,OAAO,MAAM,OAAO,OAAO,EAAE;EACnC,WAAW,SAAS,UAAU,OAAO,MAAM,SAAS,SAAS,KAAK;EAClE,SAAS,WAAW;GAClB,OAAO,MAAM,OAAO,MAAM;GAC1B,WAAW,MAAM;EACnB;EACA,IAAI,SAAS;GACX,OAAO,OAAO;EAChB;CACF;AACF"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { boundsOf, columnIndex, columnName, dropReferences, formatCell, formatRange, moveReferences, parseCell, parseRange, quoteSheet, renameReferences, renameReferencesAll, shiftFormula, splitSheet } from "./core/address.js";
|
|
2
|
+
import { changeDecimals, formatValue, parseInput } from "./core/format.js";
|
|
3
|
+
import { cellOf, valueOf } from "./core/model.js";
|
|
4
|
+
import { SheetError, isSheetError } from "./formula/error.js";
|
|
5
|
+
import { compareValues, dateText, serialOf, toBoolean, toNumber, toText } from "./formula/values.js";
|
|
6
|
+
import { detectDelimiter, parseCSV, readCSV, sheetToCSV } from "./core/csv.js";
|
|
7
|
+
import { linkTarget } from "./core/link.js";
|
|
8
|
+
import { formatClip, parseClip, parseTSV } from "./core/clipboard.js";
|
|
9
|
+
import { continueValues, fillContinues } from "./core/fill.js";
|
|
10
|
+
import { defineSheetExtension, resolveSheetExtensions } from "./core/extension.js";
|
|
11
|
+
import { defineSheetCellType, optionOf, resolveCellType } from "./core/cell-type.js";
|
|
12
|
+
import { checkWorkbook, emptyWorkbook, migrateWorkbook } from "./core/document.js";
|
|
13
|
+
import { defineSheetCommand } from "./core/commands.js";
|
|
14
|
+
import { compareForSort, meetsRule, sortRows, textCollator } from "./core/data.js";
|
|
15
|
+
import { SheetTransaction, applySheetSteps, compactSheetSteps, sheetKey } from "./core/transaction.js";
|
|
16
|
+
import { keepCommentAnchors, sheetCommentAnchors } from "./core/comments.js";
|
|
17
|
+
import { diffWorkbooks, restoreWorkbook } from "./core/versions.js";
|
|
18
|
+
import { criteriaOf, defineSheetFunction, numbersOf, scalarOf } from "./formula/functions.js";
|
|
19
|
+
import { lightThemeColor, plainStyle } from "./core/paint.js";
|
|
20
|
+
import { sheetLocales, sheetMessagesFor } from "./locale.js";
|
|
21
|
+
import { isSelected, selectCell } from "./core/selection.js";
|
|
22
|
+
import { checkProtection, isLocked, protectionOf } from "./core/protect.js";
|
|
23
|
+
import { sheetContextKey, useSheet } from "./context.js";
|
|
24
|
+
import { useSheetMessages } from "./use-messages.js";
|
|
25
|
+
import { SheetFileError, createFileSource, csvExporter, csvImporter, defineSheetExporter, defineSheetImporter, exportWorkbook, readWorkbook } from "./core/file.js";
|
|
26
|
+
import sheet_default from "./sheet.js";
|
|
27
|
+
import sheet_tabs_default from "./components/sheet-tabs.js";
|
|
28
|
+
import sheet_toolbar_default from "./components/sheet-toolbar.js";
|
|
29
|
+
import sheet_formula_bar_default from "./components/sheet-formula-bar.js";
|
|
30
|
+
import { useSheetFormulas } from "./formulas.js";
|
|
31
|
+
import { withInstall } from "dou-ui";
|
|
32
|
+
// src/index.ts
|
|
33
|
+
var DouSheet = withInstall(sheet_default);
|
|
34
|
+
var DouSheetTabs = withInstall(sheet_tabs_default);
|
|
35
|
+
var DouSheetToolbar = withInstall(sheet_toolbar_default);
|
|
36
|
+
var DouSheetFormulaBar = withInstall(sheet_formula_bar_default);
|
|
37
|
+
export { DouSheet, DouSheet as default, DouSheetFormulaBar, DouSheetTabs, DouSheetToolbar, SheetError, SheetFileError, SheetTransaction, applySheetSteps, boundsOf, cellOf, changeDecimals, checkProtection, checkWorkbook, columnIndex, columnName, compactSheetSteps, compareForSort, compareValues, continueValues, createFileSource, criteriaOf, csvExporter, csvImporter, dateText, defineSheetCellType, defineSheetCommand, defineSheetExporter, defineSheetExtension, defineSheetFunction, defineSheetImporter, detectDelimiter, diffWorkbooks, dropReferences, emptyWorkbook, exportWorkbook, fillContinues, formatCell, formatClip, formatRange, formatValue, isLocked, isSelected, isSheetError, keepCommentAnchors, lightThemeColor, linkTarget, meetsRule, migrateWorkbook, moveReferences, numbersOf, optionOf, parseCSV, parseCell, parseClip, parseInput, parseRange, parseTSV, plainStyle, protectionOf, quoteSheet, readCSV, readWorkbook, renameReferences, renameReferencesAll, resolveCellType, resolveSheetExtensions, restoreWorkbook, scalarOf, selectCell, serialOf, sheetCommentAnchors, sheetContextKey, sheetKey, sheetLocales, sheetMessagesFor, sheetToCSV, shiftFormula, sortRows, splitSheet, textCollator, toBoolean, toNumber, toText, useSheet, useSheetFormulas, useSheetMessages, valueOf };
|
|
38
|
+
|
|
39
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["Sheet","SheetTabs","SheetToolbar","SheetFormulaBar"],"sources":["../src/index.ts"],"sourcesContent":["import { withInstall } from 'dou-ui'\nimport Sheet from './sheet.vue'\nimport SheetTabs from './components/sheet-tabs.vue'\nimport SheetToolbar from './components/sheet-toolbar.vue'\nimport SheetFormulaBar from './components/sheet-formula-bar.vue'\n\nexport const DouSheet = withInstall(Sheet)\nexport const DouSheetTabs = withInstall(SheetTabs)\nexport const DouSheetToolbar = withInstall(SheetToolbar)\nexport const DouSheetFormulaBar = withInstall(SheetFormulaBar)\nexport default DouSheet\n\nexport { useSheet, sheetContextKey } from './context'\nexport { useSheetFormulas } from './formulas'\nexport type { SheetFormulas } from './formulas'\nexport type {\n SheetContext,\n SheetEditInputOptions,\n SheetEditorContext,\n SheetRangeRect,\n SheetRect,\n} from './context'\nexport { defineSheetExtension, resolveSheetExtensions } from './core/extension'\nexport type {\n ResolvedSheetExtensions,\n SheetExtension,\n SheetExtensionContext,\n SheetCommentsProvider,\n SheetHistoryHandler,\n SheetKeyHandler,\n SheetUpdate,\n} from './core/extension'\nexport { keepCommentAnchors, sheetCommentAnchors } from './core/comments'\nexport { diffWorkbooks, restoreWorkbook } from './core/versions'\nexport type { SheetCellChange, WorkbookDiff } from './core/versions'\nexport type { SheetCommentAnchor } from './core/comments'\nexport { defineSheetCommand } from './core/commands'\nexport {\n createFileSource,\n csvExporter,\n csvImporter,\n defineSheetExporter,\n defineSheetImporter,\n SheetFileError,\n exportWorkbook,\n readWorkbook,\n} from './core/file'\nexport type {\n SheetCSVExportOptions,\n SheetExporter,\n SheetExporterInfo,\n SheetExportScope,\n SheetExportWorkbookOptions,\n SheetFileSheet,\n SheetFileSource,\n SheetFileSourceOptions,\n SheetFileView,\n SheetImportContext,\n SheetImporter,\n SheetImporterInfo,\n SheetImportResult,\n SheetImportWarning,\n SheetReadWorkbookOptions,\n} from './core/file'\nexport type { SheetCommand, SheetCommandInfo, SheetCommands, SheetLabel } from './core/commands'\nexport { defineSheetCellType, optionOf, resolveCellType } from './core/cell-type'\nexport type {\n SheetCellPanelExpose,\n SheetCellPanelProps,\n SheetCellRenderProps,\n SheetCellType,\n SheetDrawContext,\n SheetDrawRect,\n SheetDrawTextOptions,\n SheetResolvedType,\n} from './core/cell-type'\nexport type {\n SheetEmits,\n SheetFormatOption,\n SheetSlots,\n SheetToolbarProps,\n SheetToolbarSlots,\n SheetToolbarTool,\n SheetToolbarItem,\n SheetExpose,\n SheetExportFileOptions,\n SheetExporterOptions,\n SheetExporterOptionsOf,\n SheetFileErrorEvent,\n SheetSaveFileOptions,\n SheetImportEvent,\n SheetImportMode,\n SheetImportFileOptions,\n SheetInvalidCell,\n SheetExportOptions,\n SheetImageOptions,\n SheetPrintOptions,\n SheetMenuContext,\n SheetMenuItem,\n SheetLinkOpenEvent,\n SheetPasteEvent,\n SheetProps,\n} from './types'\nexport {\n boundsOf,\n columnIndex,\n columnName,\n formatCell,\n formatRange,\n moveReferences,\n dropReferences,\n renameReferences,\n renameReferencesAll,\n parseCell,\n parseRange,\n quoteSheet,\n shiftFormula,\n splitSheet,\n} from './core/address'\nexport { formatClip, parseClip, parseTSV } from './core/clipboard'\nexport { detectDelimiter, parseCSV, readCSV, sheetToCSV } from './core/csv'\nexport type { SheetCSVReadOptions, SheetCSVWriteOptions } from './core/csv'\nexport type { SheetClip, SheetClipFormat } from './core/clipboard'\nexport { continueValues, fillContinues } from './core/fill'\nexport type { SheetFillMode, SheetFillOptions } from './core/fill'\nexport type {\n SheetBounds,\n SheetCellTarget,\n SheetPoint,\n SheetRange,\n SheetRefMap,\n} from './core/address'\nexport { cellOf, valueOf } from './core/model'\nexport { checkWorkbook, emptyWorkbook, migrateWorkbook } from './core/document'\nexport type { CheckWorkbookOptions, WorkbookProblem } from './core/document'\nexport type {\n SheetCell,\n SheetCellInput,\n SheetColor,\n SheetCondition,\n SheetConditionalAverage,\n SheetConditionalBar,\n SheetConditionalDuplicates,\n SheetConditionalFormat,\n SheetConditionalFormula,\n SheetConditionalRank,\n SheetConditionalScale,\n SheetConditionalStyle,\n SheetConditionalUnique,\n SheetConditionalWhen,\n SheetData,\n SheetFilter,\n SheetFilterRule,\n SheetFreeze,\n SheetProtection,\n SheetRow,\n SheetRuleRange,\n SheetSelectOption,\n SheetSortOrder,\n SheetStyle,\n SheetTypeSetup,\n SheetValidation,\n SheetValidationFormula,\n SheetValidationList,\n SheetValidationWhen,\n SheetValue,\n SheetWorkbook,\n} from './core/model'\nexport { compareForSort, meetsRule, sortRows, textCollator } from './core/data'\nexport type { SheetSortKey } from './core/data'\nexport { changeDecimals, formatValue, parseInput } from './core/format'\nexport type { SheetInput } from './core/format'\nexport { isSelected, selectCell } from './core/selection'\nexport type { SheetSelection } from './core/selection'\nexport type { SheetSearchQuery, SheetMatch } from './core/find'\nexport { checkProtection, isLocked, protectionOf } from './core/protect'\nexport { linkTarget } from './core/link'\nexport type { SheetLinkTarget } from './core/link'\nexport type { SheetProtectionCheck, SheetProtectionRefusal } from './core/protect'\nexport { applySheetSteps, compactSheetSteps, sheetKey, SheetTransaction } from './core/transaction'\nexport type {\n SheetAction,\n SheetAxisName,\n SheetCellAt,\n SheetLinesAt,\n SheetBookPatch,\n SheetPatch,\n SheetRangeAt,\n SheetRef,\n SheetStep,\n SheetStylePatch,\n SheetTransactionMeta,\n} from './core/transaction'\nexport { criteriaOf, defineSheetFunction, numbersOf, scalarOf } from './formula/functions'\nexport { compareValues, dateText, serialOf, toBoolean, toNumber, toText } from './formula/values'\nexport type { SheetFunction, SheetFunctionContext } from './formula/functions'\nexport { isSheetError, SheetError } from './formula/error'\nexport type { SheetErrorCode } from './formula/error'\nexport type { SheetArg, SheetRangeArg, SheetResult } from './formula/values'\nexport { sheetMessagesFor, sheetLocales } from './locale'\nexport { useSheetMessages } from './use-messages'\nexport type {\n SheetCommentMessages,\n SheetCompareMessages,\n SheetFileMessages,\n SheetMessages,\n SheetMessagesOverride,\n} from './locale'\n\ndeclare module 'vue' {\n export interface GlobalComponents {\n DouSheet: typeof DouSheet\n DouSheetTabs: typeof DouSheetTabs\n DouSheetToolbar: typeof DouSheetToolbar\n DouSheetFormulaBar: typeof DouSheetFormulaBar\n }\n}\nexport type { DrawCell, DrawLook, DrawTheme, SheetDrawing } from './export/draw'\nexport { lightThemeColor, plainStyle } from './core/paint'\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAMA,IAAa,WAAW,YAAYA,aAAK;AACzC,IAAa,eAAe,YAAYC,kBAAS;AACjD,IAAa,kBAAkB,YAAYC,qBAAY;AACvD,IAAa,qBAAqB,YAAYC,yBAAe"}
|