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 81a1539bf2e197de1275af762b26e98652551a8a Author: Justin Luth <[email protected]> AuthorDate: Thu Jan 8 16:52:31 2026 -0500 Commit: Justin Luth <[email protected]> CommitDate: Fri Jan 9 20:10:47 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 diff --git a/include/oox/export/chartexport.hxx b/include/oox/export/chartexport.hxx index 5248e244cbd4..385fda19f806 100644 --- a/include/oox/export/chartexport.hxx +++ b/include/oox/export/chartexport.hxx @@ -140,6 +140,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 2c695a94d7ca..f477e62664b2 100644 --- a/oox/source/export/chartexport.cxx +++ b/oox/source/export/chartexport.cxx @@ -1821,7 +1821,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 c5aeb4d1342d..bed61269e457 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx @@ -470,6 +470,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 fa8ce467faf3..00d9a1005d8f 100644 --- a/sw/source/filter/ww8/docxexport.cxx +++ b/sw/source/filter/ww8/docxexport.cxx @@ -405,7 +405,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 6f092664ad1a..ac5700d77867 100644 --- a/sw/source/filter/ww8/docxexport.hxx +++ b/sw/source/filter/ww8/docxexport.hxx @@ -126,6 +126,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; };
