sc/inc/refupdatecontext.hxx | 1 sc/qa/unit/ucalc_formula.cxx | 46 +++++++++++++++++ sc/source/core/data/formulacell.cxx | 12 ---- sc/source/core/data/refupdatecontext.cxx | 2 sc/source/core/tool/token.cxx | 81 +++++++++++++++++++++++++++++++ 5 files changed, 132 insertions(+), 10 deletions(-)
New commits: commit c7db01d4010d82fc29d47aab137ba6e978455607 Author: Kohei Yoshida <[email protected]> Date: Thu Jul 18 20:51:28 2013 -0400 Add test for no reference error on reference deletion. Change-Id: I3e6fd2b41c3bbf0ee12769a507fbf484f9ba833b diff --git a/sc/qa/unit/ucalc_formula.cxx b/sc/qa/unit/ucalc_formula.cxx index e04c741..a57c6cf 100644 --- a/sc/qa/unit/ucalc_formula.cxx +++ b/sc/qa/unit/ucalc_formula.cxx @@ -306,9 +306,25 @@ void Test::testFormulaRefUpdate() if (!checkFormula(*m_pDoc, aPos, "$A$1")) CPPUNIT_FAIL("Wrong formula in C4."); + // Delete row 1 which will delete the value cell (A1). + m_pDoc->DeleteRow(ScRange(0,0,0,MAXCOL,0,0)); + + aPos = ScAddress(2,1,0); + ScFormulaCell* pFC = m_pDoc->GetFormulaCell(aPos); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell.", pFC); + CPPUNIT_ASSERT_EQUAL(ScErrorCodes::errNoRef, pFC->GetErrCode()); + aPos = ScAddress(2,2,0); + pFC = m_pDoc->GetFormulaCell(aPos); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell.", pFC); + CPPUNIT_ASSERT_EQUAL(ScErrorCodes::errNoRef, pFC->GetErrCode()); + // Clear all and start over. clearRange(m_pDoc, ScRange(0,0,0,10,10,0)); + // ------------------------------------------ + // Test range updates + // ------------------------------------------ + // Fill B2:C3 with values. m_pDoc->SetValue(ScAddress(1,1,0), 1); m_pDoc->SetValue(ScAddress(1,2,0), 2); @@ -410,6 +426,18 @@ void Test::testFormulaRefUpdate() CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(ScAddress(0,5,0))); CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(ScAddress(0,6,0))); + // Delete rows 2:3 to completely remove the referenced range. + m_pDoc->DeleteRow(ScRange(0,1,0,MAXCOL,2,0)); + + // Both A4 and A5 should show #REF! errors. + pFC = m_pDoc->GetFormulaCell(ScAddress(0,3,0)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell.", pFC); + CPPUNIT_ASSERT_EQUAL(ScErrorCodes::errNoRef, pFC->GetErrCode()); + + pFC = m_pDoc->GetFormulaCell(ScAddress(0,4,0)); + CPPUNIT_ASSERT_MESSAGE("This should be a formula cell.", pFC); + CPPUNIT_ASSERT_EQUAL(ScErrorCodes::errNoRef, pFC->GetErrCode()); + m_pDoc->DeleteTab(0); } commit 886716bddd0ac18f3c122d6ebd6def6dedf7448e Author: Kohei Yoshida <[email protected]> Date: Thu Jul 18 20:25:12 2013 -0400 Handle deleted references. Change-Id: Ic99d8f154cf487983aa5fce59cde053a9b9d3fb3 diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx index 7e444b0..04a161a 100644 --- a/sc/source/core/tool/token.cxx +++ b/sc/source/core/tool/token.cxx @@ -2217,8 +2217,67 @@ void ScTokenArray::AdjustAbsoluteRefs( const ScDocument* pOldDoc, const ScAddres } } +namespace { + +ScRange getDeletedRange( const sc::RefUpdateContext& rCxt ) +{ + ScRange aDeletedRange(ScAddress::INITIALIZE_INVALID); + if (rCxt.mnColDelta < 0) + { + // Delete and shift to left. + aDeletedRange.aStart = ScAddress(rCxt.maRange.aStart.Col()+rCxt.mnColDelta, rCxt.maRange.aStart.Row(), rCxt.maRange.aStart.Tab()); + aDeletedRange.aEnd = ScAddress(rCxt.maRange.aStart.Col()-1, rCxt.maRange.aEnd.Row(), rCxt.maRange.aEnd.Tab()); + } + else if (rCxt.mnRowDelta < 0) + { + // Delete and shift up. + aDeletedRange.aStart = ScAddress(rCxt.maRange.aStart.Col(), rCxt.maRange.aStart.Row()+rCxt.mnRowDelta, rCxt.maRange.aStart.Tab()); + aDeletedRange.aEnd = ScAddress(rCxt.maRange.aEnd.Col(), rCxt.maRange.aStart.Row()-1, rCxt.maRange.aEnd.Tab()); + } + else if (rCxt.mnTabDelta < 0) + { + // Deleting sheets. + // TODO : Figure out what to do here. + } + + return aDeletedRange; +} + +void setRefDeleted( ScSingleRefData& rRef, const sc::RefUpdateContext& rCxt ) +{ + if (rCxt.mnColDelta < 0) + rRef.SetColDeleted(true); + else if (rCxt.mnRowDelta < 0) + rRef.SetRowDeleted(true); + else if (rCxt.mnTabDelta < 0) + rRef.SetTabDeleted(true); +} + +void setRefDeleted( ScComplexRefData& rRef, const sc::RefUpdateContext& rCxt ) +{ + if (rCxt.mnColDelta < 0) + { + rRef.Ref1.SetColDeleted(true); + rRef.Ref2.SetColDeleted(true); + } + else if (rCxt.mnRowDelta < 0) + { + rRef.Ref1.SetRowDeleted(true); + rRef.Ref2.SetRowDeleted(true); + } + else if (rCxt.mnTabDelta < 0) + { + rRef.Ref1.SetTabDeleted(true); + rRef.Ref2.SetTabDeleted(true); + } +} + +} + sc::RefUpdateResult ScTokenArray::AdjustReferenceOnShift( const sc::RefUpdateContext& rCxt, const ScAddress& rOldPos ) { + ScRange aDeletedRange = getDeletedRange(rCxt); + sc::RefUpdateResult aRes; ScAddress aNewPos = rOldPos; bool bCellShifted = rCxt.maRange.In(rOldPos); @@ -2237,6 +2296,14 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnShift( const sc::RefUpdateCon ScSingleRefData& rRef = pToken->GetSingleRef(); ScAddress aAbs = rRef.toAbs(rOldPos); + if (aDeletedRange.In(aAbs)) + { + // This reference is in the deleted region. + setRefDeleted(rRef, rCxt); + aRes.mbValueChanged = true; + break; + } + if (rCxt.maRange.In(aAbs)) aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta); @@ -2248,6 +2315,14 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnShift( const sc::RefUpdateCon ScComplexRefData& rRef = pToken->GetDoubleRef(); ScRange aAbs = rRef.toAbs(rOldPos); + if (aDeletedRange.In(aAbs)) + { + // This reference is in the deleted region. + setRefDeleted(rRef, rCxt); + aRes.mbValueChanged = true; + break; + } + if (rCxt.maRange.In(aAbs)) aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta); else if (rCxt.maRange.Intersects(aAbs)) commit 390497d548536a65d0f3a5bae32567e97d2e171b Author: Kohei Yoshida <[email protected]> Date: Thu Jul 18 17:30:10 2013 -0400 Mark formula cells dirty when a referenced range gets partially shifted. Change-Id: I5d97cb0e325c0168fdae57f8ec39f62c85bec524 diff --git a/sc/inc/refupdatecontext.hxx b/sc/inc/refupdatecontext.hxx index 7192ec7..2f33767 100644 --- a/sc/inc/refupdatecontext.hxx +++ b/sc/inc/refupdatecontext.hxx @@ -49,6 +49,7 @@ struct RefUpdateResult bool mbRangeSizeModified; RefUpdateResult(); + RefUpdateResult(const RefUpdateResult& r); }; } diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index e17d4c6..4defffd 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -2310,18 +2310,13 @@ bool ScFormulaCell::UpdateReferenceOnShift( EndListeningTo(pDocument, pOldCode.get(), aOldPos); } - bool bNeedDirty = false; // NeedDirty for changes except for Copy and Move/Insert without RelNames - if (bRangeModified || bColRowNameCompile || - (bValChanged && (bHasRelName || bInDeleteUndo || bRefSizeChanged)) || bOnRefMove) - bNeedDirty = true; + bool bNeedDirty = (bRangeModified || bValChanged || bColRowNameCompile || bOnRefMove); if (pUndoDoc && (bValChanged || bOnRefMove)) setOldCodeToUndo(pUndoDoc, aUndoPos, pOldCode.get(), eTempGrammar, cMatrixFlag); - bValChanged = false; - - if ( ( bCompile = (bCompile || bValChanged || bRangeModified || bColRowNameCompile) ) != 0 ) + if ( ( bCompile = (bCompile || bRangeModified || bColRowNameCompile) ) != 0 ) { CompileTokenArray( bNewListening ); // no Listening bNeedDirty = true; @@ -2539,7 +2534,6 @@ bool ScFormulaCell::UpdateReferenceOnCopy( bOnRefMove = (bValChanged || (aPos != aOldPos)); bool bColRowNameCompile = false; - bool bHasRelName = false; bool bNewListening = false; bool bInDeleteUndo = false; @@ -2553,8 +2547,6 @@ bool ScFormulaCell::UpdateReferenceOnCopy( ScChangeTrack* pChangeTrack = pDocument->GetChangeTrack(); bInDeleteUndo = (pChangeTrack && pChangeTrack->IsInDeleteUndo()); - // RelNameRefs are always moved - bHasRelName = HasRelNameReference(); // Reference changed and new listening needed? // Except in Insert/Delete without specialties. bNewListening = diff --git a/sc/source/core/data/refupdatecontext.cxx b/sc/source/core/data/refupdatecontext.cxx index 72dadf0..9f39f44 100644 --- a/sc/source/core/data/refupdatecontext.cxx +++ b/sc/source/core/data/refupdatecontext.cxx @@ -20,6 +20,8 @@ bool RefUpdateContext::hasDelta() const } RefUpdateResult::RefUpdateResult() : mbValueChanged(false), mbRangeSizeModified(false) {} +RefUpdateResult::RefUpdateResult(const RefUpdateResult& r) : + mbValueChanged(r.mbValueChanged), mbRangeSizeModified(r.mbRangeSizeModified) {} } diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx index 56d4ddc..7e444b0 100644 --- a/sc/source/core/tool/token.cxx +++ b/sc/source/core/tool/token.cxx @@ -2250,6 +2250,12 @@ sc::RefUpdateResult ScTokenArray::AdjustReferenceOnShift( const sc::RefUpdateCon if (rCxt.maRange.In(aAbs)) aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta); + else if (rCxt.maRange.Intersects(aAbs)) + { + // Part of the referenced range is being shifted. This + // will change the values of the range. + aRes.mbValueChanged = true; + } rRef.SetRange(aAbs, aNewPos); } commit d2c49aafcc7e6282d7f3f8cf4b27ddf6b60eb4e7 Author: Kohei Yoshida <[email protected]> Date: Thu Jul 18 17:28:43 2013 -0400 Test for recalculating formula cells on partial shifting of ref range. Change-Id: I63807a0368551c6a38cf98865a877e92810b2a22 diff --git a/sc/qa/unit/ucalc_formula.cxx b/sc/qa/unit/ucalc_formula.cxx index 134d23c..e04c741 100644 --- a/sc/qa/unit/ucalc_formula.cxx +++ b/sc/qa/unit/ucalc_formula.cxx @@ -392,6 +392,24 @@ void Test::testFormulaRefUpdate() if (!checkFormula(*m_pDoc, aPos, "SUM($B$2:$C$3)")) CPPUNIT_FAIL("Wrong formula in A7."); + // Check the values of the formula cells in A6:A7. + CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(ScAddress(0,5,0))); + CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(ScAddress(0,6,0))); + + // Insert cells over B1:B2 to partially shift value range. + m_pDoc->InsertRow(ScRange(1,0,0,1,1,0)); + + // Check the values of the formula cells in A6:A7 again. + CPPUNIT_ASSERT_EQUAL(7.0, m_pDoc->GetValue(ScAddress(0,5,0))); + CPPUNIT_ASSERT_EQUAL(7.0, m_pDoc->GetValue(ScAddress(0,6,0))); + + // ... and shift them back. + m_pDoc->DeleteRow(ScRange(1,0,0,1,1,0)); + + // The formula cell results should be back too. + CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(ScAddress(0,5,0))); + CPPUNIT_ASSERT_EQUAL(10.0, m_pDoc->GetValue(ScAddress(0,6,0))); + m_pDoc->DeleteTab(0); } _______________________________________________ Libreoffice-commits mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
