/** * @license * Copyright (c) 2025 Handsoncode. All rights reserved. */ import { ProcedureAst } from '../../parser'; import { InterpreterState } from '../InterpreterState'; import { InterpreterValue } from '../InterpreterValue'; import { FunctionPlugin, FunctionPluginTypecheck, ImplementedFunctions } from './FunctionPlugin'; /** * Interpreter plugin implementing Excel database functions. * * Implements: DAVERAGE, DCOUNT, DCOUNTA, DGET, DMAX, DMIN, DPRODUCT, DSTDEV, DSTDEVP, DSUM, DVAR, DVARP. */ export declare class DatabasePlugin extends FunctionPlugin implements FunctionPluginTypecheck { static implementedFunctions: ImplementedFunctions; /** * Resolves field index and criteria, then delegates to the callback with the parsed database arguments. * Shared boilerplate for all 12 database functions. */ private withDatabaseArgs; /** * Counts cells containing numbers in the specified field of a database range, * for rows that match all criteria. * * DCOUNT(database, field, criteria) */ dcount(ast: ProcedureAst, state: InterpreterState): InterpreterValue; /** * Counts all non-blank cells in the specified field of a database range, * for rows that match all criteria. * * DCOUNTA(database, field, criteria) */ dcounta(ast: ProcedureAst, state: InterpreterState): InterpreterValue; /** * Returns the product of numeric values in the specified field of a database range, * for rows that match all criteria. * * DPRODUCT(database, field, criteria) */ dproduct(ast: ProcedureAst, state: InterpreterState): InterpreterValue; /** * Returns the sum of numeric values in the specified field of a database range, * for rows that match all criteria. * * DSUM(database, field, criteria) */ dsum(ast: ProcedureAst, state: InterpreterState): InterpreterValue; /** * Returns the average of numeric values in the specified field of a database range, * for rows that match all criteria. * Returns #DIV/0! when no numeric values are found. * * DAVERAGE(database, field, criteria) */ daverage(ast: ProcedureAst, state: InterpreterState): InterpreterValue; /** * Returns a single value from the specified field of a database range, * for the row that matches all criteria. * Returns #VALUE! if no rows match, #NUM! if more than one row matches. * * DGET(database, field, criteria) */ dget(ast: ProcedureAst, state: InterpreterState): InterpreterValue; /** * Returns the maximum numeric value in the specified field of a database range, * for rows that match all criteria. * Returns 0 when no numeric values are found (Excel behavior). * * DMAX(database, field, criteria) */ dmax(ast: ProcedureAst, state: InterpreterState): InterpreterValue; /** * Returns the minimum numeric value in the specified field of a database range, * for rows that match all criteria. * Returns 0 when no numeric values are found (Excel behavior). * * DMIN(database, field, criteria) */ dmin(ast: ProcedureAst, state: InterpreterState): InterpreterValue; /** * Returns the sample standard deviation of numeric values in the specified field * of a database range, for rows that match all criteria. * Returns #DIV/0! when fewer than 2 numeric values are found. * * DSTDEV(database, field, criteria) */ dstdev(ast: ProcedureAst, state: InterpreterState): InterpreterValue; /** * Returns the population standard deviation of numeric values in the specified field * of a database range, for rows that match all criteria. * Returns #DIV/0! when no numeric values are found. * Returns 0 when exactly one numeric value is found. * * DSTDEVP(database, field, criteria) */ dstdevp(ast: ProcedureAst, state: InterpreterState): InterpreterValue; /** * Returns the sample variance of numeric values in the specified field * of a database range, for rows that match all criteria. * Returns #DIV/0! when fewer than 2 numeric values are found. * * DVAR(database, field, criteria) */ dvar(ast: ProcedureAst, state: InterpreterState): InterpreterValue; /** * Returns the population variance of numeric values in the specified field * of a database range, for rows that match all criteria. * Returns #DIV/0! when no numeric values are found. * Returns 0 when exactly one numeric value is found. * * DVARP(database, field, criteria) */ dvarp(ast: ProcedureAst, state: InterpreterState): InterpreterValue; /** * Collects numeric values from the specified field column of matching database rows. * * @param dbData - Full database data including header row. * @param fieldIndex - 0-based column index of the target field. * @param criteriaRows - Parsed criteria rows. * @returns Array of numeric values from matching rows, or the first CellError * encountered in a matching field cell (propagated per Excel semantics). */ private collectNumericValues; /** * Resolves the field argument to a 0-based column index within the database range. * * @param database - The database range (first row = headers). * @param field - A string (header name, case-insensitive) or number (1-based column index). * Booleans are coerced to numbers (TRUE → 1, FALSE → 0) per Excel convention. * @returns 0-based column index, or CellError if field is invalid. */ private resolveFieldIndex; /** * Parses the criteria range into an array of criteria rows. * Each row is a list of AND-ed conditions. Rows are OR-ed together. * * @param database - The database range (first row = headers). * @param criteria - The criteria range (first row = header labels, subsequent rows = conditions). * @returns Array of criteria rows, or CellError if a criterion cannot be parsed. */ private buildDatabaseCriteria; /** * Tests whether a database data row matches any of the criteria rows (OR logic). * Within each criteria row, all conditions must match (AND logic). * * @param dataRow - A single row of data from the database (excluding the header row). * @param criteriaRows - Parsed criteria rows. * @returns true if the row qualifies, false otherwise. */ private rowMatchesCriteria; }