sc/qa/unit/data/xls/pictureOrder.xls |binary sc/qa/unit/subsequent_export_test3.cxx | 18 ++++++++++++++++++ sc/source/filter/excel/excdoc.cxx | 7 ++----- sc/source/filter/excel/xeescher.cxx | 4 +++- sc/source/filter/inc/xcl97rec.hxx | 4 +++- sc/source/filter/inc/xeescher.hxx | 2 +- sc/source/filter/xcl97/xcl97rec.cxx | 11 +++++++++++ 7 files changed, 38 insertions(+), 8 deletions(-)
New commits: commit 749e49c00afbaf711c1c68c28d208e1335fb6701 Author: Ujjawal Kumar <[email protected]> AuthorDate: Fri Feb 27 14:54:05 2026 +0530 Commit: Miklos Vajna <[email protected]> CommitDate: Fri Mar 6 09:48:53 2026 +0100 ooxml: Save <picture> before control objs as listed in the ECMA specs Bug document: fdo69453-1.xls The above document contains <picture> tag on sheet 20 and 21 and is written after the <mc:AlternateContent> which is an incorrect order according to the ECMA specs and should be written before control objects. Change-Id: I14bb128281c75d47ee063dd516588a58a0f37dce Reviewed-on: https://gerrit.libreoffice.org/c/core/+/200905 Tested-by: Jenkins CollaboraOffice <[email protected]> Reviewed-by: Miklos Vajna <[email protected]> diff --git a/sc/qa/unit/data/xls/pictureOrder.xls b/sc/qa/unit/data/xls/pictureOrder.xls new file mode 100644 index 000000000000..07e8a9d4508f Binary files /dev/null and b/sc/qa/unit/data/xls/pictureOrder.xls differ diff --git a/sc/qa/unit/subsequent_export_test3.cxx b/sc/qa/unit/subsequent_export_test3.cxx index 721c8c5edc34..40a32fae80f2 100644 --- a/sc/qa/unit/subsequent_export_test3.cxx +++ b/sc/qa/unit/subsequent_export_test3.cxx @@ -2093,6 +2093,24 @@ CPPUNIT_TEST_FIXTURE(ScExportTest3, testTdf170292) u"OFFSET(_cat1,0,2,,)"); } +CPPUNIT_TEST_FIXTURE(ScExportTest3, testPictureTagOrder) +{ + createScDoc("xls/pictureOrder.xls"); + save(TestFilter::XLSX); + + xmlDocUniquePtr pSheet = parseExport(u"xl/worksheets/sheet3.xml"_ustr); + CPPUNIT_ASSERT(pSheet); + assertXPath(pSheet, "/x:worksheet/x:picture", 1); + assertXPath(pSheet, "/x:worksheet/mc:AlternateContent", 1); + assertXPath(pSheet, "/x:worksheet/x:picture/following-sibling::mc:AlternateContent", 1); + + pSheet = parseExport(u"xl/worksheets/sheet4.xml"_ustr); + CPPUNIT_ASSERT(pSheet); + assertXPath(pSheet, "/x:worksheet/x:picture", 1); + assertXPath(pSheet, "/x:worksheet/mc:AlternateContent", 1); + assertXPath(pSheet, "/x:worksheet/x:picture/following-sibling::mc:AlternateContent", 1); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/excel/excdoc.cxx b/sc/source/filter/excel/excdoc.cxx index 86e525ad690f..fcede55fe909 100644 --- a/sc/source/filter/excel/excdoc.cxx +++ b/sc/source/filter/excel/excdoc.cxx @@ -638,12 +638,9 @@ void ExcTable::FillAsTableXml() aRecList.AppendRecord( xPageSett ); + std::unique_ptr<XclExpImgData> pImgData(xPageSett->getGraphicExport()); // all MSODRAWING and OBJ stuff of this sheet goes here - aRecList.AppendRecord( GetObjectManager().ProcessDrawing( GetSdrPage( mnScTab ) ) ); - - XclExpImgData* pImgData = xPageSett->getGraphicExport(); - if (pImgData) - aRecList.AppendRecord(pImgData); + aRecList.AppendRecord( GetObjectManager().ProcessDrawing( GetSdrPage( mnScTab ), std::move(pImgData) ) ); // <tableParts> after <drawing> and before <extLst> aRecList.AppendRecord( GetTablesManager().GetTablesBySheet( mnScTab)); diff --git a/sc/source/filter/excel/xeescher.cxx b/sc/source/filter/excel/xeescher.cxx index 005ae21ef86c..ca1eb5a56463 100644 --- a/sc/source/filter/excel/xeescher.cxx +++ b/sc/source/filter/excel/xeescher.cxx @@ -2037,7 +2037,7 @@ void XclExpObjectManager::StartSheet() mxObjList = new XclExpObjList( GetRoot(), *mxEscherEx ); } -rtl::Reference< XclExpRecordBase > XclExpObjectManager::ProcessDrawing( const SdrPage* pSdrPage ) +rtl::Reference< XclExpRecordBase > XclExpObjectManager::ProcessDrawing( const SdrPage* pSdrPage, std::unique_ptr<XclExpImgData> pImgData ) { if( pSdrPage ) mxEscherEx->AddSdrPage( *pSdrPage, GetOutput() != EXC_OUTPUT_BINARY ); @@ -2045,6 +2045,8 @@ rtl::Reference< XclExpRecordBase > XclExpObjectManager::ProcessDrawing( const Sd OSL_ENSURE( mxEscherEx->GetGroupLevel() <= 1, "XclExpObjectManager::ProcessDrawing - still groups open?" ); while( mxEscherEx->GetGroupLevel() ) mxEscherEx->LeaveGroup(); + if (pImgData) + mxObjList->SetImageData(std::move(pImgData)); mxObjList->EndSheet(); return mxObjList; } diff --git a/sc/source/filter/inc/xcl97rec.hxx b/sc/source/filter/inc/xcl97rec.hxx index 27a7b4261af5..58e23be2c193 100644 --- a/sc/source/filter/inc/xcl97rec.hxx +++ b/sc/source/filter/inc/xcl97rec.hxx @@ -27,6 +27,7 @@ #include <svx/svdobj.hxx> #include <oox/export/drawingml.hxx> +class XclExpImgData; class XclObj; class XclExpMsoDrawing; class SdrCaptionObj; @@ -75,7 +76,7 @@ public: iterator end () { return maObjs.end(); } XclExpMsoDrawing* GetMsodrawingPerSheet() { return pMsodrawingPerSheet.get(); } - + void SetImageData(std::unique_ptr<XclExpImgData> pImgData); /// close groups and DgContainer opened in ctor void EndSheet(); @@ -88,6 +89,7 @@ private: XclEscherEx& mrEscherEx; std::unique_ptr<XclExpMsoDrawing> pMsodrawingPerSheet; std::unique_ptr<XclExpMsoDrawing> pSolverContainer; + std::unique_ptr<XclExpImgData> m_pImgData; std::vector<std::unique_ptr<XclObj>> maObjs; }; diff --git a/sc/source/filter/inc/xeescher.hxx b/sc/source/filter/inc/xeescher.hxx index bca4b8801ef2..7aba695f90ec 100644 --- a/sc/source/filter/inc/xeescher.hxx +++ b/sc/source/filter/inc/xeescher.hxx @@ -423,7 +423,7 @@ public: /** Processes a drawing page and returns the record block containing all related records (MSODRAWING, OBJ, TXO, charts, etc.). */ - rtl::Reference< XclExpRecordBase > ProcessDrawing( const SdrPage* pSdrPage ); + rtl::Reference< XclExpRecordBase > ProcessDrawing( const SdrPage* pSdrPage, std::unique_ptr<XclExpImgData> pImgData = nullptr); /** Processes a collection of UNO shapes and returns the record block containing all related records (MSODRAWING, OBJ, TXO, charts, etc.). */ rtl::Reference< XclExpRecordBase > ProcessDrawing( const css::uno::Reference< css::drawing::XShapes >& rxShapes ); diff --git a/sc/source/filter/xcl97/xcl97rec.cxx b/sc/source/filter/xcl97/xcl97rec.cxx index fbd00455271b..fd165830f7f9 100644 --- a/sc/source/filter/xcl97/xcl97rec.cxx +++ b/sc/source/filter/xcl97/xcl97rec.cxx @@ -132,6 +132,11 @@ std::unique_ptr<XclObj> XclExpObjList::pop_back () return ret; } +void XclExpObjList::SetImageData(std::unique_ptr<XclExpImgData> pImgData) +{ + m_pImgData = std::move(pImgData); +} + void XclExpObjList::EndSheet() { // Is there still something in the stream? -> The solver container @@ -398,10 +403,16 @@ void XclExpObjList::SaveXml( XclExpXmlStream& rStrm ) pSolverContainer->SaveXml( rStrm ); if( maObjs.empty()) + { + if (m_pImgData) + m_pImgData->SaveXml(rStrm); return; + } SaveDrawingMLObjects( *this, rStrm ); SaveVmlObjects( *this, rStrm ); + if (m_pImgData) + m_pImgData->SaveXml(rStrm); SaveFormControlObjects( *this, rStrm ); }
