@univerjs/engine-formula 1.0.0-beta.0 → 1.0.0-beta.2

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.
Files changed (37) hide show
  1. package/lib/cjs/index.js +267 -151
  2. package/lib/cjs/locale/ca-ES.js +35 -35
  3. package/lib/cjs/locale/fr-FR.js +14 -14
  4. package/lib/cjs/locale/ko-KR.js +17 -17
  5. package/lib/cjs/locale/sk-SK.js +8 -8
  6. package/lib/cjs/locale/vi-VN.js +2 -2
  7. package/lib/es/index.js +270 -153
  8. package/lib/es/locale/ca-ES.js +35 -35
  9. package/lib/es/locale/fr-FR.js +14 -14
  10. package/lib/es/locale/ko-KR.js +17 -17
  11. package/lib/es/locale/sk-SK.js +8 -8
  12. package/lib/es/locale/vi-VN.js +2 -2
  13. package/lib/index.js +270 -153
  14. package/lib/locale/ca-ES.js +35 -35
  15. package/lib/locale/fr-FR.js +14 -14
  16. package/lib/locale/ko-KR.js +17 -17
  17. package/lib/locale/sk-SK.js +8 -8
  18. package/lib/locale/vi-VN.js +2 -2
  19. package/lib/types/basics/common.d.ts +2 -0
  20. package/lib/types/basics/regex.d.ts +4 -4
  21. package/lib/types/controllers/formula-calculation-trigger.controller.d.ts +1 -2
  22. package/lib/types/controllers/formula.controller.d.ts +1 -1
  23. package/lib/types/engine/value-object/array-value-object.d.ts +1 -1
  24. package/lib/types/functions/base-function.d.ts +2 -2
  25. package/lib/types/functions/logical/percentof/index.d.ts +5 -6
  26. package/lib/types/functions/lookup/xlookup/index.d.ts +4 -0
  27. package/lib/types/index.d.ts +0 -1
  28. package/lib/types/models/formula-data.model.d.ts +3 -1
  29. package/lib/types/services/register-other-formula.service.d.ts +3 -3
  30. package/lib/types/services/runtime.service.d.ts +2 -0
  31. package/lib/umd/index.js +4 -4
  32. package/lib/umd/locale/ca-ES.js +1 -1
  33. package/lib/umd/locale/fr-FR.js +2 -2
  34. package/lib/umd/locale/ko-KR.js +3 -3
  35. package/lib/umd/locale/sk-SK.js +1 -1
  36. package/lib/umd/locale/vi-VN.js +1 -1
  37. package/package.json +4 -4
package/lib/cjs/index.js CHANGED
@@ -1477,7 +1477,8 @@ const TABLE_NAME_REGEX = "((?![~!@#$%^&*()+<>?:,./;’,。、‘:“《》
1477
1477
  const TABLE_TITLE_REGEX = "\\[#.+\\]\\s*?,\\s*?";
1478
1478
  const TABLE_CONTENT_REGEX = "\\[[^#]*#?\\]";
1479
1479
  const TABLE_MULTIPLE_COLUMN_REGEX = `${TABLE_CONTENT_REGEX}${RANGE_SYMBOL}${TABLE_CONTENT_REGEX}`;
1480
- const TABLE_UNIT_QUALIFIER_REGEX = `(?:(?:${UNIT_NAME_REGEX}|'(?:[^']|'')+'|[^\\s!\\[\\]]+)!)?(?:${UNIT_NAME_REGEX})?`;
1480
+ const TABLE_BRACKETED_UNIT_QUALIFIER_REGEX = "\\[(?:[^\\]]|\\]\\])+\\]";
1481
+ const TABLE_UNIT_QUALIFIER_REGEX = `(?:(?:${TABLE_BRACKETED_UNIT_QUALIFIER_REGEX}|'(?:[^']|'')+'|[^\\s!\\[\\]]+)!)?(?:${TABLE_BRACKETED_UNIT_QUALIFIER_REGEX})?`;
1481
1482
  const REFERENCE_TABLE_ALL_COLUMN_REGEX = `^${TABLE_UNIT_QUALIFIER_REGEX}${TABLE_NAME_REGEX}$`;
1482
1483
  const REFERENCE_TABLE_SINGLE_COLUMN_REGEX = `^${TABLE_UNIT_QUALIFIER_REGEX}${TABLE_NAME_REGEX}(${TABLE_CONTENT_REGEX}|\\[${TABLE_TITLE_REGEX}${TABLE_CONTENT_REGEX}\\])+$`;
1483
1484
  const REFERENCE_TABLE_MULTIPLE_COLUMN_REGEX = `^${TABLE_UNIT_QUALIFIER_REGEX}${TABLE_NAME_REGEX}(\\[${TABLE_MULTIPLE_COLUMN_REGEX}\\])?$|^${TABLE_UNIT_QUALIFIER_REGEX}${TABLE_NAME_REGEX}(\\[${TABLE_TITLE_REGEX}${TABLE_MULTIPLE_COLUMN_REGEX}\\])?$`;
@@ -1934,8 +1935,13 @@ function splitTableStructuredRef(ref) {
1934
1935
  }
1935
1936
  quoteOpen = !quoteOpen;
1936
1937
  } else if (!quoteOpen && char === "[") bracketDepth++;
1937
- else if (!quoteOpen && char === "]") bracketDepth--;
1938
- else if (!quoteOpen && bracketDepth === 0 && char === "!") {
1938
+ else if (!quoteOpen && char === "]") {
1939
+ if (bracketDepth > 0 && tableRef[i + 1] === "]") {
1940
+ i++;
1941
+ continue;
1942
+ }
1943
+ bracketDepth--;
1944
+ } else if (!quoteOpen && bracketDepth === 0 && char === "!") {
1939
1945
  qualifierEnd = i;
1940
1946
  break;
1941
1947
  }
@@ -1943,8 +1949,10 @@ function splitTableStructuredRef(ref) {
1943
1949
  if (qualifierEnd >= 0) {
1944
1950
  unitQualifier = tableRef.slice(0, qualifierEnd).trim();
1945
1951
  tableRef = tableRef.slice(qualifierEnd + 1);
1946
- if (unitQualifier.startsWith("'") && unitQualifier.endsWith("'")) unitQualifier = unitQualifier.slice(1, -1);
1947
- if (unitQualifier.startsWith("[") && unitQualifier.endsWith("]")) unitQualifier = unitQualifier.slice(1, -1);
1952
+ const isQuotedQualifier = unitQualifier.startsWith("'") && unitQualifier.endsWith("'");
1953
+ const isBracketedQualifier = !isQuotedQualifier && unitQualifier.startsWith("[") && unitQualifier.endsWith("]");
1954
+ if (isQuotedQualifier) unitQualifier = unitQualifier.slice(1, -1);
1955
+ else if (isBracketedQualifier) unitQualifier = unitQualifier.slice(1, -1).replaceAll("]]", "]");
1948
1956
  unitQualifier = unquoteSheetName(unitQualifier);
1949
1957
  } else if (tableRef.startsWith("[")) {
1950
1958
  const legacyQualifierEnd = tableRef.indexOf("]");
@@ -5022,12 +5030,14 @@ let FormulaDataModel = class FormulaDataModel extends _univerjs_core.Disposable
5022
5030
  super();
5023
5031
  this._univerInstanceService = _univerInstanceService;
5024
5032
  this._lexerTreeBuilder = _lexerTreeBuilder;
5033
+ _defineProperty(this, "_formulaIdMapData", {});
5025
5034
  _defineProperty(this, "_arrayFormulaRange", {});
5026
5035
  _defineProperty(this, "_arrayFormulaCellData", {});
5027
5036
  _defineProperty(this, "_unitImageFormulaData", {});
5028
5037
  }
5029
5038
  dispose() {
5030
5039
  super.dispose();
5040
+ this._formulaIdMapData = {};
5031
5041
  this._arrayFormulaRange = {};
5032
5042
  this._arrayFormulaCellData = {};
5033
5043
  this._unitImageFormulaData = {};
@@ -5099,7 +5109,7 @@ let FormulaDataModel = class FormulaDataModel extends _univerjs_core.Disposable
5099
5109
  const cellMatrix = worksheet.getCellMatrix();
5100
5110
  const sheetId = worksheet.getSheetId();
5101
5111
  this._initSheetArrayFormulaData(unitId, sheetId, cellMatrix);
5102
- initSheetFormulaData(formulaData, unitId, sheetId, cellMatrix);
5112
+ this.initSheetFormulaData(formulaData, unitId, sheetId, cellMatrix);
5103
5113
  }
5104
5114
  }
5105
5115
  const allBases = this._univerInstanceService.getAllUnitsForType(_univerjs_core.UniverInstanceType.UNIVER_BASE);
@@ -5109,9 +5119,11 @@ let FormulaDataModel = class FormulaDataModel extends _univerjs_core.Disposable
5109
5119
  const unitId = base.getUnitId();
5110
5120
  formulaData[unitId] = {};
5111
5121
  const tables = Object.values(snapshot.tables);
5122
+ const formulaTableNames = (0, _univerjs_core.createBaseFormulaTableNameMap)(snapshot);
5112
5123
  for (let j = 0; j < tables.length; j++) {
5113
5124
  const table = tables[j];
5114
5125
  const tableFormulaData = {};
5126
+ const normalizedFormulaByFieldId = /* @__PURE__ */ new Map();
5115
5127
  const recordOrder = table.recordOrder;
5116
5128
  if (!recordOrder) {
5117
5129
  formulaData[unitId][table.id] = tableFormulaData;
@@ -5127,9 +5139,14 @@ let FormulaDataModel = class FormulaDataModel extends _univerjs_core.Disposable
5127
5139
  if (!field || field.type !== "formula") continue;
5128
5140
  const formula = String(((_field$config = field.config) === null || _field$config === void 0 ? void 0 : _field$config.formula) ?? "").trim();
5129
5141
  if (!formula) continue;
5142
+ let normalizedFormula = normalizedFormulaByFieldId.get(field.id);
5143
+ if (normalizedFormula == null) {
5144
+ normalizedFormula = normalizeBaseFormulaForEngine(formula, table, snapshot, formulaTableNames);
5145
+ normalizedFormulaByFieldId.set(field.id, normalizedFormula);
5146
+ }
5130
5147
  tableFormulaData[row] ??= {};
5131
5148
  tableFormulaData[row][col] = {
5132
- f: normalizeBaseFormulaForEngine(formula, table, snapshot),
5149
+ f: normalizedFormula,
5133
5150
  si: field.id
5134
5151
  };
5135
5152
  }
@@ -5139,6 +5156,22 @@ let FormulaDataModel = class FormulaDataModel extends _univerjs_core.Disposable
5139
5156
  }
5140
5157
  return formulaData;
5141
5158
  }
