sc/inc/dpobject.hxx                                         |    4 
 sc/inc/dpoutput.hxx                                         |    3 
 sc/qa/unit/PivotTableFormatsImportExport.cxx                |   60 +++---
 sc/qa/unit/data/xlsx/pivot-table/first_header_row_zero.xlsx |binary
 sc/qa/unit/pivottable_filters_test.cxx                      |  105 ++++++------
 sc/source/core/data/dpobject.cxx                            |    7 
 sc/source/core/data/dpoutput.cxx                            |   20 +-
 sc/source/filter/excel/xepivotxml.cxx                       |    4 
 sc/source/filter/oox/pivottablebuffer.cxx                   |    2 
 9 files changed, 118 insertions(+), 87 deletions(-)

New commits:
commit cd4498d32867af26e95de84836b724b4f85ba1b0
Author:     Jaume Pujantell <jaume.pujant...@collabora.com>
AuthorDate: Tue Aug 13 20:30:56 2024 +0200
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Sun Aug 18 22:35:50 2024 +0200

    tdf#162466 calc: added handling of firstHeaderRow="0" on xlsx files
    
    Calc ignored the firstHeaderRow attibute on xlsx pivot tables causing
    it to add an extra row when firstHeaderRow="0". And then changed the
    value to "1" on export.
    
    Some xlsx pivot table filter tests have been changed because removing
    this extra row changed the position of the values.
    
    Change-Id: I95b722e4f4cc40083c752a045df4ffe37e7159c5
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/171836
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/171869
    Tested-by: Jenkins

diff --git a/sc/inc/dpobject.hxx b/sc/inc/dpobject.hxx
index 06ffc0085cf2..ce05a46f7c6b 100644
--- a/sc/inc/dpobject.hxx
+++ b/sc/inc/dpobject.hxx
@@ -107,6 +107,7 @@ private:
     bool mbAllowMove : 1;
     bool mbSettingsChanged : 1;
     bool mbEnableGetPivotData : 1;
+    bool mbHideHeader : 1 = false;
 
     void              CreateObjects();
     void              CreateOutput();
@@ -148,6 +149,9 @@ public:
     SC_DLLPUBLIC void   SetHeaderLayout(bool bUseGrid);
     bool                GetHeaderLayout() const { return mbHeaderLayout;}
 
+    SC_DLLPUBLIC void SetHideHeader(bool bHideHeader);
+    bool GetHideHeader() const { return mbHideHeader; }
+
     SC_DLLPUBLIC void   SetSheetDesc(const ScSheetSourceDesc& rDesc);
     void                SetImportDesc(const ScImportSourceDesc& rDesc);
     void                SetServiceData(const ScDPServiceDesc& rDesc);
diff --git a/sc/inc/dpoutput.hxx b/sc/inc/dpoutput.hxx
index 11251afd4fdf..29423ab66c57 100644
--- a/sc/inc/dpoutput.hxx
+++ b/sc/inc/dpoutput.hxx
@@ -88,6 +88,7 @@ private:
     bool mbHeaderLayout:1;  // true : grid, false : standard
     bool mbHasCompactRowField:1; // true: at least one of the row fields has 
compact layout.
     bool mbExpandCollapse:1; // true: show expand/collapse buttons
+    bool mbHideHeader : 1;
 
     void            DataCell( SCCOL nCol, SCROW nRow, SCTAB nTab,
                                 const css::sheet::DataResult& rData );
@@ -120,7 +121,7 @@ public:
     ScDPOutput(ScDocument* pDocument,
                css::uno::Reference<css::sheet::XDimensionsSupplier> xSource,
                const ScAddress& rPosition, bool bFilter, bool bExpandCollapse,
-               ScDPObject& rObject);
+               ScDPObject& rObject, bool bHideHeader);
     ~ScDPOutput();
 
     void            SetPosition( const ScAddress& rPos );
diff --git a/sc/qa/unit/PivotTableFormatsImportExport.cxx 
b/sc/qa/unit/PivotTableFormatsImportExport.cxx
index 3c3b9414d29e..22d56c0f11d6 100644
--- a/sc/qa/unit/PivotTableFormatsImportExport.cxx
+++ b/sc/qa/unit/PivotTableFormatsImportExport.cxx
@@ -122,13 +122,13 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport,
 
 static void assertDataFieldInColumn_ColumnLabelColor(ScDocument& rDoc)
 {
-    CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, getFontColor(rDoc, u"H5"_ustr));
-    CPPUNIT_ASSERT_EQUAL(Color(0x92D050), getBackgroundColor(rDoc, 
u"I5"_ustr));
+    CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, getFontColor(rDoc, u"H4"_ustr));
+    CPPUNIT_ASSERT_EQUAL(Color(0x92D050), getBackgroundColor(rDoc, 
u"I4"_ustr));
 
     // Make sure the other cells have the font color or background set to 
