summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@gmail.com>2013-07-23 16:02:37 -0400
committerKohei Yoshida <kohei.yoshida@gmail.com>2013-07-24 23:29:39 -0400
commitab24a2c25900948bb71acbedbdecd84bda3217f7 (patch)
tree229230be711f168dae64b984f915dab4c903cb66
parenta6b0568eca2b025f556fa4d0b702b67a01262618 (diff)
Broadcast on formula cells containing COLUMN functions on column insertion.
To ensure that the change gets propagated properly. This fixes testFuncCOLUMN() cppunit test. Change-Id: Ia1ffc2880b7dae530ceb11c617c3963f7bfaeb00
-rw-r--r--sc/inc/column.hxx1
-rw-r--r--sc/inc/table.hxx20
-rw-r--r--sc/source/core/data/column.cxx30
-rw-r--r--sc/source/core/data/document.cxx50
-rw-r--r--sc/source/core/data/table2.cxx7
5 files changed, 94 insertions, 14 deletions
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 00b2a63499af..5ef6cce7eaed 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -431,6 +431,7 @@ public:
void StartAllListeners();
void StartNeededListeners(); // only for cells where NeedsListening()==true
void SetRelNameDirty();
+ void BroadcastRecalcOnRefMove();
void CompileDBFormula();
void CompileDBFormula( bool bCreateFormulaString );
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 0e4305ad3424..00cc7e52e4df 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -862,6 +862,24 @@ public:
void SetFormulaResults( SCCOL nCol, SCROW nRow, const double* pResults, size_t nLen );
+ /**
+ * Have formula cells with NeedsListening() == true start listening to the
+ * document.
+ */
+ void StartNeededListeners();
+
+ /**
+ * Mark dirty those formula cells that has named ranges with relative
+ * references.
+ */
+ void SetRelNameDirty();
+
+ /**
+ * Broadcast dirty formula cells that contain functions such as CELL(),
+ * COLUMN() or ROW() which may change its value on move.
+ */
+ void BroadcastRecalcOnRefMove();
+
#if DEBUG_COLUMN_STORAGE
void DumpFormulaGroups( SCCOL nCol ) const;
#endif
@@ -968,8 +986,6 @@ private:
void StartListening( sc::StartListeningContext& rCxt, SCCOL nCol, SCROW nRow, SvtListener& rListener );
void EndListening( sc::EndListeningContext& rCxt, SCCOL nCol, SCROW nRow, SvtListener& rListener );
void StartAllListeners();
- void StartNeededListeners(); // only for cells where NeedsListening()==TRUE
- void SetRelNameDirty();
void SetLoadingMedium(bool bLoading);
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 23a740f9ccc4..da3cb4927613 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -2144,6 +2144,7 @@ void resetColumnPosition(sc::CellStoreType& rCells, SCCOL nCol)
void ScColumn::SwapCol(ScColumn& rCol)
{
+ maBroadcasters.swap(rCol.maBroadcasters);
maCells.swap(rCol.maCells);
maCellTextAttrs.swap(rCol.maCellTextAttrs);
@@ -2163,7 +2164,6 @@ void ScColumn::SwapCol(ScColumn& rCol)
CellStorageModified();
rCol.CellStorageModified();
-
}
void ScColumn::MoveTo(SCROW nStartRow, SCROW nEndRow, ScColumn& rCol)
@@ -3004,6 +3004,26 @@ void ScColumn::SetDirtyAfterLoad()
sc::ProcessFormula(maCells, aFunc);
}
+namespace {
+
+class RecalcOnRefMoveCollector
+{
+ std::vector<SCROW> maDirtyRows;
+public:
+ void operator() (size_t nRow, ScFormulaCell* pCell)
+ {
+ if (pCell->GetDirty() && pCell->GetCode()->IsRecalcModeOnRefMove())
+ maDirtyRows.push_back(nRow);
+ }
+
+ const std::vector<SCROW>& getDirtyRows() const
+ {
+ return maDirtyRows;
+ }
+};
+
+}
+
void ScColumn::SetRelNameDirty()
{
sc::AutoCalcSwitch aSwitch(*pDocument, false);
@@ -3011,6 +3031,14 @@ void ScColumn::SetRelNameDirty()
sc::ProcessFormula(maCells, aFunc);
}
+void ScColumn::BroadcastRecalcOnRefMove()
+{
+ sc::AutoCalcSwitch aSwitch(*pDocument, false);
+ RecalcOnRefMoveCollector aFunc;
+ sc::ProcessFormula(maCells, aFunc);
+ BroadcastCells(aFunc.getDirtyRows());
+}
+
void ScColumn::CalcAll()
{
CalcAllHandler aFunc;
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index dfc17cf90766..9cba37457454 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -1334,6 +1334,36 @@ bool ScDocument::CanInsertCol( const ScRange& rRange ) const
return bTest;
}
+namespace {
+
+struct StartNeededListenersHandler : std::unary_function<ScTable*, void>
+{
+ void operator() (ScTable* p)
+ {
+ if (p)
+ p->StartNeededListeners();
+ }
+};
+
+struct SetRelNameDirtyHandler : std::unary_function<ScTable*, void>
+{
+ void operator() (ScTable* p)
+ {
+ if (p)
+ p->SetRelNameDirty();
+ }
+};
+
+struct BroadcastRecalcOnRefMoveHandler : std::unary_function<ScTable*, void>
+{
+ void operator() (ScTable* p)
+ {
+ if (p)
+ p->BroadcastRecalcOnRefMove();
+ }
+};
+
+}
bool ScDocument::InsertCol( SCROW nStartRow, SCTAB nStartTab,
SCROW nEndRow, SCTAB nEndTab,
@@ -1394,17 +1424,15 @@ bool ScDocument::InsertCol( SCROW nStartRow, SCTAB nStartTab,
StartAllListeners();
}
else
- {// Listeners have been removed in UpdateReference
- TableContainer::iterator it = maTabs.begin();
- for (; it != maTabs.end(); ++it)
- if (*it)
- (*it)->StartNeededListeners();
- // at least all cells using range names pointing relative
- // to the moved range must recalculate
- it = maTabs.begin();
- for (; it != maTabs.end(); ++it)
- if (*it)
- (*it)->SetRelNameDirty();
+ {
+ // Listeners have been removed in UpdateReference
+ std::for_each(maTabs.begin(), maTabs.end(), StartNeededListenersHandler());
+ // at least all cells using range names pointing relative to the
+ // moved range must recalculate.
+ std::for_each(maTabs.begin(), maTabs.end(), SetRelNameDirtyHandler());
+ // Cells containing functions such as CELL, COLUMN or ROW may have
+ // changed their values on relocation. Broadcast them.
+ std::for_each(maTabs.begin(), maTabs.end(), BroadcastRecalcOnRefMoveHandler());
}
bRet = true;
}
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index 96839f10f903..5bbb6d38086b 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -48,6 +48,7 @@
#include "editutil.hxx"
#include "mtvcellfunc.hxx"
#include "refupdatecontext.hxx"
+#include "scopetools.hxx"
#include "scitems.hxx"
#include <editeng/boxitem.hxx>
@@ -1705,6 +1706,12 @@ void ScTable::SetRelNameDirty()
pDocument->SetAutoCalc( bOldAutoCalc );
}
+void ScTable::BroadcastRecalcOnRefMove()
+{
+ sc::AutoCalcSwitch aSwitch(*pDocument, false);
+ for (SCCOL i = 0; i <= MAXCOL; ++i)
+ aCol[i].BroadcastRecalcOnRefMove();
+}
void ScTable::SetLoadingMedium(bool bLoading)
{