sc/CppunitTest_sc_pivottable_filters_test.mk                                 | 
   1 
 sc/Library_sc.mk                                                             | 
   1 
 sc/inc/miscuno.hxx                                                           | 
   8 
 sc/inc/pivot/PivotTableResultTraverser.hxx                                   | 
  73 
 sc/qa/unit/PivotTable_FieldsAndItemsExport.cxx                               | 
 840 ++++++++++
 sc/qa/unit/data/xlsx/pivot/Pivot1_Row.xlsx                                   
|binary
 sc/qa/unit/data/xlsx/pivot/Pivot1_Row_Grand.xlsx                             
|binary
 sc/qa/unit/data/xlsx/pivot/Pivot1_Row_Grand_Subtotals.xlsx                   
|binary
 sc/qa/unit/data/xlsx/pivot/Pivot2_Row.xlsx                                   
|binary
 sc/qa/unit/data/xlsx/pivot/Pivot2_Row_Compact.xlsx                           
|binary
 sc/qa/unit/data/xlsx/pivot/Pivot2_Row_Grand.xlsx                             
|binary
 sc/qa/unit/data/xlsx/pivot/Pivot2_Row_Grand_Subtotals.xlsx                   
|binary
 sc/qa/unit/data/xlsx/pivot/Pivot2_Row_Subtotals.xlsx                         
|binary
 sc/qa/unit/data/xlsx/pivot/Pivot2_Row_Subtotals_SortDescendingAll.xlsx       
|binary
 sc/qa/unit/data/xlsx/pivot/Pivot3_Column_Grand_Subtotals.xlsx                
|binary
 sc/qa/unit/data/xlsx/pivot/Pivot4_Column_Grand_Subtotals_SortDescending.xlsx 
|binary
 sc/qa/unit/pivottable_filters_test.cxx                                       | 
 131 -
 sc/source/core/data/pivot/PivotTableResultTraverser.cxx                      | 
 125 +
 sc/source/filter/excel/xepivotxml.cxx                                        | 
 333 +++
 19 files changed, 1308 insertions(+), 204 deletions(-)

New commits:
commit ca071ce7fd7143ad0404fd78c7d079695efa0761
Author:     Tomaž Vajngerl <[email protected]>
AuthorDate: Tue Dec 2 14:31:11 2025 +0900
Commit:     Tomaž Vajngerl <[email protected]>
CommitDate: Thu Dec 4 08:20:48 2025 +0100

    sc: fix exporting of row / column items of a pivot table
    
    The current row and column items export implementation was quite
    naive, where it added jsut one level of items and not understood
    why t="grand" needs to be added. This fixes the implementation
    so it now gathers the row / column items correctly.
    
    There are many scenarios we need to take into account, like
    grant totals, subtotals, filters and sorts. Those are covered
    by tests using different pivot tables.
    
    If the row / column items are not correctly set, the pivot table
    in MSOffice is not shown correctly in the sheet until you actually
    refresh the pivot table, so the data refreshes. In recent MSOffice
    version it also marks the pivot table as corrupt and removes the
    pivot table from the document. With this fix it now accepts the
    pivot table and show it correctly.
    
    Change-Id: I1fbe05b4b5a2051ec9d527f5243c84c2e8818b72
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/194940
    Reviewed-by: Tomaž Vajngerl <[email protected]>
    Tested-by: Jenkins

