diff --git a/src/EPPlus/FormulaParsing/Excel/Functions/Text/NumberValue.cs b/src/EPPlus/FormulaParsing/Excel/Functions/Text/NumberValue.cs index 86bfd793e..0501432ed 100644 --- a/src/EPPlus/FormulaParsing/Excel/Functions/Text/NumberValue.cs +++ b/src/EPPlus/FormulaParsing/Excel/Functions/Text/NumberValue.cs @@ -10,6 +10,7 @@ Date Author Change ************************************************************************************************* 01/27/2020 EPPlus Software AB Initial release EPPlus 5 *************************************************************************************************/ +using OfficeOpenXml.FormulaParsing.Excel.Functions.Finance.Implementations; using OfficeOpenXml.FormulaParsing.Excel.Functions.Metadata; using OfficeOpenXml.FormulaParsing.FormulaExpressions; using System; @@ -49,9 +50,16 @@ public override CompileResult Execute(IList arguments, Parsing return CreateResult(ExcelErrorValue.Values.Value, DataType.ExcelError); } var cultureInfo = new CultureInfo("en-US", true); - cultureInfo.NumberFormat.NumberDecimalSeparator = _decimalSeparator; cultureInfo.NumberFormat.NumberGroupSeparator = _groupSeparator; - if(double.TryParse(_arg, NumberStyles.Any, cultureInfo, out double result)) + cultureInfo.NumberFormat.NumberDecimalSeparator = _decimalSeparator; + + //These are required. double.TryParse with NumberStyles.Any considers the input string a currency + //See s1018 + cultureInfo.NumberFormat.CurrencyDecimalSeparator = _decimalSeparator; + cultureInfo.NumberFormat.CurrencyGroupSeparator = _groupSeparator; + + + if (double.TryParse(_arg, NumberStyles.Any, cultureInfo, out double result)) { if(_nPercentage > 0) { diff --git a/src/EPPlusTest/FormulaParsing/Excel/Functions/TextFunctionsTests.cs b/src/EPPlusTest/FormulaParsing/Excel/Functions/TextFunctionsTests.cs index da56a51d2..85a2d473e 100644 --- a/src/EPPlusTest/FormulaParsing/Excel/Functions/TextFunctionsTests.cs +++ b/src/EPPlusTest/FormulaParsing/Excel/Functions/TextFunctionsTests.cs @@ -351,6 +351,46 @@ public void NumberValueShouldCastDecinalValueWithCurrentCulture() Thread.CurrentThread.CurrentCulture = currentCulture; } + [TestMethod] + public void NumberValueDifferingFromCurrentCultureOrUsCultureShouldStillWork() + { + var currentCulture = CultureInfo.CurrentCulture; + Thread.CurrentThread.CurrentCulture = new CultureInfo("de-DE"); + var input = $"1{"."}000{","}15"; + var func = new NumberValue(); + + var args = FunctionsHelper.CreateArgs(input, ",","."); + var result2 = func.Execute(args, _parsingContext); + Assert.AreEqual(1000.15d, result2.Result); + Thread.CurrentThread.CurrentCulture = currentCulture; + } + + [TestMethod] + public void NumberValueInternalLogicCurrencyAndDoubleParse() + { + //This logic is used to make + var cultureInfo = new CultureInfo("en-US", true); + cultureInfo.NumberFormat.NumberGroupSeparator = "."; + cultureInfo.NumberFormat.NumberDecimalSeparator = ","; + + var input = $"1{"."}000{","}15"; + + //Using NumberStyles.Any will consider this as a currency and fail to parse + var successFirst = double.TryParse(input, NumberStyles.Any, cultureInfo, out double result); + + Assert.IsFalse(successFirst); + Assert.AreNotEqual(1000.15, result); + + cultureInfo.NumberFormat.CurrencyGroupSeparator = "."; + cultureInfo.NumberFormat.CurrencyDecimalSeparator = ","; + + //Setting the currency causes it to work correctly + var successSecond = double.TryParse(input, NumberStyles.Any, cultureInfo, out double currencyResult); + + Assert.IsTrue(successSecond); + Assert.AreEqual(1000.15, currencyResult); + } + [TestMethod] public void NumberValueShouldCastDecinalValueWithSeparators() { diff --git a/src/EPPlusTest/Issues/FormulaCalculationIssues.cs b/src/EPPlusTest/Issues/FormulaCalculationIssues.cs index 07b9bb3a8..9c2db9d68 100644 --- a/src/EPPlusTest/Issues/FormulaCalculationIssues.cs +++ b/src/EPPlusTest/Issues/FormulaCalculationIssues.cs @@ -1472,6 +1472,32 @@ public void s965_3() SaveAndCleanup(package); } + + [TestMethod] + public void s1018() + { + SwitchToCulture("fi-FI"); + using (var package = OpenPackage("testValueAndNumberValue.xlsx", true)) + { + var ws = package.Workbook.Worksheets.Add("Calculation"); + ws.Cells["A2"].Value = "-9.388.757,91"; + ws.Cells["C2"].Formula = "NUMBERVALUE(A2,\",\",\".\")"; + + package.Workbook.CalcMode = ExcelCalcMode.Automatic; + var options = new OfficeOpenXml.FormulaParsing.ExcelCalculationOption + { + PrecisionAndRoundingStrategy = OfficeOpenXml.FormulaParsing.PrecisionAndRoundingStrategy.Excel, + AllowCircularReferences = true, + EnableUnicodeAwareStringOperations = true + + }; + package.Workbook.Calculate(options); + + Assert.AreEqual(-9388757.91, ws.Cells["C2"].Value); + } + SwitchBackToCurrentCulture(); + } + } }