Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/EPPlus/FormulaParsing/DependencyChain/LambdaInvoker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ internal static CompileResult InvokeLambdaFunction(RpnOptimizedDependencyChain d
}
}
}
f.OnLambdaInvoked();
return result;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1179,7 +1179,6 @@ private static FormulaRangeAddress[] ExecuteNextToken(RpnOptimizedDependencyChai
CompileResult lambdaResult = LambdaInvoker.InvokeLambdaFunction(depChain, f);
if (lambdaResult != null)
PushResult(depChain._parsingContext, f, lambdaResult);
f.OnLambdaInvoked();
}
else if(f._funcStack.Count > 0)
{
Expand Down Expand Up @@ -1257,6 +1256,11 @@ private static FormulaRangeAddress[] ExecuteNextToken(RpnOptimizedDependencyChai
}

var r = ExecFunc(depChain, f, funcExp);
if(funcExp.ExecutesLambda)
{
// these functions will always invoke at least one LAMBDA
f.OnLambdaInvoked();
}
funcExp.OnDispose();
if (r.ResultType == CompileResultType.DynamicArray_AlwaysSetCellAsDynamic)
{
Expand Down
2 changes: 2 additions & 0 deletions src/EPPlus/FormulaParsing/Excel/Functions/Logical/ByCol.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ internal class ByCol : ExcelFunction

public override string NamespacePrefix => "_xlfn.";

public override bool ExecutesLambda => true;

public override CompileResult Execute(IList<FunctionArgument> arguments, ParsingContext context)
{
var range = ArgToRangeInfo(arguments, 0);
Expand Down
2 changes: 2 additions & 0 deletions src/EPPlus/FormulaParsing/Excel/Functions/Logical/ByRow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ internal class ByRow : ExcelFunction

public override string NamespacePrefix => "_xlfn.";

public override bool ExecutesLambda => true;

public override CompileResult Execute(IList<FunctionArgument> arguments, ParsingContext context)
{
var range = ArgToRangeInfo(arguments, 0);
Expand Down
3 changes: 1 addition & 2 deletions src/EPPlus/FormulaParsing/Excel/Functions/Logical/IfError.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ public override void ConfigureArrayBehaviour(ArrayBehaviourConfig config)
config.SetArrayParameterIndexes(0, 1);
}
public override CompileResult Execute(IList<FunctionArgument> arguments, ParsingContext context)
{

{
var arg1 = arguments[0];
var arg2 = arguments[1];
if (arg1.ValueIsExcelError)
Expand Down
2 changes: 2 additions & 0 deletions src/EPPlus/FormulaParsing/Excel/Functions/Logical/Map.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ public object GetByIndex(int index)

public override string NamespacePrefix => "_xlfn.";

public override bool ExecutesLambda => true;

public override CompileResult Execute(IList<FunctionArgument> arguments, ParsingContext context)
{
var lastArg = arguments.LastOrDefault();
Expand Down
2 changes: 2 additions & 0 deletions src/EPPlus/FormulaParsing/Excel/Functions/Logical/Reduce.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ internal class Reduce : ExcelFunction

public override string NamespacePrefix => "_xlfn.";

public override bool ExecutesLambda => true;

public override CompileResult Execute(IList<FunctionArgument> arguments, ParsingContext context)
{
object initialValue = null;
Expand Down
2 changes: 2 additions & 0 deletions src/EPPlus/FormulaParsing/Excel/Functions/Logical/Scan.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ internal class Scan : ExcelFunction

public override string NamespacePrefix => "_xlfn.";

public override bool ExecutesLambda => true;

public override CompileResult Execute(IList<FunctionArgument> arguments, ParsingContext context)
{
if (arguments[0].IsExcelRange)
Expand Down
17 changes: 9 additions & 8 deletions src/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/Filter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public override CompileResult Execute(IList<FunctionArgument> arguments, Parsing
return CompileResult.GetErrorResult(eErrorType.Value);
}

if(s1.NumberOfRows==s2.NumberOfRows)
if(s1.NumberOfRows==s2.NumberOfRows & s1.NumberOfRows > 1)
{
return FilterOnRow(arg1, arg2, arg3);
}
Expand Down Expand Up @@ -79,7 +79,7 @@ private static CompileResult FilterOnRow(IRangeInfo arg1, IRangeInfo arg2, Funct
var s1 = arg1.Size;
var s2 = arg2.Size;

if (s2.NumberOfCols != 1)
if (s2.NumberOfCols != 1 && s1.NumberOfCols != s2.NumberOfCols)
{
return CompileResult.GetDynamicArrayResultError(eErrorType.Value);
}
Expand Down Expand Up @@ -127,7 +127,7 @@ private static CompileResult FilterOnColumn(IRangeInfo arg1, IRangeInfo arg2, Fu
var s1 = arg1.Size;
var s2 = arg2.Size;

if (s2.NumberOfRows != 1)
if (s2.NumberOfRows != 1 && s1.NumberOfRows != s2.NumberOfRows)
{
return CompileResult.GetDynamicArrayResultError(eErrorType.Value);
}
Expand All @@ -149,13 +149,14 @@ private static CompileResult FilterOnColumn(IRangeInfo arg1, IRangeInfo arg2, Fu
}
if (boolValue != 0)
{
var row = new List<object>();

for (int r = 0; r < s1.NumberOfCols; r++)
for (int r = 0; r < s1.NumberOfRows; r++)
{
row.Add(arg1.GetOffset(r, c));
if (filteredData.Count <= r)
{
filteredData.Add(new List<object>());
}
filteredData[r].Add(arg1.GetOffset(r, c));
}
filteredData.Add(row);
}
}
if (filteredData.Count == 0)
Expand Down
18 changes: 18 additions & 0 deletions src/EPPlusTest/FormulaParsing/Excel/Functions/Logical/MapTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -200,5 +200,23 @@ public void Map_Xleta_Attribute_IsNumber()
Assert.AreEqual(false, sheet.Cells["B2"].Value); // "hello" → FALSE
Assert.AreEqual(false, sheet.Cells["B3"].Value); // "" → FALSE
}

[TestMethod]
public void Map_ShouldWorkInsideOtherFunction()
{
using var package = new ExcelPackage();
var sheet = package.Workbook.Worksheets.Add("Sheet1");

sheet.Cells["A1"].Value = 1;
sheet.Cells["A2"].Formula = "1/0";
sheet.Cells["A3"].Value = 3;

sheet.Cells["B1"].Formula = "IFERROR(MAP(A1:A3, _xleta.SUM), \"Error!\")";
sheet.Calculate();

Assert.AreEqual(1d, sheet.Cells["B1"].Value);
Assert.AreEqual("Error!", sheet.Cells["B2"].Value);
Assert.AreEqual(3d, sheet.Cells["B3"].Value);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OfficeOpenXml;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace EPPlusTest.FormulaParsing.Excel.Functions.RefAndLookup
{
[TestClass]
public class FilterTests
{
ExcelPackage _package;
ExcelWorksheet _ws;

[TestInitialize]
public void Initialize()
{
_package = new ExcelPackage();
_ws = _package.Workbook.Worksheets.Add("Sheet1");
}

[TestCleanup]
public void Cleanup()
{
_ws = null;
_package.Dispose();
}

[TestMethod]
public void ShouldFilterOnRow()
{
_ws.Cells["A1"].Value = 1;
_ws.Cells["B1"].Value = 2;
_ws.Cells["C1"].Value = 3;
_ws.Cells["A2"].Value = 4;
_ws.Cells["B2"].Value = 5;
_ws.Cells["C2"].Value = 6;
_ws.Cells["A3"].Value = 1;
_ws.Cells["B3"].Value = 5;
_ws.Cells["C3"].Value = 7;

_ws.Cells["D1"].Formula = "FILTER(A1:C3,A1:A3=1)";
_ws.Calculate();
Assert.AreEqual(1, _ws.Cells["D1"].Value);
Assert.AreEqual(2, _ws.Cells["E1"].Value);
Assert.AreEqual(1, _ws.Cells["D2"].Value);
Assert.AreEqual(5, _ws.Cells["E2"].Value);
}

[TestMethod]
public void ShouldFilterOnColumn()
{
_ws.Cells["A1"].Value = 1;
_ws.Cells["B1"].Value = 2;
_ws.Cells["C1"].Value = 3;
_ws.Cells["A2"].Value = 4;
_ws.Cells["B2"].Value = 5;
_ws.Cells["C2"].Value = 6;
_ws.Cells["A3"].Value = 1;
_ws.Cells["B3"].Value = 5;
_ws.Cells["C3"].Value = 7;

_ws.Cells["D1"].Formula = "FILTER(A1:C3,A1:C1=1)";
_ws.Calculate();
Assert.AreEqual(1, _ws.Cells["D1"].Value);
Assert.AreEqual(4, _ws.Cells["D2"].Value);
Assert.AreEqual(1, _ws.Cells["D3"].Value);
}
}
}
Loading