Skip to content

Commit

Permalink
Issue #48 implemented switch function
Browse files Browse the repository at this point in the history
  • Loading branch information
swmal committed Feb 28, 2020
1 parent ec86904 commit fbf4d6d
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ public BuiltInFunctions()
Functions["or"] = new Or();
Functions["true"] = new True();
Functions["false"] = new False();
Functions["switch"] = new Switch();
// Reference and lookup
Functions["address"] = new Address();
Functions["hlookup"] = new HLookup();
Expand Down
2 changes: 1 addition & 1 deletion src/EPPlus/FormulaParsing/Excel/Functions/Logical/Ifs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Logical
{
public class Ifs : ExcelFunction
internal class Ifs : ExcelFunction
{
public override CompileResult Execute(IEnumerable<FunctionArgument> arguments, ParsingContext context)
{
Expand Down
69 changes: 69 additions & 0 deletions src/EPPlus/FormulaParsing/Excel/Functions/Logical/Switch.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Logical
{
internal class Switch : ExcelFunction
{
public Switch()
: this(new CompileResultFactory())
{

}
public Switch(CompileResultFactory compileResultFactory)
{
_compileResultFactory = compileResultFactory;
}

private readonly CompileResultFactory _compileResultFactory;

public override CompileResult Execute(IEnumerable<FunctionArgument> arguments, ParsingContext context)
{
ValidateArguments(arguments, 3);
var expression = arguments.ElementAt(0).ValueFirst;
var maxLength = 1 + 126 * 2;
for(var x = 1; x < (arguments.Count() - 1) || x >= maxLength; x += 2)
{
var candidate = arguments.ElementAt(x).Value;
if(IsMatch(expression, candidate))
{
return _compileResultFactory.Create(arguments.ElementAt(x + 1).Value);
}
}
if (arguments.Count() % 2 == 0) return _compileResultFactory.Create(arguments.Last().Value);
return new CompileResult(eErrorType.NA);
}

private bool IsMatch(object right, object left)
{
if(IsNumeric(right) || IsNumeric(left))
{
var r = GetNumericValue(right);
var l = GetNumericValue(left);
return r.Equals(l);
}
if(right == null && left == null)
{
return true;
}
if (right == null) return false;
return right.Equals(left);
}

private double GetNumericValue(object obj)
{
if(obj is System.DateTime)
{
return ((System.DateTime)obj).ToOADate();
}
if(obj is TimeSpan)
{
return ((TimeSpan)obj).TotalMilliseconds;
}
return Convert.ToDouble(obj);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -259,5 +259,46 @@ public void IfNaShouldReturnResultOfFormulaIfNoError()
Assert.AreEqual("hi there", s1.Cells["A1"].Value);
}
}

[TestMethod]
public void SwitchShouldReturnFirstMatchingArg()
{
using (var package = new ExcelPackage())
{
var s1 = package.Workbook.Worksheets.Add("test");
s1.Cells["A1"].Formula = "SWITCH(A2, 1, 2)";
s1.Cells["A2"].Value = 1;
s1.Calculate();
Assert.AreEqual(2d, s1.Cells["A1"].Value);
}
}

[TestMethod]
public void SwitchShouldIgnoreNonMatchingArg()
{
using (var package = new ExcelPackage())
{
var s1 = package.Workbook.Worksheets.Add("test");
s1.Cells["A1"].Formula = "SWITCH(A2, 1, 2, B2, 3)";
s1.Cells["A2"].Value = 2;
s1.Cells["B2"].Value = 2d;
s1.Calculate();
Assert.AreEqual(3d, s1.Cells["A1"].Value);
}
}

[TestMethod]
public void SwitchShouldReturnLastArgIfNoMatch()
{
using (var package = new ExcelPackage())
{
var s1 = package.Workbook.Worksheets.Add("test");
s1.Cells["A1"].Formula = "SWITCH(A2, 1, 2, B2, 3, 5)";
s1.Cells["A2"].Value = -1;
s1.Cells["B2"].Value = 2d;
s1.Calculate();
Assert.AreEqual(5d, s1.Cells["A1"].Value);
}
}
}
}

0 comments on commit fbf4d6d

Please sign in to comment.