Skip to content

Commit a17f6d2

Browse files
karlkallmanJanKallmanswmal
authored
Feature/groupby (#2328)
* WIP * WIP * WIP * WIP * Added support for multiple lambda functions to handle PercentOf in the GroupBy function with HStack * WIP * WIP * Lambda expression fix * WIP * Fixed issue with lambda invokation * Added GROUPBY function with base class and tests * Fixed failing test in AppVeyor * Fix for AppVeyor test * Broke out protected classes from GroupByFunctionBase --------- Co-authored-by: Jan Källman <jan.kallman@epplussoftware.com> Co-authored-by: swmal <897655+swmal@users.noreply.github.com>
1 parent fbefed1 commit a17f6d2

File tree

18 files changed

+1540
-18
lines changed

18 files changed

+1540
-18
lines changed

src/EPPlus/FormulaParsing/DependencyChain/RpnFormula.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ internal LambdaExpressionStackPosition GetCurrentLambdaExpressionStackPosition()
130130
internal int GetNumberOfLambdaVariables()
131131
{
132132
if (_lambdaSettings == null || _lambdaSettings.NumberOfLambdaVariables == null || _lambdaSettings.NumberOfLambdaVariables.Count == 0) return 0;
133+
if (_lambdaSettings.CurrentLambdaExpressions.Peek().Expression.ArgumentCollectionStarted == false) return 0;
133134
return _lambdaSettings.NumberOfLambdaVariables.Peek();
134135
}
135136

src/EPPlus/FormulaParsing/DependencyChain/RpnFormulaExecution.cs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1130,7 +1130,11 @@ private static FormulaRangeAddress[] ExecuteNextToken(RpnOptimizedDependencyChai
11301130
{
11311131
exp.Status |= ExpressionStatus.IsLambdaVariableDeclaration;
11321132
}
1133-
1133+
if (t.TokenType == TokenType.EtaReducedLambda)
1134+
{
1135+
((FunctionExpression)f._expressions[f._tokenIndex]).SetRpnFormula(f);
1136+
}
1137+
11341138
var cr = exp.Compile();
11351139
if (cr.DataType == DataType.LambdaTokens)
11361140
{
@@ -1140,7 +1144,11 @@ private static FormulaRangeAddress[] ExecuteNextToken(RpnOptimizedDependencyChai
11401144
{
11411145
s.Push(f._expressions[f._tokenIndex]);
11421146
}
1143-
else if (cr.DataType != DataType.LambdaVariableDeclaration && f.LambdaSettings.LambdaArgsAdded.Count > 0 && f.LambdaSettings.LambdaArgsAdded.Peek() < f.GetNumberOfLambdaVariables())
1147+
else if(
1148+
f._expressionStack.Peek() is LambdaCalculationExpression lce2 && lce2.ArgumentCollectionStarted &&
1149+
cr.DataType != DataType.LambdaVariableDeclaration
1150+
&& f.LambdaSettings.LambdaArgsAdded.Count > 0
1151+
&& f.LambdaSettings.LambdaArgsAdded.Peek() < f.GetNumberOfLambdaVariables())
11441152
{
11451153
leStackPos.Expression.SetVariable(f.LambdaSettings.LambdaArgsAdded.Peek(), cr.Result, cr.DataType, cr.Address);
11461154
var nLambdaArgsAdded = f.LambdaSettings.LambdaArgsAdded.Pop();
@@ -1155,10 +1163,7 @@ private static FormulaRangeAddress[] ExecuteNextToken(RpnOptimizedDependencyChai
11551163
{
11561164
s.Push(f._expressions[f._tokenIndex]);
11571165
}
1158-
if(t.TokenType == TokenType.EtaReducedLambda)
1159-
{
1160-
((FunctionExpression)f._expressions[f._tokenIndex]).SetRpnFormula(f);
1161-
}
1166+
11621167
break;
11631168
case TokenType.Negator:
11641169
s.Push(s.Pop().Negate());
@@ -1735,6 +1740,10 @@ private static IList<CompileResult> CompileFunctionArguments(RpnFormula f, Funct
17351740
{
17361741
si.Status |= ExpressionStatus.FunctionArgument;
17371742
}
1743+
if(si is FunctionExpression fe1)
1744+
{
1745+
fe1.SetRpnFormula(f);
1746+
}
17381747
var cr = si.Compile();
17391748
list.Insert(0, cr);
17401749
}

src/EPPlus/FormulaParsing/Excel/Functions/BuiltInFunctions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,7 @@ public BuiltInFunctions()
336336
// Reference and lookup
337337
Functions["address"] = new Address();
338338
Functions["areas"] = new Areas();
339+
Functions["groupby"] = new GroupBy();
339340
Functions["hlookup"] = new HLookup();
340341
Functions["vlookup"] = new VLookup();
341342
Functions["xlookup"] = new Xlookup();

src/EPPlus/FormulaParsing/Excel/Functions/ExcelFunction.cs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,14 @@ public virtual void GetNewParameterAddress(IList<CompileResult> args, int index,
128128
{
129129

130130
}
131+
132+
public virtual string Name
133+
{
134+
get
135+
{
136+
return GetType().Name.ToUpper();
137+
}
138+
}
131139
/// <summary>
132140
/// Indicates that the function is an ErrorHandlingFunction.
133141
/// </summary>
@@ -895,10 +903,21 @@ public virtual bool IsAllowedInCalculatedPivotTableField
895903
return true;
896904
}
897905
}
898-
/// <summary>
899-
/// Provides information about the functions parameters.
900-
/// </summary>
901-
public virtual ExcelFunctionParametersInfo ParametersInfo
906+
/// <summary>
907+
/// The function is allowed...
908+
/// </summary>
909+
public virtual bool IsAllowedAsLambdaWithMultipleArguments
910+
{
911+
get
912+
{
913+
return false;
914+
}
915+
}
916+
917+
/// <summary>
918+
/// Provides information about the functions parameters.
919+
/// </summary>
920+
public virtual ExcelFunctionParametersInfo ParametersInfo
902921
{
903922
get;
904923
} = ExcelFunctionParametersInfo.Default;

src/EPPlus/FormulaParsing/Excel/Functions/MathFunctions/PercentOf.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ internal class PercentOf : ExcelFunction
2626
{
2727
public override int ArgumentMinLength => 2;
2828
public override string NamespacePrefix => "_xlfn.";
29-
29+
public override bool IsAllowedAsLambdaWithMultipleArguments => true;
3030
public override CompileResult Execute(IList<FunctionArgument> arguments, ParsingContext context)
3131
{
3232
if (arguments.Count > 2)

src/EPPlus/FormulaParsing/Excel/Functions/MathFunctions/Sum.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ namespace OfficeOpenXml.FormulaParsing.Excel.Functions.MathFunctions
2424
internal class SumV2 : ExcelFunction
2525
{
2626
public override int ArgumentMinLength => 1;
27+
public override string Name => "SUM";
2728

2829
public override CompileResult Execute(IList<FunctionArgument> arguments, ParsingContext context)
2930
{

0 commit comments

Comments
 (0)