calc: on editing invalidation of view with different zoom is wrong
[LibreOffice.git] / sc / source / ui / unoobj / linkuno.cxx
blob6d22a06559d84fcfc0ba23973f03e14c353cc077
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
23 #include <comphelper/sequence.hxx>
24 #include <formula/token.hxx>
25 #include <svl/hint.hxx>
26 #include <sfx2/linkmgr.hxx>
27 #include <utility>
28 #include <vcl/svapp.hxx>
29 #include <svl/sharedstringpool.hxx>
31 #include <linkuno.hxx>
32 #include <miscuno.hxx>
33 #include <convuno.hxx>
34 #include <docsh.hxx>
35 #include <docfunc.hxx>
36 #include <tablink.hxx>
37 #include <arealink.hxx>
38 #include <hints.hxx>
39 #include <unonames.hxx>
40 #include <rangeseq.hxx>
41 #include <scmatrix.hxx>
42 #include <documentlinkmgr.hxx>
44 #include <string_view>
45 #include <vector>
47 using namespace com::sun::star;
48 using namespace formula;
49 using ::com::sun::star::uno::Any;
50 using ::com::sun::star::uno::Sequence;
51 using ::com::sun::star::lang::IllegalArgumentException;
52 using ::com::sun::star::uno::RuntimeException;
53 using ::std::vector;
55 // used for sheet- and area link:
56 static o3tl::span<const SfxItemPropertyMapEntry> lcl_GetSheetLinkMap()
58 static const SfxItemPropertyMapEntry aSheetLinkMap_Impl[] =
60 { SC_UNONAME_FILTER, 0, cppu::UnoType<OUString>::get(), 0, 0 },
61 { SC_UNONAME_FILTOPT, 0, cppu::UnoType<OUString>::get(), 0, 0 },
62 { SC_UNONAME_LINKURL, 0, cppu::UnoType<OUString>::get(), 0, 0 },
63 { SC_UNONAME_REFDELAY, 0, cppu::UnoType<sal_Int32>::get(), 0, 0 },
64 { SC_UNONAME_REFPERIOD, 0, cppu::UnoType<sal_Int32>::get(), 0, 0 },
66 return aSheetLinkMap_Impl;
69 SC_SIMPLE_SERVICE_INFO( ScAreaLinkObj, "ScAreaLinkObj", "com.sun.star.sheet.CellAreaLink" )
70 SC_SIMPLE_SERVICE_INFO( ScAreaLinksObj, "ScAreaLinksObj", "com.sun.star.sheet.CellAreaLinks" )
71 SC_SIMPLE_SERVICE_INFO( ScDDELinkObj, "ScDDELinkObj", "com.sun.star.sheet.DDELink" )
72 SC_SIMPLE_SERVICE_INFO( ScDDELinksObj, "ScDDELinksObj", "com.sun.star.sheet.DDELinks" )
73 SC_SIMPLE_SERVICE_INFO( ScSheetLinkObj, "ScSheetLinkObj", "com.sun.star.sheet.SheetLink" )
74 SC_SIMPLE_SERVICE_INFO( ScSheetLinksObj, "ScSheetLinksObj", "com.sun.star.sheet.SheetLinks" )
76 ScSheetLinkObj::ScSheetLinkObj(ScDocShell* pDocSh, OUString aName) :
77 aPropSet( lcl_GetSheetLinkMap() ),
78 pDocShell( pDocSh ),
79 aFileName(std::move( aName ))
81 pDocShell->GetDocument().AddUnoObject(*this);
84 ScSheetLinkObj::~ScSheetLinkObj()
86 SolarMutexGuard g;
88 if (pDocShell)
89 pDocShell->GetDocument().RemoveUnoObject(*this);
92 void ScSheetLinkObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
94 //! notify if links in document are changed
95 // UpdateRef is not needed here
97 if ( auto pRefreshHint = dynamic_cast<const ScLinkRefreshedHint*>(&rHint) )
99 if ( pRefreshHint->GetLinkType() == ScLinkRefType::SHEET && pRefreshHint->GetUrl() == aFileName )
100 Refreshed_Impl();
102 else
104 if ( rHint.GetId() == SfxHintId::Dying )
105 pDocShell = nullptr; // pointer is invalid
109 ScTableLink* ScSheetLinkObj::GetLink_Impl() const
111 if (pDocShell)
113 sfx2::LinkManager* pLinkManager = pDocShell->GetDocument().GetLinkManager();
114 size_t nCount = pLinkManager->GetLinks().size();
115 for (size_t i=0; i<nCount; i++)
117 ::sfx2::SvBaseLink* pBase = pLinkManager->GetLinks()[i].get();
118 if (auto pTabLink = dynamic_cast<ScTableLink*>( pBase))
120 if ( pTabLink->GetFileName() == aFileName )
121 return pTabLink;
125 return nullptr; // not found
128 // XNamed
130 OUString SAL_CALL ScSheetLinkObj::getName()
132 SolarMutexGuard aGuard;
133 return getFileName(); // Name is the same as filename (URL)
136 void SAL_CALL ScSheetLinkObj::setName( const OUString& aName )
138 SolarMutexGuard aGuard;
139 setFileName(aName); // Name is the same as filename (URL)
142 // XRefreshable
144 void SAL_CALL ScSheetLinkObj::refresh()
146 SolarMutexGuard aGuard;
147 ScTableLink* pLink = GetLink_Impl();
148 if (pLink)
149 pLink->Refresh( pLink->GetFileName(), pLink->GetFilterName(), nullptr, pLink->GetRefreshDelaySeconds() );
152 void SAL_CALL ScSheetLinkObj::addRefreshListener(
153 const uno::Reference<util::XRefreshListener >& xListener )
155 SolarMutexGuard aGuard;
156 aRefreshListeners.push_back( xListener );
158 // hold one additional ref to keep this object alive as long as there are listeners
159 if ( aRefreshListeners.size() == 1 )
160 acquire();
163 void SAL_CALL ScSheetLinkObj::removeRefreshListener(
164 const uno::Reference<util::XRefreshListener >& xListener )
166 SolarMutexGuard aGuard;
167 size_t nCount = aRefreshListeners.size();
168 for ( size_t n=nCount; n--; )
170 uno::Reference<util::XRefreshListener>& rObj = aRefreshListeners[n];
171 if ( rObj == xListener )
173 aRefreshListeners.erase( aRefreshListeners.begin() + n );
174 if ( aRefreshListeners.empty() )
175 release(); // release ref for listeners
176 break;
181 void ScSheetLinkObj::Refreshed_Impl()
183 lang::EventObject aEvent;
184 aEvent.Source.set(static_cast<cppu::OWeakObject*>(this));
185 for (uno::Reference<util::XRefreshListener> & xRefreshListener : aRefreshListeners)
186 xRefreshListener->refreshed( aEvent );
189 void ScSheetLinkObj::ModifyRefreshDelay_Impl( sal_Int32 nRefresh )
191 ScTableLink* pLink = GetLink_Impl();
192 if( pLink )
193 pLink->SetRefreshDelay( static_cast<sal_uLong>(nRefresh) );
196 // XPropertySet
198 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScSheetLinkObj::getPropertySetInfo()
200 SolarMutexGuard aGuard;
201 static uno::Reference<beans::XPropertySetInfo> aRef(
202 new SfxItemPropertySetInfo( aPropSet.getPropertyMap() ));
203 return aRef;
206 void SAL_CALL ScSheetLinkObj::setPropertyValue(
207 const OUString& aPropertyName, const uno::Any& aValue )
209 SolarMutexGuard aGuard;
210 OUString aValStr;
211 if ( aPropertyName == SC_UNONAME_LINKURL )
213 if ( aValue >>= aValStr )
214 setFileName( aValStr );
216 else if ( aPropertyName == SC_UNONAME_FILTER )
218 if ( aValue >>= aValStr )
219 setFilter( aValStr );
221 else if ( aPropertyName == SC_UNONAME_FILTOPT )
223 if ( aValue >>= aValStr )
224 setFilterOptions( aValStr );
226 else if ( aPropertyName == SC_UNONAME_REFPERIOD )
228 sal_Int32 nRefresh = 0;
229 if ( aValue >>= nRefresh )
230 setRefreshDelay( nRefresh );
232 else if ( aPropertyName == SC_UNONAME_REFDELAY )
234 sal_Int32 nRefresh = 0;
235 if ( aValue >>= nRefresh )
236 setRefreshDelay( nRefresh );
240 uno::Any SAL_CALL ScSheetLinkObj::getPropertyValue( const OUString& aPropertyName )
242 SolarMutexGuard aGuard;
243 uno::Any aRet;
244 if ( aPropertyName == SC_UNONAME_LINKURL )
245 aRet <<= getFileName();
246 else if ( aPropertyName == SC_UNONAME_FILTER )
247 aRet <<= getFilter();
248 else if ( aPropertyName == SC_UNONAME_FILTOPT )
249 aRet <<= getFilterOptions();
250 else if ( aPropertyName == SC_UNONAME_REFPERIOD )
251 aRet <<= getRefreshDelay();
252 else if ( aPropertyName == SC_UNONAME_REFDELAY )
253 aRet <<= getRefreshDelay();
254 return aRet;
257 SC_IMPL_DUMMY_PROPERTY_LISTENER( ScSheetLinkObj )
259 // internal:
261 OUString ScSheetLinkObj::getFileName() const
263 SolarMutexGuard aGuard;
264 return aFileName;
267 void ScSheetLinkObj::setFileName(const OUString& rNewName)
269 SolarMutexGuard aGuard;
270 ScTableLink* pLink = GetLink_Impl();
271 if (!pLink)
272 return;
274 // pLink->Refresh with a new file name confuses sfx2::LinkManager
275 // therefore we transplant the sheets manually and create new links with UpdateLinks
277 OUString aNewStr(ScGlobal::GetAbsDocName( rNewName, pDocShell ));
279 // first transplant the sheets
281 ScDocument& rDoc = pDocShell->GetDocument();
282 SCTAB nTabCount = rDoc.GetTableCount();
283 for (SCTAB nTab=0; nTab<nTabCount; nTab++)
284 if ( rDoc.IsLinked(nTab) && rDoc.GetLinkDoc(nTab) == aFileName ) // old file
285 rDoc.SetLink( nTab, rDoc.GetLinkMode(nTab), aNewStr,
286 rDoc.GetLinkFlt(nTab), rDoc.GetLinkOpt(nTab),
287 rDoc.GetLinkTab(nTab),
288 rDoc.GetLinkRefreshDelay(nTab) ); // only change the file
290 // update links
291 //! Undo !!!
293 pDocShell->UpdateLinks(); // remove old links, possibly set up new ones
295 // copy data
297 aFileName = aNewStr;
298 pLink = GetLink_Impl(); // new link with new name
299 if (pLink)
300 pLink->Update(); // incl. paint & undo for data
303 OUString ScSheetLinkObj::getFilter() const
305 SolarMutexGuard aGuard;
306 OUString aRet;
307 ScTableLink* pLink = GetLink_Impl();
308 if (pLink)
309 aRet = pLink->GetFilterName();
310 return aRet;
313 void ScSheetLinkObj::setFilter(const OUString& rFilter)
315 SolarMutexGuard aGuard;
316 ScTableLink* pLink = GetLink_Impl();
317 if (pLink)
319 pLink->Refresh( aFileName, rFilter, nullptr, pLink->GetRefreshDelaySeconds() );
323 OUString ScSheetLinkObj::getFilterOptions() const
325 SolarMutexGuard aGuard;
326 OUString aRet;
327 ScTableLink* pLink = GetLink_Impl();
328 if (pLink)
329 aRet = pLink->GetOptions();
330 return aRet;
333 void ScSheetLinkObj::setFilterOptions(const OUString& FilterOptions)
335 SolarMutexGuard aGuard;
336 ScTableLink* pLink = GetLink_Impl();
337 if (pLink)
339 OUString aOptStr(FilterOptions);
340 pLink->Refresh( aFileName, pLink->GetFilterName(), &aOptStr, pLink->GetRefreshDelaySeconds() );
344 sal_Int32 ScSheetLinkObj::getRefreshDelay() const
346 SolarMutexGuard aGuard;
347 sal_Int32 nRet = 0;
348 ScTableLink* pLink = GetLink_Impl();
349 if (pLink)
350 nRet = pLink->GetRefreshDelaySeconds();
351 return nRet;
354 void ScSheetLinkObj::setRefreshDelay(sal_Int32 nRefreshDelay)
356 SolarMutexGuard aGuard;
357 ModifyRefreshDelay_Impl( nRefreshDelay );
360 ScSheetLinksObj::ScSheetLinksObj(ScDocShell* pDocSh) :
361 pDocShell( pDocSh )
363 pDocShell->GetDocument().AddUnoObject(*this);
366 ScSheetLinksObj::~ScSheetLinksObj()
368 SolarMutexGuard g;
370 if (pDocShell)
371 pDocShell->GetDocument().RemoveUnoObject(*this);
374 void ScSheetLinksObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
376 // we don't care about update of references here
378 if ( rHint.GetId() == SfxHintId::Dying )
380 pDocShell = nullptr; // became invalid
384 // XSheetLinks
386 rtl::Reference<ScSheetLinkObj> ScSheetLinksObj::GetObjectByIndex_Impl(sal_Int32 nIndex)
388 if (!pDocShell)
389 return nullptr;
391 typedef std::unordered_set<OUString> StrSetType;
392 StrSetType aNames;
393 ScDocument& rDoc = pDocShell->GetDocument();
394 SCTAB nTabCount = rDoc.GetTableCount();
395 sal_Int32 nCount = 0;
396 for (SCTAB nTab = 0; nTab < nTabCount; ++nTab)
398 if (!rDoc.IsLinked(nTab))
399 continue;
401 OUString aLinkDoc = rDoc.GetLinkDoc(nTab);
402 if (aNames.insert(aLinkDoc).second)
404 // unique document name.
405 if (nCount == nIndex)
406 return new ScSheetLinkObj( pDocShell, aLinkDoc );
407 ++nCount;
411 return nullptr; // no document or index too large
414 rtl::Reference<ScSheetLinkObj> ScSheetLinksObj::GetObjectByName_Impl(const OUString& aName)
416 // Name is the same as file name
418 if (pDocShell)
420 ScDocument& rDoc = pDocShell->GetDocument();
421 SCTAB nTabCount = rDoc.GetTableCount();
422 for (SCTAB nTab=0; nTab<nTabCount; nTab++)
423 if (rDoc.IsLinked(nTab))
425 //! case-insensitive ???
426 OUString aLinkDoc = rDoc.GetLinkDoc( nTab );
427 if ( aLinkDoc == aName )
428 return new ScSheetLinkObj( pDocShell, aName );
432 return nullptr;
435 // XEnumerationAccess
436 uno::Reference<container::XEnumeration> SAL_CALL ScSheetLinksObj::createEnumeration()
438 SolarMutexGuard aGuard;
439 return new ScIndexEnumeration(this, "com.sun.star.sheet.SheetLinksEnumeration");
442 // XIndexAccess
443 sal_Int32 SAL_CALL ScSheetLinksObj::getCount()
445 typedef std::unordered_set<OUString> StrSetType;
447 SolarMutexGuard aGuard;
448 if (!pDocShell)
449 return 0;
451 sal_Int32 nCount = 0;
453 StrSetType aNames;
454 ScDocument& rDoc = pDocShell->GetDocument();
455 SCTAB nTabCount = rDoc.GetTableCount();
456 for (SCTAB nTab = 0; nTab < nTabCount; ++nTab)
458 if (!rDoc.IsLinked(nTab))
459 continue;
461 OUString aLinkDoc = rDoc.GetLinkDoc(nTab);
462 if (aNames.insert(aLinkDoc).second)
463 ++nCount;
465 return nCount;
468 uno::Any SAL_CALL ScSheetLinksObj::getByIndex( sal_Int32 nIndex )
470 SolarMutexGuard aGuard;
471 uno::Reference<beans::XPropertySet> xLink(GetObjectByIndex_Impl(nIndex));
472 if (!xLink.is())
473 throw lang::IndexOutOfBoundsException();
475 return uno::Any(xLink);
478 uno::Type SAL_CALL ScSheetLinksObj::getElementType()
480 return cppu::UnoType<beans::XPropertySet>::get();
483 sal_Bool SAL_CALL ScSheetLinksObj::hasElements()
485 SolarMutexGuard aGuard;
486 return ( getCount() != 0 );
489 uno::Any SAL_CALL ScSheetLinksObj::getByName( const OUString& aName )
491 SolarMutexGuard aGuard;
492 uno::Reference<beans::XPropertySet> xLink(GetObjectByName_Impl(aName));
493 if (!xLink.is())
494 throw container::NoSuchElementException();
496 return uno::Any(xLink);
499 sal_Bool SAL_CALL ScSheetLinksObj::hasByName( const OUString& aName )
501 SolarMutexGuard aGuard;
502 // Name is the same as file name
504 if (pDocShell)
506 ScDocument& rDoc = pDocShell->GetDocument();
507 SCTAB nTabCount = rDoc.GetTableCount();
508 for (SCTAB nTab=0; nTab<nTabCount; nTab++)
509 if (rDoc.IsLinked(nTab))
511 //! case-insensitive ???
512 OUString aLinkDoc(rDoc.GetLinkDoc( nTab ));
513 if ( aLinkDoc == aName )
514 return true;
517 return false;
520 uno::Sequence<OUString> SAL_CALL ScSheetLinksObj::getElementNames()
522 typedef std::unordered_set<OUString> StrSetType;
524 SolarMutexGuard aGuard;
525 // Name is the same as file name
527 if (!pDocShell)
528 return uno::Sequence<OUString>();
530 StrSetType aNames;
531 ScDocument& rDoc = pDocShell->GetDocument();
532 SCTAB nTabCount = rDoc.GetTableCount();
534 sal_Int32 nLinkCount = getCount();
535 uno::Sequence<OUString> aSeq(nLinkCount);
536 OUString* pAry = aSeq.getArray();
537 size_t nPos = 0;
538 for (SCTAB nTab = 0; nTab < nTabCount; ++nTab)
540 if (!rDoc.IsLinked(nTab))
541 continue;
543 OUString aLinkDoc = rDoc.GetLinkDoc(nTab);
544 if (aNames.insert(aLinkDoc).second)
545 pAry[nPos++] = aLinkDoc;
547 OSL_ENSURE( nPos==static_cast<size_t>(nLinkCount), "verzaehlt" );
548 return aSeq;
551 static ScAreaLink* lcl_GetAreaLink( ScDocShell* pDocShell, size_t nPos )
553 if (pDocShell)
555 sfx2::LinkManager* pLinkManager = pDocShell->GetDocument().GetLinkManager();
556 size_t nTotalCount = pLinkManager->GetLinks().size();
557 size_t nAreaCount = 0;
558 for (size_t i=0; i<nTotalCount; i++)
560 ::sfx2::SvBaseLink* pBase = pLinkManager->GetLinks()[i].get();
561 if (auto pAreaLink = dynamic_cast<ScAreaLink*>( pBase))
563 if ( nAreaCount == nPos )
564 return pAreaLink;
565 ++nAreaCount;
569 return nullptr; // not found
572 ScAreaLinkObj::ScAreaLinkObj(ScDocShell* pDocSh, size_t nP) :
573 aPropSet( lcl_GetSheetLinkMap() ),
574 pDocShell( pDocSh ),
575 nPos( nP )
577 pDocShell->GetDocument().AddUnoObject(*this);
580 ScAreaLinkObj::~ScAreaLinkObj()
582 SolarMutexGuard g;
584 if (pDocShell)
585 pDocShell->GetDocument().RemoveUnoObject(*this);
588 void ScAreaLinkObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
590 //! notify if links in document are changed
591 // UpdateRef is not needed here
593 if ( auto pRefreshedHint = dynamic_cast<const ScLinkRefreshedHint*>(&rHint) )
595 if ( pRefreshedHint->GetLinkType() == ScLinkRefType::AREA )
597 // get this link to compare dest position
598 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos);
599 if ( pLink && pLink->GetDestArea().aStart == pRefreshedHint->GetDestPos() )
600 Refreshed_Impl();
603 else
605 if ( rHint.GetId() == SfxHintId::Dying )
606 pDocShell = nullptr; // pointer is invalid
610 // XFileLink
612 void ScAreaLinkObj::Modify_Impl( const OUString* pNewFile, const OUString* pNewFilter,
613 const OUString* pNewOptions, const OUString* pNewSource,
614 const table::CellRangeAddress* pNewDest )
616 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos);
617 if (!pLink)
618 return;
620 OUString aFile (pLink->GetFile());
621 OUString aFilter (pLink->GetFilter());
622 OUString aOptions (pLink->GetOptions());
623 OUString aSource (pLink->GetSource());
624 ScRange aDest (pLink->GetDestArea());
625 sal_Int32 nRefreshDelaySeconds = pLink->GetRefreshDelaySeconds();
627 //! Undo delete
628 //! Undo merge
630 sfx2::LinkManager* pLinkManager = pDocShell->GetDocument().GetLinkManager();
631 pLinkManager->Remove( pLink );
632 pLink = nullptr; // deleted along with remove
634 bool bFitBlock = true; // move, if the size changes with update
635 if (pNewFile)
637 aFile = ScGlobal::GetAbsDocName( *pNewFile, pDocShell ); //! in InsertAreaLink?
639 if (pNewFilter)
640 aFilter = *pNewFilter;
641 if (pNewOptions)
642 aOptions = *pNewOptions;
643 if (pNewSource)
644 aSource = *pNewSource;
645 if (pNewDest)
647 ScUnoConversion::FillScRange( aDest, *pNewDest );
648 bFitBlock = false; // new range was specified -> do not move the content
650 pDocShell->GetDocFunc().InsertAreaLink( aFile, aFilter, aOptions, aSource,
651 aDest, nRefreshDelaySeconds, bFitBlock, true );
654 void ScAreaLinkObj::ModifyRefreshDelay_Impl( sal_Int32 nRefreshDelaySeconds )
656 ScAreaLink* pLink = lcl_GetAreaLink( pDocShell, nPos );
657 if( pLink )
658 pLink->SetRefreshDelay( nRefreshDelaySeconds );
661 // XRefreshable
663 void SAL_CALL ScAreaLinkObj::refresh()
665 SolarMutexGuard aGuard;
666 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos);
667 if (pLink)
668 pLink->Refresh( pLink->GetFile(), pLink->GetFilter(), pLink->GetSource(), pLink->GetRefreshDelaySeconds() );
671 void SAL_CALL ScAreaLinkObj::addRefreshListener(
672 const uno::Reference<util::XRefreshListener >& xListener )
674 SolarMutexGuard aGuard;
675 aRefreshListeners.push_back( xListener );
677 // hold one additional ref to keep this object alive as long as there are listeners
678 if ( aRefreshListeners.size() == 1 )
679 acquire();
682 void SAL_CALL ScAreaLinkObj::removeRefreshListener(
683 const uno::Reference<util::XRefreshListener >& xListener )
685 SolarMutexGuard aGuard;
686 size_t nCount = aRefreshListeners.size();
687 for ( size_t n=nCount; n--; )
689 uno::Reference<util::XRefreshListener>& rObj = aRefreshListeners[n];
690 if ( rObj == xListener )
692 aRefreshListeners.erase( aRefreshListeners.begin() + n );
693 if ( aRefreshListeners.empty() )
694 release(); // release ref for listeners
695 break;
698 if(n == 0)
699 break;
703 void ScAreaLinkObj::Refreshed_Impl()
705 lang::EventObject aEvent;
706 aEvent.Source.set(static_cast<cppu::OWeakObject*>(this));
707 for (uno::Reference<util::XRefreshListener> & xRefreshListener : aRefreshListeners)
708 xRefreshListener->refreshed( aEvent );
711 // XPropertySet
713 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScAreaLinkObj::getPropertySetInfo()
715 SolarMutexGuard aGuard;
716 static uno::Reference<beans::XPropertySetInfo> aRef(
717 new SfxItemPropertySetInfo( aPropSet.getPropertyMap() ));
718 return aRef;
721 void SAL_CALL ScAreaLinkObj::setPropertyValue(
722 const OUString& aPropertyName, const uno::Any& aValue )
724 SolarMutexGuard aGuard;
725 OUString aValStr;
726 if ( aPropertyName == SC_UNONAME_LINKURL )
728 if ( aValue >>= aValStr )
729 setFileName( aValStr );
731 else if ( aPropertyName == SC_UNONAME_FILTER )
733 if ( aValue >>= aValStr )
734 setFilter( aValStr );
736 else if ( aPropertyName == SC_UNONAME_FILTOPT )
738 if ( aValue >>= aValStr )
739 setFilterOptions( aValStr );
741 else if ( aPropertyName == SC_UNONAME_REFPERIOD )
743 sal_Int32 nRefresh = 0;
744 if ( aValue >>= nRefresh )
745 setRefreshDelay( nRefresh );
747 else if ( aPropertyName == SC_UNONAME_REFDELAY )
749 sal_Int32 nRefresh = 0;
750 if ( aValue >>= nRefresh )
751 setRefreshDelay( nRefresh );
755 uno::Any SAL_CALL ScAreaLinkObj::getPropertyValue( const OUString& aPropertyName )
757 SolarMutexGuard aGuard;
758 uno::Any aRet;
759 if ( aPropertyName == SC_UNONAME_LINKURL )
760 aRet <<= getFileName();
761 else if ( aPropertyName == SC_UNONAME_FILTER )
762 aRet <<= getFilter();
763 else if ( aPropertyName == SC_UNONAME_FILTOPT )
764 aRet <<= getFilterOptions();
765 else if ( aPropertyName == SC_UNONAME_REFPERIOD )
766 aRet <<= getRefreshDelay();
767 else if ( aPropertyName == SC_UNONAME_REFDELAY )
768 aRet <<= getRefreshDelay();
769 return aRet;
772 SC_IMPL_DUMMY_PROPERTY_LISTENER( ScAreaLinkObj )
774 // internal:
776 OUString ScAreaLinkObj::getFileName() const
778 SolarMutexGuard aGuard;
779 OUString aRet;
780 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos);
781 if (pLink)
782 aRet = pLink->GetFile();
783 return aRet;
786 void ScAreaLinkObj::setFileName(const OUString& rNewName)
788 SolarMutexGuard aGuard;
789 Modify_Impl( &rNewName, nullptr, nullptr, nullptr, nullptr );
792 OUString ScAreaLinkObj::getFilter() const
794 SolarMutexGuard aGuard;
795 OUString aRet;
796 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos);
797 if (pLink)
798 aRet = pLink->GetFilter();
799 return aRet;
802 void ScAreaLinkObj::setFilter(const OUString& Filter)
804 SolarMutexGuard aGuard;
805 Modify_Impl( nullptr, &Filter, nullptr, nullptr, nullptr );
808 OUString ScAreaLinkObj::getFilterOptions() const
810 SolarMutexGuard aGuard;
811 OUString aRet;
812 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos);
813 if (pLink)
814 aRet = pLink->GetOptions();
815 return aRet;
818 void ScAreaLinkObj::setFilterOptions(const OUString& FilterOptions)
820 SolarMutexGuard aGuard;
821 Modify_Impl( nullptr, nullptr, &FilterOptions, nullptr, nullptr );
824 sal_Int32 ScAreaLinkObj::getRefreshDelay() const
826 SolarMutexGuard aGuard;
827 sal_Int32 nRet = 0;
828 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos);
829 if (pLink)
830 nRet = pLink->GetRefreshDelaySeconds();
831 return nRet;
834 void ScAreaLinkObj::setRefreshDelay(sal_Int32 nRefreshDelay)
836 SolarMutexGuard aGuard;
837 ModifyRefreshDelay_Impl( nRefreshDelay );
840 // XAreaLink
842 OUString SAL_CALL ScAreaLinkObj::getSourceArea()
844 SolarMutexGuard aGuard;
845 OUString aRet;
846 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos);
847 if (pLink)
848 aRet = pLink->GetSource();
849 return aRet;
852 void SAL_CALL ScAreaLinkObj::setSourceArea( const OUString& aSourceArea )
854 SolarMutexGuard aGuard;
855 Modify_Impl( nullptr, nullptr, nullptr, &aSourceArea, nullptr );
858 table::CellRangeAddress SAL_CALL ScAreaLinkObj::getDestArea()
860 SolarMutexGuard aGuard;
861 table::CellRangeAddress aRet;
862 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos);
863 if (pLink)
864 ScUnoConversion::FillApiRange( aRet, pLink->GetDestArea() );
865 return aRet;
868 void SAL_CALL ScAreaLinkObj::setDestArea( const table::CellRangeAddress& aDestArea )
870 SolarMutexGuard aGuard;
871 Modify_Impl( nullptr, nullptr, nullptr, nullptr, &aDestArea );
874 ScAreaLinksObj::ScAreaLinksObj(ScDocShell* pDocSh) :
875 pDocShell( pDocSh )
877 pDocShell->GetDocument().AddUnoObject(*this);
880 ScAreaLinksObj::~ScAreaLinksObj()
882 SolarMutexGuard g;
884 if (pDocShell)
885 pDocShell->GetDocument().RemoveUnoObject(*this);
888 void ScAreaLinksObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
890 // we don't care about update of references here
892 if ( rHint.GetId() == SfxHintId::Dying )
894 pDocShell = nullptr; // became invalid
898 // XAreaLinks
900 rtl::Reference<ScAreaLinkObj> ScAreaLinksObj::GetObjectByIndex_Impl(sal_Int32 nIndex)
902 if ( pDocShell && nIndex >= 0 && nIndex < getCount() )
903 return new ScAreaLinkObj( pDocShell, static_cast<size_t>(nIndex) );
905 return nullptr; // not found
908 void SAL_CALL ScAreaLinksObj::insertAtPosition( const table::CellAddress& aDestPos,
909 const OUString& aFileName,
910 const OUString& aSourceArea,
911 const OUString& aFilter,
912 const OUString& aFilterOptions )
914 SolarMutexGuard aGuard;
915 if (pDocShell)
917 OUString aFileStr (aFileName);
918 ScAddress aDestAddr( static_cast<SCCOL>(aDestPos.Column), static_cast<SCROW>(aDestPos.Row), aDestPos.Sheet );
920 aFileStr = ScGlobal::GetAbsDocName( aFileStr, pDocShell ); //! in InsertAreaLink ???
921 pDocShell->GetDocFunc().InsertAreaLink( aFileStr, aFilter, aFilterOptions,
922 aSourceArea, ScRange(aDestAddr),
923 /*nRefreshDelaySeconds*/0, false, true ); // don't move contents
927 void SAL_CALL ScAreaLinksObj::removeByIndex( sal_Int32 nIndex )
929 SolarMutexGuard aGuard;
930 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, static_cast<size_t>(nIndex));
931 if (pLink)
933 //! SetAddUndo or what
935 sfx2::LinkManager* pLinkManager = pDocShell->GetDocument().GetLinkManager();
936 pLinkManager->Remove( pLink );
940 // XEnumerationAccess
942 uno::Reference<container::XEnumeration> SAL_CALL ScAreaLinksObj::createEnumeration()
944 SolarMutexGuard aGuard;
945 return new ScIndexEnumeration(this, "com.sun.star.sheet.CellAreaLinksEnumeration");
948 // XIndexAccess
950 sal_Int32 SAL_CALL ScAreaLinksObj::getCount()
952 SolarMutexGuard aGuard;
953 sal_Int32 nAreaCount = 0;
954 if (pDocShell)
956 sfx2::LinkManager* pLinkManager = pDocShell->GetDocument().GetLinkManager();
957 size_t nTotalCount = pLinkManager->GetLinks().size();
958 for (size_t i=0; i<nTotalCount; i++)
960 ::sfx2::SvBaseLink* pBase = pLinkManager->GetLinks()[i].get();
961 if (dynamic_cast<const ScAreaLink*>( pBase) != nullptr)
962 ++nAreaCount;
965 return nAreaCount;
968 uno::Any SAL_CALL ScAreaLinksObj::getByIndex( sal_Int32 nIndex )
970 SolarMutexGuard aGuard;
971 uno::Reference<sheet::XAreaLink> xLink(GetObjectByIndex_Impl(nIndex));
972 if (!xLink.is())
973 throw lang::IndexOutOfBoundsException();
975 return uno::Any(xLink);
979 uno::Type SAL_CALL ScAreaLinksObj::getElementType()
981 return cppu::UnoType<sheet::XAreaLink>::get();
984 sal_Bool SAL_CALL ScAreaLinksObj::hasElements()
986 SolarMutexGuard aGuard;
987 return ( getCount() != 0 );
990 ScDDELinkObj::ScDDELinkObj(ScDocShell* pDocSh, OUString aA,
991 OUString aT, OUString aI) :
992 pDocShell( pDocSh ),
993 aAppl(std::move( aA )),
994 aTopic(std::move( aT )),
995 aItem(std::move( aI ))
997 pDocShell->GetDocument().AddUnoObject(*this);
1000 ScDDELinkObj::~ScDDELinkObj()
1002 SolarMutexGuard g;
1004 if (pDocShell)
1005 pDocShell->GetDocument().RemoveUnoObject(*this);
1008 void ScDDELinkObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
1010 //! notify if links in document are changed
1011 // UpdateRef is not needed here
1013 if ( auto pRefreshedHint = dynamic_cast<const ScLinkRefreshedHint*>(&rHint) )
1015 if ( pRefreshedHint->GetLinkType() == ScLinkRefType::DDE &&
1016 pRefreshedHint->GetDdeAppl() == aAppl &&
1017 pRefreshedHint->GetDdeTopic() == aTopic &&
1018 pRefreshedHint->GetDdeItem() == aItem ) //! mode is ignored
1019 Refreshed_Impl();
1021 else
1023 if ( rHint.GetId() == SfxHintId::Dying )
1024 pDocShell = nullptr; // pointer is invalid
1028 // XNamed
1030 static OUString lcl_BuildDDEName( std::u16string_view rAppl, std::u16string_view rTopic, std::u16string_view rItem )
1032 // Appl|Topic!Item (like Excel)
1033 OUString aRet = OUString::Concat(rAppl) + "|" + rTopic + "!" + rItem;
1034 return aRet;
1037 OUString SAL_CALL ScDDELinkObj::getName()
1039 SolarMutexGuard aGuard;
1040 return lcl_BuildDDEName( aAppl, aTopic, aItem );
1043 void SAL_CALL ScDDELinkObj::setName( const OUString& /* aName */ )
1045 // name can't be changed (formulas wouldn't find the link)
1046 throw uno::RuntimeException();
1049 // XDDELink
1051 OUString SAL_CALL ScDDELinkObj::getApplication()
1053 SolarMutexGuard aGuard;
1054 //! Test if the link is still in the document?
1056 return aAppl;
1059 OUString SAL_CALL ScDDELinkObj::getTopic()
1061 SolarMutexGuard aGuard;
1062 //! Test if the link is still in the document?
1064 return aTopic;
1067 OUString SAL_CALL ScDDELinkObj::getItem()
1069 SolarMutexGuard aGuard;
1070 //! Test if the link is still in the document?
1072 return aItem;
1075 // XRefreshable
1077 void SAL_CALL ScDDELinkObj::refresh()
1079 SolarMutexGuard aGuard;
1080 if (pDocShell)
1082 sc::DocumentLinkManager& rMgr = pDocShell->GetDocument().GetDocLinkManager();
1083 rMgr.updateDdeLink(aAppl, aTopic, aItem);
1087 void SAL_CALL ScDDELinkObj::addRefreshListener(
1088 const uno::Reference<util::XRefreshListener >& xListener )
1090 SolarMutexGuard aGuard;
1091 aRefreshListeners.push_back( xListener );
1093 // hold one additional ref to keep this object alive as long as there are listeners
1094 if ( aRefreshListeners.size() == 1 )
1095 acquire();
1098 void SAL_CALL ScDDELinkObj::removeRefreshListener(
1099 const uno::Reference<util::XRefreshListener >& xListener )
1101 SolarMutexGuard aGuard;
1102 size_t nCount = aRefreshListeners.size();
1103 for ( size_t n=nCount; n--; )
1105 uno::Reference<util::XRefreshListener>& rObj = aRefreshListeners[n];
1106 if ( rObj == xListener )
1108 aRefreshListeners.erase( aRefreshListeners.begin() + n );
1109 if ( aRefreshListeners.empty() )
1110 release(); // release ref for listeners
1111 break;
1116 // XDDELinkResults
1118 uno::Sequence< uno::Sequence< uno::Any > > ScDDELinkObj::getResults( )
1120 SolarMutexGuard aGuard;
1121 uno::Sequence< uno::Sequence< uno::Any > > aReturn;
1122 bool bSuccess = false;
1124 if ( pDocShell )
1126 ScDocument& rDoc = pDocShell->GetDocument();
1127 size_t nPos = 0;
1128 if ( rDoc.FindDdeLink( aAppl, aTopic, aItem, SC_DDE_IGNOREMODE, nPos ) )
1130 const ScMatrix* pMatrix = rDoc.GetDdeLinkResultMatrix( nPos );
1131 if ( pMatrix )
1133 uno::Any aAny;
1134 if ( ScRangeToSequence::FillMixedArray( aAny, pMatrix, true ) )
1136 aAny >>= aReturn;
1139 bSuccess = true;
1143 if ( !bSuccess )
1145 throw uno::RuntimeException(
1146 "ScDDELinkObj::getResults: failed to get results!" );
1149 return aReturn;
1152 void ScDDELinkObj::setResults( const uno::Sequence< uno::Sequence< uno::Any > >& aResults )
1154 SolarMutexGuard aGuard;
1155 bool bSuccess = false;
1157 if ( pDocShell )
1159 ScDocument& rDoc = pDocShell->GetDocument();
1160 size_t nPos = 0;
1161 if ( rDoc.FindDdeLink( aAppl, aTopic, aItem, SC_DDE_IGNOREMODE, nPos ) )
1163 ScMatrixRef xMatrix = ScSequenceToMatrix::CreateMixedMatrix( Any(aResults) );
1164 bSuccess = rDoc.SetDdeLinkResultMatrix( nPos, xMatrix );
1168 if ( !bSuccess )
1170 throw uno::RuntimeException(
1171 "ScDDELinkObj::setResults: failed to set results!" );
1175 void ScDDELinkObj::Refreshed_Impl()
1177 lang::EventObject aEvent;
1178 aEvent.Source.set(static_cast<cppu::OWeakObject*>(this));
1179 for (uno::Reference<util::XRefreshListener> & xRefreshListener : aRefreshListeners)
1180 xRefreshListener->refreshed( aEvent );
1183 ScDDELinksObj::ScDDELinksObj(ScDocShell* pDocSh) :
1184 pDocShell( pDocSh )
1186 pDocShell->GetDocument().AddUnoObject(*this);
1189 ScDDELinksObj::~ScDDELinksObj()
1191 SolarMutexGuard g;
1193 if (pDocShell)
1194 pDocShell->GetDocument().RemoveUnoObject(*this);
1197 void ScDDELinksObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
1199 // we don't care about update of references here
1201 if ( rHint.GetId() == SfxHintId::Dying )
1203 pDocShell = nullptr; // became invalid
1207 // XDDELinks
1209 rtl::Reference<ScDDELinkObj> ScDDELinksObj::GetObjectByIndex_Impl(sal_Int32 nIndex)
1211 if (pDocShell)
1213 OUString aAppl, aTopic, aItem;
1214 if ( pDocShell->GetDocument().GetDdeLinkData( static_cast<size_t>(nIndex), aAppl, aTopic, aItem ) )
1215 return new ScDDELinkObj( pDocShell, aAppl, aTopic, aItem );
1217 return nullptr;
1220 rtl::Reference<ScDDELinkObj> ScDDELinksObj::GetObjectByName_Impl(std::u16string_view aName)
1222 if (pDocShell)
1224 OUString aAppl, aTopic, aItem;
1226 ScDocument& rDoc = pDocShell->GetDocument();
1227 size_t nCount = rDoc.GetDocLinkManager().getDdeLinkCount();
1228 for (size_t i=0; i<nCount; i++)
1230 rDoc.GetDdeLinkData( i, aAppl, aTopic, aItem );
1231 if ( lcl_BuildDDEName(aAppl, aTopic, aItem) == aName )
1232 return new ScDDELinkObj( pDocShell, aAppl, aTopic, aItem );
1235 return nullptr;
1238 // XEnumerationAccess
1240 uno::Reference<container::XEnumeration> SAL_CALL ScDDELinksObj::createEnumeration()
1242 SolarMutexGuard aGuard;
1243 return new ScIndexEnumeration(this, "com.sun.star.sheet.DDELinksEnumeration");
1246 // XIndexAccess
1248 sal_Int32 SAL_CALL ScDDELinksObj::getCount()
1250 SolarMutexGuard aGuard;
1251 sal_Int32 nAreaCount = 0;
1252 if (pDocShell)
1253 nAreaCount = pDocShell->GetDocument().GetDocLinkManager().getDdeLinkCount();
1254 return nAreaCount;
1257 uno::Any SAL_CALL ScDDELinksObj::getByIndex( sal_Int32 nIndex )
1259 SolarMutexGuard aGuard;
1260 uno::Reference<sheet::XDDELink> xLink(GetObjectByIndex_Impl(nIndex));
1261 if (!xLink.is())
1262 throw lang::IndexOutOfBoundsException();
1264 return uno::Any(xLink);
1267 uno::Type SAL_CALL ScDDELinksObj::getElementType()
1269 return cppu::UnoType<sheet::XDDELink>::get();
1272 sal_Bool SAL_CALL ScDDELinksObj::hasElements()
1274 SolarMutexGuard aGuard;
1275 return ( getCount() != 0 );
1278 uno::Any SAL_CALL ScDDELinksObj::getByName( const OUString& aName )
1280 SolarMutexGuard aGuard;
1281 uno::Reference<sheet::XDDELink> xLink(GetObjectByName_Impl(aName));
1282 if (!xLink.is())
1283 throw container::NoSuchElementException();
1285 return uno::Any(xLink);
1288 uno::Sequence<OUString> SAL_CALL ScDDELinksObj::getElementNames()
1290 SolarMutexGuard aGuard;
1291 if (pDocShell)
1293 OUString aAppl, aTopic, aItem;
1295 ScDocument& rDoc = pDocShell->GetDocument();
1296 size_t nCount = pDocShell->GetDocument().GetDocLinkManager().getDdeLinkCount();
1297 uno::Sequence<OUString> aSeq(nCount);
1298 OUString* pAry = aSeq.getArray();
1300 for (size_t i=0; i<nCount; i++)
1302 rDoc.GetDdeLinkData( i, aAppl, aTopic, aItem );
1303 pAry[i] = lcl_BuildDDEName(aAppl, aTopic, aItem);
1305 return aSeq;
1307 return uno::Sequence<OUString>();
1310 sal_Bool SAL_CALL ScDDELinksObj::hasByName( const OUString& aName )
1312 SolarMutexGuard aGuard;
1313 if (pDocShell)
1315 OUString aAppl, aTopic, aItem;
1317 ScDocument& rDoc = pDocShell->GetDocument();
1318 size_t nCount = pDocShell->GetDocument().GetDocLinkManager().getDdeLinkCount();
1319 for (size_t i=0; i<nCount; i++)
1321 rDoc.GetDdeLinkData( i, aAppl, aTopic, aItem );
1322 if ( lcl_BuildDDEName(aAppl, aTopic, aItem) == aName )
1323 return true;
1326 return false;
1329 // XDDELinks
1331 uno::Reference< sheet::XDDELink > ScDDELinksObj::addDDELink(
1332 const OUString& aApplication, const OUString& aTopic,
1333 const OUString& aItem, css::sheet::DDELinkMode nMode )
1335 SolarMutexGuard aGuard;
1336 uno::Reference< sheet::XDDELink > xLink;
1338 if ( pDocShell )
1340 ScDocument& rDoc = pDocShell->GetDocument();
1341 sal_uInt8 nMod = SC_DDE_DEFAULT;
1342 switch ( nMode )
1344 case sheet::DDELinkMode_DEFAULT:
1346 nMod = SC_DDE_DEFAULT;
1348 break;
1349 case sheet::DDELinkMode_ENGLISH:
1351 nMod = SC_DDE_ENGLISH;
1353 break;
1354 case sheet::DDELinkMode_TEXT:
1356 nMod = SC_DDE_TEXT;
1358 break;
1359 default:
1362 break;
1365 if ( rDoc.CreateDdeLink( aApplication, aTopic, aItem, nMod, ScMatrixRef() ) )
1367 const OUString aName( lcl_BuildDDEName( aApplication, aTopic, aItem ) );
1368 xLink.set( GetObjectByName_Impl( aName ) );
1372 if ( !xLink.is() )
1374 throw uno::RuntimeException(
1375 "ScDDELinksObj::addDDELink: cannot add DDE link!" );
1378 return xLink;
1381 ScExternalSheetCacheObj::ScExternalSheetCacheObj(ScDocShell* pDocShell, ScExternalRefCache::TableTypeRef pTable, size_t nIndex) :
1382 mpDocShell(pDocShell),
1383 mpTable(std::move(pTable)),
1384 mnIndex(nIndex)
1388 ScExternalSheetCacheObj::~ScExternalSheetCacheObj()
1392 void SAL_CALL ScExternalSheetCacheObj::setCellValue(sal_Int32 nCol, sal_Int32 nRow, const Any& rValue)
1394 SolarMutexGuard aGuard;
1395 if (nRow < 0 || nCol < 0)
1396 throw IllegalArgumentException();
1398 ScExternalRefCache::TokenRef pToken;
1399 double fVal = 0.0;
1400 OUString aVal;
1401 if (rValue >>= fVal)
1402 pToken.reset(new FormulaDoubleToken(fVal));
1403 else if (rValue >>= aVal)
1405 svl::SharedStringPool& rPool = mpDocShell->GetDocument().GetSharedStringPool();
1406 svl::SharedString aSS = rPool.intern(aVal);
1407 pToken.reset(new FormulaStringToken(std::move(aSS)));
1409 else
1410 // unidentified value type.
1411 return;
1413 mpTable->setCell(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), pToken);
1416 Any SAL_CALL ScExternalSheetCacheObj::getCellValue(sal_Int32 nCol, sal_Int32 nRow)
1418 SolarMutexGuard aGuard;
1419 if (nRow < 0 || nCol < 0)
1420 throw IllegalArgumentException();
1422 FormulaToken* pToken = mpTable->getCell(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow)).get();
1423 if (!pToken)
1424 throw IllegalArgumentException();
1426 Any aValue;
1427 switch (pToken->GetType())
1429 case svDouble:
1431 double fVal = pToken->GetDouble();
1432 aValue <<= fVal;
1434 break;
1435 case svString:
1437 OUString aVal = pToken->GetString().getString();
1438 aValue <<= aVal;
1440 break;
1441 default:
1442 throw IllegalArgumentException();
1444 return aValue;
1447 Sequence< sal_Int32 > SAL_CALL ScExternalSheetCacheObj::getAllRows()
1449 SolarMutexGuard aGuard;
1450 vector<SCROW> aRows;
1451 mpTable->getAllRows(aRows);
1452 size_t nSize = aRows.size();
1453 Sequence<sal_Int32> aRowsSeq(nSize);
1454 auto aRowsSeqRange = asNonConstRange(aRowsSeq);
1455 for (size_t i = 0; i < nSize; ++i)
1456 aRowsSeqRange[i] = aRows[i];
1458 return aRowsSeq;
1461 Sequence< sal_Int32 > SAL_CALL ScExternalSheetCacheObj::getAllColumns(sal_Int32 nRow)
1463 SolarMutexGuard aGuard;
1464 if (nRow < 0)
1465 throw IllegalArgumentException();
1467 vector<SCCOL> aCols;
1468 mpTable->getAllCols(static_cast<SCROW>(nRow), aCols);
1469 size_t nSize = aCols.size();
1470 Sequence<sal_Int32> aColsSeq(nSize);
1471 auto aColsSeqRange = asNonConstRange(aColsSeq);
1472 for (size_t i = 0; i < nSize; ++i)
1473 aColsSeqRange[i] = aCols[i];
1475 return aColsSeq;
1478 sal_Int32 SAL_CALL ScExternalSheetCacheObj::getTokenIndex()
1480 return static_cast< sal_Int32 >( mnIndex );
1483 ScExternalDocLinkObj::ScExternalDocLinkObj(ScDocShell* pDocShell, ScExternalRefManager* pRefMgr, sal_uInt16 nFileId) :
1484 mpDocShell(pDocShell), mpRefMgr(pRefMgr), mnFileId(nFileId)
1488 ScExternalDocLinkObj::~ScExternalDocLinkObj()
1492 uno::Reference< sheet::XExternalSheetCache > SAL_CALL ScExternalDocLinkObj::addSheetCache(
1493 const OUString& aSheetName, sal_Bool bDynamicCache )
1495 SolarMutexGuard aGuard;
1496 size_t nIndex = 0;
1497 ScExternalRefCache::TableTypeRef pTable = mpRefMgr->getCacheTable(mnFileId, aSheetName, true, &nIndex);
1498 if (!bDynamicCache)
1499 // Set the whole table cached to prevent access to the source document.
1500 pTable->setWholeTableCached();
1502 uno::Reference< sheet::XExternalSheetCache > aSheetCache(new ScExternalSheetCacheObj(mpDocShell, pTable, nIndex));
1503 return aSheetCache;
1506 Any SAL_CALL ScExternalDocLinkObj::getByName(const OUString &aName)
1508 SolarMutexGuard aGuard;
1509 size_t nIndex = 0;
1510 ScExternalRefCache::TableTypeRef pTable = mpRefMgr->getCacheTable(mnFileId, aName, false, &nIndex);
1511 if (!pTable)
1512 throw container::NoSuchElementException();
1514 uno::Reference< sheet::XExternalSheetCache > aSheetCache(new ScExternalSheetCacheObj(mpDocShell, pTable, nIndex));
1516 return Any(aSheetCache);
1519 Sequence< OUString > SAL_CALL ScExternalDocLinkObj::getElementNames()
1521 SolarMutexGuard aGuard;
1522 vector<OUString> aTabNames;
1523 mpRefMgr->getAllCachedTableNames(mnFileId, aTabNames);
1525 // #i116940# be consistent with getByName: include only table names which have a cache already
1526 vector<OUString> aValidNames;
1527 std::copy_if(aTabNames.begin(), aTabNames.end(), std::back_inserter(aValidNames),
1528 [&](const OUString& rTabName) { return mpRefMgr->getCacheTable(mnFileId, rTabName, false); });
1530 Sequence<OUString> aSeq(comphelper::containerToSequence(aValidNames));
1531 return aSeq;
1534 sal_Bool SAL_CALL ScExternalDocLinkObj::hasByName(const OUString &aName)
1536 SolarMutexGuard aGuard;
1538 // #i116940# be consistent with getByName: allow only table names which have a cache already
1539 ScExternalRefCache::TableTypeRef pTable = mpRefMgr->getCacheTable(mnFileId, aName, false);
1540 return bool(pTable);
1543 sal_Int32 SAL_CALL ScExternalDocLinkObj::getCount()
1545 SolarMutexGuard aGuard;
1547 // #i116940# be consistent with getByName: count only table names which have a cache already
1548 return getElementNames().getLength();
1551 Any SAL_CALL ScExternalDocLinkObj::getByIndex(sal_Int32 nApiIndex)
1553 SolarMutexGuard aGuard;
1555 // #i116940# Can't use nApiIndex as index for the ref manager, because the API counts only
1556 // the entries which have a cache already. Quick solution: Use getElementNames.
1557 Sequence< OUString > aNames( getElementNames() );
1558 if (nApiIndex < 0 || nApiIndex >= aNames.getLength())
1559 throw lang::IndexOutOfBoundsException();
1561 size_t nIndex = 0;
1562 ScExternalRefCache::TableTypeRef pTable = mpRefMgr->getCacheTable(mnFileId, aNames[nApiIndex], false, &nIndex);
1563 if (!pTable)
1564 throw lang::IndexOutOfBoundsException();
1566 uno::Reference< sheet::XExternalSheetCache > aSheetCache(new ScExternalSheetCacheObj(mpDocShell, pTable, nIndex));
1568 return Any(aSheetCache);
1571 uno::Reference< container::XEnumeration > SAL_CALL ScExternalDocLinkObj::createEnumeration()
1573 SolarMutexGuard aGuard;
1574 uno::Reference< container::XEnumeration > aRef(
1575 new ScIndexEnumeration(this, "com.sun.star.sheet.ExternalDocLink"));
1576 return aRef;
1579 uno::Type SAL_CALL ScExternalDocLinkObj::getElementType()
1581 return cppu::UnoType<sheet::XExternalDocLink>::get();
1584 sal_Bool SAL_CALL ScExternalDocLinkObj::hasElements()
1586 SolarMutexGuard aGuard;
1588 // #i116940# be consistent with getByName: count only table names which have a cache already
1589 return getElementNames().hasElements();
1592 sal_Int32 SAL_CALL ScExternalDocLinkObj::getTokenIndex()
1594 return static_cast<sal_Int32>(mnFileId);
1597 ScExternalDocLinksObj::ScExternalDocLinksObj(ScDocShell* pDocShell) :
1598 mpDocShell(pDocShell),
1599 mpRefMgr(pDocShell->GetDocument().GetExternalRefManager())
1603 ScExternalDocLinksObj::~ScExternalDocLinksObj()
1607 uno::Reference< sheet::XExternalDocLink > SAL_CALL ScExternalDocLinksObj::addDocLink(
1608 const OUString& aDocName )
1610 SolarMutexGuard aGuard;
1611 OUString aDocUrl( ScGlobal::GetAbsDocName( aDocName, mpDocShell));
1612 sal_uInt16 nFileId = mpRefMgr->getExternalFileId(aDocUrl);
1613 uno::Reference< sheet::XExternalDocLink > aDocLink(new ScExternalDocLinkObj(mpDocShell, mpRefMgr, nFileId));
1614 return aDocLink;
1617 Any SAL_CALL ScExternalDocLinksObj::getByName(const OUString &aName)
1619 SolarMutexGuard aGuard;
1620 OUString aDocUrl( ScGlobal::GetAbsDocName( aName, mpDocShell));
1621 if (!mpRefMgr->hasExternalFile(aDocUrl))
1622 throw container::NoSuchElementException();
1624 sal_uInt16 nFileId = mpRefMgr->getExternalFileId(aDocUrl);
1625 uno::Reference< sheet::XExternalDocLink > aDocLink(new ScExternalDocLinkObj(mpDocShell, mpRefMgr, nFileId));
1627 return Any(aDocLink);
1630 Sequence< OUString > SAL_CALL ScExternalDocLinksObj::getElementNames()
1632 SolarMutexGuard aGuard;
1633 sal_uInt16 n = mpRefMgr->getExternalFileCount();
1634 Sequence<OUString> aSeq(n);
1635 auto aSeqRange = asNonConstRange(aSeq);
1636 for (sal_uInt16 i = 0; i < n; ++i)
1638 const OUString* pName = mpRefMgr->getExternalFileName(i);
1639 aSeqRange[i] = pName ? *pName : OUString();
1642 return aSeq;
1645 sal_Bool SAL_CALL ScExternalDocLinksObj::hasByName(const OUString &aName)
1647 SolarMutexGuard aGuard;
1648 return mpRefMgr->hasExternalFile(aName);
1651 sal_Int32 SAL_CALL ScExternalDocLinksObj::getCount()
1653 SolarMutexGuard aGuard;
1654 return mpRefMgr->getExternalFileCount();
1657 Any SAL_CALL ScExternalDocLinksObj::getByIndex(sal_Int32 nIndex)
1659 SolarMutexGuard aGuard;
1660 if (nIndex > ::std::numeric_limits<sal_uInt16>::max() || nIndex < ::std::numeric_limits<sal_uInt16>::min())
1661 throw lang::IndexOutOfBoundsException();
1663 sal_uInt16 nFileId = static_cast<sal_uInt16>(nIndex);
1665 if (!mpRefMgr->hasExternalFile(nFileId))
1666 throw lang::IndexOutOfBoundsException();
1668 uno::Reference< sheet::XExternalDocLink > aDocLink(new ScExternalDocLinkObj(mpDocShell, mpRefMgr, nFileId));
1669 return Any(aDocLink);
1672 uno::Reference< container::XEnumeration > SAL_CALL ScExternalDocLinksObj::createEnumeration()
1674 SolarMutexGuard aGuard;
1675 uno::Reference< container::XEnumeration > aRef(
1676 new ScIndexEnumeration(this, "com.sun.star.sheet.ExternalDocLinks"));
1677 return aRef;
1680 uno::Type SAL_CALL ScExternalDocLinksObj::getElementType()
1682 return cppu::UnoType<sheet::XExternalDocLinks>::get();
1685 sal_Bool SAL_CALL ScExternalDocLinksObj::hasElements()
1687 SolarMutexGuard aGuard;
1688 return mpRefMgr->getExternalFileCount() > 0;
1691 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */