tdf#121715 XLSX: support custom first page header/footer

Add XLSX import/export support for a different header or
footer (activated separately) on the first page.
Print preview is also extended to support this.

Note: only ODS export is supported, yet. Follow-up commits
are going to add ODS import and UI support.

Change-Id: Icd3a40131bdbcd5d5a42f98c86a71345a5745051
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/116842
Tested-by: László Németh <nemeth@numbertext.org>
Reviewed-by: László Németh <nemeth@numbertext.org>
(cherry picked from commit 19fa853ce12136b5c14e0c5a0aa906c296b75388)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/118067
Tested-by: Jenkins
diff --git a/oox/source/token/properties.txt b/oox/source/token/properties.txt
index 980c1bb..68b5e2d 100644
--- a/oox/source/token/properties.txt
+++ b/oox/source/token/properties.txt
@@ -184,6 +184,10 @@ Filter
FilterCriteriaSource
FilterOptions
FirstLineOffset
FirstPageFooterContent
FirstPageHeaderContent
FirstPageFooterIsShared
FirstPageHeaderIsShared
FirstPageNumber
FocusOnClick
FontCharset
diff --git a/reportdesign/source/core/api/ReportDefinition.cxx b/reportdesign/source/core/api/ReportDefinition.cxx
index fd6bf1b..839ec94 100644
--- a/reportdesign/source/core/api/ReportDefinition.cxx
+++ b/reportdesign/source/core/api/ReportDefinition.cxx
@@ -149,6 +149,7 @@
#define SC_UNO_PAGE_HDRON           "HeaderIsOn"
#define SC_UNO_PAGE_HDRDYNAMIC      "HeaderIsDynamicHeight"
#define SC_UNO_PAGE_HDRSHARED       "HeaderIsShared"
#define SC_UNO_PAGE_FIRSTHDRSHARED  "FirstPageHeaderIsShared"
#define SC_UNO_PAGE_FTRBACKCOL      "FooterBackColor"
#define SC_UNO_PAGE_FTRBACKTRAN     "FooterBackTransparent"
#define SC_UNO_PAGE_FTRGRFFILT      "FooterBackGraphicFilter"
@@ -171,6 +172,7 @@
#define SC_UNO_PAGE_FTRON           "FooterIsOn"
#define SC_UNO_PAGE_FTRDYNAMIC      "FooterIsDynamicHeight"
#define SC_UNO_PAGE_FTRSHARED       "FooterIsShared"
#define SC_UNO_PAGE_FIRSTFTRSHARED  "FirstPageFooterIsShared"

