sc/Library_scfilt.mk                             |    2 
 sc/inc/dpoutput.hxx                              |    8 +
 sc/inc/dpsave.hxx                                |    6 
 sc/inc/pivot/PivotTableFormats.hxx               |   48 +++++++
 sc/source/core/data/dpobject.cxx                 |    8 -
 sc/source/core/data/dpoutput.cxx                 |   47 +++++++
 sc/source/core/data/dpsave.cxx                   |   18 ++
 sc/source/filter/inc/PivotTableFormat.hxx        |  106 ++++++++++++++++
 sc/source/filter/inc/PivotTableFormatContext.hxx |   49 +++++++
 sc/source/filter/inc/pivottablebuffer.hxx        |    4 
 sc/source/filter/oox/PivotTableFormat.cxx        |  148 +++++++++++++++++++++++
 sc/source/filter/oox/PivotTableFormatContext.cxx |   92 ++++++++++++++
 sc/source/filter/oox/pivottablebuffer.cxx        |   12 +
 sc/source/filter/oox/pivottablefragment.cxx      |   19 ++
 14 files changed, 559 insertions(+), 8 deletions(-)

New commits:
commit af5bb01b9430b76ae8042b5ce6ebda65798bbb18
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Tue Mar 12 21:16:20 2024 +0900
Commit:     Tomaž Vajngerl <qui...@gmail.com>
CommitDate: Thu Apr 11 17:13:20 2024 +0200

    pivot: forward pivot table format data into the pivot table model
    
    The purpuse of this is to lay out the foundation for the support
    of pivot table formatting. This adds the code to forward the
    formatting information from the OOXML import into the pivot table
    model and uses it in a use case to set the row and column labels
    in the pivot table output (DPOutput). In the follow up commits the
    support will be extended to support more use cases with tests.
    
    Change-Id: Idf23884b32167bdbad69bc67358ccf7f14566db6
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164710
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>

diff --git a/sc/inc/dpoutput.hxx b/sc/inc/dpoutput.hxx
index 9c9c068c603e..a1087d182bab 100644
--- a/sc/inc/dpoutput.hxx
+++ b/sc/inc/dpoutput.hxx
@@ -28,6 +28,7 @@
 #include "address.hxx"
 
 #include "dptypes.hxx"
+#include "pivot/PivotTableFormats.hxx"
 
 #include <memory>
 #include <vector>
@@ -64,6 +65,8 @@ private:
     sal_uInt32 mnSingleNumberFormat;
     size_t mnRowDims; // Including empty ones.
 
+    std::unique_ptr<sc::PivotTableFormats> mpFormats;
+
     // Output geometry related parameters
     sal_Int32 mnColCount;
     sal_Int32 mnRowCount;
@@ -136,6 +139,11 @@ public:
     void            SetHeaderLayout(bool bUseGrid);
     bool            GetHeaderLayout() const { return mbHeaderLayout;}
 
+    void setFormats(sc::PivotTableFormats const& rPivotTableFormats)
+    {
+        mpFormats.reset(new sc::PivotTableFormats(rPivotTableFormats));
+    }
+
     static void GetDataDimensionNames(
         OUString& rSourceName, OUString& rGivenName,
         const css::uno::Reference< css::uno::XInterface>& xDim );
