diff --git a/packages/engine-formula/src/engine/ast-node/function-node.ts b/packages/engine-formula/src/engine/ast-node/function-node.ts index e2f2eafdb44..91ee6496733 100644 --- a/packages/engine-formula/src/engine/ast-node/function-node.ts +++ b/packages/engine-formula/src/engine/ast-node/function-node.ts @@ -220,6 +220,10 @@ export class FunctionNode extends BaseAstNode { return (variant as ArrayValueObject).toValue(); } + if (variant.isLambda()) { + return variant; + } + return variant.getValue(); }) ); diff --git a/packages/engine-formula/src/engine/value-object/lambda-value-object.ts b/packages/engine-formula/src/engine/value-object/lambda-value-object.ts index 86bd578eefb..31b3cda2df9 100644 --- a/packages/engine-formula/src/engine/value-object/lambda-value-object.ts +++ b/packages/engine-formula/src/engine/value-object/lambda-value-object.ts @@ -20,10 +20,12 @@ import type { BaseAstNode } from '../ast-node/base-ast-node'; import type { LambdaParameterNode } from '../ast-node/lambda-parameter-node'; import type { Interpreter } from '../interpreter/interpreter'; import type { BaseReferenceObject, FunctionVariantType } from '../reference-object/base-reference-object'; +import type { PrimitiveValueType } from './primitive-object'; import { ErrorType } from '../../basics/error-type'; import { DEFAULT_TOKEN_TYPE_LAMBDA_RUNTIME_PARAMETER } from '../../basics/token-type'; import { AsyncObject } from '../reference-object/base-reference-object'; import { generateExecuteAstNodeData } from '../utils/ast-node-tool'; +import { ValueObjectFactory } from './array-value-object'; import { BaseValueObject, ErrorValueObject } from './base-value-object'; function getRootLexerHasValueNode(node: Nullable): Nullable { @@ -110,6 +112,16 @@ export class LambdaValueObjectObject extends BaseValueObject { return value; } + /** + * Execute custom lambda function, handle basic types + * @param variants + */ + executeCustom(...variants: PrimitiveValueType[]) { + // Create base value object from primitive value, then execute + const baseValueObjects = variants.map((variant) => ValueObjectFactory.create(variant)); + return this.execute(...baseValueObjects); + } + private _setLambdaNodeValue(node: Nullable) { if (!node) { return; diff --git a/packages/engine-formula/src/functions/base-function.ts b/packages/engine-formula/src/functions/base-function.ts index f7f20bb5b6e..edf01b7ba2c 100644 --- a/packages/engine-formula/src/functions/base-function.ts +++ b/packages/engine-formula/src/functions/base-function.ts @@ -191,7 +191,7 @@ export class BaseFunction { } calculateCustom( - ...arg: Array + ...arg: Array ): PrimitiveValueType | PrimitiveValueType[][] { return null; } diff --git a/packages/engine-formula/src/index.ts b/packages/engine-formula/src/index.ts index 466e41f3559..e672f13c9c1 100644 --- a/packages/engine-formula/src/index.ts +++ b/packages/engine-formula/src/index.ts @@ -167,3 +167,4 @@ export { ENGINE_FORMULA_CYCLE_REFERENCE_COUNT, ENGINE_FORMULA_PLUGIN_CONFIG_KEY, export { generateRandomDependencyTreeId } from './engine/dependency/formula-dependency'; export { DependencyManagerBaseService } from './services/dependency-manager.service'; +export { LambdaValueObjectObject } from './engine/value-object/lambda-value-object'; diff --git a/packages/facade/src/apis/__tests__/facade.spec.ts b/packages/facade/src/apis/__tests__/facade.spec.ts index df8ef21a244..beea8231a6d 100644 --- a/packages/facade/src/apis/__tests__/facade.spec.ts +++ b/packages/facade/src/apis/__tests__/facade.spec.ts @@ -15,6 +15,7 @@ */ import type { ICellData, Injector, Nullable } from '@univerjs/core'; +import type { LambdaValueObjectObject, PrimitiveValueType } from '@univerjs/engine-formula'; import type { ColumnHeaderLayout, RenderComponentType, @@ -24,8 +25,8 @@ import type { SpreadsheetRowHeader, } from '@univerjs/engine-render'; import type { FUniver } from '../everything'; -import { ICommandService, IUniverInstanceService } from '@univerjs/core'; +import { ICommandService, IUniverInstanceService } from '@univerjs/core'; import { RegisterFunctionMutation, SetFormulaCalculationStartMutation } from '@univerjs/engine-formula'; import { IRenderManagerService } from '@univerjs/engine-render'; import { SetRangeValuesCommand, SetRangeValuesMutation, SetStyleCommand } from '@univerjs/sheets'; @@ -178,11 +179,22 @@ describe('Test FUniver', () => { it('Function registerFunction', () => { const funcionName = 'CUSTOMSUM'; + const functionsDisposable = univerAPI.registerFunction({ calculate: [ [function (...variants) { let sum = 0; + const last = variants[variants.length - 1] as LambdaValueObjectObject; + + if (last.isLambda()) { + variants.pop(); + + const variantsList = variants.map((variant) => Array.isArray(variant) ? variant[0][0] : variant) as PrimitiveValueType[]; + + sum += +last.executeCustom(...variantsList).getValue(); + } + for (const variant of variants) { sum += Number(variant) || 0; } diff --git a/packages/sheets-formula/src/services/register-function.service.ts b/packages/sheets-formula/src/services/register-function.service.ts index 3257ca5ecc5..32d88ec4471 100644 --- a/packages/sheets-formula/src/services/register-function.service.ts +++ b/packages/sheets-formula/src/services/register-function.service.ts @@ -15,14 +15,14 @@ */ import type { IDisposable, ILocales } from '@univerjs/core'; -import type { IFunctionInfo, PrimitiveValueType } from '@univerjs/engine-formula'; +import type { BaseValueObject, IFunctionInfo, PrimitiveValueType } from '@univerjs/engine-formula'; import { createIdentifier, Disposable, DisposableCollection, Inject, LocaleService, Optional, toDisposable } from '@univerjs/core'; import { CustomFunction, FunctionType, IFunctionService } from '@univerjs/engine-formula'; import { IDescriptionService } from './description.service'; import { IRemoteRegisterFunctionService } from './remote/remote-register-function.service'; export type IRegisterFunction = ( - ...arg: Array + ...arg: Array ) => PrimitiveValueType | PrimitiveValueType[][]; // [[Function, FunctionName, Description]]