@univerjs/engine-formula 1.0.4 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/lib/cjs/{en-US-DrAfIiBE.js → en-US-BYMYuEpp.js} +15 -15
  2. package/lib/cjs/facade.js +3 -18
  3. package/lib/cjs/index.js +450 -161
  4. package/lib/cjs/locale/en-US.js +1 -1
  5. package/lib/cjs/locale/fa-IR.js +1 -1
  6. package/lib/cjs/locale/zh-HK.js +1 -1
  7. package/lib/cjs/locale/zh-TW.js +1 -1
  8. package/lib/cjs/{zh-TW-CvMudVQy.js → zh-TW-B5pYt-NJ.js} +15 -15
  9. package/lib/es/facade.js +3 -18
  10. package/lib/es/index.js +424 -135
  11. package/lib/facade.js +3 -18
  12. package/lib/index.js +424 -135
  13. package/lib/types/basics/common.d.ts +8 -2
  14. package/lib/types/commands/mutations/set-formula-calculation.mutation.d.ts +2 -1
  15. package/lib/types/config/config.d.ts +0 -2
  16. package/lib/types/engine/dependency/dependency-groups.d.ts +21 -0
  17. package/lib/types/engine/dependency/dependency-tree.d.ts +1 -0
  18. package/lib/types/engine/dependency/formula-dependency.d.ts +1 -1
  19. package/lib/types/facade/f-formula.d.ts +0 -13
  20. package/lib/types/functions/lookup/xlookup/index.d.ts +2 -4
  21. package/lib/types/index.d.ts +4 -2
  22. package/lib/types/models/formula-data.model.d.ts +5 -0
  23. package/lib/types/services/active-dirty-manager.service.d.ts +1 -0
  24. package/lib/types/services/calculate-formula.service.d.ts +34 -2
  25. package/lib/types/services/current-data.service.d.ts +4 -2
  26. package/lib/types/services/formula-calculation-trigger.service.d.ts +5 -0
  27. package/lib/types/services/formula-changeset-calculation.service.d.ts +34 -0
  28. package/lib/types/services/runtime.service.d.ts +36 -2
  29. package/lib/umd/facade.js +1 -1
  30. package/lib/umd/index.js +4 -4
  31. package/package.json +5 -5
package/lib/es/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import IntervalTree from "@flatten-js/interval-tree";
2
- import { AbsoluteRefType, AsyncLock, BooleanNumber, BuildTextUtils, CellValueType, CommandType, DataStreamTreeTokenType, DateSystem, Disposable, DisposableCollection, EXCEL_1904_OFFSET, ICommandService, IConfigService, IUniverInstanceService, Inject, Injector, LRUMap, LifecycleService, LifecycleStages, LocaleService, LocaleType, MAX_COLUMN_COUNT, MAX_ROW_COUNT, ObjectMatrix, Optional, Plugin, RANGE_TYPE, RTree, Rectangle, RichTextBuilder, Styles, Tools, UniverInstanceType, cellToRange, columnLabelToNumber, createBaseFormulaTableNameMap, createIdentifier, excelDateSerial, excelDateTimePartsToSerial, excelDateTimeSerial, excelSerialToDate, excelSerialToDateTime, excelSerialToDateTimeParts, generateRandomId, getBaseFormulaTableName, getDateSystemMaxSerial, getNumfmtParseValueFilter, hashAlgorithm, isFormulaId, isFormulaString, isNodeEnv, isNullCell, isRealNum, isTextFormat, isValidRange, merge, moveRangeByOffset, numfmt, regexp, requestImmediateMacroTask, sortRules, toDisposable, touchDependencies } from "@univerjs/core";
2
+ import { AbsoluteRefType, AsyncLock, BooleanNumber, BuildTextUtils, CellValueType, CommandType, DataStreamTreeTokenType, DateSystem, Disposable, DisposableCollection, EXCEL_1904_OFFSET, ICommandService, IConfigService, IUniverInstanceService, Inject, Injector, LRUMap, LifecycleService, LifecycleStages, LocaleService, LocaleType, MAX_COLUMN_COUNT, MAX_ROW_COUNT, ObjectMatrix, Optional, Plugin, RANGE_TYPE, RTree, Rectangle, RichTextBuilder, Styles, Tools, UniverInstanceType, cellToRange, columnLabelToNumber, createBaseFormulaTableNameMap, createIdentifier, excelDateSerial, excelDateTimePartsToSerial, excelDateTimeSerial, excelSerialToDate, excelSerialToDateTime, excelSerialToDateTimeParts, generateRandomId, getBaseFormulaTableName, getDateSystemMaxSerial, getNumfmtParseValueFilter, hashAlgorithm, isFormulaId, isFormulaString, isNodeEnv, isNullCell, isRealNum, isTextFormat, isValidRange, merge, moveRangeByOffset, normalizeWorkbookCalculationSettings, numfmt, regexp, requestImmediateMacroTask, sortRules, toDisposable, touchDependencies } from "@univerjs/core";
3
3
  import { BehaviorSubject, Observable, Subject, combineLatest, distinctUntilChanged, filter, map, shareReplay, take } from "rxjs";
4
4
  import Decimal from "decimal.js";
5
5
  import { DataSyncPrimaryController } from "@univerjs/rpc";
@@ -328,7 +328,7 @@ function getSearchModeValue(searchModeValue) {
328
328
  }
329
329
 
330
330
  //#endregion
