@univerjs/engine-formula 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js CHANGED
@@ -9740,6 +9740,89 @@ function baseValueObjectToArrayValueObject(valueObject) {
9740
9740
  if (valueObject.isArray()) return valueObject;
9741
9741
  return ArrayValueObject.createByArray([[valueObject.getValue()]]);
9742
9742
  }
9743
+ function getEqualityValueKeys(value) {
9744
+ const keys = [];
9745
+ if (value.isString()) keys.push(normalizeTextForComparison(String(value.getValue())));
9746
+ else if (!value.isNumber()) return keys;
9747
+ const number = value.isNumber() ? value : createCriteriaValueObject(String(value.getValue()), value.getDateSystem());
9748
+ if (number.isNumber() && Number.isFinite(Number(number.getValue()))) keys.push(stripErrorMargin(Number(number.getValue())));
9749
+ return keys;
9750
+ }
9751
+ function buildEqualityIndex(range) {
9752
+ const index = /* @__PURE__ */ new Map();
9753
+ range.iterator((value, row, column) => {
9754
+ if (!value) return;
9755
+ const position = [row, column];
9756
+ for (const key of getEqualityValueKeys(value)) {
9757
+ let matches = index.get(key);
9758
+ if (!matches) {
9759
+ matches = [];
9760
+ index.set(key, matches);
9761
+ }
9762
+ matches.push(position);
9763
+ }
9764
+ });
9765
+ return index;
9766
+ }
9767
+ function getIndexedPositions(index, keys, range) {
9768
+ const buckets = keys.map((key) => index.get(key) ?? []);
9769
+ if (buckets.reduce((count, bucket) => count + bucket.length, 0) >= range.getRowCount() * range.getColumnCount() / 2) return;
9770
+ if (buckets.length === 1) return buckets[0];
9771
+ return Array.from(new Set(buckets.flat())).sort((a, b) => a[0] - b[0] || a[1] - b[1]);
9772
+ }
9773
+ function pickRangePositions(range, positions) {
9774
+ return ArrayValueObject.create({
9775
+ calculateValueList: positions.map(([row, column]) => [range.get(row, column)]),
9776
+ rowCount: positions.length,
9777
+ columnCount: 1,
9778
+ unitId: "",
9779
+ sheetId: "",
9780
+ row: -1,
9781
+ column: -1
9782
+ });
9783
+ }
9784
+ function getExactCriteriaKeys(criteria) {
9785
+ if (!criteria || !criteria.isString() && !criteria.isNumber()) return;
9786
+ const [operator, value] = criteria.isString() ? findCompareToken(String(criteria.getValue()), criteria.getDateSystem()) : ["=", criteria];
9787
+ if (operator !== "=" || value.isDateFormat()) return;
9788
+ if (value.isString() && (value.getValue() === "" || isWildcard(String(value.getValue())))) return;
9789
+ const keys = getEqualityValueKeys(value);
9790
+ return keys.length > 0 ? keys : void 0;
9791
+ }
9792
+ function getCriteriaCacheKey(criteria) {
9793
+ if (criteria.length === 0 || criteria.some((value) => getExactCriteriaKeys(value) === void 0)) return;
9794
+ const values = criteria.map((value) => value.getValue());
9795
+ return values.length === 1 ? values[0] : JSON.stringify(values);
9796
+ }
9797
+ function getCriteriaPositions(pairs, indexes, row, column) {
9798
+ for (const { range, criteriaArray } of pairs) {
9799
+ const keys = getExactCriteriaKeys(criteriaArray.get(row, column));
9800
+ if (!keys) continue;
9801
+ let index = indexes.get(range);
9802
+ if (!index) {
9803
+ index = buildEqualityIndex(range);
9804
+ indexes.set(range, index);
9805
+ }
9806
+ const positions = getIndexedPositions(index, keys, range);
9807
+ if (positions !== void 0) return positions;
9808
+ }
9809
+ }
9810
+ function getConditionalAggregateResult(formulaName, comparison, targetRange) {
9811
+ if (formulaName === "COUNTIFS") {
9812
+ let count = 0;
9813
+ comparison.iterator((value) => {
9814
+ if ((value === null || value === void 0 ? void 0 : value.isBoolean()) && value.getValue() === true) count++;
9815
+ });
9816
+ return NumberValueObject.create(count);
9817
+ }
9818
+ const picked = targetRange === null || targetRange === void 0 ? void 0 : targetRange.pick(comparison);
9819
+ switch (formulaName) {
9820
+ case "SUMIFS": return picked.sum();
9821
+ case "AVERAGEIFS": return picked.sum().divided(picked.count());
9822
+ case "MAXIFS": return picked.getColumnCount() === 0 ? NumberValueObject.create(0) : picked.max();
9823
+ case "MINIFS": return picked.getColumnCount() === 0 ? NumberValueObject.create(0) : picked.min();
9824
+ }
9825
+ }
9743
9826
  /**
9744
9827
  * Get the paired range and criteria result for COUNTIFS, SUMIFS, etc.
9745
9828
  */
