diff options
author | Attila Szűcs <szucs.attila3@nisz.hu> | 2020-07-23 14:51:01 +0200 |
---|---|---|
committer | László Németh <nemeth@numbertext.org> | 2020-08-05 12:40:15 +0200 |
commit | a858284092e976fa284d5ed118e366d9860ec9bb (patch) | |
tree | 31e0d5660f9cf2d0ba76a33e5f9d9b0a9c7b5b11 | |
parent | d32dfe40f18904bbd30f497d0a2f546d58d6041b (diff) |
tdf#121716 XLSX export: fix loss of left header (footer)
when footer (header) is shared (even).
Co-authored-by: Tibor Nagy (NISZ)
Change-Id: I6e656f2df1f9b6522af933bd1c71b8d60bbfe19f
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/99315
Tested-by: László Németh <nemeth@numbertext.org>
Reviewed-by: László Németh <nemeth@numbertext.org>
-rw-r--r-- | sc/qa/unit/data/ods/tdf121716_EvenHeaderFooter.ods | bin | 0 -> 9487 bytes | |||
-rw-r--r-- | sc/qa/unit/subsequent_export-test.cxx | 36 | ||||
-rw-r--r-- | sc/source/filter/excel/xepage.cxx | 49 | ||||
-rw-r--r-- | sc/source/filter/excel/xipage.cxx | 8 | ||||
-rw-r--r-- | sc/source/filter/excel/xlpage.cxx | 3 | ||||
-rw-r--r-- | sc/source/filter/inc/xlpage.hxx | 9 |
6 files changed, 97 insertions, 8 deletions
diff --git a/sc/qa/unit/data/ods/tdf121716_EvenHeaderFooter.ods b/sc/qa/unit/data/ods/tdf121716_EvenHeaderFooter.ods Binary files differnew file mode 100644 index 000000000000..2666a9d4291e --- /dev/null +++ b/sc/qa/unit/data/ods/tdf121716_EvenHeaderFooter.ods diff --git a/sc/qa/unit/subsequent_export-test.cxx b/sc/qa/unit/subsequent_export-test.cxx index f0e4b5c44c55..4a9e85efecf0 100644 --- a/sc/qa/unit/subsequent_export-test.cxx +++ b/sc/qa/unit/subsequent_export-test.cxx @@ -252,6 +252,7 @@ public: void testTdf81470(); void testTdf122331(); void testTdf83779(); + void testTdf121716_ExportEvenHeaderFooterXLSX(); void testTdf134459_HeaderFooterColorXLSX(); void testTdf134817_HeaderFooterTextWith2SectionXLSX(); void testHeaderFontStyleXLSX(); @@ -405,6 +406,7 @@ public: CPPUNIT_TEST(testTdf81470); CPPUNIT_TEST(testTdf122331); CPPUNIT_TEST(testTdf83779); + CPPUNIT_TEST(testTdf121716_ExportEvenHeaderFooterXLSX); CPPUNIT_TEST(testTdf134459_HeaderFooterColorXLSX); CPPUNIT_TEST(testTdf134817_HeaderFooterTextWith2SectionXLSX); CPPUNIT_TEST(testHeaderFontStyleXLSX); @@ -5148,6 +5150,40 @@ void ScExportTest::testTdf83779() xShell->DoClose(); } +void ScExportTest::testTdf121716_ExportEvenHeaderFooterXLSX() +{ + // Header and footer on even pages should be exported properly + // If there are separate odd/even header, but only 1 footer for all pages (this is possible only in LibreOffice) + // then the footer will be duplicated to have the same footer separately for even/odd pages + + ScDocShellRef xShell = loadDoc("tdf121716_EvenHeaderFooter.", FORMAT_ODS); + CPPUNIT_ASSERT(xShell.is()); + + ScDocShellRef xDocSh = saveAndReload(&(*xShell), FORMAT_XLSX); + CPPUNIT_ASSERT(xDocSh.is()); + + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(&(*xDocSh), FORMAT_XLSX); + xmlDocUniquePtr pDoc = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/sheet1.xml"); + CPPUNIT_ASSERT(pDoc); + + assertXPath(pDoc, "/x:worksheet/x:headerFooter", "differentOddEven", "true"); + assertXPathContent(pDoc, "/x:worksheet/x:headerFooter/x:oddHeader", "&Lodd/right&Cpage&Rheader"); + assertXPathContent(pDoc, "/x:worksheet/x:headerFooter/x:oddFooter", "&Lboth&C&12page&Rfooter"); + assertXPathContent(pDoc, "/x:worksheet/x:headerFooter/x:evenHeader", "&Lpage&Cheader&Reven/left"); + assertXPathContent(pDoc, "/x:worksheet/x:headerFooter/x:evenFooter", "&Lboth&C&12page&Rfooter"); + + pDoc = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/sheet2.xml"); + CPPUNIT_ASSERT(pDoc); + + assertXPath(pDoc, "/x:worksheet/x:headerFooter", "differentOddEven", "true"); + assertXPathContent(pDoc, "/x:worksheet/x:headerFooter/x:oddHeader", "&Coddh"); + assertXPathContent(pDoc, "/x:worksheet/x:headerFooter/x:oddFooter", "&Coddf"); + assertXPathContent(pDoc, "/x:worksheet/x:headerFooter/x:evenHeader", "&Cevenh"); + assertXPathContent(pDoc, "/x:worksheet/x:headerFooter/x:evenFooter", "&Levenf"); + + xDocSh->DoClose(); +} + void ScExportTest::testTdf134459_HeaderFooterColorXLSX() { // Colors in header and footer should be exported, and imported properly diff --git a/sc/source/filter/excel/xepage.cxx b/sc/source/filter/excel/xepage.cxx index aea06c72157b..3941bd191f92 100644 --- a/sc/source/filter/excel/xepage.cxx +++ b/sc/source/filter/excel/xepage.cxx @@ -58,7 +58,14 @@ XclExpHeaderFooter::XclExpHeaderFooter( sal_uInt16 nRecId, const OUString& rHdrS void XclExpHeaderFooter::SaveXml( XclExpXmlStream& rStrm ) { sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream(); - sal_Int32 nElement = GetRecId() == EXC_ID_HEADER ? XML_oddHeader : XML_oddFooter; + 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_FOOTER: + default: nElement = XML_oddFooter; + } rWorksheet->startElement(nElement); rWorksheet->writeEscaped( maHdrString ); rWorksheet->endElement( nElement ); @@ -252,7 +259,6 @@ XclExpPageSettings::XclExpPageSettings( const XclExpRoot& rRoot ) : maData.mnFitToWidth = rScaleToItem.GetWidth(); maData.mnFitToHeight = rScaleToItem.GetHeight(); maData.mbFitToPages = true; - } else if( ScfTools::CheckItem( rItemSet, ATTR_PAGE_SCALETOPAGES, false ) && nPages ) { @@ -267,6 +273,7 @@ XclExpPageSettings::XclExpPageSettings( const XclExpRoot& rRoot ) : } maData.mxBrushItem.reset( new SvxBrushItem( rItemSet.Get( ATTR_BACKGROUND ) ) ); + maData.mbUseEvenHF = false; // *** header and footer *** @@ -279,6 +286,18 @@ XclExpPageSettings::XclExpPageSettings( const XclExpRoot& rRoot ) : const ScPageHFItem& rHFItem = rItemSet.Get( ATTR_PAGE_HEADERRIGHT ); aHFConv.GenerateString( rHFItem.GetLeftArea(), rHFItem.GetCenterArea(), rHFItem.GetRightArea() ); maData.maHeader = aHFConv.GetHFString(); + if ( rHdrItemSet.HasItem(ATTR_PAGE_SHARED) && !rHdrItemSet.Get(ATTR_PAGE_SHARED).GetValue()) + { + const ScPageHFItem& rHFItemLeft = rItemSet.Get( ATTR_PAGE_HEADERLEFT ); + aHFConv.GenerateString( rHFItemLeft.GetLeftArea(), rHFItemLeft.GetCenterArea(), rHFItemLeft.GetRightArea() ); + maData.maHeaderEven = aHFConv.GetHFString(); + maData.mbUseEvenHF = true; + } + else + { + // If maData.mbUseEvenHF become true, then we will need a copy of maHeader in maHeaderEven. + maData.maHeaderEven = 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 @@ -296,6 +315,17 @@ XclExpPageSettings::XclExpPageSettings( const XclExpRoot& rRoot ) : const ScPageHFItem& rHFItem = rItemSet.Get( ATTR_PAGE_FOOTERRIGHT ); aHFConv.GenerateString( rHFItem.GetLeftArea(), rHFItem.GetCenterArea(), rHFItem.GetRightArea() ); maData.maFooter = aHFConv.GetHFString(); + if (rFtrItemSet.HasItem(ATTR_PAGE_SHARED) && !rFtrItemSet.Get(ATTR_PAGE_SHARED).GetValue()) + { + const ScPageHFItem& rHFItemLeft = rItemSet.Get( ATTR_PAGE_FOOTERLEFT ); + aHFConv.GenerateString( rHFItemLeft.GetLeftArea(), rHFItemLeft.GetCenterArea(), rHFItemLeft.GetRightArea() ); + maData.maFooterEven = aHFConv.GetHFString(); + maData.mbUseEvenHF = true; + } + else + { + maData.maFooterEven = 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 @@ -340,10 +370,12 @@ namespace { class XclExpXmlStartHeaderFooterElementRecord : public XclExpXmlElementRecord { public: - explicit XclExpXmlStartHeaderFooterElementRecord(sal_Int32 const nElement) - : XclExpXmlElementRecord(nElement) {} + explicit XclExpXmlStartHeaderFooterElementRecord(sal_Int32 const nElement, bool const bDifferentOddEven = false) + : XclExpXmlElementRecord(nElement), mbDifferentOddEven(bDifferentOddEven) {} virtual void SaveXml( XclExpXmlStream& rStrm ) override; +private: + bool mbDifferentOddEven; }; } @@ -356,7 +388,7 @@ void XclExpXmlStartHeaderFooterElementRecord::SaveXml(XclExpXmlStream& rStrm) rStream->startElement( mnElement, // OOXTODO: XML_alignWithMargins, XML_differentFirst, "false", // OOXTODO - XML_differentOddEven, "false" // OOXTODO + XML_differentOddEven, mbDifferentOddEven ? "true" : "false" // OOXTODO: XML_scaleWithDoc ); } @@ -404,9 +436,14 @@ void XclExpPageSettings::SaveXml( XclExpXmlStream& rStrm ) XclExpSetup( maData ).SaveXml( rStrm ); - XclExpXmlStartHeaderFooterElementRecord(XML_headerFooter).SaveXml(rStrm); + XclExpXmlStartHeaderFooterElementRecord(XML_headerFooter, maData.mbUseEvenHF).SaveXml(rStrm); XclExpHeaderFooter( EXC_ID_HEADER, maData.maHeader ).SaveXml( rStrm ); XclExpHeaderFooter( EXC_ID_FOOTER, maData.maFooter ).SaveXml( rStrm ); + if (maData.mbUseEvenHF) + { + XclExpHeaderFooter( EXC_ID_HEADER_EVEN, maData.maHeaderEven ).SaveXml( rStrm ); + XclExpHeaderFooter( EXC_ID_FOOTER_EVEN, maData.maFooterEven ).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 7436c3eaed2c..c0207a033b00 100644 --- a/sc/source/filter/excel/xipage.cxx +++ b/sc/source/filter/excel/xipage.cxx @@ -118,13 +118,17 @@ void XclImpPageSettings::ReadHeaderFooter( XclImpStream& rStrm ) switch( rStrm.GetRecId() ) { - case EXC_ID_HEADER: maData.maHeader = aString; break; - case EXC_ID_FOOTER: maData.maFooter = aString; break; + case EXC_ID_HEADER: maData.maHeader = aString; break; + case EXC_ID_FOOTER: maData.maFooter = aString; break; + case EXC_ID_HEADER_EVEN: maData.maHeaderEven = aString; break; + case EXC_ID_FOOTER_EVEN: maData.maFooterEven = aString; break; default: OSL_FAIL( "XclImpPageSettings::ReadHeaderFooter - unknown record" ); } if (maData.maHeader.getLength() > 10 && utl::ConfigManager::IsFuzzing()) maData.maHeader = maData.maHeader.copy(0, 10); + if (maData.maHeaderEven.getLength() > 10 && utl::ConfigManager::IsFuzzing()) + maData.maHeaderEven = maData.maHeaderEven.copy(0, 10); } void XclImpPageSettings::ReadPageBreaks( XclImpStream& rStrm ) diff --git a/sc/source/filter/excel/xlpage.cxx b/sc/source/filter/excel/xlpage.cxx index fb08932872f1..3f13befddcfa 100644 --- a/sc/source/filter/excel/xlpage.cxx +++ b/sc/source/filter/excel/xlpage.cxx @@ -180,6 +180,8 @@ void XclPageData::SetDefaults() mxBrushItem.reset(); maHeader.clear(); maFooter.clear(); + maHeaderEven.clear(); + maFooterEven.clear(); mfLeftMargin = mfRightMargin = XclTools::GetInchFromHmm( EXC_MARGIN_DEFAULT_LR ); mfTopMargin = mfBottomMargin = XclTools::GetInchFromHmm( EXC_MARGIN_DEFAULT_TB ); mfHeaderMargin = mfFooterMargin = XclTools::GetInchFromHmm( EXC_MARGIN_DEFAULT_HF ); @@ -193,6 +195,7 @@ void XclPageData::SetDefaults() mnScaling = 100; mnFitToWidth = mnFitToHeight = 1; mnHorPrintRes = mnVerPrintRes = 300; + mbUseEvenHF = /*mbUseFirstHF =*/ false; mbValid = false; mbPortrait = true; mbPrintInRows = mbBlackWhite = mbDraftQuality = mbPrintNotes = mbManualStart = mbFitToPages = false; diff --git a/sc/source/filter/inc/xlpage.hxx b/sc/source/filter/inc/xlpage.hxx index 8ae20f85d1ba..36190b2e8693 100644 --- a/sc/source/filter/inc/xlpage.hxx +++ b/sc/source/filter/inc/xlpage.hxx @@ -31,6 +31,11 @@ const sal_uInt16 EXC_ID_HEADER = 0x0014; const sal_uInt16 EXC_ID_FOOTER = 0x0015; +// (0x0016, 0x0017) EVEN HEADER, EVEN FOOTER ---------------------------------- + +const sal_uInt16 EXC_ID_HEADER_EVEN = 0x0016; +const sal_uInt16 EXC_ID_FOOTER_EVEN = 0x0017; + // (0x001A, 0x001B) VERTICAL-, HORIZONTALPAGEBREAKS --------------------------- const sal_uInt16 EXC_ID_VERPAGEBREAKS = 0x001A; @@ -102,6 +107,8 @@ struct XclPageData SvxBrushItemPtr mxBrushItem; /// Background bitmap. OUString maHeader; /// Excel header string (empty = off). 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). double mfLeftMargin; /// Left margin in inches. double mfRightMargin; /// Right margin in inches. double mfTopMargin; /// Top margin in inches. @@ -123,6 +130,8 @@ struct XclPageData sal_uInt16 mnFitToHeight; /// Fit to number of pages in height. 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 mbValid; /// false = some of the values are not valid. bool mbPortrait; /// true = portrait; false = landscape. bool mbPrintInRows; /// true = in rows; false = in columns. |