@devmm/puredocs-excel-formula 1.1.0 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -275,7 +275,7 @@ declare namespace FormulaHelper {
275
275
  * Everything else — comparisons, wildcards — only gets the compiled `test`.
276
276
  */
277
277
  interface CompiledCriteria {
278
- readonly kind: 'equalsNumber' | 'equalsText' | 'compareNumber' | 'other';
278
+ readonly kind: 'equalsNumber' | 'equalsText' | 'compareNumber' | 'blankness' | 'other';
279
279
  /** For `equalsNumber` and `compareNumber`: the number compared against. */
280
280
  readonly number?: number;
281
281
  /** For `equalsText`: the criterion, upper-cased (matching is case-insensitive). */
@@ -442,6 +442,8 @@ declare class FormulaContext {
442
442
  * cell. Requires the worksheet to expose getSpillRange; otherwise #REF!.
443
443
  */
444
444
  resolveSpillRange(anchorRef: string): FormulaValue;
445
+ /** {@link resolveSpillRange} for an anchor on another sheet ('S'!A1#). */
446
+ resolveSheetSpillRange(sheetName: string, anchorRef: string): FormulaValue;
445
447
  getRangeBounds(startRef: string, endRef: string): {
446
448
  startRow: number;
447
449
  startCol: number;
package/dist/index.d.ts CHANGED
@@ -275,7 +275,7 @@ declare namespace FormulaHelper {
275
275
  * Everything else — comparisons, wildcards — only gets the compiled `test`.
276
276
  */
277
277
  interface CompiledCriteria {
278
- readonly kind: 'equalsNumber' | 'equalsText' | 'compareNumber' | 'other';
278
+ readonly kind: 'equalsNumber' | 'equalsText' | 'compareNumber' | 'blankness' | 'other';
279
279
  /** For `equalsNumber` and `compareNumber`: the number compared against. */
280
280
  readonly number?: number;
281
281
  /** For `equalsText`: the criterion, upper-cased (matching is case-insensitive). */
@@ -442,6 +442,8 @@ declare class FormulaContext {
442
442
  * cell. Requires the worksheet to expose getSpillRange; otherwise #REF!.
443
443
  */
444
444
  resolveSpillRange(anchorRef: string): FormulaValue;
445
+ /** {@link resolveSpillRange} for an anchor on another sheet ('S'!A1#). */
446
+ resolveSheetSpillRange(sheetName: string, anchorRef: string): FormulaValue;
445
447
  getRangeBounds(startRef: string, endRef: string): {
446
448
  startRow: number;
447
449
  startCol: number;
package/dist/index.js CHANGED
@@ -280,7 +280,7 @@ var _FormulaValue = class _FormulaValue {
280
280
  if (value2 === null || value2 === void 0) return _FormulaValue.blank;
281
281
  if (typeof value2 === "number") return isNaN(value2) ? _FormulaValue.errorValue : _FormulaValue.number(value2);
282
282
  if (typeof value2 === "boolean") return _FormulaValue.boolean(value2);
283
- if (typeof value2 === "string") return value2 === "" ? _FormulaValue.blank : _FormulaValue.text(value2);
283
+ if (typeof value2 === "string") return _FormulaValue.text(value2);
284
284
  if (value2 instanceof Date) {
285
285
  return _FormulaValue.number(toOADate(value2));
286
286
  }
@@ -1818,11 +1818,14 @@ function count(a, c) {
1818
1818
  function countA(a, c) {
1819
1819
  return FormulaValue.number(FormulaHelper.flattenArgs(a, c).filter((v) => !v.isBlank).length);
1820
1820
  }
1821
+ function isCountBlank(v) {
1822
+ return v.isBlank || v.isText && v.textValue === "";
1823
+ }
1821
1824
  function countBlank(a, c) {
1822
1825
  const v = a[0].evaluate(c);
1823
- if (!v.isArray) return FormulaValue.number(v.isBlank ? 1 : 0);
1826
+ if (!v.isArray) return FormulaValue.number(isCountBlank(v) ? 1 : 0);
1824
1827
  let n = 0;
1825
- for (const item of v.arrayVal.values()) if (item.isBlank) n++;
1828
+ for (const item of v.arrayVal.values()) if (isCountBlank(item)) n++;
1826
1829
  return FormulaValue.number(n);
1827
1830
  }
1828
1831
  function countIf(a, c) {
@@ -1830,11 +1833,12 @@ function countIf(a, c) {
1830
1833
  if (range.isError) return range;
1831
1834
  const crit = a[1].evaluate(c);
1832
1835
  if (crit.isError) return crit;
1833
- const criteria = crit.asText();
1834
- if (!range.isArray) return FormulaValue.number(FormulaHelper.matchesCriteria(range, criteria) ? 1 : 0);
1836
+ const compiled = FormulaHelper.compileCriteria(crit.asText());
1837
+ if (!range.isArray) return FormulaValue.number(compiled.test(range) ? 1 : 0);
1838
+ const countBlanks = compiled.kind === "blankness";
1835
1839
  let n = 0;
1836
1840
  for (const item of range.arrayVal.values()) {
1837
- if (!item.isBlank && FormulaHelper.matchesCriteria(item, criteria)) n++;
1841
+ if ((countBlanks || !item.isBlank) && compiled.test(item)) n++;
1838
1842
  }
1839
1843
  return FormulaValue.number(n);
1840
1844
  }
@@ -2811,6 +2815,8 @@ function registerLookup(r) {
2811
2815
  r.register("COLUMNS", columns, 1, 1);
2812
2816
  r.register("OFFSET", offset, 3, 5, true);
2813
2817
  r.register("INDIRECT", indirect, 1, 2, true);
2818
+ r.register("ANCHORARRAY", anchorArray, 1, 1);
2819
+ r.register("SINGLE", single, 1, 1);
2814
2820
  }
2815
2821
  function num2(a, c, i) {
2816
2822
  const r = FormulaHelper.evalDouble(a[i], c);
@@ -3258,6 +3264,15 @@ function offset(a, c) {
3258
3264
  cellRefFromRowCol(newRow + height - 1, newCol + width - 1)
3259
3265
  );
3260
3266
  }
3267
+ function anchorArray(a, c) {
3268
+ const arg2 = a[0];
3269
+ if (arg2 instanceof CellReferenceNode) return c.resolveSpillRange(arg2.reference);
3270
+ if (arg2 instanceof SheetCellReferenceNode) return c.resolveSheetSpillRange(arg2.sheetName, arg2.cellReference);
3271
+ return FormulaValue.errorRef;
3272
+ }
3273
+ function single(a, c) {
3274
+ return new ImplicitIntersectionNode(a[0]).evaluate(c);
3275
+ }
3261
3276
 
3262
3277
  // src/functions/statistical-functions.ts
3263
3278
  function registerStatistical(r) {
@@ -4726,6 +4741,8 @@ var FormulaHelper;
4726
4741
  const rhsVal = parseFloat(rhs);
4727
4742
  const rhsNum = isNaN(rhsVal) ? null : rhsVal;
4728
4743
  const rhsValue = rhsNum !== null ? FormulaValue.number(rhsNum) : FormulaValue.text(rhs);
4744
+ if (rhs === "" && op === "=") return { kind: "blankness", test: (v) => v.isBlank };
4745
+ if (rhs === "" && op === "<>") return { kind: "other", test: (v) => !v.isBlank };
4729
4746
  if (op === "=") {
4730
4747
  return rhsNum !== null ? numberEquality(rhsNum) : textEquality(rhs);
4731
4748
  }
@@ -4741,6 +4758,9 @@ var FormulaHelper;
4741
4758
  const pattern = wildcardToRegex(trimmed);
4742
4759
  return { kind: "other", test: (v) => pattern.test(v.asText()) };
4743
4760
  }
4761
+ if (trimmed === "") {
4762
+ return { kind: "blankness", test: (v) => v.isBlank || v.isText && v.textValue === "" };
4763
+ }
4744
4764
  const num5 = parseFloat(trimmed);
4745
4765
  return isNaN(num5) ? textEquality(trimmed) : numberEquality(num5);
4746
4766
  }
@@ -4919,6 +4939,15 @@ var _FormulaContext = class _FormulaContext {
4919
4939
  if (colon < 0) return this.getCellValue(spillRef);
4920
4940
  return this.getRangeValues(spillRef.slice(0, colon), spillRef.slice(colon + 1));
4921
4941
  }
4942
+ /** {@link resolveSpillRange} for an anchor on another sheet ('S'!A1#). */
4943
+ resolveSheetSpillRange(sheetName, anchorRef) {
4944
+ if (!this.workbook) return FormulaValue.errorRef;
4945
+ try {
4946
+ return __privateMethod(this, _FormulaContext_instances, forSheet_fn).call(this, sheetName).resolveSpillRange(anchorRef);
4947
+ } catch {
4948
+ return FormulaValue.errorRef;
4949
+ }
4950
+ }
4922
4951
  getRangeBounds(startRef, endRef) {
4923
4952
  const s = parseCellRef(startRef);
4924
4953
  const e = parseCellRef(endRef);
@@ -5537,6 +5566,7 @@ function createWorkbookRecalcModel(workbook) {
5537
5566
  };
5538
5567
  }
5539
5568
  var MAX_ADOPTED_SPILL_CELLS = 262144;
5569
+ var resultOf = (fv2) => fv2.isBlank ? 0 : fv2.toObject();
5540
5570
  var normSheet = (s) => s.toUpperCase();
5541
5571
  var normRef = (r) => r.replace(/\$/g, "").toUpperCase();
5542
5572
  var keyOf = (sheet, ref) => `${normSheet(sheet)}!${normRef(ref)}`;
@@ -6197,7 +6227,7 @@ writeResult_fn = function(e) {
6197
6227
  if (!fv2.isArray) {
6198
6228
  __privateMethod(this, _RecalcEngine_instances, clearSpill_fn).call(this, anchorKey, changed);
6199
6229
  __privateGet(this, _model).setCellArrayRef?.(e.sheetName, e.ref, null);
6200
- const value2 = fv2.toObject();
6230
+ const value2 = resultOf(fv2);
6201
6231
  __privateMethod(this, _RecalcEngine_instances, writeCell_fn).call(this, e.sheetName, e.ref, value2, e.row, e.col);
6202
6232
  changed.push({ sheet: e.sheet, row: e.row, col: e.col });
6203
6233
  return { result: { sheet: e.sheetName, ref: e.ref, value: value2 }, changed };
@@ -6228,7 +6258,7 @@ writeResult_fn = function(e) {
6228
6258
  for (let dc = 0; dc < cols; dc++) {
6229
6259
  const r = e.row + dr, c = e.col + dc;
6230
6260
  const ref = cellRefFromRowCol(r, c);
6231
- __privateMethod(this, _RecalcEngine_instances, writeCell_fn).call(this, e.sheetName, ref, arr.get(dr, dc).toObject(), r, c);
6261
+ __privateMethod(this, _RecalcEngine_instances, writeCell_fn).call(this, e.sheetName, ref, resultOf(arr.get(dr, dc)), r, c);
6232
6262
  changed.push({ sheet: e.sheet, row: r, col: c });
6233
6263
  if (dr !== 0 || dc !== 0) {
6234
6264
  const cellKey2 = keyOf(e.sheet, ref);
@@ -6248,7 +6278,7 @@ writeResult_fn = function(e) {
6248
6278
  const spillRef = `${e.ref}:${cellRefFromRowCol(e.row + rows2 - 1, e.col + cols - 1)}`;
6249
6279
  __privateGet(this, _model).setCellArrayRef?.(e.sheetName, e.ref, spillRef);
6250
6280
  return {
6251
- result: { sheet: e.sheetName, ref: e.ref, value: arr.get(0, 0).toObject(), spill: { rows: rows2, cols } },
6281
+ result: { sheet: e.sheetName, ref: e.ref, value: resultOf(arr.get(0, 0)), spill: { rows: rows2, cols } },
6252
6282
  changed
6253
6283
  };
6254
6284
  };