xref: /aoo41x/main/sc/source/ui/unoobj/funcuno.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 
31*cdf0e10cSrcweir 
32*cdf0e10cSrcweir 
33*cdf0e10cSrcweir #include <tools/debug.hxx>
34*cdf0e10cSrcweir #include <sfx2/app.hxx>
35*cdf0e10cSrcweir #include <svl/itemprop.hxx>
36*cdf0e10cSrcweir 
37*cdf0e10cSrcweir #include "scitems.hxx"
38*cdf0e10cSrcweir #include "funcuno.hxx"
39*cdf0e10cSrcweir #include "miscuno.hxx"
40*cdf0e10cSrcweir #include "cellsuno.hxx"
41*cdf0e10cSrcweir #include "unoguard.hxx"
42*cdf0e10cSrcweir #include "scdll.hxx"
43*cdf0e10cSrcweir #include "document.hxx"
44*cdf0e10cSrcweir #include "compiler.hxx"
45*cdf0e10cSrcweir #include "formula/errorcodes.hxx"
46*cdf0e10cSrcweir #include "callform.hxx"
47*cdf0e10cSrcweir #include "addincol.hxx"
48*cdf0e10cSrcweir #include "rangeseq.hxx"
49*cdf0e10cSrcweir #include "cell.hxx"
50*cdf0e10cSrcweir #include "docoptio.hxx"
51*cdf0e10cSrcweir #include "optuno.hxx"
52*cdf0e10cSrcweir #include <docuno.hxx>
53*cdf0e10cSrcweir // for lcl_CopyData:
54*cdf0e10cSrcweir #include "markdata.hxx"
55*cdf0e10cSrcweir #include "patattr.hxx"
56*cdf0e10cSrcweir #include "docpool.hxx"
57*cdf0e10cSrcweir #include "attrib.hxx"
58*cdf0e10cSrcweir #include "clipparam.hxx"
59*cdf0e10cSrcweir #include "dociter.hxx"
60*cdf0e10cSrcweir 
61*cdf0e10cSrcweir using namespace com::sun::star;
62*cdf0e10cSrcweir 
63*cdf0e10cSrcweir //------------------------------------------------------------------------
64*cdf0e10cSrcweir 
65*cdf0e10cSrcweir //	registered as implementation for service FunctionAccess,
66*cdf0e10cSrcweir //	also supports service SpreadsheetDocumentSettings (to set null date etc.)
67*cdf0e10cSrcweir 
68*cdf0e10cSrcweir #define SCFUNCTIONACCESS_SERVICE	"com.sun.star.sheet.FunctionAccess"
69*cdf0e10cSrcweir #define SCDOCSETTINGS_SERVICE		"com.sun.star.sheet.SpreadsheetDocumentSettings"
70*cdf0e10cSrcweir 
71*cdf0e10cSrcweir //------------------------------------------------------------------------
72*cdf0e10cSrcweir 
73*cdf0e10cSrcweir // helper to use cached document if not in use, temporary document otherwise
74*cdf0e10cSrcweir 
75*cdf0e10cSrcweir class ScTempDocSource
76*cdf0e10cSrcweir {
77*cdf0e10cSrcweir private:
78*cdf0e10cSrcweir 	ScTempDocCache&	rCache;
79*cdf0e10cSrcweir 	ScDocument*		pTempDoc;
80*cdf0e10cSrcweir 
81*cdf0e10cSrcweir 	static ScDocument*	CreateDocument();		// create and initialize doc
82*cdf0e10cSrcweir 
83*cdf0e10cSrcweir public:
84*cdf0e10cSrcweir 				ScTempDocSource( ScTempDocCache& rDocCache );
85*cdf0e10cSrcweir 				~ScTempDocSource();
86*cdf0e10cSrcweir 
87*cdf0e10cSrcweir 	ScDocument*		GetDocument();
88*cdf0e10cSrcweir };
89*cdf0e10cSrcweir 
90*cdf0e10cSrcweir //------------------------------------------------------------------------
91*cdf0e10cSrcweir 
92*cdf0e10cSrcweir // static
93*cdf0e10cSrcweir ScDocument* ScTempDocSource::CreateDocument()
94*cdf0e10cSrcweir {
95*cdf0e10cSrcweir 	ScDocument* pDoc = new ScDocument;					// SCDOCMODE_DOCUMENT
96*cdf0e10cSrcweir 	pDoc->MakeTable( 0 );
97*cdf0e10cSrcweir 	return pDoc;
98*cdf0e10cSrcweir }
99*cdf0e10cSrcweir 
100*cdf0e10cSrcweir ScTempDocSource::ScTempDocSource( ScTempDocCache& rDocCache ) :
101*cdf0e10cSrcweir 	rCache( rDocCache ),
102*cdf0e10cSrcweir 	pTempDoc( NULL )
103*cdf0e10cSrcweir {
104*cdf0e10cSrcweir 	if ( rCache.IsInUse() )
105*cdf0e10cSrcweir 		pTempDoc = CreateDocument();
106*cdf0e10cSrcweir 	else
107*cdf0e10cSrcweir 	{
108*cdf0e10cSrcweir 		rCache.SetInUse( sal_True );
109*cdf0e10cSrcweir 		if ( !rCache.GetDocument() )
110*cdf0e10cSrcweir 			rCache.SetDocument( CreateDocument() );
111*cdf0e10cSrcweir 	}
112*cdf0e10cSrcweir }
113*cdf0e10cSrcweir 
114*cdf0e10cSrcweir ScTempDocSource::~ScTempDocSource()
115*cdf0e10cSrcweir {
116*cdf0e10cSrcweir 	if ( pTempDoc )
117*cdf0e10cSrcweir 		delete pTempDoc;
118*cdf0e10cSrcweir 	else
119*cdf0e10cSrcweir 		rCache.SetInUse( sal_False );
120*cdf0e10cSrcweir }
121*cdf0e10cSrcweir 
122*cdf0e10cSrcweir ScDocument* ScTempDocSource::GetDocument()
123*cdf0e10cSrcweir {
124*cdf0e10cSrcweir 	if ( pTempDoc )
125*cdf0e10cSrcweir 		return pTempDoc;
126*cdf0e10cSrcweir 	else
127*cdf0e10cSrcweir 		return rCache.GetDocument();
128*cdf0e10cSrcweir }
129*cdf0e10cSrcweir 
130*cdf0e10cSrcweir //------------------------------------------------------------------------
131*cdf0e10cSrcweir 
132*cdf0e10cSrcweir ScTempDocCache::ScTempDocCache() :
133*cdf0e10cSrcweir 	pDoc( NULL ),
134*cdf0e10cSrcweir 	bInUse( sal_False )
135*cdf0e10cSrcweir {
136*cdf0e10cSrcweir }
137*cdf0e10cSrcweir 
138*cdf0e10cSrcweir ScTempDocCache::~ScTempDocCache()
139*cdf0e10cSrcweir {
140*cdf0e10cSrcweir 	DBG_ASSERT( !bInUse, "ScTempDocCache dtor: bInUse" );
141*cdf0e10cSrcweir 	delete pDoc;
142*cdf0e10cSrcweir }
143*cdf0e10cSrcweir 
144*cdf0e10cSrcweir void ScTempDocCache::SetDocument( ScDocument* pNew )
145*cdf0e10cSrcweir {
146*cdf0e10cSrcweir 	DBG_ASSERT( !pDoc, "ScTempDocCache::SetDocument: already set" );
147*cdf0e10cSrcweir 	pDoc = pNew;
148*cdf0e10cSrcweir }
149*cdf0e10cSrcweir 
150*cdf0e10cSrcweir void ScTempDocCache::Clear()
151*cdf0e10cSrcweir {
152*cdf0e10cSrcweir 	DBG_ASSERT( !bInUse, "ScTempDocCache::Clear: bInUse" );
153*cdf0e10cSrcweir 	delete pDoc;
154*cdf0e10cSrcweir 	pDoc = NULL;
155*cdf0e10cSrcweir }
156*cdf0e10cSrcweir 
157*cdf0e10cSrcweir //------------------------------------------------------------------------
158*cdf0e10cSrcweir 
159*cdf0e10cSrcweir //	copy results from one document into another
160*cdf0e10cSrcweir //!	merge this with ScAreaLink::Refresh
161*cdf0e10cSrcweir //!	copy directly without a clipboard document?
162*cdf0e10cSrcweir 
163*cdf0e10cSrcweir sal_Bool lcl_CopyData( ScDocument* pSrcDoc, const ScRange& rSrcRange,
164*cdf0e10cSrcweir 					ScDocument* pDestDoc, const ScAddress& rDestPos )
165*cdf0e10cSrcweir {
166*cdf0e10cSrcweir 	SCTAB nSrcTab = rSrcRange.aStart.Tab();
167*cdf0e10cSrcweir 	SCTAB nDestTab = rDestPos.Tab();
168*cdf0e10cSrcweir 
169*cdf0e10cSrcweir 	ScRange aNewRange( rDestPos, ScAddress(
170*cdf0e10cSrcweir 				rSrcRange.aEnd.Col() - rSrcRange.aStart.Col() + rDestPos.Col(),
171*cdf0e10cSrcweir 				rSrcRange.aEnd.Row() - rSrcRange.aStart.Row() + rDestPos.Row(),
172*cdf0e10cSrcweir 				nDestTab ) );
173*cdf0e10cSrcweir 
174*cdf0e10cSrcweir 	ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP );
175*cdf0e10cSrcweir 	ScMarkData aSourceMark;
176*cdf0e10cSrcweir 	aSourceMark.SelectOneTable( nSrcTab );		// for CopyToClip
177*cdf0e10cSrcweir 	aSourceMark.SetMarkArea( rSrcRange );
178*cdf0e10cSrcweir     ScClipParam aClipParam(rSrcRange, false);
179*cdf0e10cSrcweir     pSrcDoc->CopyToClip(aClipParam, pClipDoc, &aSourceMark, false);
180*cdf0e10cSrcweir 
181*cdf0e10cSrcweir 	if ( pClipDoc->HasAttrib( 0,0,nSrcTab, MAXCOL,MAXROW,nSrcTab,
182*cdf0e10cSrcweir 								HASATTR_MERGED | HASATTR_OVERLAPPED ) )
183*cdf0e10cSrcweir 	{
184*cdf0e10cSrcweir 		ScPatternAttr aPattern( pSrcDoc->GetPool() );
185*cdf0e10cSrcweir 		aPattern.GetItemSet().Put( ScMergeAttr() );				// Defaults
186*cdf0e10cSrcweir 		aPattern.GetItemSet().Put( ScMergeFlagAttr() );
187*cdf0e10cSrcweir 		pClipDoc->ApplyPatternAreaTab( 0,0, MAXCOL,MAXROW, nSrcTab, aPattern );
188*cdf0e10cSrcweir 	}
189*cdf0e10cSrcweir 
190*cdf0e10cSrcweir     // If the range contains formula cells with default number format,
191*cdf0e10cSrcweir     // apply a number format for the formula result
192*cdf0e10cSrcweir     ScCellIterator aIter( pClipDoc, rSrcRange );
193*cdf0e10cSrcweir     ScBaseCell* pCell = aIter.GetFirst();
194*cdf0e10cSrcweir     while (pCell)
195*cdf0e10cSrcweir     {
196*cdf0e10cSrcweir         if (pCell->GetCellType() == CELLTYPE_FORMULA)
197*cdf0e10cSrcweir         {
198*cdf0e10cSrcweir             ScAddress aCellPos = aIter.GetPos();
199*cdf0e10cSrcweir             sal_uInt32 nFormat = pClipDoc->GetNumberFormat(aCellPos);
200*cdf0e10cSrcweir             if ( (nFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 )
201*cdf0e10cSrcweir             {
202*cdf0e10cSrcweir                 ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell);
203*cdf0e10cSrcweir                 sal_uInt16 nErrCode = pFCell->GetErrCode();
204*cdf0e10cSrcweir                 if ( nErrCode == 0 && pFCell->IsValue() )
205*cdf0e10cSrcweir                 {
206*cdf0e10cSrcweir                     sal_uInt32 nNewFormat = pFCell->GetStandardFormat( *pClipDoc->GetFormatTable(), nFormat );
207*cdf0e10cSrcweir                     if ( nNewFormat != nFormat )
208*cdf0e10cSrcweir                         pClipDoc->ApplyAttr( aCellPos.Col(), aCellPos.Row(), aCellPos.Tab(),
209*cdf0e10cSrcweir                                              SfxUInt32Item( ATTR_VALUE_FORMAT, nNewFormat ) );
210*cdf0e10cSrcweir                 }
211*cdf0e10cSrcweir             }
212*cdf0e10cSrcweir         }
213*cdf0e10cSrcweir         pCell = aIter.GetNext();
214*cdf0e10cSrcweir     }
215*cdf0e10cSrcweir 
216*cdf0e10cSrcweir 	ScMarkData aDestMark;
217*cdf0e10cSrcweir 	aDestMark.SelectOneTable( nDestTab );
218*cdf0e10cSrcweir 	aDestMark.SetMarkArea( aNewRange );
219*cdf0e10cSrcweir 	pDestDoc->CopyFromClip( aNewRange, aDestMark, IDF_ALL & ~IDF_FORMULA, NULL, pClipDoc, sal_False );
220*cdf0e10cSrcweir 
221*cdf0e10cSrcweir 	delete pClipDoc;
222*cdf0e10cSrcweir 	return sal_True;
223*cdf0e10cSrcweir }
224*cdf0e10cSrcweir 
225*cdf0e10cSrcweir //------------------------------------------------------------------------
226*cdf0e10cSrcweir 
227*cdf0e10cSrcweir ScFunctionAccess::ScFunctionAccess() :
228*cdf0e10cSrcweir 	pOptions( NULL ),
229*cdf0e10cSrcweir     aPropertyMap( ScDocOptionsHelper::GetPropertyMap() ),
230*cdf0e10cSrcweir     mbArray( true ),    // default according to behaviour of older Office versions
231*cdf0e10cSrcweir 	mbValid( true )
232*cdf0e10cSrcweir {
233*cdf0e10cSrcweir 	StartListening( *SFX_APP() );		// for SFX_HINT_DEINITIALIZING
234*cdf0e10cSrcweir }
235*cdf0e10cSrcweir 
236*cdf0e10cSrcweir ScFunctionAccess::~ScFunctionAccess()
237*cdf0e10cSrcweir {
238*cdf0e10cSrcweir 	delete pOptions;
239*cdf0e10cSrcweir }
240*cdf0e10cSrcweir 
241*cdf0e10cSrcweir void ScFunctionAccess::Notify( SfxBroadcaster&, const SfxHint& rHint )
242*cdf0e10cSrcweir {
243*cdf0e10cSrcweir 	if ( rHint.ISA(SfxSimpleHint) &&
244*cdf0e10cSrcweir 		((SfxSimpleHint&)rHint).GetId() == SFX_HINT_DEINITIALIZING )
245*cdf0e10cSrcweir 	{
246*cdf0e10cSrcweir 		//	document must not be used anymore
247*cdf0e10cSrcweir 		aDocCache.Clear();
248*cdf0e10cSrcweir 		mbValid = false;
249*cdf0e10cSrcweir 	}
250*cdf0e10cSrcweir }
251*cdf0e10cSrcweir 
252*cdf0e10cSrcweir // stuff for exService_...
253*cdf0e10cSrcweir 
254*cdf0e10cSrcweir uno::Reference<uno::XInterface>	SAL_CALL ScFunctionAccess_CreateInstance(
255*cdf0e10cSrcweir 						const uno::Reference<lang::XMultiServiceFactory>& )
256*cdf0e10cSrcweir {
257*cdf0e10cSrcweir 	ScUnoGuard aGuard;
258*cdf0e10cSrcweir 	ScDLL::Init();
259*cdf0e10cSrcweir 	static uno::Reference< uno::XInterface > xInst((::cppu::OWeakObject*) new ScFunctionAccess);
260*cdf0e10cSrcweir 	return xInst;
261*cdf0e10cSrcweir }
262*cdf0e10cSrcweir 
263*cdf0e10cSrcweir rtl::OUString ScFunctionAccess::getImplementationName_Static()
264*cdf0e10cSrcweir {
265*cdf0e10cSrcweir 	return rtl::OUString::createFromAscii( "stardiv.StarCalc.ScFunctionAccess" );
266*cdf0e10cSrcweir }
267*cdf0e10cSrcweir 
268*cdf0e10cSrcweir uno::Sequence<rtl::OUString> ScFunctionAccess::getSupportedServiceNames_Static()
269*cdf0e10cSrcweir {
270*cdf0e10cSrcweir 	uno::Sequence<rtl::OUString> aRet(1);
271*cdf0e10cSrcweir 	rtl::OUString* pArray = aRet.getArray();
272*cdf0e10cSrcweir 	pArray[0] = rtl::OUString::createFromAscii( SCFUNCTIONACCESS_SERVICE );
273*cdf0e10cSrcweir 	return aRet;
274*cdf0e10cSrcweir }
275*cdf0e10cSrcweir 
276*cdf0e10cSrcweir // XServiceInfo
277*cdf0e10cSrcweir 
278*cdf0e10cSrcweir rtl::OUString SAL_CALL ScFunctionAccess::getImplementationName() throw(uno::RuntimeException)
279*cdf0e10cSrcweir {
280*cdf0e10cSrcweir 	return rtl::OUString::createFromAscii( "ScFunctionAccess" );
281*cdf0e10cSrcweir }
282*cdf0e10cSrcweir 
283*cdf0e10cSrcweir sal_Bool SAL_CALL ScFunctionAccess::supportsService( const rtl::OUString& rServiceName )
284*cdf0e10cSrcweir 													throw(uno::RuntimeException)
285*cdf0e10cSrcweir {
286*cdf0e10cSrcweir 	String aServiceStr(rServiceName);
287*cdf0e10cSrcweir 	return aServiceStr.EqualsAscii( SCFUNCTIONACCESS_SERVICE ) ||
288*cdf0e10cSrcweir 		   aServiceStr.EqualsAscii( SCDOCSETTINGS_SERVICE );
289*cdf0e10cSrcweir }
290*cdf0e10cSrcweir 
291*cdf0e10cSrcweir uno::Sequence<rtl::OUString> SAL_CALL ScFunctionAccess::getSupportedServiceNames()
292*cdf0e10cSrcweir 													throw(uno::RuntimeException)
293*cdf0e10cSrcweir {
294*cdf0e10cSrcweir 	uno::Sequence<rtl::OUString> aRet(2);
295*cdf0e10cSrcweir 	rtl::OUString* pArray = aRet.getArray();
296*cdf0e10cSrcweir 	pArray[0] = rtl::OUString::createFromAscii( SCFUNCTIONACCESS_SERVICE );
297*cdf0e10cSrcweir 	pArray[1] = rtl::OUString::createFromAscii( SCDOCSETTINGS_SERVICE );
298*cdf0e10cSrcweir 	return aRet;
299*cdf0e10cSrcweir }
300*cdf0e10cSrcweir 
301*cdf0e10cSrcweir // XPropertySet (document settings)
302*cdf0e10cSrcweir 
303*cdf0e10cSrcweir uno::Reference<beans::XPropertySetInfo> SAL_CALL ScFunctionAccess::getPropertySetInfo()
304*cdf0e10cSrcweir 														throw(uno::RuntimeException)
305*cdf0e10cSrcweir {
306*cdf0e10cSrcweir 	ScUnoGuard aGuard;
307*cdf0e10cSrcweir 	static uno::Reference<beans::XPropertySetInfo> aRef(
308*cdf0e10cSrcweir         new SfxItemPropertySetInfo( &aPropertyMap ));
309*cdf0e10cSrcweir 	return aRef;
310*cdf0e10cSrcweir }
311*cdf0e10cSrcweir 
312*cdf0e10cSrcweir void SAL_CALL ScFunctionAccess::setPropertyValue(
313*cdf0e10cSrcweir 						const rtl::OUString& aPropertyName, const uno::Any& aValue )
314*cdf0e10cSrcweir 				throw(beans::UnknownPropertyException, beans::PropertyVetoException,
315*cdf0e10cSrcweir 						lang::IllegalArgumentException, lang::WrappedTargetException,
316*cdf0e10cSrcweir 						uno::RuntimeException)
317*cdf0e10cSrcweir {
318*cdf0e10cSrcweir 	ScUnoGuard aGuard;
319*cdf0e10cSrcweir 
320*cdf0e10cSrcweir     if( aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsArrayFunction" ) ) )
321*cdf0e10cSrcweir     {
322*cdf0e10cSrcweir         if( !(aValue >>= mbArray) )
323*cdf0e10cSrcweir             throw lang::IllegalArgumentException();
324*cdf0e10cSrcweir     }
325*cdf0e10cSrcweir     else
326*cdf0e10cSrcweir     {
327*cdf0e10cSrcweir     	if ( !pOptions )
328*cdf0e10cSrcweir     		pOptions = new ScDocOptions();
329*cdf0e10cSrcweir 
330*cdf0e10cSrcweir     	// options aren't initialized from configuration - always get the same default behaviour
331*cdf0e10cSrcweir 
332*cdf0e10cSrcweir         sal_Bool bDone = ScDocOptionsHelper::setPropertyValue( *pOptions, aPropertyMap, aPropertyName, aValue );
333*cdf0e10cSrcweir     	if (!bDone)
334*cdf0e10cSrcweir     		throw beans::UnknownPropertyException();
335*cdf0e10cSrcweir     }
336*cdf0e10cSrcweir }
337*cdf0e10cSrcweir 
338*cdf0e10cSrcweir uno::Any SAL_CALL ScFunctionAccess::getPropertyValue( const rtl::OUString& aPropertyName )
339*cdf0e10cSrcweir 				throw(beans::UnknownPropertyException, lang::WrappedTargetException,
340*cdf0e10cSrcweir 						uno::RuntimeException)
341*cdf0e10cSrcweir {
342*cdf0e10cSrcweir 	ScUnoGuard aGuard;
343*cdf0e10cSrcweir 
344*cdf0e10cSrcweir     if( aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsArrayFunction" ) ) )
345*cdf0e10cSrcweir         return uno::Any( mbArray );
346*cdf0e10cSrcweir 
347*cdf0e10cSrcweir 	if ( !pOptions )
348*cdf0e10cSrcweir 		pOptions = new ScDocOptions();
349*cdf0e10cSrcweir 
350*cdf0e10cSrcweir 	// options aren't initialized from configuration - always get the same default behaviour
351*cdf0e10cSrcweir 
352*cdf0e10cSrcweir     return ScDocOptionsHelper::getPropertyValue( *pOptions, aPropertyMap, aPropertyName );
353*cdf0e10cSrcweir }
354*cdf0e10cSrcweir 
355*cdf0e10cSrcweir SC_IMPL_DUMMY_PROPERTY_LISTENER( ScFunctionAccess )
356*cdf0e10cSrcweir 
357*cdf0e10cSrcweir // XFunctionAccess
358*cdf0e10cSrcweir 
359*cdf0e10cSrcweir sal_Bool lcl_AddFunctionToken( ScTokenArray& rArray, const rtl::OUString& rName,const ScCompiler& rCompiler )
360*cdf0e10cSrcweir {
361*cdf0e10cSrcweir 	// function names are always case-insensitive
362*cdf0e10cSrcweir 	String aUpper( ScGlobal::pCharClass->upper( rName ) );
363*cdf0e10cSrcweir 
364*cdf0e10cSrcweir 	// same options as in ScCompiler::IsOpCode:
365*cdf0e10cSrcweir 	// 1. built-in function name
366*cdf0e10cSrcweir 
367*cdf0e10cSrcweir     OpCode eOp = rCompiler.GetEnglishOpCode( aUpper );
368*cdf0e10cSrcweir     if ( eOp != ocNone )
369*cdf0e10cSrcweir     {
370*cdf0e10cSrcweir         rArray.AddOpCode( eOp );
371*cdf0e10cSrcweir         return sal_True;
372*cdf0e10cSrcweir     }
373*cdf0e10cSrcweir 
374*cdf0e10cSrcweir 	// 2. old add in functions
375*cdf0e10cSrcweir 
376*cdf0e10cSrcweir 	sal_uInt16 nIndex;
377*cdf0e10cSrcweir 	if ( ScGlobal::GetFuncCollection()->SearchFunc( aUpper, nIndex ) )
378*cdf0e10cSrcweir 	{
379*cdf0e10cSrcweir 		rArray.AddExternal( aUpper.GetBuffer() );
380*cdf0e10cSrcweir 		return sal_True;
381*cdf0e10cSrcweir 	}
382*cdf0e10cSrcweir 
383*cdf0e10cSrcweir 	// 3. new (uno) add in functions
384*cdf0e10cSrcweir 
385*cdf0e10cSrcweir 	String aIntName(ScGlobal::GetAddInCollection()->FindFunction( aUpper, sal_False ));
386*cdf0e10cSrcweir 	if (aIntName.Len())
387*cdf0e10cSrcweir 	{
388*cdf0e10cSrcweir 		rArray.AddExternal( aIntName.GetBuffer() );		// international name
389*cdf0e10cSrcweir 		return sal_True;
390*cdf0e10cSrcweir 	}
391*cdf0e10cSrcweir 
392*cdf0e10cSrcweir 	return sal_False;		// no valid function name
393*cdf0e10cSrcweir }
394*cdf0e10cSrcweir 
395*cdf0e10cSrcweir void lcl_AddRef( ScTokenArray& rArray, long nStartRow, long nColCount, long nRowCount )
396*cdf0e10cSrcweir {
397*cdf0e10cSrcweir 	ScComplexRefData aRef;
398*cdf0e10cSrcweir 	aRef.InitFlags();
399*cdf0e10cSrcweir 	aRef.Ref1.nTab = 0;
400*cdf0e10cSrcweir 	aRef.Ref2.nTab = 0;
401*cdf0e10cSrcweir 	aRef.Ref1.nCol = 0;
402*cdf0e10cSrcweir 	aRef.Ref1.nRow = (SCROW) nStartRow;
403*cdf0e10cSrcweir 	aRef.Ref2.nCol = (SCCOL) (nColCount - 1);
404*cdf0e10cSrcweir 	aRef.Ref2.nRow = (SCROW) (nStartRow + nRowCount - 1);
405*cdf0e10cSrcweir 	rArray.AddDoubleReference(aRef);
406*cdf0e10cSrcweir }
407*cdf0e10cSrcweir 
408*cdf0e10cSrcweir class SimpleVisitor
409*cdf0e10cSrcweir {
410*cdf0e10cSrcweir protected:
411*cdf0e10cSrcweir 	bool mbArgError;
412*cdf0e10cSrcweir 	ScDocument* mpDoc;
413*cdf0e10cSrcweir public:
414*cdf0e10cSrcweir     SimpleVisitor( ScDocument* pDoc ) : mbArgError( false ), mpDoc( pDoc ) {}
415*cdf0e10cSrcweir 	// could possibly just get away with JUST the following overload
416*cdf0e10cSrcweir 	// 1) virtual void visitElem( long& nCol, long& nRow, const double& elem )
417*cdf0e10cSrcweir 	// 2) virtual void visitElem( long& nCol, long& nRow, const rtl::OUString& elem )
418*cdf0e10cSrcweir 	// 3) virtual void visitElem( long& nCol, long& nRow, const uno::Any& elem )
419*cdf0e10cSrcweir 	// the other types methods are here just to reflect the orig code and for
420*cdf0e10cSrcweir 	// completeness.
421*cdf0e10cSrcweir 
422*cdf0e10cSrcweir 	void visitElem( long nCol, long nRow, const sal_Int16& elem )
423*cdf0e10cSrcweir 	{
424*cdf0e10cSrcweir 		mpDoc->SetValue( (SCCOL) nCol, (SCROW) nRow, 0, elem );
425*cdf0e10cSrcweir 	}
426*cdf0e10cSrcweir 	void visitElem( long nCol, long nRow, const sal_Int32& elem )
427*cdf0e10cSrcweir 	{
428*cdf0e10cSrcweir 		mpDoc->SetValue( (SCCOL) nCol, (SCROW) nRow, 0, elem );
429*cdf0e10cSrcweir 	}
430*cdf0e10cSrcweir 	void visitElem( long nCol, long nRow, const double& elem )
431*cdf0e10cSrcweir 	{
432*cdf0e10cSrcweir 		mpDoc->SetValue( (SCCOL) nCol, (SCROW) nRow, 0, elem );
433*cdf0e10cSrcweir 	}
434*cdf0e10cSrcweir 	void visitElem( long nCol, long nRow, const rtl::OUString& elem )
435*cdf0e10cSrcweir 	{
436*cdf0e10cSrcweir 		if ( elem.getLength() )
437*cdf0e10cSrcweir 			mpDoc->PutCell( (SCCOL) nCol, (SCROW) nRow, 0,
438*cdf0e10cSrcweir 										new ScStringCell( elem ) );
439*cdf0e10cSrcweir 	}
440*cdf0e10cSrcweir 	void visitElem( long nCol, long nRow, const uno::Any& rElement )
441*cdf0e10cSrcweir 	{
442*cdf0e10cSrcweir 		uno::TypeClass eElemClass = rElement.getValueTypeClass();
443*cdf0e10cSrcweir 		if ( eElemClass == uno::TypeClass_VOID )
444*cdf0e10cSrcweir 		{
445*cdf0e10cSrcweir 			// leave empty
446*cdf0e10cSrcweir 		}
447*cdf0e10cSrcweir 		else if ( eElemClass == uno::TypeClass_BYTE ||
448*cdf0e10cSrcweir 					eElemClass == uno::TypeClass_SHORT ||
449*cdf0e10cSrcweir 					eElemClass == uno::TypeClass_UNSIGNED_SHORT ||
450*cdf0e10cSrcweir 					eElemClass == uno::TypeClass_LONG ||
451*cdf0e10cSrcweir 					eElemClass == uno::TypeClass_UNSIGNED_LONG ||
452*cdf0e10cSrcweir 					eElemClass == uno::TypeClass_FLOAT ||
453*cdf0e10cSrcweir 					eElemClass == uno::TypeClass_DOUBLE )
454*cdf0e10cSrcweir 		{
455*cdf0e10cSrcweir 			//	#87871# accept integer types because Basic passes a floating point
456*cdf0e10cSrcweir 			//	variable as byte, short or long if it's an integer number.
457*cdf0e10cSrcweir 			double fVal(0.0);
458*cdf0e10cSrcweir 			rElement >>= fVal;
459*cdf0e10cSrcweir 			visitElem( nCol, nRow, fVal );
460*cdf0e10cSrcweir 		}
461*cdf0e10cSrcweir 		else if ( eElemClass == uno::TypeClass_STRING )
462*cdf0e10cSrcweir 		{
463*cdf0e10cSrcweir 			rtl::OUString aUStr;
464*cdf0e10cSrcweir 			rElement >>= aUStr;
465*cdf0e10cSrcweir 			visitElem( nCol, nRow, aUStr );
466*cdf0e10cSrcweir 		}
467*cdf0e10cSrcweir 		else
468*cdf0e10cSrcweir 			mbArgError = true;
469*cdf0e10cSrcweir 	}
470*cdf0e10cSrcweir 	bool hasArgError() { return mbArgError; }
471*cdf0e10cSrcweir };
472*cdf0e10cSrcweir 
473*cdf0e10cSrcweir template< class seq >
474*cdf0e10cSrcweir class SequencesContainer
475*cdf0e10cSrcweir {
476*cdf0e10cSrcweir 	uno::Sequence< uno::Sequence< seq > > maSeq;
477*cdf0e10cSrcweir 
478*cdf0e10cSrcweir 	long& mrDocRow;
479*cdf0e10cSrcweir 	bool mbOverflow;
480*cdf0e10cSrcweir 	bool mbArgError;
481*cdf0e10cSrcweir 	ScDocument* mpDoc;
482*cdf0e10cSrcweir 	ScTokenArray& mrTokenArr;
483*cdf0e10cSrcweir 
484*cdf0e10cSrcweir public:
485*cdf0e10cSrcweir 	SequencesContainer( const uno::Any& rArg, ScTokenArray& rTokenArr, long& rDocRow, ScDocument* pDoc ) :
486*cdf0e10cSrcweir         mrDocRow( rDocRow ), mbOverflow(false), mbArgError(false), mpDoc( pDoc ), mrTokenArr( rTokenArr )
487*cdf0e10cSrcweir 	{
488*cdf0e10cSrcweir 		rArg >>= maSeq;
489*cdf0e10cSrcweir 	}
490*cdf0e10cSrcweir 
491*cdf0e10cSrcweir 	void process()
492*cdf0e10cSrcweir 	{
493*cdf0e10cSrcweir 		SimpleVisitor aVisitor(mpDoc);
494*cdf0e10cSrcweir 		long nStartRow = mrDocRow;
495*cdf0e10cSrcweir 		long nRowCount = maSeq.getLength();
496*cdf0e10cSrcweir 		long nMaxColCount = 0;
497*cdf0e10cSrcweir 		const uno::Sequence< seq >* pRowArr = maSeq.getConstArray();
498*cdf0e10cSrcweir 		for ( long nRow=0; nRow<nRowCount; nRow++ )
499*cdf0e10cSrcweir 		{
500*cdf0e10cSrcweir 			long nColCount = pRowArr[nRow].getLength();
501*cdf0e10cSrcweir 			if ( nColCount > nMaxColCount )
502*cdf0e10cSrcweir 				nMaxColCount = nColCount;
503*cdf0e10cSrcweir 			const seq* pColArr = pRowArr[nRow].getConstArray();
504*cdf0e10cSrcweir 			for (long nCol=0; nCol<nColCount; nCol++)
505*cdf0e10cSrcweir 				if ( nCol <= MAXCOL && mrDocRow <= MAXROW )
506*cdf0e10cSrcweir 					aVisitor.visitElem( nCol, mrDocRow, pColArr[ nCol ] );
507*cdf0e10cSrcweir 				else
508*cdf0e10cSrcweir 					mbOverflow=true;
509*cdf0e10cSrcweir 			mrDocRow++;
510*cdf0e10cSrcweir 		}
511*cdf0e10cSrcweir 		mbArgError = aVisitor.hasArgError();
512*cdf0e10cSrcweir 		if ( nRowCount && nMaxColCount && !mbOverflow )
513*cdf0e10cSrcweir 			lcl_AddRef( mrTokenArr, nStartRow, nMaxColCount, nRowCount );
514*cdf0e10cSrcweir 	}
515*cdf0e10cSrcweir 	bool getOverflow() { return mbOverflow; }
516*cdf0e10cSrcweir 	bool getArgError() { return mbArgError; }
517*cdf0e10cSrcweir };
518*cdf0e10cSrcweir 
519*cdf0e10cSrcweir template <class T>
520*cdf0e10cSrcweir class ArrayOfArrayProc
521*cdf0e10cSrcweir {
522*cdf0e10cSrcweir public:
523*cdf0e10cSrcweir static void processSequences( ScDocument* pDoc, const uno::Any& rArg, ScTokenArray& rTokenArr,
524*cdf0e10cSrcweir 								long& rDocRow, sal_Bool& rArgErr, sal_Bool& rOverflow )
525*cdf0e10cSrcweir {
526*cdf0e10cSrcweir 	SequencesContainer< T > aContainer( rArg, rTokenArr, rDocRow, pDoc );
527*cdf0e10cSrcweir 	aContainer.process();
528*cdf0e10cSrcweir 	rArgErr = aContainer.getArgError();
529*cdf0e10cSrcweir 	rOverflow = aContainer.getOverflow();
530*cdf0e10cSrcweir }
531*cdf0e10cSrcweir };
532*cdf0e10cSrcweir 
533*cdf0e10cSrcweir uno::Any SAL_CALL ScFunctionAccess::callFunction( const rtl::OUString& aName,
534*cdf0e10cSrcweir 							const uno::Sequence<uno::Any>& aArguments )
535*cdf0e10cSrcweir 				throw(container::NoSuchElementException, lang::IllegalArgumentException,
536*cdf0e10cSrcweir 						uno::RuntimeException)
537*cdf0e10cSrcweir {
538*cdf0e10cSrcweir 	ScUnoGuard aGuard;
539*cdf0e10cSrcweir 
540*cdf0e10cSrcweir 	if (!mbValid)
541*cdf0e10cSrcweir 		throw uno::RuntimeException();
542*cdf0e10cSrcweir 
543*cdf0e10cSrcweir 	// use cached document if not in use, temporary document otherwise
544*cdf0e10cSrcweir 	//	(deleted in ScTempDocSource dtor)
545*cdf0e10cSrcweir 	ScTempDocSource aSource( aDocCache );
546*cdf0e10cSrcweir 	ScDocument* pDoc = aSource.GetDocument();
547*cdf0e10cSrcweir 	const static SCTAB nTempSheet = 1;
548*cdf0e10cSrcweir 	// Create an extra tab to contain the Function Cell
549*cdf0e10cSrcweir 	// this will allow full rows to be used.
550*cdf0e10cSrcweir 	if ( !pDoc->HasTable( nTempSheet ) )
551*cdf0e10cSrcweir 		pDoc->MakeTable( nTempSheet );
552*cdf0e10cSrcweir 
553*cdf0e10cSrcweir     /// TODO: check
554*cdf0e10cSrcweir     ScAddress aAdr;
555*cdf0e10cSrcweir     ScCompiler aCompiler(pDoc,aAdr);
556*cdf0e10cSrcweir     aCompiler.SetGrammar(pDoc->GetGrammar());
557*cdf0e10cSrcweir 	//if (!ScCompiler::IsInitialized())
558*cdf0e10cSrcweir  //       ScCompiler::InitSymbolsEnglish();
559*cdf0e10cSrcweir 
560*cdf0e10cSrcweir 	//
561*cdf0e10cSrcweir 	//	find function
562*cdf0e10cSrcweir 	//
563*cdf0e10cSrcweir 
564*cdf0e10cSrcweir 	ScTokenArray aTokenArr;
565*cdf0e10cSrcweir 	if ( !lcl_AddFunctionToken( aTokenArr, aName,aCompiler ) )
566*cdf0e10cSrcweir 	{
567*cdf0e10cSrcweir 		// function not found
568*cdf0e10cSrcweir 		throw container::NoSuchElementException();
569*cdf0e10cSrcweir 	}
570*cdf0e10cSrcweir 
571*cdf0e10cSrcweir 	//
572*cdf0e10cSrcweir 	//	set options (null date, etc.)
573*cdf0e10cSrcweir 	//
574*cdf0e10cSrcweir 
575*cdf0e10cSrcweir 	if ( pOptions )
576*cdf0e10cSrcweir 		pDoc->SetDocOptions( *pOptions );
577*cdf0e10cSrcweir 
578*cdf0e10cSrcweir 	//
579*cdf0e10cSrcweir 	//	add arguments to token array
580*cdf0e10cSrcweir 	//
581*cdf0e10cSrcweir 
582*cdf0e10cSrcweir 	sal_Bool bArgErr = sal_False;
583*cdf0e10cSrcweir 	sal_Bool bOverflow = sal_False;
584*cdf0e10cSrcweir 	long nDocRow = 0;
585*cdf0e10cSrcweir 	long nArgCount = aArguments.getLength();
586*cdf0e10cSrcweir 	const uno::Any* pArgArr = aArguments.getConstArray();
587*cdf0e10cSrcweir 
588*cdf0e10cSrcweir 	aTokenArr.AddOpCode(ocOpen);
589*cdf0e10cSrcweir 	for (long nPos=0; nPos<nArgCount; nPos++)
590*cdf0e10cSrcweir 	{
591*cdf0e10cSrcweir 		if ( nPos > 0 )
592*cdf0e10cSrcweir 			aTokenArr.AddOpCode(ocSep);
593*cdf0e10cSrcweir 
594*cdf0e10cSrcweir 		const uno::Any& rArg = pArgArr[nPos];
595*cdf0e10cSrcweir 
596*cdf0e10cSrcweir 		uno::TypeClass eClass = rArg.getValueTypeClass();
597*cdf0e10cSrcweir 		uno::Type aType = rArg.getValueType();
598*cdf0e10cSrcweir 		if ( eClass == uno::TypeClass_BYTE ||
599*cdf0e10cSrcweir 		     eClass == uno::TypeClass_BOOLEAN ||
600*cdf0e10cSrcweir 			 eClass == uno::TypeClass_SHORT ||
601*cdf0e10cSrcweir 			 eClass == uno::TypeClass_UNSIGNED_SHORT ||
602*cdf0e10cSrcweir 			 eClass == uno::TypeClass_LONG ||
603*cdf0e10cSrcweir 			 eClass == uno::TypeClass_UNSIGNED_LONG ||
604*cdf0e10cSrcweir 			 eClass == uno::TypeClass_FLOAT ||
605*cdf0e10cSrcweir 			 eClass == uno::TypeClass_DOUBLE )
606*cdf0e10cSrcweir 		{
607*cdf0e10cSrcweir 			//	#87871# accept integer types because Basic passes a floating point
608*cdf0e10cSrcweir 			//	variable as byte, short or long if it's an integer number.
609*cdf0e10cSrcweir 			double fVal = 0;
610*cdf0e10cSrcweir 			rArg >>= fVal;
611*cdf0e10cSrcweir 			aTokenArr.AddDouble( fVal );
612*cdf0e10cSrcweir 		}
613*cdf0e10cSrcweir 		else if ( eClass == uno::TypeClass_STRING )
614*cdf0e10cSrcweir 		{
615*cdf0e10cSrcweir 			rtl::OUString aUStr;
616*cdf0e10cSrcweir 			rArg >>= aUStr;
617*cdf0e10cSrcweir 			String aStr( aUStr );
618*cdf0e10cSrcweir 			aTokenArr.AddString( aStr.GetBuffer() );
619*cdf0e10cSrcweir 		}
620*cdf0e10cSrcweir 		else if ( aType.equals( getCppuType( (uno::Sequence< uno::Sequence<sal_Int16> > *)0 ) ) )
621*cdf0e10cSrcweir 		{
622*cdf0e10cSrcweir 			ArrayOfArrayProc<sal_Int16>::processSequences( pDoc, rArg, aTokenArr, nDocRow, bArgErr, bOverflow );
623*cdf0e10cSrcweir 		}
624*cdf0e10cSrcweir 		else if ( aType.equals( getCppuType( (uno::Sequence< uno::Sequence<sal_Int32> > *)0 ) ) )
625*cdf0e10cSrcweir 		{
626*cdf0e10cSrcweir 			ArrayOfArrayProc<sal_Int32>::processSequences( pDoc, rArg, aTokenArr, nDocRow, bArgErr, bOverflow );
627*cdf0e10cSrcweir 		}
628*cdf0e10cSrcweir 		else if ( aType.equals( getCppuType( (uno::Sequence< uno::Sequence<double> > *)0 ) ) )
629*cdf0e10cSrcweir 		{
630*cdf0e10cSrcweir 			ArrayOfArrayProc<double>::processSequences( pDoc, rArg, aTokenArr, nDocRow, bArgErr, bOverflow );
631*cdf0e10cSrcweir 		}
632*cdf0e10cSrcweir 		else if ( aType.equals( getCppuType( (uno::Sequence< uno::Sequence<rtl::OUString> > *)0 ) ) )
633*cdf0e10cSrcweir 		{
634*cdf0e10cSrcweir 			ArrayOfArrayProc<rtl::OUString>::processSequences( pDoc, rArg, aTokenArr, nDocRow, bArgErr, bOverflow );
635*cdf0e10cSrcweir 		}
636*cdf0e10cSrcweir 		else if ( aType.equals( getCppuType( (uno::Sequence< uno::Sequence<uno::Any> > *)0 ) ) )
637*cdf0e10cSrcweir 		{
638*cdf0e10cSrcweir 			ArrayOfArrayProc<uno::Any>::processSequences( pDoc, rArg, aTokenArr, nDocRow, bArgErr, bOverflow );
639*cdf0e10cSrcweir 		}
640*cdf0e10cSrcweir 		else if ( aType.equals( getCppuType( (uno::Reference<table::XCellRange>*)0 ) ) )
641*cdf0e10cSrcweir 		{
642*cdf0e10cSrcweir 			// currently, only our own cell ranges are supported
643*cdf0e10cSrcweir 
644*cdf0e10cSrcweir             uno::Reference<table::XCellRange> xRange(rArg, uno::UNO_QUERY);
645*cdf0e10cSrcweir 			ScCellRangesBase* pImpl = ScCellRangesBase::getImplementation( xRange );
646*cdf0e10cSrcweir 			if ( pImpl )
647*cdf0e10cSrcweir 			{
648*cdf0e10cSrcweir 				ScDocument* pSrcDoc = pImpl->GetDocument();
649*cdf0e10cSrcweir 				const ScRangeList& rRanges = pImpl->GetRangeList();
650*cdf0e10cSrcweir 				if ( pSrcDoc && rRanges.Count() == 1 )
651*cdf0e10cSrcweir 				{
652*cdf0e10cSrcweir 					ScRange aSrcRange = *rRanges.GetObject(0);
653*cdf0e10cSrcweir 
654*cdf0e10cSrcweir 					long nStartRow = nDocRow;
655*cdf0e10cSrcweir 					long nColCount = aSrcRange.aEnd.Col() - aSrcRange.aStart.Col() + 1;
656*cdf0e10cSrcweir 					long nRowCount = aSrcRange.aEnd.Row() - aSrcRange.aStart.Row() + 1;
657*cdf0e10cSrcweir 
658*cdf0e10cSrcweir 					if ( nStartRow + nRowCount > MAXROWCOUNT )
659*cdf0e10cSrcweir 						bOverflow = sal_True;
660*cdf0e10cSrcweir 					else
661*cdf0e10cSrcweir 					{
662*cdf0e10cSrcweir 						// copy data
663*cdf0e10cSrcweir 						if ( !lcl_CopyData( pSrcDoc, aSrcRange, pDoc, ScAddress( 0, (SCROW)nDocRow, 0 ) ) )
664*cdf0e10cSrcweir 							bOverflow = sal_True;
665*cdf0e10cSrcweir 					}
666*cdf0e10cSrcweir 
667*cdf0e10cSrcweir 					nDocRow += nRowCount;
668*cdf0e10cSrcweir 					if ( !bOverflow )
669*cdf0e10cSrcweir 						lcl_AddRef( aTokenArr, nStartRow, nColCount, nRowCount );
670*cdf0e10cSrcweir 				}
671*cdf0e10cSrcweir 				else
672*cdf0e10cSrcweir 					bArgErr = sal_True;
673*cdf0e10cSrcweir 			}
674*cdf0e10cSrcweir 			else
675*cdf0e10cSrcweir 				bArgErr = sal_True;
676*cdf0e10cSrcweir 		}
677*cdf0e10cSrcweir 		else
678*cdf0e10cSrcweir 			bArgErr = sal_True;					// invalid type
679*cdf0e10cSrcweir 	}
680*cdf0e10cSrcweir 	aTokenArr.AddOpCode(ocClose);
681*cdf0e10cSrcweir 	aTokenArr.AddOpCode(ocStop);
682*cdf0e10cSrcweir 
683*cdf0e10cSrcweir 	//
684*cdf0e10cSrcweir 	//	execute formula
685*cdf0e10cSrcweir 	//
686*cdf0e10cSrcweir 
687*cdf0e10cSrcweir 	uno::Any aRet;
688*cdf0e10cSrcweir 	if ( !bArgErr && !bOverflow && nDocRow <= MAXROWCOUNT )
689*cdf0e10cSrcweir 	{
690*cdf0e10cSrcweir 		ScAddress aFormulaPos( 0, 0, nTempSheet );
691*cdf0e10cSrcweir         // GRAM_PODF_A1 doesn't really matter for the token array but fits with
692*cdf0e10cSrcweir         // other API compatibility grammars.
693*cdf0e10cSrcweir         ScFormulaCell* pFormula = new ScFormulaCell( pDoc, aFormulaPos,
694*cdf0e10cSrcweir                 &aTokenArr, formula::FormulaGrammar::GRAM_PODF_A1, (sal_uInt8)(mbArray ? MM_FORMULA : MM_NONE) );
695*cdf0e10cSrcweir 		pDoc->PutCell( aFormulaPos, pFormula );		//! necessary?
696*cdf0e10cSrcweir 
697*cdf0e10cSrcweir 		//	call GetMatrix before GetErrCode because GetMatrix always recalculates
698*cdf0e10cSrcweir 		//	if there is no matrix result
699*cdf0e10cSrcweir 
700*cdf0e10cSrcweir 		const ScMatrix* pMat = mbArray ? pFormula->GetMatrix() : 0;
701*cdf0e10cSrcweir 		sal_uInt16 nErrCode = pFormula->GetErrCode();
702*cdf0e10cSrcweir 		if ( nErrCode == 0 )
703*cdf0e10cSrcweir 		{
704*cdf0e10cSrcweir 			if ( pMat )
705*cdf0e10cSrcweir 			{
706*cdf0e10cSrcweir 				// array result
707*cdf0e10cSrcweir 				ScRangeToSequence::FillMixedArray( aRet, pMat );
708*cdf0e10cSrcweir 			}
709*cdf0e10cSrcweir 			else if ( pFormula->IsValue() )
710*cdf0e10cSrcweir 			{
711*cdf0e10cSrcweir 				// numeric value
712*cdf0e10cSrcweir 				aRet <<= (double) pFormula->GetValue();
713*cdf0e10cSrcweir 			}
714*cdf0e10cSrcweir 			else
715*cdf0e10cSrcweir 			{
716*cdf0e10cSrcweir 				// string result
717*cdf0e10cSrcweir 				String aStrVal;
718*cdf0e10cSrcweir 				pFormula->GetString( aStrVal );
719*cdf0e10cSrcweir 				aRet <<= rtl::OUString( aStrVal );
720*cdf0e10cSrcweir 			}
721*cdf0e10cSrcweir 		}
722*cdf0e10cSrcweir 		else if ( nErrCode == NOTAVAILABLE )
723*cdf0e10cSrcweir 		{
724*cdf0e10cSrcweir 			// #N/A: leave result empty, no exception
725*cdf0e10cSrcweir 		}
726*cdf0e10cSrcweir 		else
727*cdf0e10cSrcweir 		{
728*cdf0e10cSrcweir 			//	any other error: IllegalArgumentException
729*cdf0e10cSrcweir 			bArgErr = sal_True;
730*cdf0e10cSrcweir 		}
731*cdf0e10cSrcweir 
732*cdf0e10cSrcweir 		pDoc->DeleteAreaTab( 0, 0, MAXCOL, MAXROW, 0, IDF_ALL );
733*cdf0e10cSrcweir 		pDoc->DeleteAreaTab( 0, 0, 0, 0, nTempSheet, IDF_ALL );
734*cdf0e10cSrcweir 	}
735*cdf0e10cSrcweir 
736*cdf0e10cSrcweir 	if (bOverflow)
737*cdf0e10cSrcweir 		throw uno::RuntimeException();
738*cdf0e10cSrcweir 
739*cdf0e10cSrcweir 	if (bArgErr)
740*cdf0e10cSrcweir 		throw lang::IllegalArgumentException();
741*cdf0e10cSrcweir 
742*cdf0e10cSrcweir 	return aRet;
743*cdf0e10cSrcweir }
744*cdf0e10cSrcweir 
745*cdf0e10cSrcweir 
746