From 7299db371e38d1a3ecd51eb3811344ee5bb3a086 Mon Sep 17 00:00:00 2001 From: Kohei Yoshida Date: Thu, 25 Jul 2013 12:24:01 -0400 Subject: 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 Tested-by: Fridrich Strba --- sc/inc/column.hxx | 1 + sc/inc/table.hxx | 6 ++++++ sc/source/core/data/column.cxx | 21 +++++++++++++++++++++ sc/source/core/data/document.cxx | 28 ++++++++++++++++++++++++++++ sc/source/core/data/table2.cxx | 8 ++++++++ 5 files changed, 64 insertions(+) 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; iGetCellType() != CELLTYPE_FORMULA) + continue; + + ScFormulaCell* p = static_cast(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 +{ + 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) { -- cgit v1.2.3