diff --git a/sc/CppunitTest_sc_pivottable_filters_test.mk 
b/sc/CppunitTest_sc_pivottable_filters_test.mk
index 45ceded3698e..a2134039cdb0 100644
--- a/sc/CppunitTest_sc_pivottable_filters_test.mk
+++ b/sc/CppunitTest_sc_pivottable_filters_test.mk
@@ -13,6 +13,7 @@ $(eval $(call 
gb_CppunitTest_use_common_precompiled_header,sc_pivottable_filters
 
 $(eval $(call gb_CppunitTest_add_exception_objects,sc_pivottable_filters_test, 
\
     sc/qa/unit/pivottable_filters_test \
+    sc/qa/unit/PivotTable_FieldsAndItemsExport \
 ))
 
 $(eval $(call gb_CppunitTest_use_externals,sc_pivottable_filters_test, \
diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index 2567f7f21735..5960a50e1fa4 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -213,6 +213,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
     sc/source/core/data/types \
     sc/source/core/data/userdat \
     sc/source/core/data/validat \
+    sc/source/core/data/pivot/PivotTableResultTraverser \
     sc/source/core/tool/addincfg \
     sc/source/core/tool/addincol \
     sc/source/core/tool/addinhelpid \
diff --git a/sc/inc/miscuno.hxx b/sc/inc/miscuno.hxx
index 71cd9390de49..075bf0046185 100644
--- a/sc/inc/miscuno.hxx
+++ b/sc/inc/miscuno.hxx
@@ -107,7 +107,7 @@ public:
 };
 
 //  new (uno 3) variant
-class ScNameToIndexAccess final : public cppu::WeakImplHelper<
+class SC_DLLPUBLIC ScNameToIndexAccess final : public cppu::WeakImplHelper<
                                 css::container::XIndexAccess,
                                 css::lang::XServiceInfo >
 {
@@ -134,7 +134,7 @@ public:
     virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames(  
) override;
 };
 
-class ScUnoHelpFunctions
+class SC_DLLPUBLIC ScUnoHelpFunctions
 {
 public:
     static bool             GetBoolProperty( const css::uno::Reference< 
css::beans::XPropertySet>& xProp,
@@ -152,8 +152,8 @@ public:
         const css::uno::Reference<css::beans::XPropertySet>& xProp,
         const OUString& rName, const OUString& rDefault );
 
-    SC_DLLPUBLIC static bool        GetBoolFromAny( const css::uno::Any& aAny 
);
-    SC_DLLPUBLIC static sal_Int16   GetInt16FromAny( const css::uno::Any& aAny 
);
+    static bool        GetBoolFromAny( const css::uno::Any& aAny );
+    static sal_Int16   GetInt16FromAny( const css::uno::Any& aAny );
     static sal_Int32        GetInt32FromAny( const css::uno::Any& aAny );
     static sal_Int32        GetEnumFromAny( const css::uno::Any& aAny );
 
diff --git a/sc/inc/pivot/PivotTableResultTraverser.hxx 
b/sc/inc/pivot/PivotTableResultTraverser.hxx
new file mode 100644
index 000000000000..3ecd7c0c8c4a
--- /dev/null
+++ b/sc/inc/pivot/PivotTableResultTraverser.hxx
@@ -0,0 +1,73 @@
+/* -*- 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 <dpobject.hxx>
+#include <scdllapi.h>
+#include <rtl/ustring.hxx>
+
+#include <com/sun/star/sheet/MemberResult.hpp>
+#include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
+
+namespace sc
+{
+namespace pivot
+{
+SC_DLLPUBLIC css::uno::Any
+getMemberForLevel(css::uno::Reference<css::uno::XInterface> const& xLevel, 
OUString const& rName);
+}
+
+class SC_DLLPUBLIC PivotTableResultVisitor
+{
+public:
+    virtual bool filterOrientation(css::sheet::DataPilotFieldOrientation 
eOrientation)
+    {
+        return eOrientation == css::sheet::DataPilotFieldOrientation_HIDDEN;
+    }
+
+    virtual void startDimension(sal_Int32 /*nDimensionIndex*/,
+                                css::uno::Reference<css::uno::XInterface> 
const& /*xDimension*/,
+                                css::sheet::DataPilotFieldOrientation 
/*eOrientation*/)
+    {
+    }
+
+    virtual void endDimension() {}
+
+    virtual void startLevel(sal_Int32 /*nLevelIndex*/,
+                            css::uno::Reference<css::uno::XInterface> const& 
/*xLevel*/,
+                            OUString const& /*rLevelName*/)
+    {
+    }
+
+    virtual void endLevel() {}
+
+    virtual void memberResult(css::sheet::MemberResult const& rResult, 
sal_Int32 nIndex,
+                              sal_Int32 nSize)
+        = 0;
+};
+
+class SC_DLLPUBLIC PivotTableResultTraverser
+{
+private:
+    ScDPObject& mrDPObject;
+    PivotTableResultVisitor& mrVisitor;
+
+public:
+    PivotTableResultTraverser(ScDPObject& rDPObject, PivotTableResultVisitor& 
rVisitor)
+        : mrDPObject(rDPObject)
+        , mrVisitor(rVisitor)
+    {
+    }
+
+    void traverse();
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/qa/unit/PivotTable_FieldsAndItemsExport.cxx 
b/sc/qa/unit/PivotTable_FieldsAndItemsExport.cxx
new file mode 100644
index 000000000000..dbbaf3c8f3ff
--- /dev/null
+++ b/sc/qa/unit/PivotTable_FieldsAndItemsExport.cxx
@@ -0,0 +1,840 @@
+/* -*- 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 <sal/config.h>
+
+#include "helper/qahelper.hxx"
+
+#include <patattr.hxx>
+#include <scitems.hxx>
+#include <document.hxx>
+#include <generalfunction.hxx>
+#include <dpcache.hxx>
+#include <dpobject.hxx>
+#include <dpsave.hxx>
+#include <dputil.hxx>
+#include <attrib.hxx>
+#include <dpshttab.hxx>
+#include <globstr.hrc>
+#include <scresid.hxx>
+#include <queryentry.hxx>
+#include <queryparam.hxx>
+#include <rtl/string.hxx>
+
+#include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
+#include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
+
+using namespace ::com::sun::star;
+
+class PivotTableFieldsAndItemsExport : public ScModelTestBase
+{
+public:
+    PivotTableFieldsAndItemsExport()
+        : ScModelTestBase(u"sc/qa/unit/data"_ustr)
+    {
+    }
+};
+
+CPPUNIT_TEST_FIXTURE(PivotTableFieldsAndItemsExport, 
testTdf123225PivotTableRowColItems)
+{
+    createScDoc("ods/tdf123225_pivotTable_row_col_items.ods");
+    save(TestFilter::XLSX);
+
+    xmlDocUniquePtr pSheet = 
parseExport(u"xl/pivotTables/pivotTable1.xml"_ustr);
+    CPPUNIT_ASSERT(pSheet);
+
+    /* Make sure that we have <rowItems> and <colItems> element under 
<pivotTableDefinition> after export of the .ods to .xlsx */
+    /* otherwise:
+      - Excel will fail to open the xlsx document, you will get an error 
message.
+      - Excel will open the file without any errors but:
+        * context menu -by right clicking on the pivot table- will have less 
or more items than it should have after "refresh".
+        * if e.g. trying to sort the items you will get "Cannot determine 
which PivotTable field to sort by" warning.
+    */
+
+    // Row items <rowItems>
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems", 1);
+    // check if <rowItems count="8">
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems", "count", u"8");
+    // check if <rowItems> has enough <i> depending on count attribute value
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i", 8);
+    // check if first <i> has single <x/> element
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[1]/x:x", 1);
+    // check if <x/> of the first <i> element, exists (note the v=0 is default)
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[1]/x:x", 1);
+    assertXPathNoAttribute(pSheet, 
"/x:pivotTableDefinition/x:rowItems/x:i[1]/x:x", "v");
+
+    // Column items <colItems>
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems", 1);
+    // check if <colItems count="5">
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems", "count", u"5");
+    // check if <colItems> has enough <i> depending on count attribute value
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i", 5);
+    // check if first <i> has single <x/> element
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[1]/x:x", 1);
+    // check if <x/> of the first <i> element, exists (note the v=0 is default)
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[1]/x:x", 1);
+    assertXPathNoAttribute(pSheet, 
"/x:pivotTableDefinition/x:colItems/x:i[1]/x:x", "v");
+}
+
+CPPUNIT_TEST_FIXTURE(PivotTableFieldsAndItemsExport, 
testTdf123225_CheckGrandTotalIsSet)
+{
+    createScDoc("ods/tdf123225_pivotTable_no_col_items.ods");
+    save(TestFilter::XLSX);
+
+    xmlDocUniquePtr pSheet = 
parseExport(u"xl/pivotTables/pivotTable1.xml"_ustr);
+    CPPUNIT_ASSERT(pSheet);
+
+    /* If there is a grand (Total result) there needs to be a row/column item 
with t="grand"*/
+
+    // Row items <rowItems>
+
+    // check if <rowItems count="3">
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems", "count", u"3");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i", 3);
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[1]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[1]/x:x[1]", 
"v", u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[2]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[2]/x:x[1]", 
"v", u"2");
+
+    // check if last <i> element, has t="grand"
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[3]", "t", 
u"grand");
+    // check <x> element
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[3]/x:x", 1);
+
+    // Column items <colItems>
+
+    // check if <colItems count="1">
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems", "count", u"1");
+    // check if <colItems> has only a single <i> element
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i", 1);
+    // check there is no attribute "t"
+    assertXPathNoAttribute(pSheet, "/x:pivotTableDefinition/x:colItems/x:i", 
"t");
+    // check that it doesn't contain any <x> elements
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[1]/x:x", 0);
+}
+
+CPPUNIT_TEST_FIXTURE(PivotTableFieldsAndItemsExport, 
testTdf123225PivotTableEmptyRowColItems)
+{
+    // this doc contains blank row/col items
+    // <sharedItems containsBlank="1" count="..."> 
(xl/pivotCache/pivotCacheDefinition1.xml)
+    createScDoc("ods/tdf123225_pivotTable_empty_row_col_items.ods");
+    save(TestFilter::XLSX);
+
+    xmlDocUniquePtr pSheet = 
parseExport(u"xl/pivotTables/pivotTable1.xml"_ustr);
+    CPPUNIT_ASSERT(pSheet);
+
+    // Row items <rowItems>
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems", 1);
+    // check if <rowItems count="4">
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems", "count", u"4");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i", 4);
+
+    // Column items <colItems>
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems", 1);
+    // check if <colItems count="5">
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems", "count", u"5");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i", 5);
+}
+
+CPPUNIT_TEST_FIXTURE(PivotTableFieldsAndItemsExport, 
testPivotTable_RowColumnItems_Row1)
+{
+    /* Input document rowItems:
+      <rowItems count="5">
+        <i> <x /> <x v="2" /> </i>
+        <i> <x v="1" /> <x v="1" /> </i>
+        <i> <x v="2" /> <x v="1" /> </i>
+        <i> <x v="3" /> <x /> </i>
+        <i> <x v="4" /> <x v="2" /> </i>
+      </rowItems>
+    */
+    createScDoc("xlsx/pivot/Pivot1_Row.xlsx");
+    save(TestFilter::XLSX);
+
+    xmlDocUniquePtr pSheet = 
parseExport(u"xl/pivotTables/pivotTable1.xml"_ustr);
+    CPPUNIT_ASSERT(pSheet);
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems", 1);
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems", "count", u"5");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i", 5);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[1]/x:x", 2);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[2]/x:x", 2);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[3]/x:x", 2);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[4]/x:x", 2);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[5]/x:x", 2);
+
+    assertXPathNoAttribute(pSheet, 
"/x:pivotTableDefinition/x:rowItems/x:i[1]/x:x[1]", "v");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[1]/x:x[2]", 
"v", u"2");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[2]/x:x[1]", 
"v", u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[2]/x:x[2]", 
"v", u"1");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[3]/x:x[1]", 
"v", u"2");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[3]/x:x[2]", 
"v", u"1");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[4]/x:x[1]", 
"v", u"3");
+    assertXPathNoAttribute(pSheet, 
"/x:pivotTableDefinition/x:rowItems/x:i[4]/x:x[2]", "v");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[5]/x:x[1]", 
"v", u"4");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[5]/x:x[2]", 
"v", u"2");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems", "count", u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[1]/x:x", 0);
+}
+
+CPPUNIT_TEST_FIXTURE(PivotTableFieldsAndItemsExport, 
testPivotTable_RowColumnItems_Row1_Grand)
+{
+    /* Input document rowItems:
+      <rowItems count="6">
+        <i> <x /> <x v="2" /> </i>
+        <i> <x v="1" /> <x v="1" /> </i>
+        <i> <x v="2" /> <x v="1" /> </i>
+        <i> <x v="3" /> <x /> </i>
+        <i> <x v="4" /> <x v="2" /> </i>
+        <i t="grand"> <x /> </i>
+      </rowItems>
+    */
+    createScDoc("xlsx/pivot/Pivot1_Row_Grand.xlsx");
+    save(TestFilter::XLSX);
+
+    xmlDocUniquePtr pSheet = 
parseExport(u"xl/pivotTables/pivotTable1.xml"_ustr);
+    CPPUNIT_ASSERT(pSheet);
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems", 1);
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems", "count", u"6");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i", 6);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[1]/x:x", 2);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[2]/x:x", 2);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[3]/x:x", 2);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[4]/x:x", 2);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[5]/x:x", 2);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[5]/x:x", 2);
+
+    assertXPathNoAttribute(pSheet, 
"/x:pivotTableDefinition/x:rowItems/x:i[1]/x:x[1]", "v");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[1]/x:x[2]", 
"v", u"2");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[2]/x:x[1]", 
"v", u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[2]/x:x[2]", 
"v", u"1");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[3]/x:x[1]", 
"v", u"2");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[3]/x:x[2]", 
"v", u"1");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[4]/x:x[1]", 
"v", u"3");
+    assertXPathNoAttribute(pSheet, 
"/x:pivotTableDefinition/x:rowItems/x:i[4]/x:x[2]", "v");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[5]/x:x[1]", 
"v", u"4");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[5]/x:x[2]", 
"v", u"2");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[6]", "t", 
u"grand");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[6]/x:x", 1);
+    assertXPathNoAttribute(pSheet, 
"/x:pivotTableDefinition/x:rowItems/x:i[6]/x:x", "v");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems", "count", u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[1]/x:x", 0);
+}
+
+CPPUNIT_TEST_FIXTURE(PivotTableFieldsAndItemsExport,
+                     testPivotTable_RowColumnItems_Row1_Grand_Subtotals)
+{
+    /* Input document rowItems:
+      <rowItems count="11">
+        <i> <x /> <x v="2" /> </i>
+        <i t="default"> <x /> </i>
+        <i> <x v="1" /> <x v="1" /> </i>
+        <i t="default"> <x v="1" /> </i>
+        <i> <x v="2" /> <x v="1" /> </i>
+        <i t="default"><x v="2" /> </i>
+        <i> <x v="3" /> <x /> </i>
+        <i t="default"> <x v="3" /> </i>
+        <i> <x v="4" /> <x v="2" /> </i>
+        <i t="default"> <x v="4" /> </i>
+        <i t="grand"> <x /> </i>
+      </rowItems>
+    */
+    createScDoc("xlsx/pivot/Pivot1_Row_Grand_Subtotals.xlsx");
+    save(TestFilter::XLSX);
+
+    xmlDocUniquePtr pSheet = 
parseExport(u"xl/pivotTables/pivotTable1.xml"_ustr);
+    CPPUNIT_ASSERT(pSheet);
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems", 1);
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems", "count", u"11");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i", 11);
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[1]/x:x", 2);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[2]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[3]/x:x", 2);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[4]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[5]/x:x", 2);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[6]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[7]/x:x", 2);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[8]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[9]/x:x", 2);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[10]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[11]/x:x", 1);
+
+    assertXPathNoAttribute(pSheet, 
"/x:pivotTableDefinition/x:rowItems/x:i[1]/x:x[1]", "v");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[1]/x:x[2]", 
"v", u"2");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[2]", "t", 
u"default");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[2]/x:x", 1);
+    assertXPathNoAttribute(pSheet, 
"/x:pivotTableDefinition/x:rowItems/x:i[2]/x:x", "v");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[3]/x:x[1]", 
"v", u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[3]/x:x[2]", 
"v", u"1");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[4]", "t", 
u"default");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[4]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[4]/x:x", "v", 
u"1");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[5]/x:x[1]", 
"v", u"2");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[5]/x:x[2]", 
"v", u"1");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[6]", "t", 
u"default");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[6]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[6]/x:x", "v", 
u"2");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[7]/x:x[1]", 
"v", u"3");
+    assertXPathNoAttribute(pSheet, 
"/x:pivotTableDefinition/x:rowItems/x:i[7]/x:x[2]", "v");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[8]", "t", 
u"default");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[8]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[8]/x:x", "v", 
u"3");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[9]/x:x[1]", 
"v", u"4");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[9]/x:x[2]", 
"v", u"2");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[10]", "t", 
u"default");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[10]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[10]/x:x", "v", 
u"4");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[11]", "t", 
u"grand");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[11]/x:x", 1);
+    assertXPathNoAttribute(pSheet, 
"/x:pivotTableDefinition/x:rowItems/x:i[11]/x:x", "v");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems", "count", u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[1]/x:x", 0);
+}
+
+CPPUNIT_TEST_FIXTURE(PivotTableFieldsAndItemsExport, 
testPivotTable_RowColumnItems_Row2)
+{
+    /* Input document rowItems:
+      <rowItems count="5">
+        <i>  <x /> <x /> </i>
+        <i r="1"> <x v="4" /> </i>
+        <i> <x v="1" /> <x v="1" /> </i>
+        <i r="1"> <x v="2" /> </i>
+        <i> <x v="2" /> <x v="3" /> </i>
+      </rowItems>
+    */
+    createScDoc("xlsx/pivot/Pivot2_Row.xlsx");
+    save(TestFilter::XLSX);
+
+    xmlDocUniquePtr pSheet = 
parseExport(u"xl/pivotTables/pivotTable1.xml"_ustr);
+    CPPUNIT_ASSERT(pSheet);
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems", 1);
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems", "count", u"5");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i", 5);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[1]/x:x", 2);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[2]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[3]/x:x", 2);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[4]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[5]/x:x", 2);
+
+    assertXPathNoAttribute(pSheet, 
"/x:pivotTableDefinition/x:rowItems/x:i[1]/x:x[1]", "v");
+    assertXPathNoAttribute(pSheet, 
"/x:pivotTableDefinition/x:rowItems/x:i[1]/x:x[2]", "v");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[2]", "r", 
u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[2]/x:x[1]", 
"v", u"4");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[3]/x:x[1]", 
"v", u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[3]/x:x[2]", 
"v", u"1");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[4]", "r", 
u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[4]/x:x[1]", 
"v", u"2");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[5]/x:x[1]", 
"v", u"2");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[5]/x:x[2]", 
"v", u"3");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems", "count", u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[1]/x:x", 0);
+}
+
+CPPUNIT_TEST_FIXTURE(PivotTableFieldsAndItemsExport, 
testPivotTable_RowColumnItems_Row2_Grand)
+{
+    /* Input document rowItems:
+      <rowItems count="6">
+        <i> <x /> <x /> </i>
+        <i r="1"> <x v="4" /> </i>
+        <i> <x v="1" /> <x v="1" /> </i>
+        <i r="1"> <x v="2" /> </i>
+        <i> <x v="2" /> <x v="3" /> </i>
+        <i t="grand"> <x /> </i>
+      </rowItems>
+    */
+    createScDoc("xlsx/pivot/Pivot2_Row_Grand.xlsx");
+    save(TestFilter::XLSX);
+
+    xmlDocUniquePtr pSheet = 
parseExport(u"xl/pivotTables/pivotTable1.xml"_ustr);
+    CPPUNIT_ASSERT(pSheet);
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems", 1);
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems", "count", u"6");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i", 6);
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[1]/x:x", 2);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[2]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[3]/x:x", 2);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[4]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[5]/x:x", 2);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[6]/x:x", 1);
+
+    assertXPathNoAttribute(pSheet, 
"/x:pivotTableDefinition/x:rowItems/x:i[1]/x:x[1]", "v");
+    assertXPathNoAttribute(pSheet, 
"/x:pivotTableDefinition/x:rowItems/x:i[1]/x:x[2]", "v");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[2]", "r", 
u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[2]/x:x[1]", 
"v", u"4");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[3]/x:x[1]", 
"v", u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[3]/x:x[2]", 
"v", u"1");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[4]", "r", 
u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[4]/x:x[1]", 
"v", u"2");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[5]/x:x[1]", 
"v", u"2");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[5]/x:x[2]", 
"v", u"3");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[6]", "t", 
u"grand");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[6]/x:x", 1);
+    assertXPathNoAttribute(pSheet, 
"/x:pivotTableDefinition/x:rowItems/x:i[6]/x:x", "v");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems", "count", u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[1]/x:x", 0);
+}
+
+CPPUNIT_TEST_FIXTURE(PivotTableFieldsAndItemsExport, 
testPivotTable_RowColumnItems_Row2_Subtotals)
+{
+    /* Input document rowItems:
+      <rowItems count="8">
+        <i> <x /> <x /> </i>
+        <i r="1"> <x v="4" /> </i>
+        <i t="default"> <x /> </i>
+        <i> <x v="1" /> <x v="1" /> </i>
+        <i r="1"> <x v="2" /> </i>
+        <i t="default"> <x v="1" /> </i>
+        <i> <x v="2" /> <x v="3" /> </i>
+        <i t="default"> <x v="2" /> </i>
+      </rowItems>
+    */
+    createScDoc("xlsx/pivot/Pivot2_Row_Subtotals.xlsx");
+    save(TestFilter::XLSX);
+
+    xmlDocUniquePtr pSheet = 
parseExport(u"xl/pivotTables/pivotTable1.xml"_ustr);
+    CPPUNIT_ASSERT(pSheet);
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems", 1);
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems", "count", u"8");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i", 8);
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[1]/x:x", 2);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[2]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[3]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[4]/x:x", 2);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[5]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[6]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[7]/x:x", 2);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[8]/x:x", 1);
+
+    assertXPathNoAttribute(pSheet, 
"/x:pivotTableDefinition/x:rowItems/x:i[1]/x:x[1]", "v");
+    assertXPathNoAttribute(pSheet, 
"/x:pivotTableDefinition/x:rowItems/x:i[1]/x:x[2]", "v");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[2]", "r", 
u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[2]/x:x[1]", 
"v", u"4");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[3]", "t", 
u"default");
+    assertXPathNoAttribute(pSheet, 
"/x:pivotTableDefinition/x:rowItems/x:i[3]/x:x", "v");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[4]/x:x[1]", 
"v", u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[4]/x:x[2]", 
"v", u"1");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[5]", "r", 
u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[5]/x:x[1]", 
"v", u"2");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[6]", "t", 
u"default");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[6]/x:x", "v", 
u"1");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[7]/x:x[1]", 
"v", u"2");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[7]/x:x[2]", 
"v", u"3");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[8]", "t", 
u"default");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[8]/x:x", "v", 
u"2");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems", "count", u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[1]/x:x", 0);
+}
+
+CPPUNIT_TEST_FIXTURE(PivotTableFieldsAndItemsExport,
+                     testPivotTable_RowColumnItems_Row2_Grand_Subtotals)
+{
+    /* Input document rowItems:
+      <rowItems count="9">
+        <i> <x /> <x /> </i>
+        <i r="1"> <x v="4" /> </i>
+        <i t="default"> <x /> </i>
+        <i> <x v="1" /> <x v="1" /> </i>
+        <i r="1"> <x v="2" /> </i>
+        <i t="default"> <x v="1" /> </i>
+        <i> <x v="2" /> <x v="3" /> </i>
+        <i t="default"> <x v="2" /> </i>
+        <i t="grand"> <x /> </i>
+      </rowItems>
+    */
+    createScDoc("xlsx/pivot/Pivot2_Row_Grand_Subtotals.xlsx");
+    save(TestFilter::XLSX);
+
+    xmlDocUniquePtr pSheet = 
parseExport(u"xl/pivotTables/pivotTable1.xml"_ustr);
+    CPPUNIT_ASSERT(pSheet);
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems", 1);
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems", "count", u"9");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i", 9);
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[1]/x:x", 2);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[2]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[3]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[4]/x:x", 2);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[5]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[6]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[7]/x:x", 2);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[8]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[9]/x:x", 1);
+
+    assertXPathNoAttribute(pSheet, 
"/x:pivotTableDefinition/x:rowItems/x:i[1]/x:x[1]", "v");
+    assertXPathNoAttribute(pSheet, 
"/x:pivotTableDefinition/x:rowItems/x:i[1]/x:x[2]", "v");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[2]", "r", 
u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[2]/x:x[1]", 
"v", u"4");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[3]", "t", 
u"default");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[3]/x:x", 1);
+    assertXPathNoAttribute(pSheet, 
"/x:pivotTableDefinition/x:rowItems/x:i[3]/x:x", "v");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[4]/x:x[1]", 
"v", u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[4]/x:x[2]", 
"v", u"1");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[5]", "r", 
u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[5]/x:x[1]", 
"v", u"2");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[6]", "t", 
u"default");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[6]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[6]/x:x", "v", 
u"1");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[7]/x:x[1]", 
"v", u"2");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[7]/x:x[2]", 
"v", u"3");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[8]", "t", 
u"default");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[8]/x:x", "v", 
u"2");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[9]", "t", 
u"grand");
+    assertXPathNoAttribute(pSheet, 
"/x:pivotTableDefinition/x:rowItems/x:i[9]/x:x", "v");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems", "count", u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[1]/x:x", 0);
+}
+
+CPPUNIT_TEST_FIXTURE(PivotTableFieldsAndItemsExport, 
testPivotTable_RowColumnItems_Row2_Compact)
+{
+    /* Input document rowItems:
+      <rowItems count="8">
+        <i> <x /> </i>
+        <i r="1"> <x /> </i>
+        <i r="1"> <x v="4" /> </i>
+        <i> <x v="1" /> </i>
+        <i r="1"> <x v="1" /> </i>
+        <i r="1"> <x v="2" /> </i>
+        <i> <x v="2" /> </i>
+        <i r="1"> <x v="3" /> </i>
+      </rowItems>
+    */
+    createScDoc("xlsx/pivot/Pivot2_Row_Compact.xlsx");
+    save(TestFilter::XLSX);
+
+    xmlDocUniquePtr pSheet = 
parseExport(u"xl/pivotTables/pivotTable1.xml"_ustr);
+    CPPUNIT_ASSERT(pSheet);
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems", 1);
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems", "count", u"8");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i", 8);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[1]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[2]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[3]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[4]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[5]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[6]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[7]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[8]/x:x", 1);
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[1]/x:x", 1);
+    assertXPathNoAttribute(pSheet, 
"/x:pivotTableDefinition/x:rowItems/x:i[1]/x:x[1]", "v");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[2]", "r", 
u"1");
+    assertXPathNoAttribute(pSheet, 
"/x:pivotTableDefinition/x:rowItems/x:i[2]/x:x[1]", "v");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[3]", "r", 
u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[3]/x:x", "v", 
u"4");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[4]/x:x[1]", 
"v", u"1");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[5]", "r", 
u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[5]/x:x[1]", 
"v", u"1");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[6]", "r", 
u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[6]/x:x[1]", 
"v", u"2");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[7]/x:x[1]", 
"v", u"2");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[8]", "r", 
u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[8]/x:x[1]", 
"v", u"3");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems", "count", u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[1]/x:x", 0);
+}
+
+CPPUNIT_TEST_FIXTURE(PivotTableFieldsAndItemsExport,
+                     
testPivotTable_RowColumnItems_Row2_Subtotals_SortDescendingAll)
+{
+    /* Input document rowItems:
+      <rowItems count="8">
+        <i> <x /> <x v="1" /> </i>
+        <i t="default"> <x /> </i>
+        <i> <x v="1" /> <x v="2" /> </i>
+        <i r="1"> <x v="3" /> </i>
+        <i t="default"> <x v="1" /> </i>
+        <i> <x v="2" /> <x /> </i>
+        <i r="1"> <x v="4" /> </i>
+        <i t="default"> <x v="2" /> </i>
+      </rowItems>
+    */
+    createScDoc("xlsx/pivot/Pivot2_Row_Subtotals_SortDescendingAll.xlsx");
+    save(TestFilter::XLSX);
+
+    xmlDocUniquePtr pSheet = 
parseExport(u"xl/pivotTables/pivotTable1.xml"_ustr);
+    CPPUNIT_ASSERT(pSheet);
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems", 1);
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems", "count", u"8");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i", 8);
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[1]/x:x", 2);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[2]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[3]/x:x", 2);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[4]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[5]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[6]/x:x", 2);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[7]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[8]/x:x", 1);
+
+    assertXPathNoAttribute(pSheet, 
"/x:pivotTableDefinition/x:rowItems/x:i[1]/x:x[1]", "v");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[1]/x:x[2]", 
"v", u"1");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[2]", "t", 
u"default");
+    assertXPathNoAttribute(pSheet, 
"/x:pivotTableDefinition/x:rowItems/x:i[2]/x:x", "v");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[3]/x:x[1]", 
"v", u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[3]/x:x[2]", 
"v", u"2");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[4]", "r", 
u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[4]/x:x[1]", 
"v", u"3");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[5]", "t", 
u"default");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[5]/x:x", "v", 
u"1");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[6]/x:x[1]", 
"v", u"2");
+    assertXPathNoAttribute(pSheet, 
"/x:pivotTableDefinition/x:rowItems/x:i[6]/x:x[2]", "v");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[7]", "r", 
u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[7]/x:x[1]", 
"v", u"4");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[8]", "t", 
u"default");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[8]/x:x", "v", 
u"2");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems", "count", u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[1]/x:x", 0);
+}
+
+CPPUNIT_TEST_FIXTURE(PivotTableFieldsAndItemsExport,
+                     testPivotTable_RowColumnItems_Column3_Grand_Subtotals)
+{
+    /* Input colItems should be the same as output
+      <colItems count="9">
+        <i> <x /> <x /> </i>
+        <i r="1"> <x v="4" /> </i>
+        <i t="default"> <x /> </i>
+        <i> <x v="1" /> <x v="1" /> </i>
+        <i r="1"> <x v="2" /> </i>
+        <i t="default"> <x v="1" /> </i>
+        <i> <x v="2" /> <x v="3" /> </i>
+        <i t="default"> <x v="2" /> </i>
+        <i t="grand"> <x /> </i>
+      </colItems>
+    */
+    createScDoc("xlsx/pivot/Pivot3_Column_Grand_Subtotals.xlsx");
+    save(TestFilter::XLSX);
+
+    xmlDocUniquePtr pSheet = 
parseExport(u"xl/pivotTables/pivotTable1.xml"_ustr);
+    CPPUNIT_ASSERT(pSheet);
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems", "count", u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[1]/x:x", 0);
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems", "count", u"9");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i", 9);
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[1]/x:x", 2);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[2]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[3]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[4]/x:x", 2);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[5]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[6]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[7]/x:x", 2);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[8]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[9]/x:x", 1);
+
+    assertXPathNoAttribute(pSheet, 
"/x:pivotTableDefinition/x:colItems/x:i[1]/x:x[1]", "v");
+    assertXPathNoAttribute(pSheet, 
"/x:pivotTableDefinition/x:colItems/x:i[1]/x:x[2]", "v");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[2]", "r", 
u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[2]/x:x[1]", 
"v", u"4");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[3]", "t", 
u"default");
+    assertXPathNoAttribute(pSheet, 
"/x:pivotTableDefinition/x:colItems/x:i[3]/x:x", "v");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[4]/x:x[1]", 
"v", u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[4]/x:x[2]", 
"v", u"1");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[5]", "r", 
u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[5]/x:x[1]", 
"v", u"2");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[6]", "t", 
u"default");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[6]/x:x", "v", 
u"1");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[7]/x:x[1]", 
"v", u"2");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[7]/x:x[2]", 
"v", u"3");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[8]", "t", 
u"default");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[8]/x:x", "v", 
u"2");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[9]", "t", 
u"grand");
+    assertXPathNoAttribute(pSheet, 
"/x:pivotTableDefinition/x:colItems/x:i[9]/x:x", "v");
+}
+CPPUNIT_TEST_FIXTURE(PivotTableFieldsAndItemsExport,
+                     
testPivotTable_RowColumnItems_Column4_Grand_Subtotals_SortDescending)
+{
+    /* Input colItems should be the same as output
+      <colItems count="9">
+        <i> <x /> <x v="3" /> </i>
+        <i t="default"> <x /> </i>
+        <i> <x v="1" /> <x v="1" /> </i>
+        <i r="1"> <x v="2" /> </i>
+        <i t="default"> <x v="1" /> </i>
+        <i> <x v="2" /> <x /> </i>
+        <i r="1"> <x v="4" /> </i>
+        <i t="default"> <x v="2" /> </i>
+        <i t="grand"> <x /> </i>
+      </colItems>
+    */
+    
createScDoc("xlsx/pivot/Pivot4_Column_Grand_Subtotals_SortDescending.xlsx");
+    save(TestFilter::XLSX);
+
+    xmlDocUniquePtr pSheet = 
parseExport(u"xl/pivotTables/pivotTable1.xml"_ustr);
+    CPPUNIT_ASSERT(pSheet);
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems", "count", u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[1]/x:x", 0);
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems", "count", u"9");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i", 9);
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[1]/x:x", 2);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[2]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[3]/x:x", 2);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[4]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[5]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[6]/x:x", 2);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[7]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[8]/x:x", 1);
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[9]/x:x", 1);
+
+    assertXPathNoAttribute(pSheet, 
"/x:pivotTableDefinition/x:colItems/x:i[1]/x:x[1]", "v");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[1]/x:x[2]", 
"v", u"3");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[2]", "t", 
u"default");
+    assertXPathNoAttribute(pSheet, 
"/x:pivotTableDefinition/x:colItems/x:i[2]/x:x", "v");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[3]/x:x[1]", 
"v", u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[3]/x:x[2]", 
"v", u"1");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[4]", "r", 
u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[4]/x:x[1]", 
"v", u"2");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[5]", "t", 
u"default");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[5]/x:x", "v", 
u"1");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[6]/x:x[1]", 
"v", u"2");
+    assertXPathNoAttribute(pSheet, 
"/x:pivotTableDefinition/x:colItems/x:i[6]/x:x[2]", "v");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[7]", "r", 
u"1");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[7]/x:x[1]", 
"v", u"4");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[8]", "t", 
u"default");
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[8]/x:x", "v", 
u"2");
+
+    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[9]", "t", 
u"grand");
+    assertXPathNoAttribute(pSheet, 
"/x:pivotTableDefinition/x:colItems/x:i[9]/x:x", "v");
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/qa/unit/data/xlsx/pivot/Pivot1_Row.xlsx 
b/sc/qa/unit/data/xlsx/pivot/Pivot1_Row.xlsx
new file mode 100644
index 000000000000..77df731a5602
Binary files /dev/null and b/sc/qa/unit/data/xlsx/pivot/Pivot1_Row.xlsx differ
diff --git a/sc/qa/unit/data/xlsx/pivot/Pivot1_Row_Grand.xlsx 
b/sc/qa/unit/data/xlsx/pivot/Pivot1_Row_Grand.xlsx
new file mode 100644
index 000000000000..c36c6202f7a4
Binary files /dev/null and b/sc/qa/unit/data/xlsx/pivot/Pivot1_Row_Grand.xlsx 
differ
diff --git a/sc/qa/unit/data/xlsx/pivot/Pivot1_Row_Grand_Subtotals.xlsx 
b/sc/qa/unit/data/xlsx/pivot/Pivot1_Row_Grand_Subtotals.xlsx
new file mode 100644
index 000000000000..cae68e5c6904
Binary files /dev/null and 
b/sc/qa/unit/data/xlsx/pivot/Pivot1_Row_Grand_Subtotals.xlsx differ
diff --git a/sc/qa/unit/data/xlsx/pivot/Pivot2_Row.xlsx 
b/sc/qa/unit/data/xlsx/pivot/Pivot2_Row.xlsx
new file mode 100644
index 000000000000..de44fa7c6420
Binary files /dev/null and b/sc/qa/unit/data/xlsx/pivot/Pivot2_Row.xlsx differ
diff --git a/sc/qa/unit/data/xlsx/pivot/Pivot2_Row_Compact.xlsx 
b/sc/qa/unit/data/xlsx/pivot/Pivot2_Row_Compact.xlsx
new file mode 100644
index 000000000000..c48ab5b4b917
Binary files /dev/null and b/sc/qa/unit/data/xlsx/pivot/Pivot2_Row_Compact.xlsx 
differ
diff --git a/sc/qa/unit/data/xlsx/pivot/Pivot2_Row_Grand.xlsx 
b/sc/qa/unit/data/xlsx/pivot/Pivot2_Row_Grand.xlsx
new file mode 100644
index 000000000000..6e81ddc7d486
Binary files /dev/null and b/sc/qa/unit/data/xlsx/pivot/Pivot2_Row_Grand.xlsx 
differ
diff --git a/sc/qa/unit/data/xlsx/pivot/Pivot2_Row_Grand_Subtotals.xlsx 
b/sc/qa/unit/data/xlsx/pivot/Pivot2_Row_Grand_Subtotals.xlsx
new file mode 100644
index 000000000000..848c30e02a54
Binary files /dev/null and 
b/sc/qa/unit/data/xlsx/pivot/Pivot2_Row_Grand_Subtotals.xlsx differ
diff --git a/sc/qa/unit/data/xlsx/pivot/Pivot2_Row_Subtotals.xlsx 
b/sc/qa/unit/data/xlsx/pivot/Pivot2_Row_Subtotals.xlsx
new file mode 100644
index 000000000000..043e31185f03
Binary files /dev/null and 
b/sc/qa/unit/data/xlsx/pivot/Pivot2_Row_Subtotals.xlsx differ
diff --git 
a/sc/qa/unit/data/xlsx/pivot/Pivot2_Row_Subtotals_SortDescendingAll.xlsx 
b/sc/qa/unit/data/xlsx/pivot/Pivot2_Row_Subtotals_SortDescendingAll.xlsx
new file mode 100644
index 000000000000..ade6310b8c03
Binary files /dev/null and 
b/sc/qa/unit/data/xlsx/pivot/Pivot2_Row_Subtotals_SortDescendingAll.xlsx differ
diff --git a/sc/qa/unit/data/xlsx/pivot/Pivot3_Column_Grand_Subtotals.xlsx 
b/sc/qa/unit/data/xlsx/pivot/Pivot3_Column_Grand_Subtotals.xlsx
new file mode 100644
index 000000000000..3d3065b7db49
Binary files /dev/null and 
b/sc/qa/unit/data/xlsx/pivot/Pivot3_Column_Grand_Subtotals.xlsx differ
diff --git 
a/sc/qa/unit/data/xlsx/pivot/Pivot4_Column_Grand_Subtotals_SortDescending.xlsx 
b/sc/qa/unit/data/xlsx/pivot/Pivot4_Column_Grand_Subtotals_SortDescending.xlsx
new file mode 100644
index 000000000000..bca42a014dbc
Binary files /dev/null and 
b/sc/qa/unit/data/xlsx/pivot/Pivot4_Column_Grand_Subtotals_SortDescending.xlsx 
differ
diff --git a/sc/qa/unit/pivottable_filters_test.cxx 
b/sc/qa/unit/pivottable_filters_test.cxx
index b874bdd398b8..12a360790d13 100644
--- a/sc/qa/unit/pivottable_filters_test.cxx
+++ b/sc/qa/unit/pivottable_filters_test.cxx
@@ -122,137 +122,6 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, 
testPivotTableBasicODS)
                                  sal_uInt16(pDim->GetFunction()));
 }
 
-CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, 
testTdf123225PivotTableRowColItems)
-{
-    createScDoc("ods/tdf123225_pivotTable_row_col_items.ods");
-    save(TestFilter::XLSX);
-
-    xmlDocUniquePtr pSheet = 
parseExport(u"xl/pivotTables/pivotTable1.xml"_ustr);
-    CPPUNIT_ASSERT(pSheet);
-
-    /*
-        - be sure that we have <rowItems> and <colItems> element
-        under <pivotTableDefinition> after export of the .ods to .xlsx
-
-            otherwise:
-            1) Excel will fail to open the xlsx document, you will get an 
error message.
-            2) Excel will open the file without any errors but:
-                2.1) context menu -by right clicking on the pivot table- will 
have
-                    less or more items than it should have after "refresh".
-                2.2) if e.g. trying to sort the items you will get "Cannot 
determine
-                    which PivotTable field to sort by" warning.
-
-        - after exporting the .ods as .xlsx and opening the .xlsx document in 
Excel:
-        the count attribute of rowItems(or colItems) should have the expected 
value.
-        otherwise, context menu on the pivot table will have less/more items
-        than it should have after "refresh". we shouldn't need "refresh" to 
use all
-        functions/items in the context menu.
-    */
-
-    // Row items <rowItems>
-
-    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems", 1);
-    // check if <rowItems count="8">
-    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems", "count", u"8");
-    // check if <rowItems> has enough <i> depending on count attribute value
-    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i", 8);
-    // check if first <i> has single <x/> element
-    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[1]/x:x", 1);
-    // check if <x/> of the first <i> element, has v="0" attribute value
-    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[1]/x:x", "v", 
u"0");
-
-    // Column items <colItems>
-
-    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems", 1);
-    // check if <colItems count="5">
-    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems", "count", u"5");
-    // check if <colItems> has enough <i> depending on count attribute value
-    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i", 5);
-    // check if first <i> has single <x/> element
-    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[1]/x:x", 1);
-    // check if <x/> of the first <i> element, has v="0" attribute value
-    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i[1]/x:x", "v", 
u"0");
-}
-
-CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, 
testTdf123225PivotTableNoColItems)
-{
-    createScDoc("ods/tdf123225_pivotTable_no_col_items.ods");
-    save(TestFilter::XLSX);
-
-    xmlDocUniquePtr pSheet = 
parseExport(u"xl/pivotTables/pivotTable1.xml"_ustr);
-    CPPUNIT_ASSERT(pSheet);
-
-    /*
-        - after exporting the .ods to .xlsx, we should have t="grand" in the
-        last <i> element of the <rowItems> and <colItems>. Otherwise, Excel 
will not
-        have all functions in the context menu of the pivot table. Especially 
for the
-        "Grand Total" column/row cells.
-
-        - additionally, we should always export a single <rowItems> and 
<colItems> regardless of
-        whether the document has row/col items. Otherwise, in Excel, context 
menu on some
-        cells of the pivot table, will not have the expected context menu 
items.
-
-        - this tdf123225_pivotTable_no_col_items.ods document does not have
-        axisCol (DataPilotFieldOrientation_COLUMN) and that means <colItems> 
should not exist
-        during export. But in Excel, if pivot table refreshed, there will be
-
-        <colItems count="1">
-            <i/>
-        </colItems>
-
-        in the xl/pivotTables/pivotTable1.xml. So, that means we should export 
<colItems>
-        without checking the existence of it.
-        For the sake of completeness, <colItems> exported as:
-
-        <colItems count="1">
-            <i t="grand">
-                <x v="0"/>
-            </i>
-        </colItems>
-    */
-
-    // Row items <rowItems>
-
-    // check if <rowItems count="3">
-    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems", "count", u"3");
-    // check if last <i> element, has t="grand"
-    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems/x:i[last()]", "t", 
u"grand");
-
-    // Column items <colItems>
-
-    // check if <colItems count="1">
-    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems", "count", u"1");
-    // check if <colItems> has only a single <i> element
-    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i", 1);
-    // check if <i> element has t="grand"
-    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i", "t", 
u"grand");
-    // check if <i> has <x v="0"/>
-    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems/x:i/x:x", "v", 
u"0");
-}
-
-CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, 
testTdf123225PivotTableEmptyRowColItems)
-{
-    // this doc contains blank row/col items
-    // <sharedItems containsBlank="1" count="..."> 
(xl/pivotCache/pivotCacheDefinition1.xml)
-    createScDoc("ods/tdf123225_pivotTable_empty_row_col_items.ods");
-    save(TestFilter::XLSX);
-
-    xmlDocUniquePtr pSheet = 
parseExport(u"xl/pivotTables/pivotTable1.xml"_ustr);
-    CPPUNIT_ASSERT(pSheet);
-
-    // Row items <rowItems>
-
-    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems", 1);
-    // check if <rowItems count="4">
-    assertXPath(pSheet, "/x:pivotTableDefinition/x:rowItems", "count", u"4");
-
-    // Column items <colItems>
-
-    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems", 1);
-    // check if <colItems count="5">
-    assertXPath(pSheet, "/x:pivotTableDefinition/x:colItems", "count", u"5");
-}
-
 CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, 
