diff --git a/ClosedXML/Excel/Cells/XLCell.cs b/ClosedXML/Excel/Cells/XLCell.cs index a573c74..c9f9a1f 100644 --- a/ClosedXML/Excel/Cells/XLCell.cs +++ b/ClosedXML/Excel/Cells/XLCell.cs @@ -2072,36 +2072,43 @@ if (String.IsNullOrWhiteSpace(strValue)) return String.Empty; - var value = ">" + strValue + "<"; - - var regex = conversionType == FormulaConversionType.A1ToR1C1 ? A1Regex : R1C1Regex; - - var sb = new StringBuilder(); - var lastIndex = 0; - - foreach (var match in regex.Matches(value).Cast()) + try { - var matchString = match.Value; - var matchIndex = match.Index; - if (value.Substring(0, matchIndex).CharCount('"') % 2 == 0 - && value.Substring(0, matchIndex).CharCount('\'') % 2 == 0) + var value = ">" + strValue + "<"; + + var regex = conversionType == FormulaConversionType.A1ToR1C1 ? A1Regex : R1C1Regex; + + var sb = new StringBuilder(); + var lastIndex = 0; + + foreach (var match in regex.Matches(value).Cast()) { - // Check if the match is in between quotes - sb.Append(value.Substring(lastIndex, matchIndex - lastIndex)); - sb.Append(conversionType == FormulaConversionType.A1ToR1C1 - ? GetR1C1Address(matchString, rowsToShift, columnsToShift) - : GetA1Address(matchString, rowsToShift, columnsToShift)); + var matchString = match.Value; + var matchIndex = match.Index; + if (value.Substring(0, matchIndex).CharCount('"') % 2 == 0 + && value.Substring(0, matchIndex).CharCount('\'') % 2 == 0) + { + // Check if the match is in between quotes + sb.Append(value.Substring(lastIndex, matchIndex - lastIndex)); + sb.Append(conversionType == FormulaConversionType.A1ToR1C1 + ? GetR1C1Address(matchString, rowsToShift, columnsToShift) + : GetA1Address(matchString, rowsToShift, columnsToShift)); + } + else + sb.Append(value.Substring(lastIndex, matchIndex - lastIndex + matchString.Length)); + lastIndex = matchIndex + matchString.Length; } - else - sb.Append(value.Substring(lastIndex, matchIndex - lastIndex + matchString.Length)); - lastIndex = matchIndex + matchString.Length; + + if (lastIndex < value.Length) + sb.Append(value.Substring(lastIndex)); + + var retVal = sb.ToString(); + return retVal.Substring(1, retVal.Length - 2); } - - if (lastIndex < value.Length) - sb.Append(value.Substring(lastIndex)); - - var retVal = sb.ToString(); - return retVal.Substring(1, retVal.Length - 2); + catch (IndexOutOfRangeException) + { + return "#REF!"; + } } private string GetA1Address(string r1C1Address, int rowsToShift, int columnsToShift) diff --git a/ClosedXML_Tests/Excel/Cells/XLCellTests.cs b/ClosedXML_Tests/Excel/Cells/XLCellTests.cs index 72a2e05..cf20ce7 100644 --- a/ClosedXML_Tests/Excel/Cells/XLCellTests.cs +++ b/ClosedXML_Tests/Excel/Cells/XLCellTests.cs @@ -623,6 +623,33 @@ } } + [Test] + public void InvalidFormulaShiftProducesREF() + { + using (var ms = new MemoryStream()) + { + using (var wb = new XLWorkbook()) + { + var ws = wb.Worksheets.Add("Sheet1"); + ws.Cell("A1").Value = "ValueA1"; + ws.Cell("B2").FormulaA1 = "=A1"; + + ws.Range("A2").Value = ws.Range("B2"); + var fA2 = ws.Cell("A2").FormulaA1; + + wb.SaveAs(ms); + + Assert.AreEqual("#REF!", fA2); + } + + using (var wb2 = new XLWorkbook(ms)) + { + var fA2 = wb2.Worksheets.First().Cell("A2").FormulaA1; + Assert.AreEqual("#REF!", fA2); + } + } + } + public void FormulaWithCircularReferenceFails2() { var cell = new XLWorkbook().Worksheets.Add("Sheet1").FirstCell();