Posted 16 August 2024, 6:19 am EST
Hi Niels,
You do not need to work with DelegateValue class which is internal. You instead work with IDelegate, which represents the result of “calculation” parameter of LAMBDA function.
Here is the code snippet that shows how to implement custom function using lambda parameter:
fpSpread1.AsWorkbook().WorkbookSet.CalculationEngine.CalcFeatures = CalcFeatures.All;
fpSpread1.AddCustomFunction(new ForEachFunction());
fpSpread1_Sheet1.AsWorksheet().Cells["A2"].Formula2 = "{\"idA\";\"idB\";\"idC\"}";
fpSpread1_Sheet1.AsWorksheet().Cells["B1"].Formula2 = "{\"id1\",\"id2\",\"id3\"}";
fpSpread1.ActiveSheet.AsWorksheet().Cells["B2"].Formula2 = "ForEach(A2#,B1#,LAMBDA(y,x,CONCAT(x,y)))";
public class ForEachFunction : Function
{
public ForEachFunction() : base("ForEach", 3, 3, FunctionAttributes.Array | FunctionAttributes.Spillable)
{
}
protected override void Evaluate(IArguments arguments, IValue result)
{
IValue rowsArg = arguments[0];
switch (rowsArg.ValueType)
{
case GrapeCity.CalcEngine.ValueType.Reference:
case GrapeCity.CalcEngine.ValueType.AdjustableReference:
IValue colsArg = arguments[1];
switch (colsArg.ValueType)
{
case GrapeCity.CalcEngine.ValueType.Reference:
case GrapeCity.CalcEngine.ValueType.AdjustableReference:
IValue funcArg = arguments[2];
if (funcArg.ValueType == GrapeCity.CalcEngine.ValueType.Delegate)
{
IDelegate func = funcArg.GetDelegate();
IEvaluationContext context = arguments.EvaluationContext;
IReferenceSource rowSource = rowsArg.GetReferenceSource(context);
RangeReference rowRange = rowsArg.GetReference(context);
IReferenceSource colSource = colsArg.GetReferenceSource(context);
RangeReference colRange = colsArg.GetReference(context);
IValuesArray array = result.CreateValuesArray(rowRange.Row2 - rowRange.Row + 1, colRange.Column2 - colRange.Column + 1);
for (int row = rowRange.Row, row2 = rowRange.Row2; row <= row2; row++)
{
rowSource.GetValue(context, row, rowRange.Column, func[1].Value);
for (int col = colRange.Column, col2 = colRange.Column2; col <= col2; col++)
{
colSource.GetValue(context, colRange.Row, col, func[0].Value);
context.Evaluate(func, result);
array[row - rowRange.Row, col - colRange.Column].SetValue(result.GetValue(context));
}
}
result.SetValue(array);
}
else
{
result.SetValue(CalcError.Calc);
}
break;
default:
result.SetValue(CalcError.Reference);
break;
}
break;
default:
result.SetValue(CalcError.Reference);
break;
}
}
}
}
Kindly refer to the attached sample for full implementation. [See LamdaParamDemo.zip]
In case this does not meet your requirement, we kindly request you share your workbooks with us. If you can’t share the files here, you can create a case on our private support portal: https://developer.mescius.com/my-account/my-support
Hope this helps!
Thanks & Regards,
Aastha