bump product version to 4.1.6.2
[LibreOffice.git] / xmloff / source / chart / SchXMLExport.cxx
blob8cd6416a6ea31e78db5417f51632ed2aaf7201ec
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 .
21 #include <sax/tools/converter.hxx>
23 #include <xmloff/xmlprmap.hxx>
25 #include "SchXMLExport.hxx"
26 #include "XMLChartPropertySetMapper.hxx"
27 #include "ColorPropertySet.hxx"
28 #include "SchXMLTools.hxx"
29 #include "SchXMLEnumConverter.hxx"
31 #include <tools/debug.hxx>
32 #include <rtl/logfile.hxx>
33 #include <comphelper/processfactory.hxx>
34 #include <tools/globname.hxx>
35 #include <comphelper/classids.hxx>
37 #include <xmloff/nmspmap.hxx>
38 #include "xmloff/xmlnmspe.hxx"
39 #include <xmloff/xmltoken.hxx>
40 #include <xmloff/families.hxx>
41 #include <xmloff/xmlaustp.hxx>
42 #include <xmloff/xmluconv.hxx>
43 #include <xmloff/xmlmetae.hxx>
44 #include <xmloff/SchXMLSeriesHelper.hxx>
45 #include "xexptran.hxx"
46 #include <rtl/math.hxx>
47 // header for any2enum
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/XServiceInfo.hpp>
56 #include <com/sun/star/lang/XServiceName.hpp>
57 #include <com/sun/star/beans/XPropertySet.hpp>
58 #include <com/sun/star/uno/XComponentContext.hpp>
59 #include <com/sun/star/util/XRefreshable.hpp>
61 #include <com/sun/star/chart/XAxis.hpp>
62 #include <com/sun/star/chart/XAxisSupplier.hpp>
63 #include <com/sun/star/chart/XChartDocument.hpp>
64 #include <com/sun/star/chart/ChartLegendPosition.hpp>
65 #include <com/sun/star/chart/ChartLegendExpansion.hpp>
66 #include <com/sun/star/chart/ChartDataRowSource.hpp>
67 #include <com/sun/star/chart/ChartAxisAssign.hpp>
68 #include <com/sun/star/chart/ChartAxisType.hpp>
69 #include <com/sun/star/chart/TimeIncrement.hpp>
70 #include <com/sun/star/chart/TimeInterval.hpp>
71 #include <com/sun/star/chart/TimeUnit.hpp>
72 #include <com/sun/star/chart/ChartSeriesAddress.hpp>
73 #include <com/sun/star/chart/X3DDisplay.hpp>
74 #include <com/sun/star/chart/XStatisticDisplay.hpp>
75 #include <com/sun/star/chart/XSecondAxisTitleSupplier.hpp>
76 #include <com/sun/star/chart/XDiagramPositioning.hpp>
78 #include <com/sun/star/chart2/XAnyDescriptionAccess.hpp>
79 #include <com/sun/star/chart2/AxisType.hpp>
80 #include <com/sun/star/chart2/XChartDocument.hpp>
81 #include <com/sun/star/chart2/XDiagram.hpp>
82 #include <com/sun/star/chart2/RelativePosition.hpp>
83 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
84 #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
85 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
86 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
87 #include <com/sun/star/chart2/data/XDataSource.hpp>
88 #include <com/sun/star/chart2/data/XDataSink.hpp>
89 #include <com/sun/star/chart2/data/XDataReceiver.hpp>
90 #include <com/sun/star/chart2/data/XDataProvider.hpp>
91 #include <com/sun/star/chart2/data/XDatabaseDataProvider.hpp>
92 #include <com/sun/star/chart2/data/XRangeXMLConversion.hpp>
93 #include <com/sun/star/chart2/data/XTextualDataSequence.hpp>
94 #include <com/sun/star/chart2/data/XNumericalDataSequence.hpp>
96 #include <com/sun/star/util/MeasureUnit.hpp>
97 #include <com/sun/star/util/XStringMapping.hpp>
98 #include <com/sun/star/drawing/HomogenMatrix.hpp>
99 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
100 #include <com/sun/star/drawing/XShapes.hpp>
101 #include <com/sun/star/embed/Aspects.hpp>
102 #include <com/sun/star/embed/XVisualObject.hpp>
103 #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 // ========================================
119 // class SchXMLExportHelper_Impl
120 // ========================================
122 class SchXMLExportHelper_Impl
124 public:
125 // first: data sequence for label, second: data sequence for values.
126 typedef ::std::pair< ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataSequence >,
127 ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataSequence > > tLabelValuesDataPair;
128 typedef ::std::vector< tLabelValuesDataPair > tDataSequenceCont;
130 public:
131 SchXMLExportHelper_Impl( SvXMLExport& rExport,
132 SvXMLAutoStylePoolP& rASPool );
134 virtual ~SchXMLExportHelper_Impl();
136 // auto-styles
137 /// parse chart and collect all auto-styles used in current pool
138 void collectAutoStyles( com::sun::star::uno::Reference<
139 com::sun::star::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 ist the outer element of a chart. So these attributes can easily
153 be parsed again by the container
155 void exportChart( com::sun::star::uno::Reference<
156 com::sun::star::chart::XChartDocument > rChartDoc,
157 sal_Bool bIncludeTable );
159 UniReference< XMLPropertySetMapper > GetPropertySetMapper() const;
161 void SetChartRangeAddress( const OUString& rAddress )
162 { msChartAddress = rAddress; }
163 void SetTableNumberList( const OUString& rList )
164 { msTableNumberList = rList; }
166 void InitRangeSegmentationProperties(
167 const ::com::sun::star::uno::Reference<
168 ::com::sun::star::chart2::XChartDocument > & xChartDoc );
170 ::com::sun::star::awt::Size getPageSize(
171 const ::com::sun::star::uno::Reference<
172 ::com::sun::star::chart2::XChartDocument > & xChartDoc ) const;
174 /** first parseDocument: collect autostyles and store names in this queue
175 second parseDocument: export content and use names from this queue
177 ::std::queue< OUString > maAutoStyleNameQueue;
178 void CollectAutoStyle(
179 const std::vector< XMLPropertyState >& aStates );
180 void AddAutoStyleAttribute(
181 const std::vector< XMLPropertyState >& aStates );
183 SvXMLAutoStylePoolP& GetAutoStylePoolP()
184 { return mrAutoStylePool; }
186 /// if bExportContent is false the auto-styles are collected
187 void parseDocument( com::sun::star::uno::Reference<
188 com::sun::star::chart::XChartDocument >& rChartDoc,
189 sal_Bool bExportContent,
190 sal_Bool bIncludeTable = sal_False );
191 void exportTable();
192 void exportPlotArea(
193 com::sun::star::uno::Reference< com::sun::star::chart::XDiagram > xDiagram,
194 com::sun::star::uno::Reference< com::sun::star::chart2::XDiagram > xNewDiagram,
195 const ::com::sun::star::awt::Size & rPageSize,
196 sal_Bool bExportContent,
197 sal_Bool bIncludeTable );
198 void exportCoordinateRegion( const com::sun::star::uno::Reference< com::sun::star::chart::XDiagram >& xDiagram );
199 void exportAxes( const com::sun::star::uno::Reference< com::sun::star::chart::XDiagram > & xDiagram,
200 const com::sun::star::uno::Reference< com::sun::star::chart2::XDiagram > & xNewDiagram,
201 sal_Bool bExportContent );
202 void exportAxis( enum XMLTokenEnum eDimension, enum XMLTokenEnum eAxisName,
203 const Reference< beans::XPropertySet > xAxisProps, const Reference< chart2::XAxis >& xChart2Axis,
204 const OUString& rCategoriesRanges,
205 bool bHasTitle, bool bHasMajorGrid, bool bHasMinorGrid, bool bExportContent );
206 void exportGrid( const Reference< beans::XPropertySet > xGridProperties, bool bMajor, bool bExportContent );
207 void exportDateScale( const Reference< beans::XPropertySet > xAxisProps );
208 void exportAxisTitle( const Reference< beans::XPropertySet > xTitleProps, bool bExportContent );
210 void exportSeries(
211 const com::sun::star::uno::Reference< com::sun::star::chart2::XDiagram > & xNewDiagram,
212 const ::com::sun::star::awt::Size & rPageSize,
213 sal_Bool bExportContent,
214 sal_Bool bHasTwoYAxes );
215 void exportCandleStickSeries(
216 const ::com::sun::star::uno::Sequence<
217 ::com::sun::star::uno::Reference<
218 ::com::sun::star::chart2::XDataSeries > > & aSeriesSeq,
219 const ::com::sun::star::uno::Reference<
220 ::com::sun::star::chart2::XDiagram > & xDiagram,
221 sal_Bool bJapaneseCandleSticks,
222 sal_Bool bExportContent );
223 void exportDataPoints(
224 const ::com::sun::star::uno::Reference<
225 ::com::sun::star::beans::XPropertySet > & xSeriesProperties,
226 sal_Int32 nSeriesLength,
227 const ::com::sun::star::uno::Reference<
228 ::com::sun::star::chart2::XDiagram > & xDiagram,
229 sal_Bool bExportContent );
230 void exportRegressionCurve(
231 const ::com::sun::star::uno::Reference<
232 ::com::sun::star::chart2::XDataSeries > & xSeries,
233 const ::com::sun::star::uno::Reference<
234 ::com::sun::star::beans::XPropertySet > & xSeriesProp,
235 const ::com::sun::star::awt::Size & rPageSize,
236 sal_Bool bExportContent );
238 void exportErrorBar (
239 const ::com::sun::star::uno::Reference<beans::XPropertySet> &xSeriesProp, bool bYError,
240 bool bExportContent );
242 /// add svg position as attribute for current element
243 void addPosition( const ::com::sun::star::awt::Point & rPosition );
244 void addPosition( com::sun::star::uno::Reference< com::sun::star::drawing::XShape > xShape );
245 /// add svg size as attribute for current element
246 void addSize( const ::com::sun::star::awt::Size & rSize, bool bIsOOoNamespace = false );
247 void addSize( com::sun::star::uno::Reference< com::sun::star::drawing::XShape > xShape, bool bIsOOoNamespace = false );
248 /// fills the member msString with the appropriate String (i.e. "A3")
249 void getCellAddress( sal_Int32 nCol, sal_Int32 nRow );
250 /// exports a string as a paragraph element
251 void exportText( const OUString& rText, bool bConvertTabsLFs = false );
252 void exportErrorBarRanges();
254 private:
255 SchXMLExportHelper_Impl(SchXMLExportHelper_Impl &); // not defined
256 SchXMLExportHelper_Impl operator =(SchXMLExportHelper_Impl &); // not defined
258 public:
259 SvXMLExport& mrExport;
260 SvXMLAutoStylePoolP& mrAutoStylePool;
261 UniReference< XMLPropertySetMapper > mxPropertySetMapper;
262 UniReference< XMLChartExportPropertyMapper > mxExpPropMapper;
264 OUString msTableName;
265 OUStringBuffer msStringBuffer;
266 OUString msString;
268 // members filled by InitRangeSegmentationProperties (retrieved from DataProvider)
269 sal_Bool mbHasSeriesLabels;
270 sal_Bool mbHasCategoryLabels; //if the categories are only automatically generated this will be false
271 sal_Bool mbRowSourceColumns;
272 OUString msChartAddress;
273 OUString msTableNumberList;
274 ::com::sun::star::uno::Sequence< sal_Int32 > maSequenceMapping;
276 OUString msCLSID;
278 ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes > mxAdditionalShapes;
280 tDataSequenceCont m_aDataSequencesToExport;
281 OUString maCategoriesRange;
284 namespace
287 class lcl_MatchesRole : public ::std::unary_function< Reference< chart2::data::XLabeledDataSequence >, bool >
289 public:
290 explicit lcl_MatchesRole( const OUString & aRole ) :
291 m_aRole( aRole )
294 bool operator () ( const Reference< chart2::data::XLabeledDataSequence > & xSeq ) const
296 if( !xSeq.is() )
297 return false;
298 Reference< beans::XPropertySet > xProp( xSeq->getValues(), uno::UNO_QUERY );
299 OUString aRole;
301 return ( xProp.is() &&
302 (xProp->getPropertyValue(
303 OUString( "Role" ) ) >>= aRole ) &&
304 m_aRole.equals( aRole ));
307 private:
308 OUString m_aRole;
311 template< typename T >
312 void lcl_SequenceToVectorAppend( const Sequence< T > & rSource, ::std::vector< T > & rDestination )
314 rDestination.reserve( rDestination.size() + rSource.getLength());
315 ::std::copy( rSource.getConstArray(), rSource.getConstArray() + rSource.getLength(),
316 ::std::back_inserter( rDestination ));
319 template< typename T >
320 void lcl_SequenceToVector( const Sequence< T > & rSource, ::std::vector< T > & rDestination )
322 rDestination.clear();
323 lcl_SequenceToVectorAppend( rSource, rDestination );
326 Reference< chart2::data::XLabeledDataSequence > lcl_getCategories( const Reference< chart2::XDiagram > & xDiagram )
328 Reference< chart2::data::XLabeledDataSequence > xResult;
331 Reference< chart2::XCoordinateSystemContainer > xCooSysCnt(
332 xDiagram, uno::UNO_QUERY_THROW );
333 Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq(
334 xCooSysCnt->getCoordinateSystems());
335 for( sal_Int32 i=0; i<aCooSysSeq.getLength(); ++i )
337 Reference< chart2::XCoordinateSystem > xCooSys( aCooSysSeq[i] );
338 SAL_WARN_IF( !xCooSys.is(), "xmloff.chart", "xCooSys is NULL" );
339 for( sal_Int32 nN = xCooSys->getDimension(); nN--; )
341 const sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nN);
342 for(sal_Int32 nI=0; nI<=nMaxAxisIndex; ++nI)
344 Reference< chart2::XAxis > xAxis = xCooSys->getAxisByDimension( nN, nI );
345 SAL_WARN_IF( !xAxis.is(), "xmloff.chart", "xAxis is NULL");
346 if( xAxis.is())
348 chart2::ScaleData aScaleData = xAxis->getScaleData();
349 if( aScaleData.Categories.is())
351 xResult.set( aScaleData.Categories );
352 break;
359 catch( const uno::Exception & ex )
361 SAL_WARN("xmloff.chart", "Exception caught. Type: " << OUString::createFromAscii( typeid( ex ).name()) << ", Message: " << ex.Message);
364 return xResult;
367 Reference< chart2::data::XDataSource > lcl_createDataSource(
368 const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aData )
370 Reference< uno::XComponentContext > xContext(
371 comphelper::getProcessComponentContext() );
372 Reference< chart2::data::XDataSink > xSink(
373 xContext->getServiceManager()->createInstanceWithContext(
374 "com.sun.star.chart2.data.DataSource", xContext ),
375 uno::UNO_QUERY_THROW );
376 xSink->setData( aData );
378 return Reference< chart2::data::XDataSource >( xSink, uno::UNO_QUERY );
381 Sequence< Reference< chart2::data::XLabeledDataSequence > > lcl_getAllSeriesSequences( const Reference< chart2::XChartDocument >& xChartDoc )
383 ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aContainer;
384 if( xChartDoc.is() )
386 Reference< chart2::XDiagram > xDiagram( xChartDoc->getFirstDiagram());
387 ::std::vector< Reference< chart2::XDataSeries > > aSeriesVector( SchXMLSeriesHelper::getDataSeriesFromDiagram( xDiagram ));
388 for( ::std::vector< Reference< chart2::XDataSeries > >::const_iterator aSeriesIt( aSeriesVector.begin() )
389 ; aSeriesIt != aSeriesVector.end(); ++aSeriesIt )
391 Reference< chart2::data::XDataSource > xDataSource( *aSeriesIt, uno::UNO_QUERY );
392 if( !xDataSource.is() )
393 continue;
394 uno::Sequence< Reference< chart2::data::XLabeledDataSequence > > aDataSequences( xDataSource->getDataSequences() );
395 lcl_SequenceToVectorAppend( aDataSequences, aContainer );
399 Sequence< Reference< chart2::data::XLabeledDataSequence > > aRet( aContainer.size());
400 ::std::copy( aContainer.begin(), aContainer.end(), aRet.getArray());
402 return aRet;
405 Reference< chart2::data::XLabeledDataSequence >
406 lcl_getDataSequenceByRole(
407 const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aLabeledSeq,
408 const OUString & rRole )
410 Reference< chart2::data::XLabeledDataSequence > aNoResult;
412 const Reference< chart2::data::XLabeledDataSequence > * pBegin = aLabeledSeq.getConstArray();
413 const Reference< chart2::data::XLabeledDataSequence > * pEnd = pBegin + aLabeledSeq.getLength();
414 const Reference< chart2::data::XLabeledDataSequence > * pMatch =
415 ::std::find_if( pBegin, pEnd, lcl_MatchesRole( rRole ));
417 if( pMatch != pEnd )
418 return *pMatch;
420 return aNoResult;
423 Reference< chart2::data::XDataSource > lcl_pressUsedDataIntoRectangularFormat( const Reference< chart2::XChartDocument >& xChartDoc, sal_Bool& rOutSourceHasCategoryLabels )
425 ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aLabeledSeqVector;
427 //categories are always the first sequence
428 Reference< chart2::XDiagram > xDiagram( xChartDoc->getFirstDiagram());
429 Reference< chart2::data::XLabeledDataSequence > xCategories( lcl_getCategories( xDiagram ) );
430 if( xCategories.is() )
431 aLabeledSeqVector.push_back( xCategories );
432 rOutSourceHasCategoryLabels = sal_Bool(xCategories.is());
434 Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeriesSeqVector(
435 lcl_getAllSeriesSequences( xChartDoc ) );
437 //the first x-values is always the next sequence //todo ... other x-values get lost for old format
438 Reference< chart2::data::XLabeledDataSequence > xXValues(
439 lcl_getDataSequenceByRole( aSeriesSeqVector, OUString( "values-x" ) ) );
440 if( xXValues.is() )
441 aLabeledSeqVector.push_back( xXValues );
443 //add all other sequences now without x-values
444 lcl_MatchesRole aHasXValues( OUString( "values-x" ) );
445 for( sal_Int32 nN=0; nN<aSeriesSeqVector.getLength(); nN++ )
447 if( !aHasXValues( aSeriesSeqVector[nN] ) )
448 aLabeledSeqVector.push_back( aSeriesSeqVector[nN] );
451 Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeq( aLabeledSeqVector.size() );
452 ::std::copy( aLabeledSeqVector.begin(), aLabeledSeqVector.end(), aSeq.getArray() );
454 return lcl_createDataSource( aSeq );
457 bool lcl_isSeriesAttachedToFirstAxis(
458 const Reference< chart2::XDataSeries > & xDataSeries )
460 bool bResult=true;
464 sal_Int32 nAxisIndex = 0;
465 Reference< beans::XPropertySet > xProp( xDataSeries, uno::UNO_QUERY_THROW );
466 if( xProp.is() )
467 xProp->getPropertyValue( OUString( "AttachedAxisIndex" ) ) >>= nAxisIndex;
468 bResult = (0==nAxisIndex);
470 catch( const uno::Exception & ex )
472 SAL_WARN("xmloff.chart", "Exception caught. Type: " << OUString::createFromAscii( typeid( ex ).name()) << ", Message: " << ex.Message);
475 return bResult;
478 OUString lcl_ConvertRange( const OUString & rRange, const Reference< chart2::XChartDocument > & xDoc )
480 OUString aResult = rRange;
481 if( !xDoc.is() )
482 return aResult;
483 Reference< chart2::data::XRangeXMLConversion > xConversion(
484 xDoc->getDataProvider(), uno::UNO_QUERY );
485 if( xConversion.is())
486 aResult = xConversion->convertRangeToXML( rRange );
487 return aResult;
490 typedef ::std::pair< OUString, OUString > tLabelAndValueRange;
492 tLabelAndValueRange lcl_getLabelAndValueRangeByRole(
493 const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aSeqCnt,
494 const OUString & rRole,
495 const Reference< chart2::XChartDocument > & xDoc,
496 SchXMLExportHelper_Impl::tDataSequenceCont & rOutSequencesToExport )
498 tLabelAndValueRange aResult;
500 Reference< chart2::data::XLabeledDataSequence > xLabeledSeq(
501 lcl_getDataSequenceByRole( aSeqCnt, rRole ));
502 if( xLabeledSeq.is())
504 Reference< chart2::data::XDataSequence > xLabelSeq( xLabeledSeq->getLabel());
505 if( xLabelSeq.is())
506 aResult.first = lcl_ConvertRange( xLabelSeq->getSourceRangeRepresentation(), xDoc );
508 Reference< chart2::data::XDataSequence > xValueSeq( xLabeledSeq->getValues());
509 if( xValueSeq.is())
510 aResult.second = lcl_ConvertRange( xValueSeq->getSourceRangeRepresentation(), xDoc );
512 if( xLabelSeq.is() || xValueSeq.is())
513 rOutSequencesToExport.push_back( SchXMLExportHelper_Impl::tLabelValuesDataPair( xLabelSeq, xValueSeq ));
516 return aResult;
519 sal_Int32 lcl_getSequenceLengthByRole(
520 const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aSeqCnt,
521 const OUString & rRole )
523 Reference< chart2::data::XLabeledDataSequence > xLabeledSeq(
524 lcl_getDataSequenceByRole( aSeqCnt, rRole ));
525 if( xLabeledSeq.is())
527 Reference< chart2::data::XDataSequence > xSeq( xLabeledSeq->getValues());
528 return xSeq->getData().getLength();
530 return 0;
533 OUString lcl_flattenStringSequence( const Sequence< OUString > & rSequence )
535 OUStringBuffer aResult;
536 bool bPrecedeWithSpace = false;
537 for( sal_Int32 nIndex=0; nIndex<rSequence.getLength(); ++nIndex )
539 if( !rSequence[nIndex].isEmpty())
541 if( bPrecedeWithSpace )
542 aResult.append( static_cast< sal_Unicode >( ' ' ));
543 aResult.append( rSequence[nIndex] );
544 bPrecedeWithSpace = true;
547 return aResult.makeStringAndClear();
550 void lcl_getLabelStringSequence( Sequence< OUString >& rOutLabels, const Reference< chart2::data::XDataSequence > & xLabelSeq )
552 uno::Reference< chart2::data::XTextualDataSequence > xTextualDataSequence( xLabelSeq, uno::UNO_QUERY );
553 if( xTextualDataSequence.is())
555 rOutLabels = xTextualDataSequence->getTextualData();
557 else if( xLabelSeq.is())
559 Sequence< uno::Any > aAnies( xLabelSeq->getData());
560 rOutLabels.realloc( aAnies.getLength());
561 for( sal_Int32 i=0; i<aAnies.getLength(); ++i )
562 aAnies[i] >>= rOutLabels[i];
566 sal_Int32 lcl_getMaxSequenceLength(
567 const SchXMLExportHelper_Impl::tDataSequenceCont & rContainer )
569 sal_Int32 nResult = 0;
570 for( SchXMLExportHelper_Impl::tDataSequenceCont::const_iterator aIt( rContainer.begin());
571 aIt != rContainer.end(); ++aIt )
573 if( aIt->second.is())
575 sal_Int32 nSeqLength = aIt->second->getData().getLength();
576 if( nSeqLength > nResult )
577 nResult = nSeqLength;
580 return nResult;
583 uno::Sequence< OUString > lcl_DataSequenceToStringSequence(
584 const uno::Reference< chart2::data::XDataSequence >& xDataSequence )
586 uno::Sequence< OUString > aResult;
587 if(!xDataSequence.is())
588 return aResult;
590 uno::Reference< chart2::data::XTextualDataSequence > xTextualDataSequence( xDataSequence, uno::UNO_QUERY );
591 if( xTextualDataSequence.is() )
593 aResult = xTextualDataSequence->getTextualData();
595 else
597 uno::Sequence< uno::Any > aValues = xDataSequence->getData();
598 aResult.realloc(aValues.getLength());
600 for(sal_Int32 nN=aValues.getLength();nN--;)
601 aValues[nN] >>= aResult[nN];
604 return aResult;
606 ::std::vector< double > lcl_getAllValuesFromSequence( const Reference< chart2::data::XDataSequence > & xSeq )
608 double fNan = 0.0;
609 ::rtl::math::setNan( &fNan );
610 ::std::vector< double > aResult;
611 if(!xSeq.is())
612 return aResult;
614 uno::Sequence< double > aValuesSequence;
615 Reference< chart2::data::XNumericalDataSequence > xNumSeq( xSeq, uno::UNO_QUERY );
616 if( xNumSeq.is() )
618 aValuesSequence = xNumSeq->getNumericalData();
620 else
622 Sequence< uno::Any > aAnies( xSeq->getData() );
623 aValuesSequence.realloc( aAnies.getLength() );
624 for( sal_Int32 i=0; i<aAnies.getLength(); ++i )
625 aAnies[i] >>= aValuesSequence[i];
628 //special handling for x-values (if x-values do point to categories, indices are used instead )
629 Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY );
630 if( xProp.is() )
632 OUString aRole;
633 xProp->getPropertyValue( OUString( "Role" ) ) >>= aRole;
634 if( aRole.match( OUString( "values-x" ) ) )
636 //lcl_clearIfNoValuesButTextIsContained - replace by indices if the values are not appropriate
637 bool bHasValue=false;
638 bool bHasText=false;
639 sal_Int32 nCount = aValuesSequence.getLength();
640 for( sal_Int32 j = 0; j < nCount; ++j )
642 if( !::rtl::math::isNan( aValuesSequence[j] ) )
644 bHasValue=true;
645 break;
648 if(!bHasValue)
650 //no double value is countained
651 //is there any text?
652 uno::Sequence< OUString > aStrings( lcl_DataSequenceToStringSequence( xSeq ) );
653 sal_Int32 nTextCount = aStrings.getLength();
654 for( sal_Int32 j = 0; j < nTextCount; ++j )
656 if( !aStrings[j].isEmpty() )
658 bHasText=true;
659 break;
663 if( !bHasValue && bHasText )
665 for( sal_Int32 j = 0; j < nCount; ++j )
666 aValuesSequence[j] = j+1;
671 ::std::copy( aValuesSequence.getConstArray(), aValuesSequence.getConstArray() + aValuesSequence.getLength(),
672 ::std::back_inserter( aResult ));
673 return aResult;
676 bool lcl_SequenceHasUnhiddenData( const uno::Reference< chart2::data::XDataSequence >& xDataSequence )
678 if( !xDataSequence.is() )
679 return false;
680 uno::Reference< beans::XPropertySet > xProp( xDataSequence, uno::UNO_QUERY );
681 if( xProp.is() )
683 uno::Sequence< sal_Int32 > aHiddenValues;
686 xProp->getPropertyValue( OUString( "HiddenValues" ) ) >>= aHiddenValues;
687 if( !aHiddenValues.getLength() )
688 return true;
690 catch( const uno::Exception& )
692 return true;
695 if( xDataSequence->getData().getLength() )
696 return true;
697 return false;
700 typedef vector< OUString > tStringVector;
701 typedef vector< double > tDoubleVector;
702 typedef vector< vector< OUString > > t2DStringVector;
703 typedef vector< vector< double > > t2DNumberContainer;
705 struct lcl_TableData
707 t2DNumberContainer aDataInRows;
708 tStringVector aDataRangeRepresentations;
710 tStringVector aColumnDescriptions;
711 tStringVector aColumnDescriptions_Ranges;
713 tStringVector aRowDescriptions;
714 tStringVector aRowDescriptions_Ranges;
716 Sequence< Sequence< uno::Any > > aComplexColumnDescriptions;//outer index is columns - inner index is level
717 Sequence< Sequence< uno::Any > > aComplexRowDescriptions;//outer index is rows - inner index is level
719 ::std::vector< sal_Int32 > aHiddenColumns;
722 // ::std::bind2nd( ::std::mem_fun_ref( &T::resize ), nSize ) does not work
723 template< class T >
724 struct lcl_resize
726 lcl_resize( typename T::size_type nSize, typename T::value_type fDefaultValue ) : m_nSize( nSize ), m_fDefaultValue( fDefaultValue ) {}
727 void operator()( T & t )
728 { t.resize( m_nSize, m_fDefaultValue ); }
729 private:
730 typename T::size_type m_nSize;
731 typename T::value_type m_fDefaultValue;
735 typedef ::std::map< sal_Int32, SchXMLExportHelper_Impl::tLabelValuesDataPair >
736 lcl_DataSequenceMap;
738 struct lcl_SequenceToMapElement :
739 public ::std::unary_function< lcl_DataSequenceMap::mapped_type, lcl_DataSequenceMap::value_type >
741 lcl_SequenceToMapElement()
743 result_type operator() ( const argument_type & rContent )
745 sal_Int32 nIndex = -1;
746 if( rContent.second.is()) //has values
748 OUString aRangeRep( rContent.second->getSourceRangeRepresentation());
749 nIndex = aRangeRep.toInt32();
751 else if( rContent.first.is()) //has labels
752 nIndex = rContent.first->getSourceRangeRepresentation().copy( sizeof("label ")).toInt32();
753 return result_type( nIndex, rContent );
757 void lcl_ReorderInternalSequencesAccordingToTheirRangeName(
758 SchXMLExportHelper_Impl::tDataSequenceCont & rInOutSequences )
760 lcl_DataSequenceMap aIndexSequenceMap;
761 ::std::transform( rInOutSequences.begin(), rInOutSequences.end(),
762 ::std::inserter( aIndexSequenceMap, aIndexSequenceMap.begin()),
763 lcl_SequenceToMapElement());
765 rInOutSequences.clear();
766 sal_Int32 nIndex = 0;
767 for( lcl_DataSequenceMap::const_iterator aIt = aIndexSequenceMap.begin();
768 aIt != aIndexSequenceMap.end(); ++aIt, ++nIndex )
770 if( aIt->first < 0 )
771 continue;
772 // fill empty columns
773 for( ; nIndex < aIt->first; ++nIndex )
774 rInOutSequences.push_back(
775 SchXMLExportHelper_Impl::tDataSequenceCont::value_type(
776 (uno::Reference< chart2::data::XDataSequence >)0,
777 (uno::Reference< chart2::data::XDataSequence >)0 ));
778 OSL_ASSERT( nIndex == aIt->first );
779 rInOutSequences.push_back( aIt->second );
784 lcl_TableData lcl_getDataForLocalTable(
785 const SchXMLExportHelper_Impl::tDataSequenceCont & aSequencesToExport,
786 const Reference< chart2::XAnyDescriptionAccess >& xAnyDescriptionAccess,
787 const OUString& rCategoriesRange,
788 bool bSeriesFromColumns,
789 const Reference< chart2::data::XRangeXMLConversion > & xRangeConversion )
791 lcl_TableData aResult;
795 Sequence< OUString > aSimpleCategories;
796 if( xAnyDescriptionAccess.is() )
798 //categories
799 if( bSeriesFromColumns )
801 aSimpleCategories = xAnyDescriptionAccess->getRowDescriptions();
802 aResult.aComplexRowDescriptions = xAnyDescriptionAccess->getAnyRowDescriptions();
804 else
806 aSimpleCategories = xAnyDescriptionAccess->getColumnDescriptions();
807 aResult.aComplexColumnDescriptions = xAnyDescriptionAccess->getAnyColumnDescriptions();
811 //series values and series labels
812 SchXMLExportHelper_Impl::tDataSequenceCont::size_type nNumSequences = aSequencesToExport.size();
813 SchXMLExportHelper_Impl::tDataSequenceCont::const_iterator aBegin( aSequencesToExport.begin());
814 SchXMLExportHelper_Impl::tDataSequenceCont::const_iterator aEnd( aSequencesToExport.end());
815 SchXMLExportHelper_Impl::tDataSequenceCont::const_iterator aIt( aBegin );
817 size_t nMaxSequenceLength( lcl_getMaxSequenceLength( aSequencesToExport ));
818 size_t nCategoriesLength( aSimpleCategories.getLength() );
819 if( nCategoriesLength > nMaxSequenceLength )
821 aSimpleCategories.realloc(nMaxSequenceLength);//#i110617#
822 nCategoriesLength = nMaxSequenceLength;
824 size_t nNumColumns( bSeriesFromColumns ? nNumSequences : nMaxSequenceLength );
825 size_t nNumRows( bSeriesFromColumns ? nMaxSequenceLength : nNumSequences );
827 // resize data
828 aResult.aDataInRows.resize( nNumRows );
829 double fNan = 0.0;
830 ::rtl::math::setNan( &fNan );
831 ::std::for_each( aResult.aDataInRows.begin(), aResult.aDataInRows.end(),
832 lcl_resize< t2DNumberContainer::value_type >( nNumColumns, fNan ));
833 aResult.aColumnDescriptions.resize( nNumColumns );
834 aResult.aComplexColumnDescriptions.realloc( nNumColumns );
835 aResult.aRowDescriptions.resize( nNumRows );
836 aResult.aComplexRowDescriptions.realloc( nNumRows );
838 tStringVector& rCategories = bSeriesFromColumns ? aResult.aRowDescriptions : aResult.aColumnDescriptions;
839 tStringVector& rLabels = bSeriesFromColumns ? aResult.aColumnDescriptions : aResult.aRowDescriptions;
841 //categories
842 lcl_SequenceToVector( aSimpleCategories, rCategories );
843 if( !rCategoriesRange.isEmpty() )
845 OUString aRange(rCategoriesRange);
846 if( xRangeConversion.is())
847 aRange = xRangeConversion->convertRangeToXML( aRange );
848 if( bSeriesFromColumns )
849 aResult.aRowDescriptions_Ranges.push_back( aRange );
850 else
851 aResult.aColumnDescriptions_Ranges.push_back( aRange );
854 // iterate over all sequences
855 size_t nSeqIdx = 0;
856 Sequence< Sequence< OUString > > aComplexLabels(nNumSequences);
857 for( ; aIt != aEnd; ++aIt, ++nSeqIdx )
859 OUString aRange;
860 Sequence< OUString >& rCurrentComplexLabel = aComplexLabels[nSeqIdx];
861 if( aIt->first.is())
863 lcl_getLabelStringSequence( rCurrentComplexLabel, aIt->first );
864 rLabels[nSeqIdx] = lcl_flattenStringSequence( rCurrentComplexLabel );
865 aRange = aIt->first->getSourceRangeRepresentation();
866 if( xRangeConversion.is())
867 aRange = xRangeConversion->convertRangeToXML( aRange );
869 else if( aIt->second.is())
871 rCurrentComplexLabel.realloc(1);
872 rLabels[nSeqIdx] = rCurrentComplexLabel[0] = lcl_flattenStringSequence(
873 aIt->second->generateLabel( chart2::data::LabelOrigin_SHORT_SIDE ));
875 if( bSeriesFromColumns )
876 aResult.aColumnDescriptions_Ranges.push_back( aRange );
877 else
878 aResult.aRowDescriptions_Ranges.push_back( aRange );
880 ::std::vector< double > aNumbers( lcl_getAllValuesFromSequence( aIt->second ));
881 if( bSeriesFromColumns )
883 const sal_Int32 nSize( static_cast< sal_Int32 >( aNumbers.size()));
884 for( sal_Int32 nIdx=0; nIdx<nSize; ++nIdx )
885 aResult.aDataInRows[nIdx][nSeqIdx] = aNumbers[nIdx];
887 else
888 aResult.aDataInRows[nSeqIdx] = aNumbers;
890 if( aIt->second.is())
892 aRange = aIt->second->getSourceRangeRepresentation();
893 if( xRangeConversion.is())
894 aRange = xRangeConversion->convertRangeToXML( aRange );
896 aResult.aDataRangeRepresentations.push_back( aRange );
898 //is column hidden?
899 if( !lcl_SequenceHasUnhiddenData(aIt->first) && !lcl_SequenceHasUnhiddenData(aIt->second) )
900 aResult.aHiddenColumns.push_back(nSeqIdx);
902 Sequence< Sequence< Any > >& rComplexAnyLabels = bSeriesFromColumns ? aResult.aComplexColumnDescriptions : aResult.aComplexRowDescriptions;//#i116544#
903 rComplexAnyLabels.realloc(aComplexLabels.getLength());
904 for( sal_Int32 nN=0; nN<aComplexLabels.getLength();nN++ )
906 Sequence< OUString >& rSource = aComplexLabels[nN];
907 Sequence< Any >& rTarget = rComplexAnyLabels[nN];
908 rTarget.realloc( rSource.getLength() );
909 for( sal_Int32 i=0; i<rSource.getLength(); i++ )
910 rTarget[i] = uno::makeAny( rSource[i] );
913 catch( const uno::Exception & rEx )
915 SAL_INFO("xmloff.chart", "something went wrong during table data collection: " << rEx.Message);
918 return aResult;
921 void lcl_exportNumberFormat( const OUString& rPropertyName, const Reference< beans::XPropertySet >& xPropSet,
922 SvXMLExport& rExport )
924 if( xPropSet.is())
926 sal_Int32 nNumberFormat = 0;
927 Any aNumAny = xPropSet->getPropertyValue( rPropertyName );
928 if( (aNumAny >>= nNumberFormat) && (nNumberFormat != -1) )
929 rExport.addDataStyle( nNumberFormat );
933 ::std::vector< Reference< chart2::data::XDataSequence > >
934 lcl_getErrorBarSequences( const Reference< beans::XPropertySet > & xErrorBarProp )
936 ::std::vector< Reference< chart2::data::XDataSequence > > aResult;
937 Reference< chart2::data::XDataSource > xErrorBarDataSource( xErrorBarProp, uno::UNO_QUERY );
938 if( !xErrorBarDataSource.is())
939 return aResult;
941 const OUString aRolePrefix( "error-bars-" );
943 Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences(
944 xErrorBarDataSource->getDataSequences());
945 for( sal_Int32 nI=0; nI< aSequences.getLength(); ++nI )
949 if( aSequences[nI].is())
951 Reference< chart2::data::XDataSequence > xSequence( aSequences[nI]->getValues());
952 Reference< beans::XPropertySet > xSeqProp( xSequence, uno::UNO_QUERY_THROW );
953 OUString aRole;
954 if( ( xSeqProp->getPropertyValue(
955 OUString( "Role" )) >>= aRole ) &&
956 aRole.match( aRolePrefix ))
958 aResult.push_back( xSequence );
962 catch( const uno::Exception & rEx )
964 OString aBStr(OUStringToOString(rEx.Message, RTL_TEXTENCODING_ASCII_US));
965 SAL_INFO("xmloff.chart", "chart:exporting error bar ranges: " << aBStr );
969 return aResult;
972 bool lcl_exportDomainForThisSequence( const Reference< chart2::data::XDataSequence > xValues, OUString& rFirstRangeForThisDomainIndex, SvXMLExport& rExport )
974 bool bDomainExported = false;
975 if( xValues.is())
977 Reference< chart2::XChartDocument > xNewDoc( rExport.GetModel(), uno::UNO_QUERY );
978 OUString aRange( lcl_ConvertRange( xValues->getSourceRangeRepresentation(), xNewDoc ) );
980 //work around error in OOo 2.0 (problems with multiple series having a domain element)
981 if( rFirstRangeForThisDomainIndex.isEmpty() || !aRange.equals(rFirstRangeForThisDomainIndex) )
983 rExport.AddAttribute( XML_NAMESPACE_TABLE, XML_CELL_RANGE_ADDRESS, aRange);
984 SvXMLElementExport aDomain( rExport, XML_NAMESPACE_CHART, XML_DOMAIN, sal_True, sal_True );
985 bDomainExported = true;
988 if( rFirstRangeForThisDomainIndex.isEmpty() )
989 rFirstRangeForThisDomainIndex = aRange;
991 return bDomainExported;
994 } // anonymous namespace
996 struct SchXMLDataPointStruct
998 OUString maStyleName;
999 sal_Int32 mnRepeat;
1001 SchXMLDataPointStruct() : mnRepeat( 1 ) {}
1004 // ========================================
1005 // class SchXMLExportHelper
1006 // ========================================
1008 SchXMLExportHelper::SchXMLExportHelper( SvXMLExport& rExport, SvXMLAutoStylePoolP& rASPool )
1009 : m_pImpl( new SchXMLExportHelper_Impl( rExport, rASPool ) )
1013 SchXMLExportHelper::~SchXMLExportHelper()
1015 delete m_pImpl;
1018 const OUString& SchXMLExportHelper::getChartCLSID()
1020 return m_pImpl->msCLSID;
1023 UniReference< XMLPropertySetMapper > SchXMLExportHelper_Impl::GetPropertySetMapper() const
1025 return mxPropertySetMapper;
1028 void SchXMLExportHelper_Impl::exportAutoStyles()
1030 if( mxExpPropMapper.is())
1032 //ToDo: when embedded in calc/writer this is not necessary because the
1033 // numberformatter is shared between both documents
1034 mrExport.exportAutoDataStyles();
1036 // export chart auto styles
1037 mrAutoStylePool.exportXML(
1038 XML_STYLE_FAMILY_SCH_CHART_ID
1039 , mrExport.GetDocHandler(),
1040 mrExport.GetMM100UnitConverter(),
1041 mrExport.GetNamespaceMap()
1044 // export auto styles for additional shapes
1045 mrExport.GetShapeExport()->exportAutoStyles();
1046 // and for text in additional shapes
1047 mrExport.GetTextParagraphExport()->exportTextAutoStyles();
1051 // private methods
1052 // ---------------
1054 SchXMLExportHelper_Impl::SchXMLExportHelper_Impl(
1055 SvXMLExport& rExport,
1056 SvXMLAutoStylePoolP& rASPool ) :
1057 mrExport( rExport ),
1058 mrAutoStylePool( rASPool ),
1059 mbHasSeriesLabels( sal_False ),
1060 mbHasCategoryLabels( sal_False ),
1061 mbRowSourceColumns( sal_True ),
1062 msCLSID( OUString( SvGlobalName( SO3_SCH_CLASSID ).GetHexName()))
1064 msTableName = OUString( "local-table" );
1066 // create property set mapper
1067 mxPropertySetMapper = new XMLChartPropertySetMapper( true);
1068 mxExpPropMapper = new XMLChartExportPropertyMapper( mxPropertySetMapper, rExport );
1070 // register chart auto-style family
1071 mrAutoStylePool.AddFamily(
1072 XML_STYLE_FAMILY_SCH_CHART_ID,
1073 OUString( XML_STYLE_FAMILY_SCH_CHART_NAME ),
1074 mxExpPropMapper.get(),
1075 OUString( XML_STYLE_FAMILY_SCH_CHART_PREFIX ));
1077 // register shape family
1078 mrAutoStylePool.AddFamily(
1079 XML_STYLE_FAMILY_SD_GRAPHICS_ID,
1080 OUString( XML_STYLE_FAMILY_SD_GRAPHICS_NAME ),
1081 mxExpPropMapper.get(),
1082 OUString( XML_STYLE_FAMILY_SD_GRAPHICS_PREFIX ));
1083 // register paragraph family also for shapes
1084 mrAutoStylePool.AddFamily(
1085 XML_STYLE_FAMILY_TEXT_PARAGRAPH,
1086 GetXMLToken( XML_PARAGRAPH ),
1087 mxExpPropMapper.get(),
1088 OUString( 'P' ));
1089 // register text family also for shapes
1090 mrAutoStylePool.AddFamily(
1091 XML_STYLE_FAMILY_TEXT_TEXT,
1092 GetXMLToken( XML_TEXT ),
1093 mxExpPropMapper.get(),
1094 OUString( 'T' ));
1097 SchXMLExportHelper_Impl::~SchXMLExportHelper_Impl()
1101 void SchXMLExportHelper_Impl::collectAutoStyles( Reference< chart::XChartDocument > rChartDoc )
1103 parseDocument( rChartDoc, sal_False );
1106 void SchXMLExportHelper_Impl::exportChart( Reference< chart::XChartDocument > rChartDoc,
1107 sal_Bool bIncludeTable )
1109 parseDocument( rChartDoc, sal_True, bIncludeTable );
1110 SAL_WARN_IF( !maAutoStyleNameQueue.empty(), "xmloff.chart", "There are still remaining autostyle names in the queue" );
1113 static OUString lcl_GetStringFromNumberSequence( const ::com::sun::star::uno::Sequence< sal_Int32 >& rSequenceMapping, bool bRemoveOneFromEachIndex /*should be true if having categories*/ )
1115 const sal_Int32* pArray = rSequenceMapping.getConstArray();
1116 const sal_Int32 nSize = rSequenceMapping.getLength();
1117 sal_Int32 i = 0;
1118 OUStringBuffer aBuf;
1119 bool bHasPredecessor = false;
1120 for( i = 0; i < nSize; ++i )
1122 sal_Int32 nIndex = pArray[ i ];
1123 if( bRemoveOneFromEachIndex )
1124 --nIndex;
1125 if(nIndex>=0)
1127 if(bHasPredecessor)
1128 aBuf.append( static_cast< sal_Unicode >( ' ' ));
1129 aBuf.append( nIndex, 10 );
1130 bHasPredecessor = true;
1133 return aBuf.makeStringAndClear();
1136 /// if bExportContent is false the auto-styles are collected
1137 void SchXMLExportHelper_Impl::parseDocument( Reference< chart::XChartDocument >& rChartDoc,
1138 sal_Bool bExportContent,
1139 sal_Bool bIncludeTable )
1141 Reference< chart2::XChartDocument > xNewDoc( rChartDoc, uno::UNO_QUERY );
1142 if( !rChartDoc.is() || !xNewDoc.is() )
1144 SAL_WARN("xmloff.chart", "No XChartDocument was given for export." );
1145 return;
1148 mxExpPropMapper->setChartDoc(xNewDoc);
1150 awt::Size aPageSize( getPageSize( xNewDoc ));
1151 if( bExportContent )
1152 addSize( aPageSize );
1153 Reference< chart::XDiagram > xDiagram = rChartDoc->getDiagram();
1154 Reference< chart2::XDiagram > xNewDiagram;
1155 if( xNewDoc.is())
1156 xNewDiagram.set( xNewDoc->getFirstDiagram());
1158 //todo remove if model changes are notified and view is updated automatically
1159 if( bExportContent )
1161 Reference< util::XRefreshable > xRefreshable( xNewDoc, uno::UNO_QUERY );
1162 if( xRefreshable.is() )
1163 xRefreshable->refresh();
1166 // get Properties of ChartDocument
1167 sal_Bool bHasMainTitle = sal_False;
1168 sal_Bool bHasSubTitle = sal_False;
1169 sal_Bool bHasLegend = sal_False;
1170 util::DateTime aNullDate(0,0,0,0,30,12,1899, false);
1172 std::vector< XMLPropertyState > aPropertyStates;
1174 Reference< beans::XPropertySet > xDocPropSet( rChartDoc, uno::UNO_QUERY );
1175 if( xDocPropSet.is())
1179 Any aAny( xDocPropSet->getPropertyValue(
1180 OUString( "HasMainTitle" )));
1181 aAny >>= bHasMainTitle;
1182 aAny = xDocPropSet->getPropertyValue(
1183 OUString( "HasSubTitle" ));
1184 aAny >>= bHasSubTitle;
1185 aAny = xDocPropSet->getPropertyValue(
1186 OUString( "HasLegend" ));
1187 aAny >>= bHasLegend;
1188 if ( bIncludeTable )
1190 OUString sNullDate( "NullDate" );
1191 aAny = xDocPropSet->getPropertyValue(sNullDate);
1192 if ( !aAny.hasValue() )
1194 Reference<container::XChild> xChild(rChartDoc, uno::UNO_QUERY );
1195 if ( xChild.is() )
1197 Reference< beans::XPropertySet > xParentDoc( xChild->getParent(),uno::UNO_QUERY);
1198 if ( xParentDoc.is() && xParentDoc->getPropertySetInfo()->hasPropertyByName(sNullDate) )
1199 aAny = xParentDoc->getPropertyValue(sNullDate);
1203 aAny >>= aNullDate;
1206 catch( const beans::UnknownPropertyException & )
1208 SAL_WARN("xmloff.chart", "Required property not found in ChartDocument" );
1212 if ( bIncludeTable && (aNullDate.Day != 30 || aNullDate.Month != 12 || aNullDate.Year != 1899 ) )
1214 SvXMLElementExport aSet( mrExport, XML_NAMESPACE_TABLE, XML_CALCULATION_SETTINGS, sal_True, sal_True );
1216 OUStringBuffer sBuffer;
1217 ::sax::Converter::convertDateTime(sBuffer, aNullDate);
1218 mrExport.AddAttribute( XML_NAMESPACE_TABLE,XML_DATE_VALUE,sBuffer.makeStringAndClear());
1219 SvXMLElementExport aNull( mrExport, XML_NAMESPACE_TABLE, XML_NULL_DATE, sal_True, sal_True );
1223 // chart element
1224 // -------------
1226 SvXMLElementExport* pElChart = 0;
1227 // get property states for autostyles
1228 if( mxExpPropMapper.is())
1230 Reference< beans::XPropertySet > xPropSet( rChartDoc->getArea(), uno::UNO_QUERY );
1231 if( xPropSet.is())
1232 aPropertyStates = mxExpPropMapper->Filter( xPropSet );
1235 if( bExportContent )
1237 //export data provider in xlink:href attribute
1238 const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
1239 if( nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 )
1241 OUString aDataProviderURL( ".." );
1242 if( xNewDoc->hasInternalDataProvider() )
1243 aDataProviderURL = OUString( "." );
1244 else //special handling for data base data provider necessary
1246 Reference< chart2::data::XDatabaseDataProvider > xDBDataProvider( xNewDoc->getDataProvider(), uno::UNO_QUERY );
1247 if( xDBDataProvider.is() )
1248 aDataProviderURL = OUString( "." );
1250 mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, aDataProviderURL );
1251 mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
1254 OUString sChartType( xDiagram->getDiagramType() );
1256 // attributes
1257 // determine class
1258 if( !sChartType.isEmpty())
1260 enum XMLTokenEnum eXMLChartType = SchXMLTools::getTokenByChartType( sChartType, true /* bUseOldNames */ );
1262 SAL_WARN_IF( eXMLChartType == XML_TOKEN_INVALID, "xmloff.chart", "invalid chart class" );
1263 if( eXMLChartType == XML_TOKEN_INVALID )
1264 eXMLChartType = XML_BAR;
1266 if( eXMLChartType == XML_ADD_IN )
1268 // sChartType is the servie-name of the add-in
1269 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_CLASS,
1270 mrExport.GetNamespaceMap().GetQNameByKey(
1271 XML_NAMESPACE_OOO, sChartType) );
1273 else if( eXMLChartType != XML_TOKEN_INVALID )
1275 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_CLASS,
1276 mrExport.GetNamespaceMap().GetQNameByKey(
1277 XML_NAMESPACE_CHART, GetXMLToken(eXMLChartType )) );
1280 //column-mapping or row-mapping
1281 if( maSequenceMapping.getLength() )
1283 enum XMLTokenEnum eTransToken = ::xmloff::token::XML_ROW_MAPPING;
1284 if( mbRowSourceColumns )
1285 eTransToken = ::xmloff::token::XML_COLUMN_MAPPING;
1286 OUString aSequenceMappingStr( lcl_GetStringFromNumberSequence(
1287 maSequenceMapping, mbHasCategoryLabels && !xNewDoc->hasInternalDataProvider() ) );
1289 mrExport.AddAttribute( XML_NAMESPACE_CHART,
1290 ::xmloff::token::GetXMLToken( eTransToken ),
1291 aSequenceMappingStr );
1294 // write style name
1295 AddAutoStyleAttribute( aPropertyStates );
1297 //element
1298 pElChart = new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_CHART, sal_True, sal_True );
1300 else // autostyles
1302 CollectAutoStyle( aPropertyStates );
1304 // remove property states for autostyles
1305 aPropertyStates.clear();
1307 // title element
1308 // -------------
1310 if( bHasMainTitle )
1312 // get property states for autostyles
1313 if( mxExpPropMapper.is())
1315 Reference< beans::XPropertySet > xPropSet( rChartDoc->getTitle(), uno::UNO_QUERY );
1316 if( xPropSet.is())
1317 aPropertyStates = mxExpPropMapper->Filter( xPropSet );
1319 if( bExportContent )
1321 Reference< drawing::XShape > xShape = rChartDoc->getTitle();
1322 if( xShape.is()) // && "hasTitleBeenMoved"
1323 addPosition( xShape );
1325 // write style name
1326 AddAutoStyleAttribute( aPropertyStates );
1328 // element
1329 SvXMLElementExport aElTitle( mrExport, XML_NAMESPACE_CHART, XML_TITLE, sal_True, sal_True );
1331 // content (text:p)
1332 Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY );
1333 if( xPropSet.is())
1335 Any aAny( xPropSet->getPropertyValue(
1336 OUString( "String" )));
1337 OUString aText;
1338 aAny >>= aText;
1339 exportText( aText );
1342 else // autostyles
1344 CollectAutoStyle( aPropertyStates );
1346 // remove property states for autostyles
1347 aPropertyStates.clear();
1350 // subtitle element
1351 // ----------------
1353 if( bHasSubTitle )
1355 // get property states for autostyles
1356 if( mxExpPropMapper.is())
1358 Reference< beans::XPropertySet > xPropSet( rChartDoc->getSubTitle(), uno::UNO_QUERY );
1359 if( xPropSet.is())
1360 aPropertyStates = mxExpPropMapper->Filter( xPropSet );
1363 if( bExportContent )
1365 Reference< drawing::XShape > xShape = rChartDoc->getSubTitle();
1366 if( xShape.is())
1367 addPosition( xShape );
1369 // write style name
1370 AddAutoStyleAttribute( aPropertyStates );
1372 // element (has no subelements)
1373 SvXMLElementExport aElSubTitle( mrExport, XML_NAMESPACE_CHART, XML_SUBTITLE, sal_True, sal_True );
1375 // content (text:p)
1376 Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY );
1377 if( xPropSet.is())
1379 Any aAny( xPropSet->getPropertyValue(
1380 OUString( "String" )));
1381 OUString aText;
1382 aAny >>= aText;
1383 exportText( aText );
1386 else // autostyles
1388 CollectAutoStyle( aPropertyStates );
1390 // remove property states for autostyles
1391 aPropertyStates.clear();
1394 // legend element
1395 // --------------
1396 if( bHasLegend )
1398 // get property states for autostyles
1399 if( mxExpPropMapper.is())
1401 Reference< beans::XPropertySet > xPropSet( rChartDoc->getLegend(), uno::UNO_QUERY );
1402 if( xPropSet.is())
1403 aPropertyStates = mxExpPropMapper->Filter( xPropSet );
1406 if( bExportContent )
1408 Reference< beans::XPropertySet > xProp( rChartDoc->getLegend(), uno::UNO_QUERY );
1409 if( xProp.is())
1411 // export legend anchor position
1414 Any aAny( xProp->getPropertyValue( OUString( "Alignment" )));
1415 if( SchXMLEnumConverter::getLegendPositionConverter().exportXML( msString, aAny, mrExport.GetMM100UnitConverter() ) )
1416 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LEGEND_POSITION, msString );
1418 catch( const beans::UnknownPropertyException & )
1420 SAL_WARN("xmloff.chart", "Property Align not found in ChartLegend" );
1423 // export absolute legend position
1424 Reference< drawing::XShape > xLegendShape( xProp, uno::UNO_QUERY );
1425 addPosition( xLegendShape );
1427 // export legend size
1428 const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
1429 if( xLegendShape.is() && nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 )
1433 chart::ChartLegendExpansion nLegendExpansion = chart::ChartLegendExpansion_HIGH;
1434 OUString aExpansionString;
1435 Any aAny( xProp->getPropertyValue( OUString( "Expansion" )));
1436 bool bHasExpansion = (aAny >>= nLegendExpansion);
1437 if( bHasExpansion && SchXMLEnumConverter::getLegendExpansionConverter().exportXML( aExpansionString, aAny, mrExport.GetMM100UnitConverter() ) )
1439 mrExport.AddAttribute( XML_NAMESPACE_STYLE, XML_LEGEND_EXPANSION, aExpansionString );
1440 if( nLegendExpansion == chart::ChartLegendExpansion_CUSTOM)
1442 awt::Size aSize( xLegendShape->getSize() );
1443 addSize( aSize, true );
1444 OUStringBuffer aAspectRatioString;
1445 ::sax::Converter::convertDouble(
1446 aAspectRatioString,
1447 double(aSize.Width)/double(aSize.Height));
1448 mrExport.AddAttribute( XML_NAMESPACE_STYLE, XML_LEGEND_EXPANSION_ASPECT_RATIO, aAspectRatioString.makeStringAndClear() );
1452 catch( const beans::UnknownPropertyException & )
1454 SAL_WARN("xmloff.chart", "Property Expansion not found in ChartLegend" );
1459 // write style name
1460 AddAutoStyleAttribute( aPropertyStates );
1462 // element
1463 SvXMLElementExport aLegend( mrExport, XML_NAMESPACE_CHART, XML_LEGEND, sal_True, sal_True );
1465 else // autostyles
1467 CollectAutoStyle( aPropertyStates );
1469 // remove property states for autostyles
1470 aPropertyStates.clear();
1473 // plot-area element
1474 // -----------------
1475 if( xDiagram.is())
1476 exportPlotArea( xDiagram, xNewDiagram, aPageSize, bExportContent, bIncludeTable );
1478 // export additional shapes
1479 // ------------------------
1480 if( xDocPropSet.is() )
1482 if( bExportContent )
1484 if( mxAdditionalShapes.is())
1486 // can't call exportShapes with all shapes because the
1487 // initialisation happened with the complete draw page and not
1488 // the XShapes object used here. Thus the shapes have to be
1489 // exported one by one
1490 UniReference< XMLShapeExport > rShapeExport = mrExport.GetShapeExport();
1491 Reference< drawing::XShape > xShape;
1492 const sal_Int32 nShapeCount( mxAdditionalShapes->getCount());
1493 for( sal_Int32 nShapeId = 0; nShapeId < nShapeCount; nShapeId++ )
1495 mxAdditionalShapes->getByIndex( nShapeId ) >>= xShape;
1496 SAL_WARN_IF( !xShape.is(), "xmloff.chart", "Shape without an XShape?" );
1497 if( ! xShape.is())
1498 continue;
1500 rShapeExport->exportShape( xShape );
1502 // this would be the easier way if it worked:
1503 //mrExport.GetShapeExport()->exportShapes( mxAdditionalShapes );
1506 else
1508 // get a sequence of non-chart shapes (inserted via clipboard)
1511 Any aShapesAny = xDocPropSet->getPropertyValue( OUString( "AdditionalShapes" ));
1512 aShapesAny >>= mxAdditionalShapes;
1514 catch( const uno::Exception & rEx )
1516 SAL_INFO("xmloff.chart", "AdditionalShapes not found: " << rEx.Message );
1519 if( mxAdditionalShapes.is())
1521 // seek shapes has to be called for the whole page because in
1522 // the shape export the vector of shapes is accessed via the
1523 // ZOrder which might be (actually is) larger than the number of
1524 // shapes in mxAdditionalShapes
1525 Reference< drawing::XDrawPageSupplier > xSupplier( rChartDoc, uno::UNO_QUERY );
1526 SAL_WARN_IF( !xSupplier.is(), "xmloff.chart", "Cannot retrieve draw page to initialize shape export" );
1527 if( xSupplier.is() )
1529 Reference< drawing::XShapes > xDrawPage( xSupplier->getDrawPage(), uno::UNO_QUERY );
1530 SAL_WARN_IF( !xDrawPage.is(), "xmloff.chart", "Invalid draw page for initializing shape export" );
1531 if( xDrawPage.is())
1532 mrExport.GetShapeExport()->seekShapes( xDrawPage );
1535 // can't call collectShapesAutoStyles with all shapes because
1536 // the initialisation happened with the complete draw page and
1537 // not the XShapes object used here. Thus the shapes have to be
1538 // exported one by one
1539 UniReference< XMLShapeExport > rShapeExport = mrExport.GetShapeExport();
1540 Reference< drawing::XShape > xShape;
1541 const sal_Int32 nShapeCount( mxAdditionalShapes->getCount());
1542 for( sal_Int32 nShapeId = 0; nShapeId < nShapeCount; nShapeId++ )
1544 mxAdditionalShapes->getByIndex( nShapeId ) >>= xShape;
1545 SAL_WARN_IF( !xShape.is(), "xmloff.chart", "Shape without an XShape?" );
1546 if( ! xShape.is())
1547 continue;
1549 rShapeExport->collectShapeAutoStyles( xShape );
1555 // table element
1556 // (is included as subelement of chart)
1557 // ------------------------------------
1558 if( bExportContent )
1560 // #85929# always export table, otherwise clipboard may loose data
1561 exportTable();
1564 // close <chart:chart> element
1565 if( pElChart )
1566 delete pElChart;
1569 static void lcl_exportComplexLabel( const Sequence< uno::Any >& rComplexLabel, SvXMLExport& rExport )
1571 sal_Int32 nLength = rComplexLabel.getLength();
1572 if( nLength<=1 )
1573 return;
1574 SvXMLElementExport aTextList( rExport, XML_NAMESPACE_TEXT, XML_LIST, sal_True, sal_True );
1575 for(sal_Int32 nN=0; nN<nLength; nN++)
1577 SvXMLElementExport aListItem( rExport, XML_NAMESPACE_TEXT, XML_LIST_ITEM, sal_True, sal_True );
1578 OUString aString;
1579 if( !(rComplexLabel[nN]>>=aString) )
1581 //todo?
1583 SchXMLTools::exportText( rExport, aString, false /*bConvertTabsLFs*/ );
1587 void SchXMLExportHelper_Impl::exportTable()
1589 // table element
1590 // -------------
1591 mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_NAME, msTableName );
1595 bool bProtected = false;
1596 Reference< beans::XPropertySet > xProps( mrExport.GetModel(), uno::UNO_QUERY_THROW );
1597 if ( ( xProps->getPropertyValue( OUString( "DisableDataTableDialog" ) ) >>= bProtected ) &&
1598 bProtected )
1600 mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_PROTECTED, XML_TRUE );
1603 catch ( const uno::Exception& )
1607 SvXMLElementExport aTable( mrExport, XML_NAMESPACE_TABLE, XML_TABLE, sal_True, sal_True );
1609 bool bHasOwnData = false;
1610 Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
1611 Reference< chart2::data::XRangeXMLConversion > xRangeConversion;
1612 if( xNewDoc.is())
1614 bHasOwnData = xNewDoc->hasInternalDataProvider();
1615 xRangeConversion.set( xNewDoc->getDataProvider(), uno::UNO_QUERY );
1618 Reference< chart2::XAnyDescriptionAccess > xAnyDescriptionAccess;
1620 Reference< chart::XChartDocument > xChartDoc( mrExport.GetModel(), uno::UNO_QUERY );
1621 if( xChartDoc.is() )
1622 xAnyDescriptionAccess = Reference< chart2::XAnyDescriptionAccess >( xChartDoc->getData(), uno::UNO_QUERY );
1625 if( bHasOwnData )
1626 lcl_ReorderInternalSequencesAccordingToTheirRangeName( m_aDataSequencesToExport );
1627 lcl_TableData aData( lcl_getDataForLocalTable( m_aDataSequencesToExport
1628 , xAnyDescriptionAccess, maCategoriesRange
1629 , mbRowSourceColumns, xRangeConversion ));
1631 tStringVector::const_iterator aDataRangeIter( aData.aDataRangeRepresentations.begin());
1632 const tStringVector::const_iterator aDataRangeEndIter( aData.aDataRangeRepresentations.end());
1634 tStringVector::const_iterator aRowDescriptions_RangeIter( aData.aRowDescriptions_Ranges.begin());
1635 const tStringVector::const_iterator aRowDescriptions_RangeEnd( aData.aRowDescriptions_Ranges.end());
1637 // declare columns
1639 SvXMLElementExport aHeaderColumns( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_HEADER_COLUMNS, sal_True, sal_True );
1640 SvXMLElementExport aHeaderColumn( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, sal_True, sal_True );
1643 SvXMLElementExport aColumns( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMNS, sal_True, sal_True );
1645 sal_Int32 nNextIndex = 0;
1646 for( size_t nN=0; nN< aData.aHiddenColumns.size(); nN++ )
1648 //i91578 display of hidden values (copy paste scenario; export hidden flag thus it can be used during migration to locale table upon paste )
1649 sal_Int32 nHiddenIndex = aData.aHiddenColumns[nN];
1650 if( nHiddenIndex > nNextIndex )
1652 sal_Int64 nRepeat = static_cast< sal_Int64 >( nHiddenIndex - nNextIndex );
1653 if(nRepeat>1)
1654 mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED,
1655 OUString::valueOf( nRepeat ));
1656 SvXMLElementExport aColumn( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, sal_True, sal_True );
1658 mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_VISIBILITY, GetXMLToken( XML_COLLAPSE ) );
1659 SvXMLElementExport aColumn( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, sal_True, sal_True );
1660 nNextIndex = nHiddenIndex+1;
1663 sal_Int32 nEndIndex = aData.aColumnDescriptions.size()-1;
1664 if( nEndIndex >= nNextIndex )
1666 sal_Int64 nRepeat = static_cast< sal_Int64 >( nEndIndex - nNextIndex + 1 );
1667 if(nRepeat>1)
1668 mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED,
1669 OUString::valueOf( nRepeat ));
1670 SvXMLElementExport aColumn( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, sal_True, sal_True );
1674 // export rows with content
1675 //export header row
1677 SvXMLElementExport aHeaderRows( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_HEADER_ROWS, sal_True, sal_True );
1678 SvXMLElementExport aRow( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_ROW, sal_True, sal_True );
1680 //first one empty cell for the row descriptions
1682 SvXMLElementExport aEmptyCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True );
1683 SvXMLElementExport aEmptyParagraph( mrExport, XML_NAMESPACE_TEXT, XML_P, sal_True, sal_True );
1686 //export column descriptions
1687 tStringVector::const_iterator aColumnDescriptions_RangeIter( aData.aColumnDescriptions_Ranges.begin());
1688 const tStringVector::const_iterator aColumnDescriptions_RangeEnd( aData.aColumnDescriptions_Ranges.end());
1689 const Sequence< Sequence< uno::Any > >& rComplexColumnDescriptions = aData.aComplexColumnDescriptions;
1690 sal_Int32 nComplexCount = rComplexColumnDescriptions.getLength();
1691 sal_Int32 nC = 0;
1692 for( tStringVector::const_iterator aIt( aData.aColumnDescriptions.begin())
1693 ; (aIt != aData.aColumnDescriptions.end())
1694 ; ++aIt, nC++ )
1696 bool bExportString = true;
1697 if( nC < nComplexCount )
1699 const Sequence< uno::Any >& rComplexLabel = rComplexColumnDescriptions[nC];
1700 if( rComplexLabel.getLength()>0 )
1702 double fValue=0.0;
1703 if( rComplexLabel[0] >>=fValue )
1705 bExportString = false;
1707 ::sax::Converter::convertDouble(
1708 msStringBuffer, fValue);
1709 msString = msStringBuffer.makeStringAndClear();
1710 mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT );
1711 mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE, msString );
1715 if( bExportString )
1717 mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_STRING );
1720 SvXMLElementExport aCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True );
1721 exportText( *aIt );
1722 if( nC < nComplexCount )
1723 lcl_exportComplexLabel( rComplexColumnDescriptions[nC], mrExport );
1724 if( !bHasOwnData && aColumnDescriptions_RangeIter != aColumnDescriptions_RangeEnd )
1726 // remind the original range to allow a correct re-association when copying via clipboard
1727 if (!(*aColumnDescriptions_RangeIter).isEmpty())
1728 SchXMLTools::exportRangeToSomewhere( mrExport, *aColumnDescriptions_RangeIter );
1729 ++aColumnDescriptions_RangeIter;
1732 SAL_WARN_IF( !bHasOwnData && (aColumnDescriptions_RangeIter != aColumnDescriptions_RangeEnd), "xmloff.chart", "bHasOwnData == false && aColumnDescriptions_RangeIter != aColumnDescriptions_RangeEnd" );
1733 } // closing row and header-rows elements
1735 // export value rows
1737 SvXMLElementExport aRows( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_ROWS, sal_True, sal_True );
1738 tStringVector::const_iterator aRowDescriptionsIter( aData.aRowDescriptions.begin());
1739 const Sequence< Sequence< uno::Any > >& rComplexRowDescriptions = aData.aComplexRowDescriptions;
1740 sal_Int32 nComplexCount = rComplexRowDescriptions.getLength();
1741 sal_Int32 nC = 0;
1743 for( t2DNumberContainer::const_iterator aRowIt( aData.aDataInRows.begin())
1744 ; aRowIt != aData.aDataInRows.end()
1745 ; ++aRowIt, ++nC )
1747 SvXMLElementExport aRow( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_ROW, sal_True, sal_True );
1749 //export row descriptions
1751 bool bExportString = true;
1752 if( nC < nComplexCount )
1754 const Sequence< uno::Any >& rComplexLabel = rComplexRowDescriptions[nC];
1755 if( rComplexLabel.getLength()>0 )
1757 double fValue=0.0;
1758 if( rComplexLabel[0] >>=fValue )
1760 bExportString = false;
1762 ::sax::Converter::convertDouble(msStringBuffer, fValue);
1763 msString = msStringBuffer.makeStringAndClear();
1764 mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT );
1765 mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE, msString );
1769 if( bExportString )
1771 mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_STRING );
1774 SvXMLElementExport aCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True );
1775 if( aRowDescriptionsIter != aData.aRowDescriptions.end())
1777 exportText( *aRowDescriptionsIter );
1778 if( nC < nComplexCount )
1779 lcl_exportComplexLabel( rComplexRowDescriptions[nC], mrExport );
1780 if( !bHasOwnData && aRowDescriptions_RangeIter != aRowDescriptions_RangeEnd )
1782 // remind the original range to allow a correct re-association when copying via clipboard
1783 SchXMLTools::exportRangeToSomewhere( mrExport, *aRowDescriptions_RangeIter );
1784 ++aRowDescriptions_RangeIter;
1786 ++aRowDescriptionsIter;
1790 //export row values
1791 for( t2DNumberContainer::value_type::const_iterator aColIt( aRowIt->begin());
1792 aColIt != aRowIt->end(); ++aColIt )
1794 ::sax::Converter::convertDouble( msStringBuffer, *aColIt );
1795 msString = msStringBuffer.makeStringAndClear();
1796 mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT );
1797 mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE, msString );
1798 SvXMLElementExport aCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True );
1799 exportText( msString, false ); // do not convert tabs and lfs
1800 if( ( !bHasOwnData && aDataRangeIter != aDataRangeEndIter ) &&
1801 ( mbRowSourceColumns || (aColIt == aRowIt->begin()) ) )
1803 // remind the original range to allow a correct re-association when copying via clipboard
1804 if (!(*aDataRangeIter).isEmpty())
1805 SchXMLTools::exportRangeToSomewhere( mrExport, *aDataRangeIter );
1806 ++aDataRangeIter;
1812 // if range iterator was used it should have reached its end
1813 SAL_WARN_IF( !bHasOwnData && (aDataRangeIter != aDataRangeEndIter), "xmloff.chart", "bHasOwnData == false && aDataRangeIter != aDataRangeEndIter" );
1814 SAL_WARN_IF( !bHasOwnData && (aRowDescriptions_RangeIter != aRowDescriptions_RangeEnd), "xmloff.chart", "bHasOwnData == false && aRowDescriptions_RangeIter != aRowDescriptions_RangeEnd" );
1817 namespace
1820 Reference< chart2::XCoordinateSystem > lcl_getCooSys( const Reference< chart2::XDiagram > & xNewDiagram )
1822 Reference< chart2::XCoordinateSystem > xCooSys;
1823 Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xNewDiagram, uno::UNO_QUERY );
1824 if(xCooSysCnt.is())
1826 Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems() );
1827 if(aCooSysSeq.getLength()>0)
1828 xCooSys = aCooSysSeq[0];
1830 return xCooSys;
1833 Reference< chart2::XAxis > lcl_getAxis( const Reference< chart2::XCoordinateSystem >& xCooSys,
1834 enum XMLTokenEnum eDimension, bool bPrimary=true )
1836 Reference< chart2::XAxis > xNewAxis;
1839 if( xCooSys.is() )
1841 sal_Int32 nDimensionIndex=0;
1842 switch( eDimension )
1844 case XML_X:
1845 nDimensionIndex=0;
1846 break;
1847 case XML_Y:
1848 nDimensionIndex=1;
1849 break;
1850 case XML_Z:
1851 nDimensionIndex=2;
1852 break;
1853 default:
1854 break;
1857 xNewAxis = xCooSys->getAxisByDimension( nDimensionIndex, bPrimary ? 0 : 1 );
1860 catch( const uno::Exception & )
1863 return xNewAxis;
1868 void SchXMLExportHelper_Impl::exportPlotArea(
1869 Reference< chart::XDiagram > xDiagram,
1870 Reference< chart2::XDiagram > xNewDiagram,
1871 const awt::Size & rPageSize,
1872 sal_Bool bExportContent,
1873 sal_Bool bIncludeTable )
1875 SAL_WARN_IF( !xDiagram.is(), "xmloff.chart", "Invalid XDiagram as parameter" );
1876 if( ! xDiagram.is())
1877 return;
1879 // variables for autostyles
1880 Reference< beans::XPropertySet > xPropSet;
1881 std::vector< XMLPropertyState > aPropertyStates;
1883 sal_Bool bIs3DChart = sal_False;
1884 drawing::HomogenMatrix aTransMatrix;
1886 msStringBuffer.setLength( 0 );
1888 // plot-area element
1889 // -----------------
1891 SvXMLElementExport* pElPlotArea = 0;
1892 // get property states for autostyles
1893 xPropSet = Reference< beans::XPropertySet >( xDiagram, uno::UNO_QUERY );
1894 if( xPropSet.is())
1896 if( mxExpPropMapper.is())
1897 aPropertyStates = mxExpPropMapper->Filter( xPropSet );
1899 if( bExportContent )
1901 UniReference< XMLShapeExport > rShapeExport;
1903 // write style name
1904 AddAutoStyleAttribute( aPropertyStates );
1906 if( !msChartAddress.isEmpty() )
1908 if( !bIncludeTable )
1909 mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_CELL_RANGE_ADDRESS, msChartAddress );
1911 Reference< chart::XChartDocument > xDoc( mrExport.GetModel(), uno::UNO_QUERY );
1912 if( xDoc.is() )
1914 Reference< beans::XPropertySet > xDocProp( xDoc, uno::UNO_QUERY );
1915 if( xDocProp.is())
1917 Any aAny;
1918 sal_Bool bFirstCol = false, bFirstRow = false;
1922 aAny = xDocProp->getPropertyValue(
1923 OUString( "DataSourceLabelsInFirstColumn" ));
1924 aAny >>= bFirstCol;
1925 aAny = xDocProp->getPropertyValue(
1926 OUString( "DataSourceLabelsInFirstRow" ));
1927 aAny >>= bFirstRow;
1929 if( bFirstCol || bFirstRow )
1931 mrExport.AddAttribute( XML_NAMESPACE_CHART,
1932 ::xmloff::token::GetXMLToken( ::xmloff::token::XML_DATA_SOURCE_HAS_LABELS ),
1933 ( bFirstCol
1934 ? ( bFirstRow
1935 ? ::xmloff::token::GetXMLToken( ::xmloff::token::XML_BOTH )
1936 : ::xmloff::token::GetXMLToken( ::xmloff::token::XML_COLUMN ))
1937 : ::xmloff::token::GetXMLToken( ::xmloff::token::XML_ROW )));
1940 catch( const beans::UnknownPropertyException & )
1942 SAL_WARN("xmloff.chart", "Properties missing" );
1948 // #i72973#, #144135# only export table-number-list in OOo format (also for binary)
1949 Reference< beans::XPropertySet > xExportInfo( mrExport.getExportInfo());
1950 if( !msTableNumberList.isEmpty() && xExportInfo.is())
1954 OUString sExportTableNumListPropName( "ExportTableNumberList");
1955 Reference< beans::XPropertySetInfo > xInfo( xExportInfo->getPropertySetInfo());
1956 bool bExportTableNumberList = false;
1957 if( xInfo.is() && xInfo->hasPropertyByName( sExportTableNumListPropName ) &&
1958 (xExportInfo->getPropertyValue( sExportTableNumListPropName ) >>= bExportTableNumberList) &&
1959 bExportTableNumberList )
1961 // this attribute is for charts embedded in calc documents only.
1962 // With this you are able to store a file again in 5.0 binary format
1963 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_TABLE_NUMBER_LIST, msTableNumberList );
1966 catch( const uno::Exception & rEx )
1968 OString aBStr(OUStringToOString(rEx.Message, RTL_TEXTENCODING_ASCII_US));
1969 SAL_INFO("xmloff.chart", "chart:TableNumberList property caught: " << aBStr );
1973 // attributes
1974 Reference< drawing::XShape > xShape ( xDiagram, uno::UNO_QUERY );
1975 if( xShape.is())
1977 addPosition( xShape );
1978 addSize( xShape );
1981 if( xPropSet.is())
1983 Any aAny;
1985 // 3d attributes
1988 aAny = xPropSet->getPropertyValue( OUString( "Dim3D" ));
1989 aAny >>= bIs3DChart;
1991 if( bIs3DChart )
1993 rShapeExport = mrExport.GetShapeExport();
1994 if( rShapeExport.is())
1995 rShapeExport->export3DSceneAttributes( xPropSet );
1998 catch( const uno::Exception & rEx )
2000 OString aBStr(OUStringToOString(rEx.Message, RTL_TEXTENCODING_ASCII_US));
2001 SAL_INFO("xmloff.chart", "chart:exportPlotAreaException caught: " << aBStr);
2005 // plot-area element
2006 pElPlotArea = new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_PLOT_AREA, sal_True, sal_True );
2008 //inner position rectangle element
2009 exportCoordinateRegion( xDiagram );
2011 // light sources (inside plot area element)
2012 if( bIs3DChart &&
2013 rShapeExport.is())
2014 rShapeExport->export3DLamps( xPropSet );
2016 else // autostyles
2018 CollectAutoStyle( aPropertyStates );
2020 // remove property states for autostyles
2021 aPropertyStates.clear();
2023 // axis elements
2024 // -------------
2025 exportAxes( xDiagram, xNewDiagram, bExportContent );
2027 // series elements
2028 // ---------------
2029 Reference< chart2::XAxis > xSecondYAxis = lcl_getAxis( lcl_getCooSys( xNewDiagram ), XML_Y, false );
2030 exportSeries( xNewDiagram, rPageSize, bExportContent, xSecondYAxis.is() );
2032 // stock-chart elements
2033 OUString sChartType ( xDiagram->getDiagramType());
2034 if( 0 == sChartType.reverseCompareTo( "com.sun.star.chart.StockDiagram" ))
2036 Reference< chart::XStatisticDisplay > xStockPropProvider( xDiagram, uno::UNO_QUERY );
2037 if( xStockPropProvider.is())
2039 // stock-gain-marker
2040 Reference< beans::XPropertySet > xStockPropSet = xStockPropProvider->getUpBar();
2041 if( xStockPropSet.is())
2043 aPropertyStates.clear();
2044 aPropertyStates = mxExpPropMapper->Filter( xStockPropSet );
2046 if( !aPropertyStates.empty() )
2048 if( bExportContent )
2050 AddAutoStyleAttribute( aPropertyStates );
2052 SvXMLElementExport aGain( mrExport, XML_NAMESPACE_CHART, XML_STOCK_GAIN_MARKER, sal_True, sal_True );
2054 else
2056 CollectAutoStyle( aPropertyStates );
2061 // stock-loss-marker
2062 xStockPropSet = xStockPropProvider->getDownBar();
2063 if( xStockPropSet.is())
2065 aPropertyStates.clear();
2066 aPropertyStates = mxExpPropMapper->Filter( xStockPropSet );
2068 if( !aPropertyStates.empty() )
2070 if( bExportContent )
2072 AddAutoStyleAttribute( aPropertyStates );
2074 SvXMLElementExport aGain( mrExport, XML_NAMESPACE_CHART, XML_STOCK_LOSS_MARKER, sal_True, sal_True );
2076 else
2078 CollectAutoStyle( aPropertyStates );
2083 // stock-range-line
2084 xStockPropSet = xStockPropProvider->getMinMaxLine();
2085 if( xStockPropSet.is())
2087 aPropertyStates.clear();
2088 aPropertyStates = mxExpPropMapper->Filter( xStockPropSet );
2090 if( !aPropertyStates.empty() )
2092 if( bExportContent )
2094 AddAutoStyleAttribute( aPropertyStates );
2096 SvXMLElementExport aGain( mrExport, XML_NAMESPACE_CHART, XML_STOCK_RANGE_LINE, sal_True, sal_True );
2098 else
2100 CollectAutoStyle( aPropertyStates );
2107 // wall and floor element
2108 // ----------------------
2110 Reference< chart::X3DDisplay > xWallFloorSupplier( xDiagram, uno::UNO_QUERY );
2111 if( mxExpPropMapper.is() &&
2112 xWallFloorSupplier.is())
2114 // remove property states for autostyles
2115 aPropertyStates.clear();
2117 Reference< beans::XPropertySet > xWallPropSet( xWallFloorSupplier->getWall(), uno::UNO_QUERY );
2118 if( xWallPropSet.is())
2120 aPropertyStates = mxExpPropMapper->Filter( xWallPropSet );
2122 if( !aPropertyStates.empty() )
2124 // write element
2125 if( bExportContent )
2127 // add style name attribute
2128 AddAutoStyleAttribute( aPropertyStates );
2130 SvXMLElementExport aWall( mrExport, XML_NAMESPACE_CHART, XML_WALL, sal_True, sal_True );
2132 else // autostyles
2134 CollectAutoStyle( aPropertyStates );
2139 // floor element
2140 // -------------
2142 // remove property states for autostyles
2143 aPropertyStates.clear();
2145 Reference< beans::XPropertySet > xFloorPropSet( xWallFloorSupplier->getFloor(), uno::UNO_QUERY );
2146 if( xFloorPropSet.is())
2148 aPropertyStates = mxExpPropMapper->Filter( xFloorPropSet );
2150 if( !aPropertyStates.empty() )
2152 // write element
2153 if( bExportContent )
2155 // add style name attribute
2156 AddAutoStyleAttribute( aPropertyStates );
2158 SvXMLElementExport aFloor( mrExport, XML_NAMESPACE_CHART, XML_FLOOR, sal_True, sal_True );
2160 else // autostyles
2162 CollectAutoStyle( aPropertyStates );
2168 if( pElPlotArea )
2169 delete pElPlotArea;
2172 void SchXMLExportHelper_Impl::exportCoordinateRegion( const uno::Reference< chart::XDiagram >& xDiagram )
2174 const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
2175 if( nCurrentODFVersion <= SvtSaveOptions::ODFVER_012 )//do not export to ODF 1.2 or older
2176 return;
2178 Reference< chart::XDiagramPositioning > xDiaPos( xDiagram, uno::UNO_QUERY );
2179 SAL_WARN_IF( !xDiaPos.is(), "xmloff.chart", "Invalid xDiaPos as parameter" );
2180 if( !xDiaPos.is() )
2181 return;
2183 awt::Rectangle aRect( xDiaPos->calculateDiagramPositionExcludingAxes() );
2184 addPosition( awt::Point(aRect.X,aRect.Y) );
2185 addSize( awt::Size(aRect.Width,aRect.Height) );
2187 SvXMLElementExport aCoordinateRegion( mrExport, XML_NAMESPACE_CHART_EXT, XML_COORDINATE_REGION, sal_True, sal_True );//#i100778# todo: change to chart namespace in future - dependent on fileformat
2190 namespace
2192 XMLTokenEnum lcl_getTimeUnitToken( sal_Int32 nTimeUnit )
2194 XMLTokenEnum eToken = XML_DAYS;
2195 switch( nTimeUnit )
2197 case ::com::sun::star::chart::TimeUnit::YEAR:
2198 eToken = XML_YEARS;
2199 break;
2200 case ::com::sun::star::chart::TimeUnit::MONTH:
2201 eToken = XML_MONTHS;
2202 break;
2203 default://days
2204 break;
2206 return eToken;
2210 void SchXMLExportHelper_Impl::exportDateScale( const Reference< beans::XPropertySet > xAxisProps )
2212 if( !xAxisProps.is() )
2213 return;
2215 chart::TimeIncrement aIncrement;
2216 if( (xAxisProps->getPropertyValue( OUString( "TimeIncrement" )) >>= aIncrement) )
2218 sal_Int32 nTimeResolution = ::com::sun::star::chart::TimeUnit::DAY;
2219 if( aIncrement.TimeResolution >>= nTimeResolution )
2220 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_BASE_TIME_UNIT, lcl_getTimeUnitToken( nTimeResolution ) );
2222 OUStringBuffer aValue;
2223 chart::TimeInterval aInterval;
2224 if( aIncrement.MajorTimeInterval >>= aInterval )
2226 ::sax::Converter::convertNumber( aValue, aInterval.Number );
2227 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MAJOR_INTERVAL_VALUE, aValue.makeStringAndClear() );
2228 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MAJOR_INTERVAL_UNIT, lcl_getTimeUnitToken( aInterval.TimeUnit ) );
2230 if( aIncrement.MinorTimeInterval >>= aInterval )
2232 ::sax::Converter::convertNumber( aValue, aInterval.Number );
2233 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MINOR_INTERVAL_VALUE, aValue.makeStringAndClear() );
2234 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MINOR_INTERVAL_UNIT, lcl_getTimeUnitToken( aInterval.TimeUnit ) );
2237 SvXMLElementExport aDateScale( mrExport, XML_NAMESPACE_CHART_EXT, XML_DATE_SCALE, sal_True, sal_True );//#i25706#todo: change namespace for next ODF version
2241 void SchXMLExportHelper_Impl::exportAxisTitle( const Reference< beans::XPropertySet > xTitleProps, bool bExportContent )
2243 if( !xTitleProps.is() )
2244 return;
2245 std::vector< XMLPropertyState > aPropertyStates = mxExpPropMapper->Filter( xTitleProps );
2246 if( bExportContent )
2248 OUString aText;
2249 Any aAny( xTitleProps->getPropertyValue(
2250 OUString( "String" )));
2251 aAny >>= aText;
2253 Reference< drawing::XShape > xShape( xTitleProps, uno::UNO_QUERY );
2254 if( xShape.is())
2255 addPosition( xShape );
2257 AddAutoStyleAttribute( aPropertyStates );
2258 SvXMLElementExport aTitle( mrExport, XML_NAMESPACE_CHART, XML_TITLE, sal_True, sal_True );
2260 // paragraph containing title
2261 exportText( aText );
2263 else
2265 CollectAutoStyle( aPropertyStates );
2267 aPropertyStates.clear();
2270 void SchXMLExportHelper_Impl::exportGrid( const Reference< beans::XPropertySet > xGridProperties, bool bMajor, bool bExportContent )
2272 if( !xGridProperties.is() )
2273 return;
2274 std::vector< XMLPropertyState > aPropertyStates = mxExpPropMapper->Filter( xGridProperties );
2275 if( bExportContent )
2277 AddAutoStyleAttribute( aPropertyStates );
2278 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_CLASS, bMajor ? XML_MAJOR : XML_MINOR );
2279 SvXMLElementExport aGrid( mrExport, XML_NAMESPACE_CHART, XML_GRID, sal_True, sal_True );
2281 else
2283 CollectAutoStyle( aPropertyStates );
2285 aPropertyStates.clear();
2288 namespace
2291 //returns true if a date scale needs to be exported
2292 bool lcl_exportAxisType( const Reference< chart2::XAxis > xChart2Axis, SvXMLExport& rExport)
2294 bool bExportDateScale = false;
2295 if( !xChart2Axis.is() )
2296 return bExportDateScale;
2298 const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
2299 if( nCurrentODFVersion <= SvtSaveOptions::ODFVER_012 )//do not export to ODF 1.2 or older
2300 return bExportDateScale;
2302 chart2::ScaleData aScale( xChart2Axis->getScaleData() );
2303 //#i25706#todo: change namespace for next ODF version
2304 sal_uInt16 nNameSpace = XML_NAMESPACE_CHART_EXT;
2306 switch(aScale.AxisType)
2308 case chart2::AxisType::CATEGORY:
2309 if( aScale.AutoDateAxis )
2311 rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_AUTO );
2312 bExportDateScale = true;
2314 else
2315 rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_TEXT );
2316 break;
2317 case chart2::AxisType::DATE:
2318 rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_DATE );
2319 bExportDateScale = true;
2320 break;
2321 default: //AUTOMATIC
2322 rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_AUTO );
2323 break;
2326 return bExportDateScale;
2331 void SchXMLExportHelper_Impl::exportAxis(
2332 enum XMLTokenEnum eDimension,
2333 enum XMLTokenEnum eAxisName,
2334 const Reference< beans::XPropertySet > xAxisProps,
2335 const Reference< chart2::XAxis >& xChart2Axis,
2336 const OUString& rCategoriesRange,
2337 bool bHasTitle, bool bHasMajorGrid, bool bHasMinorGrid,
2338 bool bExportContent )
2340 static const OUString sNumFormat( OUString( "NumberFormat" ));
2341 std::vector< XMLPropertyState > aPropertyStates;
2342 SvXMLElementExport* pAxis = NULL;
2344 // get property states for autostyles
2345 if( xAxisProps.is() && mxExpPropMapper.is() )
2347 lcl_exportNumberFormat( sNumFormat, xAxisProps, mrExport );
2348 aPropertyStates = mxExpPropMapper->Filter( xAxisProps );
2351 bool bExportDateScale = false;
2352 if( bExportContent )
2354 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_DIMENSION, eDimension );
2355 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_NAME, eAxisName );
2356 AddAutoStyleAttribute( aPropertyStates ); // write style name
2357 if( !rCategoriesRange.isEmpty() )
2358 bExportDateScale = lcl_exportAxisType( xChart2Axis, mrExport );
2360 // open axis element
2361 pAxis = new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_AXIS, sal_True, sal_True );
2363 else
2365 CollectAutoStyle( aPropertyStates );
2367 aPropertyStates.clear();
2369 //date scale
2370 if( bExportDateScale )
2371 exportDateScale( xAxisProps );
2373 Reference< beans::XPropertySet > xTitleProps;
2374 Reference< beans::XPropertySet > xMajorGridProps;
2375 Reference< beans::XPropertySet > xMinorGridProps;
2376 Reference< chart::XAxis > xAxis( xAxisProps, uno::UNO_QUERY );
2377 if( xAxis.is() )
2379 xTitleProps = bHasTitle ? xAxis->getAxisTitle() : 0;
2380 xMajorGridProps = bHasMajorGrid ? xAxis->getMajorGrid() : 0;
2381 xMinorGridProps = bHasMinorGrid ? xAxis->getMinorGrid() : 0;
2384 // axis-title
2385 exportAxisTitle( xTitleProps , bExportContent );
2387 // categories if we have a categories chart
2388 if( bExportContent && !rCategoriesRange.isEmpty() )
2390 mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_CELL_RANGE_ADDRESS, rCategoriesRange );
2391 SvXMLElementExport aCategories( mrExport, XML_NAMESPACE_CHART, XML_CATEGORIES, sal_True, sal_True );
2394 // grid
2395 exportGrid( xMajorGridProps, true, bExportContent );
2396 exportGrid( xMinorGridProps, false, bExportContent );
2398 if( pAxis )
2400 //close axis element
2401 delete pAxis;
2402 pAxis = NULL;
2406 void SchXMLExportHelper_Impl::exportAxes(
2407 const Reference< chart::XDiagram > & xDiagram,
2408 const Reference< chart2::XDiagram > & xNewDiagram,
2409 sal_Bool bExportContent )
2411 SAL_WARN_IF( !xDiagram.is(), "xmloff.chart", "Invalid XDiagram as parameter" );
2412 if( ! xDiagram.is())
2413 return;
2415 // get some properties from document first
2416 sal_Bool bHasXAxis = sal_False,
2417 bHasYAxis = sal_False,
2418 bHasZAxis = sal_False,
2419 bHasSecondaryXAxis = sal_False,
2420 bHasSecondaryYAxis = sal_False;
2421 sal_Bool bHasXAxisTitle = sal_False,
2422 bHasYAxisTitle = sal_False,
2423 bHasZAxisTitle = sal_False,
2424 bHasSecondaryXAxisTitle = sal_False,
2425 bHasSecondaryYAxisTitle = sal_False;
2426 sal_Bool bHasXAxisMajorGrid = sal_False,
2427 bHasXAxisMinorGrid = sal_False,
2428 bHasYAxisMajorGrid = sal_False,
2429 bHasYAxisMinorGrid = sal_False,
2430 bHasZAxisMajorGrid = sal_False,
2431 bHasZAxisMinorGrid = sal_False;
2433 // get multiple properties using XMultiPropertySet
2434 MultiPropertySetHandler aDiagramProperties (xDiagram);
2436 aDiagramProperties.Add (
2437 OUString("HasXAxis"), bHasXAxis);
2438 aDiagramProperties.Add (
2439 OUString("HasYAxis"), bHasYAxis);
2440 aDiagramProperties.Add (
2441 OUString("HasZAxis"), bHasZAxis);
2442 aDiagramProperties.Add (
2443 OUString("HasSecondaryXAxis"), bHasSecondaryXAxis);
2444 aDiagramProperties.Add (
2445 OUString("HasSecondaryYAxis"), bHasSecondaryYAxis);
2447 aDiagramProperties.Add (
2448 OUString ("HasXAxisTitle"), bHasXAxisTitle);
2449 aDiagramProperties.Add (
2450 OUString ("HasYAxisTitle"), bHasYAxisTitle);
2451 aDiagramProperties.Add (
2452 OUString ("HasZAxisTitle"), bHasZAxisTitle);
2453 aDiagramProperties.Add (
2454 OUString ("HasSecondaryXAxisTitle"), bHasSecondaryXAxisTitle);
2455 aDiagramProperties.Add (
2456 OUString ("HasSecondaryYAxisTitle"), bHasSecondaryYAxisTitle);
2458 aDiagramProperties.Add (
2459 OUString ("HasXAxisGrid"), bHasXAxisMajorGrid);
2460 aDiagramProperties.Add (
2461 OUString ("HasYAxisGrid"), bHasYAxisMajorGrid);
2462 aDiagramProperties.Add (
2463 OUString ("HasZAxisGrid"), bHasZAxisMajorGrid);
2465 aDiagramProperties.Add (
2466 OUString ("HasXAxisHelpGrid"), bHasXAxisMinorGrid);
2467 aDiagramProperties.Add (
2468 OUString ("HasYAxisHelpGrid"), bHasYAxisMinorGrid);
2469 aDiagramProperties.Add (
2470 OUString ("HasZAxisHelpGrid"), bHasZAxisMinorGrid);
2472 if ( ! aDiagramProperties.GetProperties ())
2474 SAL_INFO("xmloff.chart", "Required properties not found in Chart diagram");
2477 Reference< chart2::XCoordinateSystem > xCooSys( lcl_getCooSys(xNewDiagram) );
2479 // write an axis element also if the axis itself is not visible, but a grid or a title
2481 OUString aCategoriesRange;
2482 Reference< chart::XAxisSupplier > xAxisSupp( xDiagram, uno::UNO_QUERY );
2484 // x axis
2485 // -------
2486 Reference< ::com::sun::star::chart2::XAxis > xNewAxis = lcl_getAxis( xCooSys, XML_X );
2487 if( xNewAxis.is() )
2489 Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getAxis(0) : 0, uno::UNO_QUERY );
2490 if( mbHasCategoryLabels && bExportContent )
2492 Reference< chart2::data::XLabeledDataSequence > xCategories( lcl_getCategories( xNewDiagram ) );
2493 if( xCategories.is() )
2495 Reference< chart2::data::XDataSequence > xValues( xCategories->getValues() );
2496 if( xValues.is() )
2498 Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
2499 maCategoriesRange = xValues->getSourceRangeRepresentation();
2500 aCategoriesRange = lcl_ConvertRange( maCategoriesRange, xNewDoc );
2504 exportAxis( XML_X, XML_PRIMARY_X, xAxisProps, xNewAxis, aCategoriesRange, bHasXAxisTitle, bHasXAxisMajorGrid, bHasXAxisMinorGrid, bExportContent );
2505 aCategoriesRange = OUString();
2508 // secondary x axis
2509 // -------
2510 Reference< chart::XSecondAxisTitleSupplier > xSecondTitleSupp( xDiagram, uno::UNO_QUERY );
2511 xNewAxis = lcl_getAxis( xCooSys, XML_X, false );
2512 if( xNewAxis.is() )
2514 Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getSecondaryAxis(0) : 0, uno::UNO_QUERY );
2515 exportAxis( XML_X, XML_SECONDARY_X, xAxisProps, xNewAxis, aCategoriesRange, bHasSecondaryXAxisTitle, false, false, bExportContent );
2518 // y axis
2519 // -------
2520 xNewAxis = lcl_getAxis( xCooSys, XML_Y );
2521 if( xNewAxis.is() )
2523 Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getAxis(1) : 0, uno::UNO_QUERY );
2524 exportAxis( XML_Y, XML_PRIMARY_Y, xAxisProps, xNewAxis, aCategoriesRange, bHasYAxisTitle, bHasYAxisMajorGrid, bHasYAxisMinorGrid, bExportContent );
2527 // secondary y axis
2528 // -------
2529 xNewAxis = lcl_getAxis( xCooSys, XML_Y, false );
2530 if( xNewAxis.is() )
2532 Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getSecondaryAxis(1) : 0, uno::UNO_QUERY );
2533 exportAxis( XML_Y, XML_SECONDARY_Y, xAxisProps, xNewAxis, aCategoriesRange, bHasSecondaryYAxisTitle, false, false, bExportContent );
2536 // z axis
2537 // -------
2538 xNewAxis = lcl_getAxis( xCooSys, XML_Z );
2539 if( xNewAxis.is() )
2541 Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getAxis(2) : 0, uno::UNO_QUERY );
2542 exportAxis( XML_Z, XML_PRIMARY_Z, xAxisProps, xNewAxis, aCategoriesRange, bHasZAxisTitle, bHasZAxisMajorGrid, bHasZAxisMinorGrid, bExportContent );
2546 namespace
2548 bool lcl_hasNoValuesButText( const uno::Reference< chart2::data::XDataSequence >& xDataSequence )
2550 if( !xDataSequence.is() )
2551 return false;//have no data
2553 Sequence< uno::Any > aData;
2554 Reference< chart2::data::XNumericalDataSequence > xNumericalDataSequence( xDataSequence, uno::UNO_QUERY );
2555 if( xNumericalDataSequence.is() )
2557 Sequence< double > aDoubles( xNumericalDataSequence->getNumericalData() );
2558 sal_Int32 nCount = aDoubles.getLength();
2559 for( sal_Int32 i = 0; i < nCount; ++i )
2561 if( !::rtl::math::isNan( aDoubles[i] ) )
2562 return false;//have double value
2565 else
2567 aData = xDataSequence->getData();
2568 double fDouble = 0.0;
2569 sal_Int32 nCount = aData.getLength();
2570 for( sal_Int32 i = 0; i < nCount; ++i )
2572 if( (aData[i] >>= fDouble) && !::rtl::math::isNan( fDouble ) )
2573 return false;//have double value
2577 //no values found
2579 Reference< chart2::data::XTextualDataSequence > xTextualDataSequence( xDataSequence, uno::UNO_QUERY );
2580 if( xTextualDataSequence.is() )
2582 uno::Sequence< OUString > aStrings( xTextualDataSequence->getTextualData() );
2583 sal_Int32 nCount = aStrings.getLength();
2584 for( sal_Int32 i = 0; i < nCount; ++i )
2586 if( !aStrings[i].isEmpty() )
2587 return true;//have text
2590 else
2592 if( !aData.getLength() )
2593 aData = xDataSequence->getData();
2594 uno::Any aAny;
2595 OUString aString;
2596 sal_Int32 nCount = aData.getLength();
2597 for( sal_Int32 i = 0; i < nCount; ++i )
2599 if( (aData[i]>>=aString) && !aString.isEmpty() )
2600 return true;//have text
2603 //no doubles and no texts
2604 return false;
2608 void SchXMLExportHelper_Impl::exportSeries(
2609 const Reference< chart2::XDiagram > & xNewDiagram,
2610 const awt::Size & rPageSize,
2611 sal_Bool bExportContent,
2612 sal_Bool bHasTwoYAxes )
2614 Reference< chart2::XCoordinateSystemContainer > xBCooSysCnt( xNewDiagram, uno::UNO_QUERY );
2615 if( ! xBCooSysCnt.is())
2616 return;
2617 Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
2619 OUString aFirstXDomainRange;
2620 OUString aFirstYDomainRange;
2622 std::vector< XMLPropertyState > aPropertyStates;
2624 const OUString sNumFormat("NumberFormat");
2625 const OUString sPercentageNumFormat( "PercentageNumberFormat");
2627 Sequence< Reference< chart2::XCoordinateSystem > >
2628 aCooSysSeq( xBCooSysCnt->getCoordinateSystems());
2629 for( sal_Int32 nCSIdx=0; nCSIdx<aCooSysSeq.getLength(); ++nCSIdx )
2631 Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nCSIdx], uno::UNO_QUERY );
2632 if( ! xCTCnt.is())
2633 continue;
2634 Sequence< Reference< chart2::XChartType > > aCTSeq( xCTCnt->getChartTypes());
2635 for( sal_Int32 nCTIdx=0; nCTIdx<aCTSeq.getLength(); ++nCTIdx )
2637 Reference< chart2::XDataSeriesContainer > xDSCnt( aCTSeq[nCTIdx], uno::UNO_QUERY );
2638 if( ! xDSCnt.is())
2639 continue;
2640 // note: if xDSCnt.is() then also aCTSeq[nCTIdx]
2641 OUString aChartType( aCTSeq[nCTIdx]->getChartType());
2642 OUString aLabelRole = aCTSeq[nCTIdx]->getRoleOfSequenceForSeriesLabel();
2644 // special export for stock charts
2645 if ( aChartType == "com.sun.star.chart2.CandleStickChartType" )
2647 sal_Bool bJapaneseCandleSticks = sal_False;
2648 Reference< beans::XPropertySet > xCTProp( aCTSeq[nCTIdx], uno::UNO_QUERY );
2649 if( xCTProp.is())
2650 xCTProp->getPropertyValue( OUString( "Japanese" )) >>= bJapaneseCandleSticks;
2651 exportCandleStickSeries(
2652 xDSCnt->getDataSeries(), xNewDiagram, bJapaneseCandleSticks, bExportContent );
2653 continue;
2656 // export dataseries for current chart-type
2657 Sequence< Reference< chart2::XDataSeries > > aSeriesSeq( xDSCnt->getDataSeries());
2658 for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeriesSeq.getLength(); ++nSeriesIdx )
2660 // export series
2661 Reference< chart2::data::XDataSource > xSource( aSeriesSeq[nSeriesIdx], uno::UNO_QUERY );
2662 if( xSource.is())
2664 SvXMLElementExport* pSeries = NULL;
2665 Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeqCnt(
2666 xSource->getDataSequences());
2667 sal_Int32 nMainSequenceIndex = -1;
2668 sal_Int32 nSeriesLength = 0;
2669 sal_Int32 nAttachedAxis = chart::ChartAxisAssign::PRIMARY_Y;
2670 sal_Bool bHasMeanValueLine = false;
2671 chart::ChartRegressionCurveType eRegressionType( chart::ChartRegressionCurveType_NONE );
2672 Reference< beans::XPropertySet > xPropSet;
2673 tLabelValuesDataPair aSeriesLabelValuesPair;
2675 // search for main sequence and create a series element
2677 Reference< chart2::data::XDataSequence > xValuesSeq;
2678 Reference< chart2::data::XDataSequence > xLabelSeq;
2679 sal_Int32 nSeqIdx=0;
2680 for( ; nSeqIdx<aSeqCnt.getLength(); ++nSeqIdx )
2682 OUString aRole;
2683 Reference< chart2::data::XDataSequence > xTempValueSeq( aSeqCnt[nSeqIdx]->getValues() );
2684 if( nMainSequenceIndex==-1 )
2686 Reference< beans::XPropertySet > xSeqProp( xTempValueSeq, uno::UNO_QUERY );
2687 if( xSeqProp.is())
2688 xSeqProp->getPropertyValue(OUString( "Role" )) >>= aRole;
2689 // "main" sequence
2690 if( aRole.equals( aLabelRole ))
2692 xValuesSeq.set( xTempValueSeq );
2693 xLabelSeq.set( aSeqCnt[nSeqIdx]->getLabel());
2694 nMainSequenceIndex = nSeqIdx;
2697 sal_Int32 nSequenceLength = (xTempValueSeq.is()? xTempValueSeq->getData().getLength() : sal_Int32(0));
2698 if( nSeriesLength < nSequenceLength )
2699 nSeriesLength = nSequenceLength;
2702 // have found the main sequence, then xValuesSeq and
2703 // xLabelSeq contain those. Otherwise both are empty
2705 // get property states for autostyles
2708 xPropSet = SchXMLSeriesHelper::createOldAPISeriesPropertySet(
2709 aSeriesSeq[nSeriesIdx], mrExport.GetModel() );
2711 catch( const uno::Exception & rEx )
2713 SAL_INFO("xmloff.chart", "Series not found or no XPropertySet: " << rEx.Message );
2714 continue;
2716 if( xPropSet.is())
2718 // determine attached axis
2721 Any aAny( xPropSet->getPropertyValue(
2722 OUString( "Axis" )));
2723 aAny >>= nAttachedAxis;
2725 aAny = xPropSet->getPropertyValue(
2726 OUString( "MeanValue" ));
2727 aAny >>= bHasMeanValueLine;
2729 aAny = xPropSet->getPropertyValue(
2730 OUString( "RegressionCurves" ));
2731 aAny >>= eRegressionType;
2733 catch( const beans::UnknownPropertyException & rEx )
2735 SAL_INFO("xmloff.chart", "Required property not found in DataRowProperties: " << rEx.Message );
2738 const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
2739 if( nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 )
2741 lcl_exportNumberFormat( sNumFormat, xPropSet, mrExport );
2742 lcl_exportNumberFormat( sPercentageNumFormat, xPropSet, mrExport );
2745 if( mxExpPropMapper.is())
2746 aPropertyStates = mxExpPropMapper->Filter( xPropSet );
2749 if( bExportContent )
2751 if( bHasTwoYAxes )
2753 if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
2754 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y );
2755 else
2756 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y );
2759 // write style name
2760 AddAutoStyleAttribute( aPropertyStates );
2762 if( xValuesSeq.is())
2763 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS,
2764 lcl_ConvertRange(
2765 xValuesSeq->getSourceRangeRepresentation(),
2766 xNewDoc ));
2767 else
2768 // #i75297# allow empty series, export empty range to have all ranges on import
2769 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, OUString());
2771 if( xLabelSeq.is())
2772 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS,
2773 lcl_ConvertRange(
2774 xLabelSeq->getSourceRangeRepresentation(),
2775 xNewDoc ));
2776 if( xLabelSeq.is() || xValuesSeq.is() )
2777 aSeriesLabelValuesPair = tLabelValuesDataPair( xLabelSeq, xValuesSeq );
2779 // chart-type for mixed types
2780 enum XMLTokenEnum eCTToken(
2781 SchXMLTools::getTokenByChartType( aChartType, false /* bUseOldNames */ ));
2782 //@todo: get token for current charttype
2783 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_CLASS,
2784 mrExport.GetNamespaceMap().GetQNameByKey(
2785 XML_NAMESPACE_CHART, GetXMLToken( eCTToken )));
2787 // open series element until end of for loop
2788 pSeries = new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_SERIES, sal_True, sal_True );
2790 else // autostyles
2792 CollectAutoStyle( aPropertyStates );
2794 // remove property states for autostyles
2795 aPropertyStates.clear();
2799 // export domain elements if we have a series parent element
2800 if( pSeries )
2802 // domain elements
2803 if( bExportContent )
2805 bool bIsScatterChart = aChartType == "com.sun.star.chart2.ScatterChartType";
2806 bool bIsBubbleChart = aChartType == "com.sun.star.chart2.BubbleChartType";
2807 Reference< chart2::data::XDataSequence > xYValuesForBubbleChart;
2808 if( bIsBubbleChart )
2810 Reference< chart2::data::XLabeledDataSequence > xSequence( lcl_getDataSequenceByRole( aSeqCnt, OUString( "values-y" ) ) );
2811 if( xSequence.is() )
2813 xYValuesForBubbleChart = xSequence->getValues();
2814 if( !lcl_exportDomainForThisSequence( xYValuesForBubbleChart, aFirstYDomainRange, mrExport ) )
2815 xYValuesForBubbleChart = 0;
2818 if( bIsScatterChart || bIsBubbleChart )
2820 Reference< chart2::data::XLabeledDataSequence > xSequence( lcl_getDataSequenceByRole( aSeqCnt, OUString( "values-x" ) ) );
2821 if( xSequence.is() )
2823 Reference< chart2::data::XDataSequence > xValues( xSequence->getValues() );
2824 if( lcl_exportDomainForThisSequence( xValues, aFirstXDomainRange, mrExport ) )
2825 m_aDataSequencesToExport.push_back( tLabelValuesDataPair(
2826 (uno::Reference< chart2::data::XDataSequence >)0, xValues ));
2828 else if( nSeriesIdx==0 )
2830 //might be that the categories are used as x-values (e.g. for date axis) -> export them accordingly
2831 Reference< chart2::data::XLabeledDataSequence > xCategories( lcl_getCategories( xNewDiagram ) );
2832 if( xCategories.is() )
2834 Reference< chart2::data::XDataSequence > xValues( xCategories->getValues() );
2835 if( !lcl_hasNoValuesButText( xValues ) )
2836 lcl_exportDomainForThisSequence( xValues, aFirstXDomainRange, mrExport );
2840 if( xYValuesForBubbleChart.is() )
2841 m_aDataSequencesToExport.push_back( tLabelValuesDataPair(
2842 (uno::Reference< chart2::data::XDataSequence >)0, xYValuesForBubbleChart ));
2846 // add sequences for main sequence after domain sequences,
2847 // so that the export of the local table has the correct order
2848 if( bExportContent &&
2849 (aSeriesLabelValuesPair.first.is() || aSeriesLabelValuesPair.second.is()))
2850 m_aDataSequencesToExport.push_back( aSeriesLabelValuesPair );
2852 // statistical objects:
2853 // regression curves and mean value lines
2854 if( bHasMeanValueLine &&
2855 xPropSet.is() &&
2856 mxExpPropMapper.is() )
2858 Reference< beans::XPropertySet > xStatProp;
2861 Any aPropAny( xPropSet->getPropertyValue(
2862 OUString( "DataMeanValueProperties" )));
2863 aPropAny >>= xStatProp;
2865 catch( const uno::Exception & rEx )
2867 SAL_INFO("xmloff.chart", "Exception caught during Export of series - optional DataMeanValueProperties not available: " << rEx.Message );
2870 if( xStatProp.is() )
2872 aPropertyStates = mxExpPropMapper->Filter( xStatProp );
2874 if( !aPropertyStates.empty() )
2876 // write element
2877 if( bExportContent )
2879 // add style name attribute
2880 AddAutoStyleAttribute( aPropertyStates );
2882 SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_MEAN_VALUE, sal_True, sal_True );
2884 else // autostyles
2886 CollectAutoStyle( aPropertyStates );
2892 if( eRegressionType != chart::ChartRegressionCurveType_NONE &&
2893 xPropSet.is() &&
2894 mxExpPropMapper.is() )
2896 exportRegressionCurve( aSeriesSeq[nSeriesIdx], xPropSet, rPageSize, bExportContent );
2899 exportErrorBar( xPropSet,false, bExportContent ); // X ErrorBar
2900 exportErrorBar( xPropSet,true, bExportContent ); // Y ErrorBar
2902 exportDataPoints(
2903 uno::Reference< beans::XPropertySet >( aSeriesSeq[nSeriesIdx], uno::UNO_QUERY ),
2904 nSeriesLength, xNewDiagram, bExportContent );
2906 // close series element
2907 if( pSeries )
2908 delete pSeries;
2911 aPropertyStates.clear();
2916 void SchXMLExportHelper_Impl::exportRegressionCurve(
2917 const Reference< chart2::XDataSeries > & xSeries,
2918 const Reference< beans::XPropertySet > & xSeriesProp,
2919 const awt::Size & rPageSize,
2920 sal_Bool bExportContent )
2922 OSL_ASSERT( mxExpPropMapper.is());
2924 std::vector< XMLPropertyState > aPropertyStates;
2925 std::vector< XMLPropertyState > aEquationPropertyStates;
2926 Reference< beans::XPropertySet > xStatProp;
2929 Any aPropAny( xSeriesProp->getPropertyValue(
2930 OUString( "DataRegressionProperties" )));
2931 aPropAny >>= xStatProp;
2933 catch( const uno::Exception & rEx )
2935 SAL_INFO("xmloff.chart", "Exception caught during Export of series - optional DataRegressionProperties not available: " << rEx.Message );
2938 if( xStatProp.is() )
2940 Reference< chart2::XRegressionCurve > xRegCurve( SchXMLTools::getRegressionCurve( xSeries ));
2941 Reference< beans::XPropertySet > xEquationProperties;
2942 if( xRegCurve.is())
2943 xEquationProperties.set( xRegCurve->getEquationProperties());
2945 bool bShowEquation = false;
2946 bool bShowRSquared = false;
2947 bool bExportEquation = false;
2948 aPropertyStates = mxExpPropMapper->Filter( xStatProp );
2949 if( xEquationProperties.is())
2951 xEquationProperties->getPropertyValue( OUString( "ShowEquation" ))
2952 >>= bShowEquation;
2953 xEquationProperties->getPropertyValue( OUString( "ShowCorrelationCoefficient" ))
2954 >>= bShowRSquared;
2955 bExportEquation = ( bShowEquation || bShowRSquared );
2956 const SvtSaveOptions::ODFDefaultVersion nCurrentVersion( SvtSaveOptions().GetODFDefaultVersion() );
2957 if( nCurrentVersion < SvtSaveOptions::ODFVER_012 )
2958 bExportEquation=false;
2959 if( bExportEquation )
2961 // number format
2962 sal_Int32 nNumberFormat = 0;
2963 if( ( xEquationProperties->getPropertyValue(
2964 OUString( "NumberFormat" )) >>= nNumberFormat ) &&
2965 nNumberFormat != -1 )
2967 mrExport.addDataStyle( nNumberFormat );
2969 aEquationPropertyStates = mxExpPropMapper->Filter( xEquationProperties );
2973 if( !aPropertyStates.empty() || bExportEquation )
2975 // write element
2976 if( bExportContent )
2978 // add style name attribute
2979 if( !aPropertyStates.empty())
2980 AddAutoStyleAttribute( aPropertyStates );
2981 SvXMLElementExport aRegressionExport( mrExport, XML_NAMESPACE_CHART, XML_REGRESSION_CURVE, sal_True, sal_True );
2982 if( bExportEquation )
2984 // default is true
2985 if( !bShowEquation )
2986 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_DISPLAY_EQUATION, XML_FALSE );
2987 // default is false
2988 if( bShowRSquared )
2989 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_DISPLAY_R_SQUARE, XML_TRUE );
2991 // export position
2992 chart2::RelativePosition aRelativePosition;
2993 if( xEquationProperties->getPropertyValue(
2994 OUString( "RelativePosition")) >>= aRelativePosition )
2996 double fX = aRelativePosition.Primary * rPageSize.Width;
2997 double fY = aRelativePosition.Secondary * rPageSize.Height;
2998 awt::Point aPos;
2999 aPos.X = static_cast< sal_Int32 >( ::rtl::math::round( fX ));
3000 aPos.Y = static_cast< sal_Int32 >( ::rtl::math::round( fY ));
3001 addPosition( aPos );
3004 if( !aEquationPropertyStates.empty())
3005 AddAutoStyleAttribute( aEquationPropertyStates );
3007 SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_EQUATION, sal_True, sal_True );
3010 else // autostyles
3012 if( !aPropertyStates.empty())
3013 CollectAutoStyle( aPropertyStates );
3014 if( bExportEquation && !aEquationPropertyStates.empty())
3015 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 /// Dont 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 >)0, *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, sal_True, sal_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 sal_Bool bJapaneseCandleSticks,
3106 sal_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, OUString( "values-last" ));
3128 if( bExportContent )
3130 Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
3131 //@todo: export data points
3133 // open
3134 if( bJapaneseCandleSticks )
3136 tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole(
3137 aSeqCnt, OUString( "values-first" ), xNewDoc, m_aDataSequencesToExport ));
3138 if( !aRanges.second.isEmpty())
3139 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, aRanges.second );
3140 if( !aRanges.first.isEmpty())
3141 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS, aRanges.first );
3142 if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
3143 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y );
3144 else
3145 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y );
3146 SvXMLElementExport aOpenSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, sal_True, sal_True );
3147 // export empty data points
3148 exportDataPoints( 0, nSeriesLength, xDiagram, bExportContent );
3151 // low
3153 tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole(
3154 aSeqCnt, OUString( "values-min" ), xNewDoc, m_aDataSequencesToExport ));
3155 if( !aRanges.second.isEmpty())
3156 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, aRanges.second );
3157 if( !aRanges.first.isEmpty())
3158 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS, aRanges.first );
3159 if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
3160 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y );
3161 else
3162 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y );
3163 SvXMLElementExport aLowSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, sal_True, sal_True );
3164 // export empty data points
3165 exportDataPoints( 0, nSeriesLength, xDiagram, bExportContent );
3168 // high
3170 tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole(
3171 aSeqCnt, OUString( "values-max" ), xNewDoc, m_aDataSequencesToExport ));
3172 if( !aRanges.second.isEmpty())
3173 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, aRanges.second );
3174 if( !aRanges.first.isEmpty())
3175 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS, aRanges.first );
3176 if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
3177 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y );
3178 else
3179 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y );
3180 SvXMLElementExport aHighSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, sal_True, sal_True );
3181 // export empty data points
3182 exportDataPoints( 0, nSeriesLength, xDiagram, bExportContent );
3185 // close
3187 tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole(
3188 aSeqCnt, OUString( "values-last" ), xNewDoc, m_aDataSequencesToExport ));
3189 if( !aRanges.second.isEmpty())
3190 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, aRanges.second );
3191 if( !aRanges.first.isEmpty())
3192 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS, aRanges.first );
3193 if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
3194 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y );
3195 else
3196 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y );
3197 SvXMLElementExport aCloseSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, sal_True, sal_True );
3198 // export empty data points
3199 exportDataPoints( 0, nSeriesLength, xDiagram, bExportContent );
3202 else // autostyles
3204 // for close series
3206 // remove property states for autostyles
3211 void SchXMLExportHelper_Impl::exportDataPoints(
3212 const uno::Reference< beans::XPropertySet > & xSeriesProperties,
3213 sal_Int32 nSeriesLength,
3214 const uno::Reference< chart2::XDiagram > & xDiagram,
3215 sal_Bool bExportContent )
3217 // data-points
3218 // -----------
3219 // write data-points only if they contain autostyles
3220 // objects with equal autostyles are grouped using the attribute
3221 // repeat="number"
3223 // Note: if only the nth data-point has autostyles there is an element
3224 // without style and repeat="n-1" attribute written in advance.
3226 // the sequence aDataPointSeq contains indices of data-points that
3227 // do have own attributes. This increases the performance substantially.
3229 // more performant version for #93600#
3230 if( mxExpPropMapper.is())
3232 uno::Reference< chart2::XDataSeries > xSeries( xSeriesProperties, uno::UNO_QUERY );
3234 std::vector< XMLPropertyState > aPropertyStates;
3236 const OUString sNumFormat("NumberFormat");
3237 const OUString sPercentageNumFormat( "PercentageNumberFormat");
3239 bool bVaryColorsByPoint = false;
3240 Sequence< sal_Int32 > aDataPointSeq;
3241 if( xSeriesProperties.is())
3243 Any aAny = xSeriesProperties->getPropertyValue(
3244 OUString( "AttributedDataPoints" ));
3245 aAny >>= aDataPointSeq;
3246 xSeriesProperties->getPropertyValue(
3247 OUString( "VaryColorsByPoint" )) >>= bVaryColorsByPoint;
3251 sal_Int32 nSize = aDataPointSeq.getLength();
3252 SAL_WARN_IF( nSize > nSeriesLength, "xmloff.chart", "Too many point attributes" );
3254 const sal_Int32 * pPoints = aDataPointSeq.getConstArray();
3255 sal_Int32 nElement;
3256 sal_Int32 nRepeat;
3257 Reference< chart2::XColorScheme > xColorScheme;
3258 if( xDiagram.is())
3259 xColorScheme.set( xDiagram->getDefaultColorScheme());
3261 ::std::list< SchXMLDataPointStruct > aDataPointList;
3263 sal_Int32 nLastIndex = -1;
3264 sal_Int32 nCurrIndex = 0;
3266 // collect elements
3267 if( bVaryColorsByPoint && xColorScheme.is() )
3269 ::std::set< sal_Int32 > aAttrPointSet;
3270 ::std::copy( pPoints, pPoints + aDataPointSeq.getLength(),
3271 ::std::inserter( aAttrPointSet, aAttrPointSet.begin()));
3272 const ::std::set< sal_Int32 >::const_iterator aEndIt( aAttrPointSet.end());
3273 for( nElement = 0; nElement < nSeriesLength; ++nElement )
3275 aPropertyStates.clear();
3276 uno::Reference< beans::XPropertySet > xPropSet;
3277 bool bExportNumFmt = false;
3278 if( aAttrPointSet.find( nElement ) != aEndIt )
3282 xPropSet = SchXMLSeriesHelper::createOldAPIDataPointPropertySet(
3283 xSeries, nElement, mrExport.GetModel() );
3284 bExportNumFmt = true;
3286 catch( const uno::Exception & rEx )
3288 SAL_INFO("xmloff.chart", "Exception caught during Export of data point: " << rEx.Message );
3291 else
3293 // property set only containing the color
3294 xPropSet.set( new ::xmloff::chart::ColorPropertySet(
3295 xColorScheme->getColorByIndex( nElement )));
3297 SAL_WARN_IF( !xPropSet.is(), "xmloff.chart", "Pie Segments should have properties" );
3298 if( xPropSet.is())
3300 const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
3301 if( nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 && bExportNumFmt )
3303 lcl_exportNumberFormat( sNumFormat, xPropSet, mrExport );
3304 lcl_exportNumberFormat( sPercentageNumFormat, xPropSet, mrExport );
3307 aPropertyStates = mxExpPropMapper->Filter( xPropSet );
3308 if( !aPropertyStates.empty() )
3310 if( bExportContent )
3312 // write data-point with style
3313 SAL_WARN_IF( maAutoStyleNameQueue.empty(), "xmloff.chart", "Autostyle queue empty!" );
3315 SchXMLDataPointStruct aPoint;
3316 aPoint.maStyleName = maAutoStyleNameQueue.front();
3317 maAutoStyleNameQueue.pop();
3318 aDataPointList.push_back( aPoint );
3320 else
3322 CollectAutoStyle( aPropertyStates );
3327 SAL_WARN_IF( bExportContent && (static_cast<sal_Int32>(aDataPointList.size()) != nSeriesLength), "xmloff.chart", "not enough data points on content export" );
3329 else
3331 for( nElement = 0; nElement < nSize; ++nElement )
3333 aPropertyStates.clear();
3334 nCurrIndex = pPoints[ nElement ];
3335 //assuming sorted indices in pPoints
3337 if( nCurrIndex<0 || nCurrIndex>=nSeriesLength )
3338 break;
3340 // write leading empty data points
3341 if( nCurrIndex - nLastIndex > 1 )
3343 SchXMLDataPointStruct aPoint;
3344 aPoint.mnRepeat = nCurrIndex - nLastIndex - 1;
3345 aDataPointList.push_back( aPoint );
3348 uno::Reference< beans::XPropertySet > xPropSet;
3349 // get property states
3352 xPropSet = SchXMLSeriesHelper::createOldAPIDataPointPropertySet(
3353 xSeries, nCurrIndex, mrExport.GetModel() );
3355 catch( const uno::Exception & rEx )
3357 SAL_INFO("xmloff.chart", "Exception caught during Export of data point: " << rEx.Message );
3359 if( xPropSet.is())
3361 const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
3362 if( nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 )
3364 lcl_exportNumberFormat( sNumFormat, xPropSet, mrExport );
3365 lcl_exportNumberFormat( sPercentageNumFormat, xPropSet, mrExport );
3368 aPropertyStates = mxExpPropMapper->Filter( xPropSet );
3369 if( !aPropertyStates.empty() )
3371 if( bExportContent )
3373 // write data-point with style
3374 SAL_WARN_IF( maAutoStyleNameQueue.empty(), "xmloff.chart", "Autostyle queue empty!" );
3375 SchXMLDataPointStruct aPoint;
3376 aPoint.maStyleName = maAutoStyleNameQueue.front();
3377 maAutoStyleNameQueue.pop();
3379 aDataPointList.push_back( aPoint );
3380 nLastIndex = nCurrIndex;
3382 else
3384 CollectAutoStyle( aPropertyStates );
3386 continue;
3390 // if we get here the property states are empty
3391 SchXMLDataPointStruct aPoint;
3392 aDataPointList.push_back( aPoint );
3394 nLastIndex = nCurrIndex;
3396 // final empty elements
3397 nRepeat = nSeriesLength - nLastIndex - 1;
3398 if( nRepeat > 0 )
3400 SchXMLDataPointStruct aPoint;
3401 aPoint.mnRepeat = nRepeat;
3402 aDataPointList.push_back( aPoint );
3406 if( bExportContent )
3408 // write elements (merge equal ones)
3409 ::std::list< SchXMLDataPointStruct >::iterator aIter = aDataPointList.begin();
3410 SchXMLDataPointStruct aPoint;
3411 SchXMLDataPointStruct aLastPoint;
3413 // initialize so that it doesn't matter if
3414 // the element is counted in the first iteration
3415 aLastPoint.mnRepeat = 0;
3417 for( ; aIter != aDataPointList.end(); ++aIter )
3419 aPoint = (*aIter);
3421 if( aPoint.maStyleName == aLastPoint.maStyleName )
3422 aPoint.mnRepeat += aLastPoint.mnRepeat;
3423 else if( aLastPoint.mnRepeat > 0 )
3425 // write last element
3426 if( !aLastPoint.maStyleName.isEmpty() )
3427 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_STYLE_NAME, aLastPoint.maStyleName );
3429 if( aLastPoint.mnRepeat > 1 )
3430 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_REPEATED,
3431 OUString::valueOf( (sal_Int64)( aLastPoint.mnRepeat ) ));
3433 SvXMLElementExport aPointElem( mrExport, XML_NAMESPACE_CHART, XML_DATA_POINT, sal_True, sal_True );
3435 aLastPoint = aPoint;
3437 // write last element if it hasn't been written in last iteration
3438 if( aPoint.maStyleName == aLastPoint.maStyleName )
3440 if( !aLastPoint.maStyleName.isEmpty() )
3441 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_STYLE_NAME, aLastPoint.maStyleName );
3443 if( aLastPoint.mnRepeat > 1 )
3444 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_REPEATED,
3445 OUString::valueOf( (sal_Int64)( aLastPoint.mnRepeat ) ));
3447 SvXMLElementExport aPointElem( mrExport, XML_NAMESPACE_CHART, XML_DATA_POINT, sal_True, sal_True );
3453 void SchXMLExportHelper_Impl::addPosition( const awt::Point & rPosition )
3455 mrExport.GetMM100UnitConverter().convertMeasureToXML(
3456 msStringBuffer, rPosition.X );
3457 msString = msStringBuffer.makeStringAndClear();
3458 mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_X, msString );
3460 mrExport.GetMM100UnitConverter().convertMeasureToXML(
3461 msStringBuffer, rPosition.Y );
3462 msString = msStringBuffer.makeStringAndClear();
3463 mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_Y, msString );
3466 void SchXMLExportHelper_Impl::addPosition( Reference< drawing::XShape > xShape )
3468 if( xShape.is())
3469 addPosition( xShape->getPosition());
3472 void SchXMLExportHelper_Impl::addSize( const awt::Size & rSize, bool bIsOOoNamespace)
3474 mrExport.GetMM100UnitConverter().convertMeasureToXML(
3475 msStringBuffer, rSize.Width );
3476 msString = msStringBuffer.makeStringAndClear();
3477 mrExport.AddAttribute( bIsOOoNamespace ? XML_NAMESPACE_CHART_EXT : XML_NAMESPACE_SVG , XML_WIDTH, msString );
3480 mrExport.GetMM100UnitConverter().convertMeasureToXML(
3481 msStringBuffer, rSize.Height);
3482 msString = msStringBuffer.makeStringAndClear();
3483 mrExport.AddAttribute( bIsOOoNamespace ? XML_NAMESPACE_CHART_EXT : XML_NAMESPACE_SVG, XML_HEIGHT, msString );
3486 void SchXMLExportHelper_Impl::addSize( Reference< drawing::XShape > xShape, bool bIsOOoNamespace )
3488 if( xShape.is())
3489 addSize( xShape->getSize(), bIsOOoNamespace );
3492 awt::Size SchXMLExportHelper_Impl::getPageSize( const Reference< chart2::XChartDocument > & xChartDoc ) const
3494 awt::Size aSize( 8000, 7000 );
3495 uno::Reference< embed::XVisualObject > xVisualObject( xChartDoc, uno::UNO_QUERY );
3496 SAL_WARN_IF( !xVisualObject.is(), "xmloff.chart", "need XVisualObject for page size" );
3497 if( xVisualObject.is() )
3498 aSize = xVisualObject->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );
3500 return aSize;
3503 void SchXMLExportHelper_Impl::CollectAutoStyle( const std::vector< XMLPropertyState >& aStates )
3505 if( !aStates.empty() )
3506 maAutoStyleNameQueue.push( GetAutoStylePoolP().Add( XML_STYLE_FAMILY_SCH_CHART_ID, aStates ));
3509 void SchXMLExportHelper_Impl::AddAutoStyleAttribute( const std::vector< XMLPropertyState >& aStates )
3511 if( !aStates.empty() )
3513 SAL_WARN_IF( maAutoStyleNameQueue.empty(), "xmloff.chart", "Autostyle queue empty!" );
3515 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_STYLE_NAME, maAutoStyleNameQueue.front() );
3516 maAutoStyleNameQueue.pop();
3520 void SchXMLExportHelper_Impl::exportText( const OUString& rText, bool bConvertTabsLFs )
3522 SchXMLTools::exportText( mrExport, rText, bConvertTabsLFs );
3525 // ========================================
3526 // class SchXMLExport
3527 // ========================================
3529 SchXMLExport::SchXMLExport(
3530 const Reference< uno::XComponentContext >& xContext,
3531 sal_uInt16 nExportFlags )
3532 : SvXMLExport( util::MeasureUnit::CM, xContext,
3533 ::xmloff::token::XML_CHART, nExportFlags ),
3534 maAutoStylePool( *this ),
3535 maExportHelper( *this, maAutoStylePool )
3537 if( getDefaultVersion() > SvtSaveOptions::ODFVER_012 )
3538 _GetNamespaceMap().Add( GetXMLToken(XML_NP_CHART_EXT), GetXMLToken(XML_N_CHART_EXT), XML_NAMESPACE_CHART_EXT);
3542 SchXMLExport::~SchXMLExport()
3544 // stop progress view
3545 if( mxStatusIndicator.is())
3547 mxStatusIndicator->end();
3548 mxStatusIndicator->reset();
3552 sal_uInt32 SchXMLExport::exportDoc( enum ::xmloff::token::XMLTokenEnum eClass )
3554 Reference< chart2::XChartDocument > xChartDoc( GetModel(), uno::UNO_QUERY );
3555 maExportHelper.m_pImpl->InitRangeSegmentationProperties( xChartDoc );
3556 return SvXMLExport::exportDoc( eClass );
3559 void SchXMLExport::_ExportStyles( sal_Bool bUsed )
3561 SvXMLExport::_ExportStyles( bUsed );
3564 void SchXMLExport::_ExportMasterStyles()
3566 // not available in chart
3567 SAL_INFO("xmloff.chart", "Master Style Export requested. Not available for Chart" );
3570 void SchXMLExport::_ExportAutoStyles()
3572 // there are no styles that require their own autostyles
3573 if( getExportFlags() & EXPORT_CONTENT )
3575 Reference< chart::XChartDocument > xChartDoc( GetModel(), uno::UNO_QUERY );
3576 if( xChartDoc.is())
3578 maExportHelper.m_pImpl->collectAutoStyles( xChartDoc );
3579 maExportHelper.m_pImpl->exportAutoStyles();
3581 else
3583 SAL_WARN("xmloff.chart", "Couldn't export chart due to wrong XModel (must be XChartDocument)" );
3588 void SchXMLExport::_ExportContent()
3590 Reference< chart::XChartDocument > xChartDoc( GetModel(), uno::UNO_QUERY );
3591 if( xChartDoc.is())
3593 // determine if data comes from the outside
3594 sal_Bool bIncludeTable = sal_True;
3596 Reference< chart2::XChartDocument > xNewDoc( xChartDoc, uno::UNO_QUERY );
3597 if( xNewDoc.is())
3599 // check if we have own data. If so we must not export the complete
3600 // range string, as this is our only indicator for having own or
3601 // external data. @todo: fix this in the file format!
3602 Reference< lang::XServiceInfo > xDPServiceInfo( xNewDoc->getDataProvider(), uno::UNO_QUERY );
3603 if( ! (xDPServiceInfo.is() && xDPServiceInfo->getImplementationName() == "com.sun.star.comp.chart.InternalDataProvider" ))
3605 bIncludeTable = sal_False;
3608 else
3610 Reference< lang::XServiceInfo > xServ( xChartDoc, uno::UNO_QUERY );
3611 if( xServ.is())
3613 if( xServ->supportsService(
3614 OUString( "com.sun.star.chart.ChartTableAddressSupplier" )))
3616 Reference< beans::XPropertySet > xProp( xServ, uno::UNO_QUERY );
3617 if( xProp.is())
3619 Any aAny;
3622 OUString sChartAddress;
3623 aAny = xProp->getPropertyValue(
3624 OUString( "ChartRangeAddress" ));
3625 aAny >>= sChartAddress;
3626 maExportHelper.m_pImpl->SetChartRangeAddress( sChartAddress );
3628 OUString sTableNumberList;
3629 aAny = xProp->getPropertyValue(
3630 OUString( "TableNumberList" ));
3631 aAny >>= sTableNumberList;
3632 maExportHelper.m_pImpl->SetTableNumberList( sTableNumberList );
3634 // do not include own table if there are external addresses
3635 bIncludeTable = sChartAddress.isEmpty();
3637 catch( const beans::UnknownPropertyException & )
3639 SAL_WARN("xmloff.chart", "Property ChartRangeAddress not supported by ChartDocument" );
3645 maExportHelper.m_pImpl->exportChart( xChartDoc, bIncludeTable );
3647 else
3649 SAL_WARN("xmloff.chart", "Couldn't export chart due to wrong XModel" );
3653 UniReference< XMLPropertySetMapper > SchXMLExport::GetPropertySetMapper() const
3655 return maExportHelper.m_pImpl->GetPropertySetMapper();
3658 void SchXMLExportHelper_Impl::InitRangeSegmentationProperties( const Reference< chart2::XChartDocument > & xChartDoc )
3660 if( xChartDoc.is())
3663 Reference< chart2::data::XDataProvider > xDataProvider( xChartDoc->getDataProvider() );
3664 SAL_WARN_IF( !xDataProvider.is(), "xmloff.chart", "No DataProvider" );
3665 if( xDataProvider.is())
3667 Reference< chart2::data::XDataSource > xDataSource( lcl_pressUsedDataIntoRectangularFormat( xChartDoc, mbHasCategoryLabels ));
3668 Sequence< beans::PropertyValue > aArgs( xDataProvider->detectArguments( xDataSource ));
3669 OUString sCellRange, sBrokenRange;
3670 bool bBrokenRangeAvailable = false;
3671 for( sal_Int32 i=0; i<aArgs.getLength(); ++i )
3673 if ( aArgs[i].Name == "CellRangeRepresentation" )
3674 aArgs[i].Value >>= sCellRange;
3675 else if ( aArgs[i].Name == "BrokenCellRangeForExport" )
3677 if( aArgs[i].Value >>= sBrokenRange )
3678 bBrokenRangeAvailable = true;
3680 else if ( aArgs[i].Name == "DataRowSource" )
3682 chart::ChartDataRowSource eRowSource;
3683 aArgs[i].Value >>= eRowSource;
3684 mbRowSourceColumns = ( eRowSource == chart::ChartDataRowSource_COLUMNS );
3686 else if ( aArgs[i].Name == "FirstCellAsLabel" )
3687 aArgs[i].Value >>= mbHasSeriesLabels;
3688 else if ( aArgs[i].Name == "SequenceMapping" )
3689 aArgs[i].Value >>= maSequenceMapping;
3690 else if ( aArgs[i].Name == "TableNumberList" )
3691 aArgs[i].Value >>= msTableNumberList;
3694 // #i79009# For Writer we have to export a broken version of the
3695 // range, where every row number is noe too large, so that older
3696 // version can correctly read those files.
3697 msChartAddress = (bBrokenRangeAvailable ? sBrokenRange : sCellRange);
3698 if( !msChartAddress.isEmpty() )
3700 // convert format to XML-conform one
3701 Reference< chart2::data::XRangeXMLConversion > xConversion( xDataProvider, uno::UNO_QUERY );
3702 if( xConversion.is())
3703 msChartAddress = xConversion->convertRangeToXML( msChartAddress );
3707 catch( const uno::Exception & ex )
3709 SAL_WARN("xmloff.chart", "Exception caught. Type: " << OUString::createFromAscii( typeid( ex ).name()) << ", Message: " << ex.Message);
3713 // export components ========================================
3715 // first version: everything goes in one storage
3717 Sequence< OUString > SAL_CALL SchXMLExport_getSupportedServiceNames() throw()
3719 const OUString aServiceName( "com.sun.star.comp.Chart.XMLExporter" );
3720 const Sequence< OUString > aSeq( &aServiceName, 1 );
3721 return aSeq;
3724 OUString SAL_CALL SchXMLExport_getImplementationName() throw()
3726 return OUString( "SchXMLExport.Compact" );
3729 Reference< uno::XInterface > SAL_CALL SchXMLExport_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception )
3731 // #110680#
3732 // #103997# removed some flags from EXPORT_ALL
3733 return (cppu::OWeakObject*)new SchXMLExport( comphelper::getComponentContext(rSMgr), EXPORT_ALL ^ ( EXPORT_SETTINGS | EXPORT_MASTERSTYLES | EXPORT_SCRIPTS ));
3736 // Oasis format
3737 Sequence< OUString > SAL_CALL SchXMLExport_Oasis_getSupportedServiceNames() throw()
3739 const OUString aServiceName( "com.sun.star.comp.Chart.XMLOasisExporter" );
3740 const Sequence< OUString > aSeq( &aServiceName, 1 );
3741 return aSeq;
3744 OUString SAL_CALL SchXMLExport_Oasis_getImplementationName() throw()
3746 return OUString( "SchXMLExport.Oasis.Compact" );
3749 Reference< uno::XInterface > SAL_CALL SchXMLExport_Oasis_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception )
3751 // #103997# removed some flags from EXPORT_ALL
3752 return (cppu::OWeakObject*)new SchXMLExport( comphelper::getComponentContext(rSMgr),
3753 (EXPORT_ALL ^ ( EXPORT_SETTINGS | EXPORT_MASTERSTYLES | EXPORT_SCRIPTS )) | EXPORT_OASIS );
3756 // ============================================================
3758 // multiple storage version: one for content / styles / meta
3760 Sequence< OUString > SAL_CALL SchXMLExport_Styles_getSupportedServiceNames() throw()
3762 const OUString aServiceName( "com.sun.star.comp.Chart.XMLStylesExporter" );
3763 const Sequence< OUString > aSeq( &aServiceName, 1 );
3764 return aSeq;
3767 OUString SAL_CALL SchXMLExport_Styles_getImplementationName() throw()
3769 return OUString( "SchXMLExport.Styles" );
3772 Reference< uno::XInterface > SAL_CALL SchXMLExport_Styles_createInstance(const Reference< lang::XMultiServiceFactory >& rSMgr) throw( uno::Exception )
3774 // #110680#
3775 return (cppu::OWeakObject*)new SchXMLExport( comphelper::getComponentContext(rSMgr), EXPORT_STYLES );
3778 // Oasis format
3779 Sequence< OUString > SAL_CALL SchXMLExport_Oasis_Styles_getSupportedServiceNames() throw()
3781 const OUString aServiceName( "com.sun.star.comp.Chart.XMLOasisStylesExporter" );
3782 const Sequence< OUString > aSeq( &aServiceName, 1 );
3783 return aSeq;
3786 OUString SAL_CALL SchXMLExport_Oasis_Styles_getImplementationName() throw()
3788 return OUString( "SchXMLExport.Oasis.Styles" );
3791 Reference< uno::XInterface > SAL_CALL SchXMLExport_Oasis_Styles_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception )
3793 return (cppu::OWeakObject*)new SchXMLExport( comphelper::getComponentContext(rSMgr), EXPORT_STYLES | EXPORT_OASIS );
3796 // ------------------------------------------------------------
3798 Sequence< OUString > SAL_CALL SchXMLExport_Content_getSupportedServiceNames() throw()
3800 const OUString aServiceName( "com.sun.star.comp.Chart.XMLContentExporter" );
3801 const Sequence< OUString > aSeq( &aServiceName, 1 );
3802 return aSeq;
3805 OUString SAL_CALL SchXMLExport_Content_getImplementationName() throw()
3807 return OUString( "SchXMLExport.Content" );
3810 Reference< uno::XInterface > SAL_CALL SchXMLExport_Content_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception )
3812 // #110680#
3813 return (cppu::OWeakObject*)new SchXMLExport( comphelper::getComponentContext(rSMgr), EXPORT_AUTOSTYLES | EXPORT_CONTENT | EXPORT_FONTDECLS );
3816 // Oasis format
3817 Sequence< OUString > SAL_CALL SchXMLExport_Oasis_Content_getSupportedServiceNames() throw()
3819 const OUString aServiceName( "com.sun.star.comp.Chart.XMLOasisContentExporter" );
3820 const Sequence< OUString > aSeq( &aServiceName, 1 );
3821 return aSeq;
3824 OUString SAL_CALL SchXMLExport_Oasis_Content_getImplementationName() throw()
3826 return OUString( "SchXMLExport.Oasis.Content" );
3829 Reference< uno::XInterface > SAL_CALL SchXMLExport_Oasis_Content_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception )
3831 return (cppu::OWeakObject*)new SchXMLExport( comphelper::getComponentContext(rSMgr), EXPORT_AUTOSTYLES | EXPORT_CONTENT | EXPORT_FONTDECLS | EXPORT_OASIS );
3834 // ------------------------------------------------------------
3836 // Oasis format
3837 Sequence< OUString > SAL_CALL SchXMLExport_Oasis_Meta_getSupportedServiceNames() throw()
3839 const OUString aServiceName( "com.sun.star.comp.Chart.XMLOasisMetaExporter" );
3840 const Sequence< OUString > aSeq( &aServiceName, 1 );
3841 return aSeq;
3844 OUString SAL_CALL SchXMLExport_Oasis_Meta_getImplementationName() throw()
3846 return OUString( "SchXMLExport.Oasis.Meta" );
3849 Reference< uno::XInterface > SAL_CALL SchXMLExport_Oasis_Meta_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception )
3851 return (cppu::OWeakObject*)new SchXMLExport( comphelper::getComponentContext(rSMgr), EXPORT_META | EXPORT_OASIS );
3855 // XServiceInfo
3856 OUString SAL_CALL SchXMLExport::getImplementationName() throw( uno::RuntimeException )
3858 switch( getExportFlags())
3860 case EXPORT_ALL:
3861 return SchXMLExport_getImplementationName();
3862 case EXPORT_STYLES:
3863 return SchXMLExport_Styles_getImplementationName();
3864 case ( EXPORT_AUTOSTYLES | EXPORT_CONTENT | EXPORT_FONTDECLS ):
3865 return SchXMLExport_Content_getImplementationName();
3867 // Oasis format
3868 case ( EXPORT_ALL | EXPORT_OASIS ):
3869 return SchXMLExport_Oasis_getImplementationName();
3870 case ( EXPORT_STYLES | EXPORT_OASIS ):
3871 return SchXMLExport_Oasis_Styles_getImplementationName();
3872 case ( EXPORT_AUTOSTYLES | EXPORT_CONTENT | EXPORT_FONTDECLS | EXPORT_OASIS ):
3873 return SchXMLExport_Oasis_Content_getImplementationName();
3874 case ( EXPORT_META | EXPORT_OASIS ):
3875 return SchXMLExport_Oasis_Meta_getImplementationName();
3877 case EXPORT_SETTINGS:
3878 // there is no settings component in chart
3879 default:
3880 return OUString( "SchXMLExport" );
3884 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */