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 <sal/config.h>
21 :
22 : #include <boost/noncopyable.hpp>
23 : #include <sax/tools/converter.hxx>
24 :
25 : #include <xmloff/xmlprmap.hxx>
26 :
27 : #include "SchXMLExport.hxx"
28 : #include "XMLChartPropertySetMapper.hxx"
29 : #include "ColorPropertySet.hxx"
30 : #include "SchXMLTools.hxx"
31 : #include "SchXMLEnumConverter.hxx"
32 : #include "facreg.hxx"
33 :
34 : #include <tools/debug.hxx>
35 : #include <comphelper/processfactory.hxx>
36 : #include <tools/globname.hxx>
37 : #include <comphelper/classids.hxx>
38 :
39 : #include <xmloff/nmspmap.hxx>
40 : #include <xmloff/xmlnmspe.hxx>
41 : #include <xmloff/xmltoken.hxx>
42 : #include <xmloff/families.hxx>
43 : #include <xmloff/xmlaustp.hxx>
44 : #include <xmloff/xmluconv.hxx>
45 : #include <xmloff/xmlmetae.hxx>
46 : #include <xmloff/SchXMLSeriesHelper.hxx>
47 : #include "xexptran.hxx"
48 : #include <rtl/math.hxx>
49 : // header for any2enum
50 : #include <comphelper/extract.hxx>
51 :
52 : #include <list>
53 : #include <typeinfo>
54 : #include <algorithm>
55 :
56 : #include <com/sun/star/task/XStatusIndicatorSupplier.hpp>
57 : #include <com/sun/star/lang/XServiceInfo.hpp>
58 : #include <com/sun/star/lang/XServiceName.hpp>
59 : #include <com/sun/star/beans/XPropertySet.hpp>
60 : #include <com/sun/star/uno/XComponentContext.hpp>
61 : #include <com/sun/star/util/XRefreshable.hpp>
62 :
63 : #include <com/sun/star/chart/XAxis.hpp>
64 : #include <com/sun/star/chart/XAxisSupplier.hpp>
65 : #include <com/sun/star/chart/XChartDocument.hpp>
66 : #include <com/sun/star/chart/ChartLegendPosition.hpp>
67 : #include <com/sun/star/chart/ChartLegendExpansion.hpp>
68 : #include <com/sun/star/chart/ChartDataRowSource.hpp>
69 : #include <com/sun/star/chart/ChartAxisAssign.hpp>
70 : #include <com/sun/star/chart/ChartAxisType.hpp>
71 : #include <com/sun/star/chart/TimeIncrement.hpp>
72 : #include <com/sun/star/chart/TimeInterval.hpp>
73 : #include <com/sun/star/chart/TimeUnit.hpp>
74 : #include <com/sun/star/chart/ChartSeriesAddress.hpp>
75 : #include <com/sun/star/chart/X3DDisplay.hpp>
76 : #include <com/sun/star/chart/XStatisticDisplay.hpp>
77 : #include <com/sun/star/chart/XSecondAxisTitleSupplier.hpp>
78 : #include <com/sun/star/chart/XDiagramPositioning.hpp>
79 :
80 : #include <com/sun/star/chart2/XAnyDescriptionAccess.hpp>
81 : #include <com/sun/star/chart2/AxisType.hpp>
82 : #include <com/sun/star/chart2/XChartDocument.hpp>
83 : #include <com/sun/star/chart2/XDiagram.hpp>
84 : #include <com/sun/star/chart2/RelativePosition.hpp>
85 : #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
86 : #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
87 : #include <com/sun/star/chart2/XChartTypeContainer.hpp>
88 : #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
89 : #include <com/sun/star/chart2/data/XDataSource.hpp>
90 : #include <com/sun/star/chart2/data/XDataSink.hpp>
91 : #include <com/sun/star/chart2/data/XDataReceiver.hpp>
92 : #include <com/sun/star/chart2/data/XDataProvider.hpp>
93 : #include <com/sun/star/chart2/data/XDatabaseDataProvider.hpp>
94 : #include <com/sun/star/chart2/data/XRangeXMLConversion.hpp>
95 : #include <com/sun/star/chart2/data/XTextualDataSequence.hpp>
96 : #include <com/sun/star/chart2/data/XNumericalDataSequence.hpp>
97 :
98 : #include <com/sun/star/util/MeasureUnit.hpp>
99 : #include <com/sun/star/util/XStringMapping.hpp>
100 : #include <com/sun/star/drawing/HomogenMatrix.hpp>
101 : #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
102 : #include <com/sun/star/drawing/XShapes.hpp>
103 : #include <com/sun/star/embed/Aspects.hpp>
104 : #include <com/sun/star/embed/XVisualObject.hpp>
105 : #include <com/sun/star/container/XChild.hpp>
106 :
107 : #include "MultiPropertySetHandler.hxx"
108 : #include "PropertyMap.hxx"
109 :
110 : using namespace com::sun::star;
111 : using namespace ::xmloff::token;
112 :
113 : using namespace ::com::sun::star;
114 : using ::com::sun::star::uno::Sequence;
115 : using ::com::sun::star::uno::Reference;
116 : using ::com::sun::star::uno::Any;
117 : using ::std::vector;
118 :
119 : // class SchXMLExportHelper_Impl
120 :
121 : class SchXMLExportHelper_Impl: private boost::noncopyable
122 : {
123 : public:
124 : // first: data sequence for label, second: data sequence for values.
125 : typedef ::std::pair< ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataSequence >,
126 : ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataSequence > > tLabelValuesDataPair;
127 : typedef ::std::vector< tLabelValuesDataPair > tDataSequenceCont;
128 :
129 : public:
130 : SchXMLExportHelper_Impl( SvXMLExport& rExport,
131 : SvXMLAutoStylePoolP& rASPool );
132 :
133 : virtual ~SchXMLExportHelper_Impl();
134 :
135 : // auto-styles
136 : /// parse chart and collect all auto-styles used in current pool
137 : void collectAutoStyles( com::sun::star::uno::Reference<
138 : com::sun::star::chart::XChartDocument > rChartDoc );
139 :
140 : /// write the styles collected into the current pool as <style:style> elements
141 : void exportAutoStyles();
142 :
143 : /** export the <chart:chart> element corresponding to rChartDoc
144 : if bIncludeTable is true, the chart data is exported as <table:table>
145 : element (inside the chart element).
146 :
147 : Otherwise the external references stored in the chart document are used
148 : for writing the corresponding attributes at series
149 :
150 : All attributes contained in xAttrList are written at the chart element,
151 : which is the outer element of a chart. So these attributes can easily
152 : be parsed again by the container
153 : */
154 : void exportChart( com::sun::star::uno::Reference<
155 : com::sun::star::chart::XChartDocument > rChartDoc,
156 : sal_Bool bIncludeTable );
157 :
158 : UniReference< XMLPropertySetMapper > GetPropertySetMapper() const;
159 :
160 0 : void SetChartRangeAddress( const OUString& rAddress )
161 0 : { msChartAddress = rAddress; }
162 0 : void SetTableNumberList( const OUString& rList )
163 0 : { msTableNumberList = rList; }
164 :
165 : void InitRangeSegmentationProperties(
166 : const ::com::sun::star::uno::Reference<
167 : ::com::sun::star::chart2::XChartDocument > & xChartDoc );
168 :
169 : ::com::sun::star::awt::Size getPageSize(
170 : const ::com::sun::star::uno::Reference<
171 : ::com::sun::star::chart2::XChartDocument > & xChartDoc ) const;
172 :
173 : /** first parseDocument: collect autostyles and store names in this queue
174 : second parseDocument: export content and use names from this queue
175 : */
176 : ::std::queue< OUString > maAutoStyleNameQueue;
177 : void CollectAutoStyle(
178 : const std::vector< XMLPropertyState >& aStates );
179 : void AddAutoStyleAttribute(
180 : const std::vector< XMLPropertyState >& aStates );
181 :
182 0 : SvXMLAutoStylePoolP& GetAutoStylePoolP()
183 0 : { return mrAutoStylePool; }
184 :
185 : /// if bExportContent is false the auto-styles are collected
186 : void parseDocument( com::sun::star::uno::Reference<
187 : com::sun::star::chart::XChartDocument >& rChartDoc,
188 : sal_Bool bExportContent,
189 : sal_Bool bIncludeTable = sal_False );
190 : void exportTable();
191 : void exportPlotArea(
192 : com::sun::star::uno::Reference< com::sun::star::chart::XDiagram > xDiagram,
193 : com::sun::star::uno::Reference< com::sun::star::chart2::XDiagram > xNewDiagram,
194 : const ::com::sun::star::awt::Size & rPageSize,
195 : sal_Bool bExportContent,
196 : sal_Bool bIncludeTable );
197 : void exportCoordinateRegion( const com::sun::star::uno::Reference< com::sun::star::chart::XDiagram >& xDiagram );
198 : void exportAxes( const com::sun::star::uno::Reference< com::sun::star::chart::XDiagram > & xDiagram,
199 : const com::sun::star::uno::Reference< com::sun::star::chart2::XDiagram > & xNewDiagram,
200 : sal_Bool bExportContent );
201 : void exportAxis( enum XMLTokenEnum eDimension, enum XMLTokenEnum eAxisName,
202 : const Reference< beans::XPropertySet > xAxisProps, const Reference< chart2::XAxis >& xChart2Axis,
203 : const OUString& rCategoriesRanges,
204 : bool bHasTitle, bool bHasMajorGrid, bool bHasMinorGrid, bool bExportContent );
205 : void exportGrid( const Reference< beans::XPropertySet > xGridProperties, bool bMajor, bool bExportContent );
206 : void exportDateScale( const Reference< beans::XPropertySet > xAxisProps );
207 : void exportAxisTitle( const Reference< beans::XPropertySet > xTitleProps, bool bExportContent );
208 :
209 : void exportSeries(
210 : const com::sun::star::uno::Reference< com::sun::star::chart2::XDiagram > & xNewDiagram,
211 : const ::com::sun::star::awt::Size & rPageSize,
212 : sal_Bool bExportContent,
213 : sal_Bool bHasTwoYAxes );
214 :
215 : void exportPropertyMapping(
216 : const com::sun::star::uno::Reference< com::sun::star::chart2::data::XDataSource > & xSource,
217 : Sequence< OUString >& rSupportedMappings );
218 :
219 : void exportCandleStickSeries(
220 : const ::com::sun::star::uno::Sequence<
221 : ::com::sun::star::uno::Reference<
222 : ::com::sun::star::chart2::XDataSeries > > & aSeriesSeq,
223 : const ::com::sun::star::uno::Reference<
224 : ::com::sun::star::chart2::XDiagram > & xDiagram,
225 : sal_Bool bJapaneseCandleSticks,
226 : sal_Bool bExportContent );
227 : void exportDataPoints(
228 : const ::com::sun::star::uno::Reference<
229 : ::com::sun::star::beans::XPropertySet > & xSeriesProperties,
230 : sal_Int32 nSeriesLength,
231 : const ::com::sun::star::uno::Reference<
232 : ::com::sun::star::chart2::XDiagram > & xDiagram,
233 : sal_Bool bExportContent );
234 :
235 : void exportRegressionCurve(
236 : const com::sun::star::uno::Reference<com::sun::star::chart2::XDataSeries>& xSeries,
237 : const com::sun::star::awt::Size& rPageSize,
238 : sal_Bool bExportContent );
239 :
240 : void exportErrorBar (
241 : const ::com::sun::star::uno::Reference<beans::XPropertySet> &xSeriesProp, bool bYError,
242 : bool bExportContent );
243 :
244 : /// add svg position as attribute for current element
245 : void addPosition( const ::com::sun::star::awt::Point & rPosition );
246 : void addPosition( com::sun::star::uno::Reference< com::sun::star::drawing::XShape > xShape );
247 : /// add svg size as attribute for current element
248 : void addSize( const ::com::sun::star::awt::Size & rSize, bool bIsOOoNamespace = false );
249 : void addSize( com::sun::star::uno::Reference< com::sun::star::drawing::XShape > xShape, bool bIsOOoNamespace = false );
250 : /// exports a string as a paragraph element
251 : void exportText( const OUString& rText, bool bConvertTabsLFs = false );
252 :
253 : public:
254 : SvXMLExport& mrExport;
255 : SvXMLAutoStylePoolP& mrAutoStylePool;
256 : UniReference< XMLPropertySetMapper > mxPropertySetMapper;
257 : UniReference< XMLChartExportPropertyMapper > mxExpPropMapper;
258 :
259 : OUString msTableName;
260 : OUStringBuffer msStringBuffer;
261 : OUString msString;
262 :
263 : // members filled by InitRangeSegmentationProperties (retrieved from DataProvider)
264 : sal_Bool mbHasSeriesLabels;
265 : sal_Bool mbHasCategoryLabels; //if the categories are only automatically generated this will be false
266 : sal_Bool mbRowSourceColumns;
267 : OUString msChartAddress;
268 : OUString msTableNumberList;
269 : ::com::sun::star::uno::Sequence< sal_Int32 > maSequenceMapping;
270 :
271 : OUString msCLSID;
272 :
273 : ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes > mxAdditionalShapes;
274 :
275 : tDataSequenceCont m_aDataSequencesToExport;
276 : OUString maCategoriesRange;
277 : };
278 :
279 : namespace
280 : {
281 :
282 0 : class lcl_MatchesRole : public ::std::unary_function< Reference< chart2::data::XLabeledDataSequence >, bool >
283 : {
284 : public:
285 0 : explicit lcl_MatchesRole( const OUString & aRole ) :
286 0 : m_aRole( aRole )
287 0 : {}
288 :
289 0 : bool operator () ( const Reference< chart2::data::XLabeledDataSequence > & xSeq ) const
290 : {
291 0 : if( !xSeq.is() )
292 0 : return false;
293 0 : Reference< beans::XPropertySet > xProp( xSeq->getValues(), uno::UNO_QUERY );
294 0 : OUString aRole;
295 :
296 0 : return ( xProp.is() &&
297 0 : (xProp->getPropertyValue(
298 0 : OUString( "Role" ) ) >>= aRole ) &&
299 0 : m_aRole.equals( aRole ));
300 : }
301 :
302 : private:
303 : OUString m_aRole;
304 : };
305 :
306 : template< typename T >
307 0 : void lcl_SequenceToVectorAppend( const Sequence< T > & rSource, ::std::vector< T > & rDestination )
308 : {
309 0 : rDestination.reserve( rDestination.size() + rSource.getLength());
310 0 : ::std::copy( rSource.getConstArray(), rSource.getConstArray() + rSource.getLength(),
311 0 : ::std::back_inserter( rDestination ));
312 0 : }
313 :
314 : template< typename T >
315 0 : void lcl_SequenceToVector( const Sequence< T > & rSource, ::std::vector< T > & rDestination )
316 : {
317 0 : rDestination.clear();
318 0 : lcl_SequenceToVectorAppend( rSource, rDestination );
319 0 : }
320 :
321 0 : Reference< chart2::data::XLabeledDataSequence > lcl_getCategories( const Reference< chart2::XDiagram > & xDiagram )
322 : {
323 0 : Reference< chart2::data::XLabeledDataSequence > xResult;
324 : try
325 : {
326 : Reference< chart2::XCoordinateSystemContainer > xCooSysCnt(
327 0 : xDiagram, uno::UNO_QUERY_THROW );
328 : Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq(
329 0 : xCooSysCnt->getCoordinateSystems());
330 0 : for( sal_Int32 i=0; i<aCooSysSeq.getLength(); ++i )
331 : {
332 0 : Reference< chart2::XCoordinateSystem > xCooSys( aCooSysSeq[i] );
333 : SAL_WARN_IF( !xCooSys.is(), "xmloff.chart", "xCooSys is NULL" );
334 0 : for( sal_Int32 nN = xCooSys->getDimension(); nN--; )
335 : {
336 0 : const sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nN);
337 0 : for(sal_Int32 nI=0; nI<=nMaxAxisIndex; ++nI)
338 : {
339 0 : Reference< chart2::XAxis > xAxis = xCooSys->getAxisByDimension( nN, nI );
340 : SAL_WARN_IF( !xAxis.is(), "xmloff.chart", "xAxis is NULL");
341 0 : if( xAxis.is())
342 : {
343 0 : chart2::ScaleData aScaleData = xAxis->getScaleData();
344 0 : if( aScaleData.Categories.is())
345 : {
346 0 : xResult.set( aScaleData.Categories );
347 0 : break;
348 0 : }
349 : }
350 0 : }
351 : }
352 0 : }
353 : }
354 0 : catch( const uno::Exception & ex )
355 : {
356 : SAL_WARN("xmloff.chart", "Exception caught. Type: " << OUString::createFromAscii( typeid( ex ).name()) << ", Message: " << ex.Message);
357 : }
358 :
359 0 : return xResult;
360 : }
361 :
362 0 : Reference< chart2::data::XDataSource > lcl_createDataSource(
363 : const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aData )
364 : {
365 : Reference< uno::XComponentContext > xContext(
366 0 : comphelper::getProcessComponentContext() );
367 : Reference< chart2::data::XDataSink > xSink(
368 0 : xContext->getServiceManager()->createInstanceWithContext(
369 0 : "com.sun.star.chart2.data.DataSource", xContext ),
370 0 : uno::UNO_QUERY_THROW );
371 0 : xSink->setData( aData );
372 :
373 0 : return Reference< chart2::data::XDataSource >( xSink, uno::UNO_QUERY );
374 : }
375 :
376 0 : Sequence< Reference< chart2::data::XLabeledDataSequence > > lcl_getAllSeriesSequences( const Reference< chart2::XChartDocument >& xChartDoc )
377 : {
378 0 : ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aContainer;
379 0 : if( xChartDoc.is() )
380 : {
381 0 : Reference< chart2::XDiagram > xDiagram( xChartDoc->getFirstDiagram());
382 0 : ::std::vector< Reference< chart2::XDataSeries > > aSeriesVector( SchXMLSeriesHelper::getDataSeriesFromDiagram( xDiagram ));
383 0 : for( ::std::vector< Reference< chart2::XDataSeries > >::const_iterator aSeriesIt( aSeriesVector.begin() )
384 0 : ; aSeriesIt != aSeriesVector.end(); ++aSeriesIt )
385 : {
386 0 : Reference< chart2::data::XDataSource > xDataSource( *aSeriesIt, uno::UNO_QUERY );
387 0 : if( !xDataSource.is() )
388 0 : continue;
389 0 : uno::Sequence< Reference< chart2::data::XLabeledDataSequence > > aDataSequences( xDataSource->getDataSequences() );
390 0 : lcl_SequenceToVectorAppend( aDataSequences, aContainer );
391 0 : }
392 : }
393 :
394 0 : Sequence< Reference< chart2::data::XLabeledDataSequence > > aRet( aContainer.size());
395 0 : ::std::copy( aContainer.begin(), aContainer.end(), aRet.getArray());
396 :
397 0 : return aRet;
398 : }
399 :
400 : Reference< chart2::data::XLabeledDataSequence >
401 0 : lcl_getDataSequenceByRole(
402 : const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aLabeledSeq,
403 : const OUString & rRole )
404 : {
405 0 : Reference< chart2::data::XLabeledDataSequence > aNoResult;
406 :
407 0 : const Reference< chart2::data::XLabeledDataSequence > * pBegin = aLabeledSeq.getConstArray();
408 0 : const Reference< chart2::data::XLabeledDataSequence > * pEnd = pBegin + aLabeledSeq.getLength();
409 : const Reference< chart2::data::XLabeledDataSequence > * pMatch =
410 0 : ::std::find_if( pBegin, pEnd, lcl_MatchesRole( rRole ));
411 :
412 0 : if( pMatch != pEnd )
413 0 : return *pMatch;
414 :
415 0 : return aNoResult;
416 : }
417 :
418 0 : Reference< chart2::data::XDataSource > lcl_pressUsedDataIntoRectangularFormat( const Reference< chart2::XChartDocument >& xChartDoc, sal_Bool& rOutSourceHasCategoryLabels )
419 : {
420 0 : ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aLabeledSeqVector;
421 :
422 : //categories are always the first sequence
423 0 : Reference< chart2::XDiagram > xDiagram( xChartDoc->getFirstDiagram());
424 0 : Reference< chart2::data::XLabeledDataSequence > xCategories( lcl_getCategories( xDiagram ) );
425 0 : if( xCategories.is() )
426 0 : aLabeledSeqVector.push_back( xCategories );
427 0 : rOutSourceHasCategoryLabels = sal_Bool(xCategories.is());
428 :
429 : Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeriesSeqVector(
430 0 : lcl_getAllSeriesSequences( xChartDoc ) );
431 :
432 : //the first x-values is always the next sequence //todo ... other x-values get lost for old format
433 : Reference< chart2::data::XLabeledDataSequence > xXValues(
434 0 : lcl_getDataSequenceByRole( aSeriesSeqVector, OUString( "values-x" ) ) );
435 0 : if( xXValues.is() )
436 0 : aLabeledSeqVector.push_back( xXValues );
437 :
438 : //add all other sequences now without x-values
439 0 : lcl_MatchesRole aHasXValues( OUString( "values-x" ) );
440 0 : for( sal_Int32 nN=0; nN<aSeriesSeqVector.getLength(); nN++ )
441 : {
442 0 : if( !aHasXValues( aSeriesSeqVector[nN] ) )
443 0 : aLabeledSeqVector.push_back( aSeriesSeqVector[nN] );
444 : }
445 :
446 0 : Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeq( aLabeledSeqVector.size() );
447 0 : ::std::copy( aLabeledSeqVector.begin(), aLabeledSeqVector.end(), aSeq.getArray() );
448 :
449 0 : return lcl_createDataSource( aSeq );
450 : }
451 :
452 0 : bool lcl_isSeriesAttachedToFirstAxis(
453 : const Reference< chart2::XDataSeries > & xDataSeries )
454 : {
455 0 : bool bResult=true;
456 :
457 : try
458 : {
459 0 : sal_Int32 nAxisIndex = 0;
460 0 : Reference< beans::XPropertySet > xProp( xDataSeries, uno::UNO_QUERY_THROW );
461 0 : if( xProp.is() )
462 0 : xProp->getPropertyValue("AttachedAxisIndex") >>= nAxisIndex;
463 0 : bResult = (0==nAxisIndex);
464 : }
465 0 : catch( const uno::Exception & ex )
466 : {
467 : SAL_WARN("xmloff.chart", "Exception caught. Type: " << OUString::createFromAscii( typeid( ex ).name()) << ", Message: " << ex.Message);
468 : }
469 :
470 0 : return bResult;
471 : }
472 :
473 0 : OUString lcl_ConvertRange( const OUString & rRange, const Reference< chart2::XChartDocument > & xDoc )
474 : {
475 0 : OUString aResult = rRange;
476 0 : if( !xDoc.is() )
477 0 : return aResult;
478 : Reference< chart2::data::XRangeXMLConversion > xConversion(
479 0 : xDoc->getDataProvider(), uno::UNO_QUERY );
480 0 : if( xConversion.is())
481 0 : aResult = xConversion->convertRangeToXML( rRange );
482 0 : return aResult;
483 : }
484 :
485 : typedef ::std::pair< OUString, OUString > tLabelAndValueRange;
486 :
487 0 : tLabelAndValueRange lcl_getLabelAndValueRangeByRole(
488 : const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aSeqCnt,
489 : const OUString & rRole,
490 : const Reference< chart2::XChartDocument > & xDoc,
491 : SchXMLExportHelper_Impl::tDataSequenceCont & rOutSequencesToExport )
492 : {
493 0 : tLabelAndValueRange aResult;
494 :
495 : Reference< chart2::data::XLabeledDataSequence > xLabeledSeq(
496 0 : lcl_getDataSequenceByRole( aSeqCnt, rRole ));
497 0 : if( xLabeledSeq.is())
498 : {
499 0 : Reference< chart2::data::XDataSequence > xLabelSeq( xLabeledSeq->getLabel());
500 0 : if( xLabelSeq.is())
501 0 : aResult.first = lcl_ConvertRange( xLabelSeq->getSourceRangeRepresentation(), xDoc );
502 :
503 0 : Reference< chart2::data::XDataSequence > xValueSeq( xLabeledSeq->getValues());
504 0 : if( xValueSeq.is())
505 0 : aResult.second = lcl_ConvertRange( xValueSeq->getSourceRangeRepresentation(), xDoc );
506 :
507 0 : if( xLabelSeq.is() || xValueSeq.is())
508 0 : rOutSequencesToExport.push_back( SchXMLExportHelper_Impl::tLabelValuesDataPair( xLabelSeq, xValueSeq ));
509 : }
510 :
511 0 : return aResult;
512 : }
513 :
514 0 : sal_Int32 lcl_getSequenceLengthByRole(
515 : const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aSeqCnt,
516 : const OUString & rRole )
517 : {
518 : Reference< chart2::data::XLabeledDataSequence > xLabeledSeq(
519 0 : lcl_getDataSequenceByRole( aSeqCnt, rRole ));
520 0 : if( xLabeledSeq.is())
521 : {
522 0 : Reference< chart2::data::XDataSequence > xSeq( xLabeledSeq->getValues());
523 0 : return xSeq->getData().getLength();
524 : }
525 0 : return 0;
526 : }
527 :
528 0 : OUString lcl_flattenStringSequence( const Sequence< OUString > & rSequence )
529 : {
530 0 : OUStringBuffer aResult;
531 0 : bool bPrecedeWithSpace = false;
532 0 : for( sal_Int32 nIndex=0; nIndex<rSequence.getLength(); ++nIndex )
533 : {
534 0 : if( !rSequence[nIndex].isEmpty())
535 : {
536 0 : if( bPrecedeWithSpace )
537 0 : aResult.append( ' ' );
538 0 : aResult.append( rSequence[nIndex] );
539 0 : bPrecedeWithSpace = true;
540 : }
541 : }
542 0 : return aResult.makeStringAndClear();
543 : }
544 :
545 0 : void lcl_getLabelStringSequence( Sequence< OUString >& rOutLabels, const Reference< chart2::data::XDataSequence > & xLabelSeq )
546 : {
547 0 : uno::Reference< chart2::data::XTextualDataSequence > xTextualDataSequence( xLabelSeq, uno::UNO_QUERY );
548 0 : if( xTextualDataSequence.is())
549 : {
550 0 : rOutLabels = xTextualDataSequence->getTextualData();
551 : }
552 0 : else if( xLabelSeq.is())
553 : {
554 0 : Sequence< uno::Any > aAnies( xLabelSeq->getData());
555 0 : rOutLabels.realloc( aAnies.getLength());
556 0 : for( sal_Int32 i=0; i<aAnies.getLength(); ++i )
557 0 : aAnies[i] >>= rOutLabels[i];
558 0 : }
559 0 : }
560 :
561 0 : sal_Int32 lcl_getMaxSequenceLength(
562 : const SchXMLExportHelper_Impl::tDataSequenceCont & rContainer )
563 : {
564 0 : sal_Int32 nResult = 0;
565 0 : for( SchXMLExportHelper_Impl::tDataSequenceCont::const_iterator aIt( rContainer.begin());
566 0 : aIt != rContainer.end(); ++aIt )
567 : {
568 0 : if( aIt->second.is())
569 : {
570 0 : sal_Int32 nSeqLength = aIt->second->getData().getLength();
571 0 : if( nSeqLength > nResult )
572 0 : nResult = nSeqLength;
573 : }
574 : }
575 0 : return nResult;
576 : }
577 :
578 0 : uno::Sequence< OUString > lcl_DataSequenceToStringSequence(
579 : const uno::Reference< chart2::data::XDataSequence >& xDataSequence )
580 : {
581 0 : uno::Sequence< OUString > aResult;
582 0 : if(!xDataSequence.is())
583 0 : return aResult;
584 :
585 0 : uno::Reference< chart2::data::XTextualDataSequence > xTextualDataSequence( xDataSequence, uno::UNO_QUERY );
586 0 : if( xTextualDataSequence.is() )
587 : {
588 0 : aResult = xTextualDataSequence->getTextualData();
589 : }
590 : else
591 : {
592 0 : uno::Sequence< uno::Any > aValues = xDataSequence->getData();
593 0 : aResult.realloc(aValues.getLength());
594 :
595 0 : for(sal_Int32 nN=aValues.getLength();nN--;)
596 0 : aValues[nN] >>= aResult[nN];
597 : }
598 :
599 0 : return aResult;
600 : }
601 0 : ::std::vector< double > lcl_getAllValuesFromSequence( const Reference< chart2::data::XDataSequence > & xSeq )
602 : {
603 0 : double fNan = 0.0;
604 0 : ::rtl::math::setNan( &fNan );
605 0 : ::std::vector< double > aResult;
606 0 : if(!xSeq.is())
607 0 : return aResult;
608 :
609 0 : uno::Sequence< double > aValuesSequence;
610 0 : Reference< chart2::data::XNumericalDataSequence > xNumSeq( xSeq, uno::UNO_QUERY );
611 0 : if( xNumSeq.is() )
612 : {
613 0 : aValuesSequence = xNumSeq->getNumericalData();
614 : }
615 : else
616 : {
617 0 : Sequence< uno::Any > aAnies( xSeq->getData() );
618 0 : aValuesSequence.realloc( aAnies.getLength() );
619 0 : for( sal_Int32 i=0; i<aAnies.getLength(); ++i )
620 0 : aAnies[i] >>= aValuesSequence[i];
621 : }
622 :
623 : //special handling for x-values (if x-values do point to categories, indices are used instead )
624 0 : Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY );
625 0 : if( xProp.is() )
626 : {
627 0 : OUString aRole;
628 0 : xProp->getPropertyValue("Role") >>= aRole;
629 0 : if( aRole.match( OUString( "values-x" ) ) )
630 : {
631 : //lcl_clearIfNoValuesButTextIsContained - replace by indices if the values are not appropriate
632 0 : bool bHasValue=false;
633 0 : bool bHasText=false;
634 0 : sal_Int32 nCount = aValuesSequence.getLength();
635 0 : for( sal_Int32 j = 0; j < nCount; ++j )
636 : {
637 0 : if( !::rtl::math::isNan( aValuesSequence[j] ) )
638 : {
639 0 : bHasValue=true;
640 0 : break;
641 : }
642 : }
643 0 : if(!bHasValue)
644 : {
645 : //no double value is countained
646 : //is there any text?
647 0 : uno::Sequence< OUString > aStrings( lcl_DataSequenceToStringSequence( xSeq ) );
648 0 : sal_Int32 nTextCount = aStrings.getLength();
649 0 : for( sal_Int32 j = 0; j < nTextCount; ++j )
650 : {
651 0 : if( !aStrings[j].isEmpty() )
652 : {
653 0 : bHasText=true;
654 0 : break;
655 : }
656 0 : }
657 : }
658 0 : if( !bHasValue && bHasText )
659 : {
660 0 : for( sal_Int32 j = 0; j < nCount; ++j )
661 0 : aValuesSequence[j] = j+1;
662 : }
663 0 : }
664 : }
665 :
666 0 : ::std::copy( aValuesSequence.getConstArray(), aValuesSequence.getConstArray() + aValuesSequence.getLength(),
667 0 : ::std::back_inserter( aResult ));
668 0 : return aResult;
669 : }
670 :
671 0 : bool lcl_SequenceHasUnhiddenData( const uno::Reference< chart2::data::XDataSequence >& xDataSequence )
672 : {
673 0 : if( !xDataSequence.is() )
674 0 : return false;
675 0 : uno::Reference< beans::XPropertySet > xProp( xDataSequence, uno::UNO_QUERY );
676 0 : if( xProp.is() )
677 : {
678 0 : uno::Sequence< sal_Int32 > aHiddenValues;
679 : try
680 : {
681 0 : xProp->getPropertyValue("HiddenValues") >>= aHiddenValues;
682 0 : if( !aHiddenValues.getLength() )
683 0 : return true;
684 : }
685 0 : catch( const uno::Exception& )
686 : {
687 0 : return true;
688 0 : }
689 : }
690 0 : if( xDataSequence->getData().getLength() )
691 0 : return true;
692 0 : return false;
693 : }
694 :
695 : typedef vector< OUString > tStringVector;
696 : typedef vector< double > tDoubleVector;
697 : typedef vector< vector< OUString > > t2DStringVector;
698 : typedef vector< vector< double > > t2DNumberContainer;
699 :
700 0 : struct lcl_TableData
701 : {
702 : t2DNumberContainer aDataInRows;
703 : tStringVector aDataRangeRepresentations;
704 :
705 : tStringVector aColumnDescriptions;
706 : tStringVector aColumnDescriptions_Ranges;
707 :
708 : tStringVector aRowDescriptions;
709 : tStringVector aRowDescriptions_Ranges;
710 :
711 : Sequence< Sequence< uno::Any > > aComplexColumnDescriptions;//outer index is columns - inner index is level
712 : Sequence< Sequence< uno::Any > > aComplexRowDescriptions;//outer index is rows - inner index is level
713 :
714 : ::std::vector< sal_Int32 > aHiddenColumns;
715 : };
716 :
717 : // ::std::bind2nd( ::std::mem_fun_ref( &T::resize ), nSize ) does not work
718 : template< class T >
719 : struct lcl_resize
720 : {
721 0 : lcl_resize( typename T::size_type nSize, typename T::value_type fDefaultValue ) : m_nSize( nSize ), m_fDefaultValue( fDefaultValue ) {}
722 0 : void operator()( T & t )
723 0 : { t.resize( m_nSize, m_fDefaultValue ); }
724 : private:
725 : typename T::size_type m_nSize;
726 : typename T::value_type m_fDefaultValue;
727 : };
728 :
729 : typedef ::std::map< sal_Int32, SchXMLExportHelper_Impl::tLabelValuesDataPair >
730 : lcl_DataSequenceMap;
731 :
732 : struct lcl_SequenceToMapElement :
733 : public ::std::unary_function< lcl_DataSequenceMap::mapped_type, lcl_DataSequenceMap::value_type >
734 : {
735 0 : lcl_SequenceToMapElement()
736 0 : {}
737 0 : result_type operator() ( const argument_type & rContent )
738 : {
739 0 : sal_Int32 nIndex = -1;
740 0 : if( rContent.second.is()) //has values
741 : {
742 0 : OUString aRangeRep( rContent.second->getSourceRangeRepresentation());
743 0 : nIndex = aRangeRep.toInt32();
744 : }
745 0 : else if( rContent.first.is()) //has labels
746 0 : nIndex = rContent.first->getSourceRangeRepresentation().copy( sizeof("label ")).toInt32();
747 0 : return result_type( nIndex, rContent );
748 : }
749 : };
750 :
751 0 : void lcl_ReorderInternalSequencesAccordingToTheirRangeName(
752 : SchXMLExportHelper_Impl::tDataSequenceCont & rInOutSequences )
753 : {
754 0 : lcl_DataSequenceMap aIndexSequenceMap;
755 : ::std::transform( rInOutSequences.begin(), rInOutSequences.end(),
756 : ::std::inserter( aIndexSequenceMap, aIndexSequenceMap.begin()),
757 0 : lcl_SequenceToMapElement());
758 :
759 0 : rInOutSequences.clear();
760 0 : sal_Int32 nIndex = 0;
761 0 : for( lcl_DataSequenceMap::const_iterator aIt = aIndexSequenceMap.begin();
762 0 : aIt != aIndexSequenceMap.end(); ++aIt, ++nIndex )
763 : {
764 0 : if( aIt->first < 0 )
765 0 : continue;
766 : // fill empty columns
767 0 : for( ; nIndex < aIt->first; ++nIndex )
768 : rInOutSequences.push_back(
769 : SchXMLExportHelper_Impl::tDataSequenceCont::value_type(
770 : (uno::Reference< chart2::data::XDataSequence >)0,
771 0 : (uno::Reference< chart2::data::XDataSequence >)0 ));
772 : OSL_ASSERT( nIndex == aIt->first );
773 0 : rInOutSequences.push_back( aIt->second );
774 0 : }
775 0 : }
776 :
777 0 : lcl_TableData lcl_getDataForLocalTable(
778 : const SchXMLExportHelper_Impl::tDataSequenceCont & aSequencesToExport,
779 : const Reference< chart2::XAnyDescriptionAccess >& xAnyDescriptionAccess,
780 : const OUString& rCategoriesRange,
781 : bool bSeriesFromColumns,
782 : const Reference< chart2::data::XRangeXMLConversion > & xRangeConversion )
783 : {
784 0 : lcl_TableData aResult;
785 :
786 : try
787 : {
788 0 : Sequence< OUString > aSimpleCategories;
789 0 : if( xAnyDescriptionAccess.is() )
790 : {
791 : //categories
792 0 : if( bSeriesFromColumns )
793 : {
794 0 : aSimpleCategories = xAnyDescriptionAccess->getRowDescriptions();
795 0 : aResult.aComplexRowDescriptions = xAnyDescriptionAccess->getAnyRowDescriptions();
796 : }
797 : else
798 : {
799 0 : aSimpleCategories = xAnyDescriptionAccess->getColumnDescriptions();
800 0 : aResult.aComplexColumnDescriptions = xAnyDescriptionAccess->getAnyColumnDescriptions();
801 : }
802 : }
803 :
804 : //series values and series labels
805 0 : SchXMLExportHelper_Impl::tDataSequenceCont::size_type nNumSequences = aSequencesToExport.size();
806 0 : SchXMLExportHelper_Impl::tDataSequenceCont::const_iterator aBegin( aSequencesToExport.begin());
807 0 : SchXMLExportHelper_Impl::tDataSequenceCont::const_iterator aEnd( aSequencesToExport.end());
808 0 : SchXMLExportHelper_Impl::tDataSequenceCont::const_iterator aIt( aBegin );
809 :
810 0 : size_t nMaxSequenceLength( lcl_getMaxSequenceLength( aSequencesToExport ));
811 0 : size_t nCategoriesLength( aSimpleCategories.getLength() );
812 0 : if( nCategoriesLength > nMaxSequenceLength )
813 : {
814 0 : aSimpleCategories.realloc(nMaxSequenceLength);//#i110617#
815 0 : nCategoriesLength = nMaxSequenceLength;
816 : }
817 0 : size_t nNumColumns( bSeriesFromColumns ? nNumSequences : nMaxSequenceLength );
818 0 : size_t nNumRows( bSeriesFromColumns ? nMaxSequenceLength : nNumSequences );
819 :
820 : // resize data
821 0 : aResult.aDataInRows.resize( nNumRows );
822 0 : double fNan = 0.0;
823 0 : ::rtl::math::setNan( &fNan );
824 : ::std::for_each( aResult.aDataInRows.begin(), aResult.aDataInRows.end(),
825 0 : lcl_resize< t2DNumberContainer::value_type >( nNumColumns, fNan ));
826 0 : aResult.aColumnDescriptions.resize( nNumColumns );
827 0 : aResult.aComplexColumnDescriptions.realloc( nNumColumns );
828 0 : aResult.aRowDescriptions.resize( nNumRows );
829 0 : aResult.aComplexRowDescriptions.realloc( nNumRows );
830 :
831 0 : tStringVector& rCategories = bSeriesFromColumns ? aResult.aRowDescriptions : aResult.aColumnDescriptions;
832 0 : tStringVector& rLabels = bSeriesFromColumns ? aResult.aColumnDescriptions : aResult.aRowDescriptions;
833 :
834 : //categories
835 0 : lcl_SequenceToVector( aSimpleCategories, rCategories );
836 0 : if( !rCategoriesRange.isEmpty() )
837 : {
838 0 : OUString aRange(rCategoriesRange);
839 0 : if( xRangeConversion.is())
840 0 : aRange = xRangeConversion->convertRangeToXML( aRange );
841 0 : if( bSeriesFromColumns )
842 0 : aResult.aRowDescriptions_Ranges.push_back( aRange );
843 : else
844 0 : aResult.aColumnDescriptions_Ranges.push_back( aRange );
845 : }
846 :
847 : // iterate over all sequences
848 0 : size_t nSeqIdx = 0;
849 0 : Sequence< Sequence< OUString > > aComplexLabels(nNumSequences);
850 0 : for( ; aIt != aEnd; ++aIt, ++nSeqIdx )
851 : {
852 0 : OUString aRange;
853 0 : Sequence< OUString >& rCurrentComplexLabel = aComplexLabels[nSeqIdx];
854 0 : if( aIt->first.is())
855 : {
856 0 : lcl_getLabelStringSequence( rCurrentComplexLabel, aIt->first );
857 0 : rLabels[nSeqIdx] = lcl_flattenStringSequence( rCurrentComplexLabel );
858 0 : aRange = aIt->first->getSourceRangeRepresentation();
859 0 : if( xRangeConversion.is())
860 0 : aRange = xRangeConversion->convertRangeToXML( aRange );
861 : }
862 0 : else if( aIt->second.is())
863 : {
864 0 : rCurrentComplexLabel.realloc(1);
865 0 : rLabels[nSeqIdx] = rCurrentComplexLabel[0] = lcl_flattenStringSequence(
866 0 : aIt->second->generateLabel( chart2::data::LabelOrigin_SHORT_SIDE ));
867 : }
868 0 : if( bSeriesFromColumns )
869 0 : aResult.aColumnDescriptions_Ranges.push_back( aRange );
870 : else
871 0 : aResult.aRowDescriptions_Ranges.push_back( aRange );
872 :
873 0 : ::std::vector< double > aNumbers( lcl_getAllValuesFromSequence( aIt->second ));
874 0 : if( bSeriesFromColumns )
875 : {
876 0 : const sal_Int32 nSize( static_cast< sal_Int32 >( aNumbers.size()));
877 0 : for( sal_Int32 nIdx=0; nIdx<nSize; ++nIdx )
878 0 : aResult.aDataInRows[nIdx][nSeqIdx] = aNumbers[nIdx];
879 : }
880 : else
881 0 : aResult.aDataInRows[nSeqIdx] = aNumbers;
882 :
883 0 : if( aIt->second.is())
884 : {
885 0 : aRange = aIt->second->getSourceRangeRepresentation();
886 0 : if( xRangeConversion.is())
887 0 : aRange = xRangeConversion->convertRangeToXML( aRange );
888 : }
889 0 : aResult.aDataRangeRepresentations.push_back( aRange );
890 :
891 : //is column hidden?
892 0 : if( !lcl_SequenceHasUnhiddenData(aIt->first) && !lcl_SequenceHasUnhiddenData(aIt->second) )
893 0 : aResult.aHiddenColumns.push_back(nSeqIdx);
894 0 : }
895 0 : Sequence< Sequence< Any > >& rComplexAnyLabels = bSeriesFromColumns ? aResult.aComplexColumnDescriptions : aResult.aComplexRowDescriptions;//#i116544#
896 0 : rComplexAnyLabels.realloc(aComplexLabels.getLength());
897 0 : for( sal_Int32 nN=0; nN<aComplexLabels.getLength();nN++ )
898 : {
899 0 : Sequence< OUString >& rSource = aComplexLabels[nN];
900 0 : Sequence< Any >& rTarget = rComplexAnyLabels[nN];
901 0 : rTarget.realloc( rSource.getLength() );
902 0 : for( sal_Int32 i=0; i<rSource.getLength(); i++ )
903 0 : rTarget[i] = uno::makeAny( rSource[i] );
904 0 : }
905 : }
906 0 : catch( const uno::Exception & rEx )
907 : {
908 : SAL_INFO("xmloff.chart", "something went wrong during table data collection: " << rEx.Message);
909 : }
910 :
911 0 : return aResult;
912 : }
913 :
914 0 : void lcl_exportNumberFormat( const OUString& rPropertyName, const Reference< beans::XPropertySet >& xPropSet,
915 : SvXMLExport& rExport )
916 : {
917 0 : if( xPropSet.is())
918 : {
919 0 : sal_Int32 nNumberFormat = 0;
920 0 : Any aNumAny = xPropSet->getPropertyValue( rPropertyName );
921 0 : if( (aNumAny >>= nNumberFormat) && (nNumberFormat != -1) )
922 0 : rExport.addDataStyle( nNumberFormat );
923 : }
924 0 : }
925 :
926 : ::std::vector< Reference< chart2::data::XDataSequence > >
927 0 : lcl_getErrorBarSequences( const Reference< beans::XPropertySet > & xErrorBarProp )
928 : {
929 0 : ::std::vector< Reference< chart2::data::XDataSequence > > aResult;
930 0 : Reference< chart2::data::XDataSource > xErrorBarDataSource( xErrorBarProp, uno::UNO_QUERY );
931 0 : if( !xErrorBarDataSource.is())
932 0 : return aResult;
933 :
934 0 : const OUString aRolePrefix( "error-bars-" );
935 :
936 : Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences(
937 0 : xErrorBarDataSource->getDataSequences());
938 0 : for( sal_Int32 nI=0; nI< aSequences.getLength(); ++nI )
939 : {
940 : try
941 : {
942 0 : if( aSequences[nI].is())
943 : {
944 0 : Reference< chart2::data::XDataSequence > xSequence( aSequences[nI]->getValues());
945 0 : Reference< beans::XPropertySet > xSeqProp( xSequence, uno::UNO_QUERY_THROW );
946 0 : OUString aRole;
947 0 : if( ( xSeqProp->getPropertyValue(
948 0 : OUString( "Role" )) >>= aRole ) &&
949 0 : aRole.match( aRolePrefix ))
950 : {
951 0 : aResult.push_back( xSequence );
952 0 : }
953 : }
954 : }
955 0 : catch( const uno::Exception & rEx )
956 : {
957 0 : OString aBStr(OUStringToOString(rEx.Message, RTL_TEXTENCODING_ASCII_US));
958 0 : SAL_INFO("xmloff.chart", "chart:exporting error bar ranges: " << aBStr );
959 : }
960 : }
961 :
962 0 : return aResult;
963 : }
964 :
965 0 : bool lcl_exportDomainForThisSequence( const Reference< chart2::data::XDataSequence > xValues, OUString& rFirstRangeForThisDomainIndex, SvXMLExport& rExport )
966 : {
967 0 : bool bDomainExported = false;
968 0 : if( xValues.is())
969 : {
970 0 : Reference< chart2::XChartDocument > xNewDoc( rExport.GetModel(), uno::UNO_QUERY );
971 0 : OUString aRange( lcl_ConvertRange( xValues->getSourceRangeRepresentation(), xNewDoc ) );
972 :
973 : //work around error in OOo 2.0 (problems with multiple series having a domain element)
974 0 : if( rFirstRangeForThisDomainIndex.isEmpty() || !aRange.equals(rFirstRangeForThisDomainIndex) )
975 : {
976 0 : rExport.AddAttribute( XML_NAMESPACE_TABLE, XML_CELL_RANGE_ADDRESS, aRange);
977 0 : SvXMLElementExport aDomain( rExport, XML_NAMESPACE_CHART, XML_DOMAIN, true, true );
978 0 : bDomainExported = true;
979 : }
980 :
981 0 : if( rFirstRangeForThisDomainIndex.isEmpty() )
982 0 : rFirstRangeForThisDomainIndex = aRange;
983 : }
984 0 : return bDomainExported;
985 : }
986 :
987 : } // anonymous namespace
988 :
989 0 : struct SchXMLDataPointStruct
990 : {
991 : OUString maStyleName;
992 : sal_Int32 mnRepeat;
993 :
994 0 : SchXMLDataPointStruct() : mnRepeat( 1 ) {}
995 : };
996 :
997 : // class SchXMLExportHelper
998 :
999 0 : SchXMLExportHelper::SchXMLExportHelper( SvXMLExport& rExport, SvXMLAutoStylePoolP& rASPool )
1000 0 : : m_pImpl( new SchXMLExportHelper_Impl( rExport, rASPool ) )
1001 : {
1002 0 : }
1003 :
1004 0 : SchXMLExportHelper::~SchXMLExportHelper()
1005 : {
1006 0 : delete m_pImpl;
1007 0 : }
1008 :
1009 0 : const OUString& SchXMLExportHelper::getChartCLSID()
1010 : {
1011 0 : return m_pImpl->msCLSID;
1012 : }
1013 :
1014 0 : UniReference< XMLPropertySetMapper > SchXMLExportHelper_Impl::GetPropertySetMapper() const
1015 : {
1016 0 : return mxPropertySetMapper;
1017 : }
1018 :
1019 0 : void SchXMLExportHelper_Impl::exportAutoStyles()
1020 : {
1021 0 : if( mxExpPropMapper.is())
1022 : {
1023 : //ToDo: when embedded in calc/writer this is not necessary because the
1024 : // numberformatter is shared between both documents
1025 0 : mrExport.exportAutoDataStyles();
1026 :
1027 : // export chart auto styles
1028 : mrAutoStylePool.exportXML(
1029 : XML_STYLE_FAMILY_SCH_CHART_ID
1030 0 : , mrExport.GetDocHandler(),
1031 0 : mrExport.GetMM100UnitConverter(),
1032 0 : mrExport.GetNamespaceMap()
1033 0 : );
1034 :
1035 : // export auto styles for additional shapes
1036 0 : mrExport.GetShapeExport()->exportAutoStyles();
1037 : // and for text in additional shapes
1038 0 : mrExport.GetTextParagraphExport()->exportTextAutoStyles();
1039 : }
1040 0 : }
1041 :
1042 : // private methods
1043 :
1044 0 : SchXMLExportHelper_Impl::SchXMLExportHelper_Impl(
1045 : SvXMLExport& rExport,
1046 : SvXMLAutoStylePoolP& rASPool ) :
1047 : mrExport( rExport ),
1048 : mrAutoStylePool( rASPool ),
1049 : mbHasSeriesLabels( sal_False ),
1050 : mbHasCategoryLabels( sal_False ),
1051 : mbRowSourceColumns( sal_True ),
1052 0 : msCLSID( OUString( SvGlobalName( SO3_SCH_CLASSID ).GetHexName()))
1053 : {
1054 0 : msTableName = "local-table";
1055 :
1056 : // create property set mapper
1057 0 : mxPropertySetMapper = new XMLChartPropertySetMapper( true);
1058 0 : mxExpPropMapper = new XMLChartExportPropertyMapper( mxPropertySetMapper, rExport );
1059 :
1060 : // register chart auto-style family
1061 : mrAutoStylePool.AddFamily(
1062 : XML_STYLE_FAMILY_SCH_CHART_ID,
1063 : OUString( XML_STYLE_FAMILY_SCH_CHART_NAME ),
1064 0 : mxExpPropMapper.get(),
1065 0 : OUString( XML_STYLE_FAMILY_SCH_CHART_PREFIX ));
1066 :
1067 : // register shape family
1068 : mrAutoStylePool.AddFamily(
1069 : XML_STYLE_FAMILY_SD_GRAPHICS_ID,
1070 : OUString( XML_STYLE_FAMILY_SD_GRAPHICS_NAME ),
1071 0 : mxExpPropMapper.get(),
1072 0 : OUString( XML_STYLE_FAMILY_SD_GRAPHICS_PREFIX ));
1073 : // register paragraph family also for shapes
1074 : mrAutoStylePool.AddFamily(
1075 : XML_STYLE_FAMILY_TEXT_PARAGRAPH,
1076 0 : GetXMLToken( XML_PARAGRAPH ),
1077 0 : mxExpPropMapper.get(),
1078 0 : OUString( 'P' ));
1079 : // register text family also for shapes
1080 : mrAutoStylePool.AddFamily(
1081 : XML_STYLE_FAMILY_TEXT_TEXT,
1082 0 : GetXMLToken( XML_TEXT ),
1083 0 : mxExpPropMapper.get(),
1084 0 : OUString( 'T' ));
1085 0 : }
1086 :
1087 0 : SchXMLExportHelper_Impl::~SchXMLExportHelper_Impl()
1088 : {
1089 0 : }
1090 :
1091 0 : void SchXMLExportHelper_Impl::collectAutoStyles( Reference< chart::XChartDocument > rChartDoc )
1092 : {
1093 0 : parseDocument( rChartDoc, sal_False );
1094 0 : }
1095 :
1096 0 : void SchXMLExportHelper_Impl::exportChart( Reference< chart::XChartDocument > rChartDoc,
1097 : sal_Bool bIncludeTable )
1098 : {
1099 0 : parseDocument( rChartDoc, sal_True, bIncludeTable );
1100 : SAL_WARN_IF( !maAutoStyleNameQueue.empty(), "xmloff.chart", "There are still remaining autostyle names in the queue" );
1101 0 : }
1102 :
1103 0 : static OUString lcl_GetStringFromNumberSequence( const ::com::sun::star::uno::Sequence< sal_Int32 >& rSequenceMapping, bool bRemoveOneFromEachIndex /*should be true if having categories*/ )
1104 : {
1105 0 : const sal_Int32* pArray = rSequenceMapping.getConstArray();
1106 0 : const sal_Int32 nSize = rSequenceMapping.getLength();
1107 0 : sal_Int32 i = 0;
1108 0 : OUStringBuffer aBuf;
1109 0 : bool bHasPredecessor = false;
1110 0 : for( i = 0; i < nSize; ++i )
1111 : {
1112 0 : sal_Int32 nIndex = pArray[ i ];
1113 0 : if( bRemoveOneFromEachIndex )
1114 0 : --nIndex;
1115 0 : if(nIndex>=0)
1116 : {
1117 0 : if(bHasPredecessor)
1118 0 : aBuf.append( ' ' );
1119 0 : aBuf.append( nIndex, 10 );
1120 0 : bHasPredecessor = true;
1121 : }
1122 : }
1123 0 : return aBuf.makeStringAndClear();
1124 : }
1125 :
1126 : /// if bExportContent is false the auto-styles are collected
1127 0 : void SchXMLExportHelper_Impl::parseDocument( Reference< chart::XChartDocument >& rChartDoc,
1128 : sal_Bool bExportContent,
1129 : sal_Bool bIncludeTable )
1130 : {
1131 0 : Reference< chart2::XChartDocument > xNewDoc( rChartDoc, uno::UNO_QUERY );
1132 0 : if( !rChartDoc.is() || !xNewDoc.is() )
1133 : {
1134 : SAL_WARN("xmloff.chart", "No XChartDocument was given for export." );
1135 0 : return;
1136 : }
1137 :
1138 0 : mxExpPropMapper->setChartDoc(xNewDoc);
1139 :
1140 0 : awt::Size aPageSize( getPageSize( xNewDoc ));
1141 0 : if( bExportContent )
1142 0 : addSize( aPageSize );
1143 0 : Reference< chart::XDiagram > xDiagram = rChartDoc->getDiagram();
1144 0 : Reference< chart2::XDiagram > xNewDiagram;
1145 0 : if( xNewDoc.is())
1146 0 : xNewDiagram.set( xNewDoc->getFirstDiagram());
1147 :
1148 : //todo remove if model changes are notified and view is updated automatically
1149 0 : if( bExportContent )
1150 : {
1151 0 : Reference< util::XRefreshable > xRefreshable( xNewDoc, uno::UNO_QUERY );
1152 0 : if( xRefreshable.is() )
1153 0 : xRefreshable->refresh();
1154 : }
1155 :
1156 : // get Properties of ChartDocument
1157 0 : sal_Bool bHasMainTitle = sal_False;
1158 0 : sal_Bool bHasSubTitle = sal_False;
1159 0 : sal_Bool bHasLegend = sal_False;
1160 0 : util::DateTime aNullDate(0,0,0,0,30,12,1899, false);
1161 :
1162 0 : std::vector< XMLPropertyState > aPropertyStates;
1163 :
1164 0 : Reference< beans::XPropertySet > xDocPropSet( rChartDoc, uno::UNO_QUERY );
1165 0 : if( xDocPropSet.is())
1166 : {
1167 : try
1168 : {
1169 0 : Any aAny( xDocPropSet->getPropertyValue(
1170 0 : OUString( "HasMainTitle" )));
1171 0 : aAny >>= bHasMainTitle;
1172 0 : aAny = xDocPropSet->getPropertyValue(
1173 0 : OUString( "HasSubTitle" ));
1174 0 : aAny >>= bHasSubTitle;
1175 0 : aAny = xDocPropSet->getPropertyValue(
1176 0 : OUString( "HasLegend" ));
1177 0 : aAny >>= bHasLegend;
1178 0 : if ( bIncludeTable )
1179 : {
1180 0 : OUString sNullDate( "NullDate" );
1181 0 : aAny = xDocPropSet->getPropertyValue(sNullDate);
1182 0 : if ( !aAny.hasValue() )
1183 : {
1184 0 : Reference<container::XChild> xChild(rChartDoc, uno::UNO_QUERY );
1185 0 : if ( xChild.is() )
1186 : {
1187 0 : Reference< beans::XPropertySet > xParentDoc( xChild->getParent(),uno::UNO_QUERY);
1188 0 : if ( xParentDoc.is() && xParentDoc->getPropertySetInfo()->hasPropertyByName(sNullDate) )
1189 0 : aAny = xParentDoc->getPropertyValue(sNullDate);
1190 0 : }
1191 : }
1192 :
1193 0 : aAny >>= aNullDate;
1194 0 : }
1195 : }
1196 0 : catch( const beans::UnknownPropertyException & )
1197 : {
1198 : SAL_WARN("xmloff.chart", "Required property not found in ChartDocument" );
1199 : }
1200 : }
1201 :
1202 0 : if ( bIncludeTable && (aNullDate.Day != 30 || aNullDate.Month != 12 || aNullDate.Year != 1899 ) )
1203 : {
1204 0 : SvXMLElementExport aSet( mrExport, XML_NAMESPACE_TABLE, XML_CALCULATION_SETTINGS, true, true );
1205 : {
1206 0 : OUStringBuffer sBuffer;
1207 0 : ::sax::Converter::convertDateTime(sBuffer, aNullDate, 0);
1208 0 : mrExport.AddAttribute( XML_NAMESPACE_TABLE,XML_DATE_VALUE,sBuffer.makeStringAndClear());
1209 0 : SvXMLElementExport aNull( mrExport, XML_NAMESPACE_TABLE, XML_NULL_DATE, true, true );
1210 0 : }
1211 : }
1212 :
1213 : // chart element
1214 0 : SvXMLElementExport* pElChart = 0;
1215 :
1216 : // get property states for autostyles
1217 0 : if( mxExpPropMapper.is())
1218 : {
1219 0 : Reference< beans::XPropertySet > xPropSet( rChartDoc->getArea(), uno::UNO_QUERY );
1220 0 : if( xPropSet.is())
1221 0 : aPropertyStates = mxExpPropMapper->Filter( xPropSet );
1222 : }
1223 :
1224 0 : if( bExportContent )
1225 : {
1226 : //export data provider in xlink:href attribute
1227 0 : const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
1228 0 : if( nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 )
1229 : {
1230 0 : OUString aDataProviderURL( ".." );
1231 0 : if( xNewDoc->hasInternalDataProvider() )
1232 0 : aDataProviderURL = ".";
1233 : else //special handling for data base data provider necessary
1234 : {
1235 0 : Reference< chart2::data::XDatabaseDataProvider > xDBDataProvider( xNewDoc->getDataProvider(), uno::UNO_QUERY );
1236 0 : if( xDBDataProvider.is() )
1237 0 : aDataProviderURL = ".";
1238 : }
1239 0 : mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, aDataProviderURL );
1240 0 : mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
1241 : }
1242 :
1243 0 : OUString sChartType( xDiagram->getDiagramType() );
1244 :
1245 : // attributes
1246 : // determine class
1247 0 : if( !sChartType.isEmpty())
1248 : {
1249 0 : enum XMLTokenEnum eXMLChartType = SchXMLTools::getTokenByChartType( sChartType, true /* bUseOldNames */ );
1250 :
1251 : SAL_WARN_IF( eXMLChartType == XML_TOKEN_INVALID, "xmloff.chart", "invalid chart class" );
1252 0 : if( eXMLChartType == XML_TOKEN_INVALID )
1253 0 : eXMLChartType = XML_BAR;
1254 :
1255 0 : if( eXMLChartType == XML_ADD_IN )
1256 : {
1257 : // sChartType is the servie-name of the add-in
1258 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_CLASS,
1259 0 : mrExport.GetNamespaceMap().GetQNameByKey(
1260 0 : XML_NAMESPACE_OOO, sChartType) );
1261 : }
1262 0 : else if( eXMLChartType != XML_TOKEN_INVALID )
1263 : {
1264 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_CLASS,
1265 0 : mrExport.GetNamespaceMap().GetQNameByKey(
1266 0 : XML_NAMESPACE_CHART, GetXMLToken(eXMLChartType )) );
1267 : }
1268 :
1269 : //column-mapping or row-mapping
1270 0 : if( maSequenceMapping.getLength() )
1271 : {
1272 0 : enum XMLTokenEnum eTransToken = ::xmloff::token::XML_ROW_MAPPING;
1273 0 : if( mbRowSourceColumns )
1274 0 : eTransToken = ::xmloff::token::XML_COLUMN_MAPPING;
1275 : OUString aSequenceMappingStr( lcl_GetStringFromNumberSequence(
1276 0 : maSequenceMapping, mbHasCategoryLabels && !xNewDoc->hasInternalDataProvider() ) );
1277 :
1278 : mrExport.AddAttribute( XML_NAMESPACE_CHART,
1279 0 : ::xmloff::token::GetXMLToken( eTransToken ),
1280 0 : aSequenceMappingStr );
1281 : }
1282 : }
1283 : // write style name
1284 0 : AddAutoStyleAttribute( aPropertyStates );
1285 :
1286 : //element
1287 0 : pElChart = new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_CHART, true, true );
1288 : }
1289 : else // autostyles
1290 : {
1291 0 : CollectAutoStyle( aPropertyStates );
1292 : }
1293 : // remove property states for autostyles
1294 0 : aPropertyStates.clear();
1295 :
1296 : // title element
1297 0 : if( bHasMainTitle )
1298 : {
1299 : // get property states for autostyles
1300 0 : if( mxExpPropMapper.is())
1301 : {
1302 0 : Reference< beans::XPropertySet > xPropSet( rChartDoc->getTitle(), uno::UNO_QUERY );
1303 0 : if( xPropSet.is())
1304 0 : aPropertyStates = mxExpPropMapper->Filter( xPropSet );
1305 : }
1306 0 : if( bExportContent )
1307 : {
1308 0 : Reference< drawing::XShape > xShape = rChartDoc->getTitle();
1309 0 : if( xShape.is()) // && "hasTitleBeenMoved"
1310 0 : addPosition( xShape );
1311 :
1312 : // write style name
1313 0 : AddAutoStyleAttribute( aPropertyStates );
1314 :
1315 : // element
1316 0 : SvXMLElementExport aElTitle( mrExport, XML_NAMESPACE_CHART, XML_TITLE, true, true );
1317 :
1318 : // content (text:p)
1319 0 : Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY );
1320 0 : if( xPropSet.is())
1321 : {
1322 0 : Any aAny( xPropSet->getPropertyValue(
1323 0 : OUString( "String" )));
1324 0 : OUString aText;
1325 0 : aAny >>= aText;
1326 0 : exportText( aText );
1327 0 : }
1328 : }
1329 : else // autostyles
1330 : {
1331 0 : CollectAutoStyle( aPropertyStates );
1332 : }
1333 : // remove property states for autostyles
1334 0 : aPropertyStates.clear();
1335 : }
1336 :
1337 : // subtitle element
1338 0 : if( bHasSubTitle )
1339 : {
1340 : // get property states for autostyles
1341 0 : if( mxExpPropMapper.is())
1342 : {
1343 0 : Reference< beans::XPropertySet > xPropSet( rChartDoc->getSubTitle(), uno::UNO_QUERY );
1344 0 : if( xPropSet.is())
1345 0 : aPropertyStates = mxExpPropMapper->Filter( xPropSet );
1346 : }
1347 :
1348 0 : if( bExportContent )
1349 : {
1350 0 : Reference< drawing::XShape > xShape = rChartDoc->getSubTitle();
1351 0 : if( xShape.is())
1352 0 : addPosition( xShape );
1353 :
1354 : // write style name
1355 0 : AddAutoStyleAttribute( aPropertyStates );
1356 :
1357 : // element (has no subelements)
1358 0 : SvXMLElementExport aElSubTitle( mrExport, XML_NAMESPACE_CHART, XML_SUBTITLE, true, true );
1359 :
1360 : // content (text:p)
1361 0 : Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY );
1362 0 : if( xPropSet.is())
1363 : {
1364 0 : Any aAny( xPropSet->getPropertyValue(
1365 0 : OUString( "String" )));
1366 0 : OUString aText;
1367 0 : aAny >>= aText;
1368 0 : exportText( aText );
1369 0 : }
1370 : }
1371 : else // autostyles
1372 : {
1373 0 : CollectAutoStyle( aPropertyStates );
1374 : }
1375 : // remove property states for autostyles
1376 0 : aPropertyStates.clear();
1377 : }
1378 :
1379 : // legend element
1380 0 : if( bHasLegend )
1381 : {
1382 : // get property states for autostyles
1383 0 : if( mxExpPropMapper.is())
1384 : {
1385 0 : Reference< beans::XPropertySet > xPropSet( rChartDoc->getLegend(), uno::UNO_QUERY );
1386 0 : if( xPropSet.is())
1387 0 : aPropertyStates = mxExpPropMapper->Filter( xPropSet );
1388 : }
1389 :
1390 0 : if( bExportContent )
1391 : {
1392 0 : Reference< beans::XPropertySet > xProp( rChartDoc->getLegend(), uno::UNO_QUERY );
1393 0 : if( xProp.is())
1394 : {
1395 : // export legend anchor position
1396 : try
1397 : {
1398 0 : Any aAny( xProp->getPropertyValue("Alignment"));
1399 0 : if( SchXMLEnumConverter::getLegendPositionConverter().exportXML( msString, aAny, mrExport.GetMM100UnitConverter() ) )
1400 0 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LEGEND_POSITION, msString );
1401 : }
1402 0 : catch( const beans::UnknownPropertyException & )
1403 : {
1404 : SAL_WARN("xmloff.chart", "Property Align not found in ChartLegend" );
1405 : }
1406 :
1407 : // export absolute legend position
1408 0 : Reference< drawing::XShape > xLegendShape( xProp, uno::UNO_QUERY );
1409 0 : addPosition( xLegendShape );
1410 :
1411 : // export legend size
1412 0 : const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
1413 0 : if( xLegendShape.is() && nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 )
1414 : {
1415 : try
1416 : {
1417 0 : chart::ChartLegendExpansion nLegendExpansion = chart::ChartLegendExpansion_HIGH;
1418 0 : OUString aExpansionString;
1419 0 : Any aAny( xProp->getPropertyValue("Expansion"));
1420 0 : bool bHasExpansion = (aAny >>= nLegendExpansion);
1421 0 : if( bHasExpansion && SchXMLEnumConverter::getLegendExpansionConverter().exportXML( aExpansionString, aAny, mrExport.GetMM100UnitConverter() ) )
1422 : {
1423 0 : mrExport.AddAttribute( XML_NAMESPACE_STYLE, XML_LEGEND_EXPANSION, aExpansionString );
1424 0 : if( nLegendExpansion == chart::ChartLegendExpansion_CUSTOM)
1425 : {
1426 0 : awt::Size aSize( xLegendShape->getSize() );
1427 0 : addSize( aSize, true );
1428 0 : OUStringBuffer aAspectRatioString;
1429 : ::sax::Converter::convertDouble(
1430 : aAspectRatioString,
1431 0 : double(aSize.Width)/double(aSize.Height));
1432 0 : mrExport.AddAttribute( XML_NAMESPACE_STYLE, XML_LEGEND_EXPANSION_ASPECT_RATIO, aAspectRatioString.makeStringAndClear() );
1433 : }
1434 0 : }
1435 : }
1436 0 : catch( const beans::UnknownPropertyException & )
1437 : {
1438 : SAL_WARN("xmloff.chart", "Property Expansion not found in ChartLegend" );
1439 : }
1440 0 : }
1441 : }
1442 :
1443 : // write style name
1444 0 : AddAutoStyleAttribute( aPropertyStates );
1445 :
1446 : // element
1447 0 : SvXMLElementExport aLegend( mrExport, XML_NAMESPACE_CHART, XML_LEGEND, true, true );
1448 : }
1449 : else // autostyles
1450 : {
1451 0 : CollectAutoStyle( aPropertyStates );
1452 : }
1453 : // remove property states for autostyles
1454 0 : aPropertyStates.clear();
1455 : }
1456 :
1457 : // plot-area element
1458 0 : if( xDiagram.is())
1459 0 : exportPlotArea( xDiagram, xNewDiagram, aPageSize, bExportContent, bIncludeTable );
1460 :
1461 : // export additional shapes
1462 0 : if( xDocPropSet.is() )
1463 : {
1464 0 : if( bExportContent )
1465 : {
1466 0 : if( mxAdditionalShapes.is())
1467 : {
1468 : // can't call exportShapes with all shapes because the
1469 : // initialisation happened with the complete draw page and not
1470 : // the XShapes object used here. Thus the shapes have to be
1471 : // exported one by one
1472 0 : UniReference< XMLShapeExport > rShapeExport = mrExport.GetShapeExport();
1473 0 : Reference< drawing::XShape > xShape;
1474 0 : const sal_Int32 nShapeCount( mxAdditionalShapes->getCount());
1475 0 : for( sal_Int32 nShapeId = 0; nShapeId < nShapeCount; nShapeId++ )
1476 : {
1477 0 : mxAdditionalShapes->getByIndex( nShapeId ) >>= xShape;
1478 : SAL_WARN_IF( !xShape.is(), "xmloff.chart", "Shape without an XShape?" );
1479 0 : if( ! xShape.is())
1480 0 : continue;
1481 :
1482 0 : rShapeExport->exportShape( xShape );
1483 0 : }
1484 : // this would be the easier way if it worked:
1485 : //mrExport.GetShapeExport()->exportShapes( mxAdditionalShapes );
1486 : }
1487 : }
1488 : else
1489 : {
1490 : // get a sequence of non-chart shapes (inserted via clipboard)
1491 : try
1492 : {
1493 0 : Any aShapesAny = xDocPropSet->getPropertyValue("AdditionalShapes");
1494 0 : aShapesAny >>= mxAdditionalShapes;
1495 : }
1496 0 : catch( const uno::Exception & rEx )
1497 : {
1498 : SAL_INFO("xmloff.chart", "AdditionalShapes not found: " << rEx.Message );
1499 : }
1500 :
1501 0 : if( mxAdditionalShapes.is())
1502 : {
1503 : // seek shapes has to be called for the whole page because in
1504 : // the shape export the vector of shapes is accessed via the
1505 : // ZOrder which might be (actually is) larger than the number of
1506 : // shapes in mxAdditionalShapes
1507 0 : Reference< drawing::XDrawPageSupplier > xSupplier( rChartDoc, uno::UNO_QUERY );
1508 : SAL_WARN_IF( !xSupplier.is(), "xmloff.chart", "Cannot retrieve draw page to initialize shape export" );
1509 0 : if( xSupplier.is() )
1510 : {
1511 0 : Reference< drawing::XShapes > xDrawPage( xSupplier->getDrawPage(), uno::UNO_QUERY );
1512 : SAL_WARN_IF( !xDrawPage.is(), "xmloff.chart", "Invalid draw page for initializing shape export" );
1513 0 : if( xDrawPage.is())
1514 0 : mrExport.GetShapeExport()->seekShapes( xDrawPage );
1515 : }
1516 :
1517 : // can't call collectShapesAutoStyles with all shapes because
1518 : // the initialisation happened with the complete draw page and
1519 : // not the XShapes object used here. Thus the shapes have to be
1520 : // exported one by one
1521 0 : UniReference< XMLShapeExport > rShapeExport = mrExport.GetShapeExport();
1522 0 : Reference< drawing::XShape > xShape;
1523 0 : const sal_Int32 nShapeCount( mxAdditionalShapes->getCount());
1524 0 : for( sal_Int32 nShapeId = 0; nShapeId < nShapeCount; nShapeId++ )
1525 : {
1526 0 : mxAdditionalShapes->getByIndex( nShapeId ) >>= xShape;
1527 : SAL_WARN_IF( !xShape.is(), "xmloff.chart", "Shape without an XShape?" );
1528 0 : if( ! xShape.is())
1529 0 : continue;
1530 :
1531 0 : rShapeExport->collectShapeAutoStyles( xShape );
1532 0 : }
1533 : }
1534 : }
1535 : }
1536 :
1537 : // table element
1538 : // (is included as subelement of chart)
1539 0 : if( bExportContent )
1540 : {
1541 : // #85929# always export table, otherwise clipboard may loose data
1542 0 : exportTable();
1543 : }
1544 :
1545 : // close <chart:chart> element
1546 0 : if( pElChart )
1547 0 : delete pElChart;
1548 : }
1549 :
1550 0 : static void lcl_exportComplexLabel( const Sequence< uno::Any >& rComplexLabel, SvXMLExport& rExport )
1551 : {
1552 0 : sal_Int32 nLength = rComplexLabel.getLength();
1553 0 : if( nLength<=1 )
1554 0 : return;
1555 0 : SvXMLElementExport aTextList( rExport, XML_NAMESPACE_TEXT, XML_LIST, true, true );
1556 0 : for(sal_Int32 nN=0; nN<nLength; nN++)
1557 : {
1558 0 : SvXMLElementExport aListItem( rExport, XML_NAMESPACE_TEXT, XML_LIST_ITEM, true, true );
1559 0 : OUString aString;
1560 0 : if( !(rComplexLabel[nN]>>=aString) )
1561 : {
1562 : //todo?
1563 : }
1564 0 : SchXMLTools::exportText( rExport, aString, false /*bConvertTabsLFs*/ );
1565 0 : }
1566 : }
1567 :
1568 0 : void SchXMLExportHelper_Impl::exportTable()
1569 : {
1570 : // table element
1571 0 : mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_NAME, msTableName );
1572 :
1573 : try
1574 : {
1575 0 : bool bProtected = false;
1576 0 : Reference< beans::XPropertySet > xProps( mrExport.GetModel(), uno::UNO_QUERY_THROW );
1577 0 : if ( ( xProps->getPropertyValue("DisableDataTableDialog") >>= bProtected ) &&
1578 : bProtected )
1579 : {
1580 0 : mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_PROTECTED, XML_TRUE );
1581 0 : }
1582 : }
1583 0 : catch ( const uno::Exception& )
1584 : {
1585 : }
1586 :
1587 0 : SvXMLElementExport aTable( mrExport, XML_NAMESPACE_TABLE, XML_TABLE, true, true );
1588 :
1589 0 : bool bHasOwnData = false;
1590 0 : Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
1591 0 : Reference< chart2::data::XRangeXMLConversion > xRangeConversion;
1592 0 : if( xNewDoc.is())
1593 : {
1594 0 : bHasOwnData = xNewDoc->hasInternalDataProvider();
1595 0 : xRangeConversion.set( xNewDoc->getDataProvider(), uno::UNO_QUERY );
1596 : }
1597 :
1598 0 : Reference< chart2::XAnyDescriptionAccess > xAnyDescriptionAccess;
1599 : {
1600 0 : Reference< chart::XChartDocument > xChartDoc( mrExport.GetModel(), uno::UNO_QUERY );
1601 0 : if( xChartDoc.is() )
1602 0 : xAnyDescriptionAccess = Reference< chart2::XAnyDescriptionAccess >( xChartDoc->getData(), uno::UNO_QUERY );
1603 : }
1604 :
1605 0 : if( bHasOwnData )
1606 0 : lcl_ReorderInternalSequencesAccordingToTheirRangeName( m_aDataSequencesToExport );
1607 : lcl_TableData aData( lcl_getDataForLocalTable( m_aDataSequencesToExport
1608 : , xAnyDescriptionAccess, maCategoriesRange
1609 0 : , mbRowSourceColumns, xRangeConversion ));
1610 :
1611 0 : tStringVector::const_iterator aDataRangeIter( aData.aDataRangeRepresentations.begin());
1612 0 : const tStringVector::const_iterator aDataRangeEndIter( aData.aDataRangeRepresentations.end());
1613 :
1614 0 : tStringVector::const_iterator aRowDescriptions_RangeIter( aData.aRowDescriptions_Ranges.begin());
1615 0 : const tStringVector::const_iterator aRowDescriptions_RangeEnd( aData.aRowDescriptions_Ranges.end());
1616 :
1617 : // declare columns
1618 : {
1619 0 : SvXMLElementExport aHeaderColumns( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_HEADER_COLUMNS, true, true );
1620 0 : SvXMLElementExport aHeaderColumn( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, true, true );
1621 : }
1622 : {
1623 0 : SvXMLElementExport aColumns( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMNS, true, true );
1624 :
1625 0 : sal_Int32 nNextIndex = 0;
1626 0 : for( size_t nN=0; nN< aData.aHiddenColumns.size(); nN++ )
1627 : {
1628 : //i91578 display of hidden values (copy paste scenario; export hidden flag thus it can be used during migration to locale table upon paste )
1629 0 : sal_Int32 nHiddenIndex = aData.aHiddenColumns[nN];
1630 0 : if( nHiddenIndex > nNextIndex )
1631 : {
1632 0 : sal_Int64 nRepeat = static_cast< sal_Int64 >( nHiddenIndex - nNextIndex );
1633 0 : if(nRepeat>1)
1634 : mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED,
1635 0 : OUString::number( nRepeat ));
1636 0 : SvXMLElementExport aColumn( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, true, true );
1637 : }
1638 0 : mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_VISIBILITY, GetXMLToken( XML_COLLAPSE ) );
1639 0 : SvXMLElementExport aColumn( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, true, true );
1640 0 : nNextIndex = nHiddenIndex+1;
1641 0 : }
1642 :
1643 0 : sal_Int32 nEndIndex = aData.aColumnDescriptions.size()-1;
1644 0 : if( nEndIndex >= nNextIndex )
1645 : {
1646 0 : sal_Int64 nRepeat = static_cast< sal_Int64 >( nEndIndex - nNextIndex + 1 );
1647 0 : if(nRepeat>1)
1648 : mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED,
1649 0 : OUString::number( nRepeat ));
1650 0 : SvXMLElementExport aColumn( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, true, true );
1651 0 : }
1652 : }
1653 :
1654 : // export rows with content
1655 : //export header row
1656 : {
1657 0 : SvXMLElementExport aHeaderRows( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_HEADER_ROWS, true, true );
1658 0 : SvXMLElementExport aRow( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_ROW, true, true );
1659 :
1660 : //first one empty cell for the row descriptions
1661 : {
1662 0 : SvXMLElementExport aEmptyCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, true );
1663 0 : SvXMLElementExport aEmptyParagraph( mrExport, XML_NAMESPACE_TEXT, XML_P, true, true );
1664 : }
1665 :
1666 : //export column descriptions
1667 0 : tStringVector::const_iterator aColumnDescriptions_RangeIter( aData.aColumnDescriptions_Ranges.begin());
1668 0 : const tStringVector::const_iterator aColumnDescriptions_RangeEnd( aData.aColumnDescriptions_Ranges.end());
1669 0 : const Sequence< Sequence< uno::Any > >& rComplexColumnDescriptions = aData.aComplexColumnDescriptions;
1670 0 : sal_Int32 nComplexCount = rComplexColumnDescriptions.getLength();
1671 0 : sal_Int32 nC = 0;
1672 0 : for( tStringVector::const_iterator aIt( aData.aColumnDescriptions.begin())
1673 0 : ; (aIt != aData.aColumnDescriptions.end())
1674 : ; ++aIt, nC++ )
1675 : {
1676 0 : bool bExportString = true;
1677 0 : if( nC < nComplexCount )
1678 : {
1679 0 : const Sequence< uno::Any >& rComplexLabel = rComplexColumnDescriptions[nC];
1680 0 : if( rComplexLabel.getLength()>0 )
1681 : {
1682 0 : double fValue=0.0;
1683 0 : if( rComplexLabel[0] >>=fValue )
1684 : {
1685 0 : bExportString = false;
1686 :
1687 : ::sax::Converter::convertDouble(
1688 0 : msStringBuffer, fValue);
1689 0 : msString = msStringBuffer.makeStringAndClear();
1690 0 : mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT );
1691 0 : mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE, msString );
1692 : }
1693 : }
1694 : }
1695 0 : if( bExportString )
1696 : {
1697 0 : mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_STRING );
1698 : }
1699 :
1700 0 : SvXMLElementExport aCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, true );
1701 0 : exportText( *aIt );
1702 0 : if( nC < nComplexCount )
1703 0 : lcl_exportComplexLabel( rComplexColumnDescriptions[nC], mrExport );
1704 0 : if( !bHasOwnData && aColumnDescriptions_RangeIter != aColumnDescriptions_RangeEnd )
1705 : {
1706 : // remind the original range to allow a correct re-association when copying via clipboard
1707 0 : if (!(*aColumnDescriptions_RangeIter).isEmpty())
1708 0 : SchXMLTools::exportRangeToSomewhere( mrExport, *aColumnDescriptions_RangeIter );
1709 0 : ++aColumnDescriptions_RangeIter;
1710 : }
1711 0 : }
1712 0 : SAL_WARN_IF( !bHasOwnData && (aColumnDescriptions_RangeIter != aColumnDescriptions_RangeEnd), "xmloff.chart", "bHasOwnData == false && aColumnDescriptions_RangeIter != aColumnDescriptions_RangeEnd" );
1713 : } // closing row and header-rows elements
1714 :
1715 : // export value rows
1716 : {
1717 0 : SvXMLElementExport aRows( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_ROWS, true, true );
1718 0 : tStringVector::const_iterator aRowDescriptionsIter( aData.aRowDescriptions.begin());
1719 0 : const Sequence< Sequence< uno::Any > >& rComplexRowDescriptions = aData.aComplexRowDescriptions;
1720 0 : sal_Int32 nComplexCount = rComplexRowDescriptions.getLength();
1721 0 : sal_Int32 nC = 0;
1722 :
1723 0 : for( t2DNumberContainer::const_iterator aRowIt( aData.aDataInRows.begin())
1724 0 : ; aRowIt != aData.aDataInRows.end()
1725 : ; ++aRowIt, ++nC )
1726 : {
1727 0 : SvXMLElementExport aRow( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_ROW, true, true );
1728 :
1729 : //export row descriptions
1730 : {
1731 0 : bool bExportString = true;
1732 0 : if( nC < nComplexCount )
1733 : {
1734 0 : const Sequence< uno::Any >& rComplexLabel = rComplexRowDescriptions[nC];
1735 0 : if( rComplexLabel.getLength()>0 )
1736 : {
1737 0 : double fValue=0.0;
1738 0 : if( rComplexLabel[0] >>=fValue )
1739 : {
1740 0 : bExportString = false;
1741 :
1742 0 : ::sax::Converter::convertDouble(msStringBuffer, fValue);
1743 0 : msString = msStringBuffer.makeStringAndClear();
1744 0 : mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT );
1745 0 : mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE, msString );
1746 : }
1747 : }
1748 : }
1749 0 : if( bExportString )
1750 : {
1751 0 : mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_STRING );
1752 : }
1753 :
1754 0 : SvXMLElementExport aCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, true );
1755 0 : if( aRowDescriptionsIter != aData.aRowDescriptions.end())
1756 : {
1757 0 : exportText( *aRowDescriptionsIter );
1758 0 : if( nC < nComplexCount )
1759 0 : lcl_exportComplexLabel( rComplexRowDescriptions[nC], mrExport );
1760 0 : if( !bHasOwnData && aRowDescriptions_RangeIter != aRowDescriptions_RangeEnd )
1761 : {
1762 : // remind the original range to allow a correct re-association when copying via clipboard
1763 0 : SchXMLTools::exportRangeToSomewhere( mrExport, *aRowDescriptions_RangeIter );
1764 0 : ++aRowDescriptions_RangeIter;
1765 : }
1766 0 : ++aRowDescriptionsIter;
1767 0 : }
1768 : }
1769 :
1770 : //export row values
1771 0 : for( t2DNumberContainer::value_type::const_iterator aColIt( aRowIt->begin());
1772 0 : aColIt != aRowIt->end(); ++aColIt )
1773 : {
1774 0 : ::sax::Converter::convertDouble( msStringBuffer, *aColIt );
1775 0 : msString = msStringBuffer.makeStringAndClear();
1776 0 : mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT );
1777 0 : mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE, msString );
1778 0 : SvXMLElementExport aCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, true );
1779 0 : exportText( msString, false ); // do not convert tabs and lfs
1780 0 : if( ( !bHasOwnData && aDataRangeIter != aDataRangeEndIter ) &&
1781 0 : ( mbRowSourceColumns || (aColIt == aRowIt->begin()) ) )
1782 : {
1783 : // remind the original range to allow a correct re-association when copying via clipboard
1784 0 : if (!(*aDataRangeIter).isEmpty())
1785 0 : SchXMLTools::exportRangeToSomewhere( mrExport, *aDataRangeIter );
1786 0 : ++aDataRangeIter;
1787 : }
1788 0 : }
1789 0 : }
1790 : }
1791 :
1792 : // if range iterator was used it should have reached its end
1793 : SAL_WARN_IF( !bHasOwnData && (aDataRangeIter != aDataRangeEndIter), "xmloff.chart", "bHasOwnData == false && aDataRangeIter != aDataRangeEndIter" );
1794 0 : SAL_WARN_IF( !bHasOwnData && (aRowDescriptions_RangeIter != aRowDescriptions_RangeEnd), "xmloff.chart", "bHasOwnData == false && aRowDescriptions_RangeIter != aRowDescriptions_RangeEnd" );
1795 0 : }
1796 :
1797 : namespace
1798 : {
1799 :
1800 0 : Reference< chart2::XCoordinateSystem > lcl_getCooSys( const Reference< chart2::XDiagram > & xNewDiagram )
1801 : {
1802 0 : Reference< chart2::XCoordinateSystem > xCooSys;
1803 0 : Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xNewDiagram, uno::UNO_QUERY );
1804 0 : if(xCooSysCnt.is())
1805 : {
1806 0 : Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems() );
1807 0 : if(aCooSysSeq.getLength()>0)
1808 0 : xCooSys = aCooSysSeq[0];
1809 : }
1810 0 : return xCooSys;
1811 : }
1812 :
1813 0 : Reference< chart2::XAxis > lcl_getAxis( const Reference< chart2::XCoordinateSystem >& xCooSys,
1814 : enum XMLTokenEnum eDimension, bool bPrimary=true )
1815 : {
1816 0 : Reference< chart2::XAxis > xNewAxis;
1817 : try
1818 : {
1819 0 : if( xCooSys.is() )
1820 : {
1821 0 : sal_Int32 nDimensionIndex=0;
1822 0 : switch( eDimension )
1823 : {
1824 : case XML_X:
1825 0 : nDimensionIndex=0;
1826 0 : break;
1827 : case XML_Y:
1828 0 : nDimensionIndex=1;
1829 0 : break;
1830 : case XML_Z:
1831 0 : nDimensionIndex=2;
1832 0 : break;
1833 : default:
1834 0 : break;
1835 : }
1836 :
1837 0 : xNewAxis = xCooSys->getAxisByDimension( nDimensionIndex, bPrimary ? 0 : 1 );
1838 : }
1839 : }
1840 0 : catch( const uno::Exception & )
1841 : {
1842 : }
1843 0 : return xNewAxis;
1844 : }
1845 :
1846 : }
1847 :
1848 0 : void SchXMLExportHelper_Impl::exportPlotArea(
1849 : Reference< chart::XDiagram > xDiagram,
1850 : Reference< chart2::XDiagram > xNewDiagram,
1851 : const awt::Size & rPageSize,
1852 : sal_Bool bExportContent,
1853 : sal_Bool bIncludeTable )
1854 : {
1855 : SAL_WARN_IF( !xDiagram.is(), "xmloff.chart", "Invalid XDiagram as parameter" );
1856 0 : if( ! xDiagram.is())
1857 0 : return;
1858 :
1859 : // variables for autostyles
1860 0 : Reference< beans::XPropertySet > xPropSet;
1861 0 : std::vector< XMLPropertyState > aPropertyStates;
1862 :
1863 0 : sal_Bool bIs3DChart = sal_False;
1864 0 : drawing::HomogenMatrix aTransMatrix;
1865 :
1866 0 : msStringBuffer.setLength( 0 );
1867 :
1868 : // plot-area element
1869 :
1870 0 : SvXMLElementExport* pElPlotArea = 0;
1871 : // get property states for autostyles
1872 0 : xPropSet = Reference< beans::XPropertySet >( xDiagram, uno::UNO_QUERY );
1873 0 : if( xPropSet.is())
1874 : {
1875 0 : if( mxExpPropMapper.is())
1876 0 : aPropertyStates = mxExpPropMapper->Filter( xPropSet );
1877 : }
1878 0 : if( bExportContent )
1879 : {
1880 0 : UniReference< XMLShapeExport > rShapeExport;
1881 :
1882 : // write style name
1883 0 : AddAutoStyleAttribute( aPropertyStates );
1884 :
1885 0 : if( !msChartAddress.isEmpty() )
1886 : {
1887 0 : if( !bIncludeTable )
1888 0 : mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_CELL_RANGE_ADDRESS, msChartAddress );
1889 :
1890 0 : Reference< chart::XChartDocument > xDoc( mrExport.GetModel(), uno::UNO_QUERY );
1891 0 : if( xDoc.is() )
1892 : {
1893 0 : Reference< beans::XPropertySet > xDocProp( xDoc, uno::UNO_QUERY );
1894 0 : if( xDocProp.is())
1895 : {
1896 0 : Any aAny;
1897 0 : sal_Bool bFirstCol = false, bFirstRow = false;
1898 :
1899 : try
1900 : {
1901 0 : aAny = xDocProp->getPropertyValue(
1902 0 : OUString( "DataSourceLabelsInFirstColumn" ));
1903 0 : aAny >>= bFirstCol;
1904 0 : aAny = xDocProp->getPropertyValue(
1905 0 : OUString( "DataSourceLabelsInFirstRow" ));
1906 0 : aAny >>= bFirstRow;
1907 :
1908 0 : if( bFirstCol || bFirstRow )
1909 : {
1910 : mrExport.AddAttribute( XML_NAMESPACE_CHART,
1911 0 : ::xmloff::token::GetXMLToken( ::xmloff::token::XML_DATA_SOURCE_HAS_LABELS ),
1912 : ( bFirstCol
1913 : ? ( bFirstRow
1914 : ? ::xmloff::token::GetXMLToken( ::xmloff::token::XML_BOTH )
1915 : : ::xmloff::token::GetXMLToken( ::xmloff::token::XML_COLUMN ))
1916 0 : : ::xmloff::token::GetXMLToken( ::xmloff::token::XML_ROW )));
1917 : }
1918 : }
1919 0 : catch( const beans::UnknownPropertyException & )
1920 : {
1921 : SAL_WARN("xmloff.chart", "Properties missing" );
1922 0 : }
1923 0 : }
1924 0 : }
1925 : }
1926 :
1927 : // attributes
1928 0 : Reference< drawing::XShape > xShape ( xDiagram, uno::UNO_QUERY );
1929 0 : if( xShape.is())
1930 : {
1931 0 : addPosition( xShape );
1932 0 : addSize( xShape );
1933 : }
1934 :
1935 0 : if( xPropSet.is())
1936 : {
1937 0 : Any aAny;
1938 :
1939 : // 3d attributes
1940 : try
1941 : {
1942 0 : aAny = xPropSet->getPropertyValue("Dim3D");
1943 0 : aAny >>= bIs3DChart;
1944 :
1945 0 : if( bIs3DChart )
1946 : {
1947 0 : rShapeExport = mrExport.GetShapeExport();
1948 0 : if( rShapeExport.is())
1949 0 : rShapeExport->export3DSceneAttributes( xPropSet );
1950 : }
1951 : }
1952 0 : catch( const uno::Exception & rEx )
1953 : {
1954 0 : OString aBStr(OUStringToOString(rEx.Message, RTL_TEXTENCODING_ASCII_US));
1955 0 : SAL_INFO("xmloff.chart", "chart:exportPlotAreaException caught: " << aBStr);
1956 0 : }
1957 : }
1958 :
1959 : // plot-area element
1960 0 : pElPlotArea = new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_PLOT_AREA, true, true );
1961 :
1962 : //inner position rectangle element
1963 0 : exportCoordinateRegion( xDiagram );
1964 :
1965 : // light sources (inside plot area element)
1966 0 : if( bIs3DChart &&
1967 0 : rShapeExport.is())
1968 0 : rShapeExport->export3DLamps( xPropSet );
1969 : }
1970 : else // autostyles
1971 : {
1972 0 : CollectAutoStyle( aPropertyStates );
1973 : }
1974 : // remove property states for autostyles
1975 0 : aPropertyStates.clear();
1976 :
1977 : // axis elements
1978 0 : exportAxes( xDiagram, xNewDiagram, bExportContent );
1979 :
1980 : // series elements
1981 0 : Reference< chart2::XAxis > xSecondYAxis = lcl_getAxis( lcl_getCooSys( xNewDiagram ), XML_Y, false );
1982 0 : exportSeries( xNewDiagram, rPageSize, bExportContent, xSecondYAxis.is() );
1983 :
1984 : // stock-chart elements
1985 0 : OUString sChartType ( xDiagram->getDiagramType());
1986 0 : if( sChartType == "com.sun.star.chart.StockDiagram" )
1987 : {
1988 0 : Reference< chart::XStatisticDisplay > xStockPropProvider( xDiagram, uno::UNO_QUERY );
1989 0 : if( xStockPropProvider.is())
1990 : {
1991 : // stock-gain-marker
1992 0 : Reference< beans::XPropertySet > xStockPropSet = xStockPropProvider->getUpBar();
1993 0 : if( xStockPropSet.is())
1994 : {
1995 0 : aPropertyStates.clear();
1996 0 : aPropertyStates = mxExpPropMapper->Filter( xStockPropSet );
1997 :
1998 0 : if( !aPropertyStates.empty() )
1999 : {
2000 0 : if( bExportContent )
2001 : {
2002 0 : AddAutoStyleAttribute( aPropertyStates );
2003 :
2004 0 : SvXMLElementExport aGain( mrExport, XML_NAMESPACE_CHART, XML_STOCK_GAIN_MARKER, true, true );
2005 : }
2006 : else
2007 : {
2008 0 : CollectAutoStyle( aPropertyStates );
2009 : }
2010 : }
2011 : }
2012 :
2013 : // stock-loss-marker
2014 0 : xStockPropSet = xStockPropProvider->getDownBar();
2015 0 : if( xStockPropSet.is())
2016 : {
2017 0 : aPropertyStates.clear();
2018 0 : aPropertyStates = mxExpPropMapper->Filter( xStockPropSet );
2019 :
2020 0 : if( !aPropertyStates.empty() )
2021 : {
2022 0 : if( bExportContent )
2023 : {
2024 0 : AddAutoStyleAttribute( aPropertyStates );
2025 :
2026 0 : SvXMLElementExport aGain( mrExport, XML_NAMESPACE_CHART, XML_STOCK_LOSS_MARKER, true, true );
2027 : }
2028 : else
2029 : {
2030 0 : CollectAutoStyle( aPropertyStates );
2031 : }
2032 : }
2033 : }
2034 :
2035 : // stock-range-line
2036 0 : xStockPropSet = xStockPropProvider->getMinMaxLine();
2037 0 : if( xStockPropSet.is())
2038 : {
2039 0 : aPropertyStates.clear();
2040 0 : aPropertyStates = mxExpPropMapper->Filter( xStockPropSet );
2041 :
2042 0 : if( !aPropertyStates.empty() )
2043 : {
2044 0 : if( bExportContent )
2045 : {
2046 0 : AddAutoStyleAttribute( aPropertyStates );
2047 :
2048 0 : SvXMLElementExport aGain( mrExport, XML_NAMESPACE_CHART, XML_STOCK_RANGE_LINE, true, true );
2049 : }
2050 : else
2051 : {
2052 0 : CollectAutoStyle( aPropertyStates );
2053 : }
2054 : }
2055 0 : }
2056 0 : }
2057 : }
2058 :
2059 : // wall and floor element
2060 0 : Reference< chart::X3DDisplay > xWallFloorSupplier( xDiagram, uno::UNO_QUERY );
2061 0 : if( mxExpPropMapper.is() &&
2062 0 : xWallFloorSupplier.is())
2063 : {
2064 : // remove property states for autostyles
2065 0 : aPropertyStates.clear();
2066 :
2067 0 : Reference< beans::XPropertySet > xWallPropSet( xWallFloorSupplier->getWall(), uno::UNO_QUERY );
2068 0 : if( xWallPropSet.is())
2069 : {
2070 0 : aPropertyStates = mxExpPropMapper->Filter( xWallPropSet );
2071 :
2072 0 : if( !aPropertyStates.empty() )
2073 : {
2074 : // write element
2075 0 : if( bExportContent )
2076 : {
2077 : // add style name attribute
2078 0 : AddAutoStyleAttribute( aPropertyStates );
2079 :
2080 0 : SvXMLElementExport aWall( mrExport, XML_NAMESPACE_CHART, XML_WALL, true, true );
2081 : }
2082 : else // autostyles
2083 : {
2084 0 : CollectAutoStyle( aPropertyStates );
2085 : }
2086 : }
2087 : }
2088 :
2089 : // floor element
2090 : // remove property states for autostyles
2091 0 : aPropertyStates.clear();
2092 :
2093 0 : Reference< beans::XPropertySet > xFloorPropSet( xWallFloorSupplier->getFloor(), uno::UNO_QUERY );
2094 0 : if( xFloorPropSet.is())
2095 : {
2096 0 : aPropertyStates = mxExpPropMapper->Filter( xFloorPropSet );
2097 :
2098 0 : if( !aPropertyStates.empty() )
2099 : {
2100 : // write element
2101 0 : if( bExportContent )
2102 : {
2103 : // add style name attribute
2104 0 : AddAutoStyleAttribute( aPropertyStates );
2105 :
2106 0 : SvXMLElementExport aFloor( mrExport, XML_NAMESPACE_CHART, XML_FLOOR, true, true );
2107 : }
2108 : else // autostyles
2109 : {
2110 0 : CollectAutoStyle( aPropertyStates );
2111 : }
2112 : }
2113 0 : }
2114 : }
2115 :
2116 0 : if( pElPlotArea )
2117 0 : delete pElPlotArea;
2118 : }
2119 :
2120 0 : void SchXMLExportHelper_Impl::exportCoordinateRegion( const uno::Reference< chart::XDiagram >& xDiagram )
2121 : {
2122 0 : const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
2123 0 : if( nCurrentODFVersion <= SvtSaveOptions::ODFVER_012 )//do not export to ODF 1.2 or older
2124 0 : return;
2125 :
2126 0 : Reference< chart::XDiagramPositioning > xDiaPos( xDiagram, uno::UNO_QUERY );
2127 : SAL_WARN_IF( !xDiaPos.is(), "xmloff.chart", "Invalid xDiaPos as parameter" );
2128 0 : if( !xDiaPos.is() )
2129 0 : return;
2130 :
2131 0 : awt::Rectangle aRect( xDiaPos->calculateDiagramPositionExcludingAxes() );
2132 0 : addPosition( awt::Point(aRect.X,aRect.Y) );
2133 0 : addSize( awt::Size(aRect.Width,aRect.Height) );
2134 :
2135 0 : SvXMLElementExport aCoordinateRegion( mrExport, XML_NAMESPACE_CHART_EXT, XML_COORDINATE_REGION, true, true );//#i100778# todo: change to chart namespace in future - dependent on fileformat
2136 : }
2137 :
2138 : namespace
2139 : {
2140 0 : XMLTokenEnum lcl_getTimeUnitToken( sal_Int32 nTimeUnit )
2141 : {
2142 0 : XMLTokenEnum eToken = XML_DAYS;
2143 0 : switch( nTimeUnit )
2144 : {
2145 : case ::com::sun::star::chart::TimeUnit::YEAR:
2146 0 : eToken = XML_YEARS;
2147 0 : break;
2148 : case ::com::sun::star::chart::TimeUnit::MONTH:
2149 0 : eToken = XML_MONTHS;
2150 0 : break;
2151 : default://days
2152 0 : break;
2153 : }
2154 0 : return eToken;
2155 : }
2156 : }
2157 :
2158 0 : void SchXMLExportHelper_Impl::exportDateScale( const Reference< beans::XPropertySet > xAxisProps )
2159 : {
2160 0 : if( !xAxisProps.is() )
2161 0 : return;
2162 :
2163 0 : chart::TimeIncrement aIncrement;
2164 0 : if( (xAxisProps->getPropertyValue("TimeIncrement") >>= aIncrement) )
2165 : {
2166 0 : sal_Int32 nTimeResolution = ::com::sun::star::chart::TimeUnit::DAY;
2167 0 : if( aIncrement.TimeResolution >>= nTimeResolution )
2168 0 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_BASE_TIME_UNIT, lcl_getTimeUnitToken( nTimeResolution ) );
2169 :
2170 0 : OUStringBuffer aValue;
2171 0 : chart::TimeInterval aInterval;
2172 0 : if( aIncrement.MajorTimeInterval >>= aInterval )
2173 : {
2174 0 : ::sax::Converter::convertNumber( aValue, aInterval.Number );
2175 0 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MAJOR_INTERVAL_VALUE, aValue.makeStringAndClear() );
2176 0 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MAJOR_INTERVAL_UNIT, lcl_getTimeUnitToken( aInterval.TimeUnit ) );
2177 : }
2178 0 : if( aIncrement.MinorTimeInterval >>= aInterval )
2179 : {
2180 0 : ::sax::Converter::convertNumber( aValue, aInterval.Number );
2181 0 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MINOR_INTERVAL_VALUE, aValue.makeStringAndClear() );
2182 0 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MINOR_INTERVAL_UNIT, lcl_getTimeUnitToken( aInterval.TimeUnit ) );
2183 : }
2184 :
2185 0 : SvXMLElementExport aDateScale( mrExport, XML_NAMESPACE_CHART_EXT, XML_DATE_SCALE, true, true );//#i25706#todo: change namespace for next ODF version
2186 0 : }
2187 : }
2188 :
2189 0 : void SchXMLExportHelper_Impl::exportAxisTitle( const Reference< beans::XPropertySet > xTitleProps, bool bExportContent )
2190 : {
2191 0 : if( !xTitleProps.is() )
2192 0 : return;
2193 0 : std::vector< XMLPropertyState > aPropertyStates = mxExpPropMapper->Filter( xTitleProps );
2194 0 : if( bExportContent )
2195 : {
2196 0 : OUString aText;
2197 0 : Any aAny( xTitleProps->getPropertyValue(
2198 0 : OUString( "String" )));
2199 0 : aAny >>= aText;
2200 :
2201 0 : Reference< drawing::XShape > xShape( xTitleProps, uno::UNO_QUERY );
2202 0 : if( xShape.is())
2203 0 : addPosition( xShape );
2204 :
2205 0 : AddAutoStyleAttribute( aPropertyStates );
2206 0 : SvXMLElementExport aTitle( mrExport, XML_NAMESPACE_CHART, XML_TITLE, true, true );
2207 :
2208 : // paragraph containing title
2209 0 : exportText( aText );
2210 : }
2211 : else
2212 : {
2213 0 : CollectAutoStyle( aPropertyStates );
2214 : }
2215 0 : aPropertyStates.clear();
2216 : }
2217 :
2218 0 : void SchXMLExportHelper_Impl::exportGrid( const Reference< beans::XPropertySet > xGridProperties, bool bMajor, bool bExportContent )
2219 : {
2220 0 : if( !xGridProperties.is() )
2221 0 : return;
2222 0 : std::vector< XMLPropertyState > aPropertyStates = mxExpPropMapper->Filter( xGridProperties );
2223 0 : if( bExportContent )
2224 : {
2225 0 : AddAutoStyleAttribute( aPropertyStates );
2226 0 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_CLASS, bMajor ? XML_MAJOR : XML_MINOR );
2227 0 : SvXMLElementExport aGrid( mrExport, XML_NAMESPACE_CHART, XML_GRID, true, true );
2228 : }
2229 : else
2230 : {
2231 0 : CollectAutoStyle( aPropertyStates );
2232 : }
2233 0 : aPropertyStates.clear();
2234 : }
2235 :
2236 : namespace
2237 : {
2238 :
2239 : //returns true if a date scale needs to be exported
2240 0 : bool lcl_exportAxisType( const Reference< chart2::XAxis > xChart2Axis, SvXMLExport& rExport)
2241 : {
2242 0 : bool bExportDateScale = false;
2243 0 : if( !xChart2Axis.is() )
2244 0 : return bExportDateScale;
2245 :
2246 0 : const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
2247 0 : if( nCurrentODFVersion <= SvtSaveOptions::ODFVER_012 )//do not export to ODF 1.2 or older
2248 0 : return bExportDateScale;
2249 :
2250 0 : chart2::ScaleData aScale( xChart2Axis->getScaleData() );
2251 : //#i25706#todo: change namespace for next ODF version
2252 0 : sal_uInt16 nNameSpace = XML_NAMESPACE_CHART_EXT;
2253 :
2254 0 : switch(aScale.AxisType)
2255 : {
2256 : case chart2::AxisType::CATEGORY:
2257 0 : if( aScale.AutoDateAxis )
2258 : {
2259 0 : rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_AUTO );
2260 0 : bExportDateScale = true;
2261 : }
2262 : else
2263 0 : rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_TEXT );
2264 0 : break;
2265 : case chart2::AxisType::DATE:
2266 0 : rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_DATE );
2267 0 : bExportDateScale = true;
2268 0 : break;
2269 : default: //AUTOMATIC
2270 0 : rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_AUTO );
2271 0 : break;
2272 : }
2273 :
2274 0 : return bExportDateScale;
2275 : }
2276 :
2277 : }
2278 :
2279 0 : void SchXMLExportHelper_Impl::exportAxis(
2280 : enum XMLTokenEnum eDimension,
2281 : enum XMLTokenEnum eAxisName,
2282 : const Reference< beans::XPropertySet > xAxisProps,
2283 : const Reference< chart2::XAxis >& xChart2Axis,
2284 : const OUString& rCategoriesRange,
2285 : bool bHasTitle, bool bHasMajorGrid, bool bHasMinorGrid,
2286 : bool bExportContent )
2287 : {
2288 0 : static const OUString sNumFormat( "NumberFormat" );
2289 0 : std::vector< XMLPropertyState > aPropertyStates;
2290 0 : SvXMLElementExport* pAxis = NULL;
2291 :
2292 : // get property states for autostyles
2293 0 : if( xAxisProps.is() && mxExpPropMapper.is() )
2294 : {
2295 0 : lcl_exportNumberFormat( sNumFormat, xAxisProps, mrExport );
2296 0 : aPropertyStates = mxExpPropMapper->Filter( xAxisProps );
2297 : }
2298 :
2299 0 : bool bExportDateScale = false;
2300 0 : if( bExportContent )
2301 : {
2302 0 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_DIMENSION, eDimension );
2303 0 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_NAME, eAxisName );
2304 0 : AddAutoStyleAttribute( aPropertyStates ); // write style name
2305 0 : if( !rCategoriesRange.isEmpty() )
2306 0 : bExportDateScale = lcl_exportAxisType( xChart2Axis, mrExport );
2307 :
2308 : // open axis element
2309 0 : pAxis = new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_AXIS, true, true );
2310 : }
2311 : else
2312 : {
2313 0 : CollectAutoStyle( aPropertyStates );
2314 : }
2315 0 : aPropertyStates.clear();
2316 :
2317 : //date scale
2318 0 : if( bExportDateScale )
2319 0 : exportDateScale( xAxisProps );
2320 :
2321 0 : Reference< beans::XPropertySet > xTitleProps;
2322 0 : Reference< beans::XPropertySet > xMajorGridProps;
2323 0 : Reference< beans::XPropertySet > xMinorGridProps;
2324 0 : Reference< chart::XAxis > xAxis( xAxisProps, uno::UNO_QUERY );
2325 0 : if( xAxis.is() )
2326 : {
2327 0 : xTitleProps = bHasTitle ? xAxis->getAxisTitle() : 0;
2328 0 : xMajorGridProps = bHasMajorGrid ? xAxis->getMajorGrid() : 0;
2329 0 : xMinorGridProps = bHasMinorGrid ? xAxis->getMinorGrid() : 0;
2330 : }
2331 :
2332 : // axis-title
2333 0 : exportAxisTitle( xTitleProps , bExportContent );
2334 :
2335 : // categories if we have a categories chart
2336 0 : if( bExportContent && !rCategoriesRange.isEmpty() )
2337 : {
2338 0 : mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_CELL_RANGE_ADDRESS, rCategoriesRange );
2339 0 : SvXMLElementExport aCategories( mrExport, XML_NAMESPACE_CHART, XML_CATEGORIES, true, true );
2340 : }
2341 :
2342 : // grid
2343 0 : exportGrid( xMajorGridProps, true, bExportContent );
2344 0 : exportGrid( xMinorGridProps, false, bExportContent );
2345 :
2346 0 : if( pAxis )
2347 : {
2348 : //close axis element
2349 0 : delete pAxis;
2350 0 : pAxis = NULL;
2351 0 : }
2352 0 : }
2353 :
2354 0 : void SchXMLExportHelper_Impl::exportAxes(
2355 : const Reference< chart::XDiagram > & xDiagram,
2356 : const Reference< chart2::XDiagram > & xNewDiagram,
2357 : sal_Bool bExportContent )
2358 : {
2359 : SAL_WARN_IF( !xDiagram.is(), "xmloff.chart", "Invalid XDiagram as parameter" );
2360 0 : if( ! xDiagram.is())
2361 0 : return;
2362 :
2363 : // get some properties from document first
2364 0 : sal_Bool bHasXAxis = sal_False,
2365 0 : bHasYAxis = sal_False,
2366 0 : bHasZAxis = sal_False,
2367 0 : bHasSecondaryXAxis = sal_False,
2368 0 : bHasSecondaryYAxis = sal_False;
2369 0 : sal_Bool bHasXAxisTitle = sal_False,
2370 0 : bHasYAxisTitle = sal_False,
2371 0 : bHasZAxisTitle = sal_False,
2372 0 : bHasSecondaryXAxisTitle = sal_False,
2373 0 : bHasSecondaryYAxisTitle = sal_False;
2374 0 : sal_Bool bHasXAxisMajorGrid = sal_False,
2375 0 : bHasXAxisMinorGrid = sal_False,
2376 0 : bHasYAxisMajorGrid = sal_False,
2377 0 : bHasYAxisMinorGrid = sal_False,
2378 0 : bHasZAxisMajorGrid = sal_False,
2379 0 : bHasZAxisMinorGrid = sal_False;
2380 :
2381 : // get multiple properties using XMultiPropertySet
2382 0 : MultiPropertySetHandler aDiagramProperties (xDiagram);
2383 :
2384 : aDiagramProperties.Add (
2385 0 : OUString("HasXAxis"), bHasXAxis);
2386 : aDiagramProperties.Add (
2387 0 : OUString("HasYAxis"), bHasYAxis);
2388 : aDiagramProperties.Add (
2389 0 : OUString("HasZAxis"), bHasZAxis);
2390 : aDiagramProperties.Add (
2391 0 : OUString("HasSecondaryXAxis"), bHasSecondaryXAxis);
2392 : aDiagramProperties.Add (
2393 0 : OUString("HasSecondaryYAxis"), bHasSecondaryYAxis);
2394 :
2395 : aDiagramProperties.Add (
2396 0 : OUString ("HasXAxisTitle"), bHasXAxisTitle);
2397 : aDiagramProperties.Add (
2398 0 : OUString ("HasYAxisTitle"), bHasYAxisTitle);
2399 : aDiagramProperties.Add (
2400 0 : OUString ("HasZAxisTitle"), bHasZAxisTitle);
2401 : aDiagramProperties.Add (
2402 0 : OUString ("HasSecondaryXAxisTitle"), bHasSecondaryXAxisTitle);
2403 : aDiagramProperties.Add (
2404 0 : OUString ("HasSecondaryYAxisTitle"), bHasSecondaryYAxisTitle);
2405 :
2406 : aDiagramProperties.Add (
2407 0 : OUString ("HasXAxisGrid"), bHasXAxisMajorGrid);
2408 : aDiagramProperties.Add (
2409 0 : OUString ("HasYAxisGrid"), bHasYAxisMajorGrid);
2410 : aDiagramProperties.Add (
2411 0 : OUString ("HasZAxisGrid"), bHasZAxisMajorGrid);
2412 :
2413 : aDiagramProperties.Add (
2414 0 : OUString ("HasXAxisHelpGrid"), bHasXAxisMinorGrid);
2415 : aDiagramProperties.Add (
2416 0 : OUString ("HasYAxisHelpGrid"), bHasYAxisMinorGrid);
2417 : aDiagramProperties.Add (
2418 0 : OUString ("HasZAxisHelpGrid"), bHasZAxisMinorGrid);
2419 :
2420 0 : if ( ! aDiagramProperties.GetProperties ())
2421 : {
2422 : SAL_INFO("xmloff.chart", "Required properties not found in Chart diagram");
2423 : }
2424 :
2425 0 : Reference< chart2::XCoordinateSystem > xCooSys( lcl_getCooSys(xNewDiagram) );
2426 :
2427 : // write an axis element also if the axis itself is not visible, but a grid or a title
2428 :
2429 0 : OUString aCategoriesRange;
2430 0 : Reference< chart::XAxisSupplier > xAxisSupp( xDiagram, uno::UNO_QUERY );
2431 :
2432 : // x axis
2433 :
2434 0 : Reference< ::com::sun::star::chart2::XAxis > xNewAxis = lcl_getAxis( xCooSys, XML_X );
2435 0 : if( xNewAxis.is() )
2436 : {
2437 0 : Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getAxis(0) : 0, uno::UNO_QUERY );
2438 0 : if( mbHasCategoryLabels && bExportContent )
2439 : {
2440 0 : Reference< chart2::data::XLabeledDataSequence > xCategories( lcl_getCategories( xNewDiagram ) );
2441 0 : if( xCategories.is() )
2442 : {
2443 0 : Reference< chart2::data::XDataSequence > xValues( xCategories->getValues() );
2444 0 : if( xValues.is() )
2445 : {
2446 0 : Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
2447 0 : maCategoriesRange = xValues->getSourceRangeRepresentation();
2448 0 : aCategoriesRange = lcl_ConvertRange( maCategoriesRange, xNewDoc );
2449 0 : }
2450 0 : }
2451 : }
2452 0 : exportAxis( XML_X, XML_PRIMARY_X, xAxisProps, xNewAxis, aCategoriesRange, bHasXAxisTitle, bHasXAxisMajorGrid, bHasXAxisMinorGrid, bExportContent );
2453 0 : aCategoriesRange = "";
2454 : }
2455 :
2456 : // secondary x axis
2457 :
2458 0 : Reference< chart::XSecondAxisTitleSupplier > xSecondTitleSupp( xDiagram, uno::UNO_QUERY );
2459 0 : xNewAxis = lcl_getAxis( xCooSys, XML_X, false );
2460 0 : if( xNewAxis.is() )
2461 : {
2462 0 : Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getSecondaryAxis(0) : 0, uno::UNO_QUERY );
2463 0 : exportAxis( XML_X, XML_SECONDARY_X, xAxisProps, xNewAxis, aCategoriesRange, bHasSecondaryXAxisTitle, false, false, bExportContent );
2464 : }
2465 :
2466 : // y axis
2467 :
2468 0 : xNewAxis = lcl_getAxis( xCooSys, XML_Y );
2469 0 : if( xNewAxis.is() )
2470 : {
2471 0 : Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getAxis(1) : 0, uno::UNO_QUERY );
2472 0 : exportAxis( XML_Y, XML_PRIMARY_Y, xAxisProps, xNewAxis, aCategoriesRange, bHasYAxisTitle, bHasYAxisMajorGrid, bHasYAxisMinorGrid, bExportContent );
2473 : }
2474 :
2475 : // secondary y axis
2476 :
2477 0 : xNewAxis = lcl_getAxis( xCooSys, XML_Y, false );
2478 0 : if( xNewAxis.is() )
2479 : {
2480 0 : Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getSecondaryAxis(1) : 0, uno::UNO_QUERY );
2481 0 : exportAxis( XML_Y, XML_SECONDARY_Y, xAxisProps, xNewAxis, aCategoriesRange, bHasSecondaryYAxisTitle, false, false, bExportContent );
2482 : }
2483 :
2484 : // z axis
2485 :
2486 0 : xNewAxis = lcl_getAxis( xCooSys, XML_Z );
2487 0 : if( xNewAxis.is() )
2488 : {
2489 0 : Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getAxis(2) : 0, uno::UNO_QUERY );
2490 0 : exportAxis( XML_Z, XML_PRIMARY_Z, xAxisProps, xNewAxis, aCategoriesRange, bHasZAxisTitle, bHasZAxisMajorGrid, bHasZAxisMinorGrid, bExportContent );
2491 0 : }
2492 : }
2493 :
2494 : namespace
2495 : {
2496 0 : bool lcl_hasNoValuesButText( const uno::Reference< chart2::data::XDataSequence >& xDataSequence )
2497 : {
2498 0 : if( !xDataSequence.is() )
2499 0 : return false;//have no data
2500 :
2501 0 : Sequence< uno::Any > aData;
2502 0 : Reference< chart2::data::XNumericalDataSequence > xNumericalDataSequence( xDataSequence, uno::UNO_QUERY );
2503 0 : if( xNumericalDataSequence.is() )
2504 : {
2505 0 : Sequence< double > aDoubles( xNumericalDataSequence->getNumericalData() );
2506 0 : sal_Int32 nCount = aDoubles.getLength();
2507 0 : for( sal_Int32 i = 0; i < nCount; ++i )
2508 : {
2509 0 : if( !::rtl::math::isNan( aDoubles[i] ) )
2510 0 : return false;//have double value
2511 0 : }
2512 : }
2513 : else
2514 : {
2515 0 : aData = xDataSequence->getData();
2516 0 : double fDouble = 0.0;
2517 0 : sal_Int32 nCount = aData.getLength();
2518 0 : for( sal_Int32 i = 0; i < nCount; ++i )
2519 : {
2520 0 : if( (aData[i] >>= fDouble) && !::rtl::math::isNan( fDouble ) )
2521 0 : return false;//have double value
2522 : }
2523 :
2524 : }
2525 : //no values found
2526 :
2527 0 : Reference< chart2::data::XTextualDataSequence > xTextualDataSequence( xDataSequence, uno::UNO_QUERY );
2528 0 : if( xTextualDataSequence.is() )
2529 : {
2530 0 : uno::Sequence< OUString > aStrings( xTextualDataSequence->getTextualData() );
2531 0 : sal_Int32 nCount = aStrings.getLength();
2532 0 : for( sal_Int32 i = 0; i < nCount; ++i )
2533 : {
2534 0 : if( !aStrings[i].isEmpty() )
2535 0 : return true;//have text
2536 0 : }
2537 : }
2538 : else
2539 : {
2540 0 : if( !aData.getLength() )
2541 0 : aData = xDataSequence->getData();
2542 0 : OUString aString;
2543 0 : sal_Int32 nCount = aData.getLength();
2544 0 : for( sal_Int32 i = 0; i < nCount; ++i )
2545 : {
2546 0 : if( (aData[i]>>=aString) && !aString.isEmpty() )
2547 0 : return true;//have text
2548 0 : }
2549 : }
2550 : //no doubles and no texts
2551 0 : return false;
2552 : }
2553 :
2554 0 : bool isString(const OUString& rString)
2555 : {
2556 0 : if(rString.startsWith("\"") && rString.endsWith("\""))
2557 0 : return true;
2558 :
2559 0 : return false;
2560 : }
2561 : }
2562 :
2563 0 : void SchXMLExportHelper_Impl::exportSeries(
2564 : const Reference< chart2::XDiagram > & xNewDiagram,
2565 : const awt::Size & rPageSize,
2566 : sal_Bool bExportContent,
2567 : sal_Bool bHasTwoYAxes )
2568 : {
2569 0 : Reference< chart2::XCoordinateSystemContainer > xBCooSysCnt( xNewDiagram, uno::UNO_QUERY );
2570 0 : if( ! xBCooSysCnt.is())
2571 0 : return;
2572 0 : Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
2573 :
2574 0 : OUString aFirstXDomainRange;
2575 0 : OUString aFirstYDomainRange;
2576 0 : bool modifyLabelRange = false;
2577 :
2578 0 : std::vector< XMLPropertyState > aPropertyStates;
2579 :
2580 0 : const OUString sNumFormat("NumberFormat");
2581 0 : const OUString sPercentageNumFormat( "PercentageNumberFormat");
2582 :
2583 : Sequence< Reference< chart2::XCoordinateSystem > >
2584 0 : aCooSysSeq( xBCooSysCnt->getCoordinateSystems());
2585 0 : for( sal_Int32 nCSIdx=0; nCSIdx<aCooSysSeq.getLength(); ++nCSIdx )
2586 : {
2587 0 : Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nCSIdx], uno::UNO_QUERY );
2588 0 : if( ! xCTCnt.is())
2589 0 : continue;
2590 0 : Sequence< Reference< chart2::XChartType > > aCTSeq( xCTCnt->getChartTypes());
2591 0 : for( sal_Int32 nCTIdx=0; nCTIdx<aCTSeq.getLength(); ++nCTIdx )
2592 : {
2593 0 : Reference< chart2::XDataSeriesContainer > xDSCnt( aCTSeq[nCTIdx], uno::UNO_QUERY );
2594 0 : if( ! xDSCnt.is())
2595 0 : continue;
2596 : // note: if xDSCnt.is() then also aCTSeq[nCTIdx]
2597 0 : OUString aChartType( aCTSeq[nCTIdx]->getChartType());
2598 0 : OUString aLabelRole = aCTSeq[nCTIdx]->getRoleOfSequenceForSeriesLabel();
2599 :
2600 : // special export for stock charts
2601 0 : if ( aChartType == "com.sun.star.chart2.CandleStickChartType" )
2602 : {
2603 0 : sal_Bool bJapaneseCandleSticks = sal_False;
2604 0 : Reference< beans::XPropertySet > xCTProp( aCTSeq[nCTIdx], uno::UNO_QUERY );
2605 0 : if( xCTProp.is())
2606 0 : xCTProp->getPropertyValue("Japanese") >>= bJapaneseCandleSticks;
2607 : exportCandleStickSeries(
2608 0 : xDSCnt->getDataSeries(), xNewDiagram, bJapaneseCandleSticks, bExportContent );
2609 0 : continue;
2610 : }
2611 :
2612 : // export dataseries for current chart-type
2613 0 : Sequence< Reference< chart2::XDataSeries > > aSeriesSeq( xDSCnt->getDataSeries());
2614 0 : for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeriesSeq.getLength(); ++nSeriesIdx )
2615 : {
2616 : // export series
2617 0 : Reference< chart2::data::XDataSource > xSource( aSeriesSeq[nSeriesIdx], uno::UNO_QUERY );
2618 0 : if( xSource.is())
2619 : {
2620 0 : SvXMLElementExport* pSeries = NULL;
2621 : Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeqCnt(
2622 0 : xSource->getDataSequences());
2623 0 : sal_Int32 nMainSequenceIndex = -1;
2624 0 : sal_Int32 nSeriesLength = 0;
2625 0 : sal_Int32 nAttachedAxis = chart::ChartAxisAssign::PRIMARY_Y;
2626 0 : sal_Bool bHasMeanValueLine = false;
2627 0 : Reference< beans::XPropertySet > xPropSet;
2628 0 : tLabelValuesDataPair aSeriesLabelValuesPair;
2629 :
2630 : // search for main sequence and create a series element
2631 : {
2632 0 : Reference< chart2::data::XDataSequence > xValuesSeq;
2633 0 : Reference< chart2::data::XDataSequence > xLabelSeq;
2634 0 : sal_Int32 nSeqIdx=0;
2635 0 : for( ; nSeqIdx<aSeqCnt.getLength(); ++nSeqIdx )
2636 : {
2637 0 : OUString aRole;
2638 0 : Reference< chart2::data::XDataSequence > xTempValueSeq( aSeqCnt[nSeqIdx]->getValues() );
2639 0 : if( nMainSequenceIndex==-1 )
2640 : {
2641 0 : Reference< beans::XPropertySet > xSeqProp( xTempValueSeq, uno::UNO_QUERY );
2642 0 : if( xSeqProp.is())
2643 0 : xSeqProp->getPropertyValue("Role") >>= aRole;
2644 : // "main" sequence
2645 0 : if( aRole.equals( aLabelRole ))
2646 : {
2647 0 : xValuesSeq.set( xTempValueSeq );
2648 0 : xLabelSeq.set( aSeqCnt[nSeqIdx]->getLabel());
2649 0 : nMainSequenceIndex = nSeqIdx;
2650 0 : }
2651 : }
2652 0 : sal_Int32 nSequenceLength = (xTempValueSeq.is()? xTempValueSeq->getData().getLength() : sal_Int32(0));
2653 0 : if( nSeriesLength < nSequenceLength )
2654 0 : nSeriesLength = nSequenceLength;
2655 0 : }
2656 :
2657 : // have found the main sequence, then xValuesSeq and
2658 : // xLabelSeq contain those. Otherwise both are empty
2659 : {
2660 : // get property states for autostyles
2661 : try
2662 : {
2663 0 : xPropSet = SchXMLSeriesHelper::createOldAPISeriesPropertySet(
2664 0 : aSeriesSeq[nSeriesIdx], mrExport.GetModel() );
2665 : }
2666 0 : catch( const uno::Exception & rEx )
2667 : {
2668 : SAL_INFO("xmloff.chart", "Series not found or no XPropertySet: " << rEx.Message );
2669 0 : continue;
2670 : }
2671 0 : if( xPropSet.is())
2672 : {
2673 : // determine attached axis
2674 : try
2675 : {
2676 0 : Any aAny( xPropSet->getPropertyValue(
2677 0 : OUString( "Axis" )));
2678 0 : aAny >>= nAttachedAxis;
2679 :
2680 0 : aAny = xPropSet->getPropertyValue(
2681 0 : OUString( "MeanValue" ));
2682 0 : aAny >>= bHasMeanValueLine;
2683 : }
2684 0 : catch( const beans::UnknownPropertyException & rEx )
2685 : {
2686 : SAL_INFO("xmloff.chart", "Required property not found in DataRowProperties: " << rEx.Message );
2687 : }
2688 :
2689 0 : const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
2690 0 : if( nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 )
2691 : {
2692 0 : lcl_exportNumberFormat( sNumFormat, xPropSet, mrExport );
2693 0 : lcl_exportNumberFormat( sPercentageNumFormat, xPropSet, mrExport );
2694 : }
2695 :
2696 0 : if( mxExpPropMapper.is())
2697 0 : aPropertyStates = mxExpPropMapper->Filter( xPropSet );
2698 : }
2699 :
2700 0 : if( bExportContent )
2701 : {
2702 0 : if( bHasTwoYAxes )
2703 : {
2704 0 : if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
2705 0 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y );
2706 : else
2707 0 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y );
2708 : }
2709 :
2710 : // write style name
2711 0 : AddAutoStyleAttribute( aPropertyStates );
2712 :
2713 0 : if( xValuesSeq.is())
2714 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS,
2715 : lcl_ConvertRange(
2716 0 : xValuesSeq->getSourceRangeRepresentation(),
2717 0 : xNewDoc ));
2718 : else
2719 : // #i75297# allow empty series, export empty range to have all ranges on import
2720 0 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, OUString());
2721 :
2722 0 : if( xLabelSeq.is()) {
2723 0 : OUString aRange = xLabelSeq->getSourceRangeRepresentation();
2724 0 : if ( nSeriesIdx == 0 && aRange.equalsAscii("label 1"))
2725 0 : modifyLabelRange = true;
2726 0 : if (modifyLabelRange)
2727 0 : aRange = "label " + OUString::number(aRange.copy( OUString("label").getLength()).toInt32() - 1);
2728 :
2729 0 : OUString aXMLRange = lcl_ConvertRange( aRange, xNewDoc );
2730 0 : if(aXMLRange.isEmpty() && !aRange.isEmpty())
2731 : {
2732 : // might just be a string
2733 0 : bool bIsString = isString(aRange);
2734 0 : if(bIsString)
2735 : {
2736 : mrExport.AddAttribute( XML_NAMESPACE_LO_EXT,
2737 0 : XML_LABEL_STRING, aRange );
2738 : }
2739 : }
2740 : else
2741 : mrExport.AddAttribute( XML_NAMESPACE_CHART,
2742 0 : XML_LABEL_CELL_ADDRESS, aXMLRange );
2743 : }
2744 0 : if( xLabelSeq.is() || xValuesSeq.is() )
2745 0 : aSeriesLabelValuesPair = tLabelValuesDataPair( xLabelSeq, xValuesSeq );
2746 :
2747 : // chart-type for mixed types
2748 : enum XMLTokenEnum eCTToken(
2749 0 : SchXMLTools::getTokenByChartType( aChartType, false /* bUseOldNames */ ));
2750 : //@todo: get token for current charttype
2751 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_CLASS,
2752 0 : mrExport.GetNamespaceMap().GetQNameByKey(
2753 0 : XML_NAMESPACE_CHART, GetXMLToken( eCTToken )));
2754 :
2755 : // open series element until end of for loop
2756 0 : pSeries = new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_SERIES, true, true );
2757 : }
2758 : else // autostyles
2759 : {
2760 0 : CollectAutoStyle( aPropertyStates );
2761 : }
2762 : // remove property states for autostyles
2763 0 : aPropertyStates.clear();
2764 0 : }
2765 : }
2766 :
2767 : // export domain elements if we have a series parent element
2768 0 : if( pSeries )
2769 : {
2770 : // domain elements
2771 0 : if( bExportContent )
2772 : {
2773 0 : bool bIsScatterChart = aChartType == "com.sun.star.chart2.ScatterChartType";
2774 0 : bool bIsBubbleChart = aChartType == "com.sun.star.chart2.BubbleChartType";
2775 0 : Reference< chart2::data::XDataSequence > xYValuesForBubbleChart;
2776 0 : if( bIsBubbleChart )
2777 : {
2778 0 : Reference< chart2::data::XLabeledDataSequence > xSequence( lcl_getDataSequenceByRole( aSeqCnt, OUString( "values-y" ) ) );
2779 0 : if( xSequence.is() )
2780 : {
2781 0 : xYValuesForBubbleChart = xSequence->getValues();
2782 0 : if( !lcl_exportDomainForThisSequence( xYValuesForBubbleChart, aFirstYDomainRange, mrExport ) )
2783 0 : xYValuesForBubbleChart = 0;
2784 0 : }
2785 : }
2786 0 : if( bIsScatterChart || bIsBubbleChart )
2787 : {
2788 0 : Reference< chart2::data::XLabeledDataSequence > xSequence( lcl_getDataSequenceByRole( aSeqCnt, OUString( "values-x" ) ) );
2789 0 : if( xSequence.is() )
2790 : {
2791 0 : Reference< chart2::data::XDataSequence > xValues( xSequence->getValues() );
2792 0 : if( lcl_exportDomainForThisSequence( xValues, aFirstXDomainRange, mrExport ) )
2793 : m_aDataSequencesToExport.push_back( tLabelValuesDataPair(
2794 0 : (uno::Reference< chart2::data::XDataSequence >)0, xValues ));
2795 : }
2796 0 : else if( nSeriesIdx==0 )
2797 : {
2798 : //might be that the categories are used as x-values (e.g. for date axis) -> export them accordingly
2799 0 : Reference< chart2::data::XLabeledDataSequence > xCategories( lcl_getCategories( xNewDiagram ) );
2800 0 : if( xCategories.is() )
2801 : {
2802 0 : Reference< chart2::data::XDataSequence > xValues( xCategories->getValues() );
2803 0 : if( !lcl_hasNoValuesButText( xValues ) )
2804 0 : lcl_exportDomainForThisSequence( xValues, aFirstXDomainRange, mrExport );
2805 0 : }
2806 0 : }
2807 : }
2808 0 : if( xYValuesForBubbleChart.is() )
2809 : m_aDataSequencesToExport.push_back( tLabelValuesDataPair(
2810 0 : (uno::Reference< chart2::data::XDataSequence >)0, xYValuesForBubbleChart ));
2811 : }
2812 : }
2813 :
2814 : // add sequences for main sequence after domain sequences,
2815 : // so that the export of the local table has the correct order
2816 0 : if( bExportContent &&
2817 0 : (aSeriesLabelValuesPair.first.is() || aSeriesLabelValuesPair.second.is()))
2818 0 : m_aDataSequencesToExport.push_back( aSeriesLabelValuesPair );
2819 :
2820 : // statistical objects:
2821 : // regression curves and mean value lines
2822 0 : if( bHasMeanValueLine &&
2823 0 : xPropSet.is() &&
2824 0 : mxExpPropMapper.is() )
2825 : {
2826 0 : Reference< beans::XPropertySet > xStatProp;
2827 : try
2828 : {
2829 0 : Any aPropAny( xPropSet->getPropertyValue(
2830 0 : OUString( "DataMeanValueProperties" )));
2831 0 : aPropAny >>= xStatProp;
2832 : }
2833 0 : catch( const uno::Exception & rEx )
2834 : {
2835 : SAL_INFO("xmloff.chart", "Exception caught during Export of series - optional DataMeanValueProperties not available: " << rEx.Message );
2836 : }
2837 :
2838 0 : if( xStatProp.is() )
2839 : {
2840 0 : aPropertyStates = mxExpPropMapper->Filter( xStatProp );
2841 :
2842 0 : if( !aPropertyStates.empty() )
2843 : {
2844 : // write element
2845 0 : if( bExportContent )
2846 : {
2847 : // add style name attribute
2848 0 : AddAutoStyleAttribute( aPropertyStates );
2849 :
2850 0 : SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_MEAN_VALUE, true, true );
2851 : }
2852 : else // autostyles
2853 : {
2854 0 : CollectAutoStyle( aPropertyStates );
2855 : }
2856 : }
2857 0 : }
2858 : }
2859 :
2860 0 : if( xPropSet.is() &&
2861 0 : mxExpPropMapper.is() )
2862 : {
2863 0 : exportRegressionCurve( aSeriesSeq[nSeriesIdx], rPageSize, bExportContent );
2864 : }
2865 :
2866 0 : exportErrorBar( xPropSet,false, bExportContent ); // X ErrorBar
2867 0 : exportErrorBar( xPropSet,true, bExportContent ); // Y ErrorBar
2868 :
2869 : exportDataPoints(
2870 0 : uno::Reference< beans::XPropertySet >( aSeriesSeq[nSeriesIdx], uno::UNO_QUERY ),
2871 0 : nSeriesLength, xNewDiagram, bExportContent );
2872 :
2873 0 : const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
2874 0 : if( bExportContent && nCurrentODFVersion > SvtSaveOptions::ODFVER_012 )//do not export to ODF 1.2 or older
2875 : {
2876 0 : Sequence< OUString > aSupportedMappings = aCTSeq[nCTIdx]->getSupportedPropertyRoles();
2877 0 : exportPropertyMapping( xSource, aSupportedMappings );
2878 : }
2879 :
2880 : // close series element
2881 0 : delete pSeries;
2882 : }
2883 0 : }
2884 0 : aPropertyStates.clear();
2885 0 : }
2886 0 : }
2887 : }
2888 :
2889 0 : void SchXMLExportHelper_Impl::exportPropertyMapping(
2890 : const Reference< chart2::data::XDataSource > & xSource, Sequence< OUString >& rSupportedMappings )
2891 : {
2892 0 : Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
2893 : Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeqCnt(
2894 0 : xSource->getDataSequences());
2895 :
2896 0 : for(sal_Int32 i = 0, n = rSupportedMappings.getLength(); i < n; ++i)
2897 : {
2898 0 : Reference< chart2::data::XLabeledDataSequence > xSequence( lcl_getDataSequenceByRole( aSeqCnt, rSupportedMappings[i] ) );
2899 0 : if(xSequence.is())
2900 : {
2901 0 : Reference< chart2::data::XDataSequence > xValues( xSequence->getValues() );
2902 0 : if( xValues.is())
2903 : {
2904 0 : mrExport.AddAttribute( XML_NAMESPACE_LO_EXT, XML_PROPERTY, rSupportedMappings[i]);
2905 : mrExport.AddAttribute( XML_NAMESPACE_LO_EXT, XML_CELL_RANGE_ADDRESS,
2906 : lcl_ConvertRange(
2907 0 : xValues->getSourceRangeRepresentation(),
2908 0 : xNewDoc ));
2909 0 : SvXMLElementExport( mrExport, XML_NAMESPACE_LO_EXT, XML_PROPERTY_MAPPING, true, true );
2910 :
2911 : // register range for data table export
2912 : m_aDataSequencesToExport.push_back( tLabelValuesDataPair(
2913 0 : (uno::Reference< chart2::data::XDataSequence >)0, xValues ));
2914 0 : }
2915 : }
2916 0 : }
2917 0 : }
2918 :
2919 0 : void SchXMLExportHelper_Impl::exportRegressionCurve(
2920 : const Reference< chart2::XDataSeries >& xSeries,
2921 : const awt::Size& rPageSize,
2922 : sal_Bool bExportContent )
2923 : {
2924 : OSL_ASSERT( mxExpPropMapper.is());
2925 :
2926 0 : std::vector< XMLPropertyState > aPropertyStates;
2927 0 : std::vector< XMLPropertyState > aEquationPropertyStates;
2928 :
2929 0 : Reference< chart2::XRegressionCurveContainer > xRegressionCurveContainer( xSeries, uno::UNO_QUERY );
2930 0 : if( xRegressionCurveContainer.is() )
2931 : {
2932 0 : Sequence< Reference< chart2::XRegressionCurve > > aRegCurveSeq = xRegressionCurveContainer->getRegressionCurves();
2933 :
2934 0 : const Reference< chart2::XRegressionCurve >* pBeg = aRegCurveSeq.getConstArray();
2935 0 : const Reference< chart2::XRegressionCurve >* pEnd = pBeg + aRegCurveSeq.getLength();
2936 : const Reference< chart2::XRegressionCurve >* pIt;
2937 :
2938 0 : for( pIt = pBeg; pIt != pEnd; pIt++ )
2939 : {
2940 0 : Reference< chart2::XRegressionCurve > xRegCurve = *pIt;
2941 0 : if (!xRegCurve.is())
2942 0 : continue;
2943 :
2944 0 : Reference< beans::XPropertySet > xProperties( xRegCurve , uno::UNO_QUERY );
2945 0 : if( !xProperties.is() )
2946 0 : continue;
2947 :
2948 0 : Reference< lang::XServiceName > xServiceName( xProperties, uno::UNO_QUERY );
2949 0 : if( !xServiceName.is() )
2950 0 : continue;
2951 :
2952 0 : bool bShowEquation = false;
2953 0 : bool bShowRSquared = false;
2954 0 : bool bExportEquation = false;
2955 :
2956 0 : OUString aService;
2957 0 : aService = xServiceName->getServiceName();
2958 :
2959 0 : aPropertyStates = mxExpPropMapper->Filter( xProperties );
2960 :
2961 : // Add service name (which is regression type)
2962 0 : sal_Int32 nIndex = GetPropertySetMapper()->FindEntryIndex(XML_SCH_CONTEXT_SPECIAL_REGRESSION_TYPE);
2963 0 : XMLPropertyState property(nIndex, uno::makeAny(aService));
2964 0 : aPropertyStates.push_back(property);
2965 :
2966 0 : Reference< beans::XPropertySet > xEquationProperties;
2967 0 : xEquationProperties.set( xRegCurve->getEquationProperties() );
2968 0 : if( xEquationProperties.is())
2969 : {
2970 0 : xEquationProperties->getPropertyValue( OUString("ShowEquation")) >>= bShowEquation;
2971 0 : xEquationProperties->getPropertyValue( OUString("ShowCorrelationCoefficient")) >>= bShowRSquared;
2972 :
2973 0 : bExportEquation = ( bShowEquation || bShowRSquared );
2974 0 : const SvtSaveOptions::ODFDefaultVersion nCurrentVersion( SvtSaveOptions().GetODFDefaultVersion() );
2975 0 : if( nCurrentVersion < SvtSaveOptions::ODFVER_012 )
2976 : {
2977 0 : bExportEquation=false;
2978 : }
2979 0 : if( bExportEquation )
2980 : {
2981 : // number format
2982 0 : sal_Int32 nNumberFormat = 0;
2983 0 : if( (xEquationProperties->getPropertyValue(OUString("NumberFormat")) >>= nNumberFormat ) &&
2984 0 : nNumberFormat != -1 )
2985 : {
2986 0 : mrExport.addDataStyle( nNumberFormat );
2987 : }
2988 0 : aEquationPropertyStates = mxExpPropMapper->Filter( xEquationProperties );
2989 : }
2990 : }
2991 :
2992 0 : if( !aPropertyStates.empty() || bExportEquation )
2993 : {
2994 : // write element
2995 0 : if( bExportContent )
2996 : {
2997 : // add style name attribute
2998 0 : if( !aPropertyStates.empty())
2999 : {
3000 0 : AddAutoStyleAttribute( aPropertyStates );
3001 : }
3002 :
3003 0 : SvXMLElementExport aRegressionExport( mrExport, XML_NAMESPACE_CHART, XML_REGRESSION_CURVE, true, true );
3004 0 : if( bExportEquation )
3005 : {
3006 0 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_DISPLAY_EQUATION, (bShowEquation ? XML_TRUE : XML_FALSE) );
3007 0 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_DISPLAY_R_SQUARE, (bShowRSquared ? XML_TRUE : XML_FALSE) );
3008 :
3009 : // export position
3010 0 : chart2::RelativePosition aRelativePosition;
3011 0 : if( xEquationProperties->getPropertyValue(OUString( "RelativePosition")) >>= aRelativePosition )
3012 : {
3013 0 : double fX = aRelativePosition.Primary * rPageSize.Width;
3014 0 : double fY = aRelativePosition.Secondary * rPageSize.Height;
3015 0 : awt::Point aPos;
3016 0 : aPos.X = static_cast< sal_Int32 >( ::rtl::math::round( fX ));
3017 0 : aPos.Y = static_cast< sal_Int32 >( ::rtl::math::round( fY ));
3018 0 : addPosition( aPos );
3019 : }
3020 :
3021 0 : if( !aEquationPropertyStates.empty())
3022 : {
3023 0 : AddAutoStyleAttribute( aEquationPropertyStates );
3024 : }
3025 :
3026 0 : SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_EQUATION, true, true );
3027 0 : }
3028 : }
3029 : else // autostyles
3030 : {
3031 0 : if( !aPropertyStates.empty())
3032 : {
3033 0 : CollectAutoStyle( aPropertyStates );
3034 : }
3035 0 : if( bExportEquation && !aEquationPropertyStates.empty())
3036 : {
3037 0 : CollectAutoStyle( aEquationPropertyStates );
3038 : }
3039 : }
3040 : }
3041 0 : }
3042 0 : }
3043 0 : }
3044 :
3045 0 : void SchXMLExportHelper_Impl::exportErrorBar( const Reference<beans::XPropertySet> &xSeriesProp,
3046 : bool bYError, bool bExportContent )
3047 : {
3048 : assert(mxExpPropMapper.is());
3049 :
3050 0 : const SvtSaveOptions::ODFDefaultVersion nCurrentVersion( SvtSaveOptions().GetODFDefaultVersion() );
3051 :
3052 : /// Dont export X ErrorBars for older ODF versions.
3053 0 : if ( !bYError && nCurrentVersion < SvtSaveOptions::ODFVER_012 )
3054 0 : return;
3055 :
3056 0 : if (xSeriesProp.is())
3057 : {
3058 0 : bool bNegative = false, bPositive = false;
3059 0 : sal_Int32 nErrorBarStyle = chart::ErrorBarStyle::NONE;
3060 0 : Reference< beans::XPropertySet > xErrorBarProp;
3061 :
3062 : try
3063 : {
3064 0 : Any aAny;
3065 :
3066 0 : aAny = xSeriesProp->getPropertyValue( bYError ? OUString("ErrorBarY") : OUString("ErrorBarX") );
3067 0 : aAny >>= xErrorBarProp;
3068 :
3069 0 : if ( xErrorBarProp.is() )
3070 : {
3071 0 : aAny = xErrorBarProp->getPropertyValue("ShowNegativeError" );
3072 0 : aAny >>= bNegative;
3073 :
3074 0 : aAny = xErrorBarProp->getPropertyValue("ShowPositiveError" );
3075 0 : aAny >>= bPositive;
3076 :
3077 0 : aAny = xErrorBarProp->getPropertyValue("ErrorBarStyle" );
3078 0 : aAny >>= nErrorBarStyle;
3079 0 : }
3080 : }
3081 0 : catch( const beans::UnknownPropertyException & rEx )
3082 : {
3083 : SAL_INFO("xmloff.chart", "Required property not found in DataRowProperties: " << rEx.Message );
3084 : }
3085 :
3086 0 : if( nErrorBarStyle != chart::ErrorBarStyle::NONE && (bNegative || bPositive))
3087 : {
3088 0 : if( bExportContent && nErrorBarStyle == chart::ErrorBarStyle::FROM_DATA )
3089 : {
3090 0 : uno::Reference< chart2::XChartDocument > xNewDoc(mrExport.GetModel(), uno::UNO_QUERY);
3091 :
3092 : // register data ranges for error bars for export in local table
3093 : ::std::vector< Reference< chart2::data::XDataSequence > > aErrorBarSequences(
3094 0 : lcl_getErrorBarSequences( xErrorBarProp ));
3095 0 : for( ::std::vector< Reference< chart2::data::XDataSequence > >::const_iterator aIt(
3096 0 : aErrorBarSequences.begin()); aIt != aErrorBarSequences.end(); ++aIt )
3097 : {
3098 : m_aDataSequencesToExport.push_back( tLabelValuesDataPair(
3099 0 : (uno::Reference< chart2::data::XDataSequence >)0, *aIt ));
3100 0 : }
3101 : }
3102 :
3103 0 : std::vector< XMLPropertyState > aPropertyStates = mxExpPropMapper->Filter( xErrorBarProp );
3104 :
3105 0 : if( !aPropertyStates.empty() )
3106 : {
3107 : // write element
3108 0 : if( bExportContent )
3109 : {
3110 : // add style name attribute
3111 0 : AddAutoStyleAttribute( aPropertyStates );
3112 :
3113 0 : if( nCurrentVersion >= SvtSaveOptions::ODFVER_012 )
3114 0 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_DIMENSION, bYError ? XML_Y : XML_X );//#i114149#
3115 0 : SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_ERROR_INDICATOR, true, true );
3116 : }
3117 : else // autostyles
3118 : {
3119 0 : CollectAutoStyle( aPropertyStates );
3120 : }
3121 0 : }
3122 0 : }
3123 : }
3124 : }
3125 :
3126 0 : void SchXMLExportHelper_Impl::exportCandleStickSeries(
3127 : const Sequence< Reference< chart2::XDataSeries > > & aSeriesSeq,
3128 : const Reference< chart2::XDiagram > & xDiagram,
3129 : sal_Bool bJapaneseCandleSticks,
3130 : sal_Bool bExportContent )
3131 : {
3132 :
3133 0 : for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeriesSeq.getLength(); ++nSeriesIdx )
3134 : {
3135 0 : Reference< chart2::XDataSeries > xSeries( aSeriesSeq[nSeriesIdx] );
3136 0 : sal_Int32 nAttachedAxis = lcl_isSeriesAttachedToFirstAxis( xSeries )
3137 : ? chart::ChartAxisAssign::PRIMARY_Y
3138 0 : : chart::ChartAxisAssign::SECONDARY_Y;
3139 :
3140 0 : Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY );
3141 0 : if( xSource.is())
3142 : {
3143 : // export series in correct order (as we don't store roles)
3144 : // with japanese candlesticks: open, low, high, close
3145 : // otherwise: low, high, close
3146 : Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeqCnt(
3147 0 : xSource->getDataSequences());
3148 :
3149 : sal_Int32 nSeriesLength =
3150 0 : lcl_getSequenceLengthByRole( aSeqCnt, OUString( "values-last" ));
3151 :
3152 0 : if( bExportContent )
3153 : {
3154 0 : Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
3155 : //@todo: export data points
3156 :
3157 : //TODO: moggi: same code three times
3158 : // open
3159 0 : if( bJapaneseCandleSticks )
3160 : {
3161 : tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole(
3162 0 : aSeqCnt, OUString( "values-first" ), xNewDoc, m_aDataSequencesToExport ));
3163 0 : if( !aRanges.second.isEmpty())
3164 0 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, aRanges.second );
3165 0 : if( !aRanges.first.isEmpty())
3166 0 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS, aRanges.first );
3167 0 : if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
3168 0 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y );
3169 : else
3170 0 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y );
3171 0 : SvXMLElementExport aOpenSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, true, true );
3172 : // export empty data points
3173 0 : exportDataPoints( 0, nSeriesLength, xDiagram, bExportContent );
3174 : }
3175 :
3176 : // low
3177 : {
3178 : tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole(
3179 0 : aSeqCnt, OUString( "values-min" ), xNewDoc, m_aDataSequencesToExport ));
3180 0 : if( !aRanges.second.isEmpty())
3181 0 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, aRanges.second );
3182 0 : if( !aRanges.first.isEmpty())
3183 0 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS, aRanges.first );
3184 0 : if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
3185 0 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y );
3186 : else
3187 0 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y );
3188 0 : SvXMLElementExport aLowSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, true, true );
3189 : // export empty data points
3190 0 : exportDataPoints( 0, nSeriesLength, xDiagram, bExportContent );
3191 : }
3192 :
3193 : // high
3194 : {
3195 : tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole(
3196 0 : aSeqCnt, OUString( "values-max" ), xNewDoc, m_aDataSequencesToExport ));
3197 0 : if( !aRanges.second.isEmpty())
3198 0 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, aRanges.second );
3199 0 : if( !aRanges.first.isEmpty())
3200 0 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS, aRanges.first );
3201 0 : if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
3202 0 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y );
3203 : else
3204 0 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y );
3205 0 : SvXMLElementExport aHighSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, true, true );
3206 : // export empty data points
3207 0 : exportDataPoints( 0, nSeriesLength, xDiagram, bExportContent );
3208 : }
3209 :
3210 : // close
3211 : {
3212 : tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole(
3213 0 : aSeqCnt, OUString( "values-last" ), xNewDoc, m_aDataSequencesToExport ));
3214 0 : if( !aRanges.second.isEmpty())
3215 0 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, aRanges.second );
3216 0 : if( !aRanges.first.isEmpty())
3217 0 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS, aRanges.first );
3218 0 : if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
3219 0 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y );
3220 : else
3221 0 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y );
3222 0 : SvXMLElementExport aCloseSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, true, true );
3223 : // export empty data points
3224 0 : exportDataPoints( 0, nSeriesLength, xDiagram, bExportContent );
3225 0 : }
3226 : }
3227 : else // autostyles
3228 : {
3229 : // for close series
3230 0 : }
3231 : // remove property states for autostyles
3232 : }
3233 0 : }
3234 0 : }
3235 :
3236 0 : void SchXMLExportHelper_Impl::exportDataPoints(
3237 : const uno::Reference< beans::XPropertySet > & xSeriesProperties,
3238 : sal_Int32 nSeriesLength,
3239 : const uno::Reference< chart2::XDiagram > & xDiagram,
3240 : sal_Bool bExportContent )
3241 : {
3242 : // data-points
3243 :
3244 : // write data-points only if they contain autostyles
3245 : // objects with equal autostyles are grouped using the attribute
3246 : // repeat="number"
3247 :
3248 : // Note: if only the nth data-point has autostyles there is an element
3249 : // without style and repeat="n-1" attribute written in advance.
3250 :
3251 : // the sequence aDataPointSeq contains indices of data-points that
3252 : // do have own attributes. This increases the performance substantially.
3253 :
3254 : // more performant version for #93600#
3255 0 : if( mxExpPropMapper.is())
3256 : {
3257 0 : uno::Reference< chart2::XDataSeries > xSeries( xSeriesProperties, uno::UNO_QUERY );
3258 :
3259 0 : std::vector< XMLPropertyState > aPropertyStates;
3260 :
3261 0 : const OUString sNumFormat("NumberFormat");
3262 0 : const OUString sPercentageNumFormat( "PercentageNumberFormat");
3263 :
3264 0 : bool bVaryColorsByPoint = false;
3265 0 : Sequence< sal_Int32 > aDataPointSeq;
3266 0 : if( xSeriesProperties.is())
3267 : {
3268 0 : Any aAny = xSeriesProperties->getPropertyValue(
3269 0 : OUString( "AttributedDataPoints" ));
3270 0 : aAny >>= aDataPointSeq;
3271 0 : xSeriesProperties->getPropertyValue(
3272 0 : OUString( "VaryColorsByPoint" )) >>= bVaryColorsByPoint;
3273 : }
3274 :
3275 0 : sal_Int32 nSize = aDataPointSeq.getLength();
3276 : SAL_WARN_IF( nSize > nSeriesLength, "xmloff.chart", "Too many point attributes" );
3277 :
3278 0 : const sal_Int32 * pPoints = aDataPointSeq.getConstArray();
3279 : sal_Int32 nElement;
3280 : sal_Int32 nRepeat;
3281 0 : Reference< chart2::XColorScheme > xColorScheme;
3282 0 : if( xDiagram.is())
3283 0 : xColorScheme.set( xDiagram->getDefaultColorScheme());
3284 :
3285 0 : ::std::list< SchXMLDataPointStruct > aDataPointList;
3286 :
3287 0 : sal_Int32 nLastIndex = -1;
3288 0 : sal_Int32 nCurrIndex = 0;
3289 :
3290 : // collect elements
3291 0 : if( bVaryColorsByPoint && xColorScheme.is() )
3292 : {
3293 0 : ::std::set< sal_Int32 > aAttrPointSet;
3294 0 : ::std::copy( pPoints, pPoints + aDataPointSeq.getLength(),
3295 0 : ::std::inserter( aAttrPointSet, aAttrPointSet.begin()));
3296 0 : const ::std::set< sal_Int32 >::const_iterator aEndIt( aAttrPointSet.end());
3297 0 : for( nElement = 0; nElement < nSeriesLength; ++nElement )
3298 : {
3299 0 : aPropertyStates.clear();
3300 0 : uno::Reference< beans::XPropertySet > xPropSet;
3301 0 : bool bExportNumFmt = false;
3302 0 : if( aAttrPointSet.find( nElement ) != aEndIt )
3303 : {
3304 : try
3305 : {
3306 0 : xPropSet = SchXMLSeriesHelper::createOldAPIDataPointPropertySet(
3307 0 : xSeries, nElement, mrExport.GetModel() );
3308 0 : bExportNumFmt = true;
3309 : }
3310 0 : catch( const uno::Exception & rEx )
3311 : {
3312 : SAL_INFO("xmloff.chart", "Exception caught during Export of data point: " << rEx.Message );
3313 : }
3314 : }
3315 : else
3316 : {
3317 : // property set only containing the color
3318 : xPropSet.set( new ::xmloff::chart::ColorPropertySet(
3319 0 : xColorScheme->getColorByIndex( nElement )));
3320 : }
3321 : SAL_WARN_IF( !xPropSet.is(), "xmloff.chart", "Pie Segments should have properties" );
3322 0 : if( xPropSet.is())
3323 : {
3324 0 : const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
3325 0 : if( nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 && bExportNumFmt )
3326 : {
3327 0 : lcl_exportNumberFormat( sNumFormat, xPropSet, mrExport );
3328 0 : lcl_exportNumberFormat( sPercentageNumFormat, xPropSet, mrExport );
3329 : }
3330 :
3331 0 : aPropertyStates = mxExpPropMapper->Filter( xPropSet );
3332 0 : if( !aPropertyStates.empty() )
3333 : {
3334 0 : if( bExportContent )
3335 : {
3336 : // write data-point with style
3337 : SAL_WARN_IF( maAutoStyleNameQueue.empty(), "xmloff.chart", "Autostyle queue empty!" );
3338 :
3339 0 : SchXMLDataPointStruct aPoint;
3340 0 : aPoint.maStyleName = maAutoStyleNameQueue.front();
3341 0 : maAutoStyleNameQueue.pop();
3342 0 : aDataPointList.push_back( aPoint );
3343 : }
3344 : else
3345 : {
3346 0 : CollectAutoStyle( aPropertyStates );
3347 : }
3348 : }
3349 : }
3350 0 : }
3351 0 : SAL_WARN_IF( bExportContent && (static_cast<sal_Int32>(aDataPointList.size()) != nSeriesLength), "xmloff.chart", "not enough data points on content export" );
3352 : }
3353 : else
3354 : {
3355 0 : for( nElement = 0; nElement < nSize; ++nElement )
3356 : {
3357 0 : aPropertyStates.clear();
3358 0 : nCurrIndex = pPoints[ nElement ];
3359 : //assuming sorted indices in pPoints
3360 :
3361 0 : if( nCurrIndex<0 || nCurrIndex>=nSeriesLength )
3362 : break;
3363 :
3364 : // write leading empty data points
3365 0 : if( nCurrIndex - nLastIndex > 1 )
3366 : {
3367 0 : SchXMLDataPointStruct aPoint;
3368 0 : aPoint.mnRepeat = nCurrIndex - nLastIndex - 1;
3369 0 : aDataPointList.push_back( aPoint );
3370 : }
3371 :
3372 0 : uno::Reference< beans::XPropertySet > xPropSet;
3373 : // get property states
3374 : try
3375 : {
3376 0 : xPropSet = SchXMLSeriesHelper::createOldAPIDataPointPropertySet(
3377 0 : xSeries, nCurrIndex, mrExport.GetModel() );
3378 : }
3379 0 : catch( const uno::Exception & rEx )
3380 : {
3381 : SAL_INFO("xmloff.chart", "Exception caught during Export of data point: " << rEx.Message );
3382 : }
3383 0 : if( xPropSet.is())
3384 : {
3385 0 : const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
3386 0 : if( nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 )
3387 : {
3388 0 : lcl_exportNumberFormat( sNumFormat, xPropSet, mrExport );
3389 0 : lcl_exportNumberFormat( sPercentageNumFormat, xPropSet, mrExport );
3390 : }
3391 :
3392 0 : aPropertyStates = mxExpPropMapper->Filter( xPropSet );
3393 0 : if( !aPropertyStates.empty() )
3394 : {
3395 0 : if( bExportContent )
3396 : {
3397 : // write data-point with style
3398 : SAL_WARN_IF( maAutoStyleNameQueue.empty(), "xmloff.chart", "Autostyle queue empty!" );
3399 0 : SchXMLDataPointStruct aPoint;
3400 0 : aPoint.maStyleName = maAutoStyleNameQueue.front();
3401 0 : maAutoStyleNameQueue.pop();
3402 :
3403 0 : aDataPointList.push_back( aPoint );
3404 0 : nLastIndex = nCurrIndex;
3405 : }
3406 : else
3407 : {
3408 0 : CollectAutoStyle( aPropertyStates );
3409 : }
3410 0 : continue;
3411 : }
3412 : }
3413 :
3414 : // if we get here the property states are empty
3415 0 : SchXMLDataPointStruct aPoint;
3416 0 : aDataPointList.push_back( aPoint );
3417 :
3418 0 : nLastIndex = nCurrIndex;
3419 0 : }
3420 : // final empty elements
3421 0 : nRepeat = nSeriesLength - nLastIndex - 1;
3422 0 : if( nRepeat > 0 )
3423 : {
3424 0 : SchXMLDataPointStruct aPoint;
3425 0 : aPoint.mnRepeat = nRepeat;
3426 0 : aDataPointList.push_back( aPoint );
3427 : }
3428 : }
3429 :
3430 0 : if( bExportContent )
3431 : {
3432 : // write elements (merge equal ones)
3433 0 : ::std::list< SchXMLDataPointStruct >::iterator aIter = aDataPointList.begin();
3434 0 : SchXMLDataPointStruct aPoint;
3435 0 : SchXMLDataPointStruct aLastPoint;
3436 :
3437 : // initialize so that it doesn't matter if
3438 : // the element is counted in the first iteration
3439 0 : aLastPoint.mnRepeat = 0;
3440 :
3441 0 : for( ; aIter != aDataPointList.end(); ++aIter )
3442 : {
3443 0 : aPoint = (*aIter);
3444 :
3445 0 : if( aPoint.maStyleName == aLastPoint.maStyleName )
3446 0 : aPoint.mnRepeat += aLastPoint.mnRepeat;
3447 0 : else if( aLastPoint.mnRepeat > 0 )
3448 : {
3449 : // write last element
3450 0 : if( !aLastPoint.maStyleName.isEmpty() )
3451 0 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_STYLE_NAME, aLastPoint.maStyleName );
3452 :
3453 0 : if( aLastPoint.mnRepeat > 1 )
3454 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_REPEATED,
3455 0 : OUString::number( ( aLastPoint.mnRepeat ) ));
3456 :
3457 0 : SvXMLElementExport aPointElem( mrExport, XML_NAMESPACE_CHART, XML_DATA_POINT, true, true );
3458 : }
3459 0 : aLastPoint = aPoint;
3460 : }
3461 : // write last element if it hasn't been written in last iteration
3462 0 : if( aPoint.maStyleName == aLastPoint.maStyleName )
3463 : {
3464 0 : if( !aLastPoint.maStyleName.isEmpty() )
3465 0 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_STYLE_NAME, aLastPoint.maStyleName );
3466 :
3467 0 : if( aLastPoint.mnRepeat > 1 )
3468 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_REPEATED,
3469 0 : OUString::number( ( aLastPoint.mnRepeat ) ));
3470 :
3471 0 : SvXMLElementExport aPointElem( mrExport, XML_NAMESPACE_CHART, XML_DATA_POINT, true, true );
3472 0 : }
3473 0 : }
3474 : }
3475 0 : }
3476 :
3477 0 : void SchXMLExportHelper_Impl::addPosition( const awt::Point & rPosition )
3478 : {
3479 0 : mrExport.GetMM100UnitConverter().convertMeasureToXML(
3480 0 : msStringBuffer, rPosition.X );
3481 0 : msString = msStringBuffer.makeStringAndClear();
3482 0 : mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_X, msString );
3483 :
3484 0 : mrExport.GetMM100UnitConverter().convertMeasureToXML(
3485 0 : msStringBuffer, rPosition.Y );
3486 0 : msString = msStringBuffer.makeStringAndClear();
3487 0 : mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_Y, msString );
3488 0 : }
3489 :
3490 0 : void SchXMLExportHelper_Impl::addPosition( Reference< drawing::XShape > xShape )
3491 : {
3492 0 : if( xShape.is())
3493 0 : addPosition( xShape->getPosition());
3494 0 : }
3495 :
3496 0 : void SchXMLExportHelper_Impl::addSize( const awt::Size & rSize, bool bIsOOoNamespace)
3497 : {
3498 0 : mrExport.GetMM100UnitConverter().convertMeasureToXML(
3499 0 : msStringBuffer, rSize.Width );
3500 0 : msString = msStringBuffer.makeStringAndClear();
3501 0 : mrExport.AddAttribute( bIsOOoNamespace ? XML_NAMESPACE_CHART_EXT : XML_NAMESPACE_SVG , XML_WIDTH, msString );
3502 :
3503 0 : mrExport.GetMM100UnitConverter().convertMeasureToXML(
3504 0 : msStringBuffer, rSize.Height);
3505 0 : msString = msStringBuffer.makeStringAndClear();
3506 0 : mrExport.AddAttribute( bIsOOoNamespace ? XML_NAMESPACE_CHART_EXT : XML_NAMESPACE_SVG, XML_HEIGHT, msString );
3507 0 : }
3508 :
3509 0 : void SchXMLExportHelper_Impl::addSize( Reference< drawing::XShape > xShape, bool bIsOOoNamespace )
3510 : {
3511 0 : if( xShape.is())
3512 0 : addSize( xShape->getSize(), bIsOOoNamespace );
3513 0 : }
3514 :
3515 0 : awt::Size SchXMLExportHelper_Impl::getPageSize( const Reference< chart2::XChartDocument > & xChartDoc ) const
3516 : {
3517 0 : awt::Size aSize( 8000, 7000 );
3518 0 : uno::Reference< embed::XVisualObject > xVisualObject( xChartDoc, uno::UNO_QUERY );
3519 : SAL_WARN_IF( !xVisualObject.is(), "xmloff.chart", "need XVisualObject for page size" );
3520 0 : if( xVisualObject.is() )
3521 0 : aSize = xVisualObject->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );
3522 :
3523 0 : return aSize;
3524 : }
3525 :
3526 0 : void SchXMLExportHelper_Impl::CollectAutoStyle( const std::vector< XMLPropertyState >& aStates )
3527 : {
3528 0 : if( !aStates.empty() )
3529 0 : maAutoStyleNameQueue.push( GetAutoStylePoolP().Add( XML_STYLE_FAMILY_SCH_CHART_ID, aStates ));
3530 0 : }
3531 :
3532 0 : void SchXMLExportHelper_Impl::AddAutoStyleAttribute( const std::vector< XMLPropertyState >& aStates )
3533 : {
3534 0 : if( !aStates.empty() )
3535 : {
3536 : SAL_WARN_IF( maAutoStyleNameQueue.empty(), "xmloff.chart", "Autostyle queue empty!" );
3537 :
3538 0 : mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_STYLE_NAME, maAutoStyleNameQueue.front() );
3539 0 : maAutoStyleNameQueue.pop();
3540 : }
3541 0 : }
3542 :
3543 0 : void SchXMLExportHelper_Impl::exportText( const OUString& rText, bool bConvertTabsLFs )
3544 : {
3545 0 : SchXMLTools::exportText( mrExport, rText, bConvertTabsLFs );
3546 0 : }
3547 :
3548 : // class SchXMLExport
3549 :
3550 0 : SchXMLExport::SchXMLExport(
3551 : const Reference< uno::XComponentContext >& xContext,
3552 : OUString const & implementationName, sal_uInt16 nExportFlags )
3553 : : SvXMLExport( util::MeasureUnit::CM, xContext, implementationName,
3554 : ::xmloff::token::XML_CHART, nExportFlags ),
3555 : maAutoStylePool( *this ),
3556 0 : maExportHelper( *this, maAutoStylePool )
3557 : {
3558 0 : if( getDefaultVersion() > SvtSaveOptions::ODFVER_012 )
3559 0 : _GetNamespaceMap().Add( GetXMLToken(XML_NP_CHART_EXT), GetXMLToken(XML_N_CHART_EXT), XML_NAMESPACE_CHART_EXT);
3560 0 : }
3561 :
3562 0 : SchXMLExport::~SchXMLExport()
3563 : {
3564 : // stop progress view
3565 0 : if( mxStatusIndicator.is())
3566 : {
3567 0 : mxStatusIndicator->end();
3568 0 : mxStatusIndicator->reset();
3569 : }
3570 0 : }
3571 :
3572 0 : sal_uInt32 SchXMLExport::exportDoc( enum ::xmloff::token::XMLTokenEnum eClass )
3573 : {
3574 0 : Reference< chart2::XChartDocument > xChartDoc( GetModel(), uno::UNO_QUERY );
3575 0 : maExportHelper.m_pImpl->InitRangeSegmentationProperties( xChartDoc );
3576 0 : return SvXMLExport::exportDoc( eClass );
3577 : }
3578 :
3579 0 : void SchXMLExport::_ExportStyles( bool bUsed )
3580 : {
3581 0 : SvXMLExport::_ExportStyles( bUsed );
3582 0 : }
3583 :
3584 0 : void SchXMLExport::_ExportMasterStyles()
3585 : {
3586 : // not available in chart
3587 : SAL_INFO("xmloff.chart", "Master Style Export requested. Not available for Chart" );
3588 0 : }
3589 :
3590 0 : void SchXMLExport::_ExportAutoStyles()
3591 : {
3592 : // there are no styles that require their own autostyles
3593 0 : if( getExportFlags() & EXPORT_CONTENT )
3594 : {
3595 0 : Reference< chart::XChartDocument > xChartDoc( GetModel(), uno::UNO_QUERY );
3596 0 : if( xChartDoc.is())
3597 : {
3598 0 : maExportHelper.m_pImpl->collectAutoStyles( xChartDoc );
3599 0 : maExportHelper.m_pImpl->exportAutoStyles();
3600 : }
3601 : else
3602 : {
3603 : SAL_WARN("xmloff.chart", "Couldn't export chart due to wrong XModel (must be XChartDocument)" );
3604 0 : }
3605 : }
3606 0 : }
3607 :
3608 0 : void SchXMLExport::_ExportContent()
3609 : {
3610 0 : Reference< chart::XChartDocument > xChartDoc( GetModel(), uno::UNO_QUERY );
3611 0 : if( xChartDoc.is())
3612 : {
3613 : // determine if data comes from the outside
3614 0 : sal_Bool bIncludeTable = sal_True;
3615 :
3616 0 : Reference< chart2::XChartDocument > xNewDoc( xChartDoc, uno::UNO_QUERY );
3617 0 : if( xNewDoc.is())
3618 : {
3619 : // check if we have own data. If so we must not export the complete
3620 : // range string, as this is our only indicator for having own or
3621 : // external data. @todo: fix this in the file format!
3622 0 : Reference< lang::XServiceInfo > xDPServiceInfo( xNewDoc->getDataProvider(), uno::UNO_QUERY );
3623 0 : if( ! (xDPServiceInfo.is() && xDPServiceInfo->getImplementationName() == "com.sun.star.comp.chart.InternalDataProvider" ))
3624 : {
3625 0 : bIncludeTable = sal_False;
3626 0 : }
3627 : }
3628 : else
3629 : {
3630 0 : Reference< lang::XServiceInfo > xServ( xChartDoc, uno::UNO_QUERY );
3631 0 : if( xServ.is())
3632 : {
3633 0 : if( xServ->supportsService(
3634 0 : OUString( "com.sun.star.chart.ChartTableAddressSupplier" )))
3635 : {
3636 0 : Reference< beans::XPropertySet > xProp( xServ, uno::UNO_QUERY );
3637 0 : if( xProp.is())
3638 : {
3639 0 : Any aAny;
3640 : try
3641 : {
3642 0 : OUString sChartAddress;
3643 0 : aAny = xProp->getPropertyValue(
3644 0 : OUString( "ChartRangeAddress" ));
3645 0 : aAny >>= sChartAddress;
3646 0 : maExportHelper.m_pImpl->SetChartRangeAddress( sChartAddress );
3647 :
3648 0 : OUString sTableNumberList;
3649 0 : aAny = xProp->getPropertyValue(
3650 0 : OUString( "TableNumberList" ));
3651 0 : aAny >>= sTableNumberList;
3652 0 : maExportHelper.m_pImpl->SetTableNumberList( sTableNumberList );
3653 :
3654 : // do not include own table if there are external addresses
3655 0 : bIncludeTable = sChartAddress.isEmpty();
3656 : }
3657 0 : catch( const beans::UnknownPropertyException & )
3658 : {
3659 : SAL_WARN("xmloff.chart", "Property ChartRangeAddress not supported by ChartDocument" );
3660 0 : }
3661 0 : }
3662 : }
3663 0 : }
3664 : }
3665 0 : maExportHelper.m_pImpl->exportChart( xChartDoc, bIncludeTable );
3666 : }
3667 : else
3668 : {
3669 : SAL_WARN("xmloff.chart", "Couldn't export chart due to wrong XModel" );
3670 0 : }
3671 0 : }
3672 :
3673 0 : UniReference< XMLPropertySetMapper > SchXMLExport::GetPropertySetMapper() const
3674 : {
3675 0 : return maExportHelper.m_pImpl->GetPropertySetMapper();
3676 : }
3677 :
3678 0 : void SchXMLExportHelper_Impl::InitRangeSegmentationProperties( const Reference< chart2::XChartDocument > & xChartDoc )
3679 : {
3680 0 : if( xChartDoc.is())
3681 : try
3682 : {
3683 0 : Reference< chart2::data::XDataProvider > xDataProvider( xChartDoc->getDataProvider() );
3684 : SAL_WARN_IF( !xDataProvider.is(), "xmloff.chart", "No DataProvider" );
3685 0 : if( xDataProvider.is())
3686 : {
3687 0 : Reference< chart2::data::XDataSource > xDataSource( lcl_pressUsedDataIntoRectangularFormat( xChartDoc, mbHasCategoryLabels ));
3688 0 : Sequence< beans::PropertyValue > aArgs( xDataProvider->detectArguments( xDataSource ));
3689 0 : OUString sCellRange, sBrokenRange;
3690 0 : bool bBrokenRangeAvailable = false;
3691 0 : for( sal_Int32 i=0; i<aArgs.getLength(); ++i )
3692 : {
3693 0 : if ( aArgs[i].Name == "CellRangeRepresentation" )
3694 0 : aArgs[i].Value >>= sCellRange;
3695 0 : else if ( aArgs[i].Name == "BrokenCellRangeForExport" )
3696 : {
3697 0 : if( aArgs[i].Value >>= sBrokenRange )
3698 0 : bBrokenRangeAvailable = true;
3699 : }
3700 0 : else if ( aArgs[i].Name == "DataRowSource" )
3701 : {
3702 : chart::ChartDataRowSource eRowSource;
3703 0 : aArgs[i].Value >>= eRowSource;
3704 0 : mbRowSourceColumns = ( eRowSource == chart::ChartDataRowSource_COLUMNS );
3705 : }
3706 0 : else if ( aArgs[i].Name == "FirstCellAsLabel" )
3707 0 : aArgs[i].Value >>= mbHasSeriesLabels;
3708 0 : else if ( aArgs[i].Name == "SequenceMapping" )
3709 0 : aArgs[i].Value >>= maSequenceMapping;
3710 0 : else if ( aArgs[i].Name == "TableNumberList" )
3711 0 : aArgs[i].Value >>= msTableNumberList;
3712 : }
3713 :
3714 : // #i79009# For Writer we have to export a broken version of the
3715 : // range, where every row number is noe too large, so that older
3716 : // version can correctly read those files.
3717 0 : msChartAddress = (bBrokenRangeAvailable ? sBrokenRange : sCellRange);
3718 0 : if( !msChartAddress.isEmpty() )
3719 : {
3720 : // convert format to XML-conform one
3721 0 : Reference< chart2::data::XRangeXMLConversion > xConversion( xDataProvider, uno::UNO_QUERY );
3722 0 : if( xConversion.is())
3723 0 : msChartAddress = xConversion->convertRangeToXML( msChartAddress );
3724 0 : }
3725 0 : }
3726 : }
3727 0 : catch( const uno::Exception & ex )
3728 : {
3729 : SAL_WARN("xmloff.chart", "Exception caught. Type: " << OUString::createFromAscii( typeid( ex ).name()) << ", Message: " << ex.Message);
3730 : }
3731 0 : }
3732 :
3733 : // first version: everything goes in one storage
3734 :
3735 0 : Sequence< OUString > SAL_CALL SchXMLExport_getSupportedServiceNames() throw()
3736 : {
3737 0 : const OUString aServiceName( "com.sun.star.comp.Chart.XMLExporter" );
3738 0 : const Sequence< OUString > aSeq( &aServiceName, 1 );
3739 0 : return aSeq;
3740 : }
3741 :
3742 0 : OUString SAL_CALL SchXMLExport_getImplementationName() throw()
3743 : {
3744 0 : return OUString( "SchXMLExport.Compact" );
3745 : }
3746 :
3747 0 : Reference< uno::XInterface > SAL_CALL SchXMLExport_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception )
3748 : {
3749 : // #110680#
3750 : // #103997# removed some flags from EXPORT_ALL
3751 0 : return (cppu::OWeakObject*)new SchXMLExport( comphelper::getComponentContext(rSMgr), SchXMLExport_getImplementationName(), EXPORT_ALL ^ ( EXPORT_SETTINGS | EXPORT_MASTERSTYLES | EXPORT_SCRIPTS ));
3752 : }
3753 :
3754 : // Oasis format
3755 0 : Sequence< OUString > SAL_CALL SchXMLExport_Oasis_getSupportedServiceNames() throw()
3756 : {
3757 0 : const OUString aServiceName( "com.sun.star.comp.Chart.XMLOasisExporter" );
3758 0 : const Sequence< OUString > aSeq( &aServiceName, 1 );
3759 0 : return aSeq;
3760 : }
3761 :
3762 0 : OUString SAL_CALL SchXMLExport_Oasis_getImplementationName() throw()
3763 : {
3764 0 : return OUString( "SchXMLExport.Oasis.Compact" );
3765 : }
3766 :
3767 0 : Reference< uno::XInterface > SAL_CALL SchXMLExport_Oasis_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception )
3768 : {
3769 : // #103997# removed some flags from EXPORT_ALL
3770 : return (cppu::OWeakObject*)new SchXMLExport( comphelper::getComponentContext(rSMgr),
3771 : SchXMLExport_Oasis_getImplementationName(),
3772 0 : (EXPORT_ALL ^ ( EXPORT_SETTINGS | EXPORT_MASTERSTYLES | EXPORT_SCRIPTS )) | EXPORT_OASIS );
3773 : }
3774 :
3775 : // multiple storage version: one for content / styles / meta
3776 :
3777 0 : Sequence< OUString > SAL_CALL SchXMLExport_Styles_getSupportedServiceNames() throw()
3778 : {
3779 0 : const OUString aServiceName( "com.sun.star.comp.Chart.XMLStylesExporter" );
3780 0 : const Sequence< OUString > aSeq( &aServiceName, 1 );
3781 0 : return aSeq;
3782 : }
3783 :
3784 0 : OUString SAL_CALL SchXMLExport_Styles_getImplementationName() throw()
3785 : {
3786 0 : return OUString( "SchXMLExport.Styles" );
3787 : }
3788 :
3789 0 : Reference< uno::XInterface > SAL_CALL SchXMLExport_Styles_createInstance(const Reference< lang::XMultiServiceFactory >& rSMgr) throw( uno::Exception )
3790 : {
3791 : // #110680#
3792 0 : return (cppu::OWeakObject*)new SchXMLExport( comphelper::getComponentContext(rSMgr), SchXMLExport_Styles_getImplementationName(), EXPORT_STYLES );
3793 : }
3794 :
3795 : // Oasis format
3796 0 : Sequence< OUString > SAL_CALL SchXMLExport_Oasis_Styles_getSupportedServiceNames() throw()
3797 : {
3798 0 : const OUString aServiceName( "com.sun.star.comp.Chart.XMLOasisStylesExporter" );
3799 0 : const Sequence< OUString > aSeq( &aServiceName, 1 );
3800 0 : return aSeq;
3801 : }
3802 :
3803 0 : OUString SAL_CALL SchXMLExport_Oasis_Styles_getImplementationName() throw()
3804 : {
3805 0 : return OUString( "SchXMLExport.Oasis.Styles" );
3806 : }
3807 :
3808 0 : Reference< uno::XInterface > SAL_CALL SchXMLExport_Oasis_Styles_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception )
3809 : {
3810 0 : return (cppu::OWeakObject*)new SchXMLExport( comphelper::getComponentContext(rSMgr), SchXMLExport_Oasis_Styles_getImplementationName(), EXPORT_STYLES | EXPORT_OASIS );
3811 : }
3812 :
3813 0 : Sequence< OUString > SAL_CALL SchXMLExport_Content_getSupportedServiceNames() throw()
3814 : {
3815 0 : const OUString aServiceName( "com.sun.star.comp.Chart.XMLContentExporter" );
3816 0 : const Sequence< OUString > aSeq( &aServiceName, 1 );
3817 0 : return aSeq;
3818 : }
3819 :
3820 0 : OUString SAL_CALL SchXMLExport_Content_getImplementationName() throw()
3821 : {
3822 0 : return OUString( "SchXMLExport.Content" );
3823 : }
3824 :
3825 0 : Reference< uno::XInterface > SAL_CALL SchXMLExport_Content_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception )
3826 : {
3827 : // #110680#
3828 0 : return (cppu::OWeakObject*)new SchXMLExport( comphelper::getComponentContext(rSMgr), SchXMLExport_Content_getImplementationName(), EXPORT_AUTOSTYLES | EXPORT_CONTENT | EXPORT_FONTDECLS );
3829 : }
3830 :
3831 : // Oasis format
3832 0 : Sequence< OUString > SAL_CALL SchXMLExport_Oasis_Content_getSupportedServiceNames() throw()
3833 : {
3834 0 : const OUString aServiceName( "com.sun.star.comp.Chart.XMLOasisContentExporter" );
3835 0 : const Sequence< OUString > aSeq( &aServiceName, 1 );
3836 0 : return aSeq;
3837 : }
3838 :
3839 0 : OUString SAL_CALL SchXMLExport_Oasis_Content_getImplementationName() throw()
3840 : {
3841 0 : return OUString( "SchXMLExport.Oasis.Content" );
3842 : }
3843 :
3844 0 : Reference< uno::XInterface > SAL_CALL SchXMLExport_Oasis_Content_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception )
3845 : {
3846 0 : return (cppu::OWeakObject*)new SchXMLExport( comphelper::getComponentContext(rSMgr), SchXMLExport_Oasis_Content_getImplementationName(), EXPORT_AUTOSTYLES | EXPORT_CONTENT | EXPORT_FONTDECLS | EXPORT_OASIS );
3847 : }
3848 :
3849 : // Oasis format
3850 0 : Sequence< OUString > SAL_CALL SchXMLExport_Oasis_Meta_getSupportedServiceNames() throw()
3851 : {
3852 0 : const OUString aServiceName( "com.sun.star.comp.Chart.XMLOasisMetaExporter" );
3853 0 : const Sequence< OUString > aSeq( &aServiceName, 1 );
3854 0 : return aSeq;
3855 : }
3856 :
3857 0 : OUString SAL_CALL SchXMLExport_Oasis_Meta_getImplementationName() throw()
3858 : {
3859 0 : return OUString( "SchXMLExport.Oasis.Meta" );
3860 : }
3861 :
3862 0 : Reference< uno::XInterface > SAL_CALL SchXMLExport_Oasis_Meta_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception )
3863 : {
3864 0 : return (cppu::OWeakObject*)new SchXMLExport( comphelper::getComponentContext(rSMgr), SchXMLExport_Oasis_Meta_getImplementationName(), EXPORT_META | EXPORT_OASIS );
3865 : }
3866 :
3867 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|