summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAttila Szűcs <szucs.attila3@nisz.hu>2020-07-23 14:51:01 +0200
committerLászló Németh <nemeth@numbertext.org>2020-08-05 12:40:15 +0200
commita858284092e976fa284d5ed118e366d9860ec9bb (patch)
tree31e0d5660f9cf2d0ba76a33e5f9d9b0a9c7b5b11
parentd32dfe40f18904bbd30f497d0a2f546d58d6041b (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.odsbin0 -> 9487 bytes
-rw-r--r--sc/qa/unit/subsequent_export-test.cxx36
-rw-r--r--sc/source/filter/excel/xepage.cxx49
-rw-r--r--sc/source/filter/excel/xipage.cxx8
-rw-r--r--sc/source/filter/excel/xlpage.cxx3
-rw-r--r--sc/source/filter/inc/xlpage.hxx9
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
new file mode 100644
index 000000000000..2666a9d4291e
--- /dev/null
+++ b/sc/qa/unit/data/ods/tdf121716_EvenHeaderFooter.ods
Binary files differ
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.