diff --git a/sc/inc/dpsave.hxx b/sc/inc/dpsave.hxx
index a54da59d57d8..ad1e393dc879 100644
--- a/sc/inc/dpsave.hxx
+++ b/sc/inc/dpsave.hxx
@@ -45,6 +45,7 @@ namespace com::sun::star::sheet {
 class ScDPDimensionSaveData;
 class ScDPTableData;
 enum class ScGeneralFunction;
+namespace sc { class PivotTableFormats; }
 
 // classes to save Data Pilot settings
 
@@ -253,6 +254,7 @@ private:
      *  created. */
     bool mbDimensionMembersBuilt;
 
+    std::unique_ptr<sc::PivotTableFormats> mpFormats;
     std::optional<OUString> mpGrandTotalName;
     mutable std::unique_ptr<DimOrderType> mpDimOrder; // dimension order for 
row and column dimensions, to traverse result tree.
 
@@ -265,6 +267,10 @@ public:
 
     bool operator== ( const ScDPSaveData& r ) const;
 
+    SC_DLLPUBLIC bool hasFormats();
+    SC_DLLPUBLIC sc::PivotTableFormats const& getFormats();
+    SC_DLLPUBLIC void setFormats(sc::PivotTableFormats const& 
rPivotTableFormats);
+
     SC_DLLPUBLIC void SetGrandTotalName(const OUString& rName);
     SC_DLLPUBLIC const std::optional<OUString> & GetGrandTotalName() const;
 
diff --git a/sc/inc/pivot/PivotTableFormats.hxx 
b/sc/inc/pivot/PivotTableFormats.hxx
new file mode 100644
index 000000000000..09f181e7e178
--- /dev/null
+++ b/sc/inc/pivot/PivotTableFormats.hxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <memory>
+#include <vector>
+#include <rtl/ustring.hxx>
+
+namespace sc
+{
+struct PivotTableFormat
+{
+    sal_Int32 nField;
+    sal_Int32 nDataIndex;
+    OUString aStyleName;
+
+    PivotTableFormat(sal_Int32 _nField, sal_Int32 _nDataIndex, OUString 
_aStyleName)
+        : nField(_nField)
+        , nDataIndex(_nDataIndex)
+        , aStyleName(_aStyleName)
+    {
+    }
+};
+
+class PivotTableFormats
+{
+    std::vector<PivotTableFormat> maFormats;
+
+public:
+    void add(sal_Int32 nField, sal_Int32 nDataIndex, OUString const& rStyle)
+    {
+        maFormats.emplace_back(nField, nDataIndex, rStyle);
+    }
+
+    size_t size() { return maFormats.size(); }
+
+    std::vector<PivotTableFormat> const& getVector() { return maFormats; }
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx
index 63b7021de95c..3f98a5fcc40c 100644
--- a/sc/source/core/data/dpobject.cxx
+++ b/sc/source/core/data/dpobject.cxx
@@ -526,8 +526,12 @@ void ScDPObject::CreateOutput()
         return;
 
     bool bFilterButton = IsSheetData() && mpSaveData && 
mpSaveData->GetFilterButton();
-    mpOutput.reset( new ScDPOutput(mpDocument, mxSource, maOutputRange.aStart, 
bFilterButton, mpSaveData ? mpSaveData->GetExpandCollapse() : false ) );
-    mpOutput->SetHeaderLayout ( mbHeaderLayout );
+    bool bExpandCollapse = mpSaveData ? mpSaveData->GetExpandCollapse() : 
false;
+
+    mpOutput.reset(new ScDPOutput(mpDocument, mxSource, maOutputRange.aStart, 
bFilterButton, bExpandCollapse));
+    mpOutput->SetHeaderLayout(mbHeaderLayout);
+    if (mpSaveData->hasFormats())
+        mpOutput->setFormats(mpSaveData->getFormats());
 
     sal_Int32 nOldRows = mnHeaderRows;
     mnHeaderRows = mpOutput->GetHeaderRows();
diff --git a/sc/source/core/data/dpoutput.cxx b/sc/source/core/data/dpoutput.cxx
index c269e00a3438..d88a320aeac0 100644
--- a/sc/source/core/data/dpoutput.cxx
+++ b/sc/source/core/data/dpoutput.cxx
@@ -763,6 +763,21 @@ void ScDPOutput::DataCell( SCCOL nCol, SCROW nRow, SCTAB 
nTab, const sheet::Data
     //  SubTotal formatting is controlled by headers
 }
 
+namespace
+{
+void lclApplyStyle(ScDocument* pDoc, SCTAB nTab,
+                      SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
+                      OUString const& rStyleName)
+{
+    ScStyleSheetPool* pStlPool = pDoc->GetStyleSheetPool();
+    ScStyleSheet* pStyle = 
static_cast<ScStyleSheet*>(pStlPool->Find(rStyleName, SfxStyleFamily::Para));
+    if (pStyle)
+    {
+        pDoc->ApplyStyleAreaTab(nCol1, nRow1, nCol2, nRow2, nTab, *pStyle);
+    }
+}
+}
+
 void ScDPOutput::HeaderCell( SCCOL nCol, SCROW nRow, SCTAB nTab,
                              const sheet::MemberResult& rData, bool 
bColHeader, tools::Long nLevel )
 {
@@ -1060,12 +1075,16 @@ void ScDPOutput::Output()
             MultiFieldCell(nHdrCol, mnTabStartRow, nTab, false /* bRowField 
*/);
 
         SCROW nRowPos = mnMemberStartRow + static_cast<SCROW>(nField);         
       //TODO: check for overflow
+        tools::Long nDimension = mpColFields[nField].mnDim;
         const uno::Sequence<sheet::MemberResult> rSequence = 
mpColFields[nField].maResult;
         const sheet::MemberResult* pArray = rSequence.getConstArray();
         tools::Long nThisColCount = rSequence.getLength();
         OSL_ENSURE(nThisColCount == mnColCount, "count mismatch");     //TODO: 
???
+        tools::Long nColumnIndex = -1;
         for (tools::Long nCol=0; nCol<nThisColCount; nCol++)
         {
+            if (!(pArray[nCol].Flags & sheet::MemberResultFlags::CONTINUE))
+                nColumnIndex++;
             SCCOL nColPos = mnDataStartCol + static_cast<SCCOL>(nCol);         
       //TODO: check for overflow
             HeaderCell( nColPos, nRowPos, nTab, pArray[nCol], true, nField );
             if ( ( pArray[nCol].Flags & sheet::MemberResultFlags::HASMEMBER ) 
&&
@@ -1094,6 +1113,18 @@ void ScDPOutput::Output()
             else if (  pArray[nCol].Flags & sheet::MemberResultFlags::SUBTOTAL 
)
                 outputimp.AddCol( nColPos );
 
+            // Apply format
+            if (mpFormats)
+            {
+                for (auto& aFormat : mpFormats->getVector())
+                {
+                    if (aFormat.nField == nDimension && aFormat.nDataIndex == 
nColumnIndex)
+                    {
+                        lclApplyStyle(mpDocument, nTab, nColPos, nRowPos, 
nColPos, mnDataStartRow - 1, aFormat.aStyleName);
+                    }
+                }
+            }
+
             // Apply the same number format as in data source.
             mpDocument->ApplyAttr(nColPos, nRowPos, nTab, 
SfxUInt32Item(ATTR_VALUE_FORMAT, mpColFields[nField].mnSrcNumFmt));
         }
@@ -1118,12 +1149,16 @@ void ScDPOutput::Output()
             MultiFieldCell(nHdrCol, nHdrRow, nTab, true /* bRowField */);
 
         SCCOL nColPos = mnMemberStartCol + 
static_cast<SCCOL>(nFieldColOffset);          //TODO: check for overflow
+        tools::Long nDimension = mpRowFields[nField].mnDim;
         const uno::Sequence<sheet::MemberResult> rSequence = 
mpRowFields[nField].maResult;
         const sheet::MemberResult* pArray = rSequence.getConstArray();
         sal_Int32 nThisRowCount = rSequence.getLength();
         OSL_ENSURE(nThisRowCount == mnRowCount, "count mismatch");     //TODO: 
???
+        tools::Long nRowIndex = -1;
         for (sal_Int32 nRow=0; nRow<nThisRowCount; nRow++)
         {
+            if (!(pArray[nRow].Flags & sheet::MemberResultFlags::CONTINUE))
+                nRowIndex++;
             const sheet::MemberResult& rData = pArray[nRow];
             const bool bHasMember = (rData.Flags & 
sheet::MemberResultFlags::HASMEMBER);
             const bool bSubtotal = (rData.Flags & 
sheet::MemberResultFlags::SUBTOTAL);
@@ -1174,6 +1209,18 @@ void ScDPOutput::Output()
             else if ( bSubtotal )
                 outputimp.AddRow( nRowPos );
 
+            // Apply format
+            if (mpFormats)
+            {
+                for (auto& aFormat : mpFormats->getVector())
+                {
+                    if (aFormat.nField == nDimension && aFormat.nDataIndex == 
nRowIndex)
+                    {
+                        lclApplyStyle(mpDocument, nTab, nColPos, nRowPos, 
mnDataStartCol - 1, nRowPos, aFormat.aStyleName);
+                    }
+                }
+            }
+
             // Apply the same number format as in data source.
             mpDocument->ApplyAttr(nColPos, nRowPos, nTab, 
SfxUInt32Item(ATTR_VALUE_FORMAT, mpRowFields[nField].mnSrcNumFmt));
         }
diff --git a/sc/source/core/data/dpsave.cxx b/sc/source/core/data/dpsave.cxx
index a872a6385475..ed888eebd737 100644
--- a/sc/source/core/data/dpsave.cxx
+++ b/sc/source/core/data/dpsave.cxx
@@ -25,6 +25,7 @@
 #include <dputil.hxx>
 #include <generalfunction.hxx>
 #include <dptabdat.hxx>
+#include <pivot/PivotTableFormats.hxx>
 
 #include <sal/types.h>
 #include <sal/log.hxx>
@@ -712,6 +713,8 @@ ScDPSaveData::ScDPSaveData(const ScDPSaveData& rOther)
 {
     if (rOther.mpDimensionData)
         mpDimensionData.reset(new 
ScDPDimensionSaveData(*rOther.mpDimensionData));
+    if (rOther.mpFormats)
+        mpFormats.reset(new sc::PivotTableFormats(*rOther.mpFormats));
 
     for (auto const& rOtherSaveDimension : rOther.m_DimList)
     {
@@ -764,6 +767,21 @@ ScDPSaveData::~ScDPSaveData()
 {
 }
 
+void ScDPSaveData::setFormats(sc::PivotTableFormats const& rPivotTableFormats)
+{
+    mpFormats.reset(new sc::PivotTableFormats(rPivotTableFormats));
+}
+
+bool ScDPSaveData::hasFormats()
+{
+    return bool(mpFormats);
+}
+
+sc::PivotTableFormats const& ScDPSaveData::getFormats()
+{
+    return *mpFormats;
+}
+
 void ScDPSaveData::SetGrandTotalName(const OUString& rName)
 {
     mpGrandTotalName = rName;
diff --git a/sc/source/filter/inc/PivotTableFormat.hxx 
b/sc/source/filter/inc/PivotTableFormat.hxx
index fffaf1a572df..204dea566def 100644
--- a/sc/source/filter/inc/PivotTableFormat.hxx
+++ b/sc/source/filter/inc/PivotTableFormat.hxx
@@ -56,16 +56,21 @@ private:
 
     std::vector<std::shared_ptr<PivotTableReference>> maReferences;
 
+    // Other
+    PivotTable& mrPivotTable;
+
 public:
-    explicit PivotTableFormat(const PivotTable& rPivotTable);
+    explicit PivotTableFormat(PivotTable& rPivotTable);
     void importPivotArea(const oox::AttributeList& rAttribs);
     void importFormat(const oox::AttributeList& rAttribs);
     PivotTableReference& createReference();
+    void finalizeImport();
 };
 
 class PivotTableReference : public WorkbookHelper
 {
-    //PivotTableFormat const& mrFormat;
+public:
+    PivotTableFormat const& mrFormat;
 
     std::optional<sal_uInt32> mnField;
     std::optional<sal_uInt32> mnCount;
diff --git a/sc/source/filter/oox/PivotTableFormat.cxx 
b/sc/source/filter/oox/PivotTableFormat.cxx
index 7447b352745a..1f76d5159a7d 100644
--- a/sc/source/filter/oox/PivotTableFormat.cxx
+++ b/sc/source/filter/oox/PivotTableFormat.cxx
@@ -11,11 +11,15 @@
 #include <pivottablebuffer.hxx>
 #include <oox/token/properties.hxx>
 #include <oox/token/tokens.hxx>
+#include <pivot/PivotTableFormats.hxx>
+#include <dpsave.hxx>
+#include <dpobject.hxx>
 
 namespace oox::xls
 {
-PivotTableFormat::PivotTableFormat(const PivotTable& rPivotTable)
+PivotTableFormat::PivotTableFormat(PivotTable& rPivotTable)
     : WorkbookHelper(rPivotTable)
+    , mrPivotTable(rPivotTable)
 {
 }
 
@@ -69,6 +73,34 @@ void PivotTableFormat::importPivotArea(const 
oox::AttributeList& rAttribs)
     mnFieldPosition = rAttribs.getUnsigned(XML_field);
 }
 
+void PivotTableFormat::finalizeImport()
+{
+    OUString const& rDxfStyle = getStyles().createDxfStyle(mnDxfId);
+
+    ScDPObject* pDPObj = mrPivotTable.getDPObject();
+    ScDPSaveData* pSaveData = pDPObj->GetSaveData();
+
+    sc::PivotTableFormats aFormats;
+
+    if (pSaveData->hasFormats())
+        aFormats = pSaveData->getFormats();
+
+    // Resolve references - TODO
+    for (auto const& pReference : maReferences)
+    {
+        if (pReference->mnField && pReference->mbSelected)
+        {
+            auto nField = *pReference->mnField;
+            for (auto index : pReference->maFieldItemsIndices)
+            {
+                aFormats.add(nField, index, rDxfStyle);
+            }
+        }
+    }
+
+    pSaveData->setFormats(aFormats);
+}
+
 PivotTableReference& PivotTableFormat::createReference()
 {
     auto xReference = std::make_shared<PivotTableReference>(*this);
@@ -78,6 +110,7 @@ PivotTableReference& PivotTableFormat::createReference()
 
 PivotTableReference::PivotTableReference(const PivotTableFormat& rFormat)
     : WorkbookHelper(rFormat)
+    , mrFormat(rFormat)
 {
 }
 void PivotTableReference::importReference(const oox::AttributeList& rAttribs)
diff --git a/sc/source/filter/oox/pivottablebuffer.cxx 
b/sc/source/filter/oox/pivottablebuffer.cxx
index e5c315fa9cdb..072dde626848 100644
--- a/sc/source/filter/oox/pivottablebuffer.cxx
+++ b/sc/source/filter/oox/pivottablebuffer.cxx
@@ -1337,8 +1337,8 @@ void PivotTable::finalizeImport()
         maFilters.forEachMem( &PivotTableFilter::finalizeImport );
 
         // formats
-        //for (auto& pFormat : maFormats)
-        //    pFormat->finalizeImport();
+        for (auto& pFormat : maFormats)
+            pFormat->finalizeImport();
 
         // calculate base position of table
         CellAddress aPos( maLocationModel.maRange.aStart.Tab(), 
maLocationModel.maRange.aStart.Col(), maLocationModel.maRange.aStart.Row() );
commit a180bf0c0f805462c2ba84abcdcc89c59d1e50fa
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Thu Mar 7 14:18:55 2024 +0900
Commit:     Tomaž Vajngerl <qui...@gmail.com>
CommitDate: Thu Apr 11 17:13:14 2024 +0200

    pivot: Import Pivot Table "formats" element(s)
    
    This reads the "formats" element that is a subelement of OOXML
    "pivotTableDefinition" element and is used to define the custom
    cell format of a pivot table output.
    
    Change-Id: Ice0d489d78860ef04388c59810d9f97c5cdb983e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164708
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>

diff --git a/sc/Library_scfilt.mk b/sc/Library_scfilt.mk
index 65794a9bc879..e4936656676e 100644
--- a/sc/Library_scfilt.mk
+++ b/sc/Library_scfilt.mk
@@ -196,6 +196,8 @@ $(eval $(call gb_Library_add_exception_objects,scfilt,\
        sc/source/filter/oox/pivotcachefragment \
        sc/source/filter/oox/pivottablebuffer \
        sc/source/filter/oox/pivottablefragment \
+       sc/source/filter/oox/PivotTableFormat \
+       sc/source/filter/oox/PivotTableFormatContext \
        sc/source/filter/oox/querytablebuffer \
        sc/source/filter/oox/querytablefragment \
        sc/source/filter/oox/revisionfragment \
diff --git a/sc/source/filter/inc/PivotTableFormat.hxx 
b/sc/source/filter/inc/PivotTableFormat.hxx
new file mode 100644
index 000000000000..fffaf1a572df
--- /dev/null
+++ b/sc/source/filter/inc/PivotTableFormat.hxx
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include "workbookhelper.hxx"
+
+#include <memory>
+#include <vector>
+#include <optional>
+#include <oox/helper/attributelist.hxx>
+
+namespace oox::xls
+{
+class PivotTable;
+class PivotTableFormat;
+class PivotTableReference;
+
+enum class PivotAreaType
+{
+    None,
+    Normal,
+    Data,
+    All,
+    Origin,
+    Button,
+    TopRight
+};
+
+class PivotTableFormat : public WorkbookHelper
+{
+public:
+    // DXF
+    sal_Int32 mnDxfId = -1;
+
+private:
+    // PivotArea
+    std::optional<sal_Int32> mnField;
+    PivotAreaType meType = PivotAreaType::Normal;
+    bool mbDataOnly = true;
+    bool mbLabelOnly = false;
+    bool mbGrandRow = false;
+    bool mbGrandCol = false;
+    bool mbCacheIndex = false;
+    bool mbOutline = true;
+    std::optional<OUString> msOffset;
+    bool mbCollapsedLevelsAreSubtotals = false;
+    // TODO Axis
+    std::optional<sal_uInt32> mnFieldPosition;
+
+    std::vector<std::shared_ptr<PivotTableReference>> maReferences;
+
+public:
+    explicit PivotTableFormat(const PivotTable& rPivotTable);
+    void importPivotArea(const oox::AttributeList& rAttribs);
+    void importFormat(const oox::AttributeList& rAttribs);
+    PivotTableReference& createReference();
+};
+
+class PivotTableReference : public WorkbookHelper
+{
+    //PivotTableFormat const& mrFormat;
+
+    std::optional<sal_uInt32> mnField;
+    std::optional<sal_uInt32> mnCount;
+    bool mbSelected = true;
+    bool mbByPosition = false;
+    bool mbRelative = false;
+    bool mbDefaultSubtotal = false;
+    bool mbSumSubtotal = false;
+    bool mbCountASubtotal = false;
+    bool mbAvgSubtotal = false;
+    bool mbMaxSubtotal = false;
+    bool mbMinSubtotal = false;
+    bool mbProductSubtotal = false;
+    bool mbCountSubtotal = false;
+    bool mbStdDevSubtotal = false;
+    bool mbStdDevPSubtotal = false;
+    bool mbVarSubtotal = false;
+    bool mbVarPSubtotal = false;
+
+    std::vector<sal_uInt32> maFieldItemsIndices;
+
+public:
+    explicit PivotTableReference(const PivotTableFormat& rFormat);
+
+    void importReference(const oox::AttributeList& rAttribs);
+    void addFieldItem(const oox::AttributeList& rAttribs);
+};
+
+typedef std::vector<std::shared_ptr<PivotTableFormat>> PivotTableFormatVector;
+
+} // namespace oox::xls
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/inc/PivotTableFormatContext.hxx 
b/sc/source/filter/inc/PivotTableFormatContext.hxx
new file mode 100644
index 000000000000..6eee45806726
--- /dev/null
+++ b/sc/source/filter/inc/PivotTableFormatContext.hxx
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include "excelhandlers.hxx"
+#include "worksheethelper.hxx"
+
+namespace oox::xls
+{
+class PivotTableFormat;
+class PivotTableReference;
+
+class PivotTableFormatContext : public WorksheetContextBase
+{
+public:
+    explicit PivotTableFormatContext(WorksheetFragmentBase& rFragment, 
PivotTableFormat& rFormat);
+
+    oox::core::ContextHandlerRef onCreateContext(sal_Int32 nElement,
+                                                 const AttributeList& 
rAttribs) override;
+    void onStartElement(const AttributeList& rAttribs) override;
+
+private:
+    PivotTableFormat& mrFormat;
+};
+
+class PivotTableReferenceContext : public WorksheetContextBase
+{
+public:
+    explicit PivotTableReferenceContext(PivotTableFormatContext& rFragment,
+                                        PivotTableReference& rReference);
+
+    oox::core::ContextHandlerRef onCreateContext(sal_Int32 nElement,
+                                                 const AttributeList& 
rAttribs) override;
+    void onStartElement(const AttributeList& rAttribs) override;
+
+private:
+    PivotTableReference& mrReference;
+};
+
+} // namespace oox::xls
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/inc/pivottablebuffer.hxx 
b/sc/source/filter/inc/pivottablebuffer.hxx
index a4ba60022dea..2c032277e90e 100644
--- a/sc/source/filter/inc/pivottablebuffer.hxx
+++ b/sc/source/filter/inc/pivottablebuffer.hxx
@@ -20,6 +20,7 @@
 #pragma once
 
 #include "pivotcachebuffer.hxx"
+#include "PivotTableFormat.hxx"
 #include "stylesbuffer.hxx"
 #include <rtl/ref.hxx>
 
@@ -318,6 +319,8 @@ public:
     PivotTableField&    createTableField();
     /** Creates and returns a new pivot table filter. */
     PivotTableFilter&   createTableFilter();
+    /** Creates and returns a new pivot table format. */
+    PivotTableFormat& createFormat();
     /** Inserts the pivot table into the sheet. */
     void                finalizeImport();
     /** Finalizes all fields, finds field names and creates grouping fields. */
@@ -377,6 +380,7 @@ private:
     PageFieldVector       maPageFields;       /// Settings for all fields in 
page dimension.
     DataFieldVector       maDataFields;       /// Settings for all fields in 
data area.
     PivotTableFilterVector maFilters;       /// All field filters.
+    PivotTableFormatVector maFormats;
     PTDefinitionModel     maDefModel;         /// Global pivot table settings.
     PTLocationModel       maLocationModel;    /// Location settings of the 
pivot table.
     PivotCache*           mpPivotCache;       /// The pivot cache this table 
is based on.
diff --git a/sc/source/filter/oox/PivotTableFormat.cxx 
b/sc/source/filter/oox/PivotTableFormat.cxx
new file mode 100644
index 000000000000..7447b352745a
--- /dev/null
+++ b/sc/source/filter/oox/PivotTableFormat.cxx
@@ -0,0 +1,115 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <PivotTableFormat.hxx>
+#include <pivottablebuffer.hxx>
+#include <oox/token/properties.hxx>
+#include <oox/token/tokens.hxx>
+
+namespace oox::xls
+{
+PivotTableFormat::PivotTableFormat(const PivotTable& rPivotTable)
+    : WorkbookHelper(rPivotTable)
+{
+}
+
+void PivotTableFormat::importFormat(const oox::AttributeList& rAttribs)
+{
+    mnDxfId = rAttribs.getInteger(XML_dxfId, -1);
+}
+
+void PivotTableFormat::importPivotArea(const oox::AttributeList& rAttribs)
+{
+    mnField = rAttribs.getInteger(XML_field);
+
+    auto oType = rAttribs.getToken(XML_type);
+    if (oType)
+    {
+        switch (*oType)
+        {
+            case XML_none:
+                meType = PivotAreaType::None;
+                break;
+            case XML_data:
+                meType = PivotAreaType::Data;
+                break;
+            case XML_all:
+                meType = PivotAreaType::All;
+                break;
+            case XML_origin:
+                meType = PivotAreaType::Origin;
+                break;
+            case XML_button:
+                meType = PivotAreaType::Button;
+                break;
+            case XML_topRight:
+                meType = PivotAreaType::TopRight;
+                break;
+            default:
+            case XML_normal:
+                meType = PivotAreaType::Normal;
+                break;
+        }
+    }
+
+    mbDataOnly = rAttribs.getBool(XML_dataOnly, true);
+    mbLabelOnly = rAttribs.getBool(XML_labelOnly, false);
+    mbGrandRow = rAttribs.getBool(XML_grandRow, false);
+    mbGrandCol = rAttribs.getBool(XML_grandCol, false);
+    mbCacheIndex = rAttribs.getBool(XML_cacheIndex, false);
+    mbOutline = rAttribs.getBool(XML_cacheIndex, true);
+    msOffset = rAttribs.getXString(XML_offset);
+    mbCollapsedLevelsAreSubtotals = 
rAttribs.getBool(XML_collapsedLevelsAreSubtotals, false);
+    mnFieldPosition = rAttribs.getUnsigned(XML_field);
+}
+
+PivotTableReference& PivotTableFormat::createReference()
+{
+    auto xReference = std::make_shared<PivotTableReference>(*this);
+    maReferences.push_back(xReference);
+    return *xReference;
+}
+
+PivotTableReference::PivotTableReference(const PivotTableFormat& rFormat)
+    : WorkbookHelper(rFormat)
+{
+}
+void PivotTableReference::importReference(const oox::AttributeList& rAttribs)
+{
+    mnField = rAttribs.getUnsigned(XML_field);
+    mnCount = rAttribs.getUnsigned(XML_count);
+    mbSelected = rAttribs.getBool(XML_selected, true);
+    mbByPosition = rAttribs.getBool(XML_byPosition, false);
+    mbRelative = rAttribs.getBool(XML_relative, false);
+    mbDefaultSubtotal = rAttribs.getBool(XML_defaultSubtotal, false);
+    mbSumSubtotal = rAttribs.getBool(XML_sumSubtotal, false);
+    mbCountASubtotal = rAttribs.getBool(XML_countASubtotal, false);
+    mbAvgSubtotal = rAttribs.getBool(XML_avgSubtotal, false);
+    mbMaxSubtotal = rAttribs.getBool(XML_maxSubtotal, false);
+    mbMinSubtotal = rAttribs.getBool(XML_minSubtotal, false);
+    mbProductSubtotal = rAttribs.getBool(XML_productSubtotal, false);
+    mbCountSubtotal = rAttribs.getBool(XML_countSubtotal, false);
+    mbStdDevSubtotal = rAttribs.getBool(XML_stdDevSubtotal, false);
+    mbStdDevPSubtotal = rAttribs.getBool(XML_stdDevPSubtotal, false);
+    mbVarSubtotal = rAttribs.getBool(XML_varSubtotal, false);
+    mbVarPSubtotal = rAttribs.getBool(XML_varPSubtotal, false);
+}
+
+void PivotTableReference::addFieldItem(const oox::AttributeList& rAttribs)
+{
+    auto oSharedItemsIndex = rAttribs.getUnsigned(XML_v); // XML_v - shared 
items index
+    if (oSharedItemsIndex)
+    {
+        maFieldItemsIndices.push_back(*oSharedItemsIndex);
+    }
+}
+
+} // namespace oox::xls
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/oox/PivotTableFormatContext.cxx 
b/sc/source/filter/oox/PivotTableFormatContext.cxx
new file mode 100644
index 000000000000..75893ea1022c
--- /dev/null
+++ b/sc/source/filter/oox/PivotTableFormatContext.cxx
@@ -0,0 +1,92 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <PivotTableFormatContext.hxx>
+
+#include <pivottablefragment.hxx>
+#include <pivottablebuffer.hxx>
+#include <oox/token/namespaces.hxx>
+#include <oox/helper/attributelist.hxx>
+
+namespace oox::xls
+{
+PivotTableFormatContext::PivotTableFormatContext(WorksheetFragmentBase& 
rFragment,
+                                                 PivotTableFormat& rFormat)
+    : WorksheetContextBase(rFragment)
+    , mrFormat(rFormat)
+{
+}
+
+oox::core::ContextHandlerRef
+PivotTableFormatContext::onCreateContext(sal_Int32 nElement, const 
AttributeList& /*rAttribs*/)
+{
+    switch (getCurrentElement())
+    {
+        case XLS_TOKEN(format):
+            if (nElement == XLS_TOKEN(pivotArea))
+                return this;
+            break;
+        case XLS_TOKEN(pivotArea):
+            if (nElement == XLS_TOKEN(references))
+                return this;
+            break;
+        case XLS_TOKEN(references):
+            if (nElement == XLS_TOKEN(reference))
+                return new PivotTableReferenceContext(*this, 
mrFormat.createReference());
+            break;
+    }
+    return nullptr;
+}
+
+void PivotTableFormatContext::onStartElement(const AttributeList& rAttribs)
+{
+    if (isRootElement())
+    {
+        mrFormat.importFormat(rAttribs);
+    }
+    else if (isCurrentElement(XLS_TOKEN(pivotArea)))
+    {
+        mrFormat.importPivotArea(rAttribs);
+    }
+}
+
+PivotTableReferenceContext::PivotTableReferenceContext(PivotTableFormatContext&
 rFragment,
+                                                       PivotTableReference& 
rReference)
+    : WorksheetContextBase(rFragment)
+    , mrReference(rReference)
+{
+}
+oox::core::ContextHandlerRef
+PivotTableReferenceContext::onCreateContext(sal_Int32 nElement, const 
AttributeList& /*rAttribs*/)
+{
+    switch (getCurrentElement())
+    {
+        case XLS_TOKEN(reference):
+            if (nElement == XLS_TOKEN(x))
+                return this;
+            break;
+    }
+    return nullptr;
+}
+
+void PivotTableReferenceContext::onStartElement(const AttributeList& rAttribs)
+{
+    if (isRootElement())
+    {
+        mrReference.importReference(rAttribs);
+    }
+    else if (isCurrentElement(XLS_TOKEN(x)))
+    {
+        mrReference.addFieldItem(rAttribs);
+    }
+}
+
+} // namespace oox::xls
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/oox/pivottablebuffer.cxx 
b/sc/source/filter/oox/pivottablebuffer.cxx
index f434780d2756..e5c315fa9cdb 100644
--- a/sc/source/filter/oox/pivottablebuffer.cxx
+++ b/sc/source/filter/oox/pivottablebuffer.cxx
@@ -60,6 +60,7 @@
 #include <document.hxx>
 #include <documentimport.hxx>
 #include <workbooksettings.hxx>
+#include <PivotTableFormat.hxx>
 
 namespace oox::xls {
 
@@ -1234,6 +1235,13 @@ PivotTableFilter& PivotTable::createTableFilter()
     return *xTableFilter;
 }
 
+PivotTableFormat& PivotTable::createFormat()
+{
+    PivotTableFormatVector::value_type xFormat = 
std::make_shared<PivotTableFormat>(*this);
+    maFormats.push_back(xFormat);
+    return *xFormat;
+}
+
 void PivotTable::finalizeImport()
 {
     if( !getAddressConverter().validateCellRange( maLocationModel.maRange, 
true, true ) )
@@ -1328,6 +1336,10 @@ void PivotTable::finalizeImport()
         // filters
         maFilters.forEachMem( &PivotTableFilter::finalizeImport );
 
+        // formats
+        //for (auto& pFormat : maFormats)
+        //    pFormat->finalizeImport();
+
         // calculate base position of table
         CellAddress aPos( maLocationModel.maRange.aStart.Tab(), 
maLocationModel.maRange.aStart.Col(), maLocationModel.maRange.aStart.Row() );
         /*  If page fields exist, include them into the destination
diff --git a/sc/source/filter/oox/pivottablefragment.cxx 
b/sc/source/filter/oox/pivottablefragment.cxx
index 76d2abdcde36..d173e6bf0fa3 100644
--- a/sc/source/filter/oox/pivottablefragment.cxx
+++ b/sc/source/filter/oox/pivottablefragment.cxx
@@ -19,6 +19,7 @@
 
 #include <pivottablefragment.hxx>
 #include <pivottablebuffer.hxx>
+#include <PivotTableFormatContext.hxx>
 #include <biffhelper.hxx>
 #include <oox/token/namespaces.hxx>
 
@@ -174,12 +175,14 @@ ContextHandlerRef PivotTableFragment::onCreateContext( 
sal_Int32 nElement, const
             switch( nElement )
             {
                 case XLS_TOKEN( location ):     mrPivotTable.importLocation( 
rAttribs, getSheetIndex() );   break;
-                case XLS_TOKEN( pivotFields ):  return this;
-                case XLS_TOKEN( rowFields ):    return this;
-                case XLS_TOKEN( colFields ):    return this;
-                case XLS_TOKEN( pageFields ):   return this;
-                case XLS_TOKEN( dataFields ):   return this;
-                case XLS_TOKEN( filters ):      return this;
+                case XLS_TOKEN(pivotFields):
+                case XLS_TOKEN(rowFields):
+                case XLS_TOKEN(colFields):
+                case XLS_TOKEN(pageFields):
+                case XLS_TOKEN(dataFields):
+                case XLS_TOKEN(filters):
+                case XLS_TOKEN(formats):
+                    return this;
                 case XLS_TOKEN(pivotTableStyleInfo):
                     mrPivotTable.putToInteropGrabBag("pivotTableStyleInfo", 
rAttribs);
                     break;
@@ -204,6 +207,10 @@ ContextHandlerRef PivotTableFragment::onCreateContext( 
sal_Int32 nElement, const
         case XLS_TOKEN( filters ):
             if( nElement == XLS_TOKEN( filter ) ) return new 
PivotTableFilterContext( *this, mrPivotTable.createTableFilter() );
         break;
+        case XLS_TOKEN(formats):
+            if (nElement == XLS_TOKEN(format))
+                return new PivotTableFormatContext(*this, 
mrPivotTable.createFormat());
+        break;
     }
     return nullptr;
 }

Reply via email to