summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Meeks <michael.meeks@collabora.com>2014-03-14 14:26:02 +0000
committerMichael Meeks <michael.meeks@collabora.com>2014-03-14 16:36:06 +0000
commit0698c49ccdbf62dd84d3f9c5d25ee039f4fff722 (patch)
treed6a727c31cc754805655e74f90c23c611d0a2632
parent79fa84ccb9b45b149843ac88e4d662f2a09e94bf (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.hxx1
-rw-r--r--sc/source/core/data/column.cxx31
-rw-r--r--sc/source/core/data/formulacell.cxx44
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 )