[Libreoffice-commits] core.git: include/formula sc/source

Eike Rathke erack at redhat.com
Mon Jan 18 15:38:24 PST 2016


 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(-)

New commits:
commit ac00b3c256933e667f022a49854a05e40e3d0630
Author: Eike Rathke <erack at redhat.com>
Date:   Tue Jan 19 00:18:21 2016 +0100

    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

diff --git a/include/formula/errorcodes.hxx b/include/formula/errorcodes.hxx
index 0f5fdad..e2279f3 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 c954b97..b311d7c 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 12cc662..a32f2de 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)
     {


More information about the Libreoffice-commits mailing list