Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <oox/token/tokens.hxx>
21 : #include "oox/core/xmlfilterbase.hxx"
22 : #include "oox/export/chartexport.hxx"
23 : #include "oox/export/utils.hxx"
24 : #include "drawingml/chart/typegroupconverter.hxx"
25 :
26 : #include <cstdio>
27 :
28 : #include <com/sun/star/awt/Gradient.hpp>
29 : #include <com/sun/star/chart/XChartDocument.hpp>
30 : #include <com/sun/star/chart/ChartLegendPosition.hpp>
31 : #include <com/sun/star/chart/XTwoAxisXSupplier.hpp>
32 : #include <com/sun/star/chart/XTwoAxisYSupplier.hpp>
33 : #include <com/sun/star/chart/XAxisZSupplier.hpp>
34 : #include <com/sun/star/chart/XChartDataArray.hpp>
35 : #include <com/sun/star/chart/ChartDataRowSource.hpp>
36 : #include <com/sun/star/chart/ChartAxisAssign.hpp>
37 : #include <com/sun/star/chart/ChartSeriesAddress.hpp>
38 : #include <com/sun/star/chart/X3DDisplay.hpp>
39 : #include <com/sun/star/chart/XStatisticDisplay.hpp>
40 : #include <com/sun/star/chart/XSecondAxisTitleSupplier.hpp>
41 : #include <com/sun/star/chart/ChartSymbolType.hpp>
42 : #include <com/sun/star/chart/ChartAxisMarks.hpp>
43 : #include <com/sun/star/chart/ChartAxisLabelPosition.hpp>
44 : #include <com/sun/star/chart/ChartAxisPosition.hpp>
45 : #include <com/sun/star/chart/ChartSolidType.hpp>
46 : #include <com/sun/star/chart/DataLabelPlacement.hpp>
47 : #include <com/sun/star/chart/ErrorBarStyle.hpp>
48 : #include <com/sun/star/chart/MissingValueTreatment.hpp>
49 :
50 : #include <com/sun/star/chart2/XChartDocument.hpp>
51 : #include <com/sun/star/chart2/XDiagram.hpp>
52 : #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
53 : #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
54 : #include <com/sun/star/chart2/XChartTypeContainer.hpp>
55 : #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
56 : #include <com/sun/star/chart2/DataPointGeometry3D.hpp>
57 : #include <com/sun/star/chart2/DataPointLabel.hpp>
58 : #include <com/sun/star/chart2/Symbol.hpp>
59 : #include <com/sun/star/chart2/data/XDataSource.hpp>
60 : #include <com/sun/star/chart2/data/XDataSink.hpp>
61 : #include <com/sun/star/chart2/data/XDataReceiver.hpp>
62 : #include <com/sun/star/chart2/data/XDataProvider.hpp>
63 : #include <com/sun/star/chart2/data/XDatabaseDataProvider.hpp>
64 : #include <com/sun/star/chart2/data/XRangeXMLConversion.hpp>
65 : #include <com/sun/star/chart2/data/XTextualDataSequence.hpp>
66 : #include <com/sun/star/chart2/data/XNumericalDataSequence.hpp>
67 :
68 : #include <com/sun/star/beans/XPropertySet.hpp>
69 : #include <com/sun/star/beans/XPropertyState.hpp>
70 : #include <com/sun/star/container/XEnumerationAccess.hpp>
71 : #include <com/sun/star/drawing/XShape.hpp>
72 : #include <com/sun/star/drawing/FillStyle.hpp>
73 : #include <com/sun/star/drawing/BitmapMode.hpp>
74 : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
75 : #include <com/sun/star/lang/XServiceName.hpp>
76 :
77 : #include <com/sun/star/table/CellAddress.hpp>
78 : #include <com/sun/star/sheet/XFormulaParser.hpp>
79 : #include <com/sun/star/sheet/XFormulaTokens.hpp>
80 : #include <com/sun/star/sheet/FormulaToken.hpp>
81 : #include <com/sun/star/sheet/AddressConvention.hpp>
82 :
83 : #include <com/sun/star/text/WritingMode.hpp>
84 : #include <com/sun/star/container/XNamed.hpp>
85 : #include <com/sun/star/embed/XVisualObject.hpp>
86 : #include <com/sun/star/embed/Aspects.hpp>
87 :
88 : #include <comphelper/processfactory.hxx>
89 : #include <comphelper/random.hxx>
90 : #include <xmloff/SchXMLSeriesHelper.hxx>
91 : #include "ColorPropertySet.hxx"
92 : #include <set>
93 : #include <unordered_set>
94 :
95 : #include <rtl/math.hxx>
96 :
97 : using namespace css;
98 : using namespace css::uno;
99 : using namespace css::drawing;
100 : using namespace ::oox::core;
101 : using css::beans::PropertyState;
102 : using css::beans::PropertyValue;
103 : using css::beans::XPropertySet;
104 : using css::beans::XPropertyState;
105 : using css::container::XEnumeration;
106 : using css::container::XEnumerationAccess;
107 : using css::container::XIndexAccess;
108 : using css::container::XNamed;
109 : using css::io::XOutputStream;
110 : using css::table::CellAddress;
111 : using css::sheet::XFormulaParser;
112 : using css::sheet::XFormulaTokens;
113 : using ::oox::core::XmlFilterBase;
114 : using ::sax_fastparser::FSHelperPtr;
115 :
116 : namespace cssc = css::chart;
117 :
118 : namespace oox { namespace drawingml {
119 :
120 : namespace {
121 :
122 121 : sal_Int32 translateFromChart2AxisIndexToOox(sal_Int32 nIndex)
123 : {
124 : assert(nIndex == 0 || nIndex == 1);
125 121 : if (nIndex == 1)
126 4 : return AXIS_SECONDARY_Y;
127 117 : return AXIS_PRIMARY_Y;
128 : }
129 :
130 : }
131 :
132 309 : class lcl_MatchesRole : public ::std::unary_function< Reference< chart2::data::XLabeledDataSequence >, bool >
133 : {
134 : public:
135 143 : explicit lcl_MatchesRole( const OUString & aRole ) :
136 143 : m_aRole( aRole )
137 143 : {}
138 :
139 301 : bool operator () ( const Reference< chart2::data::XLabeledDataSequence > & xSeq ) const
140 : {
141 301 : if( !xSeq.is() )
142 0 : return false;
143 301 : Reference< beans::XPropertySet > xProp( xSeq->getValues(), uno::UNO_QUERY );
144 602 : OUString aRole;
145 :
146 903 : return ( xProp.is() &&
147 301 : (xProp->getPropertyValue(
148 2107 : OUString( "Role" ) ) >>= aRole ) &&
149 903 : m_aRole.equals( aRole ));
150 : }
151 :
152 : private:
153 : OUString m_aRole;
154 : };
155 :
156 : template< typename T >
157 122 : void lcl_SequenceToVectorAppend( const Sequence< T > & rSource, ::std::vector< T > & rDestination )
158 : {
159 122 : rDestination.reserve( rDestination.size() + rSource.getLength());
160 122 : ::std::copy( rSource.begin(), rSource.end(),
161 122 : ::std::back_inserter( rDestination ));
162 122 : }
163 :
164 97 : Reference< chart2::data::XLabeledDataSequence > lcl_getCategories( const Reference< chart2::XDiagram > & xDiagram )
165 : {
166 97 : Reference< chart2::data::XLabeledDataSequence > xResult;
167 : try
168 : {
169 : Reference< chart2::XCoordinateSystemContainer > xCooSysCnt(
170 97 : xDiagram, uno::UNO_QUERY_THROW );
171 : Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq(
172 194 : xCooSysCnt->getCoordinateSystems());
173 194 : for( sal_Int32 i=0; i<aCooSysSeq.getLength(); ++i )
174 : {
175 97 : Reference< chart2::XCoordinateSystem > xCooSys( aCooSysSeq[i] );
176 : OSL_ASSERT( xCooSys.is());
177 414 : for( sal_Int32 nN = xCooSys->getDimension(); nN--; )
178 : {
179 220 : const sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nN);
180 373 : for(sal_Int32 nI=0; nI<=nMaxAxisIndex; ++nI)
181 : {
182 227 : Reference< chart2::XAxis > xAxis = xCooSys->getAxisByDimension( nN, nI );
183 : OSL_ASSERT( xAxis.is());
184 227 : if( xAxis.is())
185 : {
186 227 : chart2::ScaleData aScaleData = xAxis->getScaleData();
187 227 : if( aScaleData.Categories.is())
188 : {
189 74 : xResult.set( aScaleData.Categories );
190 74 : break;
191 153 : }
192 : }
193 153 : }
194 : }
195 194 : }
196 : }
197 0 : catch( const uno::Exception & ex )
198 : {
199 : (void)ex; // avoid warning for pro build
200 : OSL_FAIL( OUStringToOString(
201 : "Exception caught. Type: " +
202 : OUString::createFromAscii( typeid( ex ).name()) +
203 : ", Message: " +
204 : ex.Message, RTL_TEXTENCODING_ASCII_US ).getStr());
205 : }
206 :
207 97 : return xResult;
208 : }
209 :
210 60 : Reference< chart2::data::XDataSource > lcl_createDataSource(
211 : const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aData )
212 : {
213 : Reference< uno::XComponentContext > xContext(
214 60 : comphelper::getProcessComponentContext() );
215 : Reference< chart2::data::XDataSink > xSink(
216 120 : xContext->getServiceManager()->createInstanceWithContext(
217 60 : "com.sun.star.chart2.data.DataSource", xContext ),
218 120 : uno::UNO_QUERY_THROW );
219 60 : if( xSink.is())
220 60 : xSink->setData( aData );
221 :
222 120 : return Reference< chart2::data::XDataSource >( xSink, uno::UNO_QUERY );
223 : }
224 :
225 60 : Sequence< Reference< chart2::data::XLabeledDataSequence > > lcl_getAllSeriesSequences( const Reference< chart2::XChartDocument >& xChartDoc )
226 : {
227 60 : ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aContainer;
228 60 : if( xChartDoc.is() )
229 : {
230 60 : Reference< chart2::XDiagram > xDiagram( xChartDoc->getFirstDiagram());
231 120 : ::std::vector< Reference< chart2::XDataSeries > > aSeriesVector( SchXMLSeriesHelper::getDataSeriesFromDiagram( xDiagram ));
232 546 : for( ::std::vector< Reference< chart2::XDataSeries > >::const_iterator aSeriesIt( aSeriesVector.begin() )
233 364 : ; aSeriesIt != aSeriesVector.end(); ++aSeriesIt )
234 : {
235 122 : Reference< chart2::data::XDataSource > xDataSource( *aSeriesIt, uno::UNO_QUERY );
236 122 : if( !xDataSource.is() )
237 0 : continue;
238 244 : uno::Sequence< Reference< chart2::data::XLabeledDataSequence > > aDataSequences( xDataSource->getDataSequences() );
239 122 : lcl_SequenceToVectorAppend( aDataSequences, aContainer );
240 182 : }
241 : }
242 :
243 60 : Sequence< Reference< chart2::data::XLabeledDataSequence > > aRet( aContainer.size());
244 60 : ::std::copy( aContainer.begin(), aContainer.end(), aRet.getArray());
245 :
246 60 : return aRet;
247 : }
248 :
249 : Reference< chart2::data::XLabeledDataSequence >
250 83 : lcl_getDataSequenceByRole(
251 : const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aLabeledSeq,
252 : const OUString & rRole )
253 : {
254 83 : Reference< chart2::data::XLabeledDataSequence > aNoResult;
255 :
256 83 : const Reference< chart2::data::XLabeledDataSequence > * pBegin = aLabeledSeq.getConstArray();
257 83 : const Reference< chart2::data::XLabeledDataSequence > * pEnd = pBegin + aLabeledSeq.getLength();
258 : const Reference< chart2::data::XLabeledDataSequence > * pMatch =
259 83 : ::std::find_if( pBegin, pEnd, lcl_MatchesRole( rRole ));
260 :
261 83 : if( pMatch != pEnd )
262 29 : return *pMatch;
263 :
264 54 : return aNoResult;
265 : }
266 :
267 60 : Reference< chart2::data::XDataSource > lcl_pressUsedDataIntoRectangularFormat( const Reference< chart2::XChartDocument >& xChartDoc, bool& rOutSourceHasCategoryLabels )
268 : {
269 60 : ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aLabeledSeqVector;
270 :
271 : //categories are always the first sequence
272 120 : Reference< chart2::XDiagram > xDiagram( xChartDoc->getFirstDiagram());
273 120 : Reference< chart2::data::XLabeledDataSequence > xCategories( lcl_getCategories( xDiagram ) );
274 60 : if( xCategories.is() )
275 37 : aLabeledSeqVector.push_back( xCategories );
276 60 : rOutSourceHasCategoryLabels = xCategories.is();
277 :
278 : Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeriesSeqVector(
279 120 : lcl_getAllSeriesSequences( xChartDoc ) );
280 :
281 : //the first x-values is always the next sequence //todo ... other x-values get lost for old format
282 : Reference< chart2::data::XLabeledDataSequence > xXValues(
283 120 : lcl_getDataSequenceByRole( aSeriesSeqVector, OUString("values-x") ) );
284 60 : if( xXValues.is() )
285 9 : aLabeledSeqVector.push_back( xXValues );
286 :
287 : //add all other sequences now without x-values
288 120 : lcl_MatchesRole aHasXValues( OUString("values-x") );
289 200 : for( sal_Int32 nN=0; nN<aSeriesSeqVector.getLength(); nN++ )
290 : {
291 140 : if( !aHasXValues( aSeriesSeqVector[nN] ) )
292 127 : aLabeledSeqVector.push_back( aSeriesSeqVector[nN] );
293 : }
294 :
295 120 : Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeq( aLabeledSeqVector.size() );
296 60 : ::std::copy( aLabeledSeqVector.begin(), aLabeledSeqVector.end(), aSeq.getArray() );
297 :
298 120 : return lcl_createDataSource( aSeq );
299 : }
300 :
301 1 : bool lcl_isSeriesAttachedToFirstAxis(
302 : const Reference< chart2::XDataSeries > & xDataSeries )
303 : {
304 1 : bool bResult=true;
305 :
306 : try
307 : {
308 1 : sal_Int32 nAxisIndex = 0;
309 1 : Reference< beans::XPropertySet > xProp( xDataSeries, uno::UNO_QUERY_THROW );
310 1 : if( xProp.is() )
311 1 : xProp->getPropertyValue("AttachedAxisIndex") >>= nAxisIndex;
312 1 : bResult = (0==nAxisIndex);
313 : }
314 0 : catch( const uno::Exception & ex )
315 : {
316 : (void)ex; // avoid warning for pro build
317 : OSL_FAIL( OUStringToOString(
318 : "Exception caught. Type: " +
319 : OUString::createFromAscii( typeid( ex ).name()) +
320 : ", Message: " +
321 : ex.Message, RTL_TEXTENCODING_ASCII_US ).getStr());
322 : }
323 :
324 1 : return bResult;
325 : }
326 :
327 121 : OUString lcl_flattenStringSequence( const Sequence< OUString > & rSequence )
328 : {
329 121 : OUStringBuffer aResult;
330 121 : bool bPrecedeWithSpace = false;
331 242 : for( sal_Int32 nIndex=0; nIndex<rSequence.getLength(); ++nIndex )
332 : {
333 121 : if( !rSequence[nIndex].isEmpty())
334 : {
335 119 : if( bPrecedeWithSpace )
336 0 : aResult.append( ' ' );
337 119 : aResult.append( rSequence[nIndex] );
338 119 : bPrecedeWithSpace = true;
339 : }
340 : }
341 121 : return aResult.makeStringAndClear();
342 : }
343 :
344 121 : OUString lcl_getLabelString( const Reference< chart2::data::XDataSequence > & xLabelSeq )
345 : {
346 121 : Sequence< OUString > aLabels;
347 :
348 242 : uno::Reference< chart2::data::XTextualDataSequence > xTextualDataSequence( xLabelSeq, uno::UNO_QUERY );
349 121 : if( xTextualDataSequence.is())
350 : {
351 121 : aLabels = xTextualDataSequence->getTextualData();
352 : }
353 0 : else if( xLabelSeq.is())
354 : {
355 0 : Sequence< uno::Any > aAnies( xLabelSeq->getData());
356 0 : aLabels.realloc( aAnies.getLength());
357 0 : for( sal_Int32 i=0; i<aAnies.getLength(); ++i )
358 0 : aAnies[i] >>= aLabels[i];
359 : }
360 :
361 242 : return lcl_flattenStringSequence( aLabels );
362 : }
363 :
364 81 : void lcl_fillCategoriesIntoStringVector(
365 : const Reference< chart2::data::XDataSequence > & xCategories,
366 : ::std::vector< OUString > & rOutCategories )
367 : {
368 : OSL_ASSERT( xCategories.is());
369 81 : if( !xCategories.is())
370 81 : return;
371 81 : Reference< chart2::data::XTextualDataSequence > xTextualDataSequence( xCategories, uno::UNO_QUERY );
372 81 : if( xTextualDataSequence.is())
373 : {
374 81 : rOutCategories.clear();
375 81 : Sequence< OUString > aTextData( xTextualDataSequence->getTextualData());
376 : ::std::copy( aTextData.begin(), aTextData.end(),
377 81 : ::std::back_inserter( rOutCategories ));
378 : }
379 : else
380 : {
381 0 : Sequence< uno::Any > aAnies( xCategories->getData());
382 0 : rOutCategories.resize( aAnies.getLength());
383 0 : for( sal_Int32 i=0; i<aAnies.getLength(); ++i )
384 0 : aAnies[i] >>= rOutCategories[i];
385 81 : }
386 : }
387 :
388 140 : ::std::vector< double > lcl_getAllValuesFromSequence( const Reference< chart2::data::XDataSequence > & xSeq )
389 : {
390 140 : double fNan = 0.0;
391 140 : ::rtl::math::setNan( &fNan );
392 140 : ::std::vector< double > aResult;
393 :
394 280 : Reference< chart2::data::XNumericalDataSequence > xNumSeq( xSeq, uno::UNO_QUERY );
395 140 : if( xNumSeq.is())
396 : {
397 140 : Sequence< double > aValues( xNumSeq->getNumericalData());
398 : ::std::copy( aValues.begin(), aValues.end(),
399 140 : ::std::back_inserter( aResult ));
400 : }
401 0 : else if( xSeq.is())
402 : {
403 0 : Sequence< uno::Any > aAnies( xSeq->getData());
404 0 : aResult.resize( aAnies.getLength(), fNan );
405 0 : for( sal_Int32 i=0; i<aAnies.getLength(); ++i )
406 0 : aAnies[i] >>= aResult[i];
407 : }
408 280 : return aResult;
409 : }
410 :
411 214 : sal_Int32 lcl_getChartType( const OUString& sChartType )
412 : {
413 214 : chart::TypeId eChartTypeId = chart::TYPEID_UNKNOWN;
414 428 : if( sChartType == "com.sun.star.chart.BarDiagram"
415 214 : || sChartType == "com.sun.star.chart2.ColumnChartType" )
416 109 : eChartTypeId = chart::TYPEID_BAR;
417 210 : else if( sChartType == "com.sun.star.chart.AreaDiagram"
418 105 : || sChartType == "com.sun.star.chart2.AreaChartType" )
419 6 : eChartTypeId = chart::TYPEID_AREA;
420 198 : else if( sChartType == "com.sun.star.chart.LineDiagram"
421 99 : || sChartType == "com.sun.star.chart2.LineChartType" )
422 30 : eChartTypeId = chart::TYPEID_LINE;
423 138 : else if( sChartType == "com.sun.star.chart.PieDiagram"
424 69 : || sChartType == "com.sun.star.chart2.PieChartType" )
425 26 : eChartTypeId = chart::TYPEID_PIE;
426 86 : else if( sChartType == "com.sun.star.chart.DonutDiagram"
427 43 : || sChartType == "com.sun.star.chart2.DonutChartType" )
428 4 : eChartTypeId = chart::TYPEID_DOUGHNUT;
429 78 : else if( sChartType == "com.sun.star.chart.XYDiagram"
430 39 : || sChartType == "com.sun.star.chart2.ScatterChartType" )
431 29 : eChartTypeId = chart::TYPEID_SCATTER;
432 20 : else if( sChartType == "com.sun.star.chart.NetDiagram"
433 10 : || sChartType == "com.sun.star.chart2.NetChartType" )
434 0 : eChartTypeId = chart::TYPEID_RADARLINE;
435 20 : else if( sChartType == "com.sun.star.chart.FilledNetDiagram"
436 10 : || sChartType == "com.sun.star.chart2.FilledNetChartType" )
437 4 : eChartTypeId = chart::TYPEID_RADARAREA;
438 12 : else if( sChartType == "com.sun.star.chart.StockDiagram"
439 6 : || sChartType == "com.sun.star.chart2.CandleStickChartType" )
440 3 : eChartTypeId = chart::TYPEID_STOCK;
441 6 : else if( sChartType == "com.sun.star.chart.BubbleDiagram"
442 3 : || sChartType == "com.sun.star.chart2.BubbleChartType" )
443 3 : eChartTypeId = chart::TYPEID_BUBBLE;
444 :
445 214 : return eChartTypeId;
446 : }
447 :
448 116 : sal_Int32 lcl_generateRandomValue()
449 : {
450 116 : return comphelper::rng::uniform_int_distribution(0, 100000000-1);
451 : }
452 :
453 60 : ChartExport::ChartExport( sal_Int32 nXmlNamespace, FSHelperPtr pFS, Reference< frame::XModel >& xModel, XmlFilterBase* pFB, DocumentType eDocumentType )
454 : : DrawingML( pFS, pFB, eDocumentType )
455 : , mnXmlNamespace( nXmlNamespace )
456 : , mnSeriesCount(0)
457 : , mxChartModel( xModel )
458 : , mbHasCategoryLabels( false )
459 : , mbHasZAxis( false )
460 : , mbIs3DChart( false )
461 : , mbStacked(false)
462 60 : , mbPercent(false)
463 : {
464 60 : }
465 :
466 24 : sal_Int32 ChartExport::GetChartID( )
467 : {
468 24 : sal_Int32 nID = GetFB()->GetUniqueId();
469 24 : return nID;
470 : }
471 :
472 86 : sal_Int32 ChartExport::getChartType( )
473 : {
474 86 : OUString sChartType = mxDiagram->getDiagramType();
475 86 : return lcl_getChartType( sChartType );
476 : }
477 :
478 342 : OUString ChartExport::parseFormula( const OUString& rRange )
479 : {
480 342 : OUString aResult;
481 684 : Reference< XFormulaParser > xParser;
482 684 : uno::Reference< lang::XMultiServiceFactory > xSF( GetFB()->getModelFactory(), uno::UNO_QUERY );
483 342 : if( xSF.is() )
484 : {
485 : try
486 : {
487 342 : xParser.set( xSF->createInstance("com.sun.star.sheet.FormulaParser"), UNO_QUERY );
488 : }
489 252 : catch( Exception& )
490 : {
491 : }
492 : }
493 :
494 : SAL_WARN_IF(!xParser.is(), "oox", "creating formula parser failed");
495 :
496 342 : if( xParser.is() )
497 : {
498 90 : Reference< XPropertySet > xParserProps( xParser, uno::UNO_QUERY );
499 90 : if( xParserProps.is() )
500 : {
501 90 : xParserProps->setPropertyValue("FormulaConvention", uno::makeAny(css::sheet::AddressConvention::OOO) );
502 : }
503 180 : uno::Sequence<sheet::FormulaToken> aTokens = xParser->parseFormula( rRange, CellAddress( 0, 0, 0 ) );
504 90 : if( xParserProps.is() )
505 : {
506 90 : xParserProps->setPropertyValue("FormulaConvention", uno::makeAny(css::sheet::AddressConvention::XL_OOX) );
507 : }
508 180 : aResult = xParser->printFormula( aTokens, CellAddress( 0, 0, 0 ) );
509 : }
510 : else
511 : {
512 : //FIXME: currently just using simple converter, e.g $Sheet1.$A$1:$C$1 -> Sheet1!$A$1:$C$1
513 252 : OUString aRange( rRange );
514 252 : if( aRange.startsWith("$") )
515 0 : aRange = aRange.copy(1);
516 252 : aRange = aRange.replaceAll(".$", "!$" );
517 252 : aResult = aRange;
518 : }
519 :
520 684 : return aResult;
521 : }
522 :
523 24 : ChartExport& ChartExport::WriteChartObj( const Reference< XShape >& xShape, sal_Int32 nChartCount )
524 : {
525 24 : FSHelperPtr pFS = GetFS();
526 :
527 24 : pFS->startElementNS( mnXmlNamespace, XML_graphicFrame, FSEND );
528 :
529 24 : pFS->startElementNS( mnXmlNamespace, XML_nvGraphicFramePr, FSEND );
530 :
531 : // TODO: get the correct chart name chart id
532 48 : OUString sName = "Object 1";
533 48 : Reference< XNamed > xNamed( xShape, UNO_QUERY );
534 24 : if (xNamed.is())
535 24 : sName = xNamed->getName();
536 :
537 24 : sal_Int32 nID = GetChartID();
538 :
539 : pFS->singleElementNS( mnXmlNamespace, XML_cNvPr,
540 : XML_id, I32S( nID ),
541 : XML_name, USS( sName ),
542 24 : FSEND );
543 :
544 : pFS->singleElementNS( mnXmlNamespace, XML_cNvGraphicFramePr,
545 24 : FSEND );
546 :
547 24 : if( GetDocumentType() == DOCUMENT_PPTX )
548 : pFS->singleElementNS( mnXmlNamespace, XML_nvPr,
549 0 : FSEND );
550 24 : pFS->endElementNS( mnXmlNamespace, XML_nvGraphicFramePr );
551 :
552 : // visual chart properties
553 24 : WriteShapeTransformation( xShape, mnXmlNamespace );
554 :
555 : // writer chart object
556 24 : pFS->startElement( FSNS( XML_a, XML_graphic ), FSEND );
557 : pFS->startElement( FSNS( XML_a, XML_graphicData ),
558 : XML_uri, "http://schemas.openxmlformats.org/drawingml/2006/chart",
559 24 : FSEND );
560 48 : OUString sId;
561 24 : const char* sFullPath = NULL;
562 24 : const char* sRelativePath = NULL;
563 24 : switch( GetDocumentType() )
564 : {
565 : case DOCUMENT_DOCX:
566 : {
567 0 : sFullPath = "word/charts/chart";
568 0 : sRelativePath = "charts/chart";
569 0 : break;
570 : }
571 : case DOCUMENT_PPTX:
572 : {
573 0 : sFullPath = "ppt/charts/chart";
574 0 : sRelativePath = "../charts/chart";
575 0 : break;
576 : }
577 : case DOCUMENT_XLSX:
578 : {
579 24 : sFullPath = "xl/charts/chart";
580 24 : sRelativePath = "../charts/chart";
581 24 : break;
582 : }
583 : default:
584 : {
585 0 : sFullPath = "charts/chart";
586 0 : sRelativePath = "charts/chart";
587 0 : break;
588 : }
589 : }
590 : OUString sFullStream = OUStringBuffer()
591 48 : .appendAscii(sFullPath)
592 24 : .append(nChartCount)
593 24 : .appendAscii( ".xml" )
594 24 : .makeStringAndClear();
595 : OUString sRelativeStream = OUStringBuffer()
596 48 : .appendAscii(sRelativePath)
597 24 : .append(nChartCount)
598 24 : .appendAscii( ".xml" )
599 48 : .makeStringAndClear();
600 : FSHelperPtr pChart = CreateOutputStream(
601 : sFullStream,
602 : sRelativeStream,
603 : pFS->getOutputStream(),
604 : "application/vnd.openxmlformats-officedocument.drawingml.chart+xml",
605 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart",
606 48 : &sId );
607 :
608 : pFS->singleElement( FSNS( XML_c, XML_chart ),
609 : FSNS( XML_xmlns, XML_c ), "http://schemas.openxmlformats.org/drawingml/2006/chart",
610 : FSNS( XML_xmlns, XML_r ), "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
611 : FSNS( XML_r, XML_id ), USS( sId ),
612 24 : FSEND );
613 :
614 24 : pFS->endElement( FSNS( XML_a, XML_graphicData ) );
615 24 : pFS->endElement( FSNS( XML_a, XML_graphic ) );
616 24 : pFS->endElementNS( mnXmlNamespace, XML_graphicFrame );
617 :
618 24 : SetFS( pChart );
619 24 : ExportContent();
620 :
621 72 : return *this;
622 : }
623 :
624 60 : void ChartExport::InitRangeSegmentationProperties( const Reference< chart2::XChartDocument > & xChartDoc )
625 : {
626 60 : if( xChartDoc.is())
627 : try
628 : {
629 60 : Reference< chart2::data::XDataProvider > xDataProvider( xChartDoc->getDataProvider() );
630 : OSL_ENSURE( xDataProvider.is(), "No DataProvider" );
631 60 : if( xDataProvider.is())
632 : {
633 60 : Reference< chart2::data::XDataSource > xDataSource( lcl_pressUsedDataIntoRectangularFormat( xChartDoc, mbHasCategoryLabels ));
634 120 : Sequence< beans::PropertyValue > aArgs( xDataProvider->detectArguments( xDataSource ));
635 120 : OUString sCellRange, sBrokenRange;
636 60 : bool bBrokenRangeAvailable = false;
637 324 : for( sal_Int32 i=0; i<aArgs.getLength(); ++i )
638 : {
639 264 : if ( aArgs[i].Name == "CellRangeRepresentation" )
640 60 : aArgs[i].Value >>= sCellRange;
641 204 : else if ( aArgs[i].Name == "BrokenCellRangeForExport" )
642 : {
643 0 : if( aArgs[i].Value >>= sBrokenRange )
644 0 : bBrokenRangeAvailable = true;
645 : }
646 204 : else if ( aArgs[i].Name == "SequenceMapping" )
647 0 : aArgs[i].Value >>= maSequenceMapping;
648 : }
649 :
650 : // #i79009# For Writer we have to export a broken version of the
651 : // range, where every row number is noe too large, so that older
652 : // version can correctly read those files.
653 60 : msChartAddress = (bBrokenRangeAvailable ? sBrokenRange : sCellRange);
654 60 : if( !msChartAddress.isEmpty() )
655 : {
656 : // convert format to XML-conform one
657 60 : Reference< chart2::data::XRangeXMLConversion > xConversion( xDataProvider, uno::UNO_QUERY );
658 60 : if( xConversion.is())
659 60 : msChartAddress = xConversion->convertRangeToXML( msChartAddress );
660 60 : }
661 60 : }
662 : }
663 0 : catch( const uno::Exception & ex )
664 : {
665 : (void)ex; // avoid warning for pro build
666 : OSL_FAIL( OUStringToOString(
667 : "Exception caught. Type: " +
668 : OUString::createFromAscii( typeid( ex ).name()) +
669 : ", Message: " +
670 : ex.Message, RTL_TEXTENCODING_ASCII_US ).getStr());
671 : }
672 60 : }
673 :
674 60 : void ChartExport::ExportContent()
675 : {
676 60 : Reference< chart2::XChartDocument > xChartDoc( getModel(), uno::UNO_QUERY );
677 : OSL_ASSERT( xChartDoc.is() );
678 60 : if( !xChartDoc.is() )
679 60 : return;
680 60 : InitRangeSegmentationProperties( xChartDoc );
681 : // TODO: export chart
682 60 : _ExportContent( );
683 : }
684 :
685 60 : void ChartExport::_ExportContent()
686 : {
687 60 : Reference< css::chart::XChartDocument > xChartDoc( getModel(), uno::UNO_QUERY );
688 60 : if( xChartDoc.is())
689 : {
690 : // determine if data comes from the outside
691 60 : bool bIncludeTable = true;
692 :
693 60 : Reference< chart2::XChartDocument > xNewDoc( xChartDoc, uno::UNO_QUERY );
694 60 : if( xNewDoc.is())
695 : {
696 : // check if we have own data. If so we must not export the complete
697 : // range string, as this is our only indicator for having own or
698 : // external data. @todo: fix this in the file format!
699 60 : Reference< lang::XServiceInfo > xDPServiceInfo( xNewDoc->getDataProvider(), uno::UNO_QUERY );
700 60 : if( ! (xDPServiceInfo.is() && xDPServiceInfo->getImplementationName() == "com.sun.star.comp.chart.InternalDataProvider" ))
701 : {
702 24 : bIncludeTable = false;
703 60 : }
704 : }
705 : else
706 : {
707 0 : Reference< lang::XServiceInfo > xServ( xChartDoc, uno::UNO_QUERY );
708 0 : if( xServ.is())
709 : {
710 0 : if( xServ->supportsService(
711 0 : OUString("com.sun.star.chart.ChartTableAddressSupplier")))
712 : {
713 0 : Reference< beans::XPropertySet > xProp( xServ, uno::UNO_QUERY );
714 0 : if( xProp.is())
715 : {
716 0 : Any aAny;
717 : try
718 : {
719 0 : OUString sChartAddress;
720 0 : aAny = xProp->getPropertyValue(
721 0 : OUString("ChartRangeAddress"));
722 0 : aAny >>= msChartAddress;
723 : //maExportHelper.SetChartRangeAddress( sChartAddress );
724 :
725 : //maExportHelper.SetTableNumberList( sTableNumberList );
726 :
727 : // do not include own table if there are external addresses
728 0 : bIncludeTable = sChartAddress.isEmpty();
729 : }
730 0 : catch( beans::UnknownPropertyException & )
731 : {
732 : OSL_FAIL( "Property ChartRangeAddress not supported by ChartDocument" );
733 0 : }
734 0 : }
735 : }
736 0 : }
737 : }
738 60 : exportChartSpace( xChartDoc, bIncludeTable );
739 : }
740 : else
741 : {
742 : OSL_FAIL( "Couldn't export chart due to wrong XModel" );
743 60 : }
744 60 : }
745 :
746 60 : void ChartExport::exportChartSpace( Reference< css::chart::XChartDocument > xChartDoc,
747 : bool bIncludeTable )
748 : {
749 60 : FSHelperPtr pFS = GetFS();
750 : pFS->startElement( FSNS( XML_c, XML_chartSpace ),
751 : FSNS( XML_xmlns, XML_c ), "http://schemas.openxmlformats.org/drawingml/2006/chart",
752 : FSNS( XML_xmlns, XML_a ), "http://schemas.openxmlformats.org/drawingml/2006/main",
753 : FSNS( XML_xmlns, XML_r ), "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
754 60 : FSEND );
755 : // TODO: get the correct editing lanauge
756 : pFS->singleElement( FSNS( XML_c, XML_lang ),
757 : XML_val, "en-US",
758 60 : FSEND );
759 :
760 : pFS->singleElement(FSNS( XML_c, XML_roundedCorners),
761 : XML_val, "0",
762 60 : FSEND);
763 :
764 60 : if( !bIncludeTable )
765 : {
766 : // TODO:external data
767 : }
768 : //XML_chart
769 60 : exportChart(xChartDoc);
770 :
771 : // TODO: printSettings
772 : // TODO: style
773 : // TODO: text properties
774 : // TODO: shape properties
775 120 : Reference< XPropertySet > xPropSet( xChartDoc->getArea(), uno::UNO_QUERY );
776 60 : if( xPropSet.is() )
777 60 : exportShapeProps( xPropSet );
778 :
779 : //XML_externalData
780 60 : exportExternalData(xChartDoc);
781 :
782 120 : pFS->endElement( FSNS( XML_c, XML_chartSpace ) );
783 60 : }
784 :
785 60 : void ChartExport::exportExternalData( Reference< css::chart::XChartDocument > xChartDoc )
786 : {
787 : // Embedded external data is grab bagged for docx file hence adding export part of
788 : // external data for docx files only.
789 60 : if(GetDocumentType() != DOCUMENT_DOCX)
790 84 : return;
791 :
792 36 : OUString externalDataPath;
793 72 : Reference< beans::XPropertySet > xDocPropSet( xChartDoc->getDiagram(), uno::UNO_QUERY );
794 36 : if( xDocPropSet.is())
795 : {
796 : try
797 : {
798 36 : Any aAny( xDocPropSet->getPropertyValue(
799 36 : OUString( "ExternalData" )));
800 36 : aAny >>= externalDataPath;
801 : }
802 0 : catch( beans::UnknownPropertyException & )
803 : {
804 : SAL_WARN("oox", "Required property not found in ChartDocument");
805 : }
806 : }
807 36 : if(!externalDataPath.isEmpty())
808 : {
809 : // Here adding external data entry to relationship.
810 33 : OUString relationPath = externalDataPath;
811 : // Converting absolute path to relative path.
812 33 : if( externalDataPath[ 0 ] != '.' && externalDataPath[ 1 ] != '.')
813 : {
814 33 : sal_Int32 nStartPos = 0;
815 33 : sal_Int32 nSepPos = externalDataPath.indexOf( '/', nStartPos );
816 33 : if( nSepPos > 0)
817 : {
818 33 : relationPath = relationPath.copy( nSepPos, ::std::max< sal_Int32 >( externalDataPath.getLength(), 0 ) - nSepPos );
819 33 : relationPath = OUStringBuffer( ".." ).append( relationPath ).makeStringAndClear();
820 : }
821 : }
822 66 : FSHelperPtr pFS = GetFS();
823 66 : OUString type = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/package";
824 33 : if (relationPath.endsWith(OUString(".bin")))
825 0 : type = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/oleObject";
826 :
827 : OUString sRelId = GetFB()->addRelation(pFS->getOutputStream(),
828 : type,
829 66 : relationPath);
830 : pFS->singleElementNS( XML_c, XML_externalData,
831 : FSNS(XML_r, XML_id), OUStringToOString(sRelId, RTL_TEXTENCODING_UTF8),
832 66 : FSEND);
833 36 : }
834 : }
835 :
836 60 : void ChartExport::exportChart( Reference< css::chart::XChartDocument > xChartDoc )
837 : {
838 60 : Reference< chart2::XChartDocument > xNewDoc( xChartDoc, uno::UNO_QUERY );
839 60 : mxDiagram.set( xChartDoc->getDiagram() );
840 60 : if( xNewDoc.is())
841 60 : mxNewDiagram.set( xNewDoc->getFirstDiagram());
842 :
843 : // get Properties of ChartDocument
844 60 : bool bHasMainTitle = false;
845 60 : bool bHasSubTitle = false;
846 60 : bool bHasLegend = false;
847 120 : Reference< beans::XPropertySet > xDocPropSet( xChartDoc, uno::UNO_QUERY );
848 60 : if( xDocPropSet.is())
849 : {
850 : try
851 : {
852 60 : Any aAny( xDocPropSet->getPropertyValue(
853 60 : OUString( "HasMainTitle" )));
854 60 : aAny >>= bHasMainTitle;
855 180 : aAny = xDocPropSet->getPropertyValue(
856 120 : OUString( "HasSubTitle" ));
857 60 : aAny >>= bHasSubTitle;
858 180 : aAny = xDocPropSet->getPropertyValue(
859 120 : OUString( "HasLegend" ));
860 60 : aAny >>= bHasLegend;
861 : }
862 0 : catch( beans::UnknownPropertyException & )
863 : {
864 : SAL_WARN("oox", "Required property not found in ChartDocument");
865 : }
866 : } // if( xDocPropSet.is())
867 :
868 : // chart element
869 :
870 120 : FSHelperPtr pFS = GetFS();
871 : pFS->startElement( FSNS( XML_c, XML_chart ),
872 60 : FSEND );
873 :
874 : // title
875 60 : if( bHasMainTitle )
876 : {
877 27 : Reference< drawing::XShape > xShape = xChartDoc->getTitle();
878 27 : if( xShape.is() )
879 : {
880 27 : exportTitle( xShape );
881 : pFS->singleElement( FSNS(XML_c, XML_autoTitleDeleted),
882 : XML_val, "0",
883 27 : FSEND);
884 27 : }
885 : }
886 60 : InitPlotArea( );
887 60 : if( mbIs3DChart )
888 : {
889 13 : exportView3D();
890 :
891 : // floor
892 13 : Reference< beans::XPropertySet > xFloor( mxNewDiagram->getFloor(), uno::UNO_QUERY );
893 13 : if( xFloor.is() )
894 : {
895 : pFS->startElement( FSNS( XML_c, XML_floor ),
896 13 : FSEND );
897 13 : exportShapeProps( xFloor );
898 13 : pFS->endElement( FSNS( XML_c, XML_floor ) );
899 : }
900 :
901 : // sideWall
902 :
903 : // backWall
904 26 : Reference< beans::XPropertySet > xBackWall( mxNewDiagram->getWall(), uno::UNO_QUERY );
905 13 : if( xBackWall.is() )
906 : {
907 : pFS->startElement( FSNS( XML_c, XML_backWall ),
908 13 : FSEND );
909 13 : exportShapeProps( xBackWall );
910 13 : pFS->endElement( FSNS( XML_c, XML_backWall ) );
911 13 : }
912 :
913 : }
914 : // plot area
915 60 : exportPlotArea( );
916 : // legend
917 60 : if( bHasLegend )
918 49 : exportLegend( xChartDoc );
919 :
920 120 : uno::Reference<beans::XPropertySet> xDiagramPropSet(xChartDoc->getDiagram(), uno::UNO_QUERY);
921 120 : uno::Any aPlotVisOnly = xDiagramPropSet->getPropertyValue("IncludeHiddenCells");
922 60 : bool bIncludeHiddenCells = false;
923 60 : aPlotVisOnly >>= bIncludeHiddenCells;
924 : pFS->singleElement( FSNS( XML_c, XML_plotVisOnly ),
925 60 : XML_val, BS(!bIncludeHiddenCells),
926 60 : FSEND );
927 :
928 60 : exportMissingValueTreatment(Reference<beans::XPropertySet>(mxDiagram, uno::UNO_QUERY));
929 :
930 120 : pFS->endElement( FSNS( XML_c, XML_chart ) );
931 60 : }
932 :
933 60 : void ChartExport::exportMissingValueTreatment(uno::Reference<beans::XPropertySet> xPropSet)
934 : {
935 60 : if (!xPropSet.is())
936 1 : return;
937 :
938 60 : sal_Int32 nVal = 0;
939 60 : uno::Any aAny = xPropSet->getPropertyValue("MissingValueTreatment");
940 60 : if (!(aAny >>= nVal))
941 1 : return;
942 :
943 59 : const char* pVal = NULL;
944 59 : switch (nVal)
945 : {
946 : case cssc::MissingValueTreatment::LEAVE_GAP:
947 49 : pVal = "gap";
948 49 : break;
949 : case cssc::MissingValueTreatment::USE_ZERO:
950 6 : pVal = "zero";
951 6 : break;
952 : case cssc::MissingValueTreatment::CONTINUE:
953 4 : pVal = "span";
954 4 : break;
955 : default:
956 : SAL_WARN("oox", "unknown MissingValueTreatment value");
957 0 : break;
958 : }
959 :
960 59 : FSHelperPtr pFS = GetFS();
961 : pFS->singleElement( FSNS(XML_c, XML_dispBlanksAs),
962 : XML_val, pVal,
963 59 : FSEND);
964 : }
965 :
966 49 : void ChartExport::exportLegend( Reference< css::chart::XChartDocument > xChartDoc )
967 : {
968 49 : FSHelperPtr pFS = GetFS();
969 : pFS->startElement( FSNS( XML_c, XML_legend ),
970 49 : FSEND );
971 :
972 98 : Reference< beans::XPropertySet > xProp( xChartDoc->getLegend(), uno::UNO_QUERY );
973 49 : if( xProp.is() )
974 : {
975 : // position
976 49 : css::chart::ChartLegendPosition aLegendPos = css::chart::ChartLegendPosition_NONE;
977 : try
978 : {
979 49 : Any aAny( xProp->getPropertyValue(
980 49 : OUString( "Alignment" )));
981 49 : aAny >>= aLegendPos;
982 : }
983 0 : catch( beans::UnknownPropertyException & )
984 : {
985 : SAL_WARN("oox", "Property Align not found in ChartLegend");
986 : }
987 :
988 49 : const char* strPos = NULL;
989 49 : switch( aLegendPos )
990 : {
991 : case css::chart::ChartLegendPosition_LEFT:
992 1 : strPos = "l";
993 1 : break;
994 : case css::chart::ChartLegendPosition_RIGHT:
995 36 : strPos = "r";
996 36 : break;
997 : case css::chart::ChartLegendPosition_TOP:
998 1 : strPos = "t";
999 1 : break;
1000 : case css::chart::ChartLegendPosition_BOTTOM:
1001 10 : strPos = "b";
1002 10 : break;
1003 : case css::chart::ChartLegendPosition_NONE:
1004 : case css::chart::ChartLegendPosition_MAKE_FIXED_SIZE:
1005 : // nothing
1006 1 : break;
1007 : }
1008 :
1009 49 : if( strPos != NULL )
1010 : {
1011 : pFS->singleElement( FSNS( XML_c, XML_legendPos ),
1012 : XML_val, strPos,
1013 48 : FSEND );
1014 : }
1015 :
1016 49 : uno::Any aRelativePos = xProp->getPropertyValue("RelativePosition");
1017 49 : if (aRelativePos.hasValue())
1018 : {
1019 2 : chart2::RelativePosition aPos = aRelativePos.get<chart2::RelativePosition>();
1020 2 : pFS->startElement(FSNS(XML_c, XML_layout), FSEND);
1021 2 : pFS->startElement(FSNS(XML_c, XML_manualLayout), FSEND);
1022 :
1023 : pFS->singleElement(FSNS(XML_c, XML_xMode),
1024 : XML_val, "edge",
1025 2 : FSEND);
1026 : pFS->singleElement(FSNS(XML_c, XML_yMode),
1027 : XML_val, "edge",
1028 2 : FSEND);
1029 :
1030 2 : double x = aPos.Primary;
1031 2 : double y = aPos.Secondary;
1032 :
1033 : pFS->singleElement(FSNS(XML_c, XML_x),
1034 : XML_val, IS(x),
1035 2 : FSEND);
1036 : pFS->singleElement(FSNS(XML_c, XML_y),
1037 : XML_val, IS(y),
1038 2 : FSEND);
1039 : SAL_WARN_IF(aPos.Anchor != 0, "oox.chart", "unsupported anchor position");
1040 :
1041 2 : pFS->endElement(FSNS(XML_c, XML_manualLayout));
1042 2 : pFS->endElement(FSNS(XML_c, XML_layout));
1043 : }
1044 :
1045 49 : if (strPos != NULL)
1046 : {
1047 : pFS->singleElement( FSNS( XML_c, XML_overlay ),
1048 : XML_val, "0",
1049 48 : FSEND );
1050 : }
1051 :
1052 : // shape properties
1053 49 : exportShapeProps( xProp );
1054 : }
1055 :
1056 : // legendEntry
1057 :
1058 98 : pFS->endElement( FSNS( XML_c, XML_legend ) );
1059 49 : }
1060 :
1061 : namespace {
1062 :
1063 : /**
1064 : * nRotation is a 100th of a degree and the return value is
1065 : * in a 60,000th of a degree
1066 : *
1067 : * Also rotation is in opposite directions so multiply with -1
1068 : */
1069 39 : OString calcRotationValue(sal_Int32 nRotation)
1070 : {
1071 39 : if (nRotation > 18000) // 180 degree
1072 : {
1073 1 : nRotation -= 36000;
1074 : }
1075 39 : nRotation *= -600;
1076 39 : return OString::number(nRotation);
1077 : }
1078 :
1079 : }
1080 :
1081 39 : void ChartExport::exportTitle( Reference< XShape > xShape )
1082 : {
1083 39 : OUString sText;
1084 78 : Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY );
1085 39 : if( xPropSet.is())
1086 : {
1087 39 : xPropSet->getPropertyValue("String") >>= sText;
1088 : }
1089 39 : if( sText.isEmpty() )
1090 39 : return;
1091 :
1092 78 : FSHelperPtr pFS = GetFS();
1093 : pFS->startElement( FSNS( XML_c, XML_title ),
1094 39 : FSEND );
1095 :
1096 : pFS->startElement( FSNS( XML_c, XML_tx ),
1097 39 : FSEND );
1098 : pFS->startElement( FSNS( XML_c, XML_rich ),
1099 39 : FSEND );
1100 :
1101 : // TODO: bodyPr
1102 39 : const char* sWritingMode = NULL;
1103 39 : bool bVertical = false;
1104 39 : xPropSet->getPropertyValue("StackedText") >>= bVertical;
1105 39 : if( bVertical )
1106 0 : sWritingMode = "wordArtVert";
1107 :
1108 39 : sal_Int32 nRotation = 0;
1109 39 : xPropSet->getPropertyValue("TextRotation") >>= nRotation;
1110 :
1111 : pFS->singleElement( FSNS( XML_a, XML_bodyPr ),
1112 : XML_vert, sWritingMode,
1113 : XML_rot, calcRotationValue(nRotation).getStr(),
1114 39 : FSEND );
1115 : // TODO: lstStyle
1116 : pFS->singleElement( FSNS( XML_a, XML_lstStyle ),
1117 39 : FSEND );
1118 : // FIXME: handle multipul paragraphs to parse aText
1119 : pFS->startElement( FSNS( XML_a, XML_p ),
1120 39 : FSEND );
1121 :
1122 : pFS->startElement( FSNS( XML_a, XML_pPr ),
1123 39 : FSEND );
1124 :
1125 39 : WriteRunProperties(xPropSet, false, XML_defRPr);
1126 :
1127 39 : pFS->endElement( FSNS( XML_a, XML_pPr ) );
1128 :
1129 : pFS->startElement( FSNS( XML_a, XML_r ),
1130 39 : FSEND );
1131 39 : WriteRunProperties( xPropSet, false );
1132 : pFS->startElement( FSNS( XML_a, XML_t ),
1133 39 : FSEND );
1134 39 : pFS->writeEscaped( sText );
1135 39 : pFS->endElement( FSNS( XML_a, XML_t ) );
1136 39 : pFS->endElement( FSNS( XML_a, XML_r ) );
1137 :
1138 39 : pFS->endElement( FSNS( XML_a, XML_p ) );
1139 :
1140 39 : pFS->endElement( FSNS( XML_c, XML_rich ) );
1141 39 : pFS->endElement( FSNS( XML_c, XML_tx ) );
1142 :
1143 78 : uno::Any aManualLayout = xPropSet->getPropertyValue("RelativePosition");
1144 39 : if (aManualLayout.hasValue())
1145 : {
1146 1 : pFS->startElement(FSNS( XML_c, XML_layout ), FSEND);
1147 1 : pFS->startElement(FSNS(XML_c, XML_manualLayout), FSEND);
1148 : pFS->singleElement(FSNS(XML_c, XML_xMode),
1149 : XML_val, "edge",
1150 1 : FSEND);
1151 : pFS->singleElement(FSNS(XML_c, XML_yMode),
1152 : XML_val, "edge",
1153 1 : FSEND);
1154 :
1155 1 : Reference<embed::XVisualObject> xVisObject(mxChartModel, uno::UNO_QUERY);
1156 1 : awt::Size aPageSize = xVisObject->getVisualAreaSize(embed::Aspects::MSOLE_CONTENT);
1157 :
1158 : // awt::Size aSize = xShape->getSize();
1159 1 : awt::Point aPos2 = xShape->getPosition();
1160 1 : double x = (double)aPos2.X / (double) aPageSize.Width;
1161 1 : double y = (double)aPos2.Y / (double) aPageSize.Height;
1162 : /*
1163 : pFS->singleElement(FSNS(XML_c, XML_wMode),
1164 : XML_val, "edge",
1165 : FSEND);
1166 : pFS->singleElement(FSNS(XML_c, XML_hMode),
1167 : XML_val, "edge",
1168 : FSEND);
1169 : */
1170 : pFS->singleElement(FSNS(XML_c, XML_x),
1171 : XML_val, IS(x),
1172 1 : FSEND);
1173 : pFS->singleElement(FSNS(XML_c, XML_y),
1174 : XML_val, IS(y),
1175 1 : FSEND);
1176 : /*
1177 : pFS->singleElement(FSNS(XML_c, XML_w),
1178 : XML_val, "",
1179 : FSEND);
1180 : pFS->singleElement(FSNS(XML_c, XML_h),
1181 : XML_val, "",
1182 : FSEND);
1183 : */
1184 1 : pFS->endElement(FSNS(XML_c, XML_manualLayout));
1185 1 : pFS->endElement(FSNS(XML_c, XML_layout));
1186 : }
1187 :
1188 : pFS->singleElement( FSNS(XML_c, XML_overlay),
1189 : XML_val, "0",
1190 39 : FSEND);
1191 :
1192 78 : pFS->endElement( FSNS( XML_c, XML_title ) );
1193 : }
1194 :
1195 60 : void ChartExport::exportPlotArea( )
1196 : {
1197 60 : Reference< chart2::XCoordinateSystemContainer > xBCooSysCnt( mxNewDiagram, uno::UNO_QUERY );
1198 60 : if( ! xBCooSysCnt.is())
1199 0 : return;
1200 :
1201 : // plot-area element
1202 :
1203 120 : FSHelperPtr pFS = GetFS();
1204 : pFS->startElement( FSNS( XML_c, XML_plotArea ),
1205 60 : FSEND );
1206 :
1207 120 : Reference<beans::XPropertySet> xWall(mxNewDiagram, uno::UNO_QUERY);
1208 60 : if( xWall.is() )
1209 : {
1210 60 : uno::Any aAny = xWall->getPropertyValue("RelativePosition");
1211 60 : if (aAny.hasValue())
1212 : {
1213 1 : chart2::RelativePosition aPos = aAny.get<chart2::RelativePosition>();
1214 1 : aAny = xWall->getPropertyValue("RelativeSize");
1215 1 : chart2::RelativeSize aSize = aAny.get<chart2::RelativeSize>();
1216 1 : exportManualLayout(aPos, aSize);
1217 60 : }
1218 : }
1219 :
1220 : // chart type
1221 : Sequence< Reference< chart2::XCoordinateSystem > >
1222 120 : aCooSysSeq( xBCooSysCnt->getCoordinateSystems());
1223 120 : for( sal_Int32 nCSIdx=0; nCSIdx<aCooSysSeq.getLength(); ++nCSIdx )
1224 : {
1225 :
1226 60 : Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nCSIdx], uno::UNO_QUERY );
1227 60 : if( ! xCTCnt.is())
1228 0 : continue;
1229 60 : mnSeriesCount=0;
1230 120 : Sequence< Reference< chart2::XChartType > > aCTSeq( xCTCnt->getChartTypes());
1231 124 : for( sal_Int32 nCTIdx=0; nCTIdx<aCTSeq.getLength(); ++nCTIdx )
1232 : {
1233 64 : Reference< chart2::XDataSeriesContainer > xDSCnt( aCTSeq[nCTIdx], uno::UNO_QUERY );
1234 64 : if( ! xDSCnt.is())
1235 0 : return;
1236 128 : Reference< chart2::XChartType > xChartType( aCTSeq[nCTIdx], uno::UNO_QUERY );
1237 64 : if( ! xChartType.is())
1238 0 : continue;
1239 : // note: if xDSCnt.is() then also aCTSeq[nCTIdx]
1240 128 : OUString aChartType( xChartType->getChartType());
1241 64 : sal_Int32 eChartType = lcl_getChartType( aChartType );
1242 64 : switch( eChartType )
1243 : {
1244 : case chart::TYPEID_BAR:
1245 : {
1246 32 : exportBarChart( xChartType );
1247 32 : break;
1248 : }
1249 : case chart::TYPEID_AREA:
1250 : {
1251 2 : exportAreaChart( xChartType );
1252 2 : break;
1253 : }
1254 : case chart::TYPEID_LINE:
1255 : {
1256 11 : exportLineChart( xChartType );
1257 11 : break;
1258 : }
1259 : case chart::TYPEID_BUBBLE:
1260 : {
1261 1 : exportBubbleChart( xChartType );
1262 1 : break;
1263 : }
1264 : case chart::TYPEID_OFPIE:
1265 : {
1266 0 : break;
1267 : }
1268 : case chart::TYPEID_DOUGHNUT:
1269 : case chart::TYPEID_PIE:
1270 : {
1271 7 : exportPieChart( xChartType );
1272 7 : break;
1273 : }
1274 : case chart::TYPEID_RADARLINE:
1275 : case chart::TYPEID_RADARAREA:
1276 : {
1277 1 : exportRadarChart( xChartType );
1278 1 : break;
1279 : }
1280 : case chart::TYPEID_SCATTER:
1281 : {
1282 9 : exportScatterChart( xChartType );
1283 9 : break;
1284 : }
1285 : case chart::TYPEID_STOCK:
1286 : {
1287 1 : exportStockChart( xChartType );
1288 1 : break;
1289 : }
1290 : case chart::TYPEID_SURFACE:
1291 : {
1292 0 : exportSurfaceChart( xChartType );
1293 0 : break;
1294 : }
1295 : default:
1296 : {
1297 : SAL_WARN("oox", "ChartExport::exportPlotArea -- not support chart type");
1298 0 : break;
1299 : }
1300 : }
1301 :
1302 64 : }
1303 60 : }
1304 : //Axis Data
1305 60 : exportAxes( );
1306 : // Data Table
1307 60 : exportDataTable();
1308 :
1309 : // shape properties
1310 : /*
1311 : * Export the Plot area Shape Properties
1312 : * eg: Fill and Outline
1313 : */
1314 60 : Reference< css::chart::X3DDisplay > xWallFloorSupplier( mxDiagram, uno::UNO_QUERY );
1315 60 : if( xWallFloorSupplier.is() )
1316 : {
1317 60 : Reference< beans::XPropertySet > xWallPropSet( xWallFloorSupplier->getWall(), uno::UNO_QUERY );
1318 60 : if( xWallPropSet.is() )
1319 : {
1320 60 : exportPlotAreaShapeProps( xWallPropSet );
1321 60 : }
1322 : }
1323 :
1324 120 : pFS->endElement( FSNS( XML_c, XML_plotArea ) );
1325 :
1326 : }
1327 :
1328 1 : void ChartExport::exportManualLayout(const css::chart2::RelativePosition& rPos, const css::chart2::RelativeSize& rSize)
1329 : {
1330 1 : FSHelperPtr pFS = GetFS();
1331 1 : pFS->startElement(FSNS(XML_c, XML_layout), FSEND);
1332 1 : pFS->startElement(FSNS(XML_c, XML_manualLayout), FSEND);
1333 : pFS->singleElement(FSNS(XML_c, XML_layoutTarget),
1334 : XML_val, "inner",
1335 1 : FSEND);
1336 : pFS->singleElement(FSNS(XML_c, XML_xMode),
1337 : XML_val, "edge",
1338 1 : FSEND);
1339 : pFS->singleElement(FSNS(XML_c, XML_yMode),
1340 : XML_val, "edge",
1341 1 : FSEND);
1342 :
1343 1 : double x = rPos.Primary;
1344 1 : double y = rPos.Secondary;
1345 1 : double w = rSize.Primary;
1346 1 : double h = rSize.Secondary;
1347 1 : switch (rPos.Anchor)
1348 : {
1349 : case drawing::Alignment_LEFT:
1350 0 : y -= (h/2);
1351 0 : break;
1352 : case drawing::Alignment_TOP_LEFT:
1353 1 : break;
1354 : case drawing::Alignment_BOTTOM_LEFT:
1355 0 : y -= h;
1356 0 : break;
1357 : case drawing::Alignment_TOP:
1358 0 : x -= (w/2);
1359 0 : break;
1360 : case drawing::Alignment_CENTER:
1361 0 : x -= (w/2);
1362 0 : y -= (h/2);
1363 0 : break;
1364 : case drawing::Alignment_BOTTOM:
1365 0 : x -= (w/2);
1366 0 : y -= h;
1367 0 : break;
1368 : case drawing::Alignment_TOP_RIGHT:
1369 0 : x -= w;
1370 0 : break;
1371 : case drawing::Alignment_BOTTOM_RIGHT:
1372 0 : x -= w;
1373 0 : y -= h;
1374 0 : break;
1375 : case drawing::Alignment_RIGHT:
1376 0 : y -= (h/2);
1377 0 : x -= w;
1378 0 : break;
1379 : default:
1380 : SAL_WARN("oox.chart", "unhandled alignment case for manual layout export");
1381 : }
1382 :
1383 : pFS->singleElement(FSNS(XML_c, XML_x),
1384 : XML_val, IS(x),
1385 1 : FSEND);
1386 :
1387 : pFS->singleElement(FSNS(XML_c, XML_y),
1388 : XML_val, IS(y),
1389 1 : FSEND);
1390 :
1391 : pFS->singleElement(FSNS(XML_c, XML_w),
1392 : XML_val, IS(w),
1393 1 : FSEND);
1394 :
1395 : pFS->singleElement(FSNS(XML_c, XML_h),
1396 : XML_val, IS(h),
1397 1 : FSEND);
1398 :
1399 1 : pFS->endElement(FSNS(XML_c, XML_manualLayout));
1400 1 : pFS->endElement(FSNS(XML_c, XML_layout));
1401 1 : }
1402 :
1403 60 : void ChartExport::exportPlotAreaShapeProps( Reference< XPropertySet > xPropSet )
1404 : {
1405 60 : FSHelperPtr pFS = GetFS();
1406 : pFS->startElement( FSNS( XML_c, XML_spPr ),
1407 60 : FSEND );
1408 :
1409 60 : exportFill( xPropSet );
1410 60 : WriteOutline( xPropSet );
1411 :
1412 60 : pFS->endElement( FSNS( XML_c, XML_spPr ) );
1413 60 : }
1414 :
1415 60 : void ChartExport::exportFill( Reference< XPropertySet > xPropSet )
1416 : {
1417 60 : if ( !GetProperty( xPropSet, "FillStyle" ) )
1418 60 : return;
1419 60 : FillStyle aFillStyle( FillStyle_NONE );
1420 60 : xPropSet->getPropertyValue( "FillStyle" ) >>= aFillStyle;
1421 60 : switch( aFillStyle )
1422 : {
1423 : case FillStyle_GRADIENT :
1424 0 : exportGradientFill( xPropSet );
1425 0 : break;
1426 : case FillStyle_BITMAP :
1427 1 : exportBitmapFill( xPropSet );
1428 1 : break;
1429 : default:
1430 59 : WriteFill( xPropSet );
1431 : }
1432 : }
1433 :
1434 1 : void ChartExport::exportBitmapFill( Reference< XPropertySet > xPropSet )
1435 : {
1436 1 : if( xPropSet.is() )
1437 : {
1438 1 : OUString sFillBitmapName;
1439 1 : xPropSet->getPropertyValue("FillBitmapName") >>= sFillBitmapName;
1440 :
1441 2 : uno::Reference< lang::XMultiServiceFactory > xFact( getModel(), uno::UNO_QUERY );
1442 : try
1443 : {
1444 1 : uno::Reference< container::XNameAccess > xBitmap( xFact->createInstance("com.sun.star.drawing.BitmapTable"), uno::UNO_QUERY );
1445 2 : uno::Any rValue = xBitmap->getByName( sFillBitmapName );
1446 2 : OUString sBitmapURL;
1447 1 : if( (rValue >>= sBitmapURL) )
1448 : {
1449 1 : WriteBlipFill( xPropSet, sBitmapURL, XML_a, true, true );
1450 1 : }
1451 : }
1452 0 : catch (const uno::Exception & rEx)
1453 : {
1454 : SAL_INFO("oox", "ChartExport::exportBitmapFill " << rEx.Message);
1455 1 : }
1456 :
1457 : }
1458 1 : }
1459 :
1460 0 : void ChartExport::exportGradientFill( Reference< XPropertySet > xPropSet )
1461 : {
1462 0 : if( xPropSet.is() )
1463 : {
1464 0 : OUString sFillGradientName;
1465 0 : xPropSet->getPropertyValue("FillGradientName") >>= sFillGradientName;
1466 :
1467 0 : awt::Gradient aGradient;
1468 0 : uno::Reference< lang::XMultiServiceFactory > xFact( getModel(), uno::UNO_QUERY );
1469 : try
1470 : {
1471 0 : uno::Reference< container::XNameAccess > xGradient( xFact->createInstance("com.sun.star.drawing.GradientTable"), uno::UNO_QUERY );
1472 0 : uno::Any rValue = xGradient->getByName( sFillGradientName );
1473 0 : if( (rValue >>= aGradient) )
1474 : {
1475 0 : mpFS->startElementNS( XML_a, XML_gradFill, FSEND );
1476 0 : WriteGradientFill( aGradient );
1477 0 : mpFS->endElementNS( XML_a, XML_gradFill );
1478 0 : }
1479 : }
1480 0 : catch (const uno::Exception & rEx)
1481 : {
1482 : SAL_INFO("oox",
1483 : "ChartExport::exportGradientFill " << rEx.Message);
1484 0 : }
1485 :
1486 : }
1487 0 : }
1488 :
1489 60 : void ChartExport::exportDataTable( )
1490 : {
1491 60 : FSHelperPtr pFS = GetFS();
1492 120 : Reference< beans::XPropertySet > aPropSet( mxDiagram, uno::UNO_QUERY );
1493 :
1494 60 : bool bShowVBorder = false;
1495 60 : bool bShowHBorder = false;
1496 60 : bool bShowOutline = false;
1497 :
1498 60 : if (GetProperty( aPropSet, "DataTableHBorder"))
1499 60 : mAny >>= bShowHBorder;
1500 60 : if (GetProperty( aPropSet, "DataTableVBorder"))
1501 60 : mAny >>= bShowVBorder;
1502 60 : if (GetProperty( aPropSet, "DataTableOutline"))
1503 60 : mAny >>= bShowOutline;
1504 :
1505 60 : if (bShowVBorder || bShowHBorder || bShowOutline)
1506 : {
1507 : pFS->startElement( FSNS( XML_c, XML_dTable),
1508 6 : FSEND );
1509 6 : if (bShowHBorder)
1510 : pFS->singleElement( FSNS( XML_c, XML_showHorzBorder ),
1511 : XML_val, "1",
1512 6 : FSEND );
1513 6 : if (bShowVBorder)
1514 : pFS->singleElement( FSNS( XML_c, XML_showVertBorder ),
1515 : XML_val, "1",
1516 6 : FSEND );
1517 6 : if (bShowOutline)
1518 : pFS->singleElement( FSNS( XML_c, XML_showOutline ),
1519 : XML_val, "1",
1520 6 : FSEND );
1521 :
1522 6 : pFS->endElement( FSNS( XML_c, XML_dTable));
1523 60 : }
1524 :
1525 60 : }
1526 2 : void ChartExport::exportAreaChart( Reference< chart2::XChartType > xChartType )
1527 : {
1528 2 : FSHelperPtr pFS = GetFS();
1529 2 : sal_Int32 nTypeId = XML_areaChart;
1530 2 : if( mbIs3DChart )
1531 0 : nTypeId = XML_area3DChart;
1532 : pFS->startElement( FSNS( XML_c, nTypeId ),
1533 2 : FSEND );
1534 :
1535 2 : exportGrouping( );
1536 2 : sal_Int32 nAttachedAxis = AXIS_PRIMARY_Y;
1537 2 : exportAllSeries( xChartType, nAttachedAxis );
1538 2 : exportAxesId( nAttachedAxis );
1539 :
1540 2 : pFS->endElement( FSNS( XML_c, nTypeId ) );
1541 2 : }
1542 :
1543 32 : void ChartExport::exportBarChart( Reference< chart2::XChartType > xChartType )
1544 : {
1545 32 : sal_Int32 nTypeId = XML_barChart;
1546 32 : if( mbIs3DChart )
1547 11 : nTypeId = XML_bar3DChart;
1548 32 : FSHelperPtr pFS = GetFS();
1549 : pFS->startElement( FSNS( XML_c, nTypeId ),
1550 32 : FSEND );
1551 : // bar direction
1552 32 : bool bVertical = false;
1553 64 : Reference< XPropertySet > xPropSet( mxDiagram , uno::UNO_QUERY);
1554 32 : if( GetProperty( xPropSet, "Vertical" ) )
1555 32 : mAny >>= bVertical;
1556 :
1557 32 : const char* bardir = bVertical? "bar":"col";
1558 : pFS->singleElement( FSNS( XML_c, XML_barDir ),
1559 : XML_val, bardir,
1560 32 : FSEND );
1561 :
1562 32 : exportGrouping( true );
1563 :
1564 32 : const char* varyColors = "0";
1565 : pFS->singleElement( FSNS( XML_c, XML_varyColors ),
1566 : XML_val, varyColors,
1567 32 : FSEND );
1568 :
1569 32 : sal_Int32 nAttachedAxis = AXIS_PRIMARY_Y;
1570 32 : exportAllSeries( xChartType, nAttachedAxis );
1571 :
1572 64 : Reference< XPropertySet > xTypeProp( xChartType, uno::UNO_QUERY );
1573 :
1574 32 : if( xTypeProp.is() && GetProperty( xTypeProp, "GapwidthSequence") )
1575 : {
1576 32 : uno::Sequence< sal_Int32 > aBarPositionSequence;
1577 32 : mAny >>= aBarPositionSequence;
1578 32 : if( aBarPositionSequence.getLength() )
1579 : {
1580 32 : sal_Int32 nGapWidth = aBarPositionSequence[0];
1581 : pFS->singleElement( FSNS( XML_c, XML_gapWidth ),
1582 : XML_val, I32S( nGapWidth ),
1583 32 : FSEND );
1584 32 : }
1585 : }
1586 :
1587 32 : if( mbIs3DChart )
1588 : {
1589 : // Shape
1590 : namespace cssc = css::chart;
1591 11 : sal_Int32 nGeom3d = cssc::ChartSolidType::RECTANGULAR_SOLID;
1592 11 : if( xPropSet.is() && GetProperty( xPropSet, "SolidType") )
1593 11 : mAny >>= nGeom3d;
1594 11 : const char* sShapeType = NULL;
1595 11 : switch( nGeom3d )
1596 : {
1597 : case cssc::ChartSolidType::RECTANGULAR_SOLID:
1598 5 : sShapeType = "box";
1599 5 : break;
1600 : case cssc::ChartSolidType::CONE:
1601 4 : sShapeType = "cone";
1602 4 : break;
1603 : case cssc::ChartSolidType::CYLINDER:
1604 2 : sShapeType = "cylinder";
1605 2 : break;
1606 : case cssc::ChartSolidType::PYRAMID:
1607 0 : sShapeType = "pyramid";
1608 0 : break;
1609 : }
1610 : pFS->singleElement( FSNS( XML_c, XML_shape ),
1611 : XML_val, sShapeType,
1612 11 : FSEND );
1613 : }
1614 :
1615 : //overlap
1616 32 : if( !mbIs3DChart && xTypeProp.is() && GetProperty( xTypeProp, "OverlapSequence") )
1617 : {
1618 21 : uno::Sequence< sal_Int32 > aBarPositionSequence;
1619 21 : mAny >>= aBarPositionSequence;
1620 21 : if( aBarPositionSequence.getLength() )
1621 : {
1622 21 : sal_Int32 nOverlap = aBarPositionSequence[0];
1623 : pFS->singleElement( FSNS( XML_c, XML_overlap ),
1624 : XML_val, I32S( nOverlap ),
1625 21 : FSEND );
1626 21 : }
1627 : }
1628 :
1629 32 : exportAxesId( nAttachedAxis );
1630 :
1631 64 : pFS->endElement( FSNS( XML_c, nTypeId ) );
1632 32 : }
1633 :
1634 1 : void ChartExport::exportBubbleChart( Reference< chart2::XChartType > xChartType )
1635 : {
1636 1 : FSHelperPtr pFS = GetFS();
1637 : pFS->startElement( FSNS( XML_c, XML_bubbleChart ),
1638 1 : FSEND );
1639 :
1640 1 : const char* varyColors = "0";
1641 : pFS->singleElement( FSNS( XML_c, XML_varyColors ),
1642 : XML_val, varyColors,
1643 1 : FSEND );
1644 :
1645 1 : sal_Int32 nAttachedAxis = AXIS_PRIMARY_Y;
1646 1 : exportAllSeries( xChartType, nAttachedAxis );
1647 :
1648 : pFS->singleElement(FSNS(XML_c, XML_bubble3D),
1649 : XML_val, "0",
1650 1 : FSEND);
1651 :
1652 1 : exportAxesId( nAttachedAxis );
1653 :
1654 1 : pFS->endElement( FSNS( XML_c, XML_bubbleChart ) );
1655 1 : }
1656 :
1657 2 : void ChartExport::exportDoughnutChart( Reference< chart2::XChartType > xChartType )
1658 : {
1659 2 : FSHelperPtr pFS = GetFS();
1660 : pFS->startElement( FSNS( XML_c, XML_doughnutChart ),
1661 2 : FSEND );
1662 :
1663 2 : sal_Int32 nAttachedAxis = AXIS_PRIMARY_Y;
1664 2 : exportAllSeries( xChartType, nAttachedAxis );
1665 : // firstSliceAng
1666 2 : exportFirstSliceAng( );
1667 : //FIXME: holeSize
1668 2 : sal_Int32 nHoleSize = 50;
1669 : pFS->singleElement( FSNS( XML_c, XML_holeSize ),
1670 : XML_val, I32S( nHoleSize ),
1671 2 : FSEND );
1672 :
1673 2 : pFS->endElement( FSNS( XML_c, XML_doughnutChart ) );
1674 2 : }
1675 :
1676 : namespace {
1677 :
1678 20 : std::vector<Sequence<Reference<chart2::XDataSeries> > > splitDataSeriesByAxis(Reference< chart2::XChartType > xChartType)
1679 : {
1680 20 : std::vector<Sequence<Reference<chart2::XDataSeries> > > aSplitSeries;
1681 40 : std::map<sal_Int32, size_t> aMapAxisToIndex;
1682 :
1683 40 : Reference< chart2::XDataSeriesContainer > xDSCnt( xChartType, uno::UNO_QUERY );
1684 20 : if(xDSCnt.is())
1685 : {
1686 20 : Sequence< Reference< chart2::XDataSeries > > aSeriesSeq( xDSCnt->getDataSeries());
1687 55 : for (sal_Int32 nIndex = 0, nEnd = aSeriesSeq.getLength(); nIndex < nEnd; ++nIndex)
1688 : {
1689 35 : uno::Reference<chart2::XDataSeries> xSeries = aSeriesSeq[nIndex];
1690 70 : Reference<beans::XPropertySet> xPropSet(xSeries, uno::UNO_QUERY);
1691 35 : if (!xPropSet.is())
1692 0 : continue;
1693 :
1694 35 : sal_Int32 nAxisIndex = -1;
1695 70 : uno::Any aAny = xPropSet->getPropertyValue("AttachedAxisIndex");
1696 35 : aAny >>= nAxisIndex;
1697 35 : size_t nVectorPos = 0;
1698 :
1699 35 : auto it = aMapAxisToIndex.find(nAxisIndex);
1700 35 : if (it == aMapAxisToIndex.end())
1701 : {
1702 21 : aSplitSeries.push_back(Sequence<Reference<chart2::XDataSeries> >());
1703 21 : nVectorPos = aSplitSeries.size() - 1;
1704 21 : aMapAxisToIndex.insert(std::pair<sal_Int32, size_t>(nAxisIndex, nVectorPos));
1705 : }
1706 :
1707 35 : uno::Sequence<Reference<chart2::XDataSeries> >& rAxisSeriesSeq = aSplitSeries[nVectorPos];
1708 35 : sal_Int32 nLength = rAxisSeriesSeq.getLength();
1709 35 : rAxisSeriesSeq.realloc(nLength + 1);
1710 35 : rAxisSeriesSeq[nLength] = xSeries;
1711 55 : }
1712 : }
1713 :
1714 40 : return aSplitSeries;
1715 : }
1716 :
1717 : }
1718 :
1719 11 : void ChartExport::exportLineChart( Reference< chart2::XChartType > xChartType )
1720 : {
1721 11 : FSHelperPtr pFS = GetFS();
1722 22 : std::vector<Sequence<Reference<chart2::XDataSeries> > > aSplitDataSeries = splitDataSeriesByAxis(xChartType);
1723 22 : for (auto itr = aSplitDataSeries.begin(), itrEnd = aSplitDataSeries.end();
1724 : itr != itrEnd; ++itr)
1725 : {
1726 11 : if (itr->getLength() == 0)
1727 0 : continue;
1728 :
1729 11 : sal_Int32 nTypeId = XML_lineChart;
1730 11 : if( mbIs3DChart )
1731 0 : nTypeId = XML_line3DChart;
1732 : pFS->startElement( FSNS( XML_c, nTypeId ),
1733 11 : FSEND );
1734 :
1735 11 : exportGrouping( );
1736 : // TODO: show marker symbol in series?
1737 11 : sal_Int32 nAttachedAxis = AXIS_PRIMARY_Y;
1738 11 : exportSeries( xChartType, *itr, nAttachedAxis );
1739 :
1740 : // show marker?
1741 11 : sal_Int32 nSymbolType = css::chart::ChartSymbolType::NONE;
1742 11 : Reference< XPropertySet > xPropSet( mxDiagram , uno::UNO_QUERY);
1743 11 : if( GetProperty( xPropSet, "SymbolType" ) )
1744 11 : mAny >>= nSymbolType;
1745 :
1746 11 : if( !mbIs3DChart )
1747 : {
1748 11 : exportHiLowLines();
1749 11 : exportUpDownBars(xChartType);
1750 11 : const char* marker = nSymbolType == css::chart::ChartSymbolType::NONE? "0":"1";
1751 : pFS->singleElement( FSNS( XML_c, XML_marker ),
1752 : XML_val, marker,
1753 11 : FSEND );
1754 : }
1755 :
1756 11 : exportAxesId( nAttachedAxis );
1757 :
1758 11 : pFS->endElement( FSNS( XML_c, nTypeId ) );
1759 22 : }
1760 11 : }
1761 :
1762 7 : void ChartExport::exportPieChart( Reference< chart2::XChartType > xChartType )
1763 : {
1764 7 : sal_Int32 eChartType = getChartType( );
1765 7 : if(eChartType == chart::TYPEID_DOUGHNUT)
1766 : {
1767 2 : exportDoughnutChart( xChartType );
1768 9 : return;
1769 : }
1770 5 : FSHelperPtr pFS = GetFS();
1771 5 : sal_Int32 nTypeId = XML_pieChart;
1772 5 : if( mbIs3DChart )
1773 2 : nTypeId = XML_pie3DChart;
1774 : pFS->startElement( FSNS( XML_c, nTypeId ),
1775 5 : FSEND );
1776 : // TODO: varyColors
1777 5 : const char* varyColors = "1";
1778 : pFS->singleElement( FSNS( XML_c, XML_varyColors ),
1779 : XML_val, varyColors,
1780 5 : FSEND );
1781 :
1782 5 : sal_Int32 nAttachedAxis = AXIS_PRIMARY_Y;
1783 5 : exportAllSeries( xChartType, nAttachedAxis );
1784 :
1785 5 : if( !mbIs3DChart )
1786 : {
1787 : // firstSliceAng
1788 3 : exportFirstSliceAng( );
1789 : }
1790 :
1791 5 : pFS->endElement( FSNS( XML_c, nTypeId ) );
1792 : }
1793 :
1794 1 : void ChartExport::exportRadarChart( Reference< chart2::XChartType > xChartType)
1795 : {
1796 1 : FSHelperPtr pFS = GetFS();
1797 : pFS->startElement( FSNS( XML_c, XML_radarChart ),
1798 1 : FSEND );
1799 :
1800 : // radarStyle
1801 1 : sal_Int32 eChartType = getChartType( );
1802 1 : const char* radarStyle = NULL;
1803 1 : if( eChartType == chart::TYPEID_RADARAREA )
1804 1 : radarStyle = "filled";
1805 : else
1806 0 : radarStyle = "marker";
1807 : pFS->singleElement( FSNS( XML_c, XML_radarStyle ),
1808 : XML_val, radarStyle,
1809 1 : FSEND );
1810 1 : sal_Int32 nAttachedAxis = AXIS_PRIMARY_Y;
1811 1 : exportAllSeries( xChartType, nAttachedAxis );
1812 1 : exportAxesId( nAttachedAxis );
1813 :
1814 1 : pFS->endElement( FSNS( XML_c, XML_radarChart ) );
1815 1 : }
1816 :
1817 9 : void ChartExport::exportScatterChart( Reference< chart2::XChartType > xChartType )
1818 : {
1819 9 : FSHelperPtr pFS = GetFS();
1820 18 : std::vector<Sequence<Reference<chart2::XDataSeries> > > aSplitDataSeries = splitDataSeriesByAxis(xChartType);
1821 19 : for (auto itr = aSplitDataSeries.begin(), itrEnd = aSplitDataSeries.end();
1822 : itr != itrEnd; ++itr)
1823 : {
1824 10 : if (itr->getLength() == 0)
1825 0 : continue;
1826 :
1827 : pFS->startElement( FSNS( XML_c, XML_scatterChart ),
1828 10 : FSEND );
1829 : // TODO:scatterStyle
1830 :
1831 10 : sal_Int32 nSymbolType = css::chart::ChartSymbolType::NONE;
1832 10 : Reference< XPropertySet > xPropSet( mxDiagram , uno::UNO_QUERY);
1833 10 : if( GetProperty( xPropSet, "SymbolType" ) )
1834 10 : mAny >>= nSymbolType;
1835 :
1836 10 : const char* scatterStyle = "lineMarker";
1837 10 : if (nSymbolType == css::chart::ChartSymbolType::NONE)
1838 : {
1839 0 : scatterStyle = "line";
1840 : }
1841 :
1842 : pFS->singleElement( FSNS( XML_c, XML_scatterStyle ),
1843 : XML_val, scatterStyle,
1844 10 : FSEND );
1845 :
1846 : pFS->singleElement( FSNS( XML_c, XML_varyColors ),
1847 : XML_val, "0",
1848 10 : FSEND );
1849 :
1850 : // FIXME: should export xVal and yVal
1851 10 : sal_Int32 nAttachedAxis = AXIS_PRIMARY_Y;
1852 10 : exportSeries( xChartType, *itr, nAttachedAxis );
1853 10 : exportAxesId( nAttachedAxis );
1854 :
1855 10 : pFS->endElement( FSNS( XML_c, XML_scatterChart ) );
1856 19 : }
1857 9 : }
1858 :
1859 1 : void ChartExport::exportStockChart( Reference< chart2::XChartType > xChartType )
1860 : {
1861 1 : FSHelperPtr pFS = GetFS();
1862 : pFS->startElement( FSNS( XML_c, XML_stockChart ),
1863 1 : FSEND );
1864 :
1865 1 : sal_Int32 nAttachedAxis = AXIS_PRIMARY_Y;
1866 :
1867 1 : bool bJapaneseCandleSticks = false;
1868 2 : Reference< beans::XPropertySet > xCTProp( xChartType, uno::UNO_QUERY );
1869 1 : if( xCTProp.is())
1870 1 : xCTProp->getPropertyValue("Japanese") >>= bJapaneseCandleSticks;
1871 :
1872 2 : Reference< chart2::XDataSeriesContainer > xDSCnt( xChartType, uno::UNO_QUERY );
1873 1 : if(xDSCnt.is())
1874 : exportCandleStickSeries(
1875 1 : xDSCnt->getDataSeries(), bJapaneseCandleSticks, nAttachedAxis );
1876 :
1877 : // export stock properties
1878 2 : Reference< css::chart::XStatisticDisplay > xStockPropProvider( mxDiagram, uno::UNO_QUERY );
1879 1 : if( xStockPropProvider.is())
1880 : {
1881 1 : exportHiLowLines();
1882 1 : exportUpDownBars(xChartType);
1883 : }
1884 :
1885 1 : exportAxesId( nAttachedAxis );
1886 :
1887 2 : pFS->endElement( FSNS( XML_c, XML_stockChart ) );
1888 1 : }
1889 :
1890 12 : void ChartExport::exportHiLowLines()
1891 : {
1892 12 : FSHelperPtr pFS = GetFS();
1893 : // export the chart property
1894 24 : Reference< css::chart::XStatisticDisplay > xChartPropProvider( mxDiagram, uno::UNO_QUERY );
1895 :
1896 12 : if (!xChartPropProvider.is())
1897 0 : return;
1898 :
1899 24 : Reference< beans::XPropertySet > xStockPropSet = xChartPropProvider->getMinMaxLine();
1900 12 : if( !xStockPropSet.is() )
1901 0 : return;
1902 :
1903 : pFS->startElement( FSNS( XML_c, XML_hiLowLines ),
1904 12 : FSEND );
1905 12 : exportShapeProps( xStockPropSet );
1906 24 : pFS->endElement( FSNS( XML_c, XML_hiLowLines ) );
1907 : }
1908 :
1909 12 : void ChartExport::exportUpDownBars( Reference< chart2::XChartType > xChartType)
1910 : {
1911 12 : if(xChartType->getChartType() != "com.sun.star.chart2.CandleStickChartType")
1912 23 : return;
1913 :
1914 1 : FSHelperPtr pFS = GetFS();
1915 : // export the chart property
1916 2 : Reference< css::chart::XStatisticDisplay > xChartPropProvider( mxDiagram, uno::UNO_QUERY );
1917 1 : if(xChartPropProvider.is())
1918 : {
1919 : // updownbar
1920 : pFS->startElement( FSNS( XML_c, XML_upDownBars ),
1921 1 : FSEND );
1922 : // TODO: gapWidth
1923 1 : sal_Int32 nGapWidth = 150;
1924 : pFS->singleElement( FSNS( XML_c, XML_gapWidth ),
1925 : XML_val, I32S( nGapWidth ),
1926 1 : FSEND );
1927 :
1928 1 : Reference< beans::XPropertySet > xChartPropSet = xChartPropProvider->getUpBar();
1929 1 : if( xChartPropSet.is() )
1930 : {
1931 : pFS->startElement( FSNS( XML_c, XML_upBars ),
1932 1 : FSEND );
1933 : // For Linechart with UpDownBars, spPr is not getting imported
1934 : // so no need to call the exportShapeProps() for LineChart
1935 1 : if(xChartType->getChartType() == "com.sun.star.chart2.CandleStickChartType")
1936 : {
1937 1 : exportShapeProps(xChartPropSet);
1938 : }
1939 1 : pFS->endElement( FSNS( XML_c, XML_upBars ) );
1940 : }
1941 1 : xChartPropSet = xChartPropProvider->getDownBar();
1942 1 : if( xChartPropSet.is() )
1943 : {
1944 : pFS->startElement( FSNS( XML_c, XML_downBars ),
1945 1 : FSEND );
1946 1 : if(xChartType->getChartType() == "com.sun.star.chart2.CandleStickChartType")
1947 : {
1948 1 : exportShapeProps(xChartPropSet);
1949 : }
1950 1 : pFS->endElement( FSNS( XML_c, XML_downBars ) );
1951 : }
1952 1 : pFS->endElement( FSNS( XML_c, XML_upDownBars ) );
1953 1 : }
1954 : }
1955 :
1956 0 : void ChartExport::exportSurfaceChart( Reference< chart2::XChartType > xChartType )
1957 : {
1958 0 : FSHelperPtr pFS = GetFS();
1959 0 : sal_Int32 nTypeId = XML_surfaceChart;
1960 0 : if( mbIs3DChart )
1961 0 : nTypeId = XML_surface3DChart;
1962 : pFS->startElement( FSNS( XML_c, nTypeId ),
1963 0 : FSEND );
1964 0 : sal_Int32 nAttachedAxis = AXIS_PRIMARY_Y;
1965 0 : exportAllSeries( xChartType, nAttachedAxis );
1966 0 : exportAxesId( nAttachedAxis );
1967 :
1968 0 : pFS->endElement( FSNS( XML_c, nTypeId ) );
1969 0 : }
1970 :
1971 43 : void ChartExport::exportAllSeries(Reference<chart2::XChartType> xChartType, sal_Int32& rAttachedAxis)
1972 : {
1973 43 : Reference< chart2::XDataSeriesContainer > xDSCnt( xChartType, uno::UNO_QUERY );
1974 43 : if( ! xDSCnt.is())
1975 43 : return;
1976 :
1977 : // export dataseries for current chart-type
1978 86 : Sequence< Reference< chart2::XDataSeries > > aSeriesSeq( xDSCnt->getDataSeries());
1979 86 : exportSeries(xChartType, aSeriesSeq, rAttachedAxis);
1980 : }
1981 :
1982 64 : void ChartExport::exportSeries( Reference<chart2::XChartType> xChartType,
1983 : Sequence<Reference<chart2::XDataSeries> >& rSeriesSeq, sal_Int32& rAttachedAxis )
1984 : {
1985 64 : OUString aLabelRole = xChartType->getRoleOfSequenceForSeriesLabel();
1986 128 : OUString aChartType( xChartType->getChartType());
1987 64 : sal_Int32 eChartType = lcl_getChartType( aChartType );
1988 :
1989 185 : for( sal_Int32 nSeriesIdx=0; nSeriesIdx<rSeriesSeq.getLength(); ++nSeriesIdx )
1990 : {
1991 : // export series
1992 121 : Reference< chart2::data::XDataSource > xSource( rSeriesSeq[nSeriesIdx], uno::UNO_QUERY );
1993 121 : if( xSource.is())
1994 : {
1995 121 : Reference< chart2::XDataSeries > xDataSeries( xSource, uno::UNO_QUERY );
1996 : Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeqCnt(
1997 242 : xSource->getDataSequences());
1998 : // search for main sequence and create a series element
1999 : {
2000 121 : sal_Int32 nMainSequenceIndex = -1;
2001 121 : sal_Int32 nSeriesLength = 0;
2002 121 : Reference< chart2::data::XDataSequence > xValuesSeq;
2003 242 : Reference< chart2::data::XDataSequence > xLabelSeq;
2004 121 : sal_Int32 nSeqIdx=0;
2005 257 : for( ; nSeqIdx<aSeqCnt.getLength(); ++nSeqIdx )
2006 : {
2007 136 : OUString aRole;
2008 272 : Reference< chart2::data::XDataSequence > xTempValueSeq( aSeqCnt[nSeqIdx]->getValues() );
2009 136 : if( nMainSequenceIndex==-1 )
2010 : {
2011 132 : Reference< beans::XPropertySet > xSeqProp( xTempValueSeq, uno::UNO_QUERY );
2012 132 : if( xSeqProp.is())
2013 132 : xSeqProp->getPropertyValue("Role") >>= aRole;
2014 : // "main" sequence
2015 132 : if( aRole.equals( aLabelRole ))
2016 : {
2017 120 : xValuesSeq.set( xTempValueSeq );
2018 120 : xLabelSeq.set( aSeqCnt[nSeqIdx]->getLabel());
2019 120 : nMainSequenceIndex = nSeqIdx;
2020 132 : }
2021 : }
2022 136 : sal_Int32 nSequenceLength = (xTempValueSeq.is()? xTempValueSeq->getData().getLength() : sal_Int32(0));
2023 136 : if( nSeriesLength < nSequenceLength )
2024 121 : nSeriesLength = nSequenceLength;
2025 136 : }
2026 :
2027 : // have found the main sequence, then xValuesSeq and
2028 : // xLabelSeq contain those. Otherwise both are empty
2029 : {
2030 121 : FSHelperPtr pFS = GetFS();
2031 : pFS->startElement( FSNS( XML_c, XML_ser ),
2032 121 : FSEND );
2033 :
2034 : // TODO: idx and order
2035 : pFS->singleElement( FSNS( XML_c, XML_idx ),
2036 : XML_val, I32S(mnSeriesCount),
2037 121 : FSEND );
2038 : pFS->singleElement( FSNS( XML_c, XML_order ),
2039 : XML_val, I32S(mnSeriesCount++),
2040 121 : FSEND );
2041 :
2042 : // export label
2043 121 : if( xLabelSeq.is() )
2044 117 : exportSeriesText( xLabelSeq );
2045 :
2046 242 : Reference<XPropertySet> xPropSet(xDataSeries, UNO_QUERY_THROW);
2047 121 : if( GetProperty( xPropSet, "AttachedAxisIndex") )
2048 : {
2049 121 : sal_Int32 nLocalAttachedAxis = 0;
2050 121 : mAny >>= nLocalAttachedAxis;
2051 121 : rAttachedAxis = translateFromChart2AxisIndexToOox(nLocalAttachedAxis);
2052 : }
2053 :
2054 : // export shape properties
2055 : Reference< XPropertySet > xOldPropSet = SchXMLSeriesHelper::createOldAPISeriesPropertySet(
2056 242 : rSeriesSeq[nSeriesIdx], getModel() );
2057 121 : if( xOldPropSet.is() )
2058 : {
2059 121 : exportShapeProps( xOldPropSet );
2060 : }
2061 :
2062 121 : switch( eChartType )
2063 : {
2064 : case chart::TYPEID_BUBBLE:
2065 : case chart::TYPEID_HORBAR:
2066 : case chart::TYPEID_BAR:
2067 : {
2068 : pFS->singleElement(FSNS(XML_c, XML_invertIfNegative),
2069 : XML_val, "0",
2070 74 : FSEND);
2071 : }
2072 74 : break;
2073 : case chart::TYPEID_LINE:
2074 : {
2075 22 : exportMarker(xDataSeries);
2076 22 : break;
2077 : }
2078 : case chart::TYPEID_PIE:
2079 : case chart::TYPEID_DOUGHNUT:
2080 : {
2081 7 : if( xOldPropSet.is() && GetProperty( xOldPropSet, "SegmentOffset") )
2082 : {
2083 7 : sal_Int32 nOffset = 0;
2084 7 : mAny >>= nOffset;
2085 : pFS->singleElement( FSNS( XML_c, XML_explosion ),
2086 : XML_val, I32S( nOffset ),
2087 7 : FSEND );
2088 : }
2089 7 : break;
2090 : }
2091 : case chart::TYPEID_SCATTER:
2092 : {
2093 13 : exportMarker(xDataSeries);
2094 13 : break;
2095 : }
2096 : case chart::TYPEID_RADARLINE:
2097 : {
2098 0 : exportMarker(xDataSeries);
2099 0 : break;
2100 : }
2101 : }
2102 :
2103 : // export data points
2104 121 : exportDataPoints( uno::Reference< beans::XPropertySet >( rSeriesSeq[nSeriesIdx], uno::UNO_QUERY ), nSeriesLength );
2105 :
2106 : // export data labels
2107 121 : exportDataLabels(rSeriesSeq[nSeriesIdx], nSeriesLength, eChartType);
2108 :
2109 121 : exportTrendlines( rSeriesSeq[nSeriesIdx] );
2110 :
2111 121 : if( eChartType != chart::TYPEID_PIE &&
2112 : eChartType != chart::TYPEID_RADARLINE )
2113 : {
2114 : //export error bars here
2115 114 : Reference< XPropertySet > xSeriesPropSet( xSource, uno::UNO_QUERY );
2116 228 : Reference< XPropertySet > xErrorBarYProps;
2117 114 : xSeriesPropSet->getPropertyValue("ErrorBarY") >>= xErrorBarYProps;
2118 114 : if(xErrorBarYProps.is())
2119 1 : exportErrorBar(xErrorBarYProps, true);
2120 114 : if (eChartType != chart::TYPEID_BAR &&
2121 : eChartType != chart::TYPEID_HORBAR)
2122 : {
2123 43 : Reference< XPropertySet > xErrorBarXProps;
2124 43 : xSeriesPropSet->getPropertyValue("ErrorBarX") >>= xErrorBarXProps;
2125 43 : if(xErrorBarXProps.is())
2126 0 : exportErrorBar(xErrorBarXProps, false);
2127 114 : }
2128 : }
2129 :
2130 : // export categories
2131 121 : if( eChartType != chart::TYPEID_SCATTER && mxCategoriesValues.is() )
2132 77 : exportSeriesCategory( mxCategoriesValues );
2133 :
2134 121 : if( (eChartType == chart::TYPEID_SCATTER)
2135 108 : || (eChartType == chart::TYPEID_BUBBLE) )
2136 : {
2137 : // export xVal
2138 16 : Reference< chart2::data::XLabeledDataSequence > xSequence( lcl_getDataSequenceByRole( aSeqCnt, OUString("values-x") ) );
2139 16 : if( xSequence.is() )
2140 : {
2141 13 : Reference< chart2::data::XDataSequence > xValues( xSequence->getValues() );
2142 13 : if( xValues.is() )
2143 13 : exportSeriesValues( xValues, XML_xVal );
2144 16 : }
2145 : }
2146 :
2147 121 : if( eChartType == chart::TYPEID_BUBBLE )
2148 : {
2149 : // export yVal
2150 3 : Reference< chart2::data::XLabeledDataSequence > xSequence( lcl_getDataSequenceByRole( aSeqCnt, OUString("values-y") ) );
2151 3 : if( xSequence.is() )
2152 : {
2153 3 : Reference< chart2::data::XDataSequence > xValues( xSequence->getValues() );
2154 3 : if( xValues.is() )
2155 3 : exportSeriesValues( xValues, XML_yVal );
2156 3 : }
2157 : }
2158 :
2159 : // export values
2160 121 : if( xValuesSeq.is() )
2161 : {
2162 120 : sal_Int32 nYValueType = XML_val;
2163 120 : if( eChartType == chart::TYPEID_SCATTER )
2164 13 : nYValueType = XML_yVal;
2165 107 : else if( eChartType == chart::TYPEID_BUBBLE )
2166 2 : nYValueType = XML_bubbleSize;
2167 120 : exportSeriesValues( xValuesSeq, nYValueType );
2168 : }
2169 :
2170 121 : if( eChartType == chart::TYPEID_SCATTER
2171 108 : || eChartType == chart::TYPEID_LINE )
2172 35 : exportSmooth();
2173 :
2174 242 : pFS->endElement( FSNS( XML_c, XML_ser ) );
2175 121 : }
2176 121 : }
2177 : }
2178 185 : }
2179 64 : }
2180 :
2181 1 : void ChartExport::exportCandleStickSeries(
2182 : const Sequence< Reference< chart2::XDataSeries > > & aSeriesSeq,
2183 : bool /*bJapaneseCandleSticks*/,
2184 : sal_Int32& rAttachedAxis )
2185 : {
2186 2 : for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeriesSeq.getLength(); ++nSeriesIdx )
2187 : {
2188 1 : Reference< chart2::XDataSeries > xSeries( aSeriesSeq[nSeriesIdx] );
2189 1 : rAttachedAxis = lcl_isSeriesAttachedToFirstAxis( xSeries ) ? AXIS_PRIMARY_Y : AXIS_SECONDARY_Y;
2190 :
2191 2 : Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY );
2192 1 : if( xSource.is())
2193 : {
2194 : // export series in correct order (as we don't store roles)
2195 : // with japanese candlesticks: open, low, high, close
2196 : // otherwise: low, high, close
2197 : Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeqCnt(
2198 1 : xSource->getDataSequences());
2199 :
2200 2 : Reference< chart2::XChartDocument > xNewDoc( getModel(), uno::UNO_QUERY );
2201 1 : const char* sSeries[] = {"values-first","values-max","values-min","values-last",0};
2202 :
2203 5 : for( sal_Int32 idx = 0; sSeries[idx] != 0 ; idx++ )
2204 : {
2205 4 : Reference< chart2::data::XLabeledDataSequence > xLabeledSeq( lcl_getDataSequenceByRole( aSeqCnt, OUString::createFromAscii(sSeries[idx]) ) );
2206 4 : if( xLabeledSeq.is())
2207 : {
2208 4 : Reference< chart2::data::XDataSequence > xLabelSeq( xLabeledSeq->getLabel());
2209 8 : Reference< chart2::data::XDataSequence > xValueSeq( xLabeledSeq->getValues());
2210 : {
2211 4 : FSHelperPtr pFS = GetFS();
2212 : pFS->startElement( FSNS( XML_c, XML_ser ),
2213 4 : FSEND );
2214 :
2215 : // TODO: idx and order
2216 : // idx attribute should start from 1 and not from 0.
2217 : pFS->singleElement( FSNS( XML_c, XML_idx ),
2218 : XML_val, I32S(idx+1),
2219 4 : FSEND );
2220 : pFS->singleElement( FSNS( XML_c, XML_order ),
2221 : XML_val, I32S(idx+1),
2222 4 : FSEND );
2223 :
2224 : // export label
2225 4 : if( xLabelSeq.is() )
2226 4 : exportSeriesText( xLabelSeq );
2227 :
2228 : // TODO:export shape properties
2229 :
2230 : // export categories
2231 4 : if( mxCategoriesValues.is() )
2232 4 : exportSeriesCategory( mxCategoriesValues );
2233 :
2234 : // export values
2235 4 : if( xValueSeq.is() )
2236 4 : exportSeriesValues( xValueSeq );
2237 :
2238 4 : pFS->endElement( FSNS( XML_c, XML_ser ) );
2239 4 : }
2240 : }
2241 5 : }
2242 : }
2243 1 : }
2244 1 : }
2245 :
2246 121 : void ChartExport::exportSeriesText( const Reference< chart2::data::XDataSequence > & xValueSeq )
2247 : {
2248 121 : FSHelperPtr pFS = GetFS();
2249 242 : Reference< chart2::XChartDocument > xNewDoc( getModel(), uno::UNO_QUERY );
2250 : pFS->startElement( FSNS( XML_c, XML_tx ),
2251 121 : FSEND );
2252 :
2253 242 : OUString aCellRange = xValueSeq->getSourceRangeRepresentation();
2254 121 : aCellRange = parseFormula( aCellRange );
2255 : pFS->startElement( FSNS( XML_c, XML_strRef ),
2256 121 : FSEND );
2257 :
2258 : pFS->startElement( FSNS( XML_c, XML_f ),
2259 121 : FSEND );
2260 121 : pFS->writeEscaped( aCellRange );
2261 121 : pFS->endElement( FSNS( XML_c, XML_f ) );
2262 :
2263 242 : OUString aLabelString = lcl_getLabelString( xValueSeq );
2264 : pFS->startElement( FSNS( XML_c, XML_strCache ),
2265 121 : FSEND );
2266 : pFS->singleElement( FSNS( XML_c, XML_ptCount ),
2267 : XML_val, "1",
2268 121 : FSEND );
2269 : pFS->startElement( FSNS( XML_c, XML_pt ),
2270 : XML_idx, "0",
2271 121 : FSEND );
2272 : pFS->startElement( FSNS( XML_c, XML_v ),
2273 121 : FSEND );
2274 121 : pFS->writeEscaped( aLabelString );
2275 121 : pFS->endElement( FSNS( XML_c, XML_v ) );
2276 121 : pFS->endElement( FSNS( XML_c, XML_pt ) );
2277 121 : pFS->endElement( FSNS( XML_c, XML_strCache ) );
2278 121 : pFS->endElement( FSNS( XML_c, XML_strRef ) );
2279 242 : pFS->endElement( FSNS( XML_c, XML_tx ) );
2280 121 : }
2281 :
2282 81 : void ChartExport::exportSeriesCategory( const Reference< chart2::data::XDataSequence > & xValueSeq )
2283 : {
2284 81 : FSHelperPtr pFS = GetFS();
2285 162 : Reference< chart2::XChartDocument > xNewDoc( getModel(), uno::UNO_QUERY );
2286 : pFS->startElement( FSNS( XML_c, XML_cat ),
2287 81 : FSEND );
2288 :
2289 162 : OUString aCellRange = xValueSeq.is() ? xValueSeq->getSourceRangeRepresentation() : OUString();
2290 81 : aCellRange = parseFormula( aCellRange );
2291 : // TODO: need to handle XML_multiLvlStrRef according to aCellRange
2292 : pFS->startElement( FSNS( XML_c, XML_strRef ),
2293 81 : FSEND );
2294 :
2295 : pFS->startElement( FSNS( XML_c, XML_f ),
2296 81 : FSEND );
2297 81 : pFS->writeEscaped( aCellRange );
2298 81 : pFS->endElement( FSNS( XML_c, XML_f ) );
2299 :
2300 162 : ::std::vector< OUString > aCategories;
2301 81 : lcl_fillCategoriesIntoStringVector( xValueSeq, aCategories );
2302 81 : sal_Int32 ptCount = aCategories.size();
2303 : pFS->startElement( FSNS( XML_c, XML_strCache ),
2304 81 : FSEND );
2305 : pFS->singleElement( FSNS( XML_c, XML_ptCount ),
2306 : XML_val, I32S( ptCount ),
2307 81 : FSEND );
2308 481 : for( sal_Int32 i = 0; i < ptCount; i++ )
2309 : {
2310 : pFS->startElement( FSNS( XML_c, XML_pt ),
2311 : XML_idx, I32S( i ),
2312 400 : FSEND );
2313 : pFS->startElement( FSNS( XML_c, XML_v ),
2314 400 : FSEND );
2315 400 : pFS->writeEscaped( aCategories[i] );
2316 400 : pFS->endElement( FSNS( XML_c, XML_v ) );
2317 400 : pFS->endElement( FSNS( XML_c, XML_pt ) );
2318 : }
2319 :
2320 81 : pFS->endElement( FSNS( XML_c, XML_strCache ) );
2321 81 : pFS->endElement( FSNS( XML_c, XML_strRef ) );
2322 162 : pFS->endElement( FSNS( XML_c, XML_cat ) );
2323 81 : }
2324 :
2325 140 : void ChartExport::exportSeriesValues( const Reference< chart2::data::XDataSequence > & xValueSeq, sal_Int32 nValueType )
2326 : {
2327 140 : FSHelperPtr pFS = GetFS();
2328 280 : Reference< chart2::XChartDocument > xNewDoc( getModel(), uno::UNO_QUERY );
2329 : pFS->startElement( FSNS( XML_c, nValueType ),
2330 140 : FSEND );
2331 :
2332 280 : OUString aCellRange = xValueSeq.is() ? xValueSeq->getSourceRangeRepresentation() : OUString();
2333 140 : aCellRange = parseFormula( aCellRange );
2334 : // TODO: need to handle XML_multiLvlStrRef according to aCellRange
2335 : pFS->startElement( FSNS( XML_c, XML_numRef ),
2336 140 : FSEND );
2337 :
2338 : pFS->startElement( FSNS( XML_c, XML_f ),
2339 140 : FSEND );
2340 140 : pFS->writeEscaped( aCellRange );
2341 140 : pFS->endElement( FSNS( XML_c, XML_f ) );
2342 :
2343 280 : ::std::vector< double > aValues;
2344 140 : aValues = lcl_getAllValuesFromSequence( xValueSeq );
2345 140 : sal_Int32 ptCount = aValues.size();
2346 : pFS->startElement( FSNS( XML_c, XML_numCache ),
2347 140 : FSEND );
2348 : pFS->startElement( FSNS( XML_c, XML_formatCode ),
2349 140 : FSEND );
2350 : // TODO: what format code?
2351 140 : pFS->writeEscaped( "General" );
2352 140 : pFS->endElement( FSNS( XML_c, XML_formatCode ) );
2353 : pFS->singleElement( FSNS( XML_c, XML_ptCount ),
2354 : XML_val, I32S( ptCount ),
2355 140 : FSEND );
2356 :
2357 140 : bool bIsNumberValue = true;
2358 140 : bool bXSeriesValue = false;
2359 140 : double Value = 1.0;
2360 :
2361 140 : if(nValueType == XML_xVal)
2362 13 : bXSeriesValue = true;
2363 :
2364 745 : for( sal_Int32 i = 0; i < ptCount; i++ )
2365 : {
2366 : pFS->startElement( FSNS( XML_c, XML_pt ),
2367 : XML_idx, I32S( i ),
2368 605 : FSEND );
2369 : pFS->startElement( FSNS( XML_c, XML_v ),
2370 605 : FSEND );
2371 605 : if (bIsNumberValue && !rtl::math::isNan(aValues[i]))
2372 587 : pFS->write( aValues[i] );
2373 18 : else if(bXSeriesValue)
2374 : {
2375 : //In Case aValues is not a number for X Values...We write X values as 1,2,3....MS Word does the same thing.
2376 10 : pFS->write( Value );
2377 10 : Value = Value + 1;
2378 10 : bIsNumberValue = false;
2379 : }
2380 605 : pFS->endElement( FSNS( XML_c, XML_v ) );
2381 605 : pFS->endElement( FSNS( XML_c, XML_pt ) );
2382 : }
2383 :
2384 140 : pFS->endElement( FSNS( XML_c, XML_numCache ) );
2385 140 : pFS->endElement( FSNS( XML_c, XML_numRef ) );
2386 280 : pFS->endElement( FSNS( XML_c, nValueType ) );
2387 140 : }
2388 :
2389 489 : void ChartExport::exportShapeProps( Reference< XPropertySet > xPropSet )
2390 : {
2391 489 : FSHelperPtr pFS = GetFS();
2392 : pFS->startElement( FSNS( XML_c, XML_spPr ),
2393 489 : FSEND );
2394 :
2395 489 : WriteFill( xPropSet );
2396 489 : WriteOutline( xPropSet );
2397 :
2398 489 : pFS->endElement( FSNS( XML_c, XML_spPr ) );
2399 489 : }
2400 :
2401 116 : void ChartExport::exportTextProps(Reference<XPropertySet> xPropSet)
2402 : {
2403 116 : FSHelperPtr pFS = GetFS();
2404 116 : pFS->startElement(FSNS(XML_c, XML_txPr), FSEND);
2405 :
2406 116 : pFS->startElement(FSNS(XML_a, XML_bodyPr), FSEND);
2407 116 : pFS->endElement(FSNS(XML_a, XML_bodyPr));
2408 :
2409 116 : pFS->startElement(FSNS(XML_a, XML_p), FSEND);
2410 116 : pFS->startElement(FSNS(XML_a, XML_pPr), FSEND);
2411 :
2412 116 : WriteRunProperties(xPropSet, false, XML_defRPr);
2413 :
2414 116 : pFS->endElement(FSNS(XML_a, XML_pPr));
2415 116 : pFS->endElement(FSNS(XML_a, XML_p));
2416 :
2417 116 : pFS->endElement(FSNS(XML_c, XML_txPr));
2418 116 : }
2419 :
2420 60 : void ChartExport::InitPlotArea( )
2421 : {
2422 60 : Reference< XPropertySet > xDiagramProperties (mxDiagram, uno::UNO_QUERY);
2423 :
2424 : // Check for supported services and then the properties provided by this service.
2425 120 : Reference<lang::XServiceInfo> xServiceInfo (mxDiagram, uno::UNO_QUERY);
2426 60 : if (xServiceInfo.is())
2427 : {
2428 180 : if (xServiceInfo->supportsService(
2429 120 : OUString("com.sun.star.chart.ChartAxisZSupplier")))
2430 : {
2431 60 : xDiagramProperties->getPropertyValue(
2432 120 : OUString("HasZAxis")) >>= mbHasZAxis;
2433 : }
2434 : }
2435 :
2436 60 : xDiagramProperties->getPropertyValue(
2437 120 : OUString ("Dim3D")) >>= mbIs3DChart;
2438 :
2439 120 : Reference< chart2::XChartDocument > xNewDoc( getModel(), uno::UNO_QUERY );
2440 60 : if( mbHasCategoryLabels && mxNewDiagram.is())
2441 : {
2442 37 : Reference< chart2::data::XLabeledDataSequence > xCategories( lcl_getCategories( mxNewDiagram ) );
2443 37 : if( xCategories.is() )
2444 : {
2445 37 : mxCategoriesValues.set( xCategories->getValues() );
2446 37 : }
2447 60 : }
2448 60 : }
2449 :
2450 60 : void ChartExport::exportAxes( )
2451 : {
2452 60 : sal_Int32 nSize = maAxes.size();
2453 176 : for( sal_Int32 nIdx = 0; nIdx < nSize; nIdx++ )
2454 : {
2455 116 : exportAxis( maAxes[nIdx] );
2456 : }
2457 60 : }
2458 :
2459 116 : void ChartExport::exportAxis(const AxisIdPair& rAxisIdPair)
2460 : {
2461 : // get some properties from document first
2462 116 : bool bHasXAxisTitle = false,
2463 116 : bHasYAxisTitle = false,
2464 116 : bHasZAxisTitle = false,
2465 116 : bHasSecondaryXAxisTitle = false,
2466 116 : bHasSecondaryYAxisTitle = false;
2467 116 : bool bHasXAxisMajorGrid = false,
2468 116 : bHasXAxisMinorGrid = false,
2469 116 : bHasYAxisMajorGrid = false,
2470 116 : bHasYAxisMinorGrid = false,
2471 116 : bHasZAxisMajorGrid = false,
2472 116 : bHasZAxisMinorGrid = false;
2473 :
2474 116 : Reference< XPropertySet > xDiagramProperties (mxDiagram, uno::UNO_QUERY);
2475 :
2476 116 : xDiagramProperties->getPropertyValue(
2477 116 : OUString ("HasXAxisTitle")) >>= bHasXAxisTitle;
2478 116 : xDiagramProperties->getPropertyValue(
2479 116 : OUString ("HasYAxisTitle")) >>= bHasYAxisTitle;
2480 116 : xDiagramProperties->getPropertyValue(
2481 116 : OUString ("HasZAxisTitle")) >>= bHasZAxisTitle;
2482 116 : xDiagramProperties->getPropertyValue(
2483 116 : OUString ("HasSecondaryXAxisTitle")) >>= bHasSecondaryXAxisTitle;
2484 116 : xDiagramProperties->getPropertyValue(
2485 116 : OUString ("HasSecondaryYAxisTitle")) >>= bHasSecondaryYAxisTitle;
2486 :
2487 116 : xDiagramProperties->getPropertyValue(
2488 116 : OUString ("HasXAxisGrid")) >>= bHasXAxisMajorGrid;
2489 116 : xDiagramProperties->getPropertyValue(
2490 116 : OUString ("HasYAxisGrid")) >>= bHasYAxisMajorGrid;
2491 116 : xDiagramProperties->getPropertyValue(
2492 116 : OUString ("HasZAxisGrid")) >>= bHasZAxisMajorGrid;
2493 :
2494 116 : xDiagramProperties->getPropertyValue(
2495 116 : OUString ("HasXAxisHelpGrid")) >>= bHasXAxisMinorGrid;
2496 116 : xDiagramProperties->getPropertyValue(
2497 116 : OUString ("HasYAxisHelpGrid")) >>= bHasYAxisMinorGrid;
2498 116 : xDiagramProperties->getPropertyValue(
2499 116 : OUString ("HasZAxisHelpGrid")) >>= bHasZAxisMinorGrid;
2500 :
2501 232 : Reference< XPropertySet > xAxisProp;
2502 232 : Reference< drawing::XShape > xAxisTitle;
2503 232 : Reference< beans::XPropertySet > xMajorGrid;
2504 232 : Reference< beans::XPropertySet > xMinorGrid;
2505 116 : sal_Int32 nAxisType = XML_catAx;
2506 116 : const char* sAxPos = NULL;
2507 :
2508 116 : switch( rAxisIdPair.nAxisType )
2509 : {
2510 : case AXIS_PRIMARY_X:
2511 : {
2512 58 : Reference< css::chart::XAxisXSupplier > xAxisXSupp( mxDiagram, uno::UNO_QUERY );
2513 58 : if( xAxisXSupp.is())
2514 58 : xAxisProp = xAxisXSupp->getXAxis();
2515 58 : if( bHasXAxisTitle )
2516 5 : xAxisTitle.set( xAxisXSupp->getXAxisTitle(), uno::UNO_QUERY );
2517 58 : if( bHasXAxisMajorGrid )
2518 7 : xMajorGrid.set( xAxisXSupp->getXMainGrid(), uno::UNO_QUERY );
2519 58 : if( bHasXAxisMinorGrid )
2520 0 : xMinorGrid.set( xAxisXSupp->getXHelpGrid(), uno::UNO_QUERY );
2521 :
2522 58 : sal_Int32 eChartType = getChartType( );
2523 58 : if( (eChartType == chart::TYPEID_SCATTER)
2524 48 : || (eChartType == chart::TYPEID_BUBBLE) )
2525 11 : nAxisType = XML_valAx;
2526 47 : else if( eChartType == chart::TYPEID_STOCK )
2527 2 : nAxisType = XML_dateAx;
2528 : // FIXME: axPos, need to check axis direction
2529 58 : sAxPos = "b";
2530 58 : break;
2531 : }
2532 : case AXIS_PRIMARY_Y:
2533 : {
2534 54 : Reference< css::chart::XAxisYSupplier > xAxisYSupp( mxDiagram, uno::UNO_QUERY );
2535 54 : if( xAxisYSupp.is())
2536 54 : xAxisProp = xAxisYSupp->getYAxis();
2537 54 : if( bHasYAxisTitle )
2538 7 : xAxisTitle.set( xAxisYSupp->getYAxisTitle(), uno::UNO_QUERY );
2539 54 : if( bHasYAxisMajorGrid )
2540 52 : xMajorGrid.set( xAxisYSupp->getYMainGrid(), uno::UNO_QUERY );
2541 54 : if( bHasYAxisMinorGrid )
2542 5 : xMinorGrid.set( xAxisYSupp->getYHelpGrid(), uno::UNO_QUERY );
2543 :
2544 54 : nAxisType = XML_valAx;
2545 : // FIXME: axPos, need to check axis direction
2546 54 : sAxPos = "l";
2547 54 : break;
2548 : }
2549 : case AXIS_PRIMARY_Z:
2550 : {
2551 0 : Reference< css::chart::XAxisZSupplier > xAxisZSupp( mxDiagram, uno::UNO_QUERY );
2552 0 : if( xAxisZSupp.is())
2553 0 : xAxisProp = xAxisZSupp->getZAxis();
2554 0 : if( bHasZAxisTitle )
2555 0 : xAxisTitle.set( xAxisZSupp->getZAxisTitle(), uno::UNO_QUERY );
2556 0 : if( bHasZAxisMajorGrid )
2557 0 : xMajorGrid.set( xAxisZSupp->getZMainGrid(), uno::UNO_QUERY );
2558 0 : if( bHasZAxisMinorGrid )
2559 0 : xMinorGrid.set( xAxisZSupp->getZHelpGrid(), uno::UNO_QUERY );
2560 :
2561 0 : sal_Int32 eChartType = getChartType( );
2562 0 : if( (eChartType == chart::TYPEID_SCATTER)
2563 0 : || (eChartType == chart::TYPEID_BUBBLE) )
2564 0 : nAxisType = XML_valAx;
2565 0 : else if( eChartType == chart::TYPEID_STOCK )
2566 0 : nAxisType = XML_dateAx;
2567 : // FIXME: axPos, need to check axis direction
2568 0 : sAxPos = "b";
2569 0 : break;
2570 : }
2571 : case AXIS_SECONDARY_Y:
2572 : {
2573 4 : Reference< css::chart::XTwoAxisYSupplier > xAxisTwoYSupp( mxDiagram, uno::UNO_QUERY );
2574 4 : if( xAxisTwoYSupp.is())
2575 4 : xAxisProp = xAxisTwoYSupp->getSecondaryYAxis();
2576 4 : if( bHasSecondaryYAxisTitle )
2577 : {
2578 0 : Reference< css::chart::XSecondAxisTitleSupplier > xAxisSupp( mxDiagram, uno::UNO_QUERY );
2579 0 : xAxisTitle.set( xAxisSupp->getSecondYAxisTitle(), uno::UNO_QUERY );
2580 : }
2581 :
2582 4 : nAxisType = XML_valAx;
2583 : // FIXME: axPos, need to check axis direction
2584 4 : sAxPos = "r";
2585 4 : break;
2586 : }
2587 : }
2588 :
2589 232 : _exportAxis(xAxisProp, xAxisTitle, xMajorGrid, xMinorGrid, nAxisType, sAxPos, rAxisIdPair);
2590 116 : }
2591 :
2592 116 : void ChartExport::_exportAxis(
2593 : const Reference< XPropertySet >& xAxisProp,
2594 : const Reference< drawing::XShape >& xAxisTitle,
2595 : const Reference< XPropertySet >& xMajorGrid,
2596 : const Reference< XPropertySet >& xMinorGrid,
2597 : sal_Int32 nAxisType,
2598 : const char* sAxisPos,
2599 : const AxisIdPair& rAxisIdPair )
2600 : {
2601 116 : FSHelperPtr pFS = GetFS();
2602 : pFS->startElement( FSNS( XML_c, nAxisType ),
2603 116 : FSEND );
2604 : pFS->singleElement( FSNS( XML_c, XML_axId ),
2605 : XML_val, I32S( rAxisIdPair.nAxisId ),
2606 116 : FSEND );
2607 :
2608 : pFS->startElement( FSNS( XML_c, XML_scaling ),
2609 116 : FSEND );
2610 :
2611 : // logBase, min, max
2612 116 : if(GetProperty( xAxisProp, "Logarithmic" ) )
2613 : {
2614 116 : bool bLogarithmic = false;
2615 116 : mAny >>= bLogarithmic;
2616 116 : if( bLogarithmic )
2617 : {
2618 : // default value is 10?
2619 1 : sal_Int32 nLogBase = 10;
2620 : pFS->singleElement( FSNS( XML_c, XML_logBase ),
2621 : XML_val, I32S( nLogBase ),
2622 1 : FSEND );
2623 : }
2624 : }
2625 :
2626 : // orientation: minMax, maxMin
2627 116 : bool bReverseDirection = false;
2628 116 : if(GetProperty( xAxisProp, "ReverseDirection" ) )
2629 116 : mAny >>= bReverseDirection;
2630 :
2631 116 : const char* orientation = bReverseDirection ? "maxMin":"minMax";
2632 : pFS->singleElement( FSNS( XML_c, XML_orientation ),
2633 : XML_val, orientation,
2634 116 : FSEND );
2635 :
2636 116 : bool bAutoMax = false;
2637 116 : if(GetProperty( xAxisProp, "AutoMax" ) )
2638 116 : mAny >>= bAutoMax;
2639 :
2640 116 : if( !bAutoMax && (GetProperty( xAxisProp, "Max" ) ) )
2641 : {
2642 1 : double dMax = 0;
2643 1 : mAny >>= dMax;
2644 : pFS->singleElement( FSNS( XML_c, XML_max ),
2645 : XML_val, IS( dMax ),
2646 1 : FSEND );
2647 : }
2648 :
2649 116 : bool bAutoMin = false;
2650 116 : if(GetProperty( xAxisProp, "AutoMin" ) )
2651 116 : mAny >>= bAutoMin;
2652 :
2653 116 : if( !bAutoMin && (GetProperty( xAxisProp, "Min" ) ) )
2654 : {
2655 2 : double dMin = 0;
2656 2 : mAny >>= dMin;
2657 : pFS->singleElement( FSNS( XML_c, XML_min ),
2658 : XML_val, IS( dMin ),
2659 2 : FSEND );
2660 : }
2661 :
2662 116 : pFS->endElement( FSNS( XML_c, XML_scaling ) );
2663 :
2664 116 : bool bVisible = true;
2665 116 : if( xAxisProp.is() )
2666 : {
2667 116 : xAxisProp->getPropertyValue(
2668 116 : OUString ("Visible")) >>= bVisible;
2669 : }
2670 :
2671 : // only export each axis only once non-deleted
2672 : bool bDeleted = std::find(maExportedAxis.begin(),
2673 116 : maExportedAxis.end(), rAxisIdPair.nAxisType) != maExportedAxis.end();
2674 :
2675 116 : if (!bDeleted)
2676 110 : maExportedAxis.insert(rAxisIdPair.nAxisType);
2677 :
2678 : pFS->singleElement( FSNS( XML_c, XML_delete ),
2679 226 : XML_val, !bDeleted && bVisible ? "0" : "1",
2680 225 : FSEND );
2681 :
2682 : // FIXME: axPos, need to check the property "ReverseDirection"
2683 : pFS->singleElement( FSNS( XML_c, XML_axPos ),
2684 : XML_val, sAxisPos,
2685 116 : FSEND );
2686 : // major grid line
2687 116 : if( xMajorGrid.is())
2688 : {
2689 : pFS->startElement( FSNS( XML_c, XML_majorGridlines ),
2690 59 : FSEND );
2691 59 : exportShapeProps( xMajorGrid );
2692 59 : pFS->endElement( FSNS( XML_c, XML_majorGridlines ) );
2693 : }
2694 :
2695 : // minor grid line
2696 116 : if( xMinorGrid.is())
2697 : {
2698 : pFS->startElement( FSNS( XML_c, XML_minorGridlines ),
2699 5 : FSEND );
2700 5 : exportShapeProps( xMinorGrid );
2701 5 : pFS->endElement( FSNS( XML_c, XML_minorGridlines ) );
2702 : }
2703 :
2704 : // title
2705 116 : if( xAxisTitle.is() )
2706 12 : exportTitle( xAxisTitle );
2707 :
2708 116 : bool bLinkedNumFmt = true;
2709 116 : if (GetProperty(xAxisProp, "LinkNumberFormatToSource"))
2710 116 : mAny >>= bLinkedNumFmt;
2711 :
2712 232 : OUString aNumberFormatString("General");
2713 116 : if (GetProperty(xAxisProp, "NumberFormat"))
2714 : {
2715 116 : sal_Int32 nKey = 0;
2716 116 : mAny >>= nKey;
2717 116 : aNumberFormatString = getNumberFormatCode(nKey);
2718 : }
2719 :
2720 232 : OString sNumberFormatString = OUStringToOString(aNumberFormatString, RTL_TEXTENCODING_UTF8);
2721 : pFS->singleElement(FSNS(XML_c, XML_numFmt),
2722 : XML_formatCode, sNumberFormatString.getStr(),
2723 : XML_sourceLinked, bLinkedNumFmt ? "1" : "0",
2724 116 : FSEND);
2725 :
2726 : // majorTickMark
2727 116 : sal_Int32 nValue = 0;
2728 116 : if(GetProperty( xAxisProp, "Marks" ) )
2729 : {
2730 116 : mAny >>= nValue;
2731 116 : bool bInner = nValue & css::chart::ChartAxisMarks::INNER;
2732 116 : bool bOuter = nValue & css::chart::ChartAxisMarks::OUTER;
2733 116 : const char* majorTickMark = NULL;
2734 116 : if( bInner && bOuter )
2735 1 : majorTickMark = "cross";
2736 115 : else if( bInner )
2737 0 : majorTickMark = "in";
2738 115 : else if( bOuter )
2739 73 : majorTickMark = "out";
2740 : else
2741 42 : majorTickMark = "none";
2742 : pFS->singleElement( FSNS( XML_c, XML_majorTickMark ),
2743 : XML_val, majorTickMark,
2744 116 : FSEND );
2745 : }
2746 : // minorTickMark
2747 116 : if(GetProperty( xAxisProp, "HelpMarks" ) )
2748 : {
2749 116 : mAny >>= nValue;
2750 116 : bool bInner = nValue & css::chart::ChartAxisMarks::INNER;
2751 116 : bool bOuter = nValue & css::chart::ChartAxisMarks::OUTER;
2752 116 : const char* minorTickMark = NULL;
2753 116 : if( bInner && bOuter )
2754 0 : minorTickMark = "cross";
2755 116 : else if( bInner )
2756 0 : minorTickMark = "in";
2757 116 : else if( bOuter )
2758 0 : minorTickMark = "out";
2759 : else
2760 116 : minorTickMark = "none";
2761 : pFS->singleElement( FSNS( XML_c, XML_minorTickMark ),
2762 : XML_val, minorTickMark,
2763 116 : FSEND );
2764 : }
2765 : // tickLblPos
2766 116 : const char* sTickLblPos = NULL;
2767 116 : bool bDisplayLabel = true;
2768 116 : if(GetProperty( xAxisProp, "DisplayLabels" ) )
2769 116 : mAny >>= bDisplayLabel;
2770 116 : if( bDisplayLabel && (GetProperty( xAxisProp, "LabelPosition" ) ) )
2771 : {
2772 115 : css::chart::ChartAxisLabelPosition eLabelPosition = css::chart::ChartAxisLabelPosition_NEAR_AXIS;
2773 115 : mAny >>= eLabelPosition;
2774 115 : switch( eLabelPosition )
2775 : {
2776 : case css::chart::ChartAxisLabelPosition_NEAR_AXIS:
2777 : case css::chart::ChartAxisLabelPosition_NEAR_AXIS_OTHER_SIDE:
2778 115 : sTickLblPos = "nextTo";
2779 115 : break;
2780 : case css::chart::ChartAxisLabelPosition_OUTSIDE_START:
2781 0 : sTickLblPos = "low";
2782 0 : break;
2783 : case css::chart::ChartAxisLabelPosition_OUTSIDE_END:
2784 0 : sTickLblPos = "high";
2785 0 : break;
2786 : default:
2787 0 : sTickLblPos = "nextTo";
2788 0 : break;
2789 : }
2790 : }
2791 : else
2792 : {
2793 1 : sTickLblPos = "none";
2794 : }
2795 : pFS->singleElement( FSNS( XML_c, XML_tickLblPos ),
2796 : XML_val, sTickLblPos,
2797 116 : FSEND );
2798 :
2799 : // shape properties
2800 116 : exportShapeProps( xAxisProp );
2801 :
2802 116 : exportTextProps(xAxisProp);
2803 :
2804 : pFS->singleElement( FSNS( XML_c, XML_crossAx ),
2805 : XML_val, I32S( rAxisIdPair.nCrossAx ),
2806 116 : FSEND );
2807 :
2808 : // crosses & crossesAt
2809 116 : bool bCrossesValue = false;
2810 116 : const char* sCrosses = NULL;
2811 116 : if(GetProperty( xAxisProp, "CrossoverPosition" ) )
2812 : {
2813 116 : css::chart::ChartAxisPosition ePosition( css::chart::ChartAxisPosition_ZERO );
2814 116 : mAny >>= ePosition;
2815 116 : switch( ePosition )
2816 : {
2817 : case css::chart::ChartAxisPosition_START:
2818 0 : sCrosses = "min";
2819 0 : break;
2820 : case css::chart::ChartAxisPosition_END:
2821 4 : sCrosses = "max";
2822 4 : break;
2823 : case css::chart::ChartAxisPosition_ZERO:
2824 112 : sCrosses = "autoZero";
2825 112 : break;
2826 : default:
2827 0 : bCrossesValue = true;
2828 0 : break;
2829 : }
2830 : }
2831 :
2832 116 : if( bCrossesValue && GetProperty( xAxisProp, "CrossoverValue" ) )
2833 : {
2834 0 : double dValue = 0;
2835 0 : mAny >>= dValue;
2836 : pFS->singleElement( FSNS( XML_c, XML_crossesAt ),
2837 : XML_val, IS( dValue ),
2838 0 : FSEND );
2839 : }
2840 : else
2841 : {
2842 : pFS->singleElement( FSNS( XML_c, XML_crosses ),
2843 : XML_val, sCrosses,
2844 116 : FSEND );
2845 : }
2846 :
2847 116 : if( ( nAxisType == XML_catAx )
2848 71 : || ( nAxisType == XML_dateAx ) )
2849 : {
2850 : // FIXME: seems not support? use default value,
2851 47 : const char* isAuto = "1";
2852 : pFS->singleElement( FSNS( XML_c, XML_auto ),
2853 : XML_val, isAuto,
2854 47 : FSEND );
2855 :
2856 47 : if( nAxisType == XML_catAx )
2857 : {
2858 : // FIXME: seems not support? lblAlgn
2859 45 : const char* sLblAlgn = "ctr";
2860 : pFS->singleElement( FSNS( XML_c, XML_lblAlgn ),
2861 : XML_val, sLblAlgn,
2862 45 : FSEND );
2863 : }
2864 :
2865 : // FIXME: seems not support? lblOffset
2866 47 : sal_Int32 nLblOffset = 100;
2867 : pFS->singleElement( FSNS( XML_c, XML_lblOffset ),
2868 : XML_val, I32S( nLblOffset ),
2869 47 : FSEND );
2870 : }
2871 :
2872 : // majorUnit
2873 116 : bool bAutoStepMain = false;
2874 116 : if(GetProperty( xAxisProp, "AutoStepMain" ) )
2875 116 : mAny >>= bAutoStepMain;
2876 :
2877 116 : if( !bAutoStepMain && (GetProperty( xAxisProp, "StepMain" ) ) )
2878 : {
2879 1 : double dMajorUnit = 0;
2880 1 : mAny >>= dMajorUnit;
2881 : pFS->singleElement( FSNS( XML_c, XML_majorUnit ),
2882 : XML_val, IS( dMajorUnit ),
2883 1 : FSEND );
2884 : }
2885 : // minorUnit
2886 116 : bool bAutoStepHelp = false;
2887 116 : if(GetProperty( xAxisProp, "AutoStepHelp" ) )
2888 116 : mAny >>= bAutoStepHelp;
2889 :
2890 116 : if( !bAutoStepHelp && (GetProperty( xAxisProp, "StepHelp" ) ) )
2891 : {
2892 0 : double dMinorUnit = 0;
2893 0 : mAny >>= dMinorUnit;
2894 : pFS->singleElement( FSNS( XML_c, XML_minorUnit ),
2895 : XML_val, IS( dMinorUnit ),
2896 0 : FSEND );
2897 : }
2898 :
2899 116 : if( nAxisType == XML_valAx && GetProperty( xAxisProp, "DisplayUnits" ) )
2900 : {
2901 69 : bool bDisplayUnits = false;
2902 69 : mAny >>= bDisplayUnits;
2903 69 : if(bDisplayUnits)
2904 : {
2905 1 : OUString aVal;
2906 1 : if(GetProperty( xAxisProp, "BuiltInUnit" ))
2907 : {
2908 1 : mAny >>= aVal;
2909 1 : if(!aVal.isEmpty())
2910 : {
2911 : pFS->startElement( FSNS( XML_c, XML_dispUnits ),
2912 1 : FSEND );
2913 :
2914 1 : OString aBuiltInUnit = OUStringToOString(aVal, RTL_TEXTENCODING_UTF8);
2915 : pFS->singleElement( FSNS( XML_c, XML_builtInUnit ),
2916 : XML_val, aBuiltInUnit.getStr(),
2917 1 : FSEND );
2918 :
2919 1 : pFS->singleElement(FSNS( XML_c, XML_dispUnitsLbl ),FSEND);
2920 1 : pFS->endElement( FSNS( XML_c, XML_dispUnits ) );
2921 : }
2922 1 : }
2923 : }
2924 : }
2925 : // TODO: text properties
2926 :
2927 232 : pFS->endElement( FSNS( XML_c, nAxisType ) );
2928 116 : }
2929 :
2930 : namespace {
2931 :
2932 121 : struct LabelPlacementParam
2933 : {
2934 : bool mbExport;
2935 : sal_Int32 meDefault;
2936 :
2937 : std::unordered_set<sal_Int32> maAllowedValues;
2938 :
2939 121 : LabelPlacementParam() :
2940 : mbExport(true),
2941 121 : meDefault(css::chart::DataLabelPlacement::OUTSIDE) {}
2942 :
2943 121 : void allowAll()
2944 : {
2945 121 : maAllowedValues.insert(css::chart::DataLabelPlacement::OUTSIDE);
2946 121 : maAllowedValues.insert(css::chart::DataLabelPlacement::INSIDE);
2947 121 : maAllowedValues.insert(css::chart::DataLabelPlacement::CENTER);
2948 121 : maAllowedValues.insert(css::chart::DataLabelPlacement::NEAR_ORIGIN);
2949 121 : maAllowedValues.insert(css::chart::DataLabelPlacement::TOP);
2950 121 : maAllowedValues.insert(css::chart::DataLabelPlacement::BOTTOM);
2951 121 : maAllowedValues.insert(css::chart::DataLabelPlacement::LEFT);
2952 121 : maAllowedValues.insert(css::chart::DataLabelPlacement::RIGHT);
2953 121 : maAllowedValues.insert(css::chart::DataLabelPlacement::AVOID_OVERLAP);
2954 121 : }
2955 : };
2956 :
2957 111 : const char* toOOXMLPlacement( sal_Int32 nPlacement )
2958 : {
2959 111 : switch (nPlacement)
2960 : {
2961 42 : case css::chart::DataLabelPlacement::OUTSIDE: return "outEnd";
2962 1 : case css::chart::DataLabelPlacement::INSIDE: return "inEnd";
2963 5 : case css::chart::DataLabelPlacement::CENTER: return "ctr";
2964 2 : case css::chart::DataLabelPlacement::NEAR_ORIGIN: return "inBase";
2965 0 : case css::chart::DataLabelPlacement::TOP: return "t";
2966 0 : case css::chart::DataLabelPlacement::BOTTOM: return "b";
2967 0 : case css::chart::DataLabelPlacement::LEFT: return "l";
2968 28 : case css::chart::DataLabelPlacement::RIGHT: return "r";
2969 33 : case css::chart::DataLabelPlacement::AVOID_OVERLAP: return "bestFit";
2970 : default:
2971 : ;
2972 : }
2973 :
2974 0 : return "outEnd";
2975 : }
2976 :
2977 176 : void writeLabelProperties(
2978 : FSHelperPtr pFS, const uno::Reference<beans::XPropertySet>& xPropSet, const LabelPlacementParam& rLabelParam )
2979 : {
2980 176 : if (!xPropSet.is())
2981 176 : return;
2982 :
2983 176 : chart2::DataPointLabel aLabel;
2984 176 : sal_Int32 nLabelBorderWidth = 0;
2985 176 : sal_Int32 nLabelBorderColor = 0x00FFFFFF;
2986 :
2987 176 : xPropSet->getPropertyValue("Label") >>= aLabel;
2988 176 : xPropSet->getPropertyValue("LabelBorderWidth") >>= nLabelBorderWidth;
2989 176 : xPropSet->getPropertyValue("LabelBorderColor") >>= nLabelBorderColor;
2990 :
2991 176 : if (nLabelBorderWidth > 0)
2992 : {
2993 4 : pFS->startElement(FSNS(XML_c, XML_spPr), FSEND);
2994 4 : pFS->startElement(FSNS(XML_a, XML_ln), XML_w, IS(convertHmmToEmu(nLabelBorderWidth)), FSEND);
2995 4 : if (nLabelBorderColor != -1)
2996 : {
2997 4 : pFS->startElement(FSNS(XML_a, XML_solidFill), FSEND);
2998 :
2999 4 : OString aStr = OString::number(nLabelBorderColor, 16).toAsciiUpperCase();
3000 4 : pFS->singleElement(FSNS(XML_a, XML_srgbClr), XML_val, aStr.getStr(), FSEND);
3001 :
3002 4 : pFS->endElement(FSNS(XML_a, XML_solidFill));
3003 : }
3004 4 : pFS->endElement(FSNS(XML_a, XML_ln));
3005 4 : pFS->endElement(FSNS(XML_c, XML_spPr));
3006 : }
3007 :
3008 176 : if (rLabelParam.mbExport)
3009 : {
3010 124 : sal_Int32 nLabelPlacement = rLabelParam.meDefault;
3011 124 : if (xPropSet->getPropertyValue("LabelPlacement") >>= nLabelPlacement)
3012 : {
3013 111 : if (!rLabelParam.maAllowedValues.count(nLabelPlacement))
3014 14 : nLabelPlacement = rLabelParam.meDefault;
3015 111 : pFS->singleElement(FSNS(XML_c, XML_dLblPos), XML_val, toOOXMLPlacement(nLabelPlacement), FSEND);
3016 : }
3017 : }
3018 :
3019 176 : pFS->singleElement(FSNS(XML_c, XML_showLegendKey), XML_val, BS(aLabel.ShowLegendSymbol), FSEND);
3020 176 : pFS->singleElement(FSNS(XML_c, XML_showVal), XML_val, BS(aLabel.ShowNumber), FSEND);
3021 176 : pFS->singleElement(FSNS(XML_c, XML_showCatName), XML_val, BS(aLabel.ShowCategoryName), FSEND);
3022 176 : pFS->singleElement(FSNS(XML_c, XML_showSerName), XML_val, BS(false), FSEND);
3023 176 : pFS->singleElement(FSNS(XML_c, XML_showPercent), XML_val, BS(aLabel.ShowNumberInPercent), FSEND);
3024 : }
3025 :
3026 : }
3027 :
3028 121 : void ChartExport::exportDataLabels(
3029 : const uno::Reference<chart2::XDataSeries> & xSeries, sal_Int32 nSeriesLength, sal_Int32 eChartType )
3030 : {
3031 121 : if (!xSeries.is() || nSeriesLength <= 0)
3032 0 : return;
3033 :
3034 121 : uno::Reference<beans::XPropertySet> xPropSet(xSeries, uno::UNO_QUERY);
3035 121 : if (!xPropSet.is())
3036 0 : return;
3037 :
3038 242 : FSHelperPtr pFS = GetFS();
3039 121 : pFS->startElement(FSNS(XML_c, XML_dLbls), FSEND);
3040 :
3041 242 : uno::Sequence<sal_Int32> aAttrLabelIndices;
3042 121 : xPropSet->getPropertyValue("AttributedDataPoints") >>= aAttrLabelIndices;
3043 :
3044 : // We must not export label placement property when the chart type doesn't
3045 : // support this option in MS Office, else MS Office would think the file
3046 : // is corrupt & refuse to open it.
3047 :
3048 121 : const chart::TypeGroupInfo& rInfo = chart::GetTypeGroupInfo(static_cast<chart::TypeId>(eChartType));
3049 242 : LabelPlacementParam aParam;
3050 121 : aParam.mbExport = !mbIs3DChart;
3051 121 : aParam.meDefault = rInfo.mnDefLabelPos;
3052 121 : aParam.allowAll();
3053 121 : switch (eChartType) // diagram chart type
3054 : {
3055 : case chart::TYPEID_PIE:
3056 7 : if(getChartType() == chart::TYPEID_DOUGHNUT)
3057 2 : aParam.mbExport = false;
3058 : else
3059 : // All pie charts support label placement.
3060 5 : aParam.mbExport = true;
3061 7 : break;
3062 : case chart::TYPEID_AREA:
3063 : case chart::TYPEID_RADARLINE:
3064 : case chart::TYPEID_RADARAREA:
3065 : // These chart types don't support label placement.
3066 5 : aParam.mbExport = false;
3067 5 : break;
3068 : case chart::TYPEID_BAR:
3069 71 : if (mbStacked || mbPercent)
3070 : {
3071 20 : aParam.maAllowedValues.clear();
3072 20 : aParam.maAllowedValues.insert(css::chart::DataLabelPlacement::CENTER);
3073 20 : aParam.maAllowedValues.insert(css::chart::DataLabelPlacement::INSIDE);
3074 20 : aParam.maAllowedValues.insert(css::chart::DataLabelPlacement::NEAR_ORIGIN);
3075 20 : aParam.meDefault = css::chart::DataLabelPlacement::CENTER;
3076 : }
3077 : else // Clustered bar chart
3078 : {
3079 51 : aParam.maAllowedValues.clear();
3080 51 : aParam.maAllowedValues.insert(css::chart::DataLabelPlacement::CENTER);
3081 51 : aParam.maAllowedValues.insert(css::chart::DataLabelPlacement::INSIDE);
3082 51 : aParam.maAllowedValues.insert(css::chart::DataLabelPlacement::OUTSIDE);
3083 51 : aParam.maAllowedValues.insert(css::chart::DataLabelPlacement::NEAR_ORIGIN);
3084 51 : aParam.meDefault = css::chart::DataLabelPlacement::OUTSIDE;
3085 : }
3086 71 : break;
3087 : default:
3088 : ;
3089 : }
3090 :
3091 121 : const sal_Int32* p = aAttrLabelIndices.getConstArray();
3092 121 : const sal_Int32* pEnd = p + aAttrLabelIndices.getLength();
3093 176 : for (; p != pEnd; ++p)
3094 : {
3095 55 : sal_Int32 nIdx = *p;
3096 55 : uno::Reference<beans::XPropertySet> xLabelPropSet = xSeries->getDataPointByIndex(nIdx);
3097 55 : if (!xLabelPropSet.is())
3098 0 : continue;
3099 :
3100 : // Individual label property that overwrites the baseline.
3101 55 : pFS->startElement(FSNS(XML_c, XML_dLbl), FSEND);
3102 55 : pFS->singleElement(FSNS(XML_c, XML_idx), XML_val, I32S(nIdx), FSEND);
3103 55 : writeLabelProperties(pFS, xLabelPropSet, aParam);
3104 55 : pFS->endElement(FSNS(XML_c, XML_dLbl));
3105 55 : }
3106 :
3107 : // Baseline label properties for all labels.
3108 121 : writeLabelProperties(pFS, xPropSet, aParam);
3109 :
3110 : pFS->singleElement(FSNS(XML_c, XML_showLeaderLines),
3111 : XML_val, "0",
3112 121 : FSEND);
3113 :
3114 242 : pFS->endElement(FSNS(XML_c, XML_dLbls));
3115 : }
3116 :
3117 121 : void ChartExport::exportDataPoints(
3118 : const uno::Reference< beans::XPropertySet > & xSeriesProperties,
3119 : sal_Int32 nSeriesLength )
3120 : {
3121 121 : uno::Reference< chart2::XDataSeries > xSeries( xSeriesProperties, uno::UNO_QUERY );
3122 121 : bool bVaryColorsByPoint = false;
3123 242 : Sequence< sal_Int32 > aDataPointSeq;
3124 121 : if( xSeriesProperties.is())
3125 : {
3126 121 : Any aAny = xSeriesProperties->getPropertyValue(
3127 121 : OUString( "AttributedDataPoints" ));
3128 121 : aAny >>= aDataPointSeq;
3129 121 : xSeriesProperties->getPropertyValue(
3130 121 : OUString( "VaryColorsByPoint" )) >>= bVaryColorsByPoint;
3131 : }
3132 :
3133 121 : const sal_Int32 * pPoints = aDataPointSeq.getConstArray();
3134 : sal_Int32 nElement;
3135 242 : Reference< chart2::XColorScheme > xColorScheme;
3136 121 : if( mxNewDiagram.is())
3137 121 : xColorScheme.set( mxNewDiagram->getDefaultColorScheme());
3138 :
3139 121 : if( bVaryColorsByPoint && xColorScheme.is() )
3140 : {
3141 7 : ::std::set< sal_Int32 > aAttrPointSet;
3142 7 : ::std::copy( pPoints, pPoints + aDataPointSeq.getLength(),
3143 14 : ::std::inserter( aAttrPointSet, aAttrPointSet.begin()));
3144 7 : const ::std::set< sal_Int32 >::const_iterator aEndIt( aAttrPointSet.end());
3145 43 : for( nElement = 0; nElement < nSeriesLength; ++nElement )
3146 : {
3147 36 : uno::Reference< beans::XPropertySet > xPropSet;
3148 36 : if( aAttrPointSet.find( nElement ) != aEndIt )
3149 : {
3150 : try
3151 : {
3152 72 : xPropSet = SchXMLSeriesHelper::createOldAPIDataPointPropertySet(
3153 36 : xSeries, nElement, getModel() );
3154 : }
3155 0 : catch( const uno::Exception & rEx )
3156 : {
3157 : SAL_WARN( "oox", "Exception caught during Export of data point: " << rEx.Message );
3158 : }
3159 : }
3160 : else
3161 : {
3162 : // property set only containing the color
3163 0 : xPropSet.set( new ColorPropertySet( xColorScheme->getColorByIndex( nElement )));
3164 : }
3165 :
3166 36 : if( xPropSet.is() )
3167 : {
3168 36 : FSHelperPtr pFS = GetFS();
3169 : pFS->startElement( FSNS( XML_c, XML_dPt ),
3170 36 : FSEND );
3171 : pFS->singleElement( FSNS( XML_c, XML_idx ),
3172 : XML_val, I32S(nElement),
3173 36 : FSEND );
3174 36 : exportShapeProps( xPropSet );
3175 :
3176 36 : pFS->endElement( FSNS( XML_c, XML_dPt ) );
3177 : }
3178 43 : }
3179 121 : }
3180 121 : }
3181 :
3182 58 : void ChartExport::exportAxesId( sal_Int32 nAttachedAxis )
3183 : {
3184 58 : sal_Int32 nAxisIdx = lcl_generateRandomValue();
3185 58 : sal_Int32 nAxisIdy = lcl_generateRandomValue();
3186 58 : maAxes.push_back( AxisIdPair( AXIS_PRIMARY_X, nAxisIdx, nAxisIdy ) );
3187 58 : maAxes.push_back( AxisIdPair( nAttachedAxis, nAxisIdy, nAxisIdx ) );
3188 58 : FSHelperPtr pFS = GetFS();
3189 : pFS->singleElement( FSNS( XML_c, XML_axId ),
3190 : XML_val, I32S( nAxisIdx ),
3191 58 : FSEND );
3192 : pFS->singleElement( FSNS( XML_c, XML_axId ),
3193 : XML_val, I32S( nAxisIdy ),
3194 58 : FSEND );
3195 58 : if( mbHasZAxis )
3196 : {
3197 11 : sal_Int32 nAxisIdz = 0;
3198 11 : if( isDeep3dChart() )
3199 : {
3200 0 : nAxisIdz = lcl_generateRandomValue();
3201 0 : maAxes.push_back( AxisIdPair( AXIS_PRIMARY_Z, nAxisIdz, nAxisIdy ) );
3202 : }
3203 : pFS->singleElement( FSNS( XML_c, XML_axId ),
3204 : XML_val, I32S( nAxisIdz ),
3205 11 : FSEND );
3206 58 : }
3207 58 : }
3208 :
3209 45 : void ChartExport::exportGrouping( bool isBar )
3210 : {
3211 45 : FSHelperPtr pFS = GetFS();
3212 90 : Reference< XPropertySet > xPropSet( mxDiagram , uno::UNO_QUERY);
3213 : // grouping
3214 45 : if( GetProperty( xPropSet, "Stacked" ) )
3215 45 : mAny >>= mbStacked;
3216 45 : if( GetProperty( xPropSet, "Percent" ) )
3217 45 : mAny >>= mbPercent;
3218 :
3219 45 : const char* grouping = NULL;
3220 45 : if (mbStacked)
3221 4 : grouping = "stacked";
3222 41 : else if (mbPercent)
3223 4 : grouping = "percentStacked";
3224 : else
3225 : {
3226 37 : if( isBar && !isDeep3dChart() )
3227 : {
3228 26 : grouping = "clustered";
3229 : }
3230 : else
3231 11 : grouping = "standard";
3232 : }
3233 : pFS->singleElement( FSNS( XML_c, XML_grouping ),
3234 : XML_val, grouping,
3235 90 : FSEND );
3236 45 : }
3237 :
3238 121 : void ChartExport::exportTrendlines( Reference< chart2::XDataSeries > xSeries )
3239 : {
3240 121 : FSHelperPtr pFS = GetFS();
3241 242 : Reference< chart2::XRegressionCurveContainer > xRegressionCurveContainer( xSeries, UNO_QUERY );
3242 121 : if( xRegressionCurveContainer.is() )
3243 : {
3244 121 : Sequence< Reference< chart2::XRegressionCurve > > aRegCurveSeq = xRegressionCurveContainer->getRegressionCurves();
3245 121 : const Reference< chart2::XRegressionCurve >* pBeg = aRegCurveSeq.getConstArray();
3246 121 : const Reference< chart2::XRegressionCurve >* pEnd = pBeg + aRegCurveSeq.getLength();
3247 124 : for( const Reference< chart2::XRegressionCurve >* pIt = pBeg; pIt != pEnd; ++pIt )
3248 : {
3249 3 : Reference< chart2::XRegressionCurve > xRegCurve = *pIt;
3250 3 : if (!xRegCurve.is())
3251 0 : continue;
3252 :
3253 6 : Reference< XPropertySet > xProperties( xRegCurve , uno::UNO_QUERY );
3254 :
3255 6 : OUString aService;
3256 6 : Reference< lang::XServiceName > xServiceName( xProperties, UNO_QUERY );
3257 3 : if( !xServiceName.is() )
3258 0 : continue;
3259 :
3260 3 : aService = xServiceName->getServiceName();
3261 :
3262 8 : if(aService != "com.sun.star.chart2.LinearRegressionCurve" &&
3263 4 : aService != "com.sun.star.chart2.ExponentialRegressionCurve" &&
3264 4 : aService != "com.sun.star.chart2.LogarithmicRegressionCurve" &&
3265 4 : aService != "com.sun.star.chart2.PotentialRegressionCurve" &&
3266 6 : aService != "com.sun.star.chart2.PolynomialRegressionCurve" &&
3267 1 : aService != "com.sun.star.chart2.MovingAverageRegressionCurve")
3268 0 : continue;
3269 :
3270 3 : pFS->startElement( FSNS( XML_c, XML_trendline ), FSEND );
3271 :
3272 6 : OUString aName;
3273 3 : xProperties->getPropertyValue("CurveName") >>= aName;
3274 3 : if(!aName.isEmpty())
3275 : {
3276 3 : pFS->startElement( FSNS( XML_c, XML_name), FSEND);
3277 3 : pFS->writeEscaped(aName);
3278 3 : pFS->endElement( FSNS( XML_c, XML_name) );
3279 : }
3280 :
3281 3 : exportShapeProps( xProperties );
3282 :
3283 3 : if( aService == "com.sun.star.chart2.LinearRegressionCurve" )
3284 : {
3285 : pFS->singleElement( FSNS( XML_c, XML_trendlineType ),
3286 : XML_val, "linear",
3287 1 : FSEND );
3288 : }
3289 2 : else if( aService == "com.sun.star.chart2.ExponentialRegressionCurve" )
3290 : {
3291 : pFS->singleElement( FSNS( XML_c, XML_trendlineType ),
3292 : XML_val, "exp",
3293 0 : FSEND );
3294 : }
3295 2 : else if( aService == "com.sun.star.chart2.LogarithmicRegressionCurve" )
3296 : {
3297 : pFS->singleElement( FSNS( XML_c, XML_trendlineType ),
3298 : XML_val, "log",
3299 0 : FSEND );
3300 : }
3301 2 : else if( aService == "com.sun.star.chart2.PotentialRegressionCurve" )
3302 : {
3303 : pFS->singleElement( FSNS( XML_c, XML_trendlineType ),
3304 : XML_val, "power",
3305 0 : FSEND );
3306 : }
3307 2 : else if( aService == "com.sun.star.chart2.PolynomialRegressionCurve" )
3308 : {
3309 : pFS->singleElement( FSNS( XML_c, XML_trendlineType ),
3310 : XML_val, "poly",
3311 1 : FSEND );
3312 :
3313 1 : sal_Int32 aDegree = 2;
3314 1 : xProperties->getPropertyValue( "PolynomialDegree") >>= aDegree;
3315 : pFS->singleElement( FSNS( XML_c, XML_order ),
3316 : XML_val, I32S(aDegree),
3317 1 : FSEND );
3318 : }
3319 1 : else if( aService == "com.sun.star.chart2.MovingAverageRegressionCurve" )
3320 : {
3321 : pFS->singleElement( FSNS( XML_c, XML_trendlineType ),
3322 : XML_val, "movingAvg",
3323 1 : FSEND );
3324 :
3325 1 : sal_Int32 aPeriod = 2;
3326 1 : xProperties->getPropertyValue( "MovingAveragePeriod") >>= aPeriod;
3327 :
3328 : pFS->singleElement( FSNS( XML_c, XML_period ),
3329 : XML_val, I32S(aPeriod),
3330 1 : FSEND );
3331 : }
3332 : else
3333 : {
3334 : // should never happen
3335 : // This would produce invalid OOXML files so we check earlier for the type
3336 : assert(false);
3337 : }
3338 :
3339 3 : double fExtrapolateForward = 0.0;
3340 3 : double fExtrapolateBackward = 0.0;
3341 :
3342 3 : xProperties->getPropertyValue("ExtrapolateForward") >>= fExtrapolateForward;
3343 3 : xProperties->getPropertyValue("ExtrapolateBackward") >>= fExtrapolateBackward;
3344 :
3345 : pFS->singleElement( FSNS( XML_c, XML_forward ),
3346 : XML_val, OString::number(fExtrapolateForward).getStr(),
3347 3 : FSEND );
3348 :
3349 : pFS->singleElement( FSNS( XML_c, XML_backward ),
3350 : XML_val, OString::number(fExtrapolateBackward).getStr(),
3351 3 : FSEND );
3352 :
3353 3 : bool bForceIntercept = false;
3354 3 : xProperties->getPropertyValue("ForceIntercept") >>= bForceIntercept;
3355 :
3356 3 : if (bForceIntercept)
3357 : {
3358 1 : double fInterceptValue = 0.0;
3359 1 : xProperties->getPropertyValue("InterceptValue") >>= fInterceptValue;
3360 :
3361 : pFS->singleElement( FSNS( XML_c, XML_intercept ),
3362 : XML_val, OString::number(fInterceptValue).getStr(),
3363 1 : FSEND );
3364 : }
3365 :
3366 : // Equation properties
3367 6 : Reference< XPropertySet > xEquationProperties( xRegCurve->getEquationProperties() );
3368 :
3369 : // Show Equation
3370 3 : bool bShowEquation = false;
3371 3 : xEquationProperties->getPropertyValue("ShowEquation") >>= bShowEquation;
3372 :
3373 : // Show R^2
3374 3 : bool bShowCorrelationCoefficient = false;
3375 3 : xEquationProperties->getPropertyValue("ShowCorrelationCoefficient") >>= bShowCorrelationCoefficient;
3376 :
3377 : pFS->singleElement( FSNS( XML_c, XML_dispRSqr ),
3378 : XML_val, bShowCorrelationCoefficient ? "1" : "0",
3379 3 : FSEND );
3380 :
3381 : pFS->singleElement( FSNS( XML_c, XML_dispEq ),
3382 : XML_val, bShowEquation ? "1" : "0",
3383 3 : FSEND );
3384 :
3385 3 : pFS->endElement( FSNS( XML_c, XML_trendline ) );
3386 124 : }
3387 121 : }
3388 121 : }
3389 :
3390 35 : void ChartExport::exportMarker(Reference< chart2::XDataSeries > xSeries)
3391 : {
3392 35 : Reference< XPropertySet > xPropSet( xSeries, uno::UNO_QUERY );
3393 70 : chart2::Symbol aSymbol;
3394 35 : if( GetProperty( xPropSet, "Symbol" ) )
3395 35 : mAny >>= aSymbol;
3396 :
3397 35 : if(aSymbol.Style != chart2::SymbolStyle_STANDARD && aSymbol.Style != chart2::SymbolStyle_AUTO && aSymbol.Style != chart2::SymbolStyle_NONE)
3398 35 : return;
3399 :
3400 70 : FSHelperPtr pFS = GetFS();
3401 : pFS->startElement( FSNS( XML_c, XML_marker ),
3402 35 : FSEND );
3403 :
3404 35 : sal_Int32 nSymbol = aSymbol.StandardSymbol;
3405 : // TODO: more properties support for marker
3406 35 : const char* pSymbolType = NULL;
3407 35 : switch( nSymbol )
3408 : {
3409 : case 0:
3410 27 : pSymbolType = "square";
3411 27 : break;
3412 : case 1:
3413 2 : pSymbolType = "diamond";
3414 2 : break;
3415 : case 2:
3416 : case 3:
3417 : case 4:
3418 : case 5:
3419 0 : pSymbolType = "triangle";
3420 0 : break;
3421 : case 8:
3422 2 : pSymbolType = "circle";
3423 2 : break;
3424 : case 9:
3425 0 : pSymbolType = "star";
3426 0 : break;
3427 : case 10:
3428 3 : pSymbolType = "x"; // in MS office 2010 built in symbol marker 'X' is represented as 'x'
3429 3 : break;
3430 : case 11:
3431 0 : pSymbolType = "plus";
3432 0 : break;
3433 : case 13:
3434 0 : pSymbolType = "dash";
3435 0 : break;
3436 : default:
3437 1 : pSymbolType = "square";
3438 1 : break;
3439 : }
3440 :
3441 35 : bool bSkipFormatting = false;
3442 35 : if (aSymbol.Style == chart2::SymbolStyle_NONE)
3443 : {
3444 17 : bSkipFormatting = true;
3445 17 : pSymbolType = "none";
3446 : }
3447 :
3448 35 : if( pSymbolType )
3449 : {
3450 : pFS->singleElement( FSNS( XML_c, XML_symbol ),
3451 : XML_val, pSymbolType,
3452 35 : FSEND );
3453 : }
3454 :
3455 35 : if (!bSkipFormatting)
3456 : {
3457 18 : awt::Size aSymbolSize = aSymbol.Size;
3458 18 : sal_Int32 nSize = std::max( aSymbolSize.Width, aSymbolSize.Height );
3459 :
3460 18 : nSize = nSize/250.0*7.0 + 1; // just guessed based on some test cases,
3461 : //the value is always 1 less than the actual value.
3462 18 : nSize = std::min<sal_Int32>( 72, std::max<sal_Int32>( 2, nSize ) );
3463 : pFS->singleElement( FSNS( XML_c, XML_size),
3464 : XML_val, I32S(nSize),
3465 18 : FSEND );
3466 :
3467 : pFS->startElement( FSNS( XML_c, XML_spPr ),
3468 18 : FSEND );
3469 :
3470 18 : util::Color aColor = aSymbol.FillColor;
3471 18 : if (GetProperty(xPropSet, "Color"))
3472 18 : mAny >>= aColor;
3473 :
3474 18 : if (aColor == -1)
3475 : {
3476 0 : pFS->singleElement(FSNS(XML_a, XML_noFill), FSEND);
3477 : }
3478 : else
3479 18 : WriteSolidFill(aColor);
3480 :
3481 18 : pFS->endElement( FSNS( XML_c, XML_spPr ) );
3482 : }
3483 :
3484 70 : pFS->endElement( FSNS( XML_c, XML_marker ) );
3485 : }
3486 :
3487 35 : void ChartExport::exportSmooth()
3488 : {
3489 35 : FSHelperPtr pFS = GetFS();
3490 70 : Reference< XPropertySet > xPropSet( mxDiagram , uno::UNO_QUERY );
3491 35 : sal_Int32 nSplineType = 0;
3492 35 : if( GetProperty( xPropSet, "SplineType" ) )
3493 35 : mAny >>= nSplineType;
3494 35 : const char* pVal = nSplineType != 0 ? "1" : "0";
3495 : pFS->singleElement( FSNS( XML_c, XML_smooth ),
3496 : XML_val, pVal,
3497 70 : FSEND );
3498 35 : }
3499 :
3500 5 : void ChartExport::exportFirstSliceAng( )
3501 : {
3502 5 : FSHelperPtr pFS = GetFS();
3503 5 : sal_Int32 nStartingAngle = 0;
3504 10 : Reference< XPropertySet > xPropSet( mxDiagram , uno::UNO_QUERY);
3505 5 : if( GetProperty( xPropSet, "StartingAngle" ) )
3506 5 : mAny >>= nStartingAngle;
3507 :
3508 : // convert to ooxml angle
3509 5 : nStartingAngle = (450 - nStartingAngle ) % 360;
3510 : pFS->singleElement( FSNS( XML_c, XML_firstSliceAng ),
3511 : XML_val, I32S( nStartingAngle ),
3512 10 : FSEND );
3513 5 : }
3514 :
3515 : namespace {
3516 :
3517 1 : const char* getErrorBarStyle(sal_Int32 nErrorBarStyle)
3518 : {
3519 1 : switch(nErrorBarStyle)
3520 : {
3521 : case cssc::ErrorBarStyle::NONE:
3522 0 : return NULL;
3523 : case cssc::ErrorBarStyle::VARIANCE:
3524 0 : break;
3525 : case cssc::ErrorBarStyle::STANDARD_DEVIATION:
3526 0 : return "stdDev";
3527 : case cssc::ErrorBarStyle::ABSOLUTE:
3528 0 : return "fixedVal";
3529 : case cssc::ErrorBarStyle::RELATIVE:
3530 1 : return "percentage";
3531 : case cssc::ErrorBarStyle::ERROR_MARGIN:
3532 0 : break;
3533 : case cssc::ErrorBarStyle::STANDARD_ERROR:
3534 0 : return "stdErr";
3535 : case cssc::ErrorBarStyle::FROM_DATA:
3536 0 : return "cust";
3537 : default:
3538 : assert(false && "can't happen");
3539 : }
3540 0 : return NULL;
3541 : }
3542 :
3543 0 : Reference< chart2::data::XDataSequence> getLabeledSequence(
3544 : const uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > >& aSequences,
3545 : bool bPositive )
3546 : {
3547 0 : const OUString aRolePrefix( "error-bars" );
3548 0 : OUString aDirection;
3549 0 : if(bPositive)
3550 0 : aDirection = "positive";
3551 : else
3552 0 : aDirection = "negative";
3553 :
3554 0 : for( sal_Int32 nI=0; nI< aSequences.getLength(); ++nI )
3555 : {
3556 0 : if( aSequences[nI].is())
3557 : {
3558 0 : uno::Reference< chart2::data::XDataSequence > xSequence( aSequences[nI]->getValues());
3559 0 : uno::Reference< beans::XPropertySet > xSeqProp( xSequence, uno::UNO_QUERY_THROW );
3560 0 : OUString aRole;
3561 0 : if( ( xSeqProp->getPropertyValue(
3562 0 : OUString( "Role" )) >>= aRole ) &&
3563 0 : aRole.match( aRolePrefix ) && aRole.indexOf(aDirection) >= 0 )
3564 : {
3565 0 : return xSequence;
3566 0 : }
3567 : }
3568 : }
3569 :
3570 0 : return Reference< chart2::data::XDataSequence > ();
3571 : }
3572 :
3573 : }
3574 :
3575 1 : void ChartExport::exportErrorBar(Reference< XPropertySet> xErrorBarProps, bool bYError)
3576 : {
3577 1 : sal_Int32 nErrorBarStyle = cssc::ErrorBarStyle::NONE;
3578 1 : xErrorBarProps->getPropertyValue("ErrorBarStyle") >>= nErrorBarStyle;
3579 1 : const char* pErrorBarStyle = getErrorBarStyle(nErrorBarStyle);
3580 1 : if(!pErrorBarStyle)
3581 1 : return;
3582 :
3583 1 : FSHelperPtr pFS = GetFS();
3584 : pFS->startElement( FSNS( XML_c, XML_errBars ),
3585 1 : FSEND );
3586 : pFS->singleElement( FSNS( XML_c, XML_errDir ),
3587 : XML_val, bYError ? "y" : "x",
3588 1 : FSEND );
3589 1 : bool bPositive = false, bNegative = false;
3590 1 : xErrorBarProps->getPropertyValue("ShowPositiveError") >>= bPositive;
3591 1 : xErrorBarProps->getPropertyValue("ShowNegativeError") >>= bNegative;
3592 : const char* pErrBarType;
3593 1 : if(bPositive && bNegative)
3594 1 : pErrBarType = "both";
3595 0 : else if(bPositive)
3596 0 : pErrBarType = "plus";
3597 0 : else if(bNegative)
3598 0 : pErrBarType = "minus";
3599 : else
3600 : {
3601 : // what the hell should we do now?
3602 : // at least this makes the file valid
3603 0 : pErrBarType = "both";
3604 : }
3605 : pFS->singleElement( FSNS( XML_c, XML_errBarType ),
3606 : XML_val, pErrBarType,
3607 1 : FSEND );
3608 : pFS->singleElement( FSNS( XML_c, XML_errValType ),
3609 : XML_val, pErrorBarStyle,
3610 1 : FSEND );
3611 : pFS->singleElement( FSNS( XML_c, XML_noEndCap ),
3612 : XML_val, "0",
3613 1 : FSEND );
3614 1 : if(nErrorBarStyle == cssc::ErrorBarStyle::FROM_DATA)
3615 : {
3616 0 : uno::Reference< chart2::data::XDataSource > xDataSource(xErrorBarProps, uno::UNO_QUERY);
3617 : Sequence< Reference < chart2::data::XLabeledDataSequence > > aSequences =
3618 0 : xDataSource->getDataSequences();
3619 :
3620 0 : if(bPositive)
3621 : {
3622 0 : exportSeriesValues(getLabeledSequence(aSequences, true), XML_plus);
3623 : }
3624 :
3625 0 : if(bNegative)
3626 : {
3627 0 : exportSeriesValues(getLabeledSequence(aSequences, false), XML_minus);
3628 0 : }
3629 : }
3630 : else
3631 : {
3632 1 : double nVal = 0.0;
3633 1 : if(nErrorBarStyle == cssc::ErrorBarStyle::STANDARD_DEVIATION)
3634 : {
3635 0 : xErrorBarProps->getPropertyValue("Weight") >>= nVal;
3636 : }
3637 : else
3638 : {
3639 1 : if(bPositive)
3640 1 : xErrorBarProps->getPropertyValue("PositiveError") >>= nVal;
3641 : else
3642 0 : xErrorBarProps->getPropertyValue("NegativeError") >>= nVal;
3643 : }
3644 :
3645 1 : OString aVal = OString::number(nVal);
3646 :
3647 : pFS->singleElement( FSNS( XML_c, XML_val ),
3648 : XML_val, aVal.getStr(),
3649 1 : FSEND );
3650 : }
3651 :
3652 1 : pFS->endElement( FSNS( XML_c, XML_errBars) );
3653 : }
3654 :
3655 13 : void ChartExport::exportView3D()
3656 : {
3657 13 : Reference< XPropertySet > xPropSet( mxDiagram , uno::UNO_QUERY);
3658 13 : if( !xPropSet.is() )
3659 13 : return;
3660 26 : FSHelperPtr pFS = GetFS();
3661 : pFS->startElement( FSNS( XML_c, XML_view3D ),
3662 13 : FSEND );
3663 13 : sal_Int32 eChartType = getChartType( );
3664 : // rotX
3665 13 : if( GetProperty( xPropSet, "RotationHorizontal" ) )
3666 : {
3667 13 : sal_Int32 nRotationX = 0;
3668 13 : mAny >>= nRotationX;
3669 13 : if( nRotationX < 0 )
3670 : {
3671 2 : if(eChartType == chart::TYPEID_PIE)
3672 : {
3673 : /* In OOXML we get value in 0..90 range for pie chart X rotation , whereas we expect it to be in -90..90 range,
3674 : so we conver that during import. It is modified in View3DConverter::convertFromModel()
3675 : here we convert it back to 0..90 as we received in import */
3676 2 : nRotationX += 90; // X rotation (map Chart2 [-179,180] to OOXML [0..90])
3677 : }
3678 : else
3679 0 : nRotationX += 360; // X rotation (map Chart2 [-179,180] to OOXML [-90..90])
3680 : }
3681 : pFS->singleElement( FSNS( XML_c, XML_rotX ),
3682 : XML_val, I32S( nRotationX ),
3683 13 : FSEND );
3684 : }
3685 : // rotY
3686 13 : if( GetProperty( xPropSet, "RotationVertical" ) )
3687 : {
3688 : // Y rotation (map Chart2 [-179,180] to OOXML [0..359])
3689 13 : if( eChartType == chart::TYPEID_PIE && GetProperty( xPropSet, "StartingAngle" ) )
3690 : {
3691 : // Y rotation used as 'first pie slice angle' in 3D pie charts
3692 2 : sal_Int32 nStartingAngle=0;
3693 2 : mAny >>= nStartingAngle;
3694 : // convert to ooxml angle
3695 2 : nStartingAngle = (450 - nStartingAngle ) % 360;
3696 : pFS->singleElement( FSNS( XML_c, XML_rotY ),
3697 : XML_val, I32S( nStartingAngle ),
3698 2 : FSEND );
3699 : }
3700 : else
3701 : {
3702 11 : sal_Int32 nRotationY = 0;
3703 11 : mAny >>= nRotationY;
3704 : // Y rotation (map Chart2 [-179,180] to OOXML [0..359])
3705 11 : if( nRotationY < 0 )
3706 0 : nRotationY += 360;
3707 : pFS->singleElement( FSNS( XML_c, XML_rotY ),
3708 : XML_val, I32S( nRotationY ),
3709 11 : FSEND );
3710 : }
3711 : }
3712 : // rAngAx
3713 13 : if( GetProperty( xPropSet, "RightAngledAxes" ) )
3714 : {
3715 13 : bool bRightAngled = false;
3716 13 : mAny >>= bRightAngled;
3717 13 : const char* sRightAngled = bRightAngled ? "1":"0";
3718 : pFS->singleElement( FSNS( XML_c, XML_rAngAx ),
3719 : XML_val, sRightAngled,
3720 13 : FSEND );
3721 : }
3722 : // perspective
3723 13 : if( GetProperty( xPropSet, "Perspective" ) )
3724 : {
3725 13 : sal_Int32 nPerspective = 0;
3726 13 : mAny >>= nPerspective;
3727 : // map Chart2 [0,100] to OOXML [0..200]
3728 13 : nPerspective *= 2;
3729 : pFS->singleElement( FSNS( XML_c, XML_perspective ),
3730 : XML_val, I32S( nPerspective ),
3731 13 : FSEND );
3732 : }
3733 26 : pFS->endElement( FSNS( XML_c, XML_view3D ) );
3734 : }
3735 :
3736 37 : bool ChartExport::isDeep3dChart()
3737 : {
3738 37 : bool isDeep = false;
3739 37 : if( mbIs3DChart )
3740 : {
3741 17 : Reference< XPropertySet > xPropSet( mxDiagram , uno::UNO_QUERY);
3742 17 : if( GetProperty( xPropSet, "Deep" ) )
3743 17 : mAny >>= isDeep;
3744 : }
3745 37 : return isDeep;
3746 : }
3747 :
3748 116 : OUString ChartExport::getNumberFormatCode(sal_Int32 nKey) const
3749 : {
3750 116 : uno::Reference<util::XNumberFormatsSupplier> xNumberFormatsSupplier(mxChartModel, uno::UNO_QUERY_THROW);
3751 232 : uno::Reference<util::XNumberFormats> xNumberFormats = xNumberFormatsSupplier->getNumberFormats();
3752 232 : uno::Reference<beans::XPropertySet> xNumberFormat = xNumberFormats->getByKey(nKey);
3753 :
3754 116 : if (!xNumberFormat.is())
3755 0 : return OUString();
3756 :
3757 232 : uno::Any aAny = xNumberFormat->getPropertyValue("FormatString");
3758 232 : OUString aValue;
3759 116 : aAny >>= aValue;
3760 232 : return aValue;
3761 : }
3762 :
3763 : }// drawingml
3764 246 : }// oox
3765 :
3766 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|