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 "oox/drawingml/chart/typegroupconverter.hxx"
28 #include <com/sun/star/chart/XChartDocument.hpp>
29 #include <com/sun/star/chart/ChartLegendPosition.hpp>
30 #include <com/sun/star/chart/XTwoAxisXSupplier.hpp>
31 #include <com/sun/star/chart/XTwoAxisYSupplier.hpp>
32 #include <com/sun/star/chart/XAxisZSupplier.hpp>
33 #include <com/sun/star/chart/XChartDataArray.hpp>
34 #include <com/sun/star/chart/ChartDataRowSource.hpp>
35 #include <com/sun/star/chart/ChartAxisAssign.hpp>
36 #include <com/sun/star/chart/ChartSeriesAddress.hpp>
37 #include <com/sun/star/chart/X3DDisplay.hpp>
38 #include <com/sun/star/chart/XStatisticDisplay.hpp>
39 #include <com/sun/star/chart/XSecondAxisTitleSupplier.hpp>
40 #include <com/sun/star/chart/ChartSymbolType.hpp>
41 #include <com/sun/star/chart/ChartAxisMarks.hpp>
42 #include <com/sun/star/chart/ChartAxisLabelPosition.hpp>
43 #include <com/sun/star/chart/ChartAxisPosition.hpp>
44 #include <com/sun/star/chart/ChartSolidType.hpp>
45 #include <com/sun/star/chart/DataLabelPlacement.hpp>
46 #include <com/sun/star/chart/ErrorBarStyle.hpp>
48 #include <com/sun/star/chart2/XChartDocument.hpp>
49 #include <com/sun/star/chart2/XDiagram.hpp>
50 #include <com/sun/star/chart2/RelativePosition.hpp>
51 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
52 #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
53 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
54 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
55 #include <com/sun/star/chart2/DataPointGeometry3D.hpp>
56 #include <com/sun/star/chart2/DataPointLabel.hpp>
57 #include <com/sun/star/chart2/data/XDataSource.hpp>
58 #include <com/sun/star/chart2/data/XDataSink.hpp>
59 #include <com/sun/star/chart2/data/XDataReceiver.hpp>
60 #include <com/sun/star/chart2/data/XDataProvider.hpp>
61 #include <com/sun/star/chart2/data/XDatabaseDataProvider.hpp>
62 #include <com/sun/star/chart2/data/XRangeXMLConversion.hpp>
63 #include <com/sun/star/chart2/data/XTextualDataSequence.hpp>
64 #include <com/sun/star/chart2/data/XNumericalDataSequence.hpp>
66 #include <com/sun/star/beans/XPropertySet.hpp>
67 #include <com/sun/star/beans/XPropertyState.hpp>
68 #include <com/sun/star/container/XEnumerationAccess.hpp>
69 #include <com/sun/star/drawing/XShape.hpp>
70 #include <com/sun/star/drawing/FillStyle.hpp>
71 #include <com/sun/star/drawing/BitmapMode.hpp>
73 #include <com/sun/star/table/CellAddress.hpp>
74 #include <com/sun/star/sheet/XFormulaParser.hpp>
75 #include <com/sun/star/sheet/XFormulaTokens.hpp>
76 #include <com/sun/star/sheet/FormulaToken.hpp>
77 #include <com/sun/star/sheet/AddressConvention.hpp>
79 #include <com/sun/star/text/WritingMode.hpp>
80 #include <com/sun/star/container/XNamed.hpp>
82 #include <comphelper/processfactory.hxx>
83 #include <xmloff/SchXMLSeriesHelper.hxx>
84 #include "ColorPropertySet.hxx"
88 using namespace ::com::sun::star
;
89 using namespace ::com::sun::star::uno
;
90 using namespace ::com::sun::star::drawing
;
91 using namespace ::oox::core
;
92 using ::com::sun::star::beans::PropertyState
;
93 using ::com::sun::star::beans::PropertyValue
;
94 using ::com::sun::star::beans::XPropertySet
;
95 using ::com::sun::star::beans::XPropertyState
;
96 using ::com::sun::star::container::XEnumeration
;
97 using ::com::sun::star::container::XEnumerationAccess
;
98 using ::com::sun::star::container::XIndexAccess
;
99 using ::com::sun::star::container::XNamed
;
100 using ::com::sun::star::io::XOutputStream
;
101 using ::com::sun::star::table::CellAddress
;
102 using ::com::sun::star::sheet::XFormulaParser
;
103 using ::com::sun::star::sheet::XFormulaTokens
;
104 using ::oox::core::XmlFilterBase
;
105 using ::sax_fastparser::FSHelperPtr
;
107 namespace cssc
= com::sun::star::chart
;
109 DBG(extern void dump_pset(Reference
< XPropertySet
> rXPropSet
));
111 namespace oox
{ namespace drawingml
{
113 class lcl_MatchesRole
: public ::std::unary_function
< Reference
< chart2::data::XLabeledDataSequence
>, bool >
116 explicit lcl_MatchesRole( const OUString
& aRole
) :
120 bool operator () ( const Reference
< chart2::data::XLabeledDataSequence
> & xSeq
) const
124 Reference
< beans::XPropertySet
> xProp( xSeq
->getValues(), uno::UNO_QUERY
);
127 return ( xProp
.is() &&
128 (xProp
->getPropertyValue(
129 OUString( "Role" ) ) >>= aRole
) &&
130 m_aRole
.equals( aRole
));
137 template< typename T
>
138 void lcl_SequenceToVectorAppend( const Sequence
< T
> & rSource
, ::std::vector
< T
> & rDestination
)
140 rDestination
.reserve( rDestination
.size() + rSource
.getLength());
141 ::std::copy( rSource
.getConstArray(), rSource
.getConstArray() + rSource
.getLength(),
142 ::std::back_inserter( rDestination
));
145 Reference
< chart2::data::XLabeledDataSequence
> lcl_getCategories( const Reference
< chart2::XDiagram
> & xDiagram
)
147 Reference
< chart2::data::XLabeledDataSequence
> xResult
;
150 Reference
< chart2::XCoordinateSystemContainer
> xCooSysCnt(
151 xDiagram
, uno::UNO_QUERY_THROW
);
152 Sequence
< Reference
< chart2::XCoordinateSystem
> > aCooSysSeq(
153 xCooSysCnt
->getCoordinateSystems());
154 for( sal_Int32 i
=0; i
<aCooSysSeq
.getLength(); ++i
)
156 Reference
< chart2::XCoordinateSystem
> xCooSys( aCooSysSeq
[i
] );
157 OSL_ASSERT( xCooSys
.is());
158 for( sal_Int32 nN
= xCooSys
->getDimension(); nN
--; )
160 const sal_Int32 nMaxAxisIndex
= xCooSys
->getMaximumAxisIndexByDimension(nN
);
161 for(sal_Int32 nI
=0; nI
<=nMaxAxisIndex
; ++nI
)
163 Reference
< chart2::XAxis
> xAxis
= xCooSys
->getAxisByDimension( nN
, nI
);
164 OSL_ASSERT( xAxis
.is());
167 chart2::ScaleData aScaleData
= xAxis
->getScaleData();
168 if( aScaleData
.Categories
.is())
170 xResult
.set( aScaleData
.Categories
);
178 catch( const uno::Exception
& ex
)
180 (void)ex
; // avoid warning for pro build
181 OSL_FAIL( OUStringToOString(
182 OUString( "Exception caught. Type: " ) +
183 OUString::createFromAscii( typeid( ex
).name()) +
184 OUString( ", Message: " ) +
185 ex
.Message
, RTL_TEXTENCODING_ASCII_US
).getStr());
191 Reference
< chart2::data::XDataSource
> lcl_createDataSource(
192 const Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > & aData
)
194 Reference
< uno::XComponentContext
> xContext(
195 comphelper::getProcessComponentContext() );
196 Reference
< chart2::data::XDataSink
> xSink(
197 xContext
->getServiceManager()->createInstanceWithContext(
198 "com.sun.star.chart2.data.DataSource", xContext
),
199 uno::UNO_QUERY_THROW
);
201 xSink
->setData( aData
);
203 return Reference
< chart2::data::XDataSource
>( xSink
, uno::UNO_QUERY
);
206 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > lcl_getAllSeriesSequences( const Reference
< chart2::XChartDocument
>& xChartDoc
)
208 ::std::vector
< Reference
< chart2::data::XLabeledDataSequence
> > aContainer
;
211 Reference
< chart2::XDiagram
> xDiagram( xChartDoc
->getFirstDiagram());
212 ::std::vector
< Reference
< chart2::XDataSeries
> > aSeriesVector( SchXMLSeriesHelper::getDataSeriesFromDiagram( xDiagram
));
213 for( ::std::vector
< Reference
< chart2::XDataSeries
> >::const_iterator
aSeriesIt( aSeriesVector
.begin() )
214 ; aSeriesIt
!= aSeriesVector
.end(); ++aSeriesIt
)
216 Reference
< chart2::data::XDataSource
> xDataSource( *aSeriesIt
, uno::UNO_QUERY
);
217 if( !xDataSource
.is() )
219 uno::Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > aDataSequences( xDataSource
->getDataSequences() );
220 lcl_SequenceToVectorAppend( aDataSequences
, aContainer
);
224 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > aRet( aContainer
.size());
225 ::std::copy( aContainer
.begin(), aContainer
.end(), aRet
.getArray());
230 Reference
< chart2::data::XLabeledDataSequence
>
231 lcl_getDataSequenceByRole(
232 const Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > & aLabeledSeq
,
233 const OUString
& rRole
)
235 Reference
< chart2::data::XLabeledDataSequence
> aNoResult
;
237 const Reference
< chart2::data::XLabeledDataSequence
> * pBegin
= aLabeledSeq
.getConstArray();
238 const Reference
< chart2::data::XLabeledDataSequence
> * pEnd
= pBegin
+ aLabeledSeq
.getLength();
239 const Reference
< chart2::data::XLabeledDataSequence
> * pMatch
=
240 ::std::find_if( pBegin
, pEnd
, lcl_MatchesRole( rRole
));
248 Reference
< chart2::data::XDataSource
> lcl_pressUsedDataIntoRectangularFormat( const Reference
< chart2::XChartDocument
>& xChartDoc
, sal_Bool
& rOutSourceHasCategoryLabels
)
250 ::std::vector
< Reference
< chart2::data::XLabeledDataSequence
> > aLabeledSeqVector
;
252 //categories are always the first sequence
253 Reference
< chart2::XDiagram
> xDiagram( xChartDoc
->getFirstDiagram());
254 Reference
< chart2::data::XLabeledDataSequence
> xCategories( lcl_getCategories( xDiagram
) );
255 if( xCategories
.is() )
256 aLabeledSeqVector
.push_back( xCategories
);
257 rOutSourceHasCategoryLabels
= sal_Bool(xCategories
.is());
259 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > aSeriesSeqVector(
260 lcl_getAllSeriesSequences( xChartDoc
) );
262 //the first x-values is always the next sequence //todo ... other x-values get lost for old format
263 Reference
< chart2::data::XLabeledDataSequence
> xXValues(
264 lcl_getDataSequenceByRole( aSeriesSeqVector
, OUString("values-x") ) );
266 aLabeledSeqVector
.push_back( xXValues
);
268 //add all other sequences now without x-values
269 lcl_MatchesRole
aHasXValues( OUString("values-x") );
270 for( sal_Int32 nN
=0; nN
<aSeriesSeqVector
.getLength(); nN
++ )
272 if( !aHasXValues( aSeriesSeqVector
[nN
] ) )
273 aLabeledSeqVector
.push_back( aSeriesSeqVector
[nN
] );
276 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > aSeq( aLabeledSeqVector
.size() );
277 ::std::copy( aLabeledSeqVector
.begin(), aLabeledSeqVector
.end(), aSeq
.getArray() );
279 return lcl_createDataSource( aSeq
);
282 bool lcl_isSeriesAttachedToFirstAxis(
283 const Reference
< chart2::XDataSeries
> & xDataSeries
)
289 sal_Int32 nAxisIndex
= 0;
290 Reference
< beans::XPropertySet
> xProp( xDataSeries
, uno::UNO_QUERY_THROW
);
292 xProp
->getPropertyValue( OUString( "AttachedAxisIndex" ) ) >>= nAxisIndex
;
293 bResult
= (0==nAxisIndex
);
295 catch( const uno::Exception
& ex
)
297 (void)ex
; // avoid warning for pro build
298 OSL_FAIL( OUStringToOString(
299 OUString( "Exception caught. Type: " ) +
300 OUString::createFromAscii( typeid( ex
).name()) +
301 OUString( ", Message: " ) +
302 ex
.Message
, RTL_TEXTENCODING_ASCII_US
).getStr());
308 OUString
lcl_flattenStringSequence( const Sequence
< OUString
> & rSequence
)
310 OUStringBuffer aResult
;
311 bool bPrecedeWithSpace
= false;
312 for( sal_Int32 nIndex
=0; nIndex
<rSequence
.getLength(); ++nIndex
)
314 if( !rSequence
[nIndex
].isEmpty())
316 if( bPrecedeWithSpace
)
317 aResult
.append( static_cast< sal_Unicode
>( ' ' ));
318 aResult
.append( rSequence
[nIndex
] );
319 bPrecedeWithSpace
= true;
322 return aResult
.makeStringAndClear();
325 OUString
lcl_getLabelString( const Reference
< chart2::data::XDataSequence
> & xLabelSeq
)
327 Sequence
< OUString
> aLabels
;
329 uno::Reference
< chart2::data::XTextualDataSequence
> xTextualDataSequence( xLabelSeq
, uno::UNO_QUERY
);
330 if( xTextualDataSequence
.is())
332 aLabels
= xTextualDataSequence
->getTextualData();
334 else if( xLabelSeq
.is())
336 Sequence
< uno::Any
> aAnies( xLabelSeq
->getData());
337 aLabels
.realloc( aAnies
.getLength());
338 for( sal_Int32 i
=0; i
<aAnies
.getLength(); ++i
)
339 aAnies
[i
] >>= aLabels
[i
];
342 return lcl_flattenStringSequence( aLabels
);
345 void lcl_fillCategoriesIntoStringVector(
346 const Reference
< chart2::data::XDataSequence
> & xCategories
,
347 ::std::vector
< OUString
> & rOutCategories
)
349 OSL_ASSERT( xCategories
.is());
350 if( !xCategories
.is())
352 Reference
< chart2::data::XTextualDataSequence
> xTextualDataSequence( xCategories
, uno::UNO_QUERY
);
353 if( xTextualDataSequence
.is())
355 rOutCategories
.clear();
356 Sequence
< OUString
> aTextData( xTextualDataSequence
->getTextualData());
357 ::std::copy( aTextData
.getConstArray(), aTextData
.getConstArray() + aTextData
.getLength(),
358 ::std::back_inserter( rOutCategories
));
362 Sequence
< uno::Any
> aAnies( xCategories
->getData());
363 rOutCategories
.resize( aAnies
.getLength());
364 for( sal_Int32 i
=0; i
<aAnies
.getLength(); ++i
)
365 aAnies
[i
] >>= rOutCategories
[i
];
369 ::std::vector
< double > lcl_getAllValuesFromSequence( const Reference
< chart2::data::XDataSequence
> & xSeq
)
372 ::rtl::math::setNan( &fNan
);
373 ::std::vector
< double > aResult
;
375 Reference
< chart2::data::XNumericalDataSequence
> xNumSeq( xSeq
, uno::UNO_QUERY
);
378 Sequence
< double > aValues( xNumSeq
->getNumericalData());
379 ::std::copy( aValues
.getConstArray(), aValues
.getConstArray() + aValues
.getLength(),
380 ::std::back_inserter( aResult
));
384 Sequence
< uno::Any
> aAnies( xSeq
->getData());
385 aResult
.resize( aAnies
.getLength(), fNan
);
386 for( sal_Int32 i
=0; i
<aAnies
.getLength(); ++i
)
387 aAnies
[i
] >>= aResult
[i
];
392 sal_Int32
lcl_getChartType( const OUString
& sChartType
)
394 chart::TypeId eChartTypeId
= chart::TYPEID_UNKNOWN
;
395 if(( 0 == sChartType
.reverseCompareTo( "com.sun.star.chart.BarDiagram" ))
396 || ( 0 == sChartType
.reverseCompareTo( "com.sun.star.chart2.ColumnChartType" )))
397 eChartTypeId
= chart::TYPEID_BAR
;
398 else if(( 0 == sChartType
.reverseCompareTo( "com.sun.star.chart.AreaDiagram" ))
399 || ( 0 == sChartType
.reverseCompareTo( "com.sun.star.chart2.AreaChartType" ) ) )
400 eChartTypeId
= chart::TYPEID_AREA
;
401 else if(( 0 == sChartType
.reverseCompareTo( "com.sun.star.chart.LineDiagram" ))
402 || ( 0 == sChartType
.reverseCompareTo( "com.sun.star.chart2.LineChartType" ) ) )
403 eChartTypeId
= chart::TYPEID_LINE
;
404 else if(( 0 == sChartType
.reverseCompareTo( "com.sun.star.chart.PieDiagram" ))
405 || ( 0 == sChartType
.reverseCompareTo( "com.sun.star.chart2.PieChartType") ) )
406 eChartTypeId
= chart::TYPEID_PIE
;
407 else if(( 0 == sChartType
.reverseCompareTo( "com.sun.star.chart.DonutDiagram"))
408 || ( 0 == sChartType
.reverseCompareTo( "com.sun.star.chart2.DonutChartType") ) )
409 eChartTypeId
= chart::TYPEID_DOUGHNUT
;
410 else if(( 0 == sChartType
.reverseCompareTo( "com.sun.star.chart.XYDiagram"))
411 || ( 0 == sChartType
.reverseCompareTo( "com.sun.star.chart2.ScatterChartType") ) )
412 eChartTypeId
= chart::TYPEID_SCATTER
;
413 else if(( 0 == sChartType
.reverseCompareTo( "com.sun.star.chart.NetDiagram"))
414 || ( 0 == sChartType
.reverseCompareTo( "com.sun.star.chart2.NetChartType") ) )
415 eChartTypeId
= chart::TYPEID_RADARLINE
;
416 else if(( 0 == sChartType
.reverseCompareTo( "com.sun.star.chart.FilledNetDiagram"))
417 || ( 0 == sChartType
.reverseCompareTo( "com.sun.star.chart2.FilledNetChartType") ) )
418 eChartTypeId
= chart::TYPEID_RADARAREA
;
419 else if(( 0 == sChartType
.reverseCompareTo( "com.sun.star.chart.StockDiagram"))
420 || ( 0 == sChartType
.reverseCompareTo( "com.sun.star.chart2.CandleStickChartType") ) )
421 eChartTypeId
= chart::TYPEID_STOCK
;
422 else if(( 0 == sChartType
.reverseCompareTo( "com.sun.star.chart.BubbleDiagram"))
423 || ( 0 == sChartType
.reverseCompareTo( "com.sun.star.chart2.BubbleChartType") ) )
424 eChartTypeId
= chart::TYPEID_BUBBLE
;
429 sal_Int32
lcl_generateRandomValue()
431 static sal_Int32 MAX_NUMBER
= 100000000;
432 //srand( unsigned( time( NULL ) ));
433 return sal_Int32( rand() % MAX_NUMBER
);
436 ChartExport::ChartExport( sal_Int32 nXmlNamespace
, FSHelperPtr pFS
, Reference
< frame::XModel
>& xModel
, XmlFilterBase
* pFB
, DocumentType eDocumentType
)
437 : DrawingML( pFS
, pFB
, eDocumentType
)
438 , mnXmlNamespace( nXmlNamespace
)
439 , maFraction( 1, 576 )
440 , mxChartModel( xModel
)
441 , mbHasCategoryLabels( sal_False
)
442 , mbHasZAxis( sal_False
)
443 , mbIs3DChart( sal_False
)
447 sal_Int32
ChartExport::GetChartID( )
449 sal_Int32 nID
= GetFB()->GetUniqueId();
453 sal_Int32
ChartExport::getChartType( )
455 OUString sChartType
= mxDiagram
->getDiagramType();
456 return lcl_getChartType( sChartType
);
459 OUString
ChartExport::parseFormula( const OUString
& rRange
)
462 Reference
< XFormulaParser
> xParser
;
463 uno::Reference
< lang::XMultiServiceFactory
> xSF( GetFB()->getModelFactory(), uno::UNO_QUERY
);
468 xParser
.set( xSF
->createInstance( OUString("com.sun.star.sheet.FormulaParser") ), UNO_QUERY
);
476 OSL_TRACE("ChartExport::parseFormula, parser is valid");
477 Reference
< XPropertySet
> xParserProps( xParser
, uno::UNO_QUERY
);
478 if( xParserProps
.is() )
480 xParserProps
->setPropertyValue( OUString("FormulaConvention"), uno::makeAny(::com::sun::star::sheet::AddressConvention::OOO
) );
482 uno::Sequence
<sheet::FormulaToken
> aTokens
= xParser
->parseFormula( rRange
, CellAddress( 0, 0, 0 ) );
483 if( xParserProps
.is() )
485 xParserProps
->setPropertyValue( OUString("FormulaConvention"), uno::makeAny(::com::sun::star::sheet::AddressConvention::XL_OOX
) );
487 aResult
= xParser
->printFormula( aTokens
, CellAddress( 0, 0, 0 ) );
491 OSL_TRACE("ChartExport::parseFormula, parser is invalid");
492 //FIXME: currently just using simple converter, e.g $Sheet1.$A$1:$C$1 -> Sheet1!$A$1:$C$1
493 OUString
aRange( rRange
);
494 if( aRange
.indexOf("$") == 0 )
495 aRange
= aRange
.copy(1);
496 aRange
= aRange
.replaceAll(".$", "!$" );
500 OSL_TRACE("ChartExport::parseFormula, the originla formula is %s, the new formula is %s ", OUStringToOString( rRange
, RTL_TEXTENCODING_UTF8
).getStr(), OUStringToOString( aResult
, RTL_TEXTENCODING_UTF8
).getStr());
504 ChartExport
& ChartExport::WriteChartObj( const Reference
< XShape
>& xShape
, sal_Int32 nChartCount
)
506 OSL_TRACE("ChartExport::WriteChartObj -- writer chart object");
507 FSHelperPtr pFS
= GetFS();
509 pFS
->startElementNS( mnXmlNamespace
, XML_graphicFrame
, FSEND
);
511 pFS
->startElementNS( mnXmlNamespace
, XML_nvGraphicFramePr
, FSEND
);
513 // TODO: get the correct chart name chart id
514 OUString sName
= "Object 1";
515 Reference
< XNamed
> xNamed( xShape
, UNO_QUERY
);
517 sName
= xNamed
->getName();
519 sal_Int32 nID
= GetChartID();
521 pFS
->singleElementNS( mnXmlNamespace
, XML_cNvPr
,
523 XML_name
, USS( sName
),
526 pFS
->singleElementNS( mnXmlNamespace
, XML_cNvGraphicFramePr
,
529 if( GetDocumentType() == DOCUMENT_PPTX
)
530 pFS
->singleElementNS( mnXmlNamespace
, XML_nvPr
,
532 pFS
->endElementNS( mnXmlNamespace
, XML_nvGraphicFramePr
);
534 // visual chart properties
535 WriteShapeTransformation( xShape
, mnXmlNamespace
);
537 // writer chart object
538 pFS
->startElement( FSNS( XML_a
, XML_graphic
), FSEND
);
539 pFS
->startElement( FSNS( XML_a
, XML_graphicData
),
540 XML_uri
, "http://schemas.openxmlformats.org/drawingml/2006/chart",
543 const char* sFullPath
= NULL
;
544 const char* sRelativePath
= NULL
;
545 switch( GetDocumentType() )
549 sFullPath
= "word/charts/chart";
550 sRelativePath
= "charts/chart";
555 sFullPath
= "ppt/charts/chart";
556 sRelativePath
= "../charts/chart";
561 sFullPath
= "xl/charts/chart";
562 sRelativePath
= "../charts/chart";
567 sFullPath
= "charts/chart";
568 sRelativePath
= "charts/chart";
572 OUString sFullStream
= OUStringBuffer()
573 .appendAscii(sFullPath
)
575 .appendAscii( ".xml" )
576 .makeStringAndClear();
577 OUString sRelativeStream
= OUStringBuffer()
578 .appendAscii(sRelativePath
)
580 .appendAscii( ".xml" )
581 .makeStringAndClear();
582 FSHelperPtr pChart
= CreateOutputStream(
585 pFS
->getOutputStream(),
586 "application/vnd.openxmlformats-officedocument.drawingml.chart+xml",
587 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart",
590 pFS
->singleElement( FSNS( XML_c
, XML_chart
),
591 FSNS( XML_xmlns
, XML_c
), "http://schemas.openxmlformats.org/drawingml/2006/chart",
592 FSNS( XML_xmlns
, XML_r
), "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
593 FSNS( XML_r
, XML_id
), USS( sId
),
596 pFS
->endElement( FSNS( XML_a
, XML_graphicData
) );
597 pFS
->endElement( FSNS( XML_a
, XML_graphic
) );
598 pFS
->endElementNS( mnXmlNamespace
, XML_graphicFrame
);
606 void ChartExport::InitRangeSegmentationProperties( const Reference
< chart2::XChartDocument
> & xChartDoc
)
611 Reference
< chart2::data::XDataProvider
> xDataProvider( xChartDoc
->getDataProvider() );
612 OSL_ENSURE( xDataProvider
.is(), "No DataProvider" );
613 if( xDataProvider
.is())
615 Reference
< chart2::data::XDataSource
> xDataSource( lcl_pressUsedDataIntoRectangularFormat( xChartDoc
, mbHasCategoryLabels
));
616 Sequence
< beans::PropertyValue
> aArgs( xDataProvider
->detectArguments( xDataSource
));
617 OUString sCellRange
, sBrokenRange
;
618 bool bBrokenRangeAvailable
= false;
619 for( sal_Int32 i
=0; i
<aArgs
.getLength(); ++i
)
621 if ( aArgs
[i
].Name
== "CellRangeRepresentation" )
622 aArgs
[i
].Value
>>= sCellRange
;
623 else if ( aArgs
[i
].Name
== "BrokenCellRangeForExport" )
625 if( aArgs
[i
].Value
>>= sBrokenRange
)
626 bBrokenRangeAvailable
= true;
628 else if ( aArgs
[i
].Name
== "SequenceMapping" )
629 aArgs
[i
].Value
>>= maSequenceMapping
;
632 // #i79009# For Writer we have to export a broken version of the
633 // range, where every row number is noe too large, so that older
634 // version can correctly read those files.
635 msChartAddress
= (bBrokenRangeAvailable
? sBrokenRange
: sCellRange
);
636 if( !msChartAddress
.isEmpty() )
638 // convert format to XML-conform one
639 Reference
< chart2::data::XRangeXMLConversion
> xConversion( xDataProvider
, uno::UNO_QUERY
);
640 if( xConversion
.is())
641 msChartAddress
= xConversion
->convertRangeToXML( msChartAddress
);
645 catch( const uno::Exception
& ex
)
647 (void)ex
; // avoid warning for pro build
648 OSL_FAIL( OUStringToOString(
649 OUString( "Exception caught. Type: " ) +
650 OUString::createFromAscii( typeid( ex
).name()) +
651 OUString( ", Message: " ) +
652 ex
.Message
, RTL_TEXTENCODING_ASCII_US
).getStr());
656 void ChartExport::ExportContent()
658 Reference
< chart2::XChartDocument
> xChartDoc( getModel(), uno::UNO_QUERY
);
659 OSL_ASSERT( xChartDoc
.is() );
660 if( !xChartDoc
.is() )
662 InitRangeSegmentationProperties( xChartDoc
);
663 // TODO: export chart
667 void ChartExport::_ExportContent()
669 Reference
< ::com::sun::star::chart::XChartDocument
> xChartDoc( getModel(), uno::UNO_QUERY
);
672 // determine if data comes from the outside
673 sal_Bool bIncludeTable
= sal_True
;
675 Reference
< chart2::XChartDocument
> xNewDoc( xChartDoc
, uno::UNO_QUERY
);
678 // check if we have own data. If so we must not export the complete
679 // range string, as this is our only indicator for having own or
680 // external data. @todo: fix this in the file format!
681 Reference
< lang::XServiceInfo
> xDPServiceInfo( xNewDoc
->getDataProvider(), uno::UNO_QUERY
);
682 if( ! (xDPServiceInfo
.is() && xDPServiceInfo
->getImplementationName() == "com.sun.star.comp.chart.InternalDataProvider" ))
684 bIncludeTable
= sal_False
;
689 Reference
< lang::XServiceInfo
> xServ( xChartDoc
, uno::UNO_QUERY
);
692 if( xServ
->supportsService(
693 OUString("com.sun.star.chart.ChartTableAddressSupplier")))
695 Reference
< beans::XPropertySet
> xProp( xServ
, uno::UNO_QUERY
);
701 OUString sChartAddress
;
702 aAny
= xProp
->getPropertyValue(
703 OUString("ChartRangeAddress"));
704 aAny
>>= msChartAddress
;
705 //maExportHelper.SetChartRangeAddress( sChartAddress );
707 //maExportHelper.SetTableNumberList( sTableNumberList );
709 // do not include own table if there are external addresses
710 bIncludeTable
= sChartAddress
.isEmpty();
712 catch( beans::UnknownPropertyException
& )
714 OSL_FAIL( "Property ChartRangeAddress not supported by ChartDocument" );
720 exportChartSpace( xChartDoc
, bIncludeTable
);
724 OSL_FAIL( "Couldn't export chart due to wrong XModel" );
728 void ChartExport::exportChartSpace( Reference
< ::com::sun::star::chart::XChartDocument
> rChartDoc
,
729 sal_Bool bIncludeTable
)
731 FSHelperPtr pFS
= GetFS();
732 pFS
->startElement( FSNS( XML_c
, XML_chartSpace
),
733 FSNS( XML_xmlns
, XML_c
), "http://schemas.openxmlformats.org/drawingml/2006/chart",
734 FSNS( XML_xmlns
, XML_a
), "http://schemas.openxmlformats.org/drawingml/2006/main",
735 FSNS( XML_xmlns
, XML_r
), "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
737 // TODO: get the correct editing lanauge
738 pFS
->singleElement( FSNS( XML_c
, XML_lang
),
744 // TODO:external data
747 exportChart(rChartDoc
);
749 // TODO: printSettings
751 // TODO: text properties
752 // TODO: shape properties
753 Reference
< XPropertySet
> xPropSet( rChartDoc
->getArea(), uno::UNO_QUERY
);
755 exportShapeProps( xPropSet
);
756 pFS
->endElement( FSNS( XML_c
, XML_chartSpace
) );
759 void ChartExport::exportChart( Reference
< ::com::sun::star::chart::XChartDocument
> rChartDoc
)
761 Reference
< chart2::XChartDocument
> xNewDoc( rChartDoc
, uno::UNO_QUERY
);
762 mxDiagram
.set( rChartDoc
->getDiagram() );
764 mxNewDiagram
.set( xNewDoc
->getFirstDiagram());
766 // get Properties of ChartDocument
767 sal_Bool bHasMainTitle
= sal_False
;
768 sal_Bool bHasSubTitle
= sal_False
;
769 sal_Bool bHasLegend
= sal_False
;
770 Reference
< beans::XPropertySet
> xDocPropSet( rChartDoc
, uno::UNO_QUERY
);
771 if( xDocPropSet
.is())
775 Any
aAny( xDocPropSet
->getPropertyValue(
776 OUString( "HasMainTitle" )));
777 aAny
>>= bHasMainTitle
;
778 aAny
= xDocPropSet
->getPropertyValue(
779 OUString( "HasSubTitle" ));
780 aAny
>>= bHasSubTitle
;
781 aAny
= xDocPropSet
->getPropertyValue(
782 OUString( "HasLegend" ));
785 catch( beans::UnknownPropertyException
& )
787 DBG_WARNING( "Required property not found in ChartDocument" );
789 } // if( xDocPropSet.is())
793 FSHelperPtr pFS
= GetFS();
794 pFS
->startElement( FSNS( XML_c
, XML_chart
),
800 Reference
< drawing::XShape
> xShape
= rChartDoc
->getTitle();
802 exportTitle( xShape
);
810 Reference
< beans::XPropertySet
> xFloor( mxNewDiagram
->getFloor(), uno::UNO_QUERY
);
813 pFS
->startElement( FSNS( XML_c
, XML_floor
),
815 exportShapeProps( xFloor
);
816 pFS
->endElement( FSNS( XML_c
, XML_floor
) );
822 Reference
< beans::XPropertySet
> xBackWall( mxNewDiagram
->getWall(), uno::UNO_QUERY
);
825 pFS
->startElement( FSNS( XML_c
, XML_backWall
),
827 exportShapeProps( xBackWall
);
828 pFS
->endElement( FSNS( XML_c
, XML_backWall
) );
836 exportLegend( rChartDoc
);
837 // only visible cells should be plotted on the chart
838 pFS
->singleElement( FSNS( XML_c
, XML_plotVisOnly
),
842 pFS
->endElement( FSNS( XML_c
, XML_chart
) );
845 void ChartExport::exportLegend( Reference
< ::com::sun::star::chart::XChartDocument
> rChartDoc
)
847 FSHelperPtr pFS
= GetFS();
848 pFS
->startElement( FSNS( XML_c
, XML_legend
),
851 Reference
< beans::XPropertySet
> xProp( rChartDoc
->getLegend(), uno::UNO_QUERY
);
855 ::com::sun::star::chart::ChartLegendPosition aLegendPos
= ::com::sun::star::chart::ChartLegendPosition_NONE
;
858 Any
aAny( xProp
->getPropertyValue(
859 OUString( "Alignment" )));
862 catch( beans::UnknownPropertyException
& )
864 DBG_WARNING( "Property Align not found in ChartLegend" );
867 const char* strPos
= NULL
;
870 case ::com::sun::star::chart::ChartLegendPosition_LEFT
:
873 case ::com::sun::star::chart::ChartLegendPosition_RIGHT
:
876 case ::com::sun::star::chart::ChartLegendPosition_TOP
:
879 case ::com::sun::star::chart::ChartLegendPosition_BOTTOM
:
882 case ::com::sun::star::chart::ChartLegendPosition_NONE
:
883 case ::com::sun::star::chart::ChartLegendPosition_MAKE_FIXED_SIZE
:
890 pFS
->singleElement( FSNS( XML_c
, XML_legendPos
),
893 pFS
->singleElement( FSNS( XML_c
, XML_overlay
),
899 exportShapeProps( xProp
);
904 pFS
->endElement( FSNS( XML_c
, XML_legend
) );
907 void ChartExport::exportTitle( Reference
< XShape
> xShape
)
910 Reference
< beans::XPropertySet
> xPropSet( xShape
, uno::UNO_QUERY
);
913 xPropSet
->getPropertyValue( OUString( "String" )) >>= sText
;
915 if( sText
.isEmpty() )
918 FSHelperPtr pFS
= GetFS();
919 pFS
->startElement( FSNS( XML_c
, XML_title
),
922 pFS
->startElement( FSNS( XML_c
, XML_tx
),
924 pFS
->startElement( FSNS( XML_c
, XML_rich
),
928 const char* sWritingMode
= NULL
;
929 sal_Bool bVertical
= sal_False
;
930 xPropSet
->getPropertyValue( OUString( "StackedText" )) >>= bVertical
;
932 sWritingMode
= "wordArtVert";
934 pFS
->singleElement( FSNS( XML_a
, XML_bodyPr
),
935 XML_vert
, sWritingMode
,
938 pFS
->singleElement( FSNS( XML_a
, XML_lstStyle
),
940 // FIXME: handle multipul paragraphs to parse aText
941 pFS
->startElement( FSNS( XML_a
, XML_p
),
944 pFS
->startElement( FSNS( XML_a
, XML_pPr
),
946 pFS
->singleElement( FSNS( XML_a
, XML_defRPr
),
948 pFS
->endElement( FSNS( XML_a
, XML_pPr
) );
950 pFS
->startElement( FSNS( XML_a
, XML_r
),
952 WriteRunProperties( xPropSet
, sal_False
);
953 pFS
->startElement( FSNS( XML_a
, XML_t
),
955 pFS
->writeEscaped( sText
);
956 pFS
->endElement( FSNS( XML_a
, XML_t
) );
957 pFS
->endElement( FSNS( XML_a
, XML_r
) );
959 pFS
->endElement( FSNS( XML_a
, XML_p
) );
961 pFS
->endElement( FSNS( XML_c
, XML_rich
) );
962 pFS
->endElement( FSNS( XML_c
, XML_tx
) );
964 // TODO:customize layout
965 pFS
->singleElement( FSNS( XML_c
, XML_layout
),
968 pFS
->endElement( FSNS( XML_c
, XML_title
) );
971 void ChartExport::exportPlotArea( )
973 Reference
< chart2::XCoordinateSystemContainer
> xBCooSysCnt( mxNewDiagram
, uno::UNO_QUERY
);
974 if( ! xBCooSysCnt
.is())
979 FSHelperPtr pFS
= GetFS();
980 pFS
->startElement( FSNS( XML_c
, XML_plotArea
),
983 pFS
->singleElement( FSNS( XML_c
, XML_layout
),
987 Sequence
< Reference
< chart2::XCoordinateSystem
> >
988 aCooSysSeq( xBCooSysCnt
->getCoordinateSystems());
989 for( sal_Int32 nCSIdx
=0; nCSIdx
<aCooSysSeq
.getLength(); ++nCSIdx
)
991 Reference
< chart2::XChartTypeContainer
> xCTCnt( aCooSysSeq
[nCSIdx
], uno::UNO_QUERY
);
994 Sequence
< Reference
< chart2::XChartType
> > aCTSeq( xCTCnt
->getChartTypes());
995 for( sal_Int32 nCTIdx
=0; nCTIdx
<aCTSeq
.getLength(); ++nCTIdx
)
997 Reference
< chart2::XDataSeriesContainer
> xDSCnt( aCTSeq
[nCTIdx
], uno::UNO_QUERY
);
1000 Reference
< chart2::XChartType
> xChartType( aCTSeq
[nCTIdx
], uno::UNO_QUERY
);
1001 if( ! xChartType
.is())
1003 // note: if xDSCnt.is() then also aCTSeq[nCTIdx]
1004 OUString
aChartType( xChartType
->getChartType());
1005 sal_Int32 eChartType
= lcl_getChartType( aChartType
);
1006 switch( eChartType
)
1008 case chart::TYPEID_BAR
:
1010 exportBarChart( xChartType
);
1013 case chart::TYPEID_AREA
:
1015 exportAreaChart( xChartType
);
1018 case chart::TYPEID_LINE
:
1020 exportLineChart( xChartType
);
1023 case chart::TYPEID_BUBBLE
:
1025 exportBubbleChart( xChartType
);
1028 case chart::TYPEID_DOUGHNUT
:
1030 exportDoughnutChart( xChartType
);
1033 case chart::TYPEID_OFPIE
:
1035 exportOfPieChart( xChartType
);
1038 case chart::TYPEID_PIE
:
1040 exportPieChart( xChartType
);
1043 case chart::TYPEID_RADARLINE
:
1044 case chart::TYPEID_RADARAREA
:
1046 exportRadarChart( xChartType
);
1049 case chart::TYPEID_SCATTER
:
1051 exportScatterChart( xChartType
);
1054 case chart::TYPEID_STOCK
:
1056 exportStockChart( xChartType
);
1059 case chart::TYPEID_SURFACE
:
1061 exportSuffaceChart( xChartType
);
1066 OSL_TRACE("ChartExport::exportPlotArea -- not support chart type");
1077 Reference
< ::com::sun::star::chart::X3DDisplay
> xWallFloorSupplier( mxDiagram
, uno::UNO_QUERY
);
1078 if( xWallFloorSupplier
.is() )
1080 Reference
< beans::XPropertySet
> xWallPropSet( xWallFloorSupplier
->getWall(), uno::UNO_QUERY
);
1081 if( xWallPropSet
.is() )
1083 exportShapeProps( xWallPropSet
);
1087 pFS
->endElement( FSNS( XML_c
, XML_plotArea
) );
1091 void ChartExport::exportAreaChart( Reference
< chart2::XChartType
> xChartType
)
1093 FSHelperPtr pFS
= GetFS();
1094 sal_Int32 nTypeId
= XML_areaChart
;
1096 nTypeId
= XML_area3DChart
;
1097 pFS
->startElement( FSNS( XML_c
, nTypeId
),
1101 sal_Int32 nAttachedAxis
= AXIS_PRIMARY_Y
;
1102 exportSeries( xChartType
, nAttachedAxis
);
1103 exportAxesId( nAttachedAxis
);
1105 pFS
->endElement( FSNS( XML_c
, nTypeId
) );
1108 void ChartExport::exportBarChart( Reference
< chart2::XChartType
> xChartType
)
1110 sal_Int32 nTypeId
= XML_barChart
;
1112 nTypeId
= XML_bar3DChart
;
1113 FSHelperPtr pFS
= GetFS();
1114 pFS
->startElement( FSNS( XML_c
, nTypeId
),
1117 sal_Bool bVertical
= sal_False
;
1118 Reference
< XPropertySet
> xPropSet( mxDiagram
, uno::UNO_QUERY
);
1119 if( GetProperty( xPropSet
, "Vertical" ) )
1122 const char* bardir
= bVertical
? "bar":"col";
1123 pFS
->singleElement( FSNS( XML_c
, XML_barDir
),
1127 exportGrouping( sal_True
);
1128 sal_Int32 nAttachedAxis
= AXIS_PRIMARY_Y
;
1129 exportSeries( xChartType
, nAttachedAxis
);
1131 Reference
< XPropertySet
> xTypeProp( xChartType
, uno::UNO_QUERY
);
1133 if( xTypeProp
.is() && GetProperty( xTypeProp
, "GapwidthSequence") )
1135 uno::Sequence
< sal_Int32
> aBarPositionSequence
;
1136 mAny
>>= aBarPositionSequence
;
1137 if( aBarPositionSequence
.getLength() )
1139 sal_Int32 nGapWidth
= aBarPositionSequence
[0];
1140 pFS
->singleElement( FSNS( XML_c
, XML_gapWidth
),
1141 XML_val
, I32S( nGapWidth
),
1149 namespace cssc
= ::com::sun::star::chart
;
1150 sal_Int32 nGeom3d
= cssc::ChartSolidType::RECTANGULAR_SOLID
;
1151 if( xPropSet
.is() && GetProperty( xPropSet
, "SolidType") )
1153 const char* sShapeType
= NULL
;
1156 case cssc::ChartSolidType::RECTANGULAR_SOLID
:
1159 case cssc::ChartSolidType::CONE
:
1160 sShapeType
= "cone";
1162 case cssc::ChartSolidType::CYLINDER
:
1163 sShapeType
= "cylinder";
1165 case cssc::ChartSolidType::PYRAMID
:
1166 sShapeType
= "pyramid";
1169 pFS
->singleElement( FSNS( XML_c
, XML_shape
),
1170 XML_val
, sShapeType
,
1175 if( !mbIs3DChart
&& xTypeProp
.is() && GetProperty( xTypeProp
, "OverlapSequence") )
1177 uno::Sequence
< sal_Int32
> aBarPositionSequence
;
1178 mAny
>>= aBarPositionSequence
;
1179 if( aBarPositionSequence
.getLength() )
1181 sal_Int32 nOverlap
= aBarPositionSequence
[0];
1183 pFS
->singleElement( FSNS( XML_c
, XML_overlap
),
1184 XML_val
, I32S( nOverlap
),
1189 exportAxesId( nAttachedAxis
);
1191 pFS
->endElement( FSNS( XML_c
, nTypeId
) );
1194 void ChartExport::exportBubbleChart( Reference
< chart2::XChartType
> xChartType
)
1196 FSHelperPtr pFS
= GetFS();
1197 pFS
->startElement( FSNS( XML_c
, XML_bubbleChart
),
1200 sal_Int32 nAttachedAxis
= AXIS_PRIMARY_Y
;
1201 exportSeries( xChartType
, nAttachedAxis
);
1202 exportAxesId( nAttachedAxis
);
1204 pFS
->endElement( FSNS( XML_c
, XML_bubbleChart
) );
1207 void ChartExport::exportDoughnutChart( Reference
< chart2::XChartType
> xChartType
)
1209 FSHelperPtr pFS
= GetFS();
1210 pFS
->startElement( FSNS( XML_c
, XML_doughnutChart
),
1213 sal_Int32 nAttachedAxis
= AXIS_PRIMARY_Y
;
1214 exportSeries( xChartType
, nAttachedAxis
);
1216 exportFirstSliceAng( );
1218 sal_Int32 nHoleSize
= 50;
1219 pFS
->singleElement( FSNS( XML_c
, XML_holeSize
),
1220 XML_val
, I32S( nHoleSize
),
1223 exportAxesId( nAttachedAxis
);
1225 pFS
->endElement( FSNS( XML_c
, XML_doughnutChart
) );
1228 void ChartExport::exportLineChart( Reference
< chart2::XChartType
> xChartType
)
1230 FSHelperPtr pFS
= GetFS();
1231 sal_Int32 nTypeId
= XML_lineChart
;
1233 nTypeId
= XML_line3DChart
;
1234 pFS
->startElement( FSNS( XML_c
, nTypeId
),
1238 // TODO: show marker symbol in series?
1239 sal_Int32 nAttachedAxis
= AXIS_PRIMARY_Y
;
1240 exportSeries( xChartType
, nAttachedAxis
);
1243 sal_Int32 nSymbolType
= ::com::sun::star::chart::ChartSymbolType::NONE
;
1244 Reference
< XPropertySet
> xPropSet( mxDiagram
, uno::UNO_QUERY
);
1245 if( GetProperty( xPropSet
, "SymbolType" ) )
1246 mAny
>>= nSymbolType
;
1248 const char* marker
= nSymbolType
== ::com::sun::star::chart::ChartSymbolType::NONE
? "0":"1";
1249 pFS
->singleElement( FSNS( XML_c
, XML_marker
),
1253 exportAxesId( nAttachedAxis
);
1255 pFS
->endElement( FSNS( XML_c
, nTypeId
) );
1258 void ChartExport::exportOfPieChart( Reference
< chart2::XChartType
> /*xChartType*/ )
1263 void ChartExport::exportPieChart( Reference
< chart2::XChartType
> xChartType
)
1265 FSHelperPtr pFS
= GetFS();
1266 sal_Int32 nTypeId
= XML_pieChart
;
1268 nTypeId
= XML_pie3DChart
;
1269 pFS
->startElement( FSNS( XML_c
, nTypeId
),
1272 const char* varyColors
= "1";
1273 pFS
->singleElement( FSNS( XML_c
, XML_varyColors
),
1274 XML_val
, varyColors
,
1277 sal_Int32 nAttachedAxis
= AXIS_PRIMARY_Y
;
1278 exportSeries( xChartType
, nAttachedAxis
);
1283 exportFirstSliceAng( );
1286 pFS
->endElement( FSNS( XML_c
, nTypeId
) );
1289 void ChartExport::exportRadarChart( Reference
< chart2::XChartType
> xChartType
)
1291 FSHelperPtr pFS
= GetFS();
1292 pFS
->startElement( FSNS( XML_c
, XML_radarChart
),
1296 sal_Int32 eChartType
= getChartType( );
1297 const char* radarStyle
= NULL
;
1298 if( eChartType
== chart::TYPEID_RADARAREA
)
1299 radarStyle
= "filled";
1301 radarStyle
= "marker";
1302 pFS
->singleElement( FSNS( XML_c
, XML_radarStyle
),
1303 XML_val
, radarStyle
,
1305 sal_Int32 nAttachedAxis
= AXIS_PRIMARY_Y
;
1306 exportSeries( xChartType
, nAttachedAxis
);
1307 exportAxesId( nAttachedAxis
);
1309 pFS
->endElement( FSNS( XML_c
, XML_radarChart
) );
1312 void ChartExport::exportScatterChart( Reference
< chart2::XChartType
> xChartType
)
1314 FSHelperPtr pFS
= GetFS();
1315 pFS
->startElement( FSNS( XML_c
, XML_scatterChart
),
1317 // TODO:scatterStyle
1318 const char* scatterStyle
= "lineMarker";
1319 pFS
->singleElement( FSNS( XML_c
, XML_scatterStyle
),
1320 XML_val
, scatterStyle
,
1323 pFS
->singleElement( FSNS( XML_c
, XML_varyColors
),
1327 // FIXME: should export xVal and yVal
1328 sal_Int32 nAttachedAxis
= AXIS_PRIMARY_Y
;
1329 exportSeries( xChartType
, nAttachedAxis
);
1330 exportAxesId( nAttachedAxis
);
1332 pFS
->endElement( FSNS( XML_c
, XML_scatterChart
) );
1335 void ChartExport::exportStockChart( Reference
< chart2::XChartType
> xChartType
)
1337 FSHelperPtr pFS
= GetFS();
1338 pFS
->startElement( FSNS( XML_c
, XML_stockChart
),
1341 sal_Int32 nAttachedAxis
= AXIS_PRIMARY_Y
;
1342 exportSeries( xChartType
, nAttachedAxis
);
1343 // export stock properties
1344 Reference
< ::com::sun::star::chart::XStatisticDisplay
> xStockPropProvider( mxDiagram
, uno::UNO_QUERY
);
1345 if( xStockPropProvider
.is())
1348 Reference
< beans::XPropertySet
> xStockPropSet
= xStockPropProvider
->getMinMaxLine();
1349 if( xStockPropSet
.is() )
1351 pFS
->startElement( FSNS( XML_c
, XML_hiLowLines
),
1353 exportShapeProps( xStockPropSet
);
1354 pFS
->endElement( FSNS( XML_c
, XML_hiLowLines
) );
1357 pFS
->startElement( FSNS( XML_c
, XML_upDownBars
),
1360 sal_Int32 nGapWidth
= 150;
1361 pFS
->singleElement( FSNS( XML_c
, XML_gapWidth
),
1362 XML_val
, I32S( nGapWidth
),
1365 xStockPropSet
= xStockPropProvider
->getUpBar();
1366 if( xStockPropSet
.is() )
1368 pFS
->startElement( FSNS( XML_c
, XML_upBars
),
1370 exportShapeProps( xStockPropSet
);
1371 pFS
->endElement( FSNS( XML_c
, XML_upBars
) );
1374 xStockPropSet
= xStockPropProvider
->getDownBar();
1375 if( xStockPropSet
.is() )
1377 pFS
->startElement( FSNS( XML_c
, XML_downBars
),
1379 exportShapeProps( xStockPropSet
);
1380 pFS
->endElement( FSNS( XML_c
, XML_downBars
) );
1382 pFS
->endElement( FSNS( XML_c
, XML_upDownBars
) );
1385 exportAxesId( nAttachedAxis
);
1387 pFS
->endElement( FSNS( XML_c
, XML_stockChart
) );
1390 void ChartExport::exportSuffaceChart( Reference
< chart2::XChartType
> xChartType
)
1392 FSHelperPtr pFS
= GetFS();
1393 sal_Int32 nTypeId
= XML_surfaceChart
;
1395 nTypeId
= XML_surface3DChart
;
1396 pFS
->startElement( FSNS( XML_c
, nTypeId
),
1398 sal_Int32 nAttachedAxis
= AXIS_PRIMARY_Y
;
1399 exportSeries( xChartType
, nAttachedAxis
);
1400 exportAxesId( nAttachedAxis
);
1402 pFS
->endElement( FSNS( XML_c
, nTypeId
) );
1405 void ChartExport::exportSeries( Reference
< chart2::XChartType
> xChartType
, sal_Int32
& nAttachedAxis
)
1408 OUString aLabelRole
= xChartType
->getRoleOfSequenceForSeriesLabel();
1409 Reference
< chart2::XDataSeriesContainer
> xDSCnt( xChartType
, uno::UNO_QUERY
);
1413 OUString
aChartType( xChartType
->getChartType());
1414 sal_Int32 eChartType
= lcl_getChartType( aChartType
);
1416 // special export for stock charts
1417 if( eChartType
== chart::TYPEID_STOCK
)
1419 sal_Bool bJapaneseCandleSticks
= sal_False
;
1420 Reference
< beans::XPropertySet
> xCTProp( xChartType
, uno::UNO_QUERY
);
1422 xCTProp
->getPropertyValue( OUString("Japanese")) >>= bJapaneseCandleSticks
;
1423 exportCandleStickSeries(
1424 xDSCnt
->getDataSeries(), bJapaneseCandleSticks
, nAttachedAxis
);
1429 // export dataseries for current chart-type
1430 Sequence
< Reference
< chart2::XDataSeries
> > aSeriesSeq( xDSCnt
->getDataSeries());
1431 for( sal_Int32 nSeriesIdx
=0; nSeriesIdx
<aSeriesSeq
.getLength(); ++nSeriesIdx
)
1434 Reference
< chart2::data::XDataSource
> xSource( aSeriesSeq
[nSeriesIdx
], uno::UNO_QUERY
);
1437 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > aSeqCnt(
1438 xSource
->getDataSequences());
1439 // search for main sequence and create a series element
1441 sal_Int32 nMainSequenceIndex
= -1;
1442 sal_Int32 nSeriesLength
= 0;
1443 Reference
< chart2::data::XDataSequence
> xValuesSeq
;
1444 Reference
< chart2::data::XDataSequence
> xLabelSeq
;
1445 sal_Int32 nSeqIdx
=0;
1446 for( ; nSeqIdx
<aSeqCnt
.getLength(); ++nSeqIdx
)
1449 Reference
< chart2::data::XDataSequence
> xTempValueSeq( aSeqCnt
[nSeqIdx
]->getValues() );
1450 if( nMainSequenceIndex
==-1 )
1452 Reference
< beans::XPropertySet
> xSeqProp( xTempValueSeq
, uno::UNO_QUERY
);
1454 xSeqProp
->getPropertyValue(OUString("Role")) >>= aRole
;
1456 if( aRole
.equals( aLabelRole
))
1458 xValuesSeq
.set( xTempValueSeq
);
1459 xLabelSeq
.set( aSeqCnt
[nSeqIdx
]->getLabel());
1460 nMainSequenceIndex
= nSeqIdx
;
1463 sal_Int32 nSequenceLength
= (xTempValueSeq
.is()? xTempValueSeq
->getData().getLength() : sal_Int32(0));
1464 if( nSeriesLength
< nSequenceLength
)
1465 nSeriesLength
= nSequenceLength
;
1468 // have found the main sequence, then xValuesSeq and
1469 // xLabelSeq contain those. Otherwise both are empty
1471 FSHelperPtr pFS
= GetFS();
1472 pFS
->startElement( FSNS( XML_c
, XML_ser
),
1475 // TODO: idx and order
1476 pFS
->singleElement( FSNS( XML_c
, XML_idx
),
1477 XML_val
, I32S(nSeriesIdx
),
1479 pFS
->singleElement( FSNS( XML_c
, XML_order
),
1480 XML_val
, I32S(nSeriesIdx
),
1484 if( xLabelSeq
.is() )
1485 exportSeriesText( xLabelSeq
);
1487 // export shape properties
1488 Reference
< XPropertySet
> xPropSet
= SchXMLSeriesHelper::createOldAPISeriesPropertySet(
1489 aSeriesSeq
[nSeriesIdx
], getModel() );
1492 if( GetProperty( xPropSet
, "Axis") )
1494 mAny
>>= nAttachedAxis
;
1495 if( nAttachedAxis
== ::com::sun::star::chart::ChartAxisAssign::SECONDARY_Y
)
1496 nAttachedAxis
= AXIS_SECONDARY_Y
;
1498 nAttachedAxis
= AXIS_PRIMARY_Y
;
1500 exportShapeProps( xPropSet
);
1503 switch( eChartType
)
1505 case chart::TYPEID_LINE
:
1510 case chart::TYPEID_PIE
:
1511 case chart::TYPEID_DOUGHNUT
:
1513 if( xPropSet
.is() && GetProperty( xPropSet
, "SegmentOffset") )
1515 sal_Int32 nOffset
= 0;
1517 pFS
->singleElement( FSNS( XML_c
, XML_explosion
),
1518 XML_val
, I32S( nOffset
),
1523 case chart::TYPEID_SCATTER
:
1529 case chart::TYPEID_RADARLINE
:
1536 // export data points
1537 exportDataPoints( uno::Reference
< beans::XPropertySet
>( aSeriesSeq
[nSeriesIdx
], uno::UNO_QUERY
), nSeriesLength
);
1539 // export data labels
1540 // Excel does not like our current data label export
1541 // for scatter charts
1542 if( eChartType
!= chart::TYPEID_SCATTER
&& eChartType
!= chart::TYPEID_BAR
)
1543 exportDataLabels( uno::Reference
< beans::XPropertySet
>( aSeriesSeq
[nSeriesIdx
], uno::UNO_QUERY
), nSeriesLength
);
1545 //export error bars here
1546 Reference
< XPropertySet
> xSeriesPropSet( xSource
, uno::UNO_QUERY
);
1547 Reference
< XPropertySet
> xErrorBarYProps
;
1548 xSeriesPropSet
->getPropertyValue("ErrorBarY") >>= xErrorBarYProps
;
1549 if(xErrorBarYProps
.is())
1550 exportErrorBar(xErrorBarYProps
, true);
1551 Reference
< XPropertySet
> xErrorBarXProps
;
1552 xSeriesPropSet
->getPropertyValue("ErrorBarX") >>= xErrorBarXProps
;
1553 if(xErrorBarXProps
.is())
1554 exportErrorBar(xErrorBarXProps
, false);
1556 // export categories
1557 if( mxCategoriesValues
.is() )
1558 exportSeriesCategory( mxCategoriesValues
);
1560 if( (eChartType
== chart::TYPEID_SCATTER
)
1561 || (eChartType
== chart::TYPEID_BUBBLE
) )
1564 Reference
< chart2::data::XLabeledDataSequence
> xSequence( lcl_getDataSequenceByRole( aSeqCnt
, OUString("values-x") ) );
1565 if( xSequence
.is() )
1567 Reference
< chart2::data::XDataSequence
> xValues( xSequence
->getValues() );
1569 exportSeriesValues( xValues
, XML_xVal
);
1574 if( eChartType
== chart::TYPEID_BUBBLE
)
1577 Reference
< chart2::data::XLabeledDataSequence
> xSequence( lcl_getDataSequenceByRole( aSeqCnt
, OUString("values-y") ) );
1578 if( xSequence
.is() )
1580 Reference
< chart2::data::XDataSequence
> xValues( xSequence
->getValues() );
1582 exportSeriesValues( xValues
, XML_yVal
);
1587 if( xValuesSeq
.is() )
1589 sal_Int32 nYValueType
= XML_val
;
1590 if( eChartType
== chart::TYPEID_SCATTER
)
1591 nYValueType
= XML_yVal
;
1592 else if( eChartType
== chart::TYPEID_BUBBLE
)
1593 nYValueType
= XML_bubbleSize
;
1594 exportSeriesValues( xValuesSeq
, nYValueType
);
1597 pFS
->endElement( FSNS( XML_c
, XML_ser
) );
1604 void ChartExport::exportCandleStickSeries(
1605 const Sequence
< Reference
< chart2::XDataSeries
> > & aSeriesSeq
,
1606 sal_Bool
/*bJapaneseCandleSticks*/,
1607 sal_Int32
& nAttachedAxis
)
1609 for( sal_Int32 nSeriesIdx
=0; nSeriesIdx
<aSeriesSeq
.getLength(); ++nSeriesIdx
)
1611 Reference
< chart2::XDataSeries
> xSeries( aSeriesSeq
[nSeriesIdx
] );
1612 nAttachedAxis
= lcl_isSeriesAttachedToFirstAxis( xSeries
) ? AXIS_PRIMARY_Y
: AXIS_SECONDARY_Y
;
1614 Reference
< chart2::data::XDataSource
> xSource( xSeries
, uno::UNO_QUERY
);
1617 // export series in correct order (as we don't store roles)
1618 // with japanese candlesticks: open, low, high, close
1619 // otherwise: low, high, close
1620 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > aSeqCnt(
1621 xSource
->getDataSequences());
1623 Reference
< chart2::XChartDocument
> xNewDoc( getModel(), uno::UNO_QUERY
);
1624 const char* sSeries
[] = {"values-first","values-max","values-min","values-last",0};
1625 for( sal_Int32 idx
= 0; sSeries
[idx
] != 0 ; idx
++ )
1627 Reference
< chart2::data::XLabeledDataSequence
> xLabeledSeq( lcl_getDataSequenceByRole( aSeqCnt
, OUString::createFromAscii(sSeries
[idx
]) ) );
1628 if( xLabeledSeq
.is())
1630 Reference
< chart2::data::XDataSequence
> xLabelSeq( xLabeledSeq
->getLabel());
1631 Reference
< chart2::data::XDataSequence
> xValueSeq( xLabeledSeq
->getValues());
1633 FSHelperPtr pFS
= GetFS();
1634 pFS
->startElement( FSNS( XML_c
, XML_ser
),
1637 // TODO: idx and order
1638 pFS
->singleElement( FSNS( XML_c
, XML_idx
),
1641 pFS
->singleElement( FSNS( XML_c
, XML_order
),
1646 if( xLabelSeq
.is() )
1647 exportSeriesText( xLabelSeq
);
1649 // TODO:export shape properties
1651 // export categories
1652 if( mxCategoriesValues
.is() )
1653 exportSeriesCategory( mxCategoriesValues
);
1656 if( xValueSeq
.is() )
1657 exportSeriesValues( xValueSeq
);
1659 pFS
->endElement( FSNS( XML_c
, XML_ser
) );
1669 void ChartExport::exportSeriesText( const Reference
< chart2::data::XDataSequence
> & xValueSeq
)
1671 FSHelperPtr pFS
= GetFS();
1672 Reference
< chart2::XChartDocument
> xNewDoc( getModel(), uno::UNO_QUERY
);
1673 pFS
->startElement( FSNS( XML_c
, XML_tx
),
1676 OUString aCellRange
= xValueSeq
->getSourceRangeRepresentation();
1677 aCellRange
= parseFormula( aCellRange
);
1678 pFS
->startElement( FSNS( XML_c
, XML_strRef
),
1681 pFS
->startElement( FSNS( XML_c
, XML_f
),
1683 pFS
->writeEscaped( aCellRange
);
1684 pFS
->endElement( FSNS( XML_c
, XML_f
) );
1686 OUString aLabelString
= lcl_getLabelString( xValueSeq
);
1687 pFS
->startElement( FSNS( XML_c
, XML_strCache
),
1689 pFS
->singleElement( FSNS( XML_c
, XML_ptCount
),
1692 pFS
->startElement( FSNS( XML_c
, XML_pt
),
1695 pFS
->startElement( FSNS( XML_c
, XML_v
),
1697 pFS
->writeEscaped( aLabelString
);
1698 pFS
->endElement( FSNS( XML_c
, XML_v
) );
1699 pFS
->endElement( FSNS( XML_c
, XML_pt
) );
1700 pFS
->endElement( FSNS( XML_c
, XML_strCache
) );
1701 pFS
->endElement( FSNS( XML_c
, XML_strRef
) );
1702 pFS
->endElement( FSNS( XML_c
, XML_tx
) );
1705 void ChartExport::exportSeriesCategory( const Reference
< chart2::data::XDataSequence
> & xValueSeq
)
1707 FSHelperPtr pFS
= GetFS();
1708 Reference
< chart2::XChartDocument
> xNewDoc( getModel(), uno::UNO_QUERY
);
1709 pFS
->startElement( FSNS( XML_c
, XML_cat
),
1712 OUString aCellRange
= xValueSeq
->getSourceRangeRepresentation();
1713 aCellRange
= parseFormula( aCellRange
);
1714 // TODO: need to handle XML_multiLvlStrRef according to aCellRange
1715 pFS
->startElement( FSNS( XML_c
, XML_strRef
),
1718 pFS
->startElement( FSNS( XML_c
, XML_f
),
1720 pFS
->writeEscaped( aCellRange
);
1721 pFS
->endElement( FSNS( XML_c
, XML_f
) );
1723 ::std::vector
< OUString
> aCategories
;
1724 lcl_fillCategoriesIntoStringVector( xValueSeq
, aCategories
);
1725 sal_Int32 ptCount
= aCategories
.size();
1726 pFS
->startElement( FSNS( XML_c
, XML_strCache
),
1728 pFS
->singleElement( FSNS( XML_c
, XML_ptCount
),
1729 XML_val
, I32S( ptCount
),
1731 for( sal_Int32 i
= 0; i
< ptCount
; i
++ )
1733 pFS
->startElement( FSNS( XML_c
, XML_pt
),
1736 pFS
->startElement( FSNS( XML_c
, XML_v
),
1738 pFS
->writeEscaped( aCategories
[i
] );
1739 pFS
->endElement( FSNS( XML_c
, XML_v
) );
1740 pFS
->endElement( FSNS( XML_c
, XML_pt
) );
1743 pFS
->endElement( FSNS( XML_c
, XML_strCache
) );
1744 pFS
->endElement( FSNS( XML_c
, XML_strRef
) );
1745 pFS
->endElement( FSNS( XML_c
, XML_cat
) );
1748 void ChartExport::exportSeriesValues( const Reference
< chart2::data::XDataSequence
> & xValueSeq
, sal_Int32 nValueType
)
1750 FSHelperPtr pFS
= GetFS();
1751 Reference
< chart2::XChartDocument
> xNewDoc( getModel(), uno::UNO_QUERY
);
1752 pFS
->startElement( FSNS( XML_c
, nValueType
),
1755 OUString aCellRange
= xValueSeq
->getSourceRangeRepresentation();
1756 aCellRange
= parseFormula( aCellRange
);
1757 // TODO: need to handle XML_multiLvlStrRef according to aCellRange
1758 pFS
->startElement( FSNS( XML_c
, XML_numRef
),
1761 pFS
->startElement( FSNS( XML_c
, XML_f
),
1763 pFS
->writeEscaped( aCellRange
);
1764 pFS
->endElement( FSNS( XML_c
, XML_f
) );
1766 ::std::vector
< double > aValues
;
1767 aValues
= lcl_getAllValuesFromSequence( xValueSeq
);
1768 sal_Int32 ptCount
= aValues
.size();
1769 pFS
->startElement( FSNS( XML_c
, XML_numCache
),
1771 pFS
->startElement( FSNS( XML_c
, XML_formatCode
),
1773 // TODO: what format code?
1774 pFS
->writeEscaped( "General" );
1775 pFS
->endElement( FSNS( XML_c
, XML_formatCode
) );
1776 pFS
->singleElement( FSNS( XML_c
, XML_ptCount
),
1777 XML_val
, I32S( ptCount
),
1779 for( sal_Int32 i
= 0; i
< ptCount
; i
++ )
1781 pFS
->startElement( FSNS( XML_c
, XML_pt
),
1784 pFS
->startElement( FSNS( XML_c
, XML_v
),
1786 if (aValues
[i
] == aValues
[i
])
1787 pFS
->write( aValues
[i
] );
1788 pFS
->endElement( FSNS( XML_c
, XML_v
) );
1789 pFS
->endElement( FSNS( XML_c
, XML_pt
) );
1792 pFS
->endElement( FSNS( XML_c
, XML_numCache
) );
1793 pFS
->endElement( FSNS( XML_c
, XML_numRef
) );
1794 pFS
->endElement( FSNS( XML_c
, nValueType
) );
1797 void ChartExport::exportShapeProps( Reference
< XPropertySet
> xPropSet
)
1799 FSHelperPtr pFS
= GetFS();
1800 pFS
->startElement( FSNS( XML_c
, XML_spPr
),
1803 WriteFill( xPropSet
);
1804 WriteOutline( xPropSet
);
1805 pFS
->endElement( FSNS( XML_c
, XML_spPr
) );
1808 void ChartExport::InitPlotArea( )
1810 Reference
< XPropertySet
> xDiagramProperties (mxDiagram
, uno::UNO_QUERY
);
1812 // Check for supported services and then the properties provided by this service.
1813 Reference
<lang::XServiceInfo
> xServiceInfo (mxDiagram
, uno::UNO_QUERY
);
1814 if (xServiceInfo
.is())
1816 if (xServiceInfo
->supportsService(
1817 OUString("com.sun.star.chart.ChartAxisZSupplier")))
1819 xDiagramProperties
->getPropertyValue(
1820 OUString("HasZAxis")) >>= mbHasZAxis
;
1824 xDiagramProperties
->getPropertyValue(
1825 OUString ("Dim3D")) >>= mbIs3DChart
;
1827 Reference
< chart2::XChartDocument
> xNewDoc( getModel(), uno::UNO_QUERY
);
1828 if( mbHasCategoryLabels
&& mxNewDiagram
.is())
1830 Reference
< chart2::data::XLabeledDataSequence
> xCategories( lcl_getCategories( mxNewDiagram
) );
1831 if( xCategories
.is() )
1833 mxCategoriesValues
.set( xCategories
->getValues() );
1838 void ChartExport::exportAxes( )
1840 sal_Int32 nSize
= maAxes
.size();
1841 for( sal_Int32 nIdx
= 0; nIdx
< nSize
; nIdx
++ )
1843 exportAxis( maAxes
[nIdx
] );
1847 void ChartExport::exportAxis( AxisIdPair aAxisIdPair
)
1849 // get some properties from document first
1850 sal_Bool bHasXAxisTitle
= sal_False
,
1851 bHasYAxisTitle
= sal_False
,
1852 bHasZAxisTitle
= sal_False
,
1853 bHasSecondaryXAxisTitle
= sal_False
,
1854 bHasSecondaryYAxisTitle
= sal_False
;
1855 sal_Bool bHasXAxisMajorGrid
= sal_False
,
1856 bHasXAxisMinorGrid
= sal_False
,
1857 bHasYAxisMajorGrid
= sal_False
,
1858 bHasYAxisMinorGrid
= sal_False
,
1859 bHasZAxisMajorGrid
= sal_False
,
1860 bHasZAxisMinorGrid
= sal_False
;
1862 Reference
< XPropertySet
> xDiagramProperties (mxDiagram
, uno::UNO_QUERY
);
1864 xDiagramProperties
->getPropertyValue(
1865 OUString ("HasXAxisTitle")) >>= bHasXAxisTitle
;
1866 xDiagramProperties
->getPropertyValue(
1867 OUString ("HasYAxisTitle")) >>= bHasYAxisTitle
;
1868 xDiagramProperties
->getPropertyValue(
1869 OUString ("HasZAxisTitle")) >>= bHasZAxisTitle
;
1870 xDiagramProperties
->getPropertyValue(
1871 OUString ("HasSecondaryXAxisTitle")) >>= bHasSecondaryXAxisTitle
;
1872 xDiagramProperties
->getPropertyValue(
1873 OUString ("HasSecondaryYAxisTitle")) >>= bHasSecondaryYAxisTitle
;
1875 xDiagramProperties
->getPropertyValue(
1876 OUString ("HasXAxisGrid")) >>= bHasXAxisMajorGrid
;
1877 xDiagramProperties
->getPropertyValue(
1878 OUString ("HasYAxisGrid")) >>= bHasYAxisMajorGrid
;
1879 xDiagramProperties
->getPropertyValue(
1880 OUString ("HasZAxisGrid")) >>= bHasZAxisMajorGrid
;
1882 xDiagramProperties
->getPropertyValue(
1883 OUString ("HasXAxisHelpGrid")) >>= bHasXAxisMinorGrid
;
1884 xDiagramProperties
->getPropertyValue(
1885 OUString ("HasYAxisHelpGrid")) >>= bHasYAxisMinorGrid
;
1886 xDiagramProperties
->getPropertyValue(
1887 OUString ("HasZAxisHelpGrid")) >>= bHasZAxisMinorGrid
;
1889 Reference
< XPropertySet
> xAxisProp
;
1890 Reference
< drawing::XShape
> xAxisTitle
;
1891 Reference
< beans::XPropertySet
> xMajorGrid
;
1892 Reference
< beans::XPropertySet
> xMinorGrid
;
1893 sal_Int32 nAxisType
= XML_catAx
;
1894 const char* sAxPos
= NULL
;
1896 switch( aAxisIdPair
.nAxisType
)
1898 case AXIS_PRIMARY_X
:
1900 Reference
< ::com::sun::star::chart::XAxisXSupplier
> xAxisXSupp( mxDiagram
, uno::UNO_QUERY
);
1901 if( xAxisXSupp
.is())
1902 xAxisProp
= xAxisXSupp
->getXAxis();
1903 if( bHasXAxisTitle
)
1904 xAxisTitle
.set( xAxisXSupp
->getXAxisTitle(), uno::UNO_QUERY
);
1905 if( bHasXAxisMajorGrid
)
1906 xMajorGrid
.set( xAxisXSupp
->getXMainGrid(), uno::UNO_QUERY
);
1907 if( bHasXAxisMinorGrid
)
1908 xMinorGrid
.set( xAxisXSupp
->getXHelpGrid(), uno::UNO_QUERY
);
1910 sal_Int32 eChartType
= getChartType( );
1911 if( (eChartType
== chart::TYPEID_SCATTER
)
1912 || (eChartType
== chart::TYPEID_BUBBLE
) )
1913 nAxisType
= XML_valAx
;
1914 else if( eChartType
== chart::TYPEID_STOCK
)
1915 nAxisType
= XML_dateAx
;
1916 // FIXME: axPos, need to check axis direction
1920 case AXIS_PRIMARY_Y
:
1922 Reference
< ::com::sun::star::chart::XAxisYSupplier
> xAxisYSupp( mxDiagram
, uno::UNO_QUERY
);
1923 if( xAxisYSupp
.is())
1924 xAxisProp
= xAxisYSupp
->getYAxis();
1925 if( bHasYAxisTitle
)
1926 xAxisTitle
.set( xAxisYSupp
->getYAxisTitle(), uno::UNO_QUERY
);
1927 if( bHasYAxisMajorGrid
)
1928 xMajorGrid
.set( xAxisYSupp
->getYMainGrid(), uno::UNO_QUERY
);
1929 if( bHasYAxisMinorGrid
)
1930 xMinorGrid
.set( xAxisYSupp
->getYHelpGrid(), uno::UNO_QUERY
);
1932 nAxisType
= XML_valAx
;
1933 // FIXME: axPos, need to check axis direction
1937 case AXIS_PRIMARY_Z
:
1939 Reference
< ::com::sun::star::chart::XAxisZSupplier
> xAxisZSupp( mxDiagram
, uno::UNO_QUERY
);
1940 if( xAxisZSupp
.is())
1941 xAxisProp
= xAxisZSupp
->getZAxis();
1942 if( bHasZAxisTitle
)
1943 xAxisTitle
.set( xAxisZSupp
->getZAxisTitle(), uno::UNO_QUERY
);
1944 if( bHasZAxisMajorGrid
)
1945 xMajorGrid
.set( xAxisZSupp
->getZMainGrid(), uno::UNO_QUERY
);
1946 if( bHasZAxisMinorGrid
)
1947 xMinorGrid
.set( xAxisZSupp
->getZHelpGrid(), uno::UNO_QUERY
);
1949 sal_Int32 eChartType
= getChartType( );
1950 if( (eChartType
== chart::TYPEID_SCATTER
)
1951 || (eChartType
== chart::TYPEID_BUBBLE
) )
1952 nAxisType
= XML_valAx
;
1953 else if( eChartType
== chart::TYPEID_STOCK
)
1954 nAxisType
= XML_dateAx
;
1955 // FIXME: axPos, need to check axis direction
1959 case AXIS_SECONDARY_Y
:
1961 Reference
< ::com::sun::star::chart::XTwoAxisYSupplier
> xAxisTwoYSupp( mxDiagram
, uno::UNO_QUERY
);
1962 if( xAxisTwoYSupp
.is())
1963 xAxisProp
= xAxisTwoYSupp
->getSecondaryYAxis();
1964 if( bHasSecondaryYAxisTitle
)
1966 Reference
< ::com::sun::star::chart::XSecondAxisTitleSupplier
> xAxisSupp( mxDiagram
, uno::UNO_QUERY
);
1967 xAxisTitle
.set( xAxisSupp
->getSecondYAxisTitle(), uno::UNO_QUERY
);
1970 nAxisType
= XML_valAx
;
1971 // FIXME: axPos, need to check axis direction
1978 _exportAxis( xAxisProp
, xAxisTitle
, xMajorGrid
, xMinorGrid
, nAxisType
, sAxPos
, aAxisIdPair
);
1981 void ChartExport::_exportAxis(
1982 const Reference
< XPropertySet
>& xAxisProp
,
1983 const Reference
< drawing::XShape
>& xAxisTitle
,
1984 const Reference
< XPropertySet
>& xMajorGrid
,
1985 const Reference
< XPropertySet
>& xMinorGrid
,
1986 sal_Int32 nAxisType
,
1987 const char* sAxisPos
,
1988 AxisIdPair aAxisIdPair
)
1990 FSHelperPtr pFS
= GetFS();
1991 pFS
->startElement( FSNS( XML_c
, nAxisType
),
1993 pFS
->singleElement( FSNS( XML_c
, XML_axId
),
1994 XML_val
, I32S( aAxisIdPair
.nAxisId
),
1997 pFS
->startElement( FSNS( XML_c
, XML_scaling
),
1999 // orientation: minMax, maxMin
2000 sal_Bool bReverseDirection
= sal_False
;
2001 if(GetProperty( xAxisProp
, "ReverseDirection" ) )
2002 mAny
>>= bReverseDirection
;
2004 const char* orientation
= bReverseDirection
? "maxMin":"minMax";
2005 pFS
->singleElement( FSNS( XML_c
, XML_orientation
),
2006 XML_val
, orientation
,
2008 // logBase, min, max
2009 if(GetProperty( xAxisProp
, "Logarithmic" ) )
2011 sal_Bool bLogarithmic
= sal_False
;
2012 mAny
>>= bLogarithmic
;
2015 // default value is 10?
2016 sal_Int32 nLogBase
= 10;
2017 pFS
->singleElement( FSNS( XML_c
, XML_logBase
),
2018 XML_val
, I32S( nLogBase
),
2022 sal_Bool bAutoMax
= sal_False
;
2023 if(GetProperty( xAxisProp
, "AutoMax" ) )
2026 if( !bAutoMax
&& (GetProperty( xAxisProp
, "Max" ) ) )
2030 pFS
->singleElement( FSNS( XML_c
, XML_max
),
2031 XML_val
, IS( dMax
),
2035 sal_Bool bAutoMin
= sal_False
;
2036 if(GetProperty( xAxisProp
, "AutoMin" ) )
2039 if( !bAutoMin
&& (GetProperty( xAxisProp
, "Min" ) ) )
2043 pFS
->singleElement( FSNS( XML_c
, XML_min
),
2044 XML_val
, IS( dMin
),
2048 pFS
->endElement( FSNS( XML_c
, XML_scaling
) );
2050 sal_Bool bVisible
= sal_True
;
2051 if( xAxisProp
.is() )
2053 xAxisProp
->getPropertyValue(
2054 OUString ("Visible")) >>= bVisible
;
2057 pFS
->singleElement( FSNS( XML_c
, XML_delete
),
2058 XML_val
, bVisible
? "0" : "1",
2061 // FIXME: axPos, need to check the property "ReverseDirection"
2062 pFS
->singleElement( FSNS( XML_c
, XML_axPos
),
2066 if( xMajorGrid
.is())
2068 pFS
->startElement( FSNS( XML_c
, XML_majorGridlines
),
2070 exportShapeProps( xMajorGrid
);
2071 pFS
->endElement( FSNS( XML_c
, XML_majorGridlines
) );
2075 if( xMinorGrid
.is())
2077 pFS
->startElement( FSNS( XML_c
, XML_minorGridlines
),
2079 exportShapeProps( xMajorGrid
);
2080 pFS
->endElement( FSNS( XML_c
, XML_minorGridlines
) );
2084 if( xAxisTitle
.is() )
2085 exportTitle( xAxisTitle
);
2088 sal_Int32 nValue
= 0;
2089 if(GetProperty( xAxisProp
, "Marks" ) )
2092 sal_Bool bInner
= nValue
& ::com::sun::star::chart::ChartAxisMarks::INNER
;
2093 sal_Bool bOuter
= nValue
& ::com::sun::star::chart::ChartAxisMarks::OUTER
;
2094 const char* majorTickMark
= NULL
;
2095 if( bInner
&& bOuter
)
2096 majorTickMark
= "cross";
2098 majorTickMark
= "in";
2100 majorTickMark
= "out";
2102 majorTickMark
= "none";
2103 pFS
->singleElement( FSNS( XML_c
, XML_majorTickMark
),
2104 XML_val
, majorTickMark
,
2108 if(GetProperty( xAxisProp
, "HelpMarks" ) )
2111 sal_Bool bInner
= nValue
& ::com::sun::star::chart::ChartAxisMarks::INNER
;
2112 sal_Bool bOuter
= nValue
& ::com::sun::star::chart::ChartAxisMarks::OUTER
;
2113 const char* minorTickMark
= NULL
;
2114 if( bInner
&& bOuter
)
2115 minorTickMark
= "cross";
2117 minorTickMark
= "in";
2119 minorTickMark
= "out";
2121 minorTickMark
= "none";
2122 pFS
->singleElement( FSNS( XML_c
, XML_minorTickMark
),
2123 XML_val
, minorTickMark
,
2127 const char* sTickLblPos
= NULL
;
2128 sal_Bool bDisplayLabel
= sal_True
;
2129 if(GetProperty( xAxisProp
, "DisplayLabels" ) )
2130 mAny
>>= bDisplayLabel
;
2131 if( bDisplayLabel
&& (GetProperty( xAxisProp
, "LabelPosition" ) ) )
2133 ::com::sun::star::chart::ChartAxisLabelPosition eLabelPosition
= ::com::sun::star::chart::ChartAxisLabelPosition_NEAR_AXIS
;
2134 mAny
>>= eLabelPosition
;
2135 switch( eLabelPosition
)
2137 case ::com::sun::star::chart::ChartAxisLabelPosition_NEAR_AXIS
:
2138 case ::com::sun::star::chart::ChartAxisLabelPosition_NEAR_AXIS_OTHER_SIDE
:
2139 sTickLblPos
= "nextTo";
2141 case ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_START
:
2142 sTickLblPos
= "low";
2144 case ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_END
:
2145 sTickLblPos
= "high";
2148 sTickLblPos
= "nextTo";
2154 sTickLblPos
= "none";
2156 pFS
->singleElement( FSNS( XML_c
, XML_tickLblPos
),
2157 XML_val
, sTickLblPos
,
2161 exportShapeProps( xAxisProp
);
2163 pFS
->singleElement( FSNS( XML_c
, XML_crossAx
),
2164 XML_val
, I32S( aAxisIdPair
.nCrossAx
),
2167 // crosses & crossesAt
2168 sal_Bool bCrossesValue
= sal_False
;
2169 const char* sCrosses
= NULL
;
2170 if(GetProperty( xAxisProp
, "CrossoverPosition" ) )
2172 ::com::sun::star::chart::ChartAxisPosition
ePosition( ::com::sun::star::chart::ChartAxisPosition_ZERO
);
2176 case ::com::sun::star::chart::ChartAxisPosition_START
:
2179 case ::com::sun::star::chart::ChartAxisPosition_END
:
2182 case ::com::sun::star::chart::ChartAxisPosition_ZERO
:
2183 sCrosses
= "autoZero";
2186 bCrossesValue
= sal_True
;
2191 if( bCrossesValue
&& GetProperty( xAxisProp
, "CrossoverValue" ) )
2195 pFS
->singleElement( FSNS( XML_c
, XML_crossesAt
),
2196 XML_val
, IS( dValue
),
2201 pFS
->singleElement( FSNS( XML_c
, XML_crosses
),
2206 if( ( nAxisType
== XML_catAx
)
2207 || ( nAxisType
== XML_dateAx
) )
2209 // FIXME: seems not support? use default value,
2210 const char* isAuto
= "1";
2211 pFS
->singleElement( FSNS( XML_c
, XML_auto
),
2215 if( nAxisType
== XML_catAx
)
2217 // FIXME: seems not support? lblAlgn
2218 const char* sLblAlgn
= "ctr";
2219 pFS
->singleElement( FSNS( XML_c
, XML_lblAlgn
),
2224 // FIXME: seems not support? lblOffset
2225 sal_Int32 nLblOffset
= 100;
2226 pFS
->singleElement( FSNS( XML_c
, XML_lblOffset
),
2227 XML_val
, I32S( nLblOffset
),
2232 sal_Bool bAutoStepMain
= sal_False
;
2233 if(GetProperty( xAxisProp
, "AutoStepMain" ) )
2234 mAny
>>= bAutoStepMain
;
2236 if( !bAutoStepMain
&& (GetProperty( xAxisProp
, "StepMain" ) ) )
2238 double dMajorUnit
= 0;
2239 mAny
>>= dMajorUnit
;
2240 pFS
->singleElement( FSNS( XML_c
, XML_majorUnit
),
2241 XML_val
, IS( dMajorUnit
),
2245 sal_Bool bAutoStepHelp
= sal_False
;
2246 if(GetProperty( xAxisProp
, "AutoStepHelp" ) )
2247 mAny
>>= bAutoStepHelp
;
2249 if( !bAutoStepHelp
&& (GetProperty( xAxisProp
, "StepHelp" ) ) )
2251 double dMinorUnit
= 0;
2252 mAny
>>= dMinorUnit
;
2253 pFS
->singleElement( FSNS( XML_c
, XML_minorUnit
),
2254 XML_val
, IS( dMinorUnit
),
2258 // TODO: text properties
2260 pFS
->endElement( FSNS( XML_c
, nAxisType
) );
2263 void ChartExport::exportDataLabels(
2264 const uno::Reference
< beans::XPropertySet
> & xSeriesProperties
,
2265 sal_Int32 nSeriesLength
)
2267 // TODO: export field separators, missing flag vs. showing series name or not
2268 uno::Reference
< chart2::XDataSeries
> xSeries( xSeriesProperties
, uno::UNO_QUERY
);
2270 if( xSeriesProperties
.is())
2272 FSHelperPtr pFS
= GetFS();
2273 pFS
->startElement( FSNS( XML_c
, XML_dLbls
),
2277 for( nElem
= 0; nElem
< nSeriesLength
; ++nElem
)
2279 uno::Reference
< beans::XPropertySet
> xPropSet
;
2283 xPropSet
= SchXMLSeriesHelper::createOldAPIDataPointPropertySet(
2284 xSeries
, nElem
, getModel() );
2286 catch( const uno::Exception
& rEx
)
2288 SAL_WARN("oox", "Exception caught during Export of data label: " << rEx
.Message
);
2293 namespace cssc2
= ::com::sun::star::chart2
;
2294 cssc2::DataPointLabel aLabel
;
2295 if (GetProperty( xPropSet
, "Label"))
2299 namespace csscd
= ::com::sun::star::chart::DataLabelPlacement
;
2300 sal_Int32
nPlacement(csscd::AVOID_OVERLAP
);
2301 const char *aPlacement
= NULL
;
2304 if (GetProperty( xPropSet
, "LabelPlacement"))
2305 mAny
>>= nPlacement
;
2307 switch( nPlacement
)
2309 case csscd::OUTSIDE
: aPlacement
= "outEnd"; break;
2310 case csscd::INSIDE
: aPlacement
= "inEnd"; break;
2311 case csscd::CENTER
: aPlacement
= "ctr"; break;
2312 case csscd::NEAR_ORIGIN
: aPlacement
= "inBase"; break;
2313 case csscd::TOP
: aPlacement
= "t"; break;
2314 case csscd::BOTTOM
: aPlacement
= "b"; break;
2315 case csscd::LEFT
: aPlacement
= "l"; break;
2316 case csscd::RIGHT
: aPlacement
= "r"; break;
2317 case csscd::AVOID_OVERLAP
: aPlacement
= "bestFit"; break;
2320 pFS
->startElement( FSNS( XML_c
, XML_dLbl
), FSEND
);
2321 pFS
->singleElement( FSNS( XML_c
, XML_idx
), XML_val
, I32S(nElem
), FSEND
);
2322 pFS
->singleElement( FSNS( XML_c
, XML_dLblPos
), XML_val
, aPlacement
, FSEND
);
2324 pFS
->singleElement( FSNS( XML_c
, XML_showLegendKey
), XML_val
,
2325 aLabel
.ShowLegendSymbol
? "1" : "0", FSEND
);
2326 pFS
->singleElement( FSNS( XML_c
, XML_showVal
), XML_val
,
2327 aLabel
.ShowNumber
? "1" : "0", FSEND
);
2328 pFS
->singleElement( FSNS( XML_c
, XML_showCatName
), XML_val
,
2329 aLabel
.ShowCategoryName
? "1" : "0", FSEND
);
2330 // MSO somehow assumes series name to be on (=displayed) by default.
2331 // Let's put false here and switch it off then, since we have no UI means
2332 // in LibO to toggle it on anyway
2333 pFS
->singleElement( FSNS( XML_c
, XML_showSerName
), XML_val
, "0", FSEND
);
2334 pFS
->singleElement( FSNS( XML_c
, XML_showPercent
), XML_val
,
2335 aLabel
.ShowNumberInPercent
? "1" : "0", FSEND
);
2337 if (GetProperty( xPropSet
, "LabelSeparator"))
2340 pFS
->startElement( FSNS( XML_c
, XML_separator
), FSEND
);
2341 pFS
->writeEscaped(aSep
);
2342 pFS
->endElement( FSNS( XML_c
, XML_separator
) );
2344 pFS
->endElement( FSNS( XML_c
, XML_dLbl
));
2348 pFS
->endElement( FSNS( XML_c
, XML_dLbls
) );
2352 void ChartExport::exportDataPoints(
2353 const uno::Reference
< beans::XPropertySet
> & xSeriesProperties
,
2354 sal_Int32 nSeriesLength
)
2356 uno::Reference
< chart2::XDataSeries
> xSeries( xSeriesProperties
, uno::UNO_QUERY
);
2357 bool bVaryColorsByPoint
= false;
2358 Sequence
< sal_Int32
> aDataPointSeq
;
2359 if( xSeriesProperties
.is())
2361 Any aAny
= xSeriesProperties
->getPropertyValue(
2362 OUString( "AttributedDataPoints" ));
2363 aAny
>>= aDataPointSeq
;
2364 xSeriesProperties
->getPropertyValue(
2365 OUString( "VaryColorsByPoint" )) >>= bVaryColorsByPoint
;
2368 const sal_Int32
* pPoints
= aDataPointSeq
.getConstArray();
2370 Reference
< chart2::XColorScheme
> xColorScheme
;
2371 if( mxNewDiagram
.is())
2372 xColorScheme
.set( mxNewDiagram
->getDefaultColorScheme());
2374 if( bVaryColorsByPoint
&& xColorScheme
.is() )
2376 ::std::set
< sal_Int32
> aAttrPointSet
;
2377 ::std::copy( pPoints
, pPoints
+ aDataPointSeq
.getLength(),
2378 ::std::inserter( aAttrPointSet
, aAttrPointSet
.begin()));
2379 const ::std::set
< sal_Int32
>::const_iterator
aEndIt( aAttrPointSet
.end());
2380 for( nElement
= 0; nElement
< nSeriesLength
; ++nElement
)
2382 uno::Reference
< beans::XPropertySet
> xPropSet
;
2383 if( aAttrPointSet
.find( nElement
) != aEndIt
)
2387 xPropSet
= SchXMLSeriesHelper::createOldAPIDataPointPropertySet(
2388 xSeries
, nElement
, getModel() );
2390 catch( const uno::Exception
& rEx
)
2392 (void)rEx
; // avoid warning for pro build
2393 SAL_WARN( "oox", "Exception caught during Export of data point: " << rEx
.Message
);
2398 // property set only containing the color
2399 xPropSet
.set( new ColorPropertySet( xColorScheme
->getColorByIndex( nElement
)));
2404 OSL_TRACE("ChartExport::exportDataPoints -- writer data points ");
2405 FSHelperPtr pFS
= GetFS();
2406 pFS
->startElement( FSNS( XML_c
, XML_dPt
),
2408 pFS
->singleElement( FSNS( XML_c
, XML_idx
),
2409 XML_val
, I32S(nElement
),
2411 exportShapeProps( xPropSet
);
2413 pFS
->endElement( FSNS( XML_c
, XML_dPt
) );
2419 void ChartExport::exportAxesId( sal_Int32 nAttachedAxis
)
2421 sal_Int32 nAxisIdx
= lcl_generateRandomValue();
2422 sal_Int32 nAxisIdy
= lcl_generateRandomValue();
2423 maAxes
.push_back( AxisIdPair( AXIS_PRIMARY_X
, nAxisIdx
, nAxisIdy
) );
2424 maAxes
.push_back( AxisIdPair( nAttachedAxis
, nAxisIdy
, nAxisIdx
) );
2425 FSHelperPtr pFS
= GetFS();
2426 pFS
->singleElement( FSNS( XML_c
, XML_axId
),
2427 XML_val
, I32S( nAxisIdx
),
2429 pFS
->singleElement( FSNS( XML_c
, XML_axId
),
2430 XML_val
, I32S( nAxisIdy
),
2434 sal_Int32 nAxisIdz
= 0;
2435 if( isDeep3dChart() )
2437 nAxisIdz
= lcl_generateRandomValue();
2438 maAxes
.push_back( AxisIdPair( AXIS_PRIMARY_Z
, nAxisIdz
, nAxisIdy
) );
2440 pFS
->singleElement( FSNS( XML_c
, XML_axId
),
2441 XML_val
, I32S( nAxisIdz
),
2446 void ChartExport::exportGrouping( sal_Bool isBar
)
2448 FSHelperPtr pFS
= GetFS();
2449 Reference
< XPropertySet
> xPropSet( mxDiagram
, uno::UNO_QUERY
);
2451 sal_Bool bStacked
= sal_False
;
2452 if( GetProperty( xPropSet
, "Stacked" ) )
2454 sal_Bool bPercentage
= sal_False
;
2455 if( GetProperty( xPropSet
, "Percent" ) )
2456 mAny
>>= bPercentage
;
2458 const char* grouping
= NULL
;
2460 grouping
= "stacked";
2461 else if( bPercentage
)
2462 grouping
= "percentStacked";
2465 if( isBar
&& !isDeep3dChart() )
2466 grouping
= "clustered";
2468 grouping
= "standard";
2470 pFS
->singleElement( FSNS( XML_c
, XML_grouping
),
2475 void ChartExport::exportMarker()
2477 FSHelperPtr pFS
= GetFS();
2478 pFS
->startElement( FSNS( XML_c
, XML_marker
),
2480 Reference
< XPropertySet
> xPropSet( mxDiagram
, uno::UNO_QUERY
);
2481 sal_Int32 nSymbolType
= ::com::sun::star::chart::ChartSymbolType::NONE
;
2482 if( GetProperty( xPropSet
, "SymbolType" ) )
2483 mAny
>>= nSymbolType
;
2485 // TODO: more properties support for marker
2486 const char* pSymbolType
= NULL
;
2487 switch( nSymbolType
)
2489 case cssc::ChartSymbolType::NONE
:
2490 pSymbolType
= "none";
2492 case cssc::ChartSymbolType::SYMBOL0
:
2493 pSymbolType
= "square";
2495 case cssc::ChartSymbolType::SYMBOL1
:
2496 pSymbolType
= "diamond";
2498 // map all triangle variants to the OOXML version
2499 case cssc::ChartSymbolType::SYMBOL2
:
2500 case cssc::ChartSymbolType::SYMBOL3
:
2501 case cssc::ChartSymbolType::SYMBOL4
:
2502 case cssc::ChartSymbolType::SYMBOL5
:
2503 pSymbolType
= "triangle";
2505 case cssc::ChartSymbolType::SYMBOL6
:
2506 pSymbolType
= "plus";
2508 case cssc::ChartSymbolType::SYMBOL7
:
2509 pSymbolType
= "plus";
2511 case cssc::ChartSymbolType::AUTO
:
2513 case cssc::ChartSymbolType::BITMAPURL
:
2516 SAL_WARN("oox", "unknown data series symbol");
2521 pFS
->singleElement( FSNS( XML_c
, XML_symbol
),
2522 XML_val
, pSymbolType
,
2525 if( nSymbolType
!= cssc::ChartSymbolType::NONE
)
2527 awt::Size aSymbolSize
;
2528 if( GetProperty( xPropSet
, "SymbolSize" ) )
2530 mAny
>>= aSymbolSize
;;
2531 sal_Int32 nSize
= std::max( aSymbolSize
.Width
, aSymbolSize
.Height
);
2533 nSize
= nSize
/250.0*7.0; // just guessed based on some test cases
2534 nSize
= std::min
<sal_Int32
>( 72, std::max
<sal_Int32
>( 2, nSize
) );
2535 pFS
->singleElement( FSNS( XML_c
, XML_size
),
2536 XML_val
, I32S(nSize
),
2540 pFS
->endElement( FSNS( XML_c
, XML_marker
) );
2543 void ChartExport::exportSmooth()
2545 FSHelperPtr pFS
= GetFS();
2546 Reference
< XPropertySet
> xPropSet( mxDiagram
, uno::UNO_QUERY
);
2547 sal_Int32 nSplineType
= 0;
2548 if( GetProperty( xPropSet
, "SplineType" ) )
2549 mAny
>>= nSplineType
;
2550 if( nSplineType
!= 0 )
2552 pFS
->singleElement( FSNS( XML_c
, XML_smooth
),
2558 void ChartExport::exportFirstSliceAng( )
2560 FSHelperPtr pFS
= GetFS();
2561 sal_Int32 nStartingAngle
= 0;
2562 Reference
< XPropertySet
> xPropSet( mxDiagram
, uno::UNO_QUERY
);
2563 if( GetProperty( xPropSet
, "StartingAngle" ) )
2564 mAny
>>= nStartingAngle
;
2566 // convert to ooxml angle
2567 nStartingAngle
= (450 - nStartingAngle
) % 360;
2568 pFS
->singleElement( FSNS( XML_c
, XML_firstSliceAng
),
2569 XML_val
, I32S( nStartingAngle
),
2575 const char* getErrorBarStyle(sal_Int32 nErrorBarStyle
)
2577 switch(nErrorBarStyle
)
2579 case cssc::ErrorBarStyle::NONE
:
2580 // I have no idea how to map it to OOXML
2581 // this approach is as good as any else
2583 case cssc::ErrorBarStyle::VARIANCE
:
2585 case cssc::ErrorBarStyle::STANDARD_DEVIATION
:
2587 case cssc::ErrorBarStyle::ABSOLUTE
:
2589 case cssc::ErrorBarStyle::RELATIVE
:
2590 return "percentage";
2591 case cssc::ErrorBarStyle::ERROR_MARGIN
:
2593 case cssc::ErrorBarStyle::STANDARD_ERROR
:
2595 case cssc::ErrorBarStyle::FROM_DATA
:
2598 assert(false); // can't happen
2603 Reference
< chart2::data::XDataSequence
> getLabeledSequence(
2604 uno::Sequence
< uno::Reference
< chart2::data::XLabeledDataSequence
> > aSequences
,
2607 const OUString
aRolePrefix( "error-bars" );
2608 OUString aDirection
;
2610 aDirection
= "positive";
2612 aDirection
= "negative";
2614 for( sal_Int32 nI
=0; nI
< aSequences
.getLength(); ++nI
)
2616 if( aSequences
[nI
].is())
2618 uno::Reference
< chart2::data::XDataSequence
> xSequence( aSequences
[nI
]->getValues());
2619 uno::Reference
< beans::XPropertySet
> xSeqProp( xSequence
, uno::UNO_QUERY_THROW
);
2621 if( ( xSeqProp
->getPropertyValue(
2622 OUString( "Role" )) >>= aRole
) &&
2623 aRole
.match( aRolePrefix
) && aRole
.indexOf(aDirection
) >= 0 )
2630 return Reference
< chart2::data::XDataSequence
> ();
2635 void ChartExport::exportErrorBar(Reference
< XPropertySet
> xErrorBarProps
, bool bYError
)
2637 FSHelperPtr pFS
= GetFS();
2638 pFS
->startElement( FSNS( XML_c
, XML_errBars
),
2640 pFS
->singleElement( FSNS( XML_c
, XML_errDir
),
2641 XML_val
, bYError
? "y" : "x",
2643 bool bPositive
= false, bNegative
= false;
2644 xErrorBarProps
->getPropertyValue("ShowPositiveError") >>= bPositive
;
2645 xErrorBarProps
->getPropertyValue("ShowNegativeError") >>= bNegative
;
2646 const char* pErrBarType
;
2647 if(bPositive
&& bNegative
)
2648 pErrBarType
= "both";
2650 pErrBarType
= "plus";
2652 pErrBarType
= "minus";
2655 // what the hell should we do now?
2656 // at least this makes the file valid
2657 pErrBarType
= "both";
2659 pFS
->singleElement( FSNS( XML_c
, XML_errBarType
),
2660 XML_val
, pErrBarType
,
2663 sal_Int32 nErrorBarStyle
= cssc::ErrorBarStyle::NONE
;
2664 xErrorBarProps
->getPropertyValue("ErrorBarStyle") >>= nErrorBarStyle
;
2665 const char* pErrorBarStyle
= getErrorBarStyle(nErrorBarStyle
);
2666 pFS
->singleElement( FSNS( XML_c
, XML_errValType
),
2667 XML_val
, pErrorBarStyle
,
2669 pFS
->singleElement( FSNS( XML_c
, XML_noEndCap
),
2672 if(nErrorBarStyle
== cssc::ErrorBarStyle::FROM_DATA
)
2674 uno::Reference
< chart2::data::XDataSource
> xDataSource(xErrorBarProps
, uno::UNO_QUERY
);
2675 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > aSequences
=
2676 xDataSource
->getDataSequences();
2680 exportSeriesValues(getLabeledSequence(aSequences
, true), XML_plus
);
2685 exportSeriesValues(getLabeledSequence(aSequences
, false), XML_minus
);
2691 if(nErrorBarStyle
== cssc::ErrorBarStyle::STANDARD_DEVIATION
)
2693 xErrorBarProps
->getPropertyValue("Weight") >>= nVal
;
2698 xErrorBarProps
->getPropertyValue("PositiveError") >>= nVal
;
2700 xErrorBarProps
->getPropertyValue("NegativeError") >>= nVal
;
2703 OString aVal
= OString::number(nVal
);
2705 pFS
->singleElement( FSNS( XML_c
, XML_val
),
2706 XML_val
, aVal
.getStr(),
2710 pFS
->endElement( FSNS( XML_c
, XML_errBars
) );
2713 void ChartExport::exportView3D()
2715 Reference
< XPropertySet
> xPropSet( mxDiagram
, uno::UNO_QUERY
);
2716 if( !xPropSet
.is() )
2718 FSHelperPtr pFS
= GetFS();
2719 pFS
->startElement( FSNS( XML_c
, XML_view3D
),
2722 if( GetProperty( xPropSet
, "RotationHorizontal" ) )
2724 sal_Int32 nRotationX
= 0;
2725 mAny
>>= nRotationX
;
2726 // X rotation (map Chart2 [-179,180] to OOXML [0..359])
2727 if( nRotationX
< 0 )
2729 pFS
->singleElement( FSNS( XML_c
, XML_rotX
),
2730 XML_val
, I32S( nRotationX
),
2734 if( GetProperty( xPropSet
, "RotationVertical" ) )
2736 sal_Int32 nRotationY
= 0;
2737 mAny
>>= nRotationY
;
2738 // Y rotation (map Chart2 [-179,180] to OOXML [0..359])
2739 if( nRotationY
< 0 )
2741 pFS
->singleElement( FSNS( XML_c
, XML_rotY
),
2742 XML_val
, I32S( nRotationY
),
2746 if( GetProperty( xPropSet
, "RightAngledAxes" ) )
2748 sal_Bool bRightAngled
= sal_False
;
2749 mAny
>>= bRightAngled
;
2750 const char* sRightAngled
= bRightAngled
? "1":"0";
2751 pFS
->singleElement( FSNS( XML_c
, XML_rAngAx
),
2752 XML_val
, sRightAngled
,
2756 if( GetProperty( xPropSet
, "Perspective" ) )
2758 sal_Int32 nPerspective
= 0;
2759 mAny
>>= nPerspective
;
2760 // map Chart2 [0,100] to OOXML [0..200]
2762 pFS
->singleElement( FSNS( XML_c
, XML_perspective
),
2763 XML_val
, I32S( nPerspective
),
2766 pFS
->endElement( FSNS( XML_c
, XML_view3D
) );
2769 sal_Bool
ChartExport::isDeep3dChart()
2771 sal_Bool isDeep
= sal_False
;
2774 Reference
< XPropertySet
> xPropSet( mxDiagram
, uno::UNO_QUERY
);
2775 if( GetProperty( xPropSet
, "Deep" ) )
2784 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */