sc/inc/dbdata.hxx                           |   13 +
 sc/source/core/data/table3.cxx              |    6 
 sc/source/core/tool/dbdata.cxx              |  261 ++++++++++++++++++++++++++--
 sc/source/filter/excel/xedbdata.cxx         |   35 +++
 sc/source/filter/oox/tablecolumnsbuffer.cxx |    4 
 sc/source/ui/view/cellsh2.cxx               |    9 
 sc/source/ui/view/gridwin.cxx               |    2 
 sc/source/ui/view/tableshell.cxx            |    5 
 8 files changed, 304 insertions(+), 31 deletions(-)

New commits:
commit 917801869c1f9efb9c8d947f55444584b3e7873f
Author:     Balazs Varga <[email protected]>
AuthorDate: Thu Oct 30 17:49:09 2025 +0100
Commit:     Andras Timar <[email protected]>
CommitDate: Mon Nov 17 19:03:41 2025 +0100

    Disable original SubTotal functionality if table style is applied
    
    on the Dbrange (same as MSO).
    
    Change-Id: I9ad8d3f31ea8e417e7c40e930659c0bdbc55d9f7
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/193226
    Tested-by: Balazs Varga <[email protected]>
    Reviewed-by: Balazs Varga <[email protected]>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/193683
    Tested-by: Andras Timar <[email protected]>
    Reviewed-by: Andras Timar <[email protected]>

diff --git a/sc/source/ui/view/cellsh2.cxx b/sc/source/ui/view/cellsh2.cxx
index 96edd44d5114..9ca07df51670 100644
--- a/sc/source/ui/view/cellsh2.cxx
+++ b/sc/source/ui/view/cellsh2.cxx
@@ -1193,6 +1193,15 @@ void ScCellShell::GetDBState( SfxItemSet& rSet )
                                 rSet.DisableItem(nWhich);
                             }
                         }
+                        else if (nWhich == SCITEM_SUBTDATA)
+                        {
+                            // Disable if table style is applied (same as MSO)
+                            ScDBData* pDBData = 
pTabViewShell->GetDBData(false, SC_DB_OLD);
+                            if (pDBData && pDBData->GetTableStyleInfo())
+                            {
+                                rSet.DisableItem(nWhich);
+                            }
+                        }
                     }
                 }
                 break;
commit e725c5b9327424fb927ed251d54b6913ae9d8568
Author:     Balazs Varga <[email protected]>
AuthorDate: Thu Oct 30 14:14:41 2025 +0100
Commit:     Andras Timar <[email protected]>
CommitDate: Mon Nov 17 19:03:27 2025 +0100

    Table Style improvements: ooxml export of Total Row
    
    attributes. XML_totalsRowLabel, XML_totalsRowFunction,
    XML_totalsRowFormula and XML_totalsRowShown.
    
    cherry-pick from: dbe65f04327924e0d3c7bcefab5bbfba07687033
    
    Change-Id: I2b7c356cf71abe940ddbe6672c8fdb52d2513f79
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/193206
    Reviewed-by: Balazs Varga <[email protected]>
    Tested-by: Balazs Varga <[email protected]>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/193682
    Tested-by: Andras Timar <[email protected]>
    Reviewed-by: Andras Timar <[email protected]>

diff --git a/sc/inc/dbdata.hxx b/sc/inc/dbdata.hxx
index 0676e6d8dde5..65ed43be7a5b 100644
--- a/sc/inc/dbdata.hxx
+++ b/sc/inc/dbdata.hxx
@@ -36,6 +36,7 @@ class ScDocument;
 struct ScSortParam;
 struct ScQueryParam;
 struct ScSubTotalParam;
