@pixerate/editor 0.21.0 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -11
- package/dist/agent/index.cjs +8 -8
- package/dist/agent/index.d.cts +2 -2
- package/dist/agent/index.d.ts +2 -2
- package/dist/agent/index.js +2 -2
- package/dist/canvas/index.cjs +1269 -13
- package/dist/canvas/index.cjs.map +1 -1
- package/dist/canvas/index.d.cts +432 -6
- package/dist/canvas/index.d.ts +432 -6
- package/dist/canvas/index.js +1264 -8
- package/dist/canvas/index.js.map +1 -1
- package/dist/{chunk-U6NDQFOK.cjs → chunk-6M3BCTBD.cjs} +427 -138
- package/dist/chunk-6M3BCTBD.cjs.map +1 -0
- package/dist/{chunk-TVRC4KVT.cjs → chunk-AA4ZEVCC.cjs} +845 -90
- package/dist/chunk-AA4ZEVCC.cjs.map +1 -0
- package/dist/{chunk-LA7PEGU3.cjs → chunk-CL37JGFW.cjs} +4 -4
- package/dist/{chunk-LA7PEGU3.cjs.map → chunk-CL37JGFW.cjs.map} +1 -1
- package/dist/{chunk-A7DKIA72.js → chunk-DENSCKFC.js} +642 -69
- package/dist/chunk-DENSCKFC.js.map +1 -0
- package/dist/{chunk-4QPLEUL2.cjs → chunk-GVSMRPHB.cjs} +1046 -54
- package/dist/chunk-GVSMRPHB.cjs.map +1 -0
- package/dist/{chunk-KYRZDWM4.js → chunk-JJDLPEWL.js} +2 -2
- package/dist/{chunk-3TYMNULT.js → chunk-MJZBNWG7.js} +807 -52
- package/dist/chunk-MJZBNWG7.js.map +1 -0
- package/dist/{chunk-CYFJCKC4.js → chunk-QGHGJ56O.js} +997 -5
- package/dist/chunk-QGHGJ56O.js.map +1 -0
- package/dist/{chunk-GVW4P7BG.js → chunk-RU52I7QO.js} +305 -16
- package/dist/chunk-RU52I7QO.js.map +1 -0
- package/dist/{chunk-JYRIOFEN.cjs → chunk-SAZRENEZ.cjs} +647 -74
- package/dist/chunk-SAZRENEZ.cjs.map +1 -0
- package/dist/{controller-OUdxPY-X.d.ts → controller-B7GIybc4.d.cts} +139 -7
- package/dist/{controller-OUdxPY-X.d.cts → controller-B7GIybc4.d.ts} +139 -7
- package/dist/extensions/index.cjs +14 -4
- package/dist/extensions/index.cjs.map +1 -1
- package/dist/extensions/index.d.cts +3 -3
- package/dist/extensions/index.d.ts +3 -3
- package/dist/extensions/index.js +13 -3
- package/dist/{index-k3mFbPx_.d.cts → index-CCr_z9kF.d.cts} +3 -3
- package/dist/{index-Ng1pG7JE.d.ts → index-Ck6ajwXh.d.ts} +3 -3
- package/dist/index.cjs +250 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +294 -8
- package/dist/index.d.ts +294 -8
- package/dist/index.js +241 -7
- package/dist/index.js.map +1 -1
- package/dist/{registry-iAHbqkYt.d.cts → registry-GJI4gToU.d.cts} +15 -4
- package/dist/{registry-iAHbqkYt.d.ts → registry-GJI4gToU.d.ts} +15 -4
- package/dist/serializers/index.cjs +3 -3
- package/dist/serializers/index.d.cts +1 -1
- package/dist/serializers/index.d.ts +1 -1
- package/dist/serializers/index.js +2 -2
- package/dist/spreadsheet/index.cjs +7 -3
- package/dist/spreadsheet/index.cjs.map +1 -1
- package/dist/spreadsheet/index.d.cts +33 -4
- package/dist/spreadsheet/index.d.ts +33 -4
- package/dist/spreadsheet/index.js +6 -2
- package/dist/{track-changes-G8JcWB8b.d.cts → track-changes-BSF58RK0.d.cts} +92 -9
- package/dist/{track-changes-G8JcWB8b.d.ts → track-changes-BSF58RK0.d.ts} +92 -9
- package/dist/{types-DMe0vFB1.d.cts → types-CJ4U-HHI.d.cts} +1 -1
- package/dist/{types-DMe0vFB1.d.ts → types-CJ4U-HHI.d.ts} +1 -1
- package/package.json +1 -1
- package/dist/chunk-3TYMNULT.js.map +0 -1
- package/dist/chunk-4QPLEUL2.cjs.map +0 -1
- package/dist/chunk-A7DKIA72.js.map +0 -1
- package/dist/chunk-CYFJCKC4.js.map +0 -1
- package/dist/chunk-GVW4P7BG.js.map +0 -1
- package/dist/chunk-JYRIOFEN.cjs.map +0 -1
- package/dist/chunk-TVRC4KVT.cjs.map +0 -1
- package/dist/chunk-U6NDQFOK.cjs.map +0 -1
- /package/dist/{chunk-KYRZDWM4.js.map → chunk-JJDLPEWL.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/spreadsheet/formula/lexer.ts","../src/spreadsheet/formula/parser.ts","../src/spreadsheet/formula/values.ts","../src/spreadsheet/formula/criteria.ts","../src/spreadsheet/formula/format.ts","../src/spreadsheet/formula/functions/helpers.ts","../src/spreadsheet/formula/functions/math.ts","../src/spreadsheet/formula/functions/statistical.ts","../src/spreadsheet/formula/functions/conditional.ts","../src/spreadsheet/formula/functions/logical.ts","../src/spreadsheet/formula/functions/text.ts","../src/spreadsheet/formula/functions/lookup.ts","../src/spreadsheet/formula/functions/date.ts","../src/spreadsheet/formula/functions/information.ts","../src/spreadsheet/formula/functions/index.ts","../src/spreadsheet/formula/registry.ts","../src/spreadsheet/formula/evaluator.ts"],"sourcesContent":["export type FormulaTokenType =\n | 'NUMBER'\n | 'STRING'\n | 'BOOLEAN'\n | 'ERROR'\n | 'CELL_REF'\n | 'RANGE'\n | 'PROPERTY_REF'\n | 'IDENTIFIER'\n | 'OPERATOR'\n | 'LPAREN'\n | 'RPAREN'\n | 'COMMA'\n | 'EOF';\n\nexport interface FormulaToken {\n type: FormulaTokenType;\n value: string;\n position: number;\n}\n\nexport function tokenizeFormula(formula: string): FormulaToken[] {\n const tokens: FormulaToken[] = [];\n // Strip leading '=' if present\n let input = formula.trim();\n let offset = 0;\n if (input.startsWith('=')) {\n input = input.slice(1);\n offset = 1;\n }\n\n let i = 0;\n while (i < input.length) {\n const char = input[i];\n\n // Skip whitespace\n if (/\\s/.test(char)) {\n i++;\n continue;\n }\n\n // Number literal (int or float)\n if (/\\d/.test(char) || (char === '.' && i + 1 < input.length && /\\d/.test(input[i + 1]))) {\n const start = i;\n let hasDot = char === '.';\n i++;\n while (i < input.length && (/\\d/.test(input[i]) || (input[i] === '.' && !hasDot))) {\n if (input[i] === '.') hasDot = true;\n i++;\n }\n tokens.push({\n type: 'NUMBER',\n value: input.slice(start, i),\n position: start + offset\n });\n continue;\n }\n\n // String literal (\"...\" or '...')\n if (char === '\"' || char === \"'\") {\n const quote = char;\n const start = i;\n i++;\n let str = '';\n while (i < input.length && input[i] !== quote) {\n if (input[i] === '\\\\' && i + 1 < input.length) {\n i++;\n }\n str += input[i];\n i++;\n }\n if (i >= input.length) {\n throw new Error(`Unterminated string starting at position ${start + offset}`);\n }\n i++; // skip closing quote\n tokens.push({\n type: 'STRING',\n value: str,\n position: start + offset\n });\n continue;\n }\n\n // Error literal, e.g. #REF! left behind by deleting a referenced row\n if (char === '#') {\n const match = /^#(?:REF!|DIV\\/0!|VALUE!|NAME\\?|N\\/A|NUM!|CYCLE!|ERROR!)/.exec(input.slice(i));\n if (!match) {\n throw new Error(`Unexpected character '#' at position ${i + offset}`);\n }\n tokens.push({ type: 'ERROR', value: match[0], position: i + offset });\n i += match[0].length;\n continue;\n }\n\n // Property reference: [property_name] e.g. [status], [title], [effortHours]\n if (char === '[') {\n const start = i;\n i++;\n let prop = '';\n while (i < input.length && input[i] !== ']') {\n prop += input[i];\n i++;\n }\n if (i < input.length && input[i] === ']') {\n i++;\n }\n tokens.push({\n type: 'PROPERTY_REF',\n value: prop.trim(),\n position: start + offset\n });\n continue;\n }\n\n // Single character delimiters\n if (char === '(') {\n tokens.push({ type: 'LPAREN', value: '(', position: i + offset });\n i++;\n continue;\n }\n if (char === ')') {\n tokens.push({ type: 'RPAREN', value: ')', position: i + offset });\n i++;\n continue;\n }\n if (char === ',') {\n tokens.push({ type: 'COMMA', value: ',', position: i + offset });\n i++;\n continue;\n }\n\n // Multi-character comparison operators: <=, >=, <>, !=\n const twoChars = input.slice(i, i + 2);\n if (['<=', '>=', '<>', '!='].includes(twoChars)) {\n tokens.push({\n type: 'OPERATOR',\n value: twoChars === '!=' ? '<>' : twoChars,\n position: i + offset\n });\n i += 2;\n continue;\n }\n\n // Single character operators: +, -, *, /, ^, &, =, <, >\n if (['+', '-', '*', '/', '^', '&', '=', '<', '>'].includes(char)) {\n tokens.push({ type: 'OPERATOR', value: char, position: i + offset });\n i++;\n continue;\n }\n\n // Identifiers, Cell references, and Ranges (e.g. SUM, A1, B2:B10, A:A)\n if (/[a-zA-Z_$]/.test(char)) {\n const start = i;\n while (i < input.length && /[a-zA-Z0-9_$.]/.test(input[i])) {\n i++;\n }\n const rawWord = input.slice(start, i);\n\n // Check if followed by colon indicating a range e.g. A1:B10 or A:A\n if (i < input.length && input[i] === ':') {\n const colonPos = i;\n i++; // skip colon\n const secondStart = i;\n while (i < input.length && /[a-zA-Z0-9_$.]/.test(input[i])) {\n i++;\n }\n const secondWord = input.slice(secondStart, i);\n if (secondWord.length > 0) {\n tokens.push({\n type: 'RANGE',\n value: `${rawWord}:${secondWord}`.toUpperCase(),\n position: start + offset\n });\n continue;\n } else {\n // Revert back\n i = colonPos;\n }\n }\n\n // Check for boolean literal\n const upper = rawWord.toUpperCase();\n if (upper === 'TRUE' || upper === 'FALSE') {\n tokens.push({\n type: 'BOOLEAN',\n value: upper,\n position: start + offset\n });\n continue;\n }\n\n // Check for Cell Reference (e.g. A1, $B$12, AA100)\n if (/^\\$?[A-Za-z]+\\$?[0-9]+$/.test(rawWord)) {\n tokens.push({\n type: 'CELL_REF',\n value: upper.replace(/\\$/g, ''),\n position: start + offset\n });\n continue;\n }\n\n // Function or generic identifier\n tokens.push({\n type: 'IDENTIFIER',\n value: upper,\n position: start + offset\n });\n continue;\n }\n\n throw new Error(`Unexpected character '${char}' at position ${i + offset}`);\n }\n\n tokens.push({ type: 'EOF', value: '', position: input.length + offset });\n return tokens;\n}\n","import { FormulaToken, tokenizeFormula, FormulaTokenType } from './lexer';\n\n/** Row number used for the open end of whole-column ranges such as `A:A`. */\nexport const WHOLE_COLUMN_END_ROW = 1048576;\n\nexport type ASTNode =\n | LiteralNode\n | CellRefNode\n | RangeNode\n | PropertyRefNode\n | BinaryOpNode\n | UnaryOpNode\n | FunctionCallNode;\n\nexport interface LiteralNode {\n type: 'Literal';\n value: number | string | boolean;\n}\n\nexport interface CellRefNode {\n type: 'CellRef';\n ref: string;\n col: string;\n row: number;\n}\n\nexport interface RangeNode {\n type: 'Range';\n raw: string;\n startCol: string;\n startRow: number;\n endCol: string;\n endRow: number;\n}\n\nexport interface PropertyRefNode {\n type: 'PropertyRef';\n property: string;\n}\n\nexport interface BinaryOpNode {\n type: 'BinaryOp';\n op: string;\n left: ASTNode;\n right: ASTNode;\n}\n\nexport interface UnaryOpNode {\n type: 'UnaryOp';\n op: string;\n argument: ASTNode;\n}\n\nexport interface FunctionCallNode {\n type: 'FunctionCall';\n name: string;\n args: ASTNode[];\n}\n\nexport function parseCellReference(ref: string): { col: string; row: number } {\n const match = ref.match(/^([A-Za-z]+)(\\d+)$/);\n if (!match) {\n throw new Error(`Invalid cell reference: ${ref}`);\n }\n return {\n col: match[1].toUpperCase(),\n row: parseInt(match[2], 10)\n };\n}\n\nexport function parseRange(rangeStr: string): RangeNode {\n const [start, end] = rangeStr.replace(/\\$/g, '').split(':');\n const raw = rangeStr.toUpperCase();\n\n // Whole-column range, e.g. A:A or B:D\n if (/^[A-Za-z]+$/.test(start) && /^[A-Za-z]+$/.test(end)) {\n return {\n type: 'Range',\n raw,\n startCol: start.toUpperCase(),\n startRow: 1,\n endCol: end.toUpperCase(),\n endRow: WHOLE_COLUMN_END_ROW\n };\n }\n\n const startRef = parseCellReference(start);\n const endRef = parseCellReference(end);\n return {\n type: 'Range',\n raw,\n startCol: startRef.col,\n startRow: startRef.row,\n endCol: endRef.col,\n endRow: endRef.row\n };\n}\n\nexport class FormulaParser {\n private tokens: FormulaToken[] = [];\n private current = 0;\n\n constructor(tokens: FormulaToken[]) {\n this.tokens = tokens;\n }\n\n public parse(): ASTNode {\n if (this.peek().type === 'EOF') {\n return { type: 'Literal', value: '' };\n }\n const expr = this.expression();\n if (this.peek().type !== 'EOF') {\n throw new Error(`Unexpected token at position ${this.peek().position}: ${this.peek().value}`);\n }\n return expr;\n }\n\n private expression(): ASTNode {\n return this.comparison();\n }\n\n private comparison(): ASTNode {\n let expr = this.concatenation();\n\n while (\n this.matchOperator('=', '<>', '<', '>', '<=', '>=')\n ) {\n const op = this.previous().value;\n const right = this.concatenation();\n expr = { type: 'BinaryOp', op, left: expr, right };\n }\n\n return expr;\n }\n\n private concatenation(): ASTNode {\n let expr = this.addition();\n\n while (this.matchOperator('&')) {\n const op = this.previous().value;\n const right = this.addition();\n expr = { type: 'BinaryOp', op, left: expr, right };\n }\n\n return expr;\n }\n\n private addition(): ASTNode {\n let expr = this.multiplication();\n\n while (this.matchOperator('+', '-')) {\n const op = this.previous().value;\n const right = this.multiplication();\n expr = { type: 'BinaryOp', op, left: expr, right };\n }\n\n return expr;\n }\n\n private multiplication(): ASTNode {\n let expr = this.exponentiation();\n\n while (this.matchOperator('*', '/')) {\n const op = this.previous().value;\n const right = this.exponentiation();\n expr = { type: 'BinaryOp', op, left: expr, right };\n }\n\n return expr;\n }\n\n private exponentiation(): ASTNode {\n let expr = this.unary();\n\n while (this.matchOperator('^')) {\n const op = this.previous().value;\n const right = this.unary();\n expr = { type: 'BinaryOp', op, left: expr, right };\n }\n\n return expr;\n }\n\n private unary(): ASTNode {\n if (this.matchOperator('-', '+')) {\n const op = this.previous().value;\n const argument = this.unary();\n return { type: 'UnaryOp', op, argument };\n }\n return this.primary();\n }\n\n private primary(): ASTNode {\n const token = this.peek();\n\n if (token.type === 'NUMBER') {\n this.advance();\n return { type: 'Literal', value: parseFloat(token.value) };\n }\n\n if (token.type === 'STRING') {\n this.advance();\n return { type: 'Literal', value: token.value };\n }\n\n if (token.type === 'BOOLEAN') {\n this.advance();\n return { type: 'Literal', value: token.value === 'TRUE' };\n }\n\n if (token.type === 'ERROR') {\n this.advance();\n return { type: 'Literal', value: token.value };\n }\n\n if (token.type === 'CELL_REF') {\n this.advance();\n const parsed = parseCellReference(token.value);\n return {\n type: 'CellRef',\n ref: token.value,\n col: parsed.col,\n row: parsed.row\n };\n }\n\n if (token.type === 'RANGE') {\n this.advance();\n return parseRange(token.value);\n }\n\n if (token.type === 'PROPERTY_REF') {\n this.advance();\n return {\n type: 'PropertyRef',\n property: token.value\n };\n }\n\n // Function call e.g. SUM(...)\n if (token.type === 'IDENTIFIER') {\n const name = token.value;\n this.advance();\n\n if (this.check('LPAREN')) {\n this.consume('LPAREN', `Expected '(' after function ${name}`);\n const args: ASTNode[] = [];\n if (!this.check('RPAREN')) {\n do {\n args.push(this.expression());\n } while (this.match('COMMA'));\n }\n this.consume('RPAREN', `Expected ')' after function arguments`);\n return {\n type: 'FunctionCall',\n name,\n args\n };\n }\n\n // Unknown bare names are #NAME? errors, as in spreadsheet apps.\n return { type: 'Literal', value: '#NAME?' };\n }\n\n if (this.match('LPAREN')) {\n const expr = this.expression();\n this.consume('RPAREN', `Expected ')' after expression`);\n return expr;\n }\n\n throw new Error(`Unexpected token at position ${token.position}: ${token.value || token.type}`);\n }\n\n private match(...types: string[]): boolean {\n for (const type of types) {\n if (this.check(type)) {\n this.advance();\n return true;\n }\n }\n return false;\n }\n\n private matchOperator(...ops: string[]): boolean {\n if (this.check('OPERATOR') && ops.includes(this.peek().value)) {\n this.advance();\n return true;\n }\n return false;\n }\n\n private check(type: string): boolean {\n if (this.isAtEnd()) return false;\n return this.peek().type === type;\n }\n\n private advance(): FormulaToken {\n if (!this.isAtEnd()) this.current++;\n return this.previous();\n }\n\n private isAtEnd(): boolean {\n return this.peek().type === 'EOF';\n }\n\n private peek(): FormulaToken {\n return this.tokens[this.current];\n }\n\n private previous(): FormulaToken {\n return this.tokens[this.current - 1];\n }\n\n private consume(type: string, message: string): FormulaToken {\n if (this.check(type)) return this.advance();\n throw new Error(message);\n }\n}\n\nexport function parseFormula(formula: string): ASTNode {\n const tokens = tokenizeFormula(formula);\n const parser = new FormulaParser(tokens);\n return parser.parse();\n}\n","/**\n * Value helpers shared by the formula evaluator and the built-in functions:\n * error values, spreadsheet coercion rules, comparisons, ranges and dates.\n */\n\n/** Spreadsheet error values. They propagate through operators and functions. */\nexport const FORMULA_ERRORS = new Set([\n '#DIV/0!',\n '#VALUE!',\n '#REF!',\n '#NAME?',\n '#N/A',\n '#NUM!',\n '#CYCLE!',\n '#ERROR!'\n]);\n\nexport type FormulaErrorCode =\n | '#DIV/0!'\n | '#VALUE!'\n | '#REF!'\n | '#NAME?'\n | '#N/A'\n | '#NUM!'\n | '#CYCLE!'\n | '#ERROR!';\n\nexport function isFormulaError(value: unknown): value is string {\n return typeof value === 'string' && FORMULA_ERRORS.has(value);\n}\n\nexport const isBlank = (value: unknown): boolean => value === '' || value === null || value === undefined;\n\n/** Coerces to a number like a spreadsheet: blanks are 0, booleans 1/0, other text is #VALUE!. */\nexport function toNumber(value: unknown): number | string {\n if (isFormulaError(value)) return value;\n if (isBlank(value)) return 0;\n if (typeof value === 'boolean') return value ? 1 : 0;\n if (typeof value === 'number') return value;\n const trimmed = String(value).trim();\n const num = trimmed === '' ? NaN : Number(trimmed);\n return isNaN(num) ? '#VALUE!' : num;\n}\n\n/** Coerces to a boolean: numbers are non-zero, \"TRUE\"/\"FALSE\" text is parsed, other text is #VALUE!. */\nexport function toBoolean(value: unknown): boolean | string {\n if (isFormulaError(value)) return value;\n if (isBlank(value)) return false;\n if (typeof value === 'boolean') return value;\n if (typeof value === 'number') return value !== 0;\n const upper = String(value).trim().toUpperCase();\n if (upper === 'TRUE') return true;\n if (upper === 'FALSE') return false;\n return '#VALUE!';\n}\n\nexport const toText = (value: unknown): string =>\n isBlank(value) ? '' : typeof value === 'boolean' ? (value ? 'TRUE' : 'FALSE') : String(value);\n\n/**\n * Number held by a value, or null. Typed cell values are stored as text, so\n * numeric text (\"120\") counts as a number here; booleans and blanks do not.\n */\nexport function numericValue(value: unknown): number | null {\n if (typeof value === 'number') return Number.isFinite(value) ? value : null;\n if (typeof value !== 'string' || FORMULA_ERRORS.has(value)) return null;\n const trimmed = value.trim();\n if (trimmed === '') return null;\n const num = Number(trimmed);\n return Number.isFinite(num) ? num : null;\n}\n\n/** Normalizes a cell value for lookups and criteria: numeric text becomes a number. */\nexport function normalizeValue(value: unknown): unknown {\n const num = typeof value === 'string' ? numericValue(value) : null;\n return num === null ? value : num;\n}\n\n/** Orders values like spreadsheets: numbers < text < booleans; text is case-insensitive. */\nexport function compareValues(left: unknown, right: unknown): number {\n const rank = (v: unknown) => (typeof v === 'boolean' ? 2 : typeof v === 'string' ? 1 : 0);\n // A blank compares as 0 against numbers/booleans and as \"\" against text.\n const l = isBlank(left) ? (typeof right === 'string' ? '' : 0) : left;\n const r = isBlank(right) ? (typeof l === 'string' ? '' : 0) : right;\n if (rank(l) !== rank(r)) return rank(l) - rank(r);\n if (typeof l === 'string') {\n const a = l.toLowerCase();\n const b = (r as string).toLowerCase();\n return a < b ? -1 : a > b ? 1 : 0;\n }\n return Number(l) - Number(r);\n}\n\n/** Rounds half away from zero, compensating for binary floating point (ROUND(1.005, 2) = 1.01). */\nexport function roundHalfAwayFromZero(value: number, decimals: number): number {\n const factor = Math.pow(10, decimals);\n const scaled = Number((Math.abs(value) * factor).toPrecision(15));\n return (Math.sign(value) * Math.round(scaled)) / factor;\n}\n\n/** Strips binary floating point noise (0.1 * 3 = 0.30000000000000004 -> 0.3). */\nexport const cleanFloat = (value: number): number => Number(value.toPrecision(15));\n\nexport function colNameToIndex(col: string): number {\n let index = 0;\n const upper = col.toUpperCase();\n for (let i = 0; i < upper.length; i++) {\n index = index * 26 + (upper.charCodeAt(i) - 65 + 1);\n }\n return index - 1;\n}\n\nexport function indexToColName(index: number): string {\n let num = index + 1;\n let name = '';\n while (num > 0) {\n const mod = (num - 1) % 26;\n name = String.fromCharCode(65 + mod) + name;\n num = Math.floor((num - mod) / 26);\n }\n return name;\n}\n\n// --- Ranges ---\n\n/**\n * A rectangular block of values. `values` is column-major (the order in which\n * `EvaluationContext.resolveRange` returns cells): `values[col * rows + row]`.\n */\nexport interface FormulaRange {\n rows: number;\n cols: number;\n values: any[];\n}\n\n/** Shapes of the arrays produced by range references and range-returning functions. */\nconst rangeShapes = new WeakMap<any[], { rows: number; cols: number }>();\n\n/** Records the shape of a column-major array so functions can treat it as a 2D range. */\nexport function withRangeShape<T extends any[]>(values: T, rows: number, cols: number): T {\n rangeShapes.set(values, { rows, cols });\n return values;\n}\n\n/** Views an array as a range. Arrays without a known shape are a single column. */\nexport function toFormulaRange(values: any[]): FormulaRange {\n const shape = rangeShapes.get(values);\n if (shape && shape.rows * shape.cols === values.length) return { ...shape, values };\n return { rows: values.length, cols: 1, values };\n}\n\nexport const rangeGet = (range: FormulaRange, row: number, col: number): any =>\n row < range.rows && col < range.cols ? range.values[col * range.rows + row] : '';\n\n/** Builds a column-major array (with its shape recorded) from a sub-block of a range. */\nexport function sliceRange(\n range: FormulaRange,\n rowStart: number,\n rowCount: number,\n colStart: number,\n colCount: number,\n): any[] {\n const out: any[] = [];\n for (let c = colStart; c < colStart + colCount; c++) {\n for (let r = rowStart; r < rowStart + rowCount; r++) out.push(rangeGet(range, r, c));\n }\n return withRangeShape(out, rowCount, colCount);\n}\n\n// --- Dates ---\n//\n// Dates are ISO text (\"2026-01-31\", or \"2026-01-31 13:45:00\" with a time), as\n// returned by TODAY(). Numbers are read as spreadsheet serial dates (days since\n// 1899-12-30), so values pasted from Excel or Numbers still work.\n\nconst MS_PER_DAY = 24 * 60 * 60 * 1000;\nconst pad = (n: number, width = 2) => String(n).padStart(width, '0');\n\n/** Parses a date value (ISO text, serial number or Date) into a local Date, or null. */\nexport function toDate(value: unknown): Date | null {\n if (value instanceof Date) return isNaN(value.getTime()) ? null : value;\n if (typeof value === 'number') return serialToDate(value);\n if (typeof value !== 'string' || FORMULA_ERRORS.has(value)) return null;\n const text = value.trim();\n if (text === '') return null;\n const iso = /^(\\d{4})-(\\d{1,2})-(\\d{1,2})(?:[ T](\\d{1,2}):(\\d{2})(?::(\\d{2}))?)?$/.exec(text);\n if (iso) {\n const [, y, m, d, hh = '0', mm = '0', ss = '0'] = iso;\n const date = new Date(Number(y), Number(m) - 1, Number(d), Number(hh), Number(mm), Number(ss));\n // Reject impossible dates such as 2026-02-30 instead of rolling them over.\n return date.getMonth() === Number(m) - 1 ? date : null;\n }\n const serial = numericValue(text);\n if (serial !== null) return serialToDate(serial);\n // Other textual dates (\"Jan 5, 2026\", \"1/5/2026\") use the platform parser.\n if (/[a-z/]/i.test(text)) {\n const parsed = Date.parse(text);\n return isNaN(parsed) ? null : new Date(parsed);\n }\n return null;\n}\n\n/** Spreadsheet serial number (days since 1899-12-30, fraction = time of day). */\nexport function dateToSerial(date: Date): number {\n const utc = Date.UTC(\n date.getFullYear(),\n date.getMonth(),\n date.getDate(),\n date.getHours(),\n date.getMinutes(),\n date.getSeconds(),\n );\n return cleanFloat((utc - Date.UTC(1899, 11, 30)) / MS_PER_DAY);\n}\n\nexport function serialToDate(serial: number): Date | null {\n if (!Number.isFinite(serial)) return null;\n const utc = new Date(Date.UTC(1899, 11, 30) + Math.round(serial * MS_PER_DAY));\n return new Date(\n utc.getUTCFullYear(),\n utc.getUTCMonth(),\n utc.getUTCDate(),\n utc.getUTCHours(),\n utc.getUTCMinutes(),\n utc.getUTCSeconds(),\n );\n}\n\n/** Formats a local date as \"YYYY-MM-DD\" (the format TODAY() returns). */\nexport const formatIsoDate = (date: Date): string =>\n `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;\n\n/** Formats a local date and time as \"YYYY-MM-DD HH:MM:SS\" (the format NOW() returns). */\nexport const formatIsoDateTime = (date: Date): string =>\n `${formatIsoDate(date)} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;\n\n/** Whole days from `start` to `end`, ignoring time of day and DST shifts. */\nexport const daysBetween = (start: Date, end: Date): number =>\n Math.round(\n (Date.UTC(end.getFullYear(), end.getMonth(), end.getDate()) -\n Date.UTC(start.getFullYear(), start.getMonth(), start.getDate())) /\n MS_PER_DAY,\n );\n","import { FORMULA_ERRORS, isBlank, isFormulaError, numericValue } from './values';\n\n/** Tests one value against a criterion. */\nexport type FormulaCriteriaPredicate = (value: unknown) => boolean;\n\n/**\n * Builds a regular expression from a spreadsheet wildcard pattern: `*` is any\n * run of characters, `?` any single character, and `~` escapes the next\n * character (`~*` is a literal asterisk). Matching is case-insensitive.\n */\nexport function wildcardToRegExp(pattern: string): RegExp {\n let source = '';\n for (let i = 0; i < pattern.length; i++) {\n const char = pattern[i];\n if (char === '~' && i + 1 < pattern.length) {\n source += escapeRegExp(pattern[++i]);\n } else if (char === '*') {\n source += '[\\\\s\\\\S]*';\n } else if (char === '?') {\n source += '[\\\\s\\\\S]';\n } else {\n source += escapeRegExp(char);\n }\n }\n return new RegExp(`^${source}$`, 'i');\n}\n\nconst escapeRegExp = (text: string) => text.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\nexport const hasWildcards = (pattern: string): boolean => /(^|[^~])[*?]/.test(pattern);\n\n/**\n * Parses a criterion as used by SUMIF, COUNTIFS etc.:\n * - a number or boolean matches equal values (`5` matches 5 and the text \"5\");\n * - text may start with `=`, `<>`, `<`, `<=`, `>` or `>=`. Numeric operands\n * compare numbers; text operands compare text case-insensitively;\n * - `=`/`<>` text operands and plain text support `*` and `?` wildcards;\n * - `\"\"` and `\"=\"` match blank cells, `\"<>\"` matches non-blank cells.\n * Error values in the data never match.\n */\nexport function parseCriteria(criterion: unknown): FormulaCriteriaPredicate {\n if (typeof criterion === 'number') {\n return (value) => numericValue(value) === criterion;\n }\n if (typeof criterion === 'boolean') {\n return (value) => value === criterion;\n }\n if (isBlank(criterion)) return (value) => isBlank(value);\n\n const text = String(criterion);\n const match = /^(<>|<=|>=|=|<|>)?([\\s\\S]*)$/.exec(text)!;\n const op = match[1] ?? '=';\n const operand = match[2];\n\n if (operand === '') {\n if (op === '=') return (value) => isBlank(value);\n if (op === '<>') return (value) => !isBlank(value);\n // \"<\" or \">\" with nothing to compare: nothing matches.\n return () => false;\n }\n\n const operandNumber = numericValue(operand);\n const operandUpper = operand.trim().toUpperCase();\n const operandBoolean = operandUpper === 'TRUE' ? true : operandUpper === 'FALSE' ? false : null;\n\n if (op === '=' || op === '<>') {\n let equals: FormulaCriteriaPredicate;\n if (operandNumber !== null) {\n equals = (value) => numericValue(value) === operandNumber;\n } else if (operandBoolean !== null) {\n equals = (value) => value === operandBoolean || (typeof value === 'string' && value.trim().toUpperCase() === operandUpper);\n } else if (isFormulaError(operand)) {\n // Counting errors (\"#N/A\") is the one case where error values match.\n return op === '=' ? (value) => value === operand : (value) => value !== operand && !isBlank(value);\n } else {\n const regex = wildcardToRegExp(operand);\n equals = (value) => typeof value === 'string' && !isFormulaError(value) && regex.test(value);\n }\n return op === '=' ? (value) => !isFormulaError(value) && equals(value) : (value) => !isFormulaError(value) && !equals(value);\n }\n\n const test = (cmp: number) =>\n op === '<' ? cmp < 0 : op === '<=' ? cmp <= 0 : op === '>' ? cmp > 0 : cmp >= 0;\n\n if (operandNumber !== null) {\n // Numeric comparisons only consider numbers (and numeric text).\n return (value) => {\n const num = numericValue(value);\n return num !== null && test(num - operandNumber);\n };\n }\n\n const lower = operand.toLowerCase();\n return (value) => {\n if (typeof value !== 'string' || value === '' || FORMULA_ERRORS.has(value) || numericValue(value) !== null) {\n return false;\n }\n const v = value.toLowerCase();\n return test(v < lower ? -1 : v > lower ? 1 : 0);\n };\n}\n","import { numericValue, roundHalfAwayFromZero, toDate, toText } from './values';\n\n/**\n * A subset of spreadsheet number format codes, as used by TEXT():\n * - numbers: `0`, `#`, `0.00`, `#,##0`, `#,##0.00`, `0%`, `0.0%`, `0.00E+00`,\n * literal prefixes/suffixes (`$#,##0.00`, `0.0 \"kg\"`), and\n * `positive;negative;zero` sections;\n * - dates and times: `yyyy yy mmmm mmm mm m dddd ddd dd d hh h mm ss AM/PM`\n * (`m`/`mm` after an hour or before seconds means minutes).\n * Text values are returned unchanged; unsupported codes are best effort.\n */\nexport function formatValueWithCode(value: unknown, format: string): string | null {\n if (isDateFormat(format)) {\n const date = toDate(value);\n return date ? formatDate(date, format) : null;\n }\n const num = typeof value === 'boolean' ? null : numericValue(value);\n return num === null ? toText(value) : formatNumber(num, format);\n}\n\n/** Splits a format into literal and code runs; quoted text and `\\x` escapes are literal. */\nfunction tokenize(format: string): Array<{ literal: boolean; text: string }> {\n const out: Array<{ literal: boolean; text: string }> = [];\n const push = (literal: boolean, text: string) => {\n const last = out[out.length - 1];\n if (last && last.literal === literal) last.text += text;\n else out.push({ literal, text });\n };\n for (let i = 0; i < format.length; i++) {\n const char = format[i];\n if (char === '\"') {\n const end = format.indexOf('\"', i + 1);\n const stop = end === -1 ? format.length : end;\n push(true, format.slice(i + 1, stop));\n i = stop;\n } else if (char === '\\\\' && i + 1 < format.length) {\n push(true, format[++i]);\n } else {\n push(false, char);\n }\n }\n return out;\n}\n\nconst codeText = (format: string) =>\n tokenize(format)\n .filter((t) => !t.literal)\n .map((t) => t.text)\n .join('');\n\nfunction isDateFormat(format: string): boolean {\n const code = codeText(format);\n if (/[0#?]/.test(code)) return false;\n return /[ydhs]|m/i.test(code);\n}\n\n// --- Numbers ---\n\nfunction formatNumber(num: number, format: string): string {\n const sections = splitSections(format);\n let section = sections[0];\n let value = num;\n let sign = num < 0 ? '-' : '';\n if (num < 0 && sections.length > 1) {\n section = sections[1];\n value = Math.abs(num);\n sign = '';\n } else if (num === 0 && sections.length > 2) {\n section = sections[2];\n }\n\n let prefix = '';\n let suffix = '';\n let pattern = '';\n for (const token of tokenize(section)) {\n if (token.literal) {\n if (pattern) suffix += token.text;\n else prefix += token.text;\n continue;\n }\n for (let i = 0; i < token.text.length; i++) {\n const char = token.text[i];\n const isExponent = /e/i.test(char) && /[+-]/.test(token.text[i + 1] ?? '');\n const isExponentSign = /[+-]/.test(char) && /e$/i.test(pattern);\n if (/[0#?.,]/.test(char) || (pattern && (isExponent || isExponentSign))) {\n pattern += char;\n } else if (pattern) {\n suffix += char;\n } else {\n prefix += char;\n }\n }\n }\n\n const percents = (prefix + suffix).split('%').length - 1;\n value = Math.abs(value) * Math.pow(100, percents);\n if (!pattern) return `${sign}${prefix}${suffix}`;\n\n const expMatch = /^([^Ee]*)[Ee]([+-])(0+)$/.exec(pattern);\n if (expMatch) {\n const [, mantissa, expSign, expDigits] = expMatch;\n const decimals = (mantissa.split('.')[1] ?? '').length;\n const [m, e] = value.toExponential(decimals).split('e');\n const exponent = Number(e);\n const expText = String(Math.abs(exponent)).padStart(expDigits.length, '0');\n const shownSign = exponent < 0 ? '-' : expSign === '+' ? '+' : '';\n return `${sign}${prefix}${m}E${shownSign}${expText}${suffix}`;\n }\n\n const [intPattern, decPattern = ''] = pattern.split('.');\n const maxDecimals = (decPattern.match(/[0#?]/g) ?? []).length;\n const minDecimals = (decPattern.match(/0/g) ?? []).length;\n const minInt = (intPattern.match(/0/g) ?? []).length;\n const grouping = intPattern.includes(',');\n\n const rounded = roundHalfAwayFromZero(value, maxDecimals);\n let [intPart, decPart = ''] = rounded.toFixed(maxDecimals).split('.');\n while (decPart.length > minDecimals && decPart.endsWith('0')) decPart = decPart.slice(0, -1);\n if (intPart === '0' && minInt === 0) intPart = '';\n intPart = intPart.padStart(minInt, '0');\n if (grouping) intPart = intPart.replace(/\\B(?=(\\d{3})+(?!\\d))/g, ',');\n const showSign = sign && /[1-9]/.test(intPart + decPart) ? sign : '';\n return `${showSign}${prefix}${intPart}${decPart ? `.${decPart}` : ''}${suffix}`;\n}\n\nfunction splitSections(format: string): string[] {\n const sections: string[] = [''];\n let quoted = false;\n for (let i = 0; i < format.length; i++) {\n const char = format[i];\n if (char === '\"') quoted = !quoted;\n if (char === '\\\\' && i + 1 < format.length) {\n sections[sections.length - 1] += char + format[++i];\n continue;\n }\n if (char === ';' && !quoted) sections.push('');\n else sections[sections.length - 1] += char;\n }\n return sections;\n}\n\n// --- Dates ---\n\nconst MONTHS = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];\nconst DAYS = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];\nconst pad = (n: number) => String(n).padStart(2, '0');\n\nfunction formatDate(date: Date, format: string): string {\n type Part = { literal: boolean; text: string };\n const parts: Part[] = [];\n for (const token of tokenize(format)) {\n if (token.literal) {\n parts.push(token);\n continue;\n }\n const re = /AM\\/PM|am\\/pm|A\\/P|a\\/p|y+|m+|d+|h+|s+|[^ymdhsaA]+|./gi;\n for (const match of token.text.match(re) ?? []) {\n const isCode = /^(AM\\/PM|A\\/P|y+|m+|d+|h+|s+)$/i.test(match);\n parts.push({ literal: !isCode, text: match });\n }\n }\n\n const codes = parts.map((p, i) => ({ ...p, i })).filter((p) => !p.literal);\n const twelveHour = codes.some((p) => /^(AM\\/PM|A\\/P)$/i.test(p.text));\n\n return parts\n .map((part, index) => {\n if (part.literal) return part.text;\n const code = part.text;\n const lower = code.toLowerCase();\n if (/^(am\\/pm|a\\/p)$/.test(lower)) {\n const pm = date.getHours() >= 12;\n const full = pm ? 'PM' : 'AM';\n const text = lower === 'a/p' ? full[0] : full;\n return code[0] === code[0].toLowerCase() ? text.toLowerCase() : text;\n }\n if (lower.startsWith('y')) {\n return lower.length <= 2 ? pad(date.getFullYear() % 100) : String(date.getFullYear());\n }\n if (lower.startsWith('d')) {\n if (lower.length >= 4) return DAYS[date.getDay()];\n if (lower.length === 3) return DAYS[date.getDay()].slice(0, 3);\n return lower.length === 2 ? pad(date.getDate()) : String(date.getDate());\n }\n if (lower.startsWith('h')) {\n let hours = date.getHours();\n if (twelveHour) hours = hours % 12 || 12;\n return lower.length >= 2 ? pad(hours) : String(hours);\n }\n if (lower.startsWith('s')) {\n return lower.length >= 2 ? pad(date.getSeconds()) : String(date.getSeconds());\n }\n // m: minutes right after an hour code or right before a seconds code.\n const position = codes.findIndex((c) => c.i === index);\n const prev = codes[position - 1]?.text.toLowerCase() ?? '';\n const next = codes[position + 1]?.text.toLowerCase() ?? '';\n if (lower.length <= 2 && (prev.startsWith('h') || next.startsWith('s'))) {\n return lower.length === 2 ? pad(date.getMinutes()) : String(date.getMinutes());\n }\n if (lower.length >= 4) return MONTHS[date.getMonth()];\n if (lower.length === 3) return MONTHS[date.getMonth()].slice(0, 3);\n return lower.length === 2 ? pad(date.getMonth() + 1) : String(date.getMonth() + 1);\n })\n .join('');\n}\n","import type {\n FormulaArgumentSpec,\n FormulaArgumentType,\n FormulaFunctionContext,\n FormulaFunctionDefinition,\n} from '../registry';\nimport { isFormulaError } from '../values';\n\n/** Shorthand for an argument spec. */\nexport const arg = (\n name: string,\n description: string,\n type: FormulaArgumentType = 'any',\n extra: Partial<FormulaArgumentSpec> = {},\n): FormulaArgumentSpec => ({ name, description, type, ...extra });\n\nexport const optional = (\n name: string,\n description: string,\n type: FormulaArgumentType = 'any',\n): FormulaArgumentSpec => arg(name, description, type, { optional: true });\n\nexport const repeating = (\n name: string,\n description: string,\n type: FormulaArgumentType = 'any',\n): FormulaArgumentSpec => arg(name, description, type, { repeating: true });\n\nexport type FunctionTable = FormulaFunctionDefinition[];\n\n/**\n * True for error strings. Narrows `number | string` (etc.) results of the\n * context helpers; plain `string` results (ctx.text) are not narrowed, since\n * text and error codes are both strings.\n */\nexport function failed(value: string): boolean;\nexport function failed<T>(value: T): value is Extract<T, string>;\nexport function failed(value: unknown): boolean {\n return isFormulaError(value);\n}\n\n/**\n * Applies `fn` to a numeric argument (`number`), propagating errors and\n * turning non-finite results into #NUM!.\n */\nexport function unaryMath(\n ctx: FormulaFunctionContext,\n fn: (value: number) => number | string,\n): number | string {\n const value = ctx.number(0);\n if (failed(value)) return value;\n const result = fn(value);\n if (typeof result === 'number' && !Number.isFinite(result)) {\n return ctx.error('#NUM!', `${ctx.name} produced a number that is out of range.`);\n }\n return result;\n}\n","import { cleanFloat, roundHalfAwayFromZero } from '../values';\nimport { arg, failed, optional, repeating, unaryMath, type FunctionTable } from './helpers';\n\nconst NUMBER = arg('number', 'The number to use.', 'number');\nconst NUM_DIGITS = optional('num_digits', 'Decimal places to round to; negative values round to the left of the decimal point (default 0).', 'number');\n\n/** Rounds `value` to `digits` places with `mode` (away from or toward zero). */\nfunction roundWith(value: number, digits: number, mode: 'up' | 'down'): number {\n const factor = Math.pow(10, Math.trunc(digits));\n // toPrecision strips float noise so ROUNDUP(0.1*3, 1) stays 0.3.\n const scaled = Number((Math.abs(value) * factor).toPrecision(15));\n const rounded = mode === 'up' ? Math.ceil(scaled) : Math.floor(scaled);\n return cleanFloat((Math.sign(value) * rounded) / factor);\n}\n\nexport const MATH_FUNCTIONS: FunctionTable = [\n {\n name: 'SUM',\n category: 'math',\n description: 'Adds numbers and the numbers in ranges. Text and blank cells are ignored.',\n args: [repeating('value', 'A number, cell or range to add.', 'number')],\n evaluate: (ctx) => {\n const nums = ctx.numbers();\n if (failed(nums)) return nums;\n let total = 0;\n for (const num of nums) total += num;\n return total;\n },\n },\n {\n name: 'PRODUCT',\n category: 'math',\n description: 'Multiplies numbers and the numbers in ranges. Text and blank cells are ignored.',\n args: [repeating('value', 'A number, cell or range to multiply.', 'number')],\n evaluate: (ctx) => {\n const nums = ctx.numbers();\n if (failed(nums)) return nums;\n if (nums.length === 0) return 0;\n let product = 1;\n for (const num of nums) product *= num;\n return cleanFloat(product);\n },\n },\n {\n name: 'ROUND',\n category: 'math',\n description: 'Rounds a number to a number of decimal places, halves away from zero.',\n args: [NUMBER, NUM_DIGITS],\n evaluate: (ctx) => {\n const num = ctx.number(0);\n if (failed(num)) return num;\n const decimals = ctx.number(1, 0);\n if (failed(decimals)) return decimals;\n return roundHalfAwayFromZero(num, Math.trunc(decimals));\n },\n },\n {\n name: 'ROUNDUP',\n category: 'math',\n description: 'Rounds a number away from zero to a number of decimal places.',\n args: [NUMBER, NUM_DIGITS],\n evaluate: (ctx) => {\n const num = ctx.number(0);\n if (failed(num)) return num;\n const digits = ctx.number(1, 0);\n if (failed(digits)) return digits;\n return roundWith(num, digits, 'up');\n },\n },\n {\n name: 'ROUNDDOWN',\n category: 'math',\n description: 'Rounds a number toward zero to a number of decimal places.',\n args: [NUMBER, NUM_DIGITS],\n evaluate: (ctx) => {\n const num = ctx.number(0);\n if (failed(num)) return num;\n const digits = ctx.number(1, 0);\n if (failed(digits)) return digits;\n return roundWith(num, digits, 'down');\n },\n },\n {\n name: 'INT',\n category: 'math',\n description: 'Rounds a number down to the nearest integer (INT(-1.5) is -2).',\n args: [NUMBER],\n evaluate: (ctx) => unaryMath(ctx, Math.floor),\n },\n {\n name: 'ABS',\n category: 'math',\n description: 'Returns the absolute value of a number.',\n args: [NUMBER],\n evaluate: (ctx) => unaryMath(ctx, Math.abs),\n },\n {\n name: 'SIGN',\n category: 'math',\n description: 'Returns 1 for positive numbers, -1 for negative numbers and 0 for zero.',\n args: [NUMBER],\n evaluate: (ctx) => unaryMath(ctx, (n) => (n > 0 ? 1 : n < 0 ? -1 : 0)),\n },\n {\n name: 'SQRT',\n category: 'math',\n description: 'Returns the square root of a number.',\n args: [NUMBER],\n evaluate: (ctx) =>\n unaryMath(ctx, (n) =>\n n < 0 ? ctx.argError(0, '#NUM!', \"can't be negative.\") : Math.sqrt(n),\n ),\n },\n {\n name: 'POWER',\n category: 'math',\n description: 'Raises a number to a power.',\n args: [arg('number', 'The base.', 'number'), arg('power', 'The exponent.', 'number')],\n evaluate: (ctx) => {\n const base = ctx.number(0);\n if (failed(base)) return base;\n const exponent = ctx.number(1);\n if (failed(exponent)) return exponent;\n if (base === 0 && exponent < 0) return ctx.error('#DIV/0!', 'POWER of zero to a negative exponent divides by zero.');\n const result = Math.pow(base, exponent);\n return Number.isFinite(result) ? result : ctx.error('#NUM!', 'POWER produced a number that is out of range.');\n },\n },\n {\n name: 'MOD',\n category: 'math',\n description: 'Returns the remainder after division. The result has the sign of the divisor.',\n args: [arg('number', 'The number to divide.', 'number'), arg('divisor', 'The number to divide by.', 'number')],\n evaluate: (ctx) => {\n const num = ctx.number(0);\n if (failed(num)) return num;\n const divisor = ctx.number(1);\n if (failed(divisor)) return divisor;\n if (divisor === 0) return ctx.argError(1, '#DIV/0!', \"can't be zero.\");\n return cleanFloat(num - divisor * Math.floor(num / divisor));\n },\n },\n {\n name: 'CEILING',\n category: 'math',\n description: 'Rounds a number up to the nearest multiple of significance.',\n args: [NUMBER, optional('significance', 'The multiple to round to (default 1).', 'number')],\n evaluate: (ctx) => roundToMultiple(ctx.name, ctx.number(0), ctx.number(1, 1), Math.ceil, ctx),\n },\n {\n name: 'FLOOR',\n category: 'math',\n description: 'Rounds a number down to the nearest multiple of significance.',\n args: [NUMBER, optional('significance', 'The multiple to round to (default 1).', 'number')],\n evaluate: (ctx) => roundToMultiple(ctx.name, ctx.number(0), ctx.number(1, 1), Math.floor, ctx),\n },\n {\n name: 'PI',\n category: 'math',\n description: 'Returns the number π (3.14159…).',\n args: [],\n evaluate: () => Math.PI,\n },\n {\n name: 'RAND',\n category: 'math',\n description: 'Returns a random number between 0 (inclusive) and 1 (exclusive). Changes on every recalculation.',\n args: [],\n volatile: true,\n evaluate: () => Math.random(),\n },\n {\n name: 'RANDBETWEEN',\n category: 'math',\n description: 'Returns a random integer between bottom and top, inclusive. Changes on every recalculation.',\n args: [arg('bottom', 'The smallest integer to return.', 'number'), arg('top', 'The largest integer to return.', 'number')],\n volatile: true,\n evaluate: (ctx) => {\n const bottom = ctx.number(0);\n if (failed(bottom)) return bottom;\n const top = ctx.number(1);\n if (failed(top)) return top;\n const lo = Math.ceil(bottom);\n const hi = Math.floor(top);\n if (lo > hi) return ctx.error('#NUM!', 'RANDBETWEEN needs bottom to be less than or equal to top.');\n return lo + Math.floor(Math.random() * (hi - lo + 1));\n },\n },\n];\n\nfunction roundToMultiple(\n name: string,\n number: number | string,\n significance: number | string,\n round: (n: number) => number,\n ctx: { error: (code: '#NUM!' | '#DIV/0!', message?: string) => string },\n): number | string {\n if (failed(number)) return number;\n if (failed(significance)) return significance;\n if (number === 0) return 0;\n if (significance === 0) {\n return name === 'FLOOR' ? ctx.error('#DIV/0!', 'FLOOR needs a significance other than zero.') : 0;\n }\n if (number > 0 && significance < 0) {\n return ctx.error('#NUM!', `${name} can't round a positive number to a negative significance.`);\n }\n return cleanFloat(round(cleanFloat(number / significance)) * significance);\n}\n","import { cleanFloat, isBlank, isFormulaError } from '../values';\nimport type { FormulaFunctionContext } from '../registry';\nimport { arg, failed, optional, repeating, type FunctionTable } from './helpers';\n\nconst VALUES = repeating('value', 'A number, cell or range.', 'number');\n\n/** Numbers of argument 0 plus a positive integer k from argument 1, for LARGE/SMALL. */\nfunction kth(ctx: FormulaFunctionContext, pick: (sorted: number[], k: number) => number): number | string {\n const nums = ctx.numbers(0, 1);\n if (failed(nums)) return nums;\n const k = ctx.number(1);\n if (failed(k)) return k;\n const index = Math.ceil(k);\n if (index < 1 || index > nums.length) {\n return ctx.argError(1, '#NUM!', `must be between 1 and the number of values (${nums.length}).`);\n }\n return pick([...nums].sort((a, b) => a - b), index);\n}\n\nfunction variance(ctx: FormulaFunctionContext): number | string {\n const nums = ctx.numbers();\n if (failed(nums)) return nums;\n if (nums.length < 2) return ctx.error('#DIV/0!', `${ctx.name} needs at least two numbers.`);\n let mean = 0;\n for (const num of nums) mean += num;\n mean /= nums.length;\n let squares = 0;\n for (const num of nums) squares += (num - mean) ** 2;\n return squares / (nums.length - 1);\n}\n\nexport const STATISTICAL_FUNCTIONS: FunctionTable = [\n {\n name: 'AVERAGE',\n category: 'statistical',\n description: 'Returns the arithmetic mean of numbers. Blank cells and text are ignored.',\n args: [VALUES],\n evaluate: (ctx) => {\n const items = ctx.flatValues();\n const error = items.find(isFormulaError);\n if (error) return error;\n let total = 0;\n let count = 0;\n for (const item of items) {\n const num = Number(item);\n if (!isNaN(num) && !isBlank(item)) {\n total += num;\n count++;\n }\n }\n return count === 0 ? 0 : total / count;\n },\n },\n {\n name: 'COUNT',\n category: 'statistical',\n description: 'Counts the values that are numbers.',\n args: [repeating('value', 'A value, cell or range to count.')],\n evaluate: (ctx) => {\n let count = 0;\n for (const item of ctx.flatValues()) {\n if (!isNaN(Number(item)) && !isBlank(item)) count++;\n }\n return count;\n },\n },\n {\n name: 'COUNTA',\n category: 'statistical',\n description: 'Counts the values that are not blank.',\n args: [repeating('value', 'A value, cell or range to count.')],\n evaluate: (ctx) => ctx.flatValues().filter((item) => !isBlank(item)).length,\n },\n {\n name: 'COUNTBLANK',\n category: 'statistical',\n description: 'Counts the blank cells in a range.',\n args: [arg('range', 'The range to check.', 'range')],\n evaluate: (ctx) => {\n const range = ctx.range(0);\n if (failed(range)) return range;\n return range.values.filter(isBlank).length;\n },\n },\n {\n name: 'MIN',\n category: 'statistical',\n description: 'Returns the smallest number. Text and blank cells are ignored.',\n args: [VALUES],\n evaluate: (ctx) => {\n const nums = ctx.numbers();\n if (failed(nums)) return nums;\n if (nums.length === 0) return 0;\n // Loop instead of Math.min(...nums), which overflows the stack on large ranges.\n let result = nums[0];\n for (const num of nums) result = Math.min(result, num);\n return result;\n },\n },\n {\n name: 'MAX',\n category: 'statistical',\n description: 'Returns the largest number. Text and blank cells are ignored.',\n args: [VALUES],\n evaluate: (ctx) => {\n const nums = ctx.numbers();\n if (failed(nums)) return nums;\n if (nums.length === 0) return 0;\n let result = nums[0];\n for (const num of nums) result = Math.max(result, num);\n return result;\n },\n },\n {\n name: 'MEDIAN',\n category: 'statistical',\n description: 'Returns the middle number of a set of numbers.',\n args: [VALUES],\n evaluate: (ctx) => {\n const nums = ctx.numbers();\n if (failed(nums)) return nums;\n if (nums.length === 0) return ctx.error('#NUM!', 'MEDIAN needs at least one number.');\n const sorted = [...nums].sort((a, b) => a - b);\n const mid = Math.floor(sorted.length / 2);\n return sorted.length % 2 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;\n },\n },\n {\n name: 'MODE',\n category: 'statistical',\n description: 'Returns the most frequently occurring number. Ties go to the number that appears first.',\n args: [VALUES],\n evaluate: (ctx) => {\n const nums = ctx.numbers();\n if (failed(nums)) return nums;\n const counts = new Map<number, number>();\n let best: number | null = null;\n let bestCount = 1;\n for (const num of nums) {\n const count = (counts.get(num) ?? 0) + 1;\n counts.set(num, count);\n if (count > bestCount) {\n best = num;\n bestCount = count;\n }\n }\n // A later number that ties the best count must not replace an earlier one.\n if (best !== null) {\n for (const num of nums) {\n if (counts.get(num) === bestCount) return num;\n }\n }\n return ctx.error('#N/A', 'MODE found no number that appears more than once.');\n },\n },\n {\n name: 'STDEV',\n category: 'statistical',\n description: 'Estimates the standard deviation of a sample.',\n args: [VALUES],\n evaluate: (ctx) => {\n const v = variance(ctx);\n return failed(v) ? v : cleanFloat(Math.sqrt(v));\n },\n },\n {\n name: 'VAR',\n category: 'statistical',\n description: 'Estimates the variance of a sample.',\n args: [VALUES],\n evaluate: (ctx) => {\n const v = variance(ctx);\n return failed(v) ? v : cleanFloat(v);\n },\n },\n {\n name: 'LARGE',\n category: 'statistical',\n description: 'Returns the k-th largest number (LARGE(range, 1) is the maximum).',\n args: [arg('array', 'The numbers to look through.', 'range'), arg('k', 'Position from the largest (1 = largest).', 'number')],\n evaluate: (ctx) => kth(ctx, (sorted, k) => sorted[sorted.length - k]),\n },\n {\n name: 'SMALL',\n category: 'statistical',\n description: 'Returns the k-th smallest number (SMALL(range, 1) is the minimum).',\n args: [arg('array', 'The numbers to look through.', 'range'), arg('k', 'Position from the smallest (1 = smallest).', 'number')],\n evaluate: (ctx) => kth(ctx, (sorted, k) => sorted[k - 1]),\n },\n {\n name: 'RANK',\n category: 'statistical',\n description: 'Returns the rank of a number in a list. Equal numbers share a rank.',\n args: [\n arg('number', 'The number to rank.', 'number'),\n arg('ref', 'The list of numbers to rank against.', 'range'),\n optional('order', '0 or omitted ranks the largest as 1; any other value ranks the smallest as 1.', 'number'),\n ],\n evaluate: (ctx) => {\n const num = ctx.number(0);\n if (failed(num)) return num;\n const nums = ctx.numbers(1, 2);\n if (failed(nums)) return nums;\n const order = ctx.number(2, 0);\n if (failed(order)) return order;\n if (!nums.includes(num)) return ctx.argError(0, '#N/A', `(${num}) must be one of the numbers in argument 2.`);\n let rank = 1;\n for (const other of nums) {\n if (order === 0 ? other > num : other < num) rank++;\n }\n return rank;\n },\n },\n];\n","import type { FormulaFunctionContext } from '../registry';\nimport { parseCriteria } from '../criteria';\nimport { isFormulaError, numericValue, rangeGet, type FormulaRange } from '../values';\nimport { arg, failed, optional, repeating, type FunctionTable } from './helpers';\n\nconst CRITERIA_DESCRIPTION =\n 'The condition, e.g. 5, \">5\", \"<>done\", \"a*\" (wildcards * and ?), or \"\" for blank cells.';\n\n/**\n * Evaluates (criteria_range, criteria) argument pairs starting at `firstPair`\n * against cells of `base`'s shape. Returns one flag per cell (column-major),\n * or an error string.\n */\nfunction matchMask(\n ctx: FormulaFunctionContext,\n base: FormulaRange,\n baseIndex: number,\n firstPair: number,\n): boolean[] | string {\n const mask = new Array<boolean>(base.rows * base.cols).fill(true);\n for (let i = firstPair; i + 1 < ctx.args.length; i += 2) {\n const range = ctx.range(i);\n if (failed(range)) return range;\n if (i !== baseIndex && (range.rows !== base.rows || range.cols !== base.cols)) {\n return ctx.argError(i, '#VALUE!', `must be the same size as argument ${baseIndex + 1} (${base.rows}×${base.cols}).`);\n }\n const criterion = ctx.scalar(i + 1);\n if (isFormulaError(criterion)) return criterion;\n const matches = parseCriteria(criterion);\n for (let k = 0; k < mask.length; k++) {\n if (mask[k] && !matches(range.values[k])) mask[k] = false;\n }\n }\n return mask;\n}\n\n/** Numbers of `target` (resized to `base`'s shape) at matching positions. */\nfunction matchedNumbers(target: FormulaRange, base: FormulaRange, mask: boolean[]): number[] | string {\n const nums: number[] = [];\n for (let c = 0; c < base.cols; c++) {\n for (let r = 0; r < base.rows; r++) {\n if (!mask[c * base.rows + r]) continue;\n const value = rangeGet(target, r, c);\n if (isFormulaError(value)) return value;\n const num = numericValue(value);\n if (num !== null) nums.push(num);\n }\n }\n return nums;\n}\n\ntype Aggregate = (nums: number[], ctx: FormulaFunctionContext) => number | string;\n\nconst sum: Aggregate = (nums) => {\n let total = 0;\n for (const num of nums) total += num;\n return total;\n};\nconst average: Aggregate = (nums, ctx) =>\n nums.length === 0\n ? ctx.error('#DIV/0!', `${ctx.name} found no matching numbers to average.`)\n : (sum(nums, ctx) as number) / nums.length;\nconst max: Aggregate = (nums) => nums.reduce((a, b) => Math.max(a, b), nums.length ? -Infinity : 0);\nconst min: Aggregate = (nums) => nums.reduce((a, b) => Math.min(a, b), nums.length ? Infinity : 0);\n\n/** SUMIF / AVERAGEIF: (range, criteria, [target_range]). */\nfunction singleCriterion(aggregate: Aggregate) {\n return (ctx: FormulaFunctionContext) => {\n const base = ctx.range(0);\n if (failed(base)) return base;\n const mask = matchMask(ctx, base, 0, 0);\n if (failed(mask)) return mask;\n let target = base;\n if (ctx.has(2)) {\n const range = ctx.range(2);\n if (failed(range)) return range;\n target = range;\n }\n const nums = matchedNumbers(target, base, mask);\n return failed(nums) ? nums : aggregate(nums, ctx);\n };\n}\n\n/** SUMIFS / AVERAGEIFS / MAXIFS / MINIFS: (target_range, criteria_range1, criteria1, ...). */\nfunction multipleCriteria(aggregate: Aggregate) {\n return (ctx: FormulaFunctionContext) => {\n const target = ctx.range(0);\n if (failed(target)) return target;\n const mask = matchMask(ctx, target, 0, 1);\n if (failed(mask)) return mask;\n const nums = matchedNumbers(target, target, mask);\n return failed(nums) ? nums : aggregate(nums, ctx);\n };\n}\n\nconst criteriaPair = [\n repeating('criteria_range', 'A range to test. Must be the same size as the other ranges.', 'range'),\n repeating('criteria', CRITERIA_DESCRIPTION, 'criteria'),\n];\n\nexport const CONDITIONAL_FUNCTIONS: FunctionTable = [\n {\n name: 'SUMIF',\n category: 'math',\n description: 'Adds the cells that meet a condition.',\n args: [\n arg('range', 'The range to test.', 'range'),\n arg('criteria', CRITERIA_DESCRIPTION, 'criteria'),\n optional('sum_range', 'The cells to add (default: range itself).', 'range'),\n ],\n evaluate: singleCriterion(sum),\n },\n {\n name: 'SUMIFS',\n category: 'math',\n description: 'Adds the cells that meet every condition.',\n args: [arg('sum_range', 'The cells to add.', 'range'), ...criteriaPair],\n evaluate: multipleCriteria(sum),\n },\n {\n name: 'COUNTIF',\n category: 'statistical',\n description: 'Counts the cells that meet a condition.',\n args: [arg('range', 'The range to test.', 'range'), arg('criteria', CRITERIA_DESCRIPTION, 'criteria')],\n evaluate: (ctx) => {\n const base = ctx.range(0);\n if (failed(base)) return base;\n const mask = matchMask(ctx, base, 0, 0);\n return failed(mask) ? mask : mask.filter(Boolean).length;\n },\n },\n {\n name: 'COUNTIFS',\n category: 'statistical',\n description: 'Counts the cells that meet every condition.',\n args: criteriaPair,\n evaluate: (ctx) => {\n const base = ctx.range(0);\n if (failed(base)) return base;\n const mask = matchMask(ctx, base, 0, 0);\n return failed(mask) ? mask : mask.filter(Boolean).length;\n },\n },\n {\n name: 'AVERAGEIF',\n category: 'statistical',\n description: 'Averages the cells that meet a condition.',\n args: [\n arg('range', 'The range to test.', 'range'),\n arg('criteria', CRITERIA_DESCRIPTION, 'criteria'),\n optional('average_range', 'The cells to average (default: range itself).', 'range'),\n ],\n evaluate: singleCriterion(average),\n },\n {\n name: 'AVERAGEIFS',\n category: 'statistical',\n description: 'Averages the cells that meet every condition.',\n args: [arg('average_range', 'The cells to average.', 'range'), ...criteriaPair],\n evaluate: multipleCriteria(average),\n },\n {\n name: 'MAXIFS',\n category: 'statistical',\n description: 'Returns the largest number among the cells that meet every condition (0 if none match).',\n args: [arg('max_range', 'The cells to take the maximum of.', 'range'), ...criteriaPair],\n evaluate: multipleCriteria(max),\n },\n {\n name: 'MINIFS',\n category: 'statistical',\n description: 'Returns the smallest number among the cells that meet every condition (0 if none match).',\n args: [arg('min_range', 'The cells to take the minimum of.', 'range'), ...criteriaPair],\n evaluate: multipleCriteria(min),\n },\n];\n","import type { FormulaFunctionContext } from '../registry';\nimport { compareValues, isBlank, isFormulaError, normalizeValue, numericValue, toBoolean } from '../values';\nimport { arg, failed, optional, repeating, type FunctionTable } from './helpers';\n\n/**\n * Logical values among the arguments, for AND/OR/XOR. In ranges, blanks and\n * non-logical text are skipped; a direct text argument is #VALUE!.\n */\nfunction logicalValues(ctx: FormulaFunctionContext): boolean[] | string {\n const values: boolean[] = [];\n for (let i = 0; i < ctx.args.length; i++) {\n const value = ctx.value(i);\n if (Array.isArray(value)) {\n for (const item of value) {\n if (isFormulaError(item)) return item;\n if (isBlank(item)) continue;\n if (typeof item === 'boolean') values.push(item);\n else if (typeof item === 'number') values.push(item !== 0);\n else {\n const num = numericValue(item);\n const bool = num !== null ? num !== 0 : toBoolean(item);\n if (typeof bool === 'boolean') values.push(bool);\n }\n }\n continue;\n }\n const bool = ctx.boolean(i);\n if (failed(bool)) return bool;\n values.push(bool);\n }\n if (values.length === 0) return ctx.error('#VALUE!', `${ctx.name} found no logical values to test.`);\n return values;\n}\n\nconst LOGICALS = repeating('logical', 'A condition, logical value or range of logical values.', 'logical');\n\nexport const LOGICAL_FUNCTIONS: FunctionTable = [\n {\n name: 'IF',\n category: 'logical',\n description: 'Returns one value if a condition is true and another if it is false.',\n args: [\n arg('logical_test', 'The condition to test.', 'logical'),\n arg('value_if_true', 'The result when the condition is TRUE.'),\n optional('value_if_false', 'The result when the condition is FALSE (default FALSE).'),\n ],\n evaluate: (ctx) => {\n const condition = ctx.boolean(0);\n if (failed(condition)) return condition;\n if (condition) return ctx.value(1);\n return ctx.has(2) ? ctx.value(2) : false;\n },\n },\n {\n name: 'IFERROR',\n category: 'logical',\n description: 'Returns a value, or an alternative if the value is an error.',\n args: [arg('value', 'The value to check.'), arg('value_if_error', 'The result when value is an error.')],\n evaluate: (ctx) => {\n const value = ctx.value(0);\n return isFormulaError(value) ? ctx.value(1) : value;\n },\n },\n {\n name: 'IFNA',\n category: 'logical',\n description: 'Returns a value, or an alternative if the value is #N/A.',\n args: [arg('value', 'The value to check.'), arg('value_if_na', 'The result when value is #N/A.')],\n evaluate: (ctx) => {\n const value = ctx.value(0);\n return value === '#N/A' ? ctx.value(1) : value;\n },\n },\n {\n name: 'IFS',\n category: 'logical',\n description: 'Returns the value for the first condition that is TRUE.',\n args: [\n repeating('logical_test', 'A condition to test.', 'logical'),\n repeating('value_if_true', 'The result when this condition is the first TRUE one.'),\n ],\n evaluate: (ctx) => {\n for (let i = 0; i + 1 < ctx.args.length; i += 2) {\n const condition = ctx.boolean(i);\n if (failed(condition)) return condition;\n if (condition) return ctx.value(i + 1);\n }\n return ctx.error('#N/A', 'None of the conditions in IFS were TRUE.');\n },\n },\n {\n name: 'SWITCH',\n category: 'logical',\n description: 'Compares an expression with a list of values and returns the result for the first match. An extra last argument is the default.',\n args: [\n arg('expression', 'The value to compare.'),\n repeating('value', 'A value to compare the expression with.'),\n repeating('result', 'The result when the expression equals this value.'),\n ],\n allowTrailingArgument: true,\n evaluate: (ctx) => {\n const expression = ctx.scalar(0);\n if (isFormulaError(expression)) return expression;\n const target = normalizeValue(expression);\n let i = 1;\n for (; i + 1 < ctx.args.length; i += 2) {\n const candidate = ctx.scalar(i);\n if (isFormulaError(candidate)) return candidate;\n if (compareValues(target, normalizeValue(candidate)) === 0) return ctx.value(i + 1);\n }\n if (i < ctx.args.length) return ctx.value(i);\n return ctx.error('#N/A', 'SWITCH found no matching value and has no default.');\n },\n },\n {\n name: 'AND',\n category: 'logical',\n description: 'Returns TRUE if every argument is TRUE.',\n args: [LOGICALS],\n evaluate: (ctx) => {\n const values = logicalValues(ctx);\n return failed(values) ? values : values.every(Boolean);\n },\n },\n {\n name: 'OR',\n category: 'logical',\n description: 'Returns TRUE if any argument is TRUE.',\n args: [LOGICALS],\n evaluate: (ctx) => {\n const values = logicalValues(ctx);\n return failed(values) ? values : values.some(Boolean);\n },\n },\n {\n name: 'XOR',\n category: 'logical',\n description: 'Returns TRUE if an odd number of arguments are TRUE.',\n args: [LOGICALS],\n evaluate: (ctx) => {\n const values = logicalValues(ctx);\n return failed(values) ? values : values.filter(Boolean).length % 2 === 1;\n },\n },\n {\n name: 'NOT',\n category: 'logical',\n description: 'Reverses a logical value.',\n args: [arg('logical', 'The value to reverse.', 'logical')],\n evaluate: (ctx) => {\n const value = ctx.boolean(0);\n return failed(value) ? value : !value;\n },\n },\n];\n","import type { FormulaFunctionContext } from '../registry';\nimport { wildcardToRegExp } from '../criteria';\nimport { formatValueWithCode } from '../format';\nimport { dateToSerial, isBlank, isFormulaError, toDate, toText } from '../values';\nimport { arg, failed, optional, repeating, type FunctionTable } from './helpers';\n\nconst TEXT = arg('text', 'The text to use.', 'text');\n\n/** Text argument plus a non-negative character count (default `fallback`). */\nfunction textAndCount(ctx: FormulaFunctionContext, countIndex: number, fallback?: number) {\n const text = ctx.text(0);\n if (failed(text)) return text;\n const count = ctx.integer(countIndex, fallback);\n if (failed(count)) return count;\n if (count < 0) return ctx.argError(countIndex, '#VALUE!', \"can't be negative.\");\n return { text, count };\n}\n\n/** Converts text such as \"1,234.5\", \"$12\", \"50%\" or an ISO date to a number, or null. */\nexport function parseNumericText(text: string): number | null {\n let trimmed = text.trim();\n if (trimmed === '') return null;\n let scale = 1;\n if (trimmed.endsWith('%')) {\n trimmed = trimmed.slice(0, -1).trim();\n scale = 0.01;\n }\n const negative = /^\\(.*\\)$/.test(trimmed);\n if (negative) trimmed = trimmed.slice(1, -1);\n const cleaned = trimmed.replace(/^([+-]?)[$€£¥]/, '$1').replace(/,(?=\\d{3}(\\D|$))/g, '');\n if (cleaned !== '' && /^[+-]?(\\d+\\.?\\d*|\\.\\d+)(e[+-]?\\d+)?$/i.test(cleaned)) {\n const num = Number(cleaned) * scale;\n return negative ? -num : num;\n }\n if (scale === 1 && !negative) {\n const date = /^\\d{4}-\\d{1,2}-\\d{1,2}/.test(trimmed) ? toDate(trimmed) : null;\n if (date) return dateToSerial(date);\n }\n return null;\n}\n\n/** FIND / SEARCH: 1-based position of `find_text` in `within_text`. */\nfunction findText(ctx: FormulaFunctionContext, caseInsensitive: boolean): number | string {\n const needle = ctx.text(0);\n if (failed(needle)) return needle;\n const haystack = ctx.text(1);\n if (failed(haystack)) return haystack;\n const start = ctx.integer(2, 1);\n if (failed(start)) return start;\n if (start < 1 || start > haystack.length + 1) {\n return ctx.argError(2, '#VALUE!', `must be between 1 and the length of the text (${haystack.length}).`);\n }\n let index: number;\n if (caseInsensitive) {\n // SEARCH supports wildcards: find the first start position where the pattern matches a prefix.\n const pattern = wildcardToRegExp(needle).source.slice(1, -1);\n const regex = new RegExp(pattern, 'i');\n const match = regex.exec(haystack.slice(start - 1));\n index = match ? match.index + start - 1 : -1;\n } else {\n index = haystack.indexOf(needle, start - 1);\n }\n if (index === -1) return ctx.error('#VALUE!', `${ctx.name} couldn't find \"${needle}\" in \"${haystack}\".`);\n return index + 1;\n}\n\nexport const TEXT_FUNCTIONS: FunctionTable = [\n {\n name: 'CONCAT',\n category: 'text',\n description: 'Joins text, numbers and the values of ranges into one piece of text.',\n args: [repeating('text', 'A value, cell or range to join.', 'text')],\n evaluate: (ctx) => {\n const items = ctx.flatValues();\n const error = items.find(isFormulaError);\n if (error) return error;\n return items.map(toText).join('');\n },\n },\n {\n name: 'TEXTJOIN',\n category: 'text',\n description: 'Joins values with a delimiter, optionally skipping empty values.',\n args: [\n arg('delimiter', 'Text to put between values.', 'text'),\n arg('ignore_empty', 'TRUE to skip empty values.', 'logical'),\n repeating('text', 'A value, cell or range to join.', 'text'),\n ],\n evaluate: (ctx) => {\n const delimiter = ctx.text(0);\n if (failed(delimiter)) return delimiter;\n const ignoreEmpty = ctx.boolean(1);\n if (failed(ignoreEmpty)) return ignoreEmpty;\n const items = ctx.flatValues(2);\n const error = items.find(isFormulaError);\n if (error) return error;\n return items\n .map(toText)\n .filter((text) => !ignoreEmpty || text !== '')\n .join(delimiter);\n },\n },\n {\n name: 'UPPER',\n category: 'text',\n description: 'Converts text to upper case.',\n args: [TEXT],\n evaluate: (ctx) => {\n const text = ctx.text(0);\n return failed(text) ? text : text.toUpperCase();\n },\n },\n {\n name: 'LOWER',\n category: 'text',\n description: 'Converts text to lower case.',\n args: [TEXT],\n evaluate: (ctx) => {\n const text = ctx.text(0);\n return failed(text) ? text : text.toLowerCase();\n },\n },\n {\n name: 'PROPER',\n category: 'text',\n description: 'Capitalizes the first letter of each word and lower-cases the rest.',\n args: [TEXT],\n evaluate: (ctx) => {\n const text = ctx.text(0);\n if (failed(text)) return text;\n return text.toLowerCase().replace(/(^|[^\\p{L}])(\\p{L})/gu, (_, before, letter) => before + letter.toUpperCase());\n },\n },\n {\n name: 'TRIM',\n category: 'text',\n description: 'Removes leading and trailing spaces.',\n args: [TEXT],\n evaluate: (ctx) => {\n const text = ctx.text(0);\n return failed(text) ? text : text.trim();\n },\n },\n {\n name: 'LEN',\n category: 'text',\n description: 'Returns the number of characters in text.',\n args: [TEXT],\n evaluate: (ctx) => {\n const text = ctx.text(0);\n return failed(text) ? text : text.length;\n },\n },\n {\n name: 'LEFT',\n category: 'text',\n description: 'Returns the first characters of text.',\n args: [TEXT, optional('num_chars', 'How many characters to return (default 1).', 'number')],\n evaluate: (ctx) => {\n const parts = textAndCount(ctx, 1, 1);\n return typeof parts === 'string' ? parts : parts.text.slice(0, parts.count);\n },\n },\n {\n name: 'RIGHT',\n category: 'text',\n description: 'Returns the last characters of text.',\n args: [TEXT, optional('num_chars', 'How many characters to return (default 1).', 'number')],\n evaluate: (ctx) => {\n const parts = textAndCount(ctx, 1, 1);\n if (typeof parts === 'string') return parts;\n return parts.count === 0 ? '' : parts.text.slice(-parts.count);\n },\n },\n {\n name: 'MID',\n category: 'text',\n description: 'Returns characters from the middle of text, starting at a position.',\n args: [\n TEXT,\n arg('start_num', 'Position of the first character (1 = first).', 'number'),\n arg('num_chars', 'How many characters to return.', 'number'),\n ],\n evaluate: (ctx) => {\n const parts = textAndCount(ctx, 2);\n if (typeof parts === 'string') return parts;\n const start = ctx.integer(1);\n if (failed(start)) return start;\n if (start < 1) return ctx.argError(1, '#VALUE!', 'must be 1 or more.');\n return parts.text.slice(start - 1, start - 1 + parts.count);\n },\n },\n {\n name: 'FIND',\n category: 'text',\n description: 'Returns the position of text within other text (case-sensitive, no wildcards).',\n args: [\n arg('find_text', 'The text to find.', 'text'),\n arg('within_text', 'The text to search.', 'text'),\n optional('start_num', 'Position to start searching from (default 1).', 'number'),\n ],\n evaluate: (ctx) => findText(ctx, false),\n },\n {\n name: 'SEARCH',\n category: 'text',\n description: 'Returns the position of text within other text (case-insensitive, supports * and ? wildcards).',\n args: [\n arg('find_text', 'The text to find.', 'text'),\n arg('within_text', 'The text to search.', 'text'),\n optional('start_num', 'Position to start searching from (default 1).', 'number'),\n ],\n evaluate: (ctx) => findText(ctx, true),\n },\n {\n name: 'SUBSTITUTE',\n category: 'text',\n description: 'Replaces occurrences of old text with new text (all of them, or only the given instance).',\n args: [\n TEXT,\n arg('old_text', 'The text to replace.', 'text'),\n arg('new_text', 'The replacement text.', 'text'),\n optional('instance_num', 'Which occurrence to replace (default: all).', 'number'),\n ],\n evaluate: (ctx) => {\n const text = ctx.text(0);\n if (failed(text)) return text;\n const oldText = ctx.text(1);\n if (failed(oldText)) return oldText;\n const newText = ctx.text(2);\n if (failed(newText)) return newText;\n if (oldText === '') return text;\n if (!ctx.has(3)) return text.split(oldText).join(newText);\n const instance = ctx.integer(3);\n if (failed(instance)) return instance;\n if (instance < 1) return ctx.argError(3, '#VALUE!', 'must be 1 or more.');\n let index = -1;\n for (let n = 0; n < instance; n++) {\n index = text.indexOf(oldText, index + 1);\n if (index === -1) return text;\n }\n return text.slice(0, index) + newText + text.slice(index + oldText.length);\n },\n },\n {\n name: 'REPLACE',\n category: 'text',\n description: 'Replaces part of text, by position, with new text.',\n args: [\n arg('old_text', 'The text to change.', 'text'),\n arg('start_num', 'Position of the first character to replace (1 = first).', 'number'),\n arg('num_chars', 'How many characters to replace.', 'number'),\n arg('new_text', 'The replacement text.', 'text'),\n ],\n evaluate: (ctx) => {\n const text = ctx.text(0);\n if (failed(text)) return text;\n const start = ctx.integer(1);\n if (failed(start)) return start;\n if (start < 1) return ctx.argError(1, '#VALUE!', 'must be 1 or more.');\n const count = ctx.integer(2);\n if (failed(count)) return count;\n if (count < 0) return ctx.argError(2, '#VALUE!', \"can't be negative.\");\n const newText = ctx.text(3);\n if (failed(newText)) return newText;\n return text.slice(0, start - 1) + newText + text.slice(start - 1 + count);\n },\n },\n {\n name: 'REPT',\n category: 'text',\n description: 'Repeats text a number of times.',\n args: [TEXT, arg('number_times', 'How many times to repeat the text.', 'number')],\n evaluate: (ctx) => {\n const parts = textAndCount(ctx, 1);\n if (typeof parts === 'string') return parts;\n if (parts.text.length * parts.count > 32767) {\n return ctx.error('#VALUE!', 'REPT would produce text longer than 32,767 characters.');\n }\n return parts.text.repeat(parts.count);\n },\n },\n {\n name: 'EXACT',\n category: 'text',\n description: 'Returns TRUE if two pieces of text are identical, including case.',\n args: [arg('text1', 'The first text.', 'text'), arg('text2', 'The second text.', 'text')],\n evaluate: (ctx) => {\n const a = ctx.text(0);\n if (failed(a)) return a;\n const b = ctx.text(1);\n if (failed(b)) return b;\n return a === b;\n },\n },\n {\n name: 'VALUE',\n category: 'text',\n description: 'Converts text that looks like a number (e.g. \"1,234.5\", \"50%\", \"$12\") or an ISO date to a number.',\n args: [TEXT],\n evaluate: (ctx) => {\n const value = ctx.scalar(0);\n if (isFormulaError(value)) return value;\n if (typeof value === 'number') return value;\n if (isBlank(value)) return 0;\n const num = parseNumericText(toText(value));\n if (num === null) return ctx.argError(0, '#VALUE!', `(\"${toText(value)}\") can't be converted to a number.`);\n return num;\n },\n },\n {\n name: 'TEXT',\n category: 'text',\n description: 'Formats a number or date as text using a format code such as \"0.00\", \"#,##0\", \"0%\" or \"yyyy-mm-dd\".',\n args: [arg('value', 'The number or date to format.'), arg('format_text', 'The format code.', 'text')],\n evaluate: (ctx) => {\n const value = ctx.scalar(0);\n if (isFormulaError(value)) return value;\n const format = ctx.text(1);\n if (failed(format)) return format;\n const result = formatValueWithCode(value, format);\n return result ?? ctx.argError(0, '#VALUE!', `isn't a date, so it can't use the format \"${format}\".`);\n },\n },\n];\n","import type { FormulaFunctionContext } from '../registry';\nimport { hasWildcards, wildcardToRegExp } from '../criteria';\nimport {\n compareValues,\n isBlank,\n isFormulaError,\n normalizeValue,\n rangeGet,\n sliceRange,\n type FormulaRange,\n} from '../values';\nimport { arg, failed, optional, type FunctionTable } from './helpers';\n\n/**\n * Lookup functions return single values. A function that would return a whole\n * row or column (INDEX with row 0, XLOOKUP with a 2D return array) returns an\n * array: other functions can aggregate it (`SUM(INDEX(A1:C3, 0, 2))`), and a\n * cell showing it displays its first value (no dynamic-array spilling).\n */\n\ntype MatchMode = 'exact' | 'wildcard' | 'next-smaller' | 'next-larger' | 'sorted-asc' | 'sorted-desc';\n\nconst sameType = (a: unknown, b: unknown) =>\n (typeof a === 'number') === (typeof b === 'number') && (typeof a === 'boolean') === (typeof b === 'boolean');\n\n/**\n * Finds `target` in `values`; returns its index or -1.\n * - `exact`: equal values (case-insensitive text, numeric text = number);\n * - `wildcard`: like exact, but text targets may use `*`, `?` and `~`;\n * - `next-smaller` / `next-larger`: exact match, else the closest smaller / larger value;\n * - `sorted-asc` / `sorted-desc`: approximate match on sorted data, as MATCH 1 / -1 and\n * VLOOKUP TRUE: the last value <= target (ascending) or >= target (descending).\n */\nexport function lookupIndex(values: readonly unknown[], target: unknown, mode: MatchMode, reverse = false): number {\n const wanted = normalizeValue(target);\n const order = values.map((_, i) => i);\n if (reverse) order.reverse();\n\n if (mode === 'exact' || mode === 'wildcard') {\n const regex = mode === 'wildcard' && typeof wanted === 'string' && hasWildcards(wanted) ? wildcardToRegExp(wanted) : null;\n for (const i of order) {\n const value = normalizeValue(values[i]);\n if (isFormulaError(value) || isBlank(value)) continue;\n if (regex ? typeof value === 'string' && regex.test(value) : sameType(value, wanted) && compareValues(value, wanted) === 0) {\n return i;\n }\n }\n return -1;\n }\n\n if (mode === 'sorted-asc' || mode === 'sorted-desc') {\n let found = -1;\n for (let i = 0; i < values.length; i++) {\n const value = normalizeValue(values[i]);\n if (isFormulaError(value) || isBlank(value) || !sameType(value, wanted)) continue;\n const cmp = compareValues(value, wanted);\n if (mode === 'sorted-asc' ? cmp <= 0 : cmp >= 0) found = i;\n else break;\n }\n return found;\n }\n\n let best = -1;\n let bestValue: unknown;\n for (const i of order) {\n const value = normalizeValue(values[i]);\n if (isFormulaError(value) || isBlank(value) || !sameType(value, wanted)) continue;\n const cmp = compareValues(value, wanted);\n if (cmp === 0) return i;\n const candidate = mode === 'next-smaller' ? cmp < 0 : cmp > 0;\n const closer =\n best === -1 || (mode === 'next-smaller' ? compareValues(value, bestValue) > 0 : compareValues(value, bestValue) < 0);\n if (candidate && closer) {\n best = i;\n bestValue = value;\n }\n }\n return best;\n}\n\n/** Values of a one-row or one-column range, or an error if the range is 2D. */\nfunction vector(ctx: FormulaFunctionContext, index: number): { range: FormulaRange; values: any[] } | string {\n const range = ctx.range(index);\n if (failed(range)) return range;\n if (range.rows !== 1 && range.cols !== 1) {\n return ctx.argError(index, '#N/A', 'must be a single row or column.');\n }\n return { range, values: range.values };\n}\n\nconst notFound = (ctx: FormulaFunctionContext, value: unknown) =>\n ctx.error('#N/A', `${ctx.name} couldn't find ${typeof value === 'string' ? `\"${value}\"` : String(value)}.`);\n\n/** VLOOKUP / HLOOKUP share everything but orientation. */\nfunction tableLookup(ctx: FormulaFunctionContext, vertical: boolean): any {\n const target = ctx.scalar(0);\n if (isFormulaError(target)) return target;\n const table = ctx.range(1);\n if (failed(table)) return table;\n const index = ctx.integer(2);\n if (failed(index)) return index;\n const approximate = ctx.boolean(3, true);\n if (failed(approximate)) return approximate;\n\n const span = vertical ? table.cols : table.rows;\n if (index < 1) return ctx.argError(2, '#VALUE!', 'must be 1 or more.');\n if (index > span) {\n return ctx.argError(2, '#REF!', `is larger than the number of ${vertical ? 'columns' : 'rows'} in the table (${span}).`);\n }\n\n const keys = vertical ? sliceRange(table, 0, table.rows, 0, 1) : sliceRange(table, 0, 1, 0, table.cols);\n const position = lookupIndex(keys, target, approximate ? 'sorted-asc' : 'wildcard');\n if (position === -1) return notFound(ctx, target);\n return vertical ? rangeGet(table, position, index - 1) : rangeGet(table, index - 1, position);\n}\n\nexport const LOOKUP_FUNCTIONS: FunctionTable = [\n {\n name: 'VLOOKUP',\n category: 'lookup',\n description: 'Looks for a value in the first column of a table and returns the value in the same row of another column.',\n args: [\n arg('lookup_value', 'The value to find in the first column.'),\n arg('table_array', 'The table to search.', 'range'),\n arg('col_index_num', 'Which column to return (1 = first column).', 'number'),\n optional('range_lookup', 'FALSE for an exact match; TRUE or omitted for the closest match in a sorted first column.', 'logical'),\n ],\n evaluate: (ctx) => tableLookup(ctx, true),\n },\n {\n name: 'HLOOKUP',\n category: 'lookup',\n description: 'Looks for a value in the first row of a table and returns the value in the same column of another row.',\n args: [\n arg('lookup_value', 'The value to find in the first row.'),\n arg('table_array', 'The table to search.', 'range'),\n arg('row_index_num', 'Which row to return (1 = first row).', 'number'),\n optional('range_lookup', 'FALSE for an exact match; TRUE or omitted for the closest match in a sorted first row.', 'logical'),\n ],\n evaluate: (ctx) => tableLookup(ctx, false),\n },\n {\n name: 'MATCH',\n category: 'lookup',\n description: 'Returns the position of a value in a row or column.',\n args: [\n arg('lookup_value', 'The value to find.'),\n arg('lookup_array', 'A single row or column to search.', 'range'),\n optional('match_type', '0 = exact; 1 (default) = largest value <= lookup_value in ascending data; -1 = smallest value >= lookup_value in descending data.', 'number'),\n ],\n evaluate: (ctx) => {\n const target = ctx.scalar(0);\n if (isFormulaError(target)) return target;\n const list = vector(ctx, 1);\n if (failed(list)) return list;\n const type = ctx.number(2, 1);\n if (failed(type)) return type;\n const mode: MatchMode = type === 0 ? 'wildcard' : type > 0 ? 'sorted-asc' : 'sorted-desc';\n const position = lookupIndex(list.values, target, mode);\n return position === -1 ? notFound(ctx, target) : position + 1;\n },\n },\n {\n name: 'INDEX',\n category: 'lookup',\n description: 'Returns the value at a row and column of a range. Row or column 0 returns the whole column or row.',\n args: [\n arg('array', 'The range to read from.', 'range'),\n arg('row_num', 'The row (1 = first row; 0 = every row).', 'number'),\n optional('column_num', 'The column (1 = first column; 0 = every column).', 'number'),\n ],\n evaluate: (ctx) => {\n const range = ctx.range(0);\n if (failed(range)) return range;\n let row = ctx.integer(1);\n if (failed(row)) return row;\n let col = ctx.integer(2, ctx.has(2) ? undefined : 1);\n if (failed(col)) return col;\n // INDEX(single_row, n) picks the n-th column.\n if (!ctx.has(2) && range.rows === 1 && range.cols > 1) {\n col = row;\n row = 1;\n }\n if (row < 0 || row > range.rows) {\n return ctx.argError(1, '#REF!', `is outside the range (1 to ${range.rows}).`);\n }\n if (col < 0 || col > range.cols) {\n return ctx.argError(2, '#REF!', `is outside the range (1 to ${range.cols}).`);\n }\n if (row === 0 && col === 0) return range.values;\n if (row === 0) return sliceRange(range, 0, range.rows, col - 1, 1);\n if (col === 0) return sliceRange(range, row - 1, 1, 0, range.cols);\n return rangeGet(range, row - 1, col - 1);\n },\n },\n {\n name: 'XLOOKUP',\n category: 'lookup',\n description: 'Finds a value in one range and returns the value at the same position in another range.',\n args: [\n arg('lookup_value', 'The value to find.'),\n arg('lookup_array', 'A single row or column to search.', 'range'),\n arg('return_array', 'The range to return a value from; same height (or width) as lookup_array.', 'range'),\n optional('if_not_found', 'Returned when nothing matches (default #N/A).'),\n optional('match_mode', '0 (default) = exact; -1 = exact or next smaller; 1 = exact or next larger; 2 = wildcard match.', 'number'),\n optional('search_mode', '1 (default) = first to last; -1 = last to first.', 'number'),\n ],\n evaluate: (ctx) => {\n const target = ctx.scalar(0);\n if (isFormulaError(target)) return target;\n const list = vector(ctx, 1);\n if (failed(list)) return list;\n const result = ctx.range(2);\n if (failed(result)) return result;\n const matchMode = ctx.integer(4, 0);\n if (failed(matchMode)) return matchMode;\n const searchMode = ctx.integer(5, 1);\n if (failed(searchMode)) return searchMode;\n\n const vertical = list.range.cols === 1 && list.range.rows > 1;\n const length = list.values.length;\n if ((vertical ? result.rows : result.cols) !== length && !(length === 1 && (result.rows === 1 || result.cols === 1))) {\n return ctx.argError(2, '#VALUE!', 'must be the same height (or width) as argument 2.');\n }\n const modes: Record<number, MatchMode> = { 0: 'exact', [-1]: 'next-smaller', 1: 'next-larger', 2: 'wildcard' };\n const mode = modes[matchMode];\n if (!mode) return ctx.argError(4, '#VALUE!', 'must be 0, -1, 1 or 2.');\n if (![1, -1, 2, -2].includes(searchMode)) return ctx.argError(5, '#VALUE!', 'must be 1, -1, 2 or -2.');\n\n const position = lookupIndex(list.values, target, mode, searchMode < 0);\n if (position === -1) return ctx.has(3) ? ctx.value(3) : notFound(ctx, target);\n if (vertical) {\n return result.cols === 1 ? rangeGet(result, position, 0) : sliceRange(result, position, 1, 0, result.cols);\n }\n return result.rows === 1 ? rangeGet(result, 0, position) : sliceRange(result, 0, result.rows, position, 1);\n },\n },\n];\n","import type { FormulaFunctionContext } from '../registry';\nimport { daysBetween, formatIsoDate, formatIsoDateTime, isBlank, isFormulaError, toDate } from '../values';\nimport { arg, failed, optional, type FunctionTable } from './helpers';\n\n/**\n * Dates are ISO text (\"2026-01-31\"), as TODAY() has always returned, so they\n * display readably and sort correctly as text. Date arguments also accept\n * spreadsheet serial numbers. Date functions return ISO text; part functions\n * (YEAR, WEEKDAY, ...) and differences (DAYS, DATEDIF) return numbers.\n */\n\nconst START_DATE = arg('start_date', 'The date to start from.', 'date');\nconst DATE = arg('date', 'A date (e.g. \"2026-01-31\" or a cell containing one).', 'date');\n\n/** Adds months, clamping the day to the end of the target month (Jan 31 + 1 month = Feb 28). */\nfunction addMonths(date: Date, months: number): Date {\n const target = new Date(date.getFullYear(), date.getMonth() + months, 1);\n const lastDay = new Date(target.getFullYear(), target.getMonth() + 1, 0).getDate();\n target.setDate(Math.min(date.getDate(), lastDay));\n return target;\n}\n\nfunction datePart(ctx: FormulaFunctionContext, part: (date: Date) => number): number | string {\n const date = ctx.date(0);\n return failed(date) ? date : part(date);\n}\n\nconst isWorkday = (date: Date) => date.getDay() !== 0 && date.getDay() !== 6;\n\nexport const DATE_FUNCTIONS: FunctionTable = [\n {\n name: 'TODAY',\n category: 'date',\n description: 'Returns today\\'s date (YYYY-MM-DD). Changes on every recalculation.',\n args: [],\n volatile: true,\n // Local calendar date (toISOString would give the UTC date).\n evaluate: () => formatIsoDate(new Date()),\n },\n {\n name: 'NOW',\n category: 'date',\n description: 'Returns the current date and time (YYYY-MM-DD HH:MM:SS). Changes on every recalculation.',\n args: [],\n volatile: true,\n evaluate: () => formatIsoDateTime(new Date()),\n },\n {\n name: 'DATE',\n category: 'date',\n description: 'Builds a date from a year, month and day. Months and days outside their range roll over.',\n args: [\n arg('year', 'The year (0-1899 are added to 1900).', 'number'),\n arg('month', 'The month (1-12).', 'number'),\n arg('day', 'The day of the month.', 'number'),\n ],\n evaluate: (ctx) => {\n let year = ctx.integer(0);\n if (failed(year)) return year;\n const month = ctx.integer(1);\n if (failed(month)) return month;\n const day = ctx.integer(2);\n if (failed(day)) return day;\n if (year < 0 || year > 9999) return ctx.argError(0, '#NUM!', 'must be between 0 and 9999.');\n if (year < 1900) year += 1900;\n const date = new Date(year, month - 1, 1);\n date.setDate(day);\n if (date.getFullYear() < 1900 || date.getFullYear() > 9999) {\n return ctx.error('#NUM!', 'DATE produced a date outside the years 1900-9999.');\n }\n return formatIsoDate(date);\n },\n },\n {\n name: 'YEAR',\n category: 'date',\n description: 'Returns the year of a date.',\n args: [DATE],\n evaluate: (ctx) => datePart(ctx, (d) => d.getFullYear()),\n },\n {\n name: 'MONTH',\n category: 'date',\n description: 'Returns the month of a date (1-12).',\n args: [DATE],\n evaluate: (ctx) => datePart(ctx, (d) => d.getMonth() + 1),\n },\n {\n name: 'DAY',\n category: 'date',\n description: 'Returns the day of the month of a date (1-31).',\n args: [DATE],\n evaluate: (ctx) => datePart(ctx, (d) => d.getDate()),\n },\n {\n name: 'WEEKDAY',\n category: 'date',\n description: 'Returns the day of the week of a date.',\n args: [DATE, optional('return_type', '1 (default) = Sunday 1 to Saturday 7; 2 = Monday 1 to Sunday 7; 3 = Monday 0 to Sunday 6.', 'number')],\n evaluate: (ctx) => {\n const date = ctx.date(0);\n if (failed(date)) return date;\n const type = ctx.integer(1, 1);\n if (failed(type)) return type;\n const day = date.getDay(); // 0 = Sunday\n if (type === 1) return day + 1;\n if (type === 2) return day === 0 ? 7 : day;\n if (type === 3) return day === 0 ? 6 : day - 1;\n return ctx.argError(1, '#NUM!', 'must be 1, 2 or 3.');\n },\n },\n {\n name: 'DAYS',\n category: 'date',\n description: 'Returns the number of days between two dates.',\n args: [arg('end_date', 'The later date.', 'date'), START_DATE],\n evaluate: (ctx) => {\n const end = ctx.date(0);\n if (failed(end)) return end;\n const start = ctx.date(1);\n if (failed(start)) return start;\n return daysBetween(start, end);\n },\n },\n {\n name: 'EDATE',\n category: 'date',\n description: 'Returns the date a number of months before or after a date.',\n args: [START_DATE, arg('months', 'Months to add (negative for earlier dates).', 'number')],\n evaluate: (ctx) => {\n const start = ctx.date(0);\n if (failed(start)) return start;\n const months = ctx.integer(1);\n if (failed(months)) return months;\n return formatIsoDate(addMonths(start, months));\n },\n },\n {\n name: 'EOMONTH',\n category: 'date',\n description: 'Returns the last day of the month a number of months before or after a date.',\n args: [START_DATE, arg('months', 'Months to add (0 = same month).', 'number')],\n evaluate: (ctx) => {\n const start = ctx.date(0);\n if (failed(start)) return start;\n const months = ctx.integer(1);\n if (failed(months)) return months;\n return formatIsoDate(new Date(start.getFullYear(), start.getMonth() + months + 1, 0));\n },\n },\n {\n name: 'NETWORKDAYS',\n category: 'date',\n description: 'Counts the working days (Monday to Friday) between two dates, inclusive, minus holidays.',\n args: [START_DATE, arg('end_date', 'The last date.', 'date'), optional('holidays', 'Dates to exclude.', 'range')],\n evaluate: (ctx) => {\n const start = ctx.date(0);\n if (failed(start)) return start;\n const end = ctx.date(1);\n if (failed(end)) return end;\n const holidays = new Set<string>();\n if (ctx.has(2)) {\n const raw = ctx.value(2);\n for (const value of Array.isArray(raw) ? raw : [raw]) {\n if (isFormulaError(value)) return value;\n if (isBlank(value)) continue;\n const date = toDate(value);\n if (!date) return ctx.argError(2, '#VALUE!', 'must contain only dates.');\n holidays.add(formatIsoDate(date));\n }\n }\n const sign = daysBetween(start, end) < 0 ? -1 : 1;\n const [from, to] = sign < 0 ? [end, start] : [start, end];\n let count = 0;\n const total = daysBetween(from, to);\n for (let i = 0; i <= total; i++) {\n const day = new Date(from.getFullYear(), from.getMonth(), from.getDate() + i);\n if (isWorkday(day) && !holidays.has(formatIsoDate(day))) count++;\n }\n return sign * count;\n },\n },\n {\n name: 'DATEDIF',\n category: 'date',\n description: 'Returns the difference between two dates in years, months or days.',\n args: [\n START_DATE,\n arg('end_date', 'The later date.', 'date'),\n arg('unit', '\"Y\" years, \"M\" months, \"D\" days, \"MD\" days ignoring months and years, \"YM\" months ignoring years, \"YD\" days ignoring years.', 'text'),\n ],\n evaluate: (ctx) => {\n const start = ctx.date(0);\n if (failed(start)) return start;\n const end = ctx.date(1);\n if (failed(end)) return end;\n const unit = ctx.text(2);\n if (failed(unit)) return unit;\n if (daysBetween(start, end) < 0) return ctx.error('#NUM!', 'DATEDIF needs the start date to be on or before the end date.');\n\n let months = (end.getFullYear() - start.getFullYear()) * 12 + end.getMonth() - start.getMonth();\n if (end.getDate() < start.getDate()) months--;\n switch (unit.trim().toUpperCase()) {\n case 'Y':\n return Math.floor(months / 12);\n case 'M':\n return months;\n case 'D':\n return daysBetween(start, end);\n case 'YM':\n return months % 12;\n case 'MD': {\n const anchor = addMonths(start, months);\n return daysBetween(anchor, end);\n }\n case 'YD': {\n const anchor = addMonths(start, Math.floor(months / 12) * 12);\n return daysBetween(anchor, end);\n }\n default:\n return ctx.argError(2, '#NUM!', 'must be \"Y\", \"M\", \"D\", \"MD\", \"YM\" or \"YD\".');\n }\n },\n },\n];\n","import type { FormulaFunctionContext } from '../registry';\nimport { isBlank, isFormulaError, numericValue } from '../values';\nimport { arg, type FunctionTable } from './helpers';\n\nconst VALUE = arg('value', 'The value or cell to check.');\n\n/** IS* functions look at a single value without propagating errors. */\nconst check = (test: (value: unknown) => boolean) => (ctx: FormulaFunctionContext) => test(ctx.scalar(0));\n\nexport const INFORMATION_FUNCTIONS: FunctionTable = [\n {\n name: 'ISBLANK',\n category: 'information',\n description: 'Returns TRUE if the value is empty.',\n args: [VALUE],\n evaluate: check(isBlank),\n },\n {\n name: 'ISNUMBER',\n category: 'information',\n description: 'Returns TRUE if the value is a number (typed cell values that look like numbers count).',\n args: [VALUE],\n evaluate: check((value) => numericValue(value) !== null),\n },\n {\n name: 'ISTEXT',\n category: 'information',\n description: 'Returns TRUE if the value is text that is not a number.',\n args: [VALUE],\n evaluate: check(\n (value) => typeof value === 'string' && !isBlank(value) && !isFormulaError(value) && numericValue(value) === null,\n ),\n },\n {\n name: 'ISERROR',\n category: 'information',\n description: 'Returns TRUE if the value is any error.',\n args: [VALUE],\n evaluate: check(isFormulaError),\n },\n {\n name: 'ISNA',\n category: 'information',\n description: 'Returns TRUE if the value is the #N/A error.',\n args: [VALUE],\n evaluate: check((value) => value === '#N/A'),\n },\n];\n","import type { FormulaFunctionDefinition } from '../registry';\nimport { MATH_FUNCTIONS } from './math';\nimport { STATISTICAL_FUNCTIONS } from './statistical';\nimport { CONDITIONAL_FUNCTIONS } from './conditional';\nimport { LOGICAL_FUNCTIONS } from './logical';\nimport { TEXT_FUNCTIONS } from './text';\nimport { LOOKUP_FUNCTIONS } from './lookup';\nimport { DATE_FUNCTIONS } from './date';\nimport { INFORMATION_FUNCTIONS } from './information';\n\n/** Every built-in formula function. The registry is seeded from this list. */\nexport const BUILTIN_FORMULA_FUNCTIONS: readonly FormulaFunctionDefinition[] = [\n ...MATH_FUNCTIONS,\n ...STATISTICAL_FUNCTIONS,\n ...CONDITIONAL_FUNCTIONS,\n ...LOGICAL_FUNCTIONS,\n ...TEXT_FUNCTIONS,\n ...LOOKUP_FUNCTIONS,\n ...DATE_FUNCTIONS,\n ...INFORMATION_FUNCTIONS,\n];\n","import type { ASTNode } from './parser';\nimport type { FormulaErrorCode, FormulaRange } from './values';\nimport { BUILTIN_FORMULA_FUNCTIONS } from './functions';\n\nexport type FormulaFunctionCategory =\n | 'math'\n | 'statistical'\n | 'logical'\n | 'text'\n | 'lookup'\n | 'date'\n | 'information';\n\n/** What an argument expects. Used for documentation, hints and messages. */\nexport type FormulaArgumentType =\n | 'any'\n | 'number'\n | 'text'\n | 'logical'\n | 'date'\n | 'range'\n | 'criteria';\n\nexport interface FormulaArgumentSpec {\n /** Argument name shown in signatures, e.g. `sum_range`. */\n name: string;\n description: string;\n type?: FormulaArgumentType;\n /** The argument may be left out. */\n optional?: boolean;\n /**\n * The argument repeats. Consecutive repeating arguments form a group that\n * repeats together (`criteria_range, criteria` in SUMIFS). The group must be\n * the last arguments, and is required once unless its first spec is optional.\n */\n repeating?: boolean;\n}\n\n/** One argument of a call, evaluated lazily so functions like IF can short-circuit. */\nexport interface FormulaArgument {\n /** 0-based position in the call. */\n readonly index: number;\n readonly node: ASTNode;\n /** Evaluates the argument (once; later calls return the cached value). Ranges evaluate to arrays. */\n value(): any;\n}\n\n/** What a function implementation receives. Coercion helpers report argument-indexed diagnostics. */\nexport interface FormulaFunctionContext {\n /** Upper-case function name. */\n readonly name: string;\n readonly args: readonly FormulaArgument[];\n /** Returns `code` and records `message` as the reason (shown to the user if the cell ends up with that error). */\n error(code: FormulaErrorCode, message?: string): string;\n /** Like `error`, phrased as `Argument N of NAME <reason>`. */\n argError(index: number, code: FormulaErrorCode, reason: string): string;\n /** Whether argument `index` was supplied. */\n has(index: number): boolean;\n /** Raw (lazily evaluated) value of an argument; ranges are arrays. */\n value(index: number): any;\n /** Single value of an argument: a one-cell range is unwrapped, larger ranges are #VALUE!. */\n scalar(index: number): any;\n /** Argument as a number (or an error string). Text that isn't numeric is #VALUE!. */\n number(index: number, fallback?: number): number | string;\n /** Argument as an integer (truncated toward zero). */\n integer(index: number, fallback?: number): number | string;\n /** Argument as text (or an error string). */\n text(index: number, fallback?: string): string;\n /** Argument as a boolean (or an error string). */\n boolean(index: number, fallback?: boolean): boolean | string;\n /** Argument as a date (or an error string). */\n date(index: number): Date | string;\n /** Argument as a 2D range (or an error string if it is not a range). */\n range(index: number): FormulaRange | string;\n /** Every value of the arguments `from` (default 0) up to `to` (exclusive, default all), ranges flattened. */\n flatValues(from?: number, to?: number): any[];\n /**\n * Numbers among the arguments `from`..`to` (exclusive), as SUM reads them:\n * text, booleans and blanks are skipped; the first error is returned instead.\n */\n numbers(from?: number, to?: number): number[] | string;\n}\n\nexport interface FormulaFunctionDefinition {\n /** Function name; matched case-insensitively. */\n name: string;\n category: FormulaFunctionCategory;\n description: string;\n args: FormulaArgumentSpec[];\n /** Result changes on every recalculation (RAND, NOW, TODAY). */\n volatile?: boolean;\n /**\n * A repeating group may end with one extra argument (SWITCH's `default`).\n * Otherwise a group must be complete.\n */\n allowTrailingArgument?: boolean;\n evaluate(ctx: FormulaFunctionContext): any;\n}\n\n// --- Registry ---\n\nconst registry = new Map<string, FormulaFunctionDefinition>();\nlet builtinsLoaded = false;\n\nfunction ensureBuiltins(): void {\n if (builtinsLoaded) return;\n builtinsLoaded = true;\n for (const def of BUILTIN_FORMULA_FUNCTIONS) {\n if (!registry.has(def.name)) registry.set(def.name, def);\n }\n}\n\n/**\n * Adds (or replaces) a formula function. Replacing a built-in is allowed, so\n * apps can customise behaviour; the change is global.\n */\nexport function registerFormulaFunction(definition: FormulaFunctionDefinition): void {\n ensureBuiltins();\n const name = definition.name.trim().toUpperCase();\n if (!/^[A-Z_][A-Z0-9_.]*$/.test(name)) {\n throw new Error(`Invalid formula function name \"${definition.name}\"`);\n }\n registry.set(name, { ...definition, name });\n}\n\n/** Removes a formula function. Returns false if it was not registered. */\nexport function unregisterFormulaFunction(name: string): boolean {\n ensureBuiltins();\n return registry.delete(name.toUpperCase());\n}\n\nexport function getFormulaFunction(name: string): FormulaFunctionDefinition | undefined {\n ensureBuiltins();\n return registry.get(name.toUpperCase());\n}\n\n/** All registered functions sorted by name, optionally limited to one category. */\nexport function listFormulaFunctions(category?: FormulaFunctionCategory): FormulaFunctionDefinition[] {\n ensureBuiltins();\n return Array.from(registry.values())\n .filter((def) => !category || def.category === category)\n .sort((a, b) => a.name.localeCompare(b.name));\n}\n\n/**\n * Functions matching `query`, for autocomplete: names starting with the query\n * first, then names containing it. An empty query lists every function.\n */\nexport function searchFormulaFunctions(\n query: string,\n options: { limit?: number; category?: FormulaFunctionCategory } = {},\n): FormulaFunctionDefinition[] {\n const q = query.trim().toUpperCase();\n const all = listFormulaFunctions(options.category);\n const prefix = all.filter((def) => def.name.startsWith(q));\n const contains = q ? all.filter((def) => !def.name.startsWith(q) && def.name.includes(q)) : [];\n const results = [...prefix, ...contains];\n return options.limit !== undefined ? results.slice(0, options.limit) : results;\n}\n\n// --- Argument layout and signatures ---\n\ninterface ArgumentLayout {\n fixed: FormulaArgumentSpec[];\n group: FormulaArgumentSpec[];\n groupStart: number;\n}\n\nfunction layoutOf(def: FormulaFunctionDefinition): ArgumentLayout {\n const groupStart = def.args.findIndex((arg) => arg.repeating);\n if (groupStart === -1) return { fixed: def.args, group: [], groupStart: def.args.length };\n return { fixed: def.args.slice(0, groupStart), group: def.args.slice(groupStart), groupStart };\n}\n\n/**\n * Index into `def.args` of the spec describing the call argument at\n * `argIndex`, or -1 if the function takes no argument there.\n */\nexport function getFormulaArgumentSpecIndex(def: FormulaFunctionDefinition, argIndex: number): number {\n const { fixed, group, groupStart } = layoutOf(def);\n if (argIndex < fixed.length) return argIndex;\n if (group.length === 0) return -1;\n return groupStart + ((argIndex - groupStart) % group.length);\n}\n\n/**\n * Checks the number of arguments of a call. Returns a message such as\n * `SUMIF needs at least 2 arguments, but 1 was given.`, or null when valid.\n */\nexport function checkFormulaArgumentCount(def: FormulaFunctionDefinition, count: number): string | null {\n const { fixed, group } = layoutOf(def);\n const requiredFixed = fixed.filter((arg) => !arg.optional).length;\n const groupRequired = group.length > 0 && !group[0].optional;\n const min = requiredFixed + (groupRequired ? group.length : 0);\n const max = group.length > 0 ? Infinity : fixed.length;\n const given = `${count} ${count === 1 ? 'was' : 'were'} given`;\n const plural = (n: number) => `${n} argument${n === 1 ? '' : 's'}`;\n\n if (count < min) {\n const expected = min === max ? plural(min) : `at least ${plural(min)}`;\n return `${def.name} needs ${expected}, but ${given}.`;\n }\n if (count > max) {\n const expected = min === max ? plural(max) : `at most ${plural(max)}`;\n return max === 0 ? `${def.name} takes no arguments, but ${given}.` : `${def.name} takes ${expected}, but ${given}.`;\n }\n if (group.length > 1 && count > fixed.length) {\n const extra = (count - fixed.length) % group.length;\n if (extra !== 0 && !(def.allowTrailingArgument && extra === 1)) {\n const names = group.map((arg) => arg.name).join(', ');\n return `${def.name} expects its repeating arguments (${names}) in complete groups.`;\n }\n }\n return null;\n}\n\n/** A piece of a rendered signature; `specIndex` is set on argument names. */\nexport interface FormulaSignaturePart {\n text: string;\n specIndex: number | null;\n active: boolean;\n}\n\n/**\n * Renders a signature as parts, e.g. `SUMIFS(` `sum_range` `, ` ... `)`, with\n * the argument at call position `activeArgIndex` (if any) marked active. A\n * repeating group is shown twice (`value1, [value2, ...]`); arguments past\n * the first repetition highlight the second one.\n */\nexport function getFormulaSignatureParts(\n nameOrDef: string | FormulaFunctionDefinition,\n activeArgIndex?: number | null,\n): FormulaSignaturePart[] {\n const def = typeof nameOrDef === 'string' ? getFormulaFunction(nameOrDef) : nameOrDef;\n if (!def) return [];\n const { fixed, group, groupStart } = layoutOf(def);\n\n let activeSpec = -1;\n let activeRepeat = 0;\n if (activeArgIndex !== undefined && activeArgIndex !== null && activeArgIndex >= 0) {\n activeSpec = getFormulaArgumentSpecIndex(def, activeArgIndex);\n if (activeSpec >= groupStart && group.length > 0) {\n activeRepeat = Math.floor((activeArgIndex - groupStart) / group.length) > 0 ? 1 : 0;\n }\n }\n\n const parts: FormulaSignaturePart[] = [{ text: `${def.name}(`, specIndex: null, active: false }];\n const pushArg = (text: string, specIndex: number, repeat = 0) => {\n if (parts.length > 1) parts.push({ text: ', ', specIndex: null, active: false });\n parts.push({ text, specIndex, active: specIndex === activeSpec && repeat === activeRepeat });\n };\n\n fixed.forEach((arg, i) => pushArg(arg.optional ? `[${arg.name}]` : arg.name, i));\n\n if (group.length > 0) {\n const groupOptional = !!group[0].optional;\n group.forEach((arg, i) => {\n const open = groupOptional && i === 0 ? '[' : '';\n pushArg(`${open}${arg.name}1`, groupStart + i, 0);\n });\n group.forEach((arg, i) => {\n const open = !groupOptional && i === 0 ? '[' : '';\n pushArg(`${open}${arg.name}2`, groupStart + i, 1);\n });\n parts.push({ text: ', ...]', specIndex: null, active: false });\n }\n\n parts.push({ text: ')', specIndex: null, active: false });\n return parts;\n}\n\n/** Signature string such as `SUMIF(range, criteria, [sum_range])`. */\nexport function getFormulaSignature(nameOrDef: string | FormulaFunctionDefinition): string {\n return getFormulaSignatureParts(nameOrDef)\n .map((part) => part.text)\n .join('');\n}\n","import { ASTNode, parseFormula, type FunctionCallNode, type RangeNode } from './parser';\nimport {\n checkFormulaArgumentCount,\n getFormulaFunction,\n type FormulaArgument,\n type FormulaFunctionContext,\n type FormulaFunctionDefinition,\n} from './registry';\nimport {\n colNameToIndex,\n isBlank,\n isFormulaError,\n numericValue,\n toBoolean,\n toDate,\n toFormulaRange,\n toNumber,\n toText,\n compareValues,\n withRangeShape,\n type FormulaErrorCode,\n} from './values';\n\nexport { FORMULA_ERRORS, isFormulaError, colNameToIndex, indexToColName } from './values';\nexport type { FormulaErrorCode, FormulaRange } from './values';\n\nexport interface EvaluationContext {\n resolveCell?: (col: string, row: number) => any;\n /**\n * Values of a rectangular range, column by column (all rows of the first\n * column, then the next column). Lookup functions rely on this order.\n */\n resolveRange?: (startCol: string, startRow: number, endCol: string, endRow: number) => any[];\n resolveProperty?: (property: string) => any;\n}\n\n/** A human-readable reason for an error value. */\nexport interface FormulaDiagnostic {\n code: FormulaErrorCode;\n message: string;\n}\n\nexport interface FormulaEvaluationResult {\n /** The computed value; an error code such as `#VALUE!` when the formula fails. */\n value: any;\n /** The error code when `value` is an error. */\n error?: FormulaErrorCode;\n /** Why the formula failed, e.g. `Argument 2 of SUMIF must be a range.` */\n message?: string;\n}\n\nconst DEFAULT_MESSAGES: Record<FormulaErrorCode, string> = {\n '#DIV/0!': 'The formula divides by zero.',\n '#VALUE!': 'A value in the formula has the wrong type.',\n '#REF!': 'The formula refers to a cell or range that was deleted.',\n '#NAME?': 'The formula contains an unknown name.',\n '#N/A': 'A value is not available.',\n '#NUM!': 'The formula produced an invalid number.',\n '#CYCLE!': 'This formula is part of a circular reference.',\n '#ERROR!': 'The formula could not be evaluated.',\n};\n\n/** Generic explanation of an error code, used when no specific reason was recorded. */\nexport function describeFormulaError(code: string): string {\n return DEFAULT_MESSAGES[code as FormulaErrorCode] ?? 'The formula could not be evaluated.';\n}\n\nconst quote = (value: unknown) => (typeof value === 'string' ? `\"${value}\"` : String(value));\n\nexport class FormulaEvaluator {\n private context: EvaluationContext;\n private diagnostics: FormulaDiagnostic[] = [];\n\n constructor(context: EvaluationContext = {}) {\n this.context = context;\n }\n\n /**\n * Evaluates a formula. Errors in the formula are returned as error values\n * (`#VALUE!` etc.); malformed formulas and missing resolvers throw.\n */\n public evaluate(astOrFormula: ASTNode | string): any {\n const ast = typeof astOrFormula === 'string' ? parseFormula(astOrFormula) : astOrFormula;\n return this.evaluateNode(ast);\n }\n\n /**\n * Evaluates a formula and explains errors. Never throws: malformed formulas\n * return `#ERROR!` with the parser's message. A result that is a whole range\n * (no dynamic-array spilling) is reduced to its first value.\n */\n public evaluateWithDiagnostics(astOrFormula: ASTNode | string): FormulaEvaluationResult {\n const saved = this.diagnostics;\n this.diagnostics = [];\n try {\n let value = this.evaluate(astOrFormula);\n if (Array.isArray(value)) value = value.length > 0 ? value[0] : '';\n if (isFormulaError(value)) {\n const code = value as FormulaErrorCode;\n const diagnostic = this.diagnostics.find((d) => d.code === code);\n return { value, error: code, message: diagnostic?.message ?? describeFormulaError(code) };\n }\n return { value };\n } catch (err: any) {\n return { value: '#ERROR!', error: '#ERROR!', message: err?.message || 'Formula error' };\n } finally {\n this.diagnostics = saved;\n }\n }\n\n /** Records why an error happened and returns the error code. */\n private fail(code: FormulaErrorCode, message: string): string {\n this.diagnostics.push({ code, message });\n return code;\n }\n\n private evaluateNode(node: ASTNode): any {\n switch (node.type) {\n case 'Literal':\n if (node.value === '#REF!') return this.fail('#REF!', 'This formula refers to a cell or range that was deleted.');\n if (node.value === '#NAME?') return this.fail('#NAME?', 'This formula contains an unknown name.');\n return node.value;\n\n case 'CellRef': {\n if (!this.context.resolveCell) {\n throw new Error(`Cannot resolve cell reference ${node.ref}: no cell resolver provided`);\n }\n const value = this.context.resolveCell(node.col, node.row);\n if (isFormulaError(value)) {\n this.fail(\n value as FormulaErrorCode,\n value === '#CYCLE!'\n ? `Cell ${node.ref} is part of a circular reference.`\n : `Cell ${node.ref} contains an error (${value}).`,\n );\n }\n return value;\n }\n\n case 'Range':\n return this.evaluateRange(node);\n\n case 'PropertyRef': {\n if (!this.context.resolveProperty) {\n throw new Error(`Cannot resolve property [${node.property}]: no property resolver provided`);\n }\n return this.context.resolveProperty(node.property);\n }\n\n case 'UnaryOp': {\n const raw = this.evaluateNode(node.argument);\n const val = toNumber(raw);\n if (isFormulaError(val)) {\n return isFormulaError(raw) ? raw : this.fail('#VALUE!', `The ${node.op} operator can't use text (${quote(raw)}).`);\n }\n if (node.op === '-') return -(val as number);\n if (node.op === '+') return val;\n throw new Error(`Unsupported unary operator: ${node.op}`);\n }\n\n case 'BinaryOp': {\n const left = this.evaluateNode(node.left);\n if (isFormulaError(left)) return left;\n const right = this.evaluateNode(node.right);\n if (isFormulaError(right)) return right;\n\n if (['+', '-', '*', '/', '^'].includes(node.op)) {\n const a = toNumber(left);\n if (isFormulaError(a)) return this.fail('#VALUE!', `The ${node.op} operator can't use text (${quote(left)}).`);\n const b = toNumber(right);\n if (isFormulaError(b)) return this.fail('#VALUE!', `The ${node.op} operator can't use text (${quote(right)}).`);\n const x = a as number;\n const y = b as number;\n let result: number;\n switch (node.op) {\n case '+':\n result = x + y;\n break;\n case '-':\n result = x - y;\n break;\n case '*':\n result = x * y;\n break;\n case '/':\n if (y === 0) return this.fail('#DIV/0!', 'The formula divides by zero.');\n result = x / y;\n break;\n default:\n result = Math.pow(x, y);\n }\n return Number.isFinite(result) ? result : this.fail('#NUM!', 'The result is too large or not a number.');\n }\n\n switch (node.op) {\n case '&':\n return toText(left) + toText(right);\n case '=':\n return compareValues(left, right) === 0;\n case '<>':\n return compareValues(left, right) !== 0;\n case '<':\n return compareValues(left, right) < 0;\n case '<=':\n return compareValues(left, right) <= 0;\n case '>':\n return compareValues(left, right) > 0;\n case '>=':\n return compareValues(left, right) >= 0;\n default:\n throw new Error(`Unsupported binary operator: ${node.op}`);\n }\n }\n\n case 'FunctionCall':\n return this.callFunction(node);\n\n default:\n throw new Error(`Unknown AST node: ${(node as any).type}`);\n }\n }\n\n private evaluateRange(node: RangeNode): any[] {\n if (!this.context.resolveRange) {\n throw new Error(`Cannot resolve range ${node.raw}: no range resolver provided`);\n }\n const values = this.context.resolveRange(node.startCol, node.startRow, node.endCol, node.endRow);\n if (!Array.isArray(values)) return values;\n // Record the 2D shape so lookups can address rows and columns.\n const cols = Math.abs(colNameToIndex(node.endCol) - colNameToIndex(node.startCol)) + 1;\n if (values.length % cols === 0) withRangeShape(values, values.length / cols, cols);\n const error = values.find(isFormulaError);\n if (error) this.fail(error as FormulaErrorCode, `The range ${node.raw} contains an error (${error}).`);\n return values;\n }\n\n private callFunction(node: FunctionCallNode): any {\n const def = getFormulaFunction(node.name);\n if (!def) return this.fail('#NAME?', `Unknown function \"${node.name.toUpperCase()}\".`);\n\n const countError = checkFormulaArgumentCount(def, node.args.length);\n if (countError) return this.fail('#ERROR!', countError);\n\n const result = def.evaluate(this.createContext(def, node.args));\n if (typeof result === 'number' && !Number.isFinite(result)) {\n return this.fail('#NUM!', `${def.name} produced an invalid number.`);\n }\n return result === undefined || result === null ? '' : result;\n }\n\n private createContext(def: FormulaFunctionDefinition, nodes: ASTNode[]): FormulaFunctionContext {\n const cache = new Map<number, any>();\n const args: FormulaArgument[] = nodes.map((node, index) => ({\n index,\n node,\n value: () => {\n if (!cache.has(index)) cache.set(index, this.evaluateNode(node));\n return cache.get(index);\n },\n }));\n\n const has = (index: number) => index >= 0 && index < args.length;\n const value = (index: number) => (has(index) ? args[index].value() : '');\n const argError = (index: number, code: FormulaErrorCode, reason: string) =>\n this.fail(code, `Argument ${index + 1} of ${def.name} ${reason}`);\n\n const scalar = (index: number) => {\n const v = value(index);\n if (!Array.isArray(v)) return v;\n if (v.length <= 1) return v.length === 1 ? v[0] : '';\n return argError(index, '#VALUE!', 'must be a single value, not a range.');\n };\n\n const number = (index: number, fallback?: number): number | string => {\n if (!has(index) && fallback !== undefined) return fallback;\n const v = scalar(index);\n if (isFormulaError(v)) return v;\n const num = toNumber(v);\n return isFormulaError(num) ? argError(index, '#VALUE!', `can't be text (${quote(v)}).`) : num;\n };\n\n const flatValues = (from = 0, to = args.length): any[] => {\n const items: any[] = [];\n for (let i = from; i < Math.min(to, args.length); i++) {\n const v = args[i].value();\n if (Array.isArray(v)) {\n // No spread: push(...v) overflows the stack for large ranges.\n for (const item of v) items.push(item);\n } else {\n items.push(v);\n }\n }\n return items;\n };\n\n return {\n name: def.name,\n args,\n error: (code, message) => this.fail(code, message ?? describeFormulaError(code)),\n argError,\n has,\n value,\n scalar,\n number,\n integer: (index, fallback) => {\n const num = number(index, fallback);\n return isFormulaError(num) ? num : Math.trunc(num as number);\n },\n text: (index, fallback) => {\n if (!has(index) && fallback !== undefined) return fallback;\n const v = scalar(index);\n return isFormulaError(v) ? v : toText(v);\n },\n boolean: (index, fallback) => {\n if (!has(index) && fallback !== undefined) return fallback;\n const v = scalar(index);\n if (isFormulaError(v)) return v;\n const bool = toBoolean(v);\n return isFormulaError(bool) ? argError(index, '#VALUE!', `must be TRUE or FALSE, not text (${quote(v)}).`) : bool;\n },\n date: (index) => {\n const v = scalar(index);\n if (isFormulaError(v)) return v;\n if (isBlank(v)) return argError(index, '#VALUE!', 'is empty, but a date is needed.');\n return toDate(v) ?? argError(index, '#VALUE!', `(${quote(v)}) isn't a valid date.`);\n },\n range: (index) => {\n const v = value(index);\n if (Array.isArray(v)) return toFormulaRange(v);\n if (isFormulaError(v)) return v;\n return argError(index, '#VALUE!', 'must be a range.');\n },\n flatValues,\n numbers: (from, to) => {\n // Numbers among the arguments (text and blanks are skipped, as in SUM);\n // the first error found is returned instead.\n const nums: number[] = [];\n for (const item of flatValues(from, to)) {\n if (isFormulaError(item)) return item;\n if (isBlank(item) || typeof item === 'boolean') continue;\n const num = typeof item === 'number' ? item : numericValue(item);\n if (num !== null) nums.push(num);\n }\n return nums;\n },\n };\n }\n}\n"],"mappings":"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","names":["quote","pad","bool","arg","min","max"]}
|