331
- //#region \0@oxc-project+runtime@0.149.0/helpers/esm/typeof.js
331
+ //#region \0@oxc-project+runtime@0.153.0/helpers/esm/typeof.js
332
332
  function _typeof(o) {
333
333
  "@babel/helpers - typeof";
334
334
  return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
@@ -339,7 +339,7 @@ function _typeof(o) {
339
339
  }
340
340
 
341
341
  //#endregion
342
- //#region \0@oxc-project+runtime@0.149.0/helpers/esm/toPrimitive.js
342
+ //#region \0@oxc-project+runtime@0.153.0/helpers/esm/toPrimitive.js
343
343
  function toPrimitive(t, r) {
344
344
  if ("object" != _typeof(t) || !t) return t;
345
345
  var e = t[Symbol.toPrimitive];
@@ -352,14 +352,14 @@ function toPrimitive(t, r) {
352
352
  }
353
353
 
354
354
  //#endregion
355
- //#region \0@oxc-project+runtime@0.149.0/helpers/esm/toPropertyKey.js
355
+ //#region \0@oxc-project+runtime@0.153.0/helpers/esm/toPropertyKey.js
356
356
  function toPropertyKey(t) {
357
357
  var i = toPrimitive(t, "string");
358
358
  return "symbol" == _typeof(i) ? i : i + "";
359
359
  }
360
360
 
361
361
  //#endregion
362
- //#region \0@oxc-project+runtime@0.149.0/helpers/esm/defineProperty.js
362
+ //#region \0@oxc-project+runtime@0.153.0/helpers/esm/defineProperty.js
363
363
  function _defineProperty(e, r, t) {
364
364
  return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
365
365
  value: t,
@@ -1186,7 +1186,7 @@ function splitTableStructuredRef(ref) {
1186
1186
  }
1187
1187
 
1188
1188
  //#endregion
1189
- //#region \0@oxc-project+runtime@0.149.0/helpers/esm/decorateParam.js
1189
+ //#region \0@oxc-project+runtime@0.153.0/helpers/esm/decorateParam.js
1190
1190
  function __decorateParam(paramIndex, decorator) {
1191
1191
  return function(target, key) {
1192
1192
  decorator(target, key, paramIndex);
@@ -1194,7 +1194,7 @@ function __decorateParam(paramIndex, decorator) {
1194
1194
  }
1195
1195
 
1196
1196
  //#endregion
1197
- //#region \0@oxc-project+runtime@0.149.0/helpers/esm/decorate.js
1197
+ //#region \0@oxc-project+runtime@0.153.0/helpers/esm/decorate.js
1198
1198
  function __decorate(decorators, target, key, desc) {
1199
1199
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1200
1200
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -1672,8 +1672,6 @@ const SetSuperTableOptionMutation = {
1672
1672
  //#endregion
1673
1673
  //#region src/config/config.ts
1674
1674
  const ENGINE_FORMULA_PLUGIN_CONFIG_KEY = "engine-formula.config";
1675
- const DEFAULT_CYCLE_REFERENCE_COUNT = 1;
1676
- const ENGINE_FORMULA_CYCLE_REFERENCE_COUNT = "CYCLE_REFERENCE_COUNT";
1677
1675
  const ENGINE_FORMULA_RETURN_DEPENDENCY_TREE = "RETURN_DEPENDENCY_TREE";
1678
1676
  const configSymbol = Symbol(ENGINE_FORMULA_PLUGIN_CONFIG_KEY);
1679
1677
  const defaultPluginConfig = {};
@@ -3094,9 +3092,8 @@ var LexerTreeBuilder = class extends Disposable {
3094
3092
  const isCacheable = !/\b(?:LET|LAMBDA)\s*\(/iu.test(formulaString);
3095
3093
  const cacheKey = injectDefinedNameParam == null ? formulaString : `${injectDefinedNameParam.unitId ?? ""}\0${injectDefinedNameParam.sheetId ?? ""}\0${injectDefinedNameParam.refOffsetX}\0${injectDefinedNameParam.refOffsetY}\0${formulaString}`;
3096
3094
  if (transformSuffix === true && isCacheable) {
3097
- var _this$_simpleCheckDef;
3098
3095
  const lexerNode = FormulaLexerNodeCache.get(cacheKey);
3099
- const simpleCheckDefinedNameResult = injectDefinedNameParam && ((_this$_simpleCheckDef = this._simpleCheckDefinedName) === null || _this$_simpleCheckDef === void 0 ? void 0 : _this$_simpleCheckDef.call(this, formulaString, injectDefinedNameParam));
3096
+ const simpleCheckDefinedNameResult = injectDefinedNameParam && this._simpleCheckDefinedName(formulaString, injectDefinedNameParam, lexerNode);
3100
3097
  if (lexerNode && !simpleCheckDefinedNameResult) return lexerNode;
3101
3098
  }
3102
3099
  this._resetCurrentLexerNode();
@@ -3163,13 +3160,13 @@ var LexerTreeBuilder = class extends Disposable {
3163
3160
  const definedNameToken = token.trim();
3164
3161
  const definedContent = getValueByName(unitId, definedNameToken, sheetId);
3165
3162
  if (definedContent) {
3163
+ definedNames.push(definedContent.name);
3166
3164
  const refOffsetX = definedContent.localSheetId === "AllDefaultWorkbook" ? param.refOffsetX - 1 : param.refOffsetX;
3167
3165
  const refString = definedContent.formulaOrRefString.startsWith("=") ? definedContent.formulaOrRefString : this._moveDefinedNameRefOffset(definedContent.formulaOrRefString, refOffsetX, param.refOffsetY);
3168
3166
  const nestedDefinedNameParam = this._handleNestedDefinedName(refString, param);
3169
3167
  if (nestedDefinedNameParam == null || typeof nestedDefinedNameParam !== "object") {
3170
3168
  sequenceString += nestedDefinedNameParam || "#NAME?";
3171
3169
  hasDefinedName = true;
3172
- definedNames.push(definedNameToken);
3173
3170
  } else if (typeof nestedDefinedNameParam === "object") {
3174
3171
  const { sequenceString: nestedSequenceString, definedNames: nestedDefinedNames } = nestedDefinedNameParam;
3175
3172
  sequenceString += nestedSequenceString;
@@ -3234,7 +3231,7 @@ var LexerTreeBuilder = class extends Disposable {
3234
3231
  if (state === "#VALUE!" || sequenceArray.length === 0) return state;
3235
3232
  return this._handleDefinedName(sequenceArray, param);
3236
3233
  }
3237
- _simpleCheckDefinedName(formulaString, injectDefinedNameParam) {
3234
+ _simpleCheckDefinedName(formulaString, injectDefinedNameParam, lexerNode) {
3238
3235
  const { getDirtyDefinedNameMap, unitId } = injectDefinedNameParam;
3239
3236
  const definedNameMap = getDirtyDefinedNameMap();
3240
3237
  const executeUnitId = unitId;
@@ -3242,7 +3239,7 @@ var LexerTreeBuilder = class extends Disposable {
3242
3239
  const names = Object.keys(definedNameMap[executeUnitId]);
3243
3240
  for (let i = 0, len = names.length; i < len; i++) {
3244
3241
  const name = names[i];
3245
- if (formulaString.indexOf(name) > -1) return true;
3242
+ if (formulaString.indexOf(name) > -1 || (lexerNode === null || lexerNode === void 0 ? void 0 : lexerNode.getDefinedNames().includes(name))) return true;
3246
3243
  }
3247
3244
  }
3248
3245
  return false;
@@ -4301,18 +4298,43 @@ let FormulaDataModel = class FormulaDataModel extends Disposable {
4301
4298
  super();
4302
4299
  this._univerInstanceService = _univerInstanceService;
4303
4300
  this._lexerTreeBuilder = _lexerTreeBuilder;
4301
+ _defineProperty(this, "_circularReferences", /* @__PURE__ */ new Map());
4304
4302
  _defineProperty(this, "_formulaIdMapData", Object.create(null));
4305
4303
  _defineProperty(this, "_arrayFormulaRange", Object.create(null));
4306
4304
  _defineProperty(this, "_arrayFormulaCellData", Object.create(null));
4307
4305
  _defineProperty(this, "_unitImageFormulaData", Object.create(null));
4306
+ this.disposeWithMe(this._univerInstanceService.getTypeOfUnitDisposed$(UniverInstanceType.UNIVER_SHEET).subscribe((workbook) => {
4307
+ for (const [key, cell] of this._circularReferences) if (cell.unitId === workbook.getUnitId()) this._circularReferences.delete(key);
4308
+ }));
4308
4309
  }
4309
4310
  dispose() {
4310
4311
  super.dispose();
4312
+ this._circularReferences.clear();
4311
4313
  this._formulaIdMapData = Object.create(null);
4312
4314
  this._arrayFormulaRange = Object.create(null);
4313
4315
  this._arrayFormulaCellData = Object.create(null);
4314
4316
  this._unitImageFormulaData = Object.create(null);
4315
4317
  }
4318
+ setCircularReferences(cells) {
4319
+ this._circularReferences.clear();
4320
+ for (const cell of cells) this._circularReferences.set(JSON.stringify([
4321
+ cell.unitId,
4322
+ cell.sheetId,
4323
+ cell.row,
4324
+ cell.column
4325
+ ]), { ...cell });
4326
+ }
4327
+ getCircularReferences(unitId) {
4328
+ return Array.from(this._circularReferences.values()).filter((cell) => cell.unitId === unitId).map((cell) => ({ ...cell }));
4329
+ }
4330
+ isCircularReference(unitId, sheetId, row, column) {
4331
+ return this._circularReferences.has(JSON.stringify([
4332
+ unitId,
4333
+ sheetId,
4334
+ row,
4335
+ column
4336
+ ]));
4337
+ }
4316
4338
  clearPreviousArrayFormulaCellData(clearArrayFormulaCellData) {
4317
4339
  Object.keys(clearArrayFormulaCellData).forEach((unitId) => {
4318
4340
  const clearSheetData = clearArrayFormulaCellData[unitId];
@@ -5151,6 +5173,7 @@ let FormulaCurrentConfigService = class FormulaCurrentConfigService extends Disp
5151
5173
  this._localeService = _localeService;
5152
5174
  this._formulaDataModel = _formulaDataModel;
5153
5175
  this._sheetRowFilteredService = _sheetRowFilteredService;
5176
+ _defineProperty(this, "_dirtyIterationUnits", []);
5154
5177
  _defineProperty(this, "_unitData", Object.create(null));
5155
5178
  _defineProperty(this, "_unitStylesData", Object.create(null));
5156
5179
  _defineProperty(this, "_arrayFormulaCellData", Object.create(null));
@@ -5331,6 +5354,7 @@ let FormulaCurrentConfigService = class FormulaCurrentConfigService extends Disp
5331
5354
  }
5332
5355
  if (config.rowData) this._applyUnitRowData(config.rowData);
5333
5356
  this._formulaData = config.formulaData;
5357
+ this._dirtyIterationUnits = config.dirtyIterationUnits ?? [];
5334
5358
  this._arrayFormulaCellData = convertUnitDataToRuntime(config.arrayFormulaCellData);
5335
5359
  this._arrayFormulaRange = config.arrayFormulaRange;
5336
5360
  this._forceCalculate = config.forceCalculate;
@@ -5358,6 +5382,7 @@ let FormulaCurrentConfigService = class FormulaCurrentConfigService extends Disp
5358
5382
  }
5359
5383
  getDirtyData() {
5360
5384
  return {
5385
+ dirtyIterationUnits: this._dirtyIterationUnits,
5361
5386
  forceCalculation: this._forceCalculate,
5362
5387
  dirtyRanges: this._dirtyRanges,
5363
5388
  dirtyNameMap: this._dirtyNameMap,
@@ -5370,6 +5395,7 @@ let FormulaCurrentConfigService = class FormulaCurrentConfigService extends Disp
5370
5395
  };
5371
5396
  }
5372
5397
  loadDirtyRangesAndExcludedCell(dirtyRanges, excludedCell) {
5398
+ this._dirtyIterationUnits = [];
5373
5399
  this._dirtyRanges = dirtyRanges;
5374
5400
  this._excludedCell = excludedCell;
5375
5401
  /**
@@ -10029,11 +10055,14 @@ let FormulaExecutedStateType = /* @__PURE__ */ function(FormulaExecutedStateType
10029
10055
  return FormulaExecutedStateType;
10030
10056
  }({});
10031
10057
  let FormulaRuntimeService = class FormulaRuntimeService extends Disposable {
10032
- constructor(_currentConfigService, _hyperlinkEngineFormulaService) {
10058
+ constructor(_currentConfigService, _hyperlinkEngineFormulaService, _univerInstanceService) {
10033
10059
  super();
10034
10060
  this._currentConfigService = _currentConfigService;
10035
10061
  this._hyperlinkEngineFormulaService = _hyperlinkEngineFormulaService;
10062
+ this._univerInstanceService = _univerInstanceService;
10036
10063
  _defineProperty(this, "_formulaExecuteStage", 0);
10064
+ _defineProperty(this, "_circularReferences", /* @__PURE__ */ new Map());
10065
+ _defineProperty(this, "_pendingCircularReferences", /* @__PURE__ */ new Map());
10037
10066
  _defineProperty(this, "_stopState", false);
10038
10067
  _defineProperty(this, "_externalReferenceUnavailable", false);
10039
10068
  _defineProperty(this, "_currentRow", -1);
@@ -10063,6 +10092,9 @@ let FormulaRuntimeService = class FormulaRuntimeService extends Disposable {
10063
10092
  _defineProperty(this, "_formulaCycleIndex", 0);
10064
10093
  _defineProperty(this, "_isCycleDependency", false);
10065
10094
  _defineProperty(this, "_dependencyTreeModelData", []);
10095
+ this.disposeWithMe(this._univerInstanceService.getTypeOfUnitDisposed$(UniverInstanceType.UNIVER_SHEET).subscribe((workbook) => {
10096
+ for (const references of [this._circularReferences, this._pendingCircularReferences]) for (const [key, cell] of references) if (cell.unitId === workbook.getUnitId()) references.delete(key);
10097
+ }));
10066
10098
  }
10067
10099
  get currentRow() {
10068
10100
  return this._currentRow;
@@ -10087,6 +10119,8 @@ let FormulaRuntimeService = class FormulaRuntimeService extends Disposable {
10087
10119
  dispose() {
10088
10120
  super.dispose();
10089
10121
  this.reset();
10122
+ this._circularReferences.clear();
10123
+ this._pendingCircularReferences.clear();
10090
10124
  this._runtimeFeatureCellData = Object.create(null);
10091
10125
  this._runtimeFeatureRange = Object.create(null);
10092
10126
  this.clearReferenceAndNumberformatCache();
@@ -10180,8 +10214,60 @@ let FormulaRuntimeService = class FormulaRuntimeService extends Disposable {
10180
10214
  clearStringToNumberPatternCache();
10181
10215
  clearReferenceToRangeCache();
10182
10216
  }
10217
+ beginCircularReferences() {
10218
+ this._pendingCircularReferences = new Map(this._circularReferences);
10219
+ const formulaData = this._currentConfigService.getFormulaData();
10220
+ for (const [key, cell] of this._pendingCircularReferences) {
10221
+ var _formulaData$cell$uni;
10222
+ if (!((_formulaData$cell$uni = formulaData[cell.unitId]) === null || _formulaData$cell$uni === void 0 || (_formulaData$cell$uni = _formulaData$cell$uni[cell.sheetId]) === null || _formulaData$cell$uni === void 0 || (_formulaData$cell$uni = _formulaData$cell$uni[cell.row]) === null || _formulaData$cell$uni === void 0 ? void 0 : _formulaData$cell$uni[cell.column])) this._pendingCircularReferences.delete(key);
10223
+ }
10224
+ }
10225
+ clearCircularReferenceCells(cells) {
10226
+ if (this._pendingCircularReferences.size === 0) return;
10227
+ for (const cell of cells) {
10228
+ this._pendingCircularReferences.delete(JSON.stringify([
10229
+ cell.unitId,
10230
+ cell.subUnitId,
10231
+ cell.row,
10232
+ cell.column
10233
+ ]));
10234
+ if (this._pendingCircularReferences.size === 0) return;
10235
+ }
10236
+ }
10237
+ recordCircularReferences(cells) {
10238
+ for (const cell of cells) {
10239
+ if (cell.row < 0 || cell.column < 0) continue;
10240
+ this._pendingCircularReferences.set(JSON.stringify([
10241
+ cell.unitId,
10242
+ cell.sheetId,
10243
+ cell.row,
10244
+ cell.column
10245
+ ]), { ...cell });
10246
+ }
10247
+ }
10248
+ completeCircularReferences() {
10249
+ if (!this.isStopExecution()) this._circularReferences = new Map(this._pendingCircularReferences);
10250
+ }
10251
+ preserveCurrentCellData() {
10252
+ var _this$_currentConfigS;
10253
+ const unitId = this.currentUnitId;
10254
+ const sheetId = this.currentSubUnitId;
10255
+ const cell = (_this$_currentConfigS = this._currentConfigService.getUnitData()[unitId]) === null || _this$_currentConfigS === void 0 || (_this$_currentConfigS = _this$_currentConfigS[sheetId]) === null || _this$_currentConfigS === void 0 ? void 0 : _this$_currentConfigS.cellData.getValue(this.currentRow, this.currentColumn);
10256
+ if ((cell === null || cell === void 0 ? void 0 : cell.v) != null) return;
10257
+ const sheets = this._runtimeData[unitId] ??= {};
10258
+ (sheets[sheetId] ??= new ObjectMatrix()).setValue(this.currentRow, this.currentColumn, {
10259
+ v: (cell === null || cell === void 0 ? void 0 : cell.v) ?? 0,
10260
+ t: (cell === null || cell === void 0 ? void 0 : cell.v) == null ? CellValueType.NUMBER : cell.t
10261
+ });
10262
+ if (this._currentSourceFormula) {
10263
+ const formulas = this._sourceFormulaData[unitId] ??= {};
10264
+ const sheet = formulas[sheetId] ??= {};
10265
+ const row = sheet[this.currentRow] ??= {};
10266
+ row[this.currentColumn] = { ...this._currentSourceFormula };
10267
+ }
10268
+ }
10183
10269
  setCurrent(row, column, rowCount, columnCount, sheetId, unitId) {
10184
- var _this$_currentConfigS, _this$_currentConfigS2;
10270
+ var _this$_currentConfigS2, _this$_currentConfigS3;
10185
10271
  this._externalReferenceUnavailable = false;
10186
10272
  this._currentRow = row;
10187
10273
  this._currentColumn = column;
@@ -10189,8 +10275,8 @@ let FormulaRuntimeService = class FormulaRuntimeService extends Disposable {
10189
10275
  this._currentColumnCount = columnCount;
10190
10276
  this._currentSubUnitId = sheetId;
10191
10277
  this._currentUnitId = unitId;
10192
- const cell = (_this$_currentConfigS = this._currentConfigService.getUnitData()[unitId]) === null || _this$_currentConfigS === void 0 || (_this$_currentConfigS = _this$_currentConfigS[sheetId]) === null || _this$_currentConfigS === void 0 ? void 0 : _this$_currentConfigS.cellData.getValue(row, column);
10193
- const formula = (_this$_currentConfigS2 = this._currentConfigService.getFormulaData()[unitId]) === null || _this$_currentConfigS2 === void 0 || (_this$_currentConfigS2 = _this$_currentConfigS2[sheetId]) === null || _this$_currentConfigS2 === void 0 || (_this$_currentConfigS2 = _this$_currentConfigS2[row]) === null || _this$_currentConfigS2 === void 0 ? void 0 : _this$_currentConfigS2[column];
10278
+ const cell = (_this$_currentConfigS2 = this._currentConfigService.getUnitData()[unitId]) === null || _this$_currentConfigS2 === void 0 || (_this$_currentConfigS2 = _this$_currentConfigS2[sheetId]) === null || _this$_currentConfigS2 === void 0 ? void 0 : _this$_currentConfigS2.cellData.getValue(row, column);
10279
+ const formula = (_this$_currentConfigS3 = this._currentConfigService.getFormulaData()[unitId]) === null || _this$_currentConfigS3 === void 0 || (_this$_currentConfigS3 = _this$_currentConfigS3[sheetId]) === null || _this$_currentConfigS3 === void 0 || (_this$_currentConfigS3 = _this$_currentConfigS3[row]) === null || _this$_currentConfigS3 === void 0 ? void 0 : _this$_currentConfigS3[column];
10194
10280
  if (formula) {
10195
10281
  const isSharedFollower = (formula.x ?? 0) !== 0 || (formula.y ?? 0) !== 0;
10196
10282
  this._currentSourceFormula = {
@@ -10251,9 +10337,9 @@ let FormulaRuntimeService = class FormulaRuntimeService extends Disposable {
10251
10337
  }
10252
10338
  setRuntimeData(functionVariant) {
10253
10339
  if (this._externalReferenceUnavailable) {
10254
- var _this$_currentConfigS3, _this$_currentConfigS4;
10255
- const cell = (_this$_currentConfigS3 = this._currentConfigService.getUnitData()[this._currentUnitId]) === null || _this$_currentConfigS3 === void 0 || (_this$_currentConfigS3 = _this$_currentConfigS3[this._currentSubUnitId]) === null || _this$_currentConfigS3 === void 0 ? void 0 : _this$_currentConfigS3.cellData.getValue(this._currentRow, this._currentColumn);
10256
- const formula = (_this$_currentConfigS4 = this._currentConfigService.getFormulaData()[this._currentUnitId]) === null || _this$_currentConfigS4 === void 0 || (_this$_currentConfigS4 = _this$_currentConfigS4[this._currentSubUnitId]) === null || _this$_currentConfigS4 === void 0 || (_this$_currentConfigS4 = _this$_currentConfigS4[this._currentRow]) === null || _this$_currentConfigS4 === void 0 || (_this$_currentConfigS4 = _this$_currentConfigS4[this._currentColumn]) === null || _this$_currentConfigS4 === void 0 ? void 0 : _this$_currentConfigS4.f;
10340
+ var _this$_currentConfigS4, _this$_currentConfigS5;
10341
+ const cell = (_this$_currentConfigS4 = this._currentConfigService.getUnitData()[this._currentUnitId]) === null || _this$_currentConfigS4 === void 0 || (_this$_currentConfigS4 = _this$_currentConfigS4[this._currentSubUnitId]) === null || _this$_currentConfigS4 === void 0 ? void 0 : _this$_currentConfigS4.cellData.getValue(this._currentRow, this._currentColumn);
10342
+ const formula = (_this$_currentConfigS5 = this._currentConfigService.getFormulaData()[this._currentUnitId]) === null || _this$_currentConfigS5 === void 0 || (_this$_currentConfigS5 = _this$_currentConfigS5[this._currentSubUnitId]) === null || _this$_currentConfigS5 === void 0 || (_this$_currentConfigS5 = _this$_currentConfigS5[this._currentRow]) === null || _this$_currentConfigS5 === void 0 || (_this$_currentConfigS5 = _this$_currentConfigS5[this._currentColumn]) === null || _this$_currentConfigS5 === void 0 ? void 0 : _this$_currentConfigS5.f;
10257
10343
  if ((cell === null || cell === void 0 ? void 0 : cell.f) && cell.v != null && (formula == null || formula === cell.f)) return;
10258
10344
  }
10259
10345
  const row = this._currentRow;
@@ -10312,7 +10398,7 @@ let FormulaRuntimeService = class FormulaRuntimeService extends Disposable {
10312
10398
  const hasDataInArrayFormulaRange = this._checkIfArrayFormulaRangeHasData(unitId, sheetId, row, column, arrayRange);
10313
10399
  const isArrayFormulaExceeded = this._checkIfArrayFormulaExceeded(rowCount, columnCount, arrayRange);
10314
10400
  if (hasDataInArrayFormulaRange || isArrayFormulaExceeded) {
10315
- var _this$_currentConfigS5;
10401
+ var _this$_currentConfigS6;
10316
10402
  const errorObject = this._getValueObjectOfRuntimeData(ErrorValueObject.create("#SPILL!"));
10317
10403
  sheetData.setValue(row, column, errorObject);
10318
10404
  clearArrayUnitData.setValue(row, column, errorObject);
@@ -10323,7 +10409,7 @@ let FormulaRuntimeService = class FormulaRuntimeService extends Disposable {
10323
10409
  */
10324
10410
  const unitData = this._currentConfigService.getUnitData();
10325
10411
  const arrayData = this._currentConfigService.getArrayFormulaCellData();
10326
- const previousArrayFormulaRange = (_this$_currentConfigS5 = this._currentConfigService.getArrayFormulaRange()[unitId]) === null || _this$_currentConfigS5 === void 0 || (_this$_currentConfigS5 = _this$_currentConfigS5[sheetId]) === null || _this$_currentConfigS5 === void 0 || (_this$_currentConfigS5 = _this$_currentConfigS5[row]) === null || _this$_currentConfigS5 === void 0 ? void 0 : _this$_currentConfigS5[column];
10412
+ const previousArrayFormulaRange = (_this$_currentConfigS6 = this._currentConfigService.getArrayFormulaRange()[unitId]) === null || _this$_currentConfigS6 === void 0 || (_this$_currentConfigS6 = _this$_currentConfigS6[sheetId]) === null || _this$_currentConfigS6 === void 0 || (_this$_currentConfigS6 = _this$_currentConfigS6[row]) === null || _this$_currentConfigS6 === void 0 ? void 0 : _this$_currentConfigS6[column];
10327
10413
  objectValueRefOrArray.iterator((_, rowIndex, columnIndex) => {
10328
10414
  var _unitData$unitId, _arrayData$unitId;
10329
10415
  const currentRow = rowIndex - startRow + row;
@@ -10440,6 +10526,7 @@ let FormulaRuntimeService = class FormulaRuntimeService extends Disposable {
10440
10526
  getAllRuntimeData() {
10441
10527
  return {
10442
10528
  unitData: this.getUnitData(),
10529
+ circularReferences: Array.from(this._circularReferences.values(), (cell) => ({ ...cell })),
10443
10530
  sourceFormulaData: this._sourceFormulaData,
10444
10531
  arrayFormulaRange: this.getUnitArrayFormula(),
10445
10532
  arrayFormulaEmbedded: this.getUnitArrayFormulaEmbeddedMap(),
@@ -10460,6 +10547,7 @@ let FormulaRuntimeService = class FormulaRuntimeService extends Disposable {
10460
10547
  totalArrayFormulasToCalculate: this.getTotalArrayFormulasToCalculate(),
10461
10548
  completedArrayFormulasCount: this.getCompletedArrayFormulasCount(),
10462
10549
  stage: this.getFormulaExecuteStage(),
10550
+ circularReferences: Array.from(this._circularReferences.values(), (cell) => ({ ...cell })),
10463
10551
  formulaCycleIndex: this.getFormulaCycleIndex()
10464
10552
  };
10465
10553
  }
@@ -10467,11 +10555,11 @@ let FormulaRuntimeService = class FormulaRuntimeService extends Disposable {
10467
10555
  FORMULA_REF_TO_ARRAY_CACHE.clear();
10468
10556
  }
10469
10557
  _checkIfArrayFormulaRangeHasData(formulaUnitId, formulaSheetId, formulaRow, formulaColumn, arrayRange) {
10470
- var _this$_currentConfigS6;
10558
+ var _this$_currentConfigS7;
10471
10559
  const { startRow, startColumn, endRow, endColumn } = arrayRange;
10472
10560
  const unitData = this._currentConfigService.getUnitData();
10473
10561
  const arrayData = this._currentConfigService.getArrayFormulaCellData();
10474
- const previousArrayFormulaRange = (_this$_currentConfigS6 = this._currentConfigService.getArrayFormulaRange()[formulaUnitId]) === null || _this$_currentConfigS6 === void 0 || (_this$_currentConfigS6 = _this$_currentConfigS6[formulaSheetId]) === null || _this$_currentConfigS6 === void 0 || (_this$_currentConfigS6 = _this$_currentConfigS6[formulaRow]) === null || _this$_currentConfigS6 === void 0 ? void 0 : _this$_currentConfigS6[formulaColumn];
10562
+ const previousArrayFormulaRange = (_this$_currentConfigS7 = this._currentConfigService.getArrayFormulaRange()[formulaUnitId]) === null || _this$_currentConfigS7 === void 0 || (_this$_currentConfigS7 = _this$_currentConfigS7[formulaSheetId]) === null || _this$_currentConfigS7 === void 0 || (_this$_currentConfigS7 = _this$_currentConfigS7[formulaRow]) === null || _this$_currentConfigS7 === void 0 ? void 0 : _this$_currentConfigS7[formulaColumn];
10475
10563
  for (let r = startRow; r <= endRow; r++) for (let c = startColumn; c <= endColumn; c++) {
10476
10564
  var _this$_runtimeData, _arrayData$formulaUni, _unitData$formulaUnit;
10477
10565
  if (r === formulaRow && formulaColumn === c) continue;
@@ -10507,8 +10595,8 @@ let FormulaRuntimeService = class FormulaRuntimeService extends Disposable {
10507
10595
  * @returns
10508
10596
  */
10509
10597
  _isInOtherArrayFormulaRange(formulaUnitId, formulaSheetId, formulaRow, formulaColumn, r, c) {
10510
- var _this$_currentConfigS7;
10511
- const arrayFormulaRange = (_this$_currentConfigS7 = this._currentConfigService.getArrayFormulaRange()[formulaUnitId]) === null || _this$_currentConfigS7 === void 0 ? void 0 : _this$_currentConfigS7[formulaSheetId];
10598
+ var _this$_currentConfigS8;
10599
+ const arrayFormulaRange = (_this$_currentConfigS8 = this._currentConfigService.getArrayFormulaRange()[formulaUnitId]) === null || _this$_currentConfigS8 === void 0 ? void 0 : _this$_currentConfigS8[formulaSheetId];
10512
10600
  if (arrayFormulaRange == null) return false;
10513
10601
  let isCellOverlapping = false;
10514
10602
  new ObjectMatrix(arrayFormulaRange).forValue((rangeRow, rangeCol, range) => {
@@ -10521,8 +10609,8 @@ let FormulaRuntimeService = class FormulaRuntimeService extends Disposable {
10521
10609
  return isCellOverlapping;
10522
10610
  }
10523
10611
  _isCurrentSingleCellArrayFormulaRange(unitId, sheetId, row, column) {
10524
- var _this$_currentConfigS8;
10525
- const range = (_this$_currentConfigS8 = this._currentConfigService.getArrayFormulaRange()[unitId]) === null || _this$_currentConfigS8 === void 0 || (_this$_currentConfigS8 = _this$_currentConfigS8[sheetId]) === null || _this$_currentConfigS8 === void 0 || (_this$_currentConfigS8 = _this$_currentConfigS8[row]) === null || _this$_currentConfigS8 === void 0 ? void 0 : _this$_currentConfigS8[column];
10612
+ var _this$_currentConfigS9;
10613
+ const range = (_this$_currentConfigS9 = this._currentConfigService.getArrayFormulaRange()[unitId]) === null || _this$_currentConfigS9 === void 0 || (_this$_currentConfigS9 = _this$_currentConfigS9[sheetId]) === null || _this$_currentConfigS9 === void 0 || (_this$_currentConfigS9 = _this$_currentConfigS9[row]) === null || _this$_currentConfigS9 === void 0 ? void 0 : _this$_currentConfigS9[column];
10526
10614
  return range != null && range.startRow === range.endRow && range.startColumn === range.endColumn;
10527
10615
  }
10528
10616
  _isInArrayFormulaRange(range, r, c) {
@@ -10546,7 +10634,11 @@ let FormulaRuntimeService = class FormulaRuntimeService extends Disposable {
10546
10634
  return isInDirtyRange(dirtyRanges, unitId, sheetId, row, column);
10547
10635
  }
10548
10636
  };
10549
- FormulaRuntimeService = __decorate([__decorateParam(0, IFormulaCurrentConfigService), __decorateParam(1, IHyperlinkEngineFormulaService)], FormulaRuntimeService);
10637
+ FormulaRuntimeService = __decorate([
10638
+ __decorateParam(0, IFormulaCurrentConfigService),
10639
+ __decorateParam(1, IHyperlinkEngineFormulaService),
10640
+ __decorateParam(2, IUniverInstanceService)
10641
+ ], FormulaRuntimeService);
10550
10642
  const IFormulaRuntimeService = createIdentifier("univer.formula.runtime.service");
10551
10643
 
10552
10644
  //#endregion
@@ -13550,6 +13642,90 @@ var OtherFormulaManagerService = class extends Disposable {
13550
13642
  };
13551
13643
  const IOtherFormulaManagerService = createIdentifier("univer.formula.other-formula-manager.service");
13552
13644
 
13645
+ //#endregion
13646
+ //#region src/engine/dependency/dependency-groups.ts
13647
+ /**
13648
+ * Copyright 2023-present DreamNum Co., Ltd.
13649
+ *
13650
+ * Licensed under the Apache License, Version 2.0 (the "License");
13651
+ * you may not use this file except in compliance with the License.
13652
+ * You may obtain a copy of the License at
13653
+ *
13654
+ * http://www.apache.org/licenses/LICENSE-2.0
13655
+ *
13656
+ * Unless required by applicable law or agreed to in writing, software
13657
+ * distributed under the License is distributed on an "AS IS" BASIS,
13658
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13659
+ * See the License for the specific language governing permissions and
13660
+ * limitations under the License.
13661
+ */
13662
+ /**
13663
+ * Returns strongly connected components in dependency order: precedents before their dependents.
13664
+ * Mutually dependent nodes stay together so only their group needs iterative calculation.
13665
+ * Uses iterative Kosaraju traversal to avoid overflowing the call stack on large dependency graphs.
13666
+ */
13667
+ function getDependencyGroups(nodes, getId, getDependents) {
13668
+ const byId = new Map(nodes.map((node) => [getId(node), node]));
13669
+ const edges = /* @__PURE__ */ new Map();
13670
+ const reverse = /* @__PURE__ */ new Map();
13671
+ for (const node of nodes) {
13672
+ const id = getId(node);
13673
+ const dependents = Array.from(getDependents(node)).filter((dependent) => byId.has(dependent));
13674
+ edges.set(id, dependents);
13675
+ for (const dependent of dependents) {
13676
+ const incoming = reverse.get(dependent) ?? [];
13677
+ incoming.push(id);
13678
+ reverse.set(dependent, incoming);
13679
+ }
13680
+ }
13681
+ const visited = /* @__PURE__ */ new Set();
13682
+ const order = [];
13683
+ for (const id of byId.keys()) {
13684
+ if (visited.has(id)) continue;
13685
+ visited.add(id);
13686
+ const stack = [{
13687
+ id,
13688
+ next: 0
13689
+ }];
13690
+ while (stack.length) {
13691
+ const frame = stack[stack.length - 1];
13692
+ const children = edges.get(frame.id);
13693
+ if (frame.next === children.length) {
13694
+ order.push(frame.id);
13695
+ stack.pop();
13696
+ continue;
13697
+ }
13698
+ const child = children[frame.next++];
13699
+ if (!visited.has(child)) {
13700
+ visited.add(child);
13701
+ stack.push({
13702
+ id: child,
13703
+ next: 0
13704
+ });
13705
+ }
13706
+ }
13707
+ }
13708
+ visited.clear();
13709
+ const groups = [];
13710
+ for (let i = order.length - 1; i >= 0; i--) {
13711
+ const id = order[i];
13712
+ if (visited.has(id)) continue;
13713
+ const group = [];
13714
+ const stack = [id];
13715
+ visited.add(id);
13716
+ while (stack.length) {
13717
+ const current = stack.pop();
13718
+ group.push(byId.get(current));
13719
+ for (const parent of reverse.get(current) ?? []) if (!visited.has(parent)) {
13720
+ visited.add(parent);
13721
+ stack.push(parent);
13722
+ }
13723
+ }
13724
+ groups.push(group);
13725
+ }
13726
+ return groups;
13727
+ }
13728
+
13553
13729
  //#endregion
13554
13730
  //#region src/engine/dependency/dependency-tree.ts
13555
13731
  let FormulaDependencyTreeType = /* @__PURE__ */ function(FormulaDependencyTreeType) {
@@ -13562,6 +13738,7 @@ var FormulaDependencyTreeCalculator = class {
13562
13738
  constructor() {
13563
13739
  _defineProperty(this, "_state", 0);
13564
13740
  _defineProperty(this, "type", 0);
13741
+ _defineProperty(this, "cycleGroup", void 0);
13565
13742
  _defineProperty(this, "treeId", void 0);
13566
13743
  _defineProperty(this, "children", /* @__PURE__ */ new Set());
13567
13744
  _defineProperty(this, "parents", /* @__PURE__ */ new Set());
@@ -13983,7 +14160,28 @@ let FormulaDependencyGenerator = class FormulaDependencyGenerator extends Dispos
13983
14160
  await this._generateTreeList(formulaData, otherFormulaData, unitData);
13984
14161
  this._dependencyManagerService.openKdTree();
13985
14162
  const updateTreeList = this._getUpdateTreeListAndMakeDependency();
13986
- const finalTreeList = this._calculateRunList(updateTreeList);
14163
+ const runList = this._calculateRunList(updateTreeList);
14164
+ const selfReferences = /* @__PURE__ */ new Set();
14165
+ const groups = getDependencyGroups(runList, (tree) => tree.treeId, (tree) => {
14166
+ const dependents = this._dependencyManagerService.searchDependency(tree.toRTreeItem());
14167
+ const addressDependents = this._dependencyRTreeCacheForAddressFunction.bulkSearch(tree.toRTreeItem());
14168
+ for (const dependent of addressDependents) dependents.add(dependent);
14169
+ if (dependents.has(tree.treeId)) selfReferences.add(tree.treeId);
14170
+ return dependents;
14171
+ });
14172
+ this._runtimeService.clearCircularReferenceCells(runList);
14173
+ for (const group of groups) {
14174
+ const cyclic = group.length > 1 || selfReferences.has(group[0].treeId);
14175
+ const groupId = cyclic ? group.map((tree) => tree.treeId).sort((a, b) => a - b).join(",") : void 0;
14176
+ for (const tree of group) {
14177
+ tree.cycleGroup = groupId;
14178
+ if (cyclic) {
14179
+ var _this$_runtimeService;
14180
+ (_this$_runtimeService = this._runtimeService.getUnitData()[tree.unitId]) === null || _this$_runtimeService === void 0 || (_this$_runtimeService = _this$_runtimeService[tree.subUnitId]) === null || _this$_runtimeService === void 0 || _this$_runtimeService.realDeleteValue(tree.row, tree.column);
14181
+ }
14182
+ }
14183
+ }
14184
+ const finalTreeList = groups.flat().reverse();
13987
14185
  if (this._checkIsCycleDependency(finalTreeList)) this._runtimeService.enableCycleDependency();
13988
14186
  if (isCalculateTreeModel) this._runtimeService.setDependencyTreeModelData(this._getAllDependencyJson(Array.from(this._dependencyTreeCache.values())));
13989
14187
  this._dependencyTreeCache.clear();
@@ -13992,41 +14190,8 @@ let FormulaDependencyGenerator = class FormulaDependencyGenerator extends Dispos
13992
14190
  this._runtimeService.clearArrayObjectCache();
13993
14191
  return Promise.resolve(finalTreeList);
13994
14192
  }
13995
- _isCyclicUtilMap(treeId, colorMap) {
13996
- const WHITE = 0;
13997
- const GRAY = 1;
13998
- const BLACK = 2;
13999
- const stack = [treeId];
14000
- while (stack.length > 0) {
14001
- const currentTreeId = stack[stack.length - 1];
14002
- if ((colorMap.get(currentTreeId) || WHITE) === WHITE) {
14003
- colorMap.set(currentTreeId, GRAY);
14004
- const node = this._dependencyTreeCache.get(currentTreeId);
14005
- if (node == null) {
14006
- colorMap.set(currentTreeId, BLACK);
14007
- stack.pop();
14008
- continue;
14009
- }
14010
- const parents = this._dependencyManagerService.searchDependency(node.toRTreeItem());
14011
- for (const parentTreeId of parents) {
14012
- const parentColor = colorMap.get(parentTreeId) || WHITE;
14013
- if (parentColor === GRAY) return true;
14014
- else if (parentColor === WHITE) stack.push(parentTreeId);
14015
- }
14016
- } else {
14017
- colorMap.set(currentTreeId, BLACK);
14018
- stack.pop();
14019
- }
14020
- }
14021
- return false;
14022
- }
14023
14193
  _checkIsCycleDependency(treeList) {
14024
- const colorMap = /* @__PURE__ */ new Map();
14025
- for (const tree of treeList) if (!colorMap.has(tree.treeId)) {
14026
- if (this._isCyclicUtilMap(tree.treeId, colorMap)) return true;
14027
- }
14028
- colorMap.clear();
14029
- return false;
14194
+ return treeList.some((tree) => tree.cycleGroup != null);
14030
14195
  }
14031
14196
  _getFeatureFormulaTree(featureId, treeId, params) {
14032
14197
  const { unitId, subUnitId, dependencyRanges, getDirtyData } = params;
@@ -14410,11 +14575,17 @@ let FormulaDependencyGenerator = class FormulaDependencyGenerator extends Dispos
14410
14575
  if (node.nodeType === 12 && node.getToken() === "#") return true;
14411
14576
  return false;
14412
14577
  }
14578
+ _isStaticReference(node) {
14579
+ return node.nodeType === 1 || node.nodeType === 10 && node.getChildren().every((child) => this._isStaticReference(child));
14580
+ }
14413
14581
  _nodeTraversalRef(node, result) {
14414
14582
  const children = node.getChildren();
14415
14583
  const childrenCount = children.length;
14584
+ const token = node.getToken();
14585
+ const readsReferenceMetadata = node.nodeType === 4 && (token === "ROW" || token === "ROWS" || token === "COLUMN" || token === "COLUMNS");
14416
14586
  for (let i = 0; i < childrenCount; i++) {
14417
14587
  const item = children[i];
14588
+ if (readsReferenceMetadata && this._isStaticReference(item)) continue;
14418
14589
  if (this._isPreCalculateNode(item)) {
14419
14590
  result.push(item);
14420
14591
  if (item.nodeType === 10) {
@@ -14658,9 +14829,10 @@ let FormulaDependencyGenerator = class FormulaDependencyGenerator extends Dispos
14658
14829
  * @param tree
14659
14830
  */
14660
14831
  _includeTree(tree, node) {
14661
- var _this$_currentConfigS, _this$_currentConfigS2;
14832
+ var _this$_currentConfigS, _this$_currentConfigS2, _this$_currentConfigS3;
14662
14833
  const unitId = tree.unitId;
14663
14834
  const subUnitId = tree.subUnitId;
14835
+ if ((_this$_currentConfigS = this._currentConfigService.getDirtyData().dirtyIterationUnits) === null || _this$_currentConfigS === void 0 ? void 0 : _this$_currentConfigS.includes(unitId)) return true;
14664
14836
  /**
14665
14837
  * RAND, RANDBETWEEN, NOW, TODAY are volatile functions that are marked dirty and recalculated every time a calculation occurs.
14666
14838
  */
@@ -14668,13 +14840,13 @@ let FormulaDependencyGenerator = class FormulaDependencyGenerator extends Dispos
14668
14840
  if (this._includeTreeFeature(tree) === true) return true;
14669
14841
  if (this._includeOtherFormula(tree) === true) return true;
14670
14842
  if (includeDefinedName(tree, node, this._currentConfigService) === true) return true;
14671
- const excludedCell = (_this$_currentConfigS = this._currentConfigService.getExcludedRange()) === null || _this$_currentConfigS === void 0 || (_this$_currentConfigS = _this$_currentConfigS[unitId]) === null || _this$_currentConfigS === void 0 ? void 0 : _this$_currentConfigS[subUnitId];
14843
+ const excludedCell = (_this$_currentConfigS2 = this._currentConfigService.getExcludedRange()) === null || _this$_currentConfigS2 === void 0 || (_this$_currentConfigS2 = _this$_currentConfigS2[unitId]) === null || _this$_currentConfigS2 === void 0 ? void 0 : _this$_currentConfigS2[subUnitId];
14672
14844
  if ((excludedCell === null || excludedCell === void 0 ? void 0 : excludedCell.getValue(tree.row, tree.column)) != null) return false;
14673
14845
  /**
14674
14846
  * When a worksheet is inserted or deleted,
14675
14847
  * the formulas within it need to be calculated.
14676
14848
  */
14677
- if (((_this$_currentConfigS2 = this._currentConfigService.getDirtyNameMap()[unitId]) === null || _this$_currentConfigS2 === void 0 ? void 0 : _this$_currentConfigS2[subUnitId]) != null) return true;
14849
+ if (((_this$_currentConfigS3 = this._currentConfigService.getDirtyNameMap()[unitId]) === null || _this$_currentConfigS3 === void 0 ? void 0 : _this$_currentConfigS3[subUnitId]) != null) return true;
14678
14850
  if (!this._updateRangeFlattenCache.has(unitId)) return false;
14679
14851
  const sheetRangeMap = this._updateRangeFlattenCache.get(unitId);
14680
14852
  if (!sheetRangeMap.has(subUnitId)) return false;
@@ -14837,6 +15009,105 @@ FormulaDependencyGenerator = __decorate([
14837
15009
  const DEFAULT_INTERVAL_COUNT = 500;
14838
15010
  const ICalculateFormulaService = createIdentifier("engine-formula.calculate-formula.service");
14839
15011
  let CalculateFormulaService = class CalculateFormulaService extends Disposable {
15012
+ _loadCalculationSettings(settings) {
15013
+ this._workbookCalculationSettings = settings ?? {};
15014
+ this._normalizedCalculationSettings.clear();
15015
+ }
15016
+ _getCalculationSettings(unitId) {
15017
+ let settings = this._normalizedCalculationSettings.get(unitId);
15018
+ if (settings == null) {
15019
+ settings = normalizeWorkbookCalculationSettings(this._workbookCalculationSettings[unitId]);
15020
+ this._normalizedCalculationSettings.set(unitId, settings);
15021
+ }
15022
+ return settings;
15023
+ }
15024
+ _getIterationCell(tree) {
15025
+ var _this$_runtimeService, _this$_currentConfigS;
15026
+ const cell = ((_this$_runtimeService = this._runtimeService.getUnitData()[tree.unitId]) === null || _this$_runtimeService === void 0 || (_this$_runtimeService = _this$_runtimeService[tree.subUnitId]) === null || _this$_runtimeService === void 0 ? void 0 : _this$_runtimeService.getValue(tree.row, tree.column)) ?? ((_this$_currentConfigS = this._currentConfigService.getUnitData()[tree.unitId]) === null || _this$_currentConfigS === void 0 || (_this$_currentConfigS = _this$_currentConfigS[tree.subUnitId]) === null || _this$_currentConfigS === void 0 ? void 0 : _this$_currentConfigS.cellData.getValue(tree.row, tree.column)) ?? { v: 0 };
15027
+ return cell.v == null ? {
15028
+ v: 0,
15029
+ t: CellValueType.NUMBER
15030
+ } : cell;
15031
+ }
15032
+ async *_iterateCalculationGroup(group, groupId) {
15033
+ const settings = group.map((item) => this._getCalculationSettings(item.unitId));
15034
+ if (group.every((item, i) => {
15035
+ var _this$_currentConfigS2;
15036
+ const cell = (_this$_currentConfigS2 = this._currentConfigService.getUnitData()[item.unitId]) === null || _this$_currentConfigS2 === void 0 || (_this$_currentConfigS2 = _this$_currentConfigS2[item.subUnitId]) === null || _this$_currentConfigS2 === void 0 ? void 0 : _this$_currentConfigS2.cellData.getValue(item.row, item.column);
15037
+ const formula = (item.formula ?? (cell === null || cell === void 0 ? void 0 : cell.f) ?? "").toUpperCase();
15038
+ const requiresRecalculation = formula.includes(`${"INDEX"}(`) && !(formula.includes(`${"LOOKUP"}(`) && !formula.includes(`${"XLOOKUP"}(`));
15039
+ return settings[i].iterativeCalculation && this._preserveCircularUnits.has(item.unitId) && (cell === null || cell === void 0 ? void 0 : cell.v) != null && !requiresRecalculation;
15040
+ })) {
15041
+ for (const tree of group) yield {
15042
+ tree,
15043
+ preserve: true,
15044
+ iteration: 0
15045
+ };
15046
+ this._runtimeService.recordCircularReferences(group.map((item) => ({
15047
+ unitId: item.unitId,
15048
+ sheetId: item.subUnitId,
15049
+ row: item.row,
15050
+ column: item.column,
15051
+ groupId,
15052
+ iterations: 0
15053
+ })));
15054
+ return;
15055
+ }
15056
+ const limit = settings.reduce((limit, setting) => Math.max(limit, setting.iterativeCalculation ? setting.maxIterations : 0), 1);
15057
+ let converged = false;
15058
+ let iterations = 0;
15059
+ const beforeValues = [];
15060
+ const beforeTypes = [];
15061
+ for (let iteration = 0; iteration < limit; iteration++) {
15062
+ for (let i = 0; i < group.length; i++) if (settings[i].iterativeCalculation) {
15063
+ const before = this._getIterationCell(group[i]);
15064
+ beforeValues[i] = before.v;
15065
+ beforeTypes[i] = before.t;
15066
+ }
15067
+ for (let i = 0; i < group.length; i++) if (iteration < (settings[i].iterativeCalculation ? settings[i].maxIterations : 1)) {
15068
+ FORMULA_REF_TO_ARRAY_CACHE.clear();
15069
+ yield {
15070
+ tree: group[i],
15071
+ preserve: !settings[i].iterativeCalculation,
15072
+ iteration
15073
+ };
15074
+ }
15075
+ iterations = iteration + 1;
15076
+ converged = group.every((item, i) => {
15077
+ if (!settings[i].iterativeCalculation) return true;
15078
+ const after = this._getIterationCell(item);
15079
+ const previousValue = beforeValues[i];
15080
+ return typeof after.v === "number" && typeof previousValue === "number" && (after.t == null || after.t === CellValueType.NUMBER) && (beforeTypes[i] == null || beforeTypes[i] === CellValueType.NUMBER) ? Number.isFinite(after.v) && Math.abs(after.v - previousValue) <= settings[i].maxChange : after.t === beforeTypes[i] && after.v === previousValue;
15081
+ });
15082
+ if (converged) break;
15083
+ }
15084
+ FORMULA_REF_TO_ARRAY_CACHE.clear();
15085
+ this._runtimeService.recordCircularReferences(group.map((item, i) => ({
15086
+ unitId: item.unitId,
15087
+ sheetId: item.subUnitId,
15088
+ row: item.row,
15089
+ column: item.column,
15090
+ groupId,
15091
+ iterations: settings[i].iterativeCalculation ? Math.min(iterations, settings[i].maxIterations) : 0,
15092
+ converged: settings[i].iterativeCalculation ? converged : void 0
15093
+ })));
15094
+ }
15095
+ async *_getCalculationSteps(trees) {
15096
+ while (trees.length) {
15097
+ const tree = trees.pop();
15098
+ if (tree.cycleGroup == null) {
15099
+ yield {
15100
+ tree,
15101
+ preserve: false,
15102
+ iteration: 0
15103
+ };
15104
+ continue;
15105
+ }
15106
+ const group = [tree];
15107
+ while (trees.length && trees[trees.length - 1].cycleGroup === tree.cycleGroup) group.push(trees.pop());
15108
+ yield* this._iterateCalculationGroup(group, tree.cycleGroup);
15109
+ }
15110
+ }
14840
15111
  constructor(_configService, _lexer, _currentConfigService, _runtimeService, _formulaDependencyGenerator, _interpreter, _astTreeBuilder) {
14841
15112
  super();
14842
15113
  this._configService = _configService;
@@ -14852,6 +15123,9 @@ let CalculateFormulaService = class CalculateFormulaService extends Disposable {
14852
15123
  _defineProperty(this, "executionCompleteListener$", this._executionCompleteListener$.asObservable());
14853
15124
  _defineProperty(this, "_executeLock", new AsyncLock());
14854
15125
  _defineProperty(this, "_isCalculateTreeModel", false);
15126
+ _defineProperty(this, "_workbookCalculationSettings", {});
15127
+ _defineProperty(this, "_preserveCircularUnits", /* @__PURE__ */ new Set());
15128
+ _defineProperty(this, "_normalizedCalculationSettings", /* @__PURE__ */ new Map());
14855
15129
  }
14856
15130
  dispose() {
14857
15131
  super.dispose();
@@ -14887,15 +15161,12 @@ let CalculateFormulaService = class CalculateFormulaService extends Disposable {
14887
15161
  this._executionInProgressListener$.next(this._runtimeService.getRuntimeState());
14888
15162
  this._currentConfigService.load(formulaDatasetConfig);
14889
15163
  this._runtimeService.reset();
14890
- const cycleReferenceCount = formulaDatasetConfig.maxIteration || 1;
15164
+ this._loadCalculationSettings(formulaDatasetConfig.calculationSettings);
15165
+ this._preserveCircularUnits = new Set(formulaDatasetConfig.preserveCircularUnits);
15166
+ this._runtimeService.beginCircularReferences();
14891
15167
  this._isCalculateTreeModel = formulaDatasetConfig.isCalculateTreeModel || false;
14892
- for (let i = 0; i < cycleReferenceCount; i++) {
14893
- this._runtimeService.setFormulaCycleIndex(i);
14894
- const executed = await this._executeStep();
14895
- FORMULA_REF_TO_ARRAY_CACHE.clear();
14896
- const isCycleDependency = this._runtimeService.isCycleDependency();
14897
- if (!executed || !isCycleDependency) break;
14898
- }
15168
+ await this._executeStep();
15169
+ this._runtimeService.completeCircularReferences();
14899
15170
  this._runtimeService.setFormulaExecuteStage(8);
14900
15171
  this._executionInProgressListener$.next(this._runtimeService.getRuntimeState());
14901
15172
  this._executionCompleteListener$.next(this._runtimeService.getAllRuntimeData());
@@ -14976,15 +15247,9 @@ let CalculateFormulaService = class CalculateFormulaService extends Disposable {
14976
15247
  const intervalCount = (config === null || config === void 0 ? void 0 : config.intervalCount) || 500;
14977
15248
  let i = 0;
14978
15249
  const treeCount = treeList.length;
14979
- while (treeList.length > 0) {
14980
- const tree = treeList.pop();
15250
+ for await (const { tree, preserve, iteration } of this._getCalculationSteps(treeList)) {
15251
+ this._runtimeService.setFormulaCycleIndex(iteration);
14981
15252
  this._runtimeService.setCurrent(tree.row, tree.column, tree.rowCount, tree.columnCount, tree.subUnitId, tree.unitId);
14982
- const node = generateAstNode(tree.unitId, tree.formula, this._lexer, this._astTreeBuilder, this._currentConfigService, tree.subUnitId, tree.column, tree.row);
14983
- const nodeData = {
14984
- node,
14985
- refOffsetX: tree.refOffsetX,
14986
- refOffsetY: tree.refOffsetY
14987
- };
14988
15253
  const getDirtyData = tree.getDirtyData;
14989
15254
  if (i % intervalCount === 0) {
14990
15255
  /**
@@ -15002,12 +15267,23 @@ let CalculateFormulaService = class CalculateFormulaService extends Disposable {
15002
15267
  this._runtimeService.setCompletedFormulasCount(i + 1);
15003
15268
  }
15004
15269
  this._executionInProgressListener$.next(this._runtimeService.getRuntimeState());
15005
- if (this._runtimeService.isStopExecution() || nodeData == null && getDirtyData == null) {
15270
+ if (this._runtimeService.isStopExecution()) {
15006
15271
  this._runtimeService.setFormulaExecuteStage(0);
15007
15272
  this._runtimeService.markedAsStopFunctionsExecuted();
15008
15273
  return;
15009
15274
  }
15010
15275
  }
15276
+ if (preserve) {
15277
+ this._runtimeService.preserveCurrentCellData();
15278
+ i++;
15279
+ continue;
15280
+ }
15281
+ const node = generateAstNode(tree.unitId, tree.formula, this._lexer, this._astTreeBuilder, this._currentConfigService, tree.subUnitId, tree.column, tree.row);
15282
+ const nodeData = {
15283
+ node,
15284
+ refOffsetX: tree.refOffsetX,
15285
+ refOffsetY: tree.refOffsetY
15286
+ };
15011
15287
  let value;
15012
15288
  if (getDirtyData != null && tree.featureId != null) {
15013
15289
  /**
@@ -15183,11 +15459,12 @@ let CalculateController = class CalculateController extends Disposable {
15183
15459
  }));
15184
15460
  }
15185
15461
  async _calculate(formulaDirtyData) {
15186
- const { forceCalculation: forceCalculate = false, dirtyRanges = [], dirtyNameMap = {}, dirtyDefinedNameMap = {}, dirtySuperTableMap = {}, dirtyUnitFeatureMap = {}, dirtyUnitOtherFormulaMap = {}, clearDependencyTreeCache = {}, maxIteration = 1, rowData, externalReferences, isCalculateTreeModel = false } = formulaDirtyData;
15462
+ const { dirtyIterationUnits, forceCalculation: forceCalculate = false, dirtyRanges = [], dirtyNameMap = {}, dirtyDefinedNameMap = {}, dirtySuperTableMap = {}, dirtyUnitFeatureMap = {}, dirtyUnitOtherFormulaMap = {}, clearDependencyTreeCache = {}, calculationSettings, rowData, externalReferences, isCalculateTreeModel = false } = formulaDirtyData;
15187
15463
  const formulaData = this._formulaDataModel.getFormulaData();
15188
15464
  const arrayFormulaCellData = this._formulaDataModel.getArrayFormulaCellData();
15189
15465
  const arrayFormulaRange = this._formulaDataModel.getArrayFormulaRange();
15190
15466
  this._calculateFormulaService.execute({
15467
+ dirtyIterationUnits,
15191
15468
  formulaData,
15192
15469
  arrayFormulaCellData,
15193
15470
  arrayFormulaRange,
@@ -15199,7 +15476,7 @@ let CalculateController = class CalculateController extends Disposable {
15199
15476
  dirtyUnitFeatureMap,
15200
15477
  dirtyUnitOtherFormulaMap,
15201
15478
  clearDependencyTreeCache,
15202
- maxIteration,
15479
+ calculationSettings,
15203
15480
  isCalculateTreeModel,
15204
15481
  rowData,
15205
15482
  externalReferences
@@ -15247,7 +15524,10 @@ let CalculateController = class CalculateController extends Disposable {
15247
15524
  break;
15248
15525
  case 0:
15249
15526
  }
15250
- this._commandService.executeCommand(SetFormulaCalculationNotificationMutation.id, { functionsExecutedState }, { onlyLocal: true });
15527
+ this._commandService.executeCommand(SetFormulaCalculationNotificationMutation.id, {
15528
+ functionsExecutedState,
15529
+ circularReferences: data.circularReferences
15530
+ }, { onlyLocal: true });
15251
15531
  });
15252
15532
  /**
15253
15533
  * Assignment operation after formula calculation.
@@ -21325,13 +21605,13 @@ const weekendNumberMap = {
21325
21605
  17: [6]
21326
21606
  };
21327
21607
  function isValidWeekend(weekend) {
21328
- if (typeof weekend === "string" && /^[0|1]{7}/.test(weekend)) return true;
21608
+ if (typeof weekend === "string") return weekend.length === 7 && /^[01]{7}$/.test(weekend);
21329
21609
  if (weekendNumberMap[Number(weekend)]) return true;
21330
21610
  return false;
21331
21611
  }
21332
21612
  function getWeekendArray(weekend) {
21333
21613
  if (!isValidWeekend(weekend)) return [];
21334
- if (typeof weekend === "string" && /^[0|1]{7}/.test(weekend)) {
21614
+ if (typeof weekend === "string") {
21335
21615
  const result = [];
21336
21616
  for (let i = 1; i <= weekend.length; i++) if (`${weekend[i - 1]}` === "1") {
21337
21617
  if (i === weekend.length) result.push(0);
@@ -32706,7 +32986,7 @@ var Sort = class extends BaseFunction {
32706
32986
  _getResult(array, sortIndexValue, sortOrderValue, byColValue, arrayRowCount, arrayColumnCount) {
32707
32987
  if (!byColValue) {
32708
32988
  if (sortIndexValue > arrayColumnCount) return ErrorValueObject.create("#VALUE!");
32709
- const arrayValue = array.getArrayValue();
32989
+ const arrayValue = array.getArrayValue().slice();
32710
32990
  arrayValue.sort(this._sort(sortIndexValue - 1, sortOrderValue));
32711
32991
  return ArrayValueObject.create({
32712
32992
  calculateValueList: arrayValue,
@@ -33638,30 +33918,18 @@ var Xlookup = class extends BaseFunction {
33638
33918
  else resultArray = returnArray.slice(void 0, [0, 1]);
33639
33919
  if (resultArray == null) return ErrorValueObject.create("#N/A");
33640
33920
  return lookupValue.map((value) => {
33641
- const checkErrorCombination = this._checkErrorCombination(matchModeValue, searchModeValue);
33642
- if (checkErrorCombination) return checkErrorCombination;
33643
- const result = this._handleSingleObject(value, lookupArray, resultArray, matchModeValue, searchModeValue);
33644
- if (result.isError()) return ifNotFound;
33645
- return this._blankResultAsZero(result);
33921
+ return this._getLookupResult(value, lookupArray, resultArray, ifNotFound, matchModeValue, searchModeValue);
33646
33922
  });
33647
33923
  }
33648
33924
  const _lookupValue = lookupValue.isArray() ? lookupValue.get(0, 0) : lookupValue;
33649
- if (columnCountLookup === columnCountReturn && rowCountLookup === rowCountReturn) {
33650
- const checkErrorCombination = this._checkErrorCombination(matchModeValue, searchModeValue);
33651
- if (checkErrorCombination) return checkErrorCombination;
33652
- const result = this._handleSingleObject(_lookupValue, lookupArray, returnArray, matchModeValue, searchModeValue);
33653
- if (result.isError()) return ifNotFound;
33654
- return this._blankResultAsZero(result);
33655
- }
33925
+ if (columnCountLookup === columnCountReturn && rowCountLookup === rowCountReturn) return this._getLookupResult(_lookupValue, lookupArray, returnArray, ifNotFound, matchModeValue, searchModeValue);
33656
33926
  let axis = 0;
33657
33927
  /**
33658
33928
  * 0 for rows
33659
33929
  * 1 for columns
33660
33930
  */
33661
33931
  if (columnCountLookup === columnCountReturn) axis = 1;
33662
- const resultArray = this._handleExpandObject(_lookupValue, lookupArray, returnArray, matchModeValue, searchModeValue, axis);
33663
- if (resultArray == null) return ErrorValueObject.create("#N/A");
33664
- return resultArray;
33932
+ return this._getLookupResult(_lookupValue, lookupArray, returnArray, ifNotFound, matchModeValue, searchModeValue, axis);
33665
33933
  }
33666
33934
  _legacyImplicitLookupValue(lookupValue) {
33667
33935
  if (!lookupValue.isArray()) return lookupValue;
@@ -33689,35 +33957,37 @@ var Xlookup = class extends BaseFunction {
33689
33957
  if (rowIndex < 0 || rowIndex >= rowCount || columnIndex < 0 || columnIndex >= columnCount) return ErrorValueObject.create("#VALUE!");
33690
33958
  return array.get(rowIndex, columnIndex) || ErrorValueObject.create("#VALUE!");
33691
33959
  }
33692
- _handleExpandObject(value, searchArray, resultArray, matchModeValue, searchModeValue, axis = 0) {
33960
+ _getLookupResult(value, searchArray, resultArray, ifNotFound, matchModeValue, searchModeValue, axis) {
33961
+ if (value.isError()) return value;
33962
+ const checkErrorCombination = this._checkErrorCombination(matchModeValue, searchModeValue);
33963
+ if (checkErrorCombination) return checkErrorCombination;
33964
+ const position = this._findPosition(value, searchArray, matchModeValue, searchModeValue);
33965
+ if (position == null) return ifNotFound;
33966
+ if (axis === 0) return resultArray.slice([position.row, position.row + 1]) ?? ErrorValueObject.create("#N/A");
33967
+ if (axis === 1) return resultArray.slice(void 0, [position.column, position.column + 1]) ?? ErrorValueObject.create("#N/A");
33968
+ const result = resultArray.get(position.row, position.column) ?? NullValueObject.create();
33969
+ return this._blankResultAsZero(result);
33970
+ }
33971
+ _findPosition(value, searchArray, matchModeValue, searchModeValue) {
33693
33972
  if ((searchModeValue === 2 || searchModeValue === -2) && matchModeValue !== 2) {
33694
33973
  const searchType = getSearchModeValue(searchModeValue);
33695
33974
  const matchType = getMatchModeValue(matchModeValue);
33696
- return this.binarySearchExpand(value, searchArray, resultArray, axis, searchType, matchType);
33975
+ const rowOrColumn = searchArray.binarySearch(value, searchType, matchType);
33976
+ if (rowOrColumn == null) return null;
33977
+ return searchArray.getRowCount() === 1 ? {
33978
+ row: 0,
33979
+ column: rowOrColumn
33980
+ } : {
33981
+ row: rowOrColumn,
33982
+ column: 0
33983
+ };
33697
33984
  }
33698
- if (matchModeValue === 2) return this.fuzzySearchExpand(value, searchArray, resultArray, searchModeValue !== -1, axis);
33699
- if (matchModeValue === -1 || matchModeValue === 1) return this.orderSearchExpand(value, searchArray, resultArray, matchModeValue === 1 ? 2 : 1, searchModeValue === -1, axis, true);
33700
- return this._exactSearchExpand(value, searchArray, resultArray, searchModeValue !== -1, axis);
33701
- }
33702
- _handleSingleObject(value, searchArray, resultArray, matchModeValue, searchModeValue) {
33703
- if ((searchModeValue === 2 || searchModeValue === -2) && matchModeValue !== 2) {
33704
- const searchType = getSearchModeValue(searchModeValue);
33705
- const matchType = getMatchModeValue(matchModeValue);
33706
- return this.binarySearch(value, searchArray, resultArray, searchType, matchType);
33985
+ if (matchModeValue === 2) {
33986
+ const matches = searchArray.compare(value, "=");
33987
+ return searchModeValue === -1 ? matches.getLastTruePosition() : matches.getFirstTruePosition();
33707
33988
  }
33708
- if (matchModeValue === 2) return this.fuzzySearch(value, searchArray, resultArray, searchModeValue !== -1);
33709
- if (matchModeValue === -1 || matchModeValue === 1) return this.orderSearch(value, searchArray, resultArray, matchModeValue === 1 ? 2 : 1, searchModeValue === -1, true);
33710
- return this._exactSearch(value, searchArray, resultArray, searchModeValue !== -1);
33711
- }
33712
- _exactSearch(value, searchArray, resultArray, isFirst) {
33713
- const position = this._findExactPosition(value, searchArray, isFirst);
33714
- if (position == null) return ErrorValueObject.create("#N/A");
33715
- return resultArray.get(position.row, position.column) ?? ErrorValueObject.create("#N/A");
33716
- }
33717
- _exactSearchExpand(value, searchArray, resultArray, isFirst, axis) {
33718
- const position = this._findExactPosition(value, searchArray, isFirst);
33719
- if (position == null) return ErrorValueObject.create("#N/A");
33720
- 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");
33989
+ if (matchModeValue === -1 || matchModeValue === 1) return searchArray.orderSearch(value, matchModeValue === 1 ? 2 : 1, searchModeValue === -1, false, true);
33990
+ return this._findExactPosition(value, searchArray, searchModeValue !== -1);
33721
33991
  }
33722
33992
  _findExactPosition(value, searchArray, isFirst) {
33723
33993
  let position;
@@ -43744,7 +44014,7 @@ function getObjectValue(result, isUseStrip = false) {
43744
44014
  //#endregion
43745
44015
  //#region package.json
43746
44016
  var name = "@univerjs/engine-formula";
43747
- var version = "1.0.4";
44017
+ var version = "1.1.0";
43748
44018
 
43749
44019
  //#endregion
43750
44020
  //#region src/services/global-computing-status.service.ts
@@ -43830,6 +44100,7 @@ let FormulaCalculationTriggerService = class FormulaCalculationTriggerService ex
43830
44100
  _defineProperty(this, "_executionInProgress", false);
43831
44101
  _defineProperty(this, "_hasPendingCalculation", false);
43832
44102
  _defineProperty(this, "_stopRequested", false);
44103
+ _defineProperty(this, "_suppressed", false);
43833
44104
  this._registerGenericDirtyConversions();
43834
44105
  this._initialize();
43835
44106
  }
@@ -43838,6 +44109,16 @@ let FormulaCalculationTriggerService = class FormulaCalculationTriggerService ex
43838
44109
  this._started = true;
43839
44110
  this._scheduleFlush();
43840
44111
  }
44112
+ /** Snapshot reconstruction calculates these synchronous mutations in its isolated runtime. */
44113
+ runWithoutTriggering(operation) {
44114
+ const previous = this._suppressed;
44115
+ this._suppressed = true;
44116
+ try {
44117
+ return operation();
44118
+ } finally {
44119
+ this._suppressed = previous;
44120
+ }
44121
+ }
43841
44122
  dispose() {
43842
44123
  clearTimeout(this._timer);
43843
44124
  this._waitingCommandQueue = [];
@@ -43857,7 +44138,7 @@ let FormulaCalculationTriggerService = class FormulaCalculationTriggerService ex
43857
44138
  return;
43858
44139
  }
43859
44140
  const conversion = this._activeDirtyManagerService.get(command.id);
43860
- if (!conversion) return;
44141
+ if (!conversion || this._suppressed) return;
43861
44142
  if (((_conversion$shouldTri = conversion.shouldTrigger) === null || _conversion$shouldTri === void 0 ? void 0 : _conversion$shouldTri.call(conversion, command, options)) === false) return;
43862
44143
  this._waitingCommandQueue.push(command);
43863
44144
  this._scheduleFlush();
@@ -43946,6 +44227,8 @@ function mergeDirtyData(left, right) {
43946
44227
  return result;
43947
44228
  }
43948
44229
  function appendDirtyData(target, source, rangeKeys) {
44230
+ var _source$dirtyIteratio;
44231
+ if ((_source$dirtyIteratio = source.dirtyIterationUnits) === null || _source$dirtyIteratio === void 0 ? void 0 : _source$dirtyIteratio.length) target.dirtyIterationUnits = Array.from(/* @__PURE__ */ new Set([...target.dirtyIterationUnits ?? [], ...source.dirtyIterationUnits]));
43949
44232
  mergeDirtyRanges(target.dirtyRanges, source.dirtyRanges ?? [], rangeKeys);
43950
44233
  mergeDirtyUnitStringMap(target.dirtyNameMap, source.dirtyNameMap);
43951
44234
  mergeDirtyUnitStringMap(target.dirtyDefinedNameMap, source.dirtyDefinedNameMap);
@@ -43989,7 +44272,8 @@ function mergeDirtyUnitNestedMap(target, right) {
43989
44272
  });
43990
44273
  }
43991
44274
  function hasDirtyData(dirtyData) {
43992
- return dirtyData.forceCalculation || dirtyData.dirtyRanges.length > 0 || hasNestedValue(dirtyData.dirtyNameMap) || hasNestedValue(dirtyData.dirtyDefinedNameMap) || hasNestedValue(dirtyData.dirtySuperTableMap) || hasNestedValue(dirtyData.dirtyUnitFeatureMap) || hasNestedValue(dirtyData.dirtyUnitOtherFormulaMap) || hasNestedValue(dirtyData.clearDependencyTreeCache);
44275
+ var _dirtyData$dirtyItera;
44276
+ return dirtyData.forceCalculation || Boolean((_dirtyData$dirtyItera = dirtyData.dirtyIterationUnits) === null || _dirtyData$dirtyItera === void 0 ? void 0 : _dirtyData$dirtyItera.length) || dirtyData.dirtyRanges.length > 0 || hasNestedValue(dirtyData.dirtyNameMap) || hasNestedValue(dirtyData.dirtyDefinedNameMap) || hasNestedValue(dirtyData.dirtySuperTableMap) || hasNestedValue(dirtyData.dirtyUnitFeatureMap) || hasNestedValue(dirtyData.dirtyUnitOtherFormulaMap) || hasNestedValue(dirtyData.clearDependencyTreeCache);
43993
44277
  }
43994
44278
  function hasNestedValue(value) {
43995
44279
  if (value == null) return false;
@@ -43997,7 +44281,8 @@ function hasNestedValue(value) {
43997
44281
  return Object.values(value).some(hasNestedValue);
43998
44282
  }
43999
44283
  function dirtyDataIntersects(left, right) {
44000
- if (left.forceCalculation || right.forceCalculation) return true;
44284
+ var _left$dirtyIterationU, _right$dirtyIteration;
44285
+ if (left.forceCalculation || right.forceCalculation || ((_left$dirtyIterationU = left.dirtyIterationUnits) === null || _left$dirtyIterationU === void 0 ? void 0 : _left$dirtyIterationU.length) || ((_right$dirtyIteration = right.dirtyIterationUnits) === null || _right$dirtyIteration === void 0 ? void 0 : _right$dirtyIteration.length)) return true;
44001
44286
  if (left.dirtyRanges.some((leftRange) => right.dirtyRanges.some((rightRange) => leftRange.unitId === rightRange.unitId && leftRange.sheetId === rightRange.sheetId && Rectangle.intersects(leftRange.range, rightRange.range))) || clearedSheetIntersects(left, right) || clearedSheetIntersects(right, left)) return true;
44002
44287
  return [
44003
44288
  [left.dirtyNameMap, right.dirtyNameMap],
@@ -57446,4 +57731,8 @@ _defineProperty(UniverFormulaEnginePlugin, "version", version);
57446
57731
  UniverFormulaEnginePlugin = __decorate([__decorateParam(1, Inject(Injector)), __decorateParam(2, IConfigService)], UniverFormulaEnginePlugin);
57447
57732
 
57448
57733
  //#endregion
57449
- export { ALL_IMPLEMENTED_FUNCTIONS, ALL_IMPLEMENTED_FUNCTIONS_SET, ActiveDirtyManagerService, ArrayValueObject, AstRootNodeFactory, AstTreeBuilder, AsyncArrayObject, AsyncCustomFunction, AsyncObject, BaseFunction, BaseReferenceObject, BaseValueObject, BooleanValue, BooleanValueObject, CELL_INVERTED_INDEX_CACHE, CalculateController, CalculateFormulaService, CustomFunction, DEFAULT_CYCLE_REFERENCE_COUNT, DEFAULT_INTERVAL_COUNT, DEFAULT_TOKEN_LAMBDA_FUNCTION_NAME, DEFAULT_TOKEN_LET_FUNCTION_NAME, DEFAULT_TOKEN_TYPE_LAMBDA_PARAMETER, DEFAULT_TOKEN_TYPE_PARAMETER, DEFAULT_TOKEN_TYPE_ROOT, DefinedNamesService, DependencyManagerBaseService, DependencyManagerService, DescriptionService, ENGINE_FORMULA_CYCLE_REFERENCE_COUNT, ENGINE_FORMULA_PLUGIN_CONFIG_KEY, ENGINE_FORMULA_RETURN_DEPENDENCY_TREE, ERROR_TYPE_SET, ErrorType, ErrorValueObject, FORMULA_REF_TO_ARRAY_CACHE, FUNCTION_LIST, FUNCTION_LIST_ARRAY, FUNCTION_LIST_COMPATIBILITY, FUNCTION_LIST_CUBE, FUNCTION_LIST_DATABASE, FUNCTION_LIST_DATE, FUNCTION_LIST_ENGINEERING, FUNCTION_LIST_FINANCIAL, FUNCTION_LIST_INFORMATION, FUNCTION_LIST_LOGICAL, FUNCTION_LIST_LOOKUP, FUNCTION_LIST_MATH, FUNCTION_LIST_STATISTICAL, FUNCTION_LIST_TEXT, FUNCTION_LIST_UNIVER, FUNCTION_LIST_WEB, FUNCTION_NAMES_ARRAY, FUNCTION_NAMES_COMPATIBILITY, FUNCTION_NAMES_CUBE, FUNCTION_NAMES_DATABASE, FUNCTION_NAMES_DATE, FUNCTION_NAMES_ENGINEERING, FUNCTION_NAMES_FINANCIAL, FUNCTION_NAMES_INFORMATION, FUNCTION_NAMES_LOGICAL, FUNCTION_NAMES_LOOKUP, FUNCTION_NAMES_MATH, FUNCTION_NAMES_STATISTICAL, FUNCTION_NAMES_TEXT, FUNCTION_NAMES_UNIVER, FUNCTION_NAMES_WEB, FeatureCalculationManagerService, FormulaCalculationSessionController, FormulaCalculationSessionService, FormulaCalculationTriggerService, FormulaCurrentConfigService, FormulaDataModel, FormulaDependencyGenerator, FormulaDependencyTree, FormulaDependencyTreeModel, FormulaDependencyTreeType, FormulaDependencyTreeVirtual, FormulaExecuteStageType, FormulaExecutedStateType, FormulaResultApplicationType, FormulaResultStatus, FormulaRuntimeService, FormulaUnitReferenceResolver, FunctionNodeFactory, FunctionService, FunctionType, GlobalComputingStatusService, HyperlinkEngineFormulaService, IActiveDirtyManagerService, ICalculateFormulaService, IDefinedNamesService, IDependencyManagerService, IDescriptionService, IFeatureCalculationManagerService, IFormulaCurrentConfigService, IFormulaDependencyGenerator, IFormulaExternalReferenceDataLoader, IFormulaRuntimeService, IFormulaUnitReferenceResolver, IFunctionService, IHyperlinkEngineFormulaService, IOtherFormulaManagerService, IRegisterFunctionService, ISheetRowFilteredService, ISuperTableService, Interpreter, LambdaNodeFactory, LambdaParameterNodeFactory, LambdaValueObjectObject, Lexer, LexerNode, LexerTreeBuilder, NEW_EXCEL_FUNCTIONS, NoopFormulaExternalReferenceDataLoader, NullValueObject, NumberValueObject, OPERATOR_TOKEN_SET, OperatorNodeFactory, OtherFormulaBizType, OtherFormulaManagerService, OtherFormulaMarkDirty, PrefixNodeFactory, RangeReferenceObject, ReferenceNodeFactory, RegisterFunctionMutation, RegisterFunctionService, RegisterOtherFormulaService, RemoveDefinedNameMutation, RemoveFeatureCalculationMutation, RemoveOtherFormulaMutation, RemoveSuperTableMutation, SUFFIX_TOKEN_SET, SetArrayFormulaDataMutation, SetCellFormulaDependencyCalculationMutation, SetCellFormulaDependencyCalculationResultMutation, SetDefinedNameMutation, SetDefinedNameMutationFactory, SetFeatureCalculationMutation, SetFormulaCalculationNotificationMutation, SetFormulaCalculationResultMutation, SetFormulaCalculationStartMutation, SetFormulaCalculationStopMutation, SetFormulaDataMutation, SetFormulaDependencyCalculationMutation, SetFormulaDependencyCalculationResultMutation, SetFormulaStringBatchCalculationMutation, SetFormulaStringBatchCalculationResultMutation, SetImageFormulaDataMutation, SetOtherFormulaMutation, SetQueryFormulaDependencyAllMutation, SetQueryFormulaDependencyAllResultMutation, SetQueryFormulaDependencyMutation, SetQueryFormulaDependencyResultMutation, SetSuperTableMutation, SetSuperTableOptionMutation, SetTriggerFormulaCalculationStartMutation, SheetRowFilteredService, StringValueObject, SuffixNodeFactory, SuperTableActiveDirtyController, SuperTableService, UnionNodeFactory, UniverFormulaEnginePlugin, ValueNodeFactory, ValueObjectFactory, buildFormulaTextRuns, compareToken, convertUnitDataToRuntime, deserializeRangeForR1C1, deserializeRangeWithSheet, deserializeRangeWithSheetWithCache, extractFormulaError, findFormulaStructuredReferences, functionArray, functionCompatibility, functionCube, functionDatabase, functionDate, functionEngineering, functionFinancial, functionInformation, functionLogical, functionLookup, functionMath, functionMeta, functionStatistical, functionText, functionUniver, functionWeb, generateAstNode, generateExecuteAstNodeData, generateParam, generateRandomDependencyTreeId, generateStringWithSequence, getAbsoluteRefTypeWitString, getAbsoluteRefTypeWithSingleString, getFormulaHighlightDataStream, getFormulaReferenceIndex, getFormulaReplaceResult, getFormulaSequenceCharacterAtOffset, getFormulaSequenceNodeIndex, getFunctionName, getObjectValue, getRangeWithRefsString, handleNumfmtInCell, handleRefStringInfo, includeFormulaLexerToken, isFormulaLexerToken, isFormulaReferenceAddingContext, isFormulaReferenceAddingTextContext, isInDirtyRange, isReferenceString, isReferenceStringWithEffectiveColumn, isReferenceStrings, matchRefDrawToken, matchToken, needsQuoting, normalizeFormulaUnitName, normalizeSheetName, operatorToken, prefixToken, quoteSheetName, refactorFormulaUnitQualifier, resolveFormulaReferenceEditingContext, searchFormulaFunctions, sequenceNodeType, serializeRange, serializeRangeToRefString, serializeRangeWithSheet, serializeRangeWithSpreadsheet, singleReferenceToGrid, splitTableStructuredRef, strip, stripErrorMargin, unquoteSheetName };
57734
+ //#region src/services/formula-changeset-calculation.service.ts
57735
+ const IFormulaChangesetCalculationService = createIdentifier("engine-formula.changeset-calculation.service");
57736
+
57737
+ //#endregion
57738
+ export { ALL_IMPLEMENTED_FUNCTIONS, ALL_IMPLEMENTED_FUNCTIONS_SET, ActiveDirtyManagerService, ArrayValueObject, AstRootNodeFactory, AstTreeBuilder, AsyncArrayObject, AsyncCustomFunction, AsyncObject, BaseFunction, BaseReferenceObject, BaseValueObject, BooleanValue, BooleanValueObject, CELL_INVERTED_INDEX_CACHE, CalculateController, CalculateFormulaService, CustomFunction, DEFAULT_INTERVAL_COUNT, DEFAULT_TOKEN_LAMBDA_FUNCTION_NAME, DEFAULT_TOKEN_LET_FUNCTION_NAME, DEFAULT_TOKEN_TYPE_LAMBDA_PARAMETER, DEFAULT_TOKEN_TYPE_PARAMETER, DEFAULT_TOKEN_TYPE_ROOT, DefinedNamesService, DependencyManagerBaseService, DependencyManagerService, DescriptionService, ENGINE_FORMULA_PLUGIN_CONFIG_KEY, ENGINE_FORMULA_RETURN_DEPENDENCY_TREE, ERROR_TYPE_SET, ErrorType, ErrorValueObject, FORMULA_REF_TO_ARRAY_CACHE, FUNCTION_LIST, FUNCTION_LIST_ARRAY, FUNCTION_LIST_COMPATIBILITY, FUNCTION_LIST_CUBE, FUNCTION_LIST_DATABASE, FUNCTION_LIST_DATE, FUNCTION_LIST_ENGINEERING, FUNCTION_LIST_FINANCIAL, FUNCTION_LIST_INFORMATION, FUNCTION_LIST_LOGICAL, FUNCTION_LIST_LOOKUP, FUNCTION_LIST_MATH, FUNCTION_LIST_STATISTICAL, FUNCTION_LIST_TEXT, FUNCTION_LIST_UNIVER, FUNCTION_LIST_WEB, FUNCTION_NAMES_ARRAY, FUNCTION_NAMES_COMPATIBILITY, FUNCTION_NAMES_CUBE, FUNCTION_NAMES_DATABASE, FUNCTION_NAMES_DATE, FUNCTION_NAMES_ENGINEERING, FUNCTION_NAMES_FINANCIAL, FUNCTION_NAMES_INFORMATION, FUNCTION_NAMES_LOGICAL, FUNCTION_NAMES_LOOKUP, FUNCTION_NAMES_MATH, FUNCTION_NAMES_STATISTICAL, FUNCTION_NAMES_TEXT, FUNCTION_NAMES_UNIVER, FUNCTION_NAMES_WEB, FeatureCalculationManagerService, FormulaCalculationSessionController, FormulaCalculationSessionService, FormulaCalculationTriggerService, FormulaCurrentConfigService, FormulaDataModel, FormulaDependencyGenerator, FormulaDependencyTree, FormulaDependencyTreeModel, FormulaDependencyTreeType, FormulaDependencyTreeVirtual, FormulaExecuteStageType, FormulaExecutedStateType, FormulaResultApplicationType, FormulaResultStatus, FormulaRuntimeService, FormulaUnitReferenceResolver, FunctionNodeFactory, FunctionService, FunctionType, GlobalComputingStatusService, HyperlinkEngineFormulaService, IActiveDirtyManagerService, ICalculateFormulaService, IDefinedNamesService, IDependencyManagerService, IDescriptionService, IFeatureCalculationManagerService, IFormulaChangesetCalculationService, IFormulaCurrentConfigService, IFormulaDependencyGenerator, IFormulaExternalReferenceDataLoader, IFormulaRuntimeService, IFormulaUnitReferenceResolver, IFunctionService, IHyperlinkEngineFormulaService, IOtherFormulaManagerService, IRegisterFunctionService, ISheetRowFilteredService, ISuperTableService, Interpreter, LambdaNodeFactory, LambdaParameterNodeFactory, LambdaValueObjectObject, Lexer, LexerNode, LexerTreeBuilder, NEW_EXCEL_FUNCTIONS, NoopFormulaExternalReferenceDataLoader, NullValueObject, NumberValueObject, OPERATOR_TOKEN_SET, OperatorNodeFactory, OtherFormulaBizType, OtherFormulaManagerService, OtherFormulaMarkDirty, PrefixNodeFactory, RangeReferenceObject, ReferenceNodeFactory, RegisterFunctionMutation, RegisterFunctionService, RegisterOtherFormulaService, RemoveDefinedNameMutation, RemoveFeatureCalculationMutation, RemoveOtherFormulaMutation, RemoveSuperTableMutation, SUFFIX_TOKEN_SET, SetArrayFormulaDataMutation, SetCellFormulaDependencyCalculationMutation, SetCellFormulaDependencyCalculationResultMutation, SetDefinedNameMutation, SetDefinedNameMutationFactory, SetFeatureCalculationMutation, SetFormulaCalculationNotificationMutation, SetFormulaCalculationResultMutation, SetFormulaCalculationStartMutation, SetFormulaCalculationStopMutation, SetFormulaDataMutation, SetFormulaDependencyCalculationMutation, SetFormulaDependencyCalculationResultMutation, SetFormulaStringBatchCalculationMutation, SetFormulaStringBatchCalculationResultMutation, SetImageFormulaDataMutation, SetOtherFormulaMutation, SetQueryFormulaDependencyAllMutation, SetQueryFormulaDependencyAllResultMutation, SetQueryFormulaDependencyMutation, SetQueryFormulaDependencyResultMutation, SetSuperTableMutation, SetSuperTableOptionMutation, SetTriggerFormulaCalculationStartMutation, SheetRowFilteredService, StringValueObject, SuffixNodeFactory, SuperTableActiveDirtyController, SuperTableService, UnionNodeFactory, UniverFormulaEnginePlugin, ValueNodeFactory, ValueObjectFactory, buildFormulaTextRuns, compareToken, convertUnitDataToRuntime, deserializeRangeForR1C1, deserializeRangeWithSheet, deserializeRangeWithSheetWithCache, extractFormulaError, findFormulaStructuredReferences, functionArray, functionCompatibility, functionCube, functionDatabase, functionDate, functionEngineering, functionFinancial, functionInformation, functionLogical, functionLookup, functionMath, functionMeta, functionStatistical, functionText, functionUniver, functionWeb, generateAstNode, generateExecuteAstNodeData, generateParam, generateRandomDependencyTreeId, generateStringWithSequence, getAbsoluteRefTypeWitString, getAbsoluteRefTypeWithSingleString, getFormulaHighlightDataStream, getFormulaReferenceIndex, getFormulaReplaceResult, getFormulaSequenceCharacterAtOffset, getFormulaSequenceNodeIndex, getFunctionName, getObjectValue, getRangeWithRefsString, handleNumfmtInCell, handleRefStringInfo, includeFormulaLexerToken, isFormulaLexerToken, isFormulaReferenceAddingContext, isFormulaReferenceAddingTextContext, isInDirtyRange, isReferenceString, isReferenceStringWithEffectiveColumn, isReferenceStrings, matchRefDrawToken, matchToken, mergeDirtyData, needsQuoting, normalizeFormulaUnitName, normalizeSheetName, operatorToken, prefixToken, quoteSheetName, refactorFormulaUnitQualifier, resolveFormulaReferenceEditingContext, searchFormulaFunctions, sequenceNodeType, serializeRange, serializeRangeToRefString, serializeRangeWithSheet, serializeRangeWithSpreadsheet, singleReferenceToGrid, splitTableStructuredRef, strip, stripErrorMargin, unquoteSheetName };