diff options
-rw-r--r-- | chart2/qa/extras/chart2export.cxx | 11 | ||||
-rw-r--r-- | chart2/qa/extras/data/xlsx/tdf127777.xlsx | bin | 0 -> 14421 bytes | |||
-rw-r--r-- | include/oox/export/chartexport.hxx | 1 | ||||
-rw-r--r-- | oox/source/drawingml/chart/axisconverter.cxx | 2 | ||||
-rw-r--r-- | oox/source/export/chartexport.cxx | 56 |
5 files changed, 63 insertions, 7 deletions
diff --git a/chart2/qa/extras/chart2export.cxx b/chart2/qa/extras/chart2export.cxx index e1c7a4403afe..2589428831bc 100644 --- a/chart2/qa/extras/chart2export.cxx +++ b/chart2/qa/extras/chart2export.cxx @@ -120,6 +120,7 @@ public: void testSetSeriesToSecondaryAxisXLSX(); void testCombinedChartSecondaryAxisXLSX(); void testCombinedChartSecondaryAxisODS(); + void testCrossBetweenXLSX(); void testAxisTitleRotationXLSX(); void testAxisCrossBetweenXSLX(); void testPieChartDataPointExplosionXLSX(); @@ -223,6 +224,7 @@ public: CPPUNIT_TEST(testSetSeriesToSecondaryAxisXLSX); CPPUNIT_TEST(testCombinedChartSecondaryAxisXLSX); CPPUNIT_TEST(testCombinedChartSecondaryAxisODS); + CPPUNIT_TEST(testCrossBetweenXLSX); CPPUNIT_TEST(testAxisTitleRotationXLSX); CPPUNIT_TEST(testAxisCrossBetweenXSLX); CPPUNIT_TEST(testPieChartDataPointExplosionXLSX); @@ -1901,6 +1903,15 @@ void Chart2ExportTest::testCombinedChartSecondaryAxisODS() assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:catAx[2]/c:crosses", 0); } +void Chart2ExportTest::testCrossBetweenXLSX() +{ + // Original file was created with MS Office + load("/chart2/qa/extras/data/xlsx/", "tdf127777.xlsx"); + xmlDocPtr pXmlDoc = parseExport("xl/charts/chart", "Calc Office Open XML"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx/c:crossBetween", "val", "between"); +} + void Chart2ExportTest::testAxisTitleRotationXLSX() { load("/chart2/qa/extras/data/xlsx/", "axis_title_rotation.xlsx"); diff --git a/chart2/qa/extras/data/xlsx/tdf127777.xlsx b/chart2/qa/extras/data/xlsx/tdf127777.xlsx Binary files differnew file mode 100644 index 000000000000..c04de30fc8e2 --- /dev/null +++ b/chart2/qa/extras/data/xlsx/tdf127777.xlsx diff --git a/include/oox/export/chartexport.hxx b/include/oox/export/chartexport.hxx index e7474d75ac15..304bd620d1af 100644 --- a/include/oox/export/chartexport.hxx +++ b/include/oox/export/chartexport.hxx @@ -106,6 +106,7 @@ private: // members filled by InitRangeSegmentationProperties (retrieved from DataProvider) bool mbHasCategoryLabels; //if the categories are only automatically generated this will be false + bool mbIsCategoryPositionShifted; //if the value axis crosses the category axis between tickmarks this will be true //css::uno::Reference< css::drawing::XShapes > mxAdditionalShapes; css::uno::Reference< css::chart2::data::XDataSequence > mxCategoriesValues; diff --git a/oox/source/drawingml/chart/axisconverter.cxx b/oox/source/drawingml/chart/axisconverter.cxx index 9f2cc0f715dc..0f6973b02ec4 100644 --- a/oox/source/drawingml/chart/axisconverter.cxx +++ b/oox/source/drawingml/chart/axisconverter.cxx @@ -224,6 +224,8 @@ void AxisConverter::convertFromModel( case API_Y_AXIS: OSL_ENSURE( mrModel.mnTypeId == C_TOKEN( valAx ), "AxisConverter::convertFromModel - unexpected axis model type (must: c:valAx)" ); aScaleData.AxisType = isPercent(rTypeGroups) ? cssc2::AxisType::PERCENT : cssc2::AxisType::REALNUMBER; + if( mrModel.mnCrossBetween != -1 ) + aScaleData.ShiftedCategoryPosition = mrModel.mnCrossBetween == XML_between; break; case API_Z_AXIS: OSL_ENSURE( mrModel.mnTypeId == C_TOKEN( serAx ), "AxisConverter::convertFromModel - unexpected axis model type (must: c:serAx)" ); diff --git a/oox/source/export/chartexport.cxx b/oox/source/export/chartexport.cxx index c282b0d9263f..5e23e68cb631 100644 --- a/oox/source/export/chartexport.cxx +++ b/oox/source/export/chartexport.cxx @@ -227,6 +227,48 @@ static bool lcl_hasCategoryLabels( const Reference< chart2::XChartDocument >& xC return xCategories.is(); } +static bool lcl_isCategoryAxisShifted(const Reference< chart2::XChartDocument >& xChartDoc) +{ + Reference< chart2::XDiagram > xDiagram(xChartDoc->getFirstDiagram()); + bool isCategoryPositionShifted = false; + + try + { + Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( + xDiagram, uno::UNO_QUERY_THROW); + const Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( + xCooSysCnt->getCoordinateSystems()); + for( const auto& xCooSys : aCooSysSeq ) + { + OSL_ASSERT(xCooSys.is()); + for( sal_Int32 nN = xCooSys->getDimension(); nN--; ) + { + const sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nN); + for( sal_Int32 nI = 0; nI <= nMaxAxisIndex; ++nI ) + { + Reference< chart2::XAxis > xAxis = xCooSys->getAxisByDimension(nN, nI); + OSL_ASSERT(xAxis.is()); + if( xAxis.is()) + { + chart2::ScaleData aScaleData = xAxis->getScaleData(); + if( aScaleData.AxisType == AXIS_PRIMARY_Y ) + { + isCategoryPositionShifted = aScaleData.ShiftedCategoryPosition; + break; + } + } + } + } + } + } + catch (const uno::Exception &) + { + DBG_UNHANDLED_EXCEPTION("oox"); + } + + return isCategoryPositionShifted; +} + static bool lcl_isSeriesAttachedToFirstAxis( const Reference< chart2::XDataSeries > & xDataSeries ) { @@ -735,6 +777,7 @@ void ChartExport::InitRangeSegmentationProperties( const Reference< chart2::XCha if( xDataProvider.is()) { mbHasCategoryLabels = lcl_hasCategoryLabels( xChartDoc ); + mbIsCategoryPositionShifted = lcl_isCategoryAxisShifted( xChartDoc ); } } catch( const uno::Exception & ) @@ -2902,14 +2945,13 @@ void ChartExport::_exportAxis( pFS->singleElement(FSNS(XML_c, XML_noMultiLvlLbl), XML_val, OString::number(0)); } - // TODO: MSO does not support random axis cross position for - // category axis, so we ideally need an algorithm that decides - // when to map the crossing to the tick mark and when to the - // middle of the category - sal_Int32 nChartType = getChartType(); - if (nAxisType == XML_valAx && (nChartType == chart::TYPEID_LINE || nChartType == chart::TYPEID_SCATTER)) + // crossBetween + if( nAxisType == XML_valAx ) { - pFS->singleElement(FSNS(XML_c, XML_crossBetween), XML_val, "midCat"); + if( mbIsCategoryPositionShifted ) + pFS->singleElement(FSNS(XML_c, XML_crossBetween), XML_val, "between"); + else + pFS->singleElement(FSNS(XML_c, XML_crossBetween), XML_val, "midCat"); } // majorUnit |