diff --git a/ClosedXML/Excel/CalcEngine/Functions/MathTrig.cs b/ClosedXML/Excel/CalcEngine/Functions/MathTrig.cs index 688db07..ee73ea1 100644 --- a/ClosedXML/Excel/CalcEngine/Functions/MathTrig.cs +++ b/ClosedXML/Excel/CalcEngine/Functions/MathTrig.cs @@ -4,6 +4,7 @@ using System.Collections; using System.Collections.Generic; using System.Linq; +using System.Text; namespace ClosedXML.Excel.CalcEngine { @@ -26,6 +27,7 @@ ce.RegisterFunction("COS", 1, Cos); ce.RegisterFunction("COSH", 1, Cosh); ce.RegisterFunction("CSCH", 1, Csch); + ce.RegisterFunction("DECIMAL", 2, MathTrig.Decimal); ce.RegisterFunction("DEGREES", 1, Degrees); ce.RegisterFunction("EVEN", 1, Even); ce.RegisterFunction("EXP", 1, Exp); @@ -124,6 +126,40 @@ return 1 / Math.Sinh(p[0]); } + private static object Decimal(List p) + { + string source = p[0]; + double radix = p[1]; + + if (radix < 2 || radix > 36) + throw new NumberException(); + + var asciiValues = Encoding.ASCII.GetBytes(source.ToUpperInvariant()); + + double result = 0; + int i = 0; + + foreach (byte digit in asciiValues) + { + if (digit > 90) + { + throw new NumberException(); + } + + int digitNumber = digit >= 48 && digit < 58 + ? digit - 48 + : digit - 55; + + if (digitNumber > radix - 1) + throw new NumberException(); + + result = result * radix + digitNumber; + i++; + } + + return result; + } + private static object Exp(List p) { return Math.Exp(p[0]); diff --git a/ClosedXML/Excel/XLWorkbook_Load.cs b/ClosedXML/Excel/XLWorkbook_Load.cs index 549357b..3af1993 100644 --- a/ClosedXML/Excel/XLWorkbook_Load.cs +++ b/ClosedXML/Excel/XLWorkbook_Load.cs @@ -728,8 +728,10 @@ private static IXLMarker LoadMarker(IXLWorksheet ws, Xdr.MarkerType marker) { + var row = Math.Max(1, Convert.ToInt32(marker.RowId.InnerText) + 1); + var column = Math.Min(XLHelper.MaxColumnNumber, Convert.ToInt32(marker.ColumnId.InnerText) + 1); return new XLMarker( - ws.Cell(Convert.ToInt32(marker.RowId.InnerText) + 1, Convert.ToInt32(marker.ColumnId.InnerText) + 1).Address, + ws.Cell(row, column).Address, new Point( ConvertFromEnglishMetricUnits(Convert.ToInt32(marker.ColumnOffset.InnerText), GraphicsUtils.Graphics.DpiX), ConvertFromEnglishMetricUnits(Convert.ToInt32(marker.RowOffset.InnerText), GraphicsUtils.Graphics.DpiY) diff --git a/ClosedXML/Excel/XLWorkbook_Save.cs b/ClosedXML/Excel/XLWorkbook_Save.cs index d80ed6f..a60076a 100644 --- a/ClosedXML/Excel/XLWorkbook_Save.cs +++ b/ClosedXML/Excel/XLWorkbook_Save.cs @@ -148,19 +148,18 @@ string sheetName = worksheet.Name; // Get the pivot Table Parts - IEnumerable pvtTableCacheParts = wbPart.PivotTableCacheDefinitionParts; - Dictionary pvtTableCacheDefinationPart = new Dictionary(); + var pvtTableCacheParts = wbPart.PivotTableCacheDefinitionParts; + var pvtTableCacheDefinitionPart = new Dictionary(); foreach (PivotTableCacheDefinitionPart Item in pvtTableCacheParts) { PivotCacheDefinition pvtCacheDef = Item.PivotCacheDefinition; //Check if this CacheSource is linked to SheetToDelete - var pvtCache = pvtCacheDef.Descendants().Where(s => s.WorksheetSource.Sheet == sheetName); - if (pvtCache.Any()) + if (pvtCacheDef.Descendants().Any(s => s.WorksheetSource != null && s.WorksheetSource.Sheet == sheetName)) { - pvtTableCacheDefinationPart.Add(Item, Item.ToString()); + pvtTableCacheDefinitionPart.Add(Item, Item.ToString()); } } - foreach (var Item in pvtTableCacheDefinationPart) + foreach (var Item in pvtTableCacheDefinitionPart) { wbPart.DeletePart(Item.Key); } diff --git a/ClosedXML_Tests/Excel/CalcEngine/MathTrigTests.cs b/ClosedXML_Tests/Excel/CalcEngine/MathTrigTests.cs index ada5f7f..df319ad 100644 --- a/ClosedXML_Tests/Excel/CalcEngine/MathTrigTests.cs +++ b/ClosedXML_Tests/Excel/CalcEngine/MathTrigTests.cs @@ -12,6 +12,33 @@ { private readonly double tolerance = 1e-10; + [TestCase("FF", 16, 255)] + [TestCase("111", 2, 7)] + [TestCase("zap", 36, 45745)] + public void Decimal(string inputString, int radix, int expectedResult) + { + var actualResult = XLWorkbook.EvaluateExpr($"DECIMAL(\"{inputString}\", {radix})"); + Assert.AreEqual(expectedResult, actualResult); + } + + [Test] + public void Decimal_ZeroIsZeroInAnyRadix([Range(2, 36)] int radix) + { + Assert.AreEqual(0, XLWorkbook.EvaluateExpr($"DECIMAL(\"0\", {radix})")); + } + + [Theory] + public void Decimal_ReturnsErrorForRadiansGreater36([Range(37, 255)] int radix) + { + Assert.Throws(() => XLWorkbook.EvaluateExpr($"DECIMAL(\"0\", {radix})")); + } + + [Theory] + public void Decimal_ReturnsErrorForRadiansSmaller2([Range(-5, 1)] int radix) + { + Assert.Throws(() => XLWorkbook.EvaluateExpr($"DECIMAL(\"0\", {radix})")); + } + [Test] public void Floor() {