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