diff options
author | Eike Rathke <erack@redhat.com> | 2018-07-13 19:29:12 +0200 |
---|---|---|
committer | Markus Mohrhard <markus.mohrhard@googlemail.com> | 2018-07-19 01:45:41 +0200 |
commit | 4e5248f32d8fdfd4655bd15bd60d83e9a0c6e540 (patch) | |
tree | f6f75bb2f047d291660dc500d6eaf52d5866db05 /sc | |
parent | cc2c11c2e4a99adf00d184507d6925c9af37e1bd (diff) |
Resolves: tdf#94925 proper recalc mode and dirty broadcast for OOXML import
This is a combination of 4 commits.
Rework FormulaTokenArray ScRecalcMode in preparation for tdf#94925
Strictly order the exclusive bits by priority, let AddRecalcMode()
handle all sets except forced ALWAYS or NORMAL.
Introduce ONLOAD_LENIENT and ONLOAD_MUST splitting ONLOAD to be
able to distinguish later during OOXML import.
Reviewed-on: https://gerrit.libreoffice.org/57402
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Jenkins
Resolves: tdf#94925 do not unset dirty if formula cell must be recalculated
Reviewed-on: https://gerrit.libreoffice.org/57404
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Jenkins
Broadcast formula cells marked for recalc, tdf#94925 related
In fact the ScDocument::CalcFormulaTree() call in
WorkbookFragment::recalcFormulaCells() never did anything because
no formula cell was added to the tree. Only visible dirty cells
were recalculated, but not their dependents.
Reviewed-on: https://gerrit.libreoffice.org/57431
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Jenkins
Remove the check for IsRecalcModeMustAfterImport(), tdf#94925 follow-up
It's now superfluous as we set those cells dirty and broadcast in
ScDocumentImport::broadcastRecalcAfterImport()
Reviewed-on: https://gerrit.libreoffice.org/57439
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Eike Rathke <erack@redhat.com>
f70860b8babf1cce7fda2ae63412659e72dbb4c3
a9dd4ad16c20b23ee8a1d46b69a4702b1ad4c81f
188de2d53a2d54df32d24eeeb148c4f9e87e7cfc
Change-Id: I11217fa19adb766f509d0d6854502112de547c59
Reviewed-on: https://gerrit.libreoffice.org/57438
Tested-by: Jenkins
Reviewed-by: Markus Mohrhard <markus.mohrhard@googlemail.com>
Diffstat (limited to 'sc')
-rw-r--r-- | sc/inc/documentimport.hxx | 7 | ||||
-rw-r--r-- | sc/source/core/data/documentimport.cxx | 52 | ||||
-rw-r--r-- | sc/source/core/data/formulacell.cxx | 3 | ||||
-rw-r--r-- | sc/source/core/tool/interpr2.cxx | 6 | ||||
-rw-r--r-- | sc/source/core/tool/interpr4.cxx | 8 | ||||
-rw-r--r-- | sc/source/core/tool/interpr7.cxx | 3 | ||||
-rw-r--r-- | sc/source/filter/oox/formulabuffer.cxx | 5 | ||||
-rw-r--r-- | sc/source/filter/oox/workbookfragment.cxx | 3 |
8 files changed, 73 insertions, 14 deletions
diff --git a/sc/inc/documentimport.hxx b/sc/inc/documentimport.hxx index f902e1858741..1a8b1cbd514f 100644 --- a/sc/inc/documentimport.hxx +++ b/sc/inc/documentimport.hxx @@ -125,8 +125,15 @@ public: void finalize(); + /** Broadcast all formula cells that are marked with + FormulaTokenArray::IsRecalcModeMustAfterImport() for a subsequent + ScDocument::CalcFormulaTree(). + */ + void broadcastRecalcAfterImport(); + private: void initColumn(ScColumn& rCol); + void broadcastRecalcAfterImportColumn(ScColumn& rCol); }; #endif diff --git a/sc/source/core/data/documentimport.cxx b/sc/source/core/data/documentimport.cxx index 55aaadae1ce7..a7a3ba8e0326 100644 --- a/sc/source/core/data/documentimport.cxx +++ b/sc/source/core/data/documentimport.cxx @@ -22,6 +22,8 @@ #include <listenercontext.hxx> #include <attarray.hxx> #include <sharedformula.hxx> +#include <bcaslot.hxx> +#include <scopetools.hxx> #include <svl/sharedstringpool.hxx> #include <svl/languageoptions.hxx> @@ -720,4 +722,54 @@ void ScDocumentImport::initColumn(ScColumn& rCol) rCol.CellStorageModified(); } +namespace { + +class CellStoreAfterImportBroadcaster +{ +public: + + CellStoreAfterImportBroadcaster() {} + + void operator() (const sc::CellStoreType::value_type& node) + { + if (node.type == sc::element_type_formula) + { + // Broadcast all formula cells marked for recalc. + ScFormulaCell** pp = &sc::formula_block::at(*node.data, 0); + ScFormulaCell** ppEnd = pp + node.size; + for (; pp != ppEnd; ++pp) + { + if ((*pp)->GetCode()->IsRecalcModeMustAfterImport()) + (*pp)->SetDirty(); + } + } + } +}; + +} + +void ScDocumentImport::broadcastRecalcAfterImport() +{ + sc::AutoCalcSwitch aACSwitch( mpImpl->mrDoc, false); + ScBulkBroadcast aBulkBroadcast( mpImpl->mrDoc.GetBASM(), SfxHintId::ScDataChanged); + + ScDocument::TableContainer::iterator itTab = mpImpl->mrDoc.maTabs.begin(), itTabEnd = mpImpl->mrDoc.maTabs.end(); + for (; itTab != itTabEnd; ++itTab) + { + if (!*itTab) + continue; + + ScTable& rTab = **itTab; + SCCOL nNumCols = rTab.aCol.size(); + for (SCCOL nColIdx = 0; nColIdx < nNumCols; ++nColIdx) + broadcastRecalcAfterImportColumn(rTab.aCol[nColIdx]); + } +} + +void ScDocumentImport::broadcastRecalcAfterImportColumn(ScColumn& rCol) +{ + CellStoreAfterImportBroadcaster aFunc; + std::for_each(rCol.maCells.begin(), rCol.maCells.end(), aFunc); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index d20ea590441d..b7465341b15e 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -1366,8 +1366,7 @@ void ScFormulaCell::CompileXML( sc::CompileFormulaContext& rCxt, ScProgress& rPr pDocument->CheckLinkFormulaNeedingCheck(*pCode); //volatile cells must be added here for import - if( pCode->IsRecalcModeAlways() || pCode->IsRecalcModeForced() || - pCode->IsRecalcModeOnLoad() || pCode->IsRecalcModeOnLoadOnce() ) + if( !pCode->IsRecalcModeNormal() || pCode->IsRecalcModeForced()) { // During load, only those cells that are marked explicitly dirty get // recalculated. So we need to set it dirty here. diff --git a/sc/source/core/tool/interpr2.cxx b/sc/source/core/tool/interpr2.cxx index 7846d0d162b6..45cefa1d0423 100644 --- a/sc/source/core/tool/interpr2.cxx +++ b/sc/source/core/tool/interpr2.cxx @@ -2748,10 +2748,8 @@ void ScInterpreter::ScDde() return; } - // Need to reinterpret after loading (build links) - - if ( rArr.IsRecalcModeNormal() ) - rArr.SetExclusiveRecalcModeOnLoad(); + // Need to reinterpret after loading (build links) + rArr.AddRecalcMode( ScRecalcMode::ONLOAD_LENIENT ); // while the link is not evaluated, idle must be disabled (to avoid circular references) diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx index 7c149d95d94a..ecb3bdb95e07 100644 --- a/sc/source/core/tool/interpr4.cxx +++ b/sc/source/core/tool/interpr4.cxx @@ -2698,8 +2698,7 @@ void ScInterpreter::ScExternal() else { // enable asyncs after loading - if ( rArr.IsRecalcModeNormal() ) - rArr.SetExclusiveRecalcModeOnLoad(); + rArr.AddRecalcMode( ScRecalcMode::ONLOAD_LENIENT ); // assure identical handler with identical call? double nErg = 0.0; ppParam[0] = &nErg; @@ -3059,10 +3058,7 @@ void ScInterpreter::ScExternal() if ( aCall.HasVarRes() ) // handle async functions { - if ( rArr.IsRecalcModeNormal() ) - { - rArr.SetExclusiveRecalcModeOnLoad(); - } + rArr.AddRecalcMode( ScRecalcMode::ONLOAD_LENIENT ); uno::Reference<sheet::XVolatileResult> xRes = aCall.GetVarRes(); ScAddInListener* pLis = ScAddInListener::Get( xRes ); if ( !pLis ) diff --git a/sc/source/core/tool/interpr7.cxx b/sc/source/core/tool/interpr7.cxx index 274bb69e5243..7b11e6faddab 100644 --- a/sc/source/core/tool/interpr7.cxx +++ b/sc/source/core/tool/interpr7.cxx @@ -310,8 +310,7 @@ void ScInterpreter::ScWebservice() } // Need to reinterpret after loading (build links) - if (rArr.IsRecalcModeNormal()) - rArr.SetExclusiveRecalcModeOnLoad(); + rArr.AddRecalcMode( ScRecalcMode::ONLOAD_LENIENT ); // while the link is not evaluated, idle must be disabled (to avoid circular references) bool bOldEnabled = pDok->IsIdleEnabled(); diff --git a/sc/source/filter/oox/formulabuffer.cxx b/sc/source/filter/oox/formulabuffer.cxx index f09a11244de9..feb1bc6d8908 100644 --- a/sc/source/filter/oox/formulabuffer.cxx +++ b/sc/source/filter/oox/formulabuffer.cxx @@ -158,6 +158,11 @@ void applySharedFormulas( case XML_n: // numeric value. pCell->SetResultDouble(rDesc.maCellValue.toDouble()); + /* TODO: is it on purpose that we never reset dirty here + * and thus recalculate anyway if cell was dirty? Or is it + * never dirty and therefor set dirty below otherwise? This + * is different from the non-shared case in + * applyCellFormulaValues(). */ break; case XML_str: if (bGeneratorKnownGood) diff --git a/sc/source/filter/oox/workbookfragment.cxx b/sc/source/filter/oox/workbookfragment.cxx index 0899b3c557b8..75bd31cb6397 100644 --- a/sc/source/filter/oox/workbookfragment.cxx +++ b/sc/source/filter/oox/workbookfragment.cxx @@ -575,7 +575,10 @@ void WorkbookFragment::recalcFormulaCells() if (bHardRecalc) rDocSh.DoHardRecalc(); else + { + getDocImport().broadcastRecalcAfterImport(); rDoc.CalcFormulaTree(false, true, false); + } } // private -------------------------------------------------------------------- |