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 28 29 #include <svl/smplhint.hxx> 30 #include <sfx2/linkmgr.hxx> 31 32 #include "linkuno.hxx" 33 #include "miscuno.hxx" 34 #include "convuno.hxx" 35 #include "docsh.hxx" 36 #include "docfunc.hxx" 37 #include "collect.hxx" 38 #include "tablink.hxx" 39 #include "arealink.hxx" 40 #include "unoguard.hxx" 41 #include "hints.hxx" 42 #include "unonames.hxx" 43 #include "rangeseq.hxx" 44 #include "token.hxx" 45 46 #include <vector> 47 #include <climits> 48 49 using namespace com::sun::star; 50 using namespace formula; 51 using ::com::sun::star::uno::Any; 52 using ::com::sun::star::uno::Reference; 53 using ::com::sun::star::uno::Sequence; 54 using ::com::sun::star::uno::UNO_QUERY; 55 using ::com::sun::star::uno::UNO_QUERY_THROW; 56 using ::com::sun::star::lang::IllegalArgumentException; 57 using ::com::sun::star::uno::RuntimeException; 58 using ::rtl::OUString; 59 using ::std::vector; 60 61 //------------------------------------------------------------------------ 62 63 // fuer Sheet- und Area-Links benutzt: 64 const SfxItemPropertyMapEntry* lcl_GetSheetLinkMap() 65 { 66 static SfxItemPropertyMapEntry aSheetLinkMap_Impl[] = 67 { 68 {MAP_CHAR_LEN(SC_UNONAME_FILTER), 0, &getCppuType((rtl::OUString*)0), 0, 0 }, 69 {MAP_CHAR_LEN(SC_UNONAME_FILTOPT), 0, &getCppuType((rtl::OUString*)0), 0, 0 }, 70 {MAP_CHAR_LEN(SC_UNONAME_LINKURL), 0, &getCppuType((rtl::OUString*)0), 0, 0 }, 71 {MAP_CHAR_LEN(SC_UNONAME_REFDELAY), 0, &getCppuType((sal_Int32*)0), 0, 0 }, 72 {MAP_CHAR_LEN(SC_UNONAME_REFPERIOD), 0, &getCppuType((sal_Int32*)0), 0, 0 }, 73 {0,0,0,0,0,0} 74 }; 75 return aSheetLinkMap_Impl; 76 } 77 78 //------------------------------------------------------------------------ 79 80 SV_IMPL_PTRARR( XRefreshListenerArr_Impl, XRefreshListenerPtr ); 81 82 SC_SIMPLE_SERVICE_INFO( ScAreaLinkObj, "ScAreaLinkObj", "com.sun.star.sheet.CellAreaLink" ) 83 SC_SIMPLE_SERVICE_INFO( ScAreaLinksObj, "ScAreaLinksObj", "com.sun.star.sheet.CellAreaLinks" ) 84 SC_SIMPLE_SERVICE_INFO( ScDDELinkObj, "ScDDELinkObj", "com.sun.star.sheet.DDELink" ) 85 SC_SIMPLE_SERVICE_INFO( ScDDELinksObj, "ScDDELinksObj", "com.sun.star.sheet.DDELinks" ) 86 SC_SIMPLE_SERVICE_INFO( ScSheetLinkObj, "ScSheetLinkObj", "com.sun.star.sheet.SheetLink" ) 87 SC_SIMPLE_SERVICE_INFO( ScSheetLinksObj, "ScSheetLinksObj", "com.sun.star.sheet.SheetLinks" ) 88 89 //------------------------------------------------------------------------ 90 91 ScSheetLinkObj::ScSheetLinkObj(ScDocShell* pDocSh, const String& rName) : 92 aPropSet( lcl_GetSheetLinkMap() ), 93 pDocShell( pDocSh ), 94 aFileName( rName ) 95 { 96 pDocShell->GetDocument()->AddUnoObject(*this); 97 } 98 99 ScSheetLinkObj::~ScSheetLinkObj() 100 { 101 if (pDocShell) 102 pDocShell->GetDocument()->RemoveUnoObject(*this); 103 } 104 105 void ScSheetLinkObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) 106 { 107 //! notify if links in document are changed 108 // UpdateRef is not needed here 109 110 if ( rHint.ISA( SfxSimpleHint ) ) 111 { 112 if ( ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) 113 pDocShell = NULL; // pointer is invalid 114 } 115 else if ( rHint.ISA( ScLinkRefreshedHint ) ) 116 { 117 const ScLinkRefreshedHint& rLH = (const ScLinkRefreshedHint&) rHint; 118 if ( rLH.GetLinkType() == SC_LINKREFTYPE_SHEET && rLH.GetUrl() == aFileName ) 119 Refreshed_Impl(); 120 } 121 } 122 123 ScTableLink* ScSheetLinkObj::GetLink_Impl() const 124 { 125 if (pDocShell) 126 { 127 sfx2::LinkManager* pLinkManager = pDocShell->GetDocument()->GetLinkManager(); 128 sal_uInt16 nCount = pLinkManager->GetLinks().Count(); 129 for (sal_uInt16 i=0; i<nCount; i++) 130 { 131 ::sfx2::SvBaseLink* pBase = *pLinkManager->GetLinks()[i]; 132 if (pBase->ISA(ScTableLink)) 133 { 134 ScTableLink* pTabLink = (ScTableLink*)pBase; 135 if ( pTabLink->GetFileName() == aFileName ) 136 return pTabLink; 137 } 138 } 139 } 140 return NULL; // nicht gefunden 141 } 142 143 // XNamed 144 145 rtl::OUString SAL_CALL ScSheetLinkObj::getName() throw(uno::RuntimeException) 146 { 147 ScUnoGuard aGuard; 148 return getFileName(); // Name ist der Dateiname (URL) 149 } 150 151 void SAL_CALL ScSheetLinkObj::setName( const rtl::OUString& aName ) throw(uno::RuntimeException) 152 { 153 ScUnoGuard aGuard; 154 setFileName(aName); // Name ist der Dateiname (URL) 155 } 156 157 // XRefreshable 158 159 void SAL_CALL ScSheetLinkObj::refresh() throw(uno::RuntimeException) 160 { 161 ScUnoGuard aGuard; 162 ScTableLink* pLink = GetLink_Impl(); 163 if (pLink) 164 pLink->Refresh( pLink->GetFileName(), pLink->GetFilterName(), NULL, pLink->GetRefreshDelay() ); 165 } 166 167 void SAL_CALL ScSheetLinkObj::addRefreshListener( 168 const uno::Reference<util::XRefreshListener >& xListener ) 169 throw(uno::RuntimeException) 170 { 171 ScUnoGuard aGuard; 172 uno::Reference<util::XRefreshListener>* pObj = 173 new uno::Reference<util::XRefreshListener>( xListener ); 174 aRefreshListeners.Insert( pObj, aRefreshListeners.Count() ); 175 176 // hold one additional ref to keep this object alive as long as there are listeners 177 if ( aRefreshListeners.Count() == 1 ) 178 acquire(); 179 } 180 181 void SAL_CALL ScSheetLinkObj::removeRefreshListener( 182 const uno::Reference<util::XRefreshListener >& xListener ) 183 throw(uno::RuntimeException) 184 { 185 ScUnoGuard aGuard; 186 sal_uInt16 nCount = aRefreshListeners.Count(); 187 for ( sal_uInt16 n=nCount; n--; ) 188 { 189 uno::Reference<util::XRefreshListener>* pObj = aRefreshListeners[n]; 190 if ( *pObj == xListener ) 191 { 192 aRefreshListeners.DeleteAndDestroy( n ); 193 if ( aRefreshListeners.Count() == 0 ) 194 release(); // release ref for listeners 195 break; 196 } 197 } 198 } 199 200 void ScSheetLinkObj::Refreshed_Impl() 201 { 202 lang::EventObject aEvent; 203 aEvent.Source.set((cppu::OWeakObject*)this); 204 for ( sal_uInt16 n=0; n<aRefreshListeners.Count(); n++ ) 205 (*aRefreshListeners[n])->refreshed( aEvent ); 206 } 207 208 void ScSheetLinkObj::ModifyRefreshDelay_Impl( sal_Int32 nRefresh ) 209 { 210 ScTableLink* pLink = GetLink_Impl(); 211 if( pLink ) 212 pLink->SetRefreshDelay( (sal_uLong) nRefresh ); 213 } 214 215 // XPropertySet 216 217 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScSheetLinkObj::getPropertySetInfo() 218 throw(uno::RuntimeException) 219 { 220 ScUnoGuard aGuard; 221 static uno::Reference<beans::XPropertySetInfo> aRef( 222 new SfxItemPropertySetInfo( aPropSet.getPropertyMap() )); 223 return aRef; 224 } 225 226 void SAL_CALL ScSheetLinkObj::setPropertyValue( 227 const rtl::OUString& aPropertyName, const uno::Any& aValue ) 228 throw(beans::UnknownPropertyException, beans::PropertyVetoException, 229 lang::IllegalArgumentException, lang::WrappedTargetException, 230 uno::RuntimeException) 231 { 232 ScUnoGuard aGuard; 233 String aNameString(aPropertyName); 234 rtl::OUString aValStr; 235 if ( aNameString.EqualsAscii( SC_UNONAME_LINKURL ) ) 236 { 237 if ( aValue >>= aValStr ) 238 setFileName( aValStr ); 239 } 240 else if ( aNameString.EqualsAscii( SC_UNONAME_FILTER ) ) 241 { 242 if ( aValue >>= aValStr ) 243 setFilter( aValStr ); 244 } 245 else if ( aNameString.EqualsAscii( SC_UNONAME_FILTOPT ) ) 246 { 247 if ( aValue >>= aValStr ) 248 setFilterOptions( aValStr ); 249 } 250 else if ( aNameString.EqualsAscii( SC_UNONAME_REFPERIOD ) ) 251 { 252 sal_Int32 nRefresh = 0; 253 if ( aValue >>= nRefresh ) 254 setRefreshDelay( nRefresh ); 255 } 256 else if ( aNameString.EqualsAscii( SC_UNONAME_REFDELAY ) ) 257 { 258 sal_Int32 nRefresh = 0; 259 if ( aValue >>= nRefresh ) 260 setRefreshDelay( nRefresh ); 261 } 262 } 263 264 uno::Any SAL_CALL ScSheetLinkObj::getPropertyValue( const rtl::OUString& aPropertyName ) 265 throw(beans::UnknownPropertyException, lang::WrappedTargetException, 266 uno::RuntimeException) 267 { 268 ScUnoGuard aGuard; 269 String aNameString(aPropertyName); 270 uno::Any aRet; 271 if ( aNameString.EqualsAscii( SC_UNONAME_LINKURL ) ) 272 aRet <<= getFileName(); 273 else if ( aNameString.EqualsAscii( SC_UNONAME_FILTER ) ) 274 aRet <<= getFilter(); 275 else if ( aNameString.EqualsAscii( SC_UNONAME_FILTOPT ) ) 276 aRet <<= getFilterOptions(); 277 else if ( aNameString.EqualsAscii( SC_UNONAME_REFPERIOD ) ) 278 aRet <<= getRefreshDelay(); 279 else if ( aNameString.EqualsAscii( SC_UNONAME_REFDELAY ) ) 280 aRet <<= getRefreshDelay(); 281 return aRet; 282 } 283 284 SC_IMPL_DUMMY_PROPERTY_LISTENER( ScSheetLinkObj ) 285 286 // internal: 287 288 rtl::OUString ScSheetLinkObj::getFileName(void) const 289 { 290 ScUnoGuard aGuard; 291 return aFileName; 292 } 293 294 void ScSheetLinkObj::setFileName(const rtl::OUString& rNewName) 295 { 296 ScUnoGuard aGuard; 297 ScTableLink* pLink = GetLink_Impl(); 298 if (pLink) 299 { 300 // pLink->Refresh mit neuem Dateinamen bringt sfx2::LinkManager durcheinander 301 // darum per Hand die Tabellen umsetzen und Link per UpdateLinks neu erzeugen 302 303 String aNewStr(ScGlobal::GetAbsDocName( String(rNewName), pDocShell )); 304 305 // zuerst Tabellen umsetzen 306 307 ScDocument* pDoc = pDocShell->GetDocument(); 308 SCTAB nTabCount = pDoc->GetTableCount(); 309 for (SCTAB nTab=0; nTab<nTabCount; nTab++) 310 if ( pDoc->IsLinked(nTab) && pDoc->GetLinkDoc(nTab) == aFileName ) // alte Datei 311 pDoc->SetLink( nTab, pDoc->GetLinkMode(nTab), aNewStr, 312 pDoc->GetLinkFlt(nTab), pDoc->GetLinkOpt(nTab), 313 pDoc->GetLinkTab(nTab), 314 pDoc->GetLinkRefreshDelay(nTab) ); // nur Datei aendern 315 316 // Links updaten 317 //! Undo !!! 318 319 pLink = NULL; // wird bei UpdateLinks ungueltig 320 pDocShell->UpdateLinks(); // alter Link raus, evtl. neuen Link anlegen 321 322 // Daten kopieren 323 324 aFileName = aNewStr; 325 pLink = GetLink_Impl(); // neuer Link mit neuem Namen 326 if (pLink) 327 pLink->Update(); // inkl. Paint & Undo fuer Daten 328 } 329 } 330 331 rtl::OUString ScSheetLinkObj::getFilter(void) const 332 { 333 ScUnoGuard aGuard; 334 rtl::OUString aRet; 335 ScTableLink* pLink = GetLink_Impl(); 336 if (pLink) 337 aRet = pLink->GetFilterName(); 338 return aRet; 339 } 340 341 void ScSheetLinkObj::setFilter(const rtl::OUString& Filter) 342 { 343 ScUnoGuard aGuard; 344 ScTableLink* pLink = GetLink_Impl(); 345 if (pLink) 346 { 347 String aFilterStr(Filter); 348 pLink->Refresh( aFileName, aFilterStr, NULL, pLink->GetRefreshDelay() ); 349 } 350 } 351 352 rtl::OUString ScSheetLinkObj::getFilterOptions(void) const 353 { 354 ScUnoGuard aGuard; 355 rtl::OUString aRet; 356 ScTableLink* pLink = GetLink_Impl(); 357 if (pLink) 358 aRet = pLink->GetOptions(); 359 return aRet; 360 } 361 362 void ScSheetLinkObj::setFilterOptions(const rtl::OUString& FilterOptions) 363 { 364 ScUnoGuard aGuard; 365 ScTableLink* pLink = GetLink_Impl(); 366 if (pLink) 367 { 368 String aOptStr(FilterOptions); 369 pLink->Refresh( aFileName, pLink->GetFilterName(), &aOptStr, pLink->GetRefreshDelay() ); 370 } 371 } 372 373 sal_Int32 ScSheetLinkObj::getRefreshDelay(void) const 374 { 375 ScUnoGuard aGuard; 376 sal_Int32 nRet = 0; 377 ScTableLink* pLink = GetLink_Impl(); 378 if (pLink) 379 nRet = (sal_Int32) pLink->GetRefreshDelay(); 380 return nRet; 381 } 382 383 void ScSheetLinkObj::setRefreshDelay(sal_Int32 nRefreshDelay) 384 { 385 ScUnoGuard aGuard; 386 ModifyRefreshDelay_Impl( nRefreshDelay ); 387 } 388 389 //------------------------------------------------------------------------ 390 391 ScSheetLinksObj::ScSheetLinksObj(ScDocShell* pDocSh) : 392 pDocShell( pDocSh ) 393 { 394 pDocShell->GetDocument()->AddUnoObject(*this); 395 } 396 397 ScSheetLinksObj::~ScSheetLinksObj() 398 { 399 if (pDocShell) 400 pDocShell->GetDocument()->RemoveUnoObject(*this); 401 } 402 403 void ScSheetLinksObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) 404 { 405 // Referenz-Update interessiert hier nicht 406 407 if ( rHint.ISA( SfxSimpleHint ) && 408 ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) 409 { 410 pDocShell = NULL; // ungueltig geworden 411 } 412 } 413 414 // XSheetLinks 415 416 ScSheetLinkObj* ScSheetLinksObj::GetObjectByIndex_Impl(sal_Int32 nIndex) 417 { 418 if (pDocShell) 419 { 420 sal_Int32 nCount = 0; 421 ScStrCollection aNames; // um doppelte wegzulassen 422 ScDocument* pDoc = pDocShell->GetDocument(); 423 SCTAB nTabCount = pDoc->GetTableCount(); 424 for (SCTAB nTab=0; nTab<nTabCount; nTab++) 425 if (pDoc->IsLinked(nTab)) 426 { 427 String aLinkDoc = pDoc->GetLinkDoc( nTab ); 428 StrData* pData = new StrData(aLinkDoc); 429 if (aNames.Insert(pData)) 430 { 431 if ( nCount == nIndex ) 432 return new ScSheetLinkObj( pDocShell, aLinkDoc ); 433 ++nCount; 434 } 435 else 436 delete pData; 437 } 438 } 439 return NULL; // kein Dokument oder Index zu gross 440 } 441 442 ScSheetLinkObj* ScSheetLinksObj::GetObjectByName_Impl(const rtl::OUString& aName) 443 { 444 // Name ist der Dateiname 445 446 if (pDocShell) 447 { 448 String aNameStr(aName); 449 450 ScDocument* pDoc = pDocShell->GetDocument(); 451 SCTAB nTabCount = pDoc->GetTableCount(); 452 for (SCTAB nTab=0; nTab<nTabCount; nTab++) 453 if (pDoc->IsLinked(nTab)) 454 { 455 //! case-insensitiv ??? 456 String aLinkDoc = pDoc->GetLinkDoc( nTab ); 457 if ( aLinkDoc == aNameStr ) 458 return new ScSheetLinkObj( pDocShell, aNameStr ); 459 } 460 } 461 462 return NULL; 463 } 464 465 // XEnumerationAccess 466 467 uno::Reference<container::XEnumeration> SAL_CALL ScSheetLinksObj::createEnumeration() 468 throw(uno::RuntimeException) 469 { 470 ScUnoGuard aGuard; 471 return new ScIndexEnumeration(this, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.SheetLinksEnumeration"))); 472 } 473 474 // XIndexAccess 475 476 sal_Int32 SAL_CALL ScSheetLinksObj::getCount() throw(uno::RuntimeException) 477 { 478 ScUnoGuard aGuard; 479 sal_Int32 nCount = 0; 480 if (pDocShell) 481 { 482 ScStrCollection aNames; // um doppelte wegzulassen 483 ScDocument* pDoc = pDocShell->GetDocument(); 484 SCTAB nTabCount = pDoc->GetTableCount(); 485 for (SCTAB nTab=0; nTab<nTabCount; nTab++) 486 if (pDoc->IsLinked(nTab)) 487 { 488 String aLinkDoc(pDoc->GetLinkDoc( nTab )); 489 StrData* pData = new StrData(aLinkDoc); 490 if (aNames.Insert(pData)) 491 ++nCount; 492 else 493 delete pData; 494 } 495 } 496 return nCount; 497 } 498 499 uno::Any SAL_CALL ScSheetLinksObj::getByIndex( sal_Int32 nIndex ) 500 throw(lang::IndexOutOfBoundsException, 501 lang::WrappedTargetException, uno::RuntimeException) 502 { 503 ScUnoGuard aGuard; 504 uno::Reference<beans::XPropertySet> xLink(GetObjectByIndex_Impl(nIndex)); 505 if (xLink.is()) 506 return uno::makeAny(xLink); 507 else 508 throw lang::IndexOutOfBoundsException(); 509 // return uno::Any(); 510 } 511 512 uno::Type SAL_CALL ScSheetLinksObj::getElementType() throw(uno::RuntimeException) 513 { 514 ScUnoGuard aGuard; 515 return getCppuType((uno::Reference<beans::XPropertySet>*)0); 516 } 517 518 sal_Bool SAL_CALL ScSheetLinksObj::hasElements() throw(uno::RuntimeException) 519 { 520 ScUnoGuard aGuard; 521 return ( getCount() != 0 ); 522 } 523 524 uno::Any SAL_CALL ScSheetLinksObj::getByName( const rtl::OUString& aName ) 525 throw(container::NoSuchElementException, 526 lang::WrappedTargetException, uno::RuntimeException) 527 { 528 ScUnoGuard aGuard; 529 uno::Reference<beans::XPropertySet> xLink(GetObjectByName_Impl(aName)); 530 if (xLink.is()) 531 return uno::makeAny(xLink); 532 else 533 throw container::NoSuchElementException(); 534 // return uno::Any(); 535 } 536 537 sal_Bool SAL_CALL ScSheetLinksObj::hasByName( const rtl::OUString& aName ) 538 throw(uno::RuntimeException) 539 { 540 ScUnoGuard aGuard; 541 // Name ist der Dateiname 542 543 if (pDocShell) 544 { 545 String aNameStr(aName); 546 547 ScDocument* pDoc = pDocShell->GetDocument(); 548 SCTAB nTabCount = pDoc->GetTableCount(); 549 for (SCTAB nTab=0; nTab<nTabCount; nTab++) 550 if (pDoc->IsLinked(nTab)) 551 { 552 //! case-insensitiv ??? 553 String aLinkDoc(pDoc->GetLinkDoc( nTab )); 554 if ( aLinkDoc == aNameStr ) 555 return sal_True; 556 } 557 } 558 return sal_False; 559 } 560 561 uno::Sequence<rtl::OUString> SAL_CALL ScSheetLinksObj::getElementNames() throw(uno::RuntimeException) 562 { 563 ScUnoGuard aGuard; 564 // Name ist der Dateiname 565 566 if (pDocShell) 567 { 568 ScStrCollection aNames; // um doppelte wegzulassen 569 ScDocument* pDoc = pDocShell->GetDocument(); 570 SCTAB nTabCount = pDoc->GetTableCount(); 571 String aName; 572 573 sal_Int32 nLinkCount = getCount(); 574 uno::Sequence<rtl::OUString> aSeq(nLinkCount); 575 rtl::OUString* pAry = aSeq.getArray(); 576 sal_uInt16 nPos = 0; 577 for (SCTAB nTab=0; nTab<nTabCount; nTab++) 578 { 579 if (pDoc->IsLinked(nTab)) 580 { 581 String aLinkDoc(pDoc->GetLinkDoc( nTab )); 582 StrData* pData = new StrData(aLinkDoc); 583 if (aNames.Insert(pData)) 584 pAry[nPos++] = aLinkDoc; 585 else 586 delete pData; 587 } 588 } 589 DBG_ASSERT( nPos==nLinkCount, "verzaehlt" ); 590 return aSeq; 591 } 592 return uno::Sequence<rtl::OUString>(); 593 } 594 595 //------------------------------------------------------------------------ 596 597 ScAreaLink* lcl_GetAreaLink( ScDocShell* pDocShell, sal_uInt16 nPos ) 598 { 599 if (pDocShell) 600 { 601 sfx2::LinkManager* pLinkManager = pDocShell->GetDocument()->GetLinkManager(); 602 sal_uInt16 nTotalCount = pLinkManager->GetLinks().Count(); 603 sal_uInt16 nAreaCount = 0; 604 for (sal_uInt16 i=0; i<nTotalCount; i++) 605 { 606 ::sfx2::SvBaseLink* pBase = *pLinkManager->GetLinks()[i]; 607 if (pBase->ISA(ScAreaLink)) 608 { 609 if ( nAreaCount == nPos ) 610 return (ScAreaLink*)pBase; 611 ++nAreaCount; 612 } 613 } 614 } 615 return NULL; // nicht gefunden 616 } 617 618 ScAreaLinkObj::ScAreaLinkObj(ScDocShell* pDocSh, sal_uInt16 nP) : 619 aPropSet( lcl_GetSheetLinkMap() ), 620 pDocShell( pDocSh ), 621 nPos( nP ) 622 { 623 pDocShell->GetDocument()->AddUnoObject(*this); 624 } 625 626 ScAreaLinkObj::~ScAreaLinkObj() 627 { 628 if (pDocShell) 629 pDocShell->GetDocument()->RemoveUnoObject(*this); 630 } 631 632 void ScAreaLinkObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) 633 { 634 //! notify if links in document are changed 635 // UpdateRef is not needed here 636 637 if ( rHint.ISA( SfxSimpleHint ) ) 638 { 639 if ( ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) 640 pDocShell = NULL; // pointer is invalid 641 } 642 else if ( rHint.ISA( ScLinkRefreshedHint ) ) 643 { 644 const ScLinkRefreshedHint& rLH = (const ScLinkRefreshedHint&) rHint; 645 if ( rLH.GetLinkType() == SC_LINKREFTYPE_AREA ) 646 { 647 // get this link to compare dest position 648 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos); 649 if ( pLink && pLink->GetDestArea().aStart == rLH.GetDestPos() ) 650 Refreshed_Impl(); 651 } 652 } 653 } 654 655 // XFileLink 656 657 void ScAreaLinkObj::Modify_Impl( const rtl::OUString* pNewFile, const rtl::OUString* pNewFilter, 658 const rtl::OUString* pNewOptions, const rtl::OUString* pNewSource, 659 const table::CellRangeAddress* pNewDest ) 660 { 661 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos); 662 if (pLink) 663 { 664 String aFile (pLink->GetFile()); 665 String aFilter (pLink->GetFilter()); 666 String aOptions (pLink->GetOptions()); 667 String aSource (pLink->GetSource()); 668 ScRange aDest (pLink->GetDestArea()); 669 sal_uLong nRefresh = pLink->GetRefreshDelay(); 670 671 //! Undo fuer Loeschen 672 //! Undo zusammenfassen 673 674 sfx2::LinkManager* pLinkManager = pDocShell->GetDocument()->GetLinkManager(); 675 pLinkManager->Remove( pLink ); 676 pLink = NULL; // bei Remove geloescht 677 678 sal_Bool bFitBlock = sal_True; // verschieben, wenn durch Update Groesse geaendert 679 if (pNewFile) 680 { 681 aFile = String( *pNewFile ); 682 aFile = ScGlobal::GetAbsDocName( aFile, pDocShell ); //! in InsertAreaLink? 683 } 684 if (pNewFilter) 685 aFilter = String( *pNewFilter ); 686 if (pNewOptions) 687 aOptions = String( *pNewOptions ); 688 if (pNewSource) 689 aSource = String( *pNewSource ); 690 if (pNewDest) 691 { 692 ScUnoConversion::FillScRange( aDest, *pNewDest ); 693 bFitBlock = sal_False; // neuer Bereich angegeben -> keine Inhalte verschieben 694 } 695 696 ScDocFunc aFunc(*pDocShell); 697 aFunc.InsertAreaLink( aFile, aFilter, aOptions, aSource, aDest, nRefresh, bFitBlock, sal_True ); 698 } 699 } 700 701 void ScAreaLinkObj::ModifyRefreshDelay_Impl( sal_Int32 nRefresh ) 702 { 703 ScAreaLink* pLink = lcl_GetAreaLink( pDocShell, nPos ); 704 if( pLink ) 705 pLink->SetRefreshDelay( (sal_uLong) nRefresh ); 706 } 707 708 // XRefreshable 709 710 void SAL_CALL ScAreaLinkObj::refresh() throw(uno::RuntimeException) 711 { 712 ScUnoGuard aGuard; 713 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos); 714 if (pLink) 715 pLink->Refresh( pLink->GetFile(), pLink->GetFilter(), pLink->GetSource(), pLink->GetRefreshDelay() ); 716 } 717 718 void SAL_CALL ScAreaLinkObj::addRefreshListener( 719 const uno::Reference<util::XRefreshListener >& xListener ) 720 throw(uno::RuntimeException) 721 { 722 ScUnoGuard aGuard; 723 uno::Reference<util::XRefreshListener>* pObj = 724 new uno::Reference<util::XRefreshListener>( xListener ); 725 aRefreshListeners.Insert( pObj, aRefreshListeners.Count() ); 726 727 // hold one additional ref to keep this object alive as long as there are listeners 728 if ( aRefreshListeners.Count() == 1 ) 729 acquire(); 730 } 731 732 void SAL_CALL ScAreaLinkObj::removeRefreshListener( 733 const uno::Reference<util::XRefreshListener >& xListener ) 734 throw(uno::RuntimeException) 735 { 736 ScUnoGuard aGuard; 737 sal_uInt16 nCount = aRefreshListeners.Count(); 738 for ( sal_uInt16 n=nCount; n--; ) 739 { 740 uno::Reference<util::XRefreshListener>* pObj = aRefreshListeners[n]; 741 if ( *pObj == xListener ) 742 { 743 aRefreshListeners.DeleteAndDestroy( n ); 744 if ( aRefreshListeners.Count() == 0 ) 745 release(); // release ref for listeners 746 break; 747 } 748 } 749 } 750 751 void ScAreaLinkObj::Refreshed_Impl() 752 { 753 lang::EventObject aEvent; 754 aEvent.Source.set((cppu::OWeakObject*)this); 755 for ( sal_uInt16 n=0; n<aRefreshListeners.Count(); n++ ) 756 (*aRefreshListeners[n])->refreshed( aEvent ); 757 } 758 759 // XPropertySet 760 761 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScAreaLinkObj::getPropertySetInfo() 762 throw(uno::RuntimeException) 763 { 764 ScUnoGuard aGuard; 765 static uno::Reference<beans::XPropertySetInfo> aRef( 766 new SfxItemPropertySetInfo( aPropSet.getPropertyMap() )); 767 return aRef; 768 } 769 770 void SAL_CALL ScAreaLinkObj::setPropertyValue( 771 const rtl::OUString& aPropertyName, const uno::Any& aValue ) 772 throw(beans::UnknownPropertyException, beans::PropertyVetoException, 773 lang::IllegalArgumentException, lang::WrappedTargetException, 774 uno::RuntimeException) 775 { 776 ScUnoGuard aGuard; 777 String aNameString(aPropertyName); 778 rtl::OUString aValStr; 779 if ( aNameString.EqualsAscii( SC_UNONAME_LINKURL ) ) 780 { 781 if ( aValue >>= aValStr ) 782 setFileName( aValStr ); 783 } 784 else if ( aNameString.EqualsAscii( SC_UNONAME_FILTER ) ) 785 { 786 if ( aValue >>= aValStr ) 787 setFilter( aValStr ); 788 } 789 else if ( aNameString.EqualsAscii( SC_UNONAME_FILTOPT ) ) 790 { 791 if ( aValue >>= aValStr ) 792 setFilterOptions( aValStr ); 793 } 794 else if ( aNameString.EqualsAscii( SC_UNONAME_REFPERIOD ) ) 795 { 796 sal_Int32 nRefresh = 0; 797 if ( aValue >>= nRefresh ) 798 setRefreshDelay( nRefresh ); 799 } 800 else if ( aNameString.EqualsAscii( SC_UNONAME_REFDELAY ) ) 801 { 802 sal_Int32 nRefresh = 0; 803 if ( aValue >>= nRefresh ) 804 setRefreshDelay( nRefresh ); 805 } 806 } 807 808 uno::Any SAL_CALL ScAreaLinkObj::getPropertyValue( const rtl::OUString& aPropertyName ) 809 throw(beans::UnknownPropertyException, lang::WrappedTargetException, 810 uno::RuntimeException) 811 { 812 ScUnoGuard aGuard; 813 String aNameString(aPropertyName); 814 uno::Any aRet; 815 if ( aNameString.EqualsAscii( SC_UNONAME_LINKURL ) ) 816 aRet <<= getFileName(); 817 else if ( aNameString.EqualsAscii( SC_UNONAME_FILTER ) ) 818 aRet <<= getFilter(); 819 else if ( aNameString.EqualsAscii( SC_UNONAME_FILTOPT ) ) 820 aRet <<= getFilterOptions(); 821 else if ( aNameString.EqualsAscii( SC_UNONAME_REFPERIOD ) ) 822 aRet <<= getRefreshDelay(); 823 else if ( aNameString.EqualsAscii( SC_UNONAME_REFDELAY ) ) 824 aRet <<= getRefreshDelay(); 825 return aRet; 826 } 827 828 SC_IMPL_DUMMY_PROPERTY_LISTENER( ScAreaLinkObj ) 829 830 // internal: 831 832 rtl::OUString ScAreaLinkObj::getFileName(void) const 833 { 834 ScUnoGuard aGuard; 835 rtl::OUString aRet; 836 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos); 837 if (pLink) 838 aRet = pLink->GetFile(); 839 return aRet; 840 } 841 842 void ScAreaLinkObj::setFileName(const rtl::OUString& rNewName) 843 { 844 ScUnoGuard aGuard; 845 Modify_Impl( &rNewName, NULL, NULL, NULL, NULL ); 846 } 847 848 rtl::OUString ScAreaLinkObj::getFilter(void) const 849 { 850 ScUnoGuard aGuard; 851 rtl::OUString aRet; 852 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos); 853 if (pLink) 854 aRet = pLink->GetFilter(); 855 return aRet; 856 } 857 858 void ScAreaLinkObj::setFilter(const rtl::OUString& Filter) 859 { 860 ScUnoGuard aGuard; 861 Modify_Impl( NULL, &Filter, NULL, NULL, NULL ); 862 } 863 864 rtl::OUString ScAreaLinkObj::getFilterOptions(void) const 865 { 866 ScUnoGuard aGuard; 867 rtl::OUString aRet; 868 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos); 869 if (pLink) 870 aRet = pLink->GetOptions(); 871 return aRet; 872 } 873 874 void ScAreaLinkObj::setFilterOptions(const rtl::OUString& FilterOptions) 875 { 876 ScUnoGuard aGuard; 877 Modify_Impl( NULL, NULL, &FilterOptions, NULL, NULL ); 878 } 879 880 sal_Int32 ScAreaLinkObj::getRefreshDelay(void) const 881 { 882 ScUnoGuard aGuard; 883 sal_Int32 nRet = 0; 884 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos); 885 if (pLink) 886 nRet = (sal_Int32) pLink->GetRefreshDelay(); 887 return nRet; 888 } 889 890 void ScAreaLinkObj::setRefreshDelay(sal_Int32 nRefreshDelay) 891 { 892 ScUnoGuard aGuard; 893 ModifyRefreshDelay_Impl( nRefreshDelay ); 894 } 895 896 // XAreaLink 897 898 rtl::OUString SAL_CALL ScAreaLinkObj::getSourceArea() throw(uno::RuntimeException) 899 { 900 ScUnoGuard aGuard; 901 rtl::OUString aRet; 902 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos); 903 if (pLink) 904 aRet = pLink->GetSource(); 905 return aRet; 906 } 907 908 void SAL_CALL ScAreaLinkObj::setSourceArea( const rtl::OUString& aSourceArea ) 909 throw(uno::RuntimeException) 910 { 911 ScUnoGuard aGuard; 912 Modify_Impl( NULL, NULL, NULL, &aSourceArea, NULL ); 913 } 914 915 table::CellRangeAddress SAL_CALL ScAreaLinkObj::getDestArea() throw(uno::RuntimeException) 916 { 917 ScUnoGuard aGuard; 918 table::CellRangeAddress aRet; 919 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos); 920 if (pLink) 921 ScUnoConversion::FillApiRange( aRet, pLink->GetDestArea() ); 922 return aRet; 923 } 924 925 void SAL_CALL ScAreaLinkObj::setDestArea( const table::CellRangeAddress& aDestArea ) 926 throw(uno::RuntimeException) 927 { 928 ScUnoGuard aGuard; 929 Modify_Impl( NULL, NULL, NULL, NULL, &aDestArea ); 930 } 931 932 //------------------------------------------------------------------------ 933 934 ScAreaLinksObj::ScAreaLinksObj(ScDocShell* pDocSh) : 935 pDocShell( pDocSh ) 936 { 937 pDocShell->GetDocument()->AddUnoObject(*this); 938 } 939 940 ScAreaLinksObj::~ScAreaLinksObj() 941 { 942 if (pDocShell) 943 pDocShell->GetDocument()->RemoveUnoObject(*this); 944 } 945 946 void ScAreaLinksObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) 947 { 948 // Referenz-Update interessiert hier nicht 949 950 if ( rHint.ISA( SfxSimpleHint ) && 951 ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) 952 { 953 pDocShell = NULL; // ungueltig geworden 954 } 955 } 956 957 // XAreaLinks 958 959 ScAreaLinkObj* ScAreaLinksObj::GetObjectByIndex_Impl(sal_Int32 nIndex) 960 { 961 if ( pDocShell && nIndex >= 0 && nIndex < getCount() ) 962 return new ScAreaLinkObj( pDocShell, (sal_uInt16)nIndex ); 963 964 return NULL; // nicht gefunden 965 } 966 967 void SAL_CALL ScAreaLinksObj::insertAtPosition( const table::CellAddress& aDestPos, 968 const rtl::OUString& aFileName, 969 const rtl::OUString& aSourceArea, 970 const rtl::OUString& aFilter, 971 const rtl::OUString& aFilterOptions ) 972 throw(uno::RuntimeException) 973 { 974 ScUnoGuard aGuard; 975 if (pDocShell) 976 { 977 String aFileStr (aFileName); 978 String aFilterStr (aFilter); 979 String aOptionStr (aFilterOptions); 980 String aSourceStr (aSourceArea); 981 ScAddress aDestAddr( (SCCOL)aDestPos.Column, (SCROW)aDestPos.Row, aDestPos.Sheet ); 982 983 aFileStr = ScGlobal::GetAbsDocName( aFileStr, pDocShell ); //! in InsertAreaLink ??? 984 985 ScDocFunc aFunc(*pDocShell); 986 aFunc.InsertAreaLink( aFileStr, aFilterStr, aOptionStr, 987 aSourceStr, ScRange(aDestAddr), 988 0, sal_False, sal_True ); // keine Inhalte verschieben 989 } 990 } 991 992 void SAL_CALL ScAreaLinksObj::removeByIndex( sal_Int32 nIndex ) throw(uno::RuntimeException) 993 { 994 ScUnoGuard aGuard; 995 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, (sal_uInt16)nIndex); 996 if (pLink) 997 { 998 //! SetAddUndo oder so 999 1000 sfx2::LinkManager* pLinkManager = pDocShell->GetDocument()->GetLinkManager(); 1001 pLinkManager->Remove( pLink ); 1002 } 1003 } 1004 1005 // XEnumerationAccess 1006 1007 uno::Reference<container::XEnumeration> SAL_CALL ScAreaLinksObj::createEnumeration() 1008 throw(uno::RuntimeException) 1009 { 1010 ScUnoGuard aGuard; 1011 return new ScIndexEnumeration(this, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.CellAreaLinksEnumeration"))); 1012 } 1013 1014 // XIndexAccess 1015 1016 sal_Int32 SAL_CALL ScAreaLinksObj::getCount() throw(uno::RuntimeException) 1017 { 1018 ScUnoGuard aGuard; 1019 sal_Int32 nAreaCount = 0; 1020 if (pDocShell) 1021 { 1022 sfx2::LinkManager* pLinkManager = pDocShell->GetDocument()->GetLinkManager(); 1023 sal_uInt16 nTotalCount = pLinkManager->GetLinks().Count(); 1024 for (sal_uInt16 i=0; i<nTotalCount; i++) 1025 { 1026 ::sfx2::SvBaseLink* pBase = *pLinkManager->GetLinks()[i]; 1027 if (pBase->ISA(ScAreaLink)) 1028 ++nAreaCount; 1029 } 1030 } 1031 return nAreaCount; 1032 } 1033 1034 uno::Any SAL_CALL ScAreaLinksObj::getByIndex( sal_Int32 nIndex ) 1035 throw(lang::IndexOutOfBoundsException, 1036 lang::WrappedTargetException, uno::RuntimeException) 1037 { 1038 ScUnoGuard aGuard; 1039 uno::Reference<sheet::XAreaLink> xLink(GetObjectByIndex_Impl(nIndex)); 1040 if (xLink.is()) 1041 return uno::makeAny(xLink); 1042 else 1043 throw lang::IndexOutOfBoundsException(); 1044 // return uno::Any(); 1045 } 1046 1047 uno::Type SAL_CALL ScAreaLinksObj::getElementType() throw(uno::RuntimeException) 1048 { 1049 ScUnoGuard aGuard; 1050 return getCppuType((uno::Reference<sheet::XAreaLink>*)0); 1051 } 1052 1053 sal_Bool SAL_CALL ScAreaLinksObj::hasElements() throw(uno::RuntimeException) 1054 { 1055 ScUnoGuard aGuard; 1056 return ( getCount() != 0 ); 1057 } 1058 1059 //------------------------------------------------------------------------ 1060 1061 ScDDELinkObj::ScDDELinkObj(ScDocShell* pDocSh, const String& rA, 1062 const String& rT, const String& rI) : 1063 pDocShell( pDocSh ), 1064 aAppl( rA ), 1065 aTopic( rT ), 1066 aItem( rI ) 1067 { 1068 pDocShell->GetDocument()->AddUnoObject(*this); 1069 } 1070 1071 ScDDELinkObj::~ScDDELinkObj() 1072 { 1073 if (pDocShell) 1074 pDocShell->GetDocument()->RemoveUnoObject(*this); 1075 } 1076 1077 void ScDDELinkObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) 1078 { 1079 //! notify if links in document are changed 1080 // UpdateRef is not needed here 1081 1082 if ( rHint.ISA( SfxSimpleHint ) ) 1083 { 1084 if ( ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) 1085 pDocShell = NULL; // pointer is invalid 1086 } 1087 else if ( rHint.ISA( ScLinkRefreshedHint ) ) 1088 { 1089 const ScLinkRefreshedHint& rLH = (const ScLinkRefreshedHint&) rHint; 1090 if ( rLH.GetLinkType() == SC_LINKREFTYPE_DDE && 1091 rLH.GetDdeAppl() == aAppl && 1092 rLH.GetDdeTopic() == aTopic && 1093 rLH.GetDdeItem() == aItem ) //! mode is ignored 1094 Refreshed_Impl(); 1095 } 1096 } 1097 1098 // XNamed 1099 1100 String lcl_BuildDDEName( const String& rAppl, const String& rTopic, const String& rItem ) 1101 { 1102 // Appl|Topic!Item (wie Excel) 1103 String aRet = rAppl; 1104 aRet += '|'; 1105 aRet += rTopic; 1106 aRet += '!'; 1107 aRet += rItem; 1108 return aRet; 1109 } 1110 1111 rtl::OUString SAL_CALL ScDDELinkObj::getName() throw(uno::RuntimeException) 1112 { 1113 ScUnoGuard aGuard; 1114 return lcl_BuildDDEName( aAppl, aTopic, aItem ); 1115 } 1116 1117 void SAL_CALL ScDDELinkObj::setName( const rtl::OUString& /* aName */ ) throw(uno::RuntimeException) 1118 { 1119 // name can't be changed (formulas wouldn't find the link) 1120 throw uno::RuntimeException(); 1121 } 1122 1123 // XDDELink 1124 1125 rtl::OUString SAL_CALL ScDDELinkObj::getApplication() throw(uno::RuntimeException) 1126 { 1127 ScUnoGuard aGuard; 1128 //! Test, ob Link noch im Dokument enthalten? 1129 1130 return aAppl; 1131 } 1132 1133 rtl::OUString SAL_CALL ScDDELinkObj::getTopic() throw(uno::RuntimeException) 1134 { 1135 ScUnoGuard aGuard; 1136 //! Test, ob Link noch im Dokument enthalten? 1137 1138 return aTopic; 1139 } 1140 1141 rtl::OUString SAL_CALL ScDDELinkObj::getItem() throw(uno::RuntimeException) 1142 { 1143 ScUnoGuard aGuard; 1144 //! Test, ob Link noch im Dokument enthalten? 1145 1146 return aItem; 1147 } 1148 1149 // XRefreshable 1150 1151 void SAL_CALL ScDDELinkObj::refresh() throw(uno::RuntimeException) 1152 { 1153 ScUnoGuard aGuard; 1154 if (pDocShell) 1155 { 1156 ScDocument* pDoc = pDocShell->GetDocument(); 1157 (void)pDoc->UpdateDdeLink( aAppl, aTopic, aItem ); 1158 //! Fehler abfragen 1159 } 1160 } 1161 1162 void SAL_CALL ScDDELinkObj::addRefreshListener( 1163 const uno::Reference<util::XRefreshListener >& xListener ) 1164 throw(uno::RuntimeException) 1165 { 1166 ScUnoGuard aGuard; 1167 uno::Reference<util::XRefreshListener>* pObj = 1168 new uno::Reference<util::XRefreshListener>( xListener ); 1169 aRefreshListeners.Insert( pObj, aRefreshListeners.Count() ); 1170 1171 // hold one additional ref to keep this object alive as long as there are listeners 1172 if ( aRefreshListeners.Count() == 1 ) 1173 acquire(); 1174 } 1175 1176 void SAL_CALL ScDDELinkObj::removeRefreshListener( 1177 const uno::Reference<util::XRefreshListener >& xListener ) 1178 throw(uno::RuntimeException) 1179 { 1180 ScUnoGuard aGuard; 1181 sal_uInt16 nCount = aRefreshListeners.Count(); 1182 for ( sal_uInt16 n=nCount; n--; ) 1183 { 1184 uno::Reference<util::XRefreshListener>* pObj = aRefreshListeners[n]; 1185 if ( *pObj == xListener ) 1186 { 1187 aRefreshListeners.DeleteAndDestroy( n ); 1188 if ( aRefreshListeners.Count() == 0 ) 1189 release(); // release ref for listeners 1190 break; 1191 } 1192 } 1193 } 1194 1195 // XDDELinkResults 1196 1197 uno::Sequence< uno::Sequence< uno::Any > > ScDDELinkObj::getResults( ) 1198 throw (uno::RuntimeException) 1199 { 1200 ScUnoGuard aGuard; 1201 uno::Sequence< uno::Sequence< uno::Any > > aReturn; 1202 bool bSuccess = false; 1203 1204 if ( pDocShell ) 1205 { 1206 ScDocument* pDoc = pDocShell->GetDocument(); 1207 if ( pDoc ) 1208 { 1209 sal_uInt16 nPos = 0; 1210 if ( pDoc->FindDdeLink( aAppl, aTopic, aItem, SC_DDE_IGNOREMODE, nPos ) ) 1211 { 1212 const ScMatrix* pMatrix = pDoc->GetDdeLinkResultMatrix( nPos ); 1213 if ( pMatrix ) 1214 { 1215 uno::Any aAny; 1216 if ( ScRangeToSequence::FillMixedArray( aAny, pMatrix, true ) ) 1217 { 1218 aAny >>= aReturn; 1219 } 1220 } 1221 bSuccess = true; 1222 } 1223 } 1224 } 1225 1226 if ( !bSuccess ) 1227 { 1228 throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 1229 "ScDDELinkObj::getResults: failed to get results!" ) ), 1230 uno::Reference< uno::XInterface >() ); 1231 } 1232 1233 return aReturn; 1234 } 1235 1236 void ScDDELinkObj::setResults( const uno::Sequence< uno::Sequence< uno::Any > >& aResults ) 1237 throw (uno::RuntimeException) 1238 { 1239 ScUnoGuard aGuard; 1240 bool bSuccess = false; 1241 1242 if ( pDocShell ) 1243 { 1244 ScDocument* pDoc = pDocShell->GetDocument(); 1245 if ( pDoc ) 1246 { 1247 sal_uInt16 nPos = 0; 1248 if ( pDoc->FindDdeLink( aAppl, aTopic, aItem, SC_DDE_IGNOREMODE, nPos ) ) 1249 { 1250 uno::Any aAny; 1251 aAny <<= aResults; 1252 ScMatrixRef xMatrix = ScSequenceToMatrix::CreateMixedMatrix( aAny ); 1253 bSuccess = pDoc->SetDdeLinkResultMatrix( nPos, xMatrix ); 1254 } 1255 } 1256 } 1257 1258 if ( !bSuccess ) 1259 { 1260 throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 1261 "ScDDELinkObj::setResults: failed to set results!" ) ), 1262 uno::Reference< uno::XInterface >() ); 1263 } 1264 } 1265 1266 void ScDDELinkObj::Refreshed_Impl() 1267 { 1268 lang::EventObject aEvent; 1269 aEvent.Source.set((cppu::OWeakObject*)this); 1270 for ( sal_uInt16 n=0; n<aRefreshListeners.Count(); n++ ) 1271 (*aRefreshListeners[n])->refreshed( aEvent ); 1272 } 1273 1274 //------------------------------------------------------------------------ 1275 1276 ScDDELinksObj::ScDDELinksObj(ScDocShell* pDocSh) : 1277 pDocShell( pDocSh ) 1278 { 1279 pDocShell->GetDocument()->AddUnoObject(*this); 1280 } 1281 1282 ScDDELinksObj::~ScDDELinksObj() 1283 { 1284 if (pDocShell) 1285 pDocShell->GetDocument()->RemoveUnoObject(*this); 1286 } 1287 1288 void ScDDELinksObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) 1289 { 1290 // Referenz-Update interessiert hier nicht 1291 1292 if ( rHint.ISA( SfxSimpleHint ) && 1293 ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) 1294 { 1295 pDocShell = NULL; // ungueltig geworden 1296 } 1297 } 1298 1299 // XDDELinks 1300 1301 ScDDELinkObj* ScDDELinksObj::GetObjectByIndex_Impl(sal_Int32 nIndex) 1302 { 1303 if (pDocShell) 1304 { 1305 String aAppl, aTopic, aItem; 1306 if ( nIndex <= USHRT_MAX && 1307 pDocShell->GetDocument()->GetDdeLinkData( (sal_uInt16)nIndex, aAppl, aTopic, aItem ) ) 1308 return new ScDDELinkObj( pDocShell, aAppl, aTopic, aItem ); 1309 } 1310 return NULL; 1311 } 1312 1313 ScDDELinkObj* ScDDELinksObj::GetObjectByName_Impl(const rtl::OUString& aName) 1314 { 1315 if (pDocShell) 1316 { 1317 String aNamStr(aName); 1318 String aAppl, aTopic, aItem; 1319 1320 ScDocument* pDoc = pDocShell->GetDocument(); 1321 sal_uInt16 nCount = pDoc->GetDdeLinkCount(); 1322 for (sal_uInt16 i=0; i<nCount; i++) 1323 { 1324 pDoc->GetDdeLinkData( i, aAppl, aTopic, aItem ); 1325 if ( lcl_BuildDDEName(aAppl, aTopic, aItem) == aNamStr ) 1326 return new ScDDELinkObj( pDocShell, aAppl, aTopic, aItem ); 1327 } 1328 } 1329 return NULL; 1330 } 1331 1332 // XEnumerationAccess 1333 1334 uno::Reference<container::XEnumeration> SAL_CALL ScDDELinksObj::createEnumeration() 1335 throw(uno::RuntimeException) 1336 { 1337 ScUnoGuard aGuard; 1338 return new ScIndexEnumeration(this, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.DDELinksEnumeration"))); 1339 } 1340 1341 // XIndexAccess 1342 1343 sal_Int32 SAL_CALL ScDDELinksObj::getCount() throw(uno::RuntimeException) 1344 { 1345 ScUnoGuard aGuard; 1346 sal_Int32 nAreaCount = 0; 1347 if (pDocShell) 1348 nAreaCount = pDocShell->GetDocument()->GetDdeLinkCount(); 1349 return nAreaCount; 1350 } 1351 1352 uno::Any SAL_CALL ScDDELinksObj::getByIndex( sal_Int32 nIndex ) 1353 throw(lang::IndexOutOfBoundsException, 1354 lang::WrappedTargetException, uno::RuntimeException) 1355 { 1356 ScUnoGuard aGuard; 1357 uno::Reference<sheet::XDDELink> xLink(GetObjectByIndex_Impl(nIndex)); 1358 if (xLink.is()) 1359 return uno::makeAny(xLink); 1360 else 1361 throw lang::IndexOutOfBoundsException(); 1362 // return uno::Any(); 1363 } 1364 1365 uno::Type SAL_CALL ScDDELinksObj::getElementType() throw(uno::RuntimeException) 1366 { 1367 ScUnoGuard aGuard; 1368 return getCppuType((uno::Reference<sheet::XDDELink>*)0); 1369 } 1370 1371 sal_Bool SAL_CALL ScDDELinksObj::hasElements() throw(uno::RuntimeException) 1372 { 1373 ScUnoGuard aGuard; 1374 return ( getCount() != 0 ); 1375 } 1376 1377 uno::Any SAL_CALL ScDDELinksObj::getByName( const rtl::OUString& aName ) 1378 throw(container::NoSuchElementException, 1379 lang::WrappedTargetException, uno::RuntimeException) 1380 { 1381 ScUnoGuard aGuard; 1382 uno::Reference<sheet::XDDELink> xLink(GetObjectByName_Impl(aName)); 1383 if (xLink.is()) 1384 return uno::makeAny(xLink); 1385 else 1386 throw container::NoSuchElementException(); 1387 // return uno::Any(); 1388 } 1389 1390 uno::Sequence<rtl::OUString> SAL_CALL ScDDELinksObj::getElementNames() throw(uno::RuntimeException) 1391 { 1392 ScUnoGuard aGuard; 1393 if (pDocShell) 1394 { 1395 String aAppl, aTopic, aItem; 1396 1397 ScDocument* pDoc = pDocShell->GetDocument(); 1398 sal_uInt16 nCount = pDoc->GetDdeLinkCount(); 1399 uno::Sequence<rtl::OUString> aSeq(nCount); 1400 rtl::OUString* pAry = aSeq.getArray(); 1401 1402 for (sal_uInt16 i=0; i<nCount; i++) 1403 { 1404 pDoc->GetDdeLinkData( i, aAppl, aTopic, aItem ); 1405 pAry[i] = lcl_BuildDDEName(aAppl, aTopic, aItem); 1406 } 1407 return aSeq; 1408 } 1409 return uno::Sequence<rtl::OUString>(); 1410 } 1411 1412 sal_Bool SAL_CALL ScDDELinksObj::hasByName( const rtl::OUString& aName ) 1413 throw(uno::RuntimeException) 1414 { 1415 ScUnoGuard aGuard; 1416 if (pDocShell) 1417 { 1418 String aNamStr(aName); 1419 String aAppl, aTopic, aItem; 1420 1421 ScDocument* pDoc = pDocShell->GetDocument(); 1422 sal_uInt16 nCount = pDoc->GetDdeLinkCount(); 1423 for (sal_uInt16 i=0; i<nCount; i++) 1424 { 1425 pDoc->GetDdeLinkData( i, aAppl, aTopic, aItem ); 1426 if ( lcl_BuildDDEName(aAppl, aTopic, aItem) == aNamStr ) 1427 return sal_True; 1428 } 1429 } 1430 return sal_False; 1431 } 1432 1433 // XDDELinks 1434 1435 uno::Reference< sheet::XDDELink > ScDDELinksObj::addDDELink( 1436 const ::rtl::OUString& aApplication, const ::rtl::OUString& aTopic, 1437 const ::rtl::OUString& aItem, ::com::sun::star::sheet::DDELinkMode nMode ) 1438 throw (uno::RuntimeException) 1439 { 1440 ScUnoGuard aGuard; 1441 uno::Reference< sheet::XDDELink > xLink; 1442 1443 if ( pDocShell ) 1444 { 1445 ScDocument* pDoc = pDocShell->GetDocument(); 1446 if ( pDoc ) 1447 { 1448 sal_uInt8 nMod = SC_DDE_DEFAULT; 1449 switch ( nMode ) 1450 { 1451 case sheet::DDELinkMode_DEFAULT: 1452 { 1453 nMod = SC_DDE_DEFAULT; 1454 } 1455 break; 1456 case sheet::DDELinkMode_ENGLISH: 1457 { 1458 nMod = SC_DDE_ENGLISH; 1459 } 1460 break; 1461 case sheet::DDELinkMode_TEXT: 1462 { 1463 nMod = SC_DDE_TEXT; 1464 } 1465 break; 1466 default: 1467 { 1468 } 1469 break; 1470 } 1471 1472 if ( pDoc->CreateDdeLink( aApplication, aTopic, aItem, nMod ) ) 1473 { 1474 const ::rtl::OUString aName( lcl_BuildDDEName( aApplication, aTopic, aItem ) ); 1475 xLink.set( GetObjectByName_Impl( aName ) ); 1476 } 1477 } 1478 } 1479 1480 if ( !xLink.is() ) 1481 { 1482 throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 1483 "ScDDELinksObj::addDDELink: cannot add DDE link!" ) ), 1484 uno::Reference< uno::XInterface >() ); 1485 } 1486 1487 return xLink; 1488 } 1489 1490 // ============================================================================ 1491 1492 ScExternalSheetCacheObj::ScExternalSheetCacheObj(ScExternalRefCache::TableTypeRef pTable, size_t nIndex) : 1493 mpTable(pTable), 1494 mnIndex(nIndex) 1495 { 1496 } 1497 1498 ScExternalSheetCacheObj::~ScExternalSheetCacheObj() 1499 { 1500 } 1501 1502 void SAL_CALL ScExternalSheetCacheObj::setCellValue(sal_Int32 nCol, sal_Int32 nRow, const Any& rValue) 1503 throw (IllegalArgumentException, RuntimeException) 1504 { 1505 ScUnoGuard aGuard; 1506 if (nRow < 0 || nCol < 0) 1507 throw IllegalArgumentException(); 1508 1509 ScExternalRefCache::TokenRef pToken; 1510 double fVal = 0.0; 1511 OUString aVal; 1512 if (rValue >>= fVal) 1513 pToken.reset(new FormulaDoubleToken(fVal)); 1514 else if (rValue >>= aVal) 1515 pToken.reset(new FormulaStringToken(aVal)); 1516 else 1517 // unidentified value type. 1518 return; 1519 1520 mpTable->setCell(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), pToken); 1521 } 1522 1523 Any SAL_CALL ScExternalSheetCacheObj::getCellValue(sal_Int32 nCol, sal_Int32 nRow) 1524 throw (IllegalArgumentException, RuntimeException) 1525 { 1526 ScUnoGuard aGuard; 1527 if (nRow < 0 || nCol < 0) 1528 throw IllegalArgumentException(); 1529 1530 FormulaToken* pToken = mpTable->getCell(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow)).get(); 1531 if (!pToken) 1532 throw IllegalArgumentException(); 1533 1534 Any aValue; 1535 switch (pToken->GetType()) 1536 { 1537 case svDouble: 1538 { 1539 double fVal = pToken->GetDouble(); 1540 aValue <<= fVal; 1541 } 1542 break; 1543 case svString: 1544 { 1545 OUString aVal = pToken->GetString(); 1546 aValue <<= aVal; 1547 } 1548 break; 1549 default: 1550 throw IllegalArgumentException(); 1551 } 1552 return aValue; 1553 } 1554 1555 Sequence< sal_Int32 > SAL_CALL ScExternalSheetCacheObj::getAllRows() 1556 throw (RuntimeException) 1557 { 1558 ScUnoGuard aGuard; 1559 vector<SCROW> aRows; 1560 mpTable->getAllRows(aRows); 1561 size_t nSize = aRows.size(); 1562 Sequence<sal_Int32> aRowsSeq(nSize); 1563 for (size_t i = 0; i < nSize; ++i) 1564 aRowsSeq[i] = aRows[i]; 1565 1566 return aRowsSeq; 1567 } 1568 1569 Sequence< sal_Int32 > SAL_CALL ScExternalSheetCacheObj::getAllColumns(sal_Int32 nRow) 1570 throw (IllegalArgumentException, RuntimeException) 1571 { 1572 ScUnoGuard aGuard; 1573 if (nRow < 0) 1574 throw IllegalArgumentException(); 1575 1576 vector<SCCOL> aCols; 1577 mpTable->getAllCols(static_cast<SCROW>(nRow), aCols); 1578 size_t nSize = aCols.size(); 1579 Sequence<sal_Int32> aColsSeq(nSize); 1580 for (size_t i = 0; i < nSize; ++i) 1581 aColsSeq[i] = aCols[i]; 1582 1583 return aColsSeq; 1584 } 1585 1586 sal_Int32 SAL_CALL ScExternalSheetCacheObj::getTokenIndex() 1587 throw (RuntimeException) 1588 { 1589 return static_cast< sal_Int32 >( mnIndex ); 1590 } 1591 1592 // ============================================================================ 1593 1594 ScExternalDocLinkObj::ScExternalDocLinkObj(ScExternalRefManager* pRefMgr, sal_uInt16 nFileId) : 1595 mpRefMgr(pRefMgr), mnFileId(nFileId) 1596 { 1597 } 1598 1599 ScExternalDocLinkObj::~ScExternalDocLinkObj() 1600 { 1601 } 1602 1603 Reference< sheet::XExternalSheetCache > SAL_CALL ScExternalDocLinkObj::addSheetCache( 1604 const OUString& aSheetName, sal_Bool bDynamicCache ) 1605 throw (RuntimeException) 1606 { 1607 ScUnoGuard aGuard; 1608 size_t nIndex = 0; 1609 ScExternalRefCache::TableTypeRef pTable = mpRefMgr->getCacheTable(mnFileId, aSheetName, true, &nIndex); 1610 if (!bDynamicCache) 1611 // Set the whole table cached to prevent access to the source document. 1612 pTable->setWholeTableCached(); 1613 1614 Reference< sheet::XExternalSheetCache > aSheetCache(new ScExternalSheetCacheObj(pTable, nIndex)); 1615 return aSheetCache; 1616 } 1617 1618 Any SAL_CALL ScExternalDocLinkObj::getByName(const::rtl::OUString &aName) 1619 throw (container::NoSuchElementException, lang::WrappedTargetException, RuntimeException) 1620 { 1621 ScUnoGuard aGuard; 1622 size_t nIndex = 0; 1623 ScExternalRefCache::TableTypeRef pTable = mpRefMgr->getCacheTable(mnFileId, aName, false, &nIndex); 1624 if (!pTable) 1625 throw container::NoSuchElementException(); 1626 1627 Reference< sheet::XExternalSheetCache > aSheetCache(new ScExternalSheetCacheObj(pTable, nIndex)); 1628 1629 Any aAny; 1630 aAny <<= aSheetCache; 1631 return aAny; 1632 } 1633 1634 Sequence< OUString > SAL_CALL ScExternalDocLinkObj::getElementNames() 1635 throw (RuntimeException) 1636 { 1637 ScUnoGuard aGuard; 1638 vector<String> aTabNames; 1639 mpRefMgr->getAllCachedTableNames(mnFileId, aTabNames); 1640 1641 // #i116940# be consistent with getByName: include only table names which have a cache already 1642 vector<String> aValidNames; 1643 for (vector<String>::const_iterator aIter = aTabNames.begin(); aIter != aTabNames.end(); ++aIter) 1644 if (mpRefMgr->getCacheTable(mnFileId, *aIter, false)) 1645 aValidNames.push_back(*aIter); 1646 1647 size_t n = aValidNames.size(); 1648 Sequence<OUString> aSeq(n); 1649 for (size_t i = 0; i < n; ++i) 1650 aSeq[i] = aValidNames[i]; 1651 return aSeq; 1652 } 1653 1654 sal_Bool SAL_CALL ScExternalDocLinkObj::hasByName(const OUString &aName) 1655 throw (RuntimeException) 1656 { 1657 ScUnoGuard aGuard; 1658 1659 // #i116940# be consistent with getByName: allow only table names which have a cache already 1660 ScExternalRefCache::TableTypeRef pTable = mpRefMgr->getCacheTable(mnFileId, aName, false); 1661 return (pTable.get() != NULL); 1662 } 1663 1664 sal_Int32 SAL_CALL ScExternalDocLinkObj::getCount() 1665 throw (RuntimeException) 1666 { 1667 ScUnoGuard aGuard; 1668 1669 // #i116940# be consistent with getByName: count only table names which have a cache already 1670 return getElementNames().getLength(); 1671 } 1672 1673 Any SAL_CALL ScExternalDocLinkObj::getByIndex(sal_Int32 nApiIndex) 1674 throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException, RuntimeException) 1675 { 1676 ScUnoGuard aGuard; 1677 1678 // #i116940# Can't use nApiIndex as index for the ref manager, because the API counts only 1679 // the entries which have a cache already. Quick solution: Use getElementNames. 1680 1681 Sequence< OUString > aNames( getElementNames() ); 1682 if (nApiIndex < 0 || nApiIndex >= aNames.getLength()) 1683 throw lang::IndexOutOfBoundsException(); 1684 1685 size_t nIndex = 0; 1686 ScExternalRefCache::TableTypeRef pTable = mpRefMgr->getCacheTable(mnFileId, aNames[nApiIndex], false, &nIndex); 1687 if (!pTable) 1688 throw lang::IndexOutOfBoundsException(); 1689 1690 Reference< sheet::XExternalSheetCache > aSheetCache(new ScExternalSheetCacheObj(pTable, nIndex)); 1691 1692 Any aAny; 1693 aAny <<= aSheetCache; 1694 return aAny; 1695 } 1696 1697 Reference< container::XEnumeration > SAL_CALL ScExternalDocLinkObj::createEnumeration() 1698 throw (RuntimeException) 1699 { 1700 ScUnoGuard aGuard; 1701 Reference< container::XEnumeration > aRef( 1702 new ScIndexEnumeration(this, OUString::createFromAscii( 1703 "com.sun.star.sheet.ExternalDocLink"))); 1704 return aRef; 1705 } 1706 1707 uno::Type SAL_CALL ScExternalDocLinkObj::getElementType() 1708 throw (RuntimeException) 1709 { 1710 ScUnoGuard aGuard; 1711 return getCppuType(static_cast<Reference<sheet::XExternalDocLink>*>(0)); 1712 } 1713 1714 sal_Bool SAL_CALL ScExternalDocLinkObj::hasElements() 1715 throw (RuntimeException) 1716 { 1717 ScUnoGuard aGuard; 1718 1719 // #i116940# be consistent with getByName: count only table names which have a cache already 1720 return ( getElementNames().getLength() > 0 ); 1721 } 1722 1723 sal_Int32 SAL_CALL ScExternalDocLinkObj::getTokenIndex() 1724 throw (RuntimeException) 1725 { 1726 return static_cast<sal_Int32>(mnFileId); 1727 } 1728 1729 // ============================================================================ 1730 1731 ScExternalDocLinksObj::ScExternalDocLinksObj(ScDocShell* pDocShell) : 1732 mpDocShell(pDocShell), 1733 mpRefMgr(pDocShell->GetDocument()->GetExternalRefManager()) 1734 { 1735 } 1736 1737 ScExternalDocLinksObj::~ScExternalDocLinksObj() 1738 { 1739 } 1740 1741 Reference< sheet::XExternalDocLink > SAL_CALL ScExternalDocLinksObj::addDocLink( 1742 const OUString& aDocName ) 1743 throw (RuntimeException) 1744 { 1745 ScUnoGuard aGuard; 1746 sal_uInt16 nFileId = mpRefMgr->getExternalFileId(aDocName); 1747 Reference< sheet::XExternalDocLink > aDocLink(new ScExternalDocLinkObj(mpRefMgr, nFileId)); 1748 return aDocLink; 1749 } 1750 1751 Any SAL_CALL ScExternalDocLinksObj::getByName(const::rtl::OUString &aName) 1752 throw (container::NoSuchElementException, lang::WrappedTargetException, RuntimeException) 1753 { 1754 ScUnoGuard aGuard; 1755 if (!mpRefMgr->hasExternalFile(aName)) 1756 throw container::NoSuchElementException(); 1757 1758 sal_uInt16 nFileId = mpRefMgr->getExternalFileId(aName); 1759 Reference< sheet::XExternalDocLink > aDocLink(new ScExternalDocLinkObj(mpRefMgr, nFileId)); 1760 1761 Any aAny; 1762 aAny <<= aDocLink; 1763 return aAny; 1764 } 1765 1766 Sequence< OUString > SAL_CALL ScExternalDocLinksObj::getElementNames() 1767 throw (RuntimeException) 1768 { 1769 ScUnoGuard aGuard; 1770 sal_uInt16 n = mpRefMgr->getExternalFileCount(); 1771 Sequence<OUString> aSeq(n); 1772 for (sal_uInt16 i = 0; i < n; ++i) 1773 { 1774 const String* pName = mpRefMgr->getExternalFileName(i); 1775 aSeq[i] = pName ? *pName : EMPTY_STRING; 1776 } 1777 1778 return aSeq; 1779 } 1780 1781 sal_Bool SAL_CALL ScExternalDocLinksObj::hasByName(const OUString &aName) 1782 throw (RuntimeException) 1783 { 1784 ScUnoGuard aGuard; 1785 return mpRefMgr->hasExternalFile(aName); 1786 } 1787 1788 sal_Int32 SAL_CALL ScExternalDocLinksObj::getCount() 1789 throw (RuntimeException) 1790 { 1791 ScUnoGuard aGuard; 1792 return mpRefMgr->getExternalFileCount(); 1793 } 1794 1795 Any SAL_CALL ScExternalDocLinksObj::getByIndex(sal_Int32 nIndex) 1796 throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException, RuntimeException) 1797 { 1798 ScUnoGuard aGuard; 1799 if (nIndex > ::std::numeric_limits<sal_uInt16>::max() || nIndex < ::std::numeric_limits<sal_uInt16>::min()) 1800 throw lang::IndexOutOfBoundsException(); 1801 1802 sal_uInt16 nFileId = static_cast<sal_uInt16>(nIndex); 1803 1804 if (!mpRefMgr->hasExternalFile(nFileId)) 1805 throw lang::IndexOutOfBoundsException(); 1806 1807 Reference< sheet::XExternalDocLink > aDocLink(new ScExternalDocLinkObj(mpRefMgr, nFileId)); 1808 Any aAny; 1809 aAny <<= aDocLink; 1810 return aAny; 1811 } 1812 1813 Reference< container::XEnumeration > SAL_CALL ScExternalDocLinksObj::createEnumeration() 1814 throw (RuntimeException) 1815 { 1816 ScUnoGuard aGuard; 1817 Reference< container::XEnumeration > aRef( 1818 new ScIndexEnumeration(this, OUString::createFromAscii( 1819 "com.sun.star.sheet.ExternalDocLinks"))); 1820 return aRef; 1821 } 1822 1823 uno::Type SAL_CALL ScExternalDocLinksObj::getElementType() 1824 throw (RuntimeException) 1825 { 1826 ScUnoGuard aGuard; 1827 return getCppuType(static_cast<Reference<sheet::XExternalDocLinks>*>(0)); 1828 } 1829 1830 sal_Bool SAL_CALL ScExternalDocLinksObj::hasElements() 1831 throw (RuntimeException) 1832 { 1833 ScUnoGuard aGuard; 1834 return mpRefMgr->getExternalFileCount() > 0; 1835 } 1836 1837