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