summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@gmail.com>2013-07-25 12:24:01 -0400
committerFridrich Strba <fridrich@documentfoundation.org>2013-07-25 17:33:07 +0000
commit7299db371e38d1a3ecd51eb3811344ee5bb3a086 (patch)
tree9551203d51f6a11a91a969c0322bfbd30336e476
parent8a42cb382fc1fff6ed0c57b33762080cdc0bd5a4 (diff)
Propagate change on COLUMN() and ROW() functions on position change.
1) Insert =COLUMN() or =ROW() in arbitrary cell. 2) Have another cell reference that cell. 3) Insert or delete column or row to change the cell that contains COLUMN or ROW function. This will change the result of that cell. 4) Check the result of the 2nd cell that references the first. The value change is not propagated. This commit fixes that. NB: master has a similar but different fix. Due to the difference in cell storage between master and 4.1, I had to devise a different fix for the 4.1 branch. Change-Id: Ib1b730e7a4a70a11b967b88730a68362e061a8a0 Reviewed-on: https://gerrit.libreoffice.org/5113 Reviewed-by: Fridrich Strba <fridrich@documentfoundation.org> Tested-by: Fridrich Strba <fridrich@documentfoundation.org>
-rw-r--r--sc/inc/column.hxx1
-rw-r--r--sc/inc/table.hxx6
-rw-r--r--sc/source/core/data/column.cxx21
-rw-r--r--sc/source/core/data/document.cxx28
-rw-r--r--sc/source/core/data/table2.cxx8
5 files changed, 64 insertions, 0 deletions
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index dfc46b0acf9d..935c07e9ca15 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -440,6 +440,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 b62fa1e8cf56..20b0ed7bda67 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -853,6 +853,12 @@ public:
void DeleteBroadcasters( sc::ColumnBlockPosition& rBlockPos, SCCOL nCol, SCROW nRow1, SCROW nRow2 );
bool HasBroadcaster( SCCOL nCol ) const;
+ /**
+ * Broadcast dirty formula cells that contain functions such as CELL(),
+ * COLUMN() or ROW() which may change its value on move.
+ */
+ void BroadcastRecalcOnRefMove();
+
/** Replace behaves differently to the Search; adjust the rCol and rRow accordingly.
'Replace' replaces at the 'current' position, but in order to achieve
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 88cb65dcd8d6..b687489cc276 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -2175,6 +2175,27 @@ void ScColumn::SetRelNameDirty()
pDocument->SetAutoCalc( bOldAutoCalc );
}
+void ScColumn::BroadcastRecalcOnRefMove()
+{
+ bool bOldAutoCalc = pDocument->GetAutoCalc();
+ pDocument->SetAutoCalc( false ); // no multiple recalculation
+
+ ScHint aHint(SC_HINT_DATACHANGED, ScAddress(nCol, 0, nTab));
+ for (SCSIZE i=0; i<maItems.size(); i++)
+ {
+ if (maItems[i].pCell->GetCellType() != CELLTYPE_FORMULA)
+ continue;
+
+ ScFormulaCell* p = static_cast<ScFormulaCell*>(maItems[i].pCell);
+ if (p->GetDirty() && p->GetCode()->IsRecalcModeOnRefMove())
+ {
+ aHint.GetAddress().SetRow(maItems[i].nRow);
+ pDocument->Broadcast(aHint);
+ }
+
+ }
+ pDocument->SetAutoCalc( bOldAutoCalc );
+}
void ScColumn::CalcAll()
{
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 4933e5d59166..02d6e21e35bc 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -1115,6 +1115,18 @@ bool ScDocument::CanInsertRow( const ScRange& rRange ) const
return bTest;
}
+namespace {
+
+struct BroadcastRecalcOnRefMoveHandler : std::unary_function<ScTable*, void>
+{
+ void operator() (ScTable* p)
+ {
+ if (p)
+ p->BroadcastRecalcOnRefMove();
+ }
+};
+
+}
bool ScDocument::InsertRow( SCCOL nStartCol, SCTAB nStartTab,
SCCOL nEndCol, SCTAB nEndTab,
@@ -1194,6 +1206,10 @@ bool ScDocument::InsertRow( SCCOL nStartCol, SCTAB nStartTab,
for (; it != maTabs.end(); ++it)
if (*it)
(*it)->SetRelNameDirty();
+
+ // 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;
}
@@ -1285,6 +1301,10 @@ void ScDocument::DeleteRow( SCCOL nStartCol, SCTAB nStartTab,
for (; it != maTabs.end(); ++it)
if (*it)
(*it)->SetRelNameDirty();
+
+ // 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());
}
SetAutoCalc( bOldAutoCalc );
@@ -1390,6 +1410,10 @@ bool ScDocument::InsertCol( SCROW nStartRow, SCTAB nStartTab,
for (; it != maTabs.end(); ++it)
if (*it)
(*it)->SetRelNameDirty();
+
+ // 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;
}
@@ -1479,6 +1503,10 @@ void ScDocument::DeleteCol(SCROW nStartRow, SCTAB nStartTab, SCROW nEndRow, SCTA
for (; it != maTabs.end(); ++it)
if (*it)
(*it)->SetRelNameDirty();
+
+ // 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());
}
SetAutoCalc( bOldAutoCalc );
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index a44c60221cb8..4786d3063a7f 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -1664,6 +1664,14 @@ void ScTable::SetRelNameDirty()
pDocument->SetAutoCalc( bOldAutoCalc );
}
+void ScTable::BroadcastRecalcOnRefMove()
+{
+ bool bOldAutoCalc = pDocument->GetAutoCalc();
+ pDocument->SetAutoCalc( false ); // Mehrfachberechnungen vermeiden
+ for (SCCOL i = 0; i <= MAXCOL; ++i)
+ aCol[i].BroadcastRecalcOnRefMove();
+ pDocument->SetAutoCalc( bOldAutoCalc );
+}
void ScTable::SetLoadingMedium(bool bLoading)
{