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