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
SetChartRangeAddress(const::rtl::OUString & rAddress)166 void SetChartRangeAddress( const ::rtl::OUString& rAddress )
167 { msChartAddress = rAddress; }
SetTableNumberList(const::rtl::OUString & rList)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
GetAutoStylePoolP()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 {
lcl_getComponentContext()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:
lcl_MatchesRole(const OUString & aRole)305 explicit lcl_MatchesRole( const OUString & aRole ) :
306 m_aRole( aRole )
307 {}
308
operator ()(const Reference<chart2::data::XLabeledDataSequence> & xSeq) const309 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 >
lcl_SequenceToVectorAppend(const Sequence<T> & rSource,::std::vector<T> & rDestination)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 >
lcl_SequenceToVector(const Sequence<T> & rSource,::std::vector<T> & rDestination)335 void lcl_SequenceToVector( const Sequence< T > & rSource, ::std::vector< T > & rDestination )
336 {
337 rDestination.clear();
338 lcl_SequenceToVectorAppend( rSource, rDestination );
339 }
340
lcl_getCategories(const Reference<chart2::XDiagram> & xDiagram)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
lcl_createDataSource(const Sequence<Reference<chart2::data::XLabeledDataSequence>> & aData)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
lcl_getAllSeriesSequences(const Reference<chart2::XChartDocument> & xChartDoc)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 >
lcl_getDataSequenceByRole(const Sequence<Reference<chart2::data::XLabeledDataSequence>> & aLabeledSeq,const OUString & rRole)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
lcl_pressUsedDataIntoRectangularFormat(const Reference<chart2::XChartDocument> & xChartDoc,sal_Bool & rOutSourceHasCategoryLabels)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
lcl_isSeriesAttachedToFirstAxis(const Reference<chart2::XDataSeries> & xDataSeries)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
lcl_ConvertRange(const::rtl::OUString & rRange,const Reference<chart2::XChartDocument> & xDoc)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
lcl_getLabelAndValueRangeByRole(const Sequence<Reference<chart2::data::XLabeledDataSequence>> & aSeqCnt,const OUString & rRole,const Reference<chart2::XChartDocument> & xDoc,SchXMLExportHelper_Impl::tDataSequenceCont & rOutSequencesToExport)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
lcl_getSequenceLengthByRole(const Sequence<Reference<chart2::data::XLabeledDataSequence>> & aSeqCnt,const OUString & rRole)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
lcl_hasChartType(const Reference<chart2::XDiagram> & xDiagram,const OUString & rChartType)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
lcl_flattenStringSequence(const Sequence<OUString> & rSequence)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
lcl_getLabelStringSequence(Sequence<OUString> & rOutLabels,const Reference<chart2::data::XDataSequence> & xLabelSeq)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
lcl_getMaxSequenceLength(const SchXMLExportHelper_Impl::tDataSequenceCont & rContainer)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
lcl_DataSequenceToStringSequence(const uno::Reference<chart2::data::XDataSequence> & xDataSequence)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 }
lcl_getAllValuesFromSequence(const Reference<chart2::data::XDataSequence> & xSeq)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
lcl_SequenceHasUnhiddenData(const uno::Reference<chart2::data::XDataSequence> & xDataSequence)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 {
lcl_resize__anonabab0a5c0111::lcl_resize778 lcl_resize( typename T::size_type nSize, typename T::value_type fDefaultValue ) : m_nSize( nSize ), m_fDefaultValue( fDefaultValue ) {}
operator ()__anonabab0a5c0111::lcl_resize779 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 {
lcl_SequenceToMapElement__anonabab0a5c0111::lcl_SequenceToMapElement793 lcl_SequenceToMapElement()
794 {}
operator ()__anonabab0a5c0111::lcl_SequenceToMapElement795 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
lcl_ReorderInternalSequencesAccordingToTheirRangeName(SchXMLExportHelper_Impl::tDataSequenceCont & rInOutSequences)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
lcl_getDataForLocalTable(const SchXMLExportHelper_Impl::tDataSequenceCont & aSequencesToExport,const Reference<chart2::XAnyDescriptionAccess> & xAnyDescriptionAccess,const OUString & rCategoriesRange,bool bSeriesFromColumns,const Reference<chart2::data::XRangeXMLConversion> & xRangeConversion)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
lcl_exportNumberFormat(const OUString & rPropertyName,const Reference<beans::XPropertySet> & xPropSet,SvXMLExport & rExport)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 > >
lcl_getErrorBarSequences(const Reference<beans::XPropertySet> & xErrorBarProp)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
lcl_exportDomainForThisSequence(const Reference<chart2::data::XDataSequence> xValues,rtl::OUString & rFirstRangeForThisDomainIndex,SvXMLExport & rExport)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
SchXMLDataPointStructSchXMLDataPointStruct1062 SchXMLDataPointStruct() : mnRepeat( 1 ) {}
1063 };
1064
1065 // ========================================
1066 // class SchXMLExportHelper
1067 // ========================================
1068
SchXMLExportHelper(SvXMLExport & rExport,SvXMLAutoStylePoolP & rASPool)1069 SchXMLExportHelper::SchXMLExportHelper( SvXMLExport& rExport, SvXMLAutoStylePoolP& rASPool )
1070 : m_pImpl( new SchXMLExportHelper_Impl( rExport, rASPool ) )
1071 {
1072 }
1073
~SchXMLExportHelper()1074 SchXMLExportHelper::~SchXMLExportHelper()
1075 {
1076 delete m_pImpl;
1077 }
1078
getChartCLSID()1079 const OUString& SchXMLExportHelper::getChartCLSID()
1080 {
1081 return m_pImpl->msCLSID;
1082 }
1083
GetPropertySetMapper() const1084 UniReference< XMLPropertySetMapper > SchXMLExportHelper_Impl::GetPropertySetMapper() const
1085 {
1086 return mxPropertySetMapper;
1087 }
1088
exportAutoStyles()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
SchXMLExportHelper_Impl(SvXMLExport & rExport,SvXMLAutoStylePoolP & rASPool)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
~SchXMLExportHelper_Impl()1184 SchXMLExportHelper_Impl::~SchXMLExportHelper_Impl()
1185 {
1186 }
1187
collectAutoStyles(Reference<chart::XChartDocument> rChartDoc)1188 void SchXMLExportHelper_Impl::collectAutoStyles( Reference< chart::XChartDocument > rChartDoc )
1189 {
1190 parseDocument( rChartDoc, sal_False );
1191 }
1192
exportChart(Reference<chart::XChartDocument> rChartDoc,sal_Bool bIncludeTable)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
lcl_GetStringFromNumberSequence(const::com::sun::star::uno::Sequence<sal_Int32> & rSequenceMapping,bool bRemoveOneFromEachIndex)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
parseDocument(Reference<chart::XChartDocument> & rChartDoc,sal_Bool bExportContent,sal_Bool bIncludeTable)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 happened 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 happened 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
lcl_exportComplexLabel(const Sequence<uno::Any> & rComplexLabel,SvXMLExport & rExport)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
exportTable()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
lcl_getCooSys(const Reference<chart2::XDiagram> & xNewDiagram)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
lcl_getAxis(const Reference<chart2::XCoordinateSystem> & xCooSys,enum XMLTokenEnum eDimension,bool bPrimary=true)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
exportPlotArea(Reference<chart::XDiagram> xDiagram,Reference<chart2::XDiagram> xNewDiagram,const awt::Size & rPageSize,sal_Bool bExportContent,sal_Bool bIncludeTable)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
exportCoordinateRegion(const uno::Reference<chart::XDiagram> & xDiagram)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 {
lcl_getTimeUnitToken(sal_Int32 nTimeUnit)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
exportDateScale(const Reference<beans::XPropertySet> xAxisProps)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
exportAxisTitle(const Reference<beans::XPropertySet> xTitleProps,bool bExportContent)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
exportGrid(const Reference<beans::XPropertySet> xGridProperties,bool bMajor,bool bExportContent)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
lcl_exportAxisType(const Reference<chart2::XAxis> xChart2Axis,SvXMLExport & rExport)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
exportAxis(enum XMLTokenEnum eDimension,enum XMLTokenEnum eAxisName,const Reference<beans::XPropertySet> xAxisProps,const Reference<chart2::XAxis> & xChart2Axis,const OUString & rCategoriesRange,bool bHasTitle,bool bHasMajorGrid,bool bHasMinorGrid,bool bExportContent)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
exportAxes(const Reference<chart::XDiagram> & xDiagram,const Reference<chart2::XDiagram> & xNewDiagram,sal_Bool bExportContent)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 {
lcl_hasNoValuesButText(const uno::Reference<chart2::data::XDataSequence> & xDataSequence)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
exportSeries(const Reference<chart2::XDiagram> & xNewDiagram,const awt::Size & rPageSize,sal_Bool bExportContent,sal_Bool bHasTwoYAxes)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
exportRegressionCurve(const Reference<chart2::XDataSeries> & xSeries,const Reference<beans::XPropertySet> & xSeriesProp,const awt::Size & rPageSize,sal_Bool bExportContent)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
exportCandleStickSeries(const Sequence<Reference<chart2::XDataSeries>> & aSeriesSeq,const Reference<chart2::XDiagram> & xDiagram,sal_Bool bJapaneseCandleSticks,sal_Bool bExportContent)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
exportDataPoints(const uno::Reference<beans::XPropertySet> & xSeriesProperties,sal_Int32 nSeriesLength,const uno::Reference<chart2::XDiagram> & xDiagram,sal_Bool bExportContent)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
getCellAddress(sal_Int32 nCol,sal_Int32 nRow)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
addPosition(const awt::Point & rPosition)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
addPosition(Reference<drawing::XShape> xShape)3599 void SchXMLExportHelper_Impl::addPosition( Reference< drawing::XShape > xShape )
3600 {
3601 if( xShape.is())
3602 addPosition( xShape->getPosition());
3603 }
3604
addSize(const awt::Size & rSize,bool bIsOOoNamespace)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
addSize(Reference<drawing::XShape> xShape,bool bIsOOoNamespace)3617 void SchXMLExportHelper_Impl::addSize( Reference< drawing::XShape > xShape, bool bIsOOoNamespace )
3618 {
3619 if( xShape.is())
3620 addSize( xShape->getSize(), bIsOOoNamespace );
3621 }
3622
getPageSize(const Reference<chart2::XChartDocument> & xChartDoc) const3623 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
CollectAutoStyle(const std::vector<XMLPropertyState> & aStates)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
AddAutoStyleAttribute(const std::vector<XMLPropertyState> & aStates)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
exportText(const OUString & rText,bool bConvertTabsLFs)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#
SchXMLExport(const Reference<lang::XMultiServiceFactory> & xServiceFactory,sal_uInt16 nExportFlags)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
~SchXMLExport()3673 SchXMLExport::~SchXMLExport()
3674 {
3675 // stop progress view
3676 if( mxStatusIndicator.is())
3677 {
3678 mxStatusIndicator->end();
3679 mxStatusIndicator->reset();
3680 }
3681 }
3682
exportDoc(enum::xmloff::token::XMLTokenEnum eClass)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
_ExportStyles(sal_Bool bUsed)3690 void SchXMLExport::_ExportStyles( sal_Bool bUsed )
3691 {
3692 SvXMLExport::_ExportStyles( bUsed );
3693 }
3694
_ExportMasterStyles()3695 void SchXMLExport::_ExportMasterStyles()
3696 {
3697 // not available in chart
3698 DBG_WARNING( "Master Style Export requested. Not available for Chart" );
3699 }
3700
_ExportAutoStyles()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
_ExportContent()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
SetProgress(sal_Int32 nPercentage)3786 void SchXMLExport::SetProgress( sal_Int32 nPercentage )
3787 {
3788 // set progress view
3789 if( mxStatusIndicator.is())
3790 mxStatusIndicator->setValue( nPercentage );
3791 }
3792
GetPropertySetMapper() const3793 UniReference< XMLPropertySetMapper > SchXMLExport::GetPropertySetMapper() const
3794 {
3795 return maExportHelper.m_pImpl->GetPropertySetMapper();
3796 }
3797
InitRangeSegmentationProperties(const Reference<chart2::XChartDocument> & xChartDoc)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
SchXMLExport_getSupportedServiceNames()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
SchXMLExport_getImplementationName()3869 OUString SAL_CALL SchXMLExport_getImplementationName() throw()
3870 {
3871 return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Compact" ) );
3872 }
3873
SchXMLExport_createInstance(const Reference<lang::XMultiServiceFactory> & rSMgr)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
SchXMLExport_Oasis_getSupportedServiceNames()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
SchXMLExport_Oasis_getImplementationName()3890 OUString SAL_CALL SchXMLExport_Oasis_getImplementationName() throw()
3891 {
3892 return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Oasis.Compact" ) );
3893 }
3894
SchXMLExport_Oasis_createInstance(const Reference<lang::XMultiServiceFactory> & rSMgr)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
SchXMLExport_Styles_getSupportedServiceNames()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
SchXMLExport_Styles_getImplementationName()3913 OUString SAL_CALL SchXMLExport_Styles_getImplementationName() throw()
3914 {
3915 return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Styles" ));
3916 }
3917
SchXMLExport_Styles_createInstance(const Reference<lang::XMultiServiceFactory> & rSMgr)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
SchXMLExport_Oasis_Styles_getSupportedServiceNames()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
SchXMLExport_Oasis_Styles_getImplementationName()3933 OUString SAL_CALL SchXMLExport_Oasis_Styles_getImplementationName() throw()
3934 {
3935 return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Oasis.Styles" ));
3936 }
3937
SchXMLExport_Oasis_Styles_createInstance(const Reference<lang::XMultiServiceFactory> & rSMgr)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
SchXMLExport_Content_getSupportedServiceNames()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
SchXMLExport_Content_getImplementationName()3952 OUString SAL_CALL SchXMLExport_Content_getImplementationName() throw()
3953 {
3954 return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Content" ));
3955 }
3956
SchXMLExport_Content_createInstance(const Reference<lang::XMultiServiceFactory> & rSMgr)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
SchXMLExport_Oasis_Content_getSupportedServiceNames()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
SchXMLExport_Oasis_Content_getImplementationName()3972 OUString SAL_CALL SchXMLExport_Oasis_Content_getImplementationName() throw()
3973 {
3974 return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Oasis.Content" ));
3975 }
3976
SchXMLExport_Oasis_Content_createInstance(const Reference<lang::XMultiServiceFactory> & rSMgr)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
SchXMLExport_Oasis_Meta_getSupportedServiceNames()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
SchXMLExport_Oasis_Meta_getImplementationName()4009 OUString SAL_CALL SchXMLExport_Oasis_Meta_getImplementationName() throw()
4010 {
4011 return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Oasis.Meta" ));
4012 }
4013
SchXMLExport_Oasis_Meta_createInstance(const Reference<lang::XMultiServiceFactory> & rSMgr)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
getImplementationName()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