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