summaryrefslogtreecommitdiff
path: root/oox
diff options
context:
space:
mode:
authorBalazs Varga <balazs.varga991@gmail.com>2021-06-08 09:24:48 +0200
committerBalazs Varga <varga.balazs3@nisz.hu>2021-06-10 14:01:52 +0200
commit3b4c11350a631e27345e87ecfe258d12983cbfbc (patch)
tree44d0e58e5dfe1ae5ca76d10fa27382f861288491 /oox
parent8d2d627a13de56bb95802d8ca1086933314fee46 (diff)
tdf#142713 OOXML: export secondary axis of all chart types
where the secondary axis is supported by the chart model and OOXML. Change-Id: Ifbcc905139487965510063aa87991ce6f8df73ee Reviewed-on: https://gerrit.libreoffice.org/c/core/+/116809 Tested-by: Jenkins Reviewed-by: Balazs Varga <varga.balazs3@nisz.hu>
Diffstat (limited to 'oox')
-rw-r--r--oox/source/export/chartexport.cxx336
1 files changed, 185 insertions, 151 deletions
diff --git a/oox/source/export/chartexport.cxx b/oox/source/export/chartexport.cxx
index 4a9a1d027bc5..63f29a245ddc 100644
--- a/oox/source/export/chartexport.cxx
+++ b/oox/source/export/chartexport.cxx
@@ -1511,7 +1511,64 @@ void ChartExport::exportTitle( const Reference< XShape >& xShape, const OUString
pFS->endElement( FSNS( XML_c, XML_title ) );
}
-void ChartExport::exportPlotArea( const Reference< css::chart::XChartDocument >& xChartDoc )
+namespace {
+
+ std::vector<Sequence<Reference<chart2::XDataSeries> > > splitDataSeriesByAxis(const Reference< chart2::XChartType >& xChartType)
+ {
+ std::vector<Sequence<Reference<chart2::XDataSeries> > > aSplitSeries;
+ std::map<sal_Int32, size_t> aMapAxisToIndex;
+
+ Reference< chart2::XDataSeriesContainer > xDSCnt(xChartType, uno::UNO_QUERY);
+ if (xDSCnt.is())
+ {
+ sal_Int32 nAxisIndexOfFirstSeries = -1;
+ const Sequence< Reference< chart2::XDataSeries > > aSeriesSeq(xDSCnt->getDataSeries());
+ for (const uno::Reference<chart2::XDataSeries>& xSeries : aSeriesSeq)
+ {
+ Reference<beans::XPropertySet> xPropSet(xSeries, uno::UNO_QUERY);
+ if (!xPropSet.is())
+ continue;
+
+ sal_Int32 nAxisIndex = -1;
+ uno::Any aAny = xPropSet->getPropertyValue("AttachedAxisIndex");
+ aAny >>= nAxisIndex;
+ size_t nVectorPos = 0;
+ if (nAxisIndexOfFirstSeries == -1)
+ {
+ nAxisIndexOfFirstSeries = nAxisIndex;
+ }
+
+ auto it = aMapAxisToIndex.find(nAxisIndex);
+ if (it == aMapAxisToIndex.end())
+ {
+ aSplitSeries.emplace_back();
+ nVectorPos = aSplitSeries.size() - 1;
+ aMapAxisToIndex.insert(std::pair<sal_Int32, size_t>(nAxisIndex, nVectorPos));
+ }
+ else
+ {
+ nVectorPos = it->second;
+ }
+
+ uno::Sequence<Reference<chart2::XDataSeries> >& rAxisSeriesSeq = aSplitSeries[nVectorPos];
+ sal_Int32 nLength = rAxisSeriesSeq.getLength();
+ rAxisSeriesSeq.realloc(nLength + 1);
+ rAxisSeriesSeq[nLength] = xSeries;
+ }
+ // if the first series attached to secondary axis, then export those series first, which are attached to primary axis
+ // also the MS Office export every time in this order
+ if (aSplitSeries.size() > 1 && nAxisIndexOfFirstSeries == 1)
+ {
+ std::swap(aSplitSeries[0], aSplitSeries[1]);
+ }
+ }
+
+ return aSplitSeries;
+ }
+
+}
+
+void ChartExport::exportPlotArea(const Reference< css::chart::XChartDocument >& xChartDoc)
{
Reference< chart2::XCoordinateSystemContainer > xBCooSysCnt( mxNewDiagram, uno::UNO_QUERY );
if( ! xBCooSysCnt.is())
@@ -1542,7 +1599,14 @@ void ChartExport::exportPlotArea( const Reference< css::chart::XChartDocument >&
// tdf#123647 Save empty chart as empty bar chart.
if (!aCooSysSeq.hasElements())
- exportBarChart(nullptr);
+ {
+ pFS->startElement(FSNS(XML_c, XML_barChart));
+ 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");
+ exportAxesId(true);
+ pFS->endElement(FSNS(XML_c, XML_barChart));
+ }
for( const auto& rCS : aCooSysSeq )
{
@@ -1959,65 +2023,79 @@ void ChartExport::exportDataTable( )
void ChartExport::exportAreaChart( const Reference< chart2::XChartType >& xChartType )
{
FSHelperPtr pFS = GetFS();
- sal_Int32 nTypeId = XML_areaChart;
- if( mbIs3DChart )
- nTypeId = XML_area3DChart;
- pFS->startElement(FSNS(XML_c, nTypeId));
+ const std::vector<Sequence<Reference<chart2::XDataSeries> > > aSplitDataSeries = splitDataSeriesByAxis(xChartType);
+ for (const auto& splitDataSeries : aSplitDataSeries)
+ {
+ if (!splitDataSeries.hasElements())
+ continue;
- exportGrouping( );
- bool bPrimaryAxes = true;
- exportAllSeries(xChartType, bPrimaryAxes);
- exportAxesId(bPrimaryAxes);
+ sal_Int32 nTypeId = XML_areaChart;
+ if (mbIs3DChart)
+ nTypeId = XML_area3DChart;
+ pFS->startElement(FSNS(XML_c, nTypeId));
- pFS->endElement( FSNS( XML_c, nTypeId ) );
+ exportGrouping();
+ bool bPrimaryAxes = true;
+ exportSeries(xChartType, splitDataSeries, bPrimaryAxes);
+ exportAxesId(bPrimaryAxes);
+
+ pFS->endElement(FSNS(XML_c, nTypeId));
+ }
}
-void ChartExport::exportBarChart( const Reference< chart2::XChartType >& xChartType )
+void ChartExport::exportBarChart(const Reference< chart2::XChartType >& xChartType)
{
sal_Int32 nTypeId = XML_barChart;
- if( mbIs3DChart )
+ if (mbIs3DChart)
nTypeId = XML_bar3DChart;
FSHelperPtr pFS = GetFS();
- pFS->startElement(FSNS(XML_c, nTypeId));
- // bar direction
- bool bVertical = false;
- Reference< XPropertySet > xPropSet( mxDiagram , uno::UNO_QUERY);
- if( GetProperty( xPropSet, "Vertical" ) )
- mAny >>= bVertical;
- const char* bardir = bVertical? "bar":"col";
- pFS->singleElement(FSNS(XML_c, XML_barDir), XML_val, bardir);
+ const std::vector<Sequence<Reference<chart2::XDataSeries> > > aSplitDataSeries = splitDataSeriesByAxis(xChartType);
+ for (const auto& splitDataSeries : aSplitDataSeries)
+ {
+ if (!splitDataSeries.hasElements())
+ continue;
- exportGrouping( true );
+ pFS->startElement(FSNS(XML_c, nTypeId));
+ // bar direction
+ bool bVertical = false;
+ Reference< XPropertySet > xPropSet(mxDiagram, uno::UNO_QUERY);
+ if (GetProperty(xPropSet, "Vertical"))
+ mAny >>= bVertical;
- exportVaryColors(xChartType);
+ const char* bardir = bVertical ? "bar" : "col";
+ pFS->singleElement(FSNS(XML_c, XML_barDir), XML_val, bardir);
- bool bPrimaryAxes = true;
- exportAllSeries(xChartType, bPrimaryAxes);
+ exportGrouping(true);
- Reference< XPropertySet > xTypeProp( xChartType, uno::UNO_QUERY );
+ exportVaryColors(xChartType);
- if( xTypeProp.is() && GetProperty( xTypeProp, "GapwidthSequence") )
- {
- uno::Sequence< sal_Int32 > aBarPositionSequence;
- mAny >>= aBarPositionSequence;
- if( aBarPositionSequence.hasElements() )
+ bool bPrimaryAxes = true;
+ exportSeries(xChartType, splitDataSeries, bPrimaryAxes);
+
+ Reference< XPropertySet > xTypeProp(xChartType, uno::UNO_QUERY);
+
+ if (xTypeProp.is() && GetProperty(xTypeProp, "GapwidthSequence"))
{
- sal_Int32 nGapWidth = aBarPositionSequence[0];
- pFS->singleElement(FSNS(XML_c, XML_gapWidth), XML_val, OString::number(nGapWidth));
+ uno::Sequence< sal_Int32 > aBarPositionSequence;
+ mAny >>= aBarPositionSequence;
+ if (aBarPositionSequence.hasElements())
+ {
+ sal_Int32 nGapWidth = aBarPositionSequence[0];
+ pFS->singleElement(FSNS(XML_c, XML_gapWidth), XML_val, OString::number(nGapWidth));
+ }
}
- }
- if( mbIs3DChart )
- {
- // Shape
- namespace cssc = css::chart;
- sal_Int32 nGeom3d = cssc::ChartSolidType::RECTANGULAR_SOLID;
- if( xPropSet.is() && GetProperty( xPropSet, "SolidType") )
- mAny >>= nGeom3d;
- const char* sShapeType = nullptr;
- switch( nGeom3d )
+ if (mbIs3DChart)
{
+ // Shape
+ namespace cssc = css::chart;
+ sal_Int32 nGeom3d = cssc::ChartSolidType::RECTANGULAR_SOLID;
+ if (xPropSet.is() && GetProperty(xPropSet, "SolidType"))
+ mAny >>= nGeom3d;
+ const char* sShapeType = nullptr;
+ switch (nGeom3d)
+ {
case cssc::ChartSolidType::RECTANGULAR_SOLID:
sShapeType = "box";
break;
@@ -2030,53 +2108,61 @@ void ChartExport::exportBarChart( const Reference< chart2::XChartType >& xChartT
case cssc::ChartSolidType::PYRAMID:
sShapeType = "pyramid";
break;
+ }
+ pFS->singleElement(FSNS(XML_c, XML_shape), XML_val, sShapeType);
}
- pFS->singleElement(FSNS(XML_c, XML_shape), XML_val, sShapeType);
- }
- //overlap
- if( !mbIs3DChart && xTypeProp.is() && GetProperty( xTypeProp, "OverlapSequence") )
- {
- uno::Sequence< sal_Int32 > aBarPositionSequence;
- mAny >>= aBarPositionSequence;
- if( aBarPositionSequence.hasElements() )
+ //overlap
+ if (!mbIs3DChart && xTypeProp.is() && GetProperty(xTypeProp, "OverlapSequence"))
{
- sal_Int32 nOverlap = aBarPositionSequence[0];
- // Stacked/Percent Bar/Column chart Overlap-workaround
- // Export the Overlap value with 100% for stacked charts,
- // because the default overlap value of the Bar/Column chart is 0% and
- // LibreOffice do nothing with the overlap value in Stacked charts case,
- // unlike the MS Office, which is interpreted differently.
- if( ( mbStacked || mbPercent ) && nOverlap != 100 )
- {
- nOverlap = 100;
- pFS->singleElement(FSNS(XML_c, XML_overlap), XML_val, OString::number(nOverlap));
- }
- else // Normal bar chart
+ uno::Sequence< sal_Int32 > aBarPositionSequence;
+ mAny >>= aBarPositionSequence;
+ if (aBarPositionSequence.hasElements())
{
- pFS->singleElement(FSNS(XML_c, XML_overlap), XML_val, OString::number(nOverlap));
+ sal_Int32 nOverlap = aBarPositionSequence[0];
+ // Stacked/Percent Bar/Column chart Overlap-workaround
+ // Export the Overlap value with 100% for stacked charts,
+ // because the default overlap value of the Bar/Column chart is 0% and
+ // LibreOffice do nothing with the overlap value in Stacked charts case,
+ // unlike the MS Office, which is interpreted differently.
+ if ((mbStacked || mbPercent) && nOverlap != 100)
+ {
+ nOverlap = 100;
+ pFS->singleElement(FSNS(XML_c, XML_overlap), XML_val, OString::number(nOverlap));
+ }
+ else // Normal bar chart
+ {
+ pFS->singleElement(FSNS(XML_c, XML_overlap), XML_val, OString::number(nOverlap));
+ }
}
}
- }
- exportAxesId(bPrimaryAxes);
+ exportAxesId(bPrimaryAxes);
- pFS->endElement( FSNS( XML_c, nTypeId ) );
+ pFS->endElement(FSNS(XML_c, nTypeId));
+ }
}
void ChartExport::exportBubbleChart( const Reference< chart2::XChartType >& xChartType )
{
FSHelperPtr pFS = GetFS();
- pFS->startElement(FSNS(XML_c, XML_bubbleChart));
+ const std::vector<Sequence<Reference<chart2::XDataSeries> > > aSplitDataSeries = splitDataSeriesByAxis(xChartType);
+ for (const auto& splitDataSeries : aSplitDataSeries)
+ {
+ if (!splitDataSeries.hasElements())
+ continue;
- exportVaryColors(xChartType);
+ pFS->startElement(FSNS(XML_c, XML_bubbleChart));
- bool bPrimaryAxes = true;
- exportAllSeries(xChartType, bPrimaryAxes);
+ exportVaryColors(xChartType);
- exportAxesId(bPrimaryAxes);
+ bool bPrimaryAxes = true;
+ exportSeries(xChartType, splitDataSeries, bPrimaryAxes);
- pFS->endElement( FSNS( XML_c, XML_bubbleChart ) );
+ exportAxesId(bPrimaryAxes);
+
+ pFS->endElement(FSNS(XML_c, XML_bubbleChart));
+ }
}
void ChartExport::exportDoughnutChart( const Reference< chart2::XChartType >& xChartType )
@@ -2096,68 +2182,11 @@ void ChartExport::exportDoughnutChart( const Reference< chart2::XChartType >& xC
pFS->endElement( FSNS( XML_c, XML_doughnutChart ) );
}
-namespace {
-
-std::vector<Sequence<Reference<chart2::XDataSeries> > > splitDataSeriesByAxis(const Reference< chart2::XChartType >& xChartType)
-{
- std::vector<Sequence<Reference<chart2::XDataSeries> > > aSplitSeries;
- std::map<sal_Int32, size_t> aMapAxisToIndex;
-
- Reference< chart2::XDataSeriesContainer > xDSCnt( xChartType, uno::UNO_QUERY );
- if(xDSCnt.is())
- {
- sal_Int32 nAxisIndexOfFirstSeries = -1;
- const Sequence< Reference< chart2::XDataSeries > > aSeriesSeq( xDSCnt->getDataSeries());
- for (const uno::Reference<chart2::XDataSeries>& xSeries : aSeriesSeq)
- {
- Reference<beans::XPropertySet> xPropSet(xSeries, uno::UNO_QUERY);
- if (!xPropSet.is())
- continue;
-
- sal_Int32 nAxisIndex = -1;
- uno::Any aAny = xPropSet->getPropertyValue("AttachedAxisIndex");
- aAny >>= nAxisIndex;
- size_t nVectorPos = 0;
- if (nAxisIndexOfFirstSeries == -1)
- {
- nAxisIndexOfFirstSeries = nAxisIndex;
- }
-
- auto it = aMapAxisToIndex.find(nAxisIndex);
- if (it == aMapAxisToIndex.end())
- {
- aSplitSeries.emplace_back();
- nVectorPos = aSplitSeries.size() - 1;
- aMapAxisToIndex.insert(std::pair<sal_Int32, size_t>(nAxisIndex, nVectorPos));
- }
- else
- {
- nVectorPos = it->second;
- }
-
- uno::Sequence<Reference<chart2::XDataSeries> >& rAxisSeriesSeq = aSplitSeries[nVectorPos];
- sal_Int32 nLength = rAxisSeriesSeq.getLength();
- rAxisSeriesSeq.realloc(nLength + 1);
- rAxisSeriesSeq[nLength] = xSeries;
- }
- // if the first series attached to secondary axis, then export those series first, which are attached to primary axis
- // also the MS Office export every time in this order
- if ( aSplitSeries.size() > 1 && nAxisIndexOfFirstSeries == 1 )
- {
- std::swap( aSplitSeries[0], aSplitSeries[1] );
- }
- }
-
- return aSplitSeries;
-}
-
-}
-
void ChartExport::exportLineChart( const Reference< chart2::XChartType >& xChartType )
{
FSHelperPtr pFS = GetFS();
- std::vector<Sequence<Reference<chart2::XDataSeries> > > aSplitDataSeries = splitDataSeriesByAxis(xChartType);
- for (auto & splitDataSeries : aSplitDataSeries)
+ const std::vector<Sequence<Reference<chart2::XDataSeries> > > aSplitDataSeries = splitDataSeriesByAxis(xChartType);
+ for (const auto& splitDataSeries : aSplitDataSeries)
{
if (!splitDataSeries.hasElements())
continue;
@@ -2245,7 +2274,7 @@ void ChartExport::exportRadarChart( const Reference< chart2::XChartType >& xChar
}
void ChartExport::exportScatterChartSeries( const Reference< chart2::XChartType >& xChartType,
- css::uno::Sequence<css::uno::Reference<chart2::XDataSeries>>* pSeries)
+ const css::uno::Sequence<css::uno::Reference<chart2::XDataSeries>>* pSeries)
{
FSHelperPtr pFS = GetFS();
pFS->startElement(FSNS(XML_c, XML_scatterChart));
@@ -2276,9 +2305,9 @@ void ChartExport::exportScatterChartSeries( const Reference< chart2::XChartType
void ChartExport::exportScatterChart( const Reference< chart2::XChartType >& xChartType )
{
- std::vector<Sequence<Reference<chart2::XDataSeries> > > aSplitDataSeries = splitDataSeriesByAxis(xChartType);
+ const std::vector<Sequence<Reference<chart2::XDataSeries> > > aSplitDataSeries = splitDataSeriesByAxis(xChartType);
bool bExported = false;
- for (auto & splitDataSeries : aSplitDataSeries)
+ for (const auto& splitDataSeries : aSplitDataSeries)
{
if (!splitDataSeries.hasElements())
continue;
@@ -2293,24 +2322,29 @@ void ChartExport::exportScatterChart( const Reference< chart2::XChartType >& xCh
void ChartExport::exportStockChart( const Reference< chart2::XChartType >& xChartType )
{
FSHelperPtr pFS = GetFS();
- pFS->startElement(FSNS(XML_c, XML_stockChart));
+ const std::vector<Sequence<Reference<chart2::XDataSeries> > > aSplitDataSeries = splitDataSeriesByAxis(xChartType);
+ for (const auto& splitDataSeries : aSplitDataSeries)
+ {
+ if (!splitDataSeries.hasElements())
+ continue;
- bool bPrimaryAxes = true;
- Reference< chart2::XDataSeriesContainer > xDSCnt( xChartType, uno::UNO_QUERY );
- if(xDSCnt.is())
- exportCandleStickSeries( xDSCnt->getDataSeries(), bPrimaryAxes );
+ pFS->startElement(FSNS(XML_c, XML_stockChart));
- // export stock properties
- Reference< css::chart::XStatisticDisplay > xStockPropProvider( mxDiagram, uno::UNO_QUERY );
- if( xStockPropProvider.is())
- {
- exportHiLowLines();
- exportUpDownBars(xChartType);
- }
+ bool bPrimaryAxes = true;
+ exportCandleStickSeries(splitDataSeries, bPrimaryAxes);
- exportAxesId(bPrimaryAxes);
+ // export stock properties
+ Reference< css::chart::XStatisticDisplay > xStockPropProvider(mxDiagram, uno::UNO_QUERY);
+ if (xStockPropProvider.is())
+ {
+ exportHiLowLines();
+ exportUpDownBars(xChartType);
+ }
- pFS->endElement( FSNS( XML_c, XML_stockChart ) );
+ exportAxesId(bPrimaryAxes);
+
+ pFS->endElement(FSNS(XML_c, XML_stockChart));
+ }
}
void ChartExport::exportHiLowLines()
@@ -2417,13 +2451,13 @@ void ChartExport::exportVaryColors(const Reference<chart2::XChartType>& xChartTy
}
void ChartExport::exportSeries( const Reference<chart2::XChartType>& xChartType,
- Sequence<Reference<chart2::XDataSeries> >& rSeriesSeq, bool& rPrimaryAxes )
+ const Sequence<Reference<chart2::XDataSeries> >& rSeriesSeq, bool& rPrimaryAxes )
{
OUString aLabelRole = xChartType->getRoleOfSequenceForSeriesLabel();
OUString aChartType( xChartType->getChartType());
sal_Int32 eChartType = lcl_getChartType( aChartType );
- for( const auto& rSeries : std::as_const(rSeriesSeq) )
+ for( const auto& rSeries : rSeriesSeq )
{
// export series
Reference< chart2::data::XDataSource > xSource( rSeries, uno::UNO_QUERY );