@rowsncolumns/functions 14.0.29

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 (149) hide show
  1. package/LICENSE.md +100 -0
  2. package/Readme.md +5 -0
  3. package/dist/cjs/formulas/array-formula.d.ts +4 -0
  4. package/dist/cjs/formulas/array-formula.d.ts.map +1 -0
  5. package/dist/cjs/formulas/array-formula.js +7 -0
  6. package/dist/cjs/formulas/crypto-price.d.ts +4 -0
  7. package/dist/cjs/formulas/crypto-price.d.ts.map +1 -0
  8. package/dist/cjs/formulas/crypto-price.js +63 -0
  9. package/dist/cjs/formulas/datasource.d.ts +4 -0
  10. package/dist/cjs/formulas/datasource.d.ts.map +1 -0
  11. package/dist/cjs/formulas/datasource.js +21 -0
  12. package/dist/cjs/formulas/formula-text.d.ts +5 -0
  13. package/dist/cjs/formulas/formula-text.d.ts.map +1 -0
  14. package/dist/cjs/formulas/formula-text.js +17 -0
  15. package/dist/cjs/formulas/get-pivot-data.d.ts +32 -0
  16. package/dist/cjs/formulas/get-pivot-data.d.ts.map +1 -0
  17. package/dist/cjs/formulas/get-pivot-data.js +188 -0
  18. package/dist/cjs/formulas/hyperlink.d.ts +5 -0
  19. package/dist/cjs/formulas/hyperlink.d.ts.map +1 -0
  20. package/dist/cjs/formulas/hyperlink.js +22 -0
  21. package/dist/cjs/formulas/image.d.ts +5 -0
  22. package/dist/cjs/formulas/image.d.ts.map +1 -0
  23. package/dist/cjs/formulas/image.js +17 -0
  24. package/dist/cjs/formulas/import-data.d.ts +11 -0
  25. package/dist/cjs/formulas/import-data.d.ts.map +1 -0
  26. package/dist/cjs/formulas/import-data.js +46 -0
  27. package/dist/cjs/formulas/index.d.ts +18 -0
  28. package/dist/cjs/formulas/index.d.ts.map +1 -0
  29. package/dist/cjs/formulas/index.js +37 -0
  30. package/dist/cjs/formulas/join.d.ts +4 -0
  31. package/dist/cjs/formulas/join.d.ts.map +1 -0
  32. package/dist/cjs/formulas/join.js +34 -0
  33. package/dist/cjs/formulas/multiply.d.ts +4 -0
  34. package/dist/cjs/formulas/multiply.d.ts.map +1 -0
  35. package/dist/cjs/formulas/multiply.js +15 -0
  36. package/dist/cjs/formulas/real-time.d.ts +4 -0
  37. package/dist/cjs/formulas/real-time.d.ts.map +1 -0
  38. package/dist/cjs/formulas/real-time.js +18 -0
  39. package/dist/cjs/formulas/selection-status.d.ts +4 -0
  40. package/dist/cjs/formulas/selection-status.d.ts.map +1 -0
  41. package/dist/cjs/formulas/selection-status.js +65 -0
  42. package/dist/cjs/formulas/sequence.d.ts +5 -0
  43. package/dist/cjs/formulas/sequence.d.ts.map +1 -0
  44. package/dist/cjs/formulas/sequence.js +29 -0
  45. package/dist/cjs/formulas/server.d.ts +22 -0
  46. package/dist/cjs/formulas/server.d.ts.map +1 -0
  47. package/dist/cjs/formulas/server.js +44 -0
  48. package/dist/cjs/formulas/sparkline.d.ts +5 -0
  49. package/dist/cjs/formulas/sparkline.d.ts.map +1 -0
  50. package/dist/cjs/formulas/sparkline.js +58 -0
  51. package/dist/cjs/formulas/split.d.ts +12 -0
  52. package/dist/cjs/formulas/split.d.ts.map +1 -0
  53. package/dist/cjs/formulas/split.js +48 -0
  54. package/dist/cjs/formulas/star-rating.d.ts +5 -0
  55. package/dist/cjs/formulas/star-rating.d.ts.map +1 -0
  56. package/dist/cjs/formulas/star-rating.js +13 -0
  57. package/dist/cjs/formulas/unique.d.ts +12 -0
  58. package/dist/cjs/formulas/unique.d.ts.map +1 -0
  59. package/dist/cjs/formulas/unique.js +78 -0
  60. package/dist/cjs/function-descriptions.d.ts +3 -0
  61. package/dist/cjs/function-descriptions.d.ts.map +1 -0
  62. package/dist/cjs/function-descriptions.js +8724 -0
  63. package/dist/cjs/index.d.ts +4 -0
  64. package/dist/cjs/index.d.ts.map +1 -0
  65. package/dist/cjs/index.js +7 -0
  66. package/dist/cjs/server.d.ts +4 -0
  67. package/dist/cjs/server.d.ts.map +1 -0
  68. package/dist/cjs/server.js +8 -0
  69. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -0
  70. package/dist/cjs/types.d.ts +2 -0
  71. package/dist/cjs/types.d.ts.map +1 -0
  72. package/dist/cjs/types.js +2 -0
  73. package/dist/cjs/vitest.config.d.ts +3 -0
  74. package/dist/cjs/vitest.config.d.ts.map +1 -0
  75. package/dist/cjs/vitest.config.js +18 -0
  76. package/dist/esm/formulas/array-formula.d.ts +4 -0
  77. package/dist/esm/formulas/array-formula.d.ts.map +1 -0
  78. package/dist/esm/formulas/array-formula.js +3 -0
  79. package/dist/esm/formulas/crypto-price.d.ts +4 -0
  80. package/dist/esm/formulas/crypto-price.d.ts.map +1 -0
  81. package/dist/esm/formulas/crypto-price.js +33 -0
  82. package/dist/esm/formulas/datasource.d.ts +4 -0
  83. package/dist/esm/formulas/datasource.d.ts.map +1 -0
  84. package/dist/esm/formulas/datasource.js +17 -0
  85. package/dist/esm/formulas/formula-text.d.ts +5 -0
  86. package/dist/esm/formulas/formula-text.d.ts.map +1 -0
  87. package/dist/esm/formulas/formula-text.js +12 -0
  88. package/dist/esm/formulas/get-pivot-data.d.ts +32 -0
  89. package/dist/esm/formulas/get-pivot-data.d.ts.map +1 -0
  90. package/dist/esm/formulas/get-pivot-data.js +144 -0
  91. package/dist/esm/formulas/hyperlink.d.ts +5 -0
  92. package/dist/esm/formulas/hyperlink.d.ts.map +1 -0
  93. package/dist/esm/formulas/hyperlink.js +17 -0
  94. package/dist/esm/formulas/image.d.ts +5 -0
  95. package/dist/esm/formulas/image.d.ts.map +1 -0
  96. package/dist/esm/formulas/image.js +13 -0
  97. package/dist/esm/formulas/import-data.d.ts +11 -0
  98. package/dist/esm/formulas/import-data.d.ts.map +1 -0
  99. package/dist/esm/formulas/import-data.js +28 -0
  100. package/dist/esm/formulas/index.d.ts +18 -0
  101. package/dist/esm/formulas/index.d.ts.map +1 -0
  102. package/dist/esm/formulas/index.js +17 -0
  103. package/dist/esm/formulas/join.d.ts +4 -0
  104. package/dist/esm/formulas/join.d.ts.map +1 -0
  105. package/dist/esm/formulas/join.js +25 -0
  106. package/dist/esm/formulas/multiply.d.ts +4 -0
  107. package/dist/esm/formulas/multiply.d.ts.map +1 -0
  108. package/dist/esm/formulas/multiply.js +11 -0
  109. package/dist/esm/formulas/real-time.d.ts +4 -0
  110. package/dist/esm/formulas/real-time.d.ts.map +1 -0
  111. package/dist/esm/formulas/real-time.js +14 -0
  112. package/dist/esm/formulas/selection-status.d.ts +4 -0
  113. package/dist/esm/formulas/selection-status.d.ts.map +1 -0
  114. package/dist/esm/formulas/selection-status.js +39 -0
  115. package/dist/esm/formulas/sequence.d.ts +5 -0
  116. package/dist/esm/formulas/sequence.d.ts.map +1 -0
  117. package/dist/esm/formulas/sequence.js +24 -0
  118. package/dist/esm/formulas/server.d.ts +22 -0
  119. package/dist/esm/formulas/server.d.ts.map +1 -0
  120. package/dist/esm/formulas/server.js +37 -0
  121. package/dist/esm/formulas/sparkline.d.ts +5 -0
  122. package/dist/esm/formulas/sparkline.d.ts.map +1 -0
  123. package/dist/esm/formulas/sparkline.js +52 -0
  124. package/dist/esm/formulas/split.d.ts +12 -0
  125. package/dist/esm/formulas/split.d.ts.map +1 -0
  126. package/dist/esm/formulas/split.js +44 -0
  127. package/dist/esm/formulas/star-rating.d.ts +5 -0
  128. package/dist/esm/formulas/star-rating.d.ts.map +1 -0
  129. package/dist/esm/formulas/star-rating.js +9 -0
  130. package/dist/esm/formulas/unique.d.ts +12 -0
  131. package/dist/esm/formulas/unique.d.ts.map +1 -0
  132. package/dist/esm/formulas/unique.js +58 -0
  133. package/dist/esm/function-descriptions.d.ts +3 -0
  134. package/dist/esm/function-descriptions.d.ts.map +1 -0
  135. package/dist/esm/function-descriptions.js +8721 -0
  136. package/dist/esm/index.d.ts +4 -0
  137. package/dist/esm/index.d.ts.map +1 -0
  138. package/dist/esm/index.js +3 -0
  139. package/dist/esm/server.d.ts +4 -0
  140. package/dist/esm/server.d.ts.map +1 -0
  141. package/dist/esm/server.js +3 -0
  142. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -0
  143. package/dist/esm/types.d.ts +2 -0
  144. package/dist/esm/types.d.ts.map +1 -0
  145. package/dist/esm/types.js +1 -0
  146. package/dist/esm/vitest.config.d.ts +3 -0
  147. package/dist/esm/vitest.config.d.ts.map +1 -0
  148. package/dist/esm/vitest.config.js +15 -0
  149. package/package.json +51 -0
