bump product version to 5.0.4.1
[LibreOffice.git] / xmloff / source / chart / SchXMLExport.cxx
blob07a83724ca43ac56111522bffd2dfe400f36224e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <boost/noncopyable.hpp>
23 #include <sax/tools/converter.hxx>
25 #include <xmloff/xmlprmap.hxx>
27 #include "SchXMLExport.hxx"
28 #include "XMLChartPropertySetMapper.hxx"
29 #include "ColorPropertySet.hxx"
30 #include "SchXMLTools.hxx"
31 #include "SchXMLEnumConverter.hxx"
32 #include "facreg.hxx"
34 #include <comphelper/processfactory.hxx>
35 #include <tools/globname.hxx>
36 #include <comphelper/classids.hxx>
38 #include <xmloff/nmspmap.hxx>
39 #include <xmloff/xmlnmspe.hxx>
40 #include <xmloff/xmltoken.hxx>
41 #include <xmloff/families.hxx>
42 #include <xmloff/xmlaustp.hxx>
43 #include <xmloff/xmluconv.hxx>
44 #include <xmloff/xmlmetae.hxx>
45 #include <xmloff/SchXMLSeriesHelper.hxx>
46 #include "xexptran.hxx"
47 #include <rtl/math.hxx>
48 #include <comphelper/extract.hxx>
50 #include <list>
51 #include <typeinfo>
52 #include <algorithm>
54 #include <com/sun/star/task/XStatusIndicatorSupplier.hpp>
55 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
56 #include <com/sun/star/lang/XServiceInfo.hpp>
57 #include <com/sun/star/lang/XServiceName.hpp>
58 #include <com/sun/star/beans/XPropertySet.hpp>
59 #include <com/sun/star/uno/XComponentContext.hpp>
60 #include <com/sun/star/util/XRefreshable.hpp>
62 #include <com/sun/star/chart/XAxis.hpp>
63 #include <com/sun/star/chart/XAxisSupplier.hpp>
64 #include <com/sun/star/chart/XChartDocument.hpp>
65 #include <com/sun/star/chart/ChartLegendPosition.hpp>
66 #include <com/sun/star/chart/ChartLegendExpansion.hpp>
67 #include <com/sun/star/chart/ChartDataRowSource.hpp>
68 #include <com/sun/star/chart/ChartAxisAssign.hpp>
69 #include <com/sun/star/chart/ChartAxisType.hpp>
70 #include <com/sun/star/chart/TimeIncrement.hpp>
71 #include <com/sun/star/chart/TimeInterval.hpp>
72 #include <com/sun/star/chart/TimeUnit.hpp>
73 #include <com/sun/star/chart/ChartSeriesAddress.hpp>
74 #include <com/sun/star/chart/X3DDisplay.hpp>
75 #include <com/sun/star/chart/XStatisticDisplay.hpp>
76 #include <com/sun/star/chart/XSecondAxisTitleSupplier.hpp>
77 #include <com/sun/star/chart/XDiagramPositioning.hpp>
79 #include <com/sun/star/chart2/XAnyDescriptionAccess.hpp>
80 #include <com/sun/star/chart2/AxisType.hpp>
81 #include <com/sun/star/chart2/XChartDocument.hpp>
82 #include <com/sun/star/chart2/XDiagram.hpp>
83 #include <com/sun/star/chart2/RelativePosition.hpp>
84 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
85 #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
86 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
87 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
88 #include <com/sun/star/chart2/data/XDataSource.hpp>
89 #include <com/sun/star/chart2/data/XDataSink.hpp>
90 #include <com/sun/star/chart2/data/XDataReceiver.hpp>
91 #include <com/sun/star/chart2/data/XDataProvider.hpp>
92 #include <com/sun/star/chart2/data/XDatabaseDataProvider.hpp>
93 #include <com/sun/star/chart2/data/XRangeXMLConversion.hpp>
94 #include <com/sun/star/chart2/data/XTextualDataSequence.hpp>
95 #include <com/sun/star/chart2/data/XNumericalDataSequence.hpp>
97 #include <com/sun/star/util/MeasureUnit.hpp>
98 #include <com/sun/star/util/XStringMapping.hpp>
99 #include <com/sun/star/drawing/HomogenMatrix.hpp>
100 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
101 #include <com/sun/star/drawing/XShapes.hpp>
102 #include <com/sun/star/embed/Aspects.hpp>
103 #include <com/sun/star/embed/XVisualObject.hpp>
104 #include <com/sun/star/container/XChild.hpp>
106 #include "MultiPropertySetHandler.hxx"
107 #include "PropertyMap.hxx"
109 using namespace com::sun::star;
110 using namespace ::xmloff::token;
112 using namespace ::com::sun::star;
113 using ::com::sun::star::uno::Sequence;
114 using ::com::sun::star::uno::Reference;
115 using ::com::sun::star::uno::Any;
116 using ::std::vector;
118 // class SchXMLExportHelper_Impl
120 class SchXMLExportHelper_Impl: private boost::noncopyable
122 public:
123 // first: data sequence for label, second: data sequence for values.
124 typedef ::std::pair< ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataSequence >,
125 ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataSequence > > tLabelValuesDataPair;
126 typedef ::std::vector< tLabelValuesDataPair > tDataSequenceCont;
128 public:
129 SchXMLExportHelper_Impl( SvXMLExport& rExport,
130 SvXMLAutoStylePoolP& rASPool );
132 virtual ~SchXMLExportHelper_Impl();
134 // auto-styles
135 /// parse chart and collect all auto-styles used in current pool
136 void collectAutoStyles( com::sun::star::uno::Reference<
137 com::sun::star::chart::XChartDocument > rChartDoc );
139 /// write the styles collected into the current pool as <style:style> elements
140 void exportAutoStyles();
142 /** export the <chart:chart> element corresponding to rChartDoc
143 if bIncludeTable is true, the chart data is exported as <table:table>
144 element (inside the chart element).
146 Otherwise the external references stored in the chart document are used
147 for writing the corresponding attributes at series
149 All attributes contained in xAttrList are written at the chart element,
150 which is the outer element of a chart. So these attributes can easily
151 be parsed again by the container
153 void exportChart( com::sun::star::uno::Reference<
154 com::sun::star::chart::XChartDocument > rChartDoc,
155 bool bIncludeTable );
157 rtl::Reference<XMLPropertySetMapper> GetPropertySetMapper() const;
159 void SetChartRangeAddress( const OUString& rAddress )
160 { msChartAddress = rAddress; }
161 void SetTableNumberList( const OUString& rList )
162 { msTableNumberList = rList; }
164 void InitRangeSegmentationProperties(
165 const ::com::sun::star::uno::Reference<
166 ::com::sun::star::chart2::XChartDocument > & xChartDoc );
168 static ::com::sun::star::awt::Size getPageSize(
169 const ::com::sun::star::uno::Reference<
170 ::com::sun::star::chart2::XChartDocument > & xChartDoc );
172 /** first parseDocument: collect autostyles and store names in this queue
173 second parseDocument: export content and use names from this queue
175 ::std::queue< OUString > maAutoStyleNameQueue;
176 void CollectAutoStyle(
177 const std::vector< XMLPropertyState >& aStates );
178 void AddAutoStyleAttribute(
179 const std::vector< XMLPropertyState >& aStates );
181 SvXMLAutoStylePoolP& GetAutoStylePoolP()
182 { return mrAutoStylePool; }
184 /// if bExportContent is false the auto-styles are collected
185 void parseDocument( com::sun::star::uno::Reference<
186 com::sun::star::chart::XChartDocument >& rChartDoc,
187 bool bExportContent,
188 bool bIncludeTable = false );
189 void exportTable();
190 void exportPlotArea(
191 com::sun::star::uno::Reference< com::sun::star::chart::XDiagram > xDiagram,
192 com::sun::star::uno::Reference< com::sun::star::chart2::XDiagram > xNewDiagram,
193 const ::com::sun::star::awt::Size & rPageSize,
194 bool bExportContent,
195 bool bIncludeTable );
196 void exportCoordinateRegion( const com::sun::star::uno::Reference< com::sun::star::chart::XDiagram >& xDiagram );
197 void exportAxes( const com::sun::star::uno::Reference< com::sun::star::chart::XDiagram > & xDiagram,
198 const com::sun::star::uno::Reference< com::sun::star::chart2::XDiagram > & xNewDiagram,
199 bool bExportContent );
200 void exportAxis( enum XMLTokenEnum eDimension, enum XMLTokenEnum eAxisName,
201 const Reference< beans::XPropertySet >& rAxisProps, const Reference< chart2::XAxis >& rChart2Axis,
202 const OUString& rCategoriesRanges,
203 bool bHasTitle, bool bHasMajorGrid, bool bHasMinorGrid, bool bExportContent );
204 void exportGrid( const Reference< beans::XPropertySet >& rGridProperties, bool bMajor, bool bExportContent );
205 void exportDateScale( const Reference< beans::XPropertySet >& rAxisProps );
206 void exportAxisTitle( const Reference< beans::XPropertySet >& rTitleProps, bool bExportContent );
208 void exportSeries(
209 const com::sun::star::uno::Reference< com::sun::star::chart2::XDiagram > & xNewDiagram,
210 const ::com::sun::star::awt::Size & rPageSize,
211 bool bExportContent,
212 bool bHasTwoYAxes );
214 void exportPropertyMapping(
215 const com::sun::star::uno::Reference< com::sun::star::chart2::data::XDataSource > & xSource,
216 Sequence< OUString >& rSupportedMappings );
218 void exportCandleStickSeries(
219 const ::com::sun::star::uno::Sequence<
220 ::com::sun::star::uno::Reference<
221 ::com::sun::star::chart2::XDataSeries > > & aSeriesSeq,
222 const ::com::sun::star::uno::Reference<
223 ::com::sun::star::chart2::XDiagram > & xDiagram,
224 bool bJapaneseCandleSticks,
225 bool bExportContent );
226 void exportDataPoints(
227 const ::com::sun::star::uno::Reference<
228 ::com::sun::star::beans::XPropertySet > & xSeriesProperties,
229 sal_Int32 nSeriesLength,
230 const ::com::sun::star::uno::Reference<
231 ::com::sun::star::chart2::XDiagram > & xDiagram,
232 bool bExportContent );
234 void exportRegressionCurve(
235 const com::sun::star::uno::Reference<com::sun::star::chart2::XDataSeries>& xSeries,
236 const com::sun::star::awt::Size& rPageSize,
237 bool bExportContent );
239 void exportErrorBar (
240 const ::com::sun::star::uno::Reference<beans::XPropertySet> &xSeriesProp, bool bYError,
241 bool bExportContent );
243 /// add svg position as attribute for current element
244 void addPosition( const ::com::sun::star::awt::Point & rPosition );
245 void addPosition( com::sun::star::uno::Reference< com::sun::star::drawing::XShape > xShape );
246 /// add svg size as attribute for current element
247 void addSize( const ::com::sun::star::awt::Size & rSize, bool bIsOOoNamespace = false );
248 void addSize( com::sun::star::uno::Reference< com::sun::star::drawing::XShape > xShape, bool bIsOOoNamespace = false );
249 /// exports a string as a paragraph element
250 void exportText( const OUString& rText, bool bConvertTabsLFs = false );
252 public:
253 SvXMLExport& mrExport;
254 SvXMLAutoStylePoolP& mrAutoStylePool;
255 rtl::Reference< XMLPropertySetMapper > mxPropertySetMapper;
256 rtl::Reference< XMLChartExportPropertyMapper > mxExpPropMapper;
258 OUString msTableName;
259 OUStringBuffer msStringBuffer;
260 OUString msString;
262 // members filled by InitRangeSegmentationProperties (retrieved from DataProvider)
263 bool mbHasSeriesLabels;
264 bool mbHasCategoryLabels; //if the categories are only automatically generated this will be false
265 bool mbRowSourceColumns;
266 OUString msChartAddress;
267 OUString msTableNumberList;
268 ::com::sun::star::uno::Sequence< sal_Int32 > maSequenceMapping;
270 OUString msCLSID;
272 OUString maSrcShellID;
273 OUString maDestShellID;
275 ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes > mxAdditionalShapes;
277 tDataSequenceCont m_aDataSequencesToExport;
278 OUString maCategoriesRange;
281 namespace
284 class lcl_MatchesRole : public ::std::unary_function< Reference< chart2::data::XLabeledDataSequence >, bool >
286 public:
287 explicit lcl_MatchesRole( const OUString & aRole ) :
288 m_aRole( aRole )
291 bool operator () ( const Reference< chart2::data::XLabeledDataSequence > & xSeq ) const
293 if( !xSeq.is() )
294 return false;
295 Reference< beans::XPropertySet > xProp( xSeq->getValues(), uno::UNO_QUERY );
296 OUString aRole;
298 return ( xProp.is() &&
299 (xProp->getPropertyValue( "Role" ) >>= aRole ) &&
300 m_aRole.equals( aRole ));
303 private:
304 OUString m_aRole;
307 template< typename T >
308 void lcl_SequenceToVectorAppend( const Sequence< T > & rSource, ::std::vector< T > & rDestination )
310 rDestination.reserve( rDestination.size() + rSource.getLength());
311 ::std::copy( rSource.getConstArray(), rSource.getConstArray() + rSource.getLength(),
312 ::std::back_inserter( rDestination ));
315 template< typename T >
316 void lcl_SequenceToVector( const Sequence< T > & rSource, ::std::vector< T > & rDestination )
318 rDestination.clear();
319 lcl_SequenceToVectorAppend( rSource, rDestination );
322 Reference< chart2::data::XLabeledDataSequence > lcl_getCategories( const Reference< chart2::XDiagram > & xDiagram )
324 Reference< chart2::data::XLabeledDataSequence > xResult;
327 Reference< chart2::XCoordinateSystemContainer > xCooSysCnt(
328 xDiagram, uno::UNO_QUERY_THROW );
329 Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq(
330 xCooSysCnt->getCoordinateSystems());
331 for( sal_Int32 i=0; i<aCooSysSeq.getLength(); ++i )
333 Reference< chart2::XCoordinateSystem > xCooSys( aCooSysSeq[i] );
334 SAL_WARN_IF( !xCooSys.is(), "xmloff.chart", "xCooSys is NULL" );
335 for( sal_Int32 nN = xCooSys->getDimension(); nN--; )
337 const sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nN);
338 for(sal_Int32 nI=0; nI<=nMaxAxisIndex; ++nI)
340 Reference< chart2::XAxis > xAxis = xCooSys->getAxisByDimension( nN, nI );
341 SAL_WARN_IF( !xAxis.is(), "xmloff.chart", "xAxis is NULL");
342 if( xAxis.is())
344 chart2::ScaleData aScaleData = xAxis->getScaleData();
345 if( aScaleData.Categories.is())
347 xResult.set( aScaleData.Categories );
348 break;
355 catch( const uno::Exception & ex )
357 SAL_WARN("xmloff.chart", "Exception caught. Type: " << OUString::createFromAscii( typeid( ex ).name()) << ", Message: " << ex.Message);
360 return xResult;
363 Reference< chart2::data::XDataSource > lcl_createDataSource(
364 const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aData )
366 Reference< uno::XComponentContext > xContext(
367 comphelper::getProcessComponentContext() );
368 Reference< chart2::data::XDataSink > xSink(
369 xContext->getServiceManager()->createInstanceWithContext(
370 "com.sun.star.chart2.data.DataSource", xContext ),
371 uno::UNO_QUERY_THROW );
372 xSink->setData( aData );
374 return Reference< chart2::data::XDataSource >( xSink, uno::UNO_QUERY );
377 Sequence< Reference< chart2::data::XLabeledDataSequence > > lcl_getAllSeriesSequences( const Reference< chart2::XChartDocument >& xChartDoc )
379 ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aContainer;
380 if( xChartDoc.is() )
382 Reference< chart2::XDiagram > xDiagram( xChartDoc->getFirstDiagram());
383 ::std::vector< Reference< chart2::XDataSeries > > aSeriesVector( SchXMLSeriesHelper::getDataSeriesFromDiagram( xDiagram ));
384 for( ::std::vector< Reference< chart2::XDataSeries > >::const_iterator aSeriesIt( aSeriesVector.begin() )
385 ; aSeriesIt != aSeriesVector.end(); ++aSeriesIt )
387 Reference< chart2::data::XDataSource > xDataSource( *aSeriesIt, uno::UNO_QUERY );
388 if( !xDataSource.is() )
389 continue;
390 uno::Sequence< Reference< chart2::data::XLabeledDataSequence > > aDataSequences( xDataSource->getDataSequences() );
391 lcl_SequenceToVectorAppend( aDataSequences, aContainer );
395 Sequence< Reference< chart2::data::XLabeledDataSequence > > aRet( aContainer.size());
396 ::std::copy( aContainer.begin(), aContainer.end(), aRet.getArray());
398 return aRet;
401 Reference< chart2::data::XLabeledDataSequence >
402 lcl_getDataSequenceByRole(
403 const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aLabeledSeq,
404 const OUString & rRole )
406 Reference< chart2::data::XLabeledDataSequence > aNoResult;
408 const Reference< chart2::data::XLabeledDataSequence > * pBegin = aLabeledSeq.getConstArray();
409 const Reference< chart2::data::XLabeledDataSequence > * pEnd = pBegin + aLabeledSeq.getLength();
410 const Reference< chart2::data::XLabeledDataSequence > * pMatch =
411 ::std::find_if( pBegin, pEnd, lcl_MatchesRole( rRole ));
413 if( pMatch != pEnd )
414 return *pMatch;
416 return aNoResult;
419 Reference< chart2::data::XDataSource > lcl_pressUsedDataIntoRectangularFormat( const Reference< chart2::XChartDocument >& xChartDoc, bool& rOutSourceHasCategoryLabels )
421 ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aLabeledSeqVector;
423 //categories are always the first sequence
424 Reference< chart2::XDiagram > xDiagram( xChartDoc->getFirstDiagram());
425 Reference< chart2::data::XLabeledDataSequence > xCategories( lcl_getCategories( xDiagram ) );
426 if( xCategories.is() )
427 aLabeledSeqVector.push_back( xCategories );
428 rOutSourceHasCategoryLabels = xCategories.is();
430 Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeriesSeqVector(
431 lcl_getAllSeriesSequences( xChartDoc ) );
433 //the first x-values is always the next sequence //todo ... other x-values get lost for old format
434 Reference< chart2::data::XLabeledDataSequence > xXValues(
435 lcl_getDataSequenceByRole( aSeriesSeqVector, OUString( "values-x" ) ) );
436 if( xXValues.is() )
437 aLabeledSeqVector.push_back( xXValues );
439 //add all other sequences now without x-values
440 lcl_MatchesRole aHasXValues( OUString( "values-x" ) );
441 for( sal_Int32 nN=0; nN<aSeriesSeqVector.getLength(); nN++ )
443 if( !aHasXValues( aSeriesSeqVector[nN] ) )
444 aLabeledSeqVector.push_back( aSeriesSeqVector[nN] );
447 Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeq( aLabeledSeqVector.size() );
448 ::std::copy( aLabeledSeqVector.begin(), aLabeledSeqVector.end(), aSeq.getArray() );
450 return lcl_createDataSource( aSeq );
453 bool lcl_isSeriesAttachedToFirstAxis(
454 const Reference< chart2::XDataSeries > & xDataSeries )
456 bool bResult=true;
460 sal_Int32 nAxisIndex = 0;
461 Reference< beans::XPropertySet > xProp( xDataSeries, uno::UNO_QUERY_THROW );
462 if( xProp.is() )
463 xProp->getPropertyValue("AttachedAxisIndex") >>= nAxisIndex;
464 bResult = (0==nAxisIndex);
466 catch( const uno::Exception & ex )
468 SAL_WARN("xmloff.chart", "Exception caught. Type: " << OUString::createFromAscii( typeid( ex ).name()) << ", Message: " << ex.Message);
471 return bResult;
474 OUString lcl_ConvertRange( const OUString & rRange, const Reference< chart2::XChartDocument > & xDoc )
476 OUString aResult = rRange;
477 if( !xDoc.is() )
478 return aResult;
479 Reference< chart2::data::XRangeXMLConversion > xConversion(
480 xDoc->getDataProvider(), uno::UNO_QUERY );
481 if( xConversion.is())
482 aResult = xConversion->convertRangeToXML( rRange );
483 return aResult;
486 typedef ::std::pair< OUString, OUString > tLabelAndValueRange;
488 tLabelAndValueRange lcl_getLabelAndValueRangeByRole(
489 const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aSeqCnt,
490 const OUString & rRole,
491 const Reference< chart2::XChartDocument > & xDoc,
492 SchXMLExportHelper_Impl::tDataSequenceCont & rOutSequencesToExport )
494 tLabelAndValueRange aResult;
496 Reference< chart2::data::XLabeledDataSequence > xLabeledSeq(
497 lcl_getDataSequenceByRole( aSeqCnt, rRole ));
498 if( xLabeledSeq.is())
500 Reference< chart2::data::XDataSequence > xLabelSeq( xLabeledSeq->getLabel());
501 if( xLabelSeq.is())
502 aResult.first = lcl_ConvertRange( xLabelSeq->getSourceRangeRepresentation(), xDoc );
504 Reference< chart2::data::XDataSequence > xValueSeq( xLabeledSeq->getValues());
505 if( xValueSeq.is())
506 aResult.second = lcl_ConvertRange( xValueSeq->getSourceRangeRepresentation(), xDoc );
508 if( xLabelSeq.is() || xValueSeq.is())
509 rOutSequencesToExport.push_back( SchXMLExportHelper_Impl::tLabelValuesDataPair( xLabelSeq, xValueSeq ));
512 return aResult;
515 sal_Int32 lcl_getSequenceLengthByRole(
516 const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aSeqCnt,
517 const OUString & rRole )
519 Reference< chart2::data::XLabeledDataSequence > xLabeledSeq(
520 lcl_getDataSequenceByRole( aSeqCnt, rRole ));
521 if( xLabeledSeq.is())
523 Reference< chart2::data::XDataSequence > xSeq( xLabeledSeq->getValues());
524 return xSeq->getData().getLength();
526 return 0;
529 OUString lcl_flattenStringSequence( const Sequence< OUString > & rSequence )
531 OUStringBuffer aResult;
532 bool bPrecedeWithSpace = false;
533 for( sal_Int32 nIndex=0; nIndex<rSequence.getLength(); ++nIndex )
535 if( !rSequence[nIndex].isEmpty())
537 if( bPrecedeWithSpace )
538 aResult.append( ' ' );
539 aResult.append( rSequence[nIndex] );
540 bPrecedeWithSpace = true;
543 return aResult.makeStringAndClear();
546 void lcl_getLabelStringSequence( Sequence< OUString >& rOutLabels, const Reference< chart2::data::XDataSequence > & xLabelSeq )
548 uno::Reference< chart2::data::XTextualDataSequence > xTextualDataSequence( xLabelSeq, uno::UNO_QUERY );
549 if( xTextualDataSequence.is())
551 rOutLabels = xTextualDataSequence->getTextualData();
553 else if( xLabelSeq.is())
555 Sequence< uno::Any > aAnies( xLabelSeq->getData());
556 rOutLabels.realloc( aAnies.getLength());
557 for( sal_Int32 i=0; i<aAnies.getLength(); ++i )
558 aAnies[i] >>= rOutLabels[i];
562 sal_Int32 lcl_getMaxSequenceLength(
563 const SchXMLExportHelper_Impl::tDataSequenceCont & rContainer )
565 sal_Int32 nResult = 0;
566 for( SchXMLExportHelper_Impl::tDataSequenceCont::const_iterator aIt( rContainer.begin());
567 aIt != rContainer.end(); ++aIt )
569 if( aIt->second.is())
571 sal_Int32 nSeqLength = aIt->second->getData().getLength();
572 if( nSeqLength > nResult )
573 nResult = nSeqLength;
576 return nResult;
579 uno::Sequence< OUString > lcl_DataSequenceToStringSequence(
580 const uno::Reference< chart2::data::XDataSequence >& xDataSequence )
582 uno::Sequence< OUString > aResult;
583 if(!xDataSequence.is())
584 return aResult;
586 uno::Reference< chart2::data::XTextualDataSequence > xTextualDataSequence( xDataSequence, uno::UNO_QUERY );
587 if( xTextualDataSequence.is() )
589 aResult = xTextualDataSequence->getTextualData();
591 else
593 uno::Sequence< uno::Any > aValues = xDataSequence->getData();
594 aResult.realloc(aValues.getLength());
596 for(sal_Int32 nN=aValues.getLength();nN--;)
597 aValues[nN] >>= aResult[nN];
600 return aResult;
602 ::std::vector< double > lcl_getAllValuesFromSequence( const Reference< chart2::data::XDataSequence > & xSeq )
604 double fNan = 0.0;
605 ::rtl::math::setNan( &fNan );
606 ::std::vector< double > aResult;
607 if(!xSeq.is())
608 return aResult;
610 uno::Sequence< double > aValuesSequence;
611 Reference< chart2::data::XNumericalDataSequence > xNumSeq( xSeq, uno::UNO_QUERY );
612 if( xNumSeq.is() )
614 aValuesSequence = xNumSeq->getNumericalData();
616 else
618 Sequence< uno::Any > aAnies( xSeq->getData() );
619 aValuesSequence.realloc( aAnies.getLength() );
620 for( sal_Int32 i=0; i<aAnies.getLength(); ++i )
621 aAnies[i] >>= aValuesSequence[i];
624 //special handling for x-values (if x-values do point to categories, indices are used instead )
625 Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY );
626 if( xProp.is() )
628 OUString aRole;
629 xProp->getPropertyValue("Role") >>= aRole;
630 if( aRole.match( OUString( "values-x" ) ) )
632 //lcl_clearIfNoValuesButTextIsContained - replace by indices if the values are not appropriate
633 bool bHasValue=false;
634 bool bHasText=false;
635 sal_Int32 nCount = aValuesSequence.getLength();
636 for( sal_Int32 j = 0; j < nCount; ++j )
638 if( !::rtl::math::isNan( aValuesSequence[j] ) )
640 bHasValue=true;
641 break;
644 if(!bHasValue)
646 //no double value is countained
647 //is there any text?
648 uno::Sequence< OUString > aStrings( lcl_DataSequenceToStringSequence( xSeq ) );
649 sal_Int32 nTextCount = aStrings.getLength();
650 for( sal_Int32 j = 0; j < nTextCount; ++j )
652 if( !aStrings[j].isEmpty() )
654 bHasText=true;
655 break;
659 if( !bHasValue && bHasText )
661 for( sal_Int32 j = 0; j < nCount; ++j )
662 aValuesSequence[j] = j+1;
667 ::std::copy( aValuesSequence.getConstArray(), aValuesSequence.getConstArray() + aValuesSequence.getLength(),
668 ::std::back_inserter( aResult ));
669 return aResult;
672 bool lcl_SequenceHasUnhiddenData( const uno::Reference< chart2::data::XDataSequence >& xDataSequence )
674 if( !xDataSequence.is() )
675 return false;
676 uno::Reference< beans::XPropertySet > xProp( xDataSequence, uno::UNO_QUERY );
677 if( xProp.is() )
679 uno::Sequence< sal_Int32 > aHiddenValues;
682 xProp->getPropertyValue("HiddenValues") >>= aHiddenValues;
683 if( !aHiddenValues.getLength() )
684 return true;
686 catch( const uno::Exception& )
688 return true;
691 if( xDataSequence->getData().getLength() )
692 return true;
693 return false;
696 typedef vector< OUString > tStringVector;
697 typedef vector< vector< double > > t2DNumberContainer;
699 struct lcl_TableData
701 t2DNumberContainer aDataInRows;
702 tStringVector aDataRangeRepresentations;
704 tStringVector aColumnDescriptions;
705 tStringVector aColumnDescriptions_Ranges;
707 tStringVector aRowDescriptions;
708 tStringVector aRowDescriptions_Ranges;
710 Sequence< Sequence< uno::Any > > aComplexColumnDescriptions;//outer index is columns - inner index is level
711 Sequence< Sequence< uno::Any > > aComplexRowDescriptions;//outer index is rows - inner index is level
713 ::std::vector< sal_Int32 > aHiddenColumns;
716 // ::std::bind2nd( ::std::mem_fun_ref( &T::resize ), nSize ) does not work
717 template< class T >
718 struct lcl_resize
720 lcl_resize( typename T::size_type nSize, typename T::value_type fDefaultValue ) : m_nSize( nSize ), m_fDefaultValue( fDefaultValue ) {}
721 void operator()( T & t )
722 { t.resize( m_nSize, m_fDefaultValue ); }
723 private:
724 typename T::size_type m_nSize;
725 typename T::value_type m_fDefaultValue;
728 typedef ::std::map< sal_Int32, SchXMLExportHelper_Impl::tLabelValuesDataPair >
729 lcl_DataSequenceMap;
731 struct lcl_SequenceToMapElement :
732 public ::std::unary_function< lcl_DataSequenceMap::mapped_type, lcl_DataSequenceMap::value_type >
734 lcl_SequenceToMapElement()
736 result_type operator() ( const argument_type & rContent )
738 sal_Int32 nIndex = -1;
739 if( rContent.second.is()) //has values
741 OUString aRangeRep( rContent.second->getSourceRangeRepresentation());
742 nIndex = aRangeRep.toInt32();
744 else if( rContent.first.is()) //has labels
745 nIndex = rContent.first->getSourceRangeRepresentation().copy( sizeof("label ")).toInt32();
746 return result_type( nIndex, rContent );
750 void lcl_ReorderInternalSequencesAccordingToTheirRangeName(
751 SchXMLExportHelper_Impl::tDataSequenceCont & rInOutSequences )
753 lcl_DataSequenceMap aIndexSequenceMap;
754 ::std::transform( rInOutSequences.begin(), rInOutSequences.end(),
755 ::std::inserter( aIndexSequenceMap, aIndexSequenceMap.begin()),
756 lcl_SequenceToMapElement());
758 rInOutSequences.clear();
759 sal_Int32 nIndex = 0;
760 for( lcl_DataSequenceMap::const_iterator aIt = aIndexSequenceMap.begin();
761 aIt != aIndexSequenceMap.end(); ++aIt, ++nIndex )
763 if( aIt->first < 0 )
764 continue;
765 // fill empty columns
766 for( ; nIndex < aIt->first; ++nIndex )
767 rInOutSequences.push_back(
768 SchXMLExportHelper_Impl::tDataSequenceCont::value_type(
769 uno::Reference< chart2::data::XDataSequence >(),
770 uno::Reference< chart2::data::XDataSequence >() ));
771 OSL_ASSERT( nIndex == aIt->first );
772 rInOutSequences.push_back( aIt->second );
776 lcl_TableData lcl_getDataForLocalTable(
777 const SchXMLExportHelper_Impl::tDataSequenceCont & aSequencesToExport,
778 const Reference< chart2::XAnyDescriptionAccess >& xAnyDescriptionAccess,
779 const OUString& rCategoriesRange,
780 bool bSeriesFromColumns,
781 const Reference< chart2::data::XRangeXMLConversion > & xRangeConversion )
783 lcl_TableData aResult;
787 Sequence< OUString > aSimpleCategories;
788 if( xAnyDescriptionAccess.is() )
790 //categories
791 if( bSeriesFromColumns )
793 aSimpleCategories = xAnyDescriptionAccess->getRowDescriptions();
794 aResult.aComplexRowDescriptions = xAnyDescriptionAccess->getAnyRowDescriptions();
796 else
798 aSimpleCategories = xAnyDescriptionAccess->getColumnDescriptions();
799 aResult.aComplexColumnDescriptions = xAnyDescriptionAccess->getAnyColumnDescriptions();
803 //series values and series labels
804 SchXMLExportHelper_Impl::tDataSequenceCont::size_type nNumSequences = aSequencesToExport.size();
805 SchXMLExportHelper_Impl::tDataSequenceCont::const_iterator aBegin( aSequencesToExport.begin());
806 SchXMLExportHelper_Impl::tDataSequenceCont::const_iterator aEnd( aSequencesToExport.end());
807 SchXMLExportHelper_Impl::tDataSequenceCont::const_iterator aIt( aBegin );
809 size_t nMaxSequenceLength( lcl_getMaxSequenceLength( aSequencesToExport ));
810 size_t nCategoriesLength( aSimpleCategories.getLength() );
811 if( nCategoriesLength > nMaxSequenceLength )
813 aSimpleCategories.realloc(nMaxSequenceLength);//#i110617#
814 nCategoriesLength = nMaxSequenceLength;
816 size_t nNumColumns( bSeriesFromColumns ? nNumSequences : nMaxSequenceLength );
817 size_t nNumRows( bSeriesFromColumns ? nMaxSequenceLength : nNumSequences );
819 // resize data
820 aResult.aDataInRows.resize( nNumRows );
821 double fNan = 0.0;
822 ::rtl::math::setNan( &fNan );
823 ::std::for_each( aResult.aDataInRows.begin(), aResult.aDataInRows.end(),
824 lcl_resize< t2DNumberContainer::value_type >( nNumColumns, fNan ));
825 aResult.aColumnDescriptions.resize( nNumColumns );
826 aResult.aComplexColumnDescriptions.realloc( nNumColumns );
827 aResult.aRowDescriptions.resize( nNumRows );
828 aResult.aComplexRowDescriptions.realloc( nNumRows );
830 tStringVector& rCategories = bSeriesFromColumns ? aResult.aRowDescriptions : aResult.aColumnDescriptions;
831 tStringVector& rLabels = bSeriesFromColumns ? aResult.aColumnDescriptions : aResult.aRowDescriptions;
833 //categories
834 lcl_SequenceToVector( aSimpleCategories, rCategories );
835 if( !rCategoriesRange.isEmpty() )
837 OUString aRange(rCategoriesRange);
838 if( xRangeConversion.is())
839 aRange = xRangeConversion->convertRangeToXML( aRange );
840 if( bSeriesFromColumns )
841 aResult.aRowDescriptions_Ranges.push_back( aRange );
842 else
843 aResult.aColumnDescriptions_Ranges.push_back( aRange );
846 // iterate over all sequences
847 size_t nSeqIdx = 0;
848 Sequence< Sequence< OUString > > aComplexLabels(nNumSequences);
849 for( ; aIt != aEnd; ++aIt, ++nSeqIdx )
851 OUString aRange;
852 Sequence< OUString >& rCurrentComplexLabel = aComplexLabels[nSeqIdx];
853 if( aIt->first.is())
855 lcl_getLabelStringSequence( rCurrentComplexLabel, aIt->first );
856 rLabels[nSeqIdx] = lcl_flattenStringSequence( rCurrentComplexLabel );
857 aRange = aIt->first->getSourceRangeRepresentation();
858 if( xRangeConversion.is())
859 aRange = xRangeConversion->convertRangeToXML( aRange );
861 else if( aIt->second.is())
863 rCurrentComplexLabel.realloc(1);
864 rLabels[nSeqIdx] = rCurrentComplexLabel[0] = lcl_flattenStringSequence(
865 aIt->second->generateLabel( chart2::data::LabelOrigin_SHORT_SIDE ));
867 if( bSeriesFromColumns )
868 aResult.aColumnDescriptions_Ranges.push_back( aRange );
869 else
870 aResult.aRowDescriptions_Ranges.push_back( aRange );
872 ::std::vector< double > aNumbers( lcl_getAllValuesFromSequence( aIt->second ));
873 if( bSeriesFromColumns )
875 const sal_Int32 nSize( static_cast< sal_Int32 >( aNumbers.size()));
876 for( sal_Int32 nIdx=0; nIdx<nSize; ++nIdx )
877 aResult.aDataInRows[nIdx][nSeqIdx] = aNumbers[nIdx];
879 else
880 aResult.aDataInRows[nSeqIdx] = aNumbers;
882 if( aIt->second.is())
884 aRange = aIt->second->getSourceRangeRepresentation();
885 if( xRangeConversion.is())
886 aRange = xRangeConversion->convertRangeToXML( aRange );
888 aResult.aDataRangeRepresentations.push_back( aRange );
890 //is column hidden?
891 if( !lcl_SequenceHasUnhiddenData(aIt->first) && !lcl_SequenceHasUnhiddenData(aIt->second) )
892 aResult.aHiddenColumns.push_back(nSeqIdx);
894 Sequence< Sequence< Any > >& rComplexAnyLabels = bSeriesFromColumns ? aResult.aComplexColumnDescriptions : aResult.aComplexRowDescriptions;//#i116544#
895 rComplexAnyLabels.realloc(aComplexLabels.getLength());
896 for( sal_Int32 nN=0; nN<aComplexLabels.getLength();nN++ )
898 Sequence< OUString >& rSource = aComplexLabels[nN];
899 Sequence< Any >& rTarget = rComplexAnyLabels[nN];
900 rTarget.realloc( rSource.getLength() );
901 for( sal_Int32 i=0; i<rSource.getLength(); i++ )
902 rTarget[i] = uno::makeAny( rSource[i] );
905 catch( const uno::Exception & rEx )
907 SAL_INFO("xmloff.chart", "something went wrong during table data collection: " << rEx.Message);
910 return aResult;
913 void lcl_exportNumberFormat( const OUString& rPropertyName, const Reference< beans::XPropertySet >& xPropSet,
914 SvXMLExport& rExport )
916 if( xPropSet.is())
918 sal_Int32 nNumberFormat = 0;
919 Any aNumAny = xPropSet->getPropertyValue( rPropertyName );
920 if( (aNumAny >>= nNumberFormat) && (nNumberFormat != -1) )
921 rExport.addDataStyle( nNumberFormat );
925 ::std::vector< Reference< chart2::data::XDataSequence > >
926 lcl_getErrorBarSequences( const Reference< beans::XPropertySet > & xErrorBarProp )
928 ::std::vector< Reference< chart2::data::XDataSequence > > aResult;
929 Reference< chart2::data::XDataSource > xErrorBarDataSource( xErrorBarProp, uno::UNO_QUERY );
930 if( !xErrorBarDataSource.is())
931 return aResult;
933 const OUString aRolePrefix( "error-bars-" );
935 Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences(
936 xErrorBarDataSource->getDataSequences());
937 for( sal_Int32 nI=0; nI< aSequences.getLength(); ++nI )
941 if( aSequences[nI].is())
943 Reference< chart2::data::XDataSequence > xSequence( aSequences[nI]->getValues());
944 Reference< beans::XPropertySet > xSeqProp( xSequence, uno::UNO_QUERY_THROW );
945 OUString aRole;
946 if( ( xSeqProp->getPropertyValue(
947 OUString( "Role" )) >>= aRole ) &&
948 aRole.match( aRolePrefix ))
950 aResult.push_back( xSequence );
954 catch( const uno::Exception & rEx )
956 OString aBStr(OUStringToOString(rEx.Message, RTL_TEXTENCODING_ASCII_US));
957 SAL_INFO("xmloff.chart", "chart:exporting error bar ranges: " << aBStr );
961 return aResult;
964 bool lcl_exportDomainForThisSequence( const Reference< chart2::data::XDataSequence >& rValues, OUString& rFirstRangeForThisDomainIndex, SvXMLExport& rExport )
966 bool bDomainExported = false;
967 if( rValues.is())
969 Reference< chart2::XChartDocument > xNewDoc( rExport.GetModel(), uno::UNO_QUERY );
970 OUString aRange( lcl_ConvertRange( rValues->getSourceRangeRepresentation(), xNewDoc ) );
972 //work around error in OOo 2.0 (problems with multiple series having a domain element)
973 if( rFirstRangeForThisDomainIndex.isEmpty() || !aRange.equals(rFirstRangeForThisDomainIndex) )
975 rExport.AddAttribute( XML_NAMESPACE_TABLE, XML_CELL_RANGE_ADDRESS, aRange);
976 SvXMLElementExport aDomain( rExport, XML_NAMESPACE_CHART, XML_DOMAIN, true, true );
977 bDomainExported = true;
980 if( rFirstRangeForThisDomainIndex.isEmpty() )
981 rFirstRangeForThisDomainIndex = aRange;
983 return bDomainExported;
986 } // anonymous namespace
988 struct SchXMLDataPointStruct
990 OUString maStyleName;
991 sal_Int32 mnRepeat;
993 SchXMLDataPointStruct() : mnRepeat( 1 ) {}
996 // class SchXMLExportHelper
998 SchXMLExportHelper::SchXMLExportHelper( SvXMLExport& rExport, SvXMLAutoStylePoolP& rASPool )
999 : m_pImpl( new SchXMLExportHelper_Impl( rExport, rASPool ) )
1003 SchXMLExportHelper::~SchXMLExportHelper()
1005 delete m_pImpl;
1008 const OUString& SchXMLExportHelper::getChartCLSID()
1010 return m_pImpl->msCLSID;
1013 void SchXMLExportHelper::SetSourceShellID( const OUString& rShellID )
1015 m_pImpl->maSrcShellID = rShellID;
1018 void SchXMLExportHelper::SetDestinationShellID( const OUString& rShellID )
1020 m_pImpl->maDestShellID = rShellID;
1023 rtl::Reference< XMLPropertySetMapper > SchXMLExportHelper_Impl::GetPropertySetMapper() const
1025 return mxPropertySetMapper;
1028 void SchXMLExportHelper_Impl::exportAutoStyles()
1030 if( mxExpPropMapper.is())
1032 //ToDo: when embedded in calc/writer this is not necessary because the
1033 // numberformatter is shared between both documents
1034 mrExport.exportAutoDataStyles();
1036 // export chart auto styles
1037 mrAutoStylePool.exportXML(
1038 XML_STYLE_FAMILY_SCH_CHART_ID
1039 , mrExport.GetDocHandler(),
1040 mrExport.GetMM100UnitConverter(),
1041 mrExport.GetNamespaceMap()
1044 // export auto styles for additional shapes
1045 mrExport.GetShapeExport()->exportAutoStyles();
1046 // and for text in additional shapes
1047 mrExport.GetTextParagraphExport()->exportTextAutoStyles();
1051 // private methods
1053 SchXMLExportHelper_Impl::SchXMLExportHelper_Impl(
1054 SvXMLExport& rExport,
1055 SvXMLAutoStylePoolP& rASPool ) :
1056 mrExport( rExport ),
1057 mrAutoStylePool( rASPool ),
1058 mbHasSeriesLabels( false ),
1059 mbHasCategoryLabels( false ),
1060 mbRowSourceColumns( true ),
1061 msCLSID( OUString( SvGlobalName( SO3_SCH_CLASSID ).GetHexName()))
1063 msTableName = "local-table";
1065 // create property set mapper
1066 mxPropertySetMapper = new XMLChartPropertySetMapper( true);
1067 mxExpPropMapper = new XMLChartExportPropertyMapper( mxPropertySetMapper, rExport );
1069 // register chart auto-style family
1070 mrAutoStylePool.AddFamily(
1071 XML_STYLE_FAMILY_SCH_CHART_ID,
1072 OUString( XML_STYLE_FAMILY_SCH_CHART_NAME ),
1073 mxExpPropMapper.get(),
1074 OUString( XML_STYLE_FAMILY_SCH_CHART_PREFIX ));
1076 // register shape family
1077 mrAutoStylePool.AddFamily(
1078 XML_STYLE_FAMILY_SD_GRAPHICS_ID,
1079 OUString( XML_STYLE_FAMILY_SD_GRAPHICS_NAME ),
1080 mxExpPropMapper.get(),
1081 OUString( XML_STYLE_FAMILY_SD_GRAPHICS_PREFIX ));
1082 // register paragraph family also for shapes
1083 mrAutoStylePool.AddFamily(
1084 XML_STYLE_FAMILY_TEXT_PARAGRAPH,
1085 GetXMLToken( XML_PARAGRAPH ),
1086 mxExpPropMapper.get(),
1087 OUString( 'P' ));
1088 // register text family also for shapes
1089 mrAutoStylePool.AddFamily(
1090 XML_STYLE_FAMILY_TEXT_TEXT,
1091 GetXMLToken( XML_TEXT ),
1092 mxExpPropMapper.get(),
1093 OUString( 'T' ));
1096 SchXMLExportHelper_Impl::~SchXMLExportHelper_Impl()
1100 void SchXMLExportHelper_Impl::collectAutoStyles( Reference< chart::XChartDocument > rChartDoc )
1102 parseDocument( rChartDoc, false );
1105 void SchXMLExportHelper_Impl::exportChart( Reference< chart::XChartDocument > rChartDoc,
1106 bool bIncludeTable )
1108 parseDocument( rChartDoc, true, bIncludeTable );
1109 SAL_WARN_IF( !maAutoStyleNameQueue.empty(), "xmloff.chart", "There are still remaining autostyle names in the queue" );
1112 static OUString lcl_GetStringFromNumberSequence( const ::com::sun::star::uno::Sequence< sal_Int32 >& rSequenceMapping, bool bRemoveOneFromEachIndex /*should be true if having categories*/ )
1114 const sal_Int32* pArray = rSequenceMapping.getConstArray();
1115 const sal_Int32 nSize = rSequenceMapping.getLength();
1116 sal_Int32 i = 0;
1117 OUStringBuffer aBuf;
1118 bool bHasPredecessor = false;
1119 for( i = 0; i < nSize; ++i )
1121 sal_Int32 nIndex = pArray[ i ];
1122 if( bRemoveOneFromEachIndex )
1123 --nIndex;
1124 if(nIndex>=0)
1126 if(bHasPredecessor)
1127 aBuf.append( ' ' );
1128 aBuf.append( nIndex, 10 );
1129 bHasPredecessor = true;
1132 return aBuf.makeStringAndClear();
1135 /// if bExportContent is false the auto-styles are collected
1136 void SchXMLExportHelper_Impl::parseDocument( Reference< chart::XChartDocument >& rChartDoc,
1137 bool bExportContent,
1138 bool bIncludeTable )
1140 Reference< chart2::XChartDocument > xNewDoc( rChartDoc, uno::UNO_QUERY );
1141 if( !rChartDoc.is() || !xNewDoc.is() )
1143 SAL_WARN("xmloff.chart", "No XChartDocument was given for export." );
1144 return;
1147 mxExpPropMapper->setChartDoc(xNewDoc);
1149 awt::Size aPageSize( getPageSize( xNewDoc ));
1150 if( bExportContent )
1151 addSize( aPageSize );
1152 Reference< chart::XDiagram > xDiagram = rChartDoc->getDiagram();
1153 Reference< chart2::XDiagram > xNewDiagram;
1154 if( xNewDoc.is())
1155 xNewDiagram.set( xNewDoc->getFirstDiagram());
1157 //todo remove if model changes are notified and view is updated automatically
1158 if( bExportContent )
1160 Reference< util::XRefreshable > xRefreshable( xNewDoc, uno::UNO_QUERY );
1161 if( xRefreshable.is() )
1162 xRefreshable->refresh();
1165 // get Properties of ChartDocument
1166 bool bHasMainTitle = false;
1167 bool bHasSubTitle = false;
1168 bool bHasLegend = false;
1169 util::DateTime aNullDate(0,0,0,0,30,12,1899, false);
1171 std::vector< XMLPropertyState > aPropertyStates;
1173 Reference< beans::XPropertySet > xDocPropSet( rChartDoc, uno::UNO_QUERY );
1174 if( xDocPropSet.is())
1178 Any aAny = xDocPropSet->getPropertyValue("HasMainTitle");
1179 aAny >>= bHasMainTitle;
1180 aAny = xDocPropSet->getPropertyValue("HasSubTitle");
1181 aAny >>= bHasSubTitle;
1182 aAny = xDocPropSet->getPropertyValue("HasLegend");
1183 aAny >>= bHasLegend;
1184 if ( bIncludeTable )
1186 aAny = xDocPropSet->getPropertyValue("NullDate");
1187 if ( !aAny.hasValue() )
1189 Reference<container::XChild> xChild(rChartDoc, uno::UNO_QUERY );
1190 if ( xChild.is() )
1192 Reference< beans::XPropertySet > xParentDoc( xChild->getParent(),uno::UNO_QUERY);
1193 if ( xParentDoc.is() && xParentDoc->getPropertySetInfo()->hasPropertyByName("NullDate") )
1194 aAny = xParentDoc->getPropertyValue("NullDate");
1198 aAny >>= aNullDate;
1201 catch( const beans::UnknownPropertyException & )
1203 SAL_WARN("xmloff.chart", "Required property not found in ChartDocument" );
1207 if ( bIncludeTable && (aNullDate.Day != 30 || aNullDate.Month != 12 || aNullDate.Year != 1899 ) )
1209 SvXMLElementExport aSet( mrExport, XML_NAMESPACE_TABLE, XML_CALCULATION_SETTINGS, true, true );
1211 OUStringBuffer sBuffer;
1212 ::sax::Converter::convertDateTime(sBuffer, aNullDate, 0);
1213 mrExport.AddAttribute( XML_NAMESPACE_TABLE,XML_DATE_VALUE,sBuffer.makeStringAndClear());
1214 SvXMLElementExport aNull( mrExport, XML_NAMESPACE_TABLE, XML_NULL_DATE, true, true );
1218 // chart element
1219 std::unique_ptr<SvXMLElementExport> xElChart;
1221 // get property states for autostyles
1222 if( mxExpPropMapper.is())
1224 Reference< beans::XPropertySet > xPropSet( rChartDoc->getArea(), uno::UNO_QUERY );
1225 if( xPropSet.is())
1226 aPropertyStates = mxExpPropMapper->Filter( xPropSet );
1229 if( bExportContent )
1231 //export data provider in xlink:href attribute
1232 const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
1233 if( nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 )
1235 OUString aDataProviderURL( ".." );
1236 if( xNewDoc->hasInternalDataProvider() )
1237 aDataProviderURL = ".";
1238 else //special handling for data base data provider necessary
1240 Reference< chart2::data::XDatabaseDataProvider > xDBDataProvider( xNewDoc->getDataProvider(), uno::UNO_QUERY );
1241 if( xDBDataProvider.is() )
1242 aDataProviderURL = ".";
1244 mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, aDataProviderURL );
1245 mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
1248 OUString sChartType( xDiagram->getDiagramType() );
1250 // attributes
1251 // determine class
1252 if( !sChartType.isEmpty())
1254 enum XMLTokenEnum eXMLChartType = SchXMLTools::getTokenByChartType( sChartType, true /* bUseOldNames */ );
1256 SAL_WARN_IF( eXMLChartType == XML_TOKEN_INVALID, "xmloff.chart", "invalid chart class" );
1257 if( eXMLChartType == XML_TOKEN_INVALID )
1258 eXMLChartType = XML_BAR;
1260 if( eXMLChartType == XML_ADD_IN )
1262 // sChartType is the servie-name of the add-in
1263 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_CLASS,
1264 mrExport.GetNamespaceMap().GetQNameByKey(
1265 XML_NAMESPACE_OOO, sChartType) );
1267 else if( eXMLChartType != XML_TOKEN_INVALID )
1269 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_CLASS,
1270 mrExport.GetNamespaceMap().GetQNameByKey(
1271 XML_NAMESPACE_CHART, GetXMLToken(eXMLChartType )) );
1274 //column-mapping or row-mapping
1275 if( maSequenceMapping.getLength() )
1277 enum XMLTokenEnum eTransToken = ::xmloff::token::XML_ROW_MAPPING;
1278 if( mbRowSourceColumns )
1279 eTransToken = ::xmloff::token::XML_COLUMN_MAPPING;
1280 OUString aSequenceMappingStr( lcl_GetStringFromNumberSequence(
1281 maSequenceMapping, mbHasCategoryLabels && !xNewDoc->hasInternalDataProvider() ) );
1283 mrExport.AddAttribute( XML_NAMESPACE_CHART,
1284 ::xmloff::token::GetXMLToken( eTransToken ),
1285 aSequenceMappingStr );
1288 // write style name
1289 AddAutoStyleAttribute( aPropertyStates );
1291 //element
1292 xElChart.reset(new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_CHART, true, true ));
1294 else // autostyles
1296 CollectAutoStyle( aPropertyStates );
1298 // remove property states for autostyles
1299 aPropertyStates.clear();
1301 // title element
1302 if( bHasMainTitle )
1304 // get property states for autostyles
1305 if( mxExpPropMapper.is())
1307 Reference< beans::XPropertySet > xPropSet( rChartDoc->getTitle(), uno::UNO_QUERY );
1308 if( xPropSet.is())
1309 aPropertyStates = mxExpPropMapper->Filter( xPropSet );
1311 if( bExportContent )
1313 Reference< drawing::XShape > xShape = rChartDoc->getTitle();
1314 if( xShape.is()) // && "hasTitleBeenMoved"
1315 addPosition( xShape );
1317 // write style name
1318 AddAutoStyleAttribute( aPropertyStates );
1320 // element
1321 SvXMLElementExport aElTitle( mrExport, XML_NAMESPACE_CHART, XML_TITLE, true, true );
1323 // content (text:p)
1324 Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY );
1325 if( xPropSet.is())
1327 Any aAny( xPropSet->getPropertyValue(
1328 OUString( "String" )));
1329 OUString aText;
1330 aAny >>= aText;
1331 exportText( aText );
1334 else // autostyles
1336 CollectAutoStyle( aPropertyStates );
1338 // remove property states for autostyles
1339 aPropertyStates.clear();
1342 // subtitle element
1343 if( bHasSubTitle )
1345 // get property states for autostyles
1346 if( mxExpPropMapper.is())
1348 Reference< beans::XPropertySet > xPropSet( rChartDoc->getSubTitle(), uno::UNO_QUERY );
1349 if( xPropSet.is())
1350 aPropertyStates = mxExpPropMapper->Filter( xPropSet );
1353 if( bExportContent )
1355 Reference< drawing::XShape > xShape = rChartDoc->getSubTitle();
1356 if( xShape.is())
1357 addPosition( xShape );
1359 // write style name
1360 AddAutoStyleAttribute( aPropertyStates );
1362 // element (has no subelements)
1363 SvXMLElementExport aElSubTitle( mrExport, XML_NAMESPACE_CHART, XML_SUBTITLE, true, true );
1365 // content (text:p)
1366 Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY );
1367 if( xPropSet.is())
1369 Any aAny( xPropSet->getPropertyValue(
1370 OUString( "String" )));
1371 OUString aText;
1372 aAny >>= aText;
1373 exportText( aText );
1376 else // autostyles
1378 CollectAutoStyle( aPropertyStates );
1380 // remove property states for autostyles
1381 aPropertyStates.clear();
1384 // legend element
1385 if( bHasLegend )
1387 // get property states for autostyles
1388 if( mxExpPropMapper.is())
1390 Reference< beans::XPropertySet > xPropSet( rChartDoc->getLegend(), uno::UNO_QUERY );
1391 if( xPropSet.is())
1392 aPropertyStates = mxExpPropMapper->Filter( xPropSet );
1395 if( bExportContent )
1397 Reference< beans::XPropertySet > xProp( rChartDoc->getLegend(), uno::UNO_QUERY );
1398 if( xProp.is())
1400 // export legend anchor position
1403 Any aAny( xProp->getPropertyValue("Alignment"));
1404 if( SchXMLEnumConverter::getLegendPositionConverter().exportXML( msString, aAny, mrExport.GetMM100UnitConverter() ) )
1405 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LEGEND_POSITION, msString );
1407 catch( const beans::UnknownPropertyException & )
1409 SAL_WARN("xmloff.chart", "Property Align not found in ChartLegend" );
1412 // export absolute legend position
1413 Reference< drawing::XShape > xLegendShape( xProp, uno::UNO_QUERY );
1414 addPosition( xLegendShape );
1416 // export legend size
1417 const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
1418 if( xLegendShape.is() && nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 )
1422 chart::ChartLegendExpansion nLegendExpansion = chart::ChartLegendExpansion_HIGH;
1423 OUString aExpansionString;
1424 Any aAny( xProp->getPropertyValue("Expansion"));
1425 bool bHasExpansion = (aAny >>= nLegendExpansion);
1426 if( bHasExpansion && SchXMLEnumConverter::getLegendExpansionConverter().exportXML( aExpansionString, aAny, mrExport.GetMM100UnitConverter() ) )
1428 mrExport.AddAttribute( XML_NAMESPACE_STYLE, XML_LEGEND_EXPANSION, aExpansionString );
1429 if( nLegendExpansion == chart::ChartLegendExpansion_CUSTOM)
1431 awt::Size aSize( xLegendShape->getSize() );
1432 addSize( aSize, true );
1433 OUStringBuffer aAspectRatioString;
1434 ::sax::Converter::convertDouble(
1435 aAspectRatioString,
1436 (aSize.Height == 0
1437 ? 1.0
1438 : double(aSize.Width)/double(aSize.Height)));
1439 mrExport.AddAttribute( XML_NAMESPACE_STYLE, XML_LEGEND_EXPANSION_ASPECT_RATIO, aAspectRatioString.makeStringAndClear() );
1443 catch( const beans::UnknownPropertyException & )
1445 SAL_WARN("xmloff.chart", "Property Expansion not found in ChartLegend" );
1450 // write style name
1451 AddAutoStyleAttribute( aPropertyStates );
1453 // element
1454 SvXMLElementExport aLegend( mrExport, XML_NAMESPACE_CHART, XML_LEGEND, true, true );
1456 else // autostyles
1458 CollectAutoStyle( aPropertyStates );
1460 // remove property states for autostyles
1461 aPropertyStates.clear();
1464 // plot-area element
1465 if( xDiagram.is())
1466 exportPlotArea( xDiagram, xNewDiagram, aPageSize, bExportContent, bIncludeTable );
1468 // export additional shapes
1469 if( xDocPropSet.is() )
1471 if( bExportContent )
1473 if( mxAdditionalShapes.is())
1475 // can't call exportShapes with all shapes because the
1476 // initialisation happened with the complete draw page and not
1477 // the XShapes object used here. Thus the shapes have to be
1478 // exported one by one
1479 rtl::Reference< XMLShapeExport > rShapeExport = mrExport.GetShapeExport();
1480 Reference< drawing::XShape > xShape;
1481 const sal_Int32 nShapeCount( mxAdditionalShapes->getCount());
1482 for( sal_Int32 nShapeId = 0; nShapeId < nShapeCount; nShapeId++ )
1484 mxAdditionalShapes->getByIndex( nShapeId ) >>= xShape;
1485 SAL_WARN_IF( !xShape.is(), "xmloff.chart", "Shape without an XShape?" );
1486 if( ! xShape.is())
1487 continue;
1489 rShapeExport->exportShape( xShape );
1491 // this would be the easier way if it worked:
1492 //mrExport.GetShapeExport()->exportShapes( mxAdditionalShapes );
1495 else
1497 // get a sequence of non-chart shapes (inserted via clipboard)
1500 Any aShapesAny = xDocPropSet->getPropertyValue("AdditionalShapes");
1501 aShapesAny >>= mxAdditionalShapes;
1503 catch( const uno::Exception & rEx )
1505 SAL_INFO("xmloff.chart", "AdditionalShapes not found: " << rEx.Message );
1508 if( mxAdditionalShapes.is())
1510 // seek shapes has to be called for the whole page because in
1511 // the shape export the vector of shapes is accessed via the
1512 // ZOrder which might be (actually is) larger than the number of
1513 // shapes in mxAdditionalShapes
1514 Reference< drawing::XDrawPageSupplier > xSupplier( rChartDoc, uno::UNO_QUERY );
1515 SAL_WARN_IF( !xSupplier.is(), "xmloff.chart", "Cannot retrieve draw page to initialize shape export" );
1516 if( xSupplier.is() )
1518 Reference< drawing::XShapes > xDrawPage( xSupplier->getDrawPage(), uno::UNO_QUERY );
1519 SAL_WARN_IF( !xDrawPage.is(), "xmloff.chart", "Invalid draw page for initializing shape export" );
1520 if( xDrawPage.is())
1521 mrExport.GetShapeExport()->seekShapes( xDrawPage );
1524 // can't call collectShapesAutoStyles with all shapes because
1525 // the initialisation happened with the complete draw page and
1526 // not the XShapes object used here. Thus the shapes have to be
1527 // exported one by one
1528 rtl::Reference< XMLShapeExport > rShapeExport = mrExport.GetShapeExport();
1529 Reference< drawing::XShape > xShape;
1530 const sal_Int32 nShapeCount( mxAdditionalShapes->getCount());
1531 for( sal_Int32 nShapeId = 0; nShapeId < nShapeCount; nShapeId++ )
1533 mxAdditionalShapes->getByIndex( nShapeId ) >>= xShape;
1534 SAL_WARN_IF( !xShape.is(), "xmloff.chart", "Shape without an XShape?" );
1535 if( ! xShape.is())
1536 continue;
1538 rShapeExport->collectShapeAutoStyles( xShape );
1544 // table element
1545 // (is included as subelement of chart)
1546 if( bExportContent )
1548 // #85929# always export table, otherwise clipboard may lose data
1549 exportTable();
1553 static void lcl_exportComplexLabel( const Sequence< uno::Any >& rComplexLabel, SvXMLExport& rExport )
1555 sal_Int32 nLength = rComplexLabel.getLength();
1556 if( nLength<=1 )
1557 return;
1558 SvXMLElementExport aTextList( rExport, XML_NAMESPACE_TEXT, XML_LIST, true, true );
1559 for(sal_Int32 nN=0; nN<nLength; nN++)
1561 SvXMLElementExport aListItem( rExport, XML_NAMESPACE_TEXT, XML_LIST_ITEM, true, true );
1562 OUString aString;
1563 if( !(rComplexLabel[nN]>>=aString) )
1565 //todo?
1567 SchXMLTools::exportText( rExport, aString, false /*bConvertTabsLFs*/ );
1571 void SchXMLExportHelper_Impl::exportTable()
1573 // table element
1574 mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_NAME, msTableName );
1578 bool bProtected = false;
1579 Reference< beans::XPropertySet > xProps( mrExport.GetModel(), uno::UNO_QUERY_THROW );
1580 if ( ( xProps->getPropertyValue("DisableDataTableDialog") >>= bProtected ) &&
1581 bProtected )
1583 mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_PROTECTED, XML_TRUE );
1586 catch ( const uno::Exception& )
1590 SvXMLElementExport aTable( mrExport, XML_NAMESPACE_TABLE, XML_TABLE, true, true );
1592 bool bHasOwnData = false;
1593 Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
1594 Reference< chart2::data::XRangeXMLConversion > xRangeConversion;
1595 if( xNewDoc.is())
1597 bHasOwnData = xNewDoc->hasInternalDataProvider();
1598 xRangeConversion.set( xNewDoc->getDataProvider(), uno::UNO_QUERY );
1601 Reference< chart2::XAnyDescriptionAccess > xAnyDescriptionAccess;
1603 Reference< chart::XChartDocument > xChartDoc( mrExport.GetModel(), uno::UNO_QUERY );
1604 if( xChartDoc.is() )
1605 xAnyDescriptionAccess = Reference< chart2::XAnyDescriptionAccess >( xChartDoc->getData(), uno::UNO_QUERY );
1608 if( bHasOwnData )
1609 lcl_ReorderInternalSequencesAccordingToTheirRangeName( m_aDataSequencesToExport );
1610 lcl_TableData aData( lcl_getDataForLocalTable( m_aDataSequencesToExport
1611 , xAnyDescriptionAccess, maCategoriesRange
1612 , mbRowSourceColumns, xRangeConversion ));
1614 tStringVector::const_iterator aDataRangeIter( aData.aDataRangeRepresentations.begin());
1615 const tStringVector::const_iterator aDataRangeEndIter( aData.aDataRangeRepresentations.end());
1617 tStringVector::const_iterator aRowDescriptions_RangeIter( aData.aRowDescriptions_Ranges.begin());
1618 const tStringVector::const_iterator aRowDescriptions_RangeEnd( aData.aRowDescriptions_Ranges.end());
1620 // declare columns
1622 SvXMLElementExport aHeaderColumns( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_HEADER_COLUMNS, true, true );
1623 SvXMLElementExport aHeaderColumn( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, true, true );
1626 SvXMLElementExport aColumns( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMNS, true, true );
1628 sal_Int32 nNextIndex = 0;
1629 for( size_t nN=0; nN< aData.aHiddenColumns.size(); nN++ )
1631 //i91578 display of hidden values (copy paste scenario; export hidden flag thus it can be used during migration to locale table upon paste )
1632 sal_Int32 nHiddenIndex = aData.aHiddenColumns[nN];
1633 if( nHiddenIndex > nNextIndex )
1635 sal_Int64 nRepeat = static_cast< sal_Int64 >( nHiddenIndex - nNextIndex );
1636 if(nRepeat>1)
1637 mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED,
1638 OUString::number( nRepeat ));
1639 SvXMLElementExport aColumn( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, true, true );
1641 mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_VISIBILITY, GetXMLToken( XML_COLLAPSE ) );
1642 SvXMLElementExport aColumn( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, true, true );
1643 nNextIndex = nHiddenIndex+1;
1646 sal_Int32 nEndIndex = aData.aColumnDescriptions.size()-1;
1647 if( nEndIndex >= nNextIndex )
1649 sal_Int64 nRepeat = static_cast< sal_Int64 >( nEndIndex - nNextIndex + 1 );
1650 if(nRepeat>1)
1651 mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED,
1652 OUString::number( nRepeat ));
1653 SvXMLElementExport aColumn( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, true, true );
1657 // export rows with content
1658 //export header row
1660 SvXMLElementExport aHeaderRows( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_HEADER_ROWS, true, true );
1661 SvXMLElementExport aRow( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_ROW, true, true );
1663 //first one empty cell for the row descriptions
1665 SvXMLElementExport aEmptyCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, true );
1666 SvXMLElementExport aEmptyParagraph( mrExport, XML_NAMESPACE_TEXT, XML_P, true, true );
1669 //export column descriptions
1670 tStringVector::const_iterator aColumnDescriptions_RangeIter( aData.aColumnDescriptions_Ranges.begin());
1671 const tStringVector::const_iterator aColumnDescriptions_RangeEnd( aData.aColumnDescriptions_Ranges.end());
1672 const Sequence< Sequence< uno::Any > >& rComplexColumnDescriptions = aData.aComplexColumnDescriptions;
1673 sal_Int32 nComplexCount = rComplexColumnDescriptions.getLength();
1674 sal_Int32 nC = 0;
1675 for( tStringVector::const_iterator aIt( aData.aColumnDescriptions.begin())
1676 ; (aIt != aData.aColumnDescriptions.end())
1677 ; ++aIt, nC++ )
1679 bool bExportString = true;
1680 if( nC < nComplexCount )
1682 const Sequence< uno::Any >& rComplexLabel = rComplexColumnDescriptions[nC];
1683 if( rComplexLabel.getLength()>0 )
1685 double fValue=0.0;
1686 if( rComplexLabel[0] >>=fValue )
1688 bExportString = false;
1690 ::sax::Converter::convertDouble(
1691 msStringBuffer, fValue);
1692 msString = msStringBuffer.makeStringAndClear();
1693 mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT );
1694 mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE, msString );
1698 if( bExportString )
1700 mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_STRING );
1703 SvXMLElementExport aCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, true );
1704 exportText( *aIt );
1705 if( nC < nComplexCount )
1706 lcl_exportComplexLabel( rComplexColumnDescriptions[nC], mrExport );
1707 if( !bHasOwnData && aColumnDescriptions_RangeIter != aColumnDescriptions_RangeEnd )
1709 // remind the original range to allow a correct re-association when copying via clipboard
1710 if (!(*aColumnDescriptions_RangeIter).isEmpty())
1711 SchXMLTools::exportRangeToSomewhere( mrExport, *aColumnDescriptions_RangeIter );
1712 ++aColumnDescriptions_RangeIter;
1715 SAL_WARN_IF( !bHasOwnData && (aColumnDescriptions_RangeIter != aColumnDescriptions_RangeEnd), "xmloff.chart", "bHasOwnData == false && aColumnDescriptions_RangeIter != aColumnDescriptions_RangeEnd" );
1716 } // closing row and header-rows elements
1718 // export value rows
1720 SvXMLElementExport aRows( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_ROWS, true, true );
1721 tStringVector::const_iterator aRowDescriptionsIter( aData.aRowDescriptions.begin());
1722 const Sequence< Sequence< uno::Any > >& rComplexRowDescriptions = aData.aComplexRowDescriptions;
1723 sal_Int32 nComplexCount = rComplexRowDescriptions.getLength();
1724 sal_Int32 nC = 0;
1726 for( t2DNumberContainer::const_iterator aRowIt( aData.aDataInRows.begin())
1727 ; aRowIt != aData.aDataInRows.end()
1728 ; ++aRowIt, ++nC )
1730 SvXMLElementExport aRow( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_ROW, true, true );
1732 //export row descriptions
1734 bool bExportString = true;
1735 if( nC < nComplexCount )
1737 const Sequence< uno::Any >& rComplexLabel = rComplexRowDescriptions[nC];
1738 if( rComplexLabel.getLength()>0 )
1740 double fValue=0.0;
1741 if( rComplexLabel[0] >>=fValue )
1743 bExportString = false;
1745 ::sax::Converter::convertDouble(msStringBuffer, fValue);
1746 msString = msStringBuffer.makeStringAndClear();
1747 mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT );
1748 mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE, msString );
1752 if( bExportString )
1754 mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_STRING );
1757 SvXMLElementExport aCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, true );
1758 if( aRowDescriptionsIter != aData.aRowDescriptions.end())
1760 exportText( *aRowDescriptionsIter );
1761 if( nC < nComplexCount )
1762 lcl_exportComplexLabel( rComplexRowDescriptions[nC], mrExport );
1763 if( !bHasOwnData && aRowDescriptions_RangeIter != aRowDescriptions_RangeEnd )
1765 // remind the original range to allow a correct re-association when copying via clipboard
1766 SchXMLTools::exportRangeToSomewhere( mrExport, *aRowDescriptions_RangeIter );
1767 ++aRowDescriptions_RangeIter;
1769 ++aRowDescriptionsIter;
1773 //export row values
1774 for( t2DNumberContainer::value_type::const_iterator aColIt( aRowIt->begin());
1775 aColIt != aRowIt->end(); ++aColIt )
1777 ::sax::Converter::convertDouble( msStringBuffer, *aColIt );
1778 msString = msStringBuffer.makeStringAndClear();
1779 mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT );
1780 mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE, msString );
1781 SvXMLElementExport aCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, true );
1782 exportText( msString, false ); // do not convert tabs and lfs
1783 if( ( !bHasOwnData && aDataRangeIter != aDataRangeEndIter ) &&
1784 ( mbRowSourceColumns || (aColIt == aRowIt->begin()) ) )
1786 // remind the original range to allow a correct re-association when copying via clipboard
1787 if (!(*aDataRangeIter).isEmpty())
1788 SchXMLTools::exportRangeToSomewhere( mrExport, *aDataRangeIter );
1789 ++aDataRangeIter;
1795 // if range iterator was used it should have reached its end
1796 SAL_WARN_IF( !bHasOwnData && (aDataRangeIter != aDataRangeEndIter), "xmloff.chart", "bHasOwnData == false && aDataRangeIter != aDataRangeEndIter" );
1797 SAL_WARN_IF( !bHasOwnData && (aRowDescriptions_RangeIter != aRowDescriptions_RangeEnd), "xmloff.chart", "bHasOwnData == false && aRowDescriptions_RangeIter != aRowDescriptions_RangeEnd" );
1800 namespace
1803 Reference< chart2::XCoordinateSystem > lcl_getCooSys( const Reference< chart2::XDiagram > & xNewDiagram )
1805 Reference< chart2::XCoordinateSystem > xCooSys;
1806 Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xNewDiagram, uno::UNO_QUERY );
1807 if(xCooSysCnt.is())
1809 Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems() );
1810 if(aCooSysSeq.getLength()>0)
1811 xCooSys = aCooSysSeq[0];
1813 return xCooSys;
1816 Reference< chart2::XAxis > lcl_getAxis( const Reference< chart2::XCoordinateSystem >& xCooSys,
1817 enum XMLTokenEnum eDimension, bool bPrimary=true )
1819 Reference< chart2::XAxis > xNewAxis;
1822 if( xCooSys.is() )
1824 sal_Int32 nDimensionIndex=0;
1825 switch( eDimension )
1827 case XML_X:
1828 nDimensionIndex=0;
1829 break;
1830 case XML_Y:
1831 nDimensionIndex=1;
1832 break;
1833 case XML_Z:
1834 nDimensionIndex=2;
1835 break;
1836 default:
1837 break;
1840 xNewAxis = xCooSys->getAxisByDimension( nDimensionIndex, bPrimary ? 0 : 1 );
1843 catch( const uno::Exception & )
1846 return xNewAxis;
1851 void SchXMLExportHelper_Impl::exportPlotArea(
1852 Reference< chart::XDiagram > xDiagram,
1853 Reference< chart2::XDiagram > xNewDiagram,
1854 const awt::Size & rPageSize,
1855 bool bExportContent,
1856 bool bIncludeTable )
1858 SAL_WARN_IF( !xDiagram.is(), "xmloff.chart", "Invalid XDiagram as parameter" );
1859 if( ! xDiagram.is())
1860 return;
1862 // variables for autostyles
1863 Reference< beans::XPropertySet > xPropSet;
1864 std::vector< XMLPropertyState > aPropertyStates;
1866 bool bIs3DChart = false;
1867 drawing::HomogenMatrix aTransMatrix;
1869 msStringBuffer.setLength( 0 );
1871 // plot-area element
1873 std::unique_ptr<SvXMLElementExport> xElPlotArea;
1874 // get property states for autostyles
1875 xPropSet = Reference< beans::XPropertySet >( xDiagram, uno::UNO_QUERY );
1876 if( xPropSet.is())
1878 if( mxExpPropMapper.is())
1879 aPropertyStates = mxExpPropMapper->Filter( xPropSet );
1881 if( bExportContent )
1883 rtl::Reference< XMLShapeExport > rShapeExport;
1885 // write style name
1886 AddAutoStyleAttribute( aPropertyStates );
1888 if( !msChartAddress.isEmpty() )
1890 if( !bIncludeTable )
1891 mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_CELL_RANGE_ADDRESS, msChartAddress );
1893 Reference< chart::XChartDocument > xDoc( mrExport.GetModel(), uno::UNO_QUERY );
1894 if( xDoc.is() )
1896 Reference< beans::XPropertySet > xDocProp( xDoc, uno::UNO_QUERY );
1897 if( xDocProp.is())
1899 Any aAny;
1903 bool bFirstCol = false, bFirstRow = false;
1905 aAny = xDocProp->getPropertyValue(
1906 OUString( "DataSourceLabelsInFirstColumn" ));
1907 aAny >>= bFirstCol;
1908 aAny = xDocProp->getPropertyValue(
1909 OUString( "DataSourceLabelsInFirstRow" ));
1910 aAny >>= bFirstRow;
1912 if( bFirstCol || bFirstRow )
1914 mrExport.AddAttribute( XML_NAMESPACE_CHART,
1915 ::xmloff::token::GetXMLToken( ::xmloff::token::XML_DATA_SOURCE_HAS_LABELS ),
1916 ( bFirstCol
1917 ? ( bFirstRow
1918 ? ::xmloff::token::GetXMLToken( ::xmloff::token::XML_BOTH )
1919 : ::xmloff::token::GetXMLToken( ::xmloff::token::XML_COLUMN ))
1920 : ::xmloff::token::GetXMLToken( ::xmloff::token::XML_ROW )));
1923 catch( const beans::UnknownPropertyException & )
1925 SAL_WARN("xmloff.chart", "Properties missing" );
1931 // attributes
1932 Reference< drawing::XShape > xShape ( xDiagram, uno::UNO_QUERY );
1933 if( xShape.is())
1935 addPosition( xShape );
1936 addSize( xShape );
1939 if( xPropSet.is())
1941 Any aAny;
1943 // 3d attributes
1946 aAny = xPropSet->getPropertyValue("Dim3D");
1947 aAny >>= bIs3DChart;
1949 if( bIs3DChart )
1951 rShapeExport = mrExport.GetShapeExport();
1952 if( rShapeExport.is())
1953 rShapeExport->export3DSceneAttributes( xPropSet );
1956 catch( const uno::Exception & rEx )
1958 OString aBStr(OUStringToOString(rEx.Message, RTL_TEXTENCODING_ASCII_US));
1959 SAL_INFO("xmloff.chart", "chart:exportPlotAreaException caught: " << aBStr);
1963 // plot-area element
1964 xElPlotArea.reset(new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_PLOT_AREA, true, true ));
1966 //inner position rectangle element
1967 exportCoordinateRegion( xDiagram );
1969 // light sources (inside plot area element)
1970 if( bIs3DChart &&
1971 rShapeExport.is())
1972 rShapeExport->export3DLamps( xPropSet );
1974 else // autostyles
1976 CollectAutoStyle( aPropertyStates );
1978 // remove property states for autostyles
1979 aPropertyStates.clear();
1981 // axis elements
1982 exportAxes( xDiagram, xNewDiagram, bExportContent );
1984 // series elements
1985 Reference< chart2::XAxis > xSecondYAxis = lcl_getAxis( lcl_getCooSys( xNewDiagram ), XML_Y, false );
1986 exportSeries( xNewDiagram, rPageSize, bExportContent, xSecondYAxis.is() );
1988 // stock-chart elements
1989 OUString sChartType ( xDiagram->getDiagramType());
1990 if( sChartType == "com.sun.star.chart.StockDiagram" )
1992 Reference< chart::XStatisticDisplay > xStockPropProvider( xDiagram, uno::UNO_QUERY );
1993 if( xStockPropProvider.is())
1995 // stock-gain-marker
1996 Reference< beans::XPropertySet > xStockPropSet = xStockPropProvider->getUpBar();
1997 if( xStockPropSet.is())
1999 aPropertyStates.clear();
2000 aPropertyStates = mxExpPropMapper->Filter( xStockPropSet );
2002 if( !aPropertyStates.empty() )
2004 if( bExportContent )
2006 AddAutoStyleAttribute( aPropertyStates );
2008 SvXMLElementExport aGain( mrExport, XML_NAMESPACE_CHART, XML_STOCK_GAIN_MARKER, true, true );
2010 else
2012 CollectAutoStyle( aPropertyStates );
2017 // stock-loss-marker
2018 xStockPropSet = xStockPropProvider->getDownBar();
2019 if( xStockPropSet.is())
2021 aPropertyStates.clear();
2022 aPropertyStates = mxExpPropMapper->Filter( xStockPropSet );
2024 if( !aPropertyStates.empty() )
2026 if( bExportContent )
2028 AddAutoStyleAttribute( aPropertyStates );
2030 SvXMLElementExport aGain( mrExport, XML_NAMESPACE_CHART, XML_STOCK_LOSS_MARKER, true, true );
2032 else
2034 CollectAutoStyle( aPropertyStates );
2039 // stock-range-line
2040 xStockPropSet = xStockPropProvider->getMinMaxLine();
2041 if( xStockPropSet.is())
2043 aPropertyStates.clear();
2044 aPropertyStates = mxExpPropMapper->Filter( xStockPropSet );
2046 if( !aPropertyStates.empty() )
2048 if( bExportContent )
2050 AddAutoStyleAttribute( aPropertyStates );
2052 SvXMLElementExport aGain( mrExport, XML_NAMESPACE_CHART, XML_STOCK_RANGE_LINE, true, true );
2054 else
2056 CollectAutoStyle( aPropertyStates );
2063 // wall and floor element
2064 Reference< chart::X3DDisplay > xWallFloorSupplier( xDiagram, uno::UNO_QUERY );
2065 if( mxExpPropMapper.is() &&
2066 xWallFloorSupplier.is())
2068 // remove property states for autostyles
2069 aPropertyStates.clear();
2071 Reference< beans::XPropertySet > xWallPropSet( xWallFloorSupplier->getWall(), uno::UNO_QUERY );
2072 if( xWallPropSet.is())
2074 aPropertyStates = mxExpPropMapper->Filter( xWallPropSet );
2076 if( !aPropertyStates.empty() )
2078 // write element
2079 if( bExportContent )
2081 // add style name attribute
2082 AddAutoStyleAttribute( aPropertyStates );
2084 SvXMLElementExport aWall( mrExport, XML_NAMESPACE_CHART, XML_WALL, true, true );
2086 else // autostyles
2088 CollectAutoStyle( aPropertyStates );
2093 // floor element
2094 // remove property states for autostyles
2095 aPropertyStates.clear();
2097 Reference< beans::XPropertySet > xFloorPropSet( xWallFloorSupplier->getFloor(), uno::UNO_QUERY );
2098 if( xFloorPropSet.is())
2100 aPropertyStates = mxExpPropMapper->Filter( xFloorPropSet );
2102 if( !aPropertyStates.empty() )
2104 // write element
2105 if( bExportContent )
2107 // add style name attribute
2108 AddAutoStyleAttribute( aPropertyStates );
2110 SvXMLElementExport aFloor( mrExport, XML_NAMESPACE_CHART, XML_FLOOR, true, true );
2112 else // autostyles
2114 CollectAutoStyle( aPropertyStates );
2121 void SchXMLExportHelper_Impl::exportCoordinateRegion( const uno::Reference< chart::XDiagram >& xDiagram )
2123 const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
2124 if( nCurrentODFVersion <= SvtSaveOptions::ODFVER_012 )//do not export to ODF 1.2 or older
2125 return;
2127 Reference< chart::XDiagramPositioning > xDiaPos( xDiagram, uno::UNO_QUERY );
2128 SAL_WARN_IF( !xDiaPos.is(), "xmloff.chart", "Invalid xDiaPos as parameter" );
2129 if( !xDiaPos.is() )
2130 return;
2132 awt::Rectangle aRect( xDiaPos->calculateDiagramPositionExcludingAxes() );
2133 addPosition( awt::Point(aRect.X,aRect.Y) );
2134 addSize( awt::Size(aRect.Width,aRect.Height) );
2136 SvXMLElementExport aCoordinateRegion( mrExport, XML_NAMESPACE_CHART_EXT, XML_COORDINATE_REGION, true, true );//#i100778# todo: change to chart namespace in future - dependent on fileformat
2139 namespace
2141 XMLTokenEnum lcl_getTimeUnitToken( sal_Int32 nTimeUnit )
2143 XMLTokenEnum eToken = XML_DAYS;
2144 switch( nTimeUnit )
2146 case ::com::sun::star::chart::TimeUnit::YEAR:
2147 eToken = XML_YEARS;
2148 break;
2149 case ::com::sun::star::chart::TimeUnit::MONTH:
2150 eToken = XML_MONTHS;
2151 break;
2152 default://days
2153 break;
2155 return eToken;
2159 void SchXMLExportHelper_Impl::exportDateScale( const Reference< beans::XPropertySet >& rAxisProps )
2161 if( !rAxisProps.is() )
2162 return;
2164 chart::TimeIncrement aIncrement;
2165 if( (rAxisProps->getPropertyValue("TimeIncrement") >>= aIncrement) )
2167 sal_Int32 nTimeResolution = ::com::sun::star::chart::TimeUnit::DAY;
2168 if( aIncrement.TimeResolution >>= nTimeResolution )
2169 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_BASE_TIME_UNIT, lcl_getTimeUnitToken( nTimeResolution ) );
2171 OUStringBuffer aValue;
2172 chart::TimeInterval aInterval;
2173 if( aIncrement.MajorTimeInterval >>= aInterval )
2175 ::sax::Converter::convertNumber( aValue, aInterval.Number );
2176 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MAJOR_INTERVAL_VALUE, aValue.makeStringAndClear() );
2177 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MAJOR_INTERVAL_UNIT, lcl_getTimeUnitToken( aInterval.TimeUnit ) );
2179 if( aIncrement.MinorTimeInterval >>= aInterval )
2181 ::sax::Converter::convertNumber( aValue, aInterval.Number );
2182 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MINOR_INTERVAL_VALUE, aValue.makeStringAndClear() );
2183 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MINOR_INTERVAL_UNIT, lcl_getTimeUnitToken( aInterval.TimeUnit ) );
2186 SvXMLElementExport aDateScale( mrExport, XML_NAMESPACE_CHART_EXT, XML_DATE_SCALE, true, true );//#i25706#todo: change namespace for next ODF version
2190 void SchXMLExportHelper_Impl::exportAxisTitle( const Reference< beans::XPropertySet >& rTitleProps, bool bExportContent )
2192 if( !rTitleProps.is() )
2193 return;
2194 std::vector< XMLPropertyState > aPropertyStates = mxExpPropMapper->Filter( rTitleProps );
2195 if( bExportContent )
2197 OUString aText;
2198 Any aAny( rTitleProps->getPropertyValue(
2199 OUString( "String" )));
2200 aAny >>= aText;
2202 Reference< drawing::XShape > xShape( rTitleProps, uno::UNO_QUERY );
2203 if( xShape.is())
2204 addPosition( xShape );
2206 AddAutoStyleAttribute( aPropertyStates );
2207 SvXMLElementExport aTitle( mrExport, XML_NAMESPACE_CHART, XML_TITLE, true, true );
2209 // paragraph containing title
2210 exportText( aText );
2212 else
2214 CollectAutoStyle( aPropertyStates );
2216 aPropertyStates.clear();
2219 void SchXMLExportHelper_Impl::exportGrid( const Reference< beans::XPropertySet >& rGridProperties, bool bMajor, bool bExportContent )
2221 if( !rGridProperties.is() )
2222 return;
2223 std::vector< XMLPropertyState > aPropertyStates = mxExpPropMapper->Filter( rGridProperties );
2224 if( bExportContent )
2226 AddAutoStyleAttribute( aPropertyStates );
2227 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_CLASS, bMajor ? XML_MAJOR : XML_MINOR );
2228 SvXMLElementExport aGrid( mrExport, XML_NAMESPACE_CHART, XML_GRID, true, true );
2230 else
2232 CollectAutoStyle( aPropertyStates );
2234 aPropertyStates.clear();
2237 namespace
2240 //returns true if a date scale needs to be exported
2241 bool lcl_exportAxisType( const Reference< chart2::XAxis >& rChart2Axis, SvXMLExport& rExport)
2243 bool bExportDateScale = false;
2244 if( !rChart2Axis.is() )
2245 return bExportDateScale;
2247 const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
2248 if( nCurrentODFVersion <= SvtSaveOptions::ODFVER_012 )//do not export to ODF 1.2 or older
2249 return bExportDateScale;
2251 chart2::ScaleData aScale( rChart2Axis->getScaleData() );
2252 //#i25706#todo: change namespace for next ODF version
2253 sal_uInt16 nNameSpace = XML_NAMESPACE_CHART_EXT;
2255 switch(aScale.AxisType)
2257 case chart2::AxisType::CATEGORY:
2258 if( aScale.AutoDateAxis )
2260 rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_AUTO );
2261 bExportDateScale = true;
2263 else
2264 rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_TEXT );
2265 break;
2266 case chart2::AxisType::DATE:
2267 rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_DATE );
2268 bExportDateScale = true;
2269 break;
2270 default: //AUTOMATIC
2271 rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_AUTO );
2272 break;
2275 return bExportDateScale;
2278 void disableLinkedNumberFormat(
2279 std::vector<XMLPropertyState>& rPropStates, const rtl::Reference<XMLPropertySetMapper>& rMapper )
2281 for (size_t i = 0; i < rPropStates.size(); ++i)
2283 XMLPropertyState& rState = rPropStates[i];
2284 if (rState.mnIndex < 0 || rMapper->GetEntryCount() <= rState.mnIndex)
2285 continue;
2287 OUString aXMLName = rMapper->GetEntryXMLName(rState.mnIndex);
2289 if (aXMLName != "link-data-style-to-source")
2290 continue;
2292 // Entry found. Set the value to false and bail out.
2293 rState.maValue <<= false;
2294 return;
2297 // Entry not found. Insert a new entry for this.
2298 sal_Int32 nIndex = rMapper->GetEntryIndex(XML_NAMESPACE_CHART, "link-data-style-to-source", 0);
2299 XMLPropertyState aState(nIndex);
2300 aState.maValue <<= false;
2301 rPropStates.push_back(aState);
2306 void SchXMLExportHelper_Impl::exportAxis(
2307 enum XMLTokenEnum eDimension,
2308 enum XMLTokenEnum eAxisName,
2309 const Reference< beans::XPropertySet >& rAxisProps,
2310 const Reference< chart2::XAxis >& rChart2Axis,
2311 const OUString& rCategoriesRange,
2312 bool bHasTitle, bool bHasMajorGrid, bool bHasMinorGrid,
2313 bool bExportContent )
2315 std::vector< XMLPropertyState > aPropertyStates;
2316 SvXMLElementExport* pAxis = NULL;
2318 // get property states for autostyles
2319 if( rAxisProps.is() && mxExpPropMapper.is() )
2321 lcl_exportNumberFormat( "NumberFormat", rAxisProps, mrExport );
2322 aPropertyStates = mxExpPropMapper->Filter( rAxisProps );
2324 if (!maSrcShellID.isEmpty() && !maDestShellID.isEmpty() && maSrcShellID != maDestShellID)
2326 // Disable link to source number format property when pasting to
2327 // a different doc shell. These shell ID's should be both empty
2328 // during real ODF export.
2329 disableLinkedNumberFormat(aPropertyStates, mxExpPropMapper->getPropertySetMapper());
2333 bool bExportDateScale = false;
2334 if( bExportContent )
2336 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_DIMENSION, eDimension );
2337 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_NAME, eAxisName );
2338 AddAutoStyleAttribute( aPropertyStates ); // write style name
2339 if( !rCategoriesRange.isEmpty() )
2340 bExportDateScale = lcl_exportAxisType( rChart2Axis, mrExport );
2342 // open axis element
2343 pAxis = new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_AXIS, true, true );
2345 else
2347 CollectAutoStyle( aPropertyStates );
2349 aPropertyStates.clear();
2351 //date scale
2352 if( bExportDateScale )
2353 exportDateScale( rAxisProps );
2355 Reference< beans::XPropertySet > xTitleProps;
2356 Reference< beans::XPropertySet > xMajorGridProps;
2357 Reference< beans::XPropertySet > xMinorGridProps;
2358 Reference< chart::XAxis > xAxis( rAxisProps, uno::UNO_QUERY );
2359 if( xAxis.is() )
2361 xTitleProps = bHasTitle ? xAxis->getAxisTitle() : 0;
2362 xMajorGridProps = bHasMajorGrid ? xAxis->getMajorGrid() : 0;
2363 xMinorGridProps = bHasMinorGrid ? xAxis->getMinorGrid() : 0;
2366 // axis-title
2367 exportAxisTitle( xTitleProps , bExportContent );
2369 // categories if we have a categories chart
2370 if( bExportContent && !rCategoriesRange.isEmpty() )
2372 mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_CELL_RANGE_ADDRESS, rCategoriesRange );
2373 SvXMLElementExport aCategories( mrExport, XML_NAMESPACE_CHART, XML_CATEGORIES, true, true );
2376 // grid
2377 exportGrid( xMajorGridProps, true, bExportContent );
2378 exportGrid( xMinorGridProps, false, bExportContent );
2380 if( pAxis )
2382 //close axis element
2383 delete pAxis;
2384 pAxis = NULL;
2388 void SchXMLExportHelper_Impl::exportAxes(
2389 const Reference< chart::XDiagram > & xDiagram,
2390 const Reference< chart2::XDiagram > & xNewDiagram,
2391 bool bExportContent )
2393 SAL_WARN_IF( !xDiagram.is(), "xmloff.chart", "Invalid XDiagram as parameter" );
2394 if( ! xDiagram.is())
2395 return;
2397 // get some properties from document first
2398 bool bHasXAxis = false,
2399 bHasYAxis = false,
2400 bHasZAxis = false,
2401 bHasSecondaryXAxis = false,
2402 bHasSecondaryYAxis = false;
2403 bool bHasXAxisTitle = false,
2404 bHasYAxisTitle = false,
2405 bHasZAxisTitle = false,
2406 bHasSecondaryXAxisTitle = false,
2407 bHasSecondaryYAxisTitle = false;
2408 bool bHasXAxisMajorGrid = false,
2409 bHasXAxisMinorGrid = false,
2410 bHasYAxisMajorGrid = false,
2411 bHasYAxisMinorGrid = false,
2412 bHasZAxisMajorGrid = false,
2413 bHasZAxisMinorGrid = false;
2415 // get multiple properties using XMultiPropertySet
2416 MultiPropertySetHandler aDiagramProperties (xDiagram);
2418 aDiagramProperties.Add ("HasXAxis", bHasXAxis);
2419 aDiagramProperties.Add ("HasYAxis", bHasYAxis);
2420 aDiagramProperties.Add ("HasZAxis", bHasZAxis);
2421 aDiagramProperties.Add ("HasSecondaryXAxis", bHasSecondaryXAxis);
2422 aDiagramProperties.Add ("HasSecondaryYAxis", bHasSecondaryYAxis);
2424 aDiagramProperties.Add ("HasXAxisTitle", bHasXAxisTitle);
2425 aDiagramProperties.Add ("HasYAxisTitle", bHasYAxisTitle);
2426 aDiagramProperties.Add ("HasZAxisTitle", bHasZAxisTitle);
2427 aDiagramProperties.Add ("HasSecondaryXAxisTitle", bHasSecondaryXAxisTitle);
2428 aDiagramProperties.Add ("HasSecondaryYAxisTitle", bHasSecondaryYAxisTitle);
2430 aDiagramProperties.Add ("HasXAxisGrid", bHasXAxisMajorGrid);
2431 aDiagramProperties.Add ("HasYAxisGrid", bHasYAxisMajorGrid);
2432 aDiagramProperties.Add ("HasZAxisGrid", bHasZAxisMajorGrid);
2434 aDiagramProperties.Add ("HasXAxisHelpGrid", bHasXAxisMinorGrid);
2435 aDiagramProperties.Add ("HasYAxisHelpGrid", bHasYAxisMinorGrid);
2436 aDiagramProperties.Add ("HasZAxisHelpGrid", bHasZAxisMinorGrid);
2438 if ( ! aDiagramProperties.GetProperties ())
2440 SAL_INFO("xmloff.chart", "Required properties not found in Chart diagram");
2443 Reference< chart2::XCoordinateSystem > xCooSys( lcl_getCooSys(xNewDiagram) );
2445 // write an axis element also if the axis itself is not visible, but a grid or a title
2447 OUString aCategoriesRange;
2448 Reference< chart::XAxisSupplier > xAxisSupp( xDiagram, uno::UNO_QUERY );
2450 // x axis
2452 Reference< ::com::sun::star::chart2::XAxis > xNewAxis = lcl_getAxis( xCooSys, XML_X );
2453 if( xNewAxis.is() )
2455 Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getAxis(0) : 0, uno::UNO_QUERY );
2456 if( mbHasCategoryLabels && bExportContent )
2458 Reference< chart2::data::XLabeledDataSequence > xCategories( lcl_getCategories( xNewDiagram ) );
2459 if( xCategories.is() )
2461 Reference< chart2::data::XDataSequence > xValues( xCategories->getValues() );
2462 if( xValues.is() )
2464 Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
2465 maCategoriesRange = xValues->getSourceRangeRepresentation();
2466 aCategoriesRange = lcl_ConvertRange( maCategoriesRange, xNewDoc );
2470 exportAxis( XML_X, XML_PRIMARY_X, xAxisProps, xNewAxis, aCategoriesRange, bHasXAxisTitle, bHasXAxisMajorGrid, bHasXAxisMinorGrid, bExportContent );
2471 aCategoriesRange.clear();
2474 // secondary x axis
2476 Reference< chart::XSecondAxisTitleSupplier > xSecondTitleSupp( xDiagram, uno::UNO_QUERY );
2477 xNewAxis = lcl_getAxis( xCooSys, XML_X, false );
2478 if( xNewAxis.is() )
2480 Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getSecondaryAxis(0) : 0, uno::UNO_QUERY );
2481 exportAxis( XML_X, XML_SECONDARY_X, xAxisProps, xNewAxis, aCategoriesRange, bHasSecondaryXAxisTitle, false, false, bExportContent );
2484 // y axis
2486 xNewAxis = lcl_getAxis( xCooSys, XML_Y );
2487 if( xNewAxis.is() )
2489 Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getAxis(1) : 0, uno::UNO_QUERY );
2490 exportAxis( XML_Y, XML_PRIMARY_Y, xAxisProps, xNewAxis, aCategoriesRange, bHasYAxisTitle, bHasYAxisMajorGrid, bHasYAxisMinorGrid, bExportContent );
2493 // secondary y axis
2495 xNewAxis = lcl_getAxis( xCooSys, XML_Y, false );
2496 if( xNewAxis.is() )
2498 Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getSecondaryAxis(1) : 0, uno::UNO_QUERY );
2499 exportAxis( XML_Y, XML_SECONDARY_Y, xAxisProps, xNewAxis, aCategoriesRange, bHasSecondaryYAxisTitle, false, false, bExportContent );
2502 // z axis
2504 xNewAxis = lcl_getAxis( xCooSys, XML_Z );
2505 if( xNewAxis.is() )
2507 Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getAxis(2) : 0, uno::UNO_QUERY );
2508 exportAxis( XML_Z, XML_PRIMARY_Z, xAxisProps, xNewAxis, aCategoriesRange, bHasZAxisTitle, bHasZAxisMajorGrid, bHasZAxisMinorGrid, bExportContent );
2512 namespace
2514 bool lcl_hasNoValuesButText( const uno::Reference< chart2::data::XDataSequence >& xDataSequence )
2516 if( !xDataSequence.is() )
2517 return false;//have no data
2519 Sequence< uno::Any > aData;
2520 Reference< chart2::data::XNumericalDataSequence > xNumericalDataSequence( xDataSequence, uno::UNO_QUERY );
2521 if( xNumericalDataSequence.is() )
2523 Sequence< double > aDoubles( xNumericalDataSequence->getNumericalData() );
2524 sal_Int32 nCount = aDoubles.getLength();
2525 for( sal_Int32 i = 0; i < nCount; ++i )
2527 if( !::rtl::math::isNan( aDoubles[i] ) )
2528 return false;//have double value
2531 else
2533 aData = xDataSequence->getData();
2534 double fDouble = 0.0;
2535 sal_Int32 nCount = aData.getLength();
2536 for( sal_Int32 i = 0; i < nCount; ++i )
2538 if( (aData[i] >>= fDouble) && !::rtl::math::isNan( fDouble ) )
2539 return false;//have double value
2543 //no values found
2545 Reference< chart2::data::XTextualDataSequence > xTextualDataSequence( xDataSequence, uno::UNO_QUERY );
2546 if( xTextualDataSequence.is() )
2548 uno::Sequence< OUString > aStrings( xTextualDataSequence->getTextualData() );
2549 sal_Int32 nCount = aStrings.getLength();
2550 for( sal_Int32 i = 0; i < nCount; ++i )
2552 if( !aStrings[i].isEmpty() )
2553 return true;//have text
2556 else
2558 if( !aData.getLength() )
2559 aData = xDataSequence->getData();
2560 OUString aString;
2561 sal_Int32 nCount = aData.getLength();
2562 for( sal_Int32 i = 0; i < nCount; ++i )
2564 if( (aData[i]>>=aString) && !aString.isEmpty() )
2565 return true;//have text
2568 //no doubles and no texts
2569 return false;
2573 void SchXMLExportHelper_Impl::exportSeries(
2574 const Reference< chart2::XDiagram > & xNewDiagram,
2575 const awt::Size & rPageSize,
2576 bool bExportContent,
2577 bool bHasTwoYAxes )
2579 Reference< chart2::XCoordinateSystemContainer > xBCooSysCnt( xNewDiagram, uno::UNO_QUERY );
2580 if( ! xBCooSysCnt.is())
2581 return;
2582 Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
2584 OUString aFirstXDomainRange;
2585 OUString aFirstYDomainRange;
2587 std::vector< XMLPropertyState > aPropertyStates;
2589 Sequence< Reference< chart2::XCoordinateSystem > >
2590 aCooSysSeq( xBCooSysCnt->getCoordinateSystems());
2591 for( sal_Int32 nCSIdx=0; nCSIdx<aCooSysSeq.getLength(); ++nCSIdx )
2593 Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nCSIdx], uno::UNO_QUERY );
2594 if( ! xCTCnt.is())
2595 continue;
2596 Sequence< Reference< chart2::XChartType > > aCTSeq( xCTCnt->getChartTypes());
2597 for( sal_Int32 nCTIdx=0; nCTIdx<aCTSeq.getLength(); ++nCTIdx )
2599 Reference< chart2::XDataSeriesContainer > xDSCnt( aCTSeq[nCTIdx], uno::UNO_QUERY );
2600 if( ! xDSCnt.is())
2601 continue;
2602 // note: if xDSCnt.is() then also aCTSeq[nCTIdx]
2603 OUString aChartType( aCTSeq[nCTIdx]->getChartType());
2604 OUString aLabelRole = aCTSeq[nCTIdx]->getRoleOfSequenceForSeriesLabel();
2606 // special export for stock charts
2607 if ( aChartType == "com.sun.star.chart2.CandleStickChartType" )
2609 bool bJapaneseCandleSticks = false;
2610 Reference< beans::XPropertySet > xCTProp( aCTSeq[nCTIdx], uno::UNO_QUERY );
2611 if( xCTProp.is())
2612 xCTProp->getPropertyValue("Japanese") >>= bJapaneseCandleSticks;
2613 exportCandleStickSeries(
2614 xDSCnt->getDataSeries(), xNewDiagram, bJapaneseCandleSticks, bExportContent );
2615 continue;
2618 // export dataseries for current chart-type
2619 Sequence< Reference< chart2::XDataSeries > > aSeriesSeq( xDSCnt->getDataSeries());
2620 for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeriesSeq.getLength(); ++nSeriesIdx )
2622 // export series
2623 Reference< chart2::data::XDataSource > xSource( aSeriesSeq[nSeriesIdx], uno::UNO_QUERY );
2624 if( xSource.is())
2626 SvXMLElementExport* pSeries = NULL;
2627 Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeqCnt(
2628 xSource->getDataSequences());
2629 sal_Int32 nMainSequenceIndex = -1;
2630 sal_Int32 nSeriesLength = 0;
2631 sal_Int32 nAttachedAxis = chart::ChartAxisAssign::PRIMARY_Y;
2632 bool bHasMeanValueLine = false;
2633 Reference< beans::XPropertySet > xPropSet;
2634 tLabelValuesDataPair aSeriesLabelValuesPair;
2636 // search for main sequence and create a series element
2638 Reference< chart2::data::XDataSequence > xValuesSeq;
2639 Reference< chart2::data::XDataSequence > xLabelSeq;
2640 sal_Int32 nSeqIdx=0;
2641 for( ; nSeqIdx<aSeqCnt.getLength(); ++nSeqIdx )
2643 OUString aRole;
2644 Reference< chart2::data::XDataSequence > xTempValueSeq( aSeqCnt[nSeqIdx]->getValues() );
2645 if( nMainSequenceIndex==-1 )
2647 Reference< beans::XPropertySet > xSeqProp( xTempValueSeq, uno::UNO_QUERY );
2648 if( xSeqProp.is())
2649 xSeqProp->getPropertyValue("Role") >>= aRole;
2650 // "main" sequence
2651 if( aRole.equals( aLabelRole ))
2653 xValuesSeq.set( xTempValueSeq );
2654 xLabelSeq.set( aSeqCnt[nSeqIdx]->getLabel());
2655 nMainSequenceIndex = nSeqIdx;
2658 sal_Int32 nSequenceLength = (xTempValueSeq.is()? xTempValueSeq->getData().getLength() : sal_Int32(0));
2659 if( nSeriesLength < nSequenceLength )
2660 nSeriesLength = nSequenceLength;
2663 // have found the main sequence, then xValuesSeq and
2664 // xLabelSeq contain those. Otherwise both are empty
2666 // get property states for autostyles
2669 xPropSet = SchXMLSeriesHelper::createOldAPISeriesPropertySet(
2670 aSeriesSeq[nSeriesIdx], mrExport.GetModel() );
2672 catch( const uno::Exception & rEx )
2674 SAL_INFO("xmloff.chart", "Series not found or no XPropertySet: " << rEx.Message );
2675 continue;
2677 if( xPropSet.is())
2679 // determine attached axis
2682 Any aAny( xPropSet->getPropertyValue(
2683 OUString( "Axis" )));
2684 aAny >>= nAttachedAxis;
2686 aAny = xPropSet->getPropertyValue(
2687 OUString( "MeanValue" ));
2688 aAny >>= bHasMeanValueLine;
2690 catch( const beans::UnknownPropertyException & rEx )
2692 SAL_INFO("xmloff.chart", "Required property not found in DataRowProperties: " << rEx.Message );
2695 const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
2696 if( nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 )
2698 lcl_exportNumberFormat( "NumberFormat", xPropSet, mrExport );
2699 lcl_exportNumberFormat( "PercentageNumberFormat", xPropSet, mrExport );
2702 if( mxExpPropMapper.is())
2703 aPropertyStates = mxExpPropMapper->Filter( xPropSet );
2706 if( bExportContent )
2708 if( bHasTwoYAxes )
2710 if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
2711 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y );
2712 else
2713 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y );
2716 // write style name
2717 AddAutoStyleAttribute( aPropertyStates );
2719 if( xValuesSeq.is())
2720 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS,
2721 lcl_ConvertRange(
2722 xValuesSeq->getSourceRangeRepresentation(),
2723 xNewDoc ));
2724 else
2725 // #i75297# allow empty series, export empty range to have all ranges on import
2726 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, OUString());
2728 if (xLabelSeq.is())
2730 // Check if the label is direct string value rather than a reference.
2731 bool bHasString = false;
2732 uno::Reference<beans::XPropertySet> xLSProp(xLabelSeq, uno::UNO_QUERY);
2733 if (xLSProp.is())
2737 xLSProp->getPropertyValue("HasStringLabel") >>= bHasString;
2739 catch (const beans::UnknownPropertyException&) {}
2742 OUString aRange = xLabelSeq->getSourceRangeRepresentation();
2744 if (bHasString)
2746 mrExport.AddAttribute(
2747 XML_NAMESPACE_LO_EXT, XML_LABEL_STRING, aRange);
2749 else
2751 mrExport.AddAttribute(
2752 XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS,
2753 lcl_ConvertRange(
2754 xLabelSeq->getSourceRangeRepresentation(), xNewDoc));
2758 if( xLabelSeq.is() || xValuesSeq.is() )
2759 aSeriesLabelValuesPair = tLabelValuesDataPair( xLabelSeq, xValuesSeq );
2761 // chart-type for mixed types
2762 enum XMLTokenEnum eCTToken(
2763 SchXMLTools::getTokenByChartType( aChartType, false /* bUseOldNames */ ));
2764 //@todo: get token for current charttype
2765 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_CLASS,
2766 mrExport.GetNamespaceMap().GetQNameByKey(
2767 XML_NAMESPACE_CHART, GetXMLToken( eCTToken )));
2769 // open series element until end of for loop
2770 pSeries = new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_SERIES, true, true );
2772 else // autostyles
2774 CollectAutoStyle( aPropertyStates );
2776 // remove property states for autostyles
2777 aPropertyStates.clear();
2781 // export domain elements if we have a series parent element
2782 if( pSeries )
2784 // domain elements
2785 if( bExportContent )
2787 bool bIsScatterChart = aChartType == "com.sun.star.chart2.ScatterChartType";
2788 bool bIsBubbleChart = aChartType == "com.sun.star.chart2.BubbleChartType";
2789 Reference< chart2::data::XDataSequence > xYValuesForBubbleChart;
2790 if( bIsBubbleChart )
2792 Reference< chart2::data::XLabeledDataSequence > xSequence( lcl_getDataSequenceByRole( aSeqCnt, OUString( "values-y" ) ) );
2793 if( xSequence.is() )
2795 xYValuesForBubbleChart = xSequence->getValues();
2796 if( !lcl_exportDomainForThisSequence( xYValuesForBubbleChart, aFirstYDomainRange, mrExport ) )
2797 xYValuesForBubbleChart = 0;
2800 if( bIsScatterChart || bIsBubbleChart )
2802 Reference< chart2::data::XLabeledDataSequence > xSequence( lcl_getDataSequenceByRole( aSeqCnt, OUString( "values-x" ) ) );
2803 if( xSequence.is() )
2805 Reference< chart2::data::XDataSequence > xValues( xSequence->getValues() );
2806 if( lcl_exportDomainForThisSequence( xValues, aFirstXDomainRange, mrExport ) )
2807 m_aDataSequencesToExport.push_back( tLabelValuesDataPair(
2808 uno::Reference< chart2::data::XDataSequence >(), xValues ));
2810 else if( nSeriesIdx==0 )
2812 //might be that the categories are used as x-values (e.g. for date axis) -> export them accordingly
2813 Reference< chart2::data::XLabeledDataSequence > xCategories( lcl_getCategories( xNewDiagram ) );
2814 if( xCategories.is() )
2816 Reference< chart2::data::XDataSequence > xValues( xCategories->getValues() );
2817 if( !lcl_hasNoValuesButText( xValues ) )
2818 lcl_exportDomainForThisSequence( xValues, aFirstXDomainRange, mrExport );
2822 if( xYValuesForBubbleChart.is() )
2823 m_aDataSequencesToExport.push_back( tLabelValuesDataPair(
2824 uno::Reference< chart2::data::XDataSequence >(), xYValuesForBubbleChart ));
2828 // add sequences for main sequence after domain sequences,
2829 // so that the export of the local table has the correct order
2830 if( bExportContent &&
2831 (aSeriesLabelValuesPair.first.is() || aSeriesLabelValuesPair.second.is()))
2832 m_aDataSequencesToExport.push_back( aSeriesLabelValuesPair );
2834 // statistical objects:
2835 // regression curves and mean value lines
2836 if( bHasMeanValueLine &&
2837 xPropSet.is() &&
2838 mxExpPropMapper.is() )
2840 Reference< beans::XPropertySet > xStatProp;
2843 Any aPropAny( xPropSet->getPropertyValue(
2844 OUString( "DataMeanValueProperties" )));
2845 aPropAny >>= xStatProp;
2847 catch( const uno::Exception & rEx )
2849 SAL_INFO("xmloff.chart", "Exception caught during Export of series - optional DataMeanValueProperties not available: " << rEx.Message );
2852 if( xStatProp.is() )
2854 aPropertyStates = mxExpPropMapper->Filter( xStatProp );
2856 if( !aPropertyStates.empty() )
2858 // write element
2859 if( bExportContent )
2861 // add style name attribute
2862 AddAutoStyleAttribute( aPropertyStates );
2864 SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_MEAN_VALUE, true, true );
2866 else // autostyles
2868 CollectAutoStyle( aPropertyStates );
2874 if( xPropSet.is() &&
2875 mxExpPropMapper.is() )
2877 exportRegressionCurve( aSeriesSeq[nSeriesIdx], rPageSize, bExportContent );
2880 exportErrorBar( xPropSet,false, bExportContent ); // X ErrorBar
2881 exportErrorBar( xPropSet,true, bExportContent ); // Y ErrorBar
2883 exportDataPoints(
2884 uno::Reference< beans::XPropertySet >( aSeriesSeq[nSeriesIdx], uno::UNO_QUERY ),
2885 nSeriesLength, xNewDiagram, bExportContent );
2887 const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
2888 if( bExportContent && nCurrentODFVersion > SvtSaveOptions::ODFVER_012 )//do not export to ODF 1.2 or older
2890 Sequence< OUString > aSupportedMappings = aCTSeq[nCTIdx]->getSupportedPropertyRoles();
2891 exportPropertyMapping( xSource, aSupportedMappings );
2894 // close series element
2895 delete pSeries;
2898 aPropertyStates.clear();
2903 void SchXMLExportHelper_Impl::exportPropertyMapping(
2904 const Reference< chart2::data::XDataSource > & xSource, Sequence< OUString >& rSupportedMappings )
2906 Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
2907 Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeqCnt(
2908 xSource->getDataSequences());
2910 for(sal_Int32 i = 0, n = rSupportedMappings.getLength(); i < n; ++i)
2912 Reference< chart2::data::XLabeledDataSequence > xSequence( lcl_getDataSequenceByRole( aSeqCnt, rSupportedMappings[i] ) );
2913 if(xSequence.is())
2915 Reference< chart2::data::XDataSequence > xValues( xSequence->getValues() );
2916 if( xValues.is())
2918 mrExport.AddAttribute( XML_NAMESPACE_LO_EXT, XML_PROPERTY, rSupportedMappings[i]);
2919 mrExport.AddAttribute( XML_NAMESPACE_LO_EXT, XML_CELL_RANGE_ADDRESS,
2920 lcl_ConvertRange(
2921 xValues->getSourceRangeRepresentation(),
2922 xNewDoc ));
2923 SvXMLElementExport( mrExport, XML_NAMESPACE_LO_EXT, XML_PROPERTY_MAPPING, true, true );
2925 // register range for data table export
2926 m_aDataSequencesToExport.push_back( tLabelValuesDataPair(
2927 uno::Reference< chart2::data::XDataSequence >(), xValues ));
2933 void SchXMLExportHelper_Impl::exportRegressionCurve(
2934 const Reference< chart2::XDataSeries >& xSeries,
2935 const awt::Size& rPageSize,
2936 bool bExportContent )
2938 OSL_ASSERT( mxExpPropMapper.is());
2940 std::vector< XMLPropertyState > aPropertyStates;
2941 std::vector< XMLPropertyState > aEquationPropertyStates;
2943 Reference< chart2::XRegressionCurveContainer > xRegressionCurveContainer( xSeries, uno::UNO_QUERY );
2944 if( xRegressionCurveContainer.is() )
2946 Sequence< Reference< chart2::XRegressionCurve > > aRegCurveSeq = xRegressionCurveContainer->getRegressionCurves();
2948 const Reference< chart2::XRegressionCurve >* pBeg = aRegCurveSeq.getConstArray();
2949 const Reference< chart2::XRegressionCurve >* pEnd = pBeg + aRegCurveSeq.getLength();
2950 const Reference< chart2::XRegressionCurve >* pIt;
2952 for( pIt = pBeg; pIt != pEnd; pIt++ )
2954 Reference< chart2::XRegressionCurve > xRegCurve = *pIt;
2955 if (!xRegCurve.is())
2956 continue;
2958 Reference< beans::XPropertySet > xProperties( xRegCurve , uno::UNO_QUERY );
2959 if( !xProperties.is() )
2960 continue;
2962 Reference< lang::XServiceName > xServiceName( xProperties, uno::UNO_QUERY );
2963 if( !xServiceName.is() )
2964 continue;
2966 bool bShowEquation = false;
2967 bool bShowRSquared = false;
2968 bool bExportEquation = false;
2970 OUString aService;
2971 aService = xServiceName->getServiceName();
2973 aPropertyStates = mxExpPropMapper->Filter( xProperties );
2975 // Add service name (which is regression type)
2976 sal_Int32 nIndex = GetPropertySetMapper()->FindEntryIndex(XML_SCH_CONTEXT_SPECIAL_REGRESSION_TYPE);
2977 XMLPropertyState property(nIndex, uno::makeAny(aService));
2978 aPropertyStates.push_back(property);
2980 Reference< beans::XPropertySet > xEquationProperties;
2981 xEquationProperties.set( xRegCurve->getEquationProperties() );
2982 if( xEquationProperties.is())
2984 xEquationProperties->getPropertyValue( "ShowEquation") >>= bShowEquation;
2985 xEquationProperties->getPropertyValue( "ShowCorrelationCoefficient") >>= bShowRSquared;
2987 bExportEquation = ( bShowEquation || bShowRSquared );
2988 const SvtSaveOptions::ODFDefaultVersion nCurrentVersion( SvtSaveOptions().GetODFDefaultVersion() );
2989 if( nCurrentVersion < SvtSaveOptions::ODFVER_012 )
2991 bExportEquation=false;
2993 if( bExportEquation )
2995 // number format
2996 sal_Int32 nNumberFormat = 0;
2997 if( (xEquationProperties->getPropertyValue("NumberFormat") >>= nNumberFormat ) &&
2998 nNumberFormat != -1 )
3000 mrExport.addDataStyle( nNumberFormat );
3002 aEquationPropertyStates = mxExpPropMapper->Filter( xEquationProperties );
3006 if( !aPropertyStates.empty() || bExportEquation )
3008 // write element
3009 if( bExportContent )
3011 // add style name attribute
3012 if( !aPropertyStates.empty())
3014 AddAutoStyleAttribute( aPropertyStates );
3017 SvXMLElementExport aRegressionExport( mrExport, XML_NAMESPACE_CHART, XML_REGRESSION_CURVE, true, true );
3018 if( bExportEquation )
3020 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_DISPLAY_EQUATION, (bShowEquation ? XML_TRUE : XML_FALSE) );
3021 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_DISPLAY_R_SQUARE, (bShowRSquared ? XML_TRUE : XML_FALSE) );
3023 // export position
3024 chart2::RelativePosition aRelativePosition;
3025 if( xEquationProperties->getPropertyValue(OUString( "RelativePosition")) >>= aRelativePosition )
3027 double fX = aRelativePosition.Primary * rPageSize.Width;
3028 double fY = aRelativePosition.Secondary * rPageSize.Height;
3029 awt::Point aPos;
3030 aPos.X = static_cast< sal_Int32 >( ::rtl::math::round( fX ));
3031 aPos.Y = static_cast< sal_Int32 >( ::rtl::math::round( fY ));
3032 addPosition( aPos );
3035 if( !aEquationPropertyStates.empty())
3037 AddAutoStyleAttribute( aEquationPropertyStates );
3040 SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_EQUATION, true, true );
3043 else // autostyles
3045 if( !aPropertyStates.empty())
3047 CollectAutoStyle( aPropertyStates );
3049 if( bExportEquation && !aEquationPropertyStates.empty())
3051 CollectAutoStyle( aEquationPropertyStates );
3059 void SchXMLExportHelper_Impl::exportErrorBar( const Reference<beans::XPropertySet> &xSeriesProp,
3060 bool bYError, bool bExportContent )
3062 assert(mxExpPropMapper.is());
3064 const SvtSaveOptions::ODFDefaultVersion nCurrentVersion( SvtSaveOptions().GetODFDefaultVersion() );
3066 /// Dont export X ErrorBars for older ODF versions.
3067 if ( !bYError && nCurrentVersion < SvtSaveOptions::ODFVER_012 )
3068 return;
3070 if (xSeriesProp.is())
3072 bool bNegative = false, bPositive = false;
3073 sal_Int32 nErrorBarStyle = chart::ErrorBarStyle::NONE;
3074 Reference< beans::XPropertySet > xErrorBarProp;
3078 Any aAny;
3080 aAny = xSeriesProp->getPropertyValue( bYError ? OUString("ErrorBarY") : OUString("ErrorBarX") );
3081 aAny >>= xErrorBarProp;
3083 if ( xErrorBarProp.is() )
3085 aAny = xErrorBarProp->getPropertyValue("ShowNegativeError" );
3086 aAny >>= bNegative;
3088 aAny = xErrorBarProp->getPropertyValue("ShowPositiveError" );
3089 aAny >>= bPositive;
3091 aAny = xErrorBarProp->getPropertyValue("ErrorBarStyle" );
3092 aAny >>= nErrorBarStyle;
3095 catch( const beans::UnknownPropertyException & rEx )
3097 SAL_INFO("xmloff.chart", "Required property not found in DataRowProperties: " << rEx.Message );
3100 if( nErrorBarStyle != chart::ErrorBarStyle::NONE && (bNegative || bPositive))
3102 if( bExportContent && nErrorBarStyle == chart::ErrorBarStyle::FROM_DATA )
3104 uno::Reference< chart2::XChartDocument > xNewDoc(mrExport.GetModel(), uno::UNO_QUERY);
3106 // register data ranges for error bars for export in local table
3107 ::std::vector< Reference< chart2::data::XDataSequence > > aErrorBarSequences(
3108 lcl_getErrorBarSequences( xErrorBarProp ));
3109 for( ::std::vector< Reference< chart2::data::XDataSequence > >::const_iterator aIt(
3110 aErrorBarSequences.begin()); aIt != aErrorBarSequences.end(); ++aIt )
3112 m_aDataSequencesToExport.push_back( tLabelValuesDataPair(
3113 uno::Reference< chart2::data::XDataSequence >(), *aIt ));
3117 std::vector< XMLPropertyState > aPropertyStates = mxExpPropMapper->Filter( xErrorBarProp );
3119 if( !aPropertyStates.empty() )
3121 // write element
3122 if( bExportContent )
3124 // add style name attribute
3125 AddAutoStyleAttribute( aPropertyStates );
3127 if( nCurrentVersion >= SvtSaveOptions::ODFVER_012 )
3128 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_DIMENSION, bYError ? XML_Y : XML_X );//#i114149#
3129 SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_ERROR_INDICATOR, true, true );
3131 else // autostyles
3133 CollectAutoStyle( aPropertyStates );
3140 void SchXMLExportHelper_Impl::exportCandleStickSeries(
3141 const Sequence< Reference< chart2::XDataSeries > > & aSeriesSeq,
3142 const Reference< chart2::XDiagram > & xDiagram,
3143 bool bJapaneseCandleSticks,
3144 bool bExportContent )
3147 for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeriesSeq.getLength(); ++nSeriesIdx )
3149 Reference< chart2::XDataSeries > xSeries( aSeriesSeq[nSeriesIdx] );
3150 sal_Int32 nAttachedAxis = lcl_isSeriesAttachedToFirstAxis( xSeries )
3151 ? chart::ChartAxisAssign::PRIMARY_Y
3152 : chart::ChartAxisAssign::SECONDARY_Y;
3154 Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY );
3155 if( xSource.is())
3157 // export series in correct order (as we don't store roles)
3158 // with japanese candlesticks: open, low, high, close
3159 // otherwise: low, high, close
3160 Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeqCnt(
3161 xSource->getDataSequences());
3163 sal_Int32 nSeriesLength =
3164 lcl_getSequenceLengthByRole( aSeqCnt, OUString( "values-last" ));
3166 if( bExportContent )
3168 Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
3169 //@todo: export data points
3171 //TODO: moggi: same code three times
3172 // open
3173 if( bJapaneseCandleSticks )
3175 tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole(
3176 aSeqCnt, OUString( "values-first" ), xNewDoc, m_aDataSequencesToExport ));
3177 if( !aRanges.second.isEmpty())
3178 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, aRanges.second );
3179 if( !aRanges.first.isEmpty())
3180 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS, aRanges.first );
3181 if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
3182 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y );
3183 else
3184 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y );
3185 SvXMLElementExport aOpenSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, true, true );
3186 // export empty data points
3187 exportDataPoints( 0, nSeriesLength, xDiagram, bExportContent );
3190 // low
3192 tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole(
3193 aSeqCnt, OUString( "values-min" ), xNewDoc, m_aDataSequencesToExport ));
3194 if( !aRanges.second.isEmpty())
3195 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, aRanges.second );
3196 if( !aRanges.first.isEmpty())
3197 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS, aRanges.first );
3198 if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
3199 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y );
3200 else
3201 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y );
3202 SvXMLElementExport aLowSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, true, true );
3203 // export empty data points
3204 exportDataPoints( 0, nSeriesLength, xDiagram, bExportContent );
3207 // high
3209 tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole(
3210 aSeqCnt, OUString( "values-max" ), xNewDoc, m_aDataSequencesToExport ));
3211 if( !aRanges.second.isEmpty())
3212 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, aRanges.second );
3213 if( !aRanges.first.isEmpty())
3214 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS, aRanges.first );
3215 if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
3216 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y );
3217 else
3218 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y );
3219 SvXMLElementExport aHighSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, true, true );
3220 // export empty data points
3221 exportDataPoints( 0, nSeriesLength, xDiagram, bExportContent );
3224 // close
3226 tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole(
3227 aSeqCnt, OUString( "values-last" ), xNewDoc, m_aDataSequencesToExport ));
3228 if( !aRanges.second.isEmpty())
3229 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, aRanges.second );
3230 if( !aRanges.first.isEmpty())
3231 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS, aRanges.first );
3232 if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
3233 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y );
3234 else
3235 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y );
3236 SvXMLElementExport aCloseSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, true, true );
3237 // export empty data points
3238 exportDataPoints( 0, nSeriesLength, xDiagram, bExportContent );
3241 else // autostyles
3243 // for close series
3245 // remove property states for autostyles
3250 void SchXMLExportHelper_Impl::exportDataPoints(
3251 const uno::Reference< beans::XPropertySet > & xSeriesProperties,
3252 sal_Int32 nSeriesLength,
3253 const uno::Reference< chart2::XDiagram > & xDiagram,
3254 bool bExportContent )
3256 // data-points
3258 // write data-points only if they contain autostyles
3259 // objects with equal autostyles are grouped using the attribute
3260 // repeat="number"
3262 // Note: if only the nth data-point has autostyles there is an element
3263 // without style and repeat="n-1" attribute written in advance.
3265 // the sequence aDataPointSeq contains indices of data-points that
3266 // do have own attributes. This increases the performance substantially.
3268 // more performant version for #93600#
3269 if (!mxExpPropMapper.is())
3270 return;
3272 uno::Reference< chart2::XDataSeries > xSeries( xSeriesProperties, uno::UNO_QUERY );
3274 std::vector< XMLPropertyState > aPropertyStates;
3276 bool bVaryColorsByPoint = false;
3277 Sequence< sal_Int32 > aDataPointSeq;
3278 if( xSeriesProperties.is())
3280 xSeriesProperties->getPropertyValue("AttributedDataPoints") >>= aDataPointSeq;
3281 xSeriesProperties->getPropertyValue("VaryColorsByPoint") >>= bVaryColorsByPoint;
3284 sal_Int32 nSize = aDataPointSeq.getLength();
3285 SAL_WARN_IF( nSize > nSeriesLength, "xmloff.chart", "Too many point attributes" );
3287 const sal_Int32 * pPoints = aDataPointSeq.getConstArray();
3288 sal_Int32 nElement;
3289 sal_Int32 nRepeat;
3290 Reference< chart2::XColorScheme > xColorScheme;
3291 if( xDiagram.is())
3292 xColorScheme.set( xDiagram->getDefaultColorScheme());
3294 ::std::list< SchXMLDataPointStruct > aDataPointList;
3296 sal_Int32 nLastIndex = -1;
3297 sal_Int32 nCurrIndex = 0;
3299 // collect elements
3300 if( bVaryColorsByPoint && xColorScheme.is() )
3302 ::std::set< sal_Int32 > aAttrPointSet;
3303 ::std::copy( pPoints, pPoints + aDataPointSeq.getLength(),
3304 ::std::inserter( aAttrPointSet, aAttrPointSet.begin()));
3305 const ::std::set< sal_Int32 >::const_iterator aEndIt( aAttrPointSet.end());
3306 for( nElement = 0; nElement < nSeriesLength; ++nElement )
3308 aPropertyStates.clear();
3309 uno::Reference< beans::XPropertySet > xPropSet;
3310 bool bExportNumFmt = false;
3311 if( aAttrPointSet.find( nElement ) != aEndIt )
3315 xPropSet = SchXMLSeriesHelper::createOldAPIDataPointPropertySet(
3316 xSeries, nElement, mrExport.GetModel() );
3317 bExportNumFmt = true;
3319 catch( const uno::Exception & rEx )
3321 SAL_INFO("xmloff.chart", "Exception caught during Export of data point: " << rEx.Message );
3324 else
3326 // property set only containing the color
3327 xPropSet.set( new ::xmloff::chart::ColorPropertySet(
3328 xColorScheme->getColorByIndex( nElement )));
3330 SAL_WARN_IF( !xPropSet.is(), "xmloff.chart", "Pie Segments should have properties" );
3331 if( xPropSet.is())
3333 const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
3334 if( nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 && bExportNumFmt )
3336 lcl_exportNumberFormat( "NumberFormat", xPropSet, mrExport );
3337 lcl_exportNumberFormat( "PercentageNumberFormat", xPropSet, mrExport );
3340 aPropertyStates = mxExpPropMapper->Filter( xPropSet );
3341 if( !aPropertyStates.empty() )
3343 if( bExportContent )
3345 // write data-point with style
3346 SAL_WARN_IF( maAutoStyleNameQueue.empty(), "xmloff.chart", "Autostyle queue empty!" );
3348 SchXMLDataPointStruct aPoint;
3349 aPoint.maStyleName = maAutoStyleNameQueue.front();
3350 maAutoStyleNameQueue.pop();
3351 aDataPointList.push_back( aPoint );
3353 else
3355 CollectAutoStyle( aPropertyStates );
3360 SAL_WARN_IF( bExportContent && (static_cast<sal_Int32>(aDataPointList.size()) != nSeriesLength), "xmloff.chart", "not enough data points on content export" );
3362 else
3364 for( nElement = 0; nElement < nSize; ++nElement )
3366 aPropertyStates.clear();
3367 nCurrIndex = pPoints[ nElement ];
3368 //assuming sorted indices in pPoints
3370 if( nCurrIndex<0 || nCurrIndex>=nSeriesLength )
3371 break;
3373 // write leading empty data points
3374 if( nCurrIndex - nLastIndex > 1 )
3376 SchXMLDataPointStruct aPoint;
3377 aPoint.mnRepeat = nCurrIndex - nLastIndex - 1;
3378 aDataPointList.push_back( aPoint );
3381 uno::Reference< beans::XPropertySet > xPropSet;
3382 // get property states
3385 xPropSet = SchXMLSeriesHelper::createOldAPIDataPointPropertySet(
3386 xSeries, nCurrIndex, mrExport.GetModel() );
3388 catch( const uno::Exception & rEx )
3390 SAL_INFO("xmloff.chart", "Exception caught during Export of data point: " << rEx.Message );
3392 if( xPropSet.is())
3394 const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
3395 if( nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 )
3397 lcl_exportNumberFormat( "NumberFormat", xPropSet, mrExport );
3398 lcl_exportNumberFormat( "PercentageNumberFormat", xPropSet, mrExport );
3401 aPropertyStates = mxExpPropMapper->Filter( xPropSet );
3402 if( !aPropertyStates.empty() )
3404 if( bExportContent )
3406 // write data-point with style
3407 SAL_WARN_IF( maAutoStyleNameQueue.empty(), "xmloff.chart", "Autostyle queue empty!" );
3408 SchXMLDataPointStruct aPoint;
3409 aPoint.maStyleName = maAutoStyleNameQueue.front();
3410 maAutoStyleNameQueue.pop();
3412 aDataPointList.push_back( aPoint );
3413 nLastIndex = nCurrIndex;
3415 else
3417 CollectAutoStyle( aPropertyStates );
3419 continue;
3423 // if we get here the property states are empty
3424 SchXMLDataPointStruct aPoint;
3425 aDataPointList.push_back( aPoint );
3427 nLastIndex = nCurrIndex;
3429 // final empty elements
3430 nRepeat = nSeriesLength - nLastIndex - 1;
3431 if( nRepeat > 0 )
3433 SchXMLDataPointStruct aPoint;
3434 aPoint.mnRepeat = nRepeat;
3435 aDataPointList.push_back( aPoint );
3439 if (!bExportContent)
3440 return;
3442 // write elements (merge equal ones)
3443 ::std::list< SchXMLDataPointStruct >::iterator aIter = aDataPointList.begin();
3444 SchXMLDataPointStruct aPoint;
3445 SchXMLDataPointStruct aLastPoint;
3447 // initialize so that it doesn't matter if
3448 // the element is counted in the first iteration
3449 aLastPoint.mnRepeat = 0;
3451 for( ; aIter != aDataPointList.end(); ++aIter )
3453 aPoint = (*aIter);
3455 if( aPoint.maStyleName == aLastPoint.maStyleName )
3456 aPoint.mnRepeat += aLastPoint.mnRepeat;
3457 else if( aLastPoint.mnRepeat > 0 )
3459 // write last element
3460 if( !aLastPoint.maStyleName.isEmpty() )
3461 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_STYLE_NAME, aLastPoint.maStyleName );
3463 if( aLastPoint.mnRepeat > 1 )
3464 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_REPEATED,
3465 OUString::number( ( aLastPoint.mnRepeat ) ));
3467 SvXMLElementExport aPointElem( mrExport, XML_NAMESPACE_CHART, XML_DATA_POINT, true, true );
3469 aLastPoint = aPoint;
3471 // write last element if it hasn't been written in last iteration
3472 if( aPoint.maStyleName == aLastPoint.maStyleName )
3474 if( !aLastPoint.maStyleName.isEmpty() )
3475 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_STYLE_NAME, aLastPoint.maStyleName );
3477 if( aLastPoint.mnRepeat > 1 )
3478 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_REPEATED,
3479 OUString::number( ( aLastPoint.mnRepeat ) ));
3481 SvXMLElementExport aPointElem( mrExport, XML_NAMESPACE_CHART, XML_DATA_POINT, true, true );
3485 void SchXMLExportHelper_Impl::addPosition( const awt::Point & rPosition )
3487 mrExport.GetMM100UnitConverter().convertMeasureToXML(
3488 msStringBuffer, rPosition.X );
3489 msString = msStringBuffer.makeStringAndClear();
3490 mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_X, msString );
3492 mrExport.GetMM100UnitConverter().convertMeasureToXML(
3493 msStringBuffer, rPosition.Y );
3494 msString = msStringBuffer.makeStringAndClear();
3495 mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_Y, msString );
3498 void SchXMLExportHelper_Impl::addPosition( Reference< drawing::XShape > xShape )
3500 if( xShape.is())
3501 addPosition( xShape->getPosition());
3504 void SchXMLExportHelper_Impl::addSize( const awt::Size & rSize, bool bIsOOoNamespace)
3506 mrExport.GetMM100UnitConverter().convertMeasureToXML(
3507 msStringBuffer, rSize.Width );
3508 msString = msStringBuffer.makeStringAndClear();
3509 mrExport.AddAttribute( bIsOOoNamespace ? XML_NAMESPACE_CHART_EXT : XML_NAMESPACE_SVG , XML_WIDTH, msString );
3511 mrExport.GetMM100UnitConverter().convertMeasureToXML(
3512 msStringBuffer, rSize.Height);
3513 msString = msStringBuffer.makeStringAndClear();
3514 mrExport.AddAttribute( bIsOOoNamespace ? XML_NAMESPACE_CHART_EXT : XML_NAMESPACE_SVG, XML_HEIGHT, msString );
3517 void SchXMLExportHelper_Impl::addSize( Reference< drawing::XShape > xShape, bool bIsOOoNamespace )
3519 if( xShape.is())
3520 addSize( xShape->getSize(), bIsOOoNamespace );
3523 awt::Size SchXMLExportHelper_Impl::getPageSize( const Reference< chart2::XChartDocument > & xChartDoc )
3525 awt::Size aSize( 8000, 7000 );
3526 uno::Reference< embed::XVisualObject > xVisualObject( xChartDoc, uno::UNO_QUERY );
3527 SAL_WARN_IF( !xVisualObject.is(), "xmloff.chart", "need XVisualObject for page size" );
3528 if( xVisualObject.is() )
3529 aSize = xVisualObject->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );
3531 return aSize;
3534 void SchXMLExportHelper_Impl::CollectAutoStyle( const std::vector< XMLPropertyState >& aStates )
3536 if( !aStates.empty() )
3537 maAutoStyleNameQueue.push( GetAutoStylePoolP().Add( XML_STYLE_FAMILY_SCH_CHART_ID, aStates ));
3540 void SchXMLExportHelper_Impl::AddAutoStyleAttribute( const std::vector< XMLPropertyState >& aStates )
3542 if( !aStates.empty() )
3544 SAL_WARN_IF( maAutoStyleNameQueue.empty(), "xmloff.chart", "Autostyle queue empty!" );
3546 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_STYLE_NAME, maAutoStyleNameQueue.front() );
3547 maAutoStyleNameQueue.pop();
3551 void SchXMLExportHelper_Impl::exportText( const OUString& rText, bool bConvertTabsLFs )
3553 SchXMLTools::exportText( mrExport, rText, bConvertTabsLFs );
3556 // class SchXMLExport
3558 SchXMLExport::SchXMLExport(
3559 const Reference< uno::XComponentContext >& xContext,
3560 OUString const & implementationName, SvXMLExportFlags nExportFlags )
3561 : SvXMLExport( util::MeasureUnit::CM, xContext, implementationName,
3562 ::xmloff::token::XML_CHART, nExportFlags ),
3563 maAutoStylePool( *this ),
3564 maExportHelper( *this, maAutoStylePool )
3566 if( getDefaultVersion() > SvtSaveOptions::ODFVER_012 )
3567 _GetNamespaceMap().Add( GetXMLToken(XML_NP_CHART_EXT), GetXMLToken(XML_N_CHART_EXT), XML_NAMESPACE_CHART_EXT);
3570 SchXMLExport::~SchXMLExport()
3572 // stop progress view
3573 if( mxStatusIndicator.is())
3575 mxStatusIndicator->end();
3576 mxStatusIndicator->reset();
3580 sal_uInt32 SchXMLExport::exportDoc( enum ::xmloff::token::XMLTokenEnum eClass )
3582 maExportHelper.SetSourceShellID(GetSourceShellID());
3583 maExportHelper.SetDestinationShellID(GetDestinationShellID());
3585 Reference< chart2::XChartDocument > xChartDoc( GetModel(), uno::UNO_QUERY );
3586 maExportHelper.m_pImpl->InitRangeSegmentationProperties( xChartDoc );
3587 return SvXMLExport::exportDoc( eClass );
3590 void SchXMLExport::_ExportStyles( bool bUsed )
3592 SvXMLExport::_ExportStyles( bUsed );
3595 void SchXMLExport::_ExportMasterStyles()
3597 // not available in chart
3598 SAL_INFO("xmloff.chart", "Master Style Export requested. Not available for Chart" );
3601 void SchXMLExport::_ExportAutoStyles()
3603 // there are no styles that require their own autostyles
3604 if( getExportFlags() & SvXMLExportFlags::CONTENT )
3606 Reference< chart::XChartDocument > xChartDoc( GetModel(), uno::UNO_QUERY );
3607 if( xChartDoc.is())
3609 maExportHelper.m_pImpl->collectAutoStyles( xChartDoc );
3610 maExportHelper.m_pImpl->exportAutoStyles();
3612 else
3614 SAL_WARN("xmloff.chart", "Couldn't export chart due to wrong XModel (must be XChartDocument)" );
3619 void SchXMLExport::_ExportContent()
3621 Reference< chart::XChartDocument > xChartDoc( GetModel(), uno::UNO_QUERY );
3622 if( xChartDoc.is())
3624 // determine if data comes from the outside
3625 bool bIncludeTable = true;
3627 Reference< chart2::XChartDocument > xNewDoc( xChartDoc, uno::UNO_QUERY );
3628 if( xNewDoc.is())
3630 // check if we have own data. If so we must not export the complete
3631 // range string, as this is our only indicator for having own or
3632 // external data. @todo: fix this in the file format!
3633 Reference< lang::XServiceInfo > xDPServiceInfo( xNewDoc->getDataProvider(), uno::UNO_QUERY );
3634 if( ! (xDPServiceInfo.is() && xDPServiceInfo->getImplementationName() == "com.sun.star.comp.chart.InternalDataProvider" ))
3636 bIncludeTable = false;
3639 else
3641 Reference< lang::XServiceInfo > xServ( xChartDoc, uno::UNO_QUERY );
3642 if( xServ.is())
3644 if( xServ->supportsService(
3645 OUString( "com.sun.star.chart.ChartTableAddressSupplier" )))
3647 Reference< beans::XPropertySet > xProp( xServ, uno::UNO_QUERY );
3648 if( xProp.is())
3650 Any aAny;
3653 OUString sChartAddress;
3654 aAny = xProp->getPropertyValue(
3655 OUString( "ChartRangeAddress" ));
3656 aAny >>= sChartAddress;
3657 maExportHelper.m_pImpl->SetChartRangeAddress( sChartAddress );
3659 OUString sTableNumberList;
3660 aAny = xProp->getPropertyValue(
3661 OUString( "TableNumberList" ));
3662 aAny >>= sTableNumberList;
3663 maExportHelper.m_pImpl->SetTableNumberList( sTableNumberList );
3665 // do not include own table if there are external addresses
3666 bIncludeTable = sChartAddress.isEmpty();
3668 catch( const beans::UnknownPropertyException & )
3670 SAL_WARN("xmloff.chart", "Property ChartRangeAddress not supported by ChartDocument" );
3676 maExportHelper.m_pImpl->exportChart( xChartDoc, bIncludeTable );
3678 else
3680 SAL_WARN("xmloff.chart", "Couldn't export chart due to wrong XModel" );
3684 rtl::Reference< XMLPropertySetMapper > SchXMLExport::GetPropertySetMapper() const
3686 return maExportHelper.m_pImpl->GetPropertySetMapper();
3689 void SchXMLExportHelper_Impl::InitRangeSegmentationProperties( const Reference< chart2::XChartDocument > & xChartDoc )
3691 if( xChartDoc.is())
3694 Reference< chart2::data::XDataProvider > xDataProvider( xChartDoc->getDataProvider() );
3695 SAL_WARN_IF( !xDataProvider.is(), "xmloff.chart", "No DataProvider" );
3696 if( xDataProvider.is())
3698 Reference< chart2::data::XDataSource > xDataSource( lcl_pressUsedDataIntoRectangularFormat( xChartDoc, mbHasCategoryLabels ));
3699 Sequence< beans::PropertyValue > aArgs( xDataProvider->detectArguments( xDataSource ));
3700 OUString sCellRange, sBrokenRange;
3701 bool bBrokenRangeAvailable = false;
3702 for( sal_Int32 i=0; i<aArgs.getLength(); ++i )
3704 if ( aArgs[i].Name == "CellRangeRepresentation" )
3705 aArgs[i].Value >>= sCellRange;
3706 else if ( aArgs[i].Name == "BrokenCellRangeForExport" )
3708 if( aArgs[i].Value >>= sBrokenRange )
3709 bBrokenRangeAvailable = true;
3711 else if ( aArgs[i].Name == "DataRowSource" )
3713 chart::ChartDataRowSource eRowSource;
3714 aArgs[i].Value >>= eRowSource;
3715 mbRowSourceColumns = ( eRowSource == chart::ChartDataRowSource_COLUMNS );
3717 else if ( aArgs[i].Name == "FirstCellAsLabel" )
3718 aArgs[i].Value >>= mbHasSeriesLabels;
3719 else if ( aArgs[i].Name == "SequenceMapping" )
3720 aArgs[i].Value >>= maSequenceMapping;
3721 else if ( aArgs[i].Name == "TableNumberList" )
3722 aArgs[i].Value >>= msTableNumberList;
3725 // #i79009# For Writer we have to export a broken version of the
3726 // range, where every row number is noe too large, so that older
3727 // version can correctly read those files.
3728 msChartAddress = (bBrokenRangeAvailable ? sBrokenRange : sCellRange);
3729 if( !msChartAddress.isEmpty() )
3731 // convert format to XML-conform one
3732 Reference< chart2::data::XRangeXMLConversion > xConversion( xDataProvider, uno::UNO_QUERY );
3733 if( xConversion.is())
3734 msChartAddress = xConversion->convertRangeToXML( msChartAddress );
3738 catch( const uno::Exception & ex )
3740 SAL_WARN("xmloff.chart", "Exception caught. Type: " << OUString::createFromAscii( typeid( ex ).name()) << ", Message: " << ex.Message);
3744 // first version: everything goes in one storage
3746 Sequence< OUString > SAL_CALL SchXMLExport_getSupportedServiceNames() throw()
3748 const OUString aServiceName( "com.sun.star.comp.Chart.XMLExporter" );
3749 const Sequence< OUString > aSeq( &aServiceName, 1 );
3750 return aSeq;
3753 OUString SAL_CALL SchXMLExport_getImplementationName() throw()
3755 return OUString( "SchXMLExport.Compact" );
3758 Reference< uno::XInterface > SAL_CALL SchXMLExport_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception )
3760 // #110680#
3761 // #103997# removed some flags from EXPORT_ALL
3762 return (cppu::OWeakObject*)new SchXMLExport( comphelper::getComponentContext(rSMgr), SchXMLExport_getImplementationName(), SvXMLExportFlags::ALL ^ ( SvXMLExportFlags::SETTINGS | SvXMLExportFlags::MASTERSTYLES | SvXMLExportFlags::SCRIPTS ));
3765 // Oasis format
3766 Sequence< OUString > SAL_CALL SchXMLExport_Oasis_getSupportedServiceNames() throw()
3768 const OUString aServiceName( "com.sun.star.comp.Chart.XMLOasisExporter" );
3769 const Sequence< OUString > aSeq( &aServiceName, 1 );
3770 return aSeq;
3773 OUString SAL_CALL SchXMLExport_Oasis_getImplementationName() throw()
3775 return OUString( "SchXMLExport.Oasis.Compact" );
3778 Reference< uno::XInterface > SAL_CALL SchXMLExport_Oasis_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception )
3780 // #103997# removed some flags from EXPORT_ALL
3781 return (cppu::OWeakObject*)new SchXMLExport( comphelper::getComponentContext(rSMgr),
3782 SchXMLExport_Oasis_getImplementationName(),
3783 (SvXMLExportFlags::ALL ^ ( SvXMLExportFlags::SETTINGS | SvXMLExportFlags::MASTERSTYLES | SvXMLExportFlags::SCRIPTS )) | SvXMLExportFlags::OASIS );
3786 // multiple storage version: one for content / styles / meta
3788 Sequence< OUString > SAL_CALL SchXMLExport_Styles_getSupportedServiceNames() throw()
3790 const OUString aServiceName( "com.sun.star.comp.Chart.XMLStylesExporter" );
3791 const Sequence< OUString > aSeq( &aServiceName, 1 );
3792 return aSeq;
3795 OUString SAL_CALL SchXMLExport_Styles_getImplementationName() throw()
3797 return OUString( "SchXMLExport.Styles" );
3800 Reference< uno::XInterface > SAL_CALL SchXMLExport_Styles_createInstance(const Reference< lang::XMultiServiceFactory >& rSMgr) throw( uno::Exception )
3802 // #110680#
3803 return (cppu::OWeakObject*)new SchXMLExport( comphelper::getComponentContext(rSMgr), SchXMLExport_Styles_getImplementationName(), SvXMLExportFlags::STYLES );
3806 // Oasis format
3807 Sequence< OUString > SAL_CALL SchXMLExport_Oasis_Styles_getSupportedServiceNames() throw()
3809 const OUString aServiceName( "com.sun.star.comp.Chart.XMLOasisStylesExporter" );
3810 const Sequence< OUString > aSeq( &aServiceName, 1 );
3811 return aSeq;
3814 OUString SAL_CALL SchXMLExport_Oasis_Styles_getImplementationName() throw()
3816 return OUString( "SchXMLExport.Oasis.Styles" );
3819 Reference< uno::XInterface > SAL_CALL SchXMLExport_Oasis_Styles_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception )
3821 return (cppu::OWeakObject*)new SchXMLExport( comphelper::getComponentContext(rSMgr), SchXMLExport_Oasis_Styles_getImplementationName(), SvXMLExportFlags::STYLES | SvXMLExportFlags::OASIS );
3824 Sequence< OUString > SAL_CALL SchXMLExport_Content_getSupportedServiceNames() throw()
3826 const OUString aServiceName( "com.sun.star.comp.Chart.XMLContentExporter" );
3827 const Sequence< OUString > aSeq( &aServiceName, 1 );
3828 return aSeq;
3831 OUString SAL_CALL SchXMLExport_Content_getImplementationName() throw()
3833 return OUString( "SchXMLExport.Content" );
3836 Reference< uno::XInterface > SAL_CALL SchXMLExport_Content_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception )
3838 // #110680#
3839 return (cppu::OWeakObject*)new SchXMLExport( comphelper::getComponentContext(rSMgr), SchXMLExport_Content_getImplementationName(), SvXMLExportFlags::AUTOSTYLES | SvXMLExportFlags::CONTENT | SvXMLExportFlags::FONTDECLS );
3842 // Oasis format
3843 Sequence< OUString > SAL_CALL SchXMLExport_Oasis_Content_getSupportedServiceNames() throw()
3845 const OUString aServiceName( "com.sun.star.comp.Chart.XMLOasisContentExporter" );
3846 const Sequence< OUString > aSeq( &aServiceName, 1 );
3847 return aSeq;
3850 OUString SAL_CALL SchXMLExport_Oasis_Content_getImplementationName() throw()
3852 return OUString( "SchXMLExport.Oasis.Content" );
3855 Reference< uno::XInterface > SAL_CALL SchXMLExport_Oasis_Content_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception )
3857 return (cppu::OWeakObject*)new SchXMLExport( comphelper::getComponentContext(rSMgr), SchXMLExport_Oasis_Content_getImplementationName(), SvXMLExportFlags::AUTOSTYLES | SvXMLExportFlags::CONTENT | SvXMLExportFlags::FONTDECLS | SvXMLExportFlags::OASIS );
3860 // Oasis format
3861 Sequence< OUString > SAL_CALL SchXMLExport_Oasis_Meta_getSupportedServiceNames() throw()
3863 const OUString aServiceName( "com.sun.star.comp.Chart.XMLOasisMetaExporter" );
3864 const Sequence< OUString > aSeq( &aServiceName, 1 );
3865 return aSeq;
3868 OUString SAL_CALL SchXMLExport_Oasis_Meta_getImplementationName() throw()
3870 return OUString( "SchXMLExport.Oasis.Meta" );
3873 Reference< uno::XInterface > SAL_CALL SchXMLExport_Oasis_Meta_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception )
3875 return (cppu::OWeakObject*)new SchXMLExport( comphelper::getComponentContext(rSMgr), SchXMLExport_Oasis_Meta_getImplementationName(), SvXMLExportFlags::META | SvXMLExportFlags::OASIS );
3878 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */