@devmm/puredocs-excel-formula 1.0.2 → 1.0.3

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.js CHANGED
@@ -2360,6 +2360,7 @@ function registerLookup(r) {
2360
2360
  r.register("LOOKUP", lookup, 2, 3);
2361
2361
  r.register("INDEX", index_, 2, 3);
2362
2362
  r.register("MATCH", match, 2, 3);
2363
+ r.register("XMATCH", xmatch, 2, 4);
2363
2364
  r.register("CHOOSE", choose, 2);
2364
2365
  r.register("ADDRESS", address, 2, 5);
2365
2366
  r.register("ROW", row, 0, 1);
@@ -2531,6 +2532,23 @@ function xlookup(a, c) {
2531
2532
  for (let r = 0; r < ret.rows; r++) out.set(r, 0, ret.get(r, idx));
2532
2533
  return FormulaValue.array(out);
2533
2534
  }
2535
+ function xmatch(a, c) {
2536
+ const lookupVal = a[0].evaluate(c);
2537
+ if (lookupVal.isError) return lookupVal;
2538
+ const lookupRaw = a[1].evaluate(c);
2539
+ if (lookupRaw.isError) return lookupRaw;
2540
+ const matchMode = a.length > 2 ? num2(a, c, 2) : { ok: true, n: 0 };
2541
+ if (!matchMode.ok) return matchMode.e;
2542
+ const searchMode = a.length > 3 ? num2(a, c, 3) : { ok: true, n: 1 };
2543
+ if (!searchMode.ok) return searchMode.e;
2544
+ const la = lookupRaw.isArray ? lookupRaw.arrayVal : ArrayValue.fromScalar(lookupRaw);
2545
+ if (la.rows > 1 && la.columns > 1) return FormulaValue.errorValue;
2546
+ const vertical = !(la.rows === 1 && la.columns > 1);
2547
+ const n = vertical ? la.rows : la.columns;
2548
+ const get = vertical ? (i) => la.get(i, 0) : (i) => la.get(0, i);
2549
+ const idx = findMatch(n, get, lookupVal, Math.trunc(matchMode.n), Math.trunc(searchMode.n));
2550
+ return idx < 0 ? FormulaValue.errorNA : FormulaValue.number(idx + 1);
2551
+ }
2534
2552
  function index_(a, c) {
2535
2553
  const arrVal = a[0].evaluate(c);
2536
2554
  if (arrVal.isError) return arrVal;
@@ -3068,6 +3086,20 @@ function registerFinance(r) {
3068
3086
  r.register("NPER", nper, 3, 5);
3069
3087
  r.register("XNPV", xnpv, 3, 3);
3070
3088
  r.register("XIRR", xirr, 2, 3);
3089
+ r.register("IPMT", ipmt, 4, 6);
3090
+ r.register("PPMT", ppmt, 4, 6);
3091
+ }
3092
+ function pmtValue(r, n, pv2, fv2, type) {
3093
+ if (r === 0) return -(pv2 + fv2) / n;
3094
+ const pow = Math.pow(1 + r, n);
3095
+ let payment = (-fv2 - pv2 * pow) * r / (pow - 1);
3096
+ if (type === 1) payment /= 1 + r;
3097
+ return payment;
3098
+ }
3099
+ function fvValue(r, n, pmt2, pv2, type) {
3100
+ if (r === 0) return -(pv2 + pmt2 * n);
3101
+ const pow = Math.pow(1 + r, n);
3102
+ return -(pv2 * pow + pmt2 * (1 + r * type) * (pow - 1) / r);
3071
3103
  }
3072
3104
  function arg(a, c, idx, dflt) {
3073
3105
  if (idx >= a.length) return { ok: true, n: dflt };
@@ -3087,11 +3119,7 @@ function pmt(a, c) {
3087
3119
  if (!type.ok) return type.e;
3088
3120
  const r = rate2.n, n = nper2.n, present = pvv.n, future = fvv.n, t = type.n;
3089
3121
  if (n === 0) return FormulaValue.errorNum;
3090
- if (r === 0) return FormulaValue.number(-(present + future) / n);
3091
- const pow = Math.pow(1 + r, n);
3092
- let payment = (-future - present * pow) * r / (pow - 1);
3093
- if (t === 1) payment /= 1 + r;
3094
- return FormulaValue.number(payment);
3122
+ return FormulaValue.number(pmtValue(r, n, present, future, t));
3095
3123
  }
3096
3124
  function fv(a, c) {
3097
3125
  const rate2 = arg(a, c, 0, 0);
@@ -3105,9 +3133,7 @@ function fv(a, c) {
3105
3133
  const type = arg(a, c, 4, 0);
3106
3134
  if (!type.ok) return type.e;
3107
3135
  const r = rate2.n, n = nper2.n, payment = pmtv.n, present = pvv.n, t = type.n;
3108
- if (r === 0) return FormulaValue.number(-(present + payment * n));
3109
- const pow = Math.pow(1 + r, n);
3110
- return FormulaValue.number(-(present * pow + payment * (1 + r * t) * (pow - 1) / r));
3136
+ return FormulaValue.number(fvValue(r, n, payment, present, t));
3111
3137
  }
3112
3138
  function pv(a, c) {
3113
3139
  const rate2 = arg(a, c, 0, 0);
@@ -3233,6 +3259,49 @@ function nper(a, c) {
3233
3259
  if (!isFinite(result)) return FormulaValue.errorNum;
3234
3260
  return FormulaValue.number(result);
3235
3261
  }
3262
+ function interestForPeriod(r, per, n, pv2, fv2, t) {
3263
+ const pay = pmtValue(r, n, pv2, fv2, t);
3264
+ if (t === 1) {
3265
+ if (per === 1) return 0;
3266
+ return fvValue(r, per - 2, pay, pv2, 1) * r / (1 + r);
3267
+ }
3268
+ return fvValue(r, per - 1, pay, pv2, 0) * r;
3269
+ }
3270
+ function ipmt(a, c) {
3271
+ const rate2 = arg(a, c, 0, 0);
3272
+ if (!rate2.ok) return rate2.e;
3273
+ const perv = arg(a, c, 1, 0);
3274
+ if (!perv.ok) return perv.e;
3275
+ const nper2 = arg(a, c, 2, 0);
3276
+ if (!nper2.ok) return nper2.e;
3277
+ const pvv = arg(a, c, 3, 0);
3278
+ if (!pvv.ok) return pvv.e;
3279
+ const fvv = arg(a, c, 4, 0);
3280
+ if (!fvv.ok) return fvv.e;
3281
+ const type = arg(a, c, 5, 0);
3282
+ if (!type.ok) return type.e;
3283
+ const r = rate2.n, per = perv.n, n = nper2.n, pv2 = pvv.n, fv2 = fvv.n, t = type.n;
3284
+ if (n === 0 || per < 1 || per > n) return FormulaValue.errorNum;
3285
+ return FormulaValue.number(interestForPeriod(r, per, n, pv2, fv2, t));
3286
+ }
3287
+ function ppmt(a, c) {
3288
+ const rate2 = arg(a, c, 0, 0);
3289
+ if (!rate2.ok) return rate2.e;
3290
+ const perv = arg(a, c, 1, 0);
3291
+ if (!perv.ok) return perv.e;
3292
+ const nper2 = arg(a, c, 2, 0);
3293
+ if (!nper2.ok) return nper2.e;
3294
+ const pvv = arg(a, c, 3, 0);
3295
+ if (!pvv.ok) return pvv.e;
3296
+ const fvv = arg(a, c, 4, 0);
3297
+ if (!fvv.ok) return fvv.e;
3298
+ const type = arg(a, c, 5, 0);
3299
+ if (!type.ok) return type.e;
3300
+ const r = rate2.n, per = perv.n, n = nper2.n, pv2 = pvv.n, fv2 = fvv.n, t = type.n;
3301
+ if (n === 0 || per < 1 || per > n) return FormulaValue.errorNum;
3302
+ const pay = pmtValue(r, n, pv2, fv2, t);
3303
+ return FormulaValue.number(pay - interestForPeriod(r, per, n, pv2, fv2, t));
3304
+ }
3236
3305
  function flatNumbers(node, c) {
3237
3306
  const v = node.evaluate(c);
3238
3307
  if (v.isError) return { ok: false, e: v };
@@ -3660,7 +3729,13 @@ function registerArray(r) {
3660
3729
  r.register("FILTER", filter, 2, 3);
3661
3730
  r.register("MMULT", mmult, 2, 2);
3662
3731
  r.register("TEXTSPLIT", textSplit, 2, 6);
3732
+ r.register("VSTACK", vstack, 1);
3733
+ r.register("HSTACK", hstack, 1);
3734
+ r.register("TOCOL", toCol, 1, 3);
3735
+ r.register("TOROW", toRow, 1, 3);
3663
3736
  }
3737
+ var MAX_ROWS = 1048576;
3738
+ var MAX_COLS = 16384;
3664
3739
  var asArray2 = (v) => v.isArray ? v.arrayVal : ArrayValue.fromScalar(v);
3665
3740
  function fromRows(rows2) {
3666
3741
  const nr = rows2.length;
@@ -3707,26 +3782,53 @@ function sequence(a, c) {
3707
3782
  }
3708
3783
  return FormulaValue.array(arr);
3709
3784
  }
3710
- function rowsEqual(x, y) {
3711
- if (x.length !== y.length) return false;
3712
- for (let i = 0; i < x.length; i++) if (!FormulaValue.areEqual(x[i], y[i])) return false;
3713
- return true;
3785
+ function cellKey(v) {
3786
+ switch (v.kind) {
3787
+ case "number":
3788
+ return "n" + (v.numberValue === 0 ? "0" : String(v.numberValue));
3789
+ case "text":
3790
+ return "t" + v.textValue.toUpperCase();
3791
+ // case-insensitive
3792
+ case "boolean":
3793
+ return v.booleanValue ? "b1" : "b0";
3794
+ case "blank":
3795
+ return "B";
3796
+ case "error":
3797
+ return "e" + v.errorCode;
3798
+ default:
3799
+ return "x";
3800
+ }
3714
3801
  }
3715
3802
  function unique(a, c) {
3716
3803
  const v = a[0].evaluate(c);
3717
3804
  if (v.isError) return v;
3718
3805
  const byCol2 = a.length > 1 ? a[1].evaluate(c).coerceToBool().booleanValue : false;
3719
3806
  const exactlyOnce = a.length > 2 ? a[2].evaluate(c).coerceToBool().booleanValue : false;
3720
- let rows2 = toRows(byCol2 ? asArray2(v).transpose() : asArray2(v));
3721
- const counts = rows2.map((r) => rows2.filter((o) => rowsEqual(o, r)).length);
3722
- const seen = [];
3807
+ const base = byCol2 ? asArray2(v).transpose() : asArray2(v);
3808
+ const map = /* @__PURE__ */ new Map();
3809
+ const order = [];
3810
+ for (let r = 0; r < base.rows; r++) {
3811
+ const cells = new Array(base.columns);
3812
+ let key = "";
3813
+ for (let col = 0; col < base.columns; col++) {
3814
+ const cell = base.get(r, col);
3815
+ cells[col] = cell;
3816
+ const k = cellKey(cell);
3817
+ key += k.length + ":" + k;
3818
+ }
3819
+ const hit = map.get(key);
3820
+ if (hit) hit.count++;
3821
+ else {
3822
+ map.set(key, { cells, count: 1 });
3823
+ order.push(key);
3824
+ }
3825
+ }
3723
3826
  const result = [];
3724
- rows2.forEach((r, i) => {
3725
- if (seen.some((o) => rowsEqual(o, r))) return;
3726
- seen.push(r);
3727
- if (exactlyOnce && counts[i] > 1) return;
3728
- result.push(r);
3729
- });
3827
+ for (const key of order) {
3828
+ const e = map.get(key);
3829
+ if (exactlyOnce && e.count > 1) continue;
3830
+ result.push(e.cells);
3831
+ }
3730
3832
  if (result.length === 0) return FormulaValue.error(8 /* Calc */);
3731
3833
  const out = fromRows(result);
3732
3834
  return byCol2 ? FormulaValue.array(out.arrayVal.transpose()) : out;
@@ -3884,6 +3986,89 @@ function textSplit(a, c) {
3884
3986
  });
3885
3987
  return fromRows(rows2);
3886
3988
  }
3989
+ function vstack(a, c) {
3990
+ const parts = [];
3991
+ let totalRows = 0, maxCols = 0;
3992
+ for (const node of a) {
3993
+ const arr = asArray2(node.evaluate(c));
3994
+ parts.push(arr);
3995
+ totalRows += arr.rows;
3996
+ if (arr.columns > maxCols) maxCols = arr.columns;
3997
+ }
3998
+ if (totalRows > MAX_ROWS || maxCols > MAX_COLS) return FormulaValue.errorNum;
3999
+ const out = new ArrayValue(totalRows, maxCols);
4000
+ let rowOff = 0;
4001
+ for (const arr of parts) {
4002
+ for (let r = 0; r < arr.rows; r++) {
4003
+ for (let col = 0; col < maxCols; col++) {
4004
+ out.set(rowOff + r, col, col < arr.columns ? arr.get(r, col) : FormulaValue.errorNA);
4005
+ }
4006
+ }
4007
+ rowOff += arr.rows;
4008
+ }
4009
+ return FormulaValue.array(out);
4010
+ }
4011
+ function hstack(a, c) {
4012
+ const parts = [];
4013
+ let totalCols = 0, maxRows = 0;
4014
+ for (const node of a) {
4015
+ const arr = asArray2(node.evaluate(c));
4016
+ parts.push(arr);
4017
+ totalCols += arr.columns;
4018
+ if (arr.rows > maxRows) maxRows = arr.rows;
4019
+ }
4020
+ if (maxRows > MAX_ROWS || totalCols > MAX_COLS) return FormulaValue.errorNum;
4021
+ const out = new ArrayValue(maxRows, totalCols);
4022
+ let colOff = 0;
4023
+ for (const arr of parts) {
4024
+ for (let col = 0; col < arr.columns; col++) {
4025
+ for (let r = 0; r < maxRows; r++) {
4026
+ out.set(r, colOff + col, r < arr.rows ? arr.get(r, col) : FormulaValue.errorNA);
4027
+ }
4028
+ }
4029
+ colOff += arr.columns;
4030
+ }
4031
+ return FormulaValue.array(out);
4032
+ }
4033
+ function flatten(a, c) {
4034
+ const arr = asArray2(a[0].evaluate(c));
4035
+ const ig = num4(a, c, 1, 0);
4036
+ if (!ig.ok) return { ok: false, e: ig.e };
4037
+ const ignore = Math.trunc(ig.n);
4038
+ const byCol2 = a.length > 2 ? a[2].evaluate(c).coerceToBool().booleanValue : false;
4039
+ const skip = (x) => (ignore & 1) !== 0 && x.isBlank || (ignore & 2) !== 0 && x.isError;
4040
+ const values = [];
4041
+ if (byCol2) {
4042
+ for (let col = 0; col < arr.columns; col++)
4043
+ for (let r = 0; r < arr.rows; r++) {
4044
+ const x = arr.get(r, col);
4045
+ if (!skip(x)) values.push(x);
4046
+ }
4047
+ } else {
4048
+ for (let r = 0; r < arr.rows; r++)
4049
+ for (let col = 0; col < arr.columns; col++) {
4050
+ const x = arr.get(r, col);
4051
+ if (!skip(x)) values.push(x);
4052
+ }
4053
+ }
4054
+ return { ok: true, values };
4055
+ }
4056
+ function toCol(a, c) {
4057
+ const f = flatten(a, c);
4058
+ if (!f.ok) return f.e;
4059
+ if (f.values.length === 0) return FormulaValue.errorNA;
4060
+ const out = new ArrayValue(f.values.length, 1);
4061
+ for (let i = 0; i < f.values.length; i++) out.set(i, 0, f.values[i]);
4062
+ return FormulaValue.array(out);
4063
+ }
4064
+ function toRow(a, c) {
4065
+ const f = flatten(a, c);
4066
+ if (!f.ok) return f.e;
4067
+ if (f.values.length === 0) return FormulaValue.errorNA;
4068
+ const out = new ArrayValue(1, f.values.length);
4069
+ for (let i = 0; i < f.values.length; i++) out.set(0, i, f.values[i]);
4070
+ return FormulaValue.array(out);
4071
+ }
3887
4072
 
3888
4073
  // src/function-registry.ts
3889
4074
  var _default, _functions, _FunctionRegistry_instances, registerBuiltIns_fn;
@@ -4686,8 +4871,8 @@ writeResult_fn = function(e) {
4686
4871
  for (let dc = 0; dc < cols && !collides; dc++) {
4687
4872
  if (dr === 0 && dc === 0) continue;
4688
4873
  const r = e.row + dr, c = e.col + dc;
4689
- const cellKey = keyOf(e.sheet, cellRefFromRowCol(r, c));
4690
- if (__privateMethod(this, _RecalcEngine_instances, isOccupied_fn).call(this, cellKey, e.sheetName, cellRefFromRowCol(r, c), anchorKey, prevSpill)) {
4874
+ const cellKey2 = keyOf(e.sheet, cellRefFromRowCol(r, c));
4875
+ if (__privateMethod(this, _RecalcEngine_instances, isOccupied_fn).call(this, cellKey2, e.sheetName, cellRefFromRowCol(r, c), anchorKey, prevSpill)) {
4691
4876
  collides = true;
4692
4877
  }
4693
4878
  }
@@ -4708,9 +4893,9 @@ writeResult_fn = function(e) {
4708
4893
  __privateGet(this, _model).setCellValue(e.sheetName, ref, arr.get(dr, dc).toObject());
4709
4894
  changed.push({ sheet: e.sheet, row: r, col: c });
4710
4895
  if (dr !== 0 || dc !== 0) {
4711
- const cellKey = keyOf(e.sheet, ref);
4712
- newSpill.add(cellKey);
4713
- __privateGet(this, _spillOwner).set(cellKey, anchorKey);
4896
+ const cellKey2 = keyOf(e.sheet, ref);
4897
+ newSpill.add(cellKey2);
4898
+ __privateGet(this, _spillOwner).set(cellKey2, anchorKey);
4714
4899
  }
4715
4900
  }
4716
4901
  }
@@ -4730,11 +4915,11 @@ writeResult_fn = function(e) {
4730
4915
  };
4731
4916
  };
4732
4917
  /** Whether a target cell already holds content that blocks a spill. */
4733
- isOccupied_fn = function(cellKey, sheetName, ref, anchorKey, prevSpill) {
4734
- if (__privateGet(this, _formulas).has(cellKey) && cellKey !== anchorKey) return true;
4735
- const owner = __privateGet(this, _spillOwner).get(cellKey);
4918
+ isOccupied_fn = function(cellKey2, sheetName, ref, anchorKey, prevSpill) {
4919
+ if (__privateGet(this, _formulas).has(cellKey2) && cellKey2 !== anchorKey) return true;
4920
+ const owner = __privateGet(this, _spillOwner).get(cellKey2);
4736
4921
  if (owner && owner !== anchorKey) return true;
4737
- if (prevSpill.has(cellKey)) return false;
4922
+ if (prevSpill.has(cellKey2)) return false;
4738
4923
  const v = __privateGet(this, _model).getCellValue(sheetName, ref);
4739
4924
  return v !== null && v !== void 0 && v !== "";
4740
4925
  };
@@ -4742,10 +4927,10 @@ isOccupied_fn = function(cellKey, sheetName, ref, anchorKey, prevSpill) {
4742
4927
  clearSpill_fn = function(anchorKey, changed) {
4743
4928
  const spill = __privateGet(this, _spills).get(anchorKey);
4744
4929
  if (!spill) return;
4745
- for (const cellKey of spill) {
4746
- const cell = parseKey(cellKey);
4930
+ for (const cellKey2 of spill) {
4931
+ const cell = parseKey(cellKey2);
4747
4932
  __privateGet(this, _model).setCellValue(__privateGet(this, _sheetNames).get(cell.sheet) ?? cell.sheet, cell.ref, null);
4748
- __privateGet(this, _spillOwner).delete(cellKey);
4933
+ __privateGet(this, _spillOwner).delete(cellKey2);
4749
4934
  changed.push({ sheet: cell.sheet, row: cell.row, col: cell.col });
4750
4935
  }
4751
4936
  __privateGet(this, _spills).delete(anchorKey);