diff --git a/ClosedXML/Excel/CalcEngine/CalcEngine.cs b/ClosedXML/Excel/CalcEngine/CalcEngine.cs index 1738b2f..0b0aa20 100644 --- a/ClosedXML/Excel/CalcEngine/CalcEngine.cs +++ b/ClosedXML/Excel/CalcEngine/CalcEngine.cs @@ -444,10 +444,11 @@ // sub-expressions case TKTYPE.GROUP: - // anything other than opening parenthesis is illegal here + // Normally anything other than opening parenthesis is illegal here + // but Excel allows omitted parameters so return empty value expression. if (_token.ID != TKID.OPEN) { - Throw("Expression expected."); + return new EmptyValueExpression(); } // get expression diff --git a/ClosedXML/Excel/CalcEngine/Expression.cs b/ClosedXML/Excel/CalcEngine/Expression.cs index 286bedd..01399b9 100644 --- a/ClosedXML/Excel/CalcEngine/Expression.cs +++ b/ClosedXML/Excel/CalcEngine/Expression.cs @@ -403,6 +403,15 @@ return (_value as IEnumerable).GetEnumerator(); } } + + /// + /// Expression that represents an omitted parameter. + /// + class EmptyValueExpression : Expression + { + internal EmptyValueExpression() { } + } + /// /// Interface supported by external objects that have to return a value /// other than themselves (e.g. a cell range object should return the diff --git a/ClosedXML/Excel/CalcEngine/Functions/Logical.cs b/ClosedXML/Excel/CalcEngine/Functions/Logical.cs index 18d2a9d..581e97a 100644 --- a/ClosedXML/Excel/CalcEngine/Functions/Logical.cs +++ b/ClosedXML/Excel/CalcEngine/Functions/Logical.cs @@ -47,7 +47,14 @@ { return p[1].Evaluate(); } - return p.Count > 2 ? p[2].Evaluate() : false; + else if (p.Count > 2) + { + if (p[2] is EmptyValueExpression) + return false; + else + return p[2].Evaluate(); + } + else return false; } static object True(List p) @@ -72,4 +79,4 @@ } } } -} \ No newline at end of file +} diff --git a/ClosedXML_Tests/Excel/CalcEngine/FunctionsTests.cs b/ClosedXML_Tests/Excel/CalcEngine/FunctionsTests.cs index 48691a6..af57751 100644 --- a/ClosedXML_Tests/Excel/CalcEngine/FunctionsTests.cs +++ b/ClosedXML_Tests/Excel/CalcEngine/FunctionsTests.cs @@ -616,5 +616,25 @@ Assert.AreEqual(0, cell.Value); Assert.That(() => wb.Worksheet(1).Cell(3, 1).SetFormulaA1("=AVERAGE(D1,D2)").Value, Throws.Exception); } + + [Test] + public void TestOmittedParameters() + { + using (var wb = new XLWorkbook()) + { + object value; + value = wb.Evaluate("=IF(TRUE,1)"); + Assert.AreEqual(1, value); + + value = wb.Evaluate("=IF(TRUE,1,)"); + Assert.AreEqual(1, value); + + value = wb.Evaluate("=IF(FALSE,1,)"); + Assert.AreEqual(false, value); + + value = wb.Evaluate("=IF(FALSE,,2)"); + Assert.AreEqual(2, value); + } + } } }