+class ScTokenArray;
 
 class SC_DLLPUBLIC ScDatabaseSettingItem final : public SfxPoolItem
 {
@@ -276,10 +277,17 @@ public:
 
     SC_DLLPUBLIC void       GetSubTotalParam(ScSubTotalParam& rSubTotalParam) 
const;
     SC_DLLPUBLIC void       SetSubTotalParam(const ScSubTotalParam& 
rSubTotalParam);
-    SC_DLLPUBLIC void       ImportSubTotalParam(ScSubTotalParam& 
rSubTotalParam,
+
+    // Total row param handling for Table Styles
+    SC_DLLPUBLIC void       ImportTotalRowParam(ScSubTotalParam& 
rSubTotalParam,
                                                 const 
std::vector<TableColumnAttributes>& rAttributesVector,
                                                 
formula::FormulaGrammar::Grammar eGrammar) const;
-    SC_DLLPUBLIC void       CreateSubTotalParam(ScSubTotalParam& 
rSubTotalParam) const;
+    SC_DLLPUBLIC void       CreateTotalRowParam(ScSubTotalParam& 
rSubTotalParam) const;
+
+    SC_DLLPUBLIC std::vector<TableColumnAttributes>
+                            
GetTotalRowAttributes(formula::FormulaGrammar::Grammar eGrammar) const;
+
+    OUString    GetSimpleSubTotalFunction(const ScTokenArray* pTokens, SCCOL 
nCol, SCROW nHeaderRow) const;
 
     void        GetImportParam(ScImportParam& rImportParam) const;
     void        SetImportParam(const ScImportParam& rImportParam);
@@ -315,6 +323,7 @@ public:
     SC_DLLPUBLIC const ScTableStyleParam* GetTableStyleInfo() const;
 
     static ScSubTotalFunc GetSubTotalFuncFromString(std::u16string_view 
sFunction);
+    static OUString GetStringFromSubTotalFunc(ScSubTotalFunc eFunc);
 
 private:
 
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index be8931c3ab1e..c976be11bd33 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -2305,9 +2305,9 @@ bool ScTable::DoSubTotals( ScSubTotalParam& rParam )
 bool ScTable::DoSimpleSubTotals( ScSubTotalParam& rParam )
 {
     RowEntry aRowEntry;
-    aRowEntry.nGroupNo = 0;
-    aRowEntry.nSubStartRow = rParam.nRow1 + 
static_cast<SCROW>(rParam.bHasHeader); // Header
-    aRowEntry.nFuncStart = rParam.nRow1 + 
static_cast<SCROW>(rParam.bHasHeader); // Header
+    aRowEntry.nGroupNo = 0; // only one group can have
+    //aRowEntry.nSubStartRow = rParam.nRow1 + 
static_cast<SCROW>(rParam.bHasHeader); // Header
+    //aRowEntry.nFuncStart = rParam.nRow1 + 
static_cast<SCROW>(rParam.bHasHeader); // Header
     aRowEntry.nDestRow = rParam.nRow2 + 1;
     aRowEntry.nFuncEnd = rParam.nRow2;
 
diff --git a/sc/source/core/tool/dbdata.cxx b/sc/source/core/tool/dbdata.cxx
index 14d7226ef7c6..e620443fa771 100644
--- a/sc/source/core/tool/dbdata.cxx
+++ b/sc/source/core/tool/dbdata.cxx
@@ -26,6 +26,7 @@
 
 #include <dbdata.hxx>
 #include <compiler.hxx>
+#include <tokenarray.hxx>
 #include <globalnames.hxx>
 #include <refupdat.hxx>
 #include <document.hxx>
@@ -695,7 +696,7 @@ void ScDBData::SetSubTotalParam(const ScSubTotalParam& 
rSubTotalParam)
     mpSubTotal.reset(new ScSubTotalParam(rSubTotalParam));
 }
 
-void ScDBData::ImportSubTotalParam(ScSubTotalParam& rSubTotalParam,
+void ScDBData::ImportTotalRowParam(ScSubTotalParam& rSubTotalParam,
                                    const std::vector<TableColumnAttributes>& 
rAttributesVector,
                                    formula::FormulaGrammar::Grammar eGrammar) 
const
 {
@@ -772,7 +773,7 @@ void ScDBData::ImportSubTotalParam(ScSubTotalParam& 
rSubTotalParam,
     }
 }
 
-void ScDBData::CreateSubTotalParam(ScSubTotalParam& rSubTotalParam) const
+void ScDBData::CreateTotalRowParam(ScSubTotalParam& rSubTotalParam) const
 {
     rSubTotalParam.bDoSort = false;
     rSubTotalParam.bGroupedBy = false;
@@ -815,6 +816,209 @@ void ScDBData::CreateSubTotalParam(ScSubTotalParam& 
rSubTotalParam) const
     }
 }
 
+std::vector<TableColumnAttributes> 
ScDBData::GetTotalRowAttributes(formula::FormulaGrammar::Grammar eGrammar) const
+{
+    ScSubTotalParam rParam;
+    GetSubTotalParam(rParam);
+
+    const SCCOL nEntryCount = rParam.nCol2 - rParam.nCol1 + 1; // col count
+    std::vector<TableColumnAttributes> aAttributesVector(nEntryCount);
+    if (nEntryCount > 0)
+    {
+        if (HasTotals())
+        {
+            if (!mpContainer)
+                assert(!"ScDBData::GetTotalRowAttributes - how did we end up 
here without container?");
+            else
+            {
+                ScDocument& rDoc = mpContainer->GetDocument();
+                ScHorizontalCellIterator aIter(rDoc, nTable, rParam.nCol1, 
rParam.nRow2,
+                                               rParam.nCol2,
+                                               rParam.nRow2); // Total row only
+                ScRefCellValue* pCell;
+                SCCOL nCol = rParam.nCol1 - 1;
+                SCROW nRow;
+                while ((pCell = aIter.GetNext(nCol, nRow)) != nullptr)
+                {
+                    TableColumnAttributes aNameAttr;
+                    if (pCell->getType() != CELLTYPE_FORMULA)
+                    {
+                        OUString aStr = pCell->getString(&rDoc);
+                        if (!aStr.isEmpty())
+                            aNameAttr.maTotalsRowLabel = aStr;
+                    }
+                    else
+                    {
+                        if (ScFormulaCell* pFC = pCell->getFormula())
+                        {
+                            bool bSubTotal = pFC->IsSubTotal();
+                            ScTokenArray* pTokens = pFC->GetCode();
+                            if (bSubTotal && pTokens)
+                            {
+                                OUString aFunctype = 
GetSimpleSubTotalFunction(pTokens, nCol, rParam.nRow1);
+                                if (aFunctype != u"custom")
+                                    aNameAttr.maTotalsFunction = aFunctype;
+                                else
+                                    bSubTotal = false; // fallback to custom
+                            }
+
+                            if (!bSubTotal && pTokens)
+                            {
+                                ScAddress aPos(nCol, rParam.nRow2, nTable);
+                                ScCompiler aComp(rDoc, aPos, *pTokens, 
eGrammar);
+                                OUStringBuffer aBuf;
+                                aComp.CreateStringFromTokenArray(aBuf);
+                                OUString aFormula = aBuf.makeStringAndClear();
+                                aNameAttr.maTotalsFunction = "custom";
+                                aNameAttr.maCustomFunction = aFormula;
+                            }
+                        }
+                    }
+                    SCCOL nPos = nCol - rParam.nCol1;
+                    if (nPos < nEntryCount)
+                        aAttributesVector[nPos] = std::move(aNameAttr);
+                    else
+                        SAL_WARN("sc.core", "ScDBData::GetTotalRowAttributes - 
invalid attributes/columns");
+                }
+            }
+        }
+        else
+        {
+            const auto& group = rParam.aGroups[0];
+            if (group.nSubLabels > 0)
+            {
+                for (SCCOL nResult = 0; nResult < group.nSubLabels; ++nResult)
+                {
+                    SCCOL nPos = group.collabels(nResult) - rParam.nCol1;
+                    if (nPos < nEntryCount)
+                        aAttributesVector[nPos].maTotalsRowLabel = 
group.label(nResult);
+                    else
+                        SAL_WARN("sc.core", "ScDBData::GetTotalRowAttributes - 
invalid attributes/columns");
+                }
+            }
+
+            // insert the formulas
+            if (group.nCustFuncs > 0)
+            {
+                for (SCCOL nResult = 0; nResult < group.nCustFuncs; ++nResult)
+                {
+                    if (ScTokenArray* pTokens = group.custToken(nResult))
+                    {
+                        SCCOL nCol = group.colcust(nResult);
+                        bool bSubTotal = pTokens->HasOpCode(ocSubTotal);
+                        if (bSubTotal)
+                        {
+                            OUString aFunctype = 
GetSimpleSubTotalFunction(pTokens, nCol, rParam.nRow1);
+                            if (aFunctype != u"custom")
+                            {
+                                SCCOL nPos = nCol - rParam.nCol1;
+                                if (nPos < nEntryCount)
+                                    aAttributesVector[nPos].maTotalsFunction = 
aFunctype;
+                                else
+                                    SAL_WARN("sc.core", 
"ScDBData::GetTotalRowAttributes - invalid "
+                                                        "attributes/columns");
+                            }
+                            else
+                                bSubTotal = false; // fallback to custom
+                        }
+
+                        if (!bSubTotal)
+                        {
+                            if (!mpContainer)
+                                assert(!"ScDBData::GetTotalRowAttributes - how 
did we end up here without container?");
+                            else
+                            {
+                                ScDocument& rDoc = mpContainer->GetDocument();
+                                ScAddress aPos(nCol, rParam.nRow2 + 1, nTable);
+                                ScCompiler aComp(rDoc, aPos, *pTokens, 
eGrammar);
+                                OUStringBuffer aBuf;
+                                aComp.CreateStringFromTokenArray(aBuf);
+                                OUString aFormula = aBuf.makeStringAndClear();
+
+                                SCCOL nPos = nCol - rParam.nCol1;
+                                if (nPos < nEntryCount)
+                                {
+                                    aAttributesVector[nPos].maTotalsFunction = 
"custom";
+                                    aAttributesVector[nPos].maCustomFunction = 
aFormula;
+                                }
+                                else
+                                    SAL_WARN("sc.core", 
"ScDBData::GetTotalRowAttributes - invalid "
+                                                        "attributes/columns");
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return aAttributesVector;
+}
+
+OUString ScDBData::GetSimpleSubTotalFunction(const ScTokenArray* pTokens, 
SCCOL nCol, SCROW nHeaderRow) const
+{
+    std::vector<std::pair<OpCode, formula::StackVar>> expected
+        = { { ocSubTotal, formula::svByte },  { ocOpen, formula::svSep },
+            { ocPush, formula::svDouble },    { ocSep, formula::svSep },
+            { ocTableRef, formula::svIndex }, { ocTableRefOpen, formula::svSep 
},
+            { ocPush, formula::svSingleRef }, { ocTableRefClose, 
formula::svSep },
+            { ocClose, formula::svSep } };
+
+    size_t nIdx = 0;
+    ScSubTotalFunc eSubType = SUBTOTAL_FUNC_NONE;
+    formula::FormulaTokenArrayPlainIterator aIterResult(*pTokens);
+    for (formula::FormulaToken* t = aIterResult.NextNoSpaces(); t; t = 
aIterResult.NextNoSpaces())
+    {
+        // check for subtotal opcode
+        OpCode eOpCode = t->GetOpCode();
+        formula::StackVar eType = t->GetType();
+
+        if (nIdx < expected.size() && eOpCode == expected[nIdx].first
+            && eType == expected[nIdx].second)
+        {
+            if (nIdx == 2) // { ocPush, formula::svDouble }
+            {
+                sal_Int32 nFunc = static_cast<sal_Int32>(t->GetDouble());
+                if (nFunc > 100.)
+                    nFunc -= 100;
+
+                if (nFunc < 1 || nFunc > 11)
+                {
+                    return u"custom"_ustr;
+                }
+                else
+                    eSubType = static_cast<ScSubTotalFunc>(nFunc);
+            }
+            else if (nIdx == 4) // { ocTableRef, formula::svIndex }
+            {
+                sal_uInt16 nDbIndex = t->GetIndex();
+                if (GetIndex() != nDbIndex)
+                {
+                    return u"custom"_ustr;
+                }
+            }
+            else if (nIdx == 6) // { ocPush, formula::svSingleRef }
+            {
+                const ScSingleRefData* pRef = t->GetSingleRef();
+                if (!(pRef && pRef->Col() == nCol && pRef->Row() == 
nHeaderRow))
+                {
+                    return u"custom"_ustr;
+                }
+            }
+            else
+            { /*Nothing to do*/
+            }
+
+            ++nIdx;
+        }
+        else
+        {
+            return u"custom"_ustr;
+        }
+    }
+
+    return GetStringFromSubTotalFunc(eSubType);
+}
+
 void ScDBData::GetImportParam(ScImportParam& rImportParam) const
 {
     rImportParam = *mpImportParam;
@@ -1347,29 +1551,58 @@ ScSubTotalFunc 
ScDBData::GetSubTotalFuncFromString(std::u16string_view sFunction
 {
     if (sFunction == u"sum")
         return SUBTOTAL_FUNC_SUM;
-    if (sFunction == u"countNums")
+    else if (sFunction == u"countNums")
         return SUBTOTAL_FUNC_CNT;
-    if (sFunction == u"count")
+    else if (sFunction == u"count")
         return SUBTOTAL_FUNC_CNT2;
-    /*if (sFunction)
+    /*else if (sFunction)
         return SUBTOTAL_FUNC_PROD;*/
-    if (sFunction == u"average")
+    else if (sFunction == u"average")
         return SUBTOTAL_FUNC_AVE;
-    /*if (sFunction)
+    /*else if (sFunction)
         return SUBTOTAL_FUNC_MED;*/
-    if (sFunction == u"max")
+    else if (sFunction == u"max")
         return SUBTOTAL_FUNC_MAX;
-    if (sFunction == u"min")
+    else if (sFunction == u"min")
         return SUBTOTAL_FUNC_MIN;
-    if (sFunction == u"stdDev")
+    else if (sFunction == u"stdDev")
         return SUBTOTAL_FUNC_STD;
-    /*if (sFunction)
+    /*else if (sFunction)
         return SUBTOTAL_FUNC_STDP;*/
-    if (sFunction == u"var")
+    else if (sFunction == u"var")
         return SUBTOTAL_FUNC_VAR;
-    /*if (sFunction)
+    /*else if (sFunction)
         return SUBTOTAL_FUNC_VARP;*/
-    return SUBTOTAL_FUNC_NONE;
+    else
+        return SUBTOTAL_FUNC_NONE;
+}
+
+OUString ScDBData::GetStringFromSubTotalFunc(ScSubTotalFunc eFunc)
+{
+    if (eFunc == SUBTOTAL_FUNC_SUM)
+        return u"sum"_ustr;
+    else if (eFunc == SUBTOTAL_FUNC_CNT)
+        return u"countNums"_ustr;
+    else if (eFunc == SUBTOTAL_FUNC_CNT2)
+        return u"count"_ustr;
+    else if (eFunc == SUBTOTAL_FUNC_PROD)
+        return u"custom"_ustr; // ooxml not support in Total row
+    else if (eFunc == SUBTOTAL_FUNC_AVE)
+        return u"average"_ustr;
+    else if (eFunc == SUBTOTAL_FUNC_MED)
+        return u"custom"_ustr; // ooxml not support in Total row
+    else if (eFunc == SUBTOTAL_FUNC_MAX)
+        return u"max"_ustr;
+    else if (eFunc == SUBTOTAL_FUNC_MIN)
+        return u"min"_ustr;
+    else if (eFunc == SUBTOTAL_FUNC_STD)
+        return u"stdDev"_ustr;
+    else if (eFunc == SUBTOTAL_FUNC_STDP)
+        return u"custom"_ustr; // ooxml not support in Total row
+    else if (eFunc == SUBTOTAL_FUNC_VAR)
+        return u"var"_ustr;
+    else
+        return u"none"_ustr;
 }
 
 namespace {
diff --git a/sc/source/filter/excel/xedbdata.cxx 
b/sc/source/filter/excel/xedbdata.cxx
index 1283082fe13c..2440213419b4 100644
--- a/sc/source/filter/excel/xedbdata.cxx
+++ b/sc/source/filter/excel/xedbdata.cxx
@@ -189,6 +189,18 @@ void XclExpTables::SaveTableXml( XclExpXmlStream& rStrm, 
const Entry& rEntry )
     if (hasTableTypeAttr)
         tableType = rData.GetTableType();
 
+    const std::vector<TableColumnAttributes> aTotalValues
+        = rData.GetTotalRowAttributes(formula::FormulaGrammar::GRAM_OOXML);
+
+    // if the Total row have ever been showed it will be true
+    bool hasAnySetValue = std::any_of(aTotalValues.begin(), aTotalValues.end(),
+                                      [](const TableColumnAttributes& attr)
+                                      {
+                                          return 
attr.maTotalsRowLabel.has_value()
+                                                 || 
attr.maTotalsFunction.has_value()
+                                                 || 
attr.maCustomFunction.has_value();
+                                      });
+
     pTableStrm->startElement( XML_table,
         XML_xmlns, rStrm.getNamespaceURL(OOX_NS(xls)).toUtf8(),
         XML_id, OString::number( rEntry.mnTableId),
@@ -198,7 +210,7 @@ void XclExpTables::SaveTableXml( XclExpXmlStream& rStrm, 
const Entry& rEntry )
         XML_tableType, tableType,
         XML_headerRowCount, ToPsz10(rData.HasHeader()),
         XML_totalsRowCount, ToPsz10(rData.HasTotals()),
-        XML_totalsRowShown, ToPsz10(rData.HasTotals())  // we don't support 
that but if there are totals they are shown
+        XML_totalsRowShown, ToPsz10(hasAnySetValue)
         // OOXTODO: XML_comment, ...,
         // OOXTODO: XML_connectionId, ...,
         // OOXTODO: XML_dataCellStyle, ...,
@@ -233,6 +245,10 @@ void XclExpTables::SaveTableXml( XclExpXmlStream& rStrm, 
const Entry& rEntry )
     const std::vector< TableColumnModel >& rTableColumnModel = 
rData.GetTableColumnModel();
     if (!rColNames.empty())
     {
+        // rColNames and aTotalValues size should always be equal
+        assert((rColNames.size() == aTotalValues.size()) &&
+               "XclExpTables::SaveTableXml - mismatch between column names and 
total values");
+
         pTableStrm->startElement(XML_tableColumns,
                 XML_count, OString::number(aRange.aEnd.Col() - 
aRange.aStart.Col() + 1));
 
@@ -242,8 +258,6 @@ void XclExpTables::SaveTableXml( XclExpXmlStream& rStrm, 
const Entry& rEntry )
             // which case we'd need start/endElement XML_tableColumn for such
             // column.
 
-            // OOXTODO: write <totalsRowFormula> once we support it.
-
             std::optional<OUString> uniqueName = std::nullopt;
 
             // uniqueName should only be used when this table's tableType is 
queryTable or xml.
@@ -259,9 +273,9 @@ void XclExpTables::SaveTableXml( XclExpXmlStream& rStrm, 
const Entry& rEntry )
             pTableStrm->startElement( XML_tableColumn,
                     XML_id, OString::number(i+1),
                     XML_uniqueName, uniqueName,
-                    XML_name, rColNames[i].toUtf8()
-                    // XML_totalsRowLabel, (i < rColAttributes.size() ? 
rColAttributes[i].maTotalsRowLabel : std::nullopt),
-                    // XML_totalsRowFunction, (i < rColAttributes.size() ? 
rColAttributes[i].maTotalsFunction : std::nullopt)
+                    XML_name, rColNames[i].toUtf8(),
+                    XML_totalsRowLabel, (i < aTotalValues.size() ? 
aTotalValues[i].maTotalsRowLabel : std::nullopt),
+                    XML_totalsRowFunction, (i < aTotalValues.size() ? 
aTotalValues[i].maTotalsFunction : std::nullopt)
                     // OOXTODO: XML_dataCellStyle, ...,
                     // OOXTODO: XML_dataDxfId, ...,
                     // OOXTODO: XML_headerRowCellStyle, ...,
@@ -288,6 +302,15 @@ void XclExpTables::SaveTableXml( XclExpXmlStream& rStrm, 
const Entry& rEntry )
                 pTableStrm->singleElement(XML_xmlColumnPr, 
pXmlColumnPrAttrList);
             }
 
+            if (i < aTotalValues.size() && 
aTotalValues[i].maTotalsFunction.has_value()
+                && aTotalValues[i].maTotalsFunction.value() == u"custom")
+            {
+                // write custom functions
+                pTableStrm->startElement(XML_totalsRowFormula);
+                
pTableStrm->writeEscaped(aTotalValues[i].maCustomFunction.value());
+                pTableStrm->endElement(XML_totalsRowFormula);
+            }
+
             // put </tableColumn>
             pTableStrm->endElement(XML_tableColumn);
         }
diff --git a/sc/source/filter/oox/tablecolumnsbuffer.cxx 
b/sc/source/filter/oox/tablecolumnsbuffer.cxx
index 0d0b6e0a75be..aba02524ceaf 100644
--- a/sc/source/filter/oox/tablecolumnsbuffer.cxx
+++ b/sc/source/filter/oox/tablecolumnsbuffer.cxx
@@ -161,12 +161,12 @@ bool TableColumns::finalizeImport( ScDBData* pDBData )
         pDBData->SetTableColumnNames( std::move(aNames) );
 
         // Import subtotal parameters for columns
-        if (hasAnySetValue && !pDBData->HasTotals())
+        if (hasAnySetValue)
         {
             ScSubTotalParam aSubTotalParam;
             pDBData->GetSubTotalParam(aSubTotalParam);
             aSubTotalParam.bHasHeader = pDBData->HasHeader();
-            pDBData->ImportSubTotalParam(aSubTotalParam, aAttributes,
+            pDBData->ImportTotalRowParam(aSubTotalParam, aAttributes,
                                          formula::FormulaGrammar::GRAM_OOXML);
             pDBData->SetSubTotalParam(aSubTotalParam);
         }
diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx
index e71c3e4b3f83..acd21fb6d928 100644
--- a/sc/source/ui/view/gridwin.cxx
+++ b/sc/source/ui/view/gridwin.cxx
@@ -2502,7 +2502,7 @@ void ScGridWindow::MouseButtonUp( const MouseEvent& rMEvt 
)
                 pDBData->GetSubTotalParam(aSubTotalParam);
                 aSubTotalParam.bHasHeader = aNewDBData.HasHeader();
                 // store current subtotal settings
-                pDBData->CreateSubTotalParam(aSubTotalParam);
+                pDBData->CreateTotalRowParam(aSubTotalParam);
                 aNewDBData.SetSubTotalParam(aSubTotalParam);
                 // add/replace total row
                 aSubTotalParam.bRemoveOnly = false;
diff --git a/sc/source/ui/view/tableshell.cxx b/sc/source/ui/view/tableshell.cxx
index bb35a0d98ba7..6436073b9b10 100644
--- a/sc/source/ui/view/tableshell.cxx
+++ b/sc/source/ui/view/tableshell.cxx
@@ -102,10 +102,9 @@ void ScTableShell::ExecuteDatabaseSettings(SfxRequest& 
rReq)
 
                         if (!aNewDBData.HasTotals())
                         {
-                            // store current subtotal settings
-                            pDBData->CreateSubTotalParam(aSubTotalParam);
+                            // store current subtotal settings before removing 
total row
+                            pDBData->CreateTotalRowParam(aSubTotalParam);
                             aNewDBData.SetSubTotalParam(aSubTotalParam);
-                            // remove total row
                             aSubTotalParam.bRemoveOnly = true;
                             aSubTotalParam.bReplace = true;
                             aFunc.DoTableSubTotals(aNewDBData.GetTab(), 
aNewDBData, aSubTotalParam,

Reply via email to