default
     std::vector<OUString> aEmptyAddresses{
-        u"G5"_ustr, u"G6"_ustr, u"H6"_ustr, u"I6"_ustr, u"G7"_ustr, 
u"H7"_ustr, u"I7"_ustr,
-        u"G8"_ustr, u"H8"_ustr, u"I8"_ustr, u"G9"_ustr, u"H9"_ustr, u"I9"_ustr,
+        u"G4"_ustr, u"G5"_ustr, u"H5"_ustr, u"I5"_ustr, u"G6"_ustr, 
u"H6"_ustr, u"I6"_ustr,
+        u"G7"_ustr, u"H7"_ustr, u"I7"_ustr, u"G8"_ustr, u"H8"_ustr, u"I8"_ustr,
     };
     CPPUNIT_ASSERT_EQUAL(OUString(), checkNonEmptyAddresses(rDoc, 
aEmptyAddresses));
 }
@@ -145,12 +145,12 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport,
 
 static void assertDataFieldInColumn_DataColor(ScDocument& rDoc)
 {
-    CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, getFontColor(rDoc, u"H7"_ustr));
-    CPPUNIT_ASSERT_EQUAL(Color(0x92D050), getBackgroundColor(rDoc, 
u"I9"_ustr));
+    CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, getFontColor(rDoc, u"H6"_ustr));
+    CPPUNIT_ASSERT_EQUAL(Color(0x92D050), getBackgroundColor(rDoc, 
u"I8"_ustr));
 
     std::vector<OUString> aEmptyAddresses{
-        u"G5"_ustr, u"H5"_ustr, u"I5"_ustr, u"G6"_ustr, u"H6"_ustr, 
u"I6"_ustr, u"G7"_ustr,
-        u"I7"_ustr, u"G8"_ustr, u"H8"_ustr, u"I8"_ustr, u"G9"_ustr, u"H9"_ustr,
+        u"G4"_ustr, u"H4"_ustr, u"I4"_ustr, u"G5"_ustr, u"H5"_ustr, 
u"I5"_ustr, u"G6"_ustr,
+        u"I6"_ustr, u"G7"_ustr, u"H7"_ustr, u"I7"_ustr, u"G8"_ustr, u"H8"_ustr,
     };
     CPPUNIT_ASSERT_EQUAL(OUString(), checkNonEmptyAddresses(rDoc, 
aEmptyAddresses));
 }
@@ -166,17 +166,17 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport,
 
 static void assertDataFieldInColumnAndTwoRowFields_DataColor(ScDocument& rDoc)
 {
-    CPPUNIT_ASSERT_EQUAL(COL_YELLOW, getBackgroundColor(rDoc, u"I8"_ustr));
-    CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, getBackgroundColor(rDoc, u"I11"_ustr));
-    CPPUNIT_ASSERT_EQUAL(Color(0x0070C0), getBackgroundColor(rDoc, 
u"J13"_ustr));
+    CPPUNIT_ASSERT_EQUAL(COL_YELLOW, getBackgroundColor(rDoc, u"I7"_ustr));
+    CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, getBackgroundColor(rDoc, u"I10"_ustr));
+    CPPUNIT_ASSERT_EQUAL(Color(0x0070C0), getBackgroundColor(rDoc, 
u"J12"_ustr));
 
     std::vector<OUString> aEmptyAddresses{
-        u"G5"_ustr,  u"H5"_ustr,  u"I5"_ustr,  u"J5"_ustr,  u"G6"_ustr,  
u"H6"_ustr,  u"I6"_ustr,
-        u"J6"_ustr,  u"G7"_ustr,  u"H7"_ustr,  u"I7"_ustr,  u"J7"_ustr,  
u"G8"_ustr,  u"H8"_ustr,
-        u"J8"_ustr,  u"G9"_ustr,  u"H9"_ustr,  u"I9"_ustr,  u"J9"_ustr,  
u"G10"_ustr, u"H10"_ustr,
-        u"I10"_ustr, u"J10"_ustr, u"G11"_ustr, u"H11"_ustr, u"J11"_ustr, 
u"G12"_ustr, u"H12"_ustr,
-        u"I12"_ustr, u"J12"_ustr, u"G13"_ustr, u"H13"_ustr, u"I13"_ustr, 
u"G14"_ustr, u"H14"_ustr,
-        u"I14"_ustr, u"J14"_ustr,
+        u"G4"_ustr,  u"H4"_ustr,  u"I4"_ustr,  u"J4"_ustr,  u"G5"_ustr,  
u"H5"_ustr,  u"I5"_ustr,
+        u"J5"_ustr,  u"G6"_ustr,  u"H6"_ustr,  u"I6"_ustr,  u"J6"_ustr,  
u"G7"_ustr,  u"H7"_ustr,
+        u"J7"_ustr,  u"G8"_ustr,  u"H8"_ustr,  u"I8"_ustr,  u"J8"_ustr,  
u"G9"_ustr,  u"H9"_ustr,
+        u"I9"_ustr,  u"J9"_ustr,  u"G10"_ustr, u"H10"_ustr, u"J10"_ustr, 
u"G11"_ustr, u"H11"_ustr,
+        u"I11"_ustr, u"J11"_ustr, u"G12"_ustr, u"H12"_ustr, u"I12"_ustr, 
u"G13"_ustr, u"H13"_ustr,
+        u"I13"_ustr, u"J13"_ustr,
     };
     CPPUNIT_ASSERT_EQUAL(OUString(), checkNonEmptyAddresses(rDoc, 
aEmptyAddresses));
 }
