xref: /aoo41x/main/sc/source/ui/docshell/tablink.cxx (revision cdf0e10c)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_sc.hxx"
30*cdf0e10cSrcweir #ifdef _MSC_VER
31*cdf0e10cSrcweir #pragma optimize("",off)
32*cdf0e10cSrcweir #endif
33*cdf0e10cSrcweir 
34*cdf0e10cSrcweir //------------------------------------------------------------------
35*cdf0e10cSrcweir 
36*cdf0e10cSrcweir 
37*cdf0e10cSrcweir 
38*cdf0e10cSrcweir // INCLUDE ---------------------------------------------------------
39*cdf0e10cSrcweir 
40*cdf0e10cSrcweir #include <sfx2/sfxsids.hrc>
41*cdf0e10cSrcweir #include <sfx2/app.hxx>
42*cdf0e10cSrcweir #include <svl/itemset.hxx>
43*cdf0e10cSrcweir #include <svl/stritem.hxx>
44*cdf0e10cSrcweir #include <sfx2/docfile.hxx>
45*cdf0e10cSrcweir #include <sfx2/docfilt.hxx>
46*cdf0e10cSrcweir #include <sfx2/fcontnr.hxx>
47*cdf0e10cSrcweir #include <sfx2/linkmgr.hxx>
48*cdf0e10cSrcweir #include <tools/urlobj.hxx>
49*cdf0e10cSrcweir #include <unotools/transliterationwrapper.hxx>
50*cdf0e10cSrcweir 
51*cdf0e10cSrcweir #include "tablink.hxx"
52*cdf0e10cSrcweir 
53*cdf0e10cSrcweir #include "scextopt.hxx"
54*cdf0e10cSrcweir #include "table.hxx"
55*cdf0e10cSrcweir #include "document.hxx"
56*cdf0e10cSrcweir #include "docsh.hxx"
57*cdf0e10cSrcweir #include "globstr.hrc"
58*cdf0e10cSrcweir #include "undoblk.hxx"
59*cdf0e10cSrcweir #include "undotab.hxx"
60*cdf0e10cSrcweir #include "global.hxx"
61*cdf0e10cSrcweir #include "hints.hxx"
62*cdf0e10cSrcweir #include "cell.hxx"
63*cdf0e10cSrcweir #include "dociter.hxx"
64*cdf0e10cSrcweir #include "formula/opcode.hxx"
65*cdf0e10cSrcweir 
66*cdf0e10cSrcweir struct TableLink_Impl
67*cdf0e10cSrcweir {
68*cdf0e10cSrcweir     ScDocShell* m_pDocSh;
69*cdf0e10cSrcweir     Window*     m_pOldParent;
70*cdf0e10cSrcweir     Link        m_aEndEditLink;
71*cdf0e10cSrcweir 
72*cdf0e10cSrcweir     TableLink_Impl() : m_pDocSh( NULL ), m_pOldParent( NULL ) {}
73*cdf0e10cSrcweir };
74*cdf0e10cSrcweir 
75*cdf0e10cSrcweir TYPEINIT1(ScTableLink, ::sfx2::SvBaseLink);
76*cdf0e10cSrcweir 
77*cdf0e10cSrcweir //------------------------------------------------------------------------
78*cdf0e10cSrcweir 
79*cdf0e10cSrcweir ScTableLink::ScTableLink(ScDocShell* pDocSh, const String& rFile,
80*cdf0e10cSrcweir 							const String& rFilter, const String& rOpt,
81*cdf0e10cSrcweir 							sal_uLong nRefresh ):
82*cdf0e10cSrcweir     ::sfx2::SvBaseLink(sfx2::LINKUPDATE_ONCALL,FORMAT_FILE),
83*cdf0e10cSrcweir 	ScRefreshTimer( nRefresh ),
84*cdf0e10cSrcweir     pImpl( new TableLink_Impl ),
85*cdf0e10cSrcweir 	aFileName(rFile),
86*cdf0e10cSrcweir 	aFilterName(rFilter),
87*cdf0e10cSrcweir 	aOptions(rOpt),
88*cdf0e10cSrcweir 	bInCreate( sal_False ),
89*cdf0e10cSrcweir 	bInEdit( sal_False ),
90*cdf0e10cSrcweir 	bAddUndo( sal_True ),
91*cdf0e10cSrcweir 	bDoPaint( sal_True )
92*cdf0e10cSrcweir {
93*cdf0e10cSrcweir     pImpl->m_pDocSh = pDocSh;
94*cdf0e10cSrcweir }
95*cdf0e10cSrcweir 
96*cdf0e10cSrcweir ScTableLink::ScTableLink(SfxObjectShell* pShell, const String& rFile,
97*cdf0e10cSrcweir 							const String& rFilter, const String& rOpt,
98*cdf0e10cSrcweir 							sal_uLong nRefresh ):
99*cdf0e10cSrcweir     ::sfx2::SvBaseLink(sfx2::LINKUPDATE_ONCALL,FORMAT_FILE),
100*cdf0e10cSrcweir 	ScRefreshTimer( nRefresh ),
101*cdf0e10cSrcweir     pImpl( new TableLink_Impl ),
102*cdf0e10cSrcweir 	aFileName(rFile),
103*cdf0e10cSrcweir 	aFilterName(rFilter),
104*cdf0e10cSrcweir 	aOptions(rOpt),
105*cdf0e10cSrcweir 	bInCreate( sal_False ),
106*cdf0e10cSrcweir 	bInEdit( sal_False ),
107*cdf0e10cSrcweir 	bAddUndo( sal_True ),
108*cdf0e10cSrcweir 	bDoPaint( sal_True )
109*cdf0e10cSrcweir {
110*cdf0e10cSrcweir     pImpl->m_pDocSh = static_cast< ScDocShell* >( pShell );
111*cdf0e10cSrcweir 	SetRefreshHandler( LINK( this, ScTableLink, RefreshHdl ) );
112*cdf0e10cSrcweir     SetRefreshControl( pImpl->m_pDocSh->GetDocument()->GetRefreshTimerControlAddress() );
113*cdf0e10cSrcweir }
114*cdf0e10cSrcweir 
115*cdf0e10cSrcweir __EXPORT ScTableLink::~ScTableLink()
116*cdf0e10cSrcweir {
117*cdf0e10cSrcweir 	// Verbindung aufheben
118*cdf0e10cSrcweir 
119*cdf0e10cSrcweir 	StopRefreshTimer();
120*cdf0e10cSrcweir 	String aEmpty;
121*cdf0e10cSrcweir     ScDocument* pDoc = pImpl->m_pDocSh->GetDocument();
122*cdf0e10cSrcweir 	SCTAB nCount = pDoc->GetTableCount();
123*cdf0e10cSrcweir 	for (SCTAB nTab=0; nTab<nCount; nTab++)
124*cdf0e10cSrcweir 		if (pDoc->IsLinked(nTab) && pDoc->GetLinkDoc(nTab)==aFileName)
125*cdf0e10cSrcweir 			pDoc->SetLink( nTab, SC_LINK_NONE, aEmpty, aEmpty, aEmpty, aEmpty, 0 );
126*cdf0e10cSrcweir     delete pImpl;
127*cdf0e10cSrcweir }
128*cdf0e10cSrcweir 
129*cdf0e10cSrcweir void __EXPORT ScTableLink::Edit( Window* pParent, const Link& rEndEditHdl )
130*cdf0e10cSrcweir {
131*cdf0e10cSrcweir 	//	DefModalDialogParent setzen, weil evtl. aus der DocShell beim ConvertFrom
132*cdf0e10cSrcweir 	//	ein Optionen-Dialog kommt...
133*cdf0e10cSrcweir 
134*cdf0e10cSrcweir     pImpl->m_aEndEditLink = rEndEditHdl;
135*cdf0e10cSrcweir     pImpl->m_pOldParent = Application::GetDefDialogParent();
136*cdf0e10cSrcweir 	if (pParent)
137*cdf0e10cSrcweir 		Application::SetDefDialogParent(pParent);
138*cdf0e10cSrcweir 
139*cdf0e10cSrcweir 	bInEdit = sal_True;
140*cdf0e10cSrcweir     SvBaseLink::Edit( pParent, LINK( this, ScTableLink, TableEndEditHdl ) );
141*cdf0e10cSrcweir }
142*cdf0e10cSrcweir 
143*cdf0e10cSrcweir void __EXPORT ScTableLink::DataChanged( const String&,
144*cdf0e10cSrcweir 										const ::com::sun::star::uno::Any& )
145*cdf0e10cSrcweir {
146*cdf0e10cSrcweir     sfx2::LinkManager* pLinkManager=pImpl->m_pDocSh->GetDocument()->GetLinkManager();
147*cdf0e10cSrcweir 	if (pLinkManager!=NULL)
148*cdf0e10cSrcweir 	{
149*cdf0e10cSrcweir 		String aFile;
150*cdf0e10cSrcweir 		String aFilter;
151*cdf0e10cSrcweir 		pLinkManager->GetDisplayNames( this,0,&aFile,NULL,&aFilter);
152*cdf0e10cSrcweir 
153*cdf0e10cSrcweir 		//	the file dialog returns the filter name with the application prefix
154*cdf0e10cSrcweir 		//	-> remove prefix
155*cdf0e10cSrcweir 		ScDocumentLoader::RemoveAppPrefix( aFilter );
156*cdf0e10cSrcweir 
157*cdf0e10cSrcweir 		if (!bInCreate)
158*cdf0e10cSrcweir 			Refresh( aFile, aFilter, NULL, GetRefreshDelay() );	// don't load twice
159*cdf0e10cSrcweir 	}
160*cdf0e10cSrcweir }
161*cdf0e10cSrcweir 
162*cdf0e10cSrcweir void __EXPORT ScTableLink::Closed()
163*cdf0e10cSrcweir {
164*cdf0e10cSrcweir 	// Verknuepfung loeschen: Undo
165*cdf0e10cSrcweir     ScDocument* pDoc = pImpl->m_pDocSh->GetDocument();
166*cdf0e10cSrcweir 	sal_Bool bUndo (pDoc->IsUndoEnabled());
167*cdf0e10cSrcweir 
168*cdf0e10cSrcweir 	if (bAddUndo && bUndo)
169*cdf0e10cSrcweir 	{
170*cdf0e10cSrcweir         pImpl->m_pDocSh->GetUndoManager()->AddUndoAction(
171*cdf0e10cSrcweir                 new ScUndoRemoveLink( pImpl->m_pDocSh, aFileName ) );
172*cdf0e10cSrcweir 
173*cdf0e10cSrcweir 		bAddUndo = sal_False;	// nur einmal
174*cdf0e10cSrcweir 	}
175*cdf0e10cSrcweir 
176*cdf0e10cSrcweir 	// Verbindung wird im dtor aufgehoben
177*cdf0e10cSrcweir 
178*cdf0e10cSrcweir 	SvBaseLink::Closed();
179*cdf0e10cSrcweir }
180*cdf0e10cSrcweir 
181*cdf0e10cSrcweir sal_Bool ScTableLink::IsUsed() const
182*cdf0e10cSrcweir {
183*cdf0e10cSrcweir     return pImpl->m_pDocSh->GetDocument()->HasLink( aFileName, aFilterName, aOptions );
184*cdf0e10cSrcweir }
185*cdf0e10cSrcweir 
186*cdf0e10cSrcweir sal_Bool ScTableLink::Refresh(const String& rNewFile, const String& rNewFilter,
187*cdf0e10cSrcweir 							const String* pNewOptions, sal_uLong nNewRefresh )
188*cdf0e10cSrcweir {
189*cdf0e10cSrcweir 	//	Dokument laden
190*cdf0e10cSrcweir 
191*cdf0e10cSrcweir 	if (!rNewFile.Len() || !rNewFilter.Len())
192*cdf0e10cSrcweir 		return sal_False;
193*cdf0e10cSrcweir 
194*cdf0e10cSrcweir     String aNewUrl( ScGlobal::GetAbsDocName( rNewFile, pImpl->m_pDocSh ) );
195*cdf0e10cSrcweir 	sal_Bool bNewUrlName = (aNewUrl != aFileName);
196*cdf0e10cSrcweir 
197*cdf0e10cSrcweir     const SfxFilter* pFilter = pImpl->m_pDocSh->GetFactory().GetFilterContainer()->GetFilter4FilterName(rNewFilter);
198*cdf0e10cSrcweir 	if (!pFilter)
199*cdf0e10cSrcweir 		return sal_False;
200*cdf0e10cSrcweir 
201*cdf0e10cSrcweir     ScDocument* pDoc = pImpl->m_pDocSh->GetDocument();
202*cdf0e10cSrcweir 	pDoc->SetInLinkUpdate( sal_True );
203*cdf0e10cSrcweir 
204*cdf0e10cSrcweir 	sal_Bool bUndo(pDoc->IsUndoEnabled());
205*cdf0e10cSrcweir 
206*cdf0e10cSrcweir 	//	wenn neuer Filter ausgewaehlt wurde, Optionen vergessen
207*cdf0e10cSrcweir 	if ( rNewFilter != aFilterName )
208*cdf0e10cSrcweir 		aOptions.Erase();
209*cdf0e10cSrcweir 	if ( pNewOptions )					// Optionen hart angegeben?
210*cdf0e10cSrcweir 		aOptions = *pNewOptions;
211*cdf0e10cSrcweir 
212*cdf0e10cSrcweir 	//	ItemSet immer anlegen, damit die DocShell die Optionen setzen kann
213*cdf0e10cSrcweir 	SfxItemSet* pSet = new SfxAllItemSet( SFX_APP()->GetPool() );
214*cdf0e10cSrcweir 	if ( aOptions.Len() )
215*cdf0e10cSrcweir 		pSet->Put( SfxStringItem( SID_FILE_FILTEROPTIONS, aOptions ) );
216*cdf0e10cSrcweir 
217*cdf0e10cSrcweir 	SfxMedium* pMed = new SfxMedium(aNewUrl, STREAM_STD_READ, sal_False, pFilter, pSet);
218*cdf0e10cSrcweir 
219*cdf0e10cSrcweir 	if ( bInEdit )								// only if using the edit dialog,
220*cdf0e10cSrcweir 		pMed->UseInteractionHandler( sal_True );	// enable the filter options dialog
221*cdf0e10cSrcweir 
222*cdf0e10cSrcweir     // aRef->DoClose() will be called explicitly, but it is still more safe to use SfxObjectShellLock here
223*cdf0e10cSrcweir 	ScDocShell* pSrcShell = new ScDocShell(SFX_CREATE_MODE_INTERNAL);
224*cdf0e10cSrcweir     SfxObjectShellLock aRef = pSrcShell;
225*cdf0e10cSrcweir 	pSrcShell->DoLoad(pMed);
226*cdf0e10cSrcweir 
227*cdf0e10cSrcweir 	// Optionen koennten gesetzt worden sein
228*cdf0e10cSrcweir 	String aNewOpt = ScDocumentLoader::GetOptions(*pMed);
229*cdf0e10cSrcweir 	if (!aNewOpt.Len())
230*cdf0e10cSrcweir 		aNewOpt = aOptions;
231*cdf0e10cSrcweir 
232*cdf0e10cSrcweir 	//	Undo...
233*cdf0e10cSrcweir 
234*cdf0e10cSrcweir 	ScDocument* pUndoDoc = NULL;
235*cdf0e10cSrcweir 	sal_Bool bFirst = sal_True;
236*cdf0e10cSrcweir 	if (bAddUndo && bUndo)
237*cdf0e10cSrcweir 		pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
238*cdf0e10cSrcweir 
239*cdf0e10cSrcweir 	//	Tabellen kopieren
240*cdf0e10cSrcweir 
241*cdf0e10cSrcweir     ScDocShellModificator aModificator( *pImpl->m_pDocSh );
242*cdf0e10cSrcweir 
243*cdf0e10cSrcweir 	sal_Bool bNotFound = sal_False;
244*cdf0e10cSrcweir 	ScDocument* pSrcDoc = pSrcShell->GetDocument();
245*cdf0e10cSrcweir 
246*cdf0e10cSrcweir 	//	#74835# from text filters that don't set the table name,
247*cdf0e10cSrcweir 	//	use the one table regardless of link table name
248*cdf0e10cSrcweir 	sal_Bool bAutoTab = (pSrcDoc->GetTableCount() == 1) &&
249*cdf0e10cSrcweir 					ScDocShell::HasAutomaticTableName( rNewFilter );
250*cdf0e10cSrcweir 
251*cdf0e10cSrcweir 	SCTAB nCount = pDoc->GetTableCount();
252*cdf0e10cSrcweir 	for (SCTAB nTab=0; nTab<nCount; nTab++)
253*cdf0e10cSrcweir 	{
254*cdf0e10cSrcweir 		sal_uInt8 nMode = pDoc->GetLinkMode(nTab);
255*cdf0e10cSrcweir 		if (nMode && pDoc->GetLinkDoc(nTab)==aFileName)
256*cdf0e10cSrcweir 		{
257*cdf0e10cSrcweir 			String aTabName = pDoc->GetLinkTab(nTab);
258*cdf0e10cSrcweir 
259*cdf0e10cSrcweir 			//	Undo
260*cdf0e10cSrcweir 
261*cdf0e10cSrcweir 			if (bAddUndo && bUndo)
262*cdf0e10cSrcweir 			{
263*cdf0e10cSrcweir 				if (bFirst)
264*cdf0e10cSrcweir 					pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_True, sal_True );
265*cdf0e10cSrcweir 				else
266*cdf0e10cSrcweir 					pUndoDoc->AddUndoTab( nTab, nTab, sal_True, sal_True );
267*cdf0e10cSrcweir 				bFirst = sal_False;
268*cdf0e10cSrcweir 				ScRange aRange(0,0,nTab,MAXCOL,MAXROW,nTab);
269*cdf0e10cSrcweir 				pDoc->CopyToDocument(aRange, IDF_ALL, sal_False, pUndoDoc);
270*cdf0e10cSrcweir 				pUndoDoc->TransferDrawPage( pDoc, nTab, nTab );
271*cdf0e10cSrcweir 				pUndoDoc->SetLink( nTab, nMode, aFileName, aFilterName,
272*cdf0e10cSrcweir 					aOptions, aTabName, GetRefreshDelay() );
273*cdf0e10cSrcweir 			}
274*cdf0e10cSrcweir 
275*cdf0e10cSrcweir 			//	Tabellenname einer ExtDocRef anpassen
276*cdf0e10cSrcweir 
277*cdf0e10cSrcweir 			if ( bNewUrlName && nMode == SC_LINK_VALUE )
278*cdf0e10cSrcweir 			{
279*cdf0e10cSrcweir 				String aName;
280*cdf0e10cSrcweir 				pDoc->GetName( nTab, aName );
281*cdf0e10cSrcweir                 if ( ScGlobal::GetpTransliteration()->isEqual(
282*cdf0e10cSrcweir                         ScGlobal::GetDocTabName( aFileName, aTabName ), aName ) )
283*cdf0e10cSrcweir 				{
284*cdf0e10cSrcweir 					pDoc->RenameTab( nTab,
285*cdf0e10cSrcweir 						ScGlobal::GetDocTabName( aNewUrl, aTabName ),
286*cdf0e10cSrcweir 						sal_False, sal_True );	// kein RefUpdate, kein ValidTabName
287*cdf0e10cSrcweir 				}
288*cdf0e10cSrcweir 			}
289*cdf0e10cSrcweir 
290*cdf0e10cSrcweir 			//	kopieren
291*cdf0e10cSrcweir 
292*cdf0e10cSrcweir 			SCTAB nSrcTab = 0;
293*cdf0e10cSrcweir             bool bFound = false;
294*cdf0e10cSrcweir             /*  #i71497# check if external document is loaded successfully,
295*cdf0e10cSrcweir                 otherwise we may find the empty default sheet "Sheet1" in
296*cdf0e10cSrcweir                 pSrcDoc, even if the document does not exist. */
297*cdf0e10cSrcweir             if( pMed->GetError() == 0 )
298*cdf0e10cSrcweir             {
299*cdf0e10cSrcweir                 // no sheet name -> use first sheet
300*cdf0e10cSrcweir                 if ( aTabName.Len() && !bAutoTab )
301*cdf0e10cSrcweir                     bFound = pSrcDoc->GetTable( aTabName, nSrcTab );
302*cdf0e10cSrcweir                 else
303*cdf0e10cSrcweir                     bFound = true;
304*cdf0e10cSrcweir             }
305*cdf0e10cSrcweir 
306*cdf0e10cSrcweir 			if (bFound)
307*cdf0e10cSrcweir 				pDoc->TransferTab( pSrcDoc, nSrcTab, nTab, sal_False,		// nicht neu einfuegen
308*cdf0e10cSrcweir 										(nMode == SC_LINK_VALUE) );		// nur Werte?
309*cdf0e10cSrcweir 			else
310*cdf0e10cSrcweir 			{
311*cdf0e10cSrcweir 				pDoc->DeleteAreaTab( 0,0,MAXCOL,MAXROW, nTab, IDF_ALL );
312*cdf0e10cSrcweir 
313*cdf0e10cSrcweir                 bool bShowError = true;
314*cdf0e10cSrcweir                 if ( nMode == SC_LINK_VALUE )
315*cdf0e10cSrcweir                 {
316*cdf0e10cSrcweir                     //  #139464# Value link (used with external references in formulas):
317*cdf0e10cSrcweir                     //  Look for formulas that reference the sheet, and put errors in the referenced cells.
318*cdf0e10cSrcweir 
319*cdf0e10cSrcweir                     ScRangeList aErrorCells;        // cells on the linked sheets that need error values
320*cdf0e10cSrcweir 
321*cdf0e10cSrcweir                     ScCellIterator aCellIter( pDoc, 0,0,0, MAXCOL,MAXROW,MAXTAB );			// all sheets
322*cdf0e10cSrcweir                     ScBaseCell* pCell = aCellIter.GetFirst();
323*cdf0e10cSrcweir                     while (pCell)
324*cdf0e10cSrcweir                     {
325*cdf0e10cSrcweir                         if (pCell->GetCellType() == CELLTYPE_FORMULA)
326*cdf0e10cSrcweir                         {
327*cdf0e10cSrcweir                             ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell);
328*cdf0e10cSrcweir 
329*cdf0e10cSrcweir                             ScDetectiveRefIter aRefIter( pFCell );
330*cdf0e10cSrcweir                             ScRange aRefRange;
331*cdf0e10cSrcweir                             while ( aRefIter.GetNextRef( aRefRange ) )
332*cdf0e10cSrcweir                             {
333*cdf0e10cSrcweir                                 if ( aRefRange.aStart.Tab() <= nTab && aRefRange.aEnd.Tab() >= nTab )
334*cdf0e10cSrcweir                                 {
335*cdf0e10cSrcweir                                     // use first cell of range references (don't fill potentially large ranges)
336*cdf0e10cSrcweir 
337*cdf0e10cSrcweir                                     aErrorCells.Join( ScRange( aRefRange.aStart ) );
338*cdf0e10cSrcweir                                 }
339*cdf0e10cSrcweir                             }
340*cdf0e10cSrcweir                         }
341*cdf0e10cSrcweir                         pCell = aCellIter.GetNext();
342*cdf0e10cSrcweir                     }
343*cdf0e10cSrcweir 
344*cdf0e10cSrcweir                     sal_uLong nRanges = aErrorCells.Count();
345*cdf0e10cSrcweir                     if ( nRanges )                          // found any?
346*cdf0e10cSrcweir                     {
347*cdf0e10cSrcweir                         ScTokenArray aTokenArr;
348*cdf0e10cSrcweir                         aTokenArr.AddOpCode( ocNotAvail );
349*cdf0e10cSrcweir                         aTokenArr.AddOpCode( ocOpen );
350*cdf0e10cSrcweir                         aTokenArr.AddOpCode( ocClose );
351*cdf0e10cSrcweir                         aTokenArr.AddOpCode( ocStop );
352*cdf0e10cSrcweir 
353*cdf0e10cSrcweir                         for (sal_uLong nPos=0; nPos<nRanges; nPos++)
354*cdf0e10cSrcweir                         {
355*cdf0e10cSrcweir                             const ScRange* pRange = aErrorCells.GetObject(nPos);
356*cdf0e10cSrcweir                             SCCOL nStartCol = pRange->aStart.Col();
357*cdf0e10cSrcweir                             SCROW nStartRow = pRange->aStart.Row();
358*cdf0e10cSrcweir                             SCCOL nEndCol = pRange->aEnd.Col();
359*cdf0e10cSrcweir                             SCROW nEndRow = pRange->aEnd.Row();
360*cdf0e10cSrcweir                             for (SCROW nRow=nStartRow; nRow<=nEndRow; nRow++)
361*cdf0e10cSrcweir                                 for (SCCOL nCol=nStartCol; nCol<=nEndCol; nCol++)
362*cdf0e10cSrcweir                                 {
363*cdf0e10cSrcweir                                     ScAddress aDestPos( nCol, nRow, nTab );
364*cdf0e10cSrcweir                                     ScFormulaCell* pNewCell = new ScFormulaCell( pDoc, aDestPos, &aTokenArr );
365*cdf0e10cSrcweir                                     pDoc->PutCell( aDestPos, pNewCell );
366*cdf0e10cSrcweir                                 }
367*cdf0e10cSrcweir                         }
368*cdf0e10cSrcweir 
369*cdf0e10cSrcweir                         bShowError = false;
370*cdf0e10cSrcweir                     }
371*cdf0e10cSrcweir                     // if no references were found, insert error message (don't leave the sheet empty)
372*cdf0e10cSrcweir                 }
373*cdf0e10cSrcweir 
374*cdf0e10cSrcweir                 if ( bShowError )
375*cdf0e10cSrcweir                 {
376*cdf0e10cSrcweir                     //  Normal link or no references: put error message on sheet.
377*cdf0e10cSrcweir 
378*cdf0e10cSrcweir                     pDoc->SetString( 0,0,nTab, ScGlobal::GetRscString(STR_LINKERROR) );
379*cdf0e10cSrcweir                     pDoc->SetString( 0,1,nTab, ScGlobal::GetRscString(STR_LINKERRORFILE) );
380*cdf0e10cSrcweir                     pDoc->SetString( 1,1,nTab, aNewUrl );
381*cdf0e10cSrcweir                     pDoc->SetString( 0,2,nTab, ScGlobal::GetRscString(STR_LINKERRORTAB) );
382*cdf0e10cSrcweir                     pDoc->SetString( 1,2,nTab, aTabName );
383*cdf0e10cSrcweir                 }
384*cdf0e10cSrcweir 
385*cdf0e10cSrcweir 				bNotFound = sal_True;
386*cdf0e10cSrcweir 			}
387*cdf0e10cSrcweir 
388*cdf0e10cSrcweir 			if ( bNewUrlName || rNewFilter != aFilterName ||
389*cdf0e10cSrcweir 					aNewOpt != aOptions || pNewOptions ||
390*cdf0e10cSrcweir 					nNewRefresh != GetRefreshDelay() )
391*cdf0e10cSrcweir 				pDoc->SetLink( nTab, nMode, aNewUrl, rNewFilter, aNewOpt,
392*cdf0e10cSrcweir 					aTabName, nNewRefresh );
393*cdf0e10cSrcweir 		}
394*cdf0e10cSrcweir 	}
395*cdf0e10cSrcweir 
396*cdf0e10cSrcweir 	//	neue Einstellungen merken
397*cdf0e10cSrcweir 
398*cdf0e10cSrcweir 	if ( bNewUrlName )
399*cdf0e10cSrcweir 		aFileName = aNewUrl;
400*cdf0e10cSrcweir 	if ( rNewFilter != aFilterName )
401*cdf0e10cSrcweir 		aFilterName = rNewFilter;
402*cdf0e10cSrcweir 	if ( aNewOpt != aOptions )
403*cdf0e10cSrcweir 		aOptions = aNewOpt;
404*cdf0e10cSrcweir 
405*cdf0e10cSrcweir 	//	aufraeumen
406*cdf0e10cSrcweir 
407*cdf0e10cSrcweir //	pSrcShell->DoClose();
408*cdf0e10cSrcweir 	aRef->DoClose();
409*cdf0e10cSrcweir 
410*cdf0e10cSrcweir 	//	Undo
411*cdf0e10cSrcweir 
412*cdf0e10cSrcweir 	if (bAddUndo && bUndo)
413*cdf0e10cSrcweir         pImpl->m_pDocSh->GetUndoManager()->AddUndoAction(
414*cdf0e10cSrcweir                     new ScUndoRefreshLink( pImpl->m_pDocSh, pUndoDoc ) );
415*cdf0e10cSrcweir 
416*cdf0e10cSrcweir 	//	Paint (koennen mehrere Tabellen sein)
417*cdf0e10cSrcweir 
418*cdf0e10cSrcweir 	if (bDoPaint)
419*cdf0e10cSrcweir 	{
420*cdf0e10cSrcweir         pImpl->m_pDocSh->PostPaint( ScRange(0,0,0,MAXCOL,MAXROW,MAXTAB),
421*cdf0e10cSrcweir 								PAINT_GRID | PAINT_TOP | PAINT_LEFT );
422*cdf0e10cSrcweir 		aModificator.SetDocumentModified();
423*cdf0e10cSrcweir 	}
424*cdf0e10cSrcweir 
425*cdf0e10cSrcweir 	if (bNotFound)
426*cdf0e10cSrcweir 	{
427*cdf0e10cSrcweir 		//!	Fehler ausgeben ?
428*cdf0e10cSrcweir 	}
429*cdf0e10cSrcweir 
430*cdf0e10cSrcweir 	pDoc->SetInLinkUpdate( sal_False );
431*cdf0e10cSrcweir 
432*cdf0e10cSrcweir 	//	notify Uno objects (for XRefreshListener)
433*cdf0e10cSrcweir 	//!	also notify Uno objects if file name was changed!
434*cdf0e10cSrcweir 	ScLinkRefreshedHint aHint;
435*cdf0e10cSrcweir 	aHint.SetSheetLink( aFileName );
436*cdf0e10cSrcweir 	pDoc->BroadcastUno( aHint );
437*cdf0e10cSrcweir 
438*cdf0e10cSrcweir 	return sal_True;
439*cdf0e10cSrcweir }
440*cdf0e10cSrcweir 
441*cdf0e10cSrcweir IMPL_LINK( ScTableLink, RefreshHdl, ScTableLink*, EMPTYARG )
442*cdf0e10cSrcweir {
443*cdf0e10cSrcweir     long nRes = Refresh( aFileName, aFilterName, NULL, GetRefreshDelay() ) != 0;
444*cdf0e10cSrcweir     return nRes;
445*cdf0e10cSrcweir }
446*cdf0e10cSrcweir 
447*cdf0e10cSrcweir IMPL_LINK( ScTableLink, TableEndEditHdl, ::sfx2::SvBaseLink*, pLink )
448*cdf0e10cSrcweir {
449*cdf0e10cSrcweir     if ( pImpl->m_aEndEditLink.IsSet() )
450*cdf0e10cSrcweir         pImpl->m_aEndEditLink.Call( pLink );
451*cdf0e10cSrcweir     bInEdit = sal_False;
452*cdf0e10cSrcweir     Application::SetDefDialogParent( pImpl->m_pOldParent );
453*cdf0e10cSrcweir     return 0;
454*cdf0e10cSrcweir }
455*cdf0e10cSrcweir 
456*cdf0e10cSrcweir // === ScDocumentLoader ==================================================
457*cdf0e10cSrcweir 
458*cdf0e10cSrcweir String ScDocumentLoader::GetOptions( SfxMedium& rMedium )		// static
459*cdf0e10cSrcweir {
460*cdf0e10cSrcweir 	SfxItemSet* pSet = rMedium.GetItemSet();
461*cdf0e10cSrcweir 	const SfxPoolItem* pItem;
462*cdf0e10cSrcweir 	if ( pSet && SFX_ITEM_SET == pSet->GetItemState( SID_FILE_FILTEROPTIONS, sal_True, &pItem ) )
463*cdf0e10cSrcweir 		return ((const SfxStringItem*)pItem)->GetValue();
464*cdf0e10cSrcweir 
465*cdf0e10cSrcweir 	return EMPTY_STRING;
466*cdf0e10cSrcweir }
467*cdf0e10cSrcweir 
468*cdf0e10cSrcweir sal_Bool ScDocumentLoader::GetFilterName( const String& rFileName,
469*cdf0e10cSrcweir                                     String& rFilter, String& rOptions,
470*cdf0e10cSrcweir                                     sal_Bool bWithContent, sal_Bool bWithInteraction )  // static
471*cdf0e10cSrcweir {
472*cdf0e10cSrcweir 	TypeId aScType = TYPE(ScDocShell);
473*cdf0e10cSrcweir 	SfxObjectShell* pDocSh = SfxObjectShell::GetFirst( &aScType );
474*cdf0e10cSrcweir 	while ( pDocSh )
475*cdf0e10cSrcweir 	{
476*cdf0e10cSrcweir 		if ( pDocSh->HasName() )
477*cdf0e10cSrcweir 		{
478*cdf0e10cSrcweir 			SfxMedium* pMed = pDocSh->GetMedium();
479*cdf0e10cSrcweir 			if ( rFileName == pMed->GetName() )
480*cdf0e10cSrcweir 			{
481*cdf0e10cSrcweir 				rFilter = pMed->GetFilter()->GetFilterName();
482*cdf0e10cSrcweir 				rOptions = GetOptions(*pMed);
483*cdf0e10cSrcweir 				return sal_True;
484*cdf0e10cSrcweir 			}
485*cdf0e10cSrcweir 		}
486*cdf0e10cSrcweir 		pDocSh = SfxObjectShell::GetNext( *pDocSh, &aScType );
487*cdf0e10cSrcweir 	}
488*cdf0e10cSrcweir 
489*cdf0e10cSrcweir     INetURLObject aUrl( rFileName );
490*cdf0e10cSrcweir     INetProtocol eProt = aUrl.GetProtocol();
491*cdf0e10cSrcweir     if ( eProt == INET_PROT_NOT_VALID )         // invalid URL?
492*cdf0e10cSrcweir         return sal_False;                           // abort without creating a medium
493*cdf0e10cSrcweir 
494*cdf0e10cSrcweir 	//	Filter-Detection
495*cdf0e10cSrcweir 
496*cdf0e10cSrcweir 	const SfxFilter* pSfxFilter = NULL;
497*cdf0e10cSrcweir 	SfxMedium* pMedium = new SfxMedium( rFileName, STREAM_STD_READ, sal_False );
498*cdf0e10cSrcweir 	if ( pMedium->GetError() == ERRCODE_NONE )
499*cdf0e10cSrcweir 	{
500*cdf0e10cSrcweir         if ( bWithInteraction )
501*cdf0e10cSrcweir             pMedium->UseInteractionHandler(sal_True);   // #i73992# no longer called from GuessFilter
502*cdf0e10cSrcweir 
503*cdf0e10cSrcweir 		SfxFilterMatcher aMatcher( String::CreateFromAscii("scalc") );
504*cdf0e10cSrcweir         if( bWithContent )
505*cdf0e10cSrcweir             aMatcher.GuessFilter( *pMedium, &pSfxFilter );
506*cdf0e10cSrcweir         else
507*cdf0e10cSrcweir             aMatcher.GuessFilterIgnoringContent( *pMedium, &pSfxFilter );
508*cdf0e10cSrcweir 	}
509*cdf0e10cSrcweir 
510*cdf0e10cSrcweir     sal_Bool bOK = sal_False;
511*cdf0e10cSrcweir 	if ( pMedium->GetError() == ERRCODE_NONE )
512*cdf0e10cSrcweir     {
513*cdf0e10cSrcweir         if ( pSfxFilter )
514*cdf0e10cSrcweir             rFilter = pSfxFilter->GetFilterName();
515*cdf0e10cSrcweir         else
516*cdf0e10cSrcweir             rFilter = ScDocShell::GetOwnFilterName();		//	sonst Calc-Datei
517*cdf0e10cSrcweir         bOK = (rFilter.Len()>0);
518*cdf0e10cSrcweir     }
519*cdf0e10cSrcweir 
520*cdf0e10cSrcweir 	delete pMedium;
521*cdf0e10cSrcweir     return bOK;
522*cdf0e10cSrcweir }
523*cdf0e10cSrcweir 
524*cdf0e10cSrcweir void ScDocumentLoader::RemoveAppPrefix( String& rFilterName )		// static
525*cdf0e10cSrcweir {
526*cdf0e10cSrcweir 	String aAppPrefix = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM( STRING_SCAPP ));
527*cdf0e10cSrcweir 	aAppPrefix.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ": " ));
528*cdf0e10cSrcweir 	xub_StrLen nPreLen = aAppPrefix.Len();
529*cdf0e10cSrcweir 	if ( rFilterName.Copy(0,nPreLen) == aAppPrefix )
530*cdf0e10cSrcweir 		rFilterName.Erase(0,nPreLen);
531*cdf0e10cSrcweir }
532*cdf0e10cSrcweir 
533*cdf0e10cSrcweir ScDocumentLoader::ScDocumentLoader( const String& rFileName,
534*cdf0e10cSrcweir 									String& rFilterName, String& rOptions,
535*cdf0e10cSrcweir 									sal_uInt32 nRekCnt, sal_Bool bWithInteraction ) :
536*cdf0e10cSrcweir         pDocShell(0),
537*cdf0e10cSrcweir 		pMedium(0)
538*cdf0e10cSrcweir {
539*cdf0e10cSrcweir 	if ( !rFilterName.Len() )
540*cdf0e10cSrcweir         GetFilterName( rFileName, rFilterName, rOptions, sal_True, bWithInteraction );
541*cdf0e10cSrcweir 
542*cdf0e10cSrcweir 	const SfxFilter* pFilter = ScDocShell::Factory().GetFilterContainer()->GetFilter4FilterName( rFilterName );
543*cdf0e10cSrcweir 
544*cdf0e10cSrcweir 	//	ItemSet immer anlegen, damit die DocShell die Optionen setzen kann
545*cdf0e10cSrcweir 	SfxItemSet* pSet = new SfxAllItemSet( SFX_APP()->GetPool() );
546*cdf0e10cSrcweir 	if ( rOptions.Len() )
547*cdf0e10cSrcweir 		pSet->Put( SfxStringItem( SID_FILE_FILTEROPTIONS, rOptions ) );
548*cdf0e10cSrcweir 
549*cdf0e10cSrcweir 	pMedium = new SfxMedium( rFileName, STREAM_STD_READ, sal_False, pFilter, pSet );
550*cdf0e10cSrcweir 	if ( pMedium->GetError() != ERRCODE_NONE )
551*cdf0e10cSrcweir 		return ;
552*cdf0e10cSrcweir 
553*cdf0e10cSrcweir 	if ( bWithInteraction )
554*cdf0e10cSrcweir 		pMedium->UseInteractionHandler( sal_True );	// to enable the filter options dialog
555*cdf0e10cSrcweir 
556*cdf0e10cSrcweir     pDocShell = new ScDocShell( SFX_CREATE_MODE_INTERNAL );
557*cdf0e10cSrcweir     aRef = pDocShell;
558*cdf0e10cSrcweir 
559*cdf0e10cSrcweir     ScDocument* pDoc = pDocShell->GetDocument();
560*cdf0e10cSrcweir 	if( pDoc )
561*cdf0e10cSrcweir 	{
562*cdf0e10cSrcweir 		ScExtDocOptions*	pExtDocOpt = pDoc->GetExtDocOptions();
563*cdf0e10cSrcweir 		if( !pExtDocOpt )
564*cdf0e10cSrcweir 		{
565*cdf0e10cSrcweir 			pExtDocOpt = new ScExtDocOptions;
566*cdf0e10cSrcweir 			pDoc->SetExtDocOptions( pExtDocOpt );
567*cdf0e10cSrcweir 		}
568*cdf0e10cSrcweir         pExtDocOpt->GetDocSettings().mnLinkCnt = nRekCnt;
569*cdf0e10cSrcweir 	}
570*cdf0e10cSrcweir 
571*cdf0e10cSrcweir     pDocShell->DoLoad( pMedium );
572*cdf0e10cSrcweir 
573*cdf0e10cSrcweir 	String aNew = GetOptions(*pMedium);			// Optionen werden beim Laden per Dialog gesetzt
574*cdf0e10cSrcweir 	if (aNew.Len() && aNew != rOptions)
575*cdf0e10cSrcweir 		rOptions = aNew;
576*cdf0e10cSrcweir }
577*cdf0e10cSrcweir 
578*cdf0e10cSrcweir ScDocumentLoader::~ScDocumentLoader()
579*cdf0e10cSrcweir {
580*cdf0e10cSrcweir /*  if ( pDocShell )
581*cdf0e10cSrcweir         pDocShell->DoClose();
582*cdf0e10cSrcweir */
583*cdf0e10cSrcweir 	if ( aRef.Is() )
584*cdf0e10cSrcweir 		aRef->DoClose();
585*cdf0e10cSrcweir 	else if ( pMedium )
586*cdf0e10cSrcweir 		delete pMedium;
587*cdf0e10cSrcweir }
588*cdf0e10cSrcweir 
589*cdf0e10cSrcweir void ScDocumentLoader::ReleaseDocRef()
590*cdf0e10cSrcweir {
591*cdf0e10cSrcweir 	if ( aRef.Is() )
592*cdf0e10cSrcweir 	{
593*cdf0e10cSrcweir 		//	release reference without calling DoClose - caller must
594*cdf0e10cSrcweir 		//	have another reference to the doc and call DoClose later
595*cdf0e10cSrcweir 
596*cdf0e10cSrcweir         pDocShell = NULL;
597*cdf0e10cSrcweir 		pMedium = NULL;
598*cdf0e10cSrcweir 		aRef.Clear();
599*cdf0e10cSrcweir 	}
600*cdf0e10cSrcweir }
601*cdf0e10cSrcweir 
602*cdf0e10cSrcweir ScDocument* ScDocumentLoader::GetDocument()
603*cdf0e10cSrcweir {
604*cdf0e10cSrcweir     return pDocShell ? pDocShell->GetDocument() : 0;
605*cdf0e10cSrcweir }
606*cdf0e10cSrcweir 
607*cdf0e10cSrcweir sal_Bool ScDocumentLoader::IsError() const
608*cdf0e10cSrcweir {
609*cdf0e10cSrcweir     if ( pDocShell && pMedium )
610*cdf0e10cSrcweir 		return pMedium->GetError() != ERRCODE_NONE;
611*cdf0e10cSrcweir 	else
612*cdf0e10cSrcweir 		return sal_True;
613*cdf0e10cSrcweir }
614*cdf0e10cSrcweir 
615*cdf0e10cSrcweir String ScDocumentLoader::GetTitle() const
616*cdf0e10cSrcweir {
617*cdf0e10cSrcweir     if ( pDocShell )
618*cdf0e10cSrcweir         return pDocShell->GetTitle();
619*cdf0e10cSrcweir 	else
620*cdf0e10cSrcweir 		return EMPTY_STRING;
621*cdf0e10cSrcweir }
622*cdf0e10cSrcweir 
623