[Libreoffice-commits] core.git: Branch 'feature/formula-core-rework' - 3 commits - sc/inc sc/qa sc/source
Kohei Yoshida
kohei.yoshida at gmail.com
Tue Jul 23 19:31:12 PDT 2013
sc/inc/tokenarray.hxx | 3 +
sc/qa/unit/ucalc.hxx | 2
sc/qa/unit/ucalc_formula.cxx | 73 ++++++++++++++++++++++++++++++++++++
sc/source/core/data/formulacell.cxx | 22 ++++------
sc/source/core/tool/token.cxx | 52 +++++++++++++++++++++++++
5 files changed, 139 insertions(+), 13 deletions(-)
New commits:
commit a62b7f10ec1fddd7d2bd6517dec75a617aaa12be
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Tue Jul 23 22:33:27 2013 -0400
Re-implement adjusting of references on move.
Change-Id: I52a8b78ed072eb6bcd86b4f80936a869046cbc4d
diff --git a/sc/inc/tokenarray.hxx b/sc/inc/tokenarray.hxx
index 5ff7da0..2ae6c90 100644
--- a/sc/inc/tokenarray.hxx
+++ b/sc/inc/tokenarray.hxx
@@ -129,6 +129,9 @@ public:
*/
sc::RefUpdateResult AdjustReferenceOnShift( const sc::RefUpdateContext& rCxt, const ScAddress& rOldPos );
+ sc::RefUpdateResult AdjustReferenceOnMove(
+ const sc::RefUpdateContext& rCxt, const ScAddress& rOldPos, const ScAddress& rNewPos );
+
/**
* Adjust all references on sheet deletion.
*
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 63d2c9b..725c5d9 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -2365,7 +2365,6 @@ bool ScFormulaCell::UpdateReferenceOnMove(
aOldPos.Set(aPos.Col() - rCxt.mnColDelta, aPos.Row() - rCxt.mnRowDelta, aPos.Tab() - rCxt.mnTabDelta);
}
-
// Check presence of any references or column row names.
pCode->Reset();
bool bHasRefs = (pCode->GetNextReferenceRPN() != NULL);
@@ -2389,22 +2388,19 @@ bool ScFormulaCell::UpdateReferenceOnMove(
pOldCode.reset(pCode->Clone());
bool bValChanged = false;
- bool bRangeModified = false; // any range, not only shared formula
+ bool bRefModified = false;
bool bRefSizeChanged = false;
if (bHasRefs)
{
// Update cell or range references.
- ScCompiler aComp(pDocument, aPos, *pCode);
- aComp.SetGrammar(pDocument->GetGrammar());
- aComp.UpdateReference(
- URM_MOVE, aOldPos, rCxt.maRange,
- rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta,
- bValChanged, bRefSizeChanged);
- bRangeModified = aComp.HasModifiedRange();
+ sc::RefUpdateResult aRes = pCode->AdjustReferenceOnMove(rCxt, aOldPos, aPos);
+ bRefModified = aRes.mbReferenceModified;
+ bValChanged = aRes.mbValueChanged;
}
- bCellStateChanged |= bValChanged;
+ if (bValChanged || bRefModified)
+ bCellStateChanged = true;
if (bOnRefMove)
// Cell may reference itself, e.g. ocColumn, ocRow without parameter
@@ -2429,7 +2425,7 @@ bool ScFormulaCell::UpdateReferenceOnMove(
bHasRelName = HasRelNameReference();
// Reference changed and new listening needed?
// Except in Insert/Delete without specialties.
- bNewListening = (bRangeModified || bColRowNameCompile
+ bNewListening = (bRefModified || bColRowNameCompile
|| bValChanged || bHasRelName)
// #i36299# Don't duplicate action during cut&paste / drag&drop
// on a cell in the range moved, start/end listeners is done
@@ -2442,7 +2438,7 @@ bool ScFormulaCell::UpdateReferenceOnMove(
bool bNeedDirty = false;
// NeedDirty for changes except for Copy and Move/Insert without RelNames
- if ( bRangeModified || bColRowNameCompile ||
+ if ( bRefModified || bColRowNameCompile ||
(bValChanged && bHasRelName && (bHasRelName || bInDeleteUndo || bRefSizeChanged)) || bOnRefMove)
bNeedDirty = true;
@@ -2451,7 +2447,7 @@ bool ScFormulaCell::UpdateReferenceOnMove(
bValChanged = false;
- if ( ( bCompile = (bCompile || bValChanged || bRangeModified || bColRowNameCompile) ) != 0 )
+ if ( ( bCompile = (bCompile || bValChanged || bRefModified || bColRowNameCompile) ) != 0 )
{
CompileTokenArray( bNewListening ); // no Listening
bNeedDirty = true;
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index 64beedf..b783525 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -2472,6 +2472,58 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnShift( const sc::RefUpdateCon
return aRes;
}
+sc::RefUpdateResult ScTokenArray::AdjustReferenceOnMove(
+ const sc::RefUpdateContext& rCxt, const ScAddress& rOldPos, const ScAddress& rNewPos )
+{
+ // When moving, the range is the destination range. We need to use the old
+ // range prior to the move for hit analysis.
+ ScRange aOldRange = rCxt.maRange;
+ aOldRange.Move(-rCxt.mnColDelta, -rCxt.mnRowDelta, -rCxt.mnTabDelta);
+
+ sc::RefUpdateResult aRes;
+
+ FormulaToken** p = pCode;
+ FormulaToken** pEnd = p + static_cast<size_t>(nLen);
+ for (; p != pEnd; ++p)
+ {
+ switch ((*p)->GetType())
+ {
+ case svSingleRef:
+ {
+ ScToken* pToken = static_cast<ScToken*>(*p);
+ ScSingleRefData& rRef = pToken->GetSingleRef();
+ ScAddress aAbs = rRef.toAbs(rOldPos);
+ if (aOldRange.In(aAbs))
+ {
+ aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
+ aRes.mbReferenceModified = true;
+ }
+
+ rRef.SetAddress(aAbs, rNewPos);
+ }
+ break;
+ case svDoubleRef:
+ {
+ ScToken* pToken = static_cast<ScToken*>(*p);
+ ScComplexRefData& rRef = pToken->GetDoubleRef();
+ ScRange aAbs = rRef.toAbs(rOldPos);
+ if (aOldRange.In(aAbs))
+ {
+ aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
+ aRes.mbReferenceModified = true;
+ }
+
+ rRef.SetRange(aAbs, rNewPos);
+ }
+ break;
+ default:
+ ;
+ }
+ }
+
+ return aRes;
+}
+
namespace {
bool adjustSingleRef( ScSingleRefData& rRef, SCTAB nDelPos, SCTAB nSheets, const ScAddress& rOldPos, const ScAddress& rNewPos )
commit 9e304c34daae3dd8e9b7813138b5028b91819002
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Tue Jul 23 22:29:48 2013 -0400
Add test for moving the formula cells that reference stationary range.
Change-Id: I6f996e4c8535371c57c9d43012baa6118160f834
diff --git a/sc/qa/unit/ucalc_formula.cxx b/sc/qa/unit/ucalc_formula.cxx
index 69b0374..ebf74e7 100644
--- a/sc/qa/unit/ucalc_formula.cxx
+++ b/sc/qa/unit/ucalc_formula.cxx
@@ -884,6 +884,29 @@ void Test::testFormulaRefUpdateMove()
if (!checkFormula(*m_pDoc, ScAddress(0,11,0), "$D$6"))
CPPUNIT_FAIL("Wrong formula.");
+ // Move A9:A12 to B10:B13.
+ bMoved = rFunc.MoveBlock(ScRange(0,8,0,0,11,0), ScAddress(1,9,0), true, false, false, false);
+ CPPUNIT_ASSERT_MESSAGE("Failed to move A9:A12 to B10:B13", bMoved);
+
+ // The results of these formula cells should still stay the same.
+ CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(1,9,0));
+ CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(1,10,0));
+ CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(1,11,0));
+ CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(1,12,0));
+
+ // Displayed formulas should stay the same since the referenced range hasn't moved.
+ if (!checkFormula(*m_pDoc, ScAddress(1,9,0), "SUM(D4:D6)"))
+ CPPUNIT_FAIL("Wrong formula.");
+
+ if (!checkFormula(*m_pDoc, ScAddress(1,10,0), "SUM($D$4:$D$6)"))
+ CPPUNIT_FAIL("Wrong formula.");
+
+ if (!checkFormula(*m_pDoc, ScAddress(1,11,0), "D5"))
+ CPPUNIT_FAIL("Wrong formula.");
+
+ if (!checkFormula(*m_pDoc, ScAddress(1,12,0), "$D$6"))
+ CPPUNIT_FAIL("Wrong formula.");
+
m_pDoc->DeleteTab(0);
}
commit a38c2df3c20c3a3e8585b610635b751269793bf3
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Tue Jul 23 18:59:34 2013 -0400
Add starter test for reference update on range move.
This currently fails.
Change-Id: I83cdcb6ed9620079664ff35375a0457b0c9bcea0
diff --git a/sc/qa/unit/ucalc.hxx b/sc/qa/unit/ucalc.hxx
index ac17bd9..5a1d0ae 100644
--- a/sc/qa/unit/ucalc.hxx
+++ b/sc/qa/unit/ucalc.hxx
@@ -89,6 +89,7 @@ public:
void testFormulaRefUpdate();
void testFormulaRefUpdateRange();
void testFormulaRefUpdateSheets();
+ void testFormulaRefUpdateMove();
void testFuncCOLUMN();
void testFuncROW();
void testFuncSUM();
@@ -280,6 +281,7 @@ public:
CPPUNIT_TEST(testFormulaRefUpdate);
CPPUNIT_TEST(testFormulaRefUpdateRange);
CPPUNIT_TEST(testFormulaRefUpdateSheets);
+ CPPUNIT_TEST(testFormulaRefUpdateMove);
CPPUNIT_TEST(testFuncCOLUMN);
CPPUNIT_TEST(testFuncROW);
CPPUNIT_TEST(testFuncSUM);
diff --git a/sc/qa/unit/ucalc_formula.cxx b/sc/qa/unit/ucalc_formula.cxx
index c651b6d..69b0374 100644
--- a/sc/qa/unit/ucalc_formula.cxx
+++ b/sc/qa/unit/ucalc_formula.cxx
@@ -18,6 +18,8 @@
#include "formulacell.hxx"
#include "inputopt.hxx"
#include "scmod.hxx"
+#include "docsh.hxx"
+#include "docfunc.hxx"
#include <boost/scoped_ptr.hpp>
@@ -837,6 +839,54 @@ void Test::testFormulaRefUpdateSheets()
m_pDoc->DeleteTab(0);
}
+void Test::testFormulaRefUpdateMove()
+{
+ m_pDoc->InsertTab(0, "Sheet1");
+
+ sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn auto calc on.
+
+ // Set value to B4:B6.
+ m_pDoc->SetValue(ScAddress(1,3,0), 1);
+ m_pDoc->SetValue(ScAddress(1,4,0), 2);
+ m_pDoc->SetValue(ScAddress(1,5,0), 3);
+
+ // Set formulas to A9:A12 that references B4:B6.
+ m_pDoc->SetString(ScAddress(0,8,0), "=SUM(B4:B6)");
+ m_pDoc->SetString(ScAddress(0,9,0), "=SUM($B$4:$B$6)");
+ m_pDoc->SetString(ScAddress(0,10,0), "=B5");
+ m_pDoc->SetString(ScAddress(0,11,0), "=$B$6");
+
+ CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(0,8,0));
+ CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(0,9,0));
+ CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(0,10,0));
+ CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(0,11,0));
+
+ // Move B4:B6 to D4 (two columsn to the right).
+ ScDocFunc& rFunc = getDocShell().GetDocFunc();
+ bool bMoved = rFunc.MoveBlock(ScRange(1,3,0,1,5,0), ScAddress(3,3,0), true, false, false, false);
+ CPPUNIT_ASSERT_MESSAGE("Failed to move B4:B6.", bMoved);
+
+ // The results of the formula cells that reference the moved range should remain the same.
+ CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(0,8,0));
+ CPPUNIT_ASSERT_EQUAL(6.0, m_pDoc->GetValue(0,9,0));
+ CPPUNIT_ASSERT_EQUAL(2.0, m_pDoc->GetValue(0,10,0));
+ CPPUNIT_ASSERT_EQUAL(3.0, m_pDoc->GetValue(0,11,0));
+
+ if (!checkFormula(*m_pDoc, ScAddress(0,8,0), "SUM(D4:D6)"))
+ CPPUNIT_FAIL("Wrong formula.");
+
+ if (!checkFormula(*m_pDoc, ScAddress(0,9,0), "SUM($D$4:$D$6)"))
+ CPPUNIT_FAIL("Wrong formula.");
+
+ if (!checkFormula(*m_pDoc, ScAddress(0,10,0), "D5"))
+ CPPUNIT_FAIL("Wrong formula.");
+
+ if (!checkFormula(*m_pDoc, ScAddress(0,11,0), "$D$6"))
+ CPPUNIT_FAIL("Wrong formula.");
+
+ m_pDoc->DeleteTab(0);
+}
+
void Test::testFuncCOLUMN()
{
m_pDoc->InsertTab(0, "Formula");
More information about the Libreoffice-commits
mailing list