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