5159
+ initSheetFormulaData(formulaData, unitId, sheetId, cellMatrix) {
5160
+ const result = buildSheetFormulaData(formulaData, unitId, sheetId, cellMatrix);
5161
+ if (!this._formulaIdMapData[unitId]) this._formulaIdMapData[unitId] = {};
5162
+ this._formulaIdMapData[unitId][sheetId] = result.formulaIdMap;
5163
+ return result.formulaData;
5164
+ }
5165
+ clearFormulaIdMap(unitId, sheetId) {
5166
+ if (sheetId == null) {
5167
+ delete this._formulaIdMapData[unitId];
5168
+ return;
5169
+ }
5170
+ const unitFormulaIdMap = this._formulaIdMapData[unitId];
5171
+ if (!unitFormulaIdMap) return;
5172
+ delete unitFormulaIdMap[sheetId];
5173
+ if (Object.keys(unitFormulaIdMap).length === 0) delete this._formulaIdMapData[unitId];
5174
+ }
5142
5175
  getSheetFormulaData(unitId, sheetId) {
5143
5176
  const formulaData = {};
5144
5177
  const workbook = this._univerInstanceService.getUnit(unitId);
@@ -5148,7 +5181,7 @@ let FormulaDataModel = class FormulaDataModel extends _univerjs_core.Disposable
5148
5181
  if (worksheet == null) return {};
5149
5182
  const cellMatrix = worksheet.getCellMatrix();
5150
5183
  this._initSheetArrayFormulaData(unitId, sheetId, cellMatrix);
5151
- initSheetFormulaData(formulaData, unitId, sheetId, cellMatrix);
5184
+ this.initSheetFormulaData(formulaData, unitId, sheetId, cellMatrix);
5152
5185
  return formulaData[unitId][sheetId];
5153
5186
  }
5154
5187
  getArrayFormulaRange() {
@@ -5257,6 +5290,7 @@ let FormulaDataModel = class FormulaDataModel extends _univerjs_core.Disposable
5257
5290
  };
5258
5291
  const baseData = {};
5259
5292
  const tableNameMap = {};
5293
+ const formulaTableNames = (0, _univerjs_core.createBaseFormulaTableNameMap)(snapshot);
5260
5294
  for (const table of Object.values(snapshot.tables)) {
5261
5295
  var _table$recordOrder;
5262
5296
  baseData[table.id] = {
@@ -5266,7 +5300,7 @@ let FormulaDataModel = class FormulaDataModel extends _univerjs_core.Disposable
5266
5300
  rowData: {},
5267
5301
  columnData: {}
5268
5302
  };
5269
- tableNameMap[table.name] = table.id;
5303
+ addEngineBaseTableNameMappings(tableNameMap, table, formulaTableNames);
5270
5304
  }
5271
5305
  allUnitData[unitId] = baseData;
5272
5306
  unitStylesData[unitId] = new _univerjs_core.Styles();
@@ -5336,8 +5370,7 @@ let FormulaDataModel = class FormulaDataModel extends _univerjs_core.Disposable
5336
5370
  c
5337
5371
  };
5338
5372
  });
5339
- const formulaData = {};
5340
- initSheetFormulaData(formulaData, unitId, sheetId, sharedFormulaCellMatrix);
5373
+ const formulaData = buildSheetFormulaData({}, unitId, sheetId, sharedFormulaCellMatrix).formulaData;
5341
5374
  const deleteFormulaIdMap = /* @__PURE__ */ new Map();
5342
5375
  const sheetFormulaDataMatrix = new _univerjs_core.ObjectMatrix(((_formulaData$unitId = formulaData[unitId]) === null || _formulaData$unitId === void 0 ? void 0 : _formulaData$unitId[sheetId]) ?? {});
5343
5376
  cellMatrix.forValue((r, c, cell) => {
@@ -5458,16 +5491,18 @@ let FormulaDataModel = class FormulaDataModel extends _univerjs_core.Disposable
5458
5491
  const { f, si } = cell;
5459
5492
  if ((0, _univerjs_core.isFormulaString)(f)) return f;
5460
5493
  if ((0, _univerjs_core.isFormulaId)(si)) {
5461
- let formulaString = null;
5462
- cellMatrix.forValue((r, c, cell) => {
5463
- if (cell == null) return true;
5464
- const { f, si: currentId } = cell;
5465
- if ((0, _univerjs_core.isFormulaString)(f) && si === currentId) {
5466
- formulaString = this._lexerTreeBuilder.moveFormulaRefOffset(f, column - c, row - r);
5467
- return false;
5468
- }
5469
- });
5470
- return formulaString;
5494
+ var _this$_formulaIdMapDa;
5495
+ let formulaIdMap = (_this$_formulaIdMapDa = this._formulaIdMapData[unitId]) === null || _this$_formulaIdMapDa === void 0 ? void 0 : _this$_formulaIdMapDa[sheetId];
5496
+ let formulaInfo = formulaIdMap === null || formulaIdMap === void 0 ? void 0 : formulaIdMap[String(si)];
5497
+ const masterCell = formulaInfo == null ? null : cellMatrix.getValue(formulaInfo.r, formulaInfo.c);
5498
+ if (formulaInfo == null || (masterCell === null || masterCell === void 0 ? void 0 : masterCell.si) !== si || (masterCell === null || masterCell === void 0 ? void 0 : masterCell.f) !== formulaInfo.f) {
5499
+ var _this$_formulaIdMapDa2;
5500
+ this.initSheetFormulaData({}, unitId, sheetId, cellMatrix);
5501
+ formulaIdMap = (_this$_formulaIdMapDa2 = this._formulaIdMapData[unitId]) === null || _this$_formulaIdMapDa2 === void 0 ? void 0 : _this$_formulaIdMapDa2[sheetId];
5502
+ formulaInfo = formulaIdMap === null || formulaIdMap === void 0 ? void 0 : formulaIdMap[String(si)];
5503
+ }
5504
+ if (!formulaInfo) return null;
5505
+ return this._lexerTreeBuilder.moveFormulaRefOffset(formulaInfo.f, column - formulaInfo.c, row - formulaInfo.r);
5471
5506
  }
5472
5507
  return null;
5473
5508
  }
@@ -5562,10 +5597,10 @@ let FormulaDataModel = class FormulaDataModel extends _univerjs_core.Disposable
5562
5597
  }
