summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEike Rathke <erack@redhat.com>2016-01-19 00:18:21 +0100
committerEike Rathke <erack@redhat.com>2016-01-19 00:34:17 +0100
commitac00b3c256933e667f022a49854a05e40e3d0630 (patch)
treeddfbbb7a4bfb0a2b5a6cbd82e247e321cc75e297
parentd5d8320ba1fba493e0e091fd46207ea7a34cc9e7 (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.hxx3
-rw-r--r--sc/source/core/data/formulacell.cxx14
-rw-r--r--sc/source/core/tool/interpr5.cxx10
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)
{