namespace reportdesign
{
@@ -309,6 +311,7 @@ OStyle::OStyle()
    registerPropertyNoMember(SC_UNO_PAGE_FTRDYNAMIC,  ++i,nBound,cppu::UnoType<bool>::get(), css::uno::Any(false));
    registerPropertyNoMember(SC_UNO_PAGE_FTRON,       ++i,nBound,cppu::UnoType<bool>::get(), css::uno::Any(false));
    registerPropertyNoMember(SC_UNO_PAGE_FTRSHARED,   ++i,nBound,cppu::UnoType<bool>::get(), css::uno::Any(false));
    registerPropertyNoMember(SC_UNO_PAGE_FIRSTFTRSHARED, ++i,nBound,cppu::UnoType<bool>::get(), css::uno::Any(false));
    registerPropertyNoMember(SC_UNO_PAGE_FTRLEFTBOR,  ++i,nBound, cppu::UnoType<table::BorderLine2>::get(), css::uno::Any(table::BorderLine2()));
    registerPropertyNoMember(SC_UNO_PAGE_FTRLEFTBDIS, ++i,nBound, cppu::UnoType<sal_Int32>::get(), css::uno::makeAny<sal_Int32>(0));
    registerPropertyNoMember(SC_UNO_PAGE_FTRLEFTMAR,  ++i,nBound, cppu::UnoType<sal_Int32>::get(), css::uno::makeAny<sal_Int32>(0));
@@ -332,6 +335,7 @@ OStyle::OStyle()
    registerPropertyNoMember(SC_UNO_PAGE_HDRDYNAMIC,  ++i,nBound|nMayBeVoid,cppu::UnoType<bool>::get(), css::uno::Any(false));
    registerPropertyNoMember(SC_UNO_PAGE_HDRON,       ++i,nBound|nMayBeVoid,cppu::UnoType<bool>::get(), css::uno::Any(false));
    registerPropertyNoMember(SC_UNO_PAGE_HDRSHARED,   ++i,nBound|nMayBeVoid,cppu::UnoType<bool>::get(), css::uno::Any(false));
    registerPropertyNoMember(SC_UNO_PAGE_FIRSTHDRSHARED, ++i,nBound|nMayBeVoid,cppu::UnoType<bool>::get(), css::uno::Any(false));
    registerPropertyNoMember(SC_UNO_PAGE_HDRLEFTBOR,  ++i,nBound|nMayBeVoid, cppu::UnoType<table::BorderLine2>::get(), css::uno::Any(table::BorderLine2()));
    registerPropertyNoMember(SC_UNO_PAGE_HDRLEFTBDIS, ++i,nBound|nMayBeVoid, cppu::UnoType<sal_Int32>::get(), css::uno::makeAny<sal_Int32>(0));
    registerPropertyNoMember(SC_UNO_PAGE_HDRLEFTMAR,  ++i,nBound|nMayBeVoid, cppu::UnoType<sal_Int32>::get(), css::uno::makeAny<sal_Int32>(0));
diff --git a/sc/inc/scitems.hxx b/sc/inc/scitems.hxx
index 07e9b0f..eb9771b 100644
--- a/sc/inc/scitems.hxx
+++ b/sc/inc/scitems.hxx
@@ -175,31 +175,34 @@ constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_VERCENTER (163);
constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_ON (164);     // editor: header/footer-page
constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_DYNAMIC (165);
constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_SHARED (166);
constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_SHARED_FIRST (167);

constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_NOTES (167);     // editor: table
constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_GRID (168);
constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_HEADERS (169);
constexpr TypedWhichId<ScViewObjectModeItem> ATTR_PAGE_CHARTS (170);
constexpr TypedWhichId<ScViewObjectModeItem> ATTR_PAGE_OBJECTS (171);
constexpr TypedWhichId<ScViewObjectModeItem> ATTR_PAGE_DRAWINGS (172);
constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_TOPDOWN (173);
constexpr TypedWhichId<SfxUInt16Item> ATTR_PAGE_SCALE (174);
constexpr TypedWhichId<SfxUInt16Item> ATTR_PAGE_SCALETOPAGES (175);
constexpr TypedWhichId<SfxUInt16Item> ATTR_PAGE_FIRSTPAGENO (176);
constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_NOTES (168);     // editor: table
constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_GRID (169);
constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_HEADERS (170);
constexpr TypedWhichId<ScViewObjectModeItem> ATTR_PAGE_CHARTS (171);
constexpr TypedWhichId<ScViewObjectModeItem> ATTR_PAGE_OBJECTS (172);
constexpr TypedWhichId<ScViewObjectModeItem> ATTR_PAGE_DRAWINGS (173);
constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_TOPDOWN (174);
constexpr TypedWhichId<SfxUInt16Item> ATTR_PAGE_SCALE (175);
constexpr TypedWhichId<SfxUInt16Item> ATTR_PAGE_SCALETOPAGES (176);
constexpr TypedWhichId<SfxUInt16Item> ATTR_PAGE_FIRSTPAGENO (177);

constexpr TypedWhichId<ScPageHFItem> ATTR_PAGE_HEADERLEFT (177);     // contents of header/
constexpr TypedWhichId<ScPageHFItem> ATTR_PAGE_FOOTERLEFT (178);     // footer (left)
constexpr TypedWhichId<ScPageHFItem> ATTR_PAGE_HEADERRIGHT (179);     // contents of header/
constexpr TypedWhichId<ScPageHFItem> ATTR_PAGE_FOOTERRIGHT (180);     // footer (right)
constexpr TypedWhichId<SvxSetItem> ATTR_PAGE_HEADERSET (181);     // the corresponding sets
constexpr TypedWhichId<SvxSetItem> ATTR_PAGE_FOOTERSET (182);
constexpr TypedWhichId<ScPageHFItem> ATTR_PAGE_HEADERLEFT (178);     // contents of header/
constexpr TypedWhichId<ScPageHFItem> ATTR_PAGE_FOOTERLEFT (179);     // footer (left)
constexpr TypedWhichId<ScPageHFItem> ATTR_PAGE_HEADERRIGHT (180);    // contents of header/
constexpr TypedWhichId<ScPageHFItem> ATTR_PAGE_FOOTERRIGHT (181);    // footer (right)
constexpr TypedWhichId<ScPageHFItem> ATTR_PAGE_HEADERFIRST (182);    // contents of header/
constexpr TypedWhichId<ScPageHFItem> ATTR_PAGE_FOOTERFIRST (183);    // footer (first page)
constexpr TypedWhichId<SvxSetItem> ATTR_PAGE_HEADERSET (184);     // the corresponding sets
constexpr TypedWhichId<SvxSetItem> ATTR_PAGE_FOOTERSET (185);

constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_FORMULAS (183);
constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_NULLVALS (184);
constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_FORMULAS (186);
constexpr TypedWhichId<SfxBoolItem> ATTR_PAGE_NULLVALS (187);

constexpr TypedWhichId<ScPageScaleToItem> ATTR_PAGE_SCALETO (185);     // #i8868# scale printout to width/height
constexpr TypedWhichId<ScPageScaleToItem> ATTR_PAGE_SCALETO (188);     // #i8868# scale printout to width/height

constexpr TypedWhichId<SfxBoolItem> ATTR_HIDDEN (186);
constexpr TypedWhichId<SfxBoolItem> ATTR_HIDDEN (189);

constexpr sal_uInt16 ATTR_ENDINDEX(ATTR_HIDDEN);        // end of pool-range

@@ -219,6 +222,8 @@ constexpr sal_uInt16 ATTR_ENDINDEX(ATTR_HIDDEN);        // end of pool-range
#define SID_SCATTR_PAGE_FOOTERLEFT      ATTR_PAGE_FOOTERLEFT
#define SID_SCATTR_PAGE_HEADERRIGHT     ATTR_PAGE_HEADERRIGHT
#define SID_SCATTR_PAGE_FOOTERRIGHT     ATTR_PAGE_FOOTERRIGHT
#define SID_SCATTR_PAGE_HEADERFIRST     ATTR_PAGE_HEADERFIRST
#define SID_SCATTR_PAGE_FOOTERFIRST     ATTR_PAGE_FOOTERFIRST
#define SID_SCATTR_PAGE_FORMULAS        ATTR_PAGE_FORMULAS
#define SID_SCATTR_PAGE_NULLVALS        ATTR_PAGE_NULLVALS
#define SID_SCATTR_PAGE_SCALETO         ATTR_PAGE_SCALETO
diff --git a/sc/inc/unonames.hxx b/sc/inc/unonames.hxx
index fb24cc6..c4e7a23 100644
--- a/sc/inc/unonames.hxx
+++ b/sc/inc/unonames.hxx
@@ -441,10 +441,14 @@
#define SC_UNO_PAGE_SCALETOX        "ScaleToPagesX"
#define SC_UNO_PAGE_SCALETOY        "ScaleToPagesY"
#define SC_UNO_PAGE_FIRSTPAGE       "FirstPageNumber"
#define SC_UNO_PAGE_FIRSTHDRSHARED  "FirstPageHeaderIsShared"
#define SC_UNO_PAGE_FIRSTFTRSHARED  "FirstPageFooterIsShared"
#define SC_UNO_PAGE_LEFTHDRCONT     "LeftPageHeaderContent"
#define SC_UNO_PAGE_LEFTFTRCONT     "LeftPageFooterContent"
#define SC_UNO_PAGE_RIGHTHDRCON     "RightPageHeaderContent"
#define SC_UNO_PAGE_RIGHTFTRCON     "RightPageFooterContent"
#define SC_UNO_PAGE_FIRSTHDRCONT    "FirstPageHeaderContent"
#define SC_UNO_PAGE_FIRSTFTRCONT    "FirstPageFooterContent"
#define SC_UNO_PAGE_PRINTFORMUL     "PrintFormulas"
#define SC_UNO_PAGE_PRINTZERO       "PrintZeroValues"
#define SC_UNO_PAGE_HDRBACKCOL      "HeaderBackColor"
diff --git a/sc/qa/unit/data/xlsx/tdf121715.xlsx b/sc/qa/unit/data/xlsx/tdf121715.xlsx
new file mode 100644
index 0000000..4163f6b
--- /dev/null
+++ b/sc/qa/unit/data/xlsx/tdf121715.xlsx
Binary files differ
diff --git a/sc/qa/unit/subsequent_export-test2.cxx b/sc/qa/unit/subsequent_export-test2.cxx
index 310d88a..8e4f77e 100644
--- a/sc/qa/unit/subsequent_export-test2.cxx
+++ b/sc/qa/unit/subsequent_export-test2.cxx
@@ -163,6 +163,7 @@ public:
    void testTdf81470();
    void testTdf122331();
    void testTdf83779();
    void testTdf121715_FirstPageHeaderFooterXLSX();
    void testTdf121716_ExportEvenHeaderFooterXLSX();
    void testTdf134459_HeaderFooterColorXLSX();
    void testTdf134817_HeaderFooterTextWith2SectionXLSX();
@@ -256,6 +257,7 @@ public:
    CPPUNIT_TEST(testTdf81470);
    CPPUNIT_TEST(testTdf122331);
    CPPUNIT_TEST(testTdf83779);
    CPPUNIT_TEST(testTdf121715_FirstPageHeaderFooterXLSX);
    CPPUNIT_TEST(testTdf121716_ExportEvenHeaderFooterXLSX);
    CPPUNIT_TEST(testTdf134459_HeaderFooterColorXLSX);
    CPPUNIT_TEST(testTdf134817_HeaderFooterTextWith2SectionXLSX);
@@ -1679,6 +1681,25 @@ void ScExportTest2::testTdf83779()
    xShell->DoClose();
}

void ScExportTest2::testTdf121715_FirstPageHeaderFooterXLSX()
{
    // Check if first page header and footer are exported properly
    ScDocShellRef xShell = loadDoc(u"tdf121715.", FORMAT_XLSX);
    CPPUNIT_ASSERT(xShell.is());

    std::shared_ptr<utl::TempFile> pXPathFile
        = ScBootstrapFixture::exportTo(&(*xShell), FORMAT_XLSX);
    xmlDocUniquePtr pDoc
        = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/sheet1.xml");
    CPPUNIT_ASSERT(pDoc);

    assertXPath(pDoc, "/x:worksheet/x:headerFooter", "differentFirst", "true");
    assertXPathContent(pDoc, "/x:worksheet/x:headerFooter/x:firstHeader", "&CFirst Page Header");
    assertXPathContent(pDoc, "/x:worksheet/x:headerFooter/x:firstFooter", "&CFirst Page Footer");

    xShell->DoClose();
}