@@ -251,9 +251,9 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport,
 
 static void assertMultipleSelections(ScDocument& rDoc)
 {
+    CPPUNIT_ASSERT_EQUAL(COL_YELLOW, getBackgroundColor(rDoc, u"I5"_ustr));
     CPPUNIT_ASSERT_EQUAL(COL_YELLOW, getBackgroundColor(rDoc, u"I6"_ustr));
     CPPUNIT_ASSERT_EQUAL(COL_YELLOW, getBackgroundColor(rDoc, u"I7"_ustr));
-    CPPUNIT_ASSERT_EQUAL(COL_YELLOW, getBackgroundColor(rDoc, u"I8"_ustr));
 }
 
 CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport,
@@ -363,17 +363,17 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport,
 
 static void assertTwoRowsDataFieldInColumn_LabelColor(ScDocument& rDoc)
 {
-    CPPUNIT_ASSERT_EQUAL(COL_YELLOW, getBackgroundColor(rDoc, u"I5"_ustr));
-    CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, getBackgroundColor(rDoc, u"J5"_ustr));
+    CPPUNIT_ASSERT_EQUAL(COL_YELLOW, getBackgroundColor(rDoc, u"I4"_ustr));
+    CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, getBackgroundColor(rDoc, u"J4"_ustr));
 
     // Make sure the other cells have the font color or background set to 
default
     std::vector<OUString> aEmptyAddresses{
-        u"G5"_ustr,  u"H5"_ustr,  u"G6"_ustr,  u"H6"_ustr,  u"i6"_ustr,  
u"j6"_ustr,  u"G7"_ustr,
-        u"H7"_ustr,  u"i7"_ustr,  u"j7"_ustr,  u"G8"_ustr,  u"H8"_ustr,  
u"i8"_ustr,  u"j8"_ustr,
-        u"G9"_ustr,  u"H9"_ustr,  u"i9"_ustr,  u"j9"_ustr,  u"G10"_ustr, 
u"H10"_ustr, u"i10"_ustr,
-        u"j10"_ustr, u"G11"_ustr, u"H11"_ustr, u"i11"_ustr, u"j11"_ustr, 
u"G12"_ustr, u"H12"_ustr,
-        u"i12"_ustr, u"j12"_ustr, u"G13"_ustr, u"H13"_ustr, u"i13"_ustr, 
u"j13"_ustr, u"G14"_ustr,
-        u"H14"_ustr, u"i14"_ustr, u"j14"_ustr,
+        u"G4"_ustr,  u"H4"_ustr,  u"G5"_ustr,  u"H5"_ustr,  u"i5"_ustr,  
u"j5"_ustr,  u"G6"_ustr,
+        u"H6"_ustr,  u"i6"_ustr,  u"j6"_ustr,  u"G7"_ustr,  u"H7"_ustr,  
u"i7"_ustr,  u"j7"_ustr,
+        u"G8"_ustr,  u"H8"_ustr,  u"i8"_ustr,  u"j8"_ustr,  u"G9"_ustr,  
u"H9"_ustr,  u"i9"_ustr,
+        u"j9"_ustr,  u"G10"_ustr, u"H10"_ustr, u"i10"_ustr, u"j10"_ustr, 
u"G11"_ustr, u"H11"_ustr,
+        u"i11"_ustr, u"j11"_ustr, u"G12"_ustr, u"H12"_ustr, u"i12"_ustr, 
u"j12"_ustr, u"G13"_ustr,
+        u"H13"_ustr, u"i13"_ustr, u"j13"_ustr,
     };
     CPPUNIT_ASSERT_EQUAL(OUString(), checkNonEmptyAddresses(rDoc, 
aEmptyAddresses));
 }
@@ -390,18 +390,18 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport,
 
 static void assertTwoDataFieldColumns_WholeDataColumnSelected(ScDocument& rDoc)
 {
+    CPPUNIT_ASSERT_EQUAL(COL_YELLOW, getBackgroundColor(rDoc, u"H2"_ustr));
     CPPUNIT_ASSERT_EQUAL(COL_YELLOW, getBackgroundColor(rDoc, u"H3"_ustr));
     CPPUNIT_ASSERT_EQUAL(COL_YELLOW, getBackgroundColor(rDoc, u"H4"_ustr));
     CPPUNIT_ASSERT_EQUAL(COL_YELLOW, getBackgroundColor(rDoc, u"H5"_ustr));
     CPPUNIT_ASSERT_EQUAL(COL_YELLOW, getBackgroundColor(rDoc, u"H6"_ustr));
     CPPUNIT_ASSERT_EQUAL(COL_YELLOW, getBackgroundColor(rDoc, u"H7"_ustr));
-    CPPUNIT_ASSERT_EQUAL(COL_YELLOW, getBackgroundColor(rDoc, u"H8"_ustr));
 
     // Make sure the other cells have the font color or background set to 
default
     std::vector<OUString> aEmptyAddresses{
-        u"F1"_ustr, u"G1"_ustr, u"H1"_ustr, u"F2"_ustr, u"G2"_ustr, u"H2"_ustr,
-        u"F3"_ustr, u"G3"_ustr, u"F4"_ustr, u"G4"_ustr, u"F5"_ustr, u"G5"_ustr,
-        u"F6"_ustr, u"G6"_ustr, u"F7"_ustr, u"G7"_ustr, u"F8"_ustr, u"G8"_ustr,
+        u"F1"_ustr, u"G1"_ustr, u"H1"_ustr, u"F2"_ustr, u"G2"_ustr,
+        u"F3"_ustr, u"G3"_ustr, u"F4"_ustr, u"G4"_ustr, u"F5"_ustr,
+        u"G5"_ustr, u"F6"_ustr, u"G6"_ustr, u"F7"_ustr, u"G7"_ustr,
     };
     CPPUNIT_ASSERT_EQUAL(OUString(), checkNonEmptyAddresses(rDoc, 
aEmptyAddresses));
 }
