[ooo-build-commit] .: sc/inc sc/source
Kohei Yoshida
kohei at kemper.freedesktop.org
Mon Oct 4 13:50:00 PDT 2010
sc/inc/document.hxx | 6 ++++
sc/source/core/data/cell.cxx | 16 ++++++++++++
sc/source/core/data/document.cxx | 49 +++++++++++++++++++++++++++++++++++++
sc/source/ui/docshell/dbdocfun.cxx | 7 ++---
4 files changed, 74 insertions(+), 4 deletions(-)
New commits:
commit 7c5ca3a2ec39576045b4fb3c1739acdb39a15f96
Author: Kohei Yoshida <kyoshida at novell.com>
Date: Mon Oct 4 16:47:03 2010 -0400
Ported calc-subtotal-function-update.diff from ooo-build.
With this change, Calc correctly recalculates cells containing
SUBTOTAL function when sheet's filtering state changes, instead of
recalculating all formula cells that listens to those ranges whose
filtering state has changed. The latter is wrong since the values
of the filtered ranges haven't changed.
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 6596dea..2023227 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -444,6 +444,8 @@ private:
sal_Int16 mnNamedRangesLockCount;
+ ::std::set<ScFormulaCell*> maSubTotalCells;
+
public:
SC_DLLPUBLIC ULONG GetCellCount() const; // alle Zellen
SCSIZE GetCellCount(SCTAB nTab, SCCOL nCol) const;
@@ -1813,6 +1815,10 @@ public:
bool IsInVBAMode() const;
ScRowBreakIterator* GetRowBreakIterator(SCTAB nTab) const;
+ void AddSubTotalCell(ScFormulaCell* pCell);
+ void RemoveSubTotalCell(ScFormulaCell* pCell);
+ void SetSubTotalCellsDirty(const ScRange& rDirtyRange);
+
private: // CLOOK-Impl-Methoden
/**
diff --git a/sc/source/core/data/cell.cxx b/sc/source/core/data/cell.cxx
index 35840ae..05466a8 100644
--- a/sc/source/core/data/cell.cxx
+++ b/sc/source/core/data/cell.cxx
@@ -724,6 +724,9 @@ ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos,
if ( pCode->GetNextOpCodeRPN( ocSubTotal ) )
bSubTotal = TRUE;
}
+
+ if (bSubTotal)
+ pDocument->AddSubTotalCell(this);
}
ScFormulaCell::ScFormulaCell( const ScFormulaCell& rCell, ScDocument& rDoc, const ScAddress& rPos, int nCloneFlags ) :
@@ -814,11 +817,15 @@ ScFormulaCell::ScFormulaCell( const ScFormulaCell& rCell, ScDocument& rDoc, cons
if( nCloneFlags & SC_CLONECELL_STARTLISTENING )
StartListeningTo( &rDoc );
+
+ if (bSubTotal)
+ pDocument->AddSubTotalCell(this);
}
ScFormulaCell::~ScFormulaCell()
{
pDocument->RemoveFromFormulaTree( this );
+ pDocument->RemoveSubTotalCell(this);
if (pDocument->HasExternalRefManager())
pDocument->GetExternalRefManager()->removeRefCell(this);
@@ -984,6 +991,9 @@ void ScFormulaCell::CompileTokenArray( BOOL bNoListening )
}
if ( bWasInFormulaTree )
pDocument->PutInFormulaTree( this );
+
+ if (bSubTotal)
+ pDocument->AddSubTotalCell(this);
}
}
@@ -1027,6 +1037,9 @@ void ScFormulaCell::CompileXML( ScProgress& rProgress )
bCompile = FALSE;
StartListeningTo( pDocument );
}
+
+ if (bSubTotal)
+ pDocument->AddSubTotalCell(this);
}
else
{
@@ -1066,6 +1079,9 @@ void ScFormulaCell::CalcAfterLoad()
bDirty = TRUE;
bCompile = FALSE;
bNewCompiled = TRUE;
+
+ if (bSubTotal)
+ pDocument->AddSubTotalCell(this);
}
// irgendwie koennen unter os/2 mit rotter FPU-Exception /0 ohne Err503
// gespeichert werden, woraufhin spaeter im NumberFormatter die BLC Lib
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 89d2d8f..45f4d08 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -5283,6 +5283,55 @@ ScRowBreakIterator* ScDocument::GetRowBreakIterator(SCTAB nTab) const
return NULL;
}
+void ScDocument::AddSubTotalCell(ScFormulaCell* pCell)
+{
+ maSubTotalCells.insert(pCell);
+}
+
+void ScDocument::RemoveSubTotalCell(ScFormulaCell* pCell)
+{
+ maSubTotalCells.erase(pCell);
+}
+
+namespace {
+
+bool lcl_hasDirtyRange(ScFormulaCell* pCell, const ScRange& rDirtyRange)
+{
+ ScDetectiveRefIter aRefIter(pCell);
+ ScRange aRange;
+ while (aRefIter.GetNextRef(aRange))
+ {
+ if (aRange.Intersects(rDirtyRange))
+ return true;
+ }
+ return false;
+}
+
+}
+
+void ScDocument::SetSubTotalCellsDirty(const ScRange& rDirtyRange)
+{
+ // to update the list by skipping cells that no longer contain subtotal function.
+ set<ScFormulaCell*> aNewSet;
+
+ bool bOldRecalc = GetAutoCalc();
+ SetAutoCalc(false);
+ set<ScFormulaCell*>::iterator itr = maSubTotalCells.begin(), itrEnd = maSubTotalCells.end();
+ for (; itr != itrEnd; ++itr)
+ {
+ ScFormulaCell* pCell = *itr;
+ if (pCell->IsSubTotal())
+ {
+ aNewSet.insert(pCell);
+ if (lcl_hasDirtyRange(pCell, rDirtyRange))
+ pCell->SetDirty();
+ }
+ }
+
+ SetAutoCalc(bOldRecalc);
+ maSubTotalCells.swap(aNewSet); // update the list.
+}
+
void ScDocument::EnableUndo( bool bVal )
{
GetUndoManager()->EnableUndo(bVal);
diff --git a/sc/source/ui/docshell/dbdocfun.cxx b/sc/source/ui/docshell/dbdocfun.cxx
index ca09bc8..381fe9d 100644
--- a/sc/source/ui/docshell/dbdocfun.cxx
+++ b/sc/source/ui/docshell/dbdocfun.cxx
@@ -942,10 +942,9 @@ BOOL ScDBDocFunc::Query( SCTAB nTab, const ScQueryParam& rQueryParam,
pDoc->UpdatePageBreaks( nTab );
}
- // #i23299# because of Subtotal functions, the whole rows must be set dirty
- ScRange aDirtyRange( 0 , aLocalParam.nRow1, nDestTab,
- MAXCOL, aLocalParam.nRow2, nDestTab );
- pDoc->SetDirty( aDirtyRange );
+ // #i23299# Subtotal functions depend on cell's filtered states.
+ ScRange aDirtyRange(0 , aLocalParam.nRow1, nDestTab, MAXCOL, aLocalParam.nRow2, nDestTab);
+ pDoc->SetSubTotalCellsDirty(aDirtyRange);
if ( bRecord )
{
More information about the ooo-build-commit
mailing list