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