[Libreoffice-commits] core.git: Branch 'feature/formula-core-rework' - 2 commits - sc/inc sc/qa sc/source

Kohei Yoshida kohei.yoshida at gmail.com
Thu Jul 18 12:57:34 PDT 2013


 sc/inc/refupdatecontext.hxx              |    8 +
 sc/inc/tokenarray.hxx                    |   16 +++
 sc/qa/unit/ucalc_formula.cxx             |  156 ++++++++++++++++++++++++++++++-
 sc/source/core/data/formulacell.cxx      |   10 -
 sc/source/core/data/refupdatecontext.cxx |    2 
 sc/source/core/tool/token.cxx            |   46 +++++++++
 6 files changed, 228 insertions(+), 10 deletions(-)

New commits:
commit ecafe509fc7aeeb19f88c4c74a7095c205c903cc
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Thu Jul 18 15:57:10 2013 -0400

    Correctly update references on cell insertion/deletion.
    
    Change-Id: Ie7499f1f589cd384c4e2421dc81d3c1f02e4a53e

diff --git a/sc/inc/refupdatecontext.hxx b/sc/inc/refupdatecontext.hxx
index 80fdd74..7192ec7 100644
--- a/sc/inc/refupdatecontext.hxx
+++ b/sc/inc/refupdatecontext.hxx
@@ -43,6 +43,14 @@ struct RefUpdateContext
     bool hasDelta() const;
 };
 
+struct RefUpdateResult
+{
+    bool mbValueChanged;
+    bool mbRangeSizeModified;
+
+    RefUpdateResult();
+};
+
 }
 
 #endif
diff --git a/sc/inc/tokenarray.hxx b/sc/inc/tokenarray.hxx
index 9f0c463..fe6204c 100644
--- a/sc/inc/tokenarray.hxx
+++ b/sc/inc/tokenarray.hxx
@@ -27,6 +27,13 @@
 #include "calcmacros.hxx"
 #include <formula/tokenarray.hxx>
 
+namespace sc {
+
+struct RefUpdateContext;
+struct RefUpdateResult;
+
+}
+
 struct ScRawToken;
 struct ScSingleRefData;
 struct ScComplexRefData;
@@ -113,6 +120,15 @@ public:
      */
     void AdjustAbsoluteRefs( const ScDocument* pOldDoc, const ScAddress& rOldPos, const ScAddress& rNewPos, bool bRangeName = false, bool bCheckCopyArea = false );
 
+    /**
+     * Adjust all references in response to shifting of cells during cell
+     * insertion and deletion.
+     *
+     * @param rCxt context that stores details of shifted region.
+     * @param rOldPos old cell position prior to shifting.
+     */
+    sc::RefUpdateResult AdjustReferenceOnShift( const sc::RefUpdateContext& rCxt, const ScAddress& rOldPos );
+
 #if DEBUG_FORMULA_COMPILER
     void Dump() const;
 #endif
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index f74231a..e17d4c6 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -1852,7 +1852,6 @@ bool ScFormulaCell::GetMatrixOrigin( ScAddress& rPos ) const
         }
         break;
     }
-    fprintf(stdout, "ScFormulaCell::GetMatrixOrigin:   failed\n");
     return false;
 }
 
@@ -2274,12 +2273,9 @@ bool ScFormulaCell::UpdateReferenceOnShift(
     if (bHasRefs)
     {
         // Update cell or range references.
-        ScCompiler aComp(pDocument, aPos, *pCode);
-        aComp.SetGrammar(pDocument->GetGrammar());
-        aComp.UpdateReference(
-            URM_INSDEL, aOldPos, rCxt.maRange, rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta,
-            bValChanged, bRefSizeChanged);
-        bRangeModified = aComp.HasModifiedRange();
+        sc::RefUpdateResult aRes = pCode->AdjustReferenceOnShift(rCxt, aOldPos);
+        bRangeModified = aRes.mbRangeSizeModified;
+        bValChanged = aRes.mbValueChanged;
     }
 
     bCellStateChanged |= bValChanged;
diff --git a/sc/source/core/data/refupdatecontext.cxx b/sc/source/core/data/refupdatecontext.cxx
index a5c8616..72dadf0 100644
--- a/sc/source/core/data/refupdatecontext.cxx
+++ b/sc/source/core/data/refupdatecontext.cxx
@@ -19,6 +19,8 @@ bool RefUpdateContext::hasDelta() const
     return (mnColDelta > 0 || mnRowDelta > 0 || mnTabDelta > 0);
 }
 