testPivotTableNamedRangeSourceODS)
 {
     createScDoc("ods/pivot-table-named-range-source.ods");
diff --git a/sc/source/core/data/pivot/PivotTableResultTraverser.cxx 
b/sc/source/core/data/pivot/PivotTableResultTraverser.cxx
new file mode 100644
index 000000000000..90037e6684e3
--- /dev/null
+++ b/sc/source/core/data/pivot/PivotTableResultTraverser.cxx
@@ -0,0 +1,125 @@
+/* -*- 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 <pivot/PivotTableResultTraverser.hxx>
+
+#include <miscuno.hxx>
+#include <unonames.hxx>
+
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XNamed.hpp>
+
+#include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
+#include <com/sun/star/sheet/DataPilotFieldLayoutMode.hpp>
+#include <com/sun/star/sheet/DataPilotOutputRangeType.hpp>
+#include <com/sun/star/sheet/XDimensionsSupplier.hpp>
+#include <com/sun/star/sheet/XHierarchiesSupplier.hpp>
+#include <com/sun/star/sheet/XLevelsSupplier.hpp>
+#include <com/sun/star/sheet/XDataPilotResults.hpp>
+#include <com/sun/star/sheet/XDataPilotMemberResults.hpp>
+#include <com/sun/star/sheet/MemberResultFlags.hpp>
+#include <com/sun/star/sheet/XMembersSupplier.hpp>
+
+using namespace css;
+
+namespace sc
+{
+namespace pivot
+{
+uno::Any getMemberForLevel(uno::Reference<uno::XInterface> const& xLevel, 
OUString const& rName)
+{
+    uno::Reference<sheet::XMembersSupplier> xMembersSupplier(xLevel, 
uno::UNO_QUERY);
+    if (xMembersSupplier.is())
+    {
+        uno::Reference<sheet::XMembersAccess> xMembers = 
xMembersSupplier->getMembers();
+        if (xMembers.is())
+        {
+            if (xMembers->hasByName(rName))
+                return xMembers->getByName(rName);
+        }
+    }
+    return uno::Any();
+}
+}
+
+// PivotTableResultTraverser
+
+void PivotTableResultTraverser::traverse()
+{
+    uno::Reference<sheet::XDimensionsSupplier> 
xDimensionsSupplier(mrDPObject.GetSource());
+    uno::Reference<container::XIndexAccess> xDimensions
+        = new ScNameToIndexAccess(xDimensionsSupplier->getDimensions());
+
+    for (sal_Int32 nDimension = 0; nDimension < xDimensions->getCount(); 
nDimension++)
+    {
+        uno::Reference<uno::XInterface> 
xDimension(xDimensions->getByIndex(nDimension),
+                                                   uno::UNO_QUERY);
+        uno::Reference<beans::XPropertySet> xDimensionPropertySet(xDimension, 
uno::UNO_QUERY);
+        uno::Reference<sheet::XHierarchiesSupplier> 
xDimensionSupplier(xDimension, uno::UNO_QUERY);
+
+        if (xDimensionPropertySet.is() && xDimensionSupplier.is())
+        {
+            sheet::DataPilotFieldOrientation eDimensionOrientation
+                = ScUnoHelpFunctions::GetEnumProperty(xDimensionPropertySet, 
SC_UNO_DP_ORIENTATION,
+                                                      
sheet::DataPilotFieldOrientation_HIDDEN);
+            mrVisitor.startDimension(nDimension, xDimension, 
eDimensionOrientation);
+
+            if (!mrVisitor.filterOrientation(eDimensionOrientation))
+            {
+                uno::Reference<container::XIndexAccess> xHierarchies
+                    = new 
ScNameToIndexAccess(xDimensionSupplier->getHierarchies());
+                sal_Int32 nHierarchy = 
ScUnoHelpFunctions::GetLongProperty(xDimensionPropertySet,
+                                                                           
SC_UNO_DP_USEDHIERARCHY);
+                if (nHierarchy >= xHierarchies->getCount())
+                    nHierarchy = 0;
+
+                uno::Reference<sheet::XLevelsSupplier> xLevelsSupplier(
+                    xHierarchies->getByIndex(nHierarchy), uno::UNO_QUERY);
+                if (xLevelsSupplier.is())
+                {
+                    uno::Reference<container::XIndexAccess> xLevels
+                        = new 
ScNameToIndexAccess(xLevelsSupplier->getLevels());
+                    if (xLevels.is())
+                    {
+                        for (sal_Int32 nLevel = 0; nLevel < 
xLevels->getCount(); nLevel++)
+                        {
+                            uno::Reference<uno::XInterface> 
xLevel(xLevels->getByIndex(nLevel),
+                                                                   
uno::UNO_QUERY);
+                            uno::Reference<container::XNamed> 
xLevelName(xLevel, uno::UNO_QUERY);
+                            uno::Reference<sheet::XDataPilotMemberResults> 
xLevelResult(
+                                xLevel, uno::UNO_QUERY);
+
+                            if (xLevelName.is() && xLevelResult.is())
+                            {
+                                mrVisitor.startLevel(nLevel, xLevel, 
xLevelName->getName());
+
+                                const uno::Sequence<sheet::MemberResult> 
aSequence
+                                    = xLevelResult->getResults();
+                                sal_Int32 nCurrent = 0;
+                                sal_Int32 nSize = aSequence.getLength();
+                                for (sheet::MemberResult const& rMemberResult 
: aSequence)
+                                {
+                                    mrVisitor.memberResult(rMemberResult, 
nCurrent, nSize);
+                                    nCurrent++;
+                                }
+                                mrVisitor.endLevel();
+                            }
+                        }
+                    }
+                }
+            }
+            mrVisitor.endDimension();
+        }
+    }
+}
+
+} // end sc
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/excel/xepivotxml.cxx 
b/sc/source/filter/excel/xepivotxml.cxx
index 0667ef11347c..5b2596289de0 100644
--- a/sc/source/filter/excel/xepivotxml.cxx
+++ b/sc/source/filter/excel/xepivotxml.cxx
@@ -10,6 +10,7 @@
 #include <xepivotxml.hxx>
 #include <dpcache.hxx>
 #include <pivot/PivotTableFormats.hxx>
+#include <pivot/PivotTableResultTraverser.hxx>
 #include <dpdimsave.hxx>
 #include <dpitemdata.hxx>
 #include <dpobject.hxx>
@@ -30,6 +31,7 @@
 #include <sax/fastattribs.hxx>
 #include <sax/fshelper.hxx>
 #include <svl/numformat.hxx>
+#include <miscuno.hxx>
 
 #include <com/sun/star/beans/XPropertySet.hpp>
 #include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
@@ -37,8 +39,15 @@
 #include <com/sun/star/sheet/DataPilotFieldLayoutMode.hpp>
 #include <com/sun/star/sheet/DataPilotOutputRangeType.hpp>
 #include <com/sun/star/sheet/XDimensionsSupplier.hpp>
+#include <com/sun/star/sheet/XHierarchiesSupplier.hpp>
+#include <com/sun/star/sheet/XLevelsSupplier.hpp>
+#include <com/sun/star/sheet/XDataPilotResults.hpp>
+#include <com/sun/star/sheet/XDataPilotMemberResults.hpp>
+#include <com/sun/star/sheet/MemberResultFlags.hpp>
+#include <com/sun/star/sheet/XMembersSupplier.hpp>
 
 #include <vector>
+#include <unordered_map>
 
 using namespace oox;
 using namespace com::sun::star;
@@ -711,12 +720,233 @@ sal_Int32 GetSubtotalAttrToken(ScGeneralFunction eFunc)
     return XML_defaultSubtotal;
 }
 
+struct RowOrColumnItemsData
+{
+    bool mbSet = false;
+    bool mbContinue = false;
+    bool mbSubtotal = false;
+    bool mbGrandTotal = false;
+    OUString msName;
+    OUString maLevelName;
+};
+
+struct RowOrColumnMemberResultData
+{
+    std::vector<OUString> maFieldOrder;
+    std::vector<std::unordered_map<OUString, RowOrColumnItemsData>> 
maItemsData;
+    std::unordered_map<OUString, std::unordered_map<OUString, sal_Int32>> 
maLookUpIndexForMemberName;
+
+    void ensureItemData(sal_Int32 nSize)
+    {
+        if (maItemsData.size() < o3tl::make_unsigned(nSize))
+            maItemsData.resize(nSize);
+    }
+
+    RowOrColumnItemsData& addItemsData(OUString const& sName, sal_Int32 nIndex)
+    {
+        auto& rItemsMap = maItemsData[nIndex];
+
+        if (!rItemsMap.contains(sName))
+            rItemsMap.emplace(sName, RowOrColumnItemsData());
+
+        return rItemsMap[sName];
+    }
+
+    void initLookupFor(OUString const& sDimensionName)
+    {
+        maLookUpIndexForMemberName.emplace(sDimensionName, 
std::unordered_map<OUString, sal_Int32>{});
+    }
+
+    void addLookupEntryFor(OUString const& sDimensionName, OUString const& 
sMemberName, sal_Int32 nIndex)
+    {
+        maLookUpIndexForMemberName[sDimensionName].emplace(sMemberName, 
nIndex);
+    }
+
+    sal_Int32 lookup(OUString const& sDimensionName, OUString const& 
sMemberName)
+    {
+        return maLookUpIndexForMemberName[sDimensionName][sMemberName];
+    }
+};
+
+class RowColumnItemsDataVisitor : public sc::PivotTableResultVisitor
+{
+    RowOrColumnMemberResultData& mrRowMemberResultData;
+    RowOrColumnMemberResultData& mrColumnMemberResultData;
+
+public:
+    RowColumnItemsDataVisitor(RowOrColumnMemberResultData& 
rRowMemberResultData, RowOrColumnMemberResultData& rColumnMemberResultData)
+        : mrRowMemberResultData(rRowMemberResultData)
+        , mrColumnMemberResultData(rColumnMemberResultData)
+    {}
+
+    sheet::DataPilotFieldOrientation meCurrentOrientation = 
sheet::DataPilotFieldOrientation_HIDDEN;
+    OUString maLevelName;
+
+    bool filterOrientation(sheet::DataPilotFieldOrientation eOrientation) 
override
+    {
+        return eOrientation == sheet::DataPilotFieldOrientation_HIDDEN;
+    }
+
+    void startDimension(sal_Int32 /*nDimensionIndex*/, 
uno::Reference<uno::XInterface> const& /*xDimension*/, 
sheet::DataPilotFieldOrientation eOrientation) override
+    {
+        meCurrentOrientation = eOrientation;
+    }
+
+    void endDimension() override
+    {
+        meCurrentOrientation = sheet::DataPilotFieldOrientation_HIDDEN;
+    }
+
+    void startLevel(sal_Int32 /*nLevelIndex*/, uno::Reference<uno::XInterface> 
const& /*xLevel*/, OUString const& rLevelName) override
+    {
+        maLevelName = rLevelName;
+    }
+
+    void endLevel() override
+    {
+        maLevelName = OUString();
+    }
+
+    void memberResult(sheet::MemberResult const& rResult, sal_Int32 nIndex, 
sal_Int32 nSize) override
+    {
+        if (meCurrentOrientation == sheet::DataPilotFieldOrientation_ROW)
+        {
+            mrRowMemberResultData.ensureItemData(nSize);
+            gatherFieldsData(mrRowMemberResultData, rResult, nIndex);
+        }
+        else if (meCurrentOrientation == 
sheet::DataPilotFieldOrientation_COLUMN)
+        {
+            mrColumnMemberResultData.ensureItemData(nSize);
+            gatherFieldsData(mrColumnMemberResultData, rResult, nIndex);
+        }
+    }
+
+    void gatherFieldsData(RowOrColumnMemberResultData& rMemberResultData, 
sheet::MemberResult const& rResult, sal_Int32 nIndex)
+    {
+        auto& rItemsData = rMemberResultData.addItemsData(maLevelName, nIndex);
+        assert(!rItemsData.mbSet);
+
+        rItemsData.mbSet = true;
+        rItemsData.maLevelName = maLevelName;
+
+        bool bHasContinueFlag = rResult.Flags & 
sheet::MemberResultFlags::CONTINUE;
+        bool bIsGrandTotal = rResult.Flags & 
sheet::MemberResultFlags::GRANDTOTAL;
+        bool bIsSubtotal = rResult.Flags & sheet::MemberResultFlags::SUBTOTAL;
+
+        if (bIsGrandTotal)
+        {
+            rItemsData.mbGrandTotal = true;
+        }
+        else if (bIsSubtotal)
+        {
+            rItemsData.mbSubtotal = true;
+            rItemsData.msName = rResult.Name;
+        }
+        else if (bHasContinueFlag)
+        {
+            rItemsData.mbContinue = true;
+        }
+        else
+        {
+            rItemsData.msName = rResult.Name;
+        }
+    }
+};
+
+void writeRowColumnItems(sal_Int32 nItemElement, RowOrColumnMemberResultData& 
rMemberResultData, sax_fastparser::FSHelperPtr& pStream)
+{
+    if (rMemberResultData.maItemsData.empty() || 
rMemberResultData.maFieldOrder.empty())
+    {
+        pStream->startElement(nItemElement, XML_count, "1");
+        pStream->singleElement(XML_i);
+        pStream->endElement(nItemElement);
+        return;
+    }
+
+    pStream->startElement(nItemElement, XML_count, 
OString::number(rMemberResultData.maItemsData.size()));
+    for (auto& rItemMap : rMemberResultData.maItemsData)
+    {
+        bool bIsGrandTotal = false;
+        bool bIsSubtotal = false;
+
+        for (OUString const& rFieldName : rMemberResultData.maFieldOrder)
+        {
+            RowOrColumnItemsData const& rData = rItemMap[rFieldName];
+            if (rData.mbSubtotal)
+                bIsSubtotal = true;
+            if (rData.mbGrandTotal)
+                bIsGrandTotal = true;
+        }
+
+        {
+            OUString const& rFieldName = rMemberResultData.maFieldOrder[0];
+            RowOrColumnItemsData const& rData = rItemMap[rFieldName];
+            sal_Int32 nIndex = -1;
+            if (!rData.msName.isEmpty())
+                nIndex = rMemberResultData.lookup(rFieldName, rData.msName);
+            if (bIsGrandTotal)
+            {
+                pStream->startElement(XML_i, XML_t, "grand");
+                pStream->singleElement(XML_x);
+            }
+            else if (bIsSubtotal)
+            {
+                pStream->startElement(XML_i, XML_t, "default");
+
+                if (nIndex == 0) // 0 is the default
+                    pStream->singleElement(XML_x);
+                else
+                    pStream->singleElement(XML_x, XML_v, 
OString::number(nIndex));
+            }
+            else if (rData.mbContinue)
+            {
+                pStream->startElement(XML_i, XML_r, "1");
+            }
+            else if (nIndex >= 0)
+            {
+                pStream->startElement(XML_i);
+                if (nIndex == 0) // 0 is the default
+                    pStream->singleElement(XML_x);
+                else
+                    pStream->singleElement(XML_x, XML_v, 
OString::number(nIndex));
+            }
+            else
+            {
+                pStream->startElement(XML_i);
+            }
+        }
+
+        for (size_t i = 1; i < rMemberResultData.maFieldOrder.size(); i++)
+        {
+            OUString const& rItemName = rMemberResultData.maFieldOrder[i];
+            RowOrColumnItemsData const& rData = rItemMap[rItemName];
+
+            sal_Int32 nIndex = -1;
+            if (!rData.msName.isEmpty())
+                nIndex = rMemberResultData.lookup(rItemName, rData.msName);
+
+            if (nIndex >= 0)
+            {
+                if (nIndex == 0) // 0 is the default
+                    pStream->singleElement(XML_x);
+                else
+                    pStream->singleElement(XML_x, XML_v, 
OString::number(nIndex));
+            }
+        }
+
+        pStream->endElement(XML_i);
+    }
+    pStream->endElement(nItemElement);
 }
 
