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