5563
5598
  };
5564
5599
  FormulaDataModel = __decorate([__decorateParam(0, _univerjs_core.IUniverInstanceService), __decorateParam(1, (0, _univerjs_core.Inject)(LexerTreeBuilder))], FormulaDataModel);
5565
- function initSheetFormulaData(formulaData, unitId, sheetId, cellMatrix) {
5600
+ function buildSheetFormulaData(formulaData, unitId, sheetId, cellMatrix) {
5566
5601
  if (!formulaData[unitId]) formulaData[unitId] = {};
5567
5602
  if (!formulaData[unitId][sheetId]) formulaData[unitId][sheetId] = {};
5568
- const formulaIdMap = /* @__PURE__ */ new Map();
5603
+ const formulaIdMap = {};
5569
5604
  const sheetFormulaDataMatrix = new _univerjs_core.ObjectMatrix(formulaData[unitId][sheetId]);
5570
5605
  cellMatrix.forValue((r, c, cell) => {
5571
5606
  const formulaString = (cell === null || cell === void 0 ? void 0 : cell.f) || "";
@@ -5577,11 +5612,11 @@ function initSheetFormulaData(formulaData, unitId, sheetId, cellMatrix) {
5577
5612
  f: formulaString,
5578
5613
  si: formulaId
5579
5614
  });
5580
- formulaIdMap.set(formulaId, {
5615
+ formulaIdMap[formulaId] = {
5581
5616
  f: formulaString,
5582
5617
  r,
5583
5618
  c
5584
- });
5619
+ };
5585
5620
  } else if (checkFormulaString && !checkFormulaId) sheetFormulaDataMatrix.setValue(r, c, { f: formulaString });
5586
5621
  else if (!checkFormulaString && checkFormulaId) sheetFormulaDataMatrix.setValue(r, c, {
5587
5622
  f: "",
@@ -5592,7 +5627,7 @@ function initSheetFormulaData(formulaData, unitId, sheetId, cellMatrix) {
5592
5627
  const formulaString = (cell === null || cell === void 0 ? void 0 : cell.f) || "";
5593
5628
  const formulaId = (cell === null || cell === void 0 ? void 0 : cell.si) || "";
5594
5629
  if ((0, _univerjs_core.isFormulaId)(formulaId) && !(0, _univerjs_core.isFormulaString)(formulaString)) {
5595
- const formulaInfo = formulaIdMap.get(formulaId);
5630
+ const formulaInfo = formulaIdMap[formulaId];
5596
5631
  if (formulaInfo) {
5597
5632
  const x = c - formulaInfo.c;
5598
5633
  const y = r - formulaInfo.r;
@@ -5607,31 +5642,53 @@ function initSheetFormulaData(formulaData, unitId, sheetId, cellMatrix) {
5607
5642
  }
5608
5643
  });
5609
5644
  const newSheetFormulaData = sheetFormulaDataMatrix.getMatrix();
5610
- return { [unitId]: { [sheetId]: newSheetFormulaData } };
5645
+ return {
5646
+ formulaData: { [unitId]: { [sheetId]: newSheetFormulaData } },
5647
+ formulaIdMap
5648
+ };
5611
5649
  }
5612
5650
  const BASE_LEGACY_FIELD_REF_PATTERN = /\{([^}]+)\}/g;
5613
- const BASE_TABLE_FIELD_REF_PATTERN = /\b([A-Z_]\w*)\[([^\]]+)\]/gi;
5614
- const BASE_BRACKET_FIELD_REF_PATTERN = /(^|[^A-Za-z0-9_\]\[])\[([^\]]+)\]/g;
5651
+ const BASE_TABLE_SCOPED_FIELD_REF_PATTERN = /\b([A-Z_][\w.]*)\[\[\s*#(This Row|Data)\s*\],\s*\[([^\]]+)\]\]/gi;
5652
+ const BASE_TABLE_CURRENT_ROW_FIELD_REF_PATTERN = /\b([A-Z_][\w.]*)\[@\[([^\]]+)\]\]/gi;
5653
+ const BASE_TABLE_FIELD_REF_PATTERN = /\b([A-Z_][\w.]*)\[([^\[\]#]+)\]/gi;
5654
+ const BASE_SCOPED_FIELD_REF_PATTERN = /(^|[^\w\[])\[\[\s*#(This Row|Data)\s*\],\s*\[([^\]]+)\]\]/gi;
5655
+ const BASE_CURRENT_ROW_FIELD_REF_PATTERN = /(^|[^\w\[])\[@\[([^\]]+)\]\](?!\])/g;
5656
+ const BASE_BRACKET_FIELD_REF_PATTERN = /(^|[^\w\[])\[@?([^\[\]#]+)\](?!\])/g;
5615
5657
  const BASE_EXTERNAL_A1_REF_PATTERN = /(?:'\[[^\]]+\](?:[^']|'')+'|\[[^\]]+\][^\s'!]+)!\$?[A-Z]{1,3}\$?\d+(?::\$?[A-Z]{1,3}\$?\d+)?/gi;
5616
5658
  const BASE_EXTERNAL_STRUCTURED_REFERENCE_PREFIX = /(?:'((?:[^']|'')+)'|\[[^\]]+\]|[A-Za-z0-9_.-]+)![^\s!\[\]]+\[/g;
5617
- function normalizeBaseFormulaForEngine(formula, currentTable, snapshot) {
5659
+ function normalizeBaseFormulaForEngine(formula, currentTable, snapshot, formulaTableNames) {
5618
5660
  const refs = [];
5619
5661
  const hold = (ref) => {
5620
5662
  return `__BASE_FORMULA_REF_${refs.push(ref) - 1}__`;
5621
5663
  };
5622
- return protectBaseExternalReferences(formula, hold).replace(BASE_LEGACY_FIELD_REF_PATTERN, (_match, fieldName) => hold(createEngineThisRowRef(currentTable, fieldName, snapshot))).replace(BASE_TABLE_FIELD_REF_PATTERN, (_match, sourceTableName, fieldName) => {
5623
- const targetTable = resolveBaseFormulaTable(sourceTableName, currentTable, snapshot);
5624
- return targetTable ? hold(createEngineColumnRef(targetTable, fieldName, snapshot)) : `${sourceTableName}[${fieldName}]`;
5625
- }).replace(BASE_BRACKET_FIELD_REF_PATTERN, (_match, prefix, fieldName) => `${prefix}${hold(createEngineThisRowRef(currentTable, fieldName, snapshot))}`).replace(/__BASE_FORMULA_REF_(\d+)__/g, (_match, index) => refs[Number(index)] ?? "");
5664
+ return protectBaseFormulaParts(formula, hold).replace(BASE_LEGACY_FIELD_REF_PATTERN, (_match, fieldName) => hold(createEngineThisRowRef(currentTable, fieldName, formulaTableNames))).replace(BASE_TABLE_SCOPED_FIELD_REF_PATTERN, (_match, sourceTableName, scope, fieldName) => {
5665
+ const targetTable = resolveBaseFormulaTable(sourceTableName, currentTable, snapshot, formulaTableNames);
5666
+ if (!targetTable) return `${sourceTableName}[[#${scope}],[${fieldName}]]`;
5667
+ return hold(scope.toLowerCase() === "data" ? createEngineColumnRef(targetTable, fieldName, formulaTableNames) : createEngineThisRowRef(targetTable, fieldName, formulaTableNames));
5668
+ }).replace(BASE_TABLE_CURRENT_ROW_FIELD_REF_PATTERN, (_match, sourceTableName, fieldName) => {
5669
+ const targetTable = resolveBaseFormulaTable(sourceTableName, currentTable, snapshot, formulaTableNames);
5670
+ return targetTable ? hold(createEngineThisRowRef(targetTable, fieldName, formulaTableNames)) : `${sourceTableName}[@[${fieldName}]]`;
5671
+ }).replace(BASE_SCOPED_FIELD_REF_PATTERN, (_match, prefix, scope, fieldName) => `${prefix}${hold(scope.toLowerCase() === "data" ? createEngineColumnRef(currentTable, fieldName, formulaTableNames) : createEngineThisRowRef(currentTable, fieldName, formulaTableNames))}`).replace(BASE_CURRENT_ROW_FIELD_REF_PATTERN, (_match, prefix, fieldName) => `${prefix}${hold(createEngineThisRowRef(currentTable, fieldName, formulaTableNames))}`).replace(BASE_TABLE_FIELD_REF_PATTERN, (_match, sourceTableName, fieldName) => {
5672
+ const targetTable = resolveBaseFormulaTable(sourceTableName, currentTable, snapshot, formulaTableNames);
5673
+ if (targetTable) return hold(createEngineColumnRef(targetTable, fieldName, formulaTableNames));
5674
+ return `${sourceTableName}[${fieldName}]`;
5675
+ }).replace(BASE_BRACKET_FIELD_REF_PATTERN, (_match, prefix, fieldName) => `${prefix}${hold(createEngineThisRowRef(currentTable, fieldName, formulaTableNames))}`).replace(/__BASE_FORMULA_REF_(\d+)__/g, (_match, index) => refs[Number(index)] ?? "");
5626
5676
  }
5627
5677
  function protectBaseExternalReferences(formula, replace) {
5628
5678
  return protectBaseExternalStructuredReferences(formula.replace(BASE_EXTERNAL_A1_REF_PATTERN, (reference, offset) => isInsideBaseFormulaString(formula, offset) ? reference : replace(reference)), replace);
5629
5679
  }
5680
+ function protectBaseFormulaParts(formula, replace) {
5681
+ return protectBaseFormulaStrings(protectBaseExternalReferences(formula, replace), replace);
5682
+ }
5683
+ function protectBaseFormulaStrings(formula, replace) {
5684
+ return formula.replace(/"(?:""|[^"])*"/g, replace);
5685
+ }
5630
5686
  function protectBaseExternalStructuredReferences(formula, replace) {
5631
5687
  const spans = [];
5632
5688
  BASE_EXTERNAL_STRUCTURED_REFERENCE_PREFIX.lastIndex = 0;
5633
- let match;
5634
- while ((match = BASE_EXTERNAL_STRUCTURED_REFERENCE_PREFIX.exec(formula)) != null) {
5689
+ while (true) {
5690
+ const match = BASE_EXTERNAL_STRUCTURED_REFERENCE_PREFIX.exec(formula);
5691
+ if (match == null) break;
5635
5692
  if (isInsideBaseFormulaString(formula, match.index)) continue;
5636
5693
  const openBracket = BASE_EXTERNAL_STRUCTURED_REFERENCE_PREFIX.lastIndex - 1;
5637
5694
  let depth = 0;
@@ -5671,20 +5728,20 @@ function isInsideBaseFormulaString(formula, position) {
5671
5728
  }
5672
5729
  return inString;
5673
5730
  }
5674
- function createEngineThisRowRef(table, fieldName, snapshot) {
5675
- return `${getEngineBaseTableName(table, snapshot)}[[#This Row],[${fieldName}]]`;
5731
+ function createEngineThisRowRef(table, fieldName, formulaTableNames) {
5732
+ return `${formulaTableNames.get(table.id) ?? (0, _univerjs_core.getBaseFormulaTableName)(table, { tables: { [table.id]: table } })}[[#This Row],[${fieldName}]]`;
5676
5733
  }
5677
- function createEngineColumnRef(table, fieldName, snapshot) {
5678
- return `${getEngineBaseTableName(table, snapshot)}[[#Data],[${fieldName}]]`;
5734
+ function createEngineColumnRef(table, fieldName, formulaTableNames) {
5735
+ return `${formulaTableNames.get(table.id) ?? (0, _univerjs_core.getBaseFormulaTableName)(table, { tables: { [table.id]: table } })}[[#Data],[${fieldName}]]`;
5679
5736
  }
5680
- function getEngineBaseTableName(table, snapshot) {
5681
- const tables = Object.values(snapshot.tables);
5682
- let sameNameCount = 0;
5683
- for (let i = 0; i < tables.length; i++) if (tables[i].name === table.name) {
5684
- sameNameCount++;
5685
- if (sameNameCount > 1) break;
5686
- }
5687
- return sameNameCount === 1 ? table.name : table.id;
5737
+ function addEngineBaseTableNameMappings(tableNameMap, table, formulaTableNames) {
5738
+ tableNameMap[formulaTableNames.get(table.id) ?? table.name] = table.id;
5739
+ }
5740
+ function createStableExcelTableName(tableId) {
5741
+ return `_T_${Array.from(tableId, (character) => {
5742
+ var _character$codePointA;
5743
+ return /[A-Za-z0-9]/.test(character) ? character : `_x${((_character$codePointA = character.codePointAt(0)) === null || _character$codePointA === void 0 ? void 0 : _character$codePointA.toString(16)) ?? "0"}_`;
5744
+ }).join("")}`;
5688
5745
  }
5689
5746
  function buildBaseRuntimeCellData(table) {
5690
5747
  const cellData = { ...table.cellData };
@@ -5772,11 +5829,13 @@ function isArrayConstantFormula(formula) {
5772
5829
  function isBaseCellData(value) {
5773
5830
  return !!value && typeof value === "object" && (Object.prototype.hasOwnProperty.call(value, "v") || Object.prototype.hasOwnProperty.call(value, "t") || Object.prototype.hasOwnProperty.call(value, "p") || Object.prototype.hasOwnProperty.call(value, "f") || Object.prototype.hasOwnProperty.call(value, "si"));
5774
5831
  }
5775
- function resolveBaseFormulaTable(tableName, currentTable, snapshot) {
5776
- if (!tableName || tableName === "table" || tableName === currentTable.id || tableName === currentTable.name) return currentTable;
5777
- const byId = snapshot.tables[tableName];
5778
- if (byId) return byId;
5779
- const matches = Object.values(snapshot.tables).filter((table) => table.name === tableName);
5832
+ function resolveBaseFormulaTable(tableName, currentTable, snapshot, formulaTableNames) {
5833
+ if (!tableName) return currentTable;
5834
+ const normalizedName = tableName.toLowerCase();
5835
+ const matches = Object.values(snapshot.tables).filter((table) => {
5836
+ var _formulaTableNames$ge;
5837
+ return table.id.toLowerCase() === normalizedName || table.name.toLowerCase() === normalizedName || ((_formulaTableNames$ge = formulaTableNames.get(table.id)) === null || _formulaTableNames$ge === void 0 ? void 0 : _formulaTableNames$ge.toLowerCase()) === normalizedName || createStableExcelTableName(table.id).toLowerCase() === normalizedName;
5838
+ });
5780
5839
  return matches.length === 1 ? matches[0] : void 0;
5781
5840
  }
5782
5841
 
@@ -8160,11 +8219,16 @@ var ArrayValueObject = class ArrayValueObject extends BaseValueObject {
8160
8219
  * the sequential matching approach is only used for special matches in XLOOKUP and XMATCH.
8161
8220
  * For example, when match_mode is set to 1 and -1 for an exact match. If not found, it returns the next smaller item.
8162
8221
  */
8163
- orderSearch(valueObject, searchType = 1, isDesc = false, isFuzzyMatching = false) {
8222
+ orderSearch(valueObject, searchType = 1, isDesc = false, isFuzzyMatching = false, keepFirstNearest = false) {
8164
8223
  let result;
8165
8224
  let maxOrMin;
8166
8225
  let resultPosition;
8167
8226
  let maxOrMinPosition;
8227
+ const _isNearer = (itemValue, currentValue) => {
8228
+ const distance = itemValue.minus(valueObject).abs();
8229
+ const currentDistance = currentValue.minus(valueObject).abs();
8230
+ return keepFirstNearest ? distance.isLessThan(currentDistance).getValue() === true : distance.isLessThanOrEqual(currentDistance).getValue() === true;
8231
+ };
8168
8232
  const _handleMatch = (itemValue, row, column) => {
8169
8233
  if (itemValue == null || itemValue.isNull()) return true;
8170
8234
  let matchObject;
@@ -8181,7 +8245,7 @@ var ArrayValueObject = class ArrayValueObject extends BaseValueObject {
8181
8245
  }
8182
8246
  if (searchType === 2) {
8183
8247
  if (itemValue.isGreaterThan(valueObject).getValue() === true) {
8184
- if (maxOrMin == null || itemValue.minus(valueObject).abs().isLessThanOrEqual(maxOrMin.minus(valueObject).abs()).getValue() === true) {
8248
+ if (maxOrMin == null || _isNearer(itemValue, maxOrMin)) {
8185
8249
  maxOrMin = itemValue;
8186
8250
  maxOrMinPosition = {
8187
8251
  row,
@@ -8191,7 +8255,7 @@ var ArrayValueObject = class ArrayValueObject extends BaseValueObject {
8191
8255
  }
8192
8256
  } else if (searchType === 1) {
8193
8257
  if (itemValue.isLessThan(valueObject).getValue() === true) {
8194
- if (maxOrMin == null || itemValue.minus(valueObject).abs().isLessThanOrEqual(maxOrMin.minus(valueObject).abs()).getValue() === true) {
8258
+ if (maxOrMin == null || _isNearer(itemValue, maxOrMin)) {
8195
8259
  maxOrMin = itemValue;
8196
8260
  maxOrMinPosition = {
8197
8261
  row,
@@ -8694,11 +8758,12 @@ var ArrayValueObject = class ArrayValueObject extends BaseValueObject {
8694
8758
  const sheetId = this.getSheetId();
8695
8759
  const startRow = this.getCurrentRow();
8696
8760
  const startColumn = this.getCurrentColumn();
8761
+ const isWildcardComparison = batchOperatorType === 5 && valueObject.isString() && isWildcard(String(valueObject.getValue()));
8697
8762
  /**
8698
8763
  * If comparison operations are conducted for a single numerical value,
8699
8764
  * then retrieve the judgment from the inverted index. This enhances performance.
8700
8765
  */
8701
- if (batchOperatorType === 5 && this._useInvertedIndexCache) {
8766
+ if (batchOperatorType === 5 && this._useInvertedIndexCache && !isWildcardComparison) {
8702
8767
  const { rowsInCache, rowsNotInCache } = CELL_INVERTED_INDEX_CACHE.canUseCache(unitId, sheetId, column + startColumn, startRow, startRow + rowCount - 1);
8703
8768
  if (rowsInCache.length > 0) {
8704
8769
  if (operator === "=" && !(valueObject.isString() && isWildcard(valueObject.getValue()))) {
@@ -9086,6 +9151,7 @@ var BaseReferenceObject = class extends ObjectClassType {
9086
9151
  }
9087
9152
  setForcedSheetId(sheetNameMap) {
9088
9153
  var _sheetNameMap$this$ge;
9154
+ if (!this._forcedSheetName) return;
9089
9155
  this._forcedSheetId = (_sheetNameMap$this$ge = sheetNameMap[this.getUnitId()]) === null || _sheetNameMap$this$ge === void 0 ? void 0 : _sheetNameMap$this$ge[this._forcedSheetName];
9090
9156
  }
9091
9157
  setForcedSheetIdDirect(sheetId) {
@@ -9486,7 +9552,7 @@ var CellReferenceObject = class extends BaseReferenceObject {
9486
9552
  unionBy(referenceObject) {
9487
9553
  if (!referenceObject.isCell()) return ErrorValueObject.create("#REF!");
9488
9554
  const cellReferenceObject = referenceObject;
9489
- const newRangeData = this.unionRange(this.getRangeData(), cellReferenceObject.getRangeData());
9555
+ const newRangeData = this.unionRange(this.getRangePosition(), cellReferenceObject.getRangePosition());
9490
9556
  return this._createRange(newRangeData);
9491
9557
  }
9492
9558
  unionRange(rangeData1, rangeData2) {
@@ -9528,8 +9594,6 @@ var CellReferenceObject = class extends BaseReferenceObject {
9528
9594
  rangeReferenceObject.setArrayFormulaCellData(this.getArrayFormulaCellData());
9529
9595
  rangeReferenceObject.setRuntimeArrayFormulaCellData(this.getRuntimeArrayFormulaCellData());
9530
9596
  rangeReferenceObject.setRuntimeFeatureCellData(this.getRuntimeFeatureCellData());
9531
- const { x, y } = this.getRefOffset();
9532
- rangeReferenceObject.setRefOffset(x, y);
9533
9597
  const forceSheetId = this.getForcedSheetId();
9534
9598
  rangeReferenceObject.setForcedSheetName(this.getForcedSheetName());
9535
9599
  if (forceSheetId != null) rangeReferenceObject.setForcedSheetIdDirect(forceSheetId);
@@ -10285,6 +10349,9 @@ let FormulaRuntimeService = class FormulaRuntimeService extends _univerjs_core.D
10285
10349
  this._functionRefInfoOverrideStack.pop();
10286
10350
  };
10287
10351
  }
10352
+ hasFunctionRefInfoOverride() {
10353
+ return this._functionRefInfoOverrideStack.length > 0;
10354
+ }
10288
10355
  clearFunctionDefinitionPrivacyVar() {
10289
10356
  this._functionDefinitionPrivacyVar.clear();
10290
10357
  }
@@ -10741,7 +10808,7 @@ var PrefixNode = class extends BaseAstNode {
10741
10808
  if (value instanceof ArrayValueObject) return value.get(0, 0) ?? ErrorValueObject.create("#VALUE!");
10742
10809
  if (!value.isReferenceObject()) return value;
10743
10810
  const currentValue = value;
10744
- if (currentValue.isCell()) return ErrorValueObject.create("#VALUE!");
10811
+ if (currentValue.isCell()) return currentValue.getCellByPosition();
10745
10812
  if (this._preserveAtRangeForFormula2LookupArray()) return currentValue;
10746
10813
  const runtimeService = this._runtimeService;
10747
10814
  const currentRow = runtimeService.currentRow || 0;
@@ -10906,6 +10973,7 @@ var FunctionNode = class extends BaseAstNode {
10906
10973
  if (!this._functionExecutor.returnsLegacyArrayAsScalar || !isTopLevel || !result.isArray()) return result;
10907
10974
  const array = result;
10908
10975
  if (array.getRowCount() <= 1 && array.getColumnCount() <= 1) return result;
10976
+ if (this._runtimeService.hasFunctionRefInfoOverride() && (this._runtimeService.currentRowCount > 1 || this._runtimeService.currentColumnCount > 1)) return result;
10909
10977
  return array.getFirstCell();
10910
10978
  }
10911
10979
  /**
@@ -11827,6 +11895,7 @@ var TableReferenceObject = class extends BaseReferenceObject {
11827
11895
  const tableStartRow = range.startRow;
11828
11896
  const tableEndRow = range.endRow;
11829
11897
  const dataStartRow = tableStartRow + (this._tableData.showHeader === false ? 0 : 1);
11898
+ const dataEndRow = tableEndRow - (this._tableData.showFooter === true ? 1 : 0);
11830
11899
  let startRow = -1;
11831
11900
  let endRow = -1;
11832
11901
  switch (type) {
@@ -11836,7 +11905,7 @@ var TableReferenceObject = class extends BaseReferenceObject {
11836
11905
  break;
11837
11906
  case "#Data":
11838
11907
  startRow = dataStartRow;
11839
- endRow = tableEndRow;
11908
+ endRow = dataEndRow;
11840
11909
  break;
11841
11910
  case "#Headers":
11842
11911
  if (this._tableData.showHeader === false) {
@@ -11852,14 +11921,14 @@ var TableReferenceObject = class extends BaseReferenceObject {
11852
11921
  endRow = tableEndRow;
11853
11922
  break;
11854
11923
  case "#This Row": {
11855
- const r = this._resolveThisRow(tableStartRow, tableEndRow);
11924
+ const r = this._resolveThisRow(dataStartRow, dataEndRow);
11856
11925
  startRow = r;
11857
11926
  endRow = r;
11858
11927
  break;
11859
11928
  }
11860
11929
  default:
11861
11930
  startRow = dataStartRow;
11862
- endRow = tableEndRow;
11931
+ endRow = dataEndRow;
11863
11932
  break;
11864
11933
  }
11865
11934
  this.setRangeData({
@@ -11886,7 +11955,8 @@ var TableReferenceObject = class extends BaseReferenceObject {
11886
11955
  getCellData(row, column) {
11887
11956
  if (this._isCurrentRowForRange) {
11888
11957
  const { startRow, endRow } = this._tableData.range;
11889
- if (row < startRow || row > endRow) return { v: "#N/A" };
11958
+ const lastCurrentRow = endRow - (this._tableData.showFooter === true ? 1 : 0);
11959
+ if (row < startRow || row > lastCurrentRow) return { v: "#N/A" };
11890
11960
  }
11891
11961
  return super.getCellData(row, column);
11892
11962
  }
@@ -12091,9 +12161,9 @@ var TableReferenceObject = class extends BaseReferenceObject {
12091
12161
  return -1;
12092
12162
  }
12093
12163
  /** Resolve #This Row's row number; takes first data row (tableStartRow+1) when no context available */
12094
- _resolveThisRow(tableStartRow, tableEndRow) {
12164
+ _resolveThisRow(dataStartRow, dataEndRow) {
12095
12165
  this._isCurrentRowForRange = true;
12096
- return Math.min(tableStartRow + 1, tableEndRow);
12166
+ return Math.min(dataStartRow, dataEndRow);
12097
12167
  }
12098
12168
  };
12099
12169
 
@@ -15576,13 +15646,13 @@ let RegisterOtherFormulaService = class RegisterOtherFormulaService extends _uni
15576
15646
  this._activeDirtyManagerService = _activeDirtyManagerService;
15577
15647
  this._lifecycleService = _lifecycleService;
15578
15648
  _defineProperty(this, "_formulaCacheMap", /* @__PURE__ */ new Map());
15649
+ _defineProperty(this, "_mutationSyncHandler", void 0);
15579
15650
  _defineProperty(this, "_formulaChangeWithRange$", new rxjs.Subject());
15580
15651
  _defineProperty(this, "formulaChangeWithRange$", this._formulaChangeWithRange$.asObservable());
15581
15652
  _defineProperty(this, "_formulaResult$", new rxjs.Subject());
15582
15653
  _defineProperty(this, "formulaResult$", this._formulaResult$.asObservable());
15583
15654
  _defineProperty(this, "_otherFormulaResultApplied$", new rxjs.Subject());
15584
15655
  _defineProperty(this, "otherFormulaResultApplied$", this._otherFormulaResultApplied$.asObservable());
15585
- _defineProperty(this, "calculateStarted$", new rxjs.BehaviorSubject(false));
15586
15656
  this._initFormulaRegister();
15587
15657
  this._initFormulaCalculationResultChange();
15588
15658
  }
@@ -15591,7 +15661,6 @@ let RegisterOtherFormulaService = class RegisterOtherFormulaService extends _uni
15591
15661
  this._formulaChangeWithRange$.complete();
15592
15662
  this._formulaResult$.complete();
15593
15663
  this._otherFormulaResultApplied$.complete();
15594
- this.calculateStarted$.complete();
15595
15664
  }
15596
15665
  _ensureCacheMap(unitId, subUnitId) {
15597
15666
  let unitMap = this._formulaCacheMap.get(unitId);
@@ -15617,6 +15686,7 @@ let RegisterOtherFormulaService = class RegisterOtherFormulaService extends _uni
15617
15686
  }
15618
15687
  });
15619
15688
  const handleRegister = (option) => {
15689
+ var _this$_mutationSyncHa;
15620
15690
  const { unitId, subUnitId, formulaText, formulaId, ranges } = option;
15621
15691
  if (!this._ensureCacheMap(unitId, subUnitId).has(formulaId)) return;
15622
15692
  const params = {
@@ -15627,13 +15697,29 @@ let RegisterOtherFormulaService = class RegisterOtherFormulaService extends _uni
15627
15697
  ranges
15628
15698
  } }
15629
15699
  };
15630
- this._commandService.executeCommand(SetOtherFormulaMutation.id, params, { onlyLocal: true }).then(() => {
15700
+ const waitForMutationSync = (_this$_mutationSyncHa = this._mutationSyncHandler) === null || _this$_mutationSyncHa === void 0 ? void 0 : _this$_mutationSyncHa.call(this, unitId);
15701
+ this._commandService.executeCommand(SetOtherFormulaMutation.id, params, { onlyLocal: true }).then(async () => {
15702
+ if (this._disposed) return;
15703
+ await (waitForMutationSync === null || waitForMutationSync === void 0 ? void 0 : waitForMutationSync());
15631
15704
  if (this._disposed) return;
15632
15705
  this._commandService.executeCommand(OtherFormulaMarkDirty.id, { [unitId]: { [subUnitId]: { [formulaId]: true } } }, { onlyLocal: true });
15633
15706
  });
15634
15707
  };
15635
- this.disposeWithMe(this._formulaChangeWithRange$.pipe((0, rxjs.bufferWhen)(() => this.calculateStarted$.pipe((0, rxjs.skip)(1), (0, rxjs.filter)((calculateStarted) => calculateStarted)))).subscribe((options) => options.forEach(handleRegister)));
15636
- this.disposeWithMe(this._formulaChangeWithRange$.pipe((0, rxjs.filter)(() => this.calculateStarted$.getValue())).subscribe(handleRegister));
15708
+ this.disposeWithMe(this._formulaChangeWithRange$.subscribe((option) => {
15709
+ if (this._commandService.hasCommand(SetOtherFormulaMutation.id) && this._commandService.hasCommand(OtherFormulaMarkDirty.id)) {
15710
+ handleRegister(option);
15711
+ return;
15712
+ }
15713
+ this._lifecycleService.onStage(_univerjs_core.LifecycleStages.Ready).then(() => {
15714
+ if (!this._disposed) handleRegister(option);
15715
+ });
15716
+ }));
15717
+ }
15718
+ setMutationSyncHandler(handler) {
15719
+ this._mutationSyncHandler = handler;
15720
+ return (0, _univerjs_core.toDisposable)(() => {
15721
+ if (this._mutationSyncHandler === handler) this._mutationSyncHandler = void 0;
15722
+ });
15637
15723
  }
15638
15724
  _initFormulaCalculationResultChange() {
15639
15725
  this.disposeWithMe(this._commandService.onCommandExecuted((commandInfo) => {
@@ -15705,11 +15791,13 @@ let RegisterOtherFormulaService = class RegisterOtherFormulaService extends _uni
15705
15791
  return Object.fromEntries(Array.from(unitMap.entries(), ([subUnitId, formulas]) => [subUnitId, Object.fromEntries(Array.from(formulas.keys(), (formulaId) => [formulaId, true]))]));
15706
15792
  }
15707
15793
  deleteFormula(unitId, subUnitId, formulaIdList) {
15794
+ var _this$_mutationSyncHa2;
15708
15795
  const params = {
15709
15796
  unitId,
15710
15797
  subUnitId,
15711
15798
  formulaIdList
15712
15799
  };
15800
+ (_this$_mutationSyncHa2 = this._mutationSyncHandler) === null || _this$_mutationSyncHa2 === void 0 || _this$_mutationSyncHa2.call(this, unitId);
15713
15801
  this._commandService.executeCommand(RemoveOtherFormulaMutation.id, params, { onlyLocal: true });
15714
15802
  const cacheMap = this._ensureCacheMap(unitId, subUnitId);
15715
15803
  formulaIdList.forEach((id) => cacheMap.delete(id));
@@ -16598,8 +16686,8 @@ var BaseFunction = class {
16598
16686
  if (isFirst) return this._getOneFirstByRaw(resultArrayValue);
16599
16687
  return this._getOneLastByRaw(resultArrayValue);
16600
16688
  }
16601
- orderSearch(value, searchArray, resultArray, searchType = 1, isDesc = false) {
16602
- const position = searchArray.orderSearch(value, searchType, isDesc);
16689
+ orderSearch(value, searchArray, resultArray, searchType = 1, isDesc = false, keepFirstNearest = false) {
16690
+ const position = searchArray.orderSearch(value, searchType, isDesc, false, keepFirstNearest);
16603
16691
  if (position == null) return ErrorValueObject.create("#N/A");
16604
16692
  const resultValue = resultArray.get(position.row, position.column) || NullValueObject.create();
16605
16693
  if (resultValue.isNull()) return ErrorValueObject.create("#N/A");
@@ -16629,8 +16717,8 @@ var BaseFunction = class {
16629
16717
  if (axis === 0) return resultArray.slice([position.row, position.row + 1]);
16630
16718
  return resultArray.slice(void 0, [position.column, position.column + 1]);
16631
16719
  }
16632
- orderSearchExpand(value, searchArray, resultArray, searchType = 1, isDesc = false, axis = 0) {
16633
- const position = searchArray.orderSearch(value, searchType, isDesc);
16720
+ orderSearchExpand(value, searchArray, resultArray, searchType = 1, isDesc = false, axis = 0, keepFirstNearest = false) {
16721
+ const position = searchArray.orderSearch(value, searchType, isDesc, false, keepFirstNearest);
16634
16722
  if (position == null) return ErrorValueObject.create("#N/A");
16635
16723
  if (axis === 0) return resultArray.slice([position.row, position.row + 1]);
16636
16724
  return resultArray.slice(void 0, [position.column, position.column + 1]);
@@ -30430,20 +30518,72 @@ var Or = class extends BaseFunction {
30430
30518
  }
30431
30519
  };
30432
30520
 
30521
+ //#endregion
30522
+ //#region src/functions/math/sum/index.ts
30523
+ var Sum = class extends BaseFunction {
30524
+ constructor(..._args) {
30525
+ super(..._args);
30526
+ _defineProperty(this, "minParams", 1);
30527
+ _defineProperty(this, "maxParams", 255);
30528
+ }
30529
+ calculate(...variants) {
30530
+ let accumulatorAll = NumberValueObject.create(0);
30531
+ for (let i = 0; i < variants.length; i++) {
30532
+ let variant = variants[i];
30533
+ variant = this._legacyImplicitDerivedArray(variant);
30534
+ if (variant.isString()) variant = variant.convertToNumberObjectValue();
30535
+ if (variant.isError()) return variant;
30536
+ if (variant.isArray()) variant = variant.sum();
30537
+ if (variant.isError()) return variant;
30538
+ accumulatorAll = accumulatorAll.plus(variant);
30539
+ if (accumulatorAll.isError()) return accumulatorAll;
30540
+ }
30541
+ return accumulatorAll;
30542
+ }
30543
+ _legacyImplicitDerivedArray(variant) {
30544
+ if (!variant.isArray()) return variant;
30545
+ const array = variant;
30546
+ if (array.usesInvertedIndexCache() || !array.usesLegacyImplicitForAggregate()) return variant;
30547
+ const startRow = array.getCurrentRow();
30548
+ const startColumn = array.getCurrentColumn();
30549
+ if (startRow < 0 || startColumn < 0) return variant;
30550
+ const rowCount = array.getRowCount();
30551
+ const columnCount = array.getColumnCount();
30552
+ let rowIndex = -1;
30553
+ let columnIndex = -1;
30554
+ if (rowCount === 1) {
30555
+ rowIndex = 0;
30556
+ columnIndex = this.column - startColumn;
30557
+ } else if (columnCount === 1) {
30558
+ rowIndex = this.row - startRow;
30559
+ columnIndex = 0;
30560
+ } else {
30561
+ rowIndex = this.row - startRow;
30562
+ columnIndex = this.column - startColumn;
30563
+ }
30564
+ if (rowIndex < 0 || rowIndex >= rowCount || columnIndex < 0 || columnIndex >= columnCount) return variant;
30565
+ return array.get(rowIndex, columnIndex) || variant;
30566
+ }
30567
+ };
30568
+
30433
30569
  //#endregion
30434
30570
  //#region src/functions/logical/percentof/index.ts
30435
30571
  /**
30436
- * PERCENTOF is an Excel GROUPBY aggregator token. It is evaluated by GROUPBY's
30437
- * AST path, not as a standalone scalar function.
30572
+ * PERCENTOF is logically equivalent to SUM(dataSubset) / SUM(dataAll).
30573
+ * GROUPBY also consumes the function name as an aggregator token through its AST path.
30438
30574
  */
30439
- var Percentof = class extends BaseFunction {
30575
+ var Percentof = class extends Sum {
30440
30576
  constructor(..._args) {
30441
30577
  super(..._args);
30442
- _defineProperty(this, "minParams", 0);
30443
- _defineProperty(this, "maxParams", 0);
30578
+ _defineProperty(this, "minParams", 2);
30579
+ _defineProperty(this, "maxParams", 2);
30444
30580
  }
30445
- calculate(..._variants) {
30446
- return ErrorValueObject.create("#VALUE!");
30581
+ calculate(dataSubset, dataAll) {
30582
+ const subsetTotal = super.calculate(dataSubset);
30583
+ if (subsetTotal.isError()) return subsetTotal;
30584
+ const allTotal = super.calculate(dataAll);
30585
+ if (allTotal.isError()) return allTotal;
30586
+ return subsetTotal.divided(allTotal);
30447
30587
  }
30448
30588
  };
30449
30589
 
@@ -33011,8 +33151,8 @@ var Xlookup = class extends BaseFunction {
33011
33151
  return this.binarySearchExpand(value, searchArray, resultArray, axis, searchType, matchType);
33012
33152
  }
33013
33153
  if (matchModeValue === 2) return this.fuzzySearchExpand(value, searchArray, resultArray, searchModeValue !== -1, axis);
33014
- if (matchModeValue === -1 || matchModeValue === 1) return this.orderSearchExpand(value, searchArray, resultArray, matchModeValue === 1 ? 2 : 1, searchModeValue === -1, axis);
33015
- return this.equalSearchExpand(value, searchArray, resultArray, searchModeValue !== -1, axis);
33154
+ if (matchModeValue === -1 || matchModeValue === 1) return this.orderSearchExpand(value, searchArray, resultArray, matchModeValue === 1 ? 2 : 1, searchModeValue === -1, axis, true);
33155
+ return this._exactSearchExpand(value, searchArray, resultArray, searchModeValue !== -1, axis);
33016
33156
  }
33017
33157
  _handleSingleObject(value, searchArray, resultArray, matchModeValue, searchModeValue) {
33018
33158
  if ((searchModeValue === 2 || searchModeValue === -2) && matchModeValue !== 2) {
@@ -33021,8 +33161,38 @@ var Xlookup = class extends BaseFunction {
33021
33161
  return this.binarySearch(value, searchArray, resultArray, searchType, matchType);
33022
33162
  }
33023
33163
  if (matchModeValue === 2) return this.fuzzySearch(value, searchArray, resultArray, searchModeValue !== -1);
33024
- if (matchModeValue === -1 || matchModeValue === 1) return this.orderSearch(value, searchArray, resultArray, matchModeValue === 1 ? 2 : 1, searchModeValue === -1);
33025
- return this.equalSearch(value, searchArray, resultArray, searchModeValue !== -1);
33164
+ if (matchModeValue === -1 || matchModeValue === 1) return this.orderSearch(value, searchArray, resultArray, matchModeValue === 1 ? 2 : 1, searchModeValue === -1, true);
33165
+ return this._exactSearch(value, searchArray, resultArray, searchModeValue !== -1);
33166
+ }
33167
+ _exactSearch(value, searchArray, resultArray, isFirst) {
33168
+ const position = this._findExactPosition(value, searchArray, isFirst);
33169
+ if (position == null) return ErrorValueObject.create("#N/A");
33170
+ return resultArray.get(position.row, position.column) ?? ErrorValueObject.create("#N/A");
33171
+ }
33172
+ _exactSearchExpand(value, searchArray, resultArray, isFirst, axis) {
33173
+ const position = this._findExactPosition(value, searchArray, isFirst);
33174
+ if (position == null) return ErrorValueObject.create("#N/A");
33175
+ return axis === 0 ? resultArray.slice([position.row, position.row + 1]) ?? ErrorValueObject.create("#N/A") : resultArray.slice(void 0, [position.column, position.column + 1]) ?? ErrorValueObject.create("#N/A");
33176
+ }
33177
+ _findExactPosition(value, searchArray, isFirst) {
33178
+ let position;
33179
+ const find = (candidate, row, column) => {
33180
+ if (candidate != null && this._isExactMatch(candidate, value)) {
33181
+ position = {
33182
+ row,
33183
+ column
33184
+ };
33185
+ return false;
33186
+ }
33187
+ };
33188
+ if (isFirst) searchArray.iterator(find);
33189
+ else searchArray.iteratorReverse(find);
33190
+ return position;
33191
+ }
33192
+ _isExactMatch(candidate, value) {
33193
+ if (candidate.isError() || value.isError()) return candidate.isError() && value.isError() && candidate.getValue() === value.getValue();
33194
+ if (candidate.isNull() !== value.isNull() || candidate.isNumber() !== value.isNumber() || candidate.isString() !== value.isString() || candidate.isBoolean() !== value.isBoolean()) return false;
33195
+ return candidate.isEqual(value).getValue() === true;
33026
33196
  }
33027
33197
  _blankResultAsZero(value) {
33028
33198
  if (value.isNull()) return NumberValueObject.create(0);
@@ -35589,54 +35759,6 @@ var Subtotal = class extends BaseFunction {
35589
35759
  }
35590
35760
  };
35591
35761
 
35592
- //#endregion
35593
- //#region src/functions/math/sum/index.ts
35594
- var Sum = class extends BaseFunction {
35595
- constructor(..._args) {
35596
- super(..._args);
35597
- _defineProperty(this, "minParams", 1);
35598
- _defineProperty(this, "maxParams", 255);
35599
- }
35600
- calculate(...variants) {
35601
- let accumulatorAll = NumberValueObject.create(0);
35602
- for (let i = 0; i < variants.length; i++) {
35603
- let variant = variants[i];
35604
- variant = this._legacyImplicitDerivedArray(variant);
35605
- if (variant.isString()) variant = variant.convertToNumberObjectValue();
35606
- if (variant.isError()) return variant;
35607
- if (variant.isArray()) variant = variant.sum();
35608
- if (variant.isError()) return variant;
35609
- accumulatorAll = accumulatorAll.plus(variant);
35610
- if (accumulatorAll.isError()) return accumulatorAll;
35611
- }
35612
- return accumulatorAll;
35613
- }
35614
- _legacyImplicitDerivedArray(variant) {
35615
- if (!variant.isArray()) return variant;
35616
- const array = variant;
35617
- if (array.usesInvertedIndexCache() || !array.usesLegacyImplicitForAggregate()) return variant;
35618
- const startRow = array.getCurrentRow();
35619
- const startColumn = array.getCurrentColumn();
35620
- if (startRow < 0 || startColumn < 0) return variant;
35621
- const rowCount = array.getRowCount();
35622
- const columnCount = array.getColumnCount();
35623
- let rowIndex = -1;
35624
- let columnIndex = -1;
35625
- if (rowCount === 1) {
35626
- rowIndex = 0;
35627
- columnIndex = this.column - startColumn;
35628
- } else if (columnCount === 1) {
35629
- rowIndex = this.row - startRow;
35630
- columnIndex = 0;
35631
- } else {
35632
- rowIndex = this.row - startRow;
35633
- columnIndex = this.column - startColumn;
35634
- }
35635
- if (rowIndex < 0 || rowIndex >= rowCount || columnIndex < 0 || columnIndex >= columnCount) return variant;
35636
- return array.get(rowIndex, columnIndex) || variant;
35637
- }
35638
- };
35639
-
35640
35762
  //#endregion
35641
35763
  //#region src/functions/math/sumif/index.ts
35642
35764
  var Sumif = class extends BaseFunction {
@@ -43007,7 +43129,7 @@ function getObjectValue(result, isUseStrip = false) {
43007
43129
  //#endregion
43008
43130
  //#region package.json
43009
43131
  var name = "@univerjs/engine-formula";
43010
- var version = "1.0.0-beta.0";
43132
+ var version = "1.0.0-beta.2";
43011
43133
 
43012
43134
  //#endregion
43013
43135
  //#region src/services/global-computing-status.service.ts
@@ -43307,12 +43429,9 @@ function hasSameNestedKey(left, right) {
43307
43429
  * limitations under the License.
43308
43430
  */
43309
43431
  let FormulaCalculationTriggerController = class FormulaCalculationTriggerController extends _univerjs_core.Disposable {
43310
- constructor(formulaCalculationTriggerService, registerOtherFormulaService, lifecycleService) {
43432
+ constructor(formulaCalculationTriggerService, lifecycleService) {
43311
43433
  super();
43312
- const start = () => {
43313
- formulaCalculationTriggerService.start();
43314
- registerOtherFormulaService.calculateStarted$.next(true);
43315
- };
43434
+ const start = () => formulaCalculationTriggerService.start();
43316
43435
  if ((0, _univerjs_core.isNodeEnv)()) {
43317
43436
  start();
43318
43437
  return;
@@ -43320,11 +43439,7 @@ let FormulaCalculationTriggerController = class FormulaCalculationTriggerControl
43320
43439
  this.disposeWithMe(lifecycleService.lifecycle$.pipe((0, rxjs.filter)((stage) => stage >= _univerjs_core.LifecycleStages.Rendered), (0, rxjs.take)(1)).subscribe(start));
43321
43440
  }
43322
43441
  };
43323
- FormulaCalculationTriggerController = __decorate([
43324
- __decorateParam(0, (0, _univerjs_core.Inject)(FormulaCalculationTriggerService)),
43325
- __decorateParam(1, (0, _univerjs_core.Inject)(RegisterOtherFormulaService)),
43326
- __decorateParam(2, (0, _univerjs_core.Inject)(_univerjs_core.LifecycleService))
43327
- ], FormulaCalculationTriggerController);
43442
+ FormulaCalculationTriggerController = __decorate([__decorateParam(0, (0, _univerjs_core.Inject)(FormulaCalculationTriggerService)), __decorateParam(1, (0, _univerjs_core.Inject)(_univerjs_core.LifecycleService))], FormulaCalculationTriggerController);
43328
43443
 
43329
43444
  //#endregion
43330
43445
  //#region src/controllers/formula.controller.ts
@@ -43347,10 +43462,12 @@ let FormulaController = class FormulaController extends _univerjs_core.Disposabl
43347
43462
  _syncOtherFormulaUnits() {
43348
43463
  const dataSyncPrimaryController = this._dataSyncPrimaryController;
43349
43464
  if (!dataSyncPrimaryController) return;
43350
- this.disposeWithMe(this._registerOtherFormulaService.formulaChangeWithRange$.subscribe(({ unitId }) => {
43351
- if (this._syncedOtherFormulaUnits.has(unitId)) return;
43352
- this._syncedOtherFormulaUnits.add(unitId);
43353
- this.disposeWithMe(dataSyncPrimaryController.syncUnitMutations(unitId));
43465
+ this.disposeWithMe(this._registerOtherFormulaService.setMutationSyncHandler((unitId) => {
43466
+ if (!this._syncedOtherFormulaUnits.has(unitId)) {
43467
+ this._syncedOtherFormulaUnits.add(unitId);
43468
+ this.disposeWithMe(dataSyncPrimaryController.syncUnitMutations(unitId));
43469
+ }
43470
+ return () => dataSyncPrimaryController.waitForPendingMutations();
43354
43471
  }));
43355
43472
  }
43356
43473
  _registerCommands() {
@@ -57059,7 +57176,6 @@ exports.getRangeWithRefsString = getRangeWithRefsString;
57059
57176
  exports.handleNumfmtInCell = handleNumfmtInCell;
57060
57177
  exports.handleRefStringInfo = handleRefStringInfo;
57061
57178
  exports.includeFormulaLexerToken = includeFormulaLexerToken;
57062
- exports.initSheetFormulaData = initSheetFormulaData;
57063
57179
  exports.isFormulaLexerToken = isFormulaLexerToken;
57064
57180
  exports.isFormulaReferenceAddingContext = isFormulaReferenceAddingContext;
57065
57181
  exports.isFormulaReferenceAddingTextContext = isFormulaReferenceAddingTextContext;