+} // end anonymous namespace
+
 void XclExpXmlPivotTables::SavePivotTableXml( XclExpXmlStream& rStrm, const 
ScDPObject& rDPObj, sal_Int32 nCacheId )
 {
     typedef std::unordered_map<OUString, long> NameToIdMapType;
 
+    auto& rDPObjectModifiable = const_cast<ScDPObject&>(rDPObj);
+
     const XclExpXmlPivotCaches::Entry* pCacheEntry = 
mrCaches.GetCache(nCacheId);
     if (!pCacheEntry)
         // Something is horribly wrong.  Check your logic.
@@ -744,11 +974,9 @@ void XclExpXmlPivotTables::SavePivotTableXml( 
XclExpXmlStream& rStrm, const ScDP
     std::vector<tools::Long> aPageFields;
     std::vector<DataField> aDataFields;
 
-    // we should always export <rowItems> and <colItems>, even if the pivot 
table
-    // does not contain col/row items. otherwise, in Excel, pivot table will 
not
-    // have all context menu items.
-    tools::Long nRowItemsCount = 1; // for <rowItems count="..."> of 
pivotTable*.xml
-    tools::Long nColItemsCount = 1; // for <colItems count="..."> of 
pivotTable*.xml
+    RowOrColumnMemberResultData aRowMemberResultData;
+    RowOrColumnMemberResultData aColumnMemberResultData;
+
     tools::Long nDataDimCount = rSaveData.GetDataDimensionCount();
     // Use dimensions in the save data to get their correct ordering.
     // Dimension order here is significant as they specify the order of
@@ -785,9 +1013,11 @@ void XclExpXmlPivotTables::SavePivotTableXml( 
XclExpXmlStream& rStrm, const ScDP
                 if (nPos == -2 && nDataDimCount <= 1)
                     break;
                 aColFields.push_back(nPos);
+                aColumnMemberResultData.maFieldOrder.push_back(rDim.GetName());
             break;
             case sheet::DataPilotFieldOrientation_ROW:
                 aRowFields.push_back(nPos);
+                aRowMemberResultData.maFieldOrder.push_back(rDim.GetName());
             break;
             case sheet::DataPilotFieldOrientation_PAGE:
                 aPageFields.push_back(nPos);
@@ -833,9 +1063,6 @@ void XclExpXmlPivotTables::SavePivotTableXml( 
XclExpXmlStream& rStrm, const ScDP
 
     // normalize the order to prevent negative row/col counts - just in case.
     aOutRange.PutInOrder();
-    // both start and end cells are included. subtraction excludes the start 
cells, therefore add +1.
-    SCROW pivotTableRowCount = aOutRange.aEnd.Row() - aOutRange.aStart.Row() + 
1;
-    SCCOL pivotTableColCount = aOutRange.aEnd.Col() - aOutRange.aStart.Col() + 
1;
 
     sal_Int32 nFirstHeaderRow = rDPObj.GetHideHeader() ? 0 : 
(rDPObj.GetHeaderLayout() ? 2 : 1);
     sal_Int32 nFirstDataRow = rDPObj.GetHideHeader() ? 1 : 2;
@@ -901,8 +1128,8 @@ void XclExpXmlPivotTables::SavePivotTableXml( 
XclExpXmlStream& rStrm, const ScDP
             {
                 pPivotStrm->singleElement(XML_pivotField,
                     XML_compact, ToPsz10(false),
-                    XML_showAll, ToPsz10(false),
-                    XML_outline, ToPsz10(false));
+                    XML_outline, ToPsz10(false),
+                    XML_showAll, ToPsz10(false));
             }
             else
             {
@@ -924,8 +1151,8 @@ void XclExpXmlPivotTables::SavePivotTableXml( 
XclExpXmlStream& rStrm, const ScDP
                 pPivotStrm->singleElement(XML_pivotField,
                     XML_dataField, ToPsz10(true),
                     XML_compact, ToPsz10(false),
-                    XML_showAll, ToPsz10(false),
-                    XML_outline, ToPsz10(false));
+                    XML_outline, ToPsz10(false),
+                    XML_showAll, ToPsz10(false));
             }
             else
             {
@@ -946,8 +1173,7 @@ void XclExpXmlPivotTables::SavePivotTableXml( 
XclExpXmlStream& rStrm, const ScDP
         std::vector<ScDPLabelData::Member> aMembers;
         {
             // We need to get the members in actual order, getting which 
requires non-const reference here
-            auto& dpo = const_cast<ScDPObject&>(rDPObj);
-            dpo.GetMembers(i, dpo.GetUsedHierarchy(i), aMembers);
+            rDPObjectModifiable.GetMembers(i, 
rDPObjectModifiable.GetUsedHierarchy(i), aMembers);
         }
 
         std::vector<OUString> aCacheFieldItems;
@@ -968,9 +1194,16 @@ void XclExpXmlPivotTables::SavePivotTableXml( 
XclExpXmlStream& rStrm, const ScDP
         {
             aCacheFieldItems = SortGroupItems(rCache, i);
         }
+
+        if (eOrient == sheet::DataPilotFieldOrientation_ROW)
+            aRowMemberResultData.initLookupFor(pDim->GetName());
+        else if (eOrient == sheet::DataPilotFieldOrientation_COLUMN)
+            aColumnMemberResultData.initLookupFor(pDim->GetName());
+
         // The pair contains the member index in cache and if it is hidden
         std::vector< std::pair<size_t, bool> > aMemberSequence;
         std::set<size_t> aUsedCachePositions;
+        sal_Int32 nIndex = 0;
         for (const auto & rMember : aMembers)
         {
             auto it = std::find(aCacheFieldItems.begin(), 
aCacheFieldItems.end(), rMember.maName);
@@ -979,7 +1212,14 @@ void XclExpXmlPivotTables::SavePivotTableXml( 
XclExpXmlStream& rStrm, const ScDP
                 size_t nCachePos = 
static_cast<size_t>(std::distance(aCacheFieldItems.begin(), it));
                 auto aInserted = aUsedCachePositions.insert(nCachePos);
                 if (aInserted.second)
+                {
                     aMemberSequence.emplace_back(std::make_pair(nCachePos, 
!rMember.mbVisible));
+                    if (eOrient == sheet::DataPilotFieldOrientation_ROW)
+                        
aRowMemberResultData.addLookupEntryFor(pDim->GetName(), rMember.maName, nIndex);
+                    else if (eOrient == 
sheet::DataPilotFieldOrientation_COLUMN)
+                        
aColumnMemberResultData.addLookupEntryFor(pDim->GetName(), rMember.maName, 
nIndex);
+                    nIndex++;
+                }
             }
         }
         // Now add all remaining cache items as hidden
@@ -1011,6 +1251,9 @@ void XclExpXmlPivotTables::SavePivotTableXml( 
XclExpXmlStream& rStrm, const ScDP
         if (!bDimInCompactMode)
             pAttList->add(XML_compact, ToPsz10(false));
 
+        if(bDimInTabularMode)
+            pAttList->add(XML_outline, ToPsz10(false));
+
         pAttList->add(XML_showAll, ToPsz10(false));
 
         tools::Long nSubTotalCount = pDim->GetSubTotalsCount();
@@ -1030,8 +1273,7 @@ void XclExpXmlPivotTables::SavePivotTableXml( 
XclExpXmlStream& rStrm, const ScDP
         if (!bHasDefaultSubtotal)
             pAttList->add(XML_defaultSubtotal, ToPsz10(false));
 
-        if(bDimInTabularMode)
-            pAttList->add( XML_outline, ToPsz10(false));
+
         pPivotStrm->startElement(XML_pivotField, pAttList);
 
         sal_uInt32 nItems = aMemberSequence.size() + aSubtotalSequence.size();
@@ -1049,11 +1291,6 @@ void XclExpXmlPivotTables::SavePivotTableXml( 
XclExpXmlStream& rStrm, const ScDP
                 pPivotStrm->singleElement(XML_item, pItemAttList);
             }
 
-            if (strcmp(toOOXMLAxisType(eOrient), "axisCol") == 0)
-                nColItemsCount = pivotTableColCount - nFirstDataCol;
-            else if (strcmp(toOOXMLAxisType(eOrient), "axisRow") == 0)
-                nRowItemsCount = pivotTableRowCount - nFirstDataRow;
-
             for (const OString& sSubtotal : aSubtotalSequence)
             {
                 pPivotStrm->singleElement(XML_item, XML_t, sSubtotal);
@@ -1081,32 +1318,13 @@ void XclExpXmlPivotTables::SavePivotTableXml( 
XclExpXmlStream& rStrm, const ScDP
         pPivotStrm->endElement(XML_rowFields);
     }
 
-    // <rowItems>
-    if (nRowItemsCount > 0)
-    {
-        pPivotStrm->startElement(XML_rowItems, XML_count, 
OString::number(nRowItemsCount));
-
-        // export nRowItemsCount times <i> and <x> elements
-        for (tools::Long nCount = 0; nCount < nRowItemsCount; ++nCount)
-        {
-            /* we should add t="grand" to the last <i> element. Otherwise, 
Excel will not
-            have all functions in the context menu of the pivot table. 
Especially for the
-            "Grand Total" column/row cells.
-
-            note: it is not completely clear that the last <i> element always 
gets t="grand".
-            however, testing on the same docs indicate that t="grand" should be
-            in the last element, so let's try this here. */
-            if (nCount == nRowItemsCount - 1)
-                pPivotStrm->startElement(XML_i, XML_t, "grand");
-            else
-                pPivotStrm->startElement(XML_i);
+    RowColumnItemsDataVisitor aVisitor(aRowMemberResultData, 
aColumnMemberResultData);
+    sc::PivotTableResultTraverser aTraverser(rDPObjectModifiable, aVisitor);
+    aTraverser.traverse();
 
-            pPivotStrm->singleElement(XML_x, XML_v, OString::number(nCount));
-            pPivotStrm->endElement(XML_i);
-        }
+    // <rowItems>
 
-        pPivotStrm->endElement(XML_rowItems);
-    }
+    writeRowColumnItems(XML_rowItems, aRowMemberResultData, pPivotStrm);
 
     // <colFields>
 
@@ -1124,31 +1342,8 @@ void XclExpXmlPivotTables::SavePivotTableXml( 
XclExpXmlStream& rStrm, const ScDP
     }
 
     // <colItems>
-    if (nColItemsCount > 0)
-    {
-        pPivotStrm->startElement(XML_colItems, XML_count, 
OString::number(nColItemsCount));
-
-        // export nColItemsCount times <i> and <x> elements
-        for (tools::Long nCount = 0; nCount < nColItemsCount; ++nCount)
-        {
-            /* we should add t="grand" to the last <i> element. Otherwise, 
Excel will not
-            have all functions in the context menu of the pivot table. 
Especially for the
-            "Grand Total" column/row cells.
-
-            note: it is not completely clear that the last <i> element always 
gets t="grand".
-            however, testing on the some docs indicate that t="grand" should be
-            in the last element, so let's try this here. */
-            if (nCount == nColItemsCount - 1)
-                pPivotStrm->startElement(XML_i, XML_t, "grand");
-            else
-                pPivotStrm->startElement(XML_i);
-
-            pPivotStrm->singleElement(XML_x, XML_v, OString::number(nCount));
-            pPivotStrm->endElement(XML_i);
-        }
 
-        pPivotStrm->endElement(XML_colItems);
-    }
+    writeRowColumnItems(XML_colItems, aColumnMemberResultData, pPivotStrm);
 
     // <pageFields>
 

Reply via email to