@@ -0,0 +1,4 @@
1
+ export * from "./function-descriptions";
2
+ export * from "./types";
3
+ export * as functions from "./formulas/index";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,SAAS,CAAC;AACxB,OAAO,KAAK,SAAS,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.functions = void 0;
4
+ var tslib_1 = require("tslib");
5
+ tslib_1.__exportStar(require("./function-descriptions"), exports);
6
+ tslib_1.__exportStar(require("./types"), exports);
7
+ exports.functions = tslib_1.__importStar(require("./formulas/index"));
@@ -0,0 +1,4 @@
1
+ export * from "./function-descriptions";
2
+ export * from "./types";
3
+ export { functions } from "./formulas/server";
4
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../server.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.functions = void 0;
4
+ var tslib_1 = require("tslib");
5
+ tslib_1.__exportStar(require("./function-descriptions"), exports);
6
+ tslib_1.__exportStar(require("./types"), exports);
7
+ var server_1 = require("./formulas/server");
8
+ Object.defineProperty(exports, "functions", { enumerable: true, get: function () { return server_1.functions; } });
@@ -0,0 +1 @@
1
+ {"root":["../../function-descriptions.ts","../../index.ts","../../server.ts","../../types.ts","../../vitest.config.ts","../../formulas/array-formula.ts","../../formulas/crypto-price.ts","../../formulas/datasource.ts","../../formulas/formula-text.ts","../../formulas/get-pivot-data.ts","../../formulas/hyperlink.ts","../../formulas/image.ts","../../formulas/import-data.ts","../../formulas/index.ts","../../formulas/join.ts","../../formulas/multiply.ts","../../formulas/real-time.ts","../../formulas/selection-status.ts","../../formulas/sequence.ts","../../formulas/server.ts","../../formulas/sparkline.ts","../../formulas/split.ts","../../formulas/star-rating.ts","../../formulas/unique.ts"],"version":"5.8.3"}
@@ -0,0 +1,2 @@
1
+ export type { CalculatorFunction, FunctionParameter, } from "@rowsncolumns/common-types";
2
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../types.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,4BAA4B,CAAC"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,3 @@
1
+ declare const _default: import("vite").UserConfig;
2
+ export default _default;
3
+ //# sourceMappingURL=vitest.config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vitest.config.d.ts","sourceRoot":"","sources":["../../vitest.config.ts"],"names":[],"mappings":";AAGA,wBAeG"}
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ var tslib_1 = require("tslib");
4
+ var node_path_1 = tslib_1.__importDefault(require("node:path"));
5
+ var config_1 = require("vitest/config");
6
+ exports.default = (0, config_1.defineConfig)({
7
+ test: {
8
+ globals: true,
9
+ environment: "node",
10
+ },
11
+ resolve: {
12
+ alias: {
13
+ // Resolve the workspace sibling from source so the catalog guard test
14
+ // checks the current tree, not a previously built dist.
15
+ "@rowsncolumns/fast-formula-parser": node_path_1.default.resolve(__dirname, "../fast-formula-parser/index.js"),
16
+ },
17
+ },
18
+ });
@@ -0,0 +1,4 @@
1
+ import type { FunctionArgument } from "@rowsncolumns/calculator";
2
+ import type FormulaParser from "@rowsncolumns/fast-formula-parser";
3
+ export declare const ARRAYFORMULA: (_: FormulaParser, arg: FunctionArgument) => import("@rowsncolumns/fast-formula-parser").FormulaResult;
4
+ //# sourceMappingURL=array-formula.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"array-formula.d.ts","sourceRoot":"","sources":["../../../formulas/array-formula.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,aAAa,MAAM,mCAAmC,CAAC;AAEnE,eAAO,MAAM,YAAY,GAAI,GAAG,aAAa,EAAE,KAAK,gBAAgB,8DAEnE,CAAC"}
@@ -0,0 +1,3 @@
1
+ export const ARRAYFORMULA = (_, arg) => {
2
+ return arg.value;
3
+ };
@@ -0,0 +1,4 @@
1
+ import { FunctionArgument } from "@rowsncolumns/calculator";
2
+ import type FormulaParser from "@rowsncolumns/fast-formula-parser";
3
+ export declare const CRYPTOPRICE: (parser: FormulaParser, arg: FunctionArgument) => Promise<number[][]>;
4
+ //# sourceMappingURL=crypto-price.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto-price.d.ts","sourceRoot":"","sources":["../../../formulas/crypto-price.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAEjB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,aAAa,MAAM,mCAAmC,CAAC;AAGnE,eAAO,MAAM,WAAW,GACtB,QAAQ,aAAa,EACrB,KAAK,gBAAgB,wBAoCtB,CAAC"}
@@ -0,0 +1,33 @@
1
+ import { calculationPipeline, } from "@rowsncolumns/calculator";
2
+ import { FormulaError } from "@rowsncolumns/fast-formula-parser";
3
+ export const CRYPTOPRICE = async (parser, arg) => {
4
+ if (!arg || !arg.value || arg.value instanceof FormulaError) {
5
+ throw new FormulaError("#VALUE!", "Symbol pair is required");
6
+ }
7
+ const fetchPrices = async () => {
8
+ try {
9
+ const results = await fetch(`https://api.gemini.com/v2/ticker/${String(arg.value).toLowerCase()}`, {
10
+ method: "GET",
11
+ });
12
+ const values = await results.json();
13
+ return [[Number(values.ask), Number(values.bid)]];
14
+ }
15
+ catch (err) {
16
+ throw new FormulaError("#NULL!", String(err));
17
+ }
18
+ };
19
+ calculationPipeline(parser, (onUpdate) => {
20
+ let timeout = setInterval(async () => {
21
+ const values = await fetchPrices();
22
+ if (values !== undefined) {
23
+ onUpdate(values);
24
+ }
25
+ }, 5000);
26
+ console.log("Sub", timeout);
27
+ return () => {
28
+ console.log("Unsub", timeout);
29
+ clearInterval(timeout);
30
+ };
31
+ });
32
+ return await fetchPrices();
33
+ };
@@ -0,0 +1,4 @@
1
+ import { FunctionArgument, DataSource } from "@rowsncolumns/calculator";
2
+ import FormulaParser from "@rowsncolumns/fast-formula-parser";
3
+ export declare const DATASOURCE: (parser: FormulaParser, data: FunctionArgument, limit: FunctionArgument) => DataSource | undefined;
4
+ //# sourceMappingURL=datasource.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"datasource.d.ts","sourceRoot":"","sources":["../../../formulas/datasource.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,aAA+B,MAAM,mCAAmC,CAAC;AAGhF,eAAO,MAAM,UAAU,GACrB,QAAQ,aAAa,EACrB,MAAM,gBAAgB,EACtB,OAAO,gBAAgB,KACtB,UAAU,GAAG,SAsBf,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { DataSource } from "@rowsncolumns/calculator";
2
+ import { FormulaError } from "@rowsncolumns/fast-formula-parser";
3
+ import { isNil, isNumber } from "@rowsncolumns/utils";
4
+ export const DATASOURCE = (parser, data, limit) => {
5
+ if (parser.isPreview) {
6
+ return undefined;
7
+ }
8
+ if (!data.value || !Array.isArray(data.value)) {
9
+ // throw new FormulaError("#NA!", "Invalid data");
10
+ }
11
+ if (limit && !isNumber(limit.value)) {
12
+ throw new FormulaError("#NA!", "Limit should be a number");
13
+ }
14
+ const rowCount = isNil(limit?.value) ? undefined : Number(limit.value);
15
+ const datasource = new DataSource(parser, parser.position, data.value, rowCount);
16
+ return datasource;
17
+ };
@@ -0,0 +1,5 @@
1
+ import type { FunctionArgument } from "@rowsncolumns/calculator";
2
+ import type FormulaParser from "@rowsncolumns/fast-formula-parser";
3
+ import type { CellData } from "@rowsncolumns/common-types";
4
+ export declare const FORMULATEXT: (parser: FormulaParser<CellData>, arg: FunctionArgument) => string;
5
+ //# sourceMappingURL=formula-text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formula-text.d.ts","sourceRoot":"","sources":["../../../formulas/formula-text.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,aAAa,MAAM,mCAAmC,CAAC;AAEnE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAE3D,eAAO,MAAM,WAAW,GACtB,QAAQ,aAAa,CAAC,QAAQ,CAAC,EAC/B,KAAK,gBAAgB,WAatB,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { FormulaError } from "@rowsncolumns/fast-formula-parser";
2
+ export const FORMULATEXT = (parser, arg) => {
3
+ const cellData = parser.getCellData(arg.position);
4
+ const userEnteredValue = Array.isArray(cellData)
5
+ ? undefined
6
+ : cellData?.ue ?? cellData?.userEnteredValue;
7
+ const formulaValue = userEnteredValue?.formulaValue;
8
+ if (formulaValue) {
9
+ return formulaValue;
10
+ }
11
+ throw new FormulaError("#NA", "Invalid formula parse result.");
12
+ };
@@ -0,0 +1,32 @@
1
+ import type { FunctionArgument } from "@rowsncolumns/calculator";
2
+ /**
3
+ * GETPIVOTDATA(value_name, pivot_range, [field, item, ...])
4
+ *
5
+ * Looks up an aggregated value at the intersection of the named
6
+ * value column and the named field/item criteria within a rendered
7
+ * pivot range.
8
+ *
9
+ * Excel signature support:
10
+ * - GETPIVOTDATA("Sum of Revenue", $A$1)
11
+ * → grand total of "Sum of Revenue" (no criteria)
12
+ * - GETPIVOTDATA("Sum of Revenue", $A$1, "Region", "West")
13
+ * → cell at intersection where Region=West
14
+ * - GETPIVOTDATA("Sum of Revenue", $A$1, "Region", "West", "Year", 2024)
15
+ * → multi-field criteria, ANDed
16
+ *
17
+ * This implementation treats the pivot range as a 2D matrix and
18
+ * does header-matching: it scans the leading row(s) for column-
19
+ * dimension headers, the leading column(s) for row-dimension
20
+ * headers, and resolves the requested value at the intersection.
21
+ *
22
+ * Returns `#REF!` if criteria don't resolve to a unique cell, or
23
+ * `#NA!` if `value_name` isn't found in the range.
24
+ *
25
+ * Limitations vs Excel:
26
+ * - Doesn't honor pivot scoping (which pivot owns the cell). We
27
+ * work off the provided range only.
28
+ * - Doesn't auto-derive "Sum of X" / "Avg of X" — caller must
29
+ * pass the rendered header verbatim.
30
+ */
31
+ export declare const GETPIVOTDATA: (_parser: unknown, valueName: FunctionArgument, pivotRange: FunctionArgument, ...criteria: FunctionArgument[]) => unknown;
32
+ //# sourceMappingURL=get-pivot-data.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-pivot-data.d.ts","sourceRoot":"","sources":["../../../formulas/get-pivot-data.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAGjE;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,YAAY,GACvB,SAAS,OAAO,EAChB,WAAW,gBAAgB,EAC3B,YAAY,gBAAgB,EAC5B,GAAG,UAAU,gBAAgB,EAAE,KAC9B,OA4HF,CAAC"}
@@ -0,0 +1,144 @@
1
+ import { FormulaError } from "@rowsncolumns/fast-formula-parser";
2
+ /**
3
+ * GETPIVOTDATA(value_name, pivot_range, [field, item, ...])
4
+ *
5
+ * Looks up an aggregated value at the intersection of the named
6
+ * value column and the named field/item criteria within a rendered
7
+ * pivot range.
8
+ *
9
+ * Excel signature support:
10
+ * - GETPIVOTDATA("Sum of Revenue", $A$1)
11
+ * → grand total of "Sum of Revenue" (no criteria)
12
+ * - GETPIVOTDATA("Sum of Revenue", $A$1, "Region", "West")
13
+ * → cell at intersection where Region=West
14
+ * - GETPIVOTDATA("Sum of Revenue", $A$1, "Region", "West", "Year", 2024)
15
+ * → multi-field criteria, ANDed
16
+ *
17
+ * This implementation treats the pivot range as a 2D matrix and
18
+ * does header-matching: it scans the leading row(s) for column-
19
+ * dimension headers, the leading column(s) for row-dimension
20
+ * headers, and resolves the requested value at the intersection.
21
+ *
22
+ * Returns `#REF!` if criteria don't resolve to a unique cell, or
23
+ * `#NA!` if `value_name` isn't found in the range.
24
+ *
25
+ * Limitations vs Excel:
26
+ * - Doesn't honor pivot scoping (which pivot owns the cell). We
27
+ * work off the provided range only.
28
+ * - Doesn't auto-derive "Sum of X" / "Avg of X" — caller must
29
+ * pass the rendered header verbatim.
30
+ */
31
+ export const GETPIVOTDATA = (_parser, valueName, pivotRange, ...criteria) => {
32
+ if (valueName == null || pivotRange == null) {
33
+ throw new FormulaError("#NA!", "GETPIVOTDATA requires value name and pivot range");
34
+ }
35
+ const target = String(valueName.value ?? "")
36
+ .trim()
37
+ .toLowerCase();
38
+ if (!target) {
39
+ throw new FormulaError("#NA!", "GETPIVOTDATA value name is empty");
40
+ }
41
+ // The pivot range arrives as a 2-D array (FunctionArgument.value
42
+ // for a CellRange is rows[cols][]). Single-cell args come in as
43
+ // a scalar — coerce to the 2D shape.
44
+ const raw = pivotRange.value;
45
+ const matrix = Array.isArray(raw)
46
+ ? Array.isArray(raw[0])
47
+ ? raw
48
+ : [raw]
49
+ : [[raw]];
50
+ if (matrix.length === 0 || matrix[0].length === 0) {
51
+ throw new FormulaError("#REF!", "GETPIVOTDATA range is empty");
52
+ }
53
+ // Parse criteria into pairs.
54
+ const pairs = [];
55
+ for (let i = 0; i < criteria.length; i += 2) {
56
+ const field = String(criteria[i]?.value ?? "")
57
+ .trim()
58
+ .toLowerCase();
59
+ const item = String(criteria[i + 1]?.value ?? "")
60
+ .trim()
61
+ .toLowerCase();
62
+ if (!field)
63
+ continue;
64
+ pairs.push({ field, item });
65
+ }
66
+ const cellAt = (r, c) => String(matrix[r]?.[c] ?? "")
67
+ .trim()
68
+ .toLowerCase();
69
+ // Find the value column: scan all cells; the topmost row that
70
+ // contains `target` is the value-header row, and we record the
71
+ // column index. Excel typically puts these in row 0 or 1 of the
72
+ // rendered range.
73
+ const numRows = matrix.length;
74
+ const numCols = matrix[0].length;
75
+ let valueColumn = -1;
76
+ let valueHeaderRow = -1;
77
+ outer: for (let r = 0; r < numRows; r++) {
78
+ for (let c = 0; c < numCols; c++) {
79
+ if (cellAt(r, c) === target) {
80
+ valueColumn = c;
81
+ valueHeaderRow = r;
82
+ break outer;
83
+ }
84
+ }
85
+ }
86
+ if (valueColumn < 0) {
87
+ throw new FormulaError("#NA!", `GETPIVOTDATA: value '${valueName.value}' not found in range`);
88
+ }
89
+ // No criteria → assume the grand-total cell. Convention in Excel
90
+ // is the last row of the value column (after subtotals settle).
91
+ // Fall back to first non-header cell if no row qualifies.
92
+ if (pairs.length === 0) {
93
+ for (let r = numRows - 1; r > valueHeaderRow; r--) {
94
+ const v = matrix[r]?.[valueColumn];
95
+ if (v != null && v !== "")
96
+ return v;
97
+ }
98
+ return matrix[valueHeaderRow + 1]?.[valueColumn] ?? null;
99
+ }
100
+ // Match a row: for each criterion (field, item), find the
101
+ // column where the header row contains `field`, then check the
102
+ // candidate row's cell at that column equals `item`. ALL pairs
103
+ // must match (AND).
104
+ const fieldColumns = new Map();
105
+ for (const { field } of pairs) {
106
+ for (let c = 0; c < numCols; c++) {
107
+ // Find any row where header[r][c] === field. Excel pivots
108
+ // typically place row dimensions in left columns; we find
109
+ // any column whose header anywhere in the leading rows
110
+ // matches.
111
+ let matched = false;
112
+ for (let r = 0; r <= valueHeaderRow; r++) {
113
+ if (cellAt(r, c) === field) {
114
+ fieldColumns.set(field, c);
115
+ matched = true;
116
+ break;
117
+ }
118
+ }
119
+ if (matched)
120
+ break;
121
+ }
122
+ }
123
+ // If any field can't be located → #REF!
124
+ for (const { field } of pairs) {
125
+ if (!fieldColumns.has(field)) {
126
+ throw new FormulaError("#REF!", `GETPIVOTDATA: field '${field}' not found`);
127
+ }
128
+ }
129
+ for (let r = valueHeaderRow + 1; r < numRows; r++) {
130
+ let allMatch = true;
131
+ for (const { field, item } of pairs) {
132
+ const col = fieldColumns.get(field);
133
+ if (cellAt(r, col) !== item) {
134
+ allMatch = false;
135
+ break;
136
+ }
137
+ }
138
+ if (allMatch) {
139
+ const v = matrix[r]?.[valueColumn];
140
+ return v ?? null;
141
+ }
142
+ }
143
+ throw new FormulaError("#REF!", "GETPIVOTDATA: no row matches the supplied criteria");
144
+ };
@@ -0,0 +1,5 @@
1
+ import type { FunctionArgument } from "@rowsncolumns/calculator";
2
+ import type FormulaParser from "@rowsncolumns/fast-formula-parser";
3
+ import { type HyperlinkResult } from "@rowsncolumns/common-types";
4
+ export declare const HYPERLINK: (_: FormulaParser, url: FunctionArgument, title?: FunctionArgument) => HyperlinkResult | undefined;
5
+ //# sourceMappingURL=hyperlink.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hyperlink.d.ts","sourceRoot":"","sources":["../../../formulas/hyperlink.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,aAAa,MAAM,mCAAmC,CAAC;AACnE,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAGlE,eAAO,MAAM,SAAS,GACpB,GAAG,aAAa,EAChB,KAAK,gBAAgB,EACrB,QAAO,gBAAsB,KAC5B,eAAe,GAAG,SAepB,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { FormulaError } from "@rowsncolumns/fast-formula-parser";
2
+ export const HYPERLINK = (_, url, title = url) => {
3
+ if (!url.value) {
4
+ throw new FormulaError("#VALUE!", "URL is required");
5
+ }
6
+ if (typeof url.value !== "string") {
7
+ throw new FormulaError("#VALUE!", "URL should be a string");
8
+ }
9
+ if (typeof title.value !== "string") {
10
+ throw new FormulaError("#VALUE!", "URL should be a string");
11
+ }
12
+ return {
13
+ title: title.value,
14
+ url: url.value,
15
+ kind: "hyperlink",
16
+ };
17
+ };
@@ -0,0 +1,5 @@
1
+ import type { FunctionArgument } from "@rowsncolumns/calculator";
2
+ import type FormulaParser from "@rowsncolumns/fast-formula-parser";
3
+ import { type ImageResult } from "@rowsncolumns/common-types";
4
+ export declare const IMAGE: (_: FormulaParser, url: FunctionArgument) => ImageResult;
5
+ //# sourceMappingURL=image.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../../formulas/image.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,aAAa,MAAM,mCAAmC,CAAC;AACnE,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAG9D,eAAO,MAAM,KAAK,GAAI,GAAG,aAAa,EAAE,KAAK,gBAAgB,KAAG,WAW/D,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { FormulaError } from "@rowsncolumns/fast-formula-parser";
2
+ export const IMAGE = (_, url) => {
3
+ if (!url.value) {
4
+ throw new FormulaError("#VALUE!", "URL is required");
5
+ }
6
+ if (typeof url.value !== "string") {
7
+ throw new FormulaError("#VALUE!", "URL should be a string");
8
+ }
9
+ return {
10
+ imageUrl: url.value,
11
+ kind: "image",
12
+ };
13
+ };
@@ -0,0 +1,11 @@
1
+ import type { FunctionArgument } from "@rowsncolumns/calculator";
2
+ import type FormulaParser from "@rowsncolumns/fast-formula-parser";
3
+ /**
4
+ * // =IMPORTDATA("https://api.covidtracking.com/v1/us/daily.csv")
5
+ * =IMPORTDATA("https://api.covidtracking.com/v1/us/current.json")
6
+ * @param parser
7
+ * @param url
8
+ * @returns
9
+ */
10
+ export declare const IMPORTDATA: (parser: FormulaParser, url: FunctionArgument) => Promise<string[][] | undefined>;
11
+ //# sourceMappingURL=import-data.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import-data.d.ts","sourceRoot":"","sources":["../../../formulas/import-data.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,aAAa,MAAM,mCAAmC,CAAC;AAInE;;;;;;GAMG;AAEH,eAAO,MAAM,UAAU,GAErB,QAAQ,aAAa,EACrB,KAAK,gBAAgB,oCAmBtB,CAAC"}
@@ -0,0 +1,28 @@
1
+ import { FormulaError } from "@rowsncolumns/fast-formula-parser";
2
+ import { parseCSV } from "@rowsncolumns/toolkit";
3
+ /**
4
+ * // =IMPORTDATA("https://api.covidtracking.com/v1/us/daily.csv")
5
+ * =IMPORTDATA("https://api.covidtracking.com/v1/us/current.json")
6
+ * @param parser
7
+ * @param url
8
+ * @returns
9
+ */
10
+ export const IMPORTDATA = async (
11
+ // getContext,
12
+ parser, url) => {
13
+ if (!url?.value || typeof url?.value !== "string") {
14
+ throw new FormulaError("#VALUE!", "URL is missing");
15
+ }
16
+ const fileExtension = url.value.split(".").pop();
17
+ if (fileExtension && !(["tsv", "csv"].indexOf(fileExtension) !== -1)) {
18
+ throw new FormulaError("#N/A", "Only CSV and TSV are supported by IMPORTDATA");
19
+ }
20
+ const response = await (await fetch(url.value)).text();
21
+ try {
22
+ const results = await parseCSV(response);
23
+ return results;
24
+ }
25
+ catch (err) {
26
+ throw new FormulaError("#VALUE", String(err));
27
+ }
28
+ };
@@ -0,0 +1,18 @@
1
+ export { IMPORTDATA } from "./import-data";
2
+ export { ARRAYFORMULA } from "./array-formula";
3
+ export { STARRATING } from "./star-rating";
4
+ export { HYPERLINK } from "./hyperlink";
5
+ export { REALTIME } from "./real-time";
6
+ export { CRYPTOPRICE } from "./crypto-price";
7
+ export { IMAGE } from "./image";
8
+ export { SELECTION_STATUS } from "./selection-status";
9
+ export { MULTIPLY } from "./multiply";
10
+ export { UNIQUE } from "./unique";
11
+ export { SEQUENCE } from "./sequence";
12
+ export { JOIN } from "./join";
13
+ export { SPLIT } from "./split";
14
+ export { DATASOURCE } from "./datasource";
15
+ export { FORMULATEXT } from "./formula-text";
16
+ export { SPARKLINE } from "./sparkline";
17
+ export { GETPIVOTDATA } from "./get-pivot-data";
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../formulas/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,17 @@
1
+ export { IMPORTDATA } from "./import-data";
2
+ export { ARRAYFORMULA } from "./array-formula";
3
+ export { STARRATING } from "./star-rating";
4
+ export { HYPERLINK } from "./hyperlink";
5
+ export { REALTIME } from "./real-time";
6
+ export { CRYPTOPRICE } from "./crypto-price";
7
+ export { IMAGE } from "./image";
8
+ export { SELECTION_STATUS } from "./selection-status";
9
+ export { MULTIPLY } from "./multiply";
10
+ export { UNIQUE } from "./unique";
11
+ export { SEQUENCE } from "./sequence";
12
+ export { JOIN } from "./join";
13
+ export { SPLIT } from "./split";
14
+ export { DATASOURCE } from "./datasource";
15
+ export { FORMULATEXT } from "./formula-text";
16
+ export { SPARKLINE } from "./sparkline";
17
+ export { GETPIVOTDATA } from "./get-pivot-data";
@@ -0,0 +1,4 @@
1
+ import type { FunctionArgument } from "@rowsncolumns/calculator";
2
+ import type FormulaParser from "@rowsncolumns/fast-formula-parser";
3
+ export declare const JOIN: (_: FormulaParser, delimiter: FunctionArgument, ...args: FunctionArgument[]) => string;
4
+ //# sourceMappingURL=join.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"join.d.ts","sourceRoot":"","sources":["../../../formulas/join.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,aAAa,MAAM,mCAAmC,CAAC;AAInE,eAAO,MAAM,IAAI,GACf,GAAG,aAAa,EAChB,WAAW,gBAAgB,EAC3B,GAAG,MAAM,gBAAgB,EAAE,WA6B5B,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { FormulaError } from "@rowsncolumns/fast-formula-parser";
2
+ import { isNil } from "@rowsncolumns/utils";
3
+ export const JOIN = (_, delimiter, ...args) => {
4
+ if (!delimiter || isNil(delimiter.value)) {
5
+ throw new FormulaError("#NA!", "Invalid delimiter");
6
+ }
7
+ const delim = String(delimiter.value);
8
+ const values = args
9
+ .map(({ value, position, isRangeRef }) => {
10
+ if (isRangeRef) {
11
+ // Validate
12
+ let rangePosition = position;
13
+ if (rangePosition.from.col !== rangePosition.to.col &&
14
+ rangePosition.from.row !== rangePosition.to.row) {
15
+ throw new FormulaError("#VALUE!", "JOIN range must be a single row or a single column.");
16
+ }
17
+ }
18
+ if (Array.isArray(value)) {
19
+ return value.flat();
20
+ }
21
+ return value;
22
+ })
23
+ .flat();
24
+ return values.join(delim);
25
+ };
@@ -0,0 +1,4 @@
1
+ import type { FunctionArgument } from "@rowsncolumns/calculator";
2
+ import type FormulaParser from "@rowsncolumns/fast-formula-parser";
3
+ export declare const MULTIPLY: (_: FormulaParser, factor1: FunctionArgument, factor2: FunctionArgument) => number;
4
+ //# sourceMappingURL=multiply.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multiply.d.ts","sourceRoot":"","sources":["../../../formulas/multiply.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,aAAa,MAAM,mCAAmC,CAAC;AAInE,eAAO,MAAM,QAAQ,GACnB,GAAG,aAAa,EAChB,SAAS,gBAAgB,EACzB,SAAS,gBAAgB,WAiB1B,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { FormulaError } from "@rowsncolumns/fast-formula-parser";
2
+ import { isNil } from "@rowsncolumns/utils";
3
+ export const MULTIPLY = (_, factor1, factor2) => {
4
+ if (isNil(factor1.value) || isNil(factor2.value)) {
5
+ throw new FormulaError("#N/A!", "Wrong number of arguments to MULTIPLY. Expected 2 arguments.");
6
+ }
7
+ if (typeof factor1.value !== "number" || typeof factor2.value !== "number") {
8
+ throw new FormulaError("#VALUE", "Function MULTIPLY expects number values.");
9
+ }
10
+ return factor1.value * factor2.value;
11
+ };
@@ -0,0 +1,4 @@
1
+ import { FunctionArgument } from "@rowsncolumns/calculator";
2
+ import type FormulaParser from "@rowsncolumns/fast-formula-parser";
3
+ export declare const REALTIME: (parser: FormulaParser, arg: FunctionArgument) => string;
4
+ //# sourceMappingURL=real-time.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"real-time.d.ts","sourceRoot":"","sources":["../../../formulas/real-time.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAEjB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,aAAa,MAAM,mCAAmC,CAAC;AAEnE,eAAO,MAAM,QAAQ,GAAI,QAAQ,aAAa,EAAE,KAAK,gBAAgB,WAepE,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { calculationPipeline, } from "@rowsncolumns/calculator";
2
+ export const REALTIME = (parser, arg) => {
3
+ calculationPipeline(parser, (onUpdate) => {
4
+ let timer = setInterval(() => {
5
+ onUpdate([[2, Math.random(), Math.random(), 2]]);
6
+ }, 5000);
7
+ console.log("sub", timer);
8
+ return () => {
9
+ console.log("unsub", timer);
10
+ clearTimeout(timer);
11
+ };
12
+ });
13
+ return "Loading";
14
+ };
@@ -0,0 +1,4 @@
1
+ import type { FunctionArgument } from "@rowsncolumns/calculator";
2
+ import type FormulaParser from "@rowsncolumns/fast-formula-parser";
3
+ export declare const SELECTION_STATUS: (_: FormulaParser, arg: FunctionArgument) => (number | undefined)[];
4
+ //# sourceMappingURL=selection-status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selection-status.d.ts","sourceRoot":"","sources":["../../../formulas/selection-status.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,aAAa,MAAM,mCAAmC,CAAC;AAGnE,eAAO,MAAM,gBAAgB,GAAI,GAAG,aAAa,EAAE,KAAK,gBAAgB,2BAsCvE,CAAC"}