void ScExportTest2::testTdf121716_ExportEvenHeaderFooterXLSX()
{
    // Header and footer on even pages should be exported properly
diff --git a/sc/source/core/data/docpool.cxx b/sc/source/core/data/docpool.cxx
index 628c368..66d3275 100644
--- a/sc/source/core/data/docpool.cxx
+++ b/sc/source/core/data/docpool.cxx
@@ -157,6 +157,7 @@ SfxItemInfo const  aItemInfos[] =
    { SID_ATTR_PAGE_ON,             true },    // ATTR_PAGE_ON
    { SID_ATTR_PAGE_DYNAMIC,        true },    // ATTR_PAGE_DYNAMIC
    { SID_ATTR_PAGE_SHARED,         true },    // ATTR_PAGE_SHARED
    { SID_ATTR_PAGE_SHARED_FIRST,   true },    // ATTR_PAGE_SHARED_FIRST
    { SID_SCATTR_PAGE_NOTES,        true },    // ATTR_PAGE_NOTES
    { SID_SCATTR_PAGE_GRID,         true },    // ATTR_PAGE_GRID
    { SID_SCATTR_PAGE_HEADERS,      true },    // ATTR_PAGE_HEADERS
@@ -171,6 +172,8 @@ SfxItemInfo const  aItemInfos[] =
    { SID_SCATTR_PAGE_FOOTERLEFT,   true },    // ATTR_PAGE_FOOTERLEFT
    { SID_SCATTR_PAGE_HEADERRIGHT,  true },    // ATTR_PAGE_HEADERRIGHT
    { SID_SCATTR_PAGE_FOOTERRIGHT,  true },    // ATTR_PAGE_FOOTERRIGHT
    { SID_SCATTR_PAGE_HEADERFIRST,  true },    // ATTR_PAGE_HEADERFIRST
    { SID_SCATTR_PAGE_FOOTERFIRST,  true },    // ATTR_PAGE_FOOTERFIRST
    { SID_ATTR_PAGE_HEADERSET,      true },    // ATTR_PAGE_HEADERSET
    { SID_ATTR_PAGE_FOOTERSET,      true },    // ATTR_PAGE_FOOTERSET
    { SID_SCATTR_PAGE_FORMULAS,     true },    // ATTR_PAGE_FORMULAS
@@ -206,7 +209,7 @@ ScDocumentPool::ScDocumentPool()
                                     ATTR_BORDER,     ATTR_SHADOW,
                                     ATTR_LRSPACE,    ATTR_ULSPACE,
                                     ATTR_PAGE_SIZE,  ATTR_PAGE_SIZE,
                                     ATTR_PAGE_ON,    ATTR_PAGE_SHARED>{} );
                                     ATTR_PAGE_ON,    ATTR_PAGE_SHARED_FIRST>{} );

    pGlobalBorderInnerAttr->SetLine(nullptr, SvxBoxInfoItemLine::HORI);
    pGlobalBorderInnerAttr->SetLine(nullptr, SvxBoxInfoItemLine::VERT);
@@ -292,6 +295,7 @@ ScDocumentPool::ScDocumentPool()
    mvPoolDefaults[ ATTR_PAGE_ON         - ATTR_STARTINDEX ] = new SfxBoolItem( ATTR_PAGE_ON, true );
    mvPoolDefaults[ ATTR_PAGE_DYNAMIC    - ATTR_STARTINDEX ] = new SfxBoolItem( ATTR_PAGE_DYNAMIC, true );
    mvPoolDefaults[ ATTR_PAGE_SHARED     - ATTR_STARTINDEX ] = new SfxBoolItem( ATTR_PAGE_SHARED, true );
    mvPoolDefaults[ ATTR_PAGE_SHARED_FIRST- ATTR_STARTINDEX ] = new SfxBoolItem( ATTR_PAGE_SHARED_FIRST, true );
    mvPoolDefaults[ ATTR_PAGE_NOTES      - ATTR_STARTINDEX ] = new SfxBoolItem( ATTR_PAGE_NOTES, false );
    mvPoolDefaults[ ATTR_PAGE_GRID       - ATTR_STARTINDEX ] = new SfxBoolItem( ATTR_PAGE_GRID, false );
    mvPoolDefaults[ ATTR_PAGE_HEADERS    - ATTR_STARTINDEX ] = new SfxBoolItem( ATTR_PAGE_HEADERS, false );
@@ -306,6 +310,8 @@ ScDocumentPool::ScDocumentPool()
    mvPoolDefaults[ ATTR_PAGE_FOOTERLEFT - ATTR_STARTINDEX ] = new ScPageHFItem( ATTR_PAGE_FOOTERLEFT );
    mvPoolDefaults[ ATTR_PAGE_HEADERRIGHT- ATTR_STARTINDEX ] = new ScPageHFItem( ATTR_PAGE_HEADERRIGHT );
    mvPoolDefaults[ ATTR_PAGE_FOOTERRIGHT- ATTR_STARTINDEX ] = new ScPageHFItem( ATTR_PAGE_FOOTERRIGHT );
    mvPoolDefaults[ ATTR_PAGE_HEADERFIRST- ATTR_STARTINDEX ] = new ScPageHFItem( ATTR_PAGE_HEADERFIRST );
    mvPoolDefaults[ ATTR_PAGE_FOOTERFIRST- ATTR_STARTINDEX ] = new ScPageHFItem( ATTR_PAGE_FOOTERFIRST );
    mvPoolDefaults[ ATTR_PAGE_HEADERSET  - ATTR_STARTINDEX ] = new SvxSetItem( ATTR_PAGE_HEADERSET, aSetItemItemSet );
    mvPoolDefaults[ ATTR_PAGE_FOOTERSET  - ATTR_STARTINDEX ] = new SvxSetItem( ATTR_PAGE_FOOTERSET, aSetItemItemSet );
    mvPoolDefaults[ ATTR_PAGE_FORMULAS   - ATTR_STARTINDEX ] = new SfxBoolItem( ATTR_PAGE_FORMULAS, false );
@@ -412,6 +418,7 @@ static bool lcl_HFPresentation
            case ATTR_PAGE_ON:
            case ATTR_PAGE_DYNAMIC:
            case ATTR_PAGE_SHARED:
            case ATTR_PAGE_SHARED_FIRST:
            break;

            case ATTR_LRSPACE:
diff --git a/sc/source/filter/excel/xepage.cxx b/sc/source/filter/excel/xepage.cxx
index b2796ed..56ecd2d 100644
--- a/sc/source/filter/excel/xepage.cxx
+++ b/sc/source/filter/excel/xepage.cxx
@@ -60,11 +60,13 @@ void XclExpHeaderFooter::SaveXml( XclExpXmlStream& rStrm )
    sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
    sal_Int32 nElement;
    switch(GetRecId()) {
        case EXC_ID_HEADER_EVEN: nElement = XML_evenHeader; break;
        case EXC_ID_FOOTER_EVEN: nElement = XML_evenFooter; break;
        case EXC_ID_HEADER:      nElement = XML_oddHeader; break;
        case EXC_ID_HEADER_FIRST: nElement = XML_firstHeader; break;
        case EXC_ID_FOOTER_FIRST: nElement = XML_firstFooter; break;
        case EXC_ID_HEADER_EVEN:  nElement = XML_evenHeader; break;
        case EXC_ID_FOOTER_EVEN:  nElement = XML_evenFooter; break;
        case EXC_ID_HEADER:       nElement = XML_oddHeader; break;
        case EXC_ID_FOOTER:
        default:                 nElement = XML_oddFooter;
        default:                  nElement = XML_oddFooter;
    }
    rWorksheet->startElement(nElement);
    rWorksheet->writeEscaped( maHdrString );
@@ -277,6 +279,7 @@ XclExpPageSettings::XclExpPageSettings( const XclExpRoot& rRoot ) :

        maData.mxBrushItem.reset( new SvxBrushItem( rItemSet.Get( ATTR_BACKGROUND ) ) );
        maData.mbUseEvenHF = false;
        maData.mbUseFirstHF = false;

        // *** header and footer ***

