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