sc/inc/tokenarray.hxx | 2 sc/qa/unit/ucalc_formula.cxx | 50 ++++++++++++++++++++++++ sc/source/core/data/formulacell.cxx | 34 +++++----------- sc/source/core/tool/token.cxx | 73 ++++++++++++++++++++++++++++++++++++ 4 files changed, 136 insertions(+), 23 deletions(-)
New commits: commit 60e9f263676c3c10cc0fcfbfc6f80c895f289e9c Author: Kohei Yoshida <[email protected]> Date: Thu Jul 25 21:19:51 2013 -0400 Re-implement sheet reference adjustment on sheet move. Change-Id: I24e93e0bbc51c7f9a1f1ea0c126a1399ace84a9e diff --git a/sc/inc/tokenarray.hxx b/sc/inc/tokenarray.hxx index 1e8ced1..b3fb5ef 100644 --- a/sc/inc/tokenarray.hxx +++ b/sc/inc/tokenarray.hxx @@ -145,6 +145,8 @@ public: bool AdjustReferenceOnInsertedTab( SCTAB nInsPos, SCTAB nSheets, const ScAddress& rOldPos ); + void AdjustReferenceOnMovedTab( SCTAB nOldPos, SCTAB nNewPos, const ScAddress& rOldPos ); + #if DEBUG_FORMULA_COMPILER void Dump() const; #endif diff --git a/sc/qa/unit/ucalc_formula.cxx b/sc/qa/unit/ucalc_formula.cxx index 531d1d3..a8a54d3 100644 --- a/sc/qa/unit/ucalc_formula.cxx +++ b/sc/qa/unit/ucalc_formula.cxx @@ -813,6 +813,36 @@ void Test::testFormulaRefUpdateSheets() if (!checkFormula(*m_pDoc, ScAddress(1,2,2), "SUM($Sheet1.$B$2:$C$3)")) CPPUNIT_FAIL("Wrong formula in Sheet2.B3."); + // Move the last sheet (Sheet2) to the first position. + m_pDoc->MoveTab(2, 0); + + if (!checkFormula(*m_pDoc, ScAddress(1,1,0), "SUM(Sheet1.B2:C3)")) + CPPUNIT_FAIL("Wrong formula in Sheet2.B2."); + + if (!checkFormula(*m_pDoc, ScAddress(1,2,0), "SUM($Sheet1.$B$2:$C$3)")) + CPPUNIT_FAIL("Wrong formula in Sheet2.B3."); + + // Move back. + m_pDoc->MoveTab(0, 2); + + if (!checkFormula(*m_pDoc, ScAddress(1,1,2), "SUM(Sheet1.B2:C3)")) + CPPUNIT_FAIL("Wrong formula in Sheet2.B2."); + + if (!checkFormula(*m_pDoc, ScAddress(1,2,2), "SUM($Sheet1.$B$2:$C$3)")) + CPPUNIT_FAIL("Wrong formula in Sheet2.B3."); + + // Move the "Temp" sheet to the last position. + m_pDoc->MoveTab(1, 2); + + if (!checkFormula(*m_pDoc, ScAddress(1,1,1), "SUM(Sheet1.B2:C3)")) + CPPUNIT_FAIL("Wrong formula in Sheet2.B2."); + + if (!checkFormula(*m_pDoc, ScAddress(1,2,1), "SUM($Sheet1.$B$2:$C$3)")) + CPPUNIT_FAIL("Wrong formula in Sheet2.B3."); + + // Move back. + m_pDoc->MoveTab(2, 1); + // Delete the temporary sheet. m_pDoc->DeleteTab(1); @@ -848,6 +878,26 @@ void Test::testFormulaRefUpdateSheets() if (!checkFormula(*m_pDoc, ScAddress(1,2,1), "SUM($Sheet1.$B$2:$C$3)")) CPPUNIT_FAIL("Wrong formula in Sheet2.B3."); + // Append a bunch of sheets. + m_pDoc->InsertTab(2, "Temp1"); + m_pDoc->InsertTab(3, "Temp2"); + m_pDoc->InsertTab(4, "Temp3"); + + // Move these tabs around. This shouldn't affects the first 2 sheets. + m_pDoc->MoveTab(2, 4); + m_pDoc->MoveTab(3, 2); + + if (!checkFormula(*m_pDoc, ScAddress(1,1,1), "SUM(Sheet1.B2:C3)")) + CPPUNIT_FAIL("Wrong formula in Sheet2.B2."); + + if (!checkFormula(*m_pDoc, ScAddress(1,2,1), "SUM($Sheet1.$B$2:$C$3)")) + CPPUNIT_FAIL("Wrong formula in Sheet2.B3."); + + // Delete the temp sheets. + m_pDoc->DeleteTab(4); + m_pDoc->DeleteTab(3); + m_pDoc->DeleteTab(2); + // Delete Sheet1. m_pDoc->DeleteTab(0); m_pDoc->GetName(0, aName); diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index c6fb301..b20fa0c 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -2598,31 +2598,19 @@ bool ScFormulaCell::UpdateDeleteTab(SCTAB nTable, bool /*bIsMove*/, SCTAB nSheet void ScFormulaCell::UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos, SCTAB nTabNo ) { pCode->Reset(); - if( pCode->GetNextReferenceRPN() && !pDocument->IsClipOrUndo() ) + if (!pCode->GetNextReferenceRPN() || pDocument->IsClipOrUndo()) { - EndListeningTo( pDocument ); - // SetTab _after_ EndListeningTo und _before_ Compiler UpdateMoveTab ! - aPos.SetTab( nTabNo ); - ScRangeData* pRangeData; - ScCompiler aComp(pDocument, aPos, *pCode); - aComp.SetGrammar(pDocument->GetGrammar()); - pRangeData = aComp.UpdateMoveTab( nOldPos, nNewPos, false ); - if (pRangeData) // Exchange Shared Formula with real Formula - { - pDocument->RemoveFromFormulaTree( this ); // update formula count - delete pCode; - pCode = pRangeData->GetCode()->Clone(); - ScCompiler aComp2(pDocument, aPos, *pCode); - aComp2.SetGrammar(pDocument->GetGrammar()); - aComp2.CompileTokenArray(); - aComp2.MoveRelWrap(pRangeData->GetMaxCol(), pRangeData->GetMaxRow()); - aComp2.UpdateMoveTab( nOldPos, nNewPos, true ); - bCompile = true; - } - // no StartListeningTo because pTab[nTab] not yet correct! + aPos.SetTab(nTabNo); + return; } - else - aPos.SetTab( nTabNo ); + + EndListeningTo(pDocument); + ScAddress aOldPos = aPos; + // SetTab _after_ EndListeningTo und _before_ Compiler UpdateMoveTab ! + aPos.SetTab(nTabNo); + + // no StartListeningTo because pTab[nTab] not yet correct! + pCode->AdjustReferenceOnMovedTab(nOldPos, nNewPos, aOldPos); } void ScFormulaCell::UpdateInsertTabAbs(SCTAB nTable) diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx index e5381aa..79bdfa3 100644 --- a/sc/source/core/tool/token.cxx +++ b/sc/source/core/tool/token.cxx @@ -2660,6 +2660,79 @@ bool ScTokenArray::AdjustReferenceOnInsertedTab( SCTAB nInsPos, SCTAB nSheets, c return bRefChanged; } +namespace { + +void adjustTabOnMove( ScAddress& rPos, SCTAB nOldPos, SCTAB nNewPos ) +{ + // Sheets below the lower bound or above the uppper bound will not change. + SCTAB nLowerBound = std::min(nOldPos, nNewPos); + SCTAB nUpperBound = std::max(nOldPos, nNewPos); + + if (rPos.Tab() < nLowerBound || nUpperBound < rPos.Tab()) + // Outside the boundary. Nothing to adjust. + return; + + if (rPos.Tab() == nOldPos) + { + rPos.SetTab(nNewPos); + return; + } + + // It's somewhere in between. + if (nOldPos < nNewPos) + { + // Moving a sheet to the right. The rest of the sheets shifts to the left. + rPos.IncTab(-1); + } + else + { + // Moving a sheet to the left. The rest of the sheets shifts to the right. + rPos.IncTab(); + } +} + +} + +void ScTokenArray::AdjustReferenceOnMovedTab( SCTAB nOldPos, SCTAB nNewPos, const ScAddress& rOldPos ) +{ + if (nOldPos == nNewPos) + return; + + ScAddress aNewPos = rOldPos; + adjustTabOnMove(aNewPos, nOldPos, nNewPos); + + 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); + adjustTabOnMove(aAbs, nOldPos, nNewPos); + rRef.SetAddress(aAbs, aNewPos); + + } + break; + case svDoubleRef: + { + ScToken* pToken = static_cast<ScToken*>(*p); + ScComplexRefData& rRef = pToken->GetDoubleRef(); + ScRange aAbs = rRef.toAbs(rOldPos); + adjustTabOnMove(aAbs.aStart, nOldPos, nNewPos); + adjustTabOnMove(aAbs.aEnd, nOldPos, nNewPos); + rRef.SetRange(aAbs, aNewPos); + } + break; + default: + ; + } + } +} + #if DEBUG_FORMULA_COMPILER void ScTokenArray::Dump() const { _______________________________________________ Libreoffice-commits mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
