From ac00b3c256933e667f022a49854a05e40e3d0630 Mon Sep 17 00:00:00 2001 From: Eike Rathke Date: Tue, 19 Jan 2016 00:18:21 +0100 Subject: tdf#88737 handle temporary array formula matrix circular reference This does not solve the difference in how Excel seems to handle the arguments and calculation, but some corner case. See bug comment 6. Change-Id: Ifa331e8552587c40e1486a08093ed0df92a9d245 --- include/formula/errorcodes.hxx | 3 +++ sc/source/core/data/formulacell.cxx | 14 +++++++++++++- sc/source/core/tool/interpr5.cxx | 10 ++++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/include/formula/errorcodes.hxx b/include/formula/errorcodes.hxx index 0f5fdad44320..e2279f3e163b 100644 --- a/include/formula/errorcodes.hxx +++ b/include/formula/errorcodes.hxx @@ -78,6 +78,9 @@ const sal_uInt16 errJumpMatHasResult = 535; // string or empty, to be distinguished from the general errNoValue NAN and not // to be used as result. const sal_uInt16 errElementNaN = 536; +// ScInterpreter/ScFormulaCell internal: keep dirty, retry interpreting next +// round. +const sal_uInt16 errRetryCircular = 537; // Interpreter: NA() not available condition, not a real error const sal_uInt16 NOTAVAILABLE = 0x7fff; diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index c954b97e2dcc..b311d7c18a02 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -1868,9 +1868,21 @@ void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam ) if( p->GetError() && p->GetError() != errCircularReference) { - ResetDirty(); bChanged = true; + + if (p->GetError() == errRetryCircular) + { + // Array formula matrix calculation corner case. Keep dirty + // state, do not remove from formula tree or anything else, but + // store errCircularReference in case this cell does not get + // recalculated. + aResult.SetResultError( errCircularReference); + return; + } + + ResetDirty(); } + if (eTailParam == SCITP_FROM_ITERATION && IsDirtyOrInTableOpDirty()) { bool bIsValue = aResult.IsValue(); // the previous type diff --git a/sc/source/core/tool/interpr5.cxx b/sc/source/core/tool/interpr5.cxx index 12cc662703d7..a32f2defec3b 100644 --- a/sc/source/core/tool/interpr5.cxx +++ b/sc/source/core/tool/interpr5.cxx @@ -3178,6 +3178,16 @@ void ScInterpreter::ScMatRef() return; } + if (aCell.mpFormula->IsRunning()) + { + // Twisted odd corner case where an array element's cell tries to + // access the top left matrix while it is still running, see tdf#88737 + // This is a hackish workaround, not a general solution, the matrix + // isn't available anyway and errCircularReference would be set. + PushError( errRetryCircular ); + return; + } + const ScMatrix* pMat = aCell.mpFormula->GetMatrix(); if (pMat) { -- cgit