@@ -9758,50 +9841,48 @@ function getPairedRangeAndCriteriaResult(variants, params) {
9758
9841
  }
9759
9842
  if (rangeAndCriteriaArrays.length === 0) return [];
9760
9843
  const results = [];
9761
- /**
9762
- * Iterate through all criteria values for each dimension, calculate the comparison result with the corresponding range, and then calculate the Boolean intersection of all comparison results as the final result for that dimension criteria value.
9763
- * Then calculate this dimension criteria value's result.
9764
- * This avoiding store the all dimension comparison result in memory and then calculating all dimension criteria value's result, which may cause memory overflow when the range is large and there are multiple dimension criteria.
9765
- * For example, `=COUNTIFS(Q$3:Q$10002,C$3:C$5002,R$3:R$10002,L6)`.
9766
- */
9844
+ const arrayPairs = rangeAndCriteriaArrays.filter((_, index) => {
9845
+ const criteria = variants[index * 2 + 1];
9846
+ return criteria.isArray() && criteria.getRowCount() * criteria.getColumnCount() > 1;
9847
+ });
9848
+ const useEqualityIndex = isNumberSensitive && maxRowLength * maxColumnLength > 1 && arrayPairs.length > 0;
9849
+ const repeatedResults = /* @__PURE__ */ new Map();
9850
+ const equalityIndexes = /* @__PURE__ */ new Map();
9767
9851
  rangeAndCriteriaArrays[0].criteriaArray.iterator((_, rowIndex, columnIndex) => {
9768
9852
  let finalCompareResult;
9769
- for (let i = 0; i < rangeAndCriteriaArrays.length; i++) {
9770
- const { range, criteriaArray } = rangeAndCriteriaArrays[i];
9853
+ let positions;
9854
+ const cacheKey = useEqualityIndex ? getCriteriaCacheKey(arrayPairs.map(({ criteriaArray }) => criteriaArray.get(rowIndex, columnIndex))) : void 0;
9855
+ const cached = cacheKey === void 0 ? void 0 : repeatedResults.get(cacheKey);
9856
+ if (cached) {
9857
+ results[rowIndex] ??= [];
9858
+ results[rowIndex][columnIndex] = cached;
9859
+ return;
9860
+ }
9861
+ if (useEqualityIndex) {
9862
+ positions = getCriteriaPositions(arrayPairs, equalityIndexes, rowIndex, columnIndex);
9863
+ if ((positions === null || positions === void 0 ? void 0 : positions.length) === 0) {
9864
+ results[rowIndex] ??= [];
9865
+ results[rowIndex][columnIndex] = formulaName === "AVERAGEIFS" ? ErrorValueObject.create("#DIV/0!") : NumberValueObject.create(0);
9866
+ return;
9867
+ }
9868
+ }
9869
+ rangeAndCriteriaArrays.forEach(({ range: sourceRange, criteriaArray }) => {
9870
+ const range = positions === void 0 ? sourceRange : pickRangePositions(sourceRange, positions);
9771
9871
  const criteriaValueObject = criteriaArray.get(rowIndex, columnIndex);
9772
- if (!criteriaValueObject) continue;
9872
+ if (!criteriaValueObject) return;
9773
9873
  let compareResult = valueObjectCompare(range, criteriaValueObject);
9774
9874
  if (isNumberSensitive) compareResult = filterSameValueObjectResult(compareResult, range, criteriaValueObject);
9775
9875
  if (finalCompareResult === void 0) {
9776
9876
  finalCompareResult = compareResult;
9777
- continue;
9877
+ return;
9778
9878
  }
9779
9879
  finalCompareResult = booleanObjectIntersection(finalCompareResult, compareResult);
9780
- }
9781
- let result;
9782
- if (formulaName === "COUNTIFS") {
9783
- let count = 0;
9784
- finalCompareResult.iterator((value) => {
9785
- if ((value === null || value === void 0 ? void 0 : value.isBoolean()) && value.getValue() === true) count++;
9786
- });
9787
- result = NumberValueObject.create(count);
9788
- } else if (formulaName === "SUMIFS") result = targetRange.pick(finalCompareResult).sum();
9789
- else if (formulaName === "AVERAGEIFS") {
9790
- const picked = targetRange.pick(finalCompareResult);
9791
- const sum = picked.sum();
9792
- const count = picked.count();
9793
- result = sum.divided(count);
9794
- } else if (formulaName === "MAXIFS") {
9795
- const picked = targetRange.pick(finalCompareResult);
9796
- if (picked.getColumnCount() === 0) result = NumberValueObject.create(0);
9797
- else result = picked.max();
9798
- } else if (formulaName === "MINIFS") {
9799
- const picked = targetRange.pick(finalCompareResult);
9800
- if (picked.getColumnCount() === 0) result = NumberValueObject.create(0);
9801
- else result = picked.min();
9802
- }
9880
+ });
9881
+ const aggregateRange = positions === void 0 || !targetRange ? targetRange : pickRangePositions(targetRange, positions);
9882
+ const result = getConditionalAggregateResult(formulaName, finalCompareResult, aggregateRange);
9803
9883
  if (!results[rowIndex]) results[rowIndex] = [];
9804
9884
  results[rowIndex][columnIndex] = result;
9885
+ if (cacheKey !== void 0 && result) repeatedResults.set(cacheKey, result);
9805
9886
  });
