summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
authorEike Rathke <erack@redhat.com>2018-07-13 19:29:12 +0200
committerMarkus Mohrhard <markus.mohrhard@googlemail.com>2018-07-19 01:45:41 +0200
commit4e5248f32d8fdfd4655bd15bd60d83e9a0c6e540 (patch)
treef6f75bb2f047d291660dc500d6eaf52d5866db05 /sc
parentcc2c11c2e4a99adf00d184507d6925c9af37e1bd (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.hxx7
-rw-r--r--sc/source/core/data/documentimport.cxx52
-rw-r--r--sc/source/core/data/formulacell.cxx3
-rw-r--r--sc/source/core/tool/interpr2.cxx6
-rw-r--r--sc/source/core/tool/interpr4.cxx8
-rw-r--r--sc/source/core/tool/interpr7.cxx3
-rw-r--r--sc/source/filter/oox/formulabuffer.cxx5
-rw-r--r--sc/source/filter/oox/workbookfragment.cxx3
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 --------------------------------------------------------------------