Updated core
[LibreOffice.git] / oox / source / export / chartexport.cxx
blobe6da04b16695137ae7b9f374ea723c94037d7b86
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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"
26 #include <cstdio>
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"
85 #include <set>
86 #include <time.h>
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 >
115 public:
116 explicit lcl_MatchesRole( const OUString & aRole ) :
117 m_aRole( aRole )
120 bool operator () ( const Reference< chart2::data::XLabeledDataSequence > & xSeq ) const
122 if( !xSeq.is() )
123 return false;
124 Reference< beans::XPropertySet > xProp( xSeq->getValues(), uno::UNO_QUERY );
125 OUString aRole;
127 return ( xProp.is() &&
128 (xProp->getPropertyValue(
129 OUString( "Role" ) ) >>= aRole ) &&
130 m_aRole.equals( aRole ));
133 private:
134 OUString m_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());
165 if( xAxis.is())
167 chart2::ScaleData aScaleData = xAxis->getScaleData();
168 if( aScaleData.Categories.is())
170 xResult.set( aScaleData.Categories );
171 break;
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());
188 return xResult;
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 );
200 if( xSink.is())
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;
209 if( xChartDoc.is() )
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() )
218 continue;
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());
227 return aRet;
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 ));
242 if( pMatch != pEnd )
243 return *pMatch;
245 return aNoResult;
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") ) );
265 if( xXValues.is() )
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 )
285 bool bResult=true;
289 sal_Int32 nAxisIndex = 0;
290 Reference< beans::XPropertySet > xProp( xDataSeries, uno::UNO_QUERY_THROW );
291 if( xProp.is() )
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());
305 return bResult;
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())
351 return;
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 ));
360 else
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 )
371 double fNan = 0.0;
372 ::rtl::math::setNan( &fNan );
373 ::std::vector< double > aResult;
375 Reference< chart2::data::XNumericalDataSequence > xNumSeq( xSeq, uno::UNO_QUERY );
376 if( xNumSeq.is())
378 Sequence< double > aValues( xNumSeq->getNumericalData());
379 ::std::copy( aValues.getConstArray(), aValues.getConstArray() + aValues.getLength(),
380 ::std::back_inserter( aResult ));
382 else if( xSeq.is())
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];
389 return aResult;
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;
426 return eChartTypeId;
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();
450 return nID;
453 sal_Int32 ChartExport::getChartType( )
455 OUString sChartType = mxDiagram->getDiagramType();
456 return lcl_getChartType( sChartType );
459 OUString ChartExport::parseFormula( const OUString& rRange )
461 OUString aResult;
462 Reference< XFormulaParser > xParser;
463 uno::Reference< lang::XMultiServiceFactory > xSF( GetFB()->getModelFactory(), uno::UNO_QUERY );
464 if( xSF.is() )
468 xParser.set( xSF->createInstance( OUString("com.sun.star.sheet.FormulaParser") ), UNO_QUERY );
470 catch( Exception& )
474 if( xParser.is() )
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 ) );
489 else
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(".$", "!$" );
497 aResult = aRange;
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());
501 return aResult;
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 );
516 if (xNamed.is())
517 sName = xNamed->getName();
519 sal_Int32 nID = GetChartID();
521 pFS->singleElementNS( mnXmlNamespace, XML_cNvPr,
522 XML_id, I32S( nID ),
523 XML_name, USS( sName ),
524 FSEND );
526 pFS->singleElementNS( mnXmlNamespace, XML_cNvGraphicFramePr,
527 FSEND );
529 if( GetDocumentType() == DOCUMENT_PPTX )
530 pFS->singleElementNS( mnXmlNamespace, XML_nvPr,
531 FSEND );
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",
541 FSEND );
542 OUString sId;
543 const char* sFullPath = NULL;
544 const char* sRelativePath = NULL;
545 switch( GetDocumentType() )
547 case DOCUMENT_DOCX:
549 sFullPath = "word/charts/chart";
550 sRelativePath = "charts/chart";
551 break;
553 case DOCUMENT_PPTX:
555 sFullPath = "ppt/charts/chart";
556 sRelativePath = "../charts/chart";
557 break;
559 case DOCUMENT_XLSX:
561 sFullPath = "xl/charts/chart";
562 sRelativePath = "../charts/chart";
563 break;
565 default:
567 sFullPath = "charts/chart";
568 sRelativePath = "charts/chart";
569 break;
572 OUString sFullStream = OUStringBuffer()
573 .appendAscii(sFullPath)
574 .append(nChartCount)
575 .appendAscii( ".xml" )
576 .makeStringAndClear();
577 OUString sRelativeStream = OUStringBuffer()
578 .appendAscii(sRelativePath)
579 .append(nChartCount)
580 .appendAscii( ".xml" )
581 .makeStringAndClear();
582 FSHelperPtr pChart = CreateOutputStream(
583 sFullStream,
584 sRelativeStream,
585 pFS->getOutputStream(),
586 "application/vnd.openxmlformats-officedocument.drawingml.chart+xml",
587 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart",
588 &sId );
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 ),
594 FSEND );
596 pFS->endElement( FSNS( XML_a, XML_graphicData ) );
597 pFS->endElement( FSNS( XML_a, XML_graphic ) );
598 pFS->endElementNS( mnXmlNamespace, XML_graphicFrame );
600 SetFS( pChart );
601 ExportContent();
603 return *this;
606 void ChartExport::InitRangeSegmentationProperties( const Reference< chart2::XChartDocument > & xChartDoc )
608 if( xChartDoc.is())
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() )
661 return;
662 InitRangeSegmentationProperties( xChartDoc );
663 // TODO: export chart
664 _ExportContent( );
667 void ChartExport::_ExportContent()
669 Reference< ::com::sun::star::chart::XChartDocument > xChartDoc( getModel(), uno::UNO_QUERY );
670 if( xChartDoc.is())
672 // determine if data comes from the outside
673 sal_Bool bIncludeTable = sal_True;
675 Reference< chart2::XChartDocument > xNewDoc( xChartDoc, uno::UNO_QUERY );
676 if( xNewDoc.is())
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;
687 else
689 Reference< lang::XServiceInfo > xServ( xChartDoc, uno::UNO_QUERY );
690 if( xServ.is())
692 if( xServ->supportsService(
693 OUString("com.sun.star.chart.ChartTableAddressSupplier")))
695 Reference< beans::XPropertySet > xProp( xServ, uno::UNO_QUERY );
696 if( xProp.is())
698 Any aAny;
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 );
722 else
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",
736 FSEND );
737 // TODO: get the correct editing lanauge
738 pFS->singleElement( FSNS( XML_c, XML_lang ),
739 XML_val, "en-US",
740 FSEND );
742 if( !bIncludeTable )
744 // TODO:external data
746 //XML_chart
747 exportChart(rChartDoc);
749 // TODO: printSettings
750 // TODO: style
751 // TODO: text properties
752 // TODO: shape properties
753 Reference< XPropertySet > xPropSet( rChartDoc->getArea(), uno::UNO_QUERY );
754 if( xPropSet.is() )
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() );
763 if( xNewDoc.is())
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" ));
783 aAny >>= bHasLegend;
785 catch( beans::UnknownPropertyException & )
787 DBG_WARNING( "Required property not found in ChartDocument" );
789 } // if( xDocPropSet.is())
791 // chart element
792 // -------------
793 FSHelperPtr pFS = GetFS();
794 pFS->startElement( FSNS( XML_c, XML_chart ),
795 FSEND );
797 // title
798 if( bHasMainTitle )
800 Reference< drawing::XShape > xShape = rChartDoc->getTitle();
801 if( xShape.is() )
802 exportTitle( xShape );
804 InitPlotArea( );
805 if( mbIs3DChart )
807 exportView3D();
809 // floor
810 Reference< beans::XPropertySet > xFloor( mxNewDiagram->getFloor(), uno::UNO_QUERY );
811 if( xFloor.is() )
813 pFS->startElement( FSNS( XML_c, XML_floor ),
814 FSEND );
815 exportShapeProps( xFloor );
816 pFS->endElement( FSNS( XML_c, XML_floor ) );
819 // sideWall
821 // backWall
822 Reference< beans::XPropertySet > xBackWall( mxNewDiagram->getWall(), uno::UNO_QUERY );
823 if( xBackWall.is() )
825 pFS->startElement( FSNS( XML_c, XML_backWall ),
826 FSEND );
827 exportShapeProps( xBackWall );
828 pFS->endElement( FSNS( XML_c, XML_backWall ) );
832 // plot area
833 exportPlotArea( );
834 // legend
835 if( bHasLegend )
836 exportLegend( rChartDoc );
837 // only visible cells should be plotted on the chart
838 pFS->singleElement( FSNS( XML_c, XML_plotVisOnly ),
839 XML_val, "1",
840 FSEND );
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 ),
849 FSEND );
851 Reference< beans::XPropertySet > xProp( rChartDoc->getLegend(), uno::UNO_QUERY );
852 if( xProp.is() )
854 // position
855 ::com::sun::star::chart::ChartLegendPosition aLegendPos = ::com::sun::star::chart::ChartLegendPosition_NONE;
858 Any aAny( xProp->getPropertyValue(
859 OUString( "Alignment" )));
860 aAny >>= aLegendPos;
862 catch( beans::UnknownPropertyException & )
864 DBG_WARNING( "Property Align not found in ChartLegend" );
867 const char* strPos = NULL;
868 switch( aLegendPos )
870 case ::com::sun::star::chart::ChartLegendPosition_LEFT:
871 strPos = "l";
872 break;
873 case ::com::sun::star::chart::ChartLegendPosition_RIGHT:
874 strPos = "r";
875 break;
876 case ::com::sun::star::chart::ChartLegendPosition_TOP:
877 strPos = "t";
878 break;
879 case ::com::sun::star::chart::ChartLegendPosition_BOTTOM:
880 strPos = "b";
881 break;
882 case ::com::sun::star::chart::ChartLegendPosition_NONE:
883 case ::com::sun::star::chart::ChartLegendPosition_MAKE_FIXED_SIZE:
884 // nothing
885 break;
888 if( strPos != NULL )
890 pFS->singleElement( FSNS( XML_c, XML_legendPos ),
891 XML_val, strPos,
892 FSEND );
893 pFS->singleElement( FSNS( XML_c, XML_overlay ),
894 XML_val, "0",
895 FSEND );
898 // shape properties
899 exportShapeProps( xProp );
902 // legendEntry
904 pFS->endElement( FSNS( XML_c, XML_legend ) );
907 void ChartExport::exportTitle( Reference< XShape > xShape )
909 OUString sText;
910 Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY );
911 if( xPropSet.is())
913 xPropSet->getPropertyValue( OUString( "String" )) >>= sText;
915 if( sText.isEmpty() )
916 return;
918 FSHelperPtr pFS = GetFS();
919 pFS->startElement( FSNS( XML_c, XML_title ),
920 FSEND );
922 pFS->startElement( FSNS( XML_c, XML_tx ),
923 FSEND );
924 pFS->startElement( FSNS( XML_c, XML_rich ),
925 FSEND );
927 // TODO: bodyPr
928 const char* sWritingMode = NULL;
929 sal_Bool bVertical = sal_False;
930 xPropSet->getPropertyValue( OUString( "StackedText" )) >>= bVertical;
931 if( bVertical )
932 sWritingMode = "wordArtVert";
934 pFS->singleElement( FSNS( XML_a, XML_bodyPr ),
935 XML_vert, sWritingMode,
936 FSEND );
937 // TODO: lstStyle
938 pFS->singleElement( FSNS( XML_a, XML_lstStyle ),
939 FSEND );
940 // FIXME: handle multipul paragraphs to parse aText
941 pFS->startElement( FSNS( XML_a, XML_p ),
942 FSEND );
944 pFS->startElement( FSNS( XML_a, XML_pPr ),
945 FSEND );
946 pFS->singleElement( FSNS( XML_a, XML_defRPr ),
947 FSEND );
948 pFS->endElement( FSNS( XML_a, XML_pPr ) );
950 pFS->startElement( FSNS( XML_a, XML_r ),
951 FSEND );
952 WriteRunProperties( xPropSet, sal_False );
953 pFS->startElement( FSNS( XML_a, XML_t ),
954 FSEND );
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 ),
966 FSEND );
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())
975 return;
977 // plot-area element
978 // -----------------
979 FSHelperPtr pFS = GetFS();
980 pFS->startElement( FSNS( XML_c, XML_plotArea ),
981 FSEND );
982 // layout
983 pFS->singleElement( FSNS( XML_c, XML_layout ),
984 FSEND );
986 // chart type
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 );
992 if( ! xCTCnt.is())
993 continue;
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 );
998 if( ! xDSCnt.is())
999 return;
1000 Reference< chart2::XChartType > xChartType( aCTSeq[nCTIdx], uno::UNO_QUERY );
1001 if( ! xChartType.is())
1002 continue;
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 );
1011 break;
1013 case chart::TYPEID_AREA:
1015 exportAreaChart( xChartType );
1016 break;
1018 case chart::TYPEID_LINE:
1020 exportLineChart( xChartType );
1021 break;
1023 case chart::TYPEID_BUBBLE:
1025 exportBubbleChart( xChartType );
1026 break;
1028 case chart::TYPEID_DOUGHNUT:
1030 exportDoughnutChart( xChartType );
1031 break;
1033 case chart::TYPEID_OFPIE:
1035 exportOfPieChart( xChartType );
1036 break;
1038 case chart::TYPEID_PIE:
1040 exportPieChart( xChartType );
1041 break;
1043 case chart::TYPEID_RADARLINE:
1044 case chart::TYPEID_RADARAREA:
1046 exportRadarChart( xChartType );
1047 break;
1049 case chart::TYPEID_SCATTER:
1051 exportScatterChart( xChartType );
1052 break;
1054 case chart::TYPEID_STOCK:
1056 exportStockChart( xChartType );
1057 break;
1059 case chart::TYPEID_SURFACE:
1061 exportSuffaceChart( xChartType );
1062 break;
1064 default:
1066 OSL_TRACE("ChartExport::exportPlotArea -- not support chart type");
1067 break;
1073 //Axis Data
1074 exportAxes( );
1076 // shape properties
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;
1095 if( mbIs3DChart )
1096 nTypeId = XML_area3DChart;
1097 pFS->startElement( FSNS( XML_c, nTypeId ),
1098 FSEND );
1100 exportGrouping( );
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;
1111 if( mbIs3DChart )
1112 nTypeId = XML_bar3DChart;
1113 FSHelperPtr pFS = GetFS();
1114 pFS->startElement( FSNS( XML_c, nTypeId ),
1115 FSEND );
1116 // bar direction
1117 sal_Bool bVertical = sal_False;
1118 Reference< XPropertySet > xPropSet( mxDiagram , uno::UNO_QUERY);
1119 if( GetProperty( xPropSet, "Vertical" ) )
1120 mAny >>= bVertical;
1122 const char* bardir = bVertical? "bar":"col";
1123 pFS->singleElement( FSNS( XML_c, XML_barDir ),
1124 XML_val, bardir,
1125 FSEND );
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 ),
1142 FSEND );
1146 if( mbIs3DChart )
1148 // Shape
1149 namespace cssc = ::com::sun::star::chart;
1150 sal_Int32 nGeom3d = cssc::ChartSolidType::RECTANGULAR_SOLID;
1151 if( xPropSet.is() && GetProperty( xPropSet, "SolidType") )
1152 mAny >>= nGeom3d;
1153 const char* sShapeType = NULL;
1154 switch( nGeom3d )
1156 case cssc::ChartSolidType::RECTANGULAR_SOLID:
1157 sShapeType = "box";
1158 break;
1159 case cssc::ChartSolidType::CONE:
1160 sShapeType = "cone";
1161 break;
1162 case cssc::ChartSolidType::CYLINDER:
1163 sShapeType = "cylinder";
1164 break;
1165 case cssc::ChartSolidType::PYRAMID:
1166 sShapeType = "pyramid";
1167 break;
1169 pFS->singleElement( FSNS( XML_c, XML_shape ),
1170 XML_val, sShapeType,
1171 FSEND );
1174 //overlap
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];
1182 if( nOverlap > 0 )
1183 pFS->singleElement( FSNS( XML_c, XML_overlap ),
1184 XML_val, I32S( nOverlap ),
1185 FSEND );
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 ),
1198 FSEND );
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 ),
1211 FSEND );
1213 sal_Int32 nAttachedAxis = AXIS_PRIMARY_Y;
1214 exportSeries( xChartType, nAttachedAxis );
1215 // firstSliceAng
1216 exportFirstSliceAng( );
1217 //FIXME: holeSize
1218 sal_Int32 nHoleSize = 50;
1219 pFS->singleElement( FSNS( XML_c, XML_holeSize ),
1220 XML_val, I32S( nHoleSize ),
1221 FSEND );
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;
1232 if( mbIs3DChart )
1233 nTypeId = XML_line3DChart;
1234 pFS->startElement( FSNS( XML_c, nTypeId ),
1235 FSEND );
1237 exportGrouping( );
1238 // TODO: show marker symbol in series?
1239 sal_Int32 nAttachedAxis = AXIS_PRIMARY_Y;
1240 exportSeries( xChartType, nAttachedAxis );
1242 // show marker?
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 ),
1250 XML_val, marker,
1251 FSEND );
1253 exportAxesId( nAttachedAxis );
1255 pFS->endElement( FSNS( XML_c, nTypeId ) );
1258 void ChartExport::exportOfPieChart( Reference< chart2::XChartType > /*xChartType*/ )
1260 // TODO:
1263 void ChartExport::exportPieChart( Reference< chart2::XChartType > xChartType )
1265 FSHelperPtr pFS = GetFS();
1266 sal_Int32 nTypeId = XML_pieChart;
1267 if( mbIs3DChart )
1268 nTypeId = XML_pie3DChart;
1269 pFS->startElement( FSNS( XML_c, nTypeId ),
1270 FSEND );
1271 // TODO: varyColors
1272 const char* varyColors = "1";
1273 pFS->singleElement( FSNS( XML_c, XML_varyColors ),
1274 XML_val, varyColors,
1275 FSEND );
1277 sal_Int32 nAttachedAxis = AXIS_PRIMARY_Y;
1278 exportSeries( xChartType, nAttachedAxis );
1280 if( !mbIs3DChart )
1282 // firstSliceAng
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 ),
1293 FSEND );
1295 // radarStyle
1296 sal_Int32 eChartType = getChartType( );
1297 const char* radarStyle = NULL;
1298 if( eChartType == chart::TYPEID_RADARAREA )
1299 radarStyle = "filled";
1300 else
1301 radarStyle = "marker";
1302 pFS->singleElement( FSNS( XML_c, XML_radarStyle ),
1303 XML_val, radarStyle,
1304 FSEND );
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 ),
1316 FSEND );
1317 // TODO:scatterStyle
1318 const char* scatterStyle = "lineMarker";
1319 pFS->singleElement( FSNS( XML_c, XML_scatterStyle ),
1320 XML_val, scatterStyle,
1321 FSEND );
1323 pFS->singleElement( FSNS( XML_c, XML_varyColors ),
1324 XML_val, "0",
1325 FSEND );
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 ),
1339 FSEND );
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())
1347 // stock-range-line
1348 Reference< beans::XPropertySet > xStockPropSet = xStockPropProvider->getMinMaxLine();
1349 if( xStockPropSet.is() )
1351 pFS->startElement( FSNS( XML_c, XML_hiLowLines ),
1352 FSEND );
1353 exportShapeProps( xStockPropSet );
1354 pFS->endElement( FSNS( XML_c, XML_hiLowLines ) );
1356 // stock updownbar
1357 pFS->startElement( FSNS( XML_c, XML_upDownBars ),
1358 FSEND );
1359 // TODO: gapWidth
1360 sal_Int32 nGapWidth = 150;
1361 pFS->singleElement( FSNS( XML_c, XML_gapWidth ),
1362 XML_val, I32S( nGapWidth ),
1363 FSEND );
1365 xStockPropSet = xStockPropProvider->getUpBar();
1366 if( xStockPropSet.is() )
1368 pFS->startElement( FSNS( XML_c, XML_upBars ),
1369 FSEND );
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 ),
1378 FSEND );
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;
1394 if( mbIs3DChart )
1395 nTypeId = XML_surface3DChart;
1396 pFS->startElement( FSNS( XML_c, nTypeId ),
1397 FSEND );
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 );
1410 if( ! xDSCnt.is())
1411 return;
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 );
1421 if( xCTProp.is())
1422 xCTProp->getPropertyValue( OUString("Japanese")) >>= bJapaneseCandleSticks;
1423 exportCandleStickSeries(
1424 xDSCnt->getDataSeries(), bJapaneseCandleSticks, nAttachedAxis );
1425 return;
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 )
1433 // export series
1434 Reference< chart2::data::XDataSource > xSource( aSeriesSeq[nSeriesIdx], uno::UNO_QUERY );
1435 if( xSource.is())
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 )
1448 OUString aRole;
1449 Reference< chart2::data::XDataSequence > xTempValueSeq( aSeqCnt[nSeqIdx]->getValues() );
1450 if( nMainSequenceIndex==-1 )
1452 Reference< beans::XPropertySet > xSeqProp( xTempValueSeq, uno::UNO_QUERY );
1453 if( xSeqProp.is())
1454 xSeqProp->getPropertyValue(OUString("Role")) >>= aRole;
1455 // "main" sequence
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 ),
1473 FSEND );
1475 // TODO: idx and order
1476 pFS->singleElement( FSNS( XML_c, XML_idx ),
1477 XML_val, I32S(nSeriesIdx),
1478 FSEND );
1479 pFS->singleElement( FSNS( XML_c, XML_order ),
1480 XML_val, I32S(nSeriesIdx),
1481 FSEND );
1483 // export label
1484 if( xLabelSeq.is() )
1485 exportSeriesText( xLabelSeq );
1487 // export shape properties
1488 Reference< XPropertySet > xPropSet = SchXMLSeriesHelper::createOldAPISeriesPropertySet(
1489 aSeriesSeq[nSeriesIdx], getModel() );
1490 if( xPropSet.is() )
1492 if( GetProperty( xPropSet, "Axis") )
1494 mAny >>= nAttachedAxis;
1495 if( nAttachedAxis == ::com::sun::star::chart::ChartAxisAssign::SECONDARY_Y )
1496 nAttachedAxis = AXIS_SECONDARY_Y;
1497 else
1498 nAttachedAxis = AXIS_PRIMARY_Y;
1500 exportShapeProps( xPropSet );
1503 switch( eChartType )
1505 case chart::TYPEID_LINE:
1507 exportMarker( );
1508 break;
1510 case chart::TYPEID_PIE:
1511 case chart::TYPEID_DOUGHNUT:
1513 if( xPropSet.is() && GetProperty( xPropSet, "SegmentOffset") )
1515 sal_Int32 nOffset = 0;
1516 mAny >>= nOffset;
1517 pFS->singleElement( FSNS( XML_c, XML_explosion ),
1518 XML_val, I32S( nOffset ),
1519 FSEND );
1521 break;
1523 case chart::TYPEID_SCATTER:
1525 exportMarker( );
1526 exportSmooth( );
1527 break;
1529 case chart::TYPEID_RADARLINE:
1531 exportMarker( );
1532 break;
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) )
1563 // export xVal
1564 Reference< chart2::data::XLabeledDataSequence > xSequence( lcl_getDataSequenceByRole( aSeqCnt, OUString("values-x") ) );
1565 if( xSequence.is() )
1567 Reference< chart2::data::XDataSequence > xValues( xSequence->getValues() );
1568 if( xValues.is() )
1569 exportSeriesValues( xValues, XML_xVal );
1574 if( eChartType == chart::TYPEID_BUBBLE )
1576 // export yVal
1577 Reference< chart2::data::XLabeledDataSequence > xSequence( lcl_getDataSequenceByRole( aSeqCnt, OUString("values-y") ) );
1578 if( xSequence.is() )
1580 Reference< chart2::data::XDataSequence > xValues( xSequence->getValues() );
1581 if( xValues.is() )
1582 exportSeriesValues( xValues, XML_yVal );
1586 // export values
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 );
1615 if( xSource.is())
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 ),
1635 FSEND );
1637 // TODO: idx and order
1638 pFS->singleElement( FSNS( XML_c, XML_idx ),
1639 XML_val, I32S(idx),
1640 FSEND );
1641 pFS->singleElement( FSNS( XML_c, XML_order ),
1642 XML_val, I32S(idx),
1643 FSEND );
1645 // export label
1646 if( xLabelSeq.is() )
1647 exportSeriesText( xLabelSeq );
1649 // TODO:export shape properties
1651 // export categories
1652 if( mxCategoriesValues.is() )
1653 exportSeriesCategory( mxCategoriesValues );
1655 // export values
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 ),
1674 FSEND );
1676 OUString aCellRange = xValueSeq->getSourceRangeRepresentation();
1677 aCellRange = parseFormula( aCellRange );
1678 pFS->startElement( FSNS( XML_c, XML_strRef ),
1679 FSEND );
1681 pFS->startElement( FSNS( XML_c, XML_f ),
1682 FSEND );
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 ),
1688 FSEND );
1689 pFS->singleElement( FSNS( XML_c, XML_ptCount ),
1690 XML_val, "1",
1691 FSEND );
1692 pFS->startElement( FSNS( XML_c, XML_pt ),
1693 XML_idx, "0",
1694 FSEND );
1695 pFS->startElement( FSNS( XML_c, XML_v ),
1696 FSEND );
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 ),
1710 FSEND );
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 ),
1716 FSEND );
1718 pFS->startElement( FSNS( XML_c, XML_f ),
1719 FSEND );
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 ),
1727 FSEND );
1728 pFS->singleElement( FSNS( XML_c, XML_ptCount ),
1729 XML_val, I32S( ptCount ),
1730 FSEND );
1731 for( sal_Int32 i = 0; i < ptCount; i++ )
1733 pFS->startElement( FSNS( XML_c, XML_pt ),
1734 XML_idx, I32S( i ),
1735 FSEND );
1736 pFS->startElement( FSNS( XML_c, XML_v ),
1737 FSEND );
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 ),
1753 FSEND );
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 ),
1759 FSEND );
1761 pFS->startElement( FSNS( XML_c, XML_f ),
1762 FSEND );
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 ),
1770 FSEND );
1771 pFS->startElement( FSNS( XML_c, XML_formatCode ),
1772 FSEND );
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 ),
1778 FSEND );
1779 for( sal_Int32 i = 0; i < ptCount; i++ )
1781 pFS->startElement( FSNS( XML_c, XML_pt ),
1782 XML_idx, I32S( i ),
1783 FSEND );
1784 pFS->startElement( FSNS( XML_c, XML_v ),
1785 FSEND );
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 ),
1801 FSEND );
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
1917 sAxPos = "b";
1918 break;
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
1934 sAxPos = "l";
1935 break;
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
1956 sAxPos = "b";
1957 break;
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
1972 sAxPos = "l";
1973 break;
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 ),
1992 FSEND );
1993 pFS->singleElement( FSNS( XML_c, XML_axId ),
1994 XML_val, I32S( aAxisIdPair.nAxisId ),
1995 FSEND );
1997 pFS->startElement( FSNS( XML_c, XML_scaling ),
1998 FSEND );
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,
2007 FSEND );
2008 // logBase, min, max
2009 if(GetProperty( xAxisProp, "Logarithmic" ) )
2011 sal_Bool bLogarithmic = sal_False;
2012 mAny >>= bLogarithmic;
2013 if( bLogarithmic )
2015 // default value is 10?
2016 sal_Int32 nLogBase = 10;
2017 pFS->singleElement( FSNS( XML_c, XML_logBase ),
2018 XML_val, I32S( nLogBase ),
2019 FSEND );
2022 sal_Bool bAutoMax = sal_False;
2023 if(GetProperty( xAxisProp, "AutoMax" ) )
2024 mAny >>= bAutoMax;
2026 if( !bAutoMax && (GetProperty( xAxisProp, "Max" ) ) )
2028 double dMax = 0;
2029 mAny >>= dMax;
2030 pFS->singleElement( FSNS( XML_c, XML_max ),
2031 XML_val, IS( dMax ),
2032 FSEND );
2035 sal_Bool bAutoMin = sal_False;
2036 if(GetProperty( xAxisProp, "AutoMin" ) )
2037 mAny >>= bAutoMin;
2039 if( !bAutoMin && (GetProperty( xAxisProp, "Min" ) ) )
2041 double dMin = 0;
2042 mAny >>= dMin;
2043 pFS->singleElement( FSNS( XML_c, XML_min ),
2044 XML_val, IS( dMin ),
2045 FSEND );
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",
2059 FSEND );
2061 // FIXME: axPos, need to check the property "ReverseDirection"
2062 pFS->singleElement( FSNS( XML_c, XML_axPos ),
2063 XML_val, sAxisPos,
2064 FSEND );
2065 // major grid line
2066 if( xMajorGrid.is())
2068 pFS->startElement( FSNS( XML_c, XML_majorGridlines ),
2069 FSEND );
2070 exportShapeProps( xMajorGrid );
2071 pFS->endElement( FSNS( XML_c, XML_majorGridlines ) );
2074 // minor grid line
2075 if( xMinorGrid.is())
2077 pFS->startElement( FSNS( XML_c, XML_minorGridlines ),
2078 FSEND );
2079 exportShapeProps( xMajorGrid );
2080 pFS->endElement( FSNS( XML_c, XML_minorGridlines ) );
2083 // title
2084 if( xAxisTitle.is() )
2085 exportTitle( xAxisTitle );
2087 // majorTickMark
2088 sal_Int32 nValue = 0;
2089 if(GetProperty( xAxisProp, "Marks" ) )
2091 mAny >>= nValue;
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";
2097 else if( bInner )
2098 majorTickMark = "in";
2099 else if( bOuter )
2100 majorTickMark = "out";
2101 else
2102 majorTickMark = "none";
2103 pFS->singleElement( FSNS( XML_c, XML_majorTickMark ),
2104 XML_val, majorTickMark,
2105 FSEND );
2107 // minorTickMark
2108 if(GetProperty( xAxisProp, "HelpMarks" ) )
2110 mAny >>= nValue;
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";
2116 else if( bInner )
2117 minorTickMark = "in";
2118 else if( bOuter )
2119 minorTickMark = "out";
2120 else
2121 minorTickMark = "none";
2122 pFS->singleElement( FSNS( XML_c, XML_minorTickMark ),
2123 XML_val, minorTickMark,
2124 FSEND );
2126 // tickLblPos
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";
2140 break;
2141 case ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_START:
2142 sTickLblPos = "low";
2143 break;
2144 case ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_END:
2145 sTickLblPos = "high";
2146 break;
2147 default:
2148 sTickLblPos = "nextTo";
2149 break;
2152 else
2154 sTickLblPos = "none";
2156 pFS->singleElement( FSNS( XML_c, XML_tickLblPos ),
2157 XML_val, sTickLblPos,
2158 FSEND );
2160 // shape properties
2161 exportShapeProps( xAxisProp );
2163 pFS->singleElement( FSNS( XML_c, XML_crossAx ),
2164 XML_val, I32S( aAxisIdPair.nCrossAx ),
2165 FSEND );
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 );
2173 mAny >>= ePosition;
2174 switch( ePosition )
2176 case ::com::sun::star::chart::ChartAxisPosition_START:
2177 sCrosses = "min";
2178 break;
2179 case ::com::sun::star::chart::ChartAxisPosition_END:
2180 sCrosses = "max";
2181 break;
2182 case ::com::sun::star::chart::ChartAxisPosition_ZERO:
2183 sCrosses = "autoZero";
2184 break;
2185 default:
2186 bCrossesValue = sal_True;
2187 break;
2191 if( bCrossesValue && GetProperty( xAxisProp, "CrossoverValue" ) )
2193 double dValue = 0;
2194 mAny >>= dValue;
2195 pFS->singleElement( FSNS( XML_c, XML_crossesAt ),
2196 XML_val, IS( dValue ),
2197 FSEND );
2199 else
2201 pFS->singleElement( FSNS( XML_c, XML_crosses ),
2202 XML_val, sCrosses,
2203 FSEND );
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 ),
2212 XML_val, isAuto,
2213 FSEND );
2215 if( nAxisType == XML_catAx )
2217 // FIXME: seems not support? lblAlgn
2218 const char* sLblAlgn = "ctr";
2219 pFS->singleElement( FSNS( XML_c, XML_lblAlgn ),
2220 XML_val, sLblAlgn,
2221 FSEND );
2224 // FIXME: seems not support? lblOffset
2225 sal_Int32 nLblOffset = 100;
2226 pFS->singleElement( FSNS( XML_c, XML_lblOffset ),
2227 XML_val, I32S( nLblOffset ),
2228 FSEND );
2231 // majorUnit
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 ),
2242 FSEND );
2244 // minorUnit
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 ),
2255 FSEND );
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 ),
2274 FSEND );
2276 sal_Int32 nElem;
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 );
2291 if( xPropSet.is() )
2293 namespace cssc2 = ::com::sun::star::chart2;
2294 cssc2::DataPointLabel aLabel;
2295 if (GetProperty( xPropSet, "Label"))
2297 mAny >>= aLabel;
2299 namespace csscd = ::com::sun::star::chart::DataLabelPlacement;
2300 sal_Int32 nPlacement(csscd::AVOID_OVERLAP);
2301 const char *aPlacement = NULL;
2302 OUString aSep;
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"))
2339 mAny >>= aSep;
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();
2369 sal_Int32 nElement;
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 );
2396 else
2398 // property set only containing the color
2399 xPropSet.set( new ColorPropertySet( xColorScheme->getColorByIndex( nElement )));
2402 if( xPropSet.is() )
2404 OSL_TRACE("ChartExport::exportDataPoints -- writer data points ");
2405 FSHelperPtr pFS = GetFS();
2406 pFS->startElement( FSNS( XML_c, XML_dPt ),
2407 FSEND );
2408 pFS->singleElement( FSNS( XML_c, XML_idx ),
2409 XML_val, I32S(nElement),
2410 FSEND );
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 ),
2428 FSEND );
2429 pFS->singleElement( FSNS( XML_c, XML_axId ),
2430 XML_val, I32S( nAxisIdy ),
2431 FSEND );
2432 if( mbHasZAxis )
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 ),
2442 FSEND );
2446 void ChartExport::exportGrouping( sal_Bool isBar )
2448 FSHelperPtr pFS = GetFS();
2449 Reference< XPropertySet > xPropSet( mxDiagram , uno::UNO_QUERY);
2450 // grouping
2451 sal_Bool bStacked = sal_False;
2452 if( GetProperty( xPropSet, "Stacked" ) )
2453 mAny >>= bStacked;
2454 sal_Bool bPercentage = sal_False;
2455 if( GetProperty( xPropSet, "Percent" ) )
2456 mAny >>= bPercentage;
2458 const char* grouping = NULL;
2459 if( bStacked )
2460 grouping = "stacked";
2461 else if( bPercentage )
2462 grouping = "percentStacked";
2463 else
2465 if( isBar && !isDeep3dChart() )
2466 grouping = "clustered";
2467 else
2468 grouping = "standard";
2470 pFS->singleElement( FSNS( XML_c, XML_grouping ),
2471 XML_val, grouping,
2472 FSEND );
2475 void ChartExport::exportMarker()
2477 FSHelperPtr pFS = GetFS();
2478 pFS->startElement( FSNS( XML_c, XML_marker ),
2479 FSEND );
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";
2491 break;
2492 case cssc::ChartSymbolType::SYMBOL0:
2493 pSymbolType = "square";
2494 break;
2495 case cssc::ChartSymbolType::SYMBOL1:
2496 pSymbolType = "diamond";
2497 break;
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";
2504 break;
2505 case cssc::ChartSymbolType::SYMBOL6:
2506 pSymbolType = "plus";
2507 break;
2508 case cssc::ChartSymbolType::SYMBOL7:
2509 pSymbolType = "plus";
2510 break;
2511 case cssc::ChartSymbolType::AUTO:
2512 break;
2513 case cssc::ChartSymbolType::BITMAPURL:
2514 break;
2515 default:
2516 SAL_WARN("oox", "unknown data series symbol");
2519 if( pSymbolType )
2521 pFS->singleElement( FSNS( XML_c, XML_symbol ),
2522 XML_val, pSymbolType,
2523 FSEND );
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),
2537 FSEND );
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 ),
2553 XML_val, "1",
2554 FSEND );
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 ),
2570 FSEND );
2573 namespace {
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
2582 return "fixedVal";
2583 case cssc::ErrorBarStyle::VARIANCE:
2584 break;
2585 case cssc::ErrorBarStyle::STANDARD_DEVIATION:
2586 return "stdDev";
2587 case cssc::ErrorBarStyle::ABSOLUTE:
2588 return "fixedVal";
2589 case cssc::ErrorBarStyle::RELATIVE:
2590 return "percentage";
2591 case cssc::ErrorBarStyle::ERROR_MARGIN:
2592 break;
2593 case cssc::ErrorBarStyle::STANDARD_ERROR:
2594 return "stdErr";
2595 case cssc::ErrorBarStyle::FROM_DATA:
2596 return "cust";
2597 default:
2598 assert(false); // can't happen
2600 return "";
2603 Reference< chart2::data::XDataSequence> getLabeledSequence(
2604 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aSequences,
2605 bool bPositive )
2607 const OUString aRolePrefix( "error-bars" );
2608 OUString aDirection;
2609 if(bPositive)
2610 aDirection = "positive";
2611 else
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 );
2620 OUString aRole;
2621 if( ( xSeqProp->getPropertyValue(
2622 OUString( "Role" )) >>= aRole ) &&
2623 aRole.match( aRolePrefix ) && aRole.indexOf(aDirection) >= 0 )
2625 return xSequence;
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 ),
2639 FSEND );
2640 pFS->singleElement( FSNS( XML_c, XML_errDir ),
2641 XML_val, bYError ? "y" : "x",
2642 FSEND );
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";
2649 else if(bPositive)
2650 pErrBarType = "plus";
2651 else if(bNegative)
2652 pErrBarType = "minus";
2653 else
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,
2661 FSEND );
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,
2668 FSEND );
2669 pFS->singleElement( FSNS( XML_c, XML_noEndCap ),
2670 XML_val, "0",
2671 FSEND );
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();
2678 if(bPositive)
2680 exportSeriesValues(getLabeledSequence(aSequences, true), XML_plus);
2683 if(bNegative)
2685 exportSeriesValues(getLabeledSequence(aSequences, false), XML_minus);
2688 else
2690 double nVal = 0.0;
2691 if(nErrorBarStyle == cssc::ErrorBarStyle::STANDARD_DEVIATION)
2693 xErrorBarProps->getPropertyValue("Weight") >>= nVal;
2695 else
2697 if(bPositive)
2698 xErrorBarProps->getPropertyValue("PositiveError") >>= nVal;
2699 else
2700 xErrorBarProps->getPropertyValue("NegativeError") >>= nVal;
2703 OString aVal = OString::number(nVal);
2705 pFS->singleElement( FSNS( XML_c, XML_val ),
2706 XML_val, aVal.getStr(),
2707 FSEND );
2710 pFS->endElement( FSNS( XML_c, XML_errBars) );
2713 void ChartExport::exportView3D()
2715 Reference< XPropertySet > xPropSet( mxDiagram , uno::UNO_QUERY);
2716 if( !xPropSet.is() )
2717 return;
2718 FSHelperPtr pFS = GetFS();
2719 pFS->startElement( FSNS( XML_c, XML_view3D ),
2720 FSEND );
2721 // rotX
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 )
2728 nRotationX += 360;
2729 pFS->singleElement( FSNS( XML_c, XML_rotX ),
2730 XML_val, I32S( nRotationX ),
2731 FSEND );
2733 // rotY
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 )
2740 nRotationY += 360;
2741 pFS->singleElement( FSNS( XML_c, XML_rotY ),
2742 XML_val, I32S( nRotationY ),
2743 FSEND );
2745 // rAngAx
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,
2753 FSEND );
2755 // perspective
2756 if( GetProperty( xPropSet, "Perspective" ) )
2758 sal_Int32 nPerspective = 0;
2759 mAny >>= nPerspective;
2760 // map Chart2 [0,100] to OOXML [0..200]
2761 nPerspective *= 2;
2762 pFS->singleElement( FSNS( XML_c, XML_perspective ),
2763 XML_val, I32S( nPerspective ),
2764 FSEND );
2766 pFS->endElement( FSNS( XML_c, XML_view3D ) );
2769 sal_Bool ChartExport::isDeep3dChart()
2771 sal_Bool isDeep = sal_False;
2772 if( mbIs3DChart )
2774 Reference< XPropertySet > xPropSet( mxDiagram , uno::UNO_QUERY);
2775 if( GetProperty( xPropSet, "Deep" ) )
2776 mAny >>= isDeep;
2778 return isDeep;
2781 }// drawingml
2782 }// oox
2784 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */