1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sc.hxx" 30 31 #include <com/sun/star/util/XModifiable.hpp> 32 #include <com/sun/star/chart/ChartDataRowSource.hpp> 33 #include <com/sun/star/chart2/XChartDocument.hpp> 34 #include <com/sun/star/chart2/data/XDataProvider.hpp> 35 #include <com/sun/star/chart2/data/XDataReceiver.hpp> 36 #include <com/sun/star/embed/EmbedStates.hpp> 37 #include <com/sun/star/embed/XEmbeddedObject.hpp> 38 39 40 #ifdef _MSC_VER 41 #pragma optimize("",off) 42 #endif 43 44 // INCLUDE --------------------------------------------------------------- 45 46 #include <sfx2/objsh.hxx> 47 #include <svx/svditer.hxx> 48 #include <svx/svdoole2.hxx> 49 #include <svx/svdpage.hxx> 50 51 //REMOVE #ifndef SO2_DECL_SVINPLACEOBJECT_DEFINED 52 //REMOVE #define SO2_DECL_SVINPLACEOBJECT_DEFINED 53 //REMOVE SO2_DECL_REF(SvInPlaceObject) 54 //REMOVE #endif 55 56 #include "document.hxx" 57 #include "drwlayer.hxx" 58 #include "chartarr.hxx" 59 #include "chartlis.hxx" 60 #include "chartlock.hxx" 61 #include "refupdat.hxx" 62 #include <tools/globname.hxx> 63 #include <sot/exchange.hxx> 64 65 #include "miscuno.hxx" 66 #include "chart2uno.hxx" 67 #include "charthelper.hxx" 68 69 using namespace ::com::sun::star; 70 71 // ----------------------------------------------------------------------- 72 73 void lcl_GetChartParameters( const uno::Reference< chart2::XChartDocument >& xChartDoc, 74 rtl::OUString& rRanges, chart::ChartDataRowSource& rDataRowSource, 75 bool& rHasCategories, bool& rFirstCellAsLabel ) 76 { 77 rHasCategories = rFirstCellAsLabel = false; // default if not in sequence 78 79 uno::Reference< chart2::data::XDataReceiver > xReceiver( xChartDoc, uno::UNO_QUERY ); 80 81 uno::Reference< chart2::data::XDataSource > xDataSource = xReceiver->getUsedData(); 82 uno::Reference< chart2::data::XDataProvider > xProvider = xChartDoc->getDataProvider(); 83 84 if ( xProvider.is() ) 85 { 86 uno::Sequence< beans::PropertyValue > aArgs( xProvider->detectArguments( xDataSource ) ); 87 88 const beans::PropertyValue* pPropArray = aArgs.getConstArray(); 89 long nPropCount = aArgs.getLength(); 90 for (long i = 0; i < nPropCount; i++) 91 { 92 const beans::PropertyValue& rProp = pPropArray[i]; 93 String aPropName(rProp.Name); 94 95 if (aPropName.EqualsAscii( "CellRangeRepresentation" )) 96 rProp.Value >>= rRanges; 97 else if (aPropName.EqualsAscii( "DataRowSource" )) 98 rDataRowSource = (chart::ChartDataRowSource)ScUnoHelpFunctions::GetEnumFromAny( rProp.Value ); 99 else if (aPropName.EqualsAscii( "HasCategories" )) 100 rHasCategories = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value ); 101 else if (aPropName.EqualsAscii( "FirstCellAsLabel" )) 102 rFirstCellAsLabel = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value ); 103 } 104 } 105 } 106 107 void lcl_SetChartParameters( const uno::Reference< chart2::data::XDataReceiver >& xReceiver, 108 const rtl::OUString& rRanges, chart::ChartDataRowSource eDataRowSource, 109 bool bHasCategories, bool bFirstCellAsLabel ) 110 { 111 if ( xReceiver.is() ) 112 { 113 uno::Sequence< beans::PropertyValue > aArgs( 4 ); 114 aArgs[0] = beans::PropertyValue( 115 ::rtl::OUString::createFromAscii("CellRangeRepresentation"), -1, 116 uno::makeAny( rRanges ), beans::PropertyState_DIRECT_VALUE ); 117 aArgs[1] = beans::PropertyValue( 118 ::rtl::OUString::createFromAscii("HasCategories"), -1, 119 uno::makeAny( bHasCategories ), beans::PropertyState_DIRECT_VALUE ); 120 aArgs[2] = beans::PropertyValue( 121 ::rtl::OUString::createFromAscii("FirstCellAsLabel"), -1, 122 uno::makeAny( bFirstCellAsLabel ), beans::PropertyState_DIRECT_VALUE ); 123 aArgs[3] = beans::PropertyValue( 124 ::rtl::OUString::createFromAscii("DataRowSource"), -1, 125 uno::makeAny( eDataRowSource ), beans::PropertyState_DIRECT_VALUE ); 126 xReceiver->setArguments( aArgs ); 127 } 128 } 129 130 // update charts after loading old document 131 132 void ScDocument::UpdateAllCharts() 133 { 134 if ( !pDrawLayer || !pShell ) 135 return; 136 137 sal_uInt16 nDataCount = pChartCollection->GetCount(); 138 if ( !nDataCount ) 139 return ; // nothing to do 140 141 sal_uInt16 nPos; 142 143 for (SCTAB nTab=0; nTab<=MAXTAB; nTab++) 144 { 145 if (pTab[nTab]) 146 { 147 SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab)); 148 DBG_ASSERT(pPage,"Page ?"); 149 150 ScRange aRange; 151 SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS ); 152 SdrObject* pObject = aIter.Next(); 153 while (pObject) 154 { 155 if ( pObject->GetObjIdentifier() == OBJ_OLE2 ) 156 { 157 uno::Reference< embed::XEmbeddedObject > xIPObj = ((SdrOle2Obj*)pObject)->GetObjRef(); 158 if ( xIPObj.is() ) 159 { 160 String aIPName = ((SdrOle2Obj*)pObject)->GetPersistName(); 161 162 for (nPos=0; nPos<nDataCount; nPos++) 163 { 164 ScChartArray* pChartObj = (*pChartCollection)[nPos]; 165 if (pChartObj->GetName() == aIPName) 166 { 167 ScRangeListRef aRanges = pChartObj->GetRangeList(); 168 String sRangeStr; 169 aRanges->Format( sRangeStr, SCR_ABS_3D, this, GetAddressConvention() ); 170 171 chart::ChartDataRowSource eDataRowSource = chart::ChartDataRowSource_COLUMNS; 172 bool bHasCategories = pChartObj->HasRowHeaders(); 173 bool bFirstCellAsLabel = pChartObj->HasColHeaders(); 174 175 // Calc -> DataProvider 176 uno::Reference< chart2::data::XDataProvider > xDataProvider = 177 new ScChart2DataProvider( this ); 178 // Chart -> DataReceiver 179 uno::Reference< chart2::data::XDataReceiver > xReceiver; 180 uno::Reference< embed::XComponentSupplier > xCompSupp( xIPObj, uno::UNO_QUERY ); 181 if( xCompSupp.is()) 182 xReceiver.set( xCompSupp->getComponent(), uno::UNO_QUERY ); 183 if( xReceiver.is()) 184 { 185 // connect 186 xReceiver->attachDataProvider( xDataProvider ); 187 uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( 188 pShell->GetModel(), uno::UNO_QUERY ); 189 xReceiver->attachNumberFormatsSupplier( xNumberFormatsSupplier ); 190 191 lcl_SetChartParameters( xReceiver, sRangeStr, eDataRowSource, 192 bHasCategories, bFirstCellAsLabel ); 193 } 194 195 ScChartListener* pCL = new ScChartListener( 196 aIPName, this, pChartObj->GetRangeList() ); 197 pChartListenerCollection->Insert( pCL ); 198 pCL->StartListeningTo(); 199 } 200 } 201 } 202 } 203 pObject = aIter.Next(); 204 } 205 } 206 } 207 208 pChartCollection->FreeAll(); 209 } 210 211 sal_Bool ScDocument::HasChartAtPoint( SCTAB nTab, const Point& rPos, String* pName ) 212 { 213 if (pDrawLayer && pTab[nTab]) 214 { 215 SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab)); 216 DBG_ASSERT(pPage,"Page ?"); 217 218 SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS ); 219 SdrObject* pObject = aIter.Next(); 220 while (pObject) 221 { 222 if ( pObject->GetObjIdentifier() == OBJ_OLE2 && 223 pObject->GetCurrentBoundRect().IsInside(rPos) ) 224 { 225 // auch Chart-Objekte die nicht in der Collection sind 226 227 if (IsChart(pObject)) 228 { 229 if (pName) 230 *pName = ((SdrOle2Obj*)pObject)->GetPersistName(); 231 return sal_True; 232 } 233 } 234 pObject = aIter.Next(); 235 } 236 } 237 238 if (pName) 239 pName->Erase(); 240 return sal_False; // nix gefunden 241 } 242 243 void ScDocument::UpdateChartArea( const String& rChartName, 244 const ScRange& rNewArea, sal_Bool bColHeaders, sal_Bool bRowHeaders, 245 sal_Bool bAdd ) 246 { 247 ScRangeListRef aRLR( new ScRangeList ); 248 aRLR->Append( rNewArea ); 249 UpdateChartArea( rChartName, aRLR, bColHeaders, bRowHeaders, bAdd ); 250 } 251 252 uno::Reference< chart2::XChartDocument > ScDocument::GetChartByName( const String& rChartName ) 253 { 254 uno::Reference< chart2::XChartDocument > xReturn; 255 256 if (pDrawLayer) 257 { 258 sal_uInt16 nCount = pDrawLayer->GetPageCount(); 259 for (sal_uInt16 nTab=0; nTab<nCount; nTab++) 260 { 261 SdrPage* pPage = pDrawLayer->GetPage(nTab); 262 DBG_ASSERT(pPage,"Page ?"); 263 264 SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS ); 265 SdrObject* pObject = aIter.Next(); 266 while (pObject) 267 { 268 if ( pObject->GetObjIdentifier() == OBJ_OLE2 && 269 ((SdrOle2Obj*)pObject)->GetPersistName() == rChartName ) 270 { 271 xReturn.set( ScChartHelper::GetChartFromSdrObject( pObject ) ); 272 return xReturn; 273 } 274 pObject = aIter.Next(); 275 } 276 } 277 } 278 return xReturn; 279 } 280 void ScDocument::GetChartRanges( const String& rChartName, ::std::vector< ScRangeList >& rRangesVector, ScDocument* pSheetNameDoc ) 281 { 282 rRangesVector.clear(); 283 uno::Reference< chart2::XChartDocument > xChartDoc( GetChartByName( rChartName ) ); 284 if ( xChartDoc.is() ) 285 { 286 uno::Sequence< rtl::OUString > aRangeStrings; 287 ScChartHelper::GetChartRanges( xChartDoc, aRangeStrings ); 288 for( sal_Int32 nN=0; nN<aRangeStrings.getLength(); nN++ ) 289 { 290 ScRangeList aRanges; 291 aRanges.Parse( aRangeStrings[nN], pSheetNameDoc, SCA_VALID, pSheetNameDoc->GetAddressConvention() ); 292 rRangesVector.push_back(aRanges); 293 } 294 } 295 } 296 297 void ScDocument::SetChartRanges( const String& rChartName, const ::std::vector< ScRangeList >& rRangesVector ) 298 { 299 uno::Reference< chart2::XChartDocument > xChartDoc( GetChartByName( rChartName ) ); 300 if ( xChartDoc.is() ) 301 { 302 sal_Int32 nCount = static_cast<sal_Int32>( rRangesVector.size() ); 303 uno::Sequence< rtl::OUString > aRangeStrings(nCount); 304 for( sal_Int32 nN=0; nN<nCount; nN++ ) 305 { 306 ScRangeList aScRangeList( rRangesVector[nN] ); 307 String sRangeStr; // This range must be in Calc A1 format. 308 aScRangeList.Format( sRangeStr, SCR_ABS_3D, this ); 309 aRangeStrings[nN]=sRangeStr; 310 } 311 ScChartHelper::SetChartRanges( xChartDoc, aRangeStrings ); 312 } 313 } 314 315 void ScDocument::GetOldChartParameters( const String& rName, 316 ScRangeList& rRanges, sal_Bool& rColHeaders, sal_Bool& rRowHeaders ) 317 { 318 // used for undo of changing chart source area 319 320 if (!pDrawLayer) 321 return; 322 323 sal_uInt16 nCount = pDrawLayer->GetPageCount(); 324 for (sal_uInt16 nTab=0; nTab<nCount; nTab++) 325 { 326 SdrPage* pPage = pDrawLayer->GetPage(nTab); 327 DBG_ASSERT(pPage,"Page ?"); 328 329 SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS ); 330 SdrObject* pObject = aIter.Next(); 331 while (pObject) 332 { 333 if ( pObject->GetObjIdentifier() == OBJ_OLE2 && 334 ((SdrOle2Obj*)pObject)->GetPersistName() == rName ) 335 { 336 uno::Reference< chart2::XChartDocument > xChartDoc( ScChartHelper::GetChartFromSdrObject( pObject ) ); 337 if ( xChartDoc.is() ) 338 { 339 chart::ChartDataRowSource eDataRowSource = chart::ChartDataRowSource_COLUMNS; 340 bool bHasCategories = false; 341 bool bFirstCellAsLabel = false; 342 rtl::OUString aRangesStr; 343 lcl_GetChartParameters( xChartDoc, aRangesStr, eDataRowSource, bHasCategories, bFirstCellAsLabel ); 344 345 rRanges.Parse( aRangesStr, this ); 346 if ( eDataRowSource == chart::ChartDataRowSource_COLUMNS ) 347 { 348 rRowHeaders = bHasCategories; 349 rColHeaders = bFirstCellAsLabel; 350 } 351 else 352 { 353 rColHeaders = bHasCategories; 354 rRowHeaders = bFirstCellAsLabel; 355 } 356 } 357 return; 358 } 359 pObject = aIter.Next(); 360 } 361 } 362 } 363 364 void ScDocument::UpdateChartArea( const String& rChartName, 365 const ScRangeListRef& rNewList, sal_Bool bColHeaders, sal_Bool bRowHeaders, 366 sal_Bool bAdd ) 367 { 368 if (!pDrawLayer) 369 return; 370 371 for (SCTAB nTab=0; nTab<=MAXTAB && pTab[nTab]; nTab++) 372 { 373 SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab)); 374 DBG_ASSERT(pPage,"Page ?"); 375 376 SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS ); 377 SdrObject* pObject = aIter.Next(); 378 while (pObject) 379 { 380 if ( pObject->GetObjIdentifier() == OBJ_OLE2 && 381 ((SdrOle2Obj*)pObject)->GetPersistName() == rChartName ) 382 { 383 uno::Reference< chart2::XChartDocument > xChartDoc( ScChartHelper::GetChartFromSdrObject( pObject ) ); 384 uno::Reference< chart2::data::XDataReceiver > xReceiver( xChartDoc, uno::UNO_QUERY ); 385 if ( xChartDoc.is() && xReceiver.is() ) 386 { 387 ScRangeListRef aNewRanges; 388 chart::ChartDataRowSource eDataRowSource = chart::ChartDataRowSource_COLUMNS; 389 bool bHasCategories = false; 390 bool bFirstCellAsLabel = false; 391 rtl::OUString aRangesStr; 392 lcl_GetChartParameters( xChartDoc, aRangesStr, eDataRowSource, bHasCategories, bFirstCellAsLabel ); 393 394 sal_Bool bInternalData = xChartDoc->hasInternalDataProvider(); 395 396 if ( bAdd && !bInternalData ) 397 { 398 // append to old ranges, keep other settings 399 400 aNewRanges = new ScRangeList; 401 aNewRanges->Parse( aRangesStr, this ); 402 403 sal_uLong nAddCount = rNewList->Count(); 404 for ( sal_uLong nAdd=0; nAdd<nAddCount; nAdd++ ) 405 aNewRanges->Append( *rNewList->GetObject(nAdd) ); 406 } 407 else 408 { 409 // directly use new ranges (only eDataRowSource is used from old settings) 410 411 if ( eDataRowSource == chart::ChartDataRowSource_COLUMNS ) 412 { 413 bHasCategories = bRowHeaders; 414 bFirstCellAsLabel = bColHeaders; 415 } 416 else 417 { 418 bHasCategories = bColHeaders; 419 bFirstCellAsLabel = bRowHeaders; 420 } 421 aNewRanges = rNewList; 422 } 423 424 if ( bInternalData && pShell ) 425 { 426 // Calc -> DataProvider 427 uno::Reference< chart2::data::XDataProvider > xDataProvider = new ScChart2DataProvider( this ); 428 xReceiver->attachDataProvider( xDataProvider ); 429 uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( 430 pShell->GetModel(), uno::UNO_QUERY ); 431 xReceiver->attachNumberFormatsSupplier( xNumberFormatsSupplier ); 432 } 433 434 String sRangeStr; 435 aNewRanges->Format( sRangeStr, SCR_ABS_3D, this, GetAddressConvention() ); 436 437 lcl_SetChartParameters( xReceiver, sRangeStr, eDataRowSource, bHasCategories, bFirstCellAsLabel ); 438 439 pChartListenerCollection->ChangeListening( rChartName, aNewRanges ); 440 441 // ((SdrOle2Obj*)pObject)->GetNewReplacement(); 442 // pObject->ActionChanged(); 443 444 return; // nicht weitersuchen 445 } 446 } 447 pObject = aIter.Next(); 448 } 449 } 450 } 451 452 void ScDocument::UpdateChart( const String& rChartName ) 453 { 454 if (!pDrawLayer || bInDtorClear) 455 return; 456 uno::Reference< chart2::XChartDocument > xChartDoc( GetChartByName( rChartName ) ); 457 if( xChartDoc.is() ) 458 { 459 try 460 { 461 uno::Reference< util::XModifiable > xModif( xChartDoc, uno::UNO_QUERY_THROW ); 462 if( apTemporaryChartLock.get() ) 463 apTemporaryChartLock->AlsoLockThisChart( uno::Reference< frame::XModel >( xModif, uno::UNO_QUERY ) ); 464 xModif->setModified( sal_True ); 465 } 466 catch ( uno::Exception& ) 467 { 468 } 469 } 470 471 // After the update, chart keeps track of its own data source ranges, 472 // the listener doesn't need to listen anymore, except the chart has 473 // an internal data provider. 474 if ( !( xChartDoc.is() && xChartDoc->hasInternalDataProvider() ) && pChartListenerCollection ) 475 { 476 pChartListenerCollection->ChangeListening( rChartName, new ScRangeList ); 477 } 478 } 479 480 void ScDocument::RestoreChartListener( const String& rName ) 481 { 482 // Read the data ranges from the chart object, and start listening to those ranges again 483 // (called when a chart is saved, because then it might be swapped out and stop listening itself). 484 485 uno::Reference< embed::XEmbeddedObject > xObject = FindOleObjectByName( rName ); 486 if ( xObject.is() ) 487 { 488 uno::Reference< util::XCloseable > xComponent = xObject->getComponent(); 489 uno::Reference< chart2::XChartDocument > xChartDoc( xComponent, uno::UNO_QUERY ); 490 uno::Reference< chart2::data::XDataReceiver > xReceiver( xComponent, uno::UNO_QUERY ); 491 if ( xChartDoc.is() && xReceiver.is() && !xChartDoc->hasInternalDataProvider()) 492 { 493 uno::Sequence<rtl::OUString> aRepresentations( xReceiver->getUsedRangeRepresentations() ); 494 ScRangeListRef aRanges = new ScRangeList; 495 sal_Int32 nRangeCount = aRepresentations.getLength(); 496 for ( sal_Int32 i=0; i<nRangeCount; i++ ) 497 { 498 ScRange aRange; 499 ScAddress::Details aDetails(GetAddressConvention(), 0, 0); 500 if ( aRange.ParseAny( aRepresentations[i], this, aDetails ) & SCA_VALID ) 501 aRanges->Append( aRange ); 502 } 503 504 pChartListenerCollection->ChangeListening( rName, aRanges ); 505 } 506 } 507 } 508 509 void ScDocument::UpdateChartRef( UpdateRefMode eUpdateRefMode, 510 SCCOL nCol1, SCROW nRow1, SCTAB nTab1, 511 SCCOL nCol2, SCROW nRow2, SCTAB nTab2, 512 SCsCOL nDx, SCsROW nDy, SCsTAB nDz ) 513 { 514 if (!pDrawLayer) 515 return; 516 517 sal_uInt16 nChartCount = pChartListenerCollection->GetCount(); 518 for ( sal_uInt16 nIndex = 0; nIndex < nChartCount; nIndex++ ) 519 { 520 ScChartListener* pChartListener = 521 (ScChartListener*) (pChartListenerCollection->At(nIndex)); 522 ScRangeListRef aRLR( pChartListener->GetRangeList() ); 523 ScRangeListRef aNewRLR( new ScRangeList ); 524 sal_Bool bChanged = sal_False; 525 sal_Bool bDataChanged = sal_False; 526 for ( ScRangePtr pR = aRLR->First(); pR; pR = aRLR->Next() ) 527 { 528 SCCOL theCol1 = pR->aStart.Col(); 529 SCROW theRow1 = pR->aStart.Row(); 530 SCTAB theTab1 = pR->aStart.Tab(); 531 SCCOL theCol2 = pR->aEnd.Col(); 532 SCROW theRow2 = pR->aEnd.Row(); 533 SCTAB theTab2 = pR->aEnd.Tab(); 534 ScRefUpdateRes eRes = ScRefUpdate::Update( 535 this, eUpdateRefMode, 536 nCol1,nRow1,nTab1, nCol2,nRow2,nTab2, 537 nDx,nDy,nDz, 538 theCol1,theRow1,theTab1, 539 theCol2,theRow2,theTab2 ); 540 if ( eRes != UR_NOTHING ) 541 { 542 bChanged = sal_True; 543 aNewRLR->Append( ScRange( 544 theCol1, theRow1, theTab1, 545 theCol2, theRow2, theTab2 )); 546 if ( eUpdateRefMode == URM_INSDEL 547 && !bDataChanged 548 && (eRes == UR_INVALID || 549 ((pR->aEnd.Col() - pR->aStart.Col() 550 != theCol2 - theCol1) 551 || (pR->aEnd.Row() - pR->aStart.Row() 552 != theRow2 - theRow1) 553 || (pR->aEnd.Tab() - pR->aStart.Tab() 554 != theTab2 - theTab1))) ) 555 { 556 bDataChanged = sal_True; 557 } 558 } 559 else 560 aNewRLR->Append( *pR ); 561 } 562 if ( bChanged ) 563 { 564 #if 0 565 if ( nDz != 0 ) 566 { // #81844# sheet to be deleted or inserted or moved 567 // => no valid sheet names for references right now 568 pChartListener->ChangeListening( aNewRLR, bDataChanged ); 569 pChartListener->ScheduleSeriesRanges(); 570 } 571 else 572 #endif 573 { 574 // SetChartRangeList( pChartListener->GetString(), aNewRLR ); 575 // pChartListener->ChangeListening( aNewRLR, bDataChanged ); 576 577 // Force the chart to be loaded now, so it registers itself for UNO events. 578 // UNO broadcasts are done after UpdateChartRef, so the chart will get this 579 // reference change. 580 581 uno::Reference< embed::XEmbeddedObject > xIPObj = FindOleObjectByName( pChartListener->GetString() ); 582 svt::EmbeddedObjectRef::TryRunningState( xIPObj ); 583 584 // After the change, chart keeps track of its own data source ranges, 585 // the listener doesn't need to listen anymore, except the chart has 586 // an internal data provider. 587 bool bInternalDataProvider = false; 588 if ( xIPObj.is() ) 589 { 590 try 591 { 592 uno::Reference< chart2::XChartDocument > xChartDoc( xIPObj->getComponent(), uno::UNO_QUERY_THROW ); 593 bInternalDataProvider = xChartDoc->hasInternalDataProvider(); 594 } 595 catch ( uno::Exception& ) 596 { 597 } 598 } 599 if ( bInternalDataProvider ) 600 { 601 pChartListener->ChangeListening( aNewRLR, bDataChanged ); 602 } 603 else 604 { 605 pChartListener->ChangeListening( new ScRangeList, bDataChanged ); 606 } 607 } 608 } 609 } 610 } 611 612 613 void ScDocument::SetChartRangeList( const String& rChartName, 614 const ScRangeListRef& rNewRangeListRef ) 615 { 616 // called from ChartListener 617 618 if (!pDrawLayer) 619 return; 620 621 for (SCTAB nTab=0; nTab<=MAXTAB && pTab[nTab]; nTab++) 622 { 623 SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab)); 624 DBG_ASSERT(pPage,"Page ?"); 625 626 SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS ); 627 SdrObject* pObject = aIter.Next(); 628 while (pObject) 629 { 630 if ( pObject->GetObjIdentifier() == OBJ_OLE2 && 631 ((SdrOle2Obj*)pObject)->GetPersistName() == rChartName ) 632 { 633 uno::Reference< chart2::XChartDocument > xChartDoc( ScChartHelper::GetChartFromSdrObject( pObject ) ); 634 uno::Reference< chart2::data::XDataReceiver > xReceiver( xChartDoc, uno::UNO_QUERY ); 635 if ( xChartDoc.is() && xReceiver.is() ) 636 { 637 ScRangeListRef aNewRanges; 638 chart::ChartDataRowSource eDataRowSource = chart::ChartDataRowSource_COLUMNS; 639 bool bHasCategories = false; 640 bool bFirstCellAsLabel = false; 641 rtl::OUString aRangesStr; 642 lcl_GetChartParameters( xChartDoc, aRangesStr, eDataRowSource, bHasCategories, bFirstCellAsLabel ); 643 644 String sRangeStr; 645 rNewRangeListRef->Format( sRangeStr, SCR_ABS_3D, this, GetAddressConvention() ); 646 647 lcl_SetChartParameters( xReceiver, sRangeStr, eDataRowSource, bHasCategories, bFirstCellAsLabel ); 648 649 // don't modify pChartListenerCollection here, called from there 650 return; 651 } 652 } 653 pObject = aIter.Next(); 654 } 655 } 656 } 657 658 659 sal_Bool ScDocument::HasData( SCCOL nCol, SCROW nRow, SCTAB nTab ) 660 { 661 if (pTab[nTab]) 662 return pTab[nTab]->HasData( nCol, nRow ); 663 else 664 return sal_False; 665 } 666 667 uno::Reference< embed::XEmbeddedObject > 668 ScDocument::FindOleObjectByName( const String& rName ) 669 { 670 if (!pDrawLayer) 671 return uno::Reference< embed::XEmbeddedObject >(); 672 673 // die Seiten hier vom Draw-Layer nehmen, 674 // weil sie evtl. nicht mit den Tabellen uebereinstimmen 675 // (z.B. Redo von Tabelle loeschen, Draw-Redo passiert vor DeleteTab). 676 677 sal_uInt16 nCount = pDrawLayer->GetPageCount(); 678 for (sal_uInt16 nTab=0; nTab<nCount; nTab++) 679 { 680 SdrPage* pPage = pDrawLayer->GetPage(nTab); 681 DBG_ASSERT(pPage,"Page ?"); 682 683 SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS ); 684 SdrObject* pObject = aIter.Next(); 685 while (pObject) 686 { 687 if ( pObject->GetObjIdentifier() == OBJ_OLE2 ) 688 { 689 SdrOle2Obj * pOleObject ( dynamic_cast< SdrOle2Obj * >( pObject )); 690 if( pOleObject && 691 pOleObject->GetPersistName() == rName ) 692 { 693 return pOleObject->GetObjRef(); 694 } 695 } 696 pObject = aIter.Next(); 697 } 698 } 699 700 return uno::Reference< embed::XEmbeddedObject >(); 701 } 702 703 sal_Bool lcl_StringInCollection( const ScStrCollection* pColl, const String& rStr ) 704 { 705 if ( !pColl ) 706 return sal_False; 707 708 StrData aData( rStr ); 709 sal_uInt16 nDummy; 710 return pColl->Search( &aData, nDummy ); 711 } 712 713 void ScDocument::UpdateChartListenerCollection() 714 { 715 bChartListenerCollectionNeedsUpdate = sal_False; 716 if (!pDrawLayer) 717 return; 718 else 719 { 720 ScRange aRange; 721 // Range fuer Suche unwichtig 722 ScChartListener aCLSearcher( EMPTY_STRING, this, aRange ); 723 for (SCTAB nTab=0; nTab<=MAXTAB; nTab++) 724 { 725 if (pTab[nTab]) 726 { 727 SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab)); 728 DBG_ASSERT(pPage,"Page ?"); 729 730 if (!pPage) 731 continue; 732 733 SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS ); 734 SdrObject* pObject = aIter.Next(); 735 while (pObject) 736 { 737 if ( pObject->GetObjIdentifier() == OBJ_OLE2 ) 738 { 739 String aObjName = ((SdrOle2Obj*)pObject)->GetPersistName(); 740 aCLSearcher.SetString( aObjName ); 741 sal_uInt16 nIndex; 742 if ( pChartListenerCollection->Search( &aCLSearcher, nIndex ) ) 743 { 744 ((ScChartListener*) (pChartListenerCollection-> 745 At( nIndex )))->SetUsed( sal_True ); 746 } 747 else if ( lcl_StringInCollection( pOtherObjects, aObjName ) ) 748 { 749 // non-chart OLE object -> don't touch 750 } 751 else 752 { 753 bool bIsChart = false; 754 755 uno::Reference< embed::XEmbeddedObject > xIPObj = ((SdrOle2Obj*)pObject)->GetObjRef(); 756 DBG_ASSERT( xIPObj.is(), "No embedded object is given!"); 757 uno::Reference< ::com::sun::star::chart2::data::XDataReceiver > xReceiver; 758 uno::Reference< embed::XComponentSupplier > xCompSupp( xIPObj, uno::UNO_QUERY ); 759 if( xCompSupp.is()) 760 xReceiver.set( xCompSupp->getComponent(), uno::UNO_QUERY ); 761 762 // if the object is a chart2::XDataReceiver, we must attach as XDataProvider 763 if( xReceiver.is() && 764 !PastingDrawFromOtherDoc()) 765 { 766 // NOTE: this currently does not work as we are 767 // unable to set the data. So a chart from the 768 // same document is treated like a chart with 769 // own data for the time being. 770 #if 0 771 // data provider 772 uno::Reference< chart2::data::XDataProvider > xDataProvider = new 773 ScChart2DataProvider( this ); 774 xReceiver->attachDataProvider( xDataProvider ); 775 // number formats supplier 776 uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( pShell->GetModel(), uno::UNO_QUERY ); 777 xReceiver->attachNumberFormatsSupplier( xNumberFormatsSupplier ); 778 // data ? 779 // how to set?? Defined in XML-file, which is already loaded!!! 780 // => we have to do this stuff here, BEFORE the chart is actually loaded 781 782 bIsChart = true; 783 #endif 784 } 785 786 if (!bIsChart) 787 { 788 // put into list of other ole objects, so the object doesn't have to 789 // be swapped in the next time UpdateChartListenerCollection is called 790 //! remove names when objects are no longer there? 791 // (object names aren't used again before reloading the document) 792 793 if (!pOtherObjects) 794 pOtherObjects = new ScStrCollection; 795 pOtherObjects->Insert( new StrData( aObjName ) ); 796 } 797 } 798 } 799 pObject = aIter.Next(); 800 } 801 } 802 } 803 // alle nicht auf SetUsed gesetzten loeschen 804 pChartListenerCollection->FreeUnused(); 805 } 806 } 807 808 void ScDocument::AddOLEObjectToCollection(const String& rName) 809 { 810 if (!pOtherObjects) 811 pOtherObjects = new ScStrCollection; 812 pOtherObjects->Insert( new StrData( rName ) ); 813 } 814 815 816 817