diff --git a/sc/qa/unit/data/xlsx/pivot-table/first_header_row_zero.xlsx 
b/sc/qa/unit/data/xlsx/pivot-table/first_header_row_zero.xlsx
new file mode 100644
index 000000000000..9660f6354b88
Binary files /dev/null and 
b/sc/qa/unit/data/xlsx/pivot-table/first_header_row_zero.xlsx differ
diff --git a/sc/qa/unit/pivottable_filters_test.cxx 
b/sc/qa/unit/pivottable_filters_test.cxx
index 17391890e4f6..e6b49591b9c3 100644
--- a/sc/qa/unit/pivottable_filters_test.cxx
+++ b/sc/qa/unit/pivottable_filters_test.cxx
@@ -329,22 +329,22 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, 
testPivotTableSharedGroupXLSX)
 
     // Check whether right group names are imported for both tables
     // First table
-    CPPUNIT_ASSERT_EQUAL(u"a2"_ustr, pDoc->GetString(ScAddress(0, 1, 0)));
-    CPPUNIT_ASSERT_EQUAL(u"Csoport1"_ustr, pDoc->GetString(ScAddress(0, 2, 
0)));
-    CPPUNIT_ASSERT_EQUAL(u"Csoport2"_ustr, pDoc->GetString(ScAddress(0, 3, 
0)));
-    CPPUNIT_ASSERT_EQUAL(u"Csoport3"_ustr, pDoc->GetString(ScAddress(0, 4, 
0)));
-    CPPUNIT_ASSERT_EQUAL(u"16"_ustr, pDoc->GetString(ScAddress(0, 5, 0)));
-    CPPUNIT_ASSERT_EQUAL(u"17"_ustr, pDoc->GetString(ScAddress(0, 6, 0)));
-    CPPUNIT_ASSERT_EQUAL(u"18"_ustr, pDoc->GetString(ScAddress(0, 7, 0)));
+    CPPUNIT_ASSERT_EQUAL(u"a2"_ustr, pDoc->GetString(ScAddress(0, 0, 0)));
+    CPPUNIT_ASSERT_EQUAL(u"Csoport1"_ustr, pDoc->GetString(ScAddress(0, 1, 
0)));
+    CPPUNIT_ASSERT_EQUAL(u"Csoport2"_ustr, pDoc->GetString(ScAddress(0, 2, 
0)));
+    CPPUNIT_ASSERT_EQUAL(u"Csoport3"_ustr, pDoc->GetString(ScAddress(0, 3, 
0)));
+    CPPUNIT_ASSERT_EQUAL(u"16"_ustr, pDoc->GetString(ScAddress(0, 4, 0)));
+    CPPUNIT_ASSERT_EQUAL(u"17"_ustr, pDoc->GetString(ScAddress(0, 5, 0)));
+    CPPUNIT_ASSERT_EQUAL(u"18"_ustr, pDoc->GetString(ScAddress(0, 6, 0)));
 
     // Second table
-    CPPUNIT_ASSERT_EQUAL(u"a2"_ustr, pDoc->GetString(ScAddress(0, 11, 0)));
-    CPPUNIT_ASSERT_EQUAL(u"Csoport1"_ustr, pDoc->GetString(ScAddress(0, 12, 
0)));
-    CPPUNIT_ASSERT_EQUAL(u"Csoport2"_ustr, pDoc->GetString(ScAddress(0, 13, 
0)));
-    CPPUNIT_ASSERT_EQUAL(u"Csoport3"_ustr, pDoc->GetString(ScAddress(0, 14, 
0)));
-    CPPUNIT_ASSERT_EQUAL(u"16"_ustr, pDoc->GetString(ScAddress(0, 15, 0)));
-    CPPUNIT_ASSERT_EQUAL(u"17"_ustr, pDoc->GetString(ScAddress(0, 16, 0)));
-    CPPUNIT_ASSERT_EQUAL(u"18"_ustr, pDoc->GetString(ScAddress(0, 17, 0)));
+    CPPUNIT_ASSERT_EQUAL(u"a2"_ustr, pDoc->GetString(ScAddress(0, 10, 0)));
+    CPPUNIT_ASSERT_EQUAL(u"Csoport1"_ustr, pDoc->GetString(ScAddress(0, 11, 
0)));
+    CPPUNIT_ASSERT_EQUAL(u"Csoport2"_ustr, pDoc->GetString(ScAddress(0, 12, 
0)));
+    CPPUNIT_ASSERT_EQUAL(u"Csoport3"_ustr, pDoc->GetString(ScAddress(0, 13, 
0)));
+    CPPUNIT_ASSERT_EQUAL(u"16"_ustr, pDoc->GetString(ScAddress(0, 14, 0)));
+    CPPUNIT_ASSERT_EQUAL(u"17"_ustr, pDoc->GetString(ScAddress(0, 15, 0)));
+    CPPUNIT_ASSERT_EQUAL(u"18"_ustr, pDoc->GetString(ScAddress(0, 16, 0)));
 
     // There should be exactly 2 pivot tables and 1 cache.
     ScDPCollection* pDPs = pDoc->GetDPCollection();
@@ -364,22 +364,22 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, 
testPivotTableSharedDateGroupXLSX)
     auto testThis = [](ScDocument& rDoc) {
         // Check whether right date labels are imported for both tables
         // First table
-        CPPUNIT_ASSERT_EQUAL(u"a"_ustr, rDoc.GetString(ScAddress(0, 3, 1)));
-        CPPUNIT_ASSERT_EQUAL(u"1965"_ustr, rDoc.GetString(ScAddress(0, 4, 1)));
-        CPPUNIT_ASSERT_EQUAL(u"1989"_ustr, rDoc.GetString(ScAddress(0, 5, 1)));
-        CPPUNIT_ASSERT_EQUAL(u"2000"_ustr, rDoc.GetString(ScAddress(0, 6, 1)));
-        CPPUNIT_ASSERT_EQUAL(u"2004"_ustr, rDoc.GetString(ScAddress(0, 7, 1)));
+        CPPUNIT_ASSERT_EQUAL(u"a"_ustr, rDoc.GetString(ScAddress(0, 2, 1)));
+        CPPUNIT_ASSERT_EQUAL(u"1965"_ustr, rDoc.GetString(ScAddress(0, 3, 1)));
+        CPPUNIT_ASSERT_EQUAL(u"1989"_ustr, rDoc.GetString(ScAddress(0, 4, 1)));
+        CPPUNIT_ASSERT_EQUAL(u"2000"_ustr, rDoc.GetString(ScAddress(0, 5, 1)));
+        CPPUNIT_ASSERT_EQUAL(u"2004"_ustr, rDoc.GetString(ScAddress(0, 6, 1)));
         // TODO: check why this fails with 2005
-        // CPPUNIT_ASSERT_EQUAL(OUString("2007"), 
rDoc.GetString(ScAddress(0,8,1)));
+        // CPPUNIT_ASSERT_EQUAL(OUString("2007"), 
rDoc.GetString(ScAddress(0,7,1)));
 
         // Second table
-        CPPUNIT_ASSERT_EQUAL(u"a"_ustr, rDoc.GetString(ScAddress(5, 3, 1)));
-        CPPUNIT_ASSERT_EQUAL(u"1965"_ustr, rDoc.GetString(ScAddress(5, 4, 1)));
-        CPPUNIT_ASSERT_EQUAL(u"1989"_ustr, rDoc.GetString(ScAddress(5, 5, 1)));
-        CPPUNIT_ASSERT_EQUAL(u"2000"_ustr, rDoc.GetString(ScAddress(5, 6, 1)));
-        CPPUNIT_ASSERT_EQUAL(u"2004"_ustr, rDoc.GetString(ScAddress(5, 7, 1)));
+        CPPUNIT_ASSERT_EQUAL(u"a"_ustr, rDoc.GetString(ScAddress(5, 2, 1)));
+        CPPUNIT_ASSERT_EQUAL(u"1965"_ustr, rDoc.GetString(ScAddress(5, 3, 1)));
+        CPPUNIT_ASSERT_EQUAL(u"1989"_ustr, rDoc.GetString(ScAddress(5, 4, 1)));
+        CPPUNIT_ASSERT_EQUAL(u"2000"_ustr, rDoc.GetString(ScAddress(5, 5, 1)));
+        CPPUNIT_ASSERT_EQUAL(u"2004"_ustr, rDoc.GetString(ScAddress(5, 6, 1)));
         // TODO: check why this fails with 2005
-        // CPPUNIT_ASSERT_EQUAL(OUString("2007"), 
rDoc.GetString(ScAddress(5,8,1)));
+        // CPPUNIT_ASSERT_EQUAL(OUString("2007"), 
rDoc.GetString(ScAddress(5,7,1)));
 
         // There should be exactly 2 pivot tables and 1 cache.
         ScDPCollection* pDPs = rDoc.GetDPCollection();
@@ -405,19 +405,19 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, 
testPivotTableSharedNestedDateGrou
         // Check whether right date groups are imported for both tables
         // First table
         // Years, Quarters, 'a' have compact layout so the only header 
contains a multi-field filter.
-        CPPUNIT_ASSERT_EQUAL(u"1965"_ustr, rDoc.GetString(ScAddress(0, 4, 1)));
-        CPPUNIT_ASSERT_EQUAL(u"1989"_ustr, rDoc.GetString(ScAddress(0, 11, 
1)));
-        CPPUNIT_ASSERT_EQUAL(u"2000"_ustr, rDoc.GetString(ScAddress(0, 18, 
1)));
-        CPPUNIT_ASSERT_EQUAL(u"2004"_ustr, rDoc.GetString(ScAddress(0, 21, 
1)));
+        CPPUNIT_ASSERT_EQUAL(u"1965"_ustr, rDoc.GetString(ScAddress(0, 3, 1)));
+        CPPUNIT_ASSERT_EQUAL(u"1989"_ustr, rDoc.GetString(ScAddress(0, 10, 
1)));
+        CPPUNIT_ASSERT_EQUAL(u"2000"_ustr, rDoc.GetString(ScAddress(0, 17, 
1)));
+        CPPUNIT_ASSERT_EQUAL(u"2004"_ustr, rDoc.GetString(ScAddress(0, 20, 
1)));
         // TODO: check why this fails with the empty string
         //CPPUNIT_ASSERT_EQUAL(OUString("2007"), 
