chart2/qa/extras/chart2export2.cxx | 11 +++++ chart2/qa/extras/data/xlsx/waterfall2.xlsx |binary include/oox/export/chartexport.hxx | 2 - oox/source/drawingml/chart/plotareacontext.cxx | 7 +++ oox/source/drawingml/chart/titlecontext.cxx | 6 ++- oox/source/export/chartexport.cxx | 47 +++++++++++++------------ 6 files changed, 49 insertions(+), 24 deletions(-)
New commits: commit 996bf7400802ca79f99d590dea2f5aa8762977b7 Author: Kurt Nordback <[email protected]> AuthorDate: Sat Jan 31 06:31:54 2026 -0700 Commit: Tomaž Vajngerl <[email protected]> CommitDate: Mon Mar 2 07:40:43 2026 +0100 tdf#165742 Step 5.5: Fixes to chartex axis import/export Improvements and fixes for chartex axes, plus a rudimentary round-trip test. Change-Id: I1d34aae9a139ea970f3d06315d32aefffd03598a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/198453 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <[email protected]> diff --git a/chart2/qa/extras/chart2export2.cxx b/chart2/qa/extras/chart2export2.cxx index 25a51dd7381e..32766ba9b161 100644 --- a/chart2/qa/extras/chart2export2.cxx +++ b/chart2/qa/extras/chart2export2.cxx @@ -276,6 +276,17 @@ CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testChartexPPTX) "layoutId", u"funnel"); } +CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testChartexAxes) +{ + loadFromFile(u"xlsx/waterfall2.xlsx"); + save(TestFilter::XLSX); + xmlDocUniquePtr pXmlDoc = parseExport(u"xl/charts/chartEx1.xml"_ustr); + CPPUNIT_ASSERT(pXmlDoc); + + // Should be two axes + assertXPath(pXmlDoc, "/cx:chartSpace/cx:chart/cx:plotArea/cx:axis", 2); +} + CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testAxisTitleRotationXLSX) { loadFromFile(u"xlsx/axis_title_rotation.xlsx"); diff --git a/chart2/qa/extras/data/xlsx/waterfall2.xlsx b/chart2/qa/extras/data/xlsx/waterfall2.xlsx new file mode 100644 index 000000000000..573b0b69da48 Binary files /dev/null and b/chart2/qa/extras/data/xlsx/waterfall2.xlsx differ diff --git a/include/oox/export/chartexport.hxx b/include/oox/export/chartexport.hxx index 385fda19f806..6fd71cf87da1 100644 --- a/include/oox/export/chartexport.hxx +++ b/include/oox/export/chartexport.hxx @@ -282,7 +282,7 @@ private: const css::uno::Reference< css::beans::XPropertySet >& xMinorGrid, sal_Int32 nAxisType, const AxisIdPair& rAxisIdPair); - void createAxes(bool bPrimaryAxes, bool bCheckCombinedAxes); + void createAxes(bool bPrimaryAxes, bool bCheckCombinedAxes, bool bIsChartex); void exportView3D(); bool isDeep3dChart(); diff --git a/oox/source/drawingml/chart/plotareacontext.cxx b/oox/source/drawingml/chart/plotareacontext.cxx index c3c3fc6af82f..95b20c8f77d9 100644 --- a/oox/source/drawingml/chart/plotareacontext.cxx +++ b/oox/source/drawingml/chart/plotareacontext.cxx @@ -175,6 +175,13 @@ ContextHandlerRef PlotAreaContext::onCreateContext( sal_Int32 nElement, [[maybe_ if (rAttribs.hasAttribute(XML_id)) { sal_Int32 nId = rAttribs.getInteger(XML_id, -1); // TODO: also handle attribute "hidden" + + // Add the id to the axis id list in the (fictitious) + // type group + std::shared_ptr<TypeGroupModel> aTGM = + mrModel.maTypeGroups.get(mrModel.maTypeGroups.size() - 1); + aTGM->maAxisIds.push_back(nId); + return new CxAxisContext(*this, mrModel.maAxes.create(nElement, false), nId); } else { return nullptr; diff --git a/oox/source/drawingml/chart/titlecontext.cxx b/oox/source/drawingml/chart/titlecontext.cxx index 1470aa1b44e7..d9375536f5df 100644 --- a/oox/source/drawingml/chart/titlecontext.cxx +++ b/oox/source/drawingml/chart/titlecontext.cxx @@ -46,7 +46,9 @@ TextContext::~TextContext() ContextHandlerRef TextContext::onCreateContext( sal_Int32 nElement, const AttributeList& ) { // this context handler is used for <c:tx> and embedded <c:v> elements - if( isCurrentElement( C_TOKEN( tx ) ) || isCurrentElement(CX_TOKEN(tx)) ) switch( nElement ) + if( isCurrentElement( C_TOKEN( tx ) ) || + isCurrentElement(CX_TOKEN(tx)) || + isCurrentElement(CX_TOKEN(txData)) ) switch( nElement ) { case C_TOKEN( rich ): case CX_TOKEN( rich ): @@ -71,7 +73,7 @@ ContextHandlerRef TextContext::onCreateContext( sal_Int32 nElement, const Attrib void TextContext::onCharacters( const OUString& rChars ) { - if( isCurrentElement( C_TOKEN( v ) ) ) + if( isCurrentElement( C_TOKEN( v ) ) || isCurrentElement( CX_TOKEN( v ) )) { // Static text is stored as a single string formula token for Excel document. mrModel.mxDataSeq.create().maFormula = "\"" + rChars + "\""; diff --git a/oox/source/export/chartexport.cxx b/oox/source/export/chartexport.cxx index 7fb109ccdd7a..bf9486950c3d 100644 --- a/oox/source/export/chartexport.cxx +++ b/oox/source/export/chartexport.cxx @@ -2560,7 +2560,7 @@ void ChartExport::exportPlotArea(const Reference< css::chart::XChartDocument >& pFS->singleElement(FSNS(XML_c, XML_barDir), XML_val, "col"); pFS->singleElement(FSNS(XML_c, XML_grouping), XML_val, "clustered"); pFS->singleElement(FSNS(XML_c, XML_varyColors), XML_val, "0"); - createAxes(true, false); + createAxes(true, false, false); pFS->endElement(FSNS(XML_c, XML_barChart)); } @@ -3112,7 +3112,7 @@ void ChartExport::exportAreaChart( const Reference< chart2::XChartType >& xChart if (splitDataSeries.hasElements()) exportSeries_chart(xChartType, splitDataSeries, bPrimaryAxes); - createAxes(bPrimaryAxes, false); + createAxes(bPrimaryAxes, false, false); //exportAxesId(bPrimaryAxes); pFS->endElement(FSNS(XML_c, nTypeId)); @@ -3216,7 +3216,7 @@ void ChartExport::exportBarChart(const Reference< chart2::XChartType >& xChartTy } } - createAxes(bPrimaryAxes, false); + createAxes(bPrimaryAxes, false, false); pFS->endElement(FSNS(XML_c, nTypeId)); } @@ -3241,7 +3241,7 @@ void ChartExport::exportBubbleChart( const Reference< chart2::XChartType >& xCha if (splitDataSeries.hasElements()) exportSeries_chart(xChartType, splitDataSeries, bPrimaryAxes); - createAxes(bPrimaryAxes, false); + createAxes(bPrimaryAxes, false, false); pFS->endElement(FSNS(XML_c, XML_bubbleChart)); } @@ -3259,6 +3259,8 @@ void ChartExport::exportChartex( const Reference< chart2::XChartType >& xChartTy if (!splitDataSeries.hasElements()) continue; + createAxes(true, false, true); + //exportVaryColors(xChartType); exportSeries_chartex(xChartType, splitDataSeries, sTypeName); @@ -3396,7 +3398,7 @@ void ChartExport::exportLineChart( const Reference< chart2::XChartType >& xChart pFS->singleElement(FSNS(XML_c, XML_marker), XML_val, marker); } - createAxes(bPrimaryAxes, true); + createAxes(bPrimaryAxes, true, false); pFS->endElement( FSNS( XML_c, nTypeId ) ); } @@ -3441,7 +3443,7 @@ void ChartExport::exportRadarChart( const Reference< chart2::XChartType >& xChar exportVaryColors(xChartType); bool bPrimaryAxes = true; exportAllSeries(xChartType, bPrimaryAxes); - createAxes(bPrimaryAxes, false); + createAxes(bPrimaryAxes, false, false); pFS->endElement( FSNS( XML_c, XML_radarChart ) ); } @@ -3471,7 +3473,7 @@ void ChartExport::exportScatterChartSeries( const Reference< chart2::XChartType bool bPrimaryAxes = true; if (pSeries) exportSeries_chart(xChartType, *pSeries, bPrimaryAxes); - createAxes(bPrimaryAxes, false); + createAxes(bPrimaryAxes, false, false); //exportAxesId(bPrimaryAxes); pFS->endElement( FSNS( XML_c, XML_scatterChart ) ); @@ -3520,7 +3522,7 @@ void ChartExport::exportStockChart( const Reference< chart2::XChartType >& xChar exportUpDownBars(xChartType); } - createAxes(bPrimaryAxes, false); + createAxes(bPrimaryAxes, false, false); pFS->endElement(FSNS(XML_c, XML_stockChart)); } @@ -3595,7 +3597,7 @@ void ChartExport::exportSurfaceChart( const Reference< chart2::XChartType >& xCh exportVaryColors(xChartType); bool bPrimaryAxes = true; exportAllSeries(xChartType, bPrimaryAxes); - createAxes(bPrimaryAxes, false); + createAxes(bPrimaryAxes, false, false); pFS->endElement( FSNS( XML_c, nTypeId ) ); } @@ -5584,7 +5586,7 @@ void ChartExport::exportDataPoints( } // Generalized axis output -void ChartExport::createAxes(bool bPrimaryAxes, bool bCheckCombinedAxes) +void ChartExport::createAxes(bool bPrimaryAxes, bool bCheckCombinedAxes, bool bIsChartex) { sal_Int32 nAxisIdx, nAxisIdy; bool bPrimaryAxisExists = false; @@ -5610,19 +5612,22 @@ void ChartExport::createAxes(bool bPrimaryAxes, bool bCheckCombinedAxes) maAxes.emplace_back( eXAxis, nAxisIdx, nAxisIdy ); maAxes.emplace_back( eYAxis, nAxisIdy, nAxisIdx ); } - // Export IDs - FSHelperPtr pFS = GetFS(); - pFS->singleElement(FSNS(XML_c, XML_axId), XML_val, OString::number(nAxisIdx)); - pFS->singleElement(FSNS(XML_c, XML_axId), XML_val, OString::number(nAxisIdy)); - if (mbHasZAxis) - { - sal_Int32 nAxisIdz = 0; - if( isDeep3dChart() ) + + if (!bIsChartex) { + // Export IDs + FSHelperPtr pFS = GetFS(); + pFS->singleElement(FSNS(XML_c, XML_axId), XML_val, OString::number(nAxisIdx)); + pFS->singleElement(FSNS(XML_c, XML_axId), XML_val, OString::number(nAxisIdy)); + if (mbHasZAxis) { - nAxisIdz = lcl_generateRandomValue(); - maAxes.emplace_back( AXIS_PRIMARY_Z, nAxisIdz, nAxisIdy ); + sal_Int32 nAxisIdz = 0; + if( isDeep3dChart() ) + { + nAxisIdz = lcl_generateRandomValue(); + maAxes.emplace_back( AXIS_PRIMARY_Z, nAxisIdz, nAxisIdy ); + } + pFS->singleElement(FSNS(XML_c, XML_axId), XML_val, OString::number(nAxisIdz)); } - pFS->singleElement(FSNS(XML_c, XML_axId), XML_val, OString::number(nAxisIdz)); } }
