ooxml-core 1.2.0 → 1.3.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/{PptxHandler-SJTINPU4.mjs → PptxHandler-ZPJNHEZZ.mjs} +2 -2
- package/dist/automation/index.cjs +3294 -661
- package/dist/automation/index.mjs +3294 -661
- package/dist/chart/bar-cluster-geometry.d.ts +6 -0
- package/dist/chart/bar-cluster-geometry.d.ts.map +1 -1
- package/dist/chart/index.cjs +5 -2
- package/dist/chart/index.mjs +5 -3
- package/dist/chart/render/chart-spacing.d.ts.map +1 -1
- package/dist/{chunk-TEOAOAIF.mjs → chunk-BB55ASTX.mjs} +3 -3
- package/dist/{chunk-CQQAPUAG.mjs → chunk-H4TPDZV4.mjs} +11 -9
- package/dist/{chunk-VYTA2OUN.mjs → chunk-IVDC75E5.mjs} +1 -1
- package/dist/{chunk-FI4RSJ24.mjs → chunk-QPQDLSJQ.mjs} +1 -1
- package/dist/{chunk-XCZ7U3GZ.mjs → chunk-XGLKW3JJ.mjs} +13 -9
- package/dist/docx/index.cjs +4 -2
- package/dist/docx/index.mjs +4 -2
- package/dist/docx/layout/index.cjs +4 -2
- package/dist/docx/layout/index.mjs +4 -2
- package/dist/docx/ui/index.cjs +4 -2
- package/dist/docx/ui/index.mjs +4 -2
- package/dist/index.cjs +5 -2
- package/dist/index.mjs +5 -2
- package/dist/pptx/automation/index.cjs +29 -17
- package/dist/pptx/automation/index.mjs +5 -5
- package/dist/pptx/chunks/index-EZJZ7USt.d.ts.map +1 -1
- package/dist/pptx/cli/index.cjs +29 -17
- package/dist/pptx/cli/index.mjs +4 -4
- package/dist/pptx/converter/index.mjs +2 -2
- package/dist/pptx/index.cjs +29 -17
- package/dist/pptx/index.mjs +5 -5
- package/dist/teams/index.cjs +176 -92
- package/dist/teams/index.mjs +176 -92
- package/dist/visio/clipboard-resources.d.ts +11 -0
- package/dist/visio/clipboard-resources.d.ts.map +1 -0
- package/dist/visio/clipboard-types.d.ts +26 -0
- package/dist/visio/clipboard-types.d.ts.map +1 -0
- package/dist/visio/clipboard-xml.d.ts +8 -0
- package/dist/visio/clipboard-xml.d.ts.map +1 -0
- package/dist/visio/clipboard.d.ts +7 -0
- package/dist/visio/clipboard.d.ts.map +1 -0
- package/dist/visio/create-document.d.ts +8 -0
- package/dist/visio/create-document.d.ts.map +1 -0
- package/dist/visio/edit-commands.d.ts +19 -2
- package/dist/visio/edit-commands.d.ts.map +1 -1
- package/dist/visio/edit-delete.d.ts +9 -0
- package/dist/visio/edit-delete.d.ts.map +1 -0
- package/dist/visio/edit-duplicate-commands.d.ts +14 -0
- package/dist/visio/edit-duplicate-commands.d.ts.map +1 -0
- package/dist/visio/edit-duplicate-scope.d.ts +4 -0
- package/dist/visio/edit-duplicate-scope.d.ts.map +1 -0
- package/dist/visio/edit-duplicate.d.ts +10 -0
- package/dist/visio/edit-duplicate.d.ts.map +1 -0
- package/dist/visio/edit-formatting-cell-admission.d.ts +3 -0
- package/dist/visio/edit-formatting-cell-admission.d.ts.map +1 -0
- package/dist/visio/edit-formatting-commands.d.ts +46 -0
- package/dist/visio/edit-formatting-commands.d.ts.map +1 -0
- package/dist/visio/edit-formatting-font.d.ts +6 -0
- package/dist/visio/edit-formatting-font.d.ts.map +1 -0
- package/dist/visio/edit-formatting-paint-scope.d.ts +6 -0
- package/dist/visio/edit-formatting-paint-scope.d.ts.map +1 -0
- package/dist/visio/edit-formatting-paint.d.ts +6 -0
- package/dist/visio/edit-formatting-paint.d.ts.map +1 -0
- package/dist/visio/edit-formatting-rows.d.ts +14 -0
- package/dist/visio/edit-formatting-rows.d.ts.map +1 -0
- package/dist/visio/edit-formatting-scope.d.ts +6 -0
- package/dist/visio/edit-formatting-scope.d.ts.map +1 -0
- package/dist/visio/edit-formatting-text.d.ts +8 -0
- package/dist/visio/edit-formatting-text.d.ts.map +1 -0
- package/dist/visio/edit-formatting.d.ts +12 -0
- package/dist/visio/edit-formatting.d.ts.map +1 -0
- package/dist/visio/edit-geometry.d.ts.map +1 -1
- package/dist/visio/edit-paste-commands.d.ts +15 -0
- package/dist/visio/edit-paste-commands.d.ts.map +1 -0
- package/dist/visio/edit-paste.d.ts +5 -0
- package/dist/visio/edit-paste.d.ts.map +1 -0
- package/dist/visio/edit-recalculate.d.ts +3 -1
- package/dist/visio/edit-recalculate.d.ts.map +1 -1
- package/dist/visio/edit-resize-anchor.d.ts +8 -0
- package/dist/visio/edit-resize-anchor.d.ts.map +1 -0
- package/dist/visio/edit-scope.d.ts.map +1 -1
- package/dist/visio/edit-shape-create.d.ts +1 -1
- package/dist/visio/edit-shape-create.d.ts.map +1 -1
- package/dist/visio/edit-shape-order.d.ts +7 -0
- package/dist/visio/edit-shape-order.d.ts.map +1 -0
- package/dist/visio/edit-style-admission.d.ts +17 -0
- package/dist/visio/edit-style-admission.d.ts.map +1 -0
- package/dist/visio/edit-text-scope.d.ts +7 -0
- package/dist/visio/edit-text-scope.d.ts.map +1 -0
- package/dist/visio/edit-text.d.ts +1 -1
- package/dist/visio/edit-text.d.ts.map +1 -1
- package/dist/visio/edit.d.ts +1 -1
- package/dist/visio/edit.d.ts.map +1 -1
- package/dist/visio/index.cjs +3245 -1077
- package/dist/visio/index.d.ts +3 -1
- package/dist/visio/index.d.ts.map +1 -1
- package/dist/visio/index.mjs +3241 -1079
- package/dist/visio/line-pattern.d.ts +1 -1
- package/dist/visio/line-pattern.d.ts.map +1 -1
- package/dist/visio/line-style.d.ts.map +1 -1
- package/dist/visio/model.d.ts +23 -3
- package/dist/visio/model.d.ts.map +1 -1
- package/dist/visio/parser.d.ts.map +1 -1
- package/dist/visio/plain-text.d.ts +5 -0
- package/dist/visio/plain-text.d.ts.map +1 -0
- package/dist/visio/resize-anchor.d.ts +27 -0
- package/dist/visio/resize-anchor.d.ts.map +1 -0
- package/dist/visio/source-paint.d.ts +5 -0
- package/dist/visio/source-paint.d.ts.map +1 -0
- package/dist/visio/style.d.ts.map +1 -1
- package/dist/visio/theme-root.d.ts.map +1 -1
- package/dist/visio/ui/contract.d.ts +10 -6
- package/dist/visio/ui/contract.d.ts.map +1 -1
- package/dist/visio/ui/draw-plan.d.ts +32 -0
- package/dist/visio/ui/draw-plan.d.ts.map +1 -0
- package/dist/visio/ui/edit-commands.d.ts.map +1 -1
- package/dist/visio/ui/formatting.d.ts +28 -0
- package/dist/visio/ui/formatting.d.ts.map +1 -0
- package/dist/visio/ui/index.cjs +1305 -15
- package/dist/visio/ui/index.d.ts +15 -0
- package/dist/visio/ui/index.d.ts.map +1 -1
- package/dist/visio/ui/index.mjs +1261 -16
- package/dist/visio/ui/line-dash.d.ts +4 -0
- package/dist/visio/ui/line-dash.d.ts.map +1 -0
- package/dist/visio/ui/marquee.d.ts +15 -0
- package/dist/visio/ui/marquee.d.ts.map +1 -0
- package/dist/visio/ui/page-edit.d.ts.map +1 -1
- package/dist/visio/ui/scene-validation.d.ts.map +1 -1
- package/dist/visio/ui/selection.d.ts +12 -0
- package/dist/visio/ui/selection.d.ts.map +1 -0
- package/dist/visio/ui/shape-arrange.d.ts +17 -0
- package/dist/visio/ui/shape-arrange.d.ts.map +1 -0
- package/dist/visio/ui/shape-clipboard.d.ts +10 -0
- package/dist/visio/ui/shape-clipboard.d.ts.map +1 -0
- package/dist/visio/ui/shape-duplicate.d.ts +5 -0
- package/dist/visio/ui/shape-duplicate.d.ts.map +1 -0
- package/dist/visio/ui/shape-formatting.d.ts +14 -0
- package/dist/visio/ui/shape-formatting.d.ts.map +1 -0
- package/dist/visio/ui/shape-move.d.ts +14 -0
- package/dist/visio/ui/shape-move.d.ts.map +1 -0
- package/dist/visio/ui/shape-order.d.ts +4 -0
- package/dist/visio/ui/shape-order.d.ts.map +1 -0
- package/dist/visio/ui/shape-resize.d.ts +61 -0
- package/dist/visio/ui/shape-resize.d.ts.map +1 -0
- package/dist/visio/ui/size-position.d.ts +19 -0
- package/dist/visio/ui/size-position.d.ts.map +1 -0
- package/dist/visio/ui/snapshot-scene.d.ts.map +1 -1
- package/dist/visio/ui/svg-stroke.d.ts +8 -0
- package/dist/visio/ui/svg-stroke.d.ts.map +1 -0
- package/dist/visio/ui/text-replace-selection.d.ts +9 -0
- package/dist/visio/ui/text-replace-selection.d.ts.map +1 -0
- package/dist/visio/ui/text-replace-snapshot.d.ts +14 -0
- package/dist/visio/ui/text-replace-snapshot.d.ts.map +1 -0
- package/dist/visio/ui/text-replace-types.d.ts +48 -0
- package/dist/visio/ui/text-replace-types.d.ts.map +1 -0
- package/dist/visio/ui/text-replace.d.ts +18 -0
- package/dist/visio/ui/text-replace.d.ts.map +1 -0
- package/dist/xlsx/edit/context.d.ts +3 -1
- package/dist/xlsx/edit/context.d.ts.map +1 -1
- package/dist/xlsx/edit/history.d.ts +18 -0
- package/dist/xlsx/edit/history.d.ts.map +1 -1
- package/dist/xlsx/edit/session-calc.d.ts +30 -8
- package/dist/xlsx/edit/session-calc.d.ts.map +1 -1
- package/dist/xlsx/edit/session.d.ts.map +1 -1
- package/dist/xlsx/edit/sheets.d.ts.map +1 -1
- package/dist/xlsx/edit/types.d.ts +23 -3
- package/dist/xlsx/edit/types.d.ts.map +1 -1
- package/dist/xlsx/formula/engine-core.d.ts.map +1 -1
- package/dist/xlsx/formula/engine-host.d.ts +6 -2
- package/dist/xlsx/formula/engine-host.d.ts.map +1 -1
- package/dist/xlsx/formula/engine-prepare.d.ts +33 -0
- package/dist/xlsx/formula/engine-prepare.d.ts.map +1 -0
- package/dist/xlsx/formula/engine-structure.d.ts +40 -0
- package/dist/xlsx/formula/engine-structure.d.ts.map +1 -0
- package/dist/xlsx/formula/engine-types.d.ts +26 -0
- package/dist/xlsx/formula/engine-types.d.ts.map +1 -1
- package/dist/xlsx/formula/engine.d.ts.map +1 -1
- package/dist/xlsx/formula/formula-shape.d.ts +28 -0
- package/dist/xlsx/formula/formula-shape.d.ts.map +1 -0
- package/dist/xlsx/formula/graph-index.d.ts +3 -1
- package/dist/xlsx/formula/graph-index.d.ts.map +1 -1
- package/dist/xlsx/formula/graph.d.ts +5 -0
- package/dist/xlsx/formula/graph.d.ts.map +1 -1
- package/dist/xlsx/formula/lexemes.d.ts.map +1 -1
- package/dist/xlsx/formula/parse-cache.d.ts +9 -0
- package/dist/xlsx/formula/parse-cache.d.ts.map +1 -0
- package/dist/xlsx/formula/parser.d.ts +3 -0
- package/dist/xlsx/formula/parser.d.ts.map +1 -1
- package/dist/xlsx/formula/ref-text.d.ts +14 -0
- package/dist/xlsx/formula/ref-text.d.ts.map +1 -0
- package/dist/xlsx/formula/references.d.ts.map +1 -1
- package/dist/xlsx/formula/shift-formula.d.ts +19 -0
- package/dist/xlsx/formula/shift-formula.d.ts.map +1 -0
- package/dist/xlsx/formula/shift-graph.d.ts +42 -0
- package/dist/xlsx/formula/shift-graph.d.ts.map +1 -0
- package/dist/xlsx/formula/transform.d.ts +2 -23
- package/dist/xlsx/formula/transform.d.ts.map +1 -1
- package/dist/xlsx/index.cjs +1087 -338
- package/dist/xlsx/index.mjs +1087 -339
- package/dist/xlsx/layout/index.d.ts +1 -1
- package/dist/xlsx/layout/index.d.ts.map +1 -1
- package/dist/xlsx/layout/sheet-queries.d.ts +7 -0
- package/dist/xlsx/layout/sheet-queries.d.ts.map +1 -1
- package/dist/xlsx/load/index.cjs +170 -99
- package/dist/xlsx/load/index.mjs +170 -99
- package/dist/xlsx/ui/index.cjs +1072 -332
- package/dist/xlsx/ui/index.mjs +1072 -332
- package/package.json +1 -1
package/dist/xlsx/index.cjs
CHANGED
|
@@ -2108,7 +2108,7 @@ var NAME_RE = /^[A-Za-z_\\\u00A1-\uFFFF][A-Za-z0-9_.?\\\u00A1-\uFFFF]*/;
|
|
|
2108
2108
|
var CELL_RE = /^(\$?)([A-Za-z]{1,3})(\$?)(\d{1,7})/;
|
|
2109
2109
|
var COLS_RE = /^(\$?)([A-Za-z]{1,3}):(\$?)([A-Za-z]{1,3})/;
|
|
2110
2110
|
var ROWS_RE = /^(\$?)(\d{1,7}):(\$?)(\d{1,7})/;
|
|
2111
|
-
var NUMBER_RE2 = /^(?:\d
|
|
2111
|
+
var NUMBER_RE2 = /^(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?/;
|
|
2112
2112
|
var sticky = (re) => new RegExp(re.source.replace(/^\^/, ""), "y");
|
|
2113
2113
|
var CELL_AT = sticky(CELL_RE);
|
|
2114
2114
|
var COLS_AT = sticky(COLS_RE);
|
|
@@ -2268,14 +2268,13 @@ function splitSheets(text3) {
|
|
|
2268
2268
|
if (book !== void 0) out.book = book;
|
|
2269
2269
|
return out;
|
|
2270
2270
|
}
|
|
2271
|
-
var PREFIX_AT = /(\[\d+\])?([A-Za-z0-9_.\u00A1-\uFFFF]+)(?::([A-Za-z0-9_.\u00A1-\uFFFF]+))?!/y;
|
|
2272
2271
|
function readPrefix(source2, at) {
|
|
2273
2272
|
const ch = source2[at];
|
|
2274
2273
|
if (ch === "'") {
|
|
2275
2274
|
const quoted = readQuoted(source2, at);
|
|
2276
2275
|
if (source2[at + quoted.length] !== "!") return void 0;
|
|
2277
|
-
const
|
|
2278
|
-
return { prefix: { text: source2.slice(at, at +
|
|
2276
|
+
const length2 = quoted.length + 1;
|
|
2277
|
+
return { prefix: { text: source2.slice(at, at + length2), ...splitSheets(quoted.name) }, length: length2 };
|
|
2279
2278
|
}
|
|
2280
2279
|
let i2 = at;
|
|
2281
2280
|
if (ch === "[") {
|
|
@@ -2284,13 +2283,23 @@ function readPrefix(source2, at) {
|
|
|
2284
2283
|
if (i2 === at + 1 || source2[i2] !== "]") return void 0;
|
|
2285
2284
|
i2++;
|
|
2286
2285
|
}
|
|
2286
|
+
const sheetFrom = i2;
|
|
2287
2287
|
while (i2 < source2.length && isSheetCharCode(source2.charCodeAt(i2))) i2++;
|
|
2288
|
-
if (
|
|
2289
|
-
|
|
2290
|
-
if (
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2288
|
+
if (i2 === sheetFrom) return void 0;
|
|
2289
|
+
let lastFrom = -1;
|
|
2290
|
+
if (source2[i2] === ":") {
|
|
2291
|
+
lastFrom = i2 + 1;
|
|
2292
|
+
i2 = lastFrom;
|
|
2293
|
+
while (i2 < source2.length && isSheetCharCode(source2.charCodeAt(i2))) i2++;
|
|
2294
|
+
if (i2 === lastFrom) return void 0;
|
|
2295
|
+
}
|
|
2296
|
+
if (source2[i2] !== "!") return void 0;
|
|
2297
|
+
if (ch !== "[" && lastFrom < 0 && isDigitCode(source2.charCodeAt(sheetFrom))) return void 0;
|
|
2298
|
+
const length = i2 + 1 - at;
|
|
2299
|
+
return {
|
|
2300
|
+
prefix: { text: source2.slice(at, at + length), ...splitSheets(source2.slice(at, i2)) },
|
|
2301
|
+
length
|
|
2302
|
+
};
|
|
2294
2303
|
}
|
|
2295
2304
|
function numberLiteral(text3) {
|
|
2296
2305
|
if (text3.length <= 15) return Number(text3);
|
|
@@ -2480,7 +2489,9 @@ var PREC_INTERSECT = 9;
|
|
|
2480
2489
|
var PREC_RANGE = 10;
|
|
2481
2490
|
var OPERAND_START = /* @__PURE__ */ new Set(["ref", "name", "func", "open", "structured"]);
|
|
2482
2491
|
function parseFormula(formula) {
|
|
2483
|
-
|
|
2492
|
+
return parseTokens(tokenize(formula));
|
|
2493
|
+
}
|
|
2494
|
+
function parseTokens(all2) {
|
|
2484
2495
|
const tokens2 = [];
|
|
2485
2496
|
const wsBefore = [];
|
|
2486
2497
|
let sawWs = false;
|
|
@@ -2765,6 +2776,222 @@ function localDateToSerial(date, date1904 = date1904Mode) {
|
|
|
2765
2776
|
return base + (utc - dayStart) / DAY_MS;
|
|
2766
2777
|
}
|
|
2767
2778
|
|
|
2779
|
+
// xlsx/formula/area-index.ts
|
|
2780
|
+
var BUCKET_WIDTH = 64;
|
|
2781
|
+
var CHUNK_SHIFT = 6;
|
|
2782
|
+
var CHUNKS = 64;
|
|
2783
|
+
function push(map, key, value) {
|
|
2784
|
+
const list = map.get(key);
|
|
2785
|
+
if (list) list.push(value);
|
|
2786
|
+
else map.set(key, [value]);
|
|
2787
|
+
}
|
|
2788
|
+
function inner(map, sheet) {
|
|
2789
|
+
let found = map.get(sheet);
|
|
2790
|
+
if (!found) map.set(sheet, found = /* @__PURE__ */ new Map());
|
|
2791
|
+
return found;
|
|
2792
|
+
}
|
|
2793
|
+
var AreaIndex = class {
|
|
2794
|
+
cells = /* @__PURE__ */ new Map();
|
|
2795
|
+
chunked = /* @__PURE__ */ new Map();
|
|
2796
|
+
tall = /* @__PURE__ */ new Map();
|
|
2797
|
+
wide = /* @__PURE__ */ new Map();
|
|
2798
|
+
add(area, node) {
|
|
2799
|
+
const { start, end } = area.range;
|
|
2800
|
+
if (start.row === end.row && end.col - start.col + 1 <= BUCKET_WIDTH) {
|
|
2801
|
+
const cells = inner(this.cells, area.sheet);
|
|
2802
|
+
for (let col = start.col; col <= end.col; col++) push(cells, cellKey(start.row, col), node);
|
|
2803
|
+
return;
|
|
2804
|
+
}
|
|
2805
|
+
const entry3 = { range: area.range, node };
|
|
2806
|
+
if (end.col - start.col + 1 > BUCKET_WIDTH) {
|
|
2807
|
+
const list = this.wide.get(area.sheet);
|
|
2808
|
+
if (list) list.push(entry3);
|
|
2809
|
+
else this.wide.set(area.sheet, [entry3]);
|
|
2810
|
+
return;
|
|
2811
|
+
}
|
|
2812
|
+
const first2 = start.row >> CHUNK_SHIFT;
|
|
2813
|
+
const last = end.row >> CHUNK_SHIFT;
|
|
2814
|
+
if (last - first2 + 1 > CHUNKS) {
|
|
2815
|
+
const cols2 = inner(this.tall, area.sheet);
|
|
2816
|
+
for (let c2 = start.col; c2 <= end.col; c2++) push(cols2, c2, entry3);
|
|
2817
|
+
return;
|
|
2818
|
+
}
|
|
2819
|
+
const cols = inner(this.chunked, area.sheet);
|
|
2820
|
+
for (let c2 = start.col; c2 <= end.col; c2++) {
|
|
2821
|
+
let chunks = cols.get(c2);
|
|
2822
|
+
if (!chunks) cols.set(c2, chunks = /* @__PURE__ */ new Map());
|
|
2823
|
+
for (let k = first2; k <= last; k++) push(chunks, k, entry3);
|
|
2824
|
+
}
|
|
2825
|
+
}
|
|
2826
|
+
/** Items whose areas intersect `range` on `sheet` (each once). */
|
|
2827
|
+
dependents(sheet, range, out) {
|
|
2828
|
+
const found = out instanceof Set ? out : /* @__PURE__ */ new Set();
|
|
2829
|
+
this.collect(sheet, range, found);
|
|
2830
|
+
if (Array.isArray(out)) for (const node of found) out.push(node);
|
|
2831
|
+
}
|
|
2832
|
+
collect(sheet, range, out) {
|
|
2833
|
+
const { start, end } = range;
|
|
2834
|
+
const check3 = (list) => {
|
|
2835
|
+
if (list) {
|
|
2836
|
+
for (const entry3 of list) if (rangesIntersect(entry3.range, range)) out.add(entry3.node);
|
|
2837
|
+
}
|
|
2838
|
+
};
|
|
2839
|
+
const cells = this.cells.get(sheet);
|
|
2840
|
+
if (cells) {
|
|
2841
|
+
const size = (end.row - start.row + 1) * (end.col - start.col + 1);
|
|
2842
|
+
if (size <= 4096) {
|
|
2843
|
+
for (let r = start.row; r <= end.row; r++) {
|
|
2844
|
+
for (let c2 = start.col; c2 <= end.col; c2++) {
|
|
2845
|
+
const list = cells.get(cellKey(r, c2));
|
|
2846
|
+
if (list) for (const node of list) out.add(node);
|
|
2847
|
+
}
|
|
2848
|
+
}
|
|
2849
|
+
} else {
|
|
2850
|
+
for (const [key, list] of cells) {
|
|
2851
|
+
const { row: row2, col } = keyToAddress(key);
|
|
2852
|
+
if (row2 >= start.row && row2 <= end.row && col >= start.col && col <= end.col)
|
|
2853
|
+
for (const node of list) out.add(node);
|
|
2854
|
+
}
|
|
2855
|
+
}
|
|
2856
|
+
}
|
|
2857
|
+
const columns = (map, visit2) => {
|
|
2858
|
+
if (!map) return;
|
|
2859
|
+
if (end.col - start.col + 1 <= map.size) {
|
|
2860
|
+
for (let c2 = start.col; c2 <= end.col; c2++) if (map.has(c2)) visit2(c2);
|
|
2861
|
+
} else for (const c2 of map.keys()) if (c2 >= start.col && c2 <= end.col) visit2(c2);
|
|
2862
|
+
};
|
|
2863
|
+
const chunked = this.chunked.get(sheet);
|
|
2864
|
+
const first2 = start.row >> CHUNK_SHIFT;
|
|
2865
|
+
const last = end.row >> CHUNK_SHIFT;
|
|
2866
|
+
columns(chunked, (c2) => {
|
|
2867
|
+
const chunks = chunked?.get(c2);
|
|
2868
|
+
if (last - first2 + 1 <= chunks.size) {
|
|
2869
|
+
for (let k = first2; k <= last; k++) check3(chunks.get(k));
|
|
2870
|
+
} else for (const [k, list] of chunks) if (k >= first2 && k <= last) check3(list);
|
|
2871
|
+
});
|
|
2872
|
+
const tall = this.tall.get(sheet);
|
|
2873
|
+
columns(tall, (c2) => check3(tall?.get(c2)));
|
|
2874
|
+
check3(this.wide.get(sheet));
|
|
2875
|
+
}
|
|
2876
|
+
};
|
|
2877
|
+
|
|
2878
|
+
// xlsx/formula/graph-index.ts
|
|
2879
|
+
var ColumnIndex = class {
|
|
2880
|
+
sheets = /* @__PURE__ */ new Map();
|
|
2881
|
+
constructor(nodes) {
|
|
2882
|
+
for (const node of nodes) {
|
|
2883
|
+
let cols = this.sheets.get(node.sheet);
|
|
2884
|
+
if (!cols) this.sheets.set(node.sheet, cols = /* @__PURE__ */ new Map());
|
|
2885
|
+
let list = cols.get(node.col);
|
|
2886
|
+
if (!list) cols.set(node.col, list = []);
|
|
2887
|
+
list.push(node);
|
|
2888
|
+
}
|
|
2889
|
+
for (const cols of this.sheets.values())
|
|
2890
|
+
for (const list of cols.values()) list.sort((a2, b) => a2.row - b.row);
|
|
2891
|
+
}
|
|
2892
|
+
nodesIn(area, out) {
|
|
2893
|
+
const cols = this.sheets.get(area.sheet);
|
|
2894
|
+
if (!cols) return;
|
|
2895
|
+
const { start, end } = area.range;
|
|
2896
|
+
const width = end.col - start.col + 1;
|
|
2897
|
+
const scan4 = (list) => {
|
|
2898
|
+
let lo = 0;
|
|
2899
|
+
let hi = list.length;
|
|
2900
|
+
while (lo < hi) {
|
|
2901
|
+
const mid = lo + hi >> 1;
|
|
2902
|
+
if (list[mid].row < start.row) lo = mid + 1;
|
|
2903
|
+
else hi = mid;
|
|
2904
|
+
}
|
|
2905
|
+
for (let i2 = lo; i2 < list.length; i2++) {
|
|
2906
|
+
const node = list[i2];
|
|
2907
|
+
if (node.row > end.row) break;
|
|
2908
|
+
out.push(node);
|
|
2909
|
+
}
|
|
2910
|
+
};
|
|
2911
|
+
if (width <= cols.size) {
|
|
2912
|
+
for (let c2 = start.col; c2 <= end.col; c2++) {
|
|
2913
|
+
const list = cols.get(c2);
|
|
2914
|
+
if (list) scan4(list);
|
|
2915
|
+
}
|
|
2916
|
+
} else {
|
|
2917
|
+
for (const [c2, list] of cols) if (c2 >= start.col && c2 <= end.col) scan4(list);
|
|
2918
|
+
}
|
|
2919
|
+
}
|
|
2920
|
+
};
|
|
2921
|
+
var ReverseIndex = class extends AreaIndex {
|
|
2922
|
+
constructor(nodes = []) {
|
|
2923
|
+
super();
|
|
2924
|
+
for (const node of nodes) this.addNode(node);
|
|
2925
|
+
}
|
|
2926
|
+
/** Indexes one more formula's precedents. */
|
|
2927
|
+
addNode(node) {
|
|
2928
|
+
for (const dep of node.deps) this.add(dep, node);
|
|
2929
|
+
for (const dep of node.dynamicDeps) this.add(dep, node);
|
|
2930
|
+
}
|
|
2931
|
+
};
|
|
2932
|
+
|
|
2933
|
+
// xlsx/formula/engine-prepare.ts
|
|
2934
|
+
var CHECK_EVERY = 32;
|
|
2935
|
+
var GraphPreparation = class {
|
|
2936
|
+
constructor(workbook, create) {
|
|
2937
|
+
this.workbook = workbook;
|
|
2938
|
+
this.create = create;
|
|
2939
|
+
}
|
|
2940
|
+
workbook;
|
|
2941
|
+
create;
|
|
2942
|
+
reverse = new ReverseIndex();
|
|
2943
|
+
formulas = { dynamic: [], unvalued: [] };
|
|
2944
|
+
sheet = 0;
|
|
2945
|
+
rows;
|
|
2946
|
+
row = 0;
|
|
2947
|
+
cells;
|
|
2948
|
+
finished = false;
|
|
2949
|
+
/**
|
|
2950
|
+
* Adds formulas to the graph until `timeRemaining` (milliseconds, as an idle deadline reports
|
|
2951
|
+
* them) reaches zero, or until every formula is in. Returns true when the graph is complete.
|
|
2952
|
+
*/
|
|
2953
|
+
run(timeRemaining) {
|
|
2954
|
+
let visited = 0;
|
|
2955
|
+
while (!this.finished) {
|
|
2956
|
+
const cells = this.cells ?? this.nextRow();
|
|
2957
|
+
if (!cells) continue;
|
|
2958
|
+
const next = cells.next();
|
|
2959
|
+
if (next.done) {
|
|
2960
|
+
this.cells = void 0;
|
|
2961
|
+
continue;
|
|
2962
|
+
}
|
|
2963
|
+
const [col, cell] = next.value;
|
|
2964
|
+
if (cell.formula) this.add(this.create(this.sheet, this.row, col, cell), cell);
|
|
2965
|
+
if (timeRemaining && ++visited % CHECK_EVERY === 0 && timeRemaining() <= 0) break;
|
|
2966
|
+
}
|
|
2967
|
+
return this.finished;
|
|
2968
|
+
}
|
|
2969
|
+
add(node, cell) {
|
|
2970
|
+
this.reverse.addNode(node);
|
|
2971
|
+
if (!node.legacy && !node.arrayRange) this.formulas.dynamic.push(node);
|
|
2972
|
+
if (cell.value === null && !node.keepCached) this.formulas.unvalued.push(node);
|
|
2973
|
+
}
|
|
2974
|
+
/** Moves to the next stored row (and sheet), or marks the walk finished. */
|
|
2975
|
+
nextRow() {
|
|
2976
|
+
for (; ; ) {
|
|
2977
|
+
const sheet = this.workbook.sheets[this.sheet];
|
|
2978
|
+
if (!sheet) {
|
|
2979
|
+
this.finished = true;
|
|
2980
|
+
return void 0;
|
|
2981
|
+
}
|
|
2982
|
+
this.rows ??= sheet.rows.entries();
|
|
2983
|
+
const next = this.rows.next();
|
|
2984
|
+
if (!next.done) {
|
|
2985
|
+
this.row = next.value[0];
|
|
2986
|
+
this.cells = next.value[1].entries();
|
|
2987
|
+
return this.cells;
|
|
2988
|
+
}
|
|
2989
|
+
this.rows = void 0;
|
|
2990
|
+
this.sheet++;
|
|
2991
|
+
}
|
|
2992
|
+
}
|
|
2993
|
+
};
|
|
2994
|
+
|
|
2768
2995
|
// xlsx/formula/text-number.ts
|
|
2769
2996
|
var MONTHS2 = [
|
|
2770
2997
|
"jan",
|
|
@@ -5899,8 +6126,10 @@ var FINANCIAL_FUNCTIONS = [
|
|
|
5899
6126
|
|
|
5900
6127
|
// xlsx/formula/references.ts
|
|
5901
6128
|
function sheetIndex(host, name) {
|
|
6129
|
+
const sheets = host.workbook.sheets;
|
|
6130
|
+
for (let i2 = 0; i2 < sheets.length; i2++) if (sheets[i2]?.name === name) return i2;
|
|
5902
6131
|
const lower2 = name.toLowerCase();
|
|
5903
|
-
return
|
|
6132
|
+
return sheets.findIndex((sheet) => sheet.name.toLowerCase() === lower2);
|
|
5904
6133
|
}
|
|
5905
6134
|
function prefixSheets(host, prefix, current) {
|
|
5906
6135
|
if (!prefix) return [current];
|
|
@@ -7470,9 +7699,9 @@ function readBlock(ctx, area, rows, cols) {
|
|
|
7470
7699
|
if (host.readBlock) return host.readBlock(area.sheet, range);
|
|
7471
7700
|
return Matrix.build(rows, cols, (r, c2) => ctx.readCell(area.sheet, row2 + r, col + c2));
|
|
7472
7701
|
}
|
|
7473
|
-
function shapedMatrices(ctx, values2,
|
|
7702
|
+
function shapedMatrices(ctx, values2, sameShape2) {
|
|
7474
7703
|
let { rows, cols } = shapeOf(values2[0] ?? null);
|
|
7475
|
-
if (
|
|
7704
|
+
if (sameShape2) {
|
|
7476
7705
|
for (const value of values2) {
|
|
7477
7706
|
const shape2 = shapeOf(value);
|
|
7478
7707
|
if (shape2.rows !== rows || shape2.cols !== cols) fail(ERR.VALUE);
|
|
@@ -7498,12 +7727,12 @@ function shapedMatrices(ctx, values2, sameShape) {
|
|
|
7498
7727
|
});
|
|
7499
7728
|
return { matrices, total: total2, block: rows * cols };
|
|
7500
7729
|
}
|
|
7501
|
-
function matchingCells(ctx, pairs, target,
|
|
7730
|
+
function matchingCells(ctx, pairs, target, sameShape2) {
|
|
7502
7731
|
const ranges = pairs.map((p) => p.range);
|
|
7503
7732
|
const { matrices, total: total2, block } = shapedMatrices(
|
|
7504
7733
|
ctx,
|
|
7505
7734
|
target === void 0 ? ranges : [...ranges, target],
|
|
7506
|
-
|
|
7735
|
+
sameShape2
|
|
7507
7736
|
);
|
|
7508
7737
|
const tests = pairs.map((p) => makeCriteria(scalar(p.criteria)));
|
|
7509
7738
|
const values2 = matrices[matrices.length - 1];
|
|
@@ -7542,7 +7771,7 @@ function indexedCandidates(pairs, matrices) {
|
|
|
7542
7771
|
}
|
|
7543
7772
|
return void 0;
|
|
7544
7773
|
}
|
|
7545
|
-
var matchingValues = (ctx, pairs, target,
|
|
7774
|
+
var matchingValues = (ctx, pairs, target, sameShape2) => matchingCells(ctx, pairs, target, sameShape2).values;
|
|
7546
7775
|
function criteriaPairs(args, from) {
|
|
7547
7776
|
if ((args.length - from) % 2 !== 0) fail(ERR.VALUE);
|
|
7548
7777
|
const pairs = [];
|
|
@@ -11436,7 +11665,7 @@ var REFERENCE_ARGUMENT = /* @__PURE__ */ new Set([
|
|
|
11436
11665
|
"AREAS",
|
|
11437
11666
|
"ISREF"
|
|
11438
11667
|
]);
|
|
11439
|
-
var
|
|
11668
|
+
var push2 = (c2, area) => {
|
|
11440
11669
|
(c2.dynamic > 0 ? c2.dynamicDeps : c2.deps).push(area);
|
|
11441
11670
|
};
|
|
11442
11671
|
function spans(areas) {
|
|
@@ -11462,7 +11691,7 @@ function visit(node, c2) {
|
|
|
11462
11691
|
if (!sheets) return;
|
|
11463
11692
|
const range = specRange(node.ref);
|
|
11464
11693
|
const target = node.spill ? { start: range.start, end: { ...range.start } } : range;
|
|
11465
|
-
for (const sheet of sheets)
|
|
11694
|
+
for (const sheet of sheets) push2(c2, { sheet, range: target });
|
|
11466
11695
|
return;
|
|
11467
11696
|
}
|
|
11468
11697
|
case "name": {
|
|
@@ -11536,7 +11765,7 @@ function visitBinary(node, c2) {
|
|
|
11536
11765
|
const list = c2.dynamic > 0 ? c2.dynamicDeps : c2.deps;
|
|
11537
11766
|
const l = list[list.length - 2];
|
|
11538
11767
|
const r = list[list.length - 1];
|
|
11539
|
-
if (l && r && l.sheet === r.sheet)
|
|
11768
|
+
if (l && r && l.sheet === r.sheet) push2(c2, spans([l, r])[0]);
|
|
11540
11769
|
continue;
|
|
11541
11770
|
}
|
|
11542
11771
|
const mentioned = [...c2.deps.slice(staticStart), ...c2.dynamicDeps.slice(dynamicStart)];
|
|
@@ -11552,7 +11781,7 @@ function addStructured(ref, c2) {
|
|
|
11552
11781
|
sheet: c2.sheet,
|
|
11553
11782
|
row: c2.row,
|
|
11554
11783
|
col: c2.col});
|
|
11555
|
-
if (value instanceof RefValue) for (const area of value.areas)
|
|
11784
|
+
if (value instanceof RefValue) for (const area of value.areas) push2(c2, area);
|
|
11556
11785
|
}
|
|
11557
11786
|
function analyze(ast, host, sheet, row2, col) {
|
|
11558
11787
|
const c2 = {
|
|
@@ -11576,155 +11805,191 @@ function analyze(ast, host, sheet, row2, col) {
|
|
|
11576
11805
|
};
|
|
11577
11806
|
}
|
|
11578
11807
|
|
|
11579
|
-
// xlsx/formula/
|
|
11580
|
-
var
|
|
11581
|
-
|
|
11582
|
-
|
|
11583
|
-
|
|
11584
|
-
|
|
11585
|
-
|
|
11586
|
-
|
|
11808
|
+
// xlsx/formula/formula-shape.ts
|
|
11809
|
+
var isDigit4 = (code) => code >= 48 && code <= 57;
|
|
11810
|
+
function formulaShape(formula) {
|
|
11811
|
+
const starts = [];
|
|
11812
|
+
const ends = [];
|
|
11813
|
+
let hash = 2166136261;
|
|
11814
|
+
for (let i2 = 0; i2 < formula.length; i2++) {
|
|
11815
|
+
let code = formula.charCodeAt(i2);
|
|
11816
|
+
if (isDigit4(code)) {
|
|
11817
|
+
let j = i2 + 1;
|
|
11818
|
+
while (j < formula.length && isDigit4(formula.charCodeAt(j))) j++;
|
|
11819
|
+
starts.push(i2);
|
|
11820
|
+
ends.push(j);
|
|
11821
|
+
i2 = j - 1;
|
|
11822
|
+
code = 0;
|
|
11823
|
+
}
|
|
11824
|
+
hash = Math.imul(hash ^ code, 16777619);
|
|
11825
|
+
}
|
|
11826
|
+
return { hash: hash >>> 0, starts, ends };
|
|
11587
11827
|
}
|
|
11588
|
-
function
|
|
11589
|
-
let
|
|
11590
|
-
|
|
11591
|
-
return
|
|
11828
|
+
function sameText(a2, from, b, at, length) {
|
|
11829
|
+
for (let k = 0; k < length; k++)
|
|
11830
|
+
if (a2.charCodeAt(from + k) !== b.charCodeAt(at + k)) return false;
|
|
11831
|
+
return true;
|
|
11592
11832
|
}
|
|
11593
|
-
|
|
11594
|
-
|
|
11595
|
-
|
|
11596
|
-
|
|
11597
|
-
|
|
11598
|
-
|
|
11599
|
-
const
|
|
11600
|
-
|
|
11601
|
-
|
|
11602
|
-
|
|
11603
|
-
|
|
11833
|
+
function sameShape(a2, as, b, bs) {
|
|
11834
|
+
const runs = as.starts.length;
|
|
11835
|
+
if (runs !== bs.starts.length) return false;
|
|
11836
|
+
let fromA = 0;
|
|
11837
|
+
let fromB = 0;
|
|
11838
|
+
for (let i2 = 0; i2 <= runs; i2++) {
|
|
11839
|
+
const toA = i2 < runs ? as.starts[i2] : a2.length;
|
|
11840
|
+
const toB = i2 < runs ? bs.starts[i2] : b.length;
|
|
11841
|
+
if (toA - fromA !== toB - fromB || !sameText(a2, fromA, b, fromB, toA - fromA)) return false;
|
|
11842
|
+
fromA = as.ends[i2] ?? 0;
|
|
11843
|
+
fromB = bs.ends[i2] ?? 0;
|
|
11844
|
+
}
|
|
11845
|
+
return true;
|
|
11846
|
+
}
|
|
11847
|
+
function makeTemplate(formula, shape2) {
|
|
11848
|
+
let tokens2;
|
|
11849
|
+
let ast;
|
|
11850
|
+
try {
|
|
11851
|
+
tokens2 = tokenize(formula);
|
|
11852
|
+
ast = parseTokens(tokens2);
|
|
11853
|
+
} catch (e) {
|
|
11854
|
+
if (e instanceof RangeError) return new FormulaError(e.message, -1, "#VALUE!");
|
|
11855
|
+
if (e instanceof FormulaError) return e;
|
|
11856
|
+
throw e;
|
|
11857
|
+
}
|
|
11858
|
+
const { starts } = shape2;
|
|
11859
|
+
const slotted = starts.map(() => false);
|
|
11860
|
+
const refs = /* @__PURE__ */ new Map();
|
|
11861
|
+
let run2 = 0;
|
|
11862
|
+
for (const token of tokens2) {
|
|
11863
|
+
const end = token.start + token.text.length;
|
|
11864
|
+
const first2 = run2;
|
|
11865
|
+
while (run2 < starts.length && starts[run2] < end) run2++;
|
|
11866
|
+
const ref = token.kind === "ref" ? token.ref : void 0;
|
|
11867
|
+
if (!ref || ref.kind === "cols") continue;
|
|
11868
|
+
const count2 = ref.kind === "cell" ? 1 : 2;
|
|
11869
|
+
if (run2 - first2 < count2) continue;
|
|
11870
|
+
const at = run2 - count2;
|
|
11871
|
+
const indexes2 = count2 === 1 ? [at] : [at, at + 1];
|
|
11872
|
+
if (indexes2.some((i2) => formula.charCodeAt(starts[i2]) === 48)) continue;
|
|
11873
|
+
for (const i2 of indexes2) slotted[i2] = true;
|
|
11874
|
+
refs.set(ref, count2 === 1 ? { start: at } : { start: at, end: at + 1 });
|
|
11875
|
+
}
|
|
11876
|
+
return { formula, shape: shape2, ast, slotted, refs };
|
|
11877
|
+
}
|
|
11878
|
+
function rowsFor(t, formula, shape2) {
|
|
11879
|
+
if (!sameShape(t.formula, t.shape, formula, shape2)) return void 0;
|
|
11880
|
+
const rows = [];
|
|
11881
|
+
for (let i2 = 0; i2 < shape2.starts.length; i2++) {
|
|
11882
|
+
const start = shape2.starts[i2];
|
|
11883
|
+
const length = shape2.ends[i2] - start;
|
|
11884
|
+
if (!t.slotted[i2]) {
|
|
11885
|
+
const own = t.shape.starts[i2];
|
|
11886
|
+
if (t.shape.ends[i2] - own !== length) return void 0;
|
|
11887
|
+
if (!sameText(t.formula, own, formula, start, length)) return void 0;
|
|
11888
|
+
rows.push(-1);
|
|
11889
|
+
continue;
|
|
11604
11890
|
}
|
|
11605
|
-
|
|
11606
|
-
|
|
11607
|
-
|
|
11608
|
-
|
|
11609
|
-
|
|
11610
|
-
|
|
11891
|
+
if (length > 7 || formula.charCodeAt(start) === 48) return void 0;
|
|
11892
|
+
let row2 = 0;
|
|
11893
|
+
for (let k = start; k < start + length; k++) row2 = row2 * 10 + formula.charCodeAt(k) - 48;
|
|
11894
|
+
if (row2 < 1 || row2 > MAX_ROW + 1) return void 0;
|
|
11895
|
+
rows.push(row2 - 1);
|
|
11896
|
+
}
|
|
11897
|
+
return rows;
|
|
11898
|
+
}
|
|
11899
|
+
function shiftSpec(spec2, slots, rows) {
|
|
11900
|
+
const startRow = rows[slots.start];
|
|
11901
|
+
const endRow = slots.end === void 0 ? startRow : rows[slots.end];
|
|
11902
|
+
if (startRow === spec2.start.row && endRow === spec2.end.row) return spec2;
|
|
11903
|
+
const { start: from, end: to } = spec2;
|
|
11904
|
+
const start = { row: startRow, col: from.col, rowAbs: from.rowAbs, colAbs: from.colAbs };
|
|
11905
|
+
if (slots.end === void 0) return { kind: spec2.kind, start, end: start };
|
|
11906
|
+
const end = { row: endRow, col: to.col, rowAbs: to.rowAbs, colAbs: to.colAbs };
|
|
11907
|
+
return { kind: spec2.kind, start, end };
|
|
11908
|
+
}
|
|
11909
|
+
function copyTree(node, t, rows) {
|
|
11910
|
+
switch (node.type) {
|
|
11911
|
+
case "ref": {
|
|
11912
|
+
const slots = node.ref ? t.refs.get(node.ref) : void 0;
|
|
11913
|
+
if (!slots || !node.ref) return node;
|
|
11914
|
+
const ref = shiftSpec(node.ref, slots, rows);
|
|
11915
|
+
if (ref === node.ref) return node;
|
|
11916
|
+
const copy = { type: "ref" };
|
|
11917
|
+
if (node.prefix) copy.prefix = node.prefix;
|
|
11918
|
+
copy.ref = ref;
|
|
11919
|
+
if (node.spill) copy.spill = true;
|
|
11920
|
+
return copy;
|
|
11611
11921
|
}
|
|
11612
|
-
|
|
11613
|
-
|
|
11614
|
-
|
|
11615
|
-
|
|
11616
|
-
|
|
11617
|
-
return;
|
|
11922
|
+
case "unary":
|
|
11923
|
+
case "percent": {
|
|
11924
|
+
const operand4 = copyTree(node.operand, t, rows);
|
|
11925
|
+
if (operand4 === node.operand) return node;
|
|
11926
|
+
return node.type === "unary" ? { type: "unary", op: node.op, operand: operand4 } : { type: "percent", operand: operand4 };
|
|
11618
11927
|
}
|
|
11619
|
-
|
|
11620
|
-
|
|
11621
|
-
|
|
11622
|
-
if (
|
|
11623
|
-
|
|
11928
|
+
case "binary": {
|
|
11929
|
+
const left2 = copyTree(node.left, t, rows);
|
|
11930
|
+
const right2 = copyTree(node.right, t, rows);
|
|
11931
|
+
if (left2 === node.left && right2 === node.right) return node;
|
|
11932
|
+
return { type: "binary", op: node.op, left: left2, right: right2 };
|
|
11624
11933
|
}
|
|
11625
|
-
|
|
11626
|
-
|
|
11627
|
-
|
|
11628
|
-
|
|
11629
|
-
this.collect(sheet, range, found);
|
|
11630
|
-
if (Array.isArray(out)) for (const node of found) out.push(node);
|
|
11631
|
-
}
|
|
11632
|
-
collect(sheet, range, out) {
|
|
11633
|
-
const { start, end } = range;
|
|
11634
|
-
const check3 = (list) => {
|
|
11635
|
-
if (list) {
|
|
11636
|
-
for (const entry3 of list) if (rangesIntersect(entry3.range, range)) out.add(entry3.node);
|
|
11637
|
-
}
|
|
11638
|
-
};
|
|
11639
|
-
const cells = this.cells.get(sheet);
|
|
11640
|
-
if (cells) {
|
|
11641
|
-
const size = (end.row - start.row + 1) * (end.col - start.col + 1);
|
|
11642
|
-
if (size <= 4096) {
|
|
11643
|
-
for (let r = start.row; r <= end.row; r++) {
|
|
11644
|
-
for (let c2 = start.col; c2 <= end.col; c2++) {
|
|
11645
|
-
const list = cells.get(cellKey(r, c2));
|
|
11646
|
-
if (list) for (const node of list) out.add(node);
|
|
11647
|
-
}
|
|
11648
|
-
}
|
|
11649
|
-
} else {
|
|
11650
|
-
for (const [key, list] of cells) {
|
|
11651
|
-
const { row: row2, col } = keyToAddress(key);
|
|
11652
|
-
if (row2 >= start.row && row2 <= end.row && col >= start.col && col <= end.col)
|
|
11653
|
-
for (const node of list) out.add(node);
|
|
11654
|
-
}
|
|
11655
|
-
}
|
|
11934
|
+
case "call": {
|
|
11935
|
+
const args = copyAll(node.args, t, rows);
|
|
11936
|
+
if (args === node.args) return node;
|
|
11937
|
+
return { type: "call", name: node.name, rawName: node.rawName, args };
|
|
11656
11938
|
}
|
|
11657
|
-
|
|
11658
|
-
|
|
11659
|
-
|
|
11660
|
-
|
|
11661
|
-
|
|
11662
|
-
};
|
|
11663
|
-
const chunked = this.chunked.get(sheet);
|
|
11664
|
-
const first2 = start.row >> CHUNK_SHIFT;
|
|
11665
|
-
const last = end.row >> CHUNK_SHIFT;
|
|
11666
|
-
columns(chunked, (c2) => {
|
|
11667
|
-
const chunks = chunked?.get(c2);
|
|
11668
|
-
if (last - first2 + 1 <= chunks.size) {
|
|
11669
|
-
for (let k = first2; k <= last; k++) check3(chunks.get(k));
|
|
11670
|
-
} else for (const [k, list] of chunks) if (k >= first2 && k <= last) check3(list);
|
|
11671
|
-
});
|
|
11672
|
-
const tall = this.tall.get(sheet);
|
|
11673
|
-
columns(tall, (c2) => check3(tall?.get(c2)));
|
|
11674
|
-
check3(this.wide.get(sheet));
|
|
11675
|
-
}
|
|
11676
|
-
};
|
|
11677
|
-
|
|
11678
|
-
// xlsx/formula/graph-index.ts
|
|
11679
|
-
var ColumnIndex = class {
|
|
11680
|
-
sheets = /* @__PURE__ */ new Map();
|
|
11681
|
-
constructor(nodes) {
|
|
11682
|
-
for (const node of nodes) {
|
|
11683
|
-
let cols = this.sheets.get(node.sheet);
|
|
11684
|
-
if (!cols) this.sheets.set(node.sheet, cols = /* @__PURE__ */ new Map());
|
|
11685
|
-
let list = cols.get(node.col);
|
|
11686
|
-
if (!list) cols.set(node.col, list = []);
|
|
11687
|
-
list.push(node);
|
|
11939
|
+
case "invoke": {
|
|
11940
|
+
const callee = copyTree(node.callee, t, rows);
|
|
11941
|
+
const args = copyAll(node.args, t, rows);
|
|
11942
|
+
if (callee === node.callee && args === node.args) return node;
|
|
11943
|
+
return { type: "invoke", callee, args };
|
|
11688
11944
|
}
|
|
11689
|
-
|
|
11690
|
-
|
|
11945
|
+
default:
|
|
11946
|
+
return node;
|
|
11691
11947
|
}
|
|
11692
|
-
|
|
11693
|
-
|
|
11694
|
-
|
|
11695
|
-
|
|
11696
|
-
const
|
|
11697
|
-
const
|
|
11698
|
-
|
|
11699
|
-
|
|
11700
|
-
|
|
11701
|
-
|
|
11702
|
-
|
|
11703
|
-
|
|
11704
|
-
|
|
11705
|
-
|
|
11706
|
-
|
|
11707
|
-
|
|
11708
|
-
|
|
11709
|
-
|
|
11710
|
-
|
|
11711
|
-
|
|
11712
|
-
|
|
11713
|
-
|
|
11714
|
-
|
|
11715
|
-
|
|
11716
|
-
|
|
11717
|
-
|
|
11718
|
-
|
|
11948
|
+
}
|
|
11949
|
+
function copyAll(nodes, t, rows) {
|
|
11950
|
+
let out;
|
|
11951
|
+
for (let i2 = 0; i2 < nodes.length; i2++) {
|
|
11952
|
+
const node = nodes[i2];
|
|
11953
|
+
const copy = copyTree(node, t, rows);
|
|
11954
|
+
if (copy !== node && !out) out = nodes.slice(0, i2);
|
|
11955
|
+
out?.push(copy);
|
|
11956
|
+
}
|
|
11957
|
+
return out ?? nodes;
|
|
11958
|
+
}
|
|
11959
|
+
function fromTemplate(t, formula, shape2) {
|
|
11960
|
+
const rows = rowsFor(t, formula, shape2);
|
|
11961
|
+
return rows ? copyTree(t.ast, t, rows) : void 0;
|
|
11962
|
+
}
|
|
11963
|
+
|
|
11964
|
+
// xlsx/formula/parse-cache.ts
|
|
11965
|
+
var MAX_TEMPLATE_LENGTH = 2048;
|
|
11966
|
+
var MAX_ENTRIES = 1e5;
|
|
11967
|
+
var MAX_TEMPLATES = 1e4;
|
|
11968
|
+
var NO_RUNS = { hash: 0, starts: [], ends: [] };
|
|
11969
|
+
var treeOf = (made) => "ast" in made ? made.ast : made;
|
|
11970
|
+
var ParseCache = class {
|
|
11971
|
+
byText = /* @__PURE__ */ new Map();
|
|
11972
|
+
templates = /* @__PURE__ */ new Map();
|
|
11973
|
+
parse(formula) {
|
|
11974
|
+
let ast = this.byText.get(formula);
|
|
11975
|
+
if (ast) return ast;
|
|
11976
|
+
ast = this.parseNew(formula);
|
|
11977
|
+
if (this.byText.size > MAX_ENTRIES) this.byText.clear();
|
|
11978
|
+
this.byText.set(formula, ast);
|
|
11979
|
+
return ast;
|
|
11719
11980
|
}
|
|
11720
|
-
|
|
11721
|
-
|
|
11722
|
-
|
|
11723
|
-
|
|
11724
|
-
|
|
11725
|
-
|
|
11726
|
-
|
|
11981
|
+
parseNew(formula) {
|
|
11982
|
+
if (formula.length > MAX_TEMPLATE_LENGTH) return treeOf(makeTemplate(formula, NO_RUNS));
|
|
11983
|
+
const shape2 = formulaShape(formula);
|
|
11984
|
+
const template = this.templates.get(shape2.hash);
|
|
11985
|
+
const reused = template && fromTemplate(template, formula, shape2);
|
|
11986
|
+
if (reused) return reused;
|
|
11987
|
+
const made = makeTemplate(formula, shape2);
|
|
11988
|
+
if (!template && "ast" in made) {
|
|
11989
|
+
if (this.templates.size > MAX_TEMPLATES) this.templates.clear();
|
|
11990
|
+
this.templates.set(shape2.hash, made);
|
|
11727
11991
|
}
|
|
11992
|
+
return treeOf(made);
|
|
11728
11993
|
}
|
|
11729
11994
|
};
|
|
11730
11995
|
|
|
@@ -11865,7 +12130,7 @@ var EngineHost = class {
|
|
|
11865
12130
|
options;
|
|
11866
12131
|
nodes = /* @__PURE__ */ new Map();
|
|
11867
12132
|
footprints = /* @__PURE__ */ new Set();
|
|
11868
|
-
|
|
12133
|
+
parsed = new ParseCache();
|
|
11869
12134
|
boundsCache = /* @__PURE__ */ new Map();
|
|
11870
12135
|
inProgress = /* @__PURE__ */ new Set();
|
|
11871
12136
|
cycles = /* @__PURE__ */ new Set();
|
|
@@ -11889,6 +12154,8 @@ var EngineHost = class {
|
|
|
11889
12154
|
evaluations = 0;
|
|
11890
12155
|
built = false;
|
|
11891
12156
|
needsFull = false;
|
|
12157
|
+
/** No recalculation has run since the workbook was opened: stored values may stand. */
|
|
12158
|
+
fresh = true;
|
|
11892
12159
|
// ---- EvalHost ----
|
|
11893
12160
|
readCell(sheet, row2, col) {
|
|
11894
12161
|
const cell = this.workbook.sheets[sheet]?.rows.get(row2)?.get(col);
|
|
@@ -11977,41 +12244,15 @@ var EngineHost = class {
|
|
|
11977
12244
|
return this.workbook.sheets[sheet]?.rows.get(row2)?.get(col)?.formula;
|
|
11978
12245
|
}
|
|
11979
12246
|
parse(formula) {
|
|
11980
|
-
|
|
11981
|
-
if (!ast) {
|
|
11982
|
-
try {
|
|
11983
|
-
ast = parseFormula(formula);
|
|
11984
|
-
} catch (e) {
|
|
11985
|
-
if (e instanceof RangeError) ast = new FormulaError(e.message, -1, "#VALUE!");
|
|
11986
|
-
else if (!(e instanceof FormulaError)) throw e;
|
|
11987
|
-
else ast = e;
|
|
11988
|
-
}
|
|
11989
|
-
if (this.astCache.size > 1e5) this.astCache.clear();
|
|
11990
|
-
this.astCache.set(formula, ast);
|
|
11991
|
-
}
|
|
11992
|
-
return ast;
|
|
12247
|
+
return this.parsed.parse(formula);
|
|
11993
12248
|
}
|
|
11994
12249
|
now() {
|
|
11995
12250
|
return this.options.now ? this.options.now() : /* @__PURE__ */ new Date();
|
|
11996
12251
|
}
|
|
11997
|
-
random() {
|
|
11998
|
-
return this.options.random ? this.options.random() : Math.random();
|
|
11999
|
-
}
|
|
12000
|
-
// ---- graph ----
|
|
12001
|
-
build() {
|
|
12002
|
-
this.nodes.clear();
|
|
12003
|
-
this.footprints.clear();
|
|
12004
|
-
this.footprintIndex = void 0;
|
|
12005
|
-
this.workbook.sheets.forEach((sheet, s) => {
|
|
12006
|
-
for (const [row2, cells] of sheet.rows) {
|
|
12007
|
-
for (const [col, cell] of cells) {
|
|
12008
|
-
if (cell.formula) this.createNode(s, row2, col, cell, true);
|
|
12009
|
-
}
|
|
12010
|
-
}
|
|
12011
|
-
});
|
|
12012
|
-
this.built = true;
|
|
12013
|
-
this.graphChanged();
|
|
12014
|
-
}
|
|
12252
|
+
random() {
|
|
12253
|
+
return this.options.random ? this.options.random() : Math.random();
|
|
12254
|
+
}
|
|
12255
|
+
// ---- graph ----
|
|
12015
12256
|
createNode(sheet, row2, col, cell, initial) {
|
|
12016
12257
|
const formula = cell.formula ?? "";
|
|
12017
12258
|
const parsed = this.parse(formula);
|
|
@@ -12040,6 +12281,14 @@ var EngineHost = class {
|
|
|
12040
12281
|
map.set(cellKey(row2, col), node);
|
|
12041
12282
|
return node;
|
|
12042
12283
|
}
|
|
12284
|
+
/** Parses a node's text again after a structural edit rewrote it (see `FormulaNode.stale`). */
|
|
12285
|
+
refreshAst(node) {
|
|
12286
|
+
const parsed = this.parse(node.formula);
|
|
12287
|
+
delete node.stale;
|
|
12288
|
+
delete node.parseError;
|
|
12289
|
+
node.ast = parsed instanceof FormulaError ? void 0 : parsed;
|
|
12290
|
+
if (parsed instanceof FormulaError && parsed.code) node.parseError = err(parsed.code);
|
|
12291
|
+
}
|
|
12043
12292
|
removeNode(node, changed) {
|
|
12044
12293
|
const sheet = this.workbook.sheets[node.sheet];
|
|
12045
12294
|
if (node.spill && sheet) {
|
|
@@ -12470,6 +12719,7 @@ var EngineCore = class extends EngineHost {
|
|
|
12470
12719
|
return { host: this, sheet, row: row2, col, scope: void 0, depth: 0, root, legacy };
|
|
12471
12720
|
}
|
|
12472
12721
|
evaluateFormula(node) {
|
|
12722
|
+
if (node.stale) this.refreshAst(node);
|
|
12473
12723
|
if (!node.ast) return node.parseError ?? ERR.NAME;
|
|
12474
12724
|
const ast = node.ast;
|
|
12475
12725
|
const frame = this.frameFor(node.sheet, node.row, node.col, ast, node.legacy);
|
|
@@ -12487,20 +12737,363 @@ var EngineCore = class extends EngineHost {
|
|
|
12487
12737
|
}
|
|
12488
12738
|
};
|
|
12489
12739
|
|
|
12740
|
+
// xlsx/formula/shift-graph.ts
|
|
12741
|
+
var POSITIONAL = /* @__PURE__ */ new Set(["ROW", "COLUMN"]);
|
|
12742
|
+
var DESCRIPTIVE = /* @__PURE__ */ new Set(["FORMULATEXT", "CELL", "SHEET"]);
|
|
12743
|
+
var traitsCache = /* @__PURE__ */ new WeakMap();
|
|
12744
|
+
function astTraits(ast) {
|
|
12745
|
+
const cached = traitsCache.get(ast);
|
|
12746
|
+
if (cached) return cached;
|
|
12747
|
+
const sheets = /* @__PURE__ */ new Set();
|
|
12748
|
+
const traits = { complex: false, opaque: false, positional: false, descriptive: false, sheets };
|
|
12749
|
+
const stack2 = [ast];
|
|
12750
|
+
while (stack2.length) {
|
|
12751
|
+
const node = stack2.pop();
|
|
12752
|
+
switch (node.type) {
|
|
12753
|
+
case "ref":
|
|
12754
|
+
if (node.prefix) {
|
|
12755
|
+
sheets.add(node.prefix.sheet.toLowerCase());
|
|
12756
|
+
if (node.prefix.sheet2 !== void 0) {
|
|
12757
|
+
sheets.add(node.prefix.sheet2.toLowerCase());
|
|
12758
|
+
traits.complex = true;
|
|
12759
|
+
}
|
|
12760
|
+
}
|
|
12761
|
+
break;
|
|
12762
|
+
case "name":
|
|
12763
|
+
if (node.prefix) sheets.add(node.prefix.sheet.toLowerCase());
|
|
12764
|
+
traits.complex = true;
|
|
12765
|
+
break;
|
|
12766
|
+
case "structured":
|
|
12767
|
+
traits.complex = true;
|
|
12768
|
+
break;
|
|
12769
|
+
case "unary":
|
|
12770
|
+
case "percent":
|
|
12771
|
+
stack2.push(node.operand);
|
|
12772
|
+
break;
|
|
12773
|
+
case "binary":
|
|
12774
|
+
stack2.push(node.left, node.right);
|
|
12775
|
+
break;
|
|
12776
|
+
case "call":
|
|
12777
|
+
if (POSITIONAL.has(node.name)) traits.positional = true;
|
|
12778
|
+
if (DESCRIPTIVE.has(node.name)) traits.descriptive = true;
|
|
12779
|
+
if (!getFunction(node.name)) traits.complex = traits.opaque = true;
|
|
12780
|
+
stack2.push(...node.args);
|
|
12781
|
+
break;
|
|
12782
|
+
case "invoke":
|
|
12783
|
+
stack2.push(node.callee, ...node.args);
|
|
12784
|
+
break;
|
|
12785
|
+
}
|
|
12786
|
+
}
|
|
12787
|
+
traitsCache.set(ast, traits);
|
|
12788
|
+
return traits;
|
|
12789
|
+
}
|
|
12790
|
+
function intervalDelta(a2, b, shift2) {
|
|
12791
|
+
const { at, count: count2 } = shift2;
|
|
12792
|
+
if (count2 > 0) {
|
|
12793
|
+
if (b < at) return 0;
|
|
12794
|
+
if (a2 < at) return void 0;
|
|
12795
|
+
return b + count2 > (shift2.axis === "row" ? MAX_ROW : MAX_COL) ? void 0 : count2;
|
|
12796
|
+
}
|
|
12797
|
+
const last = at - count2 - 1;
|
|
12798
|
+
if (b < at) return 0;
|
|
12799
|
+
if (a2 > last) return count2;
|
|
12800
|
+
return void 0;
|
|
12801
|
+
}
|
|
12802
|
+
function areaDelta(area, sheet, shift2) {
|
|
12803
|
+
if (area.sheet !== sheet) return 0;
|
|
12804
|
+
const { start, end } = area.range;
|
|
12805
|
+
return shift2.axis === "row" ? intervalDelta(start.row, end.row, shift2) : intervalDelta(start.col, end.col, shift2);
|
|
12806
|
+
}
|
|
12807
|
+
function movedRange(range, axis, delta) {
|
|
12808
|
+
if (delta === 0) return range;
|
|
12809
|
+
return axis === "row" ? {
|
|
12810
|
+
start: { row: range.start.row + delta, col: range.start.col },
|
|
12811
|
+
end: { row: range.end.row + delta, col: range.end.col }
|
|
12812
|
+
} : {
|
|
12813
|
+
start: { row: range.start.row, col: range.start.col + delta },
|
|
12814
|
+
end: { row: range.end.row, col: range.end.col + delta }
|
|
12815
|
+
};
|
|
12816
|
+
}
|
|
12817
|
+
function reachesEdit(areas, sheet, shift2) {
|
|
12818
|
+
for (const area of areas) {
|
|
12819
|
+
if (area.sheet !== sheet) continue;
|
|
12820
|
+
if ((shift2.axis === "row" ? area.range.end.row : area.range.end.col) >= shift2.at) return true;
|
|
12821
|
+
}
|
|
12822
|
+
return false;
|
|
12823
|
+
}
|
|
12824
|
+
function intersectionMoves(area, delta, pos, nodeDelta, axis) {
|
|
12825
|
+
if (delta === nodeDelta) return false;
|
|
12826
|
+
const { start, end } = area.range;
|
|
12827
|
+
const a2 = axis === "row" ? start.row : start.col;
|
|
12828
|
+
const b = axis === "row" ? end.row : end.col;
|
|
12829
|
+
if (a2 === b) return false;
|
|
12830
|
+
return pos >= a2 && pos <= b || pos + nodeDelta >= a2 + delta && pos + nodeDelta <= b + delta;
|
|
12831
|
+
}
|
|
12832
|
+
|
|
12833
|
+
// xlsx/formula/engine-structure.ts
|
|
12834
|
+
var sameAreas = (a2, b) => a2.length === b.length && a2.every((x, i2) => {
|
|
12835
|
+
const y = b[i2];
|
|
12836
|
+
return x.sheet === y.sheet && sameRange(x.range, y.range);
|
|
12837
|
+
});
|
|
12838
|
+
var EngineStructure = class extends EngineCore {
|
|
12839
|
+
/** Formulas a structural edit left to recalculate (with their dependents) on the next pass. */
|
|
12840
|
+
structuralSeeds = /* @__PURE__ */ new Set();
|
|
12841
|
+
/** Whether the graph describes the workbook as it was before the edit just reported. */
|
|
12842
|
+
graphReady() {
|
|
12843
|
+
return this.built && !this.needsFull;
|
|
12844
|
+
}
|
|
12845
|
+
/** Parses a node's current text again and recomputes its precedents. */
|
|
12846
|
+
reanalyze(node) {
|
|
12847
|
+
const parsed = this.parse(node.formula);
|
|
12848
|
+
delete node.stale;
|
|
12849
|
+
delete node.parseError;
|
|
12850
|
+
if (parsed instanceof FormulaError) {
|
|
12851
|
+
node.ast = void 0;
|
|
12852
|
+
if (parsed.code) node.parseError = err(parsed.code);
|
|
12853
|
+
node.deps = [];
|
|
12854
|
+
node.dynamicDeps = [];
|
|
12855
|
+
return;
|
|
12856
|
+
}
|
|
12857
|
+
node.ast = parsed;
|
|
12858
|
+
const found = analyze(parsed, this, node.sheet, node.row, node.col);
|
|
12859
|
+
node.deps = found.deps;
|
|
12860
|
+
node.dynamicDeps = found.dynamicDeps;
|
|
12861
|
+
node.volatile = found.volatile;
|
|
12862
|
+
node.unsupported = found.unsupported;
|
|
12863
|
+
}
|
|
12864
|
+
/**
|
|
12865
|
+
* Moves the graph for rows or columns inserted or deleted on `sheet`, after the workbook was
|
|
12866
|
+
* changed (cells moved, formulas rewritten). Spills on the sheet, array formulas the edit cuts
|
|
12867
|
+
* and anything unexpected fall back to a rebuild on the next recalculation.
|
|
12868
|
+
*/
|
|
12869
|
+
shiftCells(sheet, shift2) {
|
|
12870
|
+
if (!this.graphReady() || !this.shiftable(sheet, shift2)) {
|
|
12871
|
+
this.invalidate();
|
|
12872
|
+
return;
|
|
12873
|
+
}
|
|
12874
|
+
const ws = this.workbook.sheets[sheet];
|
|
12875
|
+
const own = this.nodes.get(sheet);
|
|
12876
|
+
if (!ws) return;
|
|
12877
|
+
const moved = /* @__PURE__ */ new Map();
|
|
12878
|
+
if (own) {
|
|
12879
|
+
const next = /* @__PURE__ */ new Map();
|
|
12880
|
+
for (const node of own.values()) {
|
|
12881
|
+
const pos = shift2.axis === "row" ? node.row : node.col;
|
|
12882
|
+
const delta = intervalDelta(pos, pos, shift2);
|
|
12883
|
+
if (delta === void 0) {
|
|
12884
|
+
this.dropNode(node);
|
|
12885
|
+
continue;
|
|
12886
|
+
}
|
|
12887
|
+
if (delta !== 0) {
|
|
12888
|
+
moved.set(node, delta);
|
|
12889
|
+
if (shift2.axis === "row") node.row += delta;
|
|
12890
|
+
else node.col += delta;
|
|
12891
|
+
}
|
|
12892
|
+
next.set(cellKey(node.row, node.col), node);
|
|
12893
|
+
}
|
|
12894
|
+
this.nodes.set(sheet, next);
|
|
12895
|
+
}
|
|
12896
|
+
for (const map of this.nodes.values())
|
|
12897
|
+
for (const node of map.values()) {
|
|
12898
|
+
if (!this.shiftNode(node, sheet, shift2, moved.get(node) ?? 0)) {
|
|
12899
|
+
this.invalidate();
|
|
12900
|
+
return;
|
|
12901
|
+
}
|
|
12902
|
+
}
|
|
12903
|
+
this.boundsCache.clear();
|
|
12904
|
+
this.graphChanged();
|
|
12905
|
+
}
|
|
12906
|
+
/** No spill or stale spilled value on the sheet, and no array formula the edit cuts. */
|
|
12907
|
+
shiftable(sheet, shift2) {
|
|
12908
|
+
for (const node of this.footprints) {
|
|
12909
|
+
if (node.sheet !== sheet) continue;
|
|
12910
|
+
if (node.spill || node.blockedSpill) return false;
|
|
12911
|
+
if (node.arrayRange && areaDelta({ sheet, range: node.arrayRange }, sheet, shift2) === void 0)
|
|
12912
|
+
return false;
|
|
12913
|
+
}
|
|
12914
|
+
const ws = this.workbook.sheets[sheet];
|
|
12915
|
+
let spilled = false;
|
|
12916
|
+
ws?.rows.forEach((cells) => {
|
|
12917
|
+
if (!spilled) cells.forEach((cell) => spilled ||= isSpilledCell(cell));
|
|
12918
|
+
});
|
|
12919
|
+
return !spilled;
|
|
12920
|
+
}
|
|
12921
|
+
dropNode(node) {
|
|
12922
|
+
this.structuralSeeds.delete(node);
|
|
12923
|
+
this.cycles.delete(node);
|
|
12924
|
+
this.footprints.delete(node);
|
|
12925
|
+
}
|
|
12926
|
+
/** Updates one formula for the edit; false when the graph cannot follow it. */
|
|
12927
|
+
shiftNode(node, sheet, shift2, nodeDelta) {
|
|
12928
|
+
const cell = this.workbook.sheets[node.sheet]?.rows.get(node.row)?.get(node.col);
|
|
12929
|
+
if (cell?.formula === void 0) return false;
|
|
12930
|
+
if (node.arrayRange) {
|
|
12931
|
+
const delta = areaDelta({ sheet: node.sheet, range: node.arrayRange }, sheet, shift2);
|
|
12932
|
+
if (delta === void 0) return false;
|
|
12933
|
+
node.arrayRange = movedRange(node.arrayRange, shift2.axis, delta);
|
|
12934
|
+
if (!cell.arrayRange || !sameRange(node.arrayRange, normalizeRange(cell.arrayRange)))
|
|
12935
|
+
return false;
|
|
12936
|
+
}
|
|
12937
|
+
const changed = cell.formula !== node.formula;
|
|
12938
|
+
const traits = node.ast && astTraits(node.ast);
|
|
12939
|
+
const reached = reachesEdit(node.deps, sheet, shift2) || reachesEdit(node.dynamicDeps, sheet, shift2);
|
|
12940
|
+
if (!changed && !reached && nodeDelta === 0 && !traits?.descriptive && !traits?.opaque)
|
|
12941
|
+
return true;
|
|
12942
|
+
if (traits?.complex) {
|
|
12943
|
+
node.formula = cell.formula;
|
|
12944
|
+
this.reanalyze(node);
|
|
12945
|
+
this.structuralSeeds.add(node);
|
|
12946
|
+
return true;
|
|
12947
|
+
}
|
|
12948
|
+
const pos = shift2.axis === "row" ? node.row - nodeDelta : node.col - nodeDelta;
|
|
12949
|
+
const moves = { seed: !!traits?.descriptive, moved: false, cut: false };
|
|
12950
|
+
const deps = this.moveAreas(node.deps, sheet, shift2, pos, nodeDelta, moves);
|
|
12951
|
+
const dynamicDeps = this.moveAreas(node.dynamicDeps, sheet, shift2, pos, nodeDelta, moves);
|
|
12952
|
+
const { cut, moved: anyMoved } = moves;
|
|
12953
|
+
let seed = moves.seed;
|
|
12954
|
+
if (cut || changed !== anyMoved) {
|
|
12955
|
+
node.formula = cell.formula;
|
|
12956
|
+
this.reanalyze(node);
|
|
12957
|
+
this.structuralSeeds.add(node);
|
|
12958
|
+
return true;
|
|
12959
|
+
}
|
|
12960
|
+
if (traits?.positional && (anyMoved || nodeDelta !== 0)) seed = true;
|
|
12961
|
+
node.deps = deps;
|
|
12962
|
+
node.dynamicDeps = dynamicDeps;
|
|
12963
|
+
if (changed) {
|
|
12964
|
+
node.formula = cell.formula;
|
|
12965
|
+
node.stale = true;
|
|
12966
|
+
}
|
|
12967
|
+
if (seed) this.structuralSeeds.add(node);
|
|
12968
|
+
return true;
|
|
12969
|
+
}
|
|
12970
|
+
/**
|
|
12971
|
+
* Areas moved for the edit (the same list when none moves). Records in `moves` whether one
|
|
12972
|
+
* moved, one was cut (deleted, widened, pushed off the grid) and whether implicit intersection
|
|
12973
|
+
* with one can now pick another cell.
|
|
12974
|
+
*/
|
|
12975
|
+
moveAreas(list, sheet, shift2, pos, nodeDelta, moves) {
|
|
12976
|
+
let out;
|
|
12977
|
+
for (let i2 = 0; i2 < list.length; i2++) {
|
|
12978
|
+
const area = list[i2];
|
|
12979
|
+
const delta = areaDelta(area, sheet, shift2);
|
|
12980
|
+
if (delta === void 0) {
|
|
12981
|
+
moves.cut = true;
|
|
12982
|
+
continue;
|
|
12983
|
+
}
|
|
12984
|
+
if (intersectionMoves(area, delta, pos, nodeDelta, shift2.axis)) moves.seed = true;
|
|
12985
|
+
if (delta === 0) continue;
|
|
12986
|
+
moves.moved = true;
|
|
12987
|
+
out ??= list.slice();
|
|
12988
|
+
out[i2] = { sheet: area.sheet, range: movedRange(area.range, shift2.axis, delta) };
|
|
12989
|
+
}
|
|
12990
|
+
return out ?? list;
|
|
12991
|
+
}
|
|
12992
|
+
/**
|
|
12993
|
+
* Follows a sheet rename (`from` to `to`, formulas already rewritten): precedents are kept by
|
|
12994
|
+
* sheet index, so only rewritten formulas need their text parsed again, and only formulas that
|
|
12995
|
+
* name the new sheet without having been rewritten (previously unresolved), describe sheets
|
|
12996
|
+
* (CELL, SHEET, FORMULATEXT) or read defined names whose areas changed are recalculated.
|
|
12997
|
+
*/
|
|
12998
|
+
renameSheet(from, to) {
|
|
12999
|
+
if (!this.graphReady()) {
|
|
13000
|
+
this.invalidate();
|
|
13001
|
+
return;
|
|
13002
|
+
}
|
|
13003
|
+
const target = to.toLowerCase();
|
|
13004
|
+
let depsChanged = false;
|
|
13005
|
+
for (const map of this.nodes.values())
|
|
13006
|
+
for (const node of map.values()) {
|
|
13007
|
+
const cell = this.workbook.sheets[node.sheet]?.rows.get(node.row)?.get(node.col);
|
|
13008
|
+
if (cell?.formula === void 0) {
|
|
13009
|
+
this.invalidate();
|
|
13010
|
+
return;
|
|
13011
|
+
}
|
|
13012
|
+
const changed = cell.formula !== node.formula;
|
|
13013
|
+
const traits = node.ast && astTraits(node.ast);
|
|
13014
|
+
node.formula = cell.formula;
|
|
13015
|
+
if (traits?.complex || !changed && traits?.sheets.has(target)) {
|
|
13016
|
+
const deps = node.deps;
|
|
13017
|
+
const dynamicDeps = node.dynamicDeps;
|
|
13018
|
+
this.reanalyze(node);
|
|
13019
|
+
const same4 = sameAreas(deps, node.deps) && sameAreas(dynamicDeps, node.dynamicDeps);
|
|
13020
|
+
if (!same4) depsChanged = true;
|
|
13021
|
+
if (!same4 || !traits?.complex) this.structuralSeeds.add(node);
|
|
13022
|
+
} else if (changed) node.stale = true;
|
|
13023
|
+
if (traits?.descriptive || traits?.opaque) this.structuralSeeds.add(node);
|
|
13024
|
+
}
|
|
13025
|
+
if (depsChanged) this.graphChanged();
|
|
13026
|
+
}
|
|
13027
|
+
/** Takes the formulas queued by structural edits. */
|
|
13028
|
+
takeStructuralSeeds(into) {
|
|
13029
|
+
for (const node of this.structuralSeeds)
|
|
13030
|
+
if (this.nodes.get(node.sheet)?.get(cellKey(node.row, node.col)) === node) into.add(node);
|
|
13031
|
+
this.structuralSeeds.clear();
|
|
13032
|
+
}
|
|
13033
|
+
};
|
|
13034
|
+
|
|
12490
13035
|
// xlsx/formula/engine.ts
|
|
12491
|
-
var Engine = class extends
|
|
13036
|
+
var Engine = class extends EngineStructure {
|
|
13037
|
+
preparation;
|
|
13038
|
+
/** The prepared formulas the first recalculation checks (see `trustsStoredValues`). */
|
|
13039
|
+
prepared;
|
|
13040
|
+
// ---- the graph ----
|
|
13041
|
+
prepare(timeRemaining) {
|
|
13042
|
+
if (this.built || this.needsFull) return true;
|
|
13043
|
+
this.preparation ??= this.startPreparation();
|
|
13044
|
+
if (!this.preparation.run(timeRemaining)) return false;
|
|
13045
|
+
this.finishPreparation(this.preparation);
|
|
13046
|
+
return true;
|
|
13047
|
+
}
|
|
13048
|
+
discardPreparation() {
|
|
13049
|
+
if (!this.fresh || this.needsFull) return;
|
|
13050
|
+
this.preparation = void 0;
|
|
13051
|
+
this.prepared = void 0;
|
|
13052
|
+
this.structuralSeeds.clear();
|
|
13053
|
+
this.nodes.clear();
|
|
13054
|
+
this.footprints.clear();
|
|
13055
|
+
this.graphChanged();
|
|
13056
|
+
this.built = false;
|
|
13057
|
+
}
|
|
13058
|
+
/** Completes the graph, continuing a preparation that is under way. */
|
|
13059
|
+
build() {
|
|
13060
|
+
const preparation = this.preparation ?? this.startPreparation();
|
|
13061
|
+
preparation.run();
|
|
13062
|
+
this.finishPreparation(preparation);
|
|
13063
|
+
}
|
|
13064
|
+
startPreparation() {
|
|
13065
|
+
this.nodes.clear();
|
|
13066
|
+
this.footprints.clear();
|
|
13067
|
+
this.footprintIndex = void 0;
|
|
13068
|
+
this.prepared = void 0;
|
|
13069
|
+
return new GraphPreparation(
|
|
13070
|
+
this.workbook,
|
|
13071
|
+
(s, row2, col, cell) => this.createNode(s, row2, col, cell, true)
|
|
13072
|
+
);
|
|
13073
|
+
}
|
|
13074
|
+
finishPreparation(preparation) {
|
|
13075
|
+
this.preparation = void 0;
|
|
13076
|
+
this.built = true;
|
|
13077
|
+
this.graphChanged();
|
|
13078
|
+
this.reverseIndex = preparation.reverse;
|
|
13079
|
+
this.prepared = preparation.formulas;
|
|
13080
|
+
}
|
|
12492
13081
|
// ---- recalculation ----
|
|
12493
13082
|
recalculateAll() {
|
|
13083
|
+
this.fresh = false;
|
|
13084
|
+
this.prepared = void 0;
|
|
12494
13085
|
if (this.needsFull) this.releaseAllSpills();
|
|
12495
13086
|
if (!this.built || this.needsFull) this.build();
|
|
12496
13087
|
this.needsFull = false;
|
|
13088
|
+
this.structuralSeeds.clear();
|
|
12497
13089
|
this.cycles = /* @__PURE__ */ new Set();
|
|
12498
13090
|
this.run(new Set(this.allNodes()), true);
|
|
12499
13091
|
}
|
|
12500
13092
|
recalculateFrom(changes) {
|
|
12501
13093
|
const seeds = /* @__PURE__ */ new Set();
|
|
12502
|
-
if (
|
|
12503
|
-
this.
|
|
13094
|
+
if (this.fresh && !this.needsFull) {
|
|
13095
|
+
this.fresh = false;
|
|
13096
|
+
if (!this.built) this.build();
|
|
12504
13097
|
if (!this.trustsStoredValues(changes, seeds)) {
|
|
12505
13098
|
this.recalculateAll();
|
|
12506
13099
|
return;
|
|
@@ -12544,6 +13137,7 @@ var Engine = class extends EngineCore {
|
|
|
12544
13137
|
}
|
|
12545
13138
|
}
|
|
12546
13139
|
if (structural) this.graphChanged();
|
|
13140
|
+
this.takeStructuralSeeds(seeds);
|
|
12547
13141
|
const reverse2 = this.reverse();
|
|
12548
13142
|
for (const area of changed) reverse2.dependents(area.sheet, area.range, seeds);
|
|
12549
13143
|
for (const node of this.allNodes()) if (node.volatile) seeds.add(node);
|
|
@@ -12555,13 +13149,18 @@ var Engine = class extends EngineCore {
|
|
|
12555
13149
|
* without a value into `missing`.
|
|
12556
13150
|
*/
|
|
12557
13151
|
trustsStoredValues(changes, missing) {
|
|
13152
|
+
const prepared = this.prepared;
|
|
13153
|
+
this.prepared = void 0;
|
|
13154
|
+
if (!prepared) return false;
|
|
12558
13155
|
const changed = new Set(changes.map((c2) => `${c2.sheet}:${cellKey(c2.row, c2.col)}`));
|
|
12559
|
-
|
|
12560
|
-
|
|
12561
|
-
if (
|
|
13156
|
+
const current = (node) => this.nodes.get(node.sheet)?.get(cellKey(node.row, node.col)) === node;
|
|
13157
|
+
for (const node of prepared.dynamic) {
|
|
13158
|
+
if (current(node) && !changed.has(`${node.sheet}:${cellKey(node.row, node.col)}`))
|
|
12562
13159
|
return false;
|
|
13160
|
+
}
|
|
13161
|
+
for (const node of prepared.unvalued) {
|
|
12563
13162
|
const cell = this.workbook.sheets[node.sheet]?.rows.get(node.row)?.get(node.col);
|
|
12564
|
-
if (cell && cell.value === null
|
|
13163
|
+
if (current(node) && cell && cell.value === null) missing.add(node);
|
|
12565
13164
|
}
|
|
12566
13165
|
return true;
|
|
12567
13166
|
}
|
|
@@ -12575,7 +13174,10 @@ var Engine = class extends EngineCore {
|
|
|
12575
13174
|
return !!anchor?.spill && rangeHas(anchor.spill, row2, col);
|
|
12576
13175
|
}
|
|
12577
13176
|
invalidate() {
|
|
13177
|
+
this.structuralSeeds.clear();
|
|
12578
13178
|
this.releaseAllSpills();
|
|
13179
|
+
this.preparation = void 0;
|
|
13180
|
+
this.prepared = void 0;
|
|
12579
13181
|
this.nodes.clear();
|
|
12580
13182
|
this.footprints.clear();
|
|
12581
13183
|
this.graphChanged();
|
|
@@ -12620,7 +13222,7 @@ function createCalcEngine(workbook, options = {}) {
|
|
|
12620
13222
|
return new Engine(workbook, options);
|
|
12621
13223
|
}
|
|
12622
13224
|
|
|
12623
|
-
// xlsx/formula/
|
|
13225
|
+
// xlsx/formula/ref-text.ts
|
|
12624
13226
|
function safeTokens(formula) {
|
|
12625
13227
|
try {
|
|
12626
13228
|
return tokenize(formula);
|
|
@@ -12639,50 +13241,26 @@ function formatRefSpec(spec2) {
|
|
|
12639
13241
|
if (spec2.kind === "cell") return a2;
|
|
12640
13242
|
return `${a2}:${cornerText(spec2.end, spec2.kind)}`;
|
|
12641
13243
|
}
|
|
12642
|
-
function
|
|
13244
|
+
function rewriteRef(token, ref) {
|
|
12643
13245
|
const prefix = token.prefix?.text ?? "";
|
|
12644
13246
|
if (!ref) return `${prefix}#REF!`;
|
|
12645
13247
|
return `${prefix}${formatRefSpec(ref)}${token.spill ? "#" : ""}`;
|
|
12646
13248
|
}
|
|
12647
13249
|
var sameSpec = (a2, b) => a2.kind === b.kind && a2.start.row === b.start.row && a2.start.col === b.start.col && a2.end.row === b.end.row && a2.end.col === b.end.col;
|
|
12648
|
-
|
|
12649
|
-
|
|
12650
|
-
|
|
12651
|
-
|
|
12652
|
-
|
|
12653
|
-
|
|
12654
|
-
const move = (c2) => {
|
|
12655
|
-
const row2 = spec2.kind === "cols" || c2.rowAbs ? c2.row : c2.row + dRow;
|
|
12656
|
-
const col = spec2.kind === "rows" || c2.colAbs ? c2.col : c2.col + dCol;
|
|
12657
|
-
if (row2 < 0 || row2 > MAX_ROW || col < 0 || col > MAX_COL) return void 0;
|
|
12658
|
-
return { ...c2, row: row2, col };
|
|
12659
|
-
};
|
|
12660
|
-
const start = move(spec2.start);
|
|
12661
|
-
const end = move(spec2.end);
|
|
12662
|
-
const next = start && end ? { kind: spec2.kind, start, end } : void 0;
|
|
12663
|
-
if (next && sameSpec(next, spec2)) continue;
|
|
12664
|
-
token.text = rewrite(token, next);
|
|
12665
|
-
}
|
|
12666
|
-
return joinTokens(tokens2);
|
|
13250
|
+
var needsQuote = (name) => !/^[A-Za-z_¡-][A-Za-z0-9_.¡-]*$/.test(name) || /^[A-Za-z]{1,3}\d+$/.test(name) || /^(?:R\d*C?\d*|C\d*)$/i.test(name) || /^(?:TRUE|FALSE)$/i.test(name);
|
|
13251
|
+
function prefixText(prefix) {
|
|
13252
|
+
const sheets = prefix.sheet2 !== void 0 ? `${prefix.sheet}:${prefix.sheet2}` : prefix.sheet;
|
|
13253
|
+
const book = prefix.book !== void 0 ? `[${prefix.book}]` : "";
|
|
13254
|
+
const quote2 = needsQuote(prefix.sheet) || prefix.sheet2 !== void 0 && needsQuote(prefix.sheet2);
|
|
13255
|
+
return quote2 ? `'${(book + sheets).replace(/'/g, "''")}'!` : `${book}${sheets}!`;
|
|
12667
13256
|
}
|
|
12668
|
-
|
|
12669
|
-
|
|
12670
|
-
|
|
12671
|
-
|
|
12672
|
-
|
|
12673
|
-
|
|
12674
|
-
|
|
12675
|
-
const na2 = a2 >= at ? a2 + count2 : a2;
|
|
12676
|
-
const nb2 = b >= at ? b + count2 : b;
|
|
12677
|
-
if (nb2 > max) return na2 > max ? void 0 : [na2, max];
|
|
12678
|
-
return [na2, nb2];
|
|
12679
|
-
}
|
|
12680
|
-
const n2 = -count2;
|
|
12681
|
-
const last = at + n2 - 1;
|
|
12682
|
-
if (a2 >= at && b <= last) return void 0;
|
|
12683
|
-
const na = a2 < at ? a2 : a2 <= last ? at : a2 - n2;
|
|
12684
|
-
const nb = b < at ? b : b <= last ? at - 1 : b - n2;
|
|
12685
|
-
return [na, nb];
|
|
13257
|
+
|
|
13258
|
+
// xlsx/formula/shift-formula.ts
|
|
13259
|
+
var templates = /* @__PURE__ */ new Map();
|
|
13260
|
+
var MAX_TEMPLATES2 = 2e5;
|
|
13261
|
+
function remember(text3, template) {
|
|
13262
|
+
if (templates.size >= MAX_TEMPLATES2) templates.clear();
|
|
13263
|
+
templates.set(text3, template);
|
|
12686
13264
|
}
|
|
12687
13265
|
function mergeSpacedAreas(tokens2) {
|
|
12688
13266
|
const out = [];
|
|
@@ -12709,63 +13287,145 @@ function mergeSpacedAreas(tokens2) {
|
|
|
12709
13287
|
}
|
|
12710
13288
|
return out;
|
|
12711
13289
|
}
|
|
12712
|
-
function
|
|
12713
|
-
|
|
13290
|
+
function templateOf(formula) {
|
|
13291
|
+
const cached = templates.get(formula);
|
|
13292
|
+
if (cached !== void 0) return cached;
|
|
12714
13293
|
const raw2 = safeTokens(formula);
|
|
12715
|
-
|
|
12716
|
-
|
|
12717
|
-
|
|
12718
|
-
|
|
12719
|
-
|
|
12720
|
-
|
|
12721
|
-
|
|
12722
|
-
|
|
12723
|
-
|
|
12724
|
-
|
|
12725
|
-
|
|
12726
|
-
|
|
12727
|
-
|
|
12728
|
-
|
|
12729
|
-
|
|
12730
|
-
|
|
12731
|
-
|
|
12732
|
-
|
|
12733
|
-
|
|
12734
|
-
if (shifted2) {
|
|
12735
|
-
const [a2, b] = shifted2;
|
|
12736
|
-
const nlo = isRow ? { ...lo, row: a2 } : { ...lo, col: a2 };
|
|
12737
|
-
const nhi = isRow ? { ...hi, row: b } : { ...hi, col: b };
|
|
12738
|
-
next = { kind: ref.kind, start: startFirst ? nlo : nhi, end: startFirst ? nhi : nlo };
|
|
12739
|
-
if (ref.kind === "cell") next.end = next.start;
|
|
13294
|
+
let template = null;
|
|
13295
|
+
if (raw2) {
|
|
13296
|
+
template = [];
|
|
13297
|
+
let literal2 = "";
|
|
13298
|
+
for (const token of mergeSpacedAreas(raw2)) {
|
|
13299
|
+
if (token.kind !== "ref" && !(token.kind === "name" && token.prefix)) {
|
|
13300
|
+
literal2 += token.text;
|
|
13301
|
+
continue;
|
|
13302
|
+
}
|
|
13303
|
+
if (literal2) template.push(literal2);
|
|
13304
|
+
literal2 = "";
|
|
13305
|
+
const part = { kind: token.kind, text: token.text };
|
|
13306
|
+
if (token.prefix) {
|
|
13307
|
+
part.prefix = token.prefix;
|
|
13308
|
+
if (token.prefix.book === void 0) part.sheet = token.prefix.sheet.toLowerCase();
|
|
13309
|
+
}
|
|
13310
|
+
if (token.ref) part.ref = token.ref;
|
|
13311
|
+
if (token.spill) part.spill = true;
|
|
13312
|
+
template.push(part);
|
|
12740
13313
|
}
|
|
12741
|
-
if (
|
|
12742
|
-
token.text = rewrite(token, next);
|
|
13314
|
+
if (literal2) template.push(literal2);
|
|
12743
13315
|
}
|
|
12744
|
-
|
|
13316
|
+
remember(formula, template);
|
|
13317
|
+
return template;
|
|
12745
13318
|
}
|
|
12746
|
-
|
|
12747
|
-
|
|
12748
|
-
|
|
12749
|
-
|
|
12750
|
-
|
|
12751
|
-
|
|
13319
|
+
function rewriteTemplate(formula, rewrite2) {
|
|
13320
|
+
const template = templateOf(formula);
|
|
13321
|
+
if (!template) return formula;
|
|
13322
|
+
let next;
|
|
13323
|
+
for (let i2 = 0; i2 < template.length; i2++) {
|
|
13324
|
+
const part = template[i2];
|
|
13325
|
+
if (typeof part === "string") continue;
|
|
13326
|
+
const changed = rewrite2(part);
|
|
13327
|
+
if (!changed) continue;
|
|
13328
|
+
next ??= template.slice();
|
|
13329
|
+
next[i2] = changed;
|
|
13330
|
+
}
|
|
13331
|
+
if (!next) return formula;
|
|
13332
|
+
const text3 = next.map((part) => typeof part === "string" ? part : part.text).join("");
|
|
13333
|
+
remember(text3, next);
|
|
13334
|
+
return text3;
|
|
13335
|
+
}
|
|
13336
|
+
function shiftInterval(a2, b, at, count2, max) {
|
|
13337
|
+
if (count2 > 0) {
|
|
13338
|
+
const na2 = a2 >= at ? a2 + count2 : a2;
|
|
13339
|
+
const nb2 = b >= at ? b + count2 : b;
|
|
13340
|
+
if (nb2 > max) return na2 > max ? void 0 : [na2, max];
|
|
13341
|
+
return [na2, nb2];
|
|
13342
|
+
}
|
|
13343
|
+
const n2 = -count2;
|
|
13344
|
+
const last = at + n2 - 1;
|
|
13345
|
+
if (a2 >= at && b <= last) return void 0;
|
|
13346
|
+
const na = a2 < at ? a2 : a2 <= last ? at : a2 - n2;
|
|
13347
|
+
const nb = b < at ? b : b <= last ? at - 1 : b - n2;
|
|
13348
|
+
return [na, nb];
|
|
13349
|
+
}
|
|
13350
|
+
function shiftRef(ref, spec2) {
|
|
13351
|
+
const isRow = spec2.axis === "row";
|
|
13352
|
+
if (isRow && ref.kind === "cols" || !isRow && ref.kind === "rows") return ref;
|
|
13353
|
+
const startFirst = isRow ? ref.start.row <= ref.end.row : ref.start.col <= ref.end.col;
|
|
13354
|
+
const lo = startFirst ? ref.start : ref.end;
|
|
13355
|
+
const hi = startFirst ? ref.end : ref.start;
|
|
13356
|
+
const shifted2 = shiftInterval(
|
|
13357
|
+
isRow ? lo.row : lo.col,
|
|
13358
|
+
isRow ? hi.row : hi.col,
|
|
13359
|
+
spec2.at,
|
|
13360
|
+
spec2.count,
|
|
13361
|
+
isRow ? MAX_ROW : MAX_COL
|
|
13362
|
+
);
|
|
13363
|
+
if (!shifted2) return void 0;
|
|
13364
|
+
const [a2, b] = shifted2;
|
|
13365
|
+
const nlo = isRow ? { ...lo, row: a2 } : { ...lo, col: a2 };
|
|
13366
|
+
const nhi = isRow ? { ...hi, row: b } : { ...hi, col: b };
|
|
13367
|
+
const next = {
|
|
13368
|
+
kind: ref.kind,
|
|
13369
|
+
start: startFirst ? nlo : nhi,
|
|
13370
|
+
end: startFirst ? nhi : nlo
|
|
13371
|
+
};
|
|
13372
|
+
if (ref.kind === "cell") next.end = next.start;
|
|
13373
|
+
return sameSpec(next, ref) ? ref : next;
|
|
13374
|
+
}
|
|
13375
|
+
function shiftFormula(formula, formulaSheet, spec2) {
|
|
13376
|
+
if (spec2.count === 0) return formula;
|
|
13377
|
+
const sheet = spec2.sheet.toLowerCase();
|
|
13378
|
+
const own = formulaSheet.toLowerCase() === sheet;
|
|
13379
|
+
return rewriteTemplate(formula, (part) => {
|
|
13380
|
+
if (part.kind !== "ref" || !part.ref || (part.prefix ? part.sheet !== sheet : !own))
|
|
13381
|
+
return void 0;
|
|
13382
|
+
const next = shiftRef(part.ref, spec2);
|
|
13383
|
+
if (next === part.ref) return void 0;
|
|
13384
|
+
const out = { kind: "ref", text: rewriteRef(part, next) };
|
|
13385
|
+
if (part.prefix) out.prefix = part.prefix;
|
|
13386
|
+
if (part.sheet !== void 0) out.sheet = part.sheet;
|
|
13387
|
+
if (next) out.ref = next;
|
|
13388
|
+
if (part.spill) out.spill = true;
|
|
13389
|
+
return out;
|
|
13390
|
+
});
|
|
12752
13391
|
}
|
|
12753
13392
|
function renameSheetInFormula(formula, oldName, newName) {
|
|
12754
|
-
const tokens2 = safeTokens(formula);
|
|
12755
|
-
if (!tokens2) return formula;
|
|
12756
13393
|
const lower2 = oldName.toLowerCase();
|
|
12757
|
-
|
|
12758
|
-
const prefix =
|
|
12759
|
-
if (!prefix ||
|
|
12760
|
-
const first2 =
|
|
13394
|
+
return rewriteTemplate(formula, (part) => {
|
|
13395
|
+
const prefix = part.prefix;
|
|
13396
|
+
if (!prefix || part.sheet === void 0) return void 0;
|
|
13397
|
+
const first2 = part.sheet === lower2;
|
|
12761
13398
|
const second = prefix.sheet2?.toLowerCase() === lower2;
|
|
12762
|
-
if (!first2 && !second)
|
|
13399
|
+
if (!first2 && !second) return void 0;
|
|
12763
13400
|
const renamed = { ...prefix, sheet: first2 ? newName : prefix.sheet };
|
|
12764
13401
|
if (prefix.sheet2 !== void 0) renamed.sheet2 = second ? newName : prefix.sheet2;
|
|
12765
13402
|
const text3 = prefixText(renamed);
|
|
12766
|
-
token.text = text3 + token.text.slice(prefix.text.length);
|
|
12767
13403
|
renamed.text = text3;
|
|
12768
|
-
|
|
13404
|
+
const out = { ...part, text: text3 + part.text.slice(prefix.text.length) };
|
|
13405
|
+
out.prefix = renamed;
|
|
13406
|
+
out.sheet = renamed.sheet.toLowerCase();
|
|
13407
|
+
return out;
|
|
13408
|
+
});
|
|
13409
|
+
}
|
|
13410
|
+
|
|
13411
|
+
// xlsx/formula/transform.ts
|
|
13412
|
+
function translateFormula(formula, dRow, dCol) {
|
|
13413
|
+
const tokens2 = safeTokens(formula);
|
|
13414
|
+
if (!tokens2) return formula;
|
|
13415
|
+
for (const token of tokens2) {
|
|
13416
|
+
if (token.kind !== "ref" || !token.ref) continue;
|
|
13417
|
+
const spec2 = token.ref;
|
|
13418
|
+
const move = (c2) => {
|
|
13419
|
+
const row2 = spec2.kind === "cols" || c2.rowAbs ? c2.row : c2.row + dRow;
|
|
13420
|
+
const col = spec2.kind === "rows" || c2.colAbs ? c2.col : c2.col + dCol;
|
|
13421
|
+
if (row2 < 0 || row2 > MAX_ROW || col < 0 || col > MAX_COL) return void 0;
|
|
13422
|
+
return { ...c2, row: row2, col };
|
|
13423
|
+
};
|
|
13424
|
+
const start = move(spec2.start);
|
|
13425
|
+
const end = move(spec2.end);
|
|
13426
|
+
const next = start && end ? { kind: spec2.kind, start, end } : void 0;
|
|
13427
|
+
if (next && sameSpec(next, spec2)) continue;
|
|
13428
|
+
token.text = rewriteRef(token, next);
|
|
12769
13429
|
}
|
|
12770
13430
|
return joinTokens(tokens2);
|
|
12771
13431
|
}
|
|
@@ -15592,7 +16252,7 @@ var FUTURE_FUNCTIONS = new Set(
|
|
|
15592
16252
|
"AGGREGATE BETA.DIST BETA.INV BINOM.DIST BINOM.INV CEILING.PRECISE CHISQ.DIST CHISQ.DIST.RT CHISQ.INV CHISQ.INV.RT CHISQ.TEST CONFIDENCE.NORM CONFIDENCE.T COVARIANCE.P COVARIANCE.S ERF.PRECISE ERFC.PRECISE EXPON.DIST F.DIST F.DIST.RT F.INV F.INV.RT F.TEST FLOOR.PRECISE GAMMA.DIST GAMMA.INV GAMMALN.PRECISE HYPGEOM.DIST LOGNORM.DIST LOGNORM.INV MODE.MULT MODE.SNGL NEGBINOM.DIST NETWORKDAYS.INTL NORM.DIST NORM.INV NORM.S.DIST NORM.S.INV PERCENTILE.EXC PERCENTILE.INC PERCENTRANK.EXC PERCENTRANK.INC POISSON.DIST QUARTILE.EXC QUARTILE.INC RANK.AVG RANK.EQ STDEV.P STDEV.S T.DIST T.DIST.2T T.DIST.RT T.INV T.INV.2T T.TEST VAR.P VAR.S WEIBULL.DIST WORKDAY.INTL ACOT ACOTH ARABIC BASE BINOM.DIST.RANGE BITAND BITLSHIFT BITOR BITRSHIFT BITXOR CEILING.MATH COMBINA COT COTH CSC CSCH DAYS DECIMAL ENCODEURL FILTERXML FLOOR.MATH FORMULATEXT GAMMA GAUSS IFNA IMCOSH IMCOT IMCSC IMCSCH IMSEC IMSECH IMSINH IMTAN ISFORMULA ISOWEEKNUM MUNIT NUMBERVALUE PDURATION PERMUTATIONA PHI RRI SEC SECH SHEET SHEETS SKEW.P UNICHAR UNICODE WEBSERVICE XOR CONCAT FORECAST.ETS FORECAST.ETS.CONFINT FORECAST.ETS.SEASONALITY FORECAST.ETS.STAT FORECAST.LINEAR IFS MAXIFS MINIFS SWITCH TEXTJOIN XLOOKUP XMATCH FILTER SORT SORTBY UNIQUE SEQUENCE RANDARRAY LET LAMBDA TEXTBEFORE TEXTAFTER TEXTSPLIT VSTACK HSTACK TAKE DROP CHOOSEROWS CHOOSECOLS TOCOL TOROW WRAPROWS WRAPCOLS EXPAND ARRAYTOTEXT VALUETOTEXT ISOMITTED BYROW BYCOL MAP REDUCE SCAN MAKEARRAY IMAGE GROUPBY PIVOTBY PERCENTOF REGEXTEST REGEXEXTRACT REGEXREPLACE TRIMRANGE ANCHORARRAY SINGLE STOCKHISTORY FIELDVALUE".split(" ")
|
|
15593
16253
|
);
|
|
15594
16254
|
var WORKSHEET_PREFIXED = /* @__PURE__ */ new Set(["FILTER", "SORT"]);
|
|
15595
|
-
function
|
|
16255
|
+
function rewrite(formula, visit2) {
|
|
15596
16256
|
const out = [];
|
|
15597
16257
|
let i2 = 0;
|
|
15598
16258
|
while (i2 < formula.length) {
|
|
@@ -15635,7 +16295,7 @@ function rewrite2(formula, visit2) {
|
|
|
15635
16295
|
}
|
|
15636
16296
|
function stripFuturePrefixes(formula) {
|
|
15637
16297
|
if (!formula.includes("_xl")) return formula;
|
|
15638
|
-
const plain2 =
|
|
16298
|
+
const plain2 = rewrite(formula, (token, next, out) => {
|
|
15639
16299
|
if (!next.startsWith("(")) return false;
|
|
15640
16300
|
const stripped = token.replace(/^(_xlfn\.)?(_xlws\.)?/i, "");
|
|
15641
16301
|
if (stripped === token) return false;
|
|
@@ -15645,7 +16305,7 @@ function stripFuturePrefixes(formula) {
|
|
|
15645
16305
|
return fromStoredSyntax(plain2);
|
|
15646
16306
|
}
|
|
15647
16307
|
function addFuturePrefixes(formula) {
|
|
15648
|
-
return
|
|
16308
|
+
return rewrite(toStoredSyntax(formula), (token, next, out) => {
|
|
15649
16309
|
if (!next.startsWith("(")) return false;
|
|
15650
16310
|
const upper2 = token.toUpperCase();
|
|
15651
16311
|
if (!FUTURE_FUNCTIONS.has(upper2)) return false;
|
|
@@ -17727,13 +18387,13 @@ function dataBarLengths(rule, node) {
|
|
|
17727
18387
|
maxLength: rule.maxLength ?? numAttr(bar, "maxLength") ?? 90
|
|
17728
18388
|
};
|
|
17729
18389
|
}
|
|
17730
|
-
function rewriteConditionalExtension(rule,
|
|
18390
|
+
function rewriteConditionalExtension(rule, rewrite2) {
|
|
17731
18391
|
if (!rule.extensionXml) return;
|
|
17732
18392
|
const doc = parseXml(rule.extensionXml);
|
|
17733
18393
|
let changed = false;
|
|
17734
18394
|
for (const formula of descendants(doc.documentElement, "f", XM)) {
|
|
17735
18395
|
const before = formula.textContent ?? "";
|
|
17736
|
-
const next =
|
|
18396
|
+
const next = rewrite2(before);
|
|
17737
18397
|
if (before !== next) {
|
|
17738
18398
|
formula.textContent = next;
|
|
17739
18399
|
changed = true;
|
|
@@ -19876,6 +20536,7 @@ Reply:
|
|
|
19876
20536
|
}
|
|
19877
20537
|
|
|
19878
20538
|
// chart/bar-cluster-geometry.ts
|
|
20539
|
+
var DEFAULT_BAR_GAP_WIDTH = 150;
|
|
19879
20540
|
function assertBarClusterOptions(options) {
|
|
19880
20541
|
for (const [field, min, max] of [
|
|
19881
20542
|
["barGapWidth", 0, 500],
|
|
@@ -19889,7 +20550,8 @@ function assertBarClusterOptions(options) {
|
|
|
19889
20550
|
function clusteredBarGeometry(barGroupWidth, seriesCount, chartData) {
|
|
19890
20551
|
const overlap = chartData.barOverlap ?? 0;
|
|
19891
20552
|
const overlapSpan = 1 + (seriesCount - 1) * (1 - overlap / 100);
|
|
19892
|
-
const
|
|
20553
|
+
const gapWidth = chartData.barGapWidth ?? DEFAULT_BAR_GAP_WIDTH;
|
|
20554
|
+
const singleBarWidth = barGroupWidth / (overlapSpan + Math.max(gapWidth, 0) / 100);
|
|
19893
20555
|
const step2 = singleBarWidth * (1 - overlap / 100);
|
|
19894
20556
|
return { singleBarWidth, step: step2, clusterWidth: singleBarWidth + step2 * (seriesCount - 1) };
|
|
19895
20557
|
}
|
|
@@ -24381,13 +25043,13 @@ function linearTrend(values2) {
|
|
|
24381
25043
|
const slope = den ? num3 / den : 0;
|
|
24382
25044
|
return (k) => Number((meanY + slope * (k - meanX)).toPrecision(15));
|
|
24383
25045
|
}
|
|
24384
|
-
var
|
|
25046
|
+
var isDigit5 = (ch) => ch !== void 0 && ch >= "0" && ch <= "9";
|
|
24385
25047
|
function matchTextNumber(text3) {
|
|
24386
25048
|
let end = text3.length;
|
|
24387
|
-
while (end > 0 && !
|
|
25049
|
+
while (end > 0 && !isDigit5(text3[end - 1])) end--;
|
|
24388
25050
|
if (end === 0) return null;
|
|
24389
25051
|
let start = end;
|
|
24390
|
-
while (start > 0 &&
|
|
25052
|
+
while (start > 0 && isDigit5(text3[start - 1])) start--;
|
|
24391
25053
|
return [text3, text3.slice(0, start), text3.slice(start, end), text3.slice(end)];
|
|
24392
25054
|
}
|
|
24393
25055
|
var QUARTER = /^(q|qtr|quarter)(\s?)([1-4])$/i;
|
|
@@ -24570,10 +25232,10 @@ function removeValidationArea(rules, area) {
|
|
|
24570
25232
|
}
|
|
24571
25233
|
|
|
24572
25234
|
// xlsx/edit/conditional-formulas.ts
|
|
24573
|
-
function rewriteConditionalRule(rule,
|
|
25235
|
+
function rewriteConditionalRule(rule, rewrite2) {
|
|
24574
25236
|
const safe2 = (formula) => {
|
|
24575
25237
|
try {
|
|
24576
|
-
return
|
|
25238
|
+
return rewrite2(formula);
|
|
24577
25239
|
} catch {
|
|
24578
25240
|
return formula;
|
|
24579
25241
|
}
|
|
@@ -25092,7 +25754,7 @@ function shiftPreservedXml(sheet, shift2, moveRange, banded) {
|
|
|
25092
25754
|
(xml) => xml.includes("sqref")
|
|
25093
25755
|
);
|
|
25094
25756
|
}
|
|
25095
|
-
function rewritePreservedFormulas(sheet,
|
|
25757
|
+
function rewritePreservedFormulas(sheet, rewrite2) {
|
|
25096
25758
|
editEntries(
|
|
25097
25759
|
sheet,
|
|
25098
25760
|
"extLst",
|
|
@@ -25102,7 +25764,7 @@ function rewritePreservedFormulas(sheet, rewrite3) {
|
|
|
25102
25764
|
const text3 = f6.textContent ?? "";
|
|
25103
25765
|
let next = text3;
|
|
25104
25766
|
try {
|
|
25105
|
-
next =
|
|
25767
|
+
next = rewrite2(text3, sheet.name);
|
|
25106
25768
|
} catch {
|
|
25107
25769
|
next = text3;
|
|
25108
25770
|
}
|
|
@@ -25117,46 +25779,46 @@ function rewritePreservedFormulas(sheet, rewrite3) {
|
|
|
25117
25779
|
}
|
|
25118
25780
|
|
|
25119
25781
|
// xlsx/edit/shift-formulas.ts
|
|
25120
|
-
function safe(
|
|
25782
|
+
function safe(rewrite2, formula, formulaSheet) {
|
|
25121
25783
|
try {
|
|
25122
|
-
return
|
|
25784
|
+
return rewrite2(formula, formulaSheet);
|
|
25123
25785
|
} catch {
|
|
25124
25786
|
return formula;
|
|
25125
25787
|
}
|
|
25126
25788
|
}
|
|
25127
|
-
function rewriteFormulas(workbook,
|
|
25128
|
-
for (const sheet of workbook.sheets) rewriteSheetFormulas(sheet,
|
|
25789
|
+
function rewriteFormulas(workbook, rewrite2) {
|
|
25790
|
+
for (const sheet of workbook.sheets) rewriteSheetFormulas(sheet, rewrite2);
|
|
25129
25791
|
for (const definedName of workbook.definedNames) {
|
|
25130
25792
|
const local = definedName.localSheet === void 0 ? void 0 : workbook.sheets[definedName.localSheet];
|
|
25131
|
-
definedName.formula = safe(
|
|
25793
|
+
definedName.formula = safe(rewrite2, definedName.formula, local?.name ?? "");
|
|
25132
25794
|
}
|
|
25133
25795
|
}
|
|
25134
|
-
function rewriteSheetFormulas(sheet,
|
|
25135
|
-
rewritePreservedFormulas(sheet,
|
|
25796
|
+
function rewriteSheetFormulas(sheet, rewrite2) {
|
|
25797
|
+
rewritePreservedFormulas(sheet, rewrite2);
|
|
25136
25798
|
{
|
|
25137
25799
|
const name = sheet.name;
|
|
25138
25800
|
for (const table2 of sheet.tables)
|
|
25139
25801
|
for (const column of table2.columns)
|
|
25140
25802
|
if (column.calculatedColumnFormula !== void 0)
|
|
25141
|
-
column.calculatedColumnFormula = safe(
|
|
25803
|
+
column.calculatedColumnFormula = safe(rewrite2, column.calculatedColumnFormula, name);
|
|
25142
25804
|
for (const cells of sheet.rows.values())
|
|
25143
25805
|
for (const cell of cells.values())
|
|
25144
|
-
if (cell.formula !== void 0) cell.formula = safe(
|
|
25806
|
+
if (cell.formula !== void 0) cell.formula = safe(rewrite2, cell.formula, name);
|
|
25145
25807
|
for (const cf of sheet.conditionalFormats)
|
|
25146
|
-
for (const rule of cf.rules) rewriteConditionalRule(rule, (f6) =>
|
|
25808
|
+
for (const rule of cf.rules) rewriteConditionalRule(rule, (f6) => rewrite2(f6, name));
|
|
25147
25809
|
for (const dv of sheet.dataValidations) {
|
|
25148
|
-
if (dv.formula1 !== void 0) dv.formula1 = safe(
|
|
25149
|
-
if (dv.formula2 !== void 0) dv.formula2 = safe(
|
|
25810
|
+
if (dv.formula1 !== void 0) dv.formula1 = safe(rewrite2, dv.formula1, name);
|
|
25811
|
+
if (dv.formula2 !== void 0) dv.formula2 = safe(rewrite2, dv.formula2, name);
|
|
25150
25812
|
}
|
|
25151
25813
|
for (const link of sheet.hyperlinks)
|
|
25152
25814
|
if (link.location && /![A-Za-z$]/.test(link.location))
|
|
25153
|
-
link.location = safe(
|
|
25815
|
+
link.location = safe(rewrite2, link.location, name);
|
|
25154
25816
|
for (const drawing of sheet.drawings) {
|
|
25155
25817
|
if (drawing.kind !== "chart") continue;
|
|
25156
25818
|
for (const series of drawing.series) {
|
|
25157
|
-
if (series.nameRef) series.nameRef = safe(
|
|
25158
|
-
if (series.categoriesRef) series.categoriesRef = safe(
|
|
25159
|
-
if (series.valuesRef) series.valuesRef = safe(
|
|
25819
|
+
if (series.nameRef) series.nameRef = safe(rewrite2, series.nameRef, name);
|
|
25820
|
+
if (series.categoriesRef) series.categoriesRef = safe(rewrite2, series.categoriesRef, name);
|
|
25821
|
+
if (series.valuesRef) series.valuesRef = safe(rewrite2, series.valuesRef, name);
|
|
25160
25822
|
}
|
|
25161
25823
|
}
|
|
25162
25824
|
}
|
|
@@ -25343,7 +26005,7 @@ function shiftAxis(ctx, s, axis, at, count2, insert) {
|
|
|
25343
26005
|
applyAxisShift(ctx, sheet, shift2);
|
|
25344
26006
|
if (insert) inheritFormats(sheet, axis, at, count2);
|
|
25345
26007
|
},
|
|
25346
|
-
{ sheet: s, structural: true }
|
|
26008
|
+
{ sheet: s, structural: true, calc: { kind: "shift", sheet: s, shift: shift2 } }
|
|
25347
26009
|
);
|
|
25348
26010
|
}
|
|
25349
26011
|
var insertRows = (ctx, s, at, count2) => shiftAxis(ctx, s, "row", at, count2, true);
|
|
@@ -27161,6 +27823,14 @@ function setCalcMode(ctx, mode) {
|
|
|
27161
27823
|
|
|
27162
27824
|
// xlsx/edit/session-calc.ts
|
|
27163
27825
|
var isStructural = (step2) => step2.structural || step2.entries.some((entry3) => entry3.before.kind !== "cells");
|
|
27826
|
+
function hintFor(step2, mode) {
|
|
27827
|
+
const hint = step2.calc;
|
|
27828
|
+
if (!hint) return void 0;
|
|
27829
|
+
if (hint.kind === "rename")
|
|
27830
|
+
return mode === "undo" ? { kind: "rename", from: hint.to, to: hint.from } : hint;
|
|
27831
|
+
return mode === "undo" ? void 0 : hint;
|
|
27832
|
+
}
|
|
27833
|
+
var settingsOf = (workbook) => `${workbook.iterate ? `${workbook.iterate.count}:${workbook.iterate.delta}` : ""}|${workbook.date1904}`;
|
|
27164
27834
|
var SessionCalculator = class {
|
|
27165
27835
|
constructor(workbook, calc, enabled) {
|
|
27166
27836
|
this.workbook = workbook;
|
|
@@ -27170,43 +27840,113 @@ var SessionCalculator = class {
|
|
|
27170
27840
|
workbook;
|
|
27171
27841
|
calc;
|
|
27172
27842
|
enabled;
|
|
27173
|
-
/** Structural edits
|
|
27843
|
+
/** Structural edits the engine could not follow leave the dependency graph stale (manual mode). */
|
|
27174
27844
|
staleGraph = false;
|
|
27845
|
+
/** Cells changed in manual mode since the last calculation. */
|
|
27846
|
+
dirty = [];
|
|
27847
|
+
/** The settings at the last calculation; undefined before the first. */
|
|
27848
|
+
calculated;
|
|
27175
27849
|
/** Recalculates after an applied, undone or redone step (failures become warnings). */
|
|
27176
|
-
afterStep(step2) {
|
|
27177
|
-
if (!this.enabled)
|
|
27850
|
+
afterStep(step2, mode = "apply") {
|
|
27851
|
+
if (!this.enabled) {
|
|
27852
|
+
this.calc.discardPreparation();
|
|
27853
|
+
return;
|
|
27854
|
+
}
|
|
27855
|
+
const structural = isStructural(step2);
|
|
27856
|
+
const hint = structural ? hintFor(step2, mode) : void 0;
|
|
27178
27857
|
if (calcModeOf(this.workbook) === "manual") {
|
|
27179
|
-
if (
|
|
27858
|
+
if (hint && !this.staleGraph && !this.dirty.length) {
|
|
27859
|
+
this.guard(() => this.follow(hint));
|
|
27860
|
+
return;
|
|
27861
|
+
}
|
|
27862
|
+
this.calc.discardPreparation();
|
|
27863
|
+
if (structural) this.staleGraph = true;
|
|
27864
|
+
else this.dirty.push(...touchedCells(step2));
|
|
27865
|
+
return;
|
|
27866
|
+
}
|
|
27867
|
+
if (hint && !this.staleGraph) {
|
|
27868
|
+
this.guard(() => {
|
|
27869
|
+
this.follow(hint);
|
|
27870
|
+
this.calc.recalculateFrom(touchedCells(step2));
|
|
27871
|
+
this.calculated = settingsOf(this.workbook);
|
|
27872
|
+
});
|
|
27180
27873
|
return;
|
|
27181
27874
|
}
|
|
27182
|
-
this.recalc(
|
|
27875
|
+
this.recalc(structural, () => touchedCells(step2));
|
|
27183
27876
|
}
|
|
27184
27877
|
/** Recalculates after a change applied outside the history (a collaborator's edit). */
|
|
27185
27878
|
afterExternal(structural, cells) {
|
|
27186
|
-
if (!this.enabled)
|
|
27187
|
-
|
|
27879
|
+
if (!this.enabled || calcModeOf(this.workbook) === "manual") {
|
|
27880
|
+
this.calc.discardPreparation();
|
|
27881
|
+
if (!this.enabled) return;
|
|
27188
27882
|
if (structural) this.staleGraph = true;
|
|
27883
|
+
else this.dirty.push(...cells);
|
|
27189
27884
|
return;
|
|
27190
27885
|
}
|
|
27191
27886
|
this.recalc(structural, () => cells);
|
|
27192
27887
|
}
|
|
27193
|
-
|
|
27888
|
+
follow(hint) {
|
|
27889
|
+
if (hint.kind === "shift") this.calc.shiftCells(hint.sheet, hint.shift);
|
|
27890
|
+
else this.calc.renameSheet(hint.from, hint.to);
|
|
27891
|
+
}
|
|
27892
|
+
guard(run2) {
|
|
27893
|
+
try {
|
|
27894
|
+
run2();
|
|
27895
|
+
} catch (error) {
|
|
27896
|
+
const message = `Recalculation failed: ${error instanceof Error ? error.message : String(error)}`;
|
|
27897
|
+
if (!this.workbook.warnings.includes(message)) this.workbook.warnings.push(message);
|
|
27898
|
+
}
|
|
27899
|
+
}
|
|
27900
|
+
/** Builds the dependency graph ahead of the first edit (see `EditSession.prepareCalculation`). */
|
|
27901
|
+
prepare(timeRemaining) {
|
|
27902
|
+
if (!this.enabled || calcModeOf(this.workbook) === "manual" || this.staleGraph) return true;
|
|
27194
27903
|
try {
|
|
27904
|
+
return this.calc.prepare(timeRemaining);
|
|
27905
|
+
} catch {
|
|
27906
|
+
this.calc.discardPreparation();
|
|
27907
|
+
return true;
|
|
27908
|
+
}
|
|
27909
|
+
}
|
|
27910
|
+
/**
|
|
27911
|
+
* Before a structural edit the graph can follow in place: finishes a graph being prepared (or
|
|
27912
|
+
* builds it) while it still matches the workbook, so the edit moves it instead of rebuilding.
|
|
27913
|
+
*/
|
|
27914
|
+
beforeStructural() {
|
|
27915
|
+
if (!this.enabled || calcModeOf(this.workbook) === "manual" || this.staleGraph) return;
|
|
27916
|
+
this.prepare();
|
|
27917
|
+
}
|
|
27918
|
+
recalc(structural, cells) {
|
|
27919
|
+
this.guard(() => {
|
|
27195
27920
|
if (this.staleGraph || structural) this.full();
|
|
27196
27921
|
else {
|
|
27197
27922
|
const changed = cells();
|
|
27198
27923
|
if (changed.length) this.calc.recalculateFrom(changed);
|
|
27924
|
+
this.calculated = settingsOf(this.workbook);
|
|
27199
27925
|
}
|
|
27200
|
-
}
|
|
27201
|
-
const message = `Recalculation failed: ${error instanceof Error ? error.message : String(error)}`;
|
|
27202
|
-
if (!this.workbook.warnings.includes(message)) this.workbook.warnings.push(message);
|
|
27203
|
-
}
|
|
27926
|
+
});
|
|
27204
27927
|
}
|
|
27205
|
-
/** Rebuilds the dependency graph and recalculates every formula (F9). */
|
|
27928
|
+
/** Rebuilds the dependency graph and recalculates every formula (Ctrl+Alt+F9). */
|
|
27206
27929
|
full() {
|
|
27207
27930
|
this.staleGraph = false;
|
|
27931
|
+
this.dirty = [];
|
|
27208
27932
|
this.calc.invalidate();
|
|
27209
27933
|
this.calc.recalculateAll();
|
|
27934
|
+
this.calculated = settingsOf(this.workbook);
|
|
27935
|
+
}
|
|
27936
|
+
/**
|
|
27937
|
+
* Calculate Now (F9): the cells changed since the last calculation, the formulas structural
|
|
27938
|
+
* edits queued, their dependents and the volatile functions. Everything when `full`, before
|
|
27939
|
+
* the session's first calculation, after the iteration settings changed or while the graph
|
|
27940
|
+
* is stale.
|
|
27941
|
+
*/
|
|
27942
|
+
now(full) {
|
|
27943
|
+
if (full || this.staleGraph || this.calculated !== settingsOf(this.workbook)) {
|
|
27944
|
+
this.full();
|
|
27945
|
+
return;
|
|
27946
|
+
}
|
|
27947
|
+
const changed = this.dirty;
|
|
27948
|
+
this.dirty = [];
|
|
27949
|
+
this.calc.recalculateFrom(changed);
|
|
27210
27950
|
}
|
|
27211
27951
|
/**
|
|
27212
27952
|
* Recalculates one sheet's formulas and their dependents (Shift+F9); after structural edits
|
|
@@ -30977,12 +31717,12 @@ function renameSheet(ctx, index2, name) {
|
|
|
30977
31717
|
ctx.run(
|
|
30978
31718
|
"Rename sheet",
|
|
30979
31719
|
"sheets",
|
|
30980
|
-
[{ kind: "
|
|
31720
|
+
[{ kind: "refs" }],
|
|
30981
31721
|
() => {
|
|
30982
31722
|
rewriteFormulas(workbook, (formula) => renameSheetInFormula(formula, old, name));
|
|
30983
31723
|
sheet.name = name;
|
|
30984
31724
|
},
|
|
30985
|
-
{ sheet: index2, structural: true }
|
|
31725
|
+
{ sheet: index2, structural: true, calc: { kind: "rename", from: old, to: name } }
|
|
30986
31726
|
);
|
|
30987
31727
|
}
|
|
30988
31728
|
function moveSheet(ctx, from, to) {
|
|
@@ -31372,13 +32112,12 @@ function createEditSession(workbook, options = {}) {
|
|
|
31372
32112
|
for (const listener of [...listeners]) listener(change);
|
|
31373
32113
|
};
|
|
31374
32114
|
const calculator = new SessionCalculator(workbook, calc, autoRecalc);
|
|
31375
|
-
const recalc = (step2) => calculator.afterStep(step2);
|
|
31376
|
-
const begin = (label2, kind, info) =>
|
|
31377
|
-
|
|
31378
|
-
|
|
31379
|
-
sheet: info.sheet,
|
|
31380
|
-
|
|
31381
|
-
});
|
|
32115
|
+
const recalc = (step2, mode = "apply") => calculator.afterStep(step2, mode);
|
|
32116
|
+
const begin = (label2, kind, info) => {
|
|
32117
|
+
const step2 = { label: label2, entries: [], structural: info.structural ?? false };
|
|
32118
|
+
if (info.calc) step2.calc = info.calc;
|
|
32119
|
+
return { step: step2, kind, sheet: info.sheet, ranges: [...info.ranges ?? []] };
|
|
32120
|
+
};
|
|
31382
32121
|
const finish = (current) => {
|
|
31383
32122
|
if (!current.step.entries.length) return;
|
|
31384
32123
|
history.push(current.step);
|
|
@@ -31403,10 +32142,12 @@ function createEditSession(workbook, options = {}) {
|
|
|
31403
32142
|
const outer = !open;
|
|
31404
32143
|
const current = open ?? begin(label2, kind, info);
|
|
31405
32144
|
if (!outer) {
|
|
32145
|
+
delete current.step.calc;
|
|
31406
32146
|
if (info.structural) current.step.structural = true;
|
|
31407
32147
|
if (current.sheet === void 0 && info.sheet !== void 0) current.sheet = info.sheet;
|
|
31408
32148
|
current.ranges.push(...info.ranges ?? []);
|
|
31409
32149
|
}
|
|
32150
|
+
if (outer && info.calc) calculator.beforeStructural();
|
|
31410
32151
|
open = current;
|
|
31411
32152
|
const mark = current.step.entries.length;
|
|
31412
32153
|
const befores = scopes.map((scope) => captureScope(workbook, scope));
|
|
@@ -31454,7 +32195,7 @@ function createEditSession(workbook, options = {}) {
|
|
|
31454
32195
|
if (open) throw new Error(`Cannot ${kind} inside a batch`);
|
|
31455
32196
|
const step2 = kind === "undo" ? history.undo(workbook) : history.redo(workbook);
|
|
31456
32197
|
if (!step2) return false;
|
|
31457
|
-
recalc(step2);
|
|
32198
|
+
recalc(step2, kind);
|
|
31458
32199
|
emit({ kind, label: step2.label, structural: step2.structural });
|
|
31459
32200
|
return true;
|
|
31460
32201
|
};
|
|
@@ -31533,10 +32274,11 @@ function createEditSession(workbook, options = {}) {
|
|
|
31533
32274
|
setDocumentProperties: (patch2) => setDocumentProperties(ctx, patch2),
|
|
31534
32275
|
setAutoRecalc: (enabled) => setCalcMode(ctx, enabled ? "auto" : "manual"),
|
|
31535
32276
|
autoRecalc: () => autoRecalc && calcModeOf(workbook) === "auto",
|
|
31536
|
-
calculateNow() {
|
|
31537
|
-
calculator.full
|
|
32277
|
+
calculateNow(options2) {
|
|
32278
|
+
calculator.now(options2?.full ?? false);
|
|
31538
32279
|
emit({ kind: "cells", label: "Calculate now", structural: false });
|
|
31539
32280
|
},
|
|
32281
|
+
prepareCalculation: (opts) => calculator.prepare(opts?.timeRemaining),
|
|
31540
32282
|
calculateSheet(s) {
|
|
31541
32283
|
calculator.sheet(s);
|
|
31542
32284
|
emit({ kind: "cells", label: "Calculate sheet", sheet: s, structural: false });
|
|
@@ -32191,6 +32933,7 @@ function selectionStats(workbook, sheet, ranges) {
|
|
|
32191
32933
|
const seen = /* @__PURE__ */ new Set();
|
|
32192
32934
|
let min = Infinity;
|
|
32193
32935
|
let max = -Infinity;
|
|
32936
|
+
let numFmt;
|
|
32194
32937
|
for (const range of ranges)
|
|
32195
32938
|
forEachCellInRange(ws, range, (cell, row2, col) => {
|
|
32196
32939
|
if (ranges.length > 1) {
|
|
@@ -32203,6 +32946,7 @@ function selectionStats(workbook, sheet, ranges) {
|
|
|
32203
32946
|
out.count++;
|
|
32204
32947
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
32205
32948
|
out.numericCount++;
|
|
32949
|
+
numFmt ??= styleAt(workbook, effectiveStyleId(ws, row2, col)).numFmt || "General";
|
|
32206
32950
|
out.sum += value;
|
|
32207
32951
|
min = Math.min(min, value);
|
|
32208
32952
|
max = Math.max(max, value);
|
|
@@ -32212,9 +32956,13 @@ function selectionStats(workbook, sheet, ranges) {
|
|
|
32212
32956
|
out.average = out.sum / out.numericCount;
|
|
32213
32957
|
out.min = min;
|
|
32214
32958
|
out.max = max;
|
|
32959
|
+
out.numFmt = numFmt ?? "General";
|
|
32215
32960
|
}
|
|
32216
32961
|
return out;
|
|
32217
32962
|
}
|
|
32963
|
+
function formatSelectionStat(workbook, stats, value) {
|
|
32964
|
+
return formatValue(value, stats.numFmt ?? "General", { date1904: workbook.date1904 }).text;
|
|
32965
|
+
}
|
|
32218
32966
|
function isOverflowTarget(sheet, row2, col) {
|
|
32219
32967
|
const cell = getCell(sheet, row2, col);
|
|
32220
32968
|
if (cell && (cell.value !== null && cell.value !== "" || cell.formula)) return false;
|
|
@@ -33099,7 +33847,7 @@ function chartAreaRect(model, part, area) {
|
|
|
33099
33847
|
function chartBarSpacing(chart) {
|
|
33100
33848
|
const stacked = chart.grouping === "stacked" || chart.grouping === "percentStacked";
|
|
33101
33849
|
return {
|
|
33102
|
-
barGapWidth: chart.barGapWidth ??
|
|
33850
|
+
barGapWidth: chart.barGapWidth ?? DEFAULT_BAR_GAP_WIDTH,
|
|
33103
33851
|
barOverlap: chart.barOverlap ?? (stacked ? 100 : 0)
|
|
33104
33852
|
};
|
|
33105
33853
|
}
|
|
@@ -34044,6 +34792,7 @@ exports.formatAxisValue = formatAxisValue;
|
|
|
34044
34792
|
exports.formatGeneral = formatGeneral;
|
|
34045
34793
|
exports.formatRange = formatRange;
|
|
34046
34794
|
exports.formatRefSpec = formatRefSpec;
|
|
34795
|
+
exports.formatSelectionStat = formatSelectionStat;
|
|
34047
34796
|
exports.formatValue = formatValue;
|
|
34048
34797
|
exports.formulaBarText = formulaBarText;
|
|
34049
34798
|
exports.functionMatches = functionMatches;
|