9806
9887
  return results;
9807
9888
  }
@@ -9963,6 +10044,8 @@ let FormulaRuntimeService = class FormulaRuntimeService extends Disposable {
9963
10044
  _defineProperty(this, "_currentSubUnitId", "");
9964
10045
  _defineProperty(this, "_currentUnitId", "");
9965
10046
  _defineProperty(this, "_runtimeData", Object.create(null));
10047
+ _defineProperty(this, "_sourceFormulaData", Object.create(null));
10048
+ _defineProperty(this, "_currentSourceFormula", void 0);
9966
10049
  _defineProperty(this, "_runtimeOtherData", Object.create(null));
9967
10050
  _defineProperty(this, "_unitArrayFormulaRange", Object.create(null));
9968
10051
  _defineProperty(this, "_unitArrayFormulaEmbeddedMap", Object.create(null));
@@ -10075,6 +10158,8 @@ let FormulaRuntimeService = class FormulaRuntimeService extends Disposable {
10075
10158
  reset() {
10076
10159
  this._formulaExecuteStage = 0;
10077
10160
  this._runtimeData = Object.create(null);
10161
+ this._sourceFormulaData = Object.create(null);
10162
+ this._currentSourceFormula = void 0;
10078
10163
  this._runtimeOtherData = Object.create(null);
10079
10164
  this._unitArrayFormulaRange = Object.create(null);
10080
10165
  this._unitArrayFormulaEmbeddedMap = Object.create(null);
@@ -10096,6 +10181,7 @@ let FormulaRuntimeService = class FormulaRuntimeService extends Disposable {
10096
10181
  clearReferenceToRangeCache();
10097
10182
  }
10098
10183
  setCurrent(row, column, rowCount, columnCount, sheetId, unitId) {
10184
+ var _this$_currentConfigS, _this$_currentConfigS2;
10099
10185
  this._externalReferenceUnavailable = false;
10100
10186
  this._currentRow = row;
10101
10187
  this._currentColumn = column;
@@ -10103,6 +10189,18 @@ let FormulaRuntimeService = class FormulaRuntimeService extends Disposable {
10103
10189
  this._currentColumnCount = columnCount;
10104
10190
  this._currentSubUnitId = sheetId;
10105
10191
  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];
10194
+ if (formula) {
10195
+ const isSharedFollower = (formula.x ?? 0) !== 0 || (formula.y ?? 0) !== 0;
10196
+ this._currentSourceFormula = {
10197
+ f: isSharedFollower ? "" : formula.f,
10198
+ si: formula.si
10199
+ };
10200
+ } else this._currentSourceFormula = (cell === null || cell === void 0 ? void 0 : cell.f) || (cell === null || cell === void 0 ? void 0 : cell.si) ? {
10201
+ f: cell.f ?? "",
10202
+ si: cell.si ?? void 0
10203
+ } : void 0;
10106
10204
  }
10107
10205
  setFunctionRefInfoOverride(rowCount, columnCount) {
10108
10206
  this._functionRefInfoOverrideStack.push({
@@ -10153,9 +10251,9 @@ let FormulaRuntimeService = class FormulaRuntimeService extends Disposable {
10153
10251
  }
10154
10252
  setRuntimeData(functionVariant) {
10155
10253
  if (this._externalReferenceUnavailable) {
10156
- var _this$_currentConfigS, _this$_currentConfigS2;
10157
- const cell = (_this$_currentConfigS = this._currentConfigService.getUnitData()[this._currentUnitId]) === null || _this$_currentConfigS === void 0 || (_this$_currentConfigS = _this$_currentConfigS[this._currentSubUnitId]) === null || _this$_currentConfigS === void 0 ? void 0 : _this$_currentConfigS.cellData.getValue(this._currentRow, this._currentColumn);
10158
- const formula = (_this$_currentConfigS2 = this._currentConfigService.getFormulaData()[this._currentUnitId]) === null || _this$_currentConfigS2 === void 0 || (_this$_currentConfigS2 = _this$_currentConfigS2[this._currentSubUnitId]) === null || _this$_currentConfigS2 === void 0 || (_this$_currentConfigS2 = _this$_currentConfigS2[this._currentRow]) === null || _this$_currentConfigS2 === void 0 || (_this$_currentConfigS2 = _this$_currentConfigS2[this._currentColumn]) === null || _this$_currentConfigS2 === void 0 ? void 0 : _this$_currentConfigS2.f;
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;
10159
10257
  if ((cell === null || cell === void 0 ? void 0 : cell.f) && cell.v != null && (formula == null || formula === cell.f)) return;
10160
10258
  }
10161
10259
  const row = this._currentRow;
@@ -10214,7 +10312,7 @@ let FormulaRuntimeService = class FormulaRuntimeService extends Disposable {
10214
10312
  const hasDataInArrayFormulaRange = this._checkIfArrayFormulaRangeHasData(unitId, sheetId, row, column, arrayRange);
10215
10313
  const isArrayFormulaExceeded = this._checkIfArrayFormulaExceeded(rowCount, columnCount, arrayRange);
10216
10314
  if (hasDataInArrayFormulaRange || isArrayFormulaExceeded) {
10217
- var _this$_currentConfigS3;
10315
+ var _this$_currentConfigS5;
10218
10316
  const errorObject = this._getValueObjectOfRuntimeData(ErrorValueObject.create("#SPILL!"));
10219
10317
  sheetData.setValue(row, column, errorObject);
10220
10318
  clearArrayUnitData.setValue(row, column, errorObject);
@@ -10225,7 +10323,7 @@ let FormulaRuntimeService = class FormulaRuntimeService extends Disposable {
10225
10323
  */
10226
10324
  const unitData = this._currentConfigService.getUnitData();
10227
10325
  const arrayData = this._currentConfigService.getArrayFormulaCellData();
10228
- const previousArrayFormulaRange = (_this$_currentConfigS3 = this._currentConfigService.getArrayFormulaRange()[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];
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];
10229
10327
  objectValueRefOrArray.iterator((_, rowIndex, columnIndex) => {
10230
10328
  var _unitData$unitId, _arrayData$unitId;
10231
10329
  const currentRow = rowIndex - startRow + row;
@@ -10265,6 +10363,12 @@ let FormulaRuntimeService = class FormulaRuntimeService extends Disposable {
10265
10363
  } else {
10266
10364
  const valueObject = this._getValueObjectOfRuntimeData(functionVariant);
10267
10365
  sheetData.setValue(row, column, valueObject);
10366
+ if (this._currentSourceFormula != null) {
10367
+ const unitFormulas = this._sourceFormulaData[unitId] ??= {};
10368
+ const sheetFormulas = unitFormulas[sheetId] ??= {};
10369
+ const rowFormulas = sheetFormulas[row] ??= {};
10370
+ rowFormulas[column] = { ...this._currentSourceFormula };
10371
+ }
10268
10372
  if (functionVariant.isString() && functionVariant.isImage()) {
10269
10373
  const imageInfo = functionVariant.getImageInfo();
10270
10374
  if (imageInfo) this._runtimeImageFormulaData.push({
@@ -10336,6 +10440,7 @@ let FormulaRuntimeService = class FormulaRuntimeService extends Disposable {
10336
10440
  getAllRuntimeData() {
10337
10441
  return {
10338
10442
  unitData: this.getUnitData(),
10443
+ sourceFormulaData: this._sourceFormulaData,
10339
10444
  arrayFormulaRange: this.getUnitArrayFormula(),
10340
10445
  arrayFormulaEmbedded: this.getUnitArrayFormulaEmbeddedMap(),
10341
10446
  unitOtherData: this.getRuntimeOtherData(),
@@ -10362,11 +10467,11 @@ let FormulaRuntimeService = class FormulaRuntimeService extends Disposable {
10362
10467
  FORMULA_REF_TO_ARRAY_CACHE.clear();
10363
10468
  }
10364
10469
  _checkIfArrayFormulaRangeHasData(formulaUnitId, formulaSheetId, formulaRow, formulaColumn, arrayRange) {
10365
- var _this$_currentConfigS4;
10470
+ var _this$_currentConfigS6;
10366
10471
  const { startRow, startColumn, endRow, endColumn } = arrayRange;
10367
10472
  const unitData = this._currentConfigService.getUnitData();
10368
10473
  const arrayData = this._currentConfigService.getArrayFormulaCellData();
10369
- const previousArrayFormulaRange = (_this$_currentConfigS4 = this._currentConfigService.getArrayFormulaRange()[formulaUnitId]) === null || _this$_currentConfigS4 === void 0 || (_this$_currentConfigS4 = _this$_currentConfigS4[formulaSheetId]) === null || _this$_currentConfigS4 === void 0 || (_this$_currentConfigS4 = _this$_currentConfigS4[formulaRow]) === null || _this$_currentConfigS4 === void 0 ? void 0 : _this$_currentConfigS4[formulaColumn];
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];
10370
10475
  for (let r = startRow; r <= endRow; r++) for (let c = startColumn; c <= endColumn; c++) {
10371
10476
  var _this$_runtimeData, _arrayData$formulaUni, _unitData$formulaUnit;
10372
10477
  if (r === formulaRow && formulaColumn === c) continue;
@@ -10402,8 +10507,8 @@ let FormulaRuntimeService = class FormulaRuntimeService extends Disposable {
10402
10507
  * @returns
10403
10508
  */
10404
10509
  _isInOtherArrayFormulaRange(formulaUnitId, formulaSheetId, formulaRow, formulaColumn, r, c) {
10405
- var _this$_currentConfigS5;
10406
- const arrayFormulaRange = (_this$_currentConfigS5 = this._currentConfigService.getArrayFormulaRange()[formulaUnitId]) === null || _this$_currentConfigS5 === void 0 ? void 0 : _this$_currentConfigS5[formulaSheetId];
10510
+ var _this$_currentConfigS7;
10511
+ const arrayFormulaRange = (_this$_currentConfigS7 = this._currentConfigService.getArrayFormulaRange()[formulaUnitId]) === null || _this$_currentConfigS7 === void 0 ? void 0 : _this$_currentConfigS7[formulaSheetId];
10407
10512
  if (arrayFormulaRange == null) return false;
10408
10513
  let isCellOverlapping = false;
10409
10514
  new ObjectMatrix(arrayFormulaRange).forValue((rangeRow, rangeCol, range) => {
@@ -10416,8 +10521,8 @@ let FormulaRuntimeService = class FormulaRuntimeService extends Disposable {
10416
10521
  return isCellOverlapping;
10417
10522
  }
10418
10523
  _isCurrentSingleCellArrayFormulaRange(unitId, sheetId, row, column) {
10419
- var _this$_currentConfigS6;
10420
- const range = (_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];
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];
10421
10526
  return range != null && range.startRow === range.endRow && range.startColumn === range.endColumn;
10422
10527
  }
10423
10528
  _isInArrayFormulaRange(range, r, c) {
@@ -14777,13 +14882,13 @@ let CalculateFormulaService = class CalculateFormulaService extends Disposable {
14777
14882
  this._runtimeService.setRuntimeFeatureRange(featureId, featureRange);
14778
14883
  }
14779
14884
  async execute(formulaDatasetConfig) {
14780
- this._runtimeService.setFormulaExecuteStage(1);
14781
- this._executionInProgressListener$.next(this._runtimeService.getRuntimeState());
14782
- this._currentConfigService.load(formulaDatasetConfig);
14783
- this._runtimeService.reset();
14784
- const cycleReferenceCount = formulaDatasetConfig.maxIteration || 1;
14785
- this._isCalculateTreeModel = formulaDatasetConfig.isCalculateTreeModel || false;
14786
- this._executeLock.acquire("FORMULA_EXECUTION_LOCK", async () => {
14885
+ return this._executeLock.acquire("FORMULA_EXECUTION_LOCK", async () => {
14886
+ this._runtimeService.setFormulaExecuteStage(1);
14887
+ this._executionInProgressListener$.next(this._runtimeService.getRuntimeState());
14888
+ this._currentConfigService.load(formulaDatasetConfig);
14889
+ this._runtimeService.reset();
14890
+ const cycleReferenceCount = formulaDatasetConfig.maxIteration || 1;
14891
+ this._isCalculateTreeModel = formulaDatasetConfig.isCalculateTreeModel || false;
14787
14892
  for (let i = 0; i < cycleReferenceCount; i++) {
14788
14893
  this._runtimeService.setFormulaCycleIndex(i);
14789
14894
  const executed = await this._executeStep();
@@ -15156,7 +15261,7 @@ let CalculateController = class CalculateController extends Disposable {
15156
15261
  if (dependencyTreeModelData.length > 0) this._commandService.executeCommand(SetFormulaDependencyCalculationResultMutation.id, { result: dependencyTreeModelData }, { onlyLocal: true });
15157
15262
  }
15158
15263
  async _applyResult(data) {
15159
- const { unitData, unitOtherData, arrayFormulaRange, arrayFormulaCellData, clearArrayFormulaCellData, arrayFormulaEmbedded, imageFormulaData } = data;
15264
+ const { unitData, sourceFormulaData, unitOtherData, arrayFormulaRange, arrayFormulaCellData, clearArrayFormulaCellData, arrayFormulaEmbedded, imageFormulaData } = data;
15160
15265
  if (!unitData) {
15161
15266
  this._applyTreeResult(data);
15162
15267
  console.error("No sheetData from Formula Engine!");
@@ -15176,6 +15281,7 @@ let CalculateController = class CalculateController extends Disposable {
15176
15281
  this._applyTreeResult(data);
15177
15282
  this._commandService.executeCommand(SetFormulaCalculationResultMutation.id, {
15178
15283
  unitData: convertRuntimeToUnitData(unitData),
15284
+ sourceFormulaData,
15179
15285
  unitOtherData
15180
15286
  }, { onlyLocal: true });
15181
15287
  }
@@ -36215,6 +36321,19 @@ var Sumif = class extends BaseFunction {
36215
36321
  let _criteria = criteria;
36216
36322
  if (criteria.isReferenceObject()) _criteria = criteria.toArrayValueObject();
36217
36323
  if (_criteria.isArray()) {
36324
+ const criteriaArray = _criteria;
36325
+ const rangeArray = range.toArrayValueObject();
36326
+ const targetArray = sumRange ? sumRange.toArrayValueObject() : rangeArray;
36327
+ if (criteriaArray.getRowCount() * criteriaArray.getColumnCount() > 1 && rangeArray.getRowCount() === targetArray.getRowCount() && rangeArray.getColumnCount() === targetArray.getColumnCount()) {
36328
+ const values = getPairedRangeAndCriteriaResult([rangeArray, criteriaArray], {
36329
+ formulaName: "SUMIFS",
36330
+ maxRowLength: criteriaArray.getRowCount(),
36331
+ maxColumnLength: criteriaArray.getColumnCount(),
36332
+ isNumberSensitive: true,
36333
+ targetRange: targetArray
36334
+ });
36335
+ return criteriaArray.mapValue((_, row, column) => values[row][column]);
36336
+ }
36218
36337
  const resultArray = _criteria.mapValue((criteriaObject) => this._handleSingleObject(range, criteriaObject, sumRange));
36219
36338
  if (resultArray.getRowCount() === 1 && resultArray.getColumnCount() === 1) return resultArray.get(0, 0);
36220
36339
  return resultArray;
@@ -37200,6 +37319,19 @@ var Averageif = class extends BaseFunction {
37200
37319
  let _criteria = criteria;
37201
37320
  if (criteria.isReferenceObject()) _criteria = criteria.toArrayValueObject();
37202
37321
  if (_criteria.isArray()) {
37322
+ const criteriaArray = _criteria;
37323
+ const rangeArray = range.toArrayValueObject();
37324
+ const targetArray = averageRange ? averageRange.toArrayValueObject() : rangeArray;
37325
+ if (criteriaArray.getRowCount() * criteriaArray.getColumnCount() > 1 && rangeArray.getRowCount() === targetArray.getRowCount() && rangeArray.getColumnCount() === targetArray.getColumnCount()) {
37326
+ const values = getPairedRangeAndCriteriaResult([rangeArray, criteriaArray], {
37327
+ formulaName: "AVERAGEIFS",
37328
+ maxRowLength: criteriaArray.getRowCount(),
37329
+ maxColumnLength: criteriaArray.getColumnCount(),
37330
+ isNumberSensitive: true,
37331
+ targetRange: targetArray
37332
+ });
37333
+ return criteriaArray.mapValue((_, row, column) => values[row][column]);
37334
+ }
37203
37335
  const resultArray = _criteria.mapValue((criteriaObject) => this._handleSingleObject(range, criteriaObject, averageRange));
37204
37336
  if (resultArray.getRowCount() === 1 && resultArray.getColumnCount() === 1) return resultArray.get(0, 0);
37205
37337
  return resultArray;
@@ -37618,6 +37750,18 @@ var Countif = class extends BaseFunction {
37618
37750
  }
37619
37751
  }
37620
37752
  if (_criteria.isArray()) {
37753
+ const criteriaArray = _criteria;
37754
+ const rangeArray = range.toArrayValueObject();
37755
+ if (criteriaArray.getRowCount() * criteriaArray.getColumnCount() > 1) {
37756
+ const normalized = criteria.isReferenceObject() ? criteriaArray.mapValue((value) => value.isNull() ? NumberValueObject.create(0) : value) : criteriaArray;
37757
+ const values = getPairedRangeAndCriteriaResult([rangeArray, normalized], {
37758
+ formulaName: "COUNTIFS",
37759
+ maxRowLength: criteriaArray.getRowCount(),
37760
+ maxColumnLength: criteriaArray.getColumnCount(),
37761
+ isNumberSensitive: true
37762
+ });
37763
+ return criteriaArray.mapValue((_, row, column) => values[row][column]);
37764
+ }
37621
37765
  const resultArray = _criteria.mapValue((criteriaObject) => this._handleSingleObject(range, criteria.isReferenceObject() && criteriaObject.isNull() ? NumberValueObject.create(0) : criteriaObject));
37622
37766
  if (resultArray.getRowCount() === 1 && resultArray.getColumnCount() === 1) return resultArray.get(0, 0);
37623
37767
  return resultArray;
@@ -43600,7 +43744,7 @@ function getObjectValue(result, isUseStrip = false) {
43600
43744
  //#endregion
43601
43745
  //#region package.json
43602
43746
  var name = "@univerjs/engine-formula";
43603
- var version = "1.0.2";
43747
+ var version = "1.0.4";
43604
43748
 
43605
43749
  //#endregion
43606
43750
  //#region src/services/global-computing-status.service.ts
@@ -14,7 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
  import type { IExecutionOptions, IMutation, IUnitRange, Nullable } from '@univerjs/core';
17
- import type { IFormulaExecuteResultMap, IFormulaStringMap, IRuntimeOtherUnitDataType, IRuntimeUnitDataPrimitiveType } from '../../basics/common';
17
+ import type { IFormulaData, IFormulaExecuteResultMap, IFormulaStringMap, IRuntimeOtherUnitDataType, IRuntimeUnitDataPrimitiveType } from '../../basics/common';
18
18
  import type { IFormulaDependencyTreeFullJson, IFormulaDependencyTreeJson, IFormulaDependentsAndInRangeResults } from '../../engine/dependency/dependency-tree';
19
19
  import type { IFormulaDirtyData } from '../../services/current-data.service';
20
20
  import type { FormulaExecutedStateType, IExecutionInProgressParams } from '../../services/runtime.service';
@@ -73,6 +73,7 @@ export interface ISetFormulaCalculationNotificationMutation {
73
73
  export declare const SetFormulaCalculationNotificationMutation: IMutation<ISetFormulaCalculationNotificationMutation>;
74
74
  export interface ISetFormulaCalculationResultMutation {
75
75
  unitData: IRuntimeUnitDataPrimitiveType;
76
+ sourceFormulaData?: IFormulaData;
76
77
  unitOtherData: IRuntimeOtherUnitDataType;
77
78
  }
78
79
  export declare const SetFormulaCalculationResultMutation: IMutation<ISetFormulaCalculationResultMutation>;
@@ -14,7 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
  import type { Nullable } from '@univerjs/core';
17
- import type { IArrayFormulaEmbeddedMap, IArrayFormulaRangeType, IFeatureDirtyRangeType, IRuntimeImageFormulaDataType, IRuntimeOtherUnitDataType, IRuntimeUnitDataType } from '../basics/common';
17
+ import type { IArrayFormulaEmbeddedMap, IArrayFormulaRangeType, IFeatureDirtyRangeType, IFormulaData, IRuntimeImageFormulaDataType, IRuntimeOtherUnitDataType, IRuntimeUnitDataType } from '../basics/common';
18
18
  import type { BaseAstNode } from '../engine/ast-node/base-ast-node';
19
19
  import type { IFormulaDependencyTreeJson } from '../engine/dependency/dependency-tree';
20
20
  import type { FunctionVariantType } from '../engine/reference-object/base-reference-object';
@@ -44,6 +44,7 @@ export declare enum FormulaExecutedStateType {
44
44
  }
45
45
  export interface IAllRuntimeData {
46
46
  unitData: IRuntimeUnitDataType;
47
+ sourceFormulaData?: IFormulaData;
47
48
  arrayFormulaRange: IArrayFormulaRangeType;
48
49
  arrayFormulaEmbedded: IArrayFormulaEmbeddedMap;
49
50
  unitOtherData: IRuntimeOtherUnitDataType;
@@ -140,6 +141,8 @@ export declare class FormulaRuntimeService extends Disposable implements IFormul
140
141
  private _currentSubUnitId;
141
142
  private _currentUnitId;
142
143
  private _runtimeData;
144
+ private _sourceFormulaData;
145
+ private _currentSourceFormula;
143
146
  private _runtimeOtherData;
144
147
  private _unitArrayFormulaRange;
145
148
  private _unitArrayFormulaEmbeddedMap;