ooxml-core 1.2.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{PptxHandler-SJTINPU4.mjs → PptxHandler-VQQS4VS6.mjs} +2 -2
- package/dist/automation/index.cjs +1059 -328
- package/dist/automation/index.mjs +1059 -328
- 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-5U27IVB7.mjs} +3 -3
- package/dist/{chunk-VYTA2OUN.mjs → chunk-5VLNF4OX.mjs} +1 -1
- package/dist/{chunk-CQQAPUAG.mjs → chunk-V2BIGIH4.mjs} +11 -9
- package/dist/{chunk-FI4RSJ24.mjs → chunk-XBNSBDNT.mjs} +1 -1
- package/dist/{chunk-XCZ7U3GZ.mjs → chunk-XSFHGZFH.mjs} +11 -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 +27 -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 +27 -17
- package/dist/pptx/cli/index.mjs +4 -4
- package/dist/pptx/converter/index.mjs +2 -2
- package/dist/pptx/index.cjs +27 -17
- package/dist/pptx/index.mjs +5 -5
- package/dist/teams/index.cjs +157 -82
- package/dist/teams/index.mjs +157 -82
- 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 +1069 -329
- package/dist/xlsx/index.mjs +1069 -330
- 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 +152 -90
- package/dist/xlsx/load/index.mjs +152 -90
- package/dist/xlsx/ui/index.cjs +1071 -340
- package/dist/xlsx/ui/index.mjs +1071 -340
- package/package.json +1 -1
|
@@ -8618,9 +8618,9 @@ function rejectUnsafeRunSegmentation(paragraph2, base, oldRuns) {
|
|
|
8618
8618
|
(run2) => !run2.image && !run2.equation && (run2.restoredRunPropertiesXml || run2.sourceRunPropertiesXml)
|
|
8619
8619
|
))
|
|
8620
8620
|
return;
|
|
8621
|
-
const
|
|
8621
|
+
const sameText2 = paragraph2.runs.map((run2) => run2.text).join("") === base.runs.map((run2) => run2.text).join("");
|
|
8622
8622
|
const sameBoundaries = paragraph2.runs.length === base.runs.length && paragraph2.runs.every((run2, index2) => run2.text === base.runs[index2]?.text);
|
|
8623
|
-
if (sameBoundaries || !
|
|
8623
|
+
if (sameBoundaries || !sameText2 && paragraph2.runs.length === base.runs.length) return;
|
|
8624
8624
|
throw new Error(
|
|
8625
8625
|
`Cannot edit paragraph ${paragraph2.id}: changing run boundaries could drop unsupported run properties. The original DOCX package remains unchanged.`
|
|
8626
8626
|
);
|
|
@@ -12492,7 +12492,7 @@ var NAME_RE = /^[A-Za-z_\\\u00A1-\uFFFF][A-Za-z0-9_.?\\\u00A1-\uFFFF]*/;
|
|
|
12492
12492
|
var CELL_RE = /^(\$?)([A-Za-z]{1,3})(\$?)(\d{1,7})/;
|
|
12493
12493
|
var COLS_RE = /^(\$?)([A-Za-z]{1,3}):(\$?)([A-Za-z]{1,3})/;
|
|
12494
12494
|
var ROWS_RE = /^(\$?)(\d{1,7}):(\$?)(\d{1,7})/;
|
|
12495
|
-
var NUMBER_RE = /^(?:\d
|
|
12495
|
+
var NUMBER_RE = /^(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?/;
|
|
12496
12496
|
var sticky = (re) => new RegExp(re.source.replace(/^\^/, ""), "y");
|
|
12497
12497
|
var CELL_AT = sticky(CELL_RE);
|
|
12498
12498
|
var COLS_AT = sticky(COLS_RE);
|
|
@@ -12839,7 +12839,7 @@ function readName(source2, at2, start, prefix) {
|
|
|
12839
12839
|
}
|
|
12840
12840
|
var joinTokens = (tokens3) => tokens3.map((t) => t.text).join("");
|
|
12841
12841
|
|
|
12842
|
-
// xlsx/formula/
|
|
12842
|
+
// xlsx/formula/ref-text.ts
|
|
12843
12843
|
function safeTokens(formula) {
|
|
12844
12844
|
try {
|
|
12845
12845
|
return tokenize(formula);
|
|
@@ -12858,50 +12858,26 @@ function formatRefSpec(spec2) {
|
|
|
12858
12858
|
if (spec2.kind === "cell") return a2;
|
|
12859
12859
|
return `${a2}:${cornerText(spec2.end, spec2.kind)}`;
|
|
12860
12860
|
}
|
|
12861
|
-
function
|
|
12861
|
+
function rewriteRef(token, ref) {
|
|
12862
12862
|
const prefix = token.prefix?.text ?? "";
|
|
12863
12863
|
if (!ref) return `${prefix}#REF!`;
|
|
12864
12864
|
return `${prefix}${formatRefSpec(ref)}${token.spill ? "#" : ""}`;
|
|
12865
12865
|
}
|
|
12866
12866
|
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;
|
|
12867
|
-
|
|
12868
|
-
|
|
12869
|
-
|
|
12870
|
-
|
|
12871
|
-
|
|
12872
|
-
|
|
12873
|
-
const move = (c2) => {
|
|
12874
|
-
const row2 = spec2.kind === "cols" || c2.rowAbs ? c2.row : c2.row + dRow;
|
|
12875
|
-
const col = spec2.kind === "rows" || c2.colAbs ? c2.col : c2.col + dCol;
|
|
12876
|
-
if (row2 < 0 || row2 > MAX_ROW || col < 0 || col > MAX_COL) return void 0;
|
|
12877
|
-
return { ...c2, row: row2, col };
|
|
12878
|
-
};
|
|
12879
|
-
const start = move(spec2.start);
|
|
12880
|
-
const end = move(spec2.end);
|
|
12881
|
-
const next = start && end ? { kind: spec2.kind, start, end } : void 0;
|
|
12882
|
-
if (next && sameSpec(next, spec2)) continue;
|
|
12883
|
-
token.text = rewrite(token, next);
|
|
12884
|
-
}
|
|
12885
|
-
return joinTokens(tokens3);
|
|
12867
|
+
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);
|
|
12868
|
+
function prefixText(prefix) {
|
|
12869
|
+
const sheets = prefix.sheet2 !== void 0 ? `${prefix.sheet}:${prefix.sheet2}` : prefix.sheet;
|
|
12870
|
+
const book = prefix.book !== void 0 ? `[${prefix.book}]` : "";
|
|
12871
|
+
const quote2 = needsQuote(prefix.sheet) || prefix.sheet2 !== void 0 && needsQuote(prefix.sheet2);
|
|
12872
|
+
return quote2 ? `'${(book + sheets).replace(/'/g, "''")}'!` : `${book}${sheets}!`;
|
|
12886
12873
|
}
|
|
12887
|
-
|
|
12888
|
-
|
|
12889
|
-
|
|
12890
|
-
|
|
12891
|
-
|
|
12892
|
-
|
|
12893
|
-
|
|
12894
|
-
const na2 = a2 >= at2 ? a2 + count2 : a2;
|
|
12895
|
-
const nb2 = b >= at2 ? b + count2 : b;
|
|
12896
|
-
if (nb2 > max) return na2 > max ? void 0 : [na2, max];
|
|
12897
|
-
return [na2, nb2];
|
|
12898
|
-
}
|
|
12899
|
-
const n = -count2;
|
|
12900
|
-
const last = at2 + n - 1;
|
|
12901
|
-
if (a2 >= at2 && b <= last) return void 0;
|
|
12902
|
-
const na = a2 < at2 ? a2 : a2 <= last ? at2 : a2 - n;
|
|
12903
|
-
const nb = b < at2 ? b : b <= last ? at2 - 1 : b - n;
|
|
12904
|
-
return [na, nb];
|
|
12874
|
+
|
|
12875
|
+
// xlsx/formula/shift-formula.ts
|
|
12876
|
+
var templates = /* @__PURE__ */ new Map();
|
|
12877
|
+
var MAX_TEMPLATES = 2e5;
|
|
12878
|
+
function remember2(text2, template) {
|
|
12879
|
+
if (templates.size >= MAX_TEMPLATES) templates.clear();
|
|
12880
|
+
templates.set(text2, template);
|
|
12905
12881
|
}
|
|
12906
12882
|
function mergeSpacedAreas(tokens3) {
|
|
12907
12883
|
const out = [];
|
|
@@ -12928,63 +12904,145 @@ function mergeSpacedAreas(tokens3) {
|
|
|
12928
12904
|
}
|
|
12929
12905
|
return out;
|
|
12930
12906
|
}
|
|
12931
|
-
function
|
|
12932
|
-
|
|
12907
|
+
function templateOf(formula) {
|
|
12908
|
+
const cached3 = templates.get(formula);
|
|
12909
|
+
if (cached3 !== void 0) return cached3;
|
|
12933
12910
|
const raw2 = safeTokens(formula);
|
|
12934
|
-
|
|
12935
|
-
|
|
12936
|
-
|
|
12937
|
-
|
|
12938
|
-
|
|
12939
|
-
|
|
12940
|
-
|
|
12941
|
-
|
|
12942
|
-
|
|
12943
|
-
|
|
12944
|
-
|
|
12945
|
-
|
|
12946
|
-
|
|
12947
|
-
|
|
12948
|
-
|
|
12949
|
-
|
|
12950
|
-
|
|
12951
|
-
|
|
12952
|
-
|
|
12953
|
-
if (shifted2) {
|
|
12954
|
-
const [a2, b] = shifted2;
|
|
12955
|
-
const nlo = isRow ? { ...lo, row: a2 } : { ...lo, col: a2 };
|
|
12956
|
-
const nhi = isRow ? { ...hi, row: b } : { ...hi, col: b };
|
|
12957
|
-
next = { kind: ref.kind, start: startFirst ? nlo : nhi, end: startFirst ? nhi : nlo };
|
|
12958
|
-
if (ref.kind === "cell") next.end = next.start;
|
|
12911
|
+
let template = null;
|
|
12912
|
+
if (raw2) {
|
|
12913
|
+
template = [];
|
|
12914
|
+
let literal2 = "";
|
|
12915
|
+
for (const token of mergeSpacedAreas(raw2)) {
|
|
12916
|
+
if (token.kind !== "ref" && !(token.kind === "name" && token.prefix)) {
|
|
12917
|
+
literal2 += token.text;
|
|
12918
|
+
continue;
|
|
12919
|
+
}
|
|
12920
|
+
if (literal2) template.push(literal2);
|
|
12921
|
+
literal2 = "";
|
|
12922
|
+
const part = { kind: token.kind, text: token.text };
|
|
12923
|
+
if (token.prefix) {
|
|
12924
|
+
part.prefix = token.prefix;
|
|
12925
|
+
if (token.prefix.book === void 0) part.sheet = token.prefix.sheet.toLowerCase();
|
|
12926
|
+
}
|
|
12927
|
+
if (token.ref) part.ref = token.ref;
|
|
12928
|
+
if (token.spill) part.spill = true;
|
|
12929
|
+
template.push(part);
|
|
12959
12930
|
}
|
|
12960
|
-
if (
|
|
12961
|
-
token.text = rewrite(token, next);
|
|
12931
|
+
if (literal2) template.push(literal2);
|
|
12962
12932
|
}
|
|
12963
|
-
|
|
12933
|
+
remember2(formula, template);
|
|
12934
|
+
return template;
|
|
12964
12935
|
}
|
|
12965
|
-
|
|
12966
|
-
|
|
12967
|
-
|
|
12968
|
-
|
|
12969
|
-
|
|
12970
|
-
|
|
12936
|
+
function rewriteTemplate(formula, rewrite2) {
|
|
12937
|
+
const template = templateOf(formula);
|
|
12938
|
+
if (!template) return formula;
|
|
12939
|
+
let next;
|
|
12940
|
+
for (let i2 = 0; i2 < template.length; i2++) {
|
|
12941
|
+
const part = template[i2];
|
|
12942
|
+
if (typeof part === "string") continue;
|
|
12943
|
+
const changed = rewrite2(part);
|
|
12944
|
+
if (!changed) continue;
|
|
12945
|
+
next ??= template.slice();
|
|
12946
|
+
next[i2] = changed;
|
|
12947
|
+
}
|
|
12948
|
+
if (!next) return formula;
|
|
12949
|
+
const text2 = next.map((part) => typeof part === "string" ? part : part.text).join("");
|
|
12950
|
+
remember2(text2, next);
|
|
12951
|
+
return text2;
|
|
12952
|
+
}
|
|
12953
|
+
function shiftInterval(a2, b, at2, count2, max) {
|
|
12954
|
+
if (count2 > 0) {
|
|
12955
|
+
const na2 = a2 >= at2 ? a2 + count2 : a2;
|
|
12956
|
+
const nb2 = b >= at2 ? b + count2 : b;
|
|
12957
|
+
if (nb2 > max) return na2 > max ? void 0 : [na2, max];
|
|
12958
|
+
return [na2, nb2];
|
|
12959
|
+
}
|
|
12960
|
+
const n = -count2;
|
|
12961
|
+
const last = at2 + n - 1;
|
|
12962
|
+
if (a2 >= at2 && b <= last) return void 0;
|
|
12963
|
+
const na = a2 < at2 ? a2 : a2 <= last ? at2 : a2 - n;
|
|
12964
|
+
const nb = b < at2 ? b : b <= last ? at2 - 1 : b - n;
|
|
12965
|
+
return [na, nb];
|
|
12966
|
+
}
|
|
12967
|
+
function shiftRef(ref, spec2) {
|
|
12968
|
+
const isRow = spec2.axis === "row";
|
|
12969
|
+
if (isRow && ref.kind === "cols" || !isRow && ref.kind === "rows") return ref;
|
|
12970
|
+
const startFirst = isRow ? ref.start.row <= ref.end.row : ref.start.col <= ref.end.col;
|
|
12971
|
+
const lo = startFirst ? ref.start : ref.end;
|
|
12972
|
+
const hi = startFirst ? ref.end : ref.start;
|
|
12973
|
+
const shifted2 = shiftInterval(
|
|
12974
|
+
isRow ? lo.row : lo.col,
|
|
12975
|
+
isRow ? hi.row : hi.col,
|
|
12976
|
+
spec2.at,
|
|
12977
|
+
spec2.count,
|
|
12978
|
+
isRow ? MAX_ROW : MAX_COL
|
|
12979
|
+
);
|
|
12980
|
+
if (!shifted2) return void 0;
|
|
12981
|
+
const [a2, b] = shifted2;
|
|
12982
|
+
const nlo = isRow ? { ...lo, row: a2 } : { ...lo, col: a2 };
|
|
12983
|
+
const nhi = isRow ? { ...hi, row: b } : { ...hi, col: b };
|
|
12984
|
+
const next = {
|
|
12985
|
+
kind: ref.kind,
|
|
12986
|
+
start: startFirst ? nlo : nhi,
|
|
12987
|
+
end: startFirst ? nhi : nlo
|
|
12988
|
+
};
|
|
12989
|
+
if (ref.kind === "cell") next.end = next.start;
|
|
12990
|
+
return sameSpec(next, ref) ? ref : next;
|
|
12991
|
+
}
|
|
12992
|
+
function shiftFormula(formula, formulaSheet, spec2) {
|
|
12993
|
+
if (spec2.count === 0) return formula;
|
|
12994
|
+
const sheet = spec2.sheet.toLowerCase();
|
|
12995
|
+
const own = formulaSheet.toLowerCase() === sheet;
|
|
12996
|
+
return rewriteTemplate(formula, (part) => {
|
|
12997
|
+
if (part.kind !== "ref" || !part.ref || (part.prefix ? part.sheet !== sheet : !own))
|
|
12998
|
+
return void 0;
|
|
12999
|
+
const next = shiftRef(part.ref, spec2);
|
|
13000
|
+
if (next === part.ref) return void 0;
|
|
13001
|
+
const out = { kind: "ref", text: rewriteRef(part, next) };
|
|
13002
|
+
if (part.prefix) out.prefix = part.prefix;
|
|
13003
|
+
if (part.sheet !== void 0) out.sheet = part.sheet;
|
|
13004
|
+
if (next) out.ref = next;
|
|
13005
|
+
if (part.spill) out.spill = true;
|
|
13006
|
+
return out;
|
|
13007
|
+
});
|
|
12971
13008
|
}
|
|
12972
13009
|
function renameSheetInFormula(formula, oldName, newName) {
|
|
12973
|
-
const tokens3 = safeTokens(formula);
|
|
12974
|
-
if (!tokens3) return formula;
|
|
12975
13010
|
const lower2 = oldName.toLowerCase();
|
|
12976
|
-
|
|
12977
|
-
const prefix =
|
|
12978
|
-
if (!prefix ||
|
|
12979
|
-
const first3 =
|
|
13011
|
+
return rewriteTemplate(formula, (part) => {
|
|
13012
|
+
const prefix = part.prefix;
|
|
13013
|
+
if (!prefix || part.sheet === void 0) return void 0;
|
|
13014
|
+
const first3 = part.sheet === lower2;
|
|
12980
13015
|
const second = prefix.sheet2?.toLowerCase() === lower2;
|
|
12981
|
-
if (!first3 && !second)
|
|
13016
|
+
if (!first3 && !second) return void 0;
|
|
12982
13017
|
const renamed = { ...prefix, sheet: first3 ? newName : prefix.sheet };
|
|
12983
13018
|
if (prefix.sheet2 !== void 0) renamed.sheet2 = second ? newName : prefix.sheet2;
|
|
12984
13019
|
const text2 = prefixText(renamed);
|
|
12985
|
-
token.text = text2 + token.text.slice(prefix.text.length);
|
|
12986
13020
|
renamed.text = text2;
|
|
12987
|
-
|
|
13021
|
+
const out = { ...part, text: text2 + part.text.slice(prefix.text.length) };
|
|
13022
|
+
out.prefix = renamed;
|
|
13023
|
+
out.sheet = renamed.sheet.toLowerCase();
|
|
13024
|
+
return out;
|
|
13025
|
+
});
|
|
13026
|
+
}
|
|
13027
|
+
|
|
13028
|
+
// xlsx/formula/transform.ts
|
|
13029
|
+
function translateFormula(formula, dRow, dCol) {
|
|
13030
|
+
const tokens3 = safeTokens(formula);
|
|
13031
|
+
if (!tokens3) return formula;
|
|
13032
|
+
for (const token of tokens3) {
|
|
13033
|
+
if (token.kind !== "ref" || !token.ref) continue;
|
|
13034
|
+
const spec2 = token.ref;
|
|
13035
|
+
const move = (c2) => {
|
|
13036
|
+
const row2 = spec2.kind === "cols" || c2.rowAbs ? c2.row : c2.row + dRow;
|
|
13037
|
+
const col = spec2.kind === "rows" || c2.colAbs ? c2.col : c2.col + dCol;
|
|
13038
|
+
if (row2 < 0 || row2 > MAX_ROW || col < 0 || col > MAX_COL) return void 0;
|
|
13039
|
+
return { ...c2, row: row2, col };
|
|
13040
|
+
};
|
|
13041
|
+
const start = move(spec2.start);
|
|
13042
|
+
const end = move(spec2.end);
|
|
13043
|
+
const next = start && end ? { kind: spec2.kind, start, end } : void 0;
|
|
13044
|
+
if (next && sameSpec(next, spec2)) continue;
|
|
13045
|
+
token.text = rewriteRef(token, next);
|
|
12988
13046
|
}
|
|
12989
13047
|
return joinTokens(tokens3);
|
|
12990
13048
|
}
|
|
@@ -13073,7 +13131,7 @@ var FUTURE_FUNCTIONS = new Set(
|
|
|
13073
13131
|
"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(" ")
|
|
13074
13132
|
);
|
|
13075
13133
|
var WORKSHEET_PREFIXED = /* @__PURE__ */ new Set(["FILTER", "SORT"]);
|
|
13076
|
-
function
|
|
13134
|
+
function rewrite(formula, visit2) {
|
|
13077
13135
|
const out = [];
|
|
13078
13136
|
let i2 = 0;
|
|
13079
13137
|
while (i2 < formula.length) {
|
|
@@ -13116,7 +13174,7 @@ function rewrite2(formula, visit2) {
|
|
|
13116
13174
|
}
|
|
13117
13175
|
function stripFuturePrefixes(formula) {
|
|
13118
13176
|
if (!formula.includes("_xl")) return formula;
|
|
13119
|
-
const plain2 =
|
|
13177
|
+
const plain2 = rewrite(formula, (token, next, out) => {
|
|
13120
13178
|
if (!next.startsWith("(")) return false;
|
|
13121
13179
|
const stripped = token.replace(/^(_xlfn\.)?(_xlws\.)?/i, "");
|
|
13122
13180
|
if (stripped === token) return false;
|
|
@@ -13126,7 +13184,7 @@ function stripFuturePrefixes(formula) {
|
|
|
13126
13184
|
return fromStoredSyntax(plain2);
|
|
13127
13185
|
}
|
|
13128
13186
|
function addFuturePrefixes(formula) {
|
|
13129
|
-
return
|
|
13187
|
+
return rewrite(toStoredSyntax(formula), (token, next, out) => {
|
|
13130
13188
|
if (!next.startsWith("(")) return false;
|
|
13131
13189
|
const upper2 = token.toUpperCase();
|
|
13132
13190
|
if (!FUTURE_FUNCTIONS.has(upper2)) return false;
|
|
@@ -13779,13 +13837,13 @@ function dataBarLengths(rule2, node) {
|
|
|
13779
13837
|
maxLength: rule2.maxLength ?? numAttr(bar, "maxLength") ?? 90
|
|
13780
13838
|
};
|
|
13781
13839
|
}
|
|
13782
|
-
function rewriteConditionalExtension(rule2,
|
|
13840
|
+
function rewriteConditionalExtension(rule2, rewrite2) {
|
|
13783
13841
|
if (!rule2.extensionXml) return;
|
|
13784
13842
|
const doc = parseXml(rule2.extensionXml);
|
|
13785
13843
|
let changed = false;
|
|
13786
13844
|
for (const formula of descendants3(doc.documentElement, "f", XM)) {
|
|
13787
13845
|
const before = formula.textContent ?? "";
|
|
13788
|
-
const next =
|
|
13846
|
+
const next = rewrite2(before);
|
|
13789
13847
|
if (before !== next) {
|
|
13790
13848
|
formula.textContent = next;
|
|
13791
13849
|
changed = true;
|
|
@@ -17018,7 +17076,9 @@ var PREC_INTERSECT = 9;
|
|
|
17018
17076
|
var PREC_RANGE = 10;
|
|
17019
17077
|
var OPERAND_START = /* @__PURE__ */ new Set(["ref", "name", "func", "open", "structured"]);
|
|
17020
17078
|
function parseFormula(formula) {
|
|
17021
|
-
|
|
17079
|
+
return parseTokens(tokenize(formula));
|
|
17080
|
+
}
|
|
17081
|
+
function parseTokens(all2) {
|
|
17022
17082
|
const tokens3 = [];
|
|
17023
17083
|
const wsBefore = [];
|
|
17024
17084
|
let sawWs = false;
|
|
@@ -17359,6 +17419,222 @@ function localDateToSerial(date, date1904 = date1904Mode) {
|
|
|
17359
17419
|
return base + (utc - dayStart) / DAY_MS2;
|
|
17360
17420
|
}
|
|
17361
17421
|
|
|
17422
|
+
// xlsx/formula/area-index.ts
|
|
17423
|
+
var BUCKET_WIDTH = 64;
|
|
17424
|
+
var CHUNK_SHIFT = 6;
|
|
17425
|
+
var CHUNKS = 64;
|
|
17426
|
+
function push(map, key2, value) {
|
|
17427
|
+
const list = map.get(key2);
|
|
17428
|
+
if (list) list.push(value);
|
|
17429
|
+
else map.set(key2, [value]);
|
|
17430
|
+
}
|
|
17431
|
+
function inner(map, sheet) {
|
|
17432
|
+
let found = map.get(sheet);
|
|
17433
|
+
if (!found) map.set(sheet, found = /* @__PURE__ */ new Map());
|
|
17434
|
+
return found;
|
|
17435
|
+
}
|
|
17436
|
+
var AreaIndex = class {
|
|
17437
|
+
cells = /* @__PURE__ */ new Map();
|
|
17438
|
+
chunked = /* @__PURE__ */ new Map();
|
|
17439
|
+
tall = /* @__PURE__ */ new Map();
|
|
17440
|
+
wide = /* @__PURE__ */ new Map();
|
|
17441
|
+
add(area, node) {
|
|
17442
|
+
const { start, end } = area.range;
|
|
17443
|
+
if (start.row === end.row && end.col - start.col + 1 <= BUCKET_WIDTH) {
|
|
17444
|
+
const cells3 = inner(this.cells, area.sheet);
|
|
17445
|
+
for (let col = start.col; col <= end.col; col++) push(cells3, cellKey(start.row, col), node);
|
|
17446
|
+
return;
|
|
17447
|
+
}
|
|
17448
|
+
const entry3 = { range: area.range, node };
|
|
17449
|
+
if (end.col - start.col + 1 > BUCKET_WIDTH) {
|
|
17450
|
+
const list = this.wide.get(area.sheet);
|
|
17451
|
+
if (list) list.push(entry3);
|
|
17452
|
+
else this.wide.set(area.sheet, [entry3]);
|
|
17453
|
+
return;
|
|
17454
|
+
}
|
|
17455
|
+
const first3 = start.row >> CHUNK_SHIFT;
|
|
17456
|
+
const last = end.row >> CHUNK_SHIFT;
|
|
17457
|
+
if (last - first3 + 1 > CHUNKS) {
|
|
17458
|
+
const cols2 = inner(this.tall, area.sheet);
|
|
17459
|
+
for (let c2 = start.col; c2 <= end.col; c2++) push(cols2, c2, entry3);
|
|
17460
|
+
return;
|
|
17461
|
+
}
|
|
17462
|
+
const cols = inner(this.chunked, area.sheet);
|
|
17463
|
+
for (let c2 = start.col; c2 <= end.col; c2++) {
|
|
17464
|
+
let chunks = cols.get(c2);
|
|
17465
|
+
if (!chunks) cols.set(c2, chunks = /* @__PURE__ */ new Map());
|
|
17466
|
+
for (let k = first3; k <= last; k++) push(chunks, k, entry3);
|
|
17467
|
+
}
|
|
17468
|
+
}
|
|
17469
|
+
/** Items whose areas intersect `range` on `sheet` (each once). */
|
|
17470
|
+
dependents(sheet, range, out) {
|
|
17471
|
+
const found = out instanceof Set ? out : /* @__PURE__ */ new Set();
|
|
17472
|
+
this.collect(sheet, range, found);
|
|
17473
|
+
if (Array.isArray(out)) for (const node of found) out.push(node);
|
|
17474
|
+
}
|
|
17475
|
+
collect(sheet, range, out) {
|
|
17476
|
+
const { start, end } = range;
|
|
17477
|
+
const check3 = (list) => {
|
|
17478
|
+
if (list) {
|
|
17479
|
+
for (const entry3 of list) if (rangesIntersect(entry3.range, range)) out.add(entry3.node);
|
|
17480
|
+
}
|
|
17481
|
+
};
|
|
17482
|
+
const cells3 = this.cells.get(sheet);
|
|
17483
|
+
if (cells3) {
|
|
17484
|
+
const size = (end.row - start.row + 1) * (end.col - start.col + 1);
|
|
17485
|
+
if (size <= 4096) {
|
|
17486
|
+
for (let r = start.row; r <= end.row; r++) {
|
|
17487
|
+
for (let c2 = start.col; c2 <= end.col; c2++) {
|
|
17488
|
+
const list = cells3.get(cellKey(r, c2));
|
|
17489
|
+
if (list) for (const node of list) out.add(node);
|
|
17490
|
+
}
|
|
17491
|
+
}
|
|
17492
|
+
} else {
|
|
17493
|
+
for (const [key2, list] of cells3) {
|
|
17494
|
+
const { row: row2, col } = keyToAddress(key2);
|
|
17495
|
+
if (row2 >= start.row && row2 <= end.row && col >= start.col && col <= end.col)
|
|
17496
|
+
for (const node of list) out.add(node);
|
|
17497
|
+
}
|
|
17498
|
+
}
|
|
17499
|
+
}
|
|
17500
|
+
const columns = (map, visit2) => {
|
|
17501
|
+
if (!map) return;
|
|
17502
|
+
if (end.col - start.col + 1 <= map.size) {
|
|
17503
|
+
for (let c2 = start.col; c2 <= end.col; c2++) if (map.has(c2)) visit2(c2);
|
|
17504
|
+
} else for (const c2 of map.keys()) if (c2 >= start.col && c2 <= end.col) visit2(c2);
|
|
17505
|
+
};
|
|
17506
|
+
const chunked = this.chunked.get(sheet);
|
|
17507
|
+
const first3 = start.row >> CHUNK_SHIFT;
|
|
17508
|
+
const last = end.row >> CHUNK_SHIFT;
|
|
17509
|
+
columns(chunked, (c2) => {
|
|
17510
|
+
const chunks = chunked?.get(c2);
|
|
17511
|
+
if (last - first3 + 1 <= chunks.size) {
|
|
17512
|
+
for (let k = first3; k <= last; k++) check3(chunks.get(k));
|
|
17513
|
+
} else for (const [k, list] of chunks) if (k >= first3 && k <= last) check3(list);
|
|
17514
|
+
});
|
|
17515
|
+
const tall = this.tall.get(sheet);
|
|
17516
|
+
columns(tall, (c2) => check3(tall?.get(c2)));
|
|
17517
|
+
check3(this.wide.get(sheet));
|
|
17518
|
+
}
|
|
17519
|
+
};
|
|
17520
|
+
|
|
17521
|
+
// xlsx/formula/graph-index.ts
|
|
17522
|
+
var ColumnIndex = class {
|
|
17523
|
+
sheets = /* @__PURE__ */ new Map();
|
|
17524
|
+
constructor(nodes) {
|
|
17525
|
+
for (const node of nodes) {
|
|
17526
|
+
let cols = this.sheets.get(node.sheet);
|
|
17527
|
+
if (!cols) this.sheets.set(node.sheet, cols = /* @__PURE__ */ new Map());
|
|
17528
|
+
let list = cols.get(node.col);
|
|
17529
|
+
if (!list) cols.set(node.col, list = []);
|
|
17530
|
+
list.push(node);
|
|
17531
|
+
}
|
|
17532
|
+
for (const cols of this.sheets.values())
|
|
17533
|
+
for (const list of cols.values()) list.sort((a2, b) => a2.row - b.row);
|
|
17534
|
+
}
|
|
17535
|
+
nodesIn(area, out) {
|
|
17536
|
+
const cols = this.sheets.get(area.sheet);
|
|
17537
|
+
if (!cols) return;
|
|
17538
|
+
const { start, end } = area.range;
|
|
17539
|
+
const width = end.col - start.col + 1;
|
|
17540
|
+
const scan3 = (list) => {
|
|
17541
|
+
let lo = 0;
|
|
17542
|
+
let hi = list.length;
|
|
17543
|
+
while (lo < hi) {
|
|
17544
|
+
const mid = lo + hi >> 1;
|
|
17545
|
+
if (list[mid].row < start.row) lo = mid + 1;
|
|
17546
|
+
else hi = mid;
|
|
17547
|
+
}
|
|
17548
|
+
for (let i2 = lo; i2 < list.length; i2++) {
|
|
17549
|
+
const node = list[i2];
|
|
17550
|
+
if (node.row > end.row) break;
|
|
17551
|
+
out.push(node);
|
|
17552
|
+
}
|
|
17553
|
+
};
|
|
17554
|
+
if (width <= cols.size) {
|
|
17555
|
+
for (let c2 = start.col; c2 <= end.col; c2++) {
|
|
17556
|
+
const list = cols.get(c2);
|
|
17557
|
+
if (list) scan3(list);
|
|
17558
|
+
}
|
|
17559
|
+
} else {
|
|
17560
|
+
for (const [c2, list] of cols) if (c2 >= start.col && c2 <= end.col) scan3(list);
|
|
17561
|
+
}
|
|
17562
|
+
}
|
|
17563
|
+
};
|
|
17564
|
+
var ReverseIndex = class extends AreaIndex {
|
|
17565
|
+
constructor(nodes = []) {
|
|
17566
|
+
super();
|
|
17567
|
+
for (const node of nodes) this.addNode(node);
|
|
17568
|
+
}
|
|
17569
|
+
/** Indexes one more formula's precedents. */
|
|
17570
|
+
addNode(node) {
|
|
17571
|
+
for (const dep of node.deps) this.add(dep, node);
|
|
17572
|
+
for (const dep of node.dynamicDeps) this.add(dep, node);
|
|
17573
|
+
}
|
|
17574
|
+
};
|
|
17575
|
+
|
|
17576
|
+
// xlsx/formula/engine-prepare.ts
|
|
17577
|
+
var CHECK_EVERY = 32;
|
|
17578
|
+
var GraphPreparation = class {
|
|
17579
|
+
constructor(workbook, create) {
|
|
17580
|
+
this.workbook = workbook;
|
|
17581
|
+
this.create = create;
|
|
17582
|
+
}
|
|
17583
|
+
workbook;
|
|
17584
|
+
create;
|
|
17585
|
+
reverse = new ReverseIndex();
|
|
17586
|
+
formulas = { dynamic: [], unvalued: [] };
|
|
17587
|
+
sheet = 0;
|
|
17588
|
+
rows;
|
|
17589
|
+
row = 0;
|
|
17590
|
+
cells;
|
|
17591
|
+
finished = false;
|
|
17592
|
+
/**
|
|
17593
|
+
* Adds formulas to the graph until `timeRemaining` (milliseconds, as an idle deadline reports
|
|
17594
|
+
* them) reaches zero, or until every formula is in. Returns true when the graph is complete.
|
|
17595
|
+
*/
|
|
17596
|
+
run(timeRemaining) {
|
|
17597
|
+
let visited = 0;
|
|
17598
|
+
while (!this.finished) {
|
|
17599
|
+
const cells3 = this.cells ?? this.nextRow();
|
|
17600
|
+
if (!cells3) continue;
|
|
17601
|
+
const next = cells3.next();
|
|
17602
|
+
if (next.done) {
|
|
17603
|
+
this.cells = void 0;
|
|
17604
|
+
continue;
|
|
17605
|
+
}
|
|
17606
|
+
const [col, cell] = next.value;
|
|
17607
|
+
if (cell.formula) this.add(this.create(this.sheet, this.row, col, cell), cell);
|
|
17608
|
+
if (timeRemaining && ++visited % CHECK_EVERY === 0 && timeRemaining() <= 0) break;
|
|
17609
|
+
}
|
|
17610
|
+
return this.finished;
|
|
17611
|
+
}
|
|
17612
|
+
add(node, cell) {
|
|
17613
|
+
this.reverse.addNode(node);
|
|
17614
|
+
if (!node.legacy && !node.arrayRange) this.formulas.dynamic.push(node);
|
|
17615
|
+
if (cell.value === null && !node.keepCached) this.formulas.unvalued.push(node);
|
|
17616
|
+
}
|
|
17617
|
+
/** Moves to the next stored row (and sheet), or marks the walk finished. */
|
|
17618
|
+
nextRow() {
|
|
17619
|
+
for (; ; ) {
|
|
17620
|
+
const sheet = this.workbook.sheets[this.sheet];
|
|
17621
|
+
if (!sheet) {
|
|
17622
|
+
this.finished = true;
|
|
17623
|
+
return void 0;
|
|
17624
|
+
}
|
|
17625
|
+
this.rows ??= sheet.rows.entries();
|
|
17626
|
+
const next = this.rows.next();
|
|
17627
|
+
if (!next.done) {
|
|
17628
|
+
this.row = next.value[0];
|
|
17629
|
+
this.cells = next.value[1].entries();
|
|
17630
|
+
return this.cells;
|
|
17631
|
+
}
|
|
17632
|
+
this.rows = void 0;
|
|
17633
|
+
this.sheet++;
|
|
17634
|
+
}
|
|
17635
|
+
}
|
|
17636
|
+
};
|
|
17637
|
+
|
|
17362
17638
|
// xlsx/formula/text-number.ts
|
|
17363
17639
|
var MONTHS2 = [
|
|
17364
17640
|
"jan",
|
|
@@ -20493,8 +20769,10 @@ var FINANCIAL_FUNCTIONS = [
|
|
|
20493
20769
|
|
|
20494
20770
|
// xlsx/formula/references.ts
|
|
20495
20771
|
function sheetIndex(host, name) {
|
|
20772
|
+
const sheets = host.workbook.sheets;
|
|
20773
|
+
for (let i2 = 0; i2 < sheets.length; i2++) if (sheets[i2]?.name === name) return i2;
|
|
20496
20774
|
const lower2 = name.toLowerCase();
|
|
20497
|
-
return
|
|
20775
|
+
return sheets.findIndex((sheet) => sheet.name.toLowerCase() === lower2);
|
|
20498
20776
|
}
|
|
20499
20777
|
function prefixSheets(host, prefix, current) {
|
|
20500
20778
|
if (!prefix) return [current];
|
|
@@ -22108,9 +22386,9 @@ function readBlock(ctx, area, rows, cols) {
|
|
|
22108
22386
|
if (host.readBlock) return host.readBlock(area.sheet, range);
|
|
22109
22387
|
return Matrix.build(rows, cols, (r, c2) => ctx.readCell(area.sheet, row2 + r, col + c2));
|
|
22110
22388
|
}
|
|
22111
|
-
function shapedMatrices(ctx, values2,
|
|
22389
|
+
function shapedMatrices(ctx, values2, sameShape2) {
|
|
22112
22390
|
let { rows, cols } = shapeOf(values2[0] ?? null);
|
|
22113
|
-
if (
|
|
22391
|
+
if (sameShape2) {
|
|
22114
22392
|
for (const value of values2) {
|
|
22115
22393
|
const shape2 = shapeOf(value);
|
|
22116
22394
|
if (shape2.rows !== rows || shape2.cols !== cols) fail(ERR.VALUE);
|
|
@@ -22136,12 +22414,12 @@ function shapedMatrices(ctx, values2, sameShape) {
|
|
|
22136
22414
|
});
|
|
22137
22415
|
return { matrices, total: total2, block: rows * cols };
|
|
22138
22416
|
}
|
|
22139
|
-
function matchingCells(ctx, pairs, target,
|
|
22417
|
+
function matchingCells(ctx, pairs, target, sameShape2) {
|
|
22140
22418
|
const ranges = pairs.map((p) => p.range);
|
|
22141
22419
|
const { matrices, total: total2, block } = shapedMatrices(
|
|
22142
22420
|
ctx,
|
|
22143
22421
|
target === void 0 ? ranges : [...ranges, target],
|
|
22144
|
-
|
|
22422
|
+
sameShape2
|
|
22145
22423
|
);
|
|
22146
22424
|
const tests = pairs.map((p) => makeCriteria(scalar(p.criteria)));
|
|
22147
22425
|
const values2 = matrices[matrices.length - 1];
|
|
@@ -22180,7 +22458,7 @@ function indexedCandidates(pairs, matrices) {
|
|
|
22180
22458
|
}
|
|
22181
22459
|
return void 0;
|
|
22182
22460
|
}
|
|
22183
|
-
var matchingValues = (ctx, pairs, target,
|
|
22461
|
+
var matchingValues = (ctx, pairs, target, sameShape2) => matchingCells(ctx, pairs, target, sameShape2).values;
|
|
22184
22462
|
function criteriaPairs(args, from) {
|
|
22185
22463
|
if ((args.length - from) % 2 !== 0) fail(ERR.VALUE);
|
|
22186
22464
|
const pairs = [];
|
|
@@ -26074,7 +26352,7 @@ var REFERENCE_ARGUMENT = /* @__PURE__ */ new Set([
|
|
|
26074
26352
|
"AREAS",
|
|
26075
26353
|
"ISREF"
|
|
26076
26354
|
]);
|
|
26077
|
-
var
|
|
26355
|
+
var push2 = (c2, area) => {
|
|
26078
26356
|
(c2.dynamic > 0 ? c2.dynamicDeps : c2.deps).push(area);
|
|
26079
26357
|
};
|
|
26080
26358
|
function spans(areas) {
|
|
@@ -26100,7 +26378,7 @@ function visit(node, c2) {
|
|
|
26100
26378
|
if (!sheets) return;
|
|
26101
26379
|
const range = specRange(node.ref);
|
|
26102
26380
|
const target = node.spill ? { start: range.start, end: { ...range.start } } : range;
|
|
26103
|
-
for (const sheet of sheets)
|
|
26381
|
+
for (const sheet of sheets) push2(c2, { sheet, range: target });
|
|
26104
26382
|
return;
|
|
26105
26383
|
}
|
|
26106
26384
|
case "name": {
|
|
@@ -26174,7 +26452,7 @@ function visitBinary(node, c2) {
|
|
|
26174
26452
|
const list = c2.dynamic > 0 ? c2.dynamicDeps : c2.deps;
|
|
26175
26453
|
const l = list[list.length - 2];
|
|
26176
26454
|
const r = list[list.length - 1];
|
|
26177
|
-
if (l && r && l.sheet === r.sheet)
|
|
26455
|
+
if (l && r && l.sheet === r.sheet) push2(c2, spans([l, r])[0]);
|
|
26178
26456
|
continue;
|
|
26179
26457
|
}
|
|
26180
26458
|
const mentioned = [...c2.deps.slice(staticStart), ...c2.dynamicDeps.slice(dynamicStart)];
|
|
@@ -26190,7 +26468,7 @@ function addStructured(ref, c2) {
|
|
|
26190
26468
|
sheet: c2.sheet,
|
|
26191
26469
|
row: c2.row,
|
|
26192
26470
|
col: c2.col});
|
|
26193
|
-
if (value instanceof RefValue) for (const area of value.areas)
|
|
26471
|
+
if (value instanceof RefValue) for (const area of value.areas) push2(c2, area);
|
|
26194
26472
|
}
|
|
26195
26473
|
function analyze(ast, host, sheet, row2, col) {
|
|
26196
26474
|
const c2 = {
|
|
@@ -26214,155 +26492,191 @@ function analyze(ast, host, sheet, row2, col) {
|
|
|
26214
26492
|
};
|
|
26215
26493
|
}
|
|
26216
26494
|
|
|
26217
|
-
// xlsx/formula/
|
|
26218
|
-
var
|
|
26219
|
-
|
|
26220
|
-
|
|
26221
|
-
|
|
26222
|
-
|
|
26223
|
-
|
|
26224
|
-
|
|
26495
|
+
// xlsx/formula/formula-shape.ts
|
|
26496
|
+
var isDigit4 = (code) => code >= 48 && code <= 57;
|
|
26497
|
+
function formulaShape(formula) {
|
|
26498
|
+
const starts = [];
|
|
26499
|
+
const ends = [];
|
|
26500
|
+
let hash = 2166136261;
|
|
26501
|
+
for (let i2 = 0; i2 < formula.length; i2++) {
|
|
26502
|
+
let code = formula.charCodeAt(i2);
|
|
26503
|
+
if (isDigit4(code)) {
|
|
26504
|
+
let j = i2 + 1;
|
|
26505
|
+
while (j < formula.length && isDigit4(formula.charCodeAt(j))) j++;
|
|
26506
|
+
starts.push(i2);
|
|
26507
|
+
ends.push(j);
|
|
26508
|
+
i2 = j - 1;
|
|
26509
|
+
code = 0;
|
|
26510
|
+
}
|
|
26511
|
+
hash = Math.imul(hash ^ code, 16777619);
|
|
26512
|
+
}
|
|
26513
|
+
return { hash: hash >>> 0, starts, ends };
|
|
26225
26514
|
}
|
|
26226
|
-
function
|
|
26227
|
-
let
|
|
26228
|
-
|
|
26229
|
-
return
|
|
26515
|
+
function sameText(a2, from, b, at2, length) {
|
|
26516
|
+
for (let k = 0; k < length; k++)
|
|
26517
|
+
if (a2.charCodeAt(from + k) !== b.charCodeAt(at2 + k)) return false;
|
|
26518
|
+
return true;
|
|
26230
26519
|
}
|
|
26231
|
-
|
|
26232
|
-
|
|
26233
|
-
|
|
26234
|
-
|
|
26235
|
-
|
|
26236
|
-
|
|
26237
|
-
const
|
|
26238
|
-
|
|
26239
|
-
|
|
26240
|
-
|
|
26241
|
-
|
|
26520
|
+
function sameShape(a2, as, b, bs) {
|
|
26521
|
+
const runs = as.starts.length;
|
|
26522
|
+
if (runs !== bs.starts.length) return false;
|
|
26523
|
+
let fromA = 0;
|
|
26524
|
+
let fromB = 0;
|
|
26525
|
+
for (let i2 = 0; i2 <= runs; i2++) {
|
|
26526
|
+
const toA = i2 < runs ? as.starts[i2] : a2.length;
|
|
26527
|
+
const toB = i2 < runs ? bs.starts[i2] : b.length;
|
|
26528
|
+
if (toA - fromA !== toB - fromB || !sameText(a2, fromA, b, fromB, toA - fromA)) return false;
|
|
26529
|
+
fromA = as.ends[i2] ?? 0;
|
|
26530
|
+
fromB = bs.ends[i2] ?? 0;
|
|
26531
|
+
}
|
|
26532
|
+
return true;
|
|
26533
|
+
}
|
|
26534
|
+
function makeTemplate(formula, shape2) {
|
|
26535
|
+
let tokens3;
|
|
26536
|
+
let ast;
|
|
26537
|
+
try {
|
|
26538
|
+
tokens3 = tokenize(formula);
|
|
26539
|
+
ast = parseTokens(tokens3);
|
|
26540
|
+
} catch (e) {
|
|
26541
|
+
if (e instanceof RangeError) return new FormulaError(e.message, -1, "#VALUE!");
|
|
26542
|
+
if (e instanceof FormulaError) return e;
|
|
26543
|
+
throw e;
|
|
26544
|
+
}
|
|
26545
|
+
const { starts } = shape2;
|
|
26546
|
+
const slotted = starts.map(() => false);
|
|
26547
|
+
const refs = /* @__PURE__ */ new Map();
|
|
26548
|
+
let run2 = 0;
|
|
26549
|
+
for (const token of tokens3) {
|
|
26550
|
+
const end = token.start + token.text.length;
|
|
26551
|
+
const first3 = run2;
|
|
26552
|
+
while (run2 < starts.length && starts[run2] < end) run2++;
|
|
26553
|
+
const ref = token.kind === "ref" ? token.ref : void 0;
|
|
26554
|
+
if (!ref || ref.kind === "cols") continue;
|
|
26555
|
+
const count2 = ref.kind === "cell" ? 1 : 2;
|
|
26556
|
+
if (run2 - first3 < count2) continue;
|
|
26557
|
+
const at2 = run2 - count2;
|
|
26558
|
+
const indexes2 = count2 === 1 ? [at2] : [at2, at2 + 1];
|
|
26559
|
+
if (indexes2.some((i2) => formula.charCodeAt(starts[i2]) === 48)) continue;
|
|
26560
|
+
for (const i2 of indexes2) slotted[i2] = true;
|
|
26561
|
+
refs.set(ref, count2 === 1 ? { start: at2 } : { start: at2, end: at2 + 1 });
|
|
26562
|
+
}
|
|
26563
|
+
return { formula, shape: shape2, ast, slotted, refs };
|
|
26564
|
+
}
|
|
26565
|
+
function rowsFor(t, formula, shape2) {
|
|
26566
|
+
if (!sameShape(t.formula, t.shape, formula, shape2)) return void 0;
|
|
26567
|
+
const rows = [];
|
|
26568
|
+
for (let i2 = 0; i2 < shape2.starts.length; i2++) {
|
|
26569
|
+
const start = shape2.starts[i2];
|
|
26570
|
+
const length = shape2.ends[i2] - start;
|
|
26571
|
+
if (!t.slotted[i2]) {
|
|
26572
|
+
const own = t.shape.starts[i2];
|
|
26573
|
+
if (t.shape.ends[i2] - own !== length) return void 0;
|
|
26574
|
+
if (!sameText(t.formula, own, formula, start, length)) return void 0;
|
|
26575
|
+
rows.push(-1);
|
|
26576
|
+
continue;
|
|
26242
26577
|
}
|
|
26243
|
-
|
|
26244
|
-
|
|
26245
|
-
|
|
26246
|
-
|
|
26247
|
-
|
|
26248
|
-
|
|
26578
|
+
if (length > 7 || formula.charCodeAt(start) === 48) return void 0;
|
|
26579
|
+
let row2 = 0;
|
|
26580
|
+
for (let k = start; k < start + length; k++) row2 = row2 * 10 + formula.charCodeAt(k) - 48;
|
|
26581
|
+
if (row2 < 1 || row2 > MAX_ROW + 1) return void 0;
|
|
26582
|
+
rows.push(row2 - 1);
|
|
26583
|
+
}
|
|
26584
|
+
return rows;
|
|
26585
|
+
}
|
|
26586
|
+
function shiftSpec(spec2, slots, rows) {
|
|
26587
|
+
const startRow = rows[slots.start];
|
|
26588
|
+
const endRow = slots.end === void 0 ? startRow : rows[slots.end];
|
|
26589
|
+
if (startRow === spec2.start.row && endRow === spec2.end.row) return spec2;
|
|
26590
|
+
const { start: from, end: to } = spec2;
|
|
26591
|
+
const start = { row: startRow, col: from.col, rowAbs: from.rowAbs, colAbs: from.colAbs };
|
|
26592
|
+
if (slots.end === void 0) return { kind: spec2.kind, start, end: start };
|
|
26593
|
+
const end = { row: endRow, col: to.col, rowAbs: to.rowAbs, colAbs: to.colAbs };
|
|
26594
|
+
return { kind: spec2.kind, start, end };
|
|
26595
|
+
}
|
|
26596
|
+
function copyTree(node, t, rows) {
|
|
26597
|
+
switch (node.type) {
|
|
26598
|
+
case "ref": {
|
|
26599
|
+
const slots = node.ref ? t.refs.get(node.ref) : void 0;
|
|
26600
|
+
if (!slots || !node.ref) return node;
|
|
26601
|
+
const ref = shiftSpec(node.ref, slots, rows);
|
|
26602
|
+
if (ref === node.ref) return node;
|
|
26603
|
+
const copy2 = { type: "ref" };
|
|
26604
|
+
if (node.prefix) copy2.prefix = node.prefix;
|
|
26605
|
+
copy2.ref = ref;
|
|
26606
|
+
if (node.spill) copy2.spill = true;
|
|
26607
|
+
return copy2;
|
|
26249
26608
|
}
|
|
26250
|
-
|
|
26251
|
-
|
|
26252
|
-
|
|
26253
|
-
|
|
26254
|
-
|
|
26255
|
-
return;
|
|
26609
|
+
case "unary":
|
|
26610
|
+
case "percent": {
|
|
26611
|
+
const operand4 = copyTree(node.operand, t, rows);
|
|
26612
|
+
if (operand4 === node.operand) return node;
|
|
26613
|
+
return node.type === "unary" ? { type: "unary", op: node.op, operand: operand4 } : { type: "percent", operand: operand4 };
|
|
26256
26614
|
}
|
|
26257
|
-
|
|
26258
|
-
|
|
26259
|
-
|
|
26260
|
-
if (
|
|
26261
|
-
|
|
26615
|
+
case "binary": {
|
|
26616
|
+
const left2 = copyTree(node.left, t, rows);
|
|
26617
|
+
const right2 = copyTree(node.right, t, rows);
|
|
26618
|
+
if (left2 === node.left && right2 === node.right) return node;
|
|
26619
|
+
return { type: "binary", op: node.op, left: left2, right: right2 };
|
|
26262
26620
|
}
|
|
26263
|
-
|
|
26264
|
-
|
|
26265
|
-
|
|
26266
|
-
|
|
26267
|
-
this.collect(sheet, range, found);
|
|
26268
|
-
if (Array.isArray(out)) for (const node of found) out.push(node);
|
|
26269
|
-
}
|
|
26270
|
-
collect(sheet, range, out) {
|
|
26271
|
-
const { start, end } = range;
|
|
26272
|
-
const check3 = (list) => {
|
|
26273
|
-
if (list) {
|
|
26274
|
-
for (const entry3 of list) if (rangesIntersect(entry3.range, range)) out.add(entry3.node);
|
|
26275
|
-
}
|
|
26276
|
-
};
|
|
26277
|
-
const cells3 = this.cells.get(sheet);
|
|
26278
|
-
if (cells3) {
|
|
26279
|
-
const size = (end.row - start.row + 1) * (end.col - start.col + 1);
|
|
26280
|
-
if (size <= 4096) {
|
|
26281
|
-
for (let r = start.row; r <= end.row; r++) {
|
|
26282
|
-
for (let c2 = start.col; c2 <= end.col; c2++) {
|
|
26283
|
-
const list = cells3.get(cellKey(r, c2));
|
|
26284
|
-
if (list) for (const node of list) out.add(node);
|
|
26285
|
-
}
|
|
26286
|
-
}
|
|
26287
|
-
} else {
|
|
26288
|
-
for (const [key2, list] of cells3) {
|
|
26289
|
-
const { row: row2, col } = keyToAddress(key2);
|
|
26290
|
-
if (row2 >= start.row && row2 <= end.row && col >= start.col && col <= end.col)
|
|
26291
|
-
for (const node of list) out.add(node);
|
|
26292
|
-
}
|
|
26293
|
-
}
|
|
26621
|
+
case "call": {
|
|
26622
|
+
const args = copyAll(node.args, t, rows);
|
|
26623
|
+
if (args === node.args) return node;
|
|
26624
|
+
return { type: "call", name: node.name, rawName: node.rawName, args };
|
|
26294
26625
|
}
|
|
26295
|
-
|
|
26296
|
-
|
|
26297
|
-
|
|
26298
|
-
|
|
26299
|
-
|
|
26300
|
-
};
|
|
26301
|
-
const chunked = this.chunked.get(sheet);
|
|
26302
|
-
const first3 = start.row >> CHUNK_SHIFT;
|
|
26303
|
-
const last = end.row >> CHUNK_SHIFT;
|
|
26304
|
-
columns(chunked, (c2) => {
|
|
26305
|
-
const chunks = chunked?.get(c2);
|
|
26306
|
-
if (last - first3 + 1 <= chunks.size) {
|
|
26307
|
-
for (let k = first3; k <= last; k++) check3(chunks.get(k));
|
|
26308
|
-
} else for (const [k, list] of chunks) if (k >= first3 && k <= last) check3(list);
|
|
26309
|
-
});
|
|
26310
|
-
const tall = this.tall.get(sheet);
|
|
26311
|
-
columns(tall, (c2) => check3(tall?.get(c2)));
|
|
26312
|
-
check3(this.wide.get(sheet));
|
|
26313
|
-
}
|
|
26314
|
-
};
|
|
26315
|
-
|
|
26316
|
-
// xlsx/formula/graph-index.ts
|
|
26317
|
-
var ColumnIndex = class {
|
|
26318
|
-
sheets = /* @__PURE__ */ new Map();
|
|
26319
|
-
constructor(nodes) {
|
|
26320
|
-
for (const node of nodes) {
|
|
26321
|
-
let cols = this.sheets.get(node.sheet);
|
|
26322
|
-
if (!cols) this.sheets.set(node.sheet, cols = /* @__PURE__ */ new Map());
|
|
26323
|
-
let list = cols.get(node.col);
|
|
26324
|
-
if (!list) cols.set(node.col, list = []);
|
|
26325
|
-
list.push(node);
|
|
26626
|
+
case "invoke": {
|
|
26627
|
+
const callee = copyTree(node.callee, t, rows);
|
|
26628
|
+
const args = copyAll(node.args, t, rows);
|
|
26629
|
+
if (callee === node.callee && args === node.args) return node;
|
|
26630
|
+
return { type: "invoke", callee, args };
|
|
26326
26631
|
}
|
|
26327
|
-
|
|
26328
|
-
|
|
26632
|
+
default:
|
|
26633
|
+
return node;
|
|
26329
26634
|
}
|
|
26330
|
-
|
|
26331
|
-
|
|
26332
|
-
|
|
26333
|
-
|
|
26334
|
-
const
|
|
26335
|
-
const
|
|
26336
|
-
|
|
26337
|
-
|
|
26338
|
-
|
|
26339
|
-
|
|
26340
|
-
|
|
26341
|
-
|
|
26342
|
-
|
|
26343
|
-
|
|
26344
|
-
|
|
26345
|
-
|
|
26346
|
-
|
|
26347
|
-
|
|
26348
|
-
|
|
26349
|
-
|
|
26350
|
-
|
|
26351
|
-
|
|
26352
|
-
|
|
26353
|
-
|
|
26354
|
-
|
|
26355
|
-
|
|
26356
|
-
|
|
26635
|
+
}
|
|
26636
|
+
function copyAll(nodes, t, rows) {
|
|
26637
|
+
let out;
|
|
26638
|
+
for (let i2 = 0; i2 < nodes.length; i2++) {
|
|
26639
|
+
const node = nodes[i2];
|
|
26640
|
+
const copy2 = copyTree(node, t, rows);
|
|
26641
|
+
if (copy2 !== node && !out) out = nodes.slice(0, i2);
|
|
26642
|
+
out?.push(copy2);
|
|
26643
|
+
}
|
|
26644
|
+
return out ?? nodes;
|
|
26645
|
+
}
|
|
26646
|
+
function fromTemplate(t, formula, shape2) {
|
|
26647
|
+
const rows = rowsFor(t, formula, shape2);
|
|
26648
|
+
return rows ? copyTree(t.ast, t, rows) : void 0;
|
|
26649
|
+
}
|
|
26650
|
+
|
|
26651
|
+
// xlsx/formula/parse-cache.ts
|
|
26652
|
+
var MAX_TEMPLATE_LENGTH = 2048;
|
|
26653
|
+
var MAX_ENTRIES = 1e5;
|
|
26654
|
+
var MAX_TEMPLATES2 = 1e4;
|
|
26655
|
+
var NO_RUNS = { hash: 0, starts: [], ends: [] };
|
|
26656
|
+
var treeOf = (made) => "ast" in made ? made.ast : made;
|
|
26657
|
+
var ParseCache = class {
|
|
26658
|
+
byText = /* @__PURE__ */ new Map();
|
|
26659
|
+
templates = /* @__PURE__ */ new Map();
|
|
26660
|
+
parse(formula) {
|
|
26661
|
+
let ast = this.byText.get(formula);
|
|
26662
|
+
if (ast) return ast;
|
|
26663
|
+
ast = this.parseNew(formula);
|
|
26664
|
+
if (this.byText.size > MAX_ENTRIES) this.byText.clear();
|
|
26665
|
+
this.byText.set(formula, ast);
|
|
26666
|
+
return ast;
|
|
26357
26667
|
}
|
|
26358
|
-
|
|
26359
|
-
|
|
26360
|
-
|
|
26361
|
-
|
|
26362
|
-
|
|
26363
|
-
|
|
26364
|
-
|
|
26668
|
+
parseNew(formula) {
|
|
26669
|
+
if (formula.length > MAX_TEMPLATE_LENGTH) return treeOf(makeTemplate(formula, NO_RUNS));
|
|
26670
|
+
const shape2 = formulaShape(formula);
|
|
26671
|
+
const template = this.templates.get(shape2.hash);
|
|
26672
|
+
const reused = template && fromTemplate(template, formula, shape2);
|
|
26673
|
+
if (reused) return reused;
|
|
26674
|
+
const made = makeTemplate(formula, shape2);
|
|
26675
|
+
if (!template && "ast" in made) {
|
|
26676
|
+
if (this.templates.size > MAX_TEMPLATES2) this.templates.clear();
|
|
26677
|
+
this.templates.set(shape2.hash, made);
|
|
26365
26678
|
}
|
|
26679
|
+
return treeOf(made);
|
|
26366
26680
|
}
|
|
26367
26681
|
};
|
|
26368
26682
|
|
|
@@ -26502,7 +26816,7 @@ var EngineHost = class {
|
|
|
26502
26816
|
options;
|
|
26503
26817
|
nodes = /* @__PURE__ */ new Map();
|
|
26504
26818
|
footprints = /* @__PURE__ */ new Set();
|
|
26505
|
-
|
|
26819
|
+
parsed = new ParseCache();
|
|
26506
26820
|
boundsCache = /* @__PURE__ */ new Map();
|
|
26507
26821
|
inProgress = /* @__PURE__ */ new Set();
|
|
26508
26822
|
cycles = /* @__PURE__ */ new Set();
|
|
@@ -26526,6 +26840,8 @@ var EngineHost = class {
|
|
|
26526
26840
|
evaluations = 0;
|
|
26527
26841
|
built = false;
|
|
26528
26842
|
needsFull = false;
|
|
26843
|
+
/** No recalculation has run since the workbook was opened: stored values may stand. */
|
|
26844
|
+
fresh = true;
|
|
26529
26845
|
// ---- EvalHost ----
|
|
26530
26846
|
readCell(sheet, row2, col) {
|
|
26531
26847
|
const cell = this.workbook.sheets[sheet]?.rows.get(row2)?.get(col);
|
|
@@ -26614,19 +26930,7 @@ var EngineHost = class {
|
|
|
26614
26930
|
return this.workbook.sheets[sheet]?.rows.get(row2)?.get(col)?.formula;
|
|
26615
26931
|
}
|
|
26616
26932
|
parse(formula) {
|
|
26617
|
-
|
|
26618
|
-
if (!ast) {
|
|
26619
|
-
try {
|
|
26620
|
-
ast = parseFormula(formula);
|
|
26621
|
-
} catch (e) {
|
|
26622
|
-
if (e instanceof RangeError) ast = new FormulaError(e.message, -1, "#VALUE!");
|
|
26623
|
-
else if (!(e instanceof FormulaError)) throw e;
|
|
26624
|
-
else ast = e;
|
|
26625
|
-
}
|
|
26626
|
-
if (this.astCache.size > 1e5) this.astCache.clear();
|
|
26627
|
-
this.astCache.set(formula, ast);
|
|
26628
|
-
}
|
|
26629
|
-
return ast;
|
|
26933
|
+
return this.parsed.parse(formula);
|
|
26630
26934
|
}
|
|
26631
26935
|
now() {
|
|
26632
26936
|
return this.options.now ? this.options.now() : /* @__PURE__ */ new Date();
|
|
@@ -26635,20 +26939,6 @@ var EngineHost = class {
|
|
|
26635
26939
|
return this.options.random ? this.options.random() : Math.random();
|
|
26636
26940
|
}
|
|
26637
26941
|
// ---- graph ----
|
|
26638
|
-
build() {
|
|
26639
|
-
this.nodes.clear();
|
|
26640
|
-
this.footprints.clear();
|
|
26641
|
-
this.footprintIndex = void 0;
|
|
26642
|
-
this.workbook.sheets.forEach((sheet, s) => {
|
|
26643
|
-
for (const [row2, cells3] of sheet.rows) {
|
|
26644
|
-
for (const [col, cell] of cells3) {
|
|
26645
|
-
if (cell.formula) this.createNode(s, row2, col, cell, true);
|
|
26646
|
-
}
|
|
26647
|
-
}
|
|
26648
|
-
});
|
|
26649
|
-
this.built = true;
|
|
26650
|
-
this.graphChanged();
|
|
26651
|
-
}
|
|
26652
26942
|
createNode(sheet, row2, col, cell, initial) {
|
|
26653
26943
|
const formula = cell.formula ?? "";
|
|
26654
26944
|
const parsed = this.parse(formula);
|
|
@@ -26677,6 +26967,14 @@ var EngineHost = class {
|
|
|
26677
26967
|
map.set(cellKey(row2, col), node);
|
|
26678
26968
|
return node;
|
|
26679
26969
|
}
|
|
26970
|
+
/** Parses a node's text again after a structural edit rewrote it (see `FormulaNode.stale`). */
|
|
26971
|
+
refreshAst(node) {
|
|
26972
|
+
const parsed = this.parse(node.formula);
|
|
26973
|
+
delete node.stale;
|
|
26974
|
+
delete node.parseError;
|
|
26975
|
+
node.ast = parsed instanceof FormulaError ? void 0 : parsed;
|
|
26976
|
+
if (parsed instanceof FormulaError && parsed.code) node.parseError = err(parsed.code);
|
|
26977
|
+
}
|
|
26680
26978
|
removeNode(node, changed) {
|
|
26681
26979
|
const sheet = this.workbook.sheets[node.sheet];
|
|
26682
26980
|
if (node.spill && sheet) {
|
|
@@ -27107,6 +27405,7 @@ var EngineCore = class extends EngineHost {
|
|
|
27107
27405
|
return { host: this, sheet, row: row2, col, scope: void 0, depth: 0, root, legacy };
|
|
27108
27406
|
}
|
|
27109
27407
|
evaluateFormula(node) {
|
|
27408
|
+
if (node.stale) this.refreshAst(node);
|
|
27110
27409
|
if (!node.ast) return node.parseError ?? ERR.NAME;
|
|
27111
27410
|
const ast = node.ast;
|
|
27112
27411
|
const frame = this.frameFor(node.sheet, node.row, node.col, ast, node.legacy);
|
|
@@ -27124,20 +27423,363 @@ var EngineCore = class extends EngineHost {
|
|
|
27124
27423
|
}
|
|
27125
27424
|
};
|
|
27126
27425
|
|
|
27426
|
+
// xlsx/formula/shift-graph.ts
|
|
27427
|
+
var POSITIONAL = /* @__PURE__ */ new Set(["ROW", "COLUMN"]);
|
|
27428
|
+
var DESCRIPTIVE = /* @__PURE__ */ new Set(["FORMULATEXT", "CELL", "SHEET"]);
|
|
27429
|
+
var traitsCache = /* @__PURE__ */ new WeakMap();
|
|
27430
|
+
function astTraits(ast) {
|
|
27431
|
+
const cached3 = traitsCache.get(ast);
|
|
27432
|
+
if (cached3) return cached3;
|
|
27433
|
+
const sheets = /* @__PURE__ */ new Set();
|
|
27434
|
+
const traits = { complex: false, opaque: false, positional: false, descriptive: false, sheets };
|
|
27435
|
+
const stack2 = [ast];
|
|
27436
|
+
while (stack2.length) {
|
|
27437
|
+
const node = stack2.pop();
|
|
27438
|
+
switch (node.type) {
|
|
27439
|
+
case "ref":
|
|
27440
|
+
if (node.prefix) {
|
|
27441
|
+
sheets.add(node.prefix.sheet.toLowerCase());
|
|
27442
|
+
if (node.prefix.sheet2 !== void 0) {
|
|
27443
|
+
sheets.add(node.prefix.sheet2.toLowerCase());
|
|
27444
|
+
traits.complex = true;
|
|
27445
|
+
}
|
|
27446
|
+
}
|
|
27447
|
+
break;
|
|
27448
|
+
case "name":
|
|
27449
|
+
if (node.prefix) sheets.add(node.prefix.sheet.toLowerCase());
|
|
27450
|
+
traits.complex = true;
|
|
27451
|
+
break;
|
|
27452
|
+
case "structured":
|
|
27453
|
+
traits.complex = true;
|
|
27454
|
+
break;
|
|
27455
|
+
case "unary":
|
|
27456
|
+
case "percent":
|
|
27457
|
+
stack2.push(node.operand);
|
|
27458
|
+
break;
|
|
27459
|
+
case "binary":
|
|
27460
|
+
stack2.push(node.left, node.right);
|
|
27461
|
+
break;
|
|
27462
|
+
case "call":
|
|
27463
|
+
if (POSITIONAL.has(node.name)) traits.positional = true;
|
|
27464
|
+
if (DESCRIPTIVE.has(node.name)) traits.descriptive = true;
|
|
27465
|
+
if (!getFunction(node.name)) traits.complex = traits.opaque = true;
|
|
27466
|
+
stack2.push(...node.args);
|
|
27467
|
+
break;
|
|
27468
|
+
case "invoke":
|
|
27469
|
+
stack2.push(node.callee, ...node.args);
|
|
27470
|
+
break;
|
|
27471
|
+
}
|
|
27472
|
+
}
|
|
27473
|
+
traitsCache.set(ast, traits);
|
|
27474
|
+
return traits;
|
|
27475
|
+
}
|
|
27476
|
+
function intervalDelta(a2, b, shift2) {
|
|
27477
|
+
const { at: at2, count: count2 } = shift2;
|
|
27478
|
+
if (count2 > 0) {
|
|
27479
|
+
if (b < at2) return 0;
|
|
27480
|
+
if (a2 < at2) return void 0;
|
|
27481
|
+
return b + count2 > (shift2.axis === "row" ? MAX_ROW : MAX_COL) ? void 0 : count2;
|
|
27482
|
+
}
|
|
27483
|
+
const last = at2 - count2 - 1;
|
|
27484
|
+
if (b < at2) return 0;
|
|
27485
|
+
if (a2 > last) return count2;
|
|
27486
|
+
return void 0;
|
|
27487
|
+
}
|
|
27488
|
+
function areaDelta(area, sheet, shift2) {
|
|
27489
|
+
if (area.sheet !== sheet) return 0;
|
|
27490
|
+
const { start, end } = area.range;
|
|
27491
|
+
return shift2.axis === "row" ? intervalDelta(start.row, end.row, shift2) : intervalDelta(start.col, end.col, shift2);
|
|
27492
|
+
}
|
|
27493
|
+
function movedRange(range, axis, delta) {
|
|
27494
|
+
if (delta === 0) return range;
|
|
27495
|
+
return axis === "row" ? {
|
|
27496
|
+
start: { row: range.start.row + delta, col: range.start.col },
|
|
27497
|
+
end: { row: range.end.row + delta, col: range.end.col }
|
|
27498
|
+
} : {
|
|
27499
|
+
start: { row: range.start.row, col: range.start.col + delta },
|
|
27500
|
+
end: { row: range.end.row, col: range.end.col + delta }
|
|
27501
|
+
};
|
|
27502
|
+
}
|
|
27503
|
+
function reachesEdit(areas, sheet, shift2) {
|
|
27504
|
+
for (const area of areas) {
|
|
27505
|
+
if (area.sheet !== sheet) continue;
|
|
27506
|
+
if ((shift2.axis === "row" ? area.range.end.row : area.range.end.col) >= shift2.at) return true;
|
|
27507
|
+
}
|
|
27508
|
+
return false;
|
|
27509
|
+
}
|
|
27510
|
+
function intersectionMoves(area, delta, pos, nodeDelta, axis) {
|
|
27511
|
+
if (delta === nodeDelta) return false;
|
|
27512
|
+
const { start, end } = area.range;
|
|
27513
|
+
const a2 = axis === "row" ? start.row : start.col;
|
|
27514
|
+
const b = axis === "row" ? end.row : end.col;
|
|
27515
|
+
if (a2 === b) return false;
|
|
27516
|
+
return pos >= a2 && pos <= b || pos + nodeDelta >= a2 + delta && pos + nodeDelta <= b + delta;
|
|
27517
|
+
}
|
|
27518
|
+
|
|
27519
|
+
// xlsx/formula/engine-structure.ts
|
|
27520
|
+
var sameAreas = (a2, b) => a2.length === b.length && a2.every((x, i2) => {
|
|
27521
|
+
const y = b[i2];
|
|
27522
|
+
return x.sheet === y.sheet && sameRange(x.range, y.range);
|
|
27523
|
+
});
|
|
27524
|
+
var EngineStructure = class extends EngineCore {
|
|
27525
|
+
/** Formulas a structural edit left to recalculate (with their dependents) on the next pass. */
|
|
27526
|
+
structuralSeeds = /* @__PURE__ */ new Set();
|
|
27527
|
+
/** Whether the graph describes the workbook as it was before the edit just reported. */
|
|
27528
|
+
graphReady() {
|
|
27529
|
+
return this.built && !this.needsFull;
|
|
27530
|
+
}
|
|
27531
|
+
/** Parses a node's current text again and recomputes its precedents. */
|
|
27532
|
+
reanalyze(node) {
|
|
27533
|
+
const parsed = this.parse(node.formula);
|
|
27534
|
+
delete node.stale;
|
|
27535
|
+
delete node.parseError;
|
|
27536
|
+
if (parsed instanceof FormulaError) {
|
|
27537
|
+
node.ast = void 0;
|
|
27538
|
+
if (parsed.code) node.parseError = err(parsed.code);
|
|
27539
|
+
node.deps = [];
|
|
27540
|
+
node.dynamicDeps = [];
|
|
27541
|
+
return;
|
|
27542
|
+
}
|
|
27543
|
+
node.ast = parsed;
|
|
27544
|
+
const found = analyze(parsed, this, node.sheet, node.row, node.col);
|
|
27545
|
+
node.deps = found.deps;
|
|
27546
|
+
node.dynamicDeps = found.dynamicDeps;
|
|
27547
|
+
node.volatile = found.volatile;
|
|
27548
|
+
node.unsupported = found.unsupported;
|
|
27549
|
+
}
|
|
27550
|
+
/**
|
|
27551
|
+
* Moves the graph for rows or columns inserted or deleted on `sheet`, after the workbook was
|
|
27552
|
+
* changed (cells moved, formulas rewritten). Spills on the sheet, array formulas the edit cuts
|
|
27553
|
+
* and anything unexpected fall back to a rebuild on the next recalculation.
|
|
27554
|
+
*/
|
|
27555
|
+
shiftCells(sheet, shift2) {
|
|
27556
|
+
if (!this.graphReady() || !this.shiftable(sheet, shift2)) {
|
|
27557
|
+
this.invalidate();
|
|
27558
|
+
return;
|
|
27559
|
+
}
|
|
27560
|
+
const ws = this.workbook.sheets[sheet];
|
|
27561
|
+
const own = this.nodes.get(sheet);
|
|
27562
|
+
if (!ws) return;
|
|
27563
|
+
const moved = /* @__PURE__ */ new Map();
|
|
27564
|
+
if (own) {
|
|
27565
|
+
const next = /* @__PURE__ */ new Map();
|
|
27566
|
+
for (const node of own.values()) {
|
|
27567
|
+
const pos = shift2.axis === "row" ? node.row : node.col;
|
|
27568
|
+
const delta = intervalDelta(pos, pos, shift2);
|
|
27569
|
+
if (delta === void 0) {
|
|
27570
|
+
this.dropNode(node);
|
|
27571
|
+
continue;
|
|
27572
|
+
}
|
|
27573
|
+
if (delta !== 0) {
|
|
27574
|
+
moved.set(node, delta);
|
|
27575
|
+
if (shift2.axis === "row") node.row += delta;
|
|
27576
|
+
else node.col += delta;
|
|
27577
|
+
}
|
|
27578
|
+
next.set(cellKey(node.row, node.col), node);
|
|
27579
|
+
}
|
|
27580
|
+
this.nodes.set(sheet, next);
|
|
27581
|
+
}
|
|
27582
|
+
for (const map of this.nodes.values())
|
|
27583
|
+
for (const node of map.values()) {
|
|
27584
|
+
if (!this.shiftNode(node, sheet, shift2, moved.get(node) ?? 0)) {
|
|
27585
|
+
this.invalidate();
|
|
27586
|
+
return;
|
|
27587
|
+
}
|
|
27588
|
+
}
|
|
27589
|
+
this.boundsCache.clear();
|
|
27590
|
+
this.graphChanged();
|
|
27591
|
+
}
|
|
27592
|
+
/** No spill or stale spilled value on the sheet, and no array formula the edit cuts. */
|
|
27593
|
+
shiftable(sheet, shift2) {
|
|
27594
|
+
for (const node of this.footprints) {
|
|
27595
|
+
if (node.sheet !== sheet) continue;
|
|
27596
|
+
if (node.spill || node.blockedSpill) return false;
|
|
27597
|
+
if (node.arrayRange && areaDelta({ sheet, range: node.arrayRange }, sheet, shift2) === void 0)
|
|
27598
|
+
return false;
|
|
27599
|
+
}
|
|
27600
|
+
const ws = this.workbook.sheets[sheet];
|
|
27601
|
+
let spilled = false;
|
|
27602
|
+
ws?.rows.forEach((cells3) => {
|
|
27603
|
+
if (!spilled) cells3.forEach((cell) => spilled ||= isSpilledCell(cell));
|
|
27604
|
+
});
|
|
27605
|
+
return !spilled;
|
|
27606
|
+
}
|
|
27607
|
+
dropNode(node) {
|
|
27608
|
+
this.structuralSeeds.delete(node);
|
|
27609
|
+
this.cycles.delete(node);
|
|
27610
|
+
this.footprints.delete(node);
|
|
27611
|
+
}
|
|
27612
|
+
/** Updates one formula for the edit; false when the graph cannot follow it. */
|
|
27613
|
+
shiftNode(node, sheet, shift2, nodeDelta) {
|
|
27614
|
+
const cell = this.workbook.sheets[node.sheet]?.rows.get(node.row)?.get(node.col);
|
|
27615
|
+
if (cell?.formula === void 0) return false;
|
|
27616
|
+
if (node.arrayRange) {
|
|
27617
|
+
const delta = areaDelta({ sheet: node.sheet, range: node.arrayRange }, sheet, shift2);
|
|
27618
|
+
if (delta === void 0) return false;
|
|
27619
|
+
node.arrayRange = movedRange(node.arrayRange, shift2.axis, delta);
|
|
27620
|
+
if (!cell.arrayRange || !sameRange(node.arrayRange, normalizeRange(cell.arrayRange)))
|
|
27621
|
+
return false;
|
|
27622
|
+
}
|
|
27623
|
+
const changed = cell.formula !== node.formula;
|
|
27624
|
+
const traits = node.ast && astTraits(node.ast);
|
|
27625
|
+
const reached = reachesEdit(node.deps, sheet, shift2) || reachesEdit(node.dynamicDeps, sheet, shift2);
|
|
27626
|
+
if (!changed && !reached && nodeDelta === 0 && !traits?.descriptive && !traits?.opaque)
|
|
27627
|
+
return true;
|
|
27628
|
+
if (traits?.complex) {
|
|
27629
|
+
node.formula = cell.formula;
|
|
27630
|
+
this.reanalyze(node);
|
|
27631
|
+
this.structuralSeeds.add(node);
|
|
27632
|
+
return true;
|
|
27633
|
+
}
|
|
27634
|
+
const pos = shift2.axis === "row" ? node.row - nodeDelta : node.col - nodeDelta;
|
|
27635
|
+
const moves = { seed: !!traits?.descriptive, moved: false, cut: false };
|
|
27636
|
+
const deps = this.moveAreas(node.deps, sheet, shift2, pos, nodeDelta, moves);
|
|
27637
|
+
const dynamicDeps = this.moveAreas(node.dynamicDeps, sheet, shift2, pos, nodeDelta, moves);
|
|
27638
|
+
const { cut, moved: anyMoved } = moves;
|
|
27639
|
+
let seed = moves.seed;
|
|
27640
|
+
if (cut || changed !== anyMoved) {
|
|
27641
|
+
node.formula = cell.formula;
|
|
27642
|
+
this.reanalyze(node);
|
|
27643
|
+
this.structuralSeeds.add(node);
|
|
27644
|
+
return true;
|
|
27645
|
+
}
|
|
27646
|
+
if (traits?.positional && (anyMoved || nodeDelta !== 0)) seed = true;
|
|
27647
|
+
node.deps = deps;
|
|
27648
|
+
node.dynamicDeps = dynamicDeps;
|
|
27649
|
+
if (changed) {
|
|
27650
|
+
node.formula = cell.formula;
|
|
27651
|
+
node.stale = true;
|
|
27652
|
+
}
|
|
27653
|
+
if (seed) this.structuralSeeds.add(node);
|
|
27654
|
+
return true;
|
|
27655
|
+
}
|
|
27656
|
+
/**
|
|
27657
|
+
* Areas moved for the edit (the same list when none moves). Records in `moves` whether one
|
|
27658
|
+
* moved, one was cut (deleted, widened, pushed off the grid) and whether implicit intersection
|
|
27659
|
+
* with one can now pick another cell.
|
|
27660
|
+
*/
|
|
27661
|
+
moveAreas(list, sheet, shift2, pos, nodeDelta, moves) {
|
|
27662
|
+
let out;
|
|
27663
|
+
for (let i2 = 0; i2 < list.length; i2++) {
|
|
27664
|
+
const area = list[i2];
|
|
27665
|
+
const delta = areaDelta(area, sheet, shift2);
|
|
27666
|
+
if (delta === void 0) {
|
|
27667
|
+
moves.cut = true;
|
|
27668
|
+
continue;
|
|
27669
|
+
}
|
|
27670
|
+
if (intersectionMoves(area, delta, pos, nodeDelta, shift2.axis)) moves.seed = true;
|
|
27671
|
+
if (delta === 0) continue;
|
|
27672
|
+
moves.moved = true;
|
|
27673
|
+
out ??= list.slice();
|
|
27674
|
+
out[i2] = { sheet: area.sheet, range: movedRange(area.range, shift2.axis, delta) };
|
|
27675
|
+
}
|
|
27676
|
+
return out ?? list;
|
|
27677
|
+
}
|
|
27678
|
+
/**
|
|
27679
|
+
* Follows a sheet rename (`from` to `to`, formulas already rewritten): precedents are kept by
|
|
27680
|
+
* sheet index, so only rewritten formulas need their text parsed again, and only formulas that
|
|
27681
|
+
* name the new sheet without having been rewritten (previously unresolved), describe sheets
|
|
27682
|
+
* (CELL, SHEET, FORMULATEXT) or read defined names whose areas changed are recalculated.
|
|
27683
|
+
*/
|
|
27684
|
+
renameSheet(from, to) {
|
|
27685
|
+
if (!this.graphReady()) {
|
|
27686
|
+
this.invalidate();
|
|
27687
|
+
return;
|
|
27688
|
+
}
|
|
27689
|
+
const target = to.toLowerCase();
|
|
27690
|
+
let depsChanged = false;
|
|
27691
|
+
for (const map of this.nodes.values())
|
|
27692
|
+
for (const node of map.values()) {
|
|
27693
|
+
const cell = this.workbook.sheets[node.sheet]?.rows.get(node.row)?.get(node.col);
|
|
27694
|
+
if (cell?.formula === void 0) {
|
|
27695
|
+
this.invalidate();
|
|
27696
|
+
return;
|
|
27697
|
+
}
|
|
27698
|
+
const changed = cell.formula !== node.formula;
|
|
27699
|
+
const traits = node.ast && astTraits(node.ast);
|
|
27700
|
+
node.formula = cell.formula;
|
|
27701
|
+
if (traits?.complex || !changed && traits?.sheets.has(target)) {
|
|
27702
|
+
const deps = node.deps;
|
|
27703
|
+
const dynamicDeps = node.dynamicDeps;
|
|
27704
|
+
this.reanalyze(node);
|
|
27705
|
+
const same5 = sameAreas(deps, node.deps) && sameAreas(dynamicDeps, node.dynamicDeps);
|
|
27706
|
+
if (!same5) depsChanged = true;
|
|
27707
|
+
if (!same5 || !traits?.complex) this.structuralSeeds.add(node);
|
|
27708
|
+
} else if (changed) node.stale = true;
|
|
27709
|
+
if (traits?.descriptive || traits?.opaque) this.structuralSeeds.add(node);
|
|
27710
|
+
}
|
|
27711
|
+
if (depsChanged) this.graphChanged();
|
|
27712
|
+
}
|
|
27713
|
+
/** Takes the formulas queued by structural edits. */
|
|
27714
|
+
takeStructuralSeeds(into) {
|
|
27715
|
+
for (const node of this.structuralSeeds)
|
|
27716
|
+
if (this.nodes.get(node.sheet)?.get(cellKey(node.row, node.col)) === node) into.add(node);
|
|
27717
|
+
this.structuralSeeds.clear();
|
|
27718
|
+
}
|
|
27719
|
+
};
|
|
27720
|
+
|
|
27127
27721
|
// xlsx/formula/engine.ts
|
|
27128
|
-
var Engine = class extends
|
|
27722
|
+
var Engine = class extends EngineStructure {
|
|
27723
|
+
preparation;
|
|
27724
|
+
/** The prepared formulas the first recalculation checks (see `trustsStoredValues`). */
|
|
27725
|
+
prepared;
|
|
27726
|
+
// ---- the graph ----
|
|
27727
|
+
prepare(timeRemaining) {
|
|
27728
|
+
if (this.built || this.needsFull) return true;
|
|
27729
|
+
this.preparation ??= this.startPreparation();
|
|
27730
|
+
if (!this.preparation.run(timeRemaining)) return false;
|
|
27731
|
+
this.finishPreparation(this.preparation);
|
|
27732
|
+
return true;
|
|
27733
|
+
}
|
|
27734
|
+
discardPreparation() {
|
|
27735
|
+
if (!this.fresh || this.needsFull) return;
|
|
27736
|
+
this.preparation = void 0;
|
|
27737
|
+
this.prepared = void 0;
|
|
27738
|
+
this.structuralSeeds.clear();
|
|
27739
|
+
this.nodes.clear();
|
|
27740
|
+
this.footprints.clear();
|
|
27741
|
+
this.graphChanged();
|
|
27742
|
+
this.built = false;
|
|
27743
|
+
}
|
|
27744
|
+
/** Completes the graph, continuing a preparation that is under way. */
|
|
27745
|
+
build() {
|
|
27746
|
+
const preparation = this.preparation ?? this.startPreparation();
|
|
27747
|
+
preparation.run();
|
|
27748
|
+
this.finishPreparation(preparation);
|
|
27749
|
+
}
|
|
27750
|
+
startPreparation() {
|
|
27751
|
+
this.nodes.clear();
|
|
27752
|
+
this.footprints.clear();
|
|
27753
|
+
this.footprintIndex = void 0;
|
|
27754
|
+
this.prepared = void 0;
|
|
27755
|
+
return new GraphPreparation(
|
|
27756
|
+
this.workbook,
|
|
27757
|
+
(s, row2, col, cell) => this.createNode(s, row2, col, cell, true)
|
|
27758
|
+
);
|
|
27759
|
+
}
|
|
27760
|
+
finishPreparation(preparation) {
|
|
27761
|
+
this.preparation = void 0;
|
|
27762
|
+
this.built = true;
|
|
27763
|
+
this.graphChanged();
|
|
27764
|
+
this.reverseIndex = preparation.reverse;
|
|
27765
|
+
this.prepared = preparation.formulas;
|
|
27766
|
+
}
|
|
27129
27767
|
// ---- recalculation ----
|
|
27130
27768
|
recalculateAll() {
|
|
27769
|
+
this.fresh = false;
|
|
27770
|
+
this.prepared = void 0;
|
|
27131
27771
|
if (this.needsFull) this.releaseAllSpills();
|
|
27132
27772
|
if (!this.built || this.needsFull) this.build();
|
|
27133
27773
|
this.needsFull = false;
|
|
27774
|
+
this.structuralSeeds.clear();
|
|
27134
27775
|
this.cycles = /* @__PURE__ */ new Set();
|
|
27135
27776
|
this.run(new Set(this.allNodes()), true);
|
|
27136
27777
|
}
|
|
27137
27778
|
recalculateFrom(changes) {
|
|
27138
27779
|
const seeds = /* @__PURE__ */ new Set();
|
|
27139
|
-
if (
|
|
27140
|
-
this.
|
|
27780
|
+
if (this.fresh && !this.needsFull) {
|
|
27781
|
+
this.fresh = false;
|
|
27782
|
+
if (!this.built) this.build();
|
|
27141
27783
|
if (!this.trustsStoredValues(changes, seeds)) {
|
|
27142
27784
|
this.recalculateAll();
|
|
27143
27785
|
return;
|
|
@@ -27181,6 +27823,7 @@ var Engine = class extends EngineCore {
|
|
|
27181
27823
|
}
|
|
27182
27824
|
}
|
|
27183
27825
|
if (structural) this.graphChanged();
|
|
27826
|
+
this.takeStructuralSeeds(seeds);
|
|
27184
27827
|
const reverse2 = this.reverse();
|
|
27185
27828
|
for (const area of changed) reverse2.dependents(area.sheet, area.range, seeds);
|
|
27186
27829
|
for (const node of this.allNodes()) if (node.volatile) seeds.add(node);
|
|
@@ -27192,13 +27835,18 @@ var Engine = class extends EngineCore {
|
|
|
27192
27835
|
* without a value into `missing`.
|
|
27193
27836
|
*/
|
|
27194
27837
|
trustsStoredValues(changes, missing) {
|
|
27838
|
+
const prepared = this.prepared;
|
|
27839
|
+
this.prepared = void 0;
|
|
27840
|
+
if (!prepared) return false;
|
|
27195
27841
|
const changed = new Set(changes.map((c2) => `${c2.sheet}:${cellKey(c2.row, c2.col)}`));
|
|
27196
|
-
|
|
27197
|
-
|
|
27198
|
-
if (
|
|
27842
|
+
const current = (node) => this.nodes.get(node.sheet)?.get(cellKey(node.row, node.col)) === node;
|
|
27843
|
+
for (const node of prepared.dynamic) {
|
|
27844
|
+
if (current(node) && !changed.has(`${node.sheet}:${cellKey(node.row, node.col)}`))
|
|
27199
27845
|
return false;
|
|
27846
|
+
}
|
|
27847
|
+
for (const node of prepared.unvalued) {
|
|
27200
27848
|
const cell = this.workbook.sheets[node.sheet]?.rows.get(node.row)?.get(node.col);
|
|
27201
|
-
if (cell && cell.value === null
|
|
27849
|
+
if (current(node) && cell && cell.value === null) missing.add(node);
|
|
27202
27850
|
}
|
|
27203
27851
|
return true;
|
|
27204
27852
|
}
|
|
@@ -27212,7 +27860,10 @@ var Engine = class extends EngineCore {
|
|
|
27212
27860
|
return !!anchor?.spill && rangeHas(anchor.spill, row2, col);
|
|
27213
27861
|
}
|
|
27214
27862
|
invalidate() {
|
|
27863
|
+
this.structuralSeeds.clear();
|
|
27215
27864
|
this.releaseAllSpills();
|
|
27865
|
+
this.preparation = void 0;
|
|
27866
|
+
this.prepared = void 0;
|
|
27216
27867
|
this.nodes.clear();
|
|
27217
27868
|
this.footprints.clear();
|
|
27218
27869
|
this.graphChanged();
|
|
@@ -30143,13 +30794,13 @@ function linearTrend(values2) {
|
|
|
30143
30794
|
const slope = den ? num3 / den : 0;
|
|
30144
30795
|
return (k) => Number((meanY + slope * (k - meanX)).toPrecision(15));
|
|
30145
30796
|
}
|
|
30146
|
-
var
|
|
30797
|
+
var isDigit5 = (ch) => ch !== void 0 && ch >= "0" && ch <= "9";
|
|
30147
30798
|
function matchTextNumber(text2) {
|
|
30148
30799
|
let end = text2.length;
|
|
30149
|
-
while (end > 0 && !
|
|
30800
|
+
while (end > 0 && !isDigit5(text2[end - 1])) end--;
|
|
30150
30801
|
if (end === 0) return null;
|
|
30151
30802
|
let start = end;
|
|
30152
|
-
while (start > 0 &&
|
|
30803
|
+
while (start > 0 && isDigit5(text2[start - 1])) start--;
|
|
30153
30804
|
return [text2, text2.slice(0, start), text2.slice(start, end), text2.slice(end)];
|
|
30154
30805
|
}
|
|
30155
30806
|
var QUARTER = /^(q|qtr|quarter)(\s?)([1-4])$/i;
|
|
@@ -30332,10 +30983,10 @@ function removeValidationArea(rules, area) {
|
|
|
30332
30983
|
}
|
|
30333
30984
|
|
|
30334
30985
|
// xlsx/edit/conditional-formulas.ts
|
|
30335
|
-
function rewriteConditionalRule(rule2,
|
|
30986
|
+
function rewriteConditionalRule(rule2, rewrite2) {
|
|
30336
30987
|
const safe2 = (formula) => {
|
|
30337
30988
|
try {
|
|
30338
|
-
return
|
|
30989
|
+
return rewrite2(formula);
|
|
30339
30990
|
} catch {
|
|
30340
30991
|
return formula;
|
|
30341
30992
|
}
|
|
@@ -30854,7 +31505,7 @@ function shiftPreservedXml(sheet, shift2, moveRange, banded) {
|
|
|
30854
31505
|
(xml) => xml.includes("sqref")
|
|
30855
31506
|
);
|
|
30856
31507
|
}
|
|
30857
|
-
function rewritePreservedFormulas(sheet,
|
|
31508
|
+
function rewritePreservedFormulas(sheet, rewrite2) {
|
|
30858
31509
|
editEntries(
|
|
30859
31510
|
sheet,
|
|
30860
31511
|
"extLst",
|
|
@@ -30864,7 +31515,7 @@ function rewritePreservedFormulas(sheet, rewrite3) {
|
|
|
30864
31515
|
const text2 = f6.textContent ?? "";
|
|
30865
31516
|
let next = text2;
|
|
30866
31517
|
try {
|
|
30867
|
-
next =
|
|
31518
|
+
next = rewrite2(text2, sheet.name);
|
|
30868
31519
|
} catch {
|
|
30869
31520
|
next = text2;
|
|
30870
31521
|
}
|
|
@@ -30879,46 +31530,46 @@ function rewritePreservedFormulas(sheet, rewrite3) {
|
|
|
30879
31530
|
}
|
|
30880
31531
|
|
|
30881
31532
|
// xlsx/edit/shift-formulas.ts
|
|
30882
|
-
function safe(
|
|
31533
|
+
function safe(rewrite2, formula, formulaSheet) {
|
|
30883
31534
|
try {
|
|
30884
|
-
return
|
|
31535
|
+
return rewrite2(formula, formulaSheet);
|
|
30885
31536
|
} catch {
|
|
30886
31537
|
return formula;
|
|
30887
31538
|
}
|
|
30888
31539
|
}
|
|
30889
|
-
function rewriteFormulas(workbook,
|
|
30890
|
-
for (const sheet of workbook.sheets) rewriteSheetFormulas(sheet,
|
|
31540
|
+
function rewriteFormulas(workbook, rewrite2) {
|
|
31541
|
+
for (const sheet of workbook.sheets) rewriteSheetFormulas(sheet, rewrite2);
|
|
30891
31542
|
for (const definedName of workbook.definedNames) {
|
|
30892
31543
|
const local = definedName.localSheet === void 0 ? void 0 : workbook.sheets[definedName.localSheet];
|
|
30893
|
-
definedName.formula = safe(
|
|
31544
|
+
definedName.formula = safe(rewrite2, definedName.formula, local?.name ?? "");
|
|
30894
31545
|
}
|
|
30895
31546
|
}
|
|
30896
|
-
function rewriteSheetFormulas(sheet,
|
|
30897
|
-
rewritePreservedFormulas(sheet,
|
|
31547
|
+
function rewriteSheetFormulas(sheet, rewrite2) {
|
|
31548
|
+
rewritePreservedFormulas(sheet, rewrite2);
|
|
30898
31549
|
{
|
|
30899
31550
|
const name = sheet.name;
|
|
30900
31551
|
for (const table2 of sheet.tables)
|
|
30901
31552
|
for (const column of table2.columns)
|
|
30902
31553
|
if (column.calculatedColumnFormula !== void 0)
|
|
30903
|
-
column.calculatedColumnFormula = safe(
|
|
31554
|
+
column.calculatedColumnFormula = safe(rewrite2, column.calculatedColumnFormula, name);
|
|
30904
31555
|
for (const cells3 of sheet.rows.values())
|
|
30905
31556
|
for (const cell of cells3.values())
|
|
30906
|
-
if (cell.formula !== void 0) cell.formula = safe(
|
|
31557
|
+
if (cell.formula !== void 0) cell.formula = safe(rewrite2, cell.formula, name);
|
|
30907
31558
|
for (const cf of sheet.conditionalFormats)
|
|
30908
|
-
for (const rule2 of cf.rules) rewriteConditionalRule(rule2, (f6) =>
|
|
31559
|
+
for (const rule2 of cf.rules) rewriteConditionalRule(rule2, (f6) => rewrite2(f6, name));
|
|
30909
31560
|
for (const dv of sheet.dataValidations) {
|
|
30910
|
-
if (dv.formula1 !== void 0) dv.formula1 = safe(
|
|
30911
|
-
if (dv.formula2 !== void 0) dv.formula2 = safe(
|
|
31561
|
+
if (dv.formula1 !== void 0) dv.formula1 = safe(rewrite2, dv.formula1, name);
|
|
31562
|
+
if (dv.formula2 !== void 0) dv.formula2 = safe(rewrite2, dv.formula2, name);
|
|
30912
31563
|
}
|
|
30913
31564
|
for (const link of sheet.hyperlinks)
|
|
30914
31565
|
if (link.location && /![A-Za-z$]/.test(link.location))
|
|
30915
|
-
link.location = safe(
|
|
31566
|
+
link.location = safe(rewrite2, link.location, name);
|
|
30916
31567
|
for (const drawing of sheet.drawings) {
|
|
30917
31568
|
if (drawing.kind !== "chart") continue;
|
|
30918
31569
|
for (const series of drawing.series) {
|
|
30919
|
-
if (series.nameRef) series.nameRef = safe(
|
|
30920
|
-
if (series.categoriesRef) series.categoriesRef = safe(
|
|
30921
|
-
if (series.valuesRef) series.valuesRef = safe(
|
|
31570
|
+
if (series.nameRef) series.nameRef = safe(rewrite2, series.nameRef, name);
|
|
31571
|
+
if (series.categoriesRef) series.categoriesRef = safe(rewrite2, series.categoriesRef, name);
|
|
31572
|
+
if (series.valuesRef) series.valuesRef = safe(rewrite2, series.valuesRef, name);
|
|
30922
31573
|
}
|
|
30923
31574
|
}
|
|
30924
31575
|
}
|
|
@@ -31105,7 +31756,7 @@ function shiftAxis(ctx, s, axis, at2, count2, insert) {
|
|
|
31105
31756
|
applyAxisShift(ctx, sheet, shift2);
|
|
31106
31757
|
if (insert) inheritFormats(sheet, axis, at2, count2);
|
|
31107
31758
|
},
|
|
31108
|
-
{ sheet: s, structural: true }
|
|
31759
|
+
{ sheet: s, structural: true, calc: { kind: "shift", sheet: s, shift: shift2 } }
|
|
31109
31760
|
);
|
|
31110
31761
|
}
|
|
31111
31762
|
var insertRows = (ctx, s, at2, count2) => shiftAxis(ctx, s, "row", at2, count2, true);
|
|
@@ -32919,6 +33570,14 @@ function setCalcMode(ctx, mode) {
|
|
|
32919
33570
|
|
|
32920
33571
|
// xlsx/edit/session-calc.ts
|
|
32921
33572
|
var isStructural = (step) => step.structural || step.entries.some((entry3) => entry3.before.kind !== "cells");
|
|
33573
|
+
function hintFor(step, mode) {
|
|
33574
|
+
const hint = step.calc;
|
|
33575
|
+
if (!hint) return void 0;
|
|
33576
|
+
if (hint.kind === "rename")
|
|
33577
|
+
return mode === "undo" ? { kind: "rename", from: hint.to, to: hint.from } : hint;
|
|
33578
|
+
return mode === "undo" ? void 0 : hint;
|
|
33579
|
+
}
|
|
33580
|
+
var settingsOf = (workbook) => `${workbook.iterate ? `${workbook.iterate.count}:${workbook.iterate.delta}` : ""}|${workbook.date1904}`;
|
|
32922
33581
|
var SessionCalculator = class {
|
|
32923
33582
|
constructor(workbook, calc, enabled2) {
|
|
32924
33583
|
this.workbook = workbook;
|
|
@@ -32928,43 +33587,113 @@ var SessionCalculator = class {
|
|
|
32928
33587
|
workbook;
|
|
32929
33588
|
calc;
|
|
32930
33589
|
enabled;
|
|
32931
|
-
/** Structural edits
|
|
33590
|
+
/** Structural edits the engine could not follow leave the dependency graph stale (manual mode). */
|
|
32932
33591
|
staleGraph = false;
|
|
33592
|
+
/** Cells changed in manual mode since the last calculation. */
|
|
33593
|
+
dirty = [];
|
|
33594
|
+
/** The settings at the last calculation; undefined before the first. */
|
|
33595
|
+
calculated;
|
|
32933
33596
|
/** Recalculates after an applied, undone or redone step (failures become warnings). */
|
|
32934
|
-
afterStep(step) {
|
|
32935
|
-
if (!this.enabled)
|
|
33597
|
+
afterStep(step, mode = "apply") {
|
|
33598
|
+
if (!this.enabled) {
|
|
33599
|
+
this.calc.discardPreparation();
|
|
33600
|
+
return;
|
|
33601
|
+
}
|
|
33602
|
+
const structural = isStructural(step);
|
|
33603
|
+
const hint = structural ? hintFor(step, mode) : void 0;
|
|
32936
33604
|
if (calcModeOf(this.workbook) === "manual") {
|
|
32937
|
-
if (
|
|
33605
|
+
if (hint && !this.staleGraph && !this.dirty.length) {
|
|
33606
|
+
this.guard(() => this.follow(hint));
|
|
33607
|
+
return;
|
|
33608
|
+
}
|
|
33609
|
+
this.calc.discardPreparation();
|
|
33610
|
+
if (structural) this.staleGraph = true;
|
|
33611
|
+
else this.dirty.push(...touchedCells(step));
|
|
32938
33612
|
return;
|
|
32939
33613
|
}
|
|
32940
|
-
|
|
33614
|
+
if (hint && !this.staleGraph) {
|
|
33615
|
+
this.guard(() => {
|
|
33616
|
+
this.follow(hint);
|
|
33617
|
+
this.calc.recalculateFrom(touchedCells(step));
|
|
33618
|
+
this.calculated = settingsOf(this.workbook);
|
|
33619
|
+
});
|
|
33620
|
+
return;
|
|
33621
|
+
}
|
|
33622
|
+
this.recalc(structural, () => touchedCells(step));
|
|
32941
33623
|
}
|
|
32942
33624
|
/** Recalculates after a change applied outside the history (a collaborator's edit). */
|
|
32943
33625
|
afterExternal(structural, cells3) {
|
|
32944
|
-
if (!this.enabled)
|
|
32945
|
-
|
|
33626
|
+
if (!this.enabled || calcModeOf(this.workbook) === "manual") {
|
|
33627
|
+
this.calc.discardPreparation();
|
|
33628
|
+
if (!this.enabled) return;
|
|
32946
33629
|
if (structural) this.staleGraph = true;
|
|
33630
|
+
else this.dirty.push(...cells3);
|
|
32947
33631
|
return;
|
|
32948
33632
|
}
|
|
32949
33633
|
this.recalc(structural, () => cells3);
|
|
32950
33634
|
}
|
|
32951
|
-
|
|
33635
|
+
follow(hint) {
|
|
33636
|
+
if (hint.kind === "shift") this.calc.shiftCells(hint.sheet, hint.shift);
|
|
33637
|
+
else this.calc.renameSheet(hint.from, hint.to);
|
|
33638
|
+
}
|
|
33639
|
+
guard(run2) {
|
|
32952
33640
|
try {
|
|
33641
|
+
run2();
|
|
33642
|
+
} catch (error) {
|
|
33643
|
+
const message = `Recalculation failed: ${error instanceof Error ? error.message : String(error)}`;
|
|
33644
|
+
if (!this.workbook.warnings.includes(message)) this.workbook.warnings.push(message);
|
|
33645
|
+
}
|
|
33646
|
+
}
|
|
33647
|
+
/** Builds the dependency graph ahead of the first edit (see `EditSession.prepareCalculation`). */
|
|
33648
|
+
prepare(timeRemaining) {
|
|
33649
|
+
if (!this.enabled || calcModeOf(this.workbook) === "manual" || this.staleGraph) return true;
|
|
33650
|
+
try {
|
|
33651
|
+
return this.calc.prepare(timeRemaining);
|
|
33652
|
+
} catch {
|
|
33653
|
+
this.calc.discardPreparation();
|
|
33654
|
+
return true;
|
|
33655
|
+
}
|
|
33656
|
+
}
|
|
33657
|
+
/**
|
|
33658
|
+
* Before a structural edit the graph can follow in place: finishes a graph being prepared (or
|
|
33659
|
+
* builds it) while it still matches the workbook, so the edit moves it instead of rebuilding.
|
|
33660
|
+
*/
|
|
33661
|
+
beforeStructural() {
|
|
33662
|
+
if (!this.enabled || calcModeOf(this.workbook) === "manual" || this.staleGraph) return;
|
|
33663
|
+
this.prepare();
|
|
33664
|
+
}
|
|
33665
|
+
recalc(structural, cells3) {
|
|
33666
|
+
this.guard(() => {
|
|
32953
33667
|
if (this.staleGraph || structural) this.full();
|
|
32954
33668
|
else {
|
|
32955
33669
|
const changed = cells3();
|
|
32956
33670
|
if (changed.length) this.calc.recalculateFrom(changed);
|
|
33671
|
+
this.calculated = settingsOf(this.workbook);
|
|
32957
33672
|
}
|
|
32958
|
-
}
|
|
32959
|
-
const message = `Recalculation failed: ${error instanceof Error ? error.message : String(error)}`;
|
|
32960
|
-
if (!this.workbook.warnings.includes(message)) this.workbook.warnings.push(message);
|
|
32961
|
-
}
|
|
33673
|
+
});
|
|
32962
33674
|
}
|
|
32963
|
-
/** Rebuilds the dependency graph and recalculates every formula (F9). */
|
|
33675
|
+
/** Rebuilds the dependency graph and recalculates every formula (Ctrl+Alt+F9). */
|
|
32964
33676
|
full() {
|
|
32965
33677
|
this.staleGraph = false;
|
|
33678
|
+
this.dirty = [];
|
|
32966
33679
|
this.calc.invalidate();
|
|
32967
33680
|
this.calc.recalculateAll();
|
|
33681
|
+
this.calculated = settingsOf(this.workbook);
|
|
33682
|
+
}
|
|
33683
|
+
/**
|
|
33684
|
+
* Calculate Now (F9): the cells changed since the last calculation, the formulas structural
|
|
33685
|
+
* edits queued, their dependents and the volatile functions. Everything when `full`, before
|
|
33686
|
+
* the session's first calculation, after the iteration settings changed or while the graph
|
|
33687
|
+
* is stale.
|
|
33688
|
+
*/
|
|
33689
|
+
now(full) {
|
|
33690
|
+
if (full || this.staleGraph || this.calculated !== settingsOf(this.workbook)) {
|
|
33691
|
+
this.full();
|
|
33692
|
+
return;
|
|
33693
|
+
}
|
|
33694
|
+
const changed = this.dirty;
|
|
33695
|
+
this.dirty = [];
|
|
33696
|
+
this.calc.recalculateFrom(changed);
|
|
32968
33697
|
}
|
|
32969
33698
|
/**
|
|
32970
33699
|
* Recalculates one sheet's formulas and their dependents (Shift+F9); after structural edits
|
|
@@ -36768,12 +37497,12 @@ function renameSheet(ctx, index2, name) {
|
|
|
36768
37497
|
ctx.run(
|
|
36769
37498
|
"Rename sheet",
|
|
36770
37499
|
"sheets",
|
|
36771
|
-
[{ kind: "
|
|
37500
|
+
[{ kind: "refs" }],
|
|
36772
37501
|
() => {
|
|
36773
37502
|
rewriteFormulas(workbook, (formula) => renameSheetInFormula(formula, old, name));
|
|
36774
37503
|
sheet.name = name;
|
|
36775
37504
|
},
|
|
36776
|
-
{ sheet: index2, structural: true }
|
|
37505
|
+
{ sheet: index2, structural: true, calc: { kind: "rename", from: old, to: name } }
|
|
36777
37506
|
);
|
|
36778
37507
|
}
|
|
36779
37508
|
function moveSheet(ctx, from, to) {
|
|
@@ -37149,13 +37878,12 @@ function createEditSession(workbook, options = {}) {
|
|
|
37149
37878
|
for (const listener of [...listeners]) listener(change);
|
|
37150
37879
|
};
|
|
37151
37880
|
const calculator = new SessionCalculator(workbook, calc, autoRecalc);
|
|
37152
|
-
const recalc = (step) => calculator.afterStep(step);
|
|
37153
|
-
const begin = (label2, kind, info) =>
|
|
37154
|
-
step
|
|
37155
|
-
|
|
37156
|
-
sheet: info.sheet,
|
|
37157
|
-
|
|
37158
|
-
});
|
|
37881
|
+
const recalc = (step, mode = "apply") => calculator.afterStep(step, mode);
|
|
37882
|
+
const begin = (label2, kind, info) => {
|
|
37883
|
+
const step = { label: label2, entries: [], structural: info.structural ?? false };
|
|
37884
|
+
if (info.calc) step.calc = info.calc;
|
|
37885
|
+
return { step, kind, sheet: info.sheet, ranges: [...info.ranges ?? []] };
|
|
37886
|
+
};
|
|
37159
37887
|
const finish = (current) => {
|
|
37160
37888
|
if (!current.step.entries.length) return;
|
|
37161
37889
|
history.push(current.step);
|
|
@@ -37180,10 +37908,12 @@ function createEditSession(workbook, options = {}) {
|
|
|
37180
37908
|
const outer = !open;
|
|
37181
37909
|
const current = open ?? begin(label2, kind, info);
|
|
37182
37910
|
if (!outer) {
|
|
37911
|
+
delete current.step.calc;
|
|
37183
37912
|
if (info.structural) current.step.structural = true;
|
|
37184
37913
|
if (current.sheet === void 0 && info.sheet !== void 0) current.sheet = info.sheet;
|
|
37185
37914
|
current.ranges.push(...info.ranges ?? []);
|
|
37186
37915
|
}
|
|
37916
|
+
if (outer && info.calc) calculator.beforeStructural();
|
|
37187
37917
|
open = current;
|
|
37188
37918
|
const mark = current.step.entries.length;
|
|
37189
37919
|
const befores = scopes.map((scope) => captureScope(workbook, scope));
|
|
@@ -37231,7 +37961,7 @@ function createEditSession(workbook, options = {}) {
|
|
|
37231
37961
|
if (open) throw new Error(`Cannot ${kind} inside a batch`);
|
|
37232
37962
|
const step = kind === "undo" ? history.undo(workbook) : history.redo(workbook);
|
|
37233
37963
|
if (!step) return false;
|
|
37234
|
-
recalc(step);
|
|
37964
|
+
recalc(step, kind);
|
|
37235
37965
|
emit({ kind, label: step.label, structural: step.structural });
|
|
37236
37966
|
return true;
|
|
37237
37967
|
};
|
|
@@ -37310,10 +38040,11 @@ function createEditSession(workbook, options = {}) {
|
|
|
37310
38040
|
setDocumentProperties: (patch) => setDocumentProperties(ctx, patch),
|
|
37311
38041
|
setAutoRecalc: (enabled2) => setCalcMode(ctx, enabled2 ? "auto" : "manual"),
|
|
37312
38042
|
autoRecalc: () => autoRecalc && calcModeOf(workbook) === "auto",
|
|
37313
|
-
calculateNow() {
|
|
37314
|
-
calculator.full
|
|
38043
|
+
calculateNow(options2) {
|
|
38044
|
+
calculator.now(options2?.full ?? false);
|
|
37315
38045
|
emit({ kind: "cells", label: "Calculate now", structural: false });
|
|
37316
38046
|
},
|
|
38047
|
+
prepareCalculation: (opts) => calculator.prepare(opts?.timeRemaining),
|
|
37317
38048
|
calculateSheet(s) {
|
|
37318
38049
|
calculator.sheet(s);
|
|
37319
38050
|
emit({ kind: "cells", label: "Calculate sheet", sheet: s, structural: false });
|
|
@@ -45901,11 +46632,11 @@ async function assertVisioMasterIndependence(pkg, roots, commands, check3) {
|
|
|
45901
46632
|
}
|
|
45902
46633
|
const tops = children3(children3(root, "Shapes")[0], "Shape");
|
|
45903
46634
|
if (tops.length !== 1) problem("Only a uniquely rooted master can prove independence.");
|
|
45904
|
-
const
|
|
46635
|
+
const templates2 = masterShapes(root), context = /* @__PURE__ */ new Map();
|
|
45905
46636
|
assertMasterMarkup(
|
|
45906
46637
|
root,
|
|
45907
46638
|
new Set(
|
|
45908
|
-
|
|
46639
|
+
templates2.flatMap((shape2) => {
|
|
45909
46640
|
charge();
|
|
45910
46641
|
return [...masterCells(shape2, charge).values()];
|
|
45911
46642
|
})
|
|
@@ -45927,7 +46658,7 @@ async function assertVisioMasterIndependence(pkg, roots, commands, check3) {
|
|
|
45927
46658
|
if (byTemplate.has(id)) problem("MasterShape mappings are ambiguous.");
|
|
45928
46659
|
byTemplate.set(id, local);
|
|
45929
46660
|
}
|
|
45930
|
-
for (const template of
|
|
46661
|
+
for (const template of templates2) {
|
|
45931
46662
|
charge();
|
|
45932
46663
|
if (bindings.length >= 1e4) problem("Master effective binding limit exceeded.");
|
|
45933
46664
|
check3();
|