rDoc.GetString(ScAddress(0,32,1)));
 
         // Second table
         // Years, Quarters, 'a' have compact layout so the only row header 
contains a multi-field filter.
-        CPPUNIT_ASSERT_EQUAL(u"1965"_ustr, rDoc.GetString(ScAddress(6, 4, 1)));
-        CPPUNIT_ASSERT_EQUAL(u"1989"_ustr, rDoc.GetString(ScAddress(6, 11, 
1)));
-        CPPUNIT_ASSERT_EQUAL(u"2000"_ustr, rDoc.GetString(ScAddress(6, 18, 
1)));
-        CPPUNIT_ASSERT_EQUAL(u"2004"_ustr, rDoc.GetString(ScAddress(6, 21, 
1)));
+        CPPUNIT_ASSERT_EQUAL(u"1965"_ustr, rDoc.GetString(ScAddress(6, 3, 1)));
+        CPPUNIT_ASSERT_EQUAL(u"1989"_ustr, rDoc.GetString(ScAddress(6, 10, 
1)));
+        CPPUNIT_ASSERT_EQUAL(u"2000"_ustr, rDoc.GetString(ScAddress(6, 17, 
1)));
+        CPPUNIT_ASSERT_EQUAL(u"2004"_ustr, rDoc.GetString(ScAddress(6, 20, 
1)));
         // TODO: check why this fails with the empty string
         //CPPUNIT_ASSERT_EQUAL(OUString("2007"), 
rDoc.GetString(ScAddress(6,31,1)));
 
@@ -449,20 +449,20 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, 
testPivotTableSharedNumGroupXLSX)
 
     // Check whether right number groups are imported for both tables
     // First table
-    CPPUNIT_ASSERT_EQUAL(u"f"_ustr, pDoc->GetString(ScAddress(0, 3, 1)));
-    CPPUNIT_ASSERT_EQUAL(u"32674-47673"_ustr, pDoc->GetString(ScAddress(0, 4, 
1)));
-    CPPUNIT_ASSERT_EQUAL(u"47674-62673"_ustr, pDoc->GetString(ScAddress(0, 5, 
1)));
-    CPPUNIT_ASSERT_EQUAL(u"62674-77673"_ustr, pDoc->GetString(ScAddress(0, 6, 
1)));
-    CPPUNIT_ASSERT_EQUAL(u"77674-92673"_ustr, pDoc->GetString(ScAddress(0, 7, 
1)));
-    CPPUNIT_ASSERT_EQUAL(u"92674-107673"_ustr, pDoc->GetString(ScAddress(0, 8, 
1)));
+    CPPUNIT_ASSERT_EQUAL(u"f"_ustr, pDoc->GetString(ScAddress(0, 2, 1)));
+    CPPUNIT_ASSERT_EQUAL(u"32674-47673"_ustr, pDoc->GetString(ScAddress(0, 3, 
1)));
+    CPPUNIT_ASSERT_EQUAL(u"47674-62673"_ustr, pDoc->GetString(ScAddress(0, 4, 
1)));
+    CPPUNIT_ASSERT_EQUAL(u"62674-77673"_ustr, pDoc->GetString(ScAddress(0, 5, 
1)));
+    CPPUNIT_ASSERT_EQUAL(u"77674-92673"_ustr, pDoc->GetString(ScAddress(0, 6, 
1)));
+    CPPUNIT_ASSERT_EQUAL(u"92674-107673"_ustr, pDoc->GetString(ScAddress(0, 7, 
1)));
 
     // Second table
-    CPPUNIT_ASSERT_EQUAL(u"f"_ustr, pDoc->GetString(ScAddress(5, 3, 1)));
-    CPPUNIT_ASSERT_EQUAL(u"32674-47673"_ustr, pDoc->GetString(ScAddress(5, 4, 
1)));
-    CPPUNIT_ASSERT_EQUAL(u"47674-62673"_ustr, pDoc->GetString(ScAddress(5, 5, 
1)));
-    CPPUNIT_ASSERT_EQUAL(u"62674-77673"_ustr, pDoc->GetString(ScAddress(5, 6, 
1)));
-    CPPUNIT_ASSERT_EQUAL(u"77674-92673"_ustr, pDoc->GetString(ScAddress(5, 7, 
1)));
-    CPPUNIT_ASSERT_EQUAL(u"92674-107673"_ustr, pDoc->GetString(ScAddress(5, 8, 
1)));
+    CPPUNIT_ASSERT_EQUAL(u"f"_ustr, pDoc->GetString(ScAddress(5, 2, 1)));
+    CPPUNIT_ASSERT_EQUAL(u"32674-47673"_ustr, pDoc->GetString(ScAddress(5, 3, 
1)));
+    CPPUNIT_ASSERT_EQUAL(u"47674-62673"_ustr, pDoc->GetString(ScAddress(5, 4, 
1)));
+    CPPUNIT_ASSERT_EQUAL(u"62674-77673"_ustr, pDoc->GetString(ScAddress(5, 5, 
1)));
+    CPPUNIT_ASSERT_EQUAL(u"77674-92673"_ustr, pDoc->GetString(ScAddress(5, 6, 
1)));
+    CPPUNIT_ASSERT_EQUAL(u"92674-107673"_ustr, pDoc->GetString(ScAddress(5, 7, 
1)));
 
     // There should be exactly 2 pivot tables and 1 cache.
     ScDPCollection* pDPs = pDoc->GetDPCollection();