@@ -301,6 +304,17 @@ XclExpPageSettings::XclExpPageSettings( const XclExpRoot& rRoot ) :
                // If maData.mbUseEvenHF become true, then we will need a copy of maHeader in maHeaderEven.
                maData.maHeaderEven = maData.maHeader;
            }
            if (rHdrItemSet.HasItem(ATTR_PAGE_SHARED_FIRST) && !rHdrItemSet.Get(ATTR_PAGE_SHARED_FIRST).GetValue())
            {
                const ScPageHFItem& rHFItemFirst = rItemSet.Get( ATTR_PAGE_HEADERFIRST );
                aHFConv.GenerateString( rHFItemFirst.GetLeftArea(), rHFItemFirst.GetCenterArea(), rHFItemFirst.GetRightArea() );
                maData.maHeaderFirst = aHFConv.GetHFString();
                maData.mbUseFirstHF = true;
            }
            else
            {
                maData.maHeaderFirst = maData.maHeader;
            }
            // header height (Excel excludes header from top margin)
            sal_Int32 nHdrHeight = rHdrItemSet.Get( ATTR_PAGE_DYNAMIC ).GetValue() ?
                // dynamic height: calculate header height, add header <-> sheet area distance
@@ -329,6 +343,17 @@ XclExpPageSettings::XclExpPageSettings( const XclExpRoot& rRoot ) :
            {
                maData.maFooterEven = maData.maFooter;
            }
            if (rFtrItemSet.HasItem(ATTR_PAGE_SHARED_FIRST) && !rFtrItemSet.Get(ATTR_PAGE_SHARED_FIRST).GetValue())
            {
                const ScPageHFItem& rHFItemFirst = rItemSet.Get( ATTR_PAGE_FOOTERFIRST );
                aHFConv.GenerateString( rHFItemFirst.GetLeftArea(), rHFItemFirst.GetCenterArea(), rHFItemFirst.GetRightArea() );
                maData.maFooterFirst = aHFConv.GetHFString();
                maData.mbUseFirstHF = true;
            }
            else
            {
                maData.maFooterFirst = maData.maFooter;
            }
            // footer height (Excel excludes footer from bottom margin)
            sal_Int32 nFtrHeight = rFtrItemSet.Get( ATTR_PAGE_DYNAMIC ).GetValue() ?
                // dynamic height: calculate footer height, add sheet area <-> footer distance
@@ -373,12 +398,13 @@ namespace {
class XclExpXmlStartHeaderFooterElementRecord : public XclExpXmlElementRecord
{
public:
    explicit XclExpXmlStartHeaderFooterElementRecord(sal_Int32 const nElement, bool const bDifferentOddEven = false)
         : XclExpXmlElementRecord(nElement), mbDifferentOddEven(bDifferentOddEven) {}
    explicit XclExpXmlStartHeaderFooterElementRecord(sal_Int32 const nElement, bool const bDifferentOddEven = false, bool const bDifferentFirst = false)
         : XclExpXmlElementRecord(nElement), mbDifferentOddEven(bDifferentOddEven), mbDifferentFirst(bDifferentFirst) {}

    virtual void        SaveXml( XclExpXmlStream& rStrm ) override;
private:
    bool            mbDifferentOddEven;
    bool            mbDifferentFirst;
};

}
@@ -390,7 +416,7 @@ void XclExpXmlStartHeaderFooterElementRecord::SaveXml(XclExpXmlStream& rStrm)
    sax_fastparser::FSHelperPtr& rStream = rStrm.GetCurrentStream();
    rStream->startElement( mnElement,
            // OOXTODO: XML_alignWithMargins,
            XML_differentFirst,     "false",    // OOXTODO
            XML_differentFirst,     mbDifferentFirst   ? "true" : "false",
            XML_differentOddEven,   mbDifferentOddEven ? "true" : "false"
            // OOXTODO: XML_scaleWithDoc
    );
@@ -439,7 +465,7 @@ void XclExpPageSettings::SaveXml( XclExpXmlStream& rStrm )

    XclExpSetup( maData ).SaveXml( rStrm );

    XclExpXmlStartHeaderFooterElementRecord(XML_headerFooter, maData.mbUseEvenHF).SaveXml(rStrm);
    XclExpXmlStartHeaderFooterElementRecord(XML_headerFooter, maData.mbUseEvenHF, maData.mbUseFirstHF).SaveXml(rStrm);
    XclExpHeaderFooter( EXC_ID_HEADER, maData.maHeader ).SaveXml( rStrm );
    XclExpHeaderFooter( EXC_ID_FOOTER, maData.maFooter ).SaveXml( rStrm );
    if (maData.mbUseEvenHF)
@@ -447,6 +473,11 @@ void XclExpPageSettings::SaveXml( XclExpXmlStream& rStrm )
        XclExpHeaderFooter( EXC_ID_HEADER_EVEN, maData.maHeaderEven ).SaveXml( rStrm );
        XclExpHeaderFooter( EXC_ID_FOOTER_EVEN, maData.maFooterEven ).SaveXml( rStrm );
    }
    if (maData.mbUseFirstHF)
    {
        XclExpHeaderFooter( EXC_ID_HEADER_FIRST, maData.maHeaderFirst ).SaveXml( rStrm );
        XclExpHeaderFooter( EXC_ID_FOOTER_FIRST, maData.maFooterFirst ).SaveXml( rStrm );
    }
    XclExpXmlEndElementRecord( XML_headerFooter ).SaveXml( rStrm );

    XclExpPageBreaks( EXC_ID_HORPAGEBREAKS, maData.maHorPageBreaks,
diff --git a/sc/source/filter/excel/xipage.cxx b/sc/source/filter/excel/xipage.cxx
index c3b1853..41db8ab 100644
--- a/sc/source/filter/excel/xipage.cxx
+++ b/sc/source/filter/excel/xipage.cxx
@@ -299,6 +299,7 @@ void XclImpPageSettings::Finalize()
        aHFConv.ParseString( maData.maHeader );
        aHFConv.FillToItemSet( rItemSet, ATTR_PAGE_HEADERLEFT );
        aHFConv.FillToItemSet( rItemSet, ATTR_PAGE_HEADERRIGHT );
        aHFConv.FillToItemSet( rItemSet, ATTR_PAGE_HEADERFIRST );
        // #i23296# In Calc, "top margin" is distance to header
        fTopMargin = maData.mfHeaderMargin;
        // Calc uses distance between header and sheet data area
@@ -335,6 +336,7 @@ void XclImpPageSettings::Finalize()
        aHFConv.ParseString( maData.maFooter );
        aHFConv.FillToItemSet( rItemSet, ATTR_PAGE_FOOTERLEFT );
        aHFConv.FillToItemSet( rItemSet, ATTR_PAGE_FOOTERRIGHT );
        aHFConv.FillToItemSet( rItemSet, ATTR_PAGE_FOOTERFIRST );
        // #i23296# In Calc, "bottom margin" is distance to footer
        fBottomMargin = maData.mfFooterMargin;
        // Calc uses distance between footer and sheet data area
diff --git a/sc/source/filter/excel/xlpage.cxx b/sc/source/filter/excel/xlpage.cxx
index ef1742d..06da2e5 100644
--- a/sc/source/filter/excel/xlpage.cxx
+++ b/sc/source/filter/excel/xlpage.cxx
@@ -185,7 +185,7 @@ void XclPageData::SetDefaults()
    mnScaling = 100;
    mnFitToWidth = mnFitToHeight = 1;
    mnHorPrintRes = mnVerPrintRes = 300;
    mbUseEvenHF = /*mbUseFirstHF =*/ false;
    mbUseEvenHF = mbUseFirstHF = false;
    mbValid = false;
    mbPortrait = true;
    mbPrintInRows = mbBlackWhite = mbDraftQuality = mbPrintNotes = mbManualStart = mbFitToPages = false;
diff --git a/sc/source/filter/inc/pagesettings.hxx b/sc/source/filter/inc/pagesettings.hxx
index 1bee649..f951f31 100644
--- a/sc/source/filter/inc/pagesettings.hxx
+++ b/sc/source/filter/inc/pagesettings.hxx
@@ -146,13 +146,15 @@ private:
    {
        sal_Int32           mnLeftPropId;
        sal_Int32           mnRightPropId;
        sal_Int32           mnFirstPropId;
        sal_Int32           mnHeight;
        sal_Int32           mnBodyDist;
        bool                mbHasContent;
        bool                mbShareOddEven;
        bool                mbShareFirst;
        bool                mbDynamicHeight;

        explicit            HFHelperData( sal_Int32 nLeftPropId, sal_Int32 nRightPropId );
        explicit            HFHelperData( sal_Int32 nLeftPropId, sal_Int32 nRightPropId, sal_Int32 nFirstPropId );
    };

private:
@@ -161,7 +163,9 @@ private:
                            HFHelperData& orHFData,
                            const OUString& rOddContent,
                            const OUString& rEvenContent,
                            const OUString& rFirstContent,
                            bool bUseEvenContent,
                            bool bUseFirstContent,
                            double fPageMargin,
                            double fContentMargin );

