Version 5.2.6.1, tag libreoffice-5.2.6.1
[LibreOffice.git] / xmloff / source / chart / SchXMLExport.cxx
blobcde9788670281aebfbecabad5d3fd2e05a1c2086
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 <sax/tools/converter.hxx>
24 #include <xmloff/xmlprmap.hxx>
26 #include "SchXMLExport.hxx"
27 #include "XMLChartPropertySetMapper.hxx"
28 #include "ColorPropertySet.hxx"
29 #include "SchXMLTools.hxx"
30 #include "SchXMLEnumConverter.hxx"
31 #include "facreg.hxx"
33 #include <comphelper/processfactory.hxx>
34 #include <tools/globname.hxx>
35 #include <comphelper/classids.hxx>
36 #include <comphelper/sequence.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
122 public:
123 // first: data sequence for label, second: data sequence for values.
124 typedef ::std::pair< css::uno::Reference< css::chart2::data::XDataSequence >,
125 css::uno::Reference< css::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 SchXMLExportHelper_Impl(const SchXMLExportHelper_Impl&) = delete;
135 SchXMLExportHelper_Impl& operator=(const SchXMLExportHelper_Impl&) = delete;
137 // auto-styles
138 /// parse chart and collect all auto-styles used in current pool
139 void collectAutoStyles( css::uno::Reference< css::chart::XChartDocument > rChartDoc );
141 /// write the styles collected into the current pool as <style:style> elements
142 void exportAutoStyles();
144 /** export the <chart:chart> element corresponding to rChartDoc
145 if bIncludeTable is true, the chart data is exported as <table:table>
146 element (inside the chart element).
148 Otherwise the external references stored in the chart document are used
149 for writing the corresponding attributes at series
151 All attributes contained in xAttrList are written at the chart element,
152 which is the outer element of a chart. So these attributes can easily
153 be parsed again by the container
155 void exportChart( css::uno::Reference< css::chart::XChartDocument > rChartDoc,
156 bool bIncludeTable );
158 const rtl::Reference<XMLPropertySetMapper>& GetPropertySetMapper() const;
160 void SetChartRangeAddress( const OUString& rAddress )
161 { msChartAddress = rAddress; }
162 void SetTableNumberList( const OUString& rList )
163 { msTableNumberList = rList; }
165 void InitRangeSegmentationProperties(
166 const css::uno::Reference< css::chart2::XChartDocument > & xChartDoc );
168 static css::awt::Size getPageSize(
169 const css::uno::Reference< css::chart2::XChartDocument > & xChartDoc );
171 /** first parseDocument: collect autostyles and store names in this queue
172 second parseDocument: export content and use names from this queue
174 ::std::queue< OUString > maAutoStyleNameQueue;
175 void CollectAutoStyle(
176 const std::vector< XMLPropertyState >& aStates );
177 void AddAutoStyleAttribute(
178 const std::vector< XMLPropertyState >& aStates );
180 SvXMLAutoStylePoolP& GetAutoStylePoolP()
181 { return mrAutoStylePool; }
183 /// if bExportContent is false the auto-styles are collected
184 void parseDocument( css::uno::Reference< css::chart::XChartDocument >& rChartDoc,
185 bool bExportContent,
186 bool bIncludeTable = false );
187 void exportTable();
188 void exportPlotArea(
189 const css::uno::Reference< css::chart::XDiagram >& xDiagram,
190 const css::uno::Reference< css::chart2::XDiagram >& xNewDiagram,
191 const css::awt::Size & rPageSize,
192 bool bExportContent,
193 bool bIncludeTable );
194 void exportCoordinateRegion( const css::uno::Reference< css::chart::XDiagram >& xDiagram );
195 void exportAxes( const css::uno::Reference< css::chart::XDiagram > & xDiagram,
196 const css::uno::Reference< css::chart2::XDiagram > & xNewDiagram,
197 bool bExportContent );
198 void exportAxis( enum XMLTokenEnum eDimension, enum XMLTokenEnum eAxisName,
199 const Reference< beans::XPropertySet >& rAxisProps, const Reference< chart2::XAxis >& rChart2Axis,
200 const OUString& rCategoriesRanges,
201 bool bHasTitle, bool bHasMajorGrid, bool bHasMinorGrid, bool bExportContent );
202 void exportGrid( const Reference< beans::XPropertySet >& rGridProperties, bool bMajor, bool bExportContent );
203 void exportDateScale( const Reference< beans::XPropertySet >& rAxisProps );
204 void exportAxisTitle( const Reference< beans::XPropertySet >& rTitleProps, bool bExportContent );
206 void exportSeries(
207 const css::uno::Reference< css::chart2::XDiagram > & xNewDiagram,
208 const css::awt::Size & rPageSize,
209 bool bExportContent,
210 bool bHasTwoYAxes );
212 void exportPropertyMapping(
213 const css::uno::Reference< css::chart2::data::XDataSource > & xSource,
214 Sequence< OUString >& rSupportedMappings );
216 void exportCandleStickSeries(
217 const css::uno::Sequence<
218 css::uno::Reference< css::chart2::XDataSeries > > & aSeriesSeq,
219 const css::uno::Reference< css::chart2::XDiagram > & xDiagram,
220 bool bJapaneseCandleSticks,
221 bool bExportContent );
222 void exportDataPoints(
223 const css::uno::Reference< css::beans::XPropertySet > & xSeriesProperties,
224 sal_Int32 nSeriesLength,
225 const css::uno::Reference< css::chart2::XDiagram > & xDiagram,
226 bool bExportContent );
228 void exportRegressionCurve(
229 const css::uno::Reference<css::chart2::XDataSeries>& xSeries,
230 const css::awt::Size& rPageSize,
231 bool bExportContent );
233 void exportErrorBar (
234 const css::uno::Reference<beans::XPropertySet> &xSeriesProp, bool bYError,
235 bool bExportContent );
237 /// add svg position as attribute for current element
238 void addPosition( const css::awt::Point & rPosition );
239 void addPosition( const css::uno::Reference< css::drawing::XShape >& xShape );
240 /// add svg size as attribute for current element
241 void addSize( const css::awt::Size & rSize, bool bIsOOoNamespace = false );
242 void addSize( const css::uno::Reference< css::drawing::XShape >& xShape );
243 /// exports a string as a paragraph element
244 void exportText( const OUString& rText );
246 public:
247 SvXMLExport& mrExport;
248 SvXMLAutoStylePoolP& mrAutoStylePool;
249 rtl::Reference< XMLPropertySetMapper > mxPropertySetMapper;
250 rtl::Reference< XMLChartExportPropertyMapper > mxExpPropMapper;
252 OUString msTableName;
253 OUStringBuffer msStringBuffer;
254 OUString msString;
256 // members filled by InitRangeSegmentationProperties (retrieved from DataProvider)
257 bool mbHasSeriesLabels;
258 bool mbHasCategoryLabels; //if the categories are only automatically generated this will be false
259 bool mbRowSourceColumns;
260 OUString msChartAddress;
261 OUString msTableNumberList;
262 css::uno::Sequence< sal_Int32 > maSequenceMapping;
264 OUString msCLSID;
266 OUString maSrcShellID;
267 OUString maDestShellID;
269 css::uno::Reference< css::drawing::XShapes > mxAdditionalShapes;
271 tDataSequenceCont m_aDataSequencesToExport;
272 OUString maCategoriesRange;
275 namespace
278 class lcl_MatchesRole : public ::std::unary_function< Reference< chart2::data::XLabeledDataSequence >, bool >
280 public:
281 explicit lcl_MatchesRole( const OUString & aRole ) :
282 m_aRole( aRole )
285 bool operator () ( const Reference< chart2::data::XLabeledDataSequence > & xSeq ) const
287 if( !xSeq.is() )
288 return false;
289 Reference< beans::XPropertySet > xProp( xSeq->getValues(), uno::UNO_QUERY );
290 OUString aRole;
292 return ( xProp.is() &&
293 (xProp->getPropertyValue( "Role" ) >>= aRole ) &&
294 m_aRole.equals( aRole ));
297 private:
298 OUString m_aRole;
301 template< typename T >
302 void lcl_SequenceToVectorAppend( const Sequence< T > & rSource, ::std::vector< T > & rDestination )
304 rDestination.reserve( rDestination.size() + rSource.getLength());
305 ::std::copy( rSource.begin(), rSource.end(),
306 ::std::back_inserter( rDestination ));
309 template< typename T >
310 void lcl_SequenceToVector( const Sequence< T > & rSource, ::std::vector< T > & rDestination )
312 rDestination.clear();
313 lcl_SequenceToVectorAppend( rSource, rDestination );
316 Reference< chart2::data::XLabeledDataSequence > lcl_getCategories( const Reference< chart2::XDiagram > & xDiagram )
318 Reference< chart2::data::XLabeledDataSequence > xResult;
321 Reference< chart2::XCoordinateSystemContainer > xCooSysCnt(
322 xDiagram, uno::UNO_QUERY_THROW );
323 Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq(
324 xCooSysCnt->getCoordinateSystems());
325 for( sal_Int32 i=0; i<aCooSysSeq.getLength(); ++i )
327 Reference< chart2::XCoordinateSystem > xCooSys( aCooSysSeq[i] );
328 SAL_WARN_IF( !xCooSys.is(), "xmloff.chart", "xCooSys is NULL" );
329 for( sal_Int32 nN = xCooSys->getDimension(); nN--; )
331 const sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nN);
332 for(sal_Int32 nI=0; nI<=nMaxAxisIndex; ++nI)
334 Reference< chart2::XAxis > xAxis = xCooSys->getAxisByDimension( nN, nI );
335 SAL_WARN_IF( !xAxis.is(), "xmloff.chart", "xAxis is NULL");
336 if( xAxis.is())
338 chart2::ScaleData aScaleData = xAxis->getScaleData();
339 if( aScaleData.Categories.is())
341 xResult.set( aScaleData.Categories );
342 break;
349 catch( const uno::Exception & ex )
351 SAL_WARN("xmloff.chart", "Exception caught. Type: " << OUString::createFromAscii( typeid( ex ).name()) << ", Message: " << ex.Message);
354 return xResult;
357 Reference< chart2::data::XDataSource > lcl_createDataSource(
358 const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aData )
360 Reference< uno::XComponentContext > xContext(
361 comphelper::getProcessComponentContext() );
362 Reference< chart2::data::XDataSink > xSink(
363 xContext->getServiceManager()->createInstanceWithContext(
364 "com.sun.star.chart2.data.DataSource", xContext ),
365 uno::UNO_QUERY_THROW );
366 xSink->setData( aData );
368 return Reference< chart2::data::XDataSource >( xSink, uno::UNO_QUERY );
371 Sequence< Reference< chart2::data::XLabeledDataSequence > > lcl_getAllSeriesSequences( const Reference< chart2::XChartDocument >& xChartDoc )
373 ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aContainer;
374 if( xChartDoc.is() )
376 Reference< chart2::XDiagram > xDiagram( xChartDoc->getFirstDiagram());
377 ::std::vector< Reference< chart2::XDataSeries > > aSeriesVector( SchXMLSeriesHelper::getDataSeriesFromDiagram( xDiagram ));
378 for( ::std::vector< Reference< chart2::XDataSeries > >::const_iterator aSeriesIt( aSeriesVector.begin() )
379 ; aSeriesIt != aSeriesVector.end(); ++aSeriesIt )
381 Reference< chart2::data::XDataSource > xDataSource( *aSeriesIt, uno::UNO_QUERY );
382 if( !xDataSource.is() )
383 continue;
384 uno::Sequence< Reference< chart2::data::XLabeledDataSequence > > aDataSequences( xDataSource->getDataSequences() );
385 lcl_SequenceToVectorAppend( aDataSequences, aContainer );
389 return comphelper::containerToSequence< Reference< chart2::data::XLabeledDataSequence > >( aContainer );
392 Reference< chart2::data::XLabeledDataSequence >
393 lcl_getDataSequenceByRole(
394 const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aLabeledSeq,
395 const OUString & rRole )
397 Reference< chart2::data::XLabeledDataSequence > aNoResult;
399 const Reference< chart2::data::XLabeledDataSequence > * pBegin = aLabeledSeq.getConstArray();
400 const Reference< chart2::data::XLabeledDataSequence > * pEnd = pBegin + aLabeledSeq.getLength();
401 const Reference< chart2::data::XLabeledDataSequence > * pMatch =
402 ::std::find_if( pBegin, pEnd, lcl_MatchesRole( rRole ));
404 if( pMatch != pEnd )
405 return *pMatch;
407 return aNoResult;
410 Reference< chart2::data::XDataSource > lcl_pressUsedDataIntoRectangularFormat( const Reference< chart2::XChartDocument >& xChartDoc, bool& rOutSourceHasCategoryLabels )
412 ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aLabeledSeqVector;
414 //categories are always the first sequence
415 Reference< chart2::XDiagram > xDiagram( xChartDoc->getFirstDiagram());
416 Reference< chart2::data::XLabeledDataSequence > xCategories( lcl_getCategories( xDiagram ) );
417 if( xCategories.is() )
418 aLabeledSeqVector.push_back( xCategories );
419 rOutSourceHasCategoryLabels = xCategories.is();
421 Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeriesSeqVector(
422 lcl_getAllSeriesSequences( xChartDoc ) );
424 //the first x-values is always the next sequence //todo ... other x-values get lost for old format
425 Reference< chart2::data::XLabeledDataSequence > xXValues(
426 lcl_getDataSequenceByRole( aSeriesSeqVector, "values-x" ) );
427 if( xXValues.is() )
428 aLabeledSeqVector.push_back( xXValues );
430 //add all other sequences now without x-values
431 lcl_MatchesRole aHasXValues( OUString( "values-x" ) );
432 for( sal_Int32 nN=0; nN<aSeriesSeqVector.getLength(); nN++ )
434 if( !aHasXValues( aSeriesSeqVector[nN] ) )
435 aLabeledSeqVector.push_back( aSeriesSeqVector[nN] );
438 Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeq( comphelper::containerToSequence(aLabeledSeqVector) );
440 return lcl_createDataSource( aSeq );
443 bool lcl_isSeriesAttachedToFirstAxis(
444 const Reference< chart2::XDataSeries > & xDataSeries )
446 bool bResult=true;
450 sal_Int32 nAxisIndex = 0;
451 Reference< beans::XPropertySet > xProp( xDataSeries, uno::UNO_QUERY_THROW );
452 if( xProp.is() )
453 xProp->getPropertyValue("AttachedAxisIndex") >>= nAxisIndex;
454 bResult = (0==nAxisIndex);
456 catch( const uno::Exception & ex )
458 SAL_WARN("xmloff.chart", "Exception caught. Type: " << OUString::createFromAscii( typeid( ex ).name()) << ", Message: " << ex.Message);
461 return bResult;
464 OUString lcl_ConvertRange( const OUString & rRange, const Reference< chart2::XChartDocument > & xDoc )
466 OUString aResult = rRange;
467 if( !xDoc.is() )
468 return aResult;
469 Reference< chart2::data::XRangeXMLConversion > xConversion(
470 xDoc->getDataProvider(), uno::UNO_QUERY );
471 if( xConversion.is())
472 aResult = xConversion->convertRangeToXML( rRange );
473 return aResult;
476 typedef ::std::pair< OUString, OUString > tLabelAndValueRange;
478 tLabelAndValueRange lcl_getLabelAndValueRangeByRole(
479 const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aSeqCnt,
480 const OUString & rRole,
481 const Reference< chart2::XChartDocument > & xDoc,
482 SchXMLExportHelper_Impl::tDataSequenceCont & rOutSequencesToExport )
484 tLabelAndValueRange aResult;
486 Reference< chart2::data::XLabeledDataSequence > xLabeledSeq(
487 lcl_getDataSequenceByRole( aSeqCnt, rRole ));
488 if( xLabeledSeq.is())
490 Reference< chart2::data::XDataSequence > xLabelSeq( xLabeledSeq->getLabel());
491 if( xLabelSeq.is())
492 aResult.first = lcl_ConvertRange( xLabelSeq->getSourceRangeRepresentation(), xDoc );
494 Reference< chart2::data::XDataSequence > xValueSeq( xLabeledSeq->getValues());
495 if( xValueSeq.is())
496 aResult.second = lcl_ConvertRange( xValueSeq->getSourceRangeRepresentation(), xDoc );
498 if( xLabelSeq.is() || xValueSeq.is())
499 rOutSequencesToExport.push_back( SchXMLExportHelper_Impl::tLabelValuesDataPair( xLabelSeq, xValueSeq ));
502 return aResult;
505 sal_Int32 lcl_getSequenceLengthByRole(
506 const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aSeqCnt,
507 const OUString & rRole )
509 Reference< chart2::data::XLabeledDataSequence > xLabeledSeq(
510 lcl_getDataSequenceByRole( aSeqCnt, rRole ));
511 if( xLabeledSeq.is())
513 Reference< chart2::data::XDataSequence > xSeq( xLabeledSeq->getValues());
514 return xSeq->getData().getLength();
516 return 0;
519 OUString lcl_flattenStringSequence( const Sequence< OUString > & rSequence )
521 OUStringBuffer aResult;
522 bool bPrecedeWithSpace = false;
523 for( sal_Int32 nIndex=0; nIndex<rSequence.getLength(); ++nIndex )
525 if( !rSequence[nIndex].isEmpty())
527 if( bPrecedeWithSpace )
528 aResult.append( ' ' );
529 aResult.append( rSequence[nIndex] );
530 bPrecedeWithSpace = true;
533 return aResult.makeStringAndClear();
536 void lcl_getLabelStringSequence( Sequence< OUString >& rOutLabels, const Reference< chart2::data::XDataSequence > & xLabelSeq )
538 uno::Reference< chart2::data::XTextualDataSequence > xTextualDataSequence( xLabelSeq, uno::UNO_QUERY );
539 if( xTextualDataSequence.is())
541 rOutLabels = xTextualDataSequence->getTextualData();
543 else if( xLabelSeq.is())
545 Sequence< uno::Any > aAnies( xLabelSeq->getData());
546 rOutLabels.realloc( aAnies.getLength());
547 for( sal_Int32 i=0; i<aAnies.getLength(); ++i )
548 aAnies[i] >>= rOutLabels[i];
552 sal_Int32 lcl_getMaxSequenceLength(
553 const SchXMLExportHelper_Impl::tDataSequenceCont & rContainer )
555 sal_Int32 nResult = 0;
556 for( SchXMLExportHelper_Impl::tDataSequenceCont::const_iterator aIt( rContainer.begin());
557 aIt != rContainer.end(); ++aIt )
559 if( aIt->second.is())
561 sal_Int32 nSeqLength = aIt->second->getData().getLength();
562 if( nSeqLength > nResult )
563 nResult = nSeqLength;
566 return nResult;
569 uno::Sequence< OUString > lcl_DataSequenceToStringSequence(
570 const uno::Reference< chart2::data::XDataSequence >& xDataSequence )
572 uno::Sequence< OUString > aResult;
573 if(!xDataSequence.is())
574 return aResult;
576 uno::Reference< chart2::data::XTextualDataSequence > xTextualDataSequence( xDataSequence, uno::UNO_QUERY );
577 if( xTextualDataSequence.is() )
579 aResult = xTextualDataSequence->getTextualData();
581 else
583 uno::Sequence< uno::Any > aValues = xDataSequence->getData();
584 aResult.realloc(aValues.getLength());
586 for(sal_Int32 nN=aValues.getLength();nN--;)
587 aValues[nN] >>= aResult[nN];
590 return aResult;
592 ::std::vector< double > lcl_getAllValuesFromSequence( const Reference< chart2::data::XDataSequence > & xSeq )
594 double fNan = 0.0;
595 ::rtl::math::setNan( &fNan );
596 ::std::vector< double > aResult;
597 if(!xSeq.is())
598 return aResult;
600 uno::Sequence< double > aValuesSequence;
601 Reference< chart2::data::XNumericalDataSequence > xNumSeq( xSeq, uno::UNO_QUERY );
602 if( xNumSeq.is() )
604 aValuesSequence = xNumSeq->getNumericalData();
606 else
608 Sequence< uno::Any > aAnies( xSeq->getData() );
609 aValuesSequence.realloc( aAnies.getLength() );
610 for( sal_Int32 i=0; i<aAnies.getLength(); ++i )
611 aAnies[i] >>= aValuesSequence[i];
614 //special handling for x-values (if x-values do point to categories, indices are used instead )
615 Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY );
616 if( xProp.is() )
618 OUString aRole;
619 xProp->getPropertyValue("Role") >>= aRole;
620 if( aRole.match("values-x") )
622 //lcl_clearIfNoValuesButTextIsContained - replace by indices if the values are not appropriate
623 bool bHasValue=false;
624 bool bHasText=false;
625 sal_Int32 nCount = aValuesSequence.getLength();
626 for( sal_Int32 j = 0; j < nCount; ++j )
628 if( !::rtl::math::isNan( aValuesSequence[j] ) )
630 bHasValue=true;
631 break;
634 if(!bHasValue)
636 //no double value is contained
637 //is there any text?
638 uno::Sequence< OUString > aStrings( lcl_DataSequenceToStringSequence( xSeq ) );
639 sal_Int32 nTextCount = aStrings.getLength();
640 for( sal_Int32 j = 0; j < nTextCount; ++j )
642 if( !aStrings[j].isEmpty() )
644 bHasText=true;
645 break;
649 if( !bHasValue && bHasText )
651 for( sal_Int32 j = 0; j < nCount; ++j )
652 aValuesSequence[j] = j+1;
657 ::std::copy( aValuesSequence.begin(), aValuesSequence.end(),
658 ::std::back_inserter( aResult ));
659 return aResult;
662 bool lcl_SequenceHasUnhiddenData( const uno::Reference< chart2::data::XDataSequence >& xDataSequence )
664 if( !xDataSequence.is() )
665 return false;
666 uno::Reference< beans::XPropertySet > xProp( xDataSequence, uno::UNO_QUERY );
667 if( xProp.is() )
669 uno::Sequence< sal_Int32 > aHiddenValues;
672 xProp->getPropertyValue("HiddenValues") >>= aHiddenValues;
673 if( !aHiddenValues.getLength() )
674 return true;
676 catch( const uno::Exception& )
678 return true;
681 if( xDataSequence->getData().getLength() )
682 return true;
683 return false;
686 typedef vector< OUString > tStringVector;
687 typedef vector< vector< double > > t2DNumberContainer;
689 struct lcl_TableData
691 t2DNumberContainer aDataInRows;
692 tStringVector aDataRangeRepresentations;
694 tStringVector aColumnDescriptions;
695 tStringVector aColumnDescriptions_Ranges;
697 tStringVector aRowDescriptions;
698 tStringVector aRowDescriptions_Ranges;
700 Sequence< Sequence< uno::Any > > aComplexColumnDescriptions;//outer index is columns - inner index is level
701 Sequence< Sequence< uno::Any > > aComplexRowDescriptions;//outer index is rows - inner index is level
703 ::std::vector< sal_Int32 > aHiddenColumns;
706 typedef ::std::map< sal_Int32, SchXMLExportHelper_Impl::tLabelValuesDataPair >
707 lcl_DataSequenceMap;
709 struct lcl_SequenceToMapElement :
710 public ::std::unary_function< lcl_DataSequenceMap::mapped_type, lcl_DataSequenceMap::value_type >
712 lcl_SequenceToMapElement()
714 result_type operator() ( const argument_type & rContent )
716 sal_Int32 nIndex = -1;
717 if( rContent.second.is()) //has values
719 OUString aRangeRep( rContent.second->getSourceRangeRepresentation());
720 nIndex = aRangeRep.toInt32();
722 else if( rContent.first.is()) //has labels
723 nIndex = rContent.first->getSourceRangeRepresentation().copy( sizeof("label ")).toInt32();
724 return result_type( nIndex, rContent );
728 void lcl_ReorderInternalSequencesAccordingToTheirRangeName(
729 SchXMLExportHelper_Impl::tDataSequenceCont & rInOutSequences )
731 lcl_DataSequenceMap aIndexSequenceMap;
732 ::std::transform( rInOutSequences.begin(), rInOutSequences.end(),
733 ::std::inserter( aIndexSequenceMap, aIndexSequenceMap.begin()),
734 lcl_SequenceToMapElement());
736 rInOutSequences.clear();
737 sal_Int32 nIndex = 0;
738 for( lcl_DataSequenceMap::const_iterator aIt = aIndexSequenceMap.begin();
739 aIt != aIndexSequenceMap.end(); ++aIt, ++nIndex )
741 if( aIt->first < 0 )
742 continue;
743 // fill empty columns
744 for( ; nIndex < aIt->first; ++nIndex )
745 rInOutSequences.push_back(
746 SchXMLExportHelper_Impl::tDataSequenceCont::value_type(
747 uno::Reference< chart2::data::XDataSequence >(),
748 uno::Reference< chart2::data::XDataSequence >() ));
749 OSL_ASSERT( nIndex == aIt->first );
750 rInOutSequences.push_back( aIt->second );
754 lcl_TableData lcl_getDataForLocalTable(
755 const SchXMLExportHelper_Impl::tDataSequenceCont & aSequencesToExport,
756 const Reference< chart2::XAnyDescriptionAccess >& xAnyDescriptionAccess,
757 const OUString& rCategoriesRange,
758 bool bSeriesFromColumns,
759 const Reference< chart2::data::XRangeXMLConversion > & xRangeConversion )
761 lcl_TableData aResult;
765 Sequence< OUString > aSimpleCategories;
766 if( xAnyDescriptionAccess.is() )
768 //categories
769 if( bSeriesFromColumns )
771 aSimpleCategories = xAnyDescriptionAccess->getRowDescriptions();
772 aResult.aComplexRowDescriptions = xAnyDescriptionAccess->getAnyRowDescriptions();
774 else
776 aSimpleCategories = xAnyDescriptionAccess->getColumnDescriptions();
777 aResult.aComplexColumnDescriptions = xAnyDescriptionAccess->getAnyColumnDescriptions();
781 //series values and series labels
782 SchXMLExportHelper_Impl::tDataSequenceCont::size_type nNumSequences = aSequencesToExport.size();
783 SchXMLExportHelper_Impl::tDataSequenceCont::const_iterator aBegin( aSequencesToExport.begin());
784 SchXMLExportHelper_Impl::tDataSequenceCont::const_iterator aEnd( aSequencesToExport.end());
785 SchXMLExportHelper_Impl::tDataSequenceCont::const_iterator aIt( aBegin );
787 auto nMaxSequenceLength( lcl_getMaxSequenceLength( aSequencesToExport ));
788 if( aSimpleCategories.getLength() > nMaxSequenceLength )
790 aSimpleCategories.realloc(nMaxSequenceLength);//#i110617#
792 size_t nNumColumns( bSeriesFromColumns ? nNumSequences : nMaxSequenceLength );
793 size_t nNumRows( bSeriesFromColumns ? nMaxSequenceLength : nNumSequences );
795 // resize data
796 aResult.aDataInRows.resize( nNumRows );
797 double fNan = 0.0;
798 ::rtl::math::setNan( &fNan );
800 for (auto& aData: aResult.aDataInRows)
801 aData.resize(nNumColumns, fNan);
802 aResult.aColumnDescriptions.resize( nNumColumns );
803 aResult.aComplexColumnDescriptions.realloc( nNumColumns );
804 aResult.aRowDescriptions.resize( nNumRows );
805 aResult.aComplexRowDescriptions.realloc( nNumRows );
807 tStringVector& rCategories = bSeriesFromColumns ? aResult.aRowDescriptions : aResult.aColumnDescriptions;
808 tStringVector& rLabels = bSeriesFromColumns ? aResult.aColumnDescriptions : aResult.aRowDescriptions;
810 //categories
811 lcl_SequenceToVector( aSimpleCategories, rCategories );
812 if( !rCategoriesRange.isEmpty() )
814 OUString aRange(rCategoriesRange);
815 if( xRangeConversion.is())
816 aRange = xRangeConversion->convertRangeToXML( aRange );
817 if( bSeriesFromColumns )
818 aResult.aRowDescriptions_Ranges.push_back( aRange );
819 else
820 aResult.aColumnDescriptions_Ranges.push_back( aRange );
823 // iterate over all sequences
824 size_t nSeqIdx = 0;
825 Sequence< Sequence< OUString > > aComplexLabels(nNumSequences);
826 for( ; aIt != aEnd; ++aIt, ++nSeqIdx )
828 OUString aRange;
829 Sequence< OUString >& rCurrentComplexLabel = aComplexLabels[nSeqIdx];
830 if( aIt->first.is())
832 lcl_getLabelStringSequence( rCurrentComplexLabel, aIt->first );
833 rLabels[nSeqIdx] = lcl_flattenStringSequence( rCurrentComplexLabel );
834 aRange = aIt->first->getSourceRangeRepresentation();
835 if( xRangeConversion.is())
836 aRange = xRangeConversion->convertRangeToXML( aRange );
838 else if( aIt->second.is())
840 rCurrentComplexLabel.realloc(1);
841 rLabels[nSeqIdx] = rCurrentComplexLabel[0] = lcl_flattenStringSequence(
842 aIt->second->generateLabel( chart2::data::LabelOrigin_SHORT_SIDE ));
844 if( bSeriesFromColumns )
845 aResult.aColumnDescriptions_Ranges.push_back( aRange );
846 else
847 aResult.aRowDescriptions_Ranges.push_back( aRange );
849 ::std::vector< double > aNumbers( lcl_getAllValuesFromSequence( aIt->second ));
850 if( bSeriesFromColumns )
852 const sal_Int32 nSize( static_cast< sal_Int32 >( aNumbers.size()));
853 for( sal_Int32 nIdx=0; nIdx<nSize; ++nIdx )
854 aResult.aDataInRows[nIdx][nSeqIdx] = aNumbers[nIdx];
856 else
857 aResult.aDataInRows[nSeqIdx] = aNumbers;
859 if( aIt->second.is())
861 aRange = aIt->second->getSourceRangeRepresentation();
862 if( xRangeConversion.is())
863 aRange = xRangeConversion->convertRangeToXML( aRange );
865 aResult.aDataRangeRepresentations.push_back( aRange );
867 //is column hidden?
868 if( !lcl_SequenceHasUnhiddenData(aIt->first) && !lcl_SequenceHasUnhiddenData(aIt->second) )
869 aResult.aHiddenColumns.push_back(nSeqIdx);
871 Sequence< Sequence< Any > >& rComplexAnyLabels = bSeriesFromColumns ? aResult.aComplexColumnDescriptions : aResult.aComplexRowDescriptions;//#i116544#
872 rComplexAnyLabels.realloc(aComplexLabels.getLength());
873 for( sal_Int32 nN=0; nN<aComplexLabels.getLength();nN++ )
875 Sequence< OUString >& rSource = aComplexLabels[nN];
876 Sequence< Any >& rTarget = rComplexAnyLabels[nN];
877 rTarget.realloc( rSource.getLength() );
878 for( sal_Int32 i=0; i<rSource.getLength(); i++ )
879 rTarget[i] = uno::makeAny( rSource[i] );
882 catch( const uno::Exception & rEx )
884 SAL_INFO("xmloff.chart", "something went wrong during table data collection: " << rEx.Message);
887 return aResult;
890 void lcl_exportNumberFormat( const OUString& rPropertyName, const Reference< beans::XPropertySet >& xPropSet,
891 SvXMLExport& rExport )
893 if( xPropSet.is())
895 sal_Int32 nNumberFormat = 0;
896 Any aNumAny = xPropSet->getPropertyValue( rPropertyName );
897 if( (aNumAny >>= nNumberFormat) && (nNumberFormat != -1) )
898 rExport.addDataStyle( nNumberFormat );
902 ::std::vector< Reference< chart2::data::XDataSequence > >
903 lcl_getErrorBarSequences( const Reference< beans::XPropertySet > & xErrorBarProp )
905 ::std::vector< Reference< chart2::data::XDataSequence > > aResult;
906 Reference< chart2::data::XDataSource > xErrorBarDataSource( xErrorBarProp, uno::UNO_QUERY );
907 if( !xErrorBarDataSource.is())
908 return aResult;
910 Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences(
911 xErrorBarDataSource->getDataSequences());
912 for( sal_Int32 nI=0; nI< aSequences.getLength(); ++nI )
916 if( aSequences[nI].is())
918 Reference< chart2::data::XDataSequence > xSequence( aSequences[nI]->getValues());
919 Reference< beans::XPropertySet > xSeqProp( xSequence, uno::UNO_QUERY_THROW );
920 OUString aRole;
921 if( ( xSeqProp->getPropertyValue( "Role" ) >>= aRole ) &&
922 aRole.match( "error-bars-" ))
924 aResult.push_back( xSequence );
928 catch( const uno::Exception & rEx )
930 OString aBStr(OUStringToOString(rEx.Message, RTL_TEXTENCODING_ASCII_US));
931 SAL_INFO("xmloff.chart", "chart:exporting error bar ranges: " << aBStr );
935 return aResult;
938 bool lcl_exportDomainForThisSequence( const Reference< chart2::data::XDataSequence >& rValues, OUString& rFirstRangeForThisDomainIndex, SvXMLExport& rExport )
940 bool bDomainExported = false;
941 if( rValues.is())
943 Reference< chart2::XChartDocument > xNewDoc( rExport.GetModel(), uno::UNO_QUERY );
944 OUString aRange( lcl_ConvertRange( rValues->getSourceRangeRepresentation(), xNewDoc ) );
946 //work around error in OOo 2.0 (problems with multiple series having a domain element)
947 if( rFirstRangeForThisDomainIndex.isEmpty() || !aRange.equals(rFirstRangeForThisDomainIndex) )
949 rExport.AddAttribute( XML_NAMESPACE_TABLE, XML_CELL_RANGE_ADDRESS, aRange);
950 SvXMLElementExport aDomain( rExport, XML_NAMESPACE_CHART, XML_DOMAIN, true, true );
951 bDomainExported = true;
954 if( rFirstRangeForThisDomainIndex.isEmpty() )
955 rFirstRangeForThisDomainIndex = aRange;
957 return bDomainExported;
960 } // anonymous namespace
962 struct SchXMLDataPointStruct
964 OUString maStyleName;
965 sal_Int32 mnRepeat;
967 SchXMLDataPointStruct() : mnRepeat( 1 ) {}
970 // class SchXMLExportHelper
972 SchXMLExportHelper::SchXMLExportHelper( SvXMLExport& rExport, SvXMLAutoStylePoolP& rASPool )
973 : m_pImpl( new SchXMLExportHelper_Impl( rExport, rASPool ) )
977 SchXMLExportHelper::~SchXMLExportHelper()
981 const OUString& SchXMLExportHelper::getChartCLSID()
983 return m_pImpl->msCLSID;
986 void SchXMLExportHelper::SetSourceShellID( const OUString& rShellID )
988 m_pImpl->maSrcShellID = rShellID;
991 void SchXMLExportHelper::SetDestinationShellID( const OUString& rShellID )
993 m_pImpl->maDestShellID = rShellID;
996 const rtl::Reference< XMLPropertySetMapper >& SchXMLExportHelper_Impl::GetPropertySetMapper() const
998 return mxPropertySetMapper;
1001 void SchXMLExportHelper_Impl::exportAutoStyles()
1003 if( mxExpPropMapper.is())
1005 //ToDo: when embedded in calc/writer this is not necessary because the
1006 // numberformatter is shared between both documents
1007 mrExport.exportAutoDataStyles();
1009 // export chart auto styles
1010 mrAutoStylePool.exportXML(
1011 XML_STYLE_FAMILY_SCH_CHART_ID
1012 , mrExport.GetDocHandler(),
1013 mrExport.GetMM100UnitConverter(),
1014 mrExport.GetNamespaceMap()
1017 // export auto styles for additional shapes
1018 mrExport.GetShapeExport()->exportAutoStyles();
1019 // and for text in additional shapes
1020 mrExport.GetTextParagraphExport()->exportTextAutoStyles();
1024 // private methods
1026 SchXMLExportHelper_Impl::SchXMLExportHelper_Impl(
1027 SvXMLExport& rExport,
1028 SvXMLAutoStylePoolP& rASPool ) :
1029 mrExport( rExport ),
1030 mrAutoStylePool( rASPool ),
1031 mbHasSeriesLabels( false ),
1032 mbHasCategoryLabels( false ),
1033 mbRowSourceColumns( true ),
1034 msCLSID( OUString( SvGlobalName( SO3_SCH_CLASSID ).GetHexName()))
1036 msTableName = "local-table";
1038 // create property set mapper
1039 mxPropertySetMapper = new XMLChartPropertySetMapper( true);
1040 mxExpPropMapper = new XMLChartExportPropertyMapper( mxPropertySetMapper, rExport );
1042 // register chart auto-style family
1043 mrAutoStylePool.AddFamily(
1044 XML_STYLE_FAMILY_SCH_CHART_ID,
1045 OUString( XML_STYLE_FAMILY_SCH_CHART_NAME ),
1046 mxExpPropMapper.get(),
1047 OUString( XML_STYLE_FAMILY_SCH_CHART_PREFIX ));
1049 // register shape family
1050 mrAutoStylePool.AddFamily(
1051 XML_STYLE_FAMILY_SD_GRAPHICS_ID,
1052 OUString( XML_STYLE_FAMILY_SD_GRAPHICS_NAME ),
1053 mxExpPropMapper.get(),
1054 OUString( XML_STYLE_FAMILY_SD_GRAPHICS_PREFIX ));
1055 // register paragraph family also for shapes
1056 mrAutoStylePool.AddFamily(
1057 XML_STYLE_FAMILY_TEXT_PARAGRAPH,
1058 GetXMLToken( XML_PARAGRAPH ),
1059 mxExpPropMapper.get(),
1060 OUString( 'P' ));
1061 // register text family also for shapes
1062 mrAutoStylePool.AddFamily(
1063 XML_STYLE_FAMILY_TEXT_TEXT,
1064 GetXMLToken( XML_TEXT ),
1065 mxExpPropMapper.get(),
1066 OUString( 'T' ));
1069 SchXMLExportHelper_Impl::~SchXMLExportHelper_Impl()
1073 void SchXMLExportHelper_Impl::collectAutoStyles( Reference< chart::XChartDocument > rChartDoc )
1075 parseDocument( rChartDoc, false );
1078 void SchXMLExportHelper_Impl::exportChart( Reference< chart::XChartDocument > rChartDoc,
1079 bool bIncludeTable )
1081 parseDocument( rChartDoc, true, bIncludeTable );
1082 SAL_WARN_IF( !maAutoStyleNameQueue.empty(), "xmloff.chart", "There are still remaining autostyle names in the queue" );
1085 static OUString lcl_GetStringFromNumberSequence( const css::uno::Sequence< sal_Int32 >& rSequenceMapping, bool bRemoveOneFromEachIndex /*should be true if having categories*/ )
1087 const sal_Int32* pArray = rSequenceMapping.getConstArray();
1088 const sal_Int32 nSize = rSequenceMapping.getLength();
1089 sal_Int32 i = 0;
1090 OUStringBuffer aBuf;
1091 bool bHasPredecessor = false;
1092 for( i = 0; i < nSize; ++i )
1094 sal_Int32 nIndex = pArray[ i ];
1095 if( bRemoveOneFromEachIndex )
1096 --nIndex;
1097 if(nIndex>=0)
1099 if(bHasPredecessor)
1100 aBuf.append( ' ' );
1101 aBuf.append( nIndex );
1102 bHasPredecessor = true;
1105 return aBuf.makeStringAndClear();
1108 /// if bExportContent is false the auto-styles are collected
1109 void SchXMLExportHelper_Impl::parseDocument( Reference< chart::XChartDocument >& rChartDoc,
1110 bool bExportContent,
1111 bool bIncludeTable )
1113 Reference< chart2::XChartDocument > xNewDoc( rChartDoc, uno::UNO_QUERY );
1114 if( !rChartDoc.is() || !xNewDoc.is() )
1116 SAL_WARN("xmloff.chart", "No XChartDocument was given for export." );
1117 return;
1120 mxExpPropMapper->setChartDoc(xNewDoc);
1122 awt::Size aPageSize( getPageSize( xNewDoc ));
1123 if( bExportContent )
1124 addSize( aPageSize );
1125 Reference< chart::XDiagram > xDiagram = rChartDoc->getDiagram();
1126 Reference< chart2::XDiagram > xNewDiagram;
1127 if( xNewDoc.is())
1128 xNewDiagram.set( xNewDoc->getFirstDiagram());
1130 //todo remove if model changes are notified and view is updated automatically
1131 if( bExportContent )
1133 Reference< util::XRefreshable > xRefreshable( xNewDoc, uno::UNO_QUERY );
1134 if( xRefreshable.is() )
1135 xRefreshable->refresh();
1138 // get Properties of ChartDocument
1139 bool bHasMainTitle = false;
1140 bool bHasSubTitle = false;
1141 bool bHasLegend = false;
1142 util::DateTime aNullDate(0,0,0,0,30,12,1899, false);
1144 std::vector< XMLPropertyState > aPropertyStates;
1146 Reference< beans::XPropertySet > xDocPropSet( rChartDoc, uno::UNO_QUERY );
1147 if( xDocPropSet.is())
1151 Any aAny = xDocPropSet->getPropertyValue("HasMainTitle");
1152 aAny >>= bHasMainTitle;
1153 aAny = xDocPropSet->getPropertyValue("HasSubTitle");
1154 aAny >>= bHasSubTitle;
1155 aAny = xDocPropSet->getPropertyValue("HasLegend");
1156 aAny >>= bHasLegend;
1157 if ( bIncludeTable )
1159 aAny = xDocPropSet->getPropertyValue("NullDate");
1160 if ( !aAny.hasValue() )
1162 Reference<container::XChild> xChild(rChartDoc, uno::UNO_QUERY );
1163 if ( xChild.is() )
1165 Reference< beans::XPropertySet > xParentDoc( xChild->getParent(),uno::UNO_QUERY);
1166 if ( xParentDoc.is() && xParentDoc->getPropertySetInfo()->hasPropertyByName("NullDate") )
1167 aAny = xParentDoc->getPropertyValue("NullDate");
1171 aAny >>= aNullDate;
1174 catch( const beans::UnknownPropertyException & )
1176 SAL_WARN("xmloff.chart", "Required property not found in ChartDocument" );
1180 if ( bIncludeTable && (aNullDate.Day != 30 || aNullDate.Month != 12 || aNullDate.Year != 1899 ) )
1182 SvXMLElementExport aSet( mrExport, XML_NAMESPACE_TABLE, XML_CALCULATION_SETTINGS, true, true );
1184 OUStringBuffer sBuffer;
1185 ::sax::Converter::convertDateTime(sBuffer, aNullDate, nullptr);
1186 mrExport.AddAttribute( XML_NAMESPACE_TABLE,XML_DATE_VALUE,sBuffer.makeStringAndClear());
1187 SvXMLElementExport aNull( mrExport, XML_NAMESPACE_TABLE, XML_NULL_DATE, true, true );
1191 // chart element
1192 std::unique_ptr<SvXMLElementExport> xElChart;
1194 // get property states for autostyles
1195 if( mxExpPropMapper.is())
1197 Reference< beans::XPropertySet > xPropSet( rChartDoc->getArea(), uno::UNO_QUERY );
1198 if( xPropSet.is())
1199 aPropertyStates = mxExpPropMapper->Filter( xPropSet );
1202 if( bExportContent )
1204 //export data provider in xlink:href attribute
1205 const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
1206 if( nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 )
1208 OUString aDataProviderURL( ".." );
1209 if( xNewDoc->hasInternalDataProvider() )
1210 aDataProviderURL = ".";
1211 else //special handling for data base data provider necessary
1213 Reference< chart2::data::XDatabaseDataProvider > xDBDataProvider( xNewDoc->getDataProvider(), uno::UNO_QUERY );
1214 if( xDBDataProvider.is() )
1215 aDataProviderURL = ".";
1217 mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, aDataProviderURL );
1218 mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
1221 OUString sChartType( xDiagram->getDiagramType() );
1223 // attributes
1224 // determine class
1225 if( !sChartType.isEmpty())
1227 enum XMLTokenEnum eXMLChartType = SchXMLTools::getTokenByChartType( sChartType, true /* bUseOldNames */ );
1229 SAL_WARN_IF( eXMLChartType == XML_TOKEN_INVALID, "xmloff.chart", "invalid chart class" );
1230 if( eXMLChartType == XML_TOKEN_INVALID )
1231 eXMLChartType = XML_BAR;
1233 if( eXMLChartType == XML_ADD_IN )
1235 // sChartType is the servie-name of the add-in
1236 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_CLASS,
1237 mrExport.GetNamespaceMap().GetQNameByKey(
1238 XML_NAMESPACE_OOO, sChartType) );
1240 else if( eXMLChartType != XML_TOKEN_INVALID )
1242 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_CLASS,
1243 mrExport.GetNamespaceMap().GetQNameByKey(
1244 XML_NAMESPACE_CHART, GetXMLToken(eXMLChartType )) );
1247 //column-mapping or row-mapping
1248 if( maSequenceMapping.getLength() )
1250 enum XMLTokenEnum eTransToken = ::xmloff::token::XML_ROW_MAPPING;
1251 if( mbRowSourceColumns )
1252 eTransToken = ::xmloff::token::XML_COLUMN_MAPPING;
1253 OUString aSequenceMappingStr( lcl_GetStringFromNumberSequence(
1254 maSequenceMapping, mbHasCategoryLabels && !xNewDoc->hasInternalDataProvider() ) );
1256 mrExport.AddAttribute( XML_NAMESPACE_CHART,
1257 ::xmloff::token::GetXMLToken( eTransToken ),
1258 aSequenceMappingStr );
1261 // write style name
1262 AddAutoStyleAttribute( aPropertyStates );
1264 //element
1265 xElChart.reset(new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_CHART, true, true ));
1267 else // autostyles
1269 CollectAutoStyle( aPropertyStates );
1271 // remove property states for autostyles
1272 aPropertyStates.clear();
1274 // title element
1275 if( bHasMainTitle )
1277 // get property states for autostyles
1278 if( mxExpPropMapper.is())
1280 Reference< beans::XPropertySet > xPropSet( rChartDoc->getTitle(), uno::UNO_QUERY );
1281 if( xPropSet.is())
1282 aPropertyStates = mxExpPropMapper->Filter( xPropSet );
1284 if( bExportContent )
1286 Reference< drawing::XShape > xShape = rChartDoc->getTitle();
1287 if( xShape.is()) // && "hasTitleBeenMoved"
1288 addPosition( xShape );
1290 // write style name
1291 AddAutoStyleAttribute( aPropertyStates );
1293 // element
1294 SvXMLElementExport aElTitle( mrExport, XML_NAMESPACE_CHART, XML_TITLE, true, true );
1296 // content (text:p)
1297 Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY );
1298 if( xPropSet.is())
1300 Any aAny( xPropSet->getPropertyValue( "String" ));
1301 OUString aText;
1302 aAny >>= aText;
1303 exportText( aText );
1306 else // autostyles
1308 CollectAutoStyle( aPropertyStates );
1310 // remove property states for autostyles
1311 aPropertyStates.clear();
1314 // subtitle element
1315 if( bHasSubTitle )
1317 // get property states for autostyles
1318 if( mxExpPropMapper.is())
1320 Reference< beans::XPropertySet > xPropSet( rChartDoc->getSubTitle(), uno::UNO_QUERY );
1321 if( xPropSet.is())
1322 aPropertyStates = mxExpPropMapper->Filter( xPropSet );
1325 if( bExportContent )
1327 Reference< drawing::XShape > xShape = rChartDoc->getSubTitle();
1328 if( xShape.is())
1329 addPosition( xShape );
1331 // write style name
1332 AddAutoStyleAttribute( aPropertyStates );
1334 // element (has no subelements)
1335 SvXMLElementExport aElSubTitle( mrExport, XML_NAMESPACE_CHART, XML_SUBTITLE, true, true );
1337 // content (text:p)
1338 Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY );
1339 if( xPropSet.is())
1341 Any aAny( xPropSet->getPropertyValue( "String" ));
1342 OUString aText;
1343 aAny >>= aText;
1344 exportText( aText );
1347 else // autostyles
1349 CollectAutoStyle( aPropertyStates );
1351 // remove property states for autostyles
1352 aPropertyStates.clear();
1355 // legend element
1356 if( bHasLegend )
1358 // get property states for autostyles
1359 if( mxExpPropMapper.is())
1361 Reference< beans::XPropertySet > xPropSet( rChartDoc->getLegend(), uno::UNO_QUERY );
1362 if( xPropSet.is())
1363 aPropertyStates = mxExpPropMapper->Filter( xPropSet );
1366 if( bExportContent )
1368 Reference< beans::XPropertySet > xProp( rChartDoc->getLegend(), uno::UNO_QUERY );
1369 if( xProp.is())
1371 // export legend anchor position
1374 Any aAny( xProp->getPropertyValue("Alignment"));
1375 if( SchXMLEnumConverter::getLegendPositionConverter().exportXML( msString, aAny, mrExport.GetMM100UnitConverter() ) )
1376 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LEGEND_POSITION, msString );
1378 catch( const beans::UnknownPropertyException & )
1380 SAL_WARN("xmloff.chart", "Property Align not found in ChartLegend" );
1383 // export absolute legend position
1384 Reference< drawing::XShape > xLegendShape( xProp, uno::UNO_QUERY );
1385 addPosition( xLegendShape );
1387 // export legend size
1388 const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
1389 if( xLegendShape.is() && nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 )
1393 chart::ChartLegendExpansion nLegendExpansion = chart::ChartLegendExpansion_HIGH;
1394 OUString aExpansionString;
1395 Any aAny( xProp->getPropertyValue("Expansion"));
1396 bool bHasExpansion = (aAny >>= nLegendExpansion);
1397 if( bHasExpansion && SchXMLEnumConverter::getLegendExpansionConverter().exportXML( aExpansionString, aAny, mrExport.GetMM100UnitConverter() ) )
1399 mrExport.AddAttribute( XML_NAMESPACE_STYLE, XML_LEGEND_EXPANSION, aExpansionString );
1400 if( nLegendExpansion == chart::ChartLegendExpansion_CUSTOM)
1402 awt::Size aSize( xLegendShape->getSize() );
1403 addSize( aSize, true );
1404 OUStringBuffer aAspectRatioString;
1405 ::sax::Converter::convertDouble(
1406 aAspectRatioString,
1407 (aSize.Height == 0
1408 ? 1.0
1409 : double(aSize.Width)/double(aSize.Height)));
1410 mrExport.AddAttribute( XML_NAMESPACE_STYLE, XML_LEGEND_EXPANSION_ASPECT_RATIO, aAspectRatioString.makeStringAndClear() );
1414 catch( const beans::UnknownPropertyException & )
1416 SAL_WARN("xmloff.chart", "Property Expansion not found in ChartLegend" );
1421 // write style name
1422 AddAutoStyleAttribute( aPropertyStates );
1424 // element
1425 SvXMLElementExport aLegend( mrExport, XML_NAMESPACE_CHART, XML_LEGEND, true, true );
1427 else // autostyles
1429 CollectAutoStyle( aPropertyStates );
1431 // remove property states for autostyles
1432 aPropertyStates.clear();
1435 // plot-area element
1436 if( xDiagram.is())
1437 exportPlotArea( xDiagram, xNewDiagram, aPageSize, bExportContent, bIncludeTable );
1439 // export additional shapes
1440 if( xDocPropSet.is() )
1442 if( bExportContent )
1444 if( mxAdditionalShapes.is())
1446 // can't call exportShapes with all shapes because the
1447 // initialisation happened with the complete draw page and not
1448 // the XShapes object used here. Thus the shapes have to be
1449 // exported one by one
1450 rtl::Reference< XMLShapeExport > rShapeExport = mrExport.GetShapeExport();
1451 Reference< drawing::XShape > xShape;
1452 const sal_Int32 nShapeCount( mxAdditionalShapes->getCount());
1453 for( sal_Int32 nShapeId = 0; nShapeId < nShapeCount; nShapeId++ )
1455 mxAdditionalShapes->getByIndex( nShapeId ) >>= xShape;
1456 SAL_WARN_IF( !xShape.is(), "xmloff.chart", "Shape without an XShape?" );
1457 if( ! xShape.is())
1458 continue;
1460 rShapeExport->exportShape( xShape );
1462 // this would be the easier way if it worked:
1463 //mrExport.GetShapeExport()->exportShapes( mxAdditionalShapes );
1466 else
1468 // get a sequence of non-chart shapes (inserted via clipboard)
1471 Any aShapesAny = xDocPropSet->getPropertyValue("AdditionalShapes");
1472 aShapesAny >>= mxAdditionalShapes;
1474 catch( const uno::Exception & rEx )
1476 SAL_INFO("xmloff.chart", "AdditionalShapes not found: " << rEx.Message );
1479 if( mxAdditionalShapes.is())
1481 // seek shapes has to be called for the whole page because in
1482 // the shape export the vector of shapes is accessed via the
1483 // ZOrder which might be (actually is) larger than the number of
1484 // shapes in mxAdditionalShapes
1485 Reference< drawing::XDrawPageSupplier > xSupplier( rChartDoc, uno::UNO_QUERY );
1486 SAL_WARN_IF( !xSupplier.is(), "xmloff.chart", "Cannot retrieve draw page to initialize shape export" );
1487 if( xSupplier.is() )
1489 Reference< drawing::XShapes > xDrawPage( xSupplier->getDrawPage(), uno::UNO_QUERY );
1490 SAL_WARN_IF( !xDrawPage.is(), "xmloff.chart", "Invalid draw page for initializing shape export" );
1491 if( xDrawPage.is())
1492 mrExport.GetShapeExport()->seekShapes( xDrawPage );
1495 // can't call collectShapesAutoStyles with all shapes because
1496 // the initialisation happened with the complete draw page and
1497 // not the XShapes object used here. Thus the shapes have to be
1498 // exported one by one
1499 rtl::Reference< XMLShapeExport > rShapeExport = mrExport.GetShapeExport();
1500 Reference< drawing::XShape > xShape;
1501 const sal_Int32 nShapeCount( mxAdditionalShapes->getCount());
1502 for( sal_Int32 nShapeId = 0; nShapeId < nShapeCount; nShapeId++ )
1504 mxAdditionalShapes->getByIndex( nShapeId ) >>= xShape;
1505 SAL_WARN_IF( !xShape.is(), "xmloff.chart", "Shape without an XShape?" );
1506 if( ! xShape.is())
1507 continue;
1509 rShapeExport->collectShapeAutoStyles( xShape );
1515 // table element
1516 // (is included as subelement of chart)
1517 if( bExportContent )
1519 // #85929# always export table, otherwise clipboard may lose data
1520 exportTable();
1524 static void lcl_exportComplexLabel( const Sequence< uno::Any >& rComplexLabel, SvXMLExport& rExport )
1526 sal_Int32 nLength = rComplexLabel.getLength();
1527 if( nLength<=1 )
1528 return;
1529 SvXMLElementExport aTextList( rExport, XML_NAMESPACE_TEXT, XML_LIST, true, true );
1530 for(sal_Int32 nN=0; nN<nLength; nN++)
1532 SvXMLElementExport aListItem( rExport, XML_NAMESPACE_TEXT, XML_LIST_ITEM, true, true );
1533 OUString aString;
1534 if( !(rComplexLabel[nN]>>=aString) )
1536 //todo?
1538 SchXMLTools::exportText( rExport, aString, false /*bConvertTabsLFs*/ );
1542 void SchXMLExportHelper_Impl::exportTable()
1544 // table element
1545 mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_NAME, msTableName );
1549 bool bProtected = false;
1550 Reference< beans::XPropertySet > xProps( mrExport.GetModel(), uno::UNO_QUERY_THROW );
1551 if ( ( xProps->getPropertyValue("DisableDataTableDialog") >>= bProtected ) &&
1552 bProtected )
1554 mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_PROTECTED, XML_TRUE );
1557 catch ( const uno::Exception& )
1561 SvXMLElementExport aTable( mrExport, XML_NAMESPACE_TABLE, XML_TABLE, true, true );
1563 bool bHasOwnData = false;
1564 Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
1565 Reference< chart2::data::XRangeXMLConversion > xRangeConversion;
1566 if( xNewDoc.is())
1568 bHasOwnData = xNewDoc->hasInternalDataProvider();
1569 xRangeConversion.set( xNewDoc->getDataProvider(), uno::UNO_QUERY );
1572 Reference< chart2::XAnyDescriptionAccess > xAnyDescriptionAccess;
1574 Reference< chart::XChartDocument > xChartDoc( mrExport.GetModel(), uno::UNO_QUERY );
1575 if( xChartDoc.is() )
1576 xAnyDescriptionAccess.set( xChartDoc->getData(), uno::UNO_QUERY );
1579 if( bHasOwnData )
1580 lcl_ReorderInternalSequencesAccordingToTheirRangeName( m_aDataSequencesToExport );
1581 lcl_TableData aData( lcl_getDataForLocalTable( m_aDataSequencesToExport
1582 , xAnyDescriptionAccess, maCategoriesRange
1583 , mbRowSourceColumns, xRangeConversion ));
1585 tStringVector::const_iterator aDataRangeIter( aData.aDataRangeRepresentations.begin());
1586 const tStringVector::const_iterator aDataRangeEndIter( aData.aDataRangeRepresentations.end());
1588 tStringVector::const_iterator aRowDescriptions_RangeIter( aData.aRowDescriptions_Ranges.begin());
1589 const tStringVector::const_iterator aRowDescriptions_RangeEnd( aData.aRowDescriptions_Ranges.end());
1591 // declare columns
1593 SvXMLElementExport aHeaderColumns( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_HEADER_COLUMNS, true, true );
1594 SvXMLElementExport aHeaderColumn( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, true, true );
1597 SvXMLElementExport aColumns( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMNS, true, true );
1599 sal_Int32 nNextIndex = 0;
1600 for(sal_Int32 nHiddenIndex : aData.aHiddenColumns)
1602 //i91578 display of hidden values (copy paste scenario; export hidden flag thus it can be used during migration to locale table upon paste )
1603 if( nHiddenIndex > nNextIndex )
1605 sal_Int64 nRepeat = static_cast< sal_Int64 >( nHiddenIndex - nNextIndex );
1606 if(nRepeat>1)
1607 mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED,
1608 OUString::number( nRepeat ));
1609 SvXMLElementExport aColumn( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, true, true );
1611 mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_VISIBILITY, GetXMLToken( XML_COLLAPSE ) );
1612 SvXMLElementExport aColumn( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, true, true );
1613 nNextIndex = nHiddenIndex+1;
1616 sal_Int32 nEndIndex = aData.aColumnDescriptions.size()-1;
1617 if( nEndIndex >= nNextIndex )
1619 sal_Int64 nRepeat = static_cast< sal_Int64 >( nEndIndex - nNextIndex + 1 );
1620 if(nRepeat>1)
1621 mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED,
1622 OUString::number( nRepeat ));
1623 SvXMLElementExport aColumn( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, true, true );
1627 // export rows with content
1628 //export header row
1630 SvXMLElementExport aHeaderRows( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_HEADER_ROWS, true, true );
1631 SvXMLElementExport aRow( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_ROW, true, true );
1633 //first one empty cell for the row descriptions
1635 SvXMLElementExport aEmptyCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, true );
1636 SvXMLElementExport aEmptyParagraph( mrExport, XML_NAMESPACE_TEXT, XML_P, true, true );
1639 //export column descriptions
1640 tStringVector::const_iterator aColumnDescriptions_RangeIter( aData.aColumnDescriptions_Ranges.begin());
1641 const tStringVector::const_iterator aColumnDescriptions_RangeEnd( aData.aColumnDescriptions_Ranges.end());
1642 const Sequence< Sequence< uno::Any > >& rComplexColumnDescriptions = aData.aComplexColumnDescriptions;
1643 sal_Int32 nComplexCount = rComplexColumnDescriptions.getLength();
1644 sal_Int32 nC = 0;
1645 for( tStringVector::const_iterator aIt( aData.aColumnDescriptions.begin())
1646 ; (aIt != aData.aColumnDescriptions.end())
1647 ; ++aIt, nC++ )
1649 bool bExportString = true;
1650 if( nC < nComplexCount )
1652 const Sequence< uno::Any >& rComplexLabel = rComplexColumnDescriptions[nC];
1653 if( rComplexLabel.getLength()>0 )
1655 double fValue=0.0;
1656 if( rComplexLabel[0] >>=fValue )
1658 bExportString = false;
1660 ::sax::Converter::convertDouble(
1661 msStringBuffer, fValue);
1662 msString = msStringBuffer.makeStringAndClear();
1663 mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT );
1664 mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE, msString );
1668 if( bExportString )
1670 mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_STRING );
1673 SvXMLElementExport aCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, true );
1674 exportText( *aIt );
1675 if( nC < nComplexCount )
1676 lcl_exportComplexLabel( rComplexColumnDescriptions[nC], mrExport );
1677 if( !bHasOwnData && aColumnDescriptions_RangeIter != aColumnDescriptions_RangeEnd )
1679 // remind the original range to allow a correct re-association when copying via clipboard
1680 if (!(*aColumnDescriptions_RangeIter).isEmpty())
1681 SchXMLTools::exportRangeToSomewhere( mrExport, *aColumnDescriptions_RangeIter );
1682 ++aColumnDescriptions_RangeIter;
1685 SAL_WARN_IF( !bHasOwnData && (aColumnDescriptions_RangeIter != aColumnDescriptions_RangeEnd), "xmloff.chart", "bHasOwnData == false && aColumnDescriptions_RangeIter != aColumnDescriptions_RangeEnd" );
1686 } // closing row and header-rows elements
1688 // export value rows
1690 SvXMLElementExport aRows( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_ROWS, true, true );
1691 tStringVector::const_iterator aRowDescriptionsIter( aData.aRowDescriptions.begin());
1692 const Sequence< Sequence< uno::Any > >& rComplexRowDescriptions = aData.aComplexRowDescriptions;
1693 sal_Int32 nComplexCount = rComplexRowDescriptions.getLength();
1694 sal_Int32 nC = 0;
1696 for( t2DNumberContainer::const_iterator aRowIt( aData.aDataInRows.begin())
1697 ; aRowIt != aData.aDataInRows.end()
1698 ; ++aRowIt, ++nC )
1700 SvXMLElementExport aRow( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_ROW, true, true );
1702 //export row descriptions
1704 bool bExportString = true;
1705 if( nC < nComplexCount )
1707 const Sequence< uno::Any >& rComplexLabel = rComplexRowDescriptions[nC];
1708 if( rComplexLabel.getLength()>0 )
1710 double fValue=0.0;
1711 if( rComplexLabel[0] >>=fValue )
1713 bExportString = false;
1715 ::sax::Converter::convertDouble(msStringBuffer, fValue);
1716 msString = msStringBuffer.makeStringAndClear();
1717 mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT );
1718 mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE, msString );
1722 if( bExportString )
1724 mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_STRING );
1727 SvXMLElementExport aCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, true );
1728 if( aRowDescriptionsIter != aData.aRowDescriptions.end())
1730 exportText( *aRowDescriptionsIter );
1731 if( nC < nComplexCount )
1732 lcl_exportComplexLabel( rComplexRowDescriptions[nC], mrExport );
1733 if( !bHasOwnData && aRowDescriptions_RangeIter != aRowDescriptions_RangeEnd )
1735 // remind the original range to allow a correct re-association when copying via clipboard
1736 SchXMLTools::exportRangeToSomewhere( mrExport, *aRowDescriptions_RangeIter );
1737 ++aRowDescriptions_RangeIter;
1739 ++aRowDescriptionsIter;
1743 //export row values
1744 for( t2DNumberContainer::value_type::const_iterator aColIt( aRowIt->begin());
1745 aColIt != aRowIt->end(); ++aColIt )
1747 ::sax::Converter::convertDouble( msStringBuffer, *aColIt );
1748 msString = msStringBuffer.makeStringAndClear();
1749 mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT );
1750 mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE, msString );
1751 SvXMLElementExport aCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, true );
1752 exportText( msString ); // do not convert tabs and lfs
1753 if( ( !bHasOwnData && aDataRangeIter != aDataRangeEndIter ) &&
1754 ( mbRowSourceColumns || (aColIt == aRowIt->begin()) ) )
1756 // remind the original range to allow a correct re-association when copying via clipboard
1757 if (!(*aDataRangeIter).isEmpty())
1758 SchXMLTools::exportRangeToSomewhere( mrExport, *aDataRangeIter );
1759 ++aDataRangeIter;
1765 // if range iterator was used it should have reached its end
1766 SAL_WARN_IF( !bHasOwnData && (aDataRangeIter != aDataRangeEndIter), "xmloff.chart", "bHasOwnData == false && aDataRangeIter != aDataRangeEndIter" );
1767 SAL_WARN_IF( !bHasOwnData && (aRowDescriptions_RangeIter != aRowDescriptions_RangeEnd), "xmloff.chart", "bHasOwnData == false && aRowDescriptions_RangeIter != aRowDescriptions_RangeEnd" );
1770 namespace
1773 Reference< chart2::XCoordinateSystem > lcl_getCooSys( const Reference< chart2::XDiagram > & xNewDiagram )
1775 Reference< chart2::XCoordinateSystem > xCooSys;
1776 Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xNewDiagram, uno::UNO_QUERY );
1777 if(xCooSysCnt.is())
1779 Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems() );
1780 if(aCooSysSeq.getLength()>0)
1781 xCooSys = aCooSysSeq[0];
1783 return xCooSys;
1786 Reference< chart2::XAxis > lcl_getAxis( const Reference< chart2::XCoordinateSystem >& xCooSys,
1787 enum XMLTokenEnum eDimension, bool bPrimary=true )
1789 Reference< chart2::XAxis > xNewAxis;
1792 if( xCooSys.is() )
1794 sal_Int32 nDimensionIndex=0;
1795 switch( eDimension )
1797 case XML_X:
1798 nDimensionIndex=0;
1799 break;
1800 case XML_Y:
1801 nDimensionIndex=1;
1802 break;
1803 case XML_Z:
1804 nDimensionIndex=2;
1805 break;
1806 default:
1807 break;
1810 xNewAxis = xCooSys->getAxisByDimension( nDimensionIndex, bPrimary ? 0 : 1 );
1813 catch( const uno::Exception & )
1816 return xNewAxis;
1821 void SchXMLExportHelper_Impl::exportPlotArea(
1822 const Reference< chart::XDiagram >& xDiagram,
1823 const Reference< chart2::XDiagram >& xNewDiagram,
1824 const awt::Size & rPageSize,
1825 bool bExportContent,
1826 bool bIncludeTable )
1828 SAL_WARN_IF( !xDiagram.is(), "xmloff.chart", "Invalid XDiagram as parameter" );
1829 if( ! xDiagram.is())
1830 return;
1832 // variables for autostyles
1833 Reference< beans::XPropertySet > xPropSet;
1834 std::vector< XMLPropertyState > aPropertyStates;
1836 msStringBuffer.setLength( 0 );
1838 // plot-area element
1840 std::unique_ptr<SvXMLElementExport> xElPlotArea;
1841 // get property states for autostyles
1842 xPropSet.set( xDiagram, uno::UNO_QUERY );
1843 if( xPropSet.is())
1845 if( mxExpPropMapper.is())
1846 aPropertyStates = mxExpPropMapper->Filter( xPropSet );
1848 if( bExportContent )
1850 rtl::Reference< XMLShapeExport > rShapeExport;
1852 // write style name
1853 AddAutoStyleAttribute( aPropertyStates );
1855 if( !msChartAddress.isEmpty() )
1857 if( !bIncludeTable )
1858 mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_CELL_RANGE_ADDRESS, msChartAddress );
1860 Reference< chart::XChartDocument > xDoc( mrExport.GetModel(), uno::UNO_QUERY );
1861 if( xDoc.is() )
1863 Reference< beans::XPropertySet > xDocProp( xDoc, uno::UNO_QUERY );
1864 if( xDocProp.is())
1866 Any aAny;
1870 bool bFirstCol = false, bFirstRow = false;
1872 aAny = xDocProp->getPropertyValue( "DataSourceLabelsInFirstColumn" );
1873 aAny >>= bFirstCol;
1874 aAny = xDocProp->getPropertyValue( "DataSourceLabelsInFirstRow" );
1875 aAny >>= bFirstRow;
1877 if( bFirstCol || bFirstRow )
1879 mrExport.AddAttribute( XML_NAMESPACE_CHART,
1880 ::xmloff::token::GetXMLToken( ::xmloff::token::XML_DATA_SOURCE_HAS_LABELS ),
1881 ( bFirstCol
1882 ? ( bFirstRow
1883 ? ::xmloff::token::GetXMLToken( ::xmloff::token::XML_BOTH )
1884 : ::xmloff::token::GetXMLToken( ::xmloff::token::XML_COLUMN ))
1885 : ::xmloff::token::GetXMLToken( ::xmloff::token::XML_ROW )));
1888 catch( const beans::UnknownPropertyException & )
1890 SAL_WARN("xmloff.chart", "Properties missing" );
1896 // attributes
1897 Reference< drawing::XShape > xShape ( xDiagram, uno::UNO_QUERY );
1898 if( xShape.is())
1900 addPosition( xShape );
1901 addSize( xShape );
1904 bool bIs3DChart = false;
1906 if( xPropSet.is())
1908 Any aAny;
1910 // 3d attributes
1913 aAny = xPropSet->getPropertyValue("Dim3D");
1914 aAny >>= bIs3DChart;
1916 if( bIs3DChart )
1918 rShapeExport = mrExport.GetShapeExport();
1919 if( rShapeExport.is())
1920 rShapeExport->export3DSceneAttributes( xPropSet );
1923 catch( const uno::Exception & rEx )
1925 OString aBStr(OUStringToOString(rEx.Message, RTL_TEXTENCODING_ASCII_US));
1926 SAL_INFO("xmloff.chart", "chart:exportPlotAreaException caught: " << aBStr);
1930 // plot-area element
1931 xElPlotArea.reset(new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_PLOT_AREA, true, true ));
1933 //inner position rectangle element
1934 exportCoordinateRegion( xDiagram );
1936 // light sources (inside plot area element)
1937 if( bIs3DChart &&
1938 rShapeExport.is())
1939 rShapeExport->export3DLamps( xPropSet );
1941 else // autostyles
1943 CollectAutoStyle( aPropertyStates );
1945 // remove property states for autostyles
1946 aPropertyStates.clear();
1948 // axis elements
1949 exportAxes( xDiagram, xNewDiagram, bExportContent );
1951 // series elements
1952 Reference< chart2::XAxis > xSecondYAxis = lcl_getAxis( lcl_getCooSys( xNewDiagram ), XML_Y, false );
1953 exportSeries( xNewDiagram, rPageSize, bExportContent, xSecondYAxis.is() );
1955 // stock-chart elements
1956 OUString sChartType ( xDiagram->getDiagramType());
1957 if( sChartType == "com.sun.star.chart.StockDiagram" )
1959 Reference< chart::XStatisticDisplay > xStockPropProvider( xDiagram, uno::UNO_QUERY );
1960 if( xStockPropProvider.is())
1962 // stock-gain-marker
1963 Reference< beans::XPropertySet > xStockPropSet = xStockPropProvider->getUpBar();
1964 if( xStockPropSet.is())
1966 aPropertyStates.clear();
1967 aPropertyStates = mxExpPropMapper->Filter( xStockPropSet );
1969 if( !aPropertyStates.empty() )
1971 if( bExportContent )
1973 AddAutoStyleAttribute( aPropertyStates );
1975 SvXMLElementExport aGain( mrExport, XML_NAMESPACE_CHART, XML_STOCK_GAIN_MARKER, true, true );
1977 else
1979 CollectAutoStyle( aPropertyStates );
1984 // stock-loss-marker
1985 xStockPropSet = xStockPropProvider->getDownBar();
1986 if( xStockPropSet.is())
1988 aPropertyStates.clear();
1989 aPropertyStates = mxExpPropMapper->Filter( xStockPropSet );
1991 if( !aPropertyStates.empty() )
1993 if( bExportContent )
1995 AddAutoStyleAttribute( aPropertyStates );
1997 SvXMLElementExport aGain( mrExport, XML_NAMESPACE_CHART, XML_STOCK_LOSS_MARKER, true, true );
1999 else
2001 CollectAutoStyle( aPropertyStates );
2006 // stock-range-line
2007 xStockPropSet = xStockPropProvider->getMinMaxLine();
2008 if( xStockPropSet.is())
2010 aPropertyStates.clear();
2011 aPropertyStates = mxExpPropMapper->Filter( xStockPropSet );
2013 if( !aPropertyStates.empty() )
2015 if( bExportContent )
2017 AddAutoStyleAttribute( aPropertyStates );
2019 SvXMLElementExport aGain( mrExport, XML_NAMESPACE_CHART, XML_STOCK_RANGE_LINE, true, true );
2021 else
2023 CollectAutoStyle( aPropertyStates );
2030 // wall and floor element
2031 Reference< chart::X3DDisplay > xWallFloorSupplier( xDiagram, uno::UNO_QUERY );
2032 if( mxExpPropMapper.is() &&
2033 xWallFloorSupplier.is())
2035 // remove property states for autostyles
2036 aPropertyStates.clear();
2038 Reference< beans::XPropertySet > xWallPropSet( xWallFloorSupplier->getWall(), uno::UNO_QUERY );
2039 if( xWallPropSet.is())
2041 aPropertyStates = mxExpPropMapper->Filter( xWallPropSet );
2043 if( !aPropertyStates.empty() )
2045 // write element
2046 if( bExportContent )
2048 // add style name attribute
2049 AddAutoStyleAttribute( aPropertyStates );
2051 SvXMLElementExport aWall( mrExport, XML_NAMESPACE_CHART, XML_WALL, true, true );
2053 else // autostyles
2055 CollectAutoStyle( aPropertyStates );
2060 // floor element
2061 // remove property states for autostyles
2062 aPropertyStates.clear();
2064 Reference< beans::XPropertySet > xFloorPropSet( xWallFloorSupplier->getFloor(), uno::UNO_QUERY );
2065 if( xFloorPropSet.is())
2067 aPropertyStates = mxExpPropMapper->Filter( xFloorPropSet );
2069 if( !aPropertyStates.empty() )
2071 // write element
2072 if( bExportContent )
2074 // add style name attribute
2075 AddAutoStyleAttribute( aPropertyStates );
2077 SvXMLElementExport aFloor( mrExport, XML_NAMESPACE_CHART, XML_FLOOR, true, true );
2079 else // autostyles
2081 CollectAutoStyle( aPropertyStates );
2088 void SchXMLExportHelper_Impl::exportCoordinateRegion( const uno::Reference< chart::XDiagram >& xDiagram )
2090 const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
2091 if( nCurrentODFVersion <= SvtSaveOptions::ODFVER_012 )//do not export to ODF 1.2 or older
2092 return;
2094 Reference< chart::XDiagramPositioning > xDiaPos( xDiagram, uno::UNO_QUERY );
2095 SAL_WARN_IF( !xDiaPos.is(), "xmloff.chart", "Invalid xDiaPos as parameter" );
2096 if( !xDiaPos.is() )
2097 return;
2099 awt::Rectangle aRect( xDiaPos->calculateDiagramPositionExcludingAxes() );
2100 addPosition( awt::Point(aRect.X,aRect.Y) );
2101 addSize( awt::Size(aRect.Width,aRect.Height) );
2103 SvXMLElementExport aCoordinateRegion( mrExport, XML_NAMESPACE_CHART_EXT, XML_COORDINATE_REGION, true, true );//#i100778# todo: change to chart namespace in future - dependent on fileformat
2106 namespace
2108 XMLTokenEnum lcl_getTimeUnitToken( sal_Int32 nTimeUnit )
2110 XMLTokenEnum eToken = XML_DAYS;
2111 switch( nTimeUnit )
2113 case css::chart::TimeUnit::YEAR:
2114 eToken = XML_YEARS;
2115 break;
2116 case css::chart::TimeUnit::MONTH:
2117 eToken = XML_MONTHS;
2118 break;
2119 default://days
2120 break;
2122 return eToken;
2126 void SchXMLExportHelper_Impl::exportDateScale( const Reference< beans::XPropertySet >& rAxisProps )
2128 if( !rAxisProps.is() )
2129 return;
2131 chart::TimeIncrement aIncrement;
2132 if( (rAxisProps->getPropertyValue("TimeIncrement") >>= aIncrement) )
2134 sal_Int32 nTimeResolution = css::chart::TimeUnit::DAY;
2135 if( aIncrement.TimeResolution >>= nTimeResolution )
2136 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_BASE_TIME_UNIT, lcl_getTimeUnitToken( nTimeResolution ) );
2138 OUStringBuffer aValue;
2139 chart::TimeInterval aInterval;
2140 if( aIncrement.MajorTimeInterval >>= aInterval )
2142 ::sax::Converter::convertNumber( aValue, aInterval.Number );
2143 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MAJOR_INTERVAL_VALUE, aValue.makeStringAndClear() );
2144 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MAJOR_INTERVAL_UNIT, lcl_getTimeUnitToken( aInterval.TimeUnit ) );
2146 if( aIncrement.MinorTimeInterval >>= aInterval )
2148 ::sax::Converter::convertNumber( aValue, aInterval.Number );
2149 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MINOR_INTERVAL_VALUE, aValue.makeStringAndClear() );
2150 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MINOR_INTERVAL_UNIT, lcl_getTimeUnitToken( aInterval.TimeUnit ) );
2153 SvXMLElementExport aDateScale( mrExport, XML_NAMESPACE_CHART_EXT, XML_DATE_SCALE, true, true );//#i25706#todo: change namespace for next ODF version
2157 void SchXMLExportHelper_Impl::exportAxisTitle( const Reference< beans::XPropertySet >& rTitleProps, bool bExportContent )
2159 if( !rTitleProps.is() )
2160 return;
2161 std::vector< XMLPropertyState > aPropertyStates = mxExpPropMapper->Filter( rTitleProps );
2162 if( bExportContent )
2164 OUString aText;
2165 Any aAny( rTitleProps->getPropertyValue( "String" ));
2166 aAny >>= aText;
2168 Reference< drawing::XShape > xShape( rTitleProps, uno::UNO_QUERY );
2169 if( xShape.is())
2170 addPosition( xShape );
2172 AddAutoStyleAttribute( aPropertyStates );
2173 SvXMLElementExport aTitle( mrExport, XML_NAMESPACE_CHART, XML_TITLE, true, true );
2175 // paragraph containing title
2176 exportText( aText );
2178 else
2180 CollectAutoStyle( aPropertyStates );
2182 aPropertyStates.clear();
2185 void SchXMLExportHelper_Impl::exportGrid( const Reference< beans::XPropertySet >& rGridProperties, bool bMajor, bool bExportContent )
2187 if( !rGridProperties.is() )
2188 return;
2189 std::vector< XMLPropertyState > aPropertyStates = mxExpPropMapper->Filter( rGridProperties );
2190 if( bExportContent )
2192 AddAutoStyleAttribute( aPropertyStates );
2193 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_CLASS, bMajor ? XML_MAJOR : XML_MINOR );
2194 SvXMLElementExport aGrid( mrExport, XML_NAMESPACE_CHART, XML_GRID, true, true );
2196 else
2198 CollectAutoStyle( aPropertyStates );
2200 aPropertyStates.clear();
2203 namespace
2206 //returns true if a date scale needs to be exported
2207 bool lcl_exportAxisType( const Reference< chart2::XAxis >& rChart2Axis, SvXMLExport& rExport)
2209 bool bExportDateScale = false;
2210 if( !rChart2Axis.is() )
2211 return bExportDateScale;
2213 const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
2214 if( nCurrentODFVersion <= SvtSaveOptions::ODFVER_012 )//do not export to ODF 1.2 or older
2215 return bExportDateScale;
2217 chart2::ScaleData aScale( rChart2Axis->getScaleData() );
2218 //#i25706#todo: change namespace for next ODF version
2219 sal_uInt16 nNameSpace = XML_NAMESPACE_CHART_EXT;
2221 switch(aScale.AxisType)
2223 case chart2::AxisType::CATEGORY:
2224 if( aScale.AutoDateAxis )
2226 rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_AUTO );
2227 bExportDateScale = true;
2229 else
2230 rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_TEXT );
2231 break;
2232 case chart2::AxisType::DATE:
2233 rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_DATE );
2234 bExportDateScale = true;
2235 break;
2236 default: //AUTOMATIC
2237 rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_AUTO );
2238 break;
2241 return bExportDateScale;
2244 void disableLinkedNumberFormat(
2245 std::vector<XMLPropertyState>& rPropStates, const rtl::Reference<XMLPropertySetMapper>& rMapper )
2247 for (XMLPropertyState & rState : rPropStates)
2249 if (rState.mnIndex < 0 || rMapper->GetEntryCount() <= rState.mnIndex)
2250 continue;
2252 OUString aXMLName = rMapper->GetEntryXMLName(rState.mnIndex);
2254 if (aXMLName != "link-data-style-to-source")
2255 continue;
2257 // Entry found. Set the value to false and bail out.
2258 rState.maValue <<= false;
2259 return;
2262 // Entry not found. Insert a new entry for this.
2263 sal_Int32 nIndex = rMapper->GetEntryIndex(XML_NAMESPACE_CHART, "link-data-style-to-source", 0);
2264 XMLPropertyState aState(nIndex);
2265 aState.maValue <<= false;
2266 rPropStates.push_back(aState);
2271 void SchXMLExportHelper_Impl::exportAxis(
2272 enum XMLTokenEnum eDimension,
2273 enum XMLTokenEnum eAxisName,
2274 const Reference< beans::XPropertySet >& rAxisProps,
2275 const Reference< chart2::XAxis >& rChart2Axis,
2276 const OUString& rCategoriesRange,
2277 bool bHasTitle, bool bHasMajorGrid, bool bHasMinorGrid,
2278 bool bExportContent )
2280 std::vector< XMLPropertyState > aPropertyStates;
2281 SvXMLElementExport* pAxis = nullptr;
2283 // get property states for autostyles
2284 if( rAxisProps.is() && mxExpPropMapper.is() )
2286 lcl_exportNumberFormat( "NumberFormat", rAxisProps, mrExport );
2287 aPropertyStates = mxExpPropMapper->Filter( rAxisProps );
2289 if (!maSrcShellID.isEmpty() && !maDestShellID.isEmpty() && maSrcShellID != maDestShellID)
2291 // Disable link to source number format property when pasting to
2292 // a different doc shell. These shell ID's should be both empty
2293 // during real ODF export.
2294 disableLinkedNumberFormat(aPropertyStates, mxExpPropMapper->getPropertySetMapper());
2298 bool bExportDateScale = false;
2299 if( bExportContent )
2301 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_DIMENSION, eDimension );
2302 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_NAME, eAxisName );
2303 AddAutoStyleAttribute( aPropertyStates ); // write style name
2304 if( !rCategoriesRange.isEmpty() )
2305 bExportDateScale = lcl_exportAxisType( rChart2Axis, mrExport );
2307 // open axis element
2308 pAxis = new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_AXIS, true, true );
2310 else
2312 CollectAutoStyle( aPropertyStates );
2314 aPropertyStates.clear();
2316 //date scale
2317 if( bExportDateScale )
2318 exportDateScale( rAxisProps );
2320 Reference< beans::XPropertySet > xTitleProps;
2321 Reference< beans::XPropertySet > xMajorGridProps;
2322 Reference< beans::XPropertySet > xMinorGridProps;
2323 Reference< chart::XAxis > xAxis( rAxisProps, uno::UNO_QUERY );
2324 if( xAxis.is() )
2326 xTitleProps = bHasTitle ? xAxis->getAxisTitle() : nullptr;
2327 xMajorGridProps = bHasMajorGrid ? xAxis->getMajorGrid() : nullptr;
2328 xMinorGridProps = bHasMinorGrid ? xAxis->getMinorGrid() : nullptr;
2331 // axis-title
2332 exportAxisTitle( xTitleProps , bExportContent );
2334 // categories if we have a categories chart
2335 if( bExportContent && !rCategoriesRange.isEmpty() )
2337 mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_CELL_RANGE_ADDRESS, rCategoriesRange );
2338 SvXMLElementExport aCategories( mrExport, XML_NAMESPACE_CHART, XML_CATEGORIES, true, true );
2341 // grid
2342 exportGrid( xMajorGridProps, true, bExportContent );
2343 exportGrid( xMinorGridProps, false, bExportContent );
2345 if( pAxis )
2347 //close axis element
2348 delete pAxis;
2349 pAxis = nullptr;
2353 void SchXMLExportHelper_Impl::exportAxes(
2354 const Reference< chart::XDiagram > & xDiagram,
2355 const Reference< chart2::XDiagram > & xNewDiagram,
2356 bool bExportContent )
2358 SAL_WARN_IF( !xDiagram.is(), "xmloff.chart", "Invalid XDiagram as parameter" );
2359 if( ! xDiagram.is())
2360 return;
2362 // get some properties from document first
2363 bool bHasXAxis = false,
2364 bHasYAxis = false,
2365 bHasZAxis = false,
2366 bHasSecondaryXAxis = false,
2367 bHasSecondaryYAxis = false;
2368 bool bHasXAxisTitle = false,
2369 bHasYAxisTitle = false,
2370 bHasZAxisTitle = false,
2371 bHasSecondaryXAxisTitle = false,
2372 bHasSecondaryYAxisTitle = false;
2373 bool bHasXAxisMajorGrid = false,
2374 bHasXAxisMinorGrid = false,
2375 bHasYAxisMajorGrid = false,
2376 bHasYAxisMinorGrid = false,
2377 bHasZAxisMajorGrid = false,
2378 bHasZAxisMinorGrid = false;
2380 // get multiple properties using XMultiPropertySet
2381 MultiPropertySetHandler aDiagramProperties (xDiagram);
2383 aDiagramProperties.Add ("HasXAxis", bHasXAxis);
2384 aDiagramProperties.Add ("HasYAxis", bHasYAxis);
2385 aDiagramProperties.Add ("HasZAxis", bHasZAxis);
2386 aDiagramProperties.Add ("HasSecondaryXAxis", bHasSecondaryXAxis);
2387 aDiagramProperties.Add ("HasSecondaryYAxis", bHasSecondaryYAxis);
2389 aDiagramProperties.Add ("HasXAxisTitle", bHasXAxisTitle);
2390 aDiagramProperties.Add ("HasYAxisTitle", bHasYAxisTitle);
2391 aDiagramProperties.Add ("HasZAxisTitle", bHasZAxisTitle);
2392 aDiagramProperties.Add ("HasSecondaryXAxisTitle", bHasSecondaryXAxisTitle);
2393 aDiagramProperties.Add ("HasSecondaryYAxisTitle", bHasSecondaryYAxisTitle);
2395 aDiagramProperties.Add ("HasXAxisGrid", bHasXAxisMajorGrid);
2396 aDiagramProperties.Add ("HasYAxisGrid", bHasYAxisMajorGrid);
2397 aDiagramProperties.Add ("HasZAxisGrid", bHasZAxisMajorGrid);
2399 aDiagramProperties.Add ("HasXAxisHelpGrid", bHasXAxisMinorGrid);
2400 aDiagramProperties.Add ("HasYAxisHelpGrid", bHasYAxisMinorGrid);
2401 aDiagramProperties.Add ("HasZAxisHelpGrid", bHasZAxisMinorGrid);
2403 if ( ! aDiagramProperties.GetProperties ())
2405 SAL_INFO("xmloff.chart", "Required properties not found in Chart diagram");
2408 Reference< chart2::XCoordinateSystem > xCooSys( lcl_getCooSys(xNewDiagram) );
2410 // write an axis element also if the axis itself is not visible, but a grid or a title
2412 OUString aCategoriesRange;
2413 Reference< chart::XAxisSupplier > xAxisSupp( xDiagram, uno::UNO_QUERY );
2415 // x axis
2417 Reference< css::chart2::XAxis > xNewAxis = lcl_getAxis( xCooSys, XML_X );
2418 if( xNewAxis.is() )
2420 Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getAxis(0) : nullptr, uno::UNO_QUERY );
2421 if( mbHasCategoryLabels && bExportContent )
2423 Reference< chart2::data::XLabeledDataSequence > xCategories( lcl_getCategories( xNewDiagram ) );
2424 if( xCategories.is() )
2426 Reference< chart2::data::XDataSequence > xValues( xCategories->getValues() );
2427 if( xValues.is() )
2429 Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
2430 maCategoriesRange = xValues->getSourceRangeRepresentation();
2431 aCategoriesRange = lcl_ConvertRange( maCategoriesRange, xNewDoc );
2435 exportAxis( XML_X, XML_PRIMARY_X, xAxisProps, xNewAxis, aCategoriesRange, bHasXAxisTitle, bHasXAxisMajorGrid, bHasXAxisMinorGrid, bExportContent );
2436 aCategoriesRange.clear();
2439 // secondary x axis
2441 Reference< chart::XSecondAxisTitleSupplier > xSecondTitleSupp( xDiagram, uno::UNO_QUERY );
2442 xNewAxis = lcl_getAxis( xCooSys, XML_X, false );
2443 if( xNewAxis.is() )
2445 Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getSecondaryAxis(0) : nullptr, uno::UNO_QUERY );
2446 exportAxis( XML_X, XML_SECONDARY_X, xAxisProps, xNewAxis, aCategoriesRange, bHasSecondaryXAxisTitle, false, false, bExportContent );
2449 // y axis
2451 xNewAxis = lcl_getAxis( xCooSys, XML_Y );
2452 if( xNewAxis.is() )
2454 Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getAxis(1) : nullptr, uno::UNO_QUERY );
2455 exportAxis( XML_Y, XML_PRIMARY_Y, xAxisProps, xNewAxis, aCategoriesRange, bHasYAxisTitle, bHasYAxisMajorGrid, bHasYAxisMinorGrid, bExportContent );
2458 // secondary y axis
2460 xNewAxis = lcl_getAxis( xCooSys, XML_Y, false );
2461 if( xNewAxis.is() )
2463 Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getSecondaryAxis(1) : nullptr, uno::UNO_QUERY );
2464 exportAxis( XML_Y, XML_SECONDARY_Y, xAxisProps, xNewAxis, aCategoriesRange, bHasSecondaryYAxisTitle, false, false, bExportContent );
2467 // z axis
2469 xNewAxis = lcl_getAxis( xCooSys, XML_Z );
2470 if( xNewAxis.is() )
2472 Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getAxis(2) : nullptr, uno::UNO_QUERY );
2473 exportAxis( XML_Z, XML_PRIMARY_Z, xAxisProps, xNewAxis, aCategoriesRange, bHasZAxisTitle, bHasZAxisMajorGrid, bHasZAxisMinorGrid, bExportContent );
2477 namespace
2479 bool lcl_hasNoValuesButText( const uno::Reference< chart2::data::XDataSequence >& xDataSequence )
2481 if( !xDataSequence.is() )
2482 return false;//have no data
2484 Sequence< uno::Any > aData;
2485 Reference< chart2::data::XNumericalDataSequence > xNumericalDataSequence( xDataSequence, uno::UNO_QUERY );
2486 if( xNumericalDataSequence.is() )
2488 Sequence< double > aDoubles( xNumericalDataSequence->getNumericalData() );
2489 sal_Int32 nCount = aDoubles.getLength();
2490 for( sal_Int32 i = 0; i < nCount; ++i )
2492 if( !::rtl::math::isNan( aDoubles[i] ) )
2493 return false;//have double value
2496 else
2498 aData = xDataSequence->getData();
2499 double fDouble = 0.0;
2500 sal_Int32 nCount = aData.getLength();
2501 for( sal_Int32 i = 0; i < nCount; ++i )
2503 if( (aData[i] >>= fDouble) && !::rtl::math::isNan( fDouble ) )
2504 return false;//have double value
2508 //no values found
2510 Reference< chart2::data::XTextualDataSequence > xTextualDataSequence( xDataSequence, uno::UNO_QUERY );
2511 if( xTextualDataSequence.is() )
2513 uno::Sequence< OUString > aStrings( xTextualDataSequence->getTextualData() );
2514 sal_Int32 nCount = aStrings.getLength();
2515 for( sal_Int32 i = 0; i < nCount; ++i )
2517 if( !aStrings[i].isEmpty() )
2518 return true;//have text
2521 else
2523 if( !aData.getLength() )
2524 aData = xDataSequence->getData();
2525 OUString aString;
2526 sal_Int32 nCount = aData.getLength();
2527 for( sal_Int32 i = 0; i < nCount; ++i )
2529 if( (aData[i]>>=aString) && !aString.isEmpty() )
2530 return true;//have text
2533 //no doubles and no texts
2534 return false;
2538 void SchXMLExportHelper_Impl::exportSeries(
2539 const Reference< chart2::XDiagram > & xNewDiagram,
2540 const awt::Size & rPageSize,
2541 bool bExportContent,
2542 bool bHasTwoYAxes )
2544 Reference< chart2::XCoordinateSystemContainer > xBCooSysCnt( xNewDiagram, uno::UNO_QUERY );
2545 if( ! xBCooSysCnt.is())
2546 return;
2547 Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
2549 OUString aFirstXDomainRange;
2550 OUString aFirstYDomainRange;
2552 std::vector< XMLPropertyState > aPropertyStates;
2554 Sequence< Reference< chart2::XCoordinateSystem > >
2555 aCooSysSeq( xBCooSysCnt->getCoordinateSystems());
2556 for( sal_Int32 nCSIdx=0; nCSIdx<aCooSysSeq.getLength(); ++nCSIdx )
2558 Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nCSIdx], uno::UNO_QUERY );
2559 if( ! xCTCnt.is())
2560 continue;
2561 Sequence< Reference< chart2::XChartType > > aCTSeq( xCTCnt->getChartTypes());
2562 for( sal_Int32 nCTIdx=0; nCTIdx<aCTSeq.getLength(); ++nCTIdx )
2564 Reference< chart2::XDataSeriesContainer > xDSCnt( aCTSeq[nCTIdx], uno::UNO_QUERY );
2565 if( ! xDSCnt.is())
2566 continue;
2567 // note: if xDSCnt.is() then also aCTSeq[nCTIdx]
2568 OUString aChartType( aCTSeq[nCTIdx]->getChartType());
2569 OUString aLabelRole = aCTSeq[nCTIdx]->getRoleOfSequenceForSeriesLabel();
2571 // special export for stock charts
2572 if ( aChartType == "com.sun.star.chart2.CandleStickChartType" )
2574 bool bJapaneseCandleSticks = false;
2575 Reference< beans::XPropertySet > xCTProp( aCTSeq[nCTIdx], uno::UNO_QUERY );
2576 if( xCTProp.is())
2577 xCTProp->getPropertyValue("Japanese") >>= bJapaneseCandleSticks;
2578 exportCandleStickSeries(
2579 xDSCnt->getDataSeries(), xNewDiagram, bJapaneseCandleSticks, bExportContent );
2580 continue;
2583 // export dataseries for current chart-type
2584 Sequence< Reference< chart2::XDataSeries > > aSeriesSeq( xDSCnt->getDataSeries());
2585 for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeriesSeq.getLength(); ++nSeriesIdx )
2587 // export series
2588 Reference< chart2::data::XDataSource > xSource( aSeriesSeq[nSeriesIdx], uno::UNO_QUERY );
2589 if( xSource.is())
2591 SvXMLElementExport* pSeries = nullptr;
2592 Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeqCnt(
2593 xSource->getDataSequences());
2594 sal_Int32 nMainSequenceIndex = -1;
2595 sal_Int32 nSeriesLength = 0;
2596 sal_Int32 nAttachedAxis = chart::ChartAxisAssign::PRIMARY_Y;
2597 bool bHasMeanValueLine = false;
2598 Reference< beans::XPropertySet > xPropSet;
2599 tLabelValuesDataPair aSeriesLabelValuesPair;
2601 // search for main sequence and create a series element
2603 Reference< chart2::data::XDataSequence > xValuesSeq;
2604 Reference< chart2::data::XDataSequence > xLabelSeq;
2605 sal_Int32 nSeqIdx=0;
2606 for( ; nSeqIdx<aSeqCnt.getLength(); ++nSeqIdx )
2608 OUString aRole;
2609 Reference< chart2::data::XDataSequence > xTempValueSeq( aSeqCnt[nSeqIdx]->getValues() );
2610 if( nMainSequenceIndex==-1 )
2612 Reference< beans::XPropertySet > xSeqProp( xTempValueSeq, uno::UNO_QUERY );
2613 if( xSeqProp.is())
2614 xSeqProp->getPropertyValue("Role") >>= aRole;
2615 // "main" sequence
2616 if( aRole.equals( aLabelRole ))
2618 xValuesSeq.set( xTempValueSeq );
2619 xLabelSeq.set( aSeqCnt[nSeqIdx]->getLabel());
2620 nMainSequenceIndex = nSeqIdx;
2623 sal_Int32 nSequenceLength = (xTempValueSeq.is()? xTempValueSeq->getData().getLength() : sal_Int32(0));
2624 if( nSeriesLength < nSequenceLength )
2625 nSeriesLength = nSequenceLength;
2628 // have found the main sequence, then xValuesSeq and
2629 // xLabelSeq contain those. Otherwise both are empty
2631 // get property states for autostyles
2634 xPropSet = SchXMLSeriesHelper::createOldAPISeriesPropertySet(
2635 aSeriesSeq[nSeriesIdx], mrExport.GetModel() );
2637 catch( const uno::Exception & rEx )
2639 SAL_INFO("xmloff.chart", "Series not found or no XPropertySet: " << rEx.Message );
2640 continue;
2642 if( xPropSet.is())
2644 // determine attached axis
2647 Any aAny( xPropSet->getPropertyValue( "Axis" ));
2648 aAny >>= nAttachedAxis;
2650 aAny = xPropSet->getPropertyValue( "MeanValue" );
2651 aAny >>= bHasMeanValueLine;
2653 catch( const beans::UnknownPropertyException & rEx )
2655 SAL_INFO("xmloff.chart", "Required property not found in DataRowProperties: " << rEx.Message );
2658 const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
2659 if( nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 )
2661 lcl_exportNumberFormat( "NumberFormat", xPropSet, mrExport );
2662 lcl_exportNumberFormat( "PercentageNumberFormat", xPropSet, mrExport );
2665 if( mxExpPropMapper.is())
2666 aPropertyStates = mxExpPropMapper->Filter( xPropSet );
2669 if( bExportContent )
2671 if( bHasTwoYAxes )
2673 if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
2674 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y );
2675 else
2676 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y );
2679 // write style name
2680 AddAutoStyleAttribute( aPropertyStates );
2682 if( xValuesSeq.is())
2683 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS,
2684 lcl_ConvertRange(
2685 xValuesSeq->getSourceRangeRepresentation(),
2686 xNewDoc ));
2687 else
2688 // #i75297# allow empty series, export empty range to have all ranges on import
2689 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, OUString());
2691 if (xLabelSeq.is())
2693 // Check if the label is direct string value rather than a reference.
2694 bool bHasString = false;
2695 uno::Reference<beans::XPropertySet> xLSProp(xLabelSeq, uno::UNO_QUERY);
2696 if (xLSProp.is())
2700 xLSProp->getPropertyValue("HasStringLabel") >>= bHasString;
2702 catch (const beans::UnknownPropertyException&) {}
2705 OUString aRange = xLabelSeq->getSourceRangeRepresentation();
2707 if (bHasString)
2709 mrExport.AddAttribute(
2710 XML_NAMESPACE_LO_EXT, XML_LABEL_STRING, aRange);
2712 else
2714 mrExport.AddAttribute(
2715 XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS,
2716 lcl_ConvertRange(
2717 xLabelSeq->getSourceRangeRepresentation(), xNewDoc));
2721 if( xLabelSeq.is() || xValuesSeq.is() )
2722 aSeriesLabelValuesPair = tLabelValuesDataPair( xLabelSeq, xValuesSeq );
2724 // chart-type for mixed types
2725 enum XMLTokenEnum eCTToken(
2726 SchXMLTools::getTokenByChartType( aChartType, false /* bUseOldNames */ ));
2727 //@todo: get token for current charttype
2728 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_CLASS,
2729 mrExport.GetNamespaceMap().GetQNameByKey(
2730 XML_NAMESPACE_CHART, GetXMLToken( eCTToken )));
2732 // open series element until end of for loop
2733 pSeries = new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_SERIES, true, true );
2735 else // autostyles
2737 CollectAutoStyle( aPropertyStates );
2739 // remove property states for autostyles
2740 aPropertyStates.clear();
2744 // export domain elements if we have a series parent element
2745 if( pSeries )
2747 // domain elements
2748 if( bExportContent )
2750 bool bIsScatterChart = aChartType == "com.sun.star.chart2.ScatterChartType";
2751 bool bIsBubbleChart = aChartType == "com.sun.star.chart2.BubbleChartType";
2752 Reference< chart2::data::XDataSequence > xYValuesForBubbleChart;
2753 if( bIsBubbleChart )
2755 Reference< chart2::data::XLabeledDataSequence > xSequence( lcl_getDataSequenceByRole( aSeqCnt, "values-y" ) );
2756 if( xSequence.is() )
2758 xYValuesForBubbleChart = xSequence->getValues();
2759 if( !lcl_exportDomainForThisSequence( xYValuesForBubbleChart, aFirstYDomainRange, mrExport ) )
2760 xYValuesForBubbleChart = nullptr;
2763 if( bIsScatterChart || bIsBubbleChart )
2765 Reference< chart2::data::XLabeledDataSequence > xSequence( lcl_getDataSequenceByRole( aSeqCnt, "values-x" ) );
2766 if( xSequence.is() )
2768 Reference< chart2::data::XDataSequence > xValues( xSequence->getValues() );
2769 if( lcl_exportDomainForThisSequence( xValues, aFirstXDomainRange, mrExport ) )
2770 m_aDataSequencesToExport.push_back( tLabelValuesDataPair(
2771 uno::Reference< chart2::data::XDataSequence >(), xValues ));
2773 else if( nSeriesIdx==0 )
2775 //might be that the categories are used as x-values (e.g. for date axis) -> export them accordingly
2776 Reference< chart2::data::XLabeledDataSequence > xCategories( lcl_getCategories( xNewDiagram ) );
2777 if( xCategories.is() )
2779 Reference< chart2::data::XDataSequence > xValues( xCategories->getValues() );
2780 if( !lcl_hasNoValuesButText( xValues ) )
2781 lcl_exportDomainForThisSequence( xValues, aFirstXDomainRange, mrExport );
2785 if( xYValuesForBubbleChart.is() )
2786 m_aDataSequencesToExport.push_back( tLabelValuesDataPair(
2787 uno::Reference< chart2::data::XDataSequence >(), xYValuesForBubbleChart ));
2791 // add sequences for main sequence after domain sequences,
2792 // so that the export of the local table has the correct order
2793 if( bExportContent &&
2794 (aSeriesLabelValuesPair.first.is() || aSeriesLabelValuesPair.second.is()))
2795 m_aDataSequencesToExport.push_back( aSeriesLabelValuesPair );
2797 // statistical objects:
2798 // regression curves and mean value lines
2799 if( bHasMeanValueLine &&
2800 xPropSet.is() &&
2801 mxExpPropMapper.is() )
2803 Reference< beans::XPropertySet > xStatProp;
2806 Any aPropAny( xPropSet->getPropertyValue( "DataMeanValueProperties" ));
2807 aPropAny >>= xStatProp;
2809 catch( const uno::Exception & rEx )
2811 SAL_INFO("xmloff.chart", "Exception caught during Export of series - optional DataMeanValueProperties not available: " << rEx.Message );
2814 if( xStatProp.is() )
2816 aPropertyStates = mxExpPropMapper->Filter( xStatProp );
2818 if( !aPropertyStates.empty() )
2820 // write element
2821 if( bExportContent )
2823 // add style name attribute
2824 AddAutoStyleAttribute( aPropertyStates );
2826 SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_MEAN_VALUE, true, true );
2828 else // autostyles
2830 CollectAutoStyle( aPropertyStates );
2836 if( xPropSet.is() &&
2837 mxExpPropMapper.is() )
2839 exportRegressionCurve( aSeriesSeq[nSeriesIdx], rPageSize, bExportContent );
2842 exportErrorBar( xPropSet,false, bExportContent ); // X ErrorBar
2843 exportErrorBar( xPropSet,true, bExportContent ); // Y ErrorBar
2845 exportDataPoints(
2846 uno::Reference< beans::XPropertySet >( aSeriesSeq[nSeriesIdx], uno::UNO_QUERY ),
2847 nSeriesLength, xNewDiagram, bExportContent );
2849 const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
2850 if( bExportContent && nCurrentODFVersion > SvtSaveOptions::ODFVER_012 )//do not export to ODF 1.2 or older
2852 Sequence< OUString > aSupportedMappings = aCTSeq[nCTIdx]->getSupportedPropertyRoles();
2853 exportPropertyMapping( xSource, aSupportedMappings );
2856 // close series element
2857 delete pSeries;
2860 aPropertyStates.clear();
2865 void SchXMLExportHelper_Impl::exportPropertyMapping(
2866 const Reference< chart2::data::XDataSource > & xSource, Sequence< OUString >& rSupportedMappings )
2868 Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
2869 Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeqCnt(
2870 xSource->getDataSequences());
2872 for(sal_Int32 i = 0, n = rSupportedMappings.getLength(); i < n; ++i)
2874 Reference< chart2::data::XLabeledDataSequence > xSequence( lcl_getDataSequenceByRole( aSeqCnt, rSupportedMappings[i] ) );
2875 if(xSequence.is())
2877 Reference< chart2::data::XDataSequence > xValues( xSequence->getValues() );
2878 if( xValues.is())
2880 mrExport.AddAttribute( XML_NAMESPACE_LO_EXT, XML_PROPERTY, rSupportedMappings[i]);
2881 mrExport.AddAttribute( XML_NAMESPACE_LO_EXT, XML_CELL_RANGE_ADDRESS,
2882 lcl_ConvertRange(
2883 xValues->getSourceRangeRepresentation(),
2884 xNewDoc ));
2885 SvXMLElementExport( mrExport, XML_NAMESPACE_LO_EXT, XML_PROPERTY_MAPPING, true, true );
2887 // register range for data table export
2888 m_aDataSequencesToExport.push_back( tLabelValuesDataPair(
2889 uno::Reference< chart2::data::XDataSequence >(), xValues ));
2895 void SchXMLExportHelper_Impl::exportRegressionCurve(
2896 const Reference< chart2::XDataSeries >& xSeries,
2897 const awt::Size& rPageSize,
2898 bool bExportContent )
2900 OSL_ASSERT( mxExpPropMapper.is());
2902 std::vector< XMLPropertyState > aPropertyStates;
2903 std::vector< XMLPropertyState > aEquationPropertyStates;
2905 Reference< chart2::XRegressionCurveContainer > xRegressionCurveContainer( xSeries, uno::UNO_QUERY );
2906 if( xRegressionCurveContainer.is() )
2908 Sequence< Reference< chart2::XRegressionCurve > > aRegCurveSeq = xRegressionCurveContainer->getRegressionCurves();
2910 const Reference< chart2::XRegressionCurve >* pBeg = aRegCurveSeq.getConstArray();
2911 const Reference< chart2::XRegressionCurve >* pEnd = pBeg + aRegCurveSeq.getLength();
2912 const Reference< chart2::XRegressionCurve >* pIt;
2914 for( pIt = pBeg; pIt != pEnd; pIt++ )
2916 Reference< chart2::XRegressionCurve > xRegCurve = *pIt;
2917 if (!xRegCurve.is())
2918 continue;
2920 Reference< beans::XPropertySet > xProperties( xRegCurve , uno::UNO_QUERY );
2921 if( !xProperties.is() )
2922 continue;
2924 Reference< lang::XServiceName > xServiceName( xProperties, uno::UNO_QUERY );
2925 if( !xServiceName.is() )
2926 continue;
2928 bool bShowEquation = false;
2929 bool bShowRSquared = false;
2930 bool bExportEquation = false;
2932 OUString aService;
2933 aService = xServiceName->getServiceName();
2935 aPropertyStates = mxExpPropMapper->Filter( xProperties );
2937 // Add service name (which is regression type)
2938 sal_Int32 nIndex = GetPropertySetMapper()->FindEntryIndex(XML_SCH_CONTEXT_SPECIAL_REGRESSION_TYPE);
2939 XMLPropertyState property(nIndex, uno::makeAny(aService));
2940 aPropertyStates.push_back(property);
2942 Reference< beans::XPropertySet > xEquationProperties;
2943 xEquationProperties.set( xRegCurve->getEquationProperties() );
2944 if( xEquationProperties.is())
2946 xEquationProperties->getPropertyValue( "ShowEquation") >>= bShowEquation;
2947 xEquationProperties->getPropertyValue( "ShowCorrelationCoefficient") >>= bShowRSquared;
2949 bExportEquation = ( bShowEquation || bShowRSquared );
2950 const SvtSaveOptions::ODFDefaultVersion nCurrentVersion( SvtSaveOptions().GetODFDefaultVersion() );
2951 if( nCurrentVersion < SvtSaveOptions::ODFVER_012 )
2953 bExportEquation=false;
2955 if( bExportEquation )
2957 // number format
2958 sal_Int32 nNumberFormat = 0;
2959 if( (xEquationProperties->getPropertyValue("NumberFormat") >>= nNumberFormat ) &&
2960 nNumberFormat != -1 )
2962 mrExport.addDataStyle( nNumberFormat );
2964 aEquationPropertyStates = mxExpPropMapper->Filter( xEquationProperties );
2968 if( !aPropertyStates.empty() || bExportEquation )
2970 // write element
2971 if( bExportContent )
2973 // add style name attribute
2974 if( !aPropertyStates.empty())
2976 AddAutoStyleAttribute( aPropertyStates );
2979 SvXMLElementExport aRegressionExport( mrExport, XML_NAMESPACE_CHART, XML_REGRESSION_CURVE, true, true );
2980 if( bExportEquation )
2982 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_DISPLAY_EQUATION, (bShowEquation ? XML_TRUE : XML_FALSE) );
2983 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_DISPLAY_R_SQUARE, (bShowRSquared ? XML_TRUE : XML_FALSE) );
2985 // export position
2986 chart2::RelativePosition aRelativePosition;
2987 if( xEquationProperties->getPropertyValue( "RelativePosition" ) >>= aRelativePosition )
2989 double fX = aRelativePosition.Primary * rPageSize.Width;
2990 double fY = aRelativePosition.Secondary * rPageSize.Height;
2991 awt::Point aPos;
2992 aPos.X = static_cast< sal_Int32 >( ::rtl::math::round( fX ));
2993 aPos.Y = static_cast< sal_Int32 >( ::rtl::math::round( fY ));
2994 addPosition( aPos );
2997 if( !aEquationPropertyStates.empty())
2999 AddAutoStyleAttribute( aEquationPropertyStates );
3002 SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_EQUATION, true, true );
3005 else // autostyles
3007 if( !aPropertyStates.empty())
3009 CollectAutoStyle( aPropertyStates );
3011 if( bExportEquation && !aEquationPropertyStates.empty())
3013 CollectAutoStyle( aEquationPropertyStates );
3021 void SchXMLExportHelper_Impl::exportErrorBar( const Reference<beans::XPropertySet> &xSeriesProp,
3022 bool bYError, bool bExportContent )
3024 assert(mxExpPropMapper.is());
3026 const SvtSaveOptions::ODFDefaultVersion nCurrentVersion( SvtSaveOptions().GetODFDefaultVersion() );
3028 /// Don't export X ErrorBars for older ODF versions.
3029 if ( !bYError && nCurrentVersion < SvtSaveOptions::ODFVER_012 )
3030 return;
3032 if (xSeriesProp.is())
3034 bool bNegative = false, bPositive = false;
3035 sal_Int32 nErrorBarStyle = chart::ErrorBarStyle::NONE;
3036 Reference< beans::XPropertySet > xErrorBarProp;
3040 Any aAny;
3042 aAny = xSeriesProp->getPropertyValue( bYError ? OUString("ErrorBarY") : OUString("ErrorBarX") );
3043 aAny >>= xErrorBarProp;
3045 if ( xErrorBarProp.is() )
3047 aAny = xErrorBarProp->getPropertyValue("ShowNegativeError" );
3048 aAny >>= bNegative;
3050 aAny = xErrorBarProp->getPropertyValue("ShowPositiveError" );
3051 aAny >>= bPositive;
3053 aAny = xErrorBarProp->getPropertyValue("ErrorBarStyle" );
3054 aAny >>= nErrorBarStyle;
3057 catch( const beans::UnknownPropertyException & rEx )
3059 SAL_INFO("xmloff.chart", "Required property not found in DataRowProperties: " << rEx.Message );
3062 if( nErrorBarStyle != chart::ErrorBarStyle::NONE && (bNegative || bPositive))
3064 if( bExportContent && nErrorBarStyle == chart::ErrorBarStyle::FROM_DATA )
3066 uno::Reference< chart2::XChartDocument > xNewDoc(mrExport.GetModel(), uno::UNO_QUERY);
3068 // register data ranges for error bars for export in local table
3069 ::std::vector< Reference< chart2::data::XDataSequence > > aErrorBarSequences(
3070 lcl_getErrorBarSequences( xErrorBarProp ));
3071 for( ::std::vector< Reference< chart2::data::XDataSequence > >::const_iterator aIt(
3072 aErrorBarSequences.begin()); aIt != aErrorBarSequences.end(); ++aIt )
3074 m_aDataSequencesToExport.push_back( tLabelValuesDataPair(
3075 uno::Reference< chart2::data::XDataSequence >(), *aIt ));
3079 std::vector< XMLPropertyState > aPropertyStates = mxExpPropMapper->Filter( xErrorBarProp );
3081 if( !aPropertyStates.empty() )
3083 // write element
3084 if( bExportContent )
3086 // add style name attribute
3087 AddAutoStyleAttribute( aPropertyStates );
3089 if( nCurrentVersion >= SvtSaveOptions::ODFVER_012 )
3090 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_DIMENSION, bYError ? XML_Y : XML_X );//#i114149#
3091 SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_ERROR_INDICATOR, true, true );
3093 else // autostyles
3095 CollectAutoStyle( aPropertyStates );
3102 void SchXMLExportHelper_Impl::exportCandleStickSeries(
3103 const Sequence< Reference< chart2::XDataSeries > > & aSeriesSeq,
3104 const Reference< chart2::XDiagram > & xDiagram,
3105 bool bJapaneseCandleSticks,
3106 bool bExportContent )
3109 for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeriesSeq.getLength(); ++nSeriesIdx )
3111 Reference< chart2::XDataSeries > xSeries( aSeriesSeq[nSeriesIdx] );
3112 sal_Int32 nAttachedAxis = lcl_isSeriesAttachedToFirstAxis( xSeries )
3113 ? chart::ChartAxisAssign::PRIMARY_Y
3114 : chart::ChartAxisAssign::SECONDARY_Y;
3116 Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY );
3117 if( xSource.is())
3119 // export series in correct order (as we don't store roles)
3120 // with japanese candlesticks: open, low, high, close
3121 // otherwise: low, high, close
3122 Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeqCnt(
3123 xSource->getDataSequences());
3125 sal_Int32 nSeriesLength =
3126 lcl_getSequenceLengthByRole( aSeqCnt, "values-last");
3128 if( bExportContent )
3130 Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
3131 //@todo: export data points
3133 //TODO: moggi: same code three times
3134 // open
3135 if( bJapaneseCandleSticks )
3137 tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole(
3138 aSeqCnt, "values-first", xNewDoc, m_aDataSequencesToExport ));
3139 if( !aRanges.second.isEmpty())
3140 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, aRanges.second );
3141 if( !aRanges.first.isEmpty())
3142 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS, aRanges.first );
3143 if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
3144 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y );
3145 else
3146 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y );
3147 SvXMLElementExport aOpenSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, true, true );
3148 // export empty data points
3149 exportDataPoints( nullptr, nSeriesLength, xDiagram, bExportContent );
3152 // low
3154 tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole(
3155 aSeqCnt, "values-min", xNewDoc, m_aDataSequencesToExport ));
3156 if( !aRanges.second.isEmpty())
3157 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, aRanges.second );
3158 if( !aRanges.first.isEmpty())
3159 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS, aRanges.first );
3160 if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
3161 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y );
3162 else
3163 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y );
3164 SvXMLElementExport aLowSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, true, true );
3165 // export empty data points
3166 exportDataPoints( nullptr, nSeriesLength, xDiagram, bExportContent );
3169 // high
3171 tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole(
3172 aSeqCnt, "values-max", xNewDoc, m_aDataSequencesToExport ));
3173 if( !aRanges.second.isEmpty())
3174 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, aRanges.second );
3175 if( !aRanges.first.isEmpty())
3176 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS, aRanges.first );
3177 if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
3178 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y );
3179 else
3180 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y );
3181 SvXMLElementExport aHighSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, true, true );
3182 // export empty data points
3183 exportDataPoints( nullptr, nSeriesLength, xDiagram, bExportContent );
3186 // close
3188 tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole(
3189 aSeqCnt, "values-last", xNewDoc, m_aDataSequencesToExport ));
3190 if( !aRanges.second.isEmpty())
3191 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, aRanges.second );
3192 if( !aRanges.first.isEmpty())
3193 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS, aRanges.first );
3194 if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
3195 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y );
3196 else
3197 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y );
3198 SvXMLElementExport aCloseSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, true, true );
3199 // export empty data points
3200 exportDataPoints( nullptr, nSeriesLength, xDiagram, bExportContent );
3203 else // autostyles
3205 // for close series
3207 // remove property states for autostyles
3212 void SchXMLExportHelper_Impl::exportDataPoints(
3213 const uno::Reference< beans::XPropertySet > & xSeriesProperties,
3214 sal_Int32 nSeriesLength,
3215 const uno::Reference< chart2::XDiagram > & xDiagram,
3216 bool bExportContent )
3218 // data-points
3220 // write data-points only if they contain autostyles
3221 // objects with equal autostyles are grouped using the attribute
3222 // repeat="number"
3224 // Note: if only the nth data-point has autostyles there is an element
3225 // without style and repeat="n-1" attribute written in advance.
3227 // the sequence aDataPointSeq contains indices of data-points that
3228 // do have own attributes. This increases the performance substantially.
3230 // more performant version for #93600#
3231 if (!mxExpPropMapper.is())
3232 return;
3234 uno::Reference< chart2::XDataSeries > xSeries( xSeriesProperties, uno::UNO_QUERY );
3236 std::vector< XMLPropertyState > aPropertyStates;
3238 bool bVaryColorsByPoint = false;
3239 Sequence< sal_Int32 > aDataPointSeq;
3240 if( xSeriesProperties.is())
3242 xSeriesProperties->getPropertyValue("AttributedDataPoints") >>= aDataPointSeq;
3243 xSeriesProperties->getPropertyValue("VaryColorsByPoint") >>= bVaryColorsByPoint;
3246 sal_Int32 nSize = aDataPointSeq.getLength();
3247 SAL_WARN_IF( nSize > nSeriesLength, "xmloff.chart", "Too many point attributes" );
3249 const sal_Int32 * pPoints = aDataPointSeq.getConstArray();
3250 sal_Int32 nElement;
3251 sal_Int32 nRepeat;
3252 Reference< chart2::XColorScheme > xColorScheme;
3253 if( xDiagram.is())
3254 xColorScheme.set( xDiagram->getDefaultColorScheme());
3256 ::std::list< SchXMLDataPointStruct > aDataPointList;
3258 sal_Int32 nLastIndex = -1;
3259 sal_Int32 nCurrIndex = 0;
3261 // collect elements
3262 if( bVaryColorsByPoint && xColorScheme.is() )
3264 ::std::set< sal_Int32 > aAttrPointSet;
3265 ::std::copy( pPoints, pPoints + aDataPointSeq.getLength(),
3266 ::std::inserter( aAttrPointSet, aAttrPointSet.begin()));
3267 const ::std::set< sal_Int32 >::const_iterator aEndIt( aAttrPointSet.end());
3268 for( nElement = 0; nElement < nSeriesLength; ++nElement )
3270 aPropertyStates.clear();
3271 uno::Reference< beans::XPropertySet > xPropSet;
3272 bool bExportNumFmt = false;
3273 if( aAttrPointSet.find( nElement ) != aEndIt )
3277 xPropSet = SchXMLSeriesHelper::createOldAPIDataPointPropertySet(
3278 xSeries, nElement, mrExport.GetModel() );
3279 bExportNumFmt = true;
3281 catch( const uno::Exception & rEx )
3283 SAL_INFO("xmloff.chart", "Exception caught during Export of data point: " << rEx.Message );
3286 else
3288 // property set only containing the color
3289 xPropSet.set( new ::xmloff::chart::ColorPropertySet(
3290 xColorScheme->getColorByIndex( nElement )));
3292 SAL_WARN_IF( !xPropSet.is(), "xmloff.chart", "Pie Segments should have properties" );
3293 if( xPropSet.is())
3295 const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
3296 if( nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 && bExportNumFmt )
3298 lcl_exportNumberFormat( "NumberFormat", xPropSet, mrExport );
3299 lcl_exportNumberFormat( "PercentageNumberFormat", xPropSet, mrExport );
3302 aPropertyStates = mxExpPropMapper->Filter( xPropSet );
3303 if( !aPropertyStates.empty() )
3305 if( bExportContent )
3307 // write data-point with style
3308 SAL_WARN_IF( maAutoStyleNameQueue.empty(), "xmloff.chart", "Autostyle queue empty!" );
3310 SchXMLDataPointStruct aPoint;
3311 aPoint.maStyleName = maAutoStyleNameQueue.front();
3312 maAutoStyleNameQueue.pop();
3313 aDataPointList.push_back( aPoint );
3315 else
3317 CollectAutoStyle( aPropertyStates );
3322 SAL_WARN_IF( bExportContent && (static_cast<sal_Int32>(aDataPointList.size()) != nSeriesLength), "xmloff.chart", "not enough data points on content export" );
3324 else
3326 for( nElement = 0; nElement < nSize; ++nElement )
3328 aPropertyStates.clear();
3329 nCurrIndex = pPoints[ nElement ];
3330 //assuming sorted indices in pPoints
3332 if( nCurrIndex<0 || nCurrIndex>=nSeriesLength )
3333 break;
3335 // write leading empty data points
3336 if( nCurrIndex - nLastIndex > 1 )
3338 SchXMLDataPointStruct aPoint;
3339 aPoint.mnRepeat = nCurrIndex - nLastIndex - 1;
3340 aDataPointList.push_back( aPoint );
3343 uno::Reference< beans::XPropertySet > xPropSet;
3344 // get property states
3347 xPropSet = SchXMLSeriesHelper::createOldAPIDataPointPropertySet(
3348 xSeries, nCurrIndex, mrExport.GetModel() );
3350 catch( const uno::Exception & rEx )
3352 SAL_INFO("xmloff.chart", "Exception caught during Export of data point: " << rEx.Message );
3354 if( xPropSet.is())
3356 const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
3357 if( nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 )
3359 lcl_exportNumberFormat( "NumberFormat", xPropSet, mrExport );
3360 lcl_exportNumberFormat( "PercentageNumberFormat", xPropSet, mrExport );
3363 aPropertyStates = mxExpPropMapper->Filter( xPropSet );
3364 if( !aPropertyStates.empty() )
3366 if( bExportContent )
3368 // write data-point with style
3369 SAL_WARN_IF( maAutoStyleNameQueue.empty(), "xmloff.chart", "Autostyle queue empty!" );
3370 SchXMLDataPointStruct aPoint;
3371 aPoint.maStyleName = maAutoStyleNameQueue.front();
3372 maAutoStyleNameQueue.pop();
3374 aDataPointList.push_back( aPoint );
3375 nLastIndex = nCurrIndex;
3377 else
3379 CollectAutoStyle( aPropertyStates );
3381 continue;
3385 // if we get here the property states are empty
3386 SchXMLDataPointStruct aPoint;
3387 aDataPointList.push_back( aPoint );
3389 nLastIndex = nCurrIndex;
3391 // final empty elements
3392 nRepeat = nSeriesLength - nLastIndex - 1;
3393 if( nRepeat > 0 )
3395 SchXMLDataPointStruct aPoint;
3396 aPoint.mnRepeat = nRepeat;
3397 aDataPointList.push_back( aPoint );
3401 if (!bExportContent)
3402 return;
3404 // write elements (merge equal ones)
3405 ::std::list< SchXMLDataPointStruct >::iterator aIter = aDataPointList.begin();
3406 SchXMLDataPointStruct aPoint;
3407 SchXMLDataPointStruct aLastPoint;
3409 // initialize so that it doesn't matter if
3410 // the element is counted in the first iteration
3411 aLastPoint.mnRepeat = 0;
3413 for( ; aIter != aDataPointList.end(); ++aIter )
3415 aPoint = (*aIter);
3417 if( aPoint.maStyleName == aLastPoint.maStyleName )
3418 aPoint.mnRepeat += aLastPoint.mnRepeat;
3419 else if( aLastPoint.mnRepeat > 0 )
3421 // write last element
3422 if( !aLastPoint.maStyleName.isEmpty() )
3423 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_STYLE_NAME, aLastPoint.maStyleName );
3425 if( aLastPoint.mnRepeat > 1 )
3426 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_REPEATED,
3427 OUString::number( ( aLastPoint.mnRepeat ) ));
3429 SvXMLElementExport aPointElem( mrExport, XML_NAMESPACE_CHART, XML_DATA_POINT, true, true );
3431 aLastPoint = aPoint;
3433 // write last element if it hasn't been written in last iteration
3434 if( aPoint.maStyleName == aLastPoint.maStyleName )
3436 if( !aLastPoint.maStyleName.isEmpty() )
3437 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_STYLE_NAME, aLastPoint.maStyleName );
3439 if( aLastPoint.mnRepeat > 1 )
3440 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_REPEATED,
3441 OUString::number( ( aLastPoint.mnRepeat ) ));
3443 SvXMLElementExport aPointElem( mrExport, XML_NAMESPACE_CHART, XML_DATA_POINT, true, true );
3447 void SchXMLExportHelper_Impl::addPosition( const awt::Point & rPosition )
3449 mrExport.GetMM100UnitConverter().convertMeasureToXML(
3450 msStringBuffer, rPosition.X );
3451 msString = msStringBuffer.makeStringAndClear();
3452 mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_X, msString );
3454 mrExport.GetMM100UnitConverter().convertMeasureToXML(
3455 msStringBuffer, rPosition.Y );
3456 msString = msStringBuffer.makeStringAndClear();
3457 mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_Y, msString );
3460 void SchXMLExportHelper_Impl::addPosition( const Reference< drawing::XShape >& xShape )
3462 if( xShape.is())
3463 addPosition( xShape->getPosition());
3466 void SchXMLExportHelper_Impl::addSize( const awt::Size & rSize, bool bIsOOoNamespace)
3468 mrExport.GetMM100UnitConverter().convertMeasureToXML(
3469 msStringBuffer, rSize.Width );
3470 msString = msStringBuffer.makeStringAndClear();
3471 mrExport.AddAttribute( bIsOOoNamespace ? XML_NAMESPACE_CHART_EXT : XML_NAMESPACE_SVG , XML_WIDTH, msString );
3473 mrExport.GetMM100UnitConverter().convertMeasureToXML(
3474 msStringBuffer, rSize.Height);
3475 msString = msStringBuffer.makeStringAndClear();
3476 mrExport.AddAttribute( bIsOOoNamespace ? XML_NAMESPACE_CHART_EXT : XML_NAMESPACE_SVG, XML_HEIGHT, msString );
3479 void SchXMLExportHelper_Impl::addSize( const Reference< drawing::XShape >& xShape )
3481 if( xShape.is())
3482 addSize( xShape->getSize() );
3485 awt::Size SchXMLExportHelper_Impl::getPageSize( const Reference< chart2::XChartDocument > & xChartDoc )
3487 awt::Size aSize( 8000, 7000 );
3488 uno::Reference< embed::XVisualObject > xVisualObject( xChartDoc, uno::UNO_QUERY );
3489 SAL_WARN_IF( !xVisualObject.is(), "xmloff.chart", "need XVisualObject for page size" );
3490 if( xVisualObject.is() )
3491 aSize = xVisualObject->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );
3493 return aSize;
3496 void SchXMLExportHelper_Impl::CollectAutoStyle( const std::vector< XMLPropertyState >& aStates )
3498 if( !aStates.empty() )
3499 maAutoStyleNameQueue.push( GetAutoStylePoolP().Add( XML_STYLE_FAMILY_SCH_CHART_ID, aStates ));
3502 void SchXMLExportHelper_Impl::AddAutoStyleAttribute( const std::vector< XMLPropertyState >& aStates )
3504 if( !aStates.empty() )
3506 SAL_WARN_IF( maAutoStyleNameQueue.empty(), "xmloff.chart", "Autostyle queue empty!" );
3508 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_STYLE_NAME, maAutoStyleNameQueue.front() );
3509 maAutoStyleNameQueue.pop();
3513 void SchXMLExportHelper_Impl::exportText( const OUString& rText )
3515 SchXMLTools::exportText( mrExport, rText, false/*bConvertTabsLFs*/ );
3518 // class SchXMLExport
3520 SchXMLExport::SchXMLExport(
3521 const Reference< uno::XComponentContext >& xContext,
3522 OUString const & implementationName, SvXMLExportFlags nExportFlags )
3523 : SvXMLExport( util::MeasureUnit::CM, xContext, implementationName,
3524 ::xmloff::token::XML_CHART, nExportFlags ),
3525 maAutoStylePool( new SchXMLAutoStylePoolP(*this) ),
3526 maExportHelper( new SchXMLExportHelper(*this, *maAutoStylePool.get()) )
3528 if( getDefaultVersion() > SvtSaveOptions::ODFVER_012 )
3529 GetNamespaceMap_().Add( GetXMLToken(XML_NP_CHART_EXT), GetXMLToken(XML_N_CHART_EXT), XML_NAMESPACE_CHART_EXT);
3532 SchXMLExport::~SchXMLExport()
3534 // stop progress view
3535 if( mxStatusIndicator.is())
3537 mxStatusIndicator->end();
3538 mxStatusIndicator->reset();
3542 sal_uInt32 SchXMLExport::exportDoc( enum ::xmloff::token::XMLTokenEnum eClass )
3544 maExportHelper->SetSourceShellID(GetSourceShellID());
3545 maExportHelper->SetDestinationShellID(GetDestinationShellID());
3547 Reference< chart2::XChartDocument > xChartDoc( GetModel(), uno::UNO_QUERY );
3548 maExportHelper->m_pImpl->InitRangeSegmentationProperties( xChartDoc );
3549 return SvXMLExport::exportDoc( eClass );
3552 void SchXMLExport::ExportStyles_( bool bUsed )
3554 SvXMLExport::ExportStyles_( bUsed );
3557 void SchXMLExport::ExportMasterStyles_()
3559 // not available in chart
3560 SAL_INFO("xmloff.chart", "Master Style Export requested. Not available for Chart" );
3563 void SchXMLExport::ExportAutoStyles_()
3565 // there are no styles that require their own autostyles
3566 if( getExportFlags() & SvXMLExportFlags::CONTENT )
3568 Reference< chart::XChartDocument > xChartDoc( GetModel(), uno::UNO_QUERY );
3569 if( xChartDoc.is())
3571 maExportHelper->m_pImpl->collectAutoStyles( xChartDoc );
3572 maExportHelper->m_pImpl->exportAutoStyles();
3574 else
3576 SAL_WARN("xmloff.chart", "Couldn't export chart due to wrong XModel (must be XChartDocument)" );
3581 void SchXMLExport::ExportContent_()
3583 Reference< chart::XChartDocument > xChartDoc( GetModel(), uno::UNO_QUERY );
3584 if( xChartDoc.is())
3586 // determine if data comes from the outside
3587 bool bIncludeTable = true;
3589 Reference< chart2::XChartDocument > xNewDoc( xChartDoc, uno::UNO_QUERY );
3590 if( xNewDoc.is())
3592 // check if we have own data. If so we must not export the complete
3593 // range string, as this is our only indicator for having own or
3594 // external data. @todo: fix this in the file format!
3595 Reference< lang::XServiceInfo > xDPServiceInfo( xNewDoc->getDataProvider(), uno::UNO_QUERY );
3596 if( ! (xDPServiceInfo.is() && xDPServiceInfo->getImplementationName() == "com.sun.star.comp.chart.InternalDataProvider" ))
3598 bIncludeTable = false;
3601 else
3603 Reference< lang::XServiceInfo > xServ( xChartDoc, uno::UNO_QUERY );
3604 if( xServ.is())
3606 if( xServ->supportsService( "com.sun.star.chart.ChartTableAddressSupplier" ))
3608 Reference< beans::XPropertySet > xProp( xServ, uno::UNO_QUERY );
3609 if( xProp.is())
3611 Any aAny;
3614 OUString sChartAddress;
3615 aAny = xProp->getPropertyValue( "ChartRangeAddress" );
3616 aAny >>= sChartAddress;
3617 maExportHelper->m_pImpl->SetChartRangeAddress( sChartAddress );
3619 OUString sTableNumberList;
3620 aAny = xProp->getPropertyValue( "TableNumberList" );
3621 aAny >>= sTableNumberList;
3622 maExportHelper->m_pImpl->SetTableNumberList( sTableNumberList );
3624 // do not include own table if there are external addresses
3625 bIncludeTable = sChartAddress.isEmpty();
3627 catch( const beans::UnknownPropertyException & )
3629 SAL_WARN("xmloff.chart", "Property ChartRangeAddress not supported by ChartDocument" );
3635 maExportHelper->m_pImpl->exportChart( xChartDoc, bIncludeTable );
3637 else
3639 SAL_WARN("xmloff.chart", "Couldn't export chart due to wrong XModel" );
3643 rtl::Reference< XMLPropertySetMapper > SchXMLExport::GetPropertySetMapper() const
3645 return maExportHelper->m_pImpl->GetPropertySetMapper();
3648 void SchXMLExportHelper_Impl::InitRangeSegmentationProperties( const Reference< chart2::XChartDocument > & xChartDoc )
3650 if( xChartDoc.is())
3653 Reference< chart2::data::XDataProvider > xDataProvider( xChartDoc->getDataProvider() );
3654 SAL_WARN_IF( !xDataProvider.is(), "xmloff.chart", "No DataProvider" );
3655 if( xDataProvider.is())
3657 Reference< chart2::data::XDataSource > xDataSource( lcl_pressUsedDataIntoRectangularFormat( xChartDoc, mbHasCategoryLabels ));
3658 Sequence< beans::PropertyValue > aArgs( xDataProvider->detectArguments( xDataSource ));
3659 OUString sCellRange, sBrokenRange;
3660 bool bBrokenRangeAvailable = false;
3661 for( sal_Int32 i=0; i<aArgs.getLength(); ++i )
3663 if ( aArgs[i].Name == "CellRangeRepresentation" )
3664 aArgs[i].Value >>= sCellRange;
3665 else if ( aArgs[i].Name == "BrokenCellRangeForExport" )
3667 if( aArgs[i].Value >>= sBrokenRange )
3668 bBrokenRangeAvailable = true;
3670 else if ( aArgs[i].Name == "DataRowSource" )
3672 chart::ChartDataRowSource eRowSource;
3673 aArgs[i].Value >>= eRowSource;
3674 mbRowSourceColumns = ( eRowSource == chart::ChartDataRowSource_COLUMNS );
3676 else if ( aArgs[i].Name == "FirstCellAsLabel" )
3677 aArgs[i].Value >>= mbHasSeriesLabels;
3678 else if ( aArgs[i].Name == "SequenceMapping" )
3679 aArgs[i].Value >>= maSequenceMapping;
3680 else if ( aArgs[i].Name == "TableNumberList" )
3681 aArgs[i].Value >>= msTableNumberList;
3684 // #i79009# For Writer we have to export a broken version of the
3685 // range, where every row number is noe too large, so that older
3686 // version can correctly read those files.
3687 msChartAddress = (bBrokenRangeAvailable ? sBrokenRange : sCellRange);
3688 if( !msChartAddress.isEmpty() )
3690 // convert format to XML-conform one
3691 Reference< chart2::data::XRangeXMLConversion > xConversion( xDataProvider, uno::UNO_QUERY );
3692 if( xConversion.is())
3693 msChartAddress = xConversion->convertRangeToXML( msChartAddress );
3697 catch( const uno::Exception & ex )
3699 SAL_WARN("xmloff.chart", "Exception caught. Type: " << OUString::createFromAscii( typeid( ex ).name()) << ", Message: " << ex.Message);
3703 // first version: everything goes in one storage
3705 Sequence< OUString > SAL_CALL SchXMLExport_getSupportedServiceNames() throw()
3707 return Sequence< OUString > { "com.sun.star.comp.Chart.XMLExporter" };
3710 OUString SAL_CALL SchXMLExport_getImplementationName() throw()
3712 return OUString( "SchXMLExport.Compact" );
3715 Reference< uno::XInterface > SAL_CALL SchXMLExport_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception )
3717 // #103997# removed some flags from EXPORT_ALL
3718 return static_cast<cppu::OWeakObject*>(new SchXMLExport( comphelper::getComponentContext(rSMgr), SchXMLExport_getImplementationName(), SvXMLExportFlags::ALL ^ ( SvXMLExportFlags::SETTINGS | SvXMLExportFlags::MASTERSTYLES | SvXMLExportFlags::SCRIPTS )));
3721 // Oasis format
3722 Sequence< OUString > SAL_CALL SchXMLExport_Oasis_getSupportedServiceNames() throw()
3724 return Sequence< OUString > { "com.sun.star.comp.Chart.XMLOasisExporter" };
3727 OUString SAL_CALL SchXMLExport_Oasis_getImplementationName() throw()
3729 return OUString( "SchXMLExport.Oasis.Compact" );
3732 Reference< uno::XInterface > SAL_CALL SchXMLExport_Oasis_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception )
3734 // #103997# removed some flags from EXPORT_ALL
3735 return static_cast<cppu::OWeakObject*>(new SchXMLExport( comphelper::getComponentContext(rSMgr),
3736 SchXMLExport_Oasis_getImplementationName(),
3737 (SvXMLExportFlags::ALL ^ ( SvXMLExportFlags::SETTINGS | SvXMLExportFlags::MASTERSTYLES | SvXMLExportFlags::SCRIPTS )) | SvXMLExportFlags::OASIS ));
3740 // multiple storage version: one for content / styles / meta
3742 Sequence< OUString > SAL_CALL SchXMLExport_Styles_getSupportedServiceNames() throw()
3744 return Sequence< OUString > { "com.sun.star.comp.Chart.XMLStylesExporter" };
3747 OUString SAL_CALL SchXMLExport_Styles_getImplementationName() throw()
3749 return OUString( "SchXMLExport.Styles" );
3752 Reference< uno::XInterface > SAL_CALL SchXMLExport_Styles_createInstance(const Reference< lang::XMultiServiceFactory >& rSMgr) throw( uno::Exception )
3754 return static_cast<cppu::OWeakObject*>(new SchXMLExport( comphelper::getComponentContext(rSMgr), SchXMLExport_Styles_getImplementationName(), SvXMLExportFlags::STYLES ));
3757 // Oasis format
3758 Sequence< OUString > SAL_CALL SchXMLExport_Oasis_Styles_getSupportedServiceNames() throw()
3760 return Sequence< OUString > { "com.sun.star.comp.Chart.XMLOasisStylesExporter" };
3763 OUString SAL_CALL SchXMLExport_Oasis_Styles_getImplementationName() throw()
3765 return OUString( "SchXMLExport.Oasis.Styles" );
3768 Reference< uno::XInterface > SAL_CALL SchXMLExport_Oasis_Styles_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception )
3770 return static_cast<cppu::OWeakObject*>(new SchXMLExport( comphelper::getComponentContext(rSMgr), SchXMLExport_Oasis_Styles_getImplementationName(), SvXMLExportFlags::STYLES | SvXMLExportFlags::OASIS ));
3773 Sequence< OUString > SAL_CALL SchXMLExport_Content_getSupportedServiceNames() throw()
3775 return Sequence< OUString > { "com.sun.star.comp.Chart.XMLContentExporter" };
3778 OUString SAL_CALL SchXMLExport_Content_getImplementationName() throw()
3780 return OUString( "SchXMLExport.Content" );
3783 Reference< uno::XInterface > SAL_CALL SchXMLExport_Content_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception )
3785 return static_cast<cppu::OWeakObject*>(new SchXMLExport( comphelper::getComponentContext(rSMgr), SchXMLExport_Content_getImplementationName(), SvXMLExportFlags::AUTOSTYLES | SvXMLExportFlags::CONTENT | SvXMLExportFlags::FONTDECLS ));
3788 // Oasis format
3789 Sequence< OUString > SAL_CALL SchXMLExport_Oasis_Content_getSupportedServiceNames() throw()
3791 return Sequence< OUString > { "com.sun.star.comp.Chart.XMLOasisContentExporter" };
3794 OUString SAL_CALL SchXMLExport_Oasis_Content_getImplementationName() throw()
3796 return OUString( "SchXMLExport.Oasis.Content" );
3799 Reference< uno::XInterface > SAL_CALL SchXMLExport_Oasis_Content_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception )
3801 return static_cast<cppu::OWeakObject*>(new SchXMLExport( comphelper::getComponentContext(rSMgr), SchXMLExport_Oasis_Content_getImplementationName(), SvXMLExportFlags::AUTOSTYLES | SvXMLExportFlags::CONTENT | SvXMLExportFlags::FONTDECLS | SvXMLExportFlags::OASIS ));
3804 // Oasis format
3805 Sequence< OUString > SAL_CALL SchXMLExport_Oasis_Meta_getSupportedServiceNames() throw()
3807 return Sequence< OUString > { "com.sun.star.comp.Chart.XMLOasisMetaExporter" };
3810 OUString SAL_CALL SchXMLExport_Oasis_Meta_getImplementationName() throw()
3812 return OUString( "SchXMLExport.Oasis.Meta" );
3815 Reference< uno::XInterface > SAL_CALL SchXMLExport_Oasis_Meta_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception )
3817 return static_cast<cppu::OWeakObject*>(new SchXMLExport( comphelper::getComponentContext(rSMgr), SchXMLExport_Oasis_Meta_getImplementationName(), SvXMLExportFlags::META | SvXMLExportFlags::OASIS ));
3820 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */