chart2/qa/extras/chart2export3.cxx | 22 +++++++++ chart2/qa/extras/data/odt/testEmptyCharts.odt |binary oox/source/export/chartexport.cxx | 63 ++++++++++++++++---------- 3 files changed, 61 insertions(+), 24 deletions(-)
New commits: commit 15350f4d89e2bdf681c35d9b20a648bbdd6d4240 Author: Aron Budea <[email protected]> AuthorDate: Thu Oct 16 20:17:44 2025 +1030 Commit: Thorsten Behrens <[email protected]> CommitDate: Wed Nov 12 03:41:29 2025 +0100 tdf#168885 oox: save more of empty charts Otherwise Word will complain. Affected types: area, bar, bubble, line, stock. Regression from 3b4c11350a631e27345e87ecfe258d12983cbfbc. Change-Id: I56d533d9c55bae45240a1b51733ff60f47b1b2e7 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192483 Reviewed-by: Aron Budea <[email protected]> Tested-by: Jenkins Reviewed-by: Balazs Varga <[email protected]> Signed-off-by: Xisco Fauli <[email protected]> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192782 (cherry picked from commit 30ca1deeebbdb3cf69816fe65401d91e36596717) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/193798 Reviewed-by: Thorsten Behrens <[email protected]> Tested-by: Thorsten Behrens <[email protected]> diff --git a/chart2/qa/extras/chart2export3.cxx b/chart2/qa/extras/chart2export3.cxx index 838da77191b7..92d0f528231a 100644 --- a/chart2/qa/extras/chart2export3.cxx +++ b/chart2/qa/extras/chart2export3.cxx @@ -737,6 +737,28 @@ CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testBarChartSecondaryAxisXLSX) assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx[2]/c:axId"_ostr, "val"_ostr, YValueIdOf2Barchart); } +CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testEmptyCharts) +{ + loadFromFile(u"odt/testEmptyCharts.odt"); + save(u"Office Open XML Text"_ustr); + + // Make sure each chart exists in the respective XML + xmlDocUniquePtr pXmlDoc = parseExport(u"word/charts/chart1.xml"_ustr); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart"); + + pXmlDoc = parseExport(u"word/charts/chart2.xml"_ustr); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:areaChart"); + + pXmlDoc = parseExport(u"word/charts/chart3.xml"_ustr); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:bubbleChart"); + + pXmlDoc = parseExport(u"word/charts/chart4.xml"_ustr); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart"); + + pXmlDoc = parseExport(u"word/charts/chart5.xml"_ustr); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:stockChart"); +} + CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testTdf148142) { // The document contains a line chart with "Between tick marks" X axis position. diff --git a/chart2/qa/extras/data/odt/testEmptyCharts.odt b/chart2/qa/extras/data/odt/testEmptyCharts.odt new file mode 100644 index 000000000000..54bf12e85763 Binary files /dev/null and b/chart2/qa/extras/data/odt/testEmptyCharts.odt differ diff --git a/oox/source/export/chartexport.cxx b/oox/source/export/chartexport.cxx index c80e8c1ba688..b25b9fd764f4 100644 --- a/oox/source/export/chartexport.cxx +++ b/oox/source/export/chartexport.cxx @@ -2091,12 +2091,14 @@ void ChartExport::exportDataTable( ) void ChartExport::exportAreaChart( const Reference< chart2::XChartType >& xChartType ) { FSHelperPtr pFS = GetFS(); - const std::vector<Sequence<Reference<chart2::XDataSeries> > > aSplitDataSeries = splitDataSeriesByAxis(xChartType); + std::vector<Sequence<Reference<chart2::XDataSeries> > > aSplitDataSeries = splitDataSeriesByAxis(xChartType); + if (aSplitDataSeries.empty()) + { + // Use a dummy data series to output needed basic chart-related XML even in case of empty charts + aSplitDataSeries.push_back({}); + } for (const auto& splitDataSeries : aSplitDataSeries) { - if (!splitDataSeries.hasElements()) - continue; - sal_Int32 nTypeId = XML_areaChart; if (mbIs3DChart) nTypeId = XML_area3DChart; @@ -2104,7 +2106,8 @@ void ChartExport::exportAreaChart( const Reference< chart2::XChartType >& xChart exportGrouping(); bool bPrimaryAxes = true; - exportSeries(xChartType, splitDataSeries, bPrimaryAxes); + if (splitDataSeries.hasElements()) + exportSeries(xChartType, splitDataSeries, bPrimaryAxes); exportAxesId(bPrimaryAxes); pFS->endElement(FSNS(XML_c, nTypeId)); @@ -2118,12 +2121,14 @@ void ChartExport::exportBarChart(const Reference< chart2::XChartType >& xChartTy nTypeId = XML_bar3DChart; FSHelperPtr pFS = GetFS(); - const std::vector<Sequence<Reference<chart2::XDataSeries> > > aSplitDataSeries = splitDataSeriesByAxis(xChartType); + std::vector<Sequence<Reference<chart2::XDataSeries> > > aSplitDataSeries = splitDataSeriesByAxis(xChartType); + if (aSplitDataSeries.empty()) + { + // Use a dummy data series to output needed basic chart-related XML even in case of empty charts + aSplitDataSeries.push_back({}); + } for (const auto& splitDataSeries : aSplitDataSeries) { - if (!splitDataSeries.hasElements()) - continue; - pFS->startElement(FSNS(XML_c, nTypeId)); // bar direction bool bVertical = false; @@ -2139,6 +2144,7 @@ void ChartExport::exportBarChart(const Reference< chart2::XChartType >& xChartTy exportVaryColors(xChartType); bool bPrimaryAxes = true; + if (splitDataSeries.hasElements()) exportSeries(xChartType, splitDataSeries, bPrimaryAxes); Reference< XPropertySet > xTypeProp(xChartType, uno::UNO_QUERY); @@ -2214,18 +2220,21 @@ void ChartExport::exportBarChart(const Reference< chart2::XChartType >& xChartTy void ChartExport::exportBubbleChart( const Reference< chart2::XChartType >& xChartType ) { FSHelperPtr pFS = GetFS(); - const std::vector<Sequence<Reference<chart2::XDataSeries> > > aSplitDataSeries = splitDataSeriesByAxis(xChartType); + std::vector<Sequence<Reference<chart2::XDataSeries> > > aSplitDataSeries = splitDataSeriesByAxis(xChartType); + if (aSplitDataSeries.empty()) + { + // Use a dummy data series to output needed basic chart-related XML even in case of empty charts + aSplitDataSeries.push_back({}); + } for (const auto& splitDataSeries : aSplitDataSeries) { - if (!splitDataSeries.hasElements()) - continue; - pFS->startElement(FSNS(XML_c, XML_bubbleChart)); exportVaryColors(xChartType); bool bPrimaryAxes = true; - exportSeries(xChartType, splitDataSeries, bPrimaryAxes); + if (splitDataSeries.hasElements()) + exportSeries(xChartType, splitDataSeries, bPrimaryAxes); exportAxesId(bPrimaryAxes); @@ -2290,12 +2299,14 @@ void writeDataLabelsRange(const FSHelperPtr& pFS, const XmlFilterBase* pFB, Data void ChartExport::exportLineChart( const Reference< chart2::XChartType >& xChartType ) { FSHelperPtr pFS = GetFS(); - const std::vector<Sequence<Reference<chart2::XDataSeries> > > aSplitDataSeries = splitDataSeriesByAxis(xChartType); + std::vector<Sequence<Reference<chart2::XDataSeries> > > aSplitDataSeries = splitDataSeriesByAxis(xChartType); + if (aSplitDataSeries.empty()) + { + // Use a dummy data series to output needed basic chart-related XML even in case of empty charts + aSplitDataSeries.push_back({}); + } for (const auto& splitDataSeries : aSplitDataSeries) { - if (!splitDataSeries.hasElements()) - continue; - sal_Int32 nTypeId = XML_lineChart; if( mbIs3DChart ) nTypeId = XML_line3DChart; @@ -2306,7 +2317,8 @@ void ChartExport::exportLineChart( const Reference< chart2::XChartType >& xChart exportVaryColors(xChartType); // TODO: show marker symbol in series? bool bPrimaryAxes = true; - exportSeries(xChartType, splitDataSeries, bPrimaryAxes); + if (splitDataSeries.hasElements()) + exportSeries(xChartType, splitDataSeries, bPrimaryAxes); // show marker? sal_Int32 nSymbolType = css::chart::ChartSymbolType::NONE; @@ -2427,16 +2439,19 @@ void ChartExport::exportScatterChart( const Reference< chart2::XChartType >& xCh void ChartExport::exportStockChart( const Reference< chart2::XChartType >& xChartType ) { FSHelperPtr pFS = GetFS(); - const std::vector<Sequence<Reference<chart2::XDataSeries> > > aSplitDataSeries = splitDataSeriesByAxis(xChartType); + std::vector<Sequence<Reference<chart2::XDataSeries> > > aSplitDataSeries = splitDataSeriesByAxis(xChartType); + if (aSplitDataSeries.empty()) + { + // Use a dummy data series to output needed basic chart-related XML even in case of empty charts + aSplitDataSeries.push_back({}); + } for (const auto& splitDataSeries : aSplitDataSeries) { - if (!splitDataSeries.hasElements()) - continue; - pFS->startElement(FSNS(XML_c, XML_stockChart)); bool bPrimaryAxes = true; - exportCandleStickSeries(splitDataSeries, bPrimaryAxes); + if (splitDataSeries.hasElements()) + exportCandleStickSeries(splitDataSeries, bPrimaryAxes); // export stock properties Reference< css::chart::XStatisticDisplay > xStockPropProvider(mxDiagram, uno::UNO_QUERY);