diff --git a/sc/source/filter/inc/xlpage.hxx b/sc/source/filter/inc/xlpage.hxx
index 246057c..d200e8b 100644
--- a/sc/source/filter/inc/xlpage.hxx
+++ b/sc/source/filter/inc/xlpage.hxx
@@ -35,6 +35,11 @@ const sal_uInt16 EXC_ID_FOOTER              = 0x0015;
const sal_uInt16 EXC_ID_HEADER_EVEN         = 0x0016;
const sal_uInt16 EXC_ID_FOOTER_EVEN         = 0x0017;

// (0x0018, 0x0019) FIRST HEADER, FIRST FOOTER ----------------------------------

const sal_uInt16 EXC_ID_HEADER_FIRST        = 0x0018;
const sal_uInt16 EXC_ID_FOOTER_FIRST        = 0x0019;

// (0x001A, 0x001B) VERTICAL-, HORIZONTALPAGEBREAKS ---------------------------

const sal_uInt16 EXC_ID_VERPAGEBREAKS       = 0x001A;
@@ -108,6 +113,8 @@ struct XclPageData
    OUString            maFooter;           /// Excel footer string (empty = off).
    OUString            maHeaderEven;       /// Excel header string for even pages (empty = off).
    OUString            maFooterEven;       /// Excel footer string for even pages (empty = off).
    OUString            maHeaderFirst;      /// Excel header string for first page (empty = off).
    OUString            maFooterFirst;      /// Excel footer string for first page (empty = off).
    double              mfLeftMargin;       /// Left margin in inches.
    double              mfRightMargin;      /// Right margin in inches.
    double              mfTopMargin;        /// Top margin in inches.
@@ -130,7 +137,7 @@ struct XclPageData
    sal_uInt16          mnHorPrintRes;      /// Horizontal printing resolution.
    sal_uInt16          mnVerPrintRes;      /// Vertical printing resolution.
    bool                mbUseEvenHF;        /// True = use maHeaderEven/maFooterEven.
//  bool                mbUseFirstHF;       /// True = use maHeaderFirst/maFooterFirst.  TODO: not implemented yet.
    bool                mbUseFirstHF;       /// True = use maHeaderFirst/maFooterFirst.
    bool                mbValid;            /// false = some of the values are not valid.
    bool                mbPortrait;         /// true = portrait; false = landscape.
    bool                mbPrintInRows;      /// true = in rows; false = in columns.
diff --git a/sc/source/filter/oox/pagesettings.cxx b/sc/source/filter/oox/pagesettings.cxx
index bc80fc4..44aac4a 100644
--- a/sc/source/filter/oox/pagesettings.cxx
+++ b/sc/source/filter/oox/pagesettings.cxx
@@ -874,13 +874,15 @@ void HeaderFooterParser::setNewPortion( HFPortionId ePortion )
    }
}

