Skip to content

Commit fa6fc7e

Browse files
swmalswmal
and
swmal
authored
#2007 - fix for CircularReferenceException with dynamic arrays (#2008)
* #2007 - fix for CircularReferenceException with dynamic arrays * #2007 - Fixed unittest --------- Co-authored-by: swmal <{ID}+username}@users.noreply.github.com>
1 parent bbad351 commit fa6fc7e

File tree

3 files changed

+41
-3
lines changed

3 files changed

+41
-3
lines changed

src/EPPlus/FormulaParsing/DependencyChain/RpnFormulaExecution.cs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using OfficeOpenXml.Core.CellStore;
33
using OfficeOpenXml.Core.RangeQuadTree;
44
using OfficeOpenXml.FormulaParsing.Excel.Functions;
5+
using OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
56
using OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup.LookupUtils;
67
using OfficeOpenXml.FormulaParsing.Excel.Operators;
78
using OfficeOpenXml.FormulaParsing.Exceptions;
@@ -915,16 +916,25 @@ private static RangeHashset AddOrGetRDFromWsIx(RpnOptimizedDependencyChain depCh
915916
private static void CheckCircularReferences(RpnOptimizedDependencyChain depChain, RpnFormula f, FormulaRangeAddress address, ExcelCalculationOption options)
916917
{
917918
if (f._ws == null) return;
918-
if(f._arrayIndex>=0)
919+
var wsIx = f._ws?.IndexInList ?? ushort.MaxValue;
920+
if (f._arrayIndex>=0)
919921
{
920922
var sf = f._ws._sharedFormulas[f._arrayIndex];
921923
var fa = new FormulaRangeAddress(depChain._parsingContext) { FromRow = sf.StartRow, ToRow = sf.EndRow, FromCol = sf.StartCol, ToCol = sf.EndCol, WorksheetIx = f._ws.IndexInList };
922924
if (fa.CollidesWith(address) != eAddressCollition.No)
923925
{
924-
throw new CircularReferenceException($"Circular reference in array formula: {fa.Address}");
926+
if(!options.AllowCircularReferences)
927+
{
928+
throw new CircularReferenceException($"Circular reference in array formula: {fa.Address}");
929+
}
930+
else
931+
{
932+
var toCell = ExcelCellBase.GetCellId(wsIx, sf.StartRow, sf.StartCol);
933+
var fromCell = ExcelCellBase.GetCellId(f._ws.IndexInList, f._row, f._column);
934+
depChain._circularReferences.Add(new CircularReference(fromCell, toCell));
935+
}
925936
}
926937
}
927-
var wsIx=f._ws?.IndexInList ?? ushort.MaxValue;
928938
if (address.CollidesWith(wsIx, f._row, f._column))
929939
{
930940
var fId = ExcelCellBase.GetCellId(f._ws.IndexInList, f._row, f._column);

src/EPPlus/FormulaParsing/Excel/Functions/RefAndLookup/ChooseBaseFunction.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,16 @@ internal abstract class ChooseBaseFunction : ExcelFunction
2121
{
2222
public override string NamespacePrefix => "_xlfn.";
2323
public override int ArgumentMinLength => 2;
24+
25+
public override ExcelFunctionParametersInfo ParametersInfo => new ExcelFunctionParametersInfo(new Func<int, FunctionParameterInformation>((argumentIndex) =>
26+
{
27+
if (argumentIndex == 0)
28+
{
29+
return FunctionParameterInformation.IgnoreAddress;
30+
}
31+
return FunctionParameterInformation.Normal;
32+
}));
33+
2434
protected List<int> GetChooseColumns(IList<FunctionArgument> arguments, out eErrorType? ev)
2535
{
2636
var cols = new List<int>();

src/EPPlusTest/Issues/FormulaCalculationIssues.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -958,6 +958,24 @@ public void s858()
958958

959959
Assert.AreEqual(12977661.57, result2);
960960
}
961+
962+
[TestMethod]
963+
public void Issue864()
964+
{
965+
using var p1 = OpenTemplatePackage(@"sc864.xlsx");
966+
var sheet = p1.Workbook.Worksheets["Aico data"];
967+
try
968+
{
969+
sheet.Calculate(o => o.AllowCircularReferences = true);
970+
}
971+
catch(Exception ex)
972+
{
973+
int i = 0;
974+
}
975+
976+
var f = sheet.Cells["C42"].Formula;
977+
var v = sheet.Cells["C42"].Value;
978+
}
961979
}
962980
}
963981

0 commit comments

Comments
 (0)