+RefUpdateResult::RefUpdateResult() : mbValueChanged(false), mbRangeSizeModified(false) {}
+
 }
 
 
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index 3447432..56d4ddc 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -37,6 +37,7 @@
 #include "rangeseq.hxx"
 #include "externalrefmgr.hxx"
 #include "document.hxx"
+#include "refupdatecontext.hxx"
 
 using ::std::vector;
 
@@ -2216,6 +2217,51 @@ void ScTokenArray::AdjustAbsoluteRefs( const ScDocument* pOldDoc, const ScAddres
     }
 }
 
+sc::RefUpdateResult ScTokenArray::AdjustReferenceOnShift( const sc::RefUpdateContext& rCxt, const ScAddress& rOldPos )
+{
+    sc::RefUpdateResult aRes;
+    ScAddress aNewPos = rOldPos;
+    bool bCellShifted = rCxt.maRange.In(rOldPos);
+    if (bCellShifted)
+        aNewPos.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
+
+    FormulaToken** p = pCode;
+    FormulaToken** pEnd = p + static_cast<size_t>(nLen);
+    for (; p != pEnd; ++p)
+    {
+        ScToken* pToken = static_cast<ScToken*>(*p);
+        switch (pToken->GetType())
+        {
+            case svSingleRef:
+            {
+                ScSingleRefData& rRef = pToken->GetSingleRef();
+                ScAddress aAbs = rRef.toAbs(rOldPos);
+
+                if (rCxt.maRange.In(aAbs))
+                    aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
+
+                rRef.SetAddress(aAbs, aNewPos);
+            }
+            break;
+            case svDoubleRef:
+            {
+                ScComplexRefData& rRef = pToken->GetDoubleRef();
+                ScRange aAbs = rRef.toAbs(rOldPos);
+
+                if (rCxt.maRange.In(aAbs))
+                    aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
+
+                rRef.SetRange(aAbs, aNewPos);
+            }
+            break;
+            default:
+                ;
+        }
+    }
+
+    return aRes;
+}
+
 #if DEBUG_FORMULA_COMPILER
 void ScTokenArray::Dump() const
 {
commit 779e01640c280e96bf837c2e2762ed8fd093c45a
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Thu Jul 18 15:56:37 2013 -0400

    More test on reference updates.
    
    Change-Id: Icf0222ee08157836e3119a2c67b320a14d4be8bd

diff --git a/sc/qa/unit/ucalc_formula.cxx b/sc/qa/unit/ucalc_formula.cxx
index 4954d88..134d23c 100644
--- a/sc/qa/unit/ucalc_formula.cxx
+++ b/sc/qa/unit/ucalc_formula.cxx
@@ -206,7 +206,7 @@ void Test::testFormulaRefUpdate()
 
     sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn auto calc on.
 
-    m_pDoc->SetValue(ScAddress(0,0,0), 2.0);
+    m_pDoc->SetValue(ScAddress(0,0,0), 2.0); // A1
     m_pDoc->SetString(ScAddress(2,2,0), "=A1");   // C3
     m_pDoc->SetString(ScAddress(2,3,0), "=$A$1"); // C4
 
@@ -240,9 +240,159 @@ void Test::testFormulaRefUpdate()
     if (!checkFormula(*m_pDoc, aPos, "$A$1"))
         CPPUNIT_FAIL("Wrong formula in C4.");
 
-    m_pDoc->DeleteTab(0);
+    // Insert 2 rows at row 1 to shift all of A1 and C3:C4 down.
+    m_pDoc->InsertRow(ScRange(0,0,0,MAXCOL,1,0));
+
+    aPos = ScAddress(2,4,0);
+    if (!checkFormula(*m_pDoc, aPos, "A3"))
+        CPPUNIT_FAIL("Wrong formula in C5.");
+
+    aPos = ScAddress(2,5,0);
+    if (!checkFormula(*m_pDoc, aPos, "$A$3"))
+        CPPUNIT_FAIL("Wrong formula in C6.");
+
+    // Delete 2 rows at row 1 to shift them back.
+    m_pDoc->DeleteRow(ScRange(0,0,0,MAXCOL,1,0));
+
+    aPos = ScAddress(2,2,0);
+    if (!checkFormula(*m_pDoc, aPos, "A1"))
+        CPPUNIT_FAIL("Wrong formula in C3.");
+
+    aPos = ScAddress(2,3,0);
+    if (!checkFormula(*m_pDoc, aPos, "$A$1"))
+        CPPUNIT_FAIL("Wrong formula in C4.");
+
+    // Insert 3 columns at column B. to shift C3:C4 to F3:F4.
+    m_pDoc->InsertCol(ScRange(1,0,0,3,MAXROW,0));
+
+    aPos = ScAddress(5,2,0);
+    if (!checkFormula(*m_pDoc, aPos, "A1"))
+        CPPUNIT_FAIL("Wrong formula in F3.");
+
+    aPos = ScAddress(5,3,0);
+    if (!checkFormula(*m_pDoc, aPos, "$A$1"))
+        CPPUNIT_FAIL("Wrong formula in F4.");
+
+    // Delete columns B:D to shift them back.
+    m_pDoc->DeleteCol(ScRange(1,0,0,3,MAXROW,0));
+
+    aPos = ScAddress(2,2,0);
+    if (!checkFormula(*m_pDoc, aPos, "A1"))
+        CPPUNIT_FAIL("Wrong formula in C3.");
+
+    aPos = ScAddress(2,3,0);
+    if (!checkFormula(*m_pDoc, aPos, "$A$1"))
+        CPPUNIT_FAIL("Wrong formula in C4.");
+
+    // Insert cells over A1:A3 to only shift A1 down to A4.
+    m_pDoc->InsertRow(ScRange(0,0,0,0,2,0));
+
+    aPos = ScAddress(2,2,0);
+    if (!checkFormula(*m_pDoc, aPos, "A4"))
+        CPPUNIT_FAIL("Wrong formula in C3.");
+
+    aPos = ScAddress(2,3,0);
+    if (!checkFormula(*m_pDoc, aPos, "$A$4"))
+        CPPUNIT_FAIL("Wrong formula in C4.");
 
-    CPPUNIT_ASSERT_MESSAGE("All looks good!", false);
+    // .. and back.
+    m_pDoc->DeleteRow(ScRange(0,0,0,0,2,0));
+
+    aPos = ScAddress(2,2,0);
+    if (!checkFormula(*m_pDoc, aPos, "A1"))
+        CPPUNIT_FAIL("Wrong formula in C3.");
+
+    aPos = ScAddress(2,3,0);
+    if (!checkFormula(*m_pDoc, aPos, "$A$1"))
+        CPPUNIT_FAIL("Wrong formula in C4.");
+
+    // Clear all and start over.
+    clearRange(m_pDoc, ScRange(0,0,0,10,10,0));
+
+    // Fill B2:C3 with values.
+    m_pDoc->SetValue(ScAddress(1,1,0), 1);
+    m_pDoc->SetValue(ScAddress(1,2,0), 2);
+    m_pDoc->SetValue(ScAddress(2,1,0), 3);
+    m_pDoc->SetValue(ScAddress(2,2,0), 4);
+
+    m_pDoc->SetString(ScAddress(0,5,0), "=SUM(B2:C3)");
+    m_pDoc->SetString(ScAddress(0,6,0), "=SUM($B$2:$C$3)");
+
+    aPos = ScAddress(0,5,0);
+    if (!checkFormula(*m_pDoc, aPos, "SUM(B2:C3)"))
+        CPPUNIT_FAIL("Wrong formula in A6.");
+
+    aPos = ScAddress(0,6,0);
+    if (!checkFormula(*m_pDoc, aPos, "SUM($B$2:$C$3)"))
+        CPPUNIT_FAIL("Wrong formula in A7.");
+
+    // Insert a row at row 1.
+    m_pDoc->InsertRow(ScRange(0,0,0,MAXCOL,0,0));
+
+    aPos = ScAddress(0,6,0);
+    if (!checkFormula(*m_pDoc, aPos, "SUM(B3:C4)"))
+        CPPUNIT_FAIL("Wrong formula in A7.");
+
+    aPos = ScAddress(0,7,0);
+    if (!checkFormula(*m_pDoc, aPos, "SUM($B$3:$C$4)"))
+        CPPUNIT_FAIL("Wrong formula in A8.");
+
+    // ... and back.
+    m_pDoc->DeleteRow(ScRange(0,0,0,MAXCOL,0,0));
+
+    aPos = ScAddress(0,5,0);
+    if (!checkFormula(*m_pDoc, aPos, "SUM(B2:C3)"))
+        CPPUNIT_FAIL("Wrong formula in A6.");
+
+    aPos = ScAddress(0,6,0);
+    if (!checkFormula(*m_pDoc, aPos, "SUM($B$2:$C$3)"))
+        CPPUNIT_FAIL("Wrong formula in A7.");
+
+    // Insert columns B:C to shift only the value range.
+    m_pDoc->InsertCol(ScRange(1,0,0,2,MAXROW,0));
+
+    aPos = ScAddress(0,5,0);
+    if (!checkFormula(*m_pDoc, aPos, "SUM(D2:E3)"))
+        CPPUNIT_FAIL("Wrong formula in A6.");
+
+    aPos = ScAddress(0,6,0);
+    if (!checkFormula(*m_pDoc, aPos, "SUM($D$2:$E$3)"))
+        CPPUNIT_FAIL("Wrong formula in A7.");
+
+    // ... and back.
+    m_pDoc->DeleteCol(ScRange(1,0,0,2,MAXROW,0));
+
+    aPos = ScAddress(0,5,0);
+    if (!checkFormula(*m_pDoc, aPos, "SUM(B2:C3)"))
+        CPPUNIT_FAIL("Wrong formula in A6.");
+
+    aPos = ScAddress(0,6,0);
+    if (!checkFormula(*m_pDoc, aPos, "SUM($B$2:$C$3)"))
+        CPPUNIT_FAIL("Wrong formula in A7.");
+
+    // Insert rows 5:6 to shift the formula cells only.
+    m_pDoc->InsertRow(ScRange(0,4,0,MAXCOL,5,0));
+
+    aPos = ScAddress(0,7,0);
+    if (!checkFormula(*m_pDoc, aPos, "SUM(B2:C3)"))
+        CPPUNIT_FAIL("Wrong formula in A8.");
+
+    aPos = ScAddress(0,8,0);
+    if (!checkFormula(*m_pDoc, aPos, "SUM($B$2:$C$3)"))
+        CPPUNIT_FAIL("Wrong formula in A9.");
+
+    // ... and back.
+    m_pDoc->DeleteRow(ScRange(0,4,0,MAXCOL,5,0));
+
+    aPos = ScAddress(0,5,0);
+    if (!checkFormula(*m_pDoc, aPos, "SUM(B2:C3)"))
+        CPPUNIT_FAIL("Wrong formula in A6.");
+
+    aPos = ScAddress(0,6,0);
+    if (!checkFormula(*m_pDoc, aPos, "SUM($B$2:$C$3)"))
+        CPPUNIT_FAIL("Wrong formula in A7.");
+
+    m_pDoc->DeleteTab(0);
 }
 
 void Test::testFuncSUM()


More information about the Libreoffice-commits mailing list