PageSettingsConverter::HFHelperData::HFHelperData( sal_Int32 nLeftPropId, sal_Int32 nRightPropId ) :
PageSettingsConverter::HFHelperData::HFHelperData( sal_Int32 nLeftPropId, sal_Int32 nRightPropId, sal_Int32 nFirstPropId ) :
    mnLeftPropId( nLeftPropId ),
    mnRightPropId( nRightPropId ),
    mnFirstPropId( nFirstPropId ),
    mnHeight( 0 ),
    mnBodyDist( 0 ),
    mbHasContent( false ),
    mbShareOddEven( false ),
    mbShareFirst( false ),
    mbDynamicHeight( false )
{
}
@@ -888,8 +890,8 @@ PageSettingsConverter::HFHelperData::HFHelperData( sal_Int32 nLeftPropId, sal_In
PageSettingsConverter::PageSettingsConverter( const WorkbookHelper& rHelper ) :
    WorkbookHelper( rHelper ),
    mxHFParser( new HeaderFooterParser( rHelper ) ),
    maHeaderData( PROP_LeftPageHeaderContent, PROP_RightPageHeaderContent ),
    maFooterData( PROP_LeftPageFooterContent, PROP_RightPageFooterContent )
    maHeaderData( PROP_LeftPageHeaderContent, PROP_RightPageHeaderContent, PROP_FirstPageHeaderContent ),
    maFooterData( PROP_LeftPageFooterContent, PROP_RightPageFooterContent, PROP_FirstPageFooterContent )
{
}

@@ -955,8 +957,8 @@ void PageSettingsConverter::writePageSettingsProperties(
    }

    // header/footer
    convertHeaderFooterData( rPropSet, maHeaderData, rModel.maOddHeader, rModel.maEvenHeader, rModel.mbUseEvenHF, rModel.mfTopMargin,    rModel.mfHeaderMargin );
    convertHeaderFooterData( rPropSet, maFooterData, rModel.maOddFooter, rModel.maEvenFooter, rModel.mbUseEvenHF, rModel.mfBottomMargin, rModel.mfFooterMargin );
    convertHeaderFooterData( rPropSet, maHeaderData, rModel.maOddHeader, rModel.maEvenHeader, rModel.maFirstHeader, rModel.mbUseEvenHF, rModel.mbUseFirstHF, rModel.mfTopMargin,    rModel.mfHeaderMargin );
    convertHeaderFooterData( rPropSet, maFooterData, rModel.maOddFooter, rModel.maEvenFooter, rModel.maFirstFooter, rModel.mbUseEvenHF, rModel.mbUseFirstHF, rModel.mfBottomMargin, rModel.mfFooterMargin );

    // write all properties to property set
    const UnitConverter& rUnitConv = getUnitConverter();
@@ -977,11 +979,13 @@ void PageSettingsConverter::writePageSettingsProperties(
    aPropMap.setProperty( PROP_BottomMargin, rUnitConv.scaleToMm100( maFooterData.mbHasContent ? rModel.mfFooterMargin : rModel.mfBottomMargin, Unit::Inch ));
    aPropMap.setProperty( PROP_HeaderIsOn, maHeaderData.mbHasContent);
    aPropMap.setProperty( PROP_HeaderIsShared, maHeaderData.mbShareOddEven);
    aPropMap.setProperty( PROP_FirstPageHeaderIsShared, maHeaderData.mbShareFirst);
    aPropMap.setProperty( PROP_HeaderIsDynamicHeight, maHeaderData.mbDynamicHeight);
    aPropMap.setProperty( PROP_HeaderHeight, maHeaderData.mnHeight);
    aPropMap.setProperty( PROP_HeaderBodyDistance, maHeaderData.mnBodyDist);
    aPropMap.setProperty( PROP_FooterIsOn, maFooterData.mbHasContent);
    aPropMap.setProperty( PROP_FooterIsShared, maFooterData.mbShareOddEven);
    aPropMap.setProperty( PROP_FirstPageFooterIsShared, maFooterData.mbShareFirst);
    aPropMap.setProperty( PROP_FooterIsDynamicHeight, maFooterData.mbDynamicHeight);
    aPropMap.setProperty( PROP_FooterHeight, maFooterData.mnHeight);
    aPropMap.setProperty( PROP_FooterBodyDistance, maFooterData.mnBodyDist);
@@ -997,26 +1001,30 @@ void PageSettingsConverter::writePageSettingsProperties(

void PageSettingsConverter::convertHeaderFooterData(
        PropertySet& rPropSet, HFHelperData& orHFData,
        const OUString& rOddContent, const OUString& rEvenContent, bool bUseEvenContent,
        const OUString& rOddContent, const OUString& rEvenContent, const OUString& rFirstContent,
        bool bUseEvenContent, bool bUseFirstContent,
        double fPageMargin, double fContentMargin )
{
    bool bHasOddContent  = !rOddContent.isEmpty();
    bool bHasEvenContent = bUseEvenContent && !rEvenContent.isEmpty();
    bool bHasFirstContent = bUseFirstContent && !rFirstContent.isEmpty();

    sal_Int32 nOddHeight  = bHasOddContent  ? writeHeaderFooter( rPropSet, orHFData.mnRightPropId, rOddContent  ) : 0;
    sal_Int32 nEvenHeight = bHasEvenContent ? writeHeaderFooter( rPropSet, orHFData.mnLeftPropId,  rEvenContent ) : 0;
    sal_Int32 nOddHeight   = bHasOddContent   ? writeHeaderFooter( rPropSet, orHFData.mnRightPropId, rOddContent   ) : 0;
    sal_Int32 nEvenHeight  = bHasEvenContent  ? writeHeaderFooter( rPropSet, orHFData.mnLeftPropId,  rEvenContent  ) : 0;
    sal_Int32 nFirstHeight = bHasFirstContent ? writeHeaderFooter( rPropSet, orHFData.mnFirstPropId, rFirstContent ) : 0;

    orHFData.mnHeight = 750;
    orHFData.mnBodyDist = 250;
    orHFData.mbHasContent = bHasOddContent || bHasEvenContent;
    orHFData.mbHasContent = bHasOddContent || bHasEvenContent || bHasFirstContent;
    orHFData.mbShareOddEven = !bUseEvenContent;
    orHFData.mbShareFirst = !bUseFirstContent;
    orHFData.mbDynamicHeight = true;

    if( !orHFData.mbHasContent )
        return;

    // use maximum height of odd/even header/footer
    orHFData.mnHeight = ::std::max( nOddHeight, nEvenHeight );
    // use maximum height of odd/even/first header/footer
    orHFData.mnHeight = ::std::max( ::std::max( nOddHeight, nEvenHeight ), nFirstHeight );
    /*  Calc contains distance between bottom of header and top of page
        body in "HeaderBodyDistance" property, and distance between bottom
        of page body and top of footer in "FooterBodyDistance" property */
diff --git a/sc/source/filter/xml/XMLTableHeaderFooterContext.cxx b/sc/source/filter/xml/XMLTableHeaderFooterContext.cxx
index 62d3a21..a34015a 100644
--- a/sc/source/filter/xml/XMLTableHeaderFooterContext.cxx
+++ b/sc/source/filter/xml/XMLTableHeaderFooterContext.cxx
@@ -41,7 +41,7 @@ XMLTableHeaderFooterContext::XMLTableHeaderFooterContext( SvXMLImport& rImport, 
                       const uno::Reference<
                            xml::sax::XFastAttributeList > & xAttrList,
                       const Reference < XPropertySet > & rPageStylePropSet,
                       bool bFooter, bool bLeft ) :
                       bool bFooter, bool bLeft, bool bFirst ) :
    SvXMLImportContext( rImport ),
    xPropSet( rPageStylePropSet ),
    bContainsLeft(false),
@@ -51,6 +51,7 @@ XMLTableHeaderFooterContext::XMLTableHeaderFooterContext( SvXMLImport& rImport, 
    OUString sOn( bFooter ? OUString(SC_UNO_PAGE_FTRON) : OUString(SC_UNO_PAGE_HDRON) );
    OUString sContent( bFooter ? OUString(SC_UNO_PAGE_RIGHTFTRCON) : OUString(SC_UNO_PAGE_RIGHTHDRCON) );
    OUString sContentLeft( bFooter ? OUString(SC_UNO_PAGE_LEFTFTRCONT) : OUString(SC_UNO_PAGE_LEFTHDRCONT) );
    OUString sContentFirst( bFooter ? OUString(SC_UNO_PAGE_FIRSTFTRCONT) : OUString(SC_UNO_PAGE_FIRSTHDRCONT) );
    OUString sShareContent( bFooter ? OUString(SC_UNO_PAGE_FTRSHARED) : OUString(SC_UNO_PAGE_HDRSHARED) );
    bool bDisplay( true );
    for( auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ) )
@@ -85,6 +86,8 @@ XMLTableHeaderFooterContext::XMLTableHeaderFooterContext( SvXMLImport& rImport, 
    }
    if (bLeft)
        sCont = sContentLeft;
    else if (bFirst)
        sCont = sContentFirst;
    else
        sCont = sContent;
    xPropSet->getPropertyValue( sCont ) >>= xHeaderFooterContent;
diff --git a/sc/source/filter/xml/XMLTableHeaderFooterContext.hxx b/sc/source/filter/xml/XMLTableHeaderFooterContext.hxx
index bc7bf13..ccb6a15 100644
--- a/sc/source/filter/xml/XMLTableHeaderFooterContext.hxx
+++ b/sc/source/filter/xml/XMLTableHeaderFooterContext.hxx
@@ -45,7 +45,7 @@ public:
    XMLTableHeaderFooterContext( SvXMLImport& rImport, sal_Int32 nElement,
            const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList,
            const css::uno::Reference< css::beans::XPropertySet > & rPageStylePropSet,
               bool bFooter, bool bLft );
               bool bFooter, bool bLft, bool bFirst );

    virtual ~XMLTableHeaderFooterContext() override;

diff --git a/sc/source/filter/xml/XMLTableMasterPageExport.cxx b/sc/source/filter/xml/XMLTableMasterPageExport.cxx
index 03078b8..bf43b2c 100644
--- a/sc/source/filter/xml/XMLTableMasterPageExport.cxx
+++ b/sc/source/filter/xml/XMLTableMasterPageExport.cxx
@@ -116,10 +116,14 @@ void XMLTableMasterPageExport::exportMasterPageContent(

    Reference < sheet::XHeaderFooterContent > xHeaderLeft(rPropSet->getPropertyValue( SC_UNO_PAGE_LEFTHDRCONT ), uno::UNO_QUERY);

    Reference < sheet::XHeaderFooterContent > xHeaderFirst(rPropSet->getPropertyValue( SC_UNO_PAGE_FIRSTHDRCONT ), uno::UNO_QUERY);

    Reference < sheet::XHeaderFooterContent > xFooter(rPropSet->getPropertyValue( SC_UNO_PAGE_RIGHTFTRCON ), uno::UNO_QUERY);

    Reference < sheet::XHeaderFooterContent > xFooterLeft(rPropSet->getPropertyValue( SC_UNO_PAGE_LEFTFTRCONT ), uno::UNO_QUERY);

    Reference < sheet::XHeaderFooterContent > xFooterFirst(rPropSet->getPropertyValue( SC_UNO_PAGE_FIRSTFTRCONT ), uno::UNO_QUERY);

    if( bAutoStyles )
    {
        if( xHeader.is() )
@@ -134,6 +138,12 @@ void XMLTableMasterPageExport::exportMasterPageContent(
            exportHeaderFooterContent( xHeaderLeft->getLeftText(), true, false );
            exportHeaderFooterContent( xHeaderLeft->getRightText(), true, false );
        }
        if( xHeaderFirst.is())
        {
            exportHeaderFooterContent( xHeaderFirst->getCenterText(), true, false );
            exportHeaderFooterContent( xHeaderFirst->getLeftText(), true, false );
            exportHeaderFooterContent( xHeaderFirst->getRightText(), true, false );
        }
        if( xFooter.is() )
        {
            exportHeaderFooterContent( xFooter->getCenterText(), true, false );
@@ -146,6 +156,12 @@ void XMLTableMasterPageExport::exportMasterPageContent(
            exportHeaderFooterContent( xFooterLeft->getLeftText(), true, false );
            exportHeaderFooterContent( xFooterLeft->getRightText(), true, false );
        }
        if( xFooterFirst.is())
        {
            exportHeaderFooterContent( xFooterFirst->getCenterText(), true, false );
            exportHeaderFooterContent( xFooterFirst->getLeftText(), true, false );
            exportHeaderFooterContent( xFooterFirst->getRightText(), true, false );
        }
    }
    else
    {
@@ -157,6 +173,10 @@ void XMLTableMasterPageExport::exportMasterPageContent(

        exportHeaderFooter( xHeaderLeft, XML_HEADER_LEFT, bLeftHeader );

        bool bFirstHeader(!::cppu::any2bool(rPropSet->getPropertyValue( SC_UNO_PAGE_FIRSTHDRSHARED )) && bHeader);

        exportHeaderFooter( xHeaderFirst, XML_HEADER_FIRST, bFirstHeader );

        bool bFooter(::cppu::any2bool(rPropSet->getPropertyValue( SC_UNO_PAGE_FTRON )));

        exportHeaderFooter( xFooter, XML_FOOTER, bFooter );
@@ -164,6 +184,10 @@ void XMLTableMasterPageExport::exportMasterPageContent(
        bool bLeftFooter = (!::cppu::any2bool(rPropSet->getPropertyValue( SC_UNO_PAGE_FTRSHARED )) && bFooter);

        exportHeaderFooter( xFooterLeft, XML_FOOTER_LEFT, bLeftFooter );

        bool bFirstFooter = (!::cppu::any2bool(rPropSet->getPropertyValue( SC_UNO_PAGE_FIRSTFTRSHARED )) && bFooter);

        exportHeaderFooter( xFooterLeft, XML_FOOTER_FIRST, bFirstFooter );
    }
}

diff --git a/sc/source/filter/xml/xmlfonte.cxx b/sc/source/filter/xml/xmlfonte.cxx
index 76782d1..ab8e42f 100644
--- a/sc/source/filter/xml/xmlfonte.cxx
+++ b/sc/source/filter/xml/xmlfonte.cxx
@@ -77,7 +77,8 @@ ScXMLFontAutoStylePool_Impl::ScXMLFontAutoStylePool_Impl(ScXMLExport& rExportP, 
    sal_uInt16 const aEditWhichIds[] { EE_CHAR_FONTINFO, EE_CHAR_FONTINFO_CJK,
                                       EE_CHAR_FONTINFO_CTL };
    sal_uInt16 const aPageWhichIds[] { ATTR_PAGE_HEADERLEFT, ATTR_PAGE_FOOTERLEFT,
                                       ATTR_PAGE_HEADERRIGHT, ATTR_PAGE_FOOTERRIGHT };
                                       ATTR_PAGE_HEADERRIGHT, ATTR_PAGE_FOOTERRIGHT,
                                       ATTR_PAGE_HEADERFIRST, ATTR_PAGE_FOOTERFIRST };

    const SfxItemPool* pItemPool(rExportP.GetDocument()->GetPool());
    AddFontItems(aWhichIds, 3, pItemPool, true);
diff --git a/sc/source/filter/xml/xmlstyli.cxx b/sc/source/filter/xml/xmlstyli.cxx
index a3db1cf..2c89092 100644
--- a/sc/source/filter/xml/xmlstyli.cxx
+++ b/sc/source/filter/xml/xmlstyli.cxx
@@ -943,7 +943,7 @@ SvXMLImportContext *ScMasterPageContext::CreateHeaderFooterContext(
            const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList,
            const bool bFooter,
            const bool bLeft,
            const bool /*bFirst*/ )
            const bool bFirst )
{
    if (!bLeft)
    {
@@ -958,7 +958,7 @@ SvXMLImportContext *ScMasterPageContext::CreateHeaderFooterContext(
                                                nElement,
                                                xAttrList,
                                                xPropSet,
                                                bFooter, bLeft );
                                                bFooter, bLeft, bFirst );
}

void ScMasterPageContext::ClearContent(const OUString& rContent)
diff --git a/sc/source/ui/inc/printfun.hxx b/sc/source/ui/inc/printfun.hxx
index 4cb4fbe..e972183 100644
--- a/sc/source/ui/inc/printfun.hxx
+++ b/sc/source/ui/inc/printfun.hxx
@@ -50,6 +50,7 @@ struct ScPrintHFParam
    bool                bEnable;
    bool                bDynamic;
    bool                bShared;
    bool                bSharedFirst;
    tools::Long                nHeight;            // in total (height + distance + frames)
    tools::Long                nManHeight;         // set size (min when dynamic)
    sal_uInt16          nDistance;
@@ -57,6 +58,7 @@ struct ScPrintHFParam
    sal_uInt16          nRight;
    const ScPageHFItem* pLeft;
    const ScPageHFItem* pRight;
    const ScPageHFItem* pFirst;
    const SvxBoxItem*   pBorder;
    const SvxBrushItem* pBack;
    const SvxShadowItem* pShadow;
diff --git a/sc/source/ui/pagedlg/tphf.cxx b/sc/source/ui/pagedlg/tphf.cxx
index 3fb27a9..2a8af81 100644
--- a/sc/source/ui/pagedlg/tphf.cxx
+++ b/sc/source/ui/pagedlg/tphf.cxx
@@ -42,7 +42,7 @@

ScHFPage::ScHFPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet, sal_uInt16 nSetId)
    : SvxHFPage(pPage, pController, rSet, nSetId)
    , aDataSet(*rSet.GetPool(), svl::Items<ATTR_PAGE, ATTR_PAGE, ATTR_PAGE_HEADERLEFT, ATTR_PAGE_FOOTERRIGHT>{})
    , aDataSet(*rSet.GetPool(), svl::Items<ATTR_PAGE, ATTR_PAGE, ATTR_PAGE_HEADERLEFT, ATTR_PAGE_FOOTERFIRST>{})
    , nPageUsage(SvxPageUsage::All)
    , pStyleDlg(nullptr)
    , m_xBtnEdit(m_xBuilder->weld_button("buttonEdit"))
@@ -91,11 +91,13 @@ bool ScHFPage::FillItemSet( SfxItemSet* rOutSet )
    {
        rOutSet->Put( aDataSet.Get( ATTR_PAGE_HEADERLEFT ) );
        rOutSet->Put( aDataSet.Get( ATTR_PAGE_HEADERRIGHT ) );
        rOutSet->Put( aDataSet.Get( ATTR_PAGE_HEADERFIRST ) );
    }
    else
    {
        rOutSet->Put( aDataSet.Get( ATTR_PAGE_FOOTERLEFT ) );
        rOutSet->Put( aDataSet.Get( ATTR_PAGE_FOOTERRIGHT ) );
        rOutSet->Put( aDataSet.Get( ATTR_PAGE_FOOTERFIRST ) );
    }

    return bResult;
diff --git a/sc/source/ui/unoobj/styleuno.cxx b/sc/source/ui/unoobj/styleuno.cxx
index 5af2c60..3d63b60 100644
--- a/sc/source/ui/unoobj/styleuno.cxx
+++ b/sc/source/ui/unoobj/styleuno.cxx
@@ -194,6 +194,10 @@ static const SfxItemPropertySet * lcl_GetPageStyleSet()
        {u"" SC_UNO_PAGE_CENTERVER,   ATTR_PAGE_VERCENTER,cppu::UnoType<bool>::get(),            0, 0 },
        {u"" SC_UNONAME_DISPNAME,     SC_WID_UNO_DISPNAME,::cppu::UnoType<OUString>::get(),  beans::PropertyAttribute::READONLY, 0 },
        {u"" SC_UNO_PAGE_FIRSTPAGE,   ATTR_PAGE_FIRSTPAGENO,::cppu::UnoType<sal_Int16>::get(),      0, 0 },
        {u"" SC_UNO_PAGE_FIRSTFTRSHARED, SC_WID_UNO_FOOTERSET,cppu::UnoType<bool>::get(),                       0, 0 },
        {u"" SC_UNO_PAGE_FIRSTHDRSHARED, SC_WID_UNO_HEADERSET,cppu::UnoType<bool>::get(),                       0, 0 },
        {u"" SC_UNO_PAGE_FIRSTFTRCONT, ATTR_PAGE_FOOTERFIRST,cppu::UnoType<sheet::XHeaderFooterContent>::get(), 0, 0 },
        {u"" SC_UNO_PAGE_FIRSTHDRCONT, ATTR_PAGE_HEADERFIRST,cppu::UnoType<sheet::XHeaderFooterContent>::get(), 0, 0 },

        {u"" SC_UNO_PAGE_FTRBACKCOL,  SC_WID_UNO_FOOTERSET,::cppu::UnoType<sal_Int32>::get(),           0, 0 },
        {u"" SC_UNO_PAGE_FTRGRFFILT,  SC_WID_UNO_FOOTERSET,::cppu::UnoType<OUString>::get(),     0, 0 },
@@ -319,6 +323,7 @@ static const SfxItemPropertyMap* lcl_GetHeaderStyleMap()
        {u"" SC_UNO_PAGE_HDRDYNAMIC,  ATTR_PAGE_DYNAMIC,  cppu::UnoType<bool>::get(),            0, 0 },
        {u"" SC_UNO_PAGE_HDRON,       ATTR_PAGE_ON,       cppu::UnoType<bool>::get(),            0, 0 },
        {u"" SC_UNO_PAGE_HDRSHARED,   ATTR_PAGE_SHARED,   cppu::UnoType<bool>::get(),            0, 0 },
        {u"" SC_UNO_PAGE_FIRSTHDRSHARED, ATTR_PAGE_SHARED_FIRST, cppu::UnoType<bool>::get(),     0, 0 },
        {u"" SC_UNO_PAGE_HDRLEFTBOR,  ATTR_BORDER,        ::cppu::UnoType<table::BorderLine>::get(),        0, LEFT_BORDER | CONVERT_TWIPS },
        {u"" SC_UNO_PAGE_HDRLEFTBDIS, ATTR_BORDER,        ::cppu::UnoType<sal_Int32>::get(),    0, LEFT_BORDER_DISTANCE | CONVERT_TWIPS },
        {u"" SC_UNO_PAGE_HDRLEFTMAR,  ATTR_LRSPACE,       ::cppu::UnoType<sal_Int32>::get(),            0, MID_L_MARGIN | CONVERT_TWIPS },
@@ -359,6 +364,7 @@ static const SfxItemPropertyMap* lcl_GetFooterStyleMap()
        {u"" SC_UNO_PAGE_FTRDYNAMIC,  ATTR_PAGE_DYNAMIC,  cppu::UnoType<bool>::get(),            0, 0 },
        {u"" SC_UNO_PAGE_FTRON,       ATTR_PAGE_ON,       cppu::UnoType<bool>::get(),            0, 0 },
        {u"" SC_UNO_PAGE_FTRSHARED,   ATTR_PAGE_SHARED,   cppu::UnoType<bool>::get(),            0, 0 },
        {u"" SC_UNO_PAGE_FIRSTFTRSHARED, ATTR_PAGE_SHARED_FIRST, cppu::UnoType<bool>::get(),     0, 0 },
        {u"" SC_UNO_PAGE_FTRLEFTBOR,  ATTR_BORDER,        ::cppu::UnoType<table::BorderLine>::get(),        0, LEFT_BORDER | CONVERT_TWIPS },
        {u"" SC_UNO_PAGE_FTRLEFTBDIS, ATTR_BORDER,        ::cppu::UnoType<sal_Int32>::get(),    0, LEFT_BORDER_DISTANCE | CONVERT_TWIPS },
        {u"" SC_UNO_PAGE_FTRLEFTMAR,  ATTR_LRSPACE,       ::cppu::UnoType<sal_Int32>::get(),            0, MID_L_MARGIN | CONVERT_TWIPS },
diff --git a/sc/source/ui/view/printfun.cxx b/sc/source/ui/view/printfun.cxx
index dc084ec..f099247 100644
--- a/sc/source/ui/view/printfun.cxx
+++ b/sc/source/ui/view/printfun.cxx
@@ -653,6 +653,7 @@ static void lcl_FillHFParam( ScPrintHFParam& rParam, const SfxItemSet* pHFSet )
        rParam.bEnable  = pHFSet->Get(ATTR_PAGE_ON).GetValue();
        rParam.bDynamic = pHFSet->Get(ATTR_PAGE_DYNAMIC).GetValue();
        rParam.bShared  = pHFSet->Get(ATTR_PAGE_SHARED).GetValue();
        rParam.bSharedFirst = pHFSet->Get(ATTR_PAGE_SHARED_FIRST).GetValue();
        rParam.nHeight  = pHFSet->Get(ATTR_PAGE_SIZE).GetSize().Height();
        const SvxLRSpaceItem* pHFLR = &pHFSet->Get(ATTR_LRSPACE);
        tools::Long nTmp;
@@ -814,6 +815,12 @@ void ScPrintFunc::UpdateHFHeight( ScPrintHFParam& rParam )
        nMaxHeight = std::max( nMaxHeight, TextHeight( rParam.pRight->GetCenterArea() ) );
        nMaxHeight = std::max( nMaxHeight, TextHeight( rParam.pRight->GetRightArea() ) );
    }
    if ( rParam.pFirst )
    {
        nMaxHeight = std::max( nMaxHeight, TextHeight( rParam.pFirst->GetLeftArea() ) );
        nMaxHeight = std::max( nMaxHeight, TextHeight( rParam.pFirst->GetCenterArea() ) );
        nMaxHeight = std::max( nMaxHeight, TextHeight( rParam.pFirst->GetRightArea() ) );
    }

    rParam.nHeight = nMaxHeight + rParam.nDistance;
    if (rParam.pBorder)
@@ -868,6 +875,7 @@ void ScPrintFunc::InitParam( const ScPrintOptions* pOptions )

    aHdr.pLeft      = &pParamSet->Get(ATTR_PAGE_HEADERLEFT);      // Content
    aHdr.pRight     = &pParamSet->Get(ATTR_PAGE_HEADERRIGHT);
    aHdr.pFirst     = &pParamSet->Get(ATTR_PAGE_HEADERFIRST);

    const SvxSetItem* pHeaderSetItem;
    const SfxItemSet* pHeaderSet = nullptr;
@@ -884,6 +892,7 @@ void ScPrintFunc::InitParam( const ScPrintOptions* pOptions )

    aFtr.pLeft      = &pParamSet->Get(ATTR_PAGE_FOOTERLEFT);      // Content
    aFtr.pRight     = &pParamSet->Get(ATTR_PAGE_FOOTERRIGHT);
    aFtr.pFirst     = &pParamSet->Get(ATTR_PAGE_FOOTERFIRST);

    const SvxSetItem* pFooterSetItem;
    const SfxItemSet* pFooterSet = nullptr;
@@ -1742,8 +1751,9 @@ void ScPrintFunc::PrintHF( tools::Long nPageNo, bool bHeader, tools::Long nStart

    pDev->SetMapMode( aTwipMode );          // Head-/Footlines in Twips

    bool bFirst = 0 == nPageNo && !rParam.bSharedFirst;
    bool bLeft = IsLeft(nPageNo) && !rParam.bShared;
    const ScPageHFItem* pHFItem = bLeft ? rParam.pLeft : rParam.pRight;
    const ScPageHFItem* pHFItem = bFirst ? rParam.pFirst : (bLeft ? rParam.pLeft : rParam.pRight);

    tools::Long nLineStartX = aPageRect.Left()  + rParam.nLeft;
    tools::Long nLineEndX   = aPageRect.Right() - rParam.nRight;