diff options
author | Michael Meeks <michael.meeks@collabora.com> | 2014-03-14 14:26:02 +0000 |
---|---|---|
committer | Michael Meeks <michael.meeks@collabora.com> | 2014-03-14 16:36:06 +0000 |
commit | 0698c49ccdbf62dd84d3f9c5d25ee039f4fff722 (patch) | |
tree | d6a727c31cc754805655e74f90c23c611d0a2632 | |
parent | 79fa84ccb9b45b149843ac88e4d662f2a09e94bf (diff) |
fdo#72741 - swap values only inside a formula group.
Speeds up sorting large ranges containing formula groups by a
computational order or two: can sort 1 million rows of =A1 in sub 10s
Change-Id: I729c801e68154986956b1726e1c35ef973cc4248
-rw-r--r-- | sc/inc/formulacell.hxx | 1 | ||||
-rw-r--r-- | sc/source/core/data/column.cxx | 31 | ||||
-rw-r--r-- | sc/source/core/data/formulacell.cxx | 44 |
3 files changed, 62 insertions, 14 deletions
diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx index f2bc36cbc398..9b47046c36e7 100644 --- a/sc/inc/formulacell.hxx +++ b/sc/inc/formulacell.hxx @@ -203,6 +203,7 @@ public: void SetDirtyAfterLoad(); void ResetTableOpDirtyVar(); void SetTableOpDirty(); + bool SwapWithinGroup( ScFormulaCell *pSwap ); bool IsDirtyOrInTableOpDirty() const; bool GetDirty() const; void ResetDirty(); diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx index 1fa7120729bf..2e9192df31a5 100644 --- a/sc/source/core/data/column.cxx +++ b/sc/source/core/data/column.cxx @@ -871,18 +871,25 @@ void ScColumn::SwapRow(SCROW nRow1, SCROW nRow2) std::advance(itf1, aPos1.second); std::advance(itf2, aPos2.second); - // TODO: Find out a way to adjust references without cloning new instances. - boost::scoped_ptr<ScFormulaCell> pOld1(*itf1); - boost::scoped_ptr<ScFormulaCell> pOld2(*itf2); - DetachFormulaCell(aPos1, **itf1); - DetachFormulaCell(aPos2, **itf2); - ScFormulaCell* pNew1 = cloneFormulaCell(pDocument, ScAddress(nCol, nRow1, nTab), *pOld2); - ScFormulaCell* pNew2 = cloneFormulaCell(pDocument, ScAddress(nCol, nRow2, nTab), *pOld1); - *itf1 = pNew1; - *itf2 = pNew2; - - ActivateNewFormulaCell(aPos1, *pNew1); - ActivateNewFormulaCell(aPos2, *pNew2); + // Is it an identical formula in the same group - if so, + // take a shortcut to swap the result data: + if(!(*itf1)->SwapWithinGroup(*itf2)) + { + // otherwise we need to really move the formula & + // re-write dependencies etc. + boost::scoped_ptr<ScFormulaCell> pOld1(*itf1); + boost::scoped_ptr<ScFormulaCell> pOld2(*itf2); + + DetachFormulaCell(aPos1, **itf1); + DetachFormulaCell(aPos2, **itf2); + ScFormulaCell* pNew1 = cloneFormulaCell(pDocument, ScAddress(nCol, nRow1, nTab), *pOld2); + ScFormulaCell* pNew2 = cloneFormulaCell(pDocument, ScAddress(nCol, nRow2, nTab), *pOld1); + *itf1 = pNew1; + *itf2 = pNew2; + + ActivateNewFormulaCell(aPos1, *pNew1); + ActivateNewFormulaCell(aPos2, *pNew2); + } } break; default: diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index 9bbc75d2d5af..957d8b2439f3 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -1977,15 +1977,55 @@ void ScFormulaCell::SetTableOpDirty() } } - bool ScFormulaCell::IsDirtyOrInTableOpDirty() const { return bDirty || (bTableOpDirty && pDocument->IsInInterpreterTableOp()); } +/** Exchange formulae cell result data inside a formula + group if possible. Return true if both Formula cells + are inside the same formula group and the data has + been successfully exchanged; otherwise false - leaving + the formulae untouched. + */ +bool ScFormulaCell::SwapWithinGroup( ScFormulaCell *pSwap ) +{ + if (!mxGroup || // ungrouped + mxGroup != pSwap->mxGroup) + return false; + + if (pDocument != pSwap->pDocument || + nSeenInIteration != pSwap->nSeenInIteration || + eTempGrammar != pSwap->eTempGrammar || + cMatrixFlag != pSwap->cMatrixFlag || + nFormatType != pSwap->nFormatType || + bDirty != pSwap->bDirty || + bChanged != pSwap->bChanged || + bRunning != pSwap->bRunning || + bCompile != pSwap->bCompile || + bSubTotal != pSwap->bSubTotal || + bIsIterCell != pSwap->bIsIterCell || + bInChangeTrack != pSwap->bInChangeTrack || + bTableOpDirty != pSwap->bTableOpDirty || + bNeedListening != pSwap->bNeedListening || + mbNeedsNumberFormat != pSwap->mbNeedsNumberFormat || + mbPostponedDirty != pSwap->mbPostponedDirty + ) + return false; // we are paranoid for good reason. + + // retain aPos as is. + + // swap result value + ScFormulaResult aTemp(aResult); + aResult = pSwap->aResult; + pSwap->aResult.Assign(aTemp); + + return true; +} + void ScFormulaCell::SetResultDouble( double n ) { - aResult.SetDouble( n); + aResult.SetDouble(n); } void ScFormulaCell::SetResultToken( const formula::FormulaToken* pToken ) |