diff --git a/ClosedXML/Excel/CalcEngine/XLCalcEngine.cs b/ClosedXML/Excel/CalcEngine/XLCalcEngine.cs index e7457e2..6686621 100644 --- a/ClosedXML/Excel/CalcEngine/XLCalcEngine.cs +++ b/ClosedXML/Excel/CalcEngine/XLCalcEngine.cs @@ -27,14 +27,36 @@ { if (identifier.Contains("!") && _wb != null) { - var wsName = identifier.Substring(0, identifier.IndexOf("!")); - return new CellRangeReference(_wb.Worksheet(wsName).Range(identifier.Substring(identifier.IndexOf("!") + 1)), this); + var referencedSheetNames = identifier.Split(':') + .Select(part => + { + if (part.Contains("!")) + return part.Substring(0, part.IndexOf('!')).ToLower(); + else + return null; + }) + .Where(sheet => sheet != null) + .Distinct(); + + if (!referencedSheetNames.Any()) + return new CellRangeReference(_ws.Range(identifier), this); + else if (referencedSheetNames.Count() > 1) + throw new ArgumentOutOfRangeException(referencedSheetNames.Last(), "Cross worksheet references may references no more than 1 other worksheet"); + else + { + IXLWorksheet worksheet; + if (!_wb.TryGetWorksheet(referencedSheetNames.Single(), out worksheet)) + throw new ArgumentOutOfRangeException(referencedSheetNames.Single(), "The required worksheet cannot be found"); + + identifier = identifier.ToLower().Replace(string.Format("{0}!", worksheet.Name.ToLower()), ""); + + return new CellRangeReference(worksheet.Range(identifier), this); + } } - - if (_ws != null) + else if (_ws != null) return new CellRangeReference(_ws.Range(identifier), this); - - return identifier; + else + return identifier; } } diff --git a/ClosedXML/Excel/XLWorkbook.cs b/ClosedXML/Excel/XLWorkbook.cs index a33adcc..645d536 100644 --- a/ClosedXML/Excel/XLWorkbook.cs +++ b/ClosedXML/Excel/XLWorkbook.cs @@ -396,7 +396,7 @@ public Boolean TryGetWorksheet(String name, out IXLWorksheet worksheet) { - if (Worksheets.Any(w => w.Name.ToLower().Equals(name.ToLower()))) + if (Worksheets.Any(w => string.Equals(w.Name, XLWorksheets.TrimSheetName(name), StringComparison.OrdinalIgnoreCase))) { worksheet = Worksheet(name); return true; diff --git a/ClosedXML/Excel/XLWorksheets.cs b/ClosedXML/Excel/XLWorksheets.cs index ee17781..6207f57 100644 --- a/ClosedXML/Excel/XLWorksheets.cs +++ b/ClosedXML/Excel/XLWorksheets.cs @@ -56,17 +56,24 @@ return false; } - public IXLWorksheet Worksheet(String sheetName) + internal static string TrimSheetName(string sheetName) { - XLWorksheet w; if (sheetName.StartsWith("'") && sheetName.EndsWith("'") && sheetName.Length > 2) sheetName = sheetName.Substring(1, sheetName.Length - 2); + return sheetName; + } + + public IXLWorksheet Worksheet(String sheetName) + { + sheetName = TrimSheetName(sheetName); + + XLWorksheet w; + if (_worksheets.TryGetValue(sheetName, out w)) return w; - var wss = _worksheets.Where(ws => ws.Key.ToLower().Equals(sheetName.ToLower())); - + var wss = _worksheets.Where(ws => string.Equals(ws.Key, sheetName, StringComparison.OrdinalIgnoreCase)); if (wss.Any()) return wss.First().Value; diff --git a/ClosedXML_Tests/Excel/Misc/FormulaTests.cs b/ClosedXML_Tests/Excel/Misc/FormulaTests.cs index a1e1a66..9cfaf7e 100644 --- a/ClosedXML_Tests/Excel/Misc/FormulaTests.cs +++ b/ClosedXML_Tests/Excel/Misc/FormulaTests.cs @@ -1,6 +1,7 @@ using ClosedXML.Excel; using NUnit.Framework; using System; +using System.Linq; namespace ClosedXML_Tests.Excel { @@ -63,6 +64,47 @@ } [Test] + public void FormulaWithReferenceIncludingSheetName() + { + using (var wb = new XLWorkbook()) + { + object value; + var ws = wb.AddWorksheet("Sheet1"); + ws.Cell("A1").InsertData(Enumerable.Range(1, 50)); + ws.Cell("B1").FormulaA1 = "=SUM(A1:A50)"; + value = ws.Cell("B1").Value; + Assert.AreEqual(1275, value); + + ws = wb.AddWorksheet("Sheet2"); + + ws.Cell("A1").FormulaA1 = "=SUM(Sheet1!A1:Sheet1!A50)"; + value = ws.Cell("A1").Value; + Assert.AreEqual(1275, value); + + ws.Cell("B1").FormulaA1 = "=SUM(Sheet1!A1:A50)"; + value = ws.Cell("B1").Value; + Assert.AreEqual(1275, value); + } + } + + [Test] + public void InvalidReferences() + { + using (var wb = new XLWorkbook()) + { + var ws = wb.AddWorksheet("Sheet1"); + ws.Cell("A1").InsertData(Enumerable.Range(1, 50)); + ws = wb.AddWorksheet("Sheet2"); + + ws.Cell("A1").FormulaA1 = "=SUM(Sheet1!A1:Sheet2!A50)"; + Assert.That(() => ws.Cell("A1").Value, Throws.InstanceOf()); + + ws.Cell("B1").FormulaA1 = "=SUM(Sheet1!A1:UnknownSheet!A50)"; + Assert.That(() => ws.Cell("B1").Value, Throws.InstanceOf()); + } + } + + [Test] public void DateAgainstStringComparison() { using (var wb = new XLWorkbook())