[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