chart2/qa/extras/chart2export3.cxx | 22 ++++++++ chart2/qa/extras/data/odt/testEmptyCharts.odt |binary oox/source/export/chartexport.cxx | 66 ++++++++++++++++---------- 3 files changed, 63 insertions(+), 25 deletions(-)
New commits: commit f059851ccef11d835bd09678414ebcf56c73f7d6 Author: Aron Budea <[email protected]> AuthorDate: Thu Oct 16 20:17:44 2025 +1030 Commit: Andras Timar <[email protected]> CommitDate: Fri Oct 17 16:50:32 2025 +0200 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]> (cherry picked from commit bc1f96229eaf67321c384593a4e59e33b8e80a8f) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192576 Reviewed-by: Andras Timar <[email protected]> Tested-by: Jenkins CollaboraOffice <[email protected]> diff --git a/chart2/qa/extras/chart2export3.cxx b/chart2/qa/extras/chart2export3.cxx index 1b17d0ba1e6c..ebd1d914c93a 100644 --- a/chart2/qa/extras/chart2export3.cxx +++ b/chart2/qa/extras/chart2export3.cxx @@ -686,6 +686,28 @@ CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testBarChartSecondaryAxisXLSX) assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx[2]/c:axId", "val", 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 ee6150d47f2a..11aa39786daf 100644 --- a/oox/source/export/chartexport.cxx +++ b/oox/source/export/chartexport.cxx @@ -2843,12 +2843,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; @@ -2856,7 +2858,9 @@ void ChartExport::exportAreaChart( const Reference< chart2::XChartType >& xChart exportGrouping(); bool bPrimaryAxes = true; - exportSeries_chart(xChartType, splitDataSeries, bPrimaryAxes); + if (splitDataSeries.hasElements()) + exportSeries_chart(xChartType, splitDataSeries, bPrimaryAxes); + createAxes(bPrimaryAxes, false); //exportAxesId(bPrimaryAxes); @@ -2871,12 +2875,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; @@ -2892,7 +2898,8 @@ void ChartExport::exportBarChart(const Reference< chart2::XChartType >& xChartTy exportVaryColors(xChartType); bool bPrimaryAxes = true; - exportSeries_chart(xChartType, splitDataSeries, bPrimaryAxes); + if (splitDataSeries.hasElements()) + exportSeries_chart(xChartType, splitDataSeries, bPrimaryAxes); Reference< XPropertySet > xTypeProp(xChartType, uno::UNO_QUERY); @@ -2967,18 +2974,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_chart(xChartType, splitDataSeries, bPrimaryAxes); + if (splitDataSeries.hasElements()) + exportSeries_chart(xChartType, splitDataSeries, bPrimaryAxes); createAxes(bPrimaryAxes, false); @@ -3079,12 +3089,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; @@ -3095,7 +3107,8 @@ void ChartExport::exportLineChart( const Reference< chart2::XChartType >& xChart exportVaryColors(xChartType); // TODO: show marker symbol in series? bool bPrimaryAxes = true; - exportSeries_chart(xChartType, splitDataSeries, bPrimaryAxes); + if (splitDataSeries.hasElements()) + exportSeries_chart(xChartType, splitDataSeries, bPrimaryAxes); // show marker? sal_Int32 nSymbolType = css::chart::ChartSymbolType::NONE; @@ -3211,16 +3224,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);
