officecfg/registry/schema/org/openoffice/Office/Calc.xcs | 24 +++++ sc/inc/formulaopt.hxx | 4 sc/inc/globstr.hrc | 1 sc/source/core/tool/formulaopt.cxx | 62 +++++++++++++-- sc/source/filter/oox/workbookhelper.cxx | 4 sc/source/filter/xml/xmlimprt.cxx | 3 sc/source/ui/docshell/docsh.cxx | 56 +++++++++++++ sc/source/ui/inc/docsh.hxx | 2 sc/source/ui/inc/tpformula.hxx | 1 sc/source/ui/optdlg/tpformula.cxx | 12 ++ sc/uiconfig/scalc/ui/optformula.ui | 37 ++++++++ 11 files changed, 197 insertions(+), 9 deletions(-)
New commits: commit 1bc97e82c793574ec16238a38b4ab644c623fd4b Author: Balazs Varga <balazs.varga.ext...@allotropia.de> AuthorDate: Wed Feb 14 22:34:10 2024 +0100 Commit: Justin Luth <jl...@mail.com> CommitDate: Wed Mar 20 15:41:40 2024 +0100 tdf#124098 sc add global config setting "RecalcOptimalRowHeightMode" to optimal row height recalculation for optimal document loading. THIS COMMIT MERGES commits 0748c2b0789a and 0e0e7de07686 AS WELL, so XLSX is handled too! If the "RecalcOptimalRowHeightMode" is set to "Recalc always" we always recalculate the optimal row heights at load time, without any warning dialog. If the "RecalcOptimalRowHeightMode" is set to "Recalc" we never recalculate the optimal row heights at load time, without any warning dialog. If the "RecalcOptimalRowHeightMode" is set to "Ask before Recalc" we ask the user if want to recalculate the optimal row heights at load time or not. The default value is the same what we are doing now: "Recalc always" This option was necessary, since optimal row height calculation depending on also the result of the conditional formatted formulas and it takes a lot of time to calculate the optimal row heights and load the document. Because we allow a lot of text/cell format attribute which are effect on the cell size, therefor it is necessary to evaluate all the formulas. Also if we have 20 condition for a cell range we need to evaluate all the 20 formulas for all the cells and it is very expensive at load time. Change-Id: I9288d11dd2f061f85fa36292a909402a6bb89ea9 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163421 Tested-by: Jenkins Reviewed-by: Balazs Varga <balazs.varga.ext...@allotropia.de> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164796 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Justin Luth <jl...@mail.com> Reviewed-by: Michael Meeks <michael.me...@collabora.com> diff --git a/officecfg/registry/schema/org/openoffice/Office/Calc.xcs b/officecfg/registry/schema/org/openoffice/Office/Calc.xcs index d54b092eca66..a8830ab1ba19 100644 --- a/officecfg/registry/schema/org/openoffice/Office/Calc.xcs +++ b/officecfg/registry/schema/org/openoffice/Office/Calc.xcs @@ -1532,6 +1532,30 @@ </constraints> <value>1</value> </prop> + <prop oor:name="RecalcOptimalRowHeightMode" oor:type="xs:int" oor:nillable="false"> + <!-- UIHint: Tools - Options - Spreadsheet - Formula --> + <info> + <desc>Specifies whether to force a hard recalc after load on optimal row heights.</desc> + </info> + <constraints> + <enumeration oor:value="0"> + <info> + <desc>Recalc always</desc> + </info> + </enumeration> + <enumeration oor:value="1"> + <info> + <desc>Recalc never</desc> + </info> + </enumeration> + <enumeration oor:value="2"> + <info> + <desc>Ask before Recalc</desc> + </info> + </enumeration> + </constraints> + <value>0</value> + </prop> </group> </group> <group oor:name="Revision"> diff --git a/sc/inc/formulaopt.hxx b/sc/inc/formulaopt.hxx index de46b52643c8..6cc1dedcbbb4 100644 --- a/sc/inc/formulaopt.hxx +++ b/sc/inc/formulaopt.hxx @@ -30,6 +30,7 @@ private: ScRecalcOptions meOOXMLRecalc; ScRecalcOptions meODFRecalc; + ScRecalcOptions meReCalcOptiRowHeights; public: ScFormulaOptions(); @@ -64,6 +65,9 @@ public: void SetODFRecalcOptions( ScRecalcOptions eOpt ) { meODFRecalc = eOpt; } ScRecalcOptions GetODFRecalcOptions() const { return meODFRecalc; } + void SetReCalcOptiRowHeights( ScRecalcOptions eOpt ) { meReCalcOptiRowHeights = eOpt; } + ScRecalcOptions GetReCalcOptiRowHeights() const { return meReCalcOptiRowHeights; } + void ResetFormulaSeparators(); static void GetDefaultFormulaSeparators(OUString& rSepArg, OUString& rSepArrayCol, OUString& rSepArrayRow); diff --git a/sc/inc/globstr.hrc b/sc/inc/globstr.hrc index 8b07dc508edd..6d73c41fdc51 100644 --- a/sc/inc/globstr.hrc +++ b/sc/inc/globstr.hrc @@ -505,6 +505,7 @@ #define STR_EDIT_EXISTING_COND_FORMATS NC_("STR_EDIT_EXISTING_COND_FORMATS", "The selected cell already contains conditional formatting. You can either edit the existing conditional format or you define a new overlapping conditional format. Do you want to edit the existing conditional format?") #define STR_QUERY_FORMULA_RECALC_ONLOAD_ODS NC_("STR_QUERY_FORMULA_RECALC_ONLOAD_ODS", "This document was last saved by an application other than %PRODUCTNAME. Some formula cells may produce different results when recalculated. Do you want to recalculate all formula cells in this document now?") #define STR_QUERY_FORMULA_RECALC_ONLOAD_XLS NC_("STR_QUERY_FORMULA_RECALC_ONLOAD_XLS", "This document was saved in Excel file format (.xlsx). Some formula cells may produce different results when recalculated. Do you want to recalculate all formula cells now?") +#define STR_QUERY_OPT_ROW_HEIGHT_RECALC_ONLOAD NC_("STR_QUERY_OPT_ROW_HEIGHT_RECALC_ONLOAD", "The content of some cells may not be entirely visible. Recalculating row heights will make them visible, but may take some time. Do you want to recalculate all row heights now?") #define STR_NO_INSERT_DELETE_OVER_PIVOT_TABLE NC_("STR_NO_INSERT_DELETE_OVER_PIVOT_TABLE", "You cannot insert or delete cells when the affected range intersects with pivot table.") #define STR_DPFIELD_GROUP_BY_SECONDS NC_("STR_DPFIELD_GROUP_BY_SECONDS", "Seconds") #define STR_DPFIELD_GROUP_BY_MINUTES NC_("STR_DPFIELD_GROUP_BY_MINUTES", "Minutes") diff --git a/sc/source/core/tool/formulaopt.cxx b/sc/source/core/tool/formulaopt.cxx index 08c660a44ac1..77a5e3cad9f2 100644 --- a/sc/source/core/tool/formulaopt.cxx +++ b/sc/source/core/tool/formulaopt.cxx @@ -35,6 +35,7 @@ void ScFormulaOptions::SetDefaults() mbWriteCalcConfig = true; meOOXMLRecalc = RECALC_ASK; meODFRecalc = RECALC_ASK; + meReCalcOptiRowHeights = RECALC_ASK; // unspecified means use the current formula syntax. aCalcConfig.reset(); @@ -116,7 +117,8 @@ bool ScFormulaOptions::operator==( const ScFormulaOptions& rOpt ) const && aFormulaSepArrayRow == rOpt.aFormulaSepArrayRow && aFormulaSepArrayCol == rOpt.aFormulaSepArrayCol && meOOXMLRecalc == rOpt.meOOXMLRecalc - && meODFRecalc == rOpt.meODFRecalc; + && meODFRecalc == rOpt.meODFRecalc + && meReCalcOptiRowHeights == rOpt.meReCalcOptiRowHeights; } bool ScFormulaOptions::operator!=( const ScFormulaOptions& rOpt ) const @@ -159,11 +161,12 @@ constexpr OUStringLiteral CFGPATH_FORMULA = u"Office.Calc/Formula"; #define SCFORMULAOPT_EMPTY_OUSTRING_AS_ZERO 7 #define SCFORMULAOPT_OOXML_RECALC 8 #define SCFORMULAOPT_ODF_RECALC 9 -#define SCFORMULAOPT_OPENCL_AUTOSELECT 10 -#define SCFORMULAOPT_OPENCL_DEVICE 11 -#define SCFORMULAOPT_OPENCL_SUBSET_ONLY 12 -#define SCFORMULAOPT_OPENCL_MIN_SIZE 13 -#define SCFORMULAOPT_OPENCL_SUBSET_OPS 14 +#define SCFORMULAOPT_ROW_HEIGHT_RECALC 10 +#define SCFORMULAOPT_OPENCL_AUTOSELECT 11 +#define SCFORMULAOPT_OPENCL_DEVICE 12 +#define SCFORMULAOPT_OPENCL_SUBSET_ONLY 13 +#define SCFORMULAOPT_OPENCL_MIN_SIZE 14 +#define SCFORMULAOPT_OPENCL_SUBSET_OPS 15 Sequence<OUString> ScFormulaCfg::GetPropertyNames() { @@ -177,6 +180,7 @@ Sequence<OUString> ScFormulaCfg::GetPropertyNames() "Syntax/EmptyStringAsZero", // SCFORMULAOPT_EMPTY_OUSTRING_AS_ZERO "Load/OOXMLRecalcMode", // SCFORMULAOPT_OOXML_RECALC "Load/ODFRecalcMode", // SCFORMULAOPT_ODF_RECALC + "Load/RecalcOptimalRowHeightMode", // SCFORMULAOPT_ROW_HEIGHT_RECALC "Calculation/OpenCLAutoSelect", // SCFORMULAOPT_OPENCL_AUTOSELECT "Calculation/OpenCLDevice", // SCFORMULAOPT_OPENCL_DEVICE "Calculation/OpenCLSubsetOnly", // SCFORMULAOPT_OPENCL_SUBSET_ONLY @@ -198,6 +202,7 @@ ScFormulaCfg::PropsToIds ScFormulaCfg::GetPropNamesToId() SCFORMULAOPT_EMPTY_OUSTRING_AS_ZERO, SCFORMULAOPT_OOXML_RECALC, SCFORMULAOPT_ODF_RECALC, + SCFORMULAOPT_ROW_HEIGHT_RECALC, SCFORMULAOPT_OPENCL_AUTOSELECT, SCFORMULAOPT_OPENCL_DEVICE, SCFORMULAOPT_OPENCL_SUBSET_ONLY, @@ -419,6 +424,30 @@ void ScFormulaCfg::UpdateFromProperties( const Sequence<OUString>& aNames ) SetODFRecalcOptions(eOpt); } break; + case SCFORMULAOPT_ROW_HEIGHT_RECALC: + { + ScRecalcOptions eOpt = RECALC_ASK; + if (pValues[nProp] >>= nIntVal) + { + switch (nIntVal) + { + case 0: + eOpt = RECALC_ALWAYS; + break; + case 1: + eOpt = RECALC_NEVER; + break; + case 2: + eOpt = RECALC_ASK; + break; + default: + SAL_WARN("sc", "unknown optimal row height recalc option!"); + } + } + + SetReCalcOptiRowHeights(eOpt); + } + break; case SCFORMULAOPT_OPENCL_AUTOSELECT: { bool bVal = GetCalcConfig().mbOpenCLAutoSelect; @@ -595,6 +624,27 @@ void ScFormulaCfg::ImplCommit() pValues[nProp] <<= nVal; } break; + case SCFORMULAOPT_ROW_HEIGHT_RECALC: + { + sal_Int32 nVal = 2; + switch (GetReCalcOptiRowHeights()) + { + case RECALC_ALWAYS: + nVal = 0; + break; + case RECALC_NEVER: + nVal = 1; + break; + case RECALC_ASK: + nVal = 2; + break; + default: + SAL_WARN("sc", "unknown optimal row height recalc option!"); + } + + pValues[nProp] <<= nVal; + } + break; case SCFORMULAOPT_OPENCL_AUTOSELECT: { bool bVal = GetCalcConfig().mbOpenCLAutoSelect; diff --git a/sc/source/filter/oox/workbookhelper.cxx b/sc/source/filter/oox/workbookhelper.cxx index 45105946e40a..e9bf85d9e0b9 100644 --- a/sc/source/filter/oox/workbookhelper.cxx +++ b/sc/source/filter/oox/workbookhelper.cxx @@ -639,7 +639,9 @@ void WorkbookGlobals::finalize() mpDoc->EnableExecuteLink(true); // #i79826# enable updating automatic row height after loading the document mpDoc->UnlockAdjustHeight(); - mpDocShell->UpdateAllRowHeights(/*bOnlyUsedRows=*/true); + // check settings (potentially asking the user if optimal row height should be run now) + if (mpDocShell->GetRecalcRowHeightsMode()) // default is to always update + mpDocShell->UpdateAllRowHeights(/*bOnlyUsedRows=*/true); // #i76026# enable Undo after loading the document mpDoc->EnableUndo(true); diff --git a/sc/source/filter/xml/xmlimprt.cxx b/sc/source/filter/xml/xmlimprt.cxx index 60fa7ba71741..5289be445ffa 100644 --- a/sc/source/filter/xml/xmlimprt.cxx +++ b/sc/source/filter/xml/xmlimprt.cxx @@ -1420,7 +1420,8 @@ void SAL_CALL ScXMLImport::endDocument() } // There are rows with optimal height which need to be updated - if (pDoc && !maRecalcRowRanges.empty()) + if (pDoc && !maRecalcRowRanges.empty() && pDoc->GetDocumentShell() + && pDoc->GetDocumentShell()->GetRecalcRowHeightsMode()) { bool bLockHeight = pDoc->IsAdjustHeightLocked(); if (bLockHeight) diff --git a/sc/source/ui/docshell/docsh.cxx b/sc/source/ui/docshell/docsh.cxx index 71f72090d2a4..2c11b26d22b2 100644 --- a/sc/source/ui/docshell/docsh.cxx +++ b/sc/source/ui/docshell/docsh.cxx @@ -504,6 +504,62 @@ public: } +bool ScDocShell::GetRecalcRowHeightsMode() +{ + const ScRecalcOptions nRecalcMode = static_cast<ScRecalcOptions>( + officecfg::Office::Calc::Formula::Load::RecalcOptimalRowHeightMode::get()); + + bool bHardRecalc = false; + switch (nRecalcMode) + { + case RECALC_ASK: + { + if (m_pDocument->IsUserInteractionEnabled()) + { + // Ask if the user wants to perform full re-calculation. + MessageWithCheck aQueryBox(ScDocShell::GetActiveDialogParent(), + "modules/scalc/ui/recalcquerydialog.ui", + "RecalcQueryDialog"); + aQueryBox.set_primary_text(ScResId(STR_QUERY_OPT_ROW_HEIGHT_RECALC_ONLOAD)); + aQueryBox.set_default_response(RET_YES); + + if (officecfg::Office::Calc::Formula::Load::RecalcOptimalRowHeightMode::isReadOnly()) + aQueryBox.hide_ask(); + + bHardRecalc = aQueryBox.run() == RET_YES; + + if (aQueryBox.get_active()) + { + // Always perform selected action in the future. + std::shared_ptr<comphelper::ConfigurationChanges> batch( + comphelper::ConfigurationChanges::create()); + officecfg::Office::Calc::Formula::Load::RecalcOptimalRowHeightMode::set( + bHardRecalc ? static_cast<sal_Int32>(RECALC_ALWAYS) + : static_cast<sal_Int32>(RECALC_NEVER), + batch); + + ScFormulaOptions aOpt = SC_MOD()->GetFormulaOptions(); + aOpt.SetReCalcOptiRowHeights(bHardRecalc ? RECALC_ALWAYS : RECALC_NEVER); + SC_MOD()->SetFormulaOptions(aOpt); + + batch->commit(); + } + } + } + break; + case RECALC_ALWAYS: + bHardRecalc = true; + break; + case RECALC_NEVER: + bHardRecalc = false; + break; + default: + SAL_WARN("sc", "unknown optimal row height recalc option!"); + } + + return bHardRecalc; +} + bool ScDocShell::LoadXML( SfxMedium* pLoadMedium, const css::uno::Reference< css::embed::XStorage >& xStor ) { LoadMediumGuard aLoadGuard(m_pDocument.get()); diff --git a/sc/source/ui/inc/docsh.hxx b/sc/source/ui/inc/docsh.hxx index a146ea0723e7..e3ee48a43ea8 100644 --- a/sc/source/ui/inc/docsh.hxx +++ b/sc/source/ui/inc/docsh.hxx @@ -266,6 +266,8 @@ public: void ErrorMessage(TranslateId pGlobStrId); bool IsEditable() const; + /// check config if on file-open optimal row heights should run, or if the user should be asked + bool GetRecalcRowHeightsMode(); bool AdjustRowHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab ); void UpdateAllRowHeights( const ScMarkData* pTabMark = nullptr ); void UpdateAllRowHeights(const bool bOnlyUsedRows); diff --git a/sc/source/ui/inc/tpformula.hxx b/sc/source/ui/inc/tpformula.hxx index 14a72b751183..1172a323d948 100644 --- a/sc/source/ui/inc/tpformula.hxx +++ b/sc/source/ui/inc/tpformula.hxx @@ -82,6 +82,7 @@ private: std::unique_ptr<weld::ComboBox> mxLbOOXMLRecalcOptions; std::unique_ptr<weld::ComboBox> mxLbODFRecalcOptions; + std::unique_ptr<weld::ComboBox> mxLbRowHeightReCalcOptions; }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/optdlg/tpformula.cxx b/sc/source/ui/optdlg/tpformula.cxx index ab8cc38c122e..046cfc807e54 100644 --- a/sc/source/ui/optdlg/tpformula.cxx +++ b/sc/source/ui/optdlg/tpformula.cxx @@ -45,6 +45,7 @@ ScTpFormulaOptions::ScTpFormulaOptions(weld::Container* pPage, weld::DialogContr , mxBtnSepReset(m_xBuilder->weld_button("reset")) , mxLbOOXMLRecalcOptions(m_xBuilder->weld_combo_box("ooxmlrecalc")) , mxLbODFRecalcOptions(m_xBuilder->weld_combo_box("odfrecalc")) + , mxLbRowHeightReCalcOptions(m_xBuilder->weld_combo_box("rowheightrecalc")) { mxLbFormulaSyntax->append_text(ScResId(SCSTR_FORMULA_SYNTAX_CALC_A1)); mxLbFormulaSyntax->append_text(ScResId(SCSTR_FORMULA_SYNTAX_XL_A1)); @@ -306,6 +307,7 @@ bool ScTpFormulaOptions::FillItemSet(SfxItemSet* rCoreSet) OUString aSepArrayRow = mxEdSepArrayRow->get_text(); sal_Int16 nOOXMLRecalcMode = mxLbOOXMLRecalcOptions->get_active(); sal_Int16 nODFRecalcMode = mxLbODFRecalcOptions->get_active(); + sal_Int16 nReCalcOptRowHeights = mxLbRowHeightReCalcOptions->get_active(); if (mxBtnCustomCalcDefault->get_active()) { @@ -320,6 +322,7 @@ bool ScTpFormulaOptions::FillItemSet(SfxItemSet* rCoreSet) || mxEdSepArrayRow->get_saved_value() != aSepArrayRow || mxLbOOXMLRecalcOptions->get_saved_value() != mxLbOOXMLRecalcOptions->get_text(nOOXMLRecalcMode) || mxLbODFRecalcOptions->get_saved_value() != mxLbODFRecalcOptions->get_text(nODFRecalcMode) + || mxLbRowHeightReCalcOptions->get_saved_value() != mxLbRowHeightReCalcOptions->get_text(nReCalcOptRowHeights) || maSavedConfig != maCurrentConfig || maSavedDocOptions != maCurrentDocOptions ) { @@ -340,6 +343,7 @@ bool ScTpFormulaOptions::FillItemSet(SfxItemSet* rCoreSet) ScRecalcOptions eOOXMLRecalc = static_cast<ScRecalcOptions>(nOOXMLRecalcMode); ScRecalcOptions eODFRecalc = static_cast<ScRecalcOptions>(nODFRecalcMode); + ScRecalcOptions eReCalcOptRowHeights = static_cast<ScRecalcOptions>(nReCalcOptRowHeights); aOpt.SetFormulaSyntax(eGram); aOpt.SetUseEnglishFuncName(bEnglishFuncName); @@ -349,6 +353,7 @@ bool ScTpFormulaOptions::FillItemSet(SfxItemSet* rCoreSet) aOpt.SetCalcConfig(maCurrentConfig); aOpt.SetOOXMLRecalcOptions(eOOXMLRecalc); aOpt.SetODFRecalcOptions(eODFRecalc); + aOpt.SetReCalcOptiRowHeights(eReCalcOptRowHeights); aOpt.SetWriteCalcConfig( maCurrentDocOptions.IsWriteCalcConfig()); rCoreSet->Put( ScTpFormulaItem( std::move(aOpt) ) ); @@ -396,6 +401,13 @@ void ScTpFormulaOptions::Reset(const SfxItemSet* rCoreSet) mxLbODFRecalcOptions->save_value(); mxLbODFRecalcOptions->set_sensitive( !officecfg::Office::Calc::Formula::Load::ODFRecalcMode::isReadOnly() ); + // Recalc optimal row heights at load + ScRecalcOptions eReCalcOptRowHeights = aOpt.GetReCalcOptiRowHeights(); + mxLbRowHeightReCalcOptions->set_active(static_cast<sal_uInt16>(eReCalcOptRowHeights)); + mxLbRowHeightReCalcOptions->save_value(); + mxLbRowHeightReCalcOptions->set_sensitive( + !officecfg::Office::Calc::Formula::Load::RecalcOptimalRowHeightMode::isReadOnly() ); + // english function name. mxCbEnglishFuncName->set_active( aOpt.GetUseEnglishFuncName() ); mxCbEnglishFuncName->save_state(); diff --git a/sc/uiconfig/scalc/ui/optformula.ui b/sc/uiconfig/scalc/ui/optformula.ui index 68a2ad8166a9..87af5d850268 100644 --- a/sc/uiconfig/scalc/ui/optformula.ui +++ b/sc/uiconfig/scalc/ui/optformula.ui @@ -99,7 +99,7 @@ <property name="label_xalign">0</property> <property name="shadow_type">none</property> <child> - <!-- n-columns=1 n-rows=1 --> + <!-- n-columns=2 n-rows=3 --> <object class="GtkGrid" id="grid4"> <property name="visible">True</property> <property name="can_focus">False</property> @@ -167,6 +167,41 @@ <property name="top_attach">1</property> </packing> </child> + <child> + <object class="GtkLabel" id="label5"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="label" translatable="yes" context="optformula|label10">Optimal row height:</property> + <property name="use-underline">True</property> + <property name="mnemonic-widget">odfrecalc</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left-attach">0</property> + <property name="top-attach">2</property> + </packing> + </child> + <child> + <object class="GtkComboBoxText" id="rowheightrecalc"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="hexpand">True</property> + <items> + <item translatable="yes" context="optformula|odfrecalc">Always recalculate</item> + <item translatable="yes" context="optformula|odfrecalc">Never recalculate</item> + <item translatable="yes" context="optformula|odfrecalc">Prompt user</item> + </items> + <child internal-child="accessible"> + <object class="AtkObject" id="rowheightrecalc-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="optformula|extended_tip|rowheightrecalc">Define either we want to calculate the optimal row heights or we do not want at load time.</property> + </object> + </child> + </object> + <packing> + <property name="left-attach">1</property> + <property name="top-attach">2</property> + </packing> + </child> </object> </child> <child type="label">