include/formula/tokenarray.hxx | 5 +++++ sc/inc/document.hxx | 2 +- sc/inc/formulacell.hxx | 3 ++- sc/source/core/data/formulacell.cxx | 8 +++----- sc/source/filter/oox/formulabuffer.cxx | 31 ++++++++++++++++++++++++++++--- sc/source/ui/view/output2.cxx | 13 +++++++------ 6 files changed, 46 insertions(+), 16 deletions(-)
New commits: commit 816b0e97f32df82a1ffc23950d5bf21760a4cd39 Author: Eike Rathke <er...@redhat.com> AuthorDate: Thu Feb 23 01:22:16 2023 +0100 Commit: Xisco Fauli <xiscofa...@libreoffice.org> CommitDate: Wed Mar 1 10:20:40 2023 +0000 Resolves: tdf#153767 Try harder to import OOXML bool shared formula result ... by setting the result value or if necessary recalculating even if AutoCalc is turned off for the document. Similar for other implicitly recalculating formula types. Also set a boolean number format if none. Change-Id: I2f75735707180eccf4b2c525738ac0b763901230 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/147425 Reviewed-by: Eike Rathke <er...@redhat.com> Tested-by: Jenkins (cherry picked from commit 05ac57f85eb622b798719db03bbdd07b79e1703a) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/147444 Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org> diff --git a/include/formula/tokenarray.hxx b/include/formula/tokenarray.hxx index cbff6a3e469d..330543d427dc 100644 --- a/include/formula/tokenarray.hxx +++ b/include/formula/tokenarray.hxx @@ -430,6 +430,11 @@ public: example OOXML. */ bool IsRecalcModeMustAfterImport() const { return (nMode & ScRecalcMode::EMask) <= ScRecalcMode::ONLOAD_ONCE; } + void ClearRecalcModeMustAfterImport() + { + if (IsRecalcModeMustAfterImport() && !IsRecalcModeAlways()) + SetExclusiveRecalcModeNormal(); + } /** Get OpCode of the most outer function */ inline OpCode GetOuterFuncOpCode() const; diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index 4873307ea01d..092d9ba0d9a9 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -1224,7 +1224,7 @@ public: SC_DLLPUBLIC sal_uInt32 GetNumberFormat( SCCOL nCol, SCROW nRow, SCTAB nTab ) const; sal_uInt32 GetNumberFormat( const ScRange& rRange ) const; SC_DLLPUBLIC sal_uInt32 GetNumberFormat( const ScInterpreterContext& rContext, const ScAddress& ) const; - void SetNumberFormat( const ScAddress& rPos, sal_uInt32 nNumberFormat ); + SC_DLLPUBLIC void SetNumberFormat( const ScAddress& rPos, sal_uInt32 nNumberFormat ); void GetNumberFormatInfo( const ScInterpreterContext& rContext, SvNumFormatType& nType, sal_uInt32& nIndex, const ScAddress& rPos ) const; SC_DLLPUBLIC const ScFormulaCell* GetFormulaCell( const ScAddress& rPos ) const; diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx index e4bc41772e0e..42b7f6120149 100644 --- a/sc/inc/formulacell.hxx +++ b/sc/inc/formulacell.hxx @@ -445,7 +445,8 @@ public: if (!IsDirtyOrInTableOpDirty()) return false; - return (rDocument.GetAutoCalc() || (cMatrixFlag != ScMatrixMode::NONE)); + return rDocument.GetAutoCalc() || (cMatrixFlag != ScMatrixMode::NONE) + || (pCode->IsRecalcModeMustAfterImport() && !pCode->IsRecalcModeAlways()); } void MaybeInterpret() diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index 023a4214bd93..9b065329ba26 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -2331,6 +2331,8 @@ void ScFormulaCell::InterpretTail( ScInterpreterContext& rContext, ScInterpretTa OSL_ENSURE( pCode->GetCodeError() != FormulaError::NONE, "no RPN code and no errors ?!?!" ); ResetDirty(); } + + pCode->ClearRecalcModeMustAfterImport(); } void ScFormulaCell::HandleStuffAfterParallelCalculation(ScInterpreter* pInterpreter) @@ -2546,7 +2548,7 @@ void ScFormulaCell::SetDirty( bool bDirtyFlag ) // the FormulaTree, once in there it would be assumed that its // dependents already had been tracked and it would be skipped on a // subsequent notify. Postpone tracking until all listeners are set. - if (!rDocument.IsImportingXML()) + if (!rDocument.IsImportingXML() && !rDocument.IsInsertingFromOtherDoc()) rDocument.TrackFormulas(); } @@ -2647,10 +2649,6 @@ void ScFormulaCell::AddRecalcMode( ScRecalcMode nBits ) { if ( (nBits & ScRecalcMode::EMask) != ScRecalcMode::NORMAL ) SetDirtyVar(); - if ( nBits & ScRecalcMode::ONLOAD_ONCE ) - { // OnLoadOnce is used only to set Dirty after filter import. - nBits = (nBits & ~ScRecalcMode::EMask) | ScRecalcMode::NORMAL; - } pCode->AddRecalcMode( nBits ); } diff --git a/sc/source/filter/oox/formulabuffer.cxx b/sc/source/filter/oox/formulabuffer.cxx index 3b81e89e45c2..dc934d1d41a4 100644 --- a/sc/source/filter/oox/formulabuffer.cxx +++ b/sc/source/filter/oox/formulabuffer.cxx @@ -22,6 +22,7 @@ #include <oox/token/tokens.hxx> #include <oox/helper/progressbar.hxx> #include <svl/sharedstringpool.hxx> +#include <svl/numformat.hxx> #include <sal/log.hxx> using namespace ::com::sun::star::uno; @@ -154,20 +155,41 @@ void applySharedFormulas( pCell = new ScFormulaCell(rDoc.getDoc(), aPos, *pArray); rDoc.setFormulaCell(aPos, pCell); - if (rDoc.getDoc().GetNumberFormat(aPos.Col(), aPos.Row(), aPos.Tab()) % SV_COUNTRY_LANGUAGE_OFFSET == 0) + const bool bNeedNumberFormat = ((rDoc.getDoc().GetNumberFormat( + aPos.Col(), aPos.Row(), aPos.Tab()) % SV_COUNTRY_LANGUAGE_OFFSET) == 0); + if (bNeedNumberFormat) pCell->SetNeedNumberFormat(true); if (rDesc.maCellValue.isEmpty()) { // No cached cell value. Mark it for re-calculation. pCell->SetDirty(); + // Recalc even if AutoCalc is disabled. Must be after + // SetDirty() as it also calls SetDirtyVar(). + pCell->AddRecalcMode( ScRecalcMode::ONLOAD_ONCE); continue; } - // Set cached formula results. For now, we only use numeric and string-formula - // results. Find out how to utilize cached results of other types. + // Set cached formula results. For now, we only use boolean, + // numeric and string-formula results. Find out how to utilize + // cached results of other types. switch (rDesc.mnValueType) { + case XML_b: + // boolean value. + if (bNeedNumberFormat) + { + rDoc.getDoc().SetNumberFormat( aPos, + rDoc.getDoc().GetFormatTable()->GetStandardFormat( SvNumFormatType::LOGICAL)); + } + if (rDesc.maCellValue == "1" || rDesc.maCellValue == "0") + pCell->SetResultDouble(rDesc.maCellValue == "1" ? 1.0 : 0.0); + else + { + // Recalc even if AutoCalc is disabled. + pCell->AddRecalcMode( ScRecalcMode::ONLOAD_ONCE); + } + break; case XML_n: // numeric value. pCell->SetResultDouble(rDesc.maCellValue.toDouble()); @@ -193,6 +215,9 @@ void applySharedFormulas( default: // Mark it for re-calculation. pCell->SetDirty(); + // Recalc even if AutoCalc is disabled. Must be after + // SetDirty() as it also calls SetDirtyVar(). + pCell->AddRecalcMode( ScRecalcMode::ONLOAD_ONCE); } } } diff --git a/sc/source/ui/view/output2.cxx b/sc/source/ui/view/output2.cxx index 5f09c292c176..649ccdd7349e 100644 --- a/sc/source/ui/view/output2.cxx +++ b/sc/source/ui/view/output2.cxx @@ -1484,9 +1484,15 @@ tools::Rectangle ScOutputData::LayoutStrings(bool bPixelToLogic, bool bPaint, co mpDev->GetMapMode().GetMapUnit() == mpRefDevice->GetMapMode().GetMapUnit(), "LayoutStrings: different MapUnits ?!?!" ); + sc::IdleSwitch aIdleSwitch(*mpDoc, false); + + // Try to limit interpreting to only visible cells. Calling e.g. IsValue() + // on a formula cell that needs interpreting would call Interpret() + // for the entire formula group, which could be large. + mpDoc->InterpretCellsIfNeeded( ScRange( nX1, nY1, nTab, nX2, nY2, nTab )); + vcl::PDFExtOutDevData* pPDFData = dynamic_cast< vcl::PDFExtOutDevData* >(mpDev->GetExtOutDevData() ); - sc::IdleSwitch aIdleSwitch(*mpDoc, false); ScDrawStringsVars aVars( this, bPixelToLogic ); bool bProgress = false; @@ -1514,11 +1520,6 @@ tools::Rectangle ScOutputData::LayoutStrings(bool bPixelToLogic, bool bPaint, co const SfxItemSet* pOldCondSet = nullptr; SvtScriptType nOldScript = SvtScriptType::NONE; - // Try to limit interpreting to only visible cells. Calling e.g. IsValue() - // on a formula cell that needs interpreting would call Interpret() - // for the entire formula group, which could be large. - mpDoc->InterpretCellsIfNeeded( ScRange( nX1, nY1, nTab, nX2, nY2, nTab )); - // alternative pattern instances in case we need to modify the pattern // before processing the cell value. std::vector<std::unique_ptr<ScPatternAttr> > aAltPatterns;