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