@@ -2714,6 +2714,19 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest,
     testThis(*getScDoc());
 }
 
+CPPUNIT_TEST_FIXTURE(ScPivotTableFiltersTest, testFirstHeaderRowZero)
+{
+    // Test that an xlsx pivot table with `firstHeaderRow="0"` is shown and 
exported correctly
+    createScDoc("xlsx/pivot-table/first_header_row_zero.xlsx");
+    // Check that the text under the table is visible
+    CPPUNIT_ASSERT_EQUAL(OUString("under"), getScDoc()->GetString(ScAddress(2, 
6, 1)));
+
+    save("Calc Office Open XML");
+    xmlDocUniquePtr pDoc = parseExport("xl/pivotTables/pivotTable1.xml");
+    CPPUNIT_ASSERT(pDoc);
+    assertXPath(pDoc, "/x:pivotTableDefinition/x:location"_ostr, 
"firstHeaderRow"_ostr, "0");
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx
index e4ef0c877850..c96ccaa7de74 100644
--- a/sc/source/core/data/dpobject.cxx
+++ b/sc/source/core/data/dpobject.cxx
@@ -314,6 +314,7 @@ ScDPObject::ScDPObject(ScDocument* pDocument)
     , mbAllowMove(false)
     , mbSettingsChanged(false)
     , mbEnableGetPivotData(true)
+    , mbHideHeader(false)
 {
 }
 
@@ -328,6 +329,7 @@ ScDPObject::ScDPObject(const ScDPObject& rOther)
     , mbAllowMove(false)
     , mbSettingsChanged(false)
     , mbEnableGetPivotData(rOther.mbEnableGetPivotData)
+    , mbHideHeader(rOther.mbHideHeader)
 {
     if (rOther.mpSaveData)
         mpSaveData.reset(new ScDPSaveData(*rOther.mpSaveData));
@@ -361,6 +363,7 @@ ScDPObject& ScDPObject::operator= (const ScDPObject& rOther)
         mbAllowMove = false;
         mbSettingsChanged = false;
         mbEnableGetPivotData = rOther.mbEnableGetPivotData;
+        mbHideHeader = rOther.mbHideHeader;
 
         if (rOther.mpSaveData)
             mpSaveData.reset(new ScDPSaveData(*rOther.mpSaveData));
@@ -399,6 +402,8 @@ void ScDPObject::SetHeaderLayout (bool bUseGrid)
     mbHeaderLayout = bUseGrid;
 }
 
+void ScDPObject::SetHideHeader(bool bHideHeader) { mbHideHeader = bHideHeader; 
}
+
 void ScDPObject::SetOutRange(const ScRange& rRange)
 {
     maOutputRange = rRange;
@@ -528,7 +533,7 @@ void ScDPObject::CreateOutput()
     bool bFilterButton = IsSheetData() && mpSaveData && 
mpSaveData->GetFilterButton();
     bool bExpandCollapse = mpSaveData ? mpSaveData->GetExpandCollapse() : 
false;
 
-    mpOutput.reset(new ScDPOutput(mpDocument, mxSource, maOutputRange.aStart, 
bFilterButton, bExpandCollapse, *this));
+    mpOutput.reset(new ScDPOutput(mpDocument, mxSource, maOutputRange.aStart, 
bFilterButton, bExpandCollapse, *this, mbHideHeader));
     mpOutput->SetHeaderLayout(mbHeaderLayout);
     if (mpSaveData->hasFormats())
         mpOutput->setFormats(mpSaveData->getFormats());
diff --git a/sc/source/core/data/dpoutput.cxx b/sc/source/core/data/dpoutput.cxx
index 1b20d6fc3a56..83cf29066e5b 100644
--- a/sc/source/core/data/dpoutput.cxx
+++ b/sc/source/core/data/dpoutput.cxx
@@ -486,7 +486,7 @@ uno::Sequence<sheet::MemberResult> 
getVisiblePageMembersAsResults( const uno::Re
 } // end anonymous namespace
 
 ScDPOutput::ScDPOutput(ScDocument* pDocument, 
uno::Reference<sheet::XDimensionsSupplier> xSource,
-                       const ScAddress& rPosition, bool bFilter, bool 
bExpandCollapse, ScDPObject& rObject)
+                       const ScAddress& rPosition, bool bFilter, bool 
bExpandCollapse, ScDPObject& rObject, bool bHideHeader)
     : mpDocument(pDocument)
     , maFormatOutput(rObject)
     , mxSource(std::move(xSource))
@@ -505,6 +505,7 @@ ScDPOutput::ScDPOutput(ScDocument* pDocument, 
uno::Reference<sheet::XDimensionsS
     , mbHeaderLayout(false)
     , mbHasCompactRowField(false)
     , mbExpandCollapse(bExpandCollapse)
+    , mbHideHeader(bHideHeader)
 {
     mnTabStartCol = mnMemberStartCol = mnDataStartCol = mnTabEndCol = 0;
     mnTabStartRow = mnMemberStartRow = mnDataStartRow = mnTabEndRow = 0;
@@ -879,7 +880,9 @@ void ScDPOutput::CalcSizes()
     mnColCount = mnRowCount ? ( pRowAry[0].getLength() ) : 0;
 
     mnHeaderSize = 1;
-    if (GetHeaderLayout() && mpColFields.empty())
+    if (mbHideHeader)
+        mnHeaderSize = 0;
+    else if (GetHeaderLayout() && mpColFields.empty())
         // Insert an extra header row only when there is no column field.
         mnHeaderSize = 2;
 
@@ -1003,10 +1006,13 @@ void ScDPOutput::outputColumnHeaders(SCTAB nTab, 
ScDPOutputImpl& rOutputImpl)
     {
         SCCOL nHeaderCol = mnDataStartCol + SCCOL(nField); //TODO: check for 
overflow
 
-        if (!mbHasCompactRowField || nNumColFields == 1)
-            FieldCell(nHeaderCol, mnTabStartRow, nTab, mpColFields[nField], 
true);
-        else if (!nField)
-            MultiFieldCell(nHeaderCol, mnTabStartRow, nTab, false /* bRowField 
*/);
+        if (mnMemberStartRow > mnTabStartRow)
+        {
+            if (!mbHasCompactRowField || nNumColFields == 1)
+                FieldCell(nHeaderCol, mnTabStartRow, nTab, 
mpColFields[nField], true);
+            else if (!nField)
+                MultiFieldCell(nHeaderCol, mnTabStartRow, nTab, false /* 
bRowField */);
+        }
 
         SCROW nRowPos = mnMemberStartRow + SCROW(nField); //TODO: check for 
overflow
         const uno::Sequence<sheet::MemberResult> rMemberSequence = 
mpColFields[nField].maResult;
@@ -1060,7 +1066,7 @@ void ScDPOutput::outputColumnHeaders(SCTAB nTab, 
ScDPOutputImpl& rOutputImpl)
             // Apply the same number format as in data source.
             mpDocument->ApplyAttr(nColPos, nRowPos, nTab, 
SfxUInt32Item(ATTR_VALUE_FORMAT, mpColFields[nField].mnSrcNumFmt));
         }
-        if (nField == 0 && mpColFields.size() == 1)
+        if (nField == 0 && mpColFields.size() == 1 && mnMemberStartRow > 
mnTabStartRow)
             rOutputImpl.OutputBlockFrame(mnDataStartCol, mnTabStartRow, 
mnTabEndCol, nRowPos - 1);
     }
 }
diff --git a/sc/source/filter/excel/xepivotxml.cxx 
b/sc/source/filter/excel/xepivotxml.cxx
index d6e8bad4d4b8..ddccb1cd36f6 100644
--- a/sc/source/filter/excel/xepivotxml.cxx
+++ b/sc/source/filter/excel/xepivotxml.cxx
@@ -858,8 +858,8 @@ void XclExpXmlPivotTables::SavePivotTableXml( 
XclExpXmlStream& rStrm, const ScDP
     // NB: Excel's range does not include page field area (if any).
     ScRange aOutRange = 
rDPObj.GetOutputRangeByType(sheet::DataPilotOutputRangeType::TABLE);
 
-    sal_Int32 nFirstHeaderRow = rDPObj.GetHeaderLayout() ? 2 : 1;
-    sal_Int32 nFirstDataRow = 2;
+    sal_Int32 nFirstHeaderRow = rDPObj.GetHideHeader() ? 0 : 
(rDPObj.GetHeaderLayout() ? 2 : 1);
+    sal_Int32 nFirstDataRow = rDPObj.GetHideHeader() ? 1 : 2;
     sal_Int32 nFirstDataCol = 1;
     ScRange aResRange = 
rDPObj.GetOutputRangeByType(sheet::DataPilotOutputRangeType::RESULT);
 
diff --git a/sc/source/filter/oox/pivottablebuffer.cxx 
b/sc/source/filter/oox/pivottablebuffer.cxx
index 5439b1d58357..249176cf2b7b 100644
--- a/sc/source/filter/oox/pivottablebuffer.cxx
+++ b/sc/source/filter/oox/pivottablebuffer.cxx
@@ -1288,6 +1288,8 @@ void PivotTable::finalizeImport()
         aDescProp.setProperty( PROP_ShowFilterButton, false );
         aDescProp.setProperty( PROP_DrillDownOnDoubleClick, 
maDefModel.mbEnableDrill );
 
+        mpDPObject->SetHideHeader(maLocationModel.mnFirstHeaderRow == 0);
+
         if (auto* pSaveData = mpDPObject->GetSaveData())
             pSaveData->SetExpandCollapse(maDefModel.mbShowDrill);
 

Reply via email to