diff options
author | Eike Rathke <erack@redhat.com> | 2016-01-19 00:18:21 +0100 |
---|---|---|
committer | Eike Rathke <erack@redhat.com> | 2016-01-19 00:34:17 +0100 |
commit | ac00b3c256933e667f022a49854a05e40e3d0630 (patch) | |
tree | ddfbbb7a4bfb0a2b5a6cbd82e247e321cc75e297 | |
parent | d5d8320ba1fba493e0e091fd46207ea7a34cc9e7 (diff) |
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
-rw-r--r-- | include/formula/errorcodes.hxx | 3 | ||||
-rw-r--r-- | sc/source/core/data/formulacell.cxx | 14 | ||||
-rw-r--r-- | sc/source/core/tool/interpr5.cxx | 10 |
3 files changed, 26 insertions, 1 deletions
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) { |