1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <oox/token/tokens.hxx>
21 #include "oox/core/xmlfilterbase.hxx"
22 #include "oox/export/chartexport.hxx"
23 #include "oox/export/utils.hxx"
24 #include "drawingml/chart/typegroupconverter.hxx"
28 #include <com/sun/star/awt/Gradient.hpp>
29 #include <com/sun/star/chart/XChartDocument.hpp>
30 #include <com/sun/star/chart/ChartLegendPosition.hpp>
31 #include <com/sun/star/chart/XTwoAxisXSupplier.hpp>
32 #include <com/sun/star/chart/XTwoAxisYSupplier.hpp>
33 #include <com/sun/star/chart/XAxisZSupplier.hpp>
34 #include <com/sun/star/chart/XChartDataArray.hpp>
35 #include <com/sun/star/chart/ChartDataRowSource.hpp>
36 #include <com/sun/star/chart/ChartAxisAssign.hpp>
37 #include <com/sun/star/chart/ChartSeriesAddress.hpp>
38 #include <com/sun/star/chart/X3DDisplay.hpp>
39 #include <com/sun/star/chart/XStatisticDisplay.hpp>
40 #include <com/sun/star/chart/XSecondAxisTitleSupplier.hpp>
41 #include <com/sun/star/chart/ChartSymbolType.hpp>
42 #include <com/sun/star/chart/ChartAxisMarks.hpp>
43 #include <com/sun/star/chart/ChartAxisLabelPosition.hpp>
44 #include <com/sun/star/chart/ChartAxisPosition.hpp>
45 #include <com/sun/star/chart/ChartSolidType.hpp>
46 #include <com/sun/star/chart/DataLabelPlacement.hpp>
47 #include <com/sun/star/chart/ErrorBarStyle.hpp>
48 #include <com/sun/star/chart/MissingValueTreatment.hpp>
50 #include <com/sun/star/chart2/XChartDocument.hpp>
51 #include <com/sun/star/chart2/XDiagram.hpp>
52 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
53 #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
54 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
55 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
56 #include <com/sun/star/chart2/DataPointGeometry3D.hpp>
57 #include <com/sun/star/chart2/DataPointLabel.hpp>
58 #include <com/sun/star/chart2/Symbol.hpp>
59 #include <com/sun/star/chart2/data/XDataSource.hpp>
60 #include <com/sun/star/chart2/data/XDataSink.hpp>
61 #include <com/sun/star/chart2/data/XDataReceiver.hpp>
62 #include <com/sun/star/chart2/data/XDataProvider.hpp>
63 #include <com/sun/star/chart2/data/XDatabaseDataProvider.hpp>
64 #include <com/sun/star/chart2/data/XRangeXMLConversion.hpp>
65 #include <com/sun/star/chart2/data/XTextualDataSequence.hpp>
66 #include <com/sun/star/chart2/data/XNumericalDataSequence.hpp>
68 #include <com/sun/star/beans/XPropertySet.hpp>
69 #include <com/sun/star/beans/XPropertyState.hpp>
70 #include <com/sun/star/container/XEnumerationAccess.hpp>
71 #include <com/sun/star/drawing/XShape.hpp>
72 #include <com/sun/star/drawing/FillStyle.hpp>
73 #include <com/sun/star/drawing/BitmapMode.hpp>
74 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
75 #include <com/sun/star/lang/XServiceName.hpp>
77 #include <com/sun/star/table/CellAddress.hpp>
78 #include <com/sun/star/sheet/XFormulaParser.hpp>
79 #include <com/sun/star/sheet/XFormulaTokens.hpp>
80 #include <com/sun/star/sheet/FormulaToken.hpp>
81 #include <com/sun/star/sheet/AddressConvention.hpp>
83 #include <com/sun/star/text/WritingMode.hpp>
84 #include <com/sun/star/container/XNamed.hpp>
85 #include <com/sun/star/embed/XVisualObject.hpp>
86 #include <com/sun/star/embed/Aspects.hpp>
88 #include <comphelper/processfactory.hxx>
89 #include <comphelper/random.hxx>
90 #include <xmloff/SchXMLSeriesHelper.hxx>
91 #include "ColorPropertySet.hxx"
93 #include <unordered_set>
95 #include <rtl/math.hxx>
98 using namespace css::uno
;
99 using namespace css::drawing
;
100 using namespace ::oox::core
;
101 using css::beans::PropertyState
;
102 using css::beans::PropertyValue
;
103 using css::beans::XPropertySet
;
104 using css::beans::XPropertyState
;
105 using css::container::XEnumeration
;
106 using css::container::XEnumerationAccess
;
107 using css::container::XIndexAccess
;
108 using css::container::XNamed
;
109 using css::io::XOutputStream
;
110 using css::table::CellAddress
;
111 using css::sheet::XFormulaParser
;
112 using css::sheet::XFormulaTokens
;
113 using ::oox::core::XmlFilterBase
;
114 using ::sax_fastparser::FSHelperPtr
;
116 namespace cssc
= css::chart
;
118 namespace oox
{ namespace drawingml
{
122 sal_Int32
translateFromChart2AxisIndexToOox(sal_Int32 nIndex
)
124 assert(nIndex
== 0 || nIndex
== 1);
126 return AXIS_SECONDARY_Y
;
127 return AXIS_PRIMARY_Y
;
132 class lcl_MatchesRole
: public ::std::unary_function
< Reference
< chart2::data::XLabeledDataSequence
>, bool >
135 explicit lcl_MatchesRole( const OUString
& aRole
) :
139 bool operator () ( const Reference
< chart2::data::XLabeledDataSequence
> & xSeq
) const
143 Reference
< beans::XPropertySet
> xProp( xSeq
->getValues(), uno::UNO_QUERY
);
146 return ( xProp
.is() &&
147 (xProp
->getPropertyValue(
148 OUString( "Role" ) ) >>= aRole
) &&
149 m_aRole
.equals( aRole
));
156 template< typename T
>
157 void lcl_SequenceToVectorAppend( const Sequence
< T
> & rSource
, ::std::vector
< T
> & rDestination
)
159 rDestination
.reserve( rDestination
.size() + rSource
.getLength());
160 ::std::copy( rSource
.begin(), rSource
.end(),
161 ::std::back_inserter( rDestination
));
164 Reference
< chart2::data::XLabeledDataSequence
> lcl_getCategories( const Reference
< chart2::XDiagram
> & xDiagram
)
166 Reference
< chart2::data::XLabeledDataSequence
> xResult
;
169 Reference
< chart2::XCoordinateSystemContainer
> xCooSysCnt(
170 xDiagram
, uno::UNO_QUERY_THROW
);
171 Sequence
< Reference
< chart2::XCoordinateSystem
> > aCooSysSeq(
172 xCooSysCnt
->getCoordinateSystems());
173 for( sal_Int32 i
=0; i
<aCooSysSeq
.getLength(); ++i
)
175 Reference
< chart2::XCoordinateSystem
> xCooSys( aCooSysSeq
[i
] );
176 OSL_ASSERT( xCooSys
.is());
177 for( sal_Int32 nN
= xCooSys
->getDimension(); nN
--; )
179 const sal_Int32 nMaxAxisIndex
= xCooSys
->getMaximumAxisIndexByDimension(nN
);
180 for(sal_Int32 nI
=0; nI
<=nMaxAxisIndex
; ++nI
)
182 Reference
< chart2::XAxis
> xAxis
= xCooSys
->getAxisByDimension( nN
, nI
);
183 OSL_ASSERT( xAxis
.is());
186 chart2::ScaleData aScaleData
= xAxis
->getScaleData();
187 if( aScaleData
.Categories
.is())
189 xResult
.set( aScaleData
.Categories
);
197 catch( const uno::Exception
& ex
)
199 (void)ex
; // avoid warning for pro build
200 OSL_FAIL( OUStringToOString(
201 "Exception caught. Type: " +
202 OUString::createFromAscii( typeid( ex
).name()) +
204 ex
.Message
, RTL_TEXTENCODING_ASCII_US
).getStr());
210 Reference
< chart2::data::XDataSource
> lcl_createDataSource(
211 const Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > & aData
)
213 Reference
< uno::XComponentContext
> xContext(
214 comphelper::getProcessComponentContext() );
215 Reference
< chart2::data::XDataSink
> xSink(
216 xContext
->getServiceManager()->createInstanceWithContext(
217 "com.sun.star.chart2.data.DataSource", xContext
),
218 uno::UNO_QUERY_THROW
);
220 xSink
->setData( aData
);
222 return Reference
< chart2::data::XDataSource
>( xSink
, uno::UNO_QUERY
);
225 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > lcl_getAllSeriesSequences( const Reference
< chart2::XChartDocument
>& xChartDoc
)
227 ::std::vector
< Reference
< chart2::data::XLabeledDataSequence
> > aContainer
;
230 Reference
< chart2::XDiagram
> xDiagram( xChartDoc
->getFirstDiagram());
231 ::std::vector
< Reference
< chart2::XDataSeries
> > aSeriesVector( SchXMLSeriesHelper::getDataSeriesFromDiagram( xDiagram
));
232 for( ::std::vector
< Reference
< chart2::XDataSeries
> >::const_iterator
aSeriesIt( aSeriesVector
.begin() )
233 ; aSeriesIt
!= aSeriesVector
.end(); ++aSeriesIt
)
235 Reference
< chart2::data::XDataSource
> xDataSource( *aSeriesIt
, uno::UNO_QUERY
);
236 if( !xDataSource
.is() )
238 uno::Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > aDataSequences( xDataSource
->getDataSequences() );
239 lcl_SequenceToVectorAppend( aDataSequences
, aContainer
);
243 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > aRet( aContainer
.size());
244 ::std::copy( aContainer
.begin(), aContainer
.end(), aRet
.getArray());
249 Reference
< chart2::data::XLabeledDataSequence
>
250 lcl_getDataSequenceByRole(
251 const Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > & aLabeledSeq
,
252 const OUString
& rRole
)
254 Reference
< chart2::data::XLabeledDataSequence
> aNoResult
;
256 const Reference
< chart2::data::XLabeledDataSequence
> * pBegin
= aLabeledSeq
.getConstArray();
257 const Reference
< chart2::data::XLabeledDataSequence
> * pEnd
= pBegin
+ aLabeledSeq
.getLength();
258 const Reference
< chart2::data::XLabeledDataSequence
> * pMatch
=
259 ::std::find_if( pBegin
, pEnd
, lcl_MatchesRole( rRole
));
267 Reference
< chart2::data::XDataSource
> lcl_pressUsedDataIntoRectangularFormat( const Reference
< chart2::XChartDocument
>& xChartDoc
, bool& rOutSourceHasCategoryLabels
)
269 ::std::vector
< Reference
< chart2::data::XLabeledDataSequence
> > aLabeledSeqVector
;
271 //categories are always the first sequence
272 Reference
< chart2::XDiagram
> xDiagram( xChartDoc
->getFirstDiagram());
273 Reference
< chart2::data::XLabeledDataSequence
> xCategories( lcl_getCategories( xDiagram
) );
274 if( xCategories
.is() )
275 aLabeledSeqVector
.push_back( xCategories
);
276 rOutSourceHasCategoryLabels
= xCategories
.is();
278 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > aSeriesSeqVector(
279 lcl_getAllSeriesSequences( xChartDoc
) );
281 //the first x-values is always the next sequence //todo ... other x-values get lost for old format
282 Reference
< chart2::data::XLabeledDataSequence
> xXValues(
283 lcl_getDataSequenceByRole( aSeriesSeqVector
, OUString("values-x") ) );
285 aLabeledSeqVector
.push_back( xXValues
);
287 //add all other sequences now without x-values
288 lcl_MatchesRole
aHasXValues( OUString("values-x") );
289 for( sal_Int32 nN
=0; nN
<aSeriesSeqVector
.getLength(); nN
++ )
291 if( !aHasXValues( aSeriesSeqVector
[nN
] ) )
292 aLabeledSeqVector
.push_back( aSeriesSeqVector
[nN
] );
295 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > aSeq( aLabeledSeqVector
.size() );
296 ::std::copy( aLabeledSeqVector
.begin(), aLabeledSeqVector
.end(), aSeq
.getArray() );
298 return lcl_createDataSource( aSeq
);
301 bool lcl_isSeriesAttachedToFirstAxis(
302 const Reference
< chart2::XDataSeries
> & xDataSeries
)
308 sal_Int32 nAxisIndex
= 0;
309 Reference
< beans::XPropertySet
> xProp( xDataSeries
, uno::UNO_QUERY_THROW
);
311 xProp
->getPropertyValue("AttachedAxisIndex") >>= nAxisIndex
;
312 bResult
= (0==nAxisIndex
);
314 catch( const uno::Exception
& ex
)
316 (void)ex
; // avoid warning for pro build
317 OSL_FAIL( OUStringToOString(
318 "Exception caught. Type: " +
319 OUString::createFromAscii( typeid( ex
).name()) +
321 ex
.Message
, RTL_TEXTENCODING_ASCII_US
).getStr());
327 OUString
lcl_flattenStringSequence( const Sequence
< OUString
> & rSequence
)
329 OUStringBuffer aResult
;
330 bool bPrecedeWithSpace
= false;
331 for( sal_Int32 nIndex
=0; nIndex
<rSequence
.getLength(); ++nIndex
)
333 if( !rSequence
[nIndex
].isEmpty())
335 if( bPrecedeWithSpace
)
336 aResult
.append( ' ' );
337 aResult
.append( rSequence
[nIndex
] );
338 bPrecedeWithSpace
= true;
341 return aResult
.makeStringAndClear();
344 OUString
lcl_getLabelString( const Reference
< chart2::data::XDataSequence
> & xLabelSeq
)
346 Sequence
< OUString
> aLabels
;
348 uno::Reference
< chart2::data::XTextualDataSequence
> xTextualDataSequence( xLabelSeq
, uno::UNO_QUERY
);
349 if( xTextualDataSequence
.is())
351 aLabels
= xTextualDataSequence
->getTextualData();
353 else if( xLabelSeq
.is())
355 Sequence
< uno::Any
> aAnies( xLabelSeq
->getData());
356 aLabels
.realloc( aAnies
.getLength());
357 for( sal_Int32 i
=0; i
<aAnies
.getLength(); ++i
)
358 aAnies
[i
] >>= aLabels
[i
];
361 return lcl_flattenStringSequence( aLabels
);
364 void lcl_fillCategoriesIntoStringVector(
365 const Reference
< chart2::data::XDataSequence
> & xCategories
,
366 ::std::vector
< OUString
> & rOutCategories
)
368 OSL_ASSERT( xCategories
.is());
369 if( !xCategories
.is())
371 Reference
< chart2::data::XTextualDataSequence
> xTextualDataSequence( xCategories
, uno::UNO_QUERY
);
372 if( xTextualDataSequence
.is())
374 rOutCategories
.clear();
375 Sequence
< OUString
> aTextData( xTextualDataSequence
->getTextualData());
376 ::std::copy( aTextData
.begin(), aTextData
.end(),
377 ::std::back_inserter( rOutCategories
));
381 Sequence
< uno::Any
> aAnies( xCategories
->getData());
382 rOutCategories
.resize( aAnies
.getLength());
383 for( sal_Int32 i
=0; i
<aAnies
.getLength(); ++i
)
384 aAnies
[i
] >>= rOutCategories
[i
];
388 ::std::vector
< double > lcl_getAllValuesFromSequence( const Reference
< chart2::data::XDataSequence
> & xSeq
)
391 ::rtl::math::setNan( &fNan
);
392 ::std::vector
< double > aResult
;
394 Reference
< chart2::data::XNumericalDataSequence
> xNumSeq( xSeq
, uno::UNO_QUERY
);
397 Sequence
< double > aValues( xNumSeq
->getNumericalData());
398 ::std::copy( aValues
.begin(), aValues
.end(),
399 ::std::back_inserter( aResult
));
403 Sequence
< uno::Any
> aAnies( xSeq
->getData());
404 aResult
.resize( aAnies
.getLength(), fNan
);
405 for( sal_Int32 i
=0; i
<aAnies
.getLength(); ++i
)
406 aAnies
[i
] >>= aResult
[i
];
411 sal_Int32
lcl_getChartType( const OUString
& sChartType
)
413 chart::TypeId eChartTypeId
= chart::TYPEID_UNKNOWN
;
414 if( sChartType
== "com.sun.star.chart.BarDiagram"
415 || sChartType
== "com.sun.star.chart2.ColumnChartType" )
416 eChartTypeId
= chart::TYPEID_BAR
;
417 else if( sChartType
== "com.sun.star.chart.AreaDiagram"
418 || sChartType
== "com.sun.star.chart2.AreaChartType" )
419 eChartTypeId
= chart::TYPEID_AREA
;
420 else if( sChartType
== "com.sun.star.chart.LineDiagram"
421 || sChartType
== "com.sun.star.chart2.LineChartType" )
422 eChartTypeId
= chart::TYPEID_LINE
;
423 else if( sChartType
== "com.sun.star.chart.PieDiagram"
424 || sChartType
== "com.sun.star.chart2.PieChartType" )
425 eChartTypeId
= chart::TYPEID_PIE
;
426 else if( sChartType
== "com.sun.star.chart.DonutDiagram"
427 || sChartType
== "com.sun.star.chart2.DonutChartType" )
428 eChartTypeId
= chart::TYPEID_DOUGHNUT
;
429 else if( sChartType
== "com.sun.star.chart.XYDiagram"
430 || sChartType
== "com.sun.star.chart2.ScatterChartType" )
431 eChartTypeId
= chart::TYPEID_SCATTER
;
432 else if( sChartType
== "com.sun.star.chart.NetDiagram"
433 || sChartType
== "com.sun.star.chart2.NetChartType" )
434 eChartTypeId
= chart::TYPEID_RADARLINE
;
435 else if( sChartType
== "com.sun.star.chart.FilledNetDiagram"
436 || sChartType
== "com.sun.star.chart2.FilledNetChartType" )
437 eChartTypeId
= chart::TYPEID_RADARAREA
;
438 else if( sChartType
== "com.sun.star.chart.StockDiagram"
439 || sChartType
== "com.sun.star.chart2.CandleStickChartType" )
440 eChartTypeId
= chart::TYPEID_STOCK
;
441 else if( sChartType
== "com.sun.star.chart.BubbleDiagram"
442 || sChartType
== "com.sun.star.chart2.BubbleChartType" )
443 eChartTypeId
= chart::TYPEID_BUBBLE
;
448 sal_Int32
lcl_generateRandomValue()
450 return comphelper::rng::uniform_int_distribution(0, 100000000-1);
453 ChartExport::ChartExport( sal_Int32 nXmlNamespace
, FSHelperPtr pFS
, Reference
< frame::XModel
>& xModel
, XmlFilterBase
* pFB
, DocumentType eDocumentType
)
454 : DrawingML( pFS
, pFB
, eDocumentType
)
455 , mnXmlNamespace( nXmlNamespace
)
457 , mxChartModel( xModel
)
458 , mbHasCategoryLabels( false )
459 , mbHasZAxis( false )
460 , mbIs3DChart( false )
466 sal_Int32
ChartExport::GetChartID( )
468 sal_Int32 nID
= GetFB()->GetUniqueId();
472 sal_Int32
ChartExport::getChartType( )
474 OUString sChartType
= mxDiagram
->getDiagramType();
475 return lcl_getChartType( sChartType
);
478 OUString
ChartExport::parseFormula( const OUString
& rRange
)
481 Reference
< XFormulaParser
> xParser
;
482 uno::Reference
< lang::XMultiServiceFactory
> xSF( GetFB()->getModelFactory(), uno::UNO_QUERY
);
487 xParser
.set( xSF
->createInstance("com.sun.star.sheet.FormulaParser"), UNO_QUERY
);
494 SAL_WARN_IF(!xParser
.is(), "oox", "creating formula parser failed");
498 Reference
< XPropertySet
> xParserProps( xParser
, uno::UNO_QUERY
);
499 if( xParserProps
.is() )
501 xParserProps
->setPropertyValue("FormulaConvention", uno::makeAny(css::sheet::AddressConvention::OOO
) );
503 uno::Sequence
<sheet::FormulaToken
> aTokens
= xParser
->parseFormula( rRange
, CellAddress( 0, 0, 0 ) );
504 if( xParserProps
.is() )
506 xParserProps
->setPropertyValue("FormulaConvention", uno::makeAny(css::sheet::AddressConvention::XL_OOX
) );
508 aResult
= xParser
->printFormula( aTokens
, CellAddress( 0, 0, 0 ) );
512 //FIXME: currently just using simple converter, e.g $Sheet1.$A$1:$C$1 -> Sheet1!$A$1:$C$1
513 OUString
aRange( rRange
);
514 if( aRange
.startsWith("$") )
515 aRange
= aRange
.copy(1);
516 aRange
= aRange
.replaceAll(".$", "!$" );
523 ChartExport
& ChartExport::WriteChartObj( const Reference
< XShape
>& xShape
, sal_Int32 nChartCount
)
525 FSHelperPtr pFS
= GetFS();
527 pFS
->startElementNS( mnXmlNamespace
, XML_graphicFrame
, FSEND
);
529 pFS
->startElementNS( mnXmlNamespace
, XML_nvGraphicFramePr
, FSEND
);
531 // TODO: get the correct chart name chart id
532 OUString sName
= "Object 1";
533 Reference
< XNamed
> xNamed( xShape
, UNO_QUERY
);
535 sName
= xNamed
->getName();
537 sal_Int32 nID
= GetChartID();
539 pFS
->singleElementNS( mnXmlNamespace
, XML_cNvPr
,
541 XML_name
, USS( sName
),
544 pFS
->singleElementNS( mnXmlNamespace
, XML_cNvGraphicFramePr
,
547 if( GetDocumentType() == DOCUMENT_PPTX
)
548 pFS
->singleElementNS( mnXmlNamespace
, XML_nvPr
,
550 pFS
->endElementNS( mnXmlNamespace
, XML_nvGraphicFramePr
);
552 // visual chart properties
553 WriteShapeTransformation( xShape
, mnXmlNamespace
);
555 // writer chart object
556 pFS
->startElement( FSNS( XML_a
, XML_graphic
), FSEND
);
557 pFS
->startElement( FSNS( XML_a
, XML_graphicData
),
558 XML_uri
, "http://schemas.openxmlformats.org/drawingml/2006/chart",
561 const char* sFullPath
= NULL
;
562 const char* sRelativePath
= NULL
;
563 switch( GetDocumentType() )
567 sFullPath
= "word/charts/chart";
568 sRelativePath
= "charts/chart";
573 sFullPath
= "ppt/charts/chart";
574 sRelativePath
= "../charts/chart";
579 sFullPath
= "xl/charts/chart";
580 sRelativePath
= "../charts/chart";
585 sFullPath
= "charts/chart";
586 sRelativePath
= "charts/chart";
590 OUString sFullStream
= OUStringBuffer()
591 .appendAscii(sFullPath
)
593 .appendAscii( ".xml" )
594 .makeStringAndClear();
595 OUString sRelativeStream
= OUStringBuffer()
596 .appendAscii(sRelativePath
)
598 .appendAscii( ".xml" )
599 .makeStringAndClear();
600 FSHelperPtr pChart
= CreateOutputStream(
603 pFS
->getOutputStream(),
604 "application/vnd.openxmlformats-officedocument.drawingml.chart+xml",
605 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart",
608 pFS
->singleElement( FSNS( XML_c
, XML_chart
),
609 FSNS( XML_xmlns
, XML_c
), "http://schemas.openxmlformats.org/drawingml/2006/chart",
610 FSNS( XML_xmlns
, XML_r
), "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
611 FSNS( XML_r
, XML_id
), USS( sId
),
614 pFS
->endElement( FSNS( XML_a
, XML_graphicData
) );
615 pFS
->endElement( FSNS( XML_a
, XML_graphic
) );
616 pFS
->endElementNS( mnXmlNamespace
, XML_graphicFrame
);
624 void ChartExport::InitRangeSegmentationProperties( const Reference
< chart2::XChartDocument
> & xChartDoc
)
629 Reference
< chart2::data::XDataProvider
> xDataProvider( xChartDoc
->getDataProvider() );
630 OSL_ENSURE( xDataProvider
.is(), "No DataProvider" );
631 if( xDataProvider
.is())
633 Reference
< chart2::data::XDataSource
> xDataSource( lcl_pressUsedDataIntoRectangularFormat( xChartDoc
, mbHasCategoryLabels
));
634 Sequence
< beans::PropertyValue
> aArgs( xDataProvider
->detectArguments( xDataSource
));
635 OUString sCellRange
, sBrokenRange
;
636 bool bBrokenRangeAvailable
= false;
637 for( sal_Int32 i
=0; i
<aArgs
.getLength(); ++i
)
639 if ( aArgs
[i
].Name
== "CellRangeRepresentation" )
640 aArgs
[i
].Value
>>= sCellRange
;
641 else if ( aArgs
[i
].Name
== "BrokenCellRangeForExport" )
643 if( aArgs
[i
].Value
>>= sBrokenRange
)
644 bBrokenRangeAvailable
= true;
646 else if ( aArgs
[i
].Name
== "SequenceMapping" )
647 aArgs
[i
].Value
>>= maSequenceMapping
;
650 // #i79009# For Writer we have to export a broken version of the
651 // range, where every row number is noe too large, so that older
652 // version can correctly read those files.
653 msChartAddress
= (bBrokenRangeAvailable
? sBrokenRange
: sCellRange
);
654 if( !msChartAddress
.isEmpty() )
656 // convert format to XML-conform one
657 Reference
< chart2::data::XRangeXMLConversion
> xConversion( xDataProvider
, uno::UNO_QUERY
);
658 if( xConversion
.is())
659 msChartAddress
= xConversion
->convertRangeToXML( msChartAddress
);
663 catch( const uno::Exception
& ex
)
665 (void)ex
; // avoid warning for pro build
666 OSL_FAIL( OUStringToOString(
667 "Exception caught. Type: " +
668 OUString::createFromAscii( typeid( ex
).name()) +
670 ex
.Message
, RTL_TEXTENCODING_ASCII_US
).getStr());
674 void ChartExport::ExportContent()
676 Reference
< chart2::XChartDocument
> xChartDoc( getModel(), uno::UNO_QUERY
);
677 OSL_ASSERT( xChartDoc
.is() );
678 if( !xChartDoc
.is() )
680 InitRangeSegmentationProperties( xChartDoc
);
681 // TODO: export chart
685 void ChartExport::_ExportContent()
687 Reference
< css::chart::XChartDocument
> xChartDoc( getModel(), uno::UNO_QUERY
);
690 // determine if data comes from the outside
691 bool bIncludeTable
= true;
693 Reference
< chart2::XChartDocument
> xNewDoc( xChartDoc
, uno::UNO_QUERY
);
696 // check if we have own data. If so we must not export the complete
697 // range string, as this is our only indicator for having own or
698 // external data. @todo: fix this in the file format!
699 Reference
< lang::XServiceInfo
> xDPServiceInfo( xNewDoc
->getDataProvider(), uno::UNO_QUERY
);
700 if( ! (xDPServiceInfo
.is() && xDPServiceInfo
->getImplementationName() == "com.sun.star.comp.chart.InternalDataProvider" ))
702 bIncludeTable
= false;
707 Reference
< lang::XServiceInfo
> xServ( xChartDoc
, uno::UNO_QUERY
);
710 if( xServ
->supportsService(
711 OUString("com.sun.star.chart.ChartTableAddressSupplier")))
713 Reference
< beans::XPropertySet
> xProp( xServ
, uno::UNO_QUERY
);
719 OUString sChartAddress
;
720 aAny
= xProp
->getPropertyValue(
721 OUString("ChartRangeAddress"));
722 aAny
>>= msChartAddress
;
723 //maExportHelper.SetChartRangeAddress( sChartAddress );
725 //maExportHelper.SetTableNumberList( sTableNumberList );
727 // do not include own table if there are external addresses
728 bIncludeTable
= sChartAddress
.isEmpty();
730 catch( beans::UnknownPropertyException
& )
732 OSL_FAIL( "Property ChartRangeAddress not supported by ChartDocument" );
738 exportChartSpace( xChartDoc
, bIncludeTable
);
742 OSL_FAIL( "Couldn't export chart due to wrong XModel" );
746 void ChartExport::exportChartSpace( Reference
< css::chart::XChartDocument
> xChartDoc
,
749 FSHelperPtr pFS
= GetFS();
750 pFS
->startElement( FSNS( XML_c
, XML_chartSpace
),
751 FSNS( XML_xmlns
, XML_c
), "http://schemas.openxmlformats.org/drawingml/2006/chart",
752 FSNS( XML_xmlns
, XML_a
), "http://schemas.openxmlformats.org/drawingml/2006/main",
753 FSNS( XML_xmlns
, XML_r
), "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
755 // TODO: get the correct editing lanauge
756 pFS
->singleElement( FSNS( XML_c
, XML_lang
),
760 pFS
->singleElement(FSNS( XML_c
, XML_roundedCorners
),
766 // TODO:external data
769 exportChart(xChartDoc
);
771 // TODO: printSettings
773 // TODO: text properties
774 // TODO: shape properties
775 Reference
< XPropertySet
> xPropSet( xChartDoc
->getArea(), uno::UNO_QUERY
);
777 exportShapeProps( xPropSet
);
780 exportExternalData(xChartDoc
);
782 pFS
->endElement( FSNS( XML_c
, XML_chartSpace
) );
785 void ChartExport::exportExternalData( Reference
< css::chart::XChartDocument
> xChartDoc
)
787 // Embedded external data is grab bagged for docx file hence adding export part of
788 // external data for docx files only.
789 if(GetDocumentType() != DOCUMENT_DOCX
)
792 OUString externalDataPath
;
793 Reference
< beans::XPropertySet
> xDocPropSet( xChartDoc
->getDiagram(), uno::UNO_QUERY
);
794 if( xDocPropSet
.is())
798 Any
aAny( xDocPropSet
->getPropertyValue(
799 OUString( "ExternalData" )));
800 aAny
>>= externalDataPath
;
802 catch( beans::UnknownPropertyException
& )
804 SAL_WARN("oox", "Required property not found in ChartDocument");
807 if(!externalDataPath
.isEmpty())
809 // Here adding external data entry to relationship.
810 OUString relationPath
= externalDataPath
;
811 // Converting absolute path to relative path.
812 if( externalDataPath
[ 0 ] != '.' && externalDataPath
[ 1 ] != '.')
814 sal_Int32 nStartPos
= 0;
815 sal_Int32 nSepPos
= externalDataPath
.indexOf( '/', nStartPos
);
818 relationPath
= relationPath
.copy( nSepPos
, ::std::max
< sal_Int32
>( externalDataPath
.getLength(), 0 ) - nSepPos
);
819 relationPath
= OUStringBuffer( ".." ).append( relationPath
).makeStringAndClear();
822 FSHelperPtr pFS
= GetFS();
823 OUString type
= "http://schemas.openxmlformats.org/officeDocument/2006/relationships/package";
824 if (relationPath
.endsWith(OUString(".bin")))
825 type
= "http://schemas.openxmlformats.org/officeDocument/2006/relationships/oleObject";
827 OUString sRelId
= GetFB()->addRelation(pFS
->getOutputStream(),
830 pFS
->singleElementNS( XML_c
, XML_externalData
,
831 FSNS(XML_r
, XML_id
), OUStringToOString(sRelId
, RTL_TEXTENCODING_UTF8
),
836 void ChartExport::exportChart( Reference
< css::chart::XChartDocument
> xChartDoc
)
838 Reference
< chart2::XChartDocument
> xNewDoc( xChartDoc
, uno::UNO_QUERY
);
839 mxDiagram
.set( xChartDoc
->getDiagram() );
841 mxNewDiagram
.set( xNewDoc
->getFirstDiagram());
843 // get Properties of ChartDocument
844 bool bHasMainTitle
= false;
845 bool bHasSubTitle
= false;
846 bool bHasLegend
= false;
847 Reference
< beans::XPropertySet
> xDocPropSet( xChartDoc
, uno::UNO_QUERY
);
848 if( xDocPropSet
.is())
852 Any
aAny( xDocPropSet
->getPropertyValue(
853 OUString( "HasMainTitle" )));
854 aAny
>>= bHasMainTitle
;
855 aAny
= xDocPropSet
->getPropertyValue(
856 OUString( "HasSubTitle" ));
857 aAny
>>= bHasSubTitle
;
858 aAny
= xDocPropSet
->getPropertyValue(
859 OUString( "HasLegend" ));
862 catch( beans::UnknownPropertyException
& )
864 SAL_WARN("oox", "Required property not found in ChartDocument");
866 } // if( xDocPropSet.is())
870 FSHelperPtr pFS
= GetFS();
871 pFS
->startElement( FSNS( XML_c
, XML_chart
),
877 Reference
< drawing::XShape
> xShape
= xChartDoc
->getTitle();
880 exportTitle( xShape
);
881 pFS
->singleElement( FSNS(XML_c
, XML_autoTitleDeleted
),
892 Reference
< beans::XPropertySet
> xFloor( mxNewDiagram
->getFloor(), uno::UNO_QUERY
);
895 pFS
->startElement( FSNS( XML_c
, XML_floor
),
897 exportShapeProps( xFloor
);
898 pFS
->endElement( FSNS( XML_c
, XML_floor
) );
904 Reference
< beans::XPropertySet
> xBackWall( mxNewDiagram
->getWall(), uno::UNO_QUERY
);
907 pFS
->startElement( FSNS( XML_c
, XML_backWall
),
909 exportShapeProps( xBackWall
);
910 pFS
->endElement( FSNS( XML_c
, XML_backWall
) );
918 exportLegend( xChartDoc
);
920 uno::Reference
<beans::XPropertySet
> xDiagramPropSet(xChartDoc
->getDiagram(), uno::UNO_QUERY
);
921 uno::Any aPlotVisOnly
= xDiagramPropSet
->getPropertyValue("IncludeHiddenCells");
922 bool bIncludeHiddenCells
= false;
923 aPlotVisOnly
>>= bIncludeHiddenCells
;
924 pFS
->singleElement( FSNS( XML_c
, XML_plotVisOnly
),
925 XML_val
, BS(!bIncludeHiddenCells
),
928 exportMissingValueTreatment(Reference
<beans::XPropertySet
>(mxDiagram
, uno::UNO_QUERY
));
930 pFS
->endElement( FSNS( XML_c
, XML_chart
) );
933 void ChartExport::exportMissingValueTreatment(uno::Reference
<beans::XPropertySet
> xPropSet
)
939 uno::Any aAny
= xPropSet
->getPropertyValue("MissingValueTreatment");
940 if (!(aAny
>>= nVal
))
943 const char* pVal
= NULL
;
946 case cssc::MissingValueTreatment::LEAVE_GAP
:
949 case cssc::MissingValueTreatment::USE_ZERO
:
952 case cssc::MissingValueTreatment::CONTINUE
:
956 SAL_WARN("oox", "unknown MissingValueTreatment value");
960 FSHelperPtr pFS
= GetFS();
961 pFS
->singleElement( FSNS(XML_c
, XML_dispBlanksAs
),
966 void ChartExport::exportLegend( Reference
< css::chart::XChartDocument
> xChartDoc
)
968 FSHelperPtr pFS
= GetFS();
969 pFS
->startElement( FSNS( XML_c
, XML_legend
),
972 Reference
< beans::XPropertySet
> xProp( xChartDoc
->getLegend(), uno::UNO_QUERY
);
976 css::chart::ChartLegendPosition aLegendPos
= css::chart::ChartLegendPosition_NONE
;
979 Any
aAny( xProp
->getPropertyValue(
980 OUString( "Alignment" )));
983 catch( beans::UnknownPropertyException
& )
985 SAL_WARN("oox", "Property Align not found in ChartLegend");
988 const char* strPos
= NULL
;
991 case css::chart::ChartLegendPosition_LEFT
:
994 case css::chart::ChartLegendPosition_RIGHT
:
997 case css::chart::ChartLegendPosition_TOP
:
1000 case css::chart::ChartLegendPosition_BOTTOM
:
1003 case css::chart::ChartLegendPosition_NONE
:
1004 case css::chart::ChartLegendPosition_MAKE_FIXED_SIZE
:
1009 if( strPos
!= NULL
)
1011 pFS
->singleElement( FSNS( XML_c
, XML_legendPos
),
1016 uno::Any aRelativePos
= xProp
->getPropertyValue("RelativePosition");
1017 if (aRelativePos
.hasValue())
1019 chart2::RelativePosition aPos
= aRelativePos
.get
<chart2::RelativePosition
>();
1020 pFS
->startElement(FSNS(XML_c
, XML_layout
), FSEND
);
1021 pFS
->startElement(FSNS(XML_c
, XML_manualLayout
), FSEND
);
1023 pFS
->singleElement(FSNS(XML_c
, XML_xMode
),
1026 pFS
->singleElement(FSNS(XML_c
, XML_yMode
),
1030 double x
= aPos
.Primary
;
1031 double y
= aPos
.Secondary
;
1033 pFS
->singleElement(FSNS(XML_c
, XML_x
),
1036 pFS
->singleElement(FSNS(XML_c
, XML_y
),
1039 SAL_WARN_IF(aPos
.Anchor
!= 0, "oox.chart", "unsupported anchor position");
1041 pFS
->endElement(FSNS(XML_c
, XML_manualLayout
));
1042 pFS
->endElement(FSNS(XML_c
, XML_layout
));
1047 pFS
->singleElement( FSNS( XML_c
, XML_overlay
),
1053 exportShapeProps( xProp
);
1058 pFS
->endElement( FSNS( XML_c
, XML_legend
) );
1064 * nRotation is a 100th of a degree and the return value is
1065 * in a 60,000th of a degree
1067 * Also rotation is in opposite directions so multiply with -1
1069 OString
calcRotationValue(sal_Int32 nRotation
)
1071 if (nRotation
> 18000) // 180 degree
1076 return OString::number(nRotation
);
1081 void ChartExport::exportTitle( Reference
< XShape
> xShape
)
1084 Reference
< beans::XPropertySet
> xPropSet( xShape
, uno::UNO_QUERY
);
1087 xPropSet
->getPropertyValue("String") >>= sText
;
1089 if( sText
.isEmpty() )
1092 FSHelperPtr pFS
= GetFS();
1093 pFS
->startElement( FSNS( XML_c
, XML_title
),
1096 pFS
->startElement( FSNS( XML_c
, XML_tx
),
1098 pFS
->startElement( FSNS( XML_c
, XML_rich
),
1102 const char* sWritingMode
= NULL
;
1103 bool bVertical
= false;
1104 xPropSet
->getPropertyValue("StackedText") >>= bVertical
;
1106 sWritingMode
= "wordArtVert";
1108 sal_Int32 nRotation
= 0;
1109 xPropSet
->getPropertyValue("TextRotation") >>= nRotation
;
1111 pFS
->singleElement( FSNS( XML_a
, XML_bodyPr
),
1112 XML_vert
, sWritingMode
,
1113 XML_rot
, nRotation
== 0 ? NULL
: calcRotationValue(nRotation
).getStr(),
1116 pFS
->singleElement( FSNS( XML_a
, XML_lstStyle
),
1118 // FIXME: handle multipul paragraphs to parse aText
1119 pFS
->startElement( FSNS( XML_a
, XML_p
),
1122 pFS
->startElement( FSNS( XML_a
, XML_pPr
),
1125 WriteRunProperties(xPropSet
, false, XML_defRPr
);
1127 pFS
->endElement( FSNS( XML_a
, XML_pPr
) );
1129 pFS
->startElement( FSNS( XML_a
, XML_r
),
1131 WriteRunProperties( xPropSet
, false );
1132 pFS
->startElement( FSNS( XML_a
, XML_t
),
1134 pFS
->writeEscaped( sText
);
1135 pFS
->endElement( FSNS( XML_a
, XML_t
) );
1136 pFS
->endElement( FSNS( XML_a
, XML_r
) );
1138 pFS
->endElement( FSNS( XML_a
, XML_p
) );
1140 pFS
->endElement( FSNS( XML_c
, XML_rich
) );
1141 pFS
->endElement( FSNS( XML_c
, XML_tx
) );
1143 uno::Any aManualLayout
= xPropSet
->getPropertyValue("RelativePosition");
1144 if (aManualLayout
.hasValue())
1146 pFS
->startElement(FSNS( XML_c
, XML_layout
), FSEND
);
1147 pFS
->startElement(FSNS(XML_c
, XML_manualLayout
), FSEND
);
1148 pFS
->singleElement(FSNS(XML_c
, XML_xMode
),
1151 pFS
->singleElement(FSNS(XML_c
, XML_yMode
),
1155 Reference
<embed::XVisualObject
> xVisObject(mxChartModel
, uno::UNO_QUERY
);
1156 awt::Size aPageSize
= xVisObject
->getVisualAreaSize(embed::Aspects::MSOLE_CONTENT
);
1158 // awt::Size aSize = xShape->getSize();
1159 awt::Point aPos2
= xShape
->getPosition();
1160 double x
= (double)aPos2
.X
/ (double) aPageSize
.Width
;
1161 double y
= (double)aPos2
.Y
/ (double) aPageSize
.Height
;
1163 pFS->singleElement(FSNS(XML_c, XML_wMode),
1166 pFS->singleElement(FSNS(XML_c, XML_hMode),
1170 pFS
->singleElement(FSNS(XML_c
, XML_x
),
1173 pFS
->singleElement(FSNS(XML_c
, XML_y
),
1177 pFS->singleElement(FSNS(XML_c, XML_w),
1180 pFS->singleElement(FSNS(XML_c, XML_h),
1184 pFS
->endElement(FSNS(XML_c
, XML_manualLayout
));
1185 pFS
->endElement(FSNS(XML_c
, XML_layout
));
1188 pFS
->singleElement( FSNS(XML_c
, XML_overlay
),
1192 pFS
->endElement( FSNS( XML_c
, XML_title
) );
1195 void ChartExport::exportPlotArea( )
1197 Reference
< chart2::XCoordinateSystemContainer
> xBCooSysCnt( mxNewDiagram
, uno::UNO_QUERY
);
1198 if( ! xBCooSysCnt
.is())
1201 // plot-area element
1203 FSHelperPtr pFS
= GetFS();
1204 pFS
->startElement( FSNS( XML_c
, XML_plotArea
),
1207 Reference
<beans::XPropertySet
> xWall(mxNewDiagram
, uno::UNO_QUERY
);
1210 uno::Any aAny
= xWall
->getPropertyValue("RelativePosition");
1211 if (aAny
.hasValue())
1213 chart2::RelativePosition aPos
= aAny
.get
<chart2::RelativePosition
>();
1214 aAny
= xWall
->getPropertyValue("RelativeSize");
1215 chart2::RelativeSize aSize
= aAny
.get
<chart2::RelativeSize
>();
1216 exportManualLayout(aPos
, aSize
);
1221 Sequence
< Reference
< chart2::XCoordinateSystem
> >
1222 aCooSysSeq( xBCooSysCnt
->getCoordinateSystems());
1223 for( sal_Int32 nCSIdx
=0; nCSIdx
<aCooSysSeq
.getLength(); ++nCSIdx
)
1226 Reference
< chart2::XChartTypeContainer
> xCTCnt( aCooSysSeq
[nCSIdx
], uno::UNO_QUERY
);
1230 Sequence
< Reference
< chart2::XChartType
> > aCTSeq( xCTCnt
->getChartTypes());
1231 for( sal_Int32 nCTIdx
=0; nCTIdx
<aCTSeq
.getLength(); ++nCTIdx
)
1233 Reference
< chart2::XDataSeriesContainer
> xDSCnt( aCTSeq
[nCTIdx
], uno::UNO_QUERY
);
1236 Reference
< chart2::XChartType
> xChartType( aCTSeq
[nCTIdx
], uno::UNO_QUERY
);
1237 if( ! xChartType
.is())
1239 // note: if xDSCnt.is() then also aCTSeq[nCTIdx]
1240 OUString
aChartType( xChartType
->getChartType());
1241 sal_Int32 eChartType
= lcl_getChartType( aChartType
);
1242 switch( eChartType
)
1244 case chart::TYPEID_BAR
:
1246 exportBarChart( xChartType
);
1249 case chart::TYPEID_AREA
:
1251 exportAreaChart( xChartType
);
1254 case chart::TYPEID_LINE
:
1256 exportLineChart( xChartType
);
1259 case chart::TYPEID_BUBBLE
:
1261 exportBubbleChart( xChartType
);
1264 case chart::TYPEID_OFPIE
:
1268 case chart::TYPEID_DOUGHNUT
:
1269 case chart::TYPEID_PIE
:
1271 exportPieChart( xChartType
);
1274 case chart::TYPEID_RADARLINE
:
1275 case chart::TYPEID_RADARAREA
:
1277 exportRadarChart( xChartType
);
1280 case chart::TYPEID_SCATTER
:
1282 exportScatterChart( xChartType
);
1285 case chart::TYPEID_STOCK
:
1287 exportStockChart( xChartType
);
1290 case chart::TYPEID_SURFACE
:
1292 exportSurfaceChart( xChartType
);
1297 SAL_WARN("oox", "ChartExport::exportPlotArea -- not support chart type");
1311 * Export the Plot area Shape Properties
1312 * eg: Fill and Outline
1314 Reference
< css::chart::X3DDisplay
> xWallFloorSupplier( mxDiagram
, uno::UNO_QUERY
);
1315 if( xWallFloorSupplier
.is() )
1317 Reference
< beans::XPropertySet
> xWallPropSet( xWallFloorSupplier
->getWall(), uno::UNO_QUERY
);
1318 if( xWallPropSet
.is() )
1320 exportPlotAreaShapeProps( xWallPropSet
);
1324 pFS
->endElement( FSNS( XML_c
, XML_plotArea
) );
1328 void ChartExport::exportManualLayout(const css::chart2::RelativePosition
& rPos
, const css::chart2::RelativeSize
& rSize
)
1330 FSHelperPtr pFS
= GetFS();
1331 pFS
->startElement(FSNS(XML_c
, XML_layout
), FSEND
);
1332 pFS
->startElement(FSNS(XML_c
, XML_manualLayout
), FSEND
);
1333 pFS
->singleElement(FSNS(XML_c
, XML_layoutTarget
),
1336 pFS
->singleElement(FSNS(XML_c
, XML_xMode
),
1339 pFS
->singleElement(FSNS(XML_c
, XML_yMode
),
1343 double x
= rPos
.Primary
;
1344 double y
= rPos
.Secondary
;
1345 double w
= rSize
.Primary
;
1346 double h
= rSize
.Secondary
;
1347 switch (rPos
.Anchor
)
1349 case drawing::Alignment_LEFT
:
1352 case drawing::Alignment_TOP_LEFT
:
1354 case drawing::Alignment_BOTTOM_LEFT
:
1357 case drawing::Alignment_TOP
:
1360 case drawing::Alignment_CENTER
:
1364 case drawing::Alignment_BOTTOM
:
1368 case drawing::Alignment_TOP_RIGHT
:
1371 case drawing::Alignment_BOTTOM_RIGHT
:
1375 case drawing::Alignment_RIGHT
:
1380 SAL_WARN("oox.chart", "unhandled alignment case for manual layout export");
1383 pFS
->singleElement(FSNS(XML_c
, XML_x
),
1387 pFS
->singleElement(FSNS(XML_c
, XML_y
),
1391 pFS
->singleElement(FSNS(XML_c
, XML_w
),
1395 pFS
->singleElement(FSNS(XML_c
, XML_h
),
1399 pFS
->endElement(FSNS(XML_c
, XML_manualLayout
));
1400 pFS
->endElement(FSNS(XML_c
, XML_layout
));
1403 void ChartExport::exportPlotAreaShapeProps( Reference
< XPropertySet
> xPropSet
)
1405 FSHelperPtr pFS
= GetFS();
1406 pFS
->startElement( FSNS( XML_c
, XML_spPr
),
1409 exportFill( xPropSet
);
1410 WriteOutline( xPropSet
);
1412 pFS
->endElement( FSNS( XML_c
, XML_spPr
) );
1415 void ChartExport::exportFill( Reference
< XPropertySet
> xPropSet
)
1417 if ( !GetProperty( xPropSet
, "FillStyle" ) )
1419 FillStyle
aFillStyle( FillStyle_NONE
);
1420 xPropSet
->getPropertyValue( "FillStyle" ) >>= aFillStyle
;
1421 switch( aFillStyle
)
1423 case FillStyle_GRADIENT
:
1424 exportGradientFill( xPropSet
);
1426 case FillStyle_BITMAP
:
1427 exportBitmapFill( xPropSet
);
1430 WriteFill( xPropSet
);
1434 void ChartExport::exportBitmapFill( Reference
< XPropertySet
> xPropSet
)
1438 OUString sFillBitmapName
;
1439 xPropSet
->getPropertyValue("FillBitmapName") >>= sFillBitmapName
;
1441 uno::Reference
< lang::XMultiServiceFactory
> xFact( getModel(), uno::UNO_QUERY
);
1444 uno::Reference
< container::XNameAccess
> xBitmap( xFact
->createInstance("com.sun.star.drawing.BitmapTable"), uno::UNO_QUERY
);
1445 uno::Any rValue
= xBitmap
->getByName( sFillBitmapName
);
1446 OUString sBitmapURL
;
1447 if( (rValue
>>= sBitmapURL
) )
1449 WriteBlipFill( xPropSet
, sBitmapURL
, XML_a
, true, true );
1452 catch (const uno::Exception
& rEx
)
1454 SAL_INFO("oox", "ChartExport::exportBitmapFill " << rEx
.Message
);
1460 void ChartExport::exportGradientFill( Reference
< XPropertySet
> xPropSet
)
1464 OUString sFillGradientName
;
1465 xPropSet
->getPropertyValue("FillGradientName") >>= sFillGradientName
;
1467 awt::Gradient aGradient
;
1468 uno::Reference
< lang::XMultiServiceFactory
> xFact( getModel(), uno::UNO_QUERY
);
1471 uno::Reference
< container::XNameAccess
> xGradient( xFact
->createInstance("com.sun.star.drawing.GradientTable"), uno::UNO_QUERY
);
1472 uno::Any rValue
= xGradient
->getByName( sFillGradientName
);
1473 if( (rValue
>>= aGradient
) )
1475 mpFS
->startElementNS( XML_a
, XML_gradFill
, FSEND
);
1476 WriteGradientFill( aGradient
);
1477 mpFS
->endElementNS( XML_a
, XML_gradFill
);
1480 catch (const uno::Exception
& rEx
)
1483 "ChartExport::exportGradientFill " << rEx
.Message
);
1489 void ChartExport::exportDataTable( )
1491 FSHelperPtr pFS
= GetFS();
1492 Reference
< beans::XPropertySet
> aPropSet( mxDiagram
, uno::UNO_QUERY
);
1494 bool bShowVBorder
= false;
1495 bool bShowHBorder
= false;
1496 bool bShowOutline
= false;
1498 if (GetProperty( aPropSet
, "DataTableHBorder"))
1499 mAny
>>= bShowHBorder
;
1500 if (GetProperty( aPropSet
, "DataTableVBorder"))
1501 mAny
>>= bShowVBorder
;
1502 if (GetProperty( aPropSet
, "DataTableOutline"))
1503 mAny
>>= bShowOutline
;
1505 if (bShowVBorder
|| bShowHBorder
|| bShowOutline
)
1507 pFS
->startElement( FSNS( XML_c
, XML_dTable
),
1510 pFS
->singleElement( FSNS( XML_c
, XML_showHorzBorder
),
1514 pFS
->singleElement( FSNS( XML_c
, XML_showVertBorder
),
1518 pFS
->singleElement( FSNS( XML_c
, XML_showOutline
),
1522 pFS
->endElement( FSNS( XML_c
, XML_dTable
));
1526 void ChartExport::exportAreaChart( Reference
< chart2::XChartType
> xChartType
)
1528 FSHelperPtr pFS
= GetFS();
1529 sal_Int32 nTypeId
= XML_areaChart
;
1531 nTypeId
= XML_area3DChart
;
1532 pFS
->startElement( FSNS( XML_c
, nTypeId
),
1536 sal_Int32 nAttachedAxis
= AXIS_PRIMARY_Y
;
1537 exportAllSeries( xChartType
, nAttachedAxis
);
1538 exportAxesId( nAttachedAxis
);
1540 pFS
->endElement( FSNS( XML_c
, nTypeId
) );
1543 void ChartExport::exportBarChart( Reference
< chart2::XChartType
> xChartType
)
1545 sal_Int32 nTypeId
= XML_barChart
;
1547 nTypeId
= XML_bar3DChart
;
1548 FSHelperPtr pFS
= GetFS();
1549 pFS
->startElement( FSNS( XML_c
, nTypeId
),
1552 bool bVertical
= false;
1553 Reference
< XPropertySet
> xPropSet( mxDiagram
, uno::UNO_QUERY
);
1554 if( GetProperty( xPropSet
, "Vertical" ) )
1557 const char* bardir
= bVertical
? "bar":"col";
1558 pFS
->singleElement( FSNS( XML_c
, XML_barDir
),
1562 exportGrouping( true );
1564 const char* varyColors
= "0";
1565 pFS
->singleElement( FSNS( XML_c
, XML_varyColors
),
1566 XML_val
, varyColors
,
1569 sal_Int32 nAttachedAxis
= AXIS_PRIMARY_Y
;
1570 exportAllSeries( xChartType
, nAttachedAxis
);
1572 Reference
< XPropertySet
> xTypeProp( xChartType
, uno::UNO_QUERY
);
1574 if( xTypeProp
.is() && GetProperty( xTypeProp
, "GapwidthSequence") )
1576 uno::Sequence
< sal_Int32
> aBarPositionSequence
;
1577 mAny
>>= aBarPositionSequence
;
1578 if( aBarPositionSequence
.getLength() )
1580 sal_Int32 nGapWidth
= aBarPositionSequence
[0];
1581 pFS
->singleElement( FSNS( XML_c
, XML_gapWidth
),
1582 XML_val
, I32S( nGapWidth
),
1590 namespace cssc
= css::chart
;
1591 sal_Int32 nGeom3d
= cssc::ChartSolidType::RECTANGULAR_SOLID
;
1592 if( xPropSet
.is() && GetProperty( xPropSet
, "SolidType") )
1594 const char* sShapeType
= NULL
;
1597 case cssc::ChartSolidType::RECTANGULAR_SOLID
:
1600 case cssc::ChartSolidType::CONE
:
1601 sShapeType
= "cone";
1603 case cssc::ChartSolidType::CYLINDER
:
1604 sShapeType
= "cylinder";
1606 case cssc::ChartSolidType::PYRAMID
:
1607 sShapeType
= "pyramid";
1610 pFS
->singleElement( FSNS( XML_c
, XML_shape
),
1611 XML_val
, sShapeType
,
1616 if( !mbIs3DChart
&& xTypeProp
.is() && GetProperty( xTypeProp
, "OverlapSequence") )
1618 uno::Sequence
< sal_Int32
> aBarPositionSequence
;
1619 mAny
>>= aBarPositionSequence
;
1620 if( aBarPositionSequence
.getLength() )
1622 sal_Int32 nOverlap
= aBarPositionSequence
[0];
1623 pFS
->singleElement( FSNS( XML_c
, XML_overlap
),
1624 XML_val
, I32S( nOverlap
),
1629 exportAxesId( nAttachedAxis
);
1631 pFS
->endElement( FSNS( XML_c
, nTypeId
) );
1634 void ChartExport::exportBubbleChart( Reference
< chart2::XChartType
> xChartType
)
1636 FSHelperPtr pFS
= GetFS();
1637 pFS
->startElement( FSNS( XML_c
, XML_bubbleChart
),
1640 const char* varyColors
= "0";
1641 pFS
->singleElement( FSNS( XML_c
, XML_varyColors
),
1642 XML_val
, varyColors
,
1645 sal_Int32 nAttachedAxis
= AXIS_PRIMARY_Y
;
1646 exportAllSeries( xChartType
, nAttachedAxis
);
1648 pFS
->singleElement(FSNS(XML_c
, XML_bubble3D
),
1652 exportAxesId( nAttachedAxis
);
1654 pFS
->endElement( FSNS( XML_c
, XML_bubbleChart
) );
1657 void ChartExport::exportDoughnutChart( Reference
< chart2::XChartType
> xChartType
)
1659 FSHelperPtr pFS
= GetFS();
1660 pFS
->startElement( FSNS( XML_c
, XML_doughnutChart
),
1663 sal_Int32 nAttachedAxis
= AXIS_PRIMARY_Y
;
1664 exportAllSeries( xChartType
, nAttachedAxis
);
1666 exportFirstSliceAng( );
1668 sal_Int32 nHoleSize
= 50;
1669 pFS
->singleElement( FSNS( XML_c
, XML_holeSize
),
1670 XML_val
, I32S( nHoleSize
),
1673 pFS
->endElement( FSNS( XML_c
, XML_doughnutChart
) );
1678 std::vector
<Sequence
<Reference
<chart2::XDataSeries
> > > splitDataSeriesByAxis(Reference
< chart2::XChartType
> xChartType
)
1680 std::vector
<Sequence
<Reference
<chart2::XDataSeries
> > > aSplitSeries
;
1681 std::map
<sal_Int32
, size_t> aMapAxisToIndex
;
1683 Reference
< chart2::XDataSeriesContainer
> xDSCnt( xChartType
, uno::UNO_QUERY
);
1686 Sequence
< Reference
< chart2::XDataSeries
> > aSeriesSeq( xDSCnt
->getDataSeries());
1687 for (sal_Int32 nIndex
= 0, nEnd
= aSeriesSeq
.getLength(); nIndex
< nEnd
; ++nIndex
)
1689 uno::Reference
<chart2::XDataSeries
> xSeries
= aSeriesSeq
[nIndex
];
1690 Reference
<beans::XPropertySet
> xPropSet(xSeries
, uno::UNO_QUERY
);
1694 sal_Int32 nAxisIndex
= -1;
1695 uno::Any aAny
= xPropSet
->getPropertyValue("AttachedAxisIndex");
1696 aAny
>>= nAxisIndex
;
1697 size_t nVectorPos
= 0;
1699 auto it
= aMapAxisToIndex
.find(nAxisIndex
);
1700 if (it
== aMapAxisToIndex
.end())
1702 aSplitSeries
.push_back(Sequence
<Reference
<chart2::XDataSeries
> >());
1703 nVectorPos
= aSplitSeries
.size() - 1;
1704 aMapAxisToIndex
.insert(std::pair
<sal_Int32
, size_t>(nAxisIndex
, nVectorPos
));
1707 uno::Sequence
<Reference
<chart2::XDataSeries
> >& rAxisSeriesSeq
= aSplitSeries
[nVectorPos
];
1708 sal_Int32 nLength
= rAxisSeriesSeq
.getLength();
1709 rAxisSeriesSeq
.realloc(nLength
+ 1);
1710 rAxisSeriesSeq
[nLength
] = xSeries
;
1714 return aSplitSeries
;
1719 void ChartExport::exportLineChart( Reference
< chart2::XChartType
> xChartType
)
1721 FSHelperPtr pFS
= GetFS();
1722 std::vector
<Sequence
<Reference
<chart2::XDataSeries
> > > aSplitDataSeries
= splitDataSeriesByAxis(xChartType
);
1723 for (auto itr
= aSplitDataSeries
.begin(), itrEnd
= aSplitDataSeries
.end();
1724 itr
!= itrEnd
; ++itr
)
1726 if (itr
->getLength() == 0)
1729 sal_Int32 nTypeId
= XML_lineChart
;
1731 nTypeId
= XML_line3DChart
;
1732 pFS
->startElement( FSNS( XML_c
, nTypeId
),
1736 // TODO: show marker symbol in series?
1737 sal_Int32 nAttachedAxis
= AXIS_PRIMARY_Y
;
1738 exportSeries( xChartType
, *itr
, nAttachedAxis
);
1741 sal_Int32 nSymbolType
= css::chart::ChartSymbolType::NONE
;
1742 Reference
< XPropertySet
> xPropSet( mxDiagram
, uno::UNO_QUERY
);
1743 if( GetProperty( xPropSet
, "SymbolType" ) )
1744 mAny
>>= nSymbolType
;
1749 exportUpDownBars(xChartType
);
1750 const char* marker
= nSymbolType
== css::chart::ChartSymbolType::NONE
? "0":"1";
1751 pFS
->singleElement( FSNS( XML_c
, XML_marker
),
1756 exportAxesId( nAttachedAxis
);
1758 pFS
->endElement( FSNS( XML_c
, nTypeId
) );
1762 void ChartExport::exportPieChart( Reference
< chart2::XChartType
> xChartType
)
1764 sal_Int32 eChartType
= getChartType( );
1765 if(eChartType
== chart::TYPEID_DOUGHNUT
)
1767 exportDoughnutChart( xChartType
);
1770 FSHelperPtr pFS
= GetFS();
1771 sal_Int32 nTypeId
= XML_pieChart
;
1773 nTypeId
= XML_pie3DChart
;
1774 pFS
->startElement( FSNS( XML_c
, nTypeId
),
1777 const char* varyColors
= "1";
1778 pFS
->singleElement( FSNS( XML_c
, XML_varyColors
),
1779 XML_val
, varyColors
,
1782 sal_Int32 nAttachedAxis
= AXIS_PRIMARY_Y
;
1783 exportAllSeries( xChartType
, nAttachedAxis
);
1788 exportFirstSliceAng( );
1791 pFS
->endElement( FSNS( XML_c
, nTypeId
) );
1794 void ChartExport::exportRadarChart( Reference
< chart2::XChartType
> xChartType
)
1796 FSHelperPtr pFS
= GetFS();
1797 pFS
->startElement( FSNS( XML_c
, XML_radarChart
),
1801 sal_Int32 eChartType
= getChartType( );
1802 const char* radarStyle
= NULL
;
1803 if( eChartType
== chart::TYPEID_RADARAREA
)
1804 radarStyle
= "filled";
1806 radarStyle
= "marker";
1807 pFS
->singleElement( FSNS( XML_c
, XML_radarStyle
),
1808 XML_val
, radarStyle
,
1810 sal_Int32 nAttachedAxis
= AXIS_PRIMARY_Y
;
1811 exportAllSeries( xChartType
, nAttachedAxis
);
1812 exportAxesId( nAttachedAxis
);
1814 pFS
->endElement( FSNS( XML_c
, XML_radarChart
) );
1817 void ChartExport::exportScatterChart( Reference
< chart2::XChartType
> xChartType
)
1819 FSHelperPtr pFS
= GetFS();
1820 std::vector
<Sequence
<Reference
<chart2::XDataSeries
> > > aSplitDataSeries
= splitDataSeriesByAxis(xChartType
);
1821 for (auto itr
= aSplitDataSeries
.begin(), itrEnd
= aSplitDataSeries
.end();
1822 itr
!= itrEnd
; ++itr
)
1824 if (itr
->getLength() == 0)
1827 pFS
->startElement( FSNS( XML_c
, XML_scatterChart
),
1829 // TODO:scatterStyle
1831 sal_Int32 nSymbolType
= css::chart::ChartSymbolType::NONE
;
1832 Reference
< XPropertySet
> xPropSet( mxDiagram
, uno::UNO_QUERY
);
1833 if( GetProperty( xPropSet
, "SymbolType" ) )
1834 mAny
>>= nSymbolType
;
1836 const char* scatterStyle
= "lineMarker";
1837 if (nSymbolType
== css::chart::ChartSymbolType::NONE
)
1839 scatterStyle
= "line";
1842 pFS
->singleElement( FSNS( XML_c
, XML_scatterStyle
),
1843 XML_val
, scatterStyle
,
1846 pFS
->singleElement( FSNS( XML_c
, XML_varyColors
),
1850 // FIXME: should export xVal and yVal
1851 sal_Int32 nAttachedAxis
= AXIS_PRIMARY_Y
;
1852 exportSeries( xChartType
, *itr
, nAttachedAxis
);
1853 exportAxesId( nAttachedAxis
);
1855 pFS
->endElement( FSNS( XML_c
, XML_scatterChart
) );
1859 void ChartExport::exportStockChart( Reference
< chart2::XChartType
> xChartType
)
1861 FSHelperPtr pFS
= GetFS();
1862 pFS
->startElement( FSNS( XML_c
, XML_stockChart
),
1865 sal_Int32 nAttachedAxis
= AXIS_PRIMARY_Y
;
1867 bool bJapaneseCandleSticks
= false;
1868 Reference
< beans::XPropertySet
> xCTProp( xChartType
, uno::UNO_QUERY
);
1870 xCTProp
->getPropertyValue("Japanese") >>= bJapaneseCandleSticks
;
1872 Reference
< chart2::XDataSeriesContainer
> xDSCnt( xChartType
, uno::UNO_QUERY
);
1874 exportCandleStickSeries(
1875 xDSCnt
->getDataSeries(), bJapaneseCandleSticks
, nAttachedAxis
);
1877 // export stock properties
1878 Reference
< css::chart::XStatisticDisplay
> xStockPropProvider( mxDiagram
, uno::UNO_QUERY
);
1879 if( xStockPropProvider
.is())
1882 exportUpDownBars(xChartType
);
1885 exportAxesId( nAttachedAxis
);
1887 pFS
->endElement( FSNS( XML_c
, XML_stockChart
) );
1890 void ChartExport::exportHiLowLines()
1892 FSHelperPtr pFS
= GetFS();
1893 // export the chart property
1894 Reference
< css::chart::XStatisticDisplay
> xChartPropProvider( mxDiagram
, uno::UNO_QUERY
);
1896 if (!xChartPropProvider
.is())
1899 Reference
< beans::XPropertySet
> xStockPropSet
= xChartPropProvider
->getMinMaxLine();
1900 if( !xStockPropSet
.is() )
1903 pFS
->startElement( FSNS( XML_c
, XML_hiLowLines
),
1905 exportShapeProps( xStockPropSet
);
1906 pFS
->endElement( FSNS( XML_c
, XML_hiLowLines
) );
1909 void ChartExport::exportUpDownBars( Reference
< chart2::XChartType
> xChartType
)
1911 if(xChartType
->getChartType() != "com.sun.star.chart2.CandleStickChartType")
1914 FSHelperPtr pFS
= GetFS();
1915 // export the chart property
1916 Reference
< css::chart::XStatisticDisplay
> xChartPropProvider( mxDiagram
, uno::UNO_QUERY
);
1917 if(xChartPropProvider
.is())
1920 pFS
->startElement( FSNS( XML_c
, XML_upDownBars
),
1923 sal_Int32 nGapWidth
= 150;
1924 pFS
->singleElement( FSNS( XML_c
, XML_gapWidth
),
1925 XML_val
, I32S( nGapWidth
),
1928 Reference
< beans::XPropertySet
> xChartPropSet
= xChartPropProvider
->getUpBar();
1929 if( xChartPropSet
.is() )
1931 pFS
->startElement( FSNS( XML_c
, XML_upBars
),
1933 // For Linechart with UpDownBars, spPr is not getting imported
1934 // so no need to call the exportShapeProps() for LineChart
1935 if(xChartType
->getChartType() == "com.sun.star.chart2.CandleStickChartType")
1937 exportShapeProps(xChartPropSet
);
1939 pFS
->endElement( FSNS( XML_c
, XML_upBars
) );
1941 xChartPropSet
= xChartPropProvider
->getDownBar();
1942 if( xChartPropSet
.is() )
1944 pFS
->startElement( FSNS( XML_c
, XML_downBars
),
1946 if(xChartType
->getChartType() == "com.sun.star.chart2.CandleStickChartType")
1948 exportShapeProps(xChartPropSet
);
1950 pFS
->endElement( FSNS( XML_c
, XML_downBars
) );
1952 pFS
->endElement( FSNS( XML_c
, XML_upDownBars
) );
1956 void ChartExport::exportSurfaceChart( Reference
< chart2::XChartType
> xChartType
)
1958 FSHelperPtr pFS
= GetFS();
1959 sal_Int32 nTypeId
= XML_surfaceChart
;
1961 nTypeId
= XML_surface3DChart
;
1962 pFS
->startElement( FSNS( XML_c
, nTypeId
),
1964 sal_Int32 nAttachedAxis
= AXIS_PRIMARY_Y
;
1965 exportAllSeries( xChartType
, nAttachedAxis
);
1966 exportAxesId( nAttachedAxis
);
1968 pFS
->endElement( FSNS( XML_c
, nTypeId
) );
1971 void ChartExport::exportAllSeries(Reference
<chart2::XChartType
> xChartType
, sal_Int32
& rAttachedAxis
)
1973 Reference
< chart2::XDataSeriesContainer
> xDSCnt( xChartType
, uno::UNO_QUERY
);
1977 // export dataseries for current chart-type
1978 Sequence
< Reference
< chart2::XDataSeries
> > aSeriesSeq( xDSCnt
->getDataSeries());
1979 exportSeries(xChartType
, aSeriesSeq
, rAttachedAxis
);
1982 void ChartExport::exportSeries( Reference
<chart2::XChartType
> xChartType
,
1983 Sequence
<Reference
<chart2::XDataSeries
> >& rSeriesSeq
, sal_Int32
& rAttachedAxis
)
1985 OUString aLabelRole
= xChartType
->getRoleOfSequenceForSeriesLabel();
1986 OUString
aChartType( xChartType
->getChartType());
1987 sal_Int32 eChartType
= lcl_getChartType( aChartType
);
1989 for( sal_Int32 nSeriesIdx
=0; nSeriesIdx
<rSeriesSeq
.getLength(); ++nSeriesIdx
)
1992 Reference
< chart2::data::XDataSource
> xSource( rSeriesSeq
[nSeriesIdx
], uno::UNO_QUERY
);
1995 Reference
< chart2::XDataSeries
> xDataSeries( xSource
, uno::UNO_QUERY
);
1996 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > aSeqCnt(
1997 xSource
->getDataSequences());
1998 // search for main sequence and create a series element
2000 sal_Int32 nMainSequenceIndex
= -1;
2001 sal_Int32 nSeriesLength
= 0;
2002 Reference
< chart2::data::XDataSequence
> xValuesSeq
;
2003 Reference
< chart2::data::XDataSequence
> xLabelSeq
;
2004 sal_Int32 nSeqIdx
=0;
2005 for( ; nSeqIdx
<aSeqCnt
.getLength(); ++nSeqIdx
)
2008 Reference
< chart2::data::XDataSequence
> xTempValueSeq( aSeqCnt
[nSeqIdx
]->getValues() );
2009 if( nMainSequenceIndex
==-1 )
2011 Reference
< beans::XPropertySet
> xSeqProp( xTempValueSeq
, uno::UNO_QUERY
);
2013 xSeqProp
->getPropertyValue("Role") >>= aRole
;
2015 if( aRole
.equals( aLabelRole
))
2017 xValuesSeq
.set( xTempValueSeq
);
2018 xLabelSeq
.set( aSeqCnt
[nSeqIdx
]->getLabel());
2019 nMainSequenceIndex
= nSeqIdx
;
2022 sal_Int32 nSequenceLength
= (xTempValueSeq
.is()? xTempValueSeq
->getData().getLength() : sal_Int32(0));
2023 if( nSeriesLength
< nSequenceLength
)
2024 nSeriesLength
= nSequenceLength
;
2027 // have found the main sequence, then xValuesSeq and
2028 // xLabelSeq contain those. Otherwise both are empty
2030 FSHelperPtr pFS
= GetFS();
2031 pFS
->startElement( FSNS( XML_c
, XML_ser
),
2034 // TODO: idx and order
2035 pFS
->singleElement( FSNS( XML_c
, XML_idx
),
2036 XML_val
, I32S(mnSeriesCount
),
2038 pFS
->singleElement( FSNS( XML_c
, XML_order
),
2039 XML_val
, I32S(mnSeriesCount
++),
2043 if( xLabelSeq
.is() )
2044 exportSeriesText( xLabelSeq
);
2046 Reference
<XPropertySet
> xPropSet(xDataSeries
, UNO_QUERY_THROW
);
2047 if( GetProperty( xPropSet
, "AttachedAxisIndex") )
2049 sal_Int32 nLocalAttachedAxis
;
2050 mAny
>>= nLocalAttachedAxis
;
2051 rAttachedAxis
= translateFromChart2AxisIndexToOox(nLocalAttachedAxis
);
2054 // export shape properties
2055 Reference
< XPropertySet
> xOldPropSet
= SchXMLSeriesHelper::createOldAPISeriesPropertySet(
2056 rSeriesSeq
[nSeriesIdx
], getModel() );
2057 if( xOldPropSet
.is() )
2059 exportShapeProps( xOldPropSet
);
2062 switch( eChartType
)
2064 case chart::TYPEID_BUBBLE
:
2065 case chart::TYPEID_HORBAR
:
2066 case chart::TYPEID_BAR
:
2068 pFS
->singleElement(FSNS(XML_c
, XML_invertIfNegative
),
2073 case chart::TYPEID_LINE
:
2075 exportMarker(xDataSeries
);
2078 case chart::TYPEID_PIE
:
2079 case chart::TYPEID_DOUGHNUT
:
2081 if( xOldPropSet
.is() && GetProperty( xOldPropSet
, "SegmentOffset") )
2083 sal_Int32 nOffset
= 0;
2085 pFS
->singleElement( FSNS( XML_c
, XML_explosion
),
2086 XML_val
, I32S( nOffset
),
2091 case chart::TYPEID_SCATTER
:
2093 exportMarker(xDataSeries
);
2096 case chart::TYPEID_RADARLINE
:
2098 exportMarker(xDataSeries
);
2103 // export data points
2104 exportDataPoints( uno::Reference
< beans::XPropertySet
>( rSeriesSeq
[nSeriesIdx
], uno::UNO_QUERY
), nSeriesLength
);
2106 // export data labels
2107 exportDataLabels(rSeriesSeq
[nSeriesIdx
], nSeriesLength
, eChartType
);
2109 exportTrendlines( rSeriesSeq
[nSeriesIdx
] );
2111 if( eChartType
!= chart::TYPEID_PIE
&&
2112 eChartType
!= chart::TYPEID_RADARLINE
)
2114 //export error bars here
2115 Reference
< XPropertySet
> xSeriesPropSet( xSource
, uno::UNO_QUERY
);
2116 Reference
< XPropertySet
> xErrorBarYProps
;
2117 xSeriesPropSet
->getPropertyValue("ErrorBarY") >>= xErrorBarYProps
;
2118 if(xErrorBarYProps
.is())
2119 exportErrorBar(xErrorBarYProps
, true);
2120 if (eChartType
!= chart::TYPEID_BAR
&&
2121 eChartType
!= chart::TYPEID_HORBAR
)
2123 Reference
< XPropertySet
> xErrorBarXProps
;
2124 xSeriesPropSet
->getPropertyValue("ErrorBarX") >>= xErrorBarXProps
;
2125 if(xErrorBarXProps
.is())
2126 exportErrorBar(xErrorBarXProps
, false);
2130 // export categories
2131 if( eChartType
!= chart::TYPEID_SCATTER
&& mxCategoriesValues
.is() )
2132 exportSeriesCategory( mxCategoriesValues
);
2134 if( (eChartType
== chart::TYPEID_SCATTER
)
2135 || (eChartType
== chart::TYPEID_BUBBLE
) )
2138 Reference
< chart2::data::XLabeledDataSequence
> xSequence( lcl_getDataSequenceByRole( aSeqCnt
, OUString("values-x") ) );
2139 if( xSequence
.is() )
2141 Reference
< chart2::data::XDataSequence
> xValues( xSequence
->getValues() );
2143 exportSeriesValues( xValues
, XML_xVal
);
2147 if( eChartType
== chart::TYPEID_BUBBLE
)
2150 Reference
< chart2::data::XLabeledDataSequence
> xSequence( lcl_getDataSequenceByRole( aSeqCnt
, OUString("values-y") ) );
2151 if( xSequence
.is() )
2153 Reference
< chart2::data::XDataSequence
> xValues( xSequence
->getValues() );
2155 exportSeriesValues( xValues
, XML_yVal
);
2160 if( xValuesSeq
.is() )
2162 sal_Int32 nYValueType
= XML_val
;
2163 if( eChartType
== chart::TYPEID_SCATTER
)
2164 nYValueType
= XML_yVal
;
2165 else if( eChartType
== chart::TYPEID_BUBBLE
)
2166 nYValueType
= XML_bubbleSize
;
2167 exportSeriesValues( xValuesSeq
, nYValueType
);
2170 if( eChartType
== chart::TYPEID_SCATTER
2171 || eChartType
== chart::TYPEID_LINE
)
2174 pFS
->endElement( FSNS( XML_c
, XML_ser
) );
2181 void ChartExport::exportCandleStickSeries(
2182 const Sequence
< Reference
< chart2::XDataSeries
> > & aSeriesSeq
,
2183 bool /*bJapaneseCandleSticks*/,
2184 sal_Int32
& rAttachedAxis
)
2186 for( sal_Int32 nSeriesIdx
=0; nSeriesIdx
<aSeriesSeq
.getLength(); ++nSeriesIdx
)
2188 Reference
< chart2::XDataSeries
> xSeries( aSeriesSeq
[nSeriesIdx
] );
2189 rAttachedAxis
= lcl_isSeriesAttachedToFirstAxis( xSeries
) ? AXIS_PRIMARY_Y
: AXIS_SECONDARY_Y
;
2191 Reference
< chart2::data::XDataSource
> xSource( xSeries
, uno::UNO_QUERY
);
2194 // export series in correct order (as we don't store roles)
2195 // with japanese candlesticks: open, low, high, close
2196 // otherwise: low, high, close
2197 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > aSeqCnt(
2198 xSource
->getDataSequences());
2200 Reference
< chart2::XChartDocument
> xNewDoc( getModel(), uno::UNO_QUERY
);
2201 const char* sSeries
[] = {"values-first","values-max","values-min","values-last",0};
2203 for( sal_Int32 idx
= 0; sSeries
[idx
] != 0 ; idx
++ )
2205 Reference
< chart2::data::XLabeledDataSequence
> xLabeledSeq( lcl_getDataSequenceByRole( aSeqCnt
, OUString::createFromAscii(sSeries
[idx
]) ) );
2206 if( xLabeledSeq
.is())
2208 Reference
< chart2::data::XDataSequence
> xLabelSeq( xLabeledSeq
->getLabel());
2209 Reference
< chart2::data::XDataSequence
> xValueSeq( xLabeledSeq
->getValues());
2211 FSHelperPtr pFS
= GetFS();
2212 pFS
->startElement( FSNS( XML_c
, XML_ser
),
2215 // TODO: idx and order
2216 // idx attribute should start from 1 and not from 0.
2217 pFS
->singleElement( FSNS( XML_c
, XML_idx
),
2218 XML_val
, I32S(idx
+1),
2220 pFS
->singleElement( FSNS( XML_c
, XML_order
),
2221 XML_val
, I32S(idx
+1),
2225 if( xLabelSeq
.is() )
2226 exportSeriesText( xLabelSeq
);
2228 // TODO:export shape properties
2230 // export categories
2231 if( mxCategoriesValues
.is() )
2232 exportSeriesCategory( mxCategoriesValues
);
2235 if( xValueSeq
.is() )
2236 exportSeriesValues( xValueSeq
);
2238 pFS
->endElement( FSNS( XML_c
, XML_ser
) );
2246 void ChartExport::exportSeriesText( const Reference
< chart2::data::XDataSequence
> & xValueSeq
)
2248 FSHelperPtr pFS
= GetFS();
2249 Reference
< chart2::XChartDocument
> xNewDoc( getModel(), uno::UNO_QUERY
);
2250 pFS
->startElement( FSNS( XML_c
, XML_tx
),
2253 OUString aCellRange
= xValueSeq
->getSourceRangeRepresentation();
2254 aCellRange
= parseFormula( aCellRange
);
2255 pFS
->startElement( FSNS( XML_c
, XML_strRef
),
2258 pFS
->startElement( FSNS( XML_c
, XML_f
),
2260 pFS
->writeEscaped( aCellRange
);
2261 pFS
->endElement( FSNS( XML_c
, XML_f
) );
2263 OUString aLabelString
= lcl_getLabelString( xValueSeq
);
2264 pFS
->startElement( FSNS( XML_c
, XML_strCache
),
2266 pFS
->singleElement( FSNS( XML_c
, XML_ptCount
),
2269 pFS
->startElement( FSNS( XML_c
, XML_pt
),
2272 pFS
->startElement( FSNS( XML_c
, XML_v
),
2274 pFS
->writeEscaped( aLabelString
);
2275 pFS
->endElement( FSNS( XML_c
, XML_v
) );
2276 pFS
->endElement( FSNS( XML_c
, XML_pt
) );
2277 pFS
->endElement( FSNS( XML_c
, XML_strCache
) );
2278 pFS
->endElement( FSNS( XML_c
, XML_strRef
) );
2279 pFS
->endElement( FSNS( XML_c
, XML_tx
) );
2282 void ChartExport::exportSeriesCategory( const Reference
< chart2::data::XDataSequence
> & xValueSeq
)
2284 FSHelperPtr pFS
= GetFS();
2285 Reference
< chart2::XChartDocument
> xNewDoc( getModel(), uno::UNO_QUERY
);
2286 pFS
->startElement( FSNS( XML_c
, XML_cat
),
2289 OUString aCellRange
= xValueSeq
.is() ? xValueSeq
->getSourceRangeRepresentation() : OUString();
2290 aCellRange
= parseFormula( aCellRange
);
2291 // TODO: need to handle XML_multiLvlStrRef according to aCellRange
2292 pFS
->startElement( FSNS( XML_c
, XML_strRef
),
2295 pFS
->startElement( FSNS( XML_c
, XML_f
),
2297 pFS
->writeEscaped( aCellRange
);
2298 pFS
->endElement( FSNS( XML_c
, XML_f
) );
2300 ::std::vector
< OUString
> aCategories
;
2301 lcl_fillCategoriesIntoStringVector( xValueSeq
, aCategories
);
2302 sal_Int32 ptCount
= aCategories
.size();
2303 pFS
->startElement( FSNS( XML_c
, XML_strCache
),
2305 pFS
->singleElement( FSNS( XML_c
, XML_ptCount
),
2306 XML_val
, I32S( ptCount
),
2308 for( sal_Int32 i
= 0; i
< ptCount
; i
++ )
2310 pFS
->startElement( FSNS( XML_c
, XML_pt
),
2313 pFS
->startElement( FSNS( XML_c
, XML_v
),
2315 pFS
->writeEscaped( aCategories
[i
] );
2316 pFS
->endElement( FSNS( XML_c
, XML_v
) );
2317 pFS
->endElement( FSNS( XML_c
, XML_pt
) );
2320 pFS
->endElement( FSNS( XML_c
, XML_strCache
) );
2321 pFS
->endElement( FSNS( XML_c
, XML_strRef
) );
2322 pFS
->endElement( FSNS( XML_c
, XML_cat
) );
2325 void ChartExport::exportSeriesValues( const Reference
< chart2::data::XDataSequence
> & xValueSeq
, sal_Int32 nValueType
)
2327 FSHelperPtr pFS
= GetFS();
2328 Reference
< chart2::XChartDocument
> xNewDoc( getModel(), uno::UNO_QUERY
);
2329 pFS
->startElement( FSNS( XML_c
, nValueType
),
2332 OUString aCellRange
= xValueSeq
.is() ? xValueSeq
->getSourceRangeRepresentation() : OUString();
2333 aCellRange
= parseFormula( aCellRange
);
2334 // TODO: need to handle XML_multiLvlStrRef according to aCellRange
2335 pFS
->startElement( FSNS( XML_c
, XML_numRef
),
2338 pFS
->startElement( FSNS( XML_c
, XML_f
),
2340 pFS
->writeEscaped( aCellRange
);
2341 pFS
->endElement( FSNS( XML_c
, XML_f
) );
2343 ::std::vector
< double > aValues
;
2344 aValues
= lcl_getAllValuesFromSequence( xValueSeq
);
2345 sal_Int32 ptCount
= aValues
.size();
2346 pFS
->startElement( FSNS( XML_c
, XML_numCache
),
2348 pFS
->startElement( FSNS( XML_c
, XML_formatCode
),
2350 // TODO: what format code?
2351 pFS
->writeEscaped( "General" );
2352 pFS
->endElement( FSNS( XML_c
, XML_formatCode
) );
2353 pFS
->singleElement( FSNS( XML_c
, XML_ptCount
),
2354 XML_val
, I32S( ptCount
),
2357 bool bIsNumberValue
= true;
2358 bool bXSeriesValue
= false;
2361 if(nValueType
== XML_xVal
)
2362 bXSeriesValue
= true;
2364 for( sal_Int32 i
= 0; i
< ptCount
; i
++ )
2366 pFS
->startElement( FSNS( XML_c
, XML_pt
),
2369 pFS
->startElement( FSNS( XML_c
, XML_v
),
2371 if (bIsNumberValue
&& !rtl::math::isNan(aValues
[i
]))
2372 pFS
->write( aValues
[i
] );
2373 else if(bXSeriesValue
)
2375 //In Case aValues is not a number for X Values...We write X values as 1,2,3....MS Word does the same thing.
2376 pFS
->write( Value
);
2378 bIsNumberValue
= false;
2380 pFS
->endElement( FSNS( XML_c
, XML_v
) );
2381 pFS
->endElement( FSNS( XML_c
, XML_pt
) );
2384 pFS
->endElement( FSNS( XML_c
, XML_numCache
) );
2385 pFS
->endElement( FSNS( XML_c
, XML_numRef
) );
2386 pFS
->endElement( FSNS( XML_c
, nValueType
) );
2389 void ChartExport::exportShapeProps( Reference
< XPropertySet
> xPropSet
)
2391 FSHelperPtr pFS
= GetFS();
2392 pFS
->startElement( FSNS( XML_c
, XML_spPr
),
2395 WriteFill( xPropSet
);
2396 WriteOutline( xPropSet
);
2398 pFS
->endElement( FSNS( XML_c
, XML_spPr
) );
2401 void ChartExport::exportTextProps(Reference
<XPropertySet
> xPropSet
)
2403 FSHelperPtr pFS
= GetFS();
2404 pFS
->startElement(FSNS(XML_c
, XML_txPr
), FSEND
);
2406 pFS
->startElement(FSNS(XML_a
, XML_bodyPr
), FSEND
);
2407 pFS
->endElement(FSNS(XML_a
, XML_bodyPr
));
2409 pFS
->startElement(FSNS(XML_a
, XML_p
), FSEND
);
2410 pFS
->startElement(FSNS(XML_a
, XML_pPr
), FSEND
);
2412 WriteRunProperties(xPropSet
, false, XML_defRPr
);
2414 pFS
->endElement(FSNS(XML_a
, XML_pPr
));
2415 pFS
->endElement(FSNS(XML_a
, XML_p
));
2417 pFS
->endElement(FSNS(XML_c
, XML_txPr
));
2420 void ChartExport::InitPlotArea( )
2422 Reference
< XPropertySet
> xDiagramProperties (mxDiagram
, uno::UNO_QUERY
);
2424 // Check for supported services and then the properties provided by this service.
2425 Reference
<lang::XServiceInfo
> xServiceInfo (mxDiagram
, uno::UNO_QUERY
);
2426 if (xServiceInfo
.is())
2428 if (xServiceInfo
->supportsService(
2429 OUString("com.sun.star.chart.ChartAxisZSupplier")))
2431 xDiagramProperties
->getPropertyValue(
2432 OUString("HasZAxis")) >>= mbHasZAxis
;
2436 xDiagramProperties
->getPropertyValue(
2437 OUString ("Dim3D")) >>= mbIs3DChart
;
2439 Reference
< chart2::XChartDocument
> xNewDoc( getModel(), uno::UNO_QUERY
);
2440 if( mbHasCategoryLabels
&& mxNewDiagram
.is())
2442 Reference
< chart2::data::XLabeledDataSequence
> xCategories( lcl_getCategories( mxNewDiagram
) );
2443 if( xCategories
.is() )
2445 mxCategoriesValues
.set( xCategories
->getValues() );
2450 void ChartExport::exportAxes( )
2452 sal_Int32 nSize
= maAxes
.size();
2453 for( sal_Int32 nIdx
= 0; nIdx
< nSize
; nIdx
++ )
2455 exportAxis( maAxes
[nIdx
] );
2459 void ChartExport::exportAxis(const AxisIdPair
& rAxisIdPair
)
2461 // get some properties from document first
2462 bool bHasXAxisTitle
= false,
2463 bHasYAxisTitle
= false,
2464 bHasZAxisTitle
= false,
2465 bHasSecondaryXAxisTitle
= false,
2466 bHasSecondaryYAxisTitle
= false;
2467 bool bHasXAxisMajorGrid
= false,
2468 bHasXAxisMinorGrid
= false,
2469 bHasYAxisMajorGrid
= false,
2470 bHasYAxisMinorGrid
= false,
2471 bHasZAxisMajorGrid
= false,
2472 bHasZAxisMinorGrid
= false;
2474 Reference
< XPropertySet
> xDiagramProperties (mxDiagram
, uno::UNO_QUERY
);
2476 xDiagramProperties
->getPropertyValue(
2477 OUString ("HasXAxisTitle")) >>= bHasXAxisTitle
;
2478 xDiagramProperties
->getPropertyValue(
2479 OUString ("HasYAxisTitle")) >>= bHasYAxisTitle
;
2480 xDiagramProperties
->getPropertyValue(
2481 OUString ("HasZAxisTitle")) >>= bHasZAxisTitle
;
2482 xDiagramProperties
->getPropertyValue(
2483 OUString ("HasSecondaryXAxisTitle")) >>= bHasSecondaryXAxisTitle
;
2484 xDiagramProperties
->getPropertyValue(
2485 OUString ("HasSecondaryYAxisTitle")) >>= bHasSecondaryYAxisTitle
;
2487 xDiagramProperties
->getPropertyValue(
2488 OUString ("HasXAxisGrid")) >>= bHasXAxisMajorGrid
;
2489 xDiagramProperties
->getPropertyValue(
2490 OUString ("HasYAxisGrid")) >>= bHasYAxisMajorGrid
;
2491 xDiagramProperties
->getPropertyValue(
2492 OUString ("HasZAxisGrid")) >>= bHasZAxisMajorGrid
;
2494 xDiagramProperties
->getPropertyValue(
2495 OUString ("HasXAxisHelpGrid")) >>= bHasXAxisMinorGrid
;
2496 xDiagramProperties
->getPropertyValue(
2497 OUString ("HasYAxisHelpGrid")) >>= bHasYAxisMinorGrid
;
2498 xDiagramProperties
->getPropertyValue(
2499 OUString ("HasZAxisHelpGrid")) >>= bHasZAxisMinorGrid
;
2501 Reference
< XPropertySet
> xAxisProp
;
2502 Reference
< drawing::XShape
> xAxisTitle
;
2503 Reference
< beans::XPropertySet
> xMajorGrid
;
2504 Reference
< beans::XPropertySet
> xMinorGrid
;
2505 sal_Int32 nAxisType
= XML_catAx
;
2506 const char* sAxPos
= NULL
;
2508 switch( rAxisIdPair
.nAxisType
)
2510 case AXIS_PRIMARY_X
:
2512 Reference
< css::chart::XAxisXSupplier
> xAxisXSupp( mxDiagram
, uno::UNO_QUERY
);
2513 if( xAxisXSupp
.is())
2514 xAxisProp
= xAxisXSupp
->getXAxis();
2515 if( bHasXAxisTitle
)
2516 xAxisTitle
.set( xAxisXSupp
->getXAxisTitle(), uno::UNO_QUERY
);
2517 if( bHasXAxisMajorGrid
)
2518 xMajorGrid
.set( xAxisXSupp
->getXMainGrid(), uno::UNO_QUERY
);
2519 if( bHasXAxisMinorGrid
)
2520 xMinorGrid
.set( xAxisXSupp
->getXHelpGrid(), uno::UNO_QUERY
);
2522 sal_Int32 eChartType
= getChartType( );
2523 if( (eChartType
== chart::TYPEID_SCATTER
)
2524 || (eChartType
== chart::TYPEID_BUBBLE
) )
2525 nAxisType
= XML_valAx
;
2526 else if( eChartType
== chart::TYPEID_STOCK
)
2527 nAxisType
= XML_dateAx
;
2528 // FIXME: axPos, need to check axis direction
2532 case AXIS_PRIMARY_Y
:
2534 Reference
< css::chart::XAxisYSupplier
> xAxisYSupp( mxDiagram
, uno::UNO_QUERY
);
2535 if( xAxisYSupp
.is())
2536 xAxisProp
= xAxisYSupp
->getYAxis();
2537 if( bHasYAxisTitle
)
2538 xAxisTitle
.set( xAxisYSupp
->getYAxisTitle(), uno::UNO_QUERY
);
2539 if( bHasYAxisMajorGrid
)
2540 xMajorGrid
.set( xAxisYSupp
->getYMainGrid(), uno::UNO_QUERY
);
2541 if( bHasYAxisMinorGrid
)
2542 xMinorGrid
.set( xAxisYSupp
->getYHelpGrid(), uno::UNO_QUERY
);
2544 nAxisType
= XML_valAx
;
2545 // FIXME: axPos, need to check axis direction
2549 case AXIS_PRIMARY_Z
:
2551 Reference
< css::chart::XAxisZSupplier
> xAxisZSupp( mxDiagram
, uno::UNO_QUERY
);
2552 if( xAxisZSupp
.is())
2553 xAxisProp
= xAxisZSupp
->getZAxis();
2554 if( bHasZAxisTitle
)
2555 xAxisTitle
.set( xAxisZSupp
->getZAxisTitle(), uno::UNO_QUERY
);
2556 if( bHasZAxisMajorGrid
)
2557 xMajorGrid
.set( xAxisZSupp
->getZMainGrid(), uno::UNO_QUERY
);
2558 if( bHasZAxisMinorGrid
)
2559 xMinorGrid
.set( xAxisZSupp
->getZHelpGrid(), uno::UNO_QUERY
);
2561 sal_Int32 eChartType
= getChartType( );
2562 if( (eChartType
== chart::TYPEID_SCATTER
)
2563 || (eChartType
== chart::TYPEID_BUBBLE
) )
2564 nAxisType
= XML_valAx
;
2565 else if( eChartType
== chart::TYPEID_STOCK
)
2566 nAxisType
= XML_dateAx
;
2567 // FIXME: axPos, need to check axis direction
2571 case AXIS_SECONDARY_Y
:
2573 Reference
< css::chart::XTwoAxisYSupplier
> xAxisTwoYSupp( mxDiagram
, uno::UNO_QUERY
);
2574 if( xAxisTwoYSupp
.is())
2575 xAxisProp
= xAxisTwoYSupp
->getSecondaryYAxis();
2576 if( bHasSecondaryYAxisTitle
)
2578 Reference
< css::chart::XSecondAxisTitleSupplier
> xAxisSupp( mxDiagram
, uno::UNO_QUERY
);
2579 xAxisTitle
.set( xAxisSupp
->getSecondYAxisTitle(), uno::UNO_QUERY
);
2582 nAxisType
= XML_valAx
;
2583 // FIXME: axPos, need to check axis direction
2589 _exportAxis(xAxisProp
, xAxisTitle
, xMajorGrid
, xMinorGrid
, nAxisType
, sAxPos
, rAxisIdPair
);
2592 void ChartExport::_exportAxis(
2593 const Reference
< XPropertySet
>& xAxisProp
,
2594 const Reference
< drawing::XShape
>& xAxisTitle
,
2595 const Reference
< XPropertySet
>& xMajorGrid
,
2596 const Reference
< XPropertySet
>& xMinorGrid
,
2597 sal_Int32 nAxisType
,
2598 const char* sAxisPos
,
2599 const AxisIdPair
& rAxisIdPair
)
2601 FSHelperPtr pFS
= GetFS();
2602 pFS
->startElement( FSNS( XML_c
, nAxisType
),
2604 pFS
->singleElement( FSNS( XML_c
, XML_axId
),
2605 XML_val
, I32S( rAxisIdPair
.nAxisId
),
2608 pFS
->startElement( FSNS( XML_c
, XML_scaling
),
2611 // logBase, min, max
2612 if(GetProperty( xAxisProp
, "Logarithmic" ) )
2614 bool bLogarithmic
= false;
2615 mAny
>>= bLogarithmic
;
2618 // default value is 10?
2619 sal_Int32 nLogBase
= 10;
2620 pFS
->singleElement( FSNS( XML_c
, XML_logBase
),
2621 XML_val
, I32S( nLogBase
),
2626 // orientation: minMax, maxMin
2627 bool bReverseDirection
= false;
2628 if(GetProperty( xAxisProp
, "ReverseDirection" ) )
2629 mAny
>>= bReverseDirection
;
2631 const char* orientation
= bReverseDirection
? "maxMin":"minMax";
2632 pFS
->singleElement( FSNS( XML_c
, XML_orientation
),
2633 XML_val
, orientation
,
2636 bool bAutoMax
= false;
2637 if(GetProperty( xAxisProp
, "AutoMax" ) )
2640 if( !bAutoMax
&& (GetProperty( xAxisProp
, "Max" ) ) )
2644 pFS
->singleElement( FSNS( XML_c
, XML_max
),
2645 XML_val
, IS( dMax
),
2649 bool bAutoMin
= false;
2650 if(GetProperty( xAxisProp
, "AutoMin" ) )
2653 if( !bAutoMin
&& (GetProperty( xAxisProp
, "Min" ) ) )
2657 pFS
->singleElement( FSNS( XML_c
, XML_min
),
2658 XML_val
, IS( dMin
),
2662 pFS
->endElement( FSNS( XML_c
, XML_scaling
) );
2664 bool bVisible
= true;
2665 if( xAxisProp
.is() )
2667 xAxisProp
->getPropertyValue(
2668 OUString ("Visible")) >>= bVisible
;
2671 // only export each axis only once non-deleted
2672 bool bDeleted
= std::find(maExportedAxis
.begin(),
2673 maExportedAxis
.end(), rAxisIdPair
.nAxisType
) != maExportedAxis
.end();
2676 maExportedAxis
.insert(rAxisIdPair
.nAxisType
);
2678 pFS
->singleElement( FSNS( XML_c
, XML_delete
),
2679 XML_val
, !bDeleted
&& bVisible
? "0" : "1",
2682 // FIXME: axPos, need to check the property "ReverseDirection"
2683 pFS
->singleElement( FSNS( XML_c
, XML_axPos
),
2687 if( xMajorGrid
.is())
2689 pFS
->startElement( FSNS( XML_c
, XML_majorGridlines
),
2691 exportShapeProps( xMajorGrid
);
2692 pFS
->endElement( FSNS( XML_c
, XML_majorGridlines
) );
2696 if( xMinorGrid
.is())
2698 pFS
->startElement( FSNS( XML_c
, XML_minorGridlines
),
2700 exportShapeProps( xMinorGrid
);
2701 pFS
->endElement( FSNS( XML_c
, XML_minorGridlines
) );
2705 if( xAxisTitle
.is() )
2706 exportTitle( xAxisTitle
);
2708 bool bLinkedNumFmt
= true;
2709 if (GetProperty(xAxisProp
, "LinkNumberFormatToSource"))
2710 mAny
>>= bLinkedNumFmt
;
2712 OUString
aNumberFormatString("General");
2713 if (GetProperty(xAxisProp
, "NumberFormat"))
2717 aNumberFormatString
= getNumberFormatCode(nKey
);
2720 OString sNumberFormatString
= OUStringToOString(aNumberFormatString
, RTL_TEXTENCODING_UTF8
);
2721 pFS
->singleElement(FSNS(XML_c
, XML_numFmt
),
2722 XML_formatCode
, sNumberFormatString
.getStr(),
2723 XML_sourceLinked
, bLinkedNumFmt
? "1" : "0",
2727 sal_Int32 nValue
= 0;
2728 if(GetProperty( xAxisProp
, "Marks" ) )
2731 bool bInner
= nValue
& css::chart::ChartAxisMarks::INNER
;
2732 bool bOuter
= nValue
& css::chart::ChartAxisMarks::OUTER
;
2733 const char* majorTickMark
= NULL
;
2734 if( bInner
&& bOuter
)
2735 majorTickMark
= "cross";
2737 majorTickMark
= "in";
2739 majorTickMark
= "out";
2741 majorTickMark
= "none";
2742 pFS
->singleElement( FSNS( XML_c
, XML_majorTickMark
),
2743 XML_val
, majorTickMark
,
2747 if(GetProperty( xAxisProp
, "HelpMarks" ) )
2750 bool bInner
= nValue
& css::chart::ChartAxisMarks::INNER
;
2751 bool bOuter
= nValue
& css::chart::ChartAxisMarks::OUTER
;
2752 const char* minorTickMark
= NULL
;
2753 if( bInner
&& bOuter
)
2754 minorTickMark
= "cross";
2756 minorTickMark
= "in";
2758 minorTickMark
= "out";
2760 minorTickMark
= "none";
2761 pFS
->singleElement( FSNS( XML_c
, XML_minorTickMark
),
2762 XML_val
, minorTickMark
,
2766 const char* sTickLblPos
= NULL
;
2767 bool bDisplayLabel
= true;
2768 if(GetProperty( xAxisProp
, "DisplayLabels" ) )
2769 mAny
>>= bDisplayLabel
;
2770 if( bDisplayLabel
&& (GetProperty( xAxisProp
, "LabelPosition" ) ) )
2772 css::chart::ChartAxisLabelPosition eLabelPosition
= css::chart::ChartAxisLabelPosition_NEAR_AXIS
;
2773 mAny
>>= eLabelPosition
;
2774 switch( eLabelPosition
)
2776 case css::chart::ChartAxisLabelPosition_NEAR_AXIS
:
2777 case css::chart::ChartAxisLabelPosition_NEAR_AXIS_OTHER_SIDE
:
2778 sTickLblPos
= "nextTo";
2780 case css::chart::ChartAxisLabelPosition_OUTSIDE_START
:
2781 sTickLblPos
= "low";
2783 case css::chart::ChartAxisLabelPosition_OUTSIDE_END
:
2784 sTickLblPos
= "high";
2787 sTickLblPos
= "nextTo";
2793 sTickLblPos
= "none";
2795 pFS
->singleElement( FSNS( XML_c
, XML_tickLblPos
),
2796 XML_val
, sTickLblPos
,
2800 exportShapeProps( xAxisProp
);
2802 exportTextProps(xAxisProp
);
2804 pFS
->singleElement( FSNS( XML_c
, XML_crossAx
),
2805 XML_val
, I32S( rAxisIdPair
.nCrossAx
),
2808 // crosses & crossesAt
2809 bool bCrossesValue
= false;
2810 const char* sCrosses
= NULL
;
2811 if(GetProperty( xAxisProp
, "CrossoverPosition" ) )
2813 css::chart::ChartAxisPosition
ePosition( css::chart::ChartAxisPosition_ZERO
);
2817 case css::chart::ChartAxisPosition_START
:
2820 case css::chart::ChartAxisPosition_END
:
2823 case css::chart::ChartAxisPosition_ZERO
:
2824 sCrosses
= "autoZero";
2827 bCrossesValue
= true;
2832 if( bCrossesValue
&& GetProperty( xAxisProp
, "CrossoverValue" ) )
2836 pFS
->singleElement( FSNS( XML_c
, XML_crossesAt
),
2837 XML_val
, IS( dValue
),
2842 pFS
->singleElement( FSNS( XML_c
, XML_crosses
),
2847 if( ( nAxisType
== XML_catAx
)
2848 || ( nAxisType
== XML_dateAx
) )
2850 // FIXME: seems not support? use default value,
2851 const char* isAuto
= "1";
2852 pFS
->singleElement( FSNS( XML_c
, XML_auto
),
2856 if( nAxisType
== XML_catAx
)
2858 // FIXME: seems not support? lblAlgn
2859 const char* sLblAlgn
= "ctr";
2860 pFS
->singleElement( FSNS( XML_c
, XML_lblAlgn
),
2865 // FIXME: seems not support? lblOffset
2866 sal_Int32 nLblOffset
= 100;
2867 pFS
->singleElement( FSNS( XML_c
, XML_lblOffset
),
2868 XML_val
, I32S( nLblOffset
),
2873 bool bAutoStepMain
= false;
2874 if(GetProperty( xAxisProp
, "AutoStepMain" ) )
2875 mAny
>>= bAutoStepMain
;
2877 if( !bAutoStepMain
&& (GetProperty( xAxisProp
, "StepMain" ) ) )
2879 double dMajorUnit
= 0;
2880 mAny
>>= dMajorUnit
;
2881 pFS
->singleElement( FSNS( XML_c
, XML_majorUnit
),
2882 XML_val
, IS( dMajorUnit
),
2886 bool bAutoStepHelp
= false;
2887 if(GetProperty( xAxisProp
, "AutoStepHelp" ) )
2888 mAny
>>= bAutoStepHelp
;
2890 if( !bAutoStepHelp
&& (GetProperty( xAxisProp
, "StepHelp" ) ) )
2892 double dMinorUnit
= 0;
2893 mAny
>>= dMinorUnit
;
2894 pFS
->singleElement( FSNS( XML_c
, XML_minorUnit
),
2895 XML_val
, IS( dMinorUnit
),
2899 if( nAxisType
== XML_valAx
&& GetProperty( xAxisProp
, "DisplayUnits" ) )
2901 bool bDisplayUnits
= false;
2902 mAny
>>= bDisplayUnits
;
2906 if(GetProperty( xAxisProp
, "BuiltInUnit" ))
2911 pFS
->startElement( FSNS( XML_c
, XML_dispUnits
),
2914 OString aBuiltInUnit
= OUStringToOString(aVal
, RTL_TEXTENCODING_UTF8
);
2915 pFS
->singleElement( FSNS( XML_c
, XML_builtInUnit
),
2916 XML_val
, aBuiltInUnit
.getStr(),
2919 pFS
->singleElement(FSNS( XML_c
, XML_dispUnitsLbl
),FSEND
);
2920 pFS
->endElement( FSNS( XML_c
, XML_dispUnits
) );
2925 // TODO: text properties
2927 pFS
->endElement( FSNS( XML_c
, nAxisType
) );
2932 struct LabelPlacementParam
2935 sal_Int32 meDefault
;
2937 std::unordered_set
<sal_Int32
> maAllowedValues
;
2939 LabelPlacementParam() :
2941 meDefault(css::chart::DataLabelPlacement::OUTSIDE
) {}
2945 maAllowedValues
.insert(css::chart::DataLabelPlacement::OUTSIDE
);
2946 maAllowedValues
.insert(css::chart::DataLabelPlacement::INSIDE
);
2947 maAllowedValues
.insert(css::chart::DataLabelPlacement::CENTER
);
2948 maAllowedValues
.insert(css::chart::DataLabelPlacement::NEAR_ORIGIN
);
2949 maAllowedValues
.insert(css::chart::DataLabelPlacement::TOP
);
2950 maAllowedValues
.insert(css::chart::DataLabelPlacement::BOTTOM
);
2951 maAllowedValues
.insert(css::chart::DataLabelPlacement::LEFT
);
2952 maAllowedValues
.insert(css::chart::DataLabelPlacement::RIGHT
);
2953 maAllowedValues
.insert(css::chart::DataLabelPlacement::AVOID_OVERLAP
);
2957 const char* toOOXMLPlacement( sal_Int32 nPlacement
)
2961 case css::chart::DataLabelPlacement::OUTSIDE
: return "outEnd";
2962 case css::chart::DataLabelPlacement::INSIDE
: return "inEnd";
2963 case css::chart::DataLabelPlacement::CENTER
: return "ctr";
2964 case css::chart::DataLabelPlacement::NEAR_ORIGIN
: return "inBase";
2965 case css::chart::DataLabelPlacement::TOP
: return "t";
2966 case css::chart::DataLabelPlacement::BOTTOM
: return "b";
2967 case css::chart::DataLabelPlacement::LEFT
: return "l";
2968 case css::chart::DataLabelPlacement::RIGHT
: return "r";
2969 case css::chart::DataLabelPlacement::AVOID_OVERLAP
: return "bestFit";
2977 void writeLabelProperties(
2978 FSHelperPtr pFS
, const uno::Reference
<beans::XPropertySet
>& xPropSet
, const LabelPlacementParam
& rLabelParam
)
2983 chart2::DataPointLabel aLabel
;
2984 sal_Int32 nLabelBorderWidth
= 0;
2985 sal_Int32 nLabelBorderColor
= 0x00FFFFFF;
2987 xPropSet
->getPropertyValue("Label") >>= aLabel
;
2988 xPropSet
->getPropertyValue("LabelBorderWidth") >>= nLabelBorderWidth
;
2989 xPropSet
->getPropertyValue("LabelBorderColor") >>= nLabelBorderColor
;
2991 if (nLabelBorderWidth
> 0)
2993 pFS
->startElement(FSNS(XML_c
, XML_spPr
), FSEND
);
2994 pFS
->startElement(FSNS(XML_a
, XML_ln
), XML_w
, IS(convertHmmToEmu(nLabelBorderWidth
)), FSEND
);
2995 if (nLabelBorderColor
!= -1)
2997 pFS
->startElement(FSNS(XML_a
, XML_solidFill
), FSEND
);
2999 OString aStr
= OString::number(nLabelBorderColor
, 16).toAsciiUpperCase();
3000 pFS
->singleElement(FSNS(XML_a
, XML_srgbClr
), XML_val
, aStr
.getStr(), FSEND
);
3002 pFS
->endElement(FSNS(XML_a
, XML_solidFill
));
3004 pFS
->endElement(FSNS(XML_a
, XML_ln
));
3005 pFS
->endElement(FSNS(XML_c
, XML_spPr
));
3008 if (rLabelParam
.mbExport
)
3010 sal_Int32 nLabelPlacement
= rLabelParam
.meDefault
;
3011 if (xPropSet
->getPropertyValue("LabelPlacement") >>= nLabelPlacement
)
3013 if (!rLabelParam
.maAllowedValues
.count(nLabelPlacement
))
3014 nLabelPlacement
= rLabelParam
.meDefault
;
3015 pFS
->singleElement(FSNS(XML_c
, XML_dLblPos
), XML_val
, toOOXMLPlacement(nLabelPlacement
), FSEND
);
3019 pFS
->singleElement(FSNS(XML_c
, XML_showLegendKey
), XML_val
, BS(aLabel
.ShowLegendSymbol
), FSEND
);
3020 pFS
->singleElement(FSNS(XML_c
, XML_showVal
), XML_val
, BS(aLabel
.ShowNumber
), FSEND
);
3021 pFS
->singleElement(FSNS(XML_c
, XML_showCatName
), XML_val
, BS(aLabel
.ShowCategoryName
), FSEND
);
3022 pFS
->singleElement(FSNS(XML_c
, XML_showSerName
), XML_val
, BS(false), FSEND
);
3023 pFS
->singleElement(FSNS(XML_c
, XML_showPercent
), XML_val
, BS(aLabel
.ShowNumberInPercent
), FSEND
);
3028 void ChartExport::exportDataLabels(
3029 const uno::Reference
<chart2::XDataSeries
> & xSeries
, sal_Int32 nSeriesLength
, sal_Int32 eChartType
)
3031 if (!xSeries
.is() || nSeriesLength
<= 0)
3034 uno::Reference
<beans::XPropertySet
> xPropSet(xSeries
, uno::UNO_QUERY
);
3038 FSHelperPtr pFS
= GetFS();
3039 pFS
->startElement(FSNS(XML_c
, XML_dLbls
), FSEND
);
3041 uno::Sequence
<sal_Int32
> aAttrLabelIndices
;
3042 xPropSet
->getPropertyValue("AttributedDataPoints") >>= aAttrLabelIndices
;
3044 // We must not export label placement property when the chart type doesn't
3045 // support this option in MS Office, else MS Office would think the file
3046 // is corrupt & refuse to open it.
3048 const chart::TypeGroupInfo
& rInfo
= chart::GetTypeGroupInfo(static_cast<chart::TypeId
>(eChartType
));
3049 LabelPlacementParam aParam
;
3050 aParam
.mbExport
= !mbIs3DChart
;
3051 aParam
.meDefault
= rInfo
.mnDefLabelPos
;
3053 switch (eChartType
) // diagram chart type
3055 case chart::TYPEID_PIE
:
3056 if(getChartType() == chart::TYPEID_DOUGHNUT
)
3057 aParam
.mbExport
= false;
3059 // All pie charts support label placement.
3060 aParam
.mbExport
= true;
3062 case chart::TYPEID_AREA
:
3063 case chart::TYPEID_RADARLINE
:
3064 case chart::TYPEID_RADARAREA
:
3065 // These chart types don't support label placement.
3066 aParam
.mbExport
= false;
3068 case chart::TYPEID_BAR
:
3069 if (mbStacked
|| mbPercent
)
3071 aParam
.maAllowedValues
.clear();
3072 aParam
.maAllowedValues
.insert(css::chart::DataLabelPlacement::CENTER
);
3073 aParam
.maAllowedValues
.insert(css::chart::DataLabelPlacement::INSIDE
);
3074 aParam
.maAllowedValues
.insert(css::chart::DataLabelPlacement::NEAR_ORIGIN
);
3075 aParam
.meDefault
= css::chart::DataLabelPlacement::CENTER
;
3077 else // Clustered bar chart
3079 aParam
.maAllowedValues
.clear();
3080 aParam
.maAllowedValues
.insert(css::chart::DataLabelPlacement::CENTER
);
3081 aParam
.maAllowedValues
.insert(css::chart::DataLabelPlacement::INSIDE
);
3082 aParam
.maAllowedValues
.insert(css::chart::DataLabelPlacement::OUTSIDE
);
3083 aParam
.maAllowedValues
.insert(css::chart::DataLabelPlacement::NEAR_ORIGIN
);
3084 aParam
.meDefault
= css::chart::DataLabelPlacement::OUTSIDE
;
3091 const sal_Int32
* p
= aAttrLabelIndices
.getConstArray();
3092 const sal_Int32
* pEnd
= p
+ aAttrLabelIndices
.getLength();
3093 for (; p
!= pEnd
; ++p
)
3095 sal_Int32 nIdx
= *p
;
3096 uno::Reference
<beans::XPropertySet
> xLabelPropSet
= xSeries
->getDataPointByIndex(nIdx
);
3097 if (!xLabelPropSet
.is())
3100 // Individual label property that overwrites the baseline.
3101 pFS
->startElement(FSNS(XML_c
, XML_dLbl
), FSEND
);
3102 pFS
->singleElement(FSNS(XML_c
, XML_idx
), XML_val
, I32S(nIdx
), FSEND
);
3103 writeLabelProperties(pFS
, xLabelPropSet
, aParam
);
3104 pFS
->endElement(FSNS(XML_c
, XML_dLbl
));
3107 // Baseline label properties for all labels.
3108 writeLabelProperties(pFS
, xPropSet
, aParam
);
3110 pFS
->singleElement(FSNS(XML_c
, XML_showLeaderLines
),
3114 pFS
->endElement(FSNS(XML_c
, XML_dLbls
));
3117 void ChartExport::exportDataPoints(
3118 const uno::Reference
< beans::XPropertySet
> & xSeriesProperties
,
3119 sal_Int32 nSeriesLength
)
3121 uno::Reference
< chart2::XDataSeries
> xSeries( xSeriesProperties
, uno::UNO_QUERY
);
3122 bool bVaryColorsByPoint
= false;
3123 Sequence
< sal_Int32
> aDataPointSeq
;
3124 if( xSeriesProperties
.is())
3126 Any aAny
= xSeriesProperties
->getPropertyValue(
3127 OUString( "AttributedDataPoints" ));
3128 aAny
>>= aDataPointSeq
;
3129 xSeriesProperties
->getPropertyValue(
3130 OUString( "VaryColorsByPoint" )) >>= bVaryColorsByPoint
;
3133 const sal_Int32
* pPoints
= aDataPointSeq
.getConstArray();
3135 Reference
< chart2::XColorScheme
> xColorScheme
;
3136 if( mxNewDiagram
.is())
3137 xColorScheme
.set( mxNewDiagram
->getDefaultColorScheme());
3139 if( bVaryColorsByPoint
&& xColorScheme
.is() )
3141 ::std::set
< sal_Int32
> aAttrPointSet
;
3142 ::std::copy( pPoints
, pPoints
+ aDataPointSeq
.getLength(),
3143 ::std::inserter( aAttrPointSet
, aAttrPointSet
.begin()));
3144 const ::std::set
< sal_Int32
>::const_iterator
aEndIt( aAttrPointSet
.end());
3145 for( nElement
= 0; nElement
< nSeriesLength
; ++nElement
)
3147 uno::Reference
< beans::XPropertySet
> xPropSet
;
3148 if( aAttrPointSet
.find( nElement
) != aEndIt
)
3152 xPropSet
= SchXMLSeriesHelper::createOldAPIDataPointPropertySet(
3153 xSeries
, nElement
, getModel() );
3155 catch( const uno::Exception
& rEx
)
3157 SAL_WARN( "oox", "Exception caught during Export of data point: " << rEx
.Message
);
3162 // property set only containing the color
3163 xPropSet
.set( new ColorPropertySet( xColorScheme
->getColorByIndex( nElement
)));
3168 FSHelperPtr pFS
= GetFS();
3169 pFS
->startElement( FSNS( XML_c
, XML_dPt
),
3171 pFS
->singleElement( FSNS( XML_c
, XML_idx
),
3172 XML_val
, I32S(nElement
),
3174 exportShapeProps( xPropSet
);
3176 pFS
->endElement( FSNS( XML_c
, XML_dPt
) );
3182 void ChartExport::exportAxesId( sal_Int32 nAttachedAxis
)
3184 sal_Int32 nAxisIdx
= lcl_generateRandomValue();
3185 sal_Int32 nAxisIdy
= lcl_generateRandomValue();
3186 maAxes
.push_back( AxisIdPair( AXIS_PRIMARY_X
, nAxisIdx
, nAxisIdy
) );
3187 maAxes
.push_back( AxisIdPair( nAttachedAxis
, nAxisIdy
, nAxisIdx
) );
3188 FSHelperPtr pFS
= GetFS();
3189 pFS
->singleElement( FSNS( XML_c
, XML_axId
),
3190 XML_val
, I32S( nAxisIdx
),
3192 pFS
->singleElement( FSNS( XML_c
, XML_axId
),
3193 XML_val
, I32S( nAxisIdy
),
3197 sal_Int32 nAxisIdz
= 0;
3198 if( isDeep3dChart() )
3200 nAxisIdz
= lcl_generateRandomValue();
3201 maAxes
.push_back( AxisIdPair( AXIS_PRIMARY_Z
, nAxisIdz
, nAxisIdy
) );
3203 pFS
->singleElement( FSNS( XML_c
, XML_axId
),
3204 XML_val
, I32S( nAxisIdz
),
3209 void ChartExport::exportGrouping( bool isBar
)
3211 FSHelperPtr pFS
= GetFS();
3212 Reference
< XPropertySet
> xPropSet( mxDiagram
, uno::UNO_QUERY
);
3214 if( GetProperty( xPropSet
, "Stacked" ) )
3216 if( GetProperty( xPropSet
, "Percent" ) )
3219 const char* grouping
= NULL
;
3221 grouping
= "stacked";
3223 grouping
= "percentStacked";
3226 if( isBar
&& !isDeep3dChart() )
3228 grouping
= "clustered";
3231 grouping
= "standard";
3233 pFS
->singleElement( FSNS( XML_c
, XML_grouping
),
3238 void ChartExport::exportTrendlines( Reference
< chart2::XDataSeries
> xSeries
)
3240 FSHelperPtr pFS
= GetFS();
3241 Reference
< chart2::XRegressionCurveContainer
> xRegressionCurveContainer( xSeries
, UNO_QUERY
);
3242 if( xRegressionCurveContainer
.is() )
3244 Sequence
< Reference
< chart2::XRegressionCurve
> > aRegCurveSeq
= xRegressionCurveContainer
->getRegressionCurves();
3245 const Reference
< chart2::XRegressionCurve
>* pBeg
= aRegCurveSeq
.getConstArray();
3246 const Reference
< chart2::XRegressionCurve
>* pEnd
= pBeg
+ aRegCurveSeq
.getLength();
3247 for( const Reference
< chart2::XRegressionCurve
>* pIt
= pBeg
; pIt
!= pEnd
; ++pIt
)
3249 Reference
< chart2::XRegressionCurve
> xRegCurve
= *pIt
;
3250 if (!xRegCurve
.is())
3253 Reference
< XPropertySet
> xProperties( xRegCurve
, uno::UNO_QUERY
);
3256 Reference
< lang::XServiceName
> xServiceName( xProperties
, UNO_QUERY
);
3257 if( !xServiceName
.is() )
3260 aService
= xServiceName
->getServiceName();
3262 if(aService
!= "com.sun.star.chart2.LinearRegressionCurve" &&
3263 aService
!= "com.sun.star.chart2.ExponentialRegressionCurve" &&
3264 aService
!= "com.sun.star.chart2.LogarithmicRegressionCurve" &&
3265 aService
!= "com.sun.star.chart2.PotentialRegressionCurve" &&
3266 aService
!= "com.sun.star.chart2.PolynomialRegressionCurve" &&
3267 aService
!= "com.sun.star.chart2.MovingAverageRegressionCurve")
3270 pFS
->startElement( FSNS( XML_c
, XML_trendline
), FSEND
);
3273 xProperties
->getPropertyValue("CurveName") >>= aName
;
3274 if(!aName
.isEmpty())
3276 pFS
->startElement( FSNS( XML_c
, XML_name
), FSEND
);
3277 pFS
->writeEscaped(aName
);
3278 pFS
->endElement( FSNS( XML_c
, XML_name
) );
3281 exportShapeProps( xProperties
);
3283 if( aService
== "com.sun.star.chart2.LinearRegressionCurve" )
3285 pFS
->singleElement( FSNS( XML_c
, XML_trendlineType
),
3289 else if( aService
== "com.sun.star.chart2.ExponentialRegressionCurve" )
3291 pFS
->singleElement( FSNS( XML_c
, XML_trendlineType
),
3295 else if( aService
== "com.sun.star.chart2.LogarithmicRegressionCurve" )
3297 pFS
->singleElement( FSNS( XML_c
, XML_trendlineType
),
3301 else if( aService
== "com.sun.star.chart2.PotentialRegressionCurve" )
3303 pFS
->singleElement( FSNS( XML_c
, XML_trendlineType
),
3307 else if( aService
== "com.sun.star.chart2.PolynomialRegressionCurve" )
3309 pFS
->singleElement( FSNS( XML_c
, XML_trendlineType
),
3313 sal_Int32 aDegree
= 2;
3314 xProperties
->getPropertyValue( "PolynomialDegree") >>= aDegree
;
3315 pFS
->singleElement( FSNS( XML_c
, XML_order
),
3316 XML_val
, I32S(aDegree
),
3319 else if( aService
== "com.sun.star.chart2.MovingAverageRegressionCurve" )
3321 pFS
->singleElement( FSNS( XML_c
, XML_trendlineType
),
3322 XML_val
, "movingAvg",
3325 sal_Int32 aPeriod
= 2;
3326 xProperties
->getPropertyValue( "MovingAveragePeriod") >>= aPeriod
;
3328 pFS
->singleElement( FSNS( XML_c
, XML_period
),
3329 XML_val
, I32S(aPeriod
),
3334 // should never happen
3335 // This would produce invalid OOXML files so we check earlier for the type
3339 double fExtrapolateForward
= 0.0;
3340 double fExtrapolateBackward
= 0.0;
3342 xProperties
->getPropertyValue("ExtrapolateForward") >>= fExtrapolateForward
;
3343 xProperties
->getPropertyValue("ExtrapolateBackward") >>= fExtrapolateBackward
;
3345 pFS
->singleElement( FSNS( XML_c
, XML_forward
),
3346 XML_val
, OString::number(fExtrapolateForward
).getStr(),
3349 pFS
->singleElement( FSNS( XML_c
, XML_backward
),
3350 XML_val
, OString::number(fExtrapolateBackward
).getStr(),
3353 bool bForceIntercept
= false;
3354 xProperties
->getPropertyValue("ForceIntercept") >>= bForceIntercept
;
3356 if (bForceIntercept
)
3358 double fInterceptValue
= 0.0;
3359 xProperties
->getPropertyValue("InterceptValue") >>= fInterceptValue
;
3361 pFS
->singleElement( FSNS( XML_c
, XML_intercept
),
3362 XML_val
, OString::number(fInterceptValue
).getStr(),
3366 // Equation properties
3367 Reference
< XPropertySet
> xEquationProperties( xRegCurve
->getEquationProperties() );
3370 bool bShowEquation
= false;
3371 xEquationProperties
->getPropertyValue("ShowEquation") >>= bShowEquation
;
3374 bool bShowCorrelationCoefficient
= false;
3375 xEquationProperties
->getPropertyValue("ShowCorrelationCoefficient") >>= bShowCorrelationCoefficient
;
3377 pFS
->singleElement( FSNS( XML_c
, XML_dispRSqr
),
3378 XML_val
, bShowCorrelationCoefficient
? "1" : "0",
3381 pFS
->singleElement( FSNS( XML_c
, XML_dispEq
),
3382 XML_val
, bShowEquation
? "1" : "0",
3385 pFS
->endElement( FSNS( XML_c
, XML_trendline
) );
3390 void ChartExport::exportMarker(Reference
< chart2::XDataSeries
> xSeries
)
3392 Reference
< XPropertySet
> xPropSet( xSeries
, uno::UNO_QUERY
);
3393 chart2::Symbol aSymbol
;
3394 if( GetProperty( xPropSet
, "Symbol" ) )
3397 if(aSymbol
.Style
!= chart2::SymbolStyle_STANDARD
&& aSymbol
.Style
!= chart2::SymbolStyle_AUTO
&& aSymbol
.Style
!= chart2::SymbolStyle_NONE
)
3400 FSHelperPtr pFS
= GetFS();
3401 pFS
->startElement( FSNS( XML_c
, XML_marker
),
3404 sal_Int32 nSymbol
= aSymbol
.StandardSymbol
;
3405 // TODO: more properties support for marker
3406 const char* pSymbolType
= NULL
;
3410 pSymbolType
= "square";
3413 pSymbolType
= "diamond";
3419 pSymbolType
= "triangle";
3422 pSymbolType
= "circle";
3425 pSymbolType
= "star";
3428 pSymbolType
= "x"; // in MS office 2010 built in symbol marker 'X' is represented as 'x'
3431 pSymbolType
= "plus";
3434 pSymbolType
= "dash";
3437 pSymbolType
= "square";
3441 bool bSkipFormatting
= false;
3442 if (aSymbol
.Style
== chart2::SymbolStyle_NONE
)
3444 bSkipFormatting
= true;
3445 pSymbolType
= "none";
3450 pFS
->singleElement( FSNS( XML_c
, XML_symbol
),
3451 XML_val
, pSymbolType
,
3455 if (!bSkipFormatting
)
3457 awt::Size aSymbolSize
= aSymbol
.Size
;
3458 sal_Int32 nSize
= std::max( aSymbolSize
.Width
, aSymbolSize
.Height
);
3460 nSize
= nSize
/250.0*7.0 + 1; // just guessed based on some test cases,
3461 //the value is always 1 less than the actual value.
3462 nSize
= std::min
<sal_Int32
>( 72, std::max
<sal_Int32
>( 2, nSize
) );
3463 pFS
->singleElement( FSNS( XML_c
, XML_size
),
3464 XML_val
, I32S(nSize
),
3467 pFS
->startElement( FSNS( XML_c
, XML_spPr
),
3470 util::Color aColor
= aSymbol
.FillColor
;
3471 if (GetProperty(xPropSet
, "Color"))
3476 pFS
->singleElement(FSNS(XML_a
, XML_noFill
), FSEND
);
3479 WriteSolidFill(aColor
);
3481 pFS
->endElement( FSNS( XML_c
, XML_spPr
) );
3484 pFS
->endElement( FSNS( XML_c
, XML_marker
) );
3487 void ChartExport::exportSmooth()
3489 FSHelperPtr pFS
= GetFS();
3490 Reference
< XPropertySet
> xPropSet( mxDiagram
, uno::UNO_QUERY
);
3491 sal_Int32 nSplineType
= 0;
3492 if( GetProperty( xPropSet
, "SplineType" ) )
3493 mAny
>>= nSplineType
;
3494 const char* pVal
= nSplineType
!= 0 ? "1" : "0";
3495 pFS
->singleElement( FSNS( XML_c
, XML_smooth
),
3500 void ChartExport::exportFirstSliceAng( )
3502 FSHelperPtr pFS
= GetFS();
3503 sal_Int32 nStartingAngle
= 0;
3504 Reference
< XPropertySet
> xPropSet( mxDiagram
, uno::UNO_QUERY
);
3505 if( GetProperty( xPropSet
, "StartingAngle" ) )
3506 mAny
>>= nStartingAngle
;
3508 // convert to ooxml angle
3509 nStartingAngle
= (450 - nStartingAngle
) % 360;
3510 pFS
->singleElement( FSNS( XML_c
, XML_firstSliceAng
),
3511 XML_val
, I32S( nStartingAngle
),
3517 const char* getErrorBarStyle(sal_Int32 nErrorBarStyle
)
3519 switch(nErrorBarStyle
)
3521 case cssc::ErrorBarStyle::NONE
:
3523 case cssc::ErrorBarStyle::VARIANCE
:
3525 case cssc::ErrorBarStyle::STANDARD_DEVIATION
:
3527 case cssc::ErrorBarStyle::ABSOLUTE
:
3529 case cssc::ErrorBarStyle::RELATIVE
:
3530 return "percentage";
3531 case cssc::ErrorBarStyle::ERROR_MARGIN
:
3533 case cssc::ErrorBarStyle::STANDARD_ERROR
:
3535 case cssc::ErrorBarStyle::FROM_DATA
:
3538 assert(false && "can't happen");
3543 Reference
< chart2::data::XDataSequence
> getLabeledSequence(
3544 const uno::Sequence
< uno::Reference
< chart2::data::XLabeledDataSequence
> >& aSequences
,
3547 const OUString
aRolePrefix( "error-bars" );
3548 OUString aDirection
;
3550 aDirection
= "positive";
3552 aDirection
= "negative";
3554 for( sal_Int32 nI
=0; nI
< aSequences
.getLength(); ++nI
)
3556 if( aSequences
[nI
].is())
3558 uno::Reference
< chart2::data::XDataSequence
> xSequence( aSequences
[nI
]->getValues());
3559 uno::Reference
< beans::XPropertySet
> xSeqProp( xSequence
, uno::UNO_QUERY_THROW
);
3561 if( ( xSeqProp
->getPropertyValue(
3562 OUString( "Role" )) >>= aRole
) &&
3563 aRole
.match( aRolePrefix
) && aRole
.indexOf(aDirection
) >= 0 )
3570 return Reference
< chart2::data::XDataSequence
> ();
3575 void ChartExport::exportErrorBar(Reference
< XPropertySet
> xErrorBarProps
, bool bYError
)
3577 sal_Int32 nErrorBarStyle
= cssc::ErrorBarStyle::NONE
;
3578 xErrorBarProps
->getPropertyValue("ErrorBarStyle") >>= nErrorBarStyle
;
3579 const char* pErrorBarStyle
= getErrorBarStyle(nErrorBarStyle
);
3583 FSHelperPtr pFS
= GetFS();
3584 pFS
->startElement( FSNS( XML_c
, XML_errBars
),
3586 pFS
->singleElement( FSNS( XML_c
, XML_errDir
),
3587 XML_val
, bYError
? "y" : "x",
3589 bool bPositive
= false, bNegative
= false;
3590 xErrorBarProps
->getPropertyValue("ShowPositiveError") >>= bPositive
;
3591 xErrorBarProps
->getPropertyValue("ShowNegativeError") >>= bNegative
;
3592 const char* pErrBarType
;
3593 if(bPositive
&& bNegative
)
3594 pErrBarType
= "both";
3596 pErrBarType
= "plus";
3598 pErrBarType
= "minus";
3601 // what the hell should we do now?
3602 // at least this makes the file valid
3603 pErrBarType
= "both";
3605 pFS
->singleElement( FSNS( XML_c
, XML_errBarType
),
3606 XML_val
, pErrBarType
,
3608 pFS
->singleElement( FSNS( XML_c
, XML_errValType
),
3609 XML_val
, pErrorBarStyle
,
3611 pFS
->singleElement( FSNS( XML_c
, XML_noEndCap
),
3614 if(nErrorBarStyle
== cssc::ErrorBarStyle::FROM_DATA
)
3616 uno::Reference
< chart2::data::XDataSource
> xDataSource(xErrorBarProps
, uno::UNO_QUERY
);
3617 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > aSequences
=
3618 xDataSource
->getDataSequences();
3622 exportSeriesValues(getLabeledSequence(aSequences
, true), XML_plus
);
3627 exportSeriesValues(getLabeledSequence(aSequences
, false), XML_minus
);
3633 if(nErrorBarStyle
== cssc::ErrorBarStyle::STANDARD_DEVIATION
)
3635 xErrorBarProps
->getPropertyValue("Weight") >>= nVal
;
3640 xErrorBarProps
->getPropertyValue("PositiveError") >>= nVal
;
3642 xErrorBarProps
->getPropertyValue("NegativeError") >>= nVal
;
3645 OString aVal
= OString::number(nVal
);
3647 pFS
->singleElement( FSNS( XML_c
, XML_val
),
3648 XML_val
, aVal
.getStr(),
3652 pFS
->endElement( FSNS( XML_c
, XML_errBars
) );
3655 void ChartExport::exportView3D()
3657 Reference
< XPropertySet
> xPropSet( mxDiagram
, uno::UNO_QUERY
);
3658 if( !xPropSet
.is() )
3660 FSHelperPtr pFS
= GetFS();
3661 pFS
->startElement( FSNS( XML_c
, XML_view3D
),
3663 sal_Int32 eChartType
= getChartType( );
3665 if( GetProperty( xPropSet
, "RotationHorizontal" ) )
3667 sal_Int32 nRotationX
= 0;
3668 mAny
>>= nRotationX
;
3669 if( nRotationX
< 0 )
3671 if(eChartType
== chart::TYPEID_PIE
)
3673 /* In OOXML we get value in 0..90 range for pie chart X rotation , whereas we expect it to be in -90..90 range,
3674 so we conver that during import. It is modified in View3DConverter::convertFromModel()
3675 here we convert it back to 0..90 as we received in import */
3676 nRotationX
+= 90; // X rotation (map Chart2 [-179,180] to OOXML [0..90])
3679 nRotationX
+= 360; // X rotation (map Chart2 [-179,180] to OOXML [-90..90])
3681 pFS
->singleElement( FSNS( XML_c
, XML_rotX
),
3682 XML_val
, I32S( nRotationX
),
3686 if( GetProperty( xPropSet
, "RotationVertical" ) )
3688 // Y rotation (map Chart2 [-179,180] to OOXML [0..359])
3689 if( eChartType
== chart::TYPEID_PIE
&& GetProperty( xPropSet
, "StartingAngle" ) )
3691 // Y rotation used as 'first pie slice angle' in 3D pie charts
3692 sal_Int32 nStartingAngle
=0;
3693 mAny
>>= nStartingAngle
;
3694 // convert to ooxml angle
3695 nStartingAngle
= (450 - nStartingAngle
) % 360;
3696 pFS
->singleElement( FSNS( XML_c
, XML_rotY
),
3697 XML_val
, I32S( nStartingAngle
),
3702 sal_Int32 nRotationY
= 0;
3703 mAny
>>= nRotationY
;
3704 // Y rotation (map Chart2 [-179,180] to OOXML [0..359])
3705 if( nRotationY
< 0 )
3707 pFS
->singleElement( FSNS( XML_c
, XML_rotY
),
3708 XML_val
, I32S( nRotationY
),
3713 if( GetProperty( xPropSet
, "RightAngledAxes" ) )
3715 bool bRightAngled
= false;
3716 mAny
>>= bRightAngled
;
3717 const char* sRightAngled
= bRightAngled
? "1":"0";
3718 pFS
->singleElement( FSNS( XML_c
, XML_rAngAx
),
3719 XML_val
, sRightAngled
,
3723 if( GetProperty( xPropSet
, "Perspective" ) )
3725 sal_Int32 nPerspective
= 0;
3726 mAny
>>= nPerspective
;
3727 // map Chart2 [0,100] to OOXML [0..200]
3729 pFS
->singleElement( FSNS( XML_c
, XML_perspective
),
3730 XML_val
, I32S( nPerspective
),
3733 pFS
->endElement( FSNS( XML_c
, XML_view3D
) );
3736 bool ChartExport::isDeep3dChart()
3738 bool isDeep
= false;
3741 Reference
< XPropertySet
> xPropSet( mxDiagram
, uno::UNO_QUERY
);
3742 if( GetProperty( xPropSet
, "Deep" ) )
3748 OUString
ChartExport::getNumberFormatCode(sal_Int32 nKey
) const
3750 uno::Reference
<util::XNumberFormatsSupplier
> xNumberFormatsSupplier(mxChartModel
, uno::UNO_QUERY_THROW
);
3751 uno::Reference
<util::XNumberFormats
> xNumberFormats
= xNumberFormatsSupplier
->getNumberFormats();
3752 uno::Reference
<beans::XPropertySet
> xNumberFormat
= xNumberFormats
->getByKey(nKey
);
3754 if (!xNumberFormat
.is())
3757 uno::Any aAny
= xNumberFormat
->getPropertyValue("FormatString");
3766 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */