include/oox/export/chartexport.hxx | 1 + oox/source/export/chartexport.cxx | 2 +- sw/qa/extras/ooxmlexport/ooxmlexport4.cxx | 15 +++++++++++++++ sw/source/filter/ww8/docxexport.cxx | 14 ++++++++++++++ sw/source/filter/ww8/docxexport.hxx | 2 ++ 5 files changed, 33 insertions(+), 1 deletion(-)
New commits: commit 1545e246fd15bbbcb4ebe9234d8d915989b0aba4 Author: Justin Luth <[email protected]> AuthorDate: Thu Jan 8 16:52:31 2026 -0500 Commit: Miklos Vajna <[email protected]> CommitDate: Mon Jan 12 10:12:42 2026 +0100 tdf#168977 docx export: prevent multiple chart rels to embeddings/file MS Word considers a document to be corrupt if multiple files have a relationship to the same embeddings/file. Since we only round-trip existing embeddings, just make sure that if we duplicate a chart internally, that we only write an externalData link once. make CppunitTest_sw_ooxmlexport4 CPPUNIT_TEST_NAME=testChartInFooter Change-Id: I8905412b07fdf8dc065d1fed4c239c63aab24935 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/196895 Reviewed-by: Justin Luth <[email protected]> Tested-by: Jenkins (cherry picked from commit 81a1539bf2e197de1275af762b26e98652551a8a) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/196940 Tested-by: Jenkins CollaboraOffice <[email protected]> Reviewed-by: Miklos Vajna <[email protected]> diff --git a/include/oox/export/chartexport.hxx b/include/oox/export/chartexport.hxx index 61828fac5a31..2dd2dc1517ac 100644 --- a/include/oox/export/chartexport.hxx +++ b/include/oox/export/chartexport.hxx @@ -142,6 +142,7 @@ class ChartExport final : public DrawingML { public: // first: data sequence for label, second: data sequence for values. typedef ::std::vector< AxisIdPair > AxisVector; + bool mbLinkToExternalData = true; private: sal_Int32 mnXmlNamespace; diff --git a/oox/source/export/chartexport.cxx b/oox/source/export/chartexport.cxx index c2947c9edf5c..96707264c9d2 100644 --- a/oox/source/export/chartexport.cxx +++ b/oox/source/export/chartexport.cxx @@ -1683,7 +1683,7 @@ void ChartExport::exportExternalData( const Reference< css::chart::XChartDocumen if (bIsChartex) return; // TODO!! // Embedded external data is grab bagged for docx file hence adding export part of // external data for docx files only. - if(GetDocumentType() != DOCUMENT_DOCX) + if(!mbLinkToExternalData || GetDocumentType() != DOCUMENT_DOCX) return; OUString externalDataPath; diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx index 5f8dacd51b80..9e14f0deb2f5 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx @@ -429,6 +429,21 @@ CPPUNIT_TEST_FIXTURE(Test, testChartInFooter) u"rId1"); CPPUNIT_ASSERT_EQUAL(1, getShapes()); + + // tdf#168977: MS Word reports corrupt if same embeddings/file referred to by multiple charts + // Currently, we duplicate a chart into the first page footer (from the 'default' footer) + xmlDocUniquePtr pXmlChart1Rels = parseExport(u"word/charts/_rels/chart1.xml.rels"_ustr); + assertXPath(pXmlChart1Rels, + "//rels:Relationship[@Target='../embeddings/Microsoft_Excel_Worksheet1.xlsx']"); + + uno::Reference<packages::zip::XZipFileAccess2> xNameAccess + = packages::zip::ZipFileAccess::createWithURL(comphelper::getComponentContext(m_xSFactory), + maTempFile.GetURL()); + CPPUNIT_ASSERT(xNameAccess->hasByName(u"word/charts/chart2.xml"_ustr)); // first page footer + // without the fix, this was true; both charts referred to the same 'Microsoft_Excel_Worksheet1' + CPPUNIT_ASSERT_EQUAL(false, + bool(xNameAccess->hasByName(u"word/charts/_rels/chart2.xml.rels"_ustr))); + } CPPUNIT_TEST_FIXTURE(Test, testNestedTextFrames) diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx index 5a24c0597868..74959a4a1437 100644 --- a/sw/source/filter/ww8/docxexport.cxx +++ b/sw/source/filter/ww8/docxexport.cxx @@ -404,7 +404,21 @@ OString DocxExport::OutputChart( uno::Reference< frame::XModel > const & xModel, oox::drawingml::ChartExport aChartExport(XML_w, pChartFS, xModel, &m_rFilter, oox::drawingml::DOCUMENT_DOCX); css::uno::Reference<css::util::XModifiable> xModifiable(xModel, css::uno::UNO_QUERY); const bool bOldModified = xModifiable && xModifiable->isModified(); + + // Currently, content in ../embeddings is simply grab-bagged as OOEmbeddings + // and must only be referred to once or else MS Word considers the document corrupt, + // so if a chart is duplicated (common in headers/footers) then only exportExternalData once. + for (const auto& xExport : m_aExportedCharts) + { + if (xExport != xModel) + continue; + + aChartExport.mbLinkToExternalData = false; + break; + } + aChartExport.ExportContent(); + m_aExportedCharts.push_back(xModel); if (!bOldModified && xModifiable && xModifiable->isModified()) // tdf#134973: the model could get modified: e.g., calling XChartDocument::getSubTitle(), // which creates the object if absent, and sets the modified state. diff --git a/sw/source/filter/ww8/docxexport.hxx b/sw/source/filter/ww8/docxexport.hxx index ad339ad3bde1..0e20b9f30e58 100644 --- a/sw/source/filter/ww8/docxexport.hxx +++ b/sw/source/filter/ww8/docxexport.hxx @@ -131,6 +131,8 @@ class DocxExport : public MSWordExportBase std::set<SwNode*> m_aDummyFloatingTableAnchors; + std::vector<css::uno::Reference<frame::XModel>> m_aExportedCharts; + public: DocxExportFilter& GetFilter() { return m_rFilter; };
