1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <cppuhelper/supportsservice.hxx>
21 #include <sfx2/app.hxx>
22 #include <svl/itemprop.hxx>
23 #include <svl/sharedstringpool.hxx>
24 #include <unotools/charclass.hxx>
25 #include <osl/diagnose.h>
26 #include <vcl/svapp.hxx>
28 #include <funcuno.hxx>
29 #include <miscuno.hxx>
30 #include <cellsuno.hxx>
32 #include <document.hxx>
33 #include <compiler.hxx>
34 #include <formula/errorcodes.hxx>
35 #include <callform.hxx>
36 #include <addincol.hxx>
37 #include <rangeseq.hxx>
38 #include <formulacell.hxx>
39 #include <docoptio.hxx>
41 #include <markdata.hxx>
42 #include <patattr.hxx>
43 #include <docpool.hxx>
45 #include <clipparam.hxx>
46 #include <stringutil.hxx>
47 #include <tokenarray.hxx>
48 #include <unonames.hxx>
51 using namespace com::sun::star
;
53 // registered as implementation for service FunctionAccess,
54 // also supports service SpreadsheetDocumentSettings (to set null date etc.)
56 constexpr OUString SCFUNCTIONACCESS_SERVICE
= u
"com.sun.star.sheet.FunctionAccess"_ustr
;
57 constexpr OUString SCDOCSETTINGS_SERVICE
= u
"com.sun.star.sheet.SpreadsheetDocumentSettings"_ustr
;
59 // helper to use cached document if not in use, temporary document otherwise
66 ScTempDocCache
& rCache
;
67 ScDocumentUniquePtr pTempDoc
;
69 static ScDocument
* CreateDocument(); // create and initialize doc
72 explicit ScTempDocSource( ScTempDocCache
& rDocCache
);
73 ~ScTempDocSource() COVERITY_NOEXCEPT_FALSE
;
75 ScDocument
* GetDocument();
80 ScDocument
* ScTempDocSource::CreateDocument()
82 ScDocument
* pDoc
= new ScDocument( SCDOCMODE_FUNCTIONACCESS
);
87 ScTempDocSource::ScTempDocSource( ScTempDocCache
& rDocCache
) :
90 if ( rCache
.IsInUse() )
91 pTempDoc
.reset(CreateDocument());
94 rCache
.SetInUse( true );
95 if ( !rCache
.GetDocument() )
96 rCache
.SetDocument( CreateDocument() );
100 ScTempDocSource::~ScTempDocSource() COVERITY_NOEXCEPT_FALSE
103 rCache
.SetInUse( false );
106 ScDocument
* ScTempDocSource::GetDocument()
109 return pTempDoc
.get();
111 return rCache
.GetDocument();
114 ScTempDocCache::ScTempDocCache()
119 void ScTempDocCache::SetDocument( ScDocument
* pNew
)
121 OSL_ENSURE(!xDoc
, "ScTempDocCache::SetDocument: already set");
125 void ScTempDocCache::Clear()
127 OSL_ENSURE( !bInUse
, "ScTempDocCache::Clear: bInUse" );
131 // copy results from one document into another
132 //! merge this with ScAreaLink::Refresh
133 //! copy directly without a clipboard document?
135 static bool lcl_CopyData( ScDocument
* pSrcDoc
, const ScRange
& rSrcRange
,
136 ScDocument
* pDestDoc
, const ScAddress
& rDestPos
)
138 SCTAB nSrcTab
= rSrcRange
.aStart
.Tab();
139 SCTAB nDestTab
= rDestPos
.Tab();
141 ScRange
aNewRange( rDestPos
, ScAddress(
142 rSrcRange
.aEnd
.Col() - rSrcRange
.aStart
.Col() + rDestPos
.Col(),
143 rSrcRange
.aEnd
.Row() - rSrcRange
.aStart
.Row() + rDestPos
.Row(),
146 ScDocumentUniquePtr
pClipDoc(new ScDocument( SCDOCMODE_CLIP
));
147 ScMarkData
aSourceMark(pSrcDoc
->GetSheetLimits());
148 aSourceMark
.SelectOneTable( nSrcTab
); // for CopyToClip
149 aSourceMark
.SetMarkArea( rSrcRange
);
150 ScClipParam
aClipParam(rSrcRange
, false);
151 pSrcDoc
->CopyToClip(aClipParam
, pClipDoc
.get(), &aSourceMark
, false, false);
153 if ( pClipDoc
->HasAttrib( 0,0,nSrcTab
, pClipDoc
->MaxCol(), pClipDoc
->MaxRow(),nSrcTab
,
154 HasAttrFlags::Merged
| HasAttrFlags::Overlapped
) )
156 ScPatternAttr
aPattern(pSrcDoc
->getCellAttributeHelper());
157 aPattern
.GetItemSet().Put( ScMergeAttr() ); // Defaults
158 aPattern
.GetItemSet().Put( ScMergeFlagAttr() );
159 pClipDoc
->ApplyPatternAreaTab( 0,0, pClipDoc
->MaxCol(), pClipDoc
->MaxRow(), nSrcTab
, aPattern
);
162 ScMarkData
aDestMark(pDestDoc
->GetSheetLimits());
163 aDestMark
.SelectOneTable( nDestTab
);
164 aDestMark
.SetMarkArea( aNewRange
);
165 pDestDoc
->CopyFromClip( aNewRange
, aDestMark
, InsertDeleteFlags::ALL
& ~InsertDeleteFlags::FORMULA
, nullptr, pClipDoc
.get(), false );
172 std::span
<const SfxItemPropertyMapEntry
> GetPropertyMap()
174 static const SfxItemPropertyMapEntry aMap
[] =
176 { SC_UNO_CALCASSHOWN
, PROP_UNO_CALCASSHOWN
, cppu::UnoType
<bool>::get(), 0, 0},
177 { SC_UNO_DEFTABSTOP
, PROP_UNO_DEFTABSTOP
, cppu::UnoType
<sal_Int16
>::get(), 0, 0},
178 { SC_UNO_IGNORECASE
, PROP_UNO_IGNORECASE
, cppu::UnoType
<bool>::get(), 0, 0},
179 { SC_UNO_ITERENABLED
, PROP_UNO_ITERENABLED
, cppu::UnoType
<bool>::get(), 0, 0},
180 { SC_UNO_ITERCOUNT
, PROP_UNO_ITERCOUNT
, cppu::UnoType
<sal_Int32
>::get(), 0, 0},
181 { SC_UNO_ITEREPSILON
, PROP_UNO_ITEREPSILON
, cppu::UnoType
<double>::get(), 0, 0},
182 { SC_UNO_LOOKUPLABELS
, PROP_UNO_LOOKUPLABELS
, cppu::UnoType
<bool>::get(), 0, 0},
183 { SC_UNO_MATCHWHOLE
, PROP_UNO_MATCHWHOLE
, cppu::UnoType
<bool>::get(), 0, 0},
184 { SC_UNO_NULLDATE
, PROP_UNO_NULLDATE
, cppu::UnoType
<util::Date
>::get(), 0, 0},
185 // SpreadsheetDocumentSettings supports "SpellOnline" so we must claim to support this here too
186 { SC_UNO_SPELLONLINE
, 0 , cppu::UnoType
<bool>::get(), 0, 0},
187 { SC_UNO_STANDARDDEC
, PROP_UNO_STANDARDDEC
, cppu::UnoType
<sal_Int16
>::get(), 0, 0},
188 { SC_UNO_REGEXENABLED
, PROP_UNO_REGEXENABLED
, cppu::UnoType
<bool>::get(), 0, 0},
189 { SC_UNO_WILDCARDSENABLED
, PROP_UNO_WILDCARDSENABLED
, cppu::UnoType
<bool>::get(), 0, 0},
195 ScFunctionAccess::ScFunctionAccess() :
196 aPropertyMap( GetPropertyMap() ),
197 mbArray( true ), // default according to behaviour of older Office versions
199 mbSpellOnline( false )
201 StartListening( *SfxGetpApp() ); // for SfxHintId::Deinitializing
204 ScFunctionAccess::~ScFunctionAccess()
208 // SfxBroadcaster::RemoveListener checks DBG_TESTSOLARMUTEX():
214 void ScFunctionAccess::Notify( SfxBroadcaster
&, const SfxHint
& rHint
)
216 if ( rHint
.GetId() == SfxHintId::Deinitializing
)
218 // document must not be used anymore
224 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
225 ScFunctionAccess_get_implementation(css::uno::XComponentContext
*, css::uno::Sequence
<css::uno::Any
> const &)
227 SolarMutexGuard aGuard
;
229 return cppu::acquire(new ScFunctionAccess
);
233 OUString SAL_CALL
ScFunctionAccess::getImplementationName()
235 return u
"stardiv.StarCalc.ScFunctionAccess"_ustr
;
238 sal_Bool SAL_CALL
ScFunctionAccess::supportsService( const OUString
& rServiceName
)
240 return cppu::supportsService(this, rServiceName
);
243 uno::Sequence
<OUString
> SAL_CALL
ScFunctionAccess::getSupportedServiceNames()
245 return {SCFUNCTIONACCESS_SERVICE
, SCDOCSETTINGS_SERVICE
};
248 // XPropertySet (document settings)
250 uno::Reference
<beans::XPropertySetInfo
> SAL_CALL
ScFunctionAccess::getPropertySetInfo()
252 SolarMutexGuard aGuard
;
253 static uno::Reference
<beans::XPropertySetInfo
> aRef(
254 new SfxItemPropertySetInfo( aPropertyMap
));
258 void SAL_CALL
ScFunctionAccess::setPropertyValue(
259 const OUString
& aPropertyName
, const uno::Any
& aValue
)
261 SolarMutexGuard aGuard
;
263 if ( aPropertyName
== "IsArrayFunction" )
265 if( !(aValue
>>= mbArray
) )
266 throw lang::IllegalArgumentException();
268 else if (aPropertyName
== SC_UNO_SPELLONLINE
)
270 // Allow this property because SpreadsheetDocumentSettings lists it
271 if( !(aValue
>>= mbSpellOnline
) )
272 throw lang::IllegalArgumentException();
277 pOptions
.reset( new ScDocOptions() );
279 // options aren't initialized from configuration - always get the same default behaviour
280 bool bDone
= ScDocOptionsHelper::setPropertyValue( *pOptions
, aPropertyMap
, aPropertyName
, aValue
);
282 throw beans::UnknownPropertyException(aPropertyName
);
286 uno::Any SAL_CALL
ScFunctionAccess::getPropertyValue( const OUString
& aPropertyName
)
288 SolarMutexGuard aGuard
;
290 if ( aPropertyName
== "IsArrayFunction" )
291 return uno::Any( mbArray
);
293 // Allow this property because SpreadsheetDocumentSettings lists it
294 if (aPropertyName
== SC_UNO_SPELLONLINE
)
295 return uno::Any(mbSpellOnline
);
298 pOptions
.reset( new ScDocOptions() );
300 // options aren't initialized from configuration - always get the same default behaviour
302 return ScDocOptionsHelper::getPropertyValue( *pOptions
, aPropertyMap
, aPropertyName
);
305 SC_IMPL_DUMMY_PROPERTY_LISTENER( ScFunctionAccess
)
309 static bool lcl_AddFunctionToken( ScTokenArray
& rArray
, const OUString
& rName
,const ScCompiler
& rCompiler
)
311 // function names are always case-insensitive
312 OUString aUpper
= ScGlobal::getCharClass().uppercase(rName
);
314 // same options as in ScCompiler::IsOpCode:
315 // 1. built-in function name
317 OpCode eOp
= rCompiler
.GetEnglishOpCode( aUpper
);
320 rArray
.AddOpCode( eOp
);
324 // 2. old add in functions
326 if (ScGlobal::GetLegacyFuncCollection()->findByName(aUpper
))
328 rArray
.AddExternal(aUpper
.getStr());
332 // 3. new (uno) add in functions
335 ScGlobal::GetAddInCollection()->FindFunction(aUpper
, false);
336 if (!aIntName
.isEmpty())
338 rArray
.AddExternal(aIntName
.getStr()); // international name
342 return false; // no valid function name
345 static void lcl_AddRef( ScTokenArray
& rArray
, sal_Int32 nStartRow
, sal_Int32 nColCount
, sal_Int32 nRowCount
)
347 ScComplexRefData aRef
;
348 aRef
.InitRange(ScRange(0,nStartRow
,0,nColCount
-1,nStartRow
+nRowCount
-1,0));
349 rArray
.AddDoubleReference(aRef
);
360 explicit SimpleVisitor( ScDocument
* pDoc
) : mbArgError( false ), mpDoc( pDoc
) {}
361 // could possibly just get away with JUST the following overload
362 // 1) virtual void visitElem( long& nCol, long& nRow, const double& elem )
363 // 2) virtual void visitElem( long& nCol, long& nRow, const OUString& elem )
364 // 3) virtual void visitElem( long& nCol, long& nRow, const uno::Any& elem )
365 // the other types methods are here just to reflect the orig code and for
368 void visitElem( sal_Int32 nCol
, sal_Int32 nRow
, sal_Int16 elem
)
370 mpDoc
->SetValue( static_cast<SCCOL
>(nCol
), static_cast<SCROW
>(nRow
), 0, elem
);
372 void visitElem( sal_Int32 nCol
, sal_Int32 nRow
, sal_Int32 elem
)
374 mpDoc
->SetValue( static_cast<SCCOL
>(nCol
), static_cast<SCROW
>(nRow
), 0, elem
);
376 void visitElem( sal_Int32 nCol
, sal_Int32 nRow
, const double& elem
)
378 mpDoc
->SetValue( static_cast<SCCOL
>(nCol
), static_cast<SCROW
>(nRow
), 0, elem
);
380 void visitElem( sal_Int32 nCol
, sal_Int32 nRow
, const OUString
& elem
)
384 ScSetStringParam aParam
;
385 aParam
.setTextInput();
386 mpDoc
->SetString(ScAddress(nCol
,nRow
,0), elem
, &aParam
);
389 void visitElem( sal_Int32 nCol
, sal_Int32 nRow
, const uno::Any
& rElement
)
391 uno::TypeClass eElemClass
= rElement
.getValueTypeClass();
392 if ( eElemClass
== uno::TypeClass_VOID
)
396 else if ( eElemClass
== uno::TypeClass_BYTE
||
397 eElemClass
== uno::TypeClass_SHORT
||
398 eElemClass
== uno::TypeClass_UNSIGNED_SHORT
||
399 eElemClass
== uno::TypeClass_LONG
||
400 eElemClass
== uno::TypeClass_UNSIGNED_LONG
||
401 eElemClass
== uno::TypeClass_FLOAT
||
402 eElemClass
== uno::TypeClass_DOUBLE
)
404 // accept integer types because Basic passes a floating point
405 // variable as byte, short or long if it's an integer number.
408 visitElem( nCol
, nRow
, fVal
);
410 else if ( eElemClass
== uno::TypeClass_STRING
)
414 visitElem( nCol
, nRow
, aUStr
);
419 bool hasArgError() const { return mbArgError
; }
422 template< class seq
>
423 class SequencesContainer
425 uno::Sequence
< uno::Sequence
< seq
> > maSeq
;
431 ScTokenArray
& mrTokenArr
;
434 SequencesContainer( const uno::Any
& rArg
, ScTokenArray
& rTokenArr
, sal_Int32
& rDocRow
, ScDocument
* pDoc
) :
435 mrDocRow( rDocRow
), mbOverflow(false), mbArgError(false), mpDoc( pDoc
), mrTokenArr( rTokenArr
)
442 SimpleVisitor
aVisitor(mpDoc
);
443 sal_Int32 nStartRow
= mrDocRow
;
444 sal_Int32 nRowCount
= maSeq
.getLength();
445 sal_Int32 nMaxColCount
= 0;
446 for (const uno::Sequence
<seq
>& rRow
: maSeq
)
448 sal_Int32 nColCount
= rRow
.getLength();
449 if ( nColCount
> nMaxColCount
)
450 nMaxColCount
= nColCount
;
451 for (sal_Int32 nCol
=0; nCol
<nColCount
; nCol
++)
452 if ( nCol
<= mpDoc
->MaxCol() && mrDocRow
<= mpDoc
->MaxRow() )
453 aVisitor
.visitElem( nCol
, mrDocRow
, rRow
[ nCol
] );
458 mbArgError
= aVisitor
.hasArgError();
461 if (nRowCount
&& nMaxColCount
)
462 lcl_AddRef( mrTokenArr
, nStartRow
, nMaxColCount
, nRowCount
);
463 else if (nRowCount
== 1 && !nMaxColCount
)
464 // Empty Sequence<Sequence<Any>> is omitted argument.
465 mrTokenArr
.AddOpCode( ocMissing
);
468 bool getOverflow() const { return mbOverflow
; }
469 bool getArgError() const { return mbArgError
; }
473 class ArrayOfArrayProc
476 static void processSequences( ScDocument
* pDoc
, const uno::Any
& rArg
, ScTokenArray
& rTokenArr
,
477 sal_Int32
& rDocRow
, bool& rArgErr
, bool& rOverflow
)
479 SequencesContainer
< T
> aContainer( rArg
, rTokenArr
, rDocRow
, pDoc
);
480 aContainer
.process();
481 rArgErr
= aContainer
.getArgError();
482 rOverflow
= aContainer
.getOverflow();
488 uno::Any SAL_CALL
ScFunctionAccess::callFunction( const OUString
& aName
,
489 const uno::Sequence
<uno::Any
>& aArguments
)
491 SolarMutexGuard aGuard
;
494 throw uno::RuntimeException();
496 // use cached document if not in use, temporary document otherwise
497 // (deleted in ScTempDocSource dtor)
498 ScTempDocSource
aSource( aDocCache
);
499 ScDocument
* pDoc
= aSource
.GetDocument();
500 const static SCTAB nTempSheet
= 1;
501 // Create an extra tab to contain the Function Cell
502 // this will allow full rows to be used.
503 if ( !pDoc
->HasTable( nTempSheet
) )
504 pDoc
->MakeTable( nTempSheet
);
508 ScCompiler
aCompiler(*pDoc
, aAdr
, pDoc
->GetGrammar());
512 ScTokenArray
aTokenArr(*pDoc
);
513 if ( !lcl_AddFunctionToken( aTokenArr
, aName
,aCompiler
) )
515 // function not found
516 throw container::NoSuchElementException();
519 // set options (null date, etc.)
522 pDoc
->SetDocOptions( *pOptions
);
524 // add arguments to token array
526 bool bArgErr
= false;
527 bool bOverflow
= false;
528 sal_Int32 nDocRow
= 0;
529 tools::Long nArgCount
= aArguments
.getLength();
530 const uno::Any
* pArgArr
= aArguments
.getConstArray();
532 svl::SharedStringPool
& rSPool
= pDoc
->GetSharedStringPool();
533 aTokenArr
.AddOpCode(ocOpen
);
534 for (tools::Long nPos
=0; nPos
<nArgCount
; nPos
++)
537 aTokenArr
.AddOpCode(ocSep
);
539 const uno::Any
& rArg
= pArgArr
[nPos
];
541 uno::TypeClass eClass
= rArg
.getValueTypeClass();
542 const uno::Type
& aType
= rArg
.getValueType();
543 if ( eClass
== uno::TypeClass_BYTE
||
544 eClass
== uno::TypeClass_BOOLEAN
||
545 eClass
== uno::TypeClass_SHORT
||
546 eClass
== uno::TypeClass_UNSIGNED_SHORT
||
547 eClass
== uno::TypeClass_LONG
||
548 eClass
== uno::TypeClass_UNSIGNED_LONG
||
549 eClass
== uno::TypeClass_FLOAT
||
550 eClass
== uno::TypeClass_DOUBLE
)
552 // accept integer types because Basic passes a floating point
553 // variable as byte, short or long if it's an integer number.
556 aTokenArr
.AddDouble( fVal
);
558 else if ( eClass
== uno::TypeClass_STRING
)
562 aTokenArr
.AddString(rSPool
.intern(aUStr
));
564 else if ( aType
.equals( cppu::UnoType
<uno::Sequence
< uno::Sequence
<sal_Int16
> >>::get() ) )
566 ArrayOfArrayProc
<sal_Int16
>::processSequences( pDoc
, rArg
, aTokenArr
, nDocRow
, bArgErr
, bOverflow
);
568 else if ( aType
.equals( cppu::UnoType
<uno::Sequence
< uno::Sequence
<sal_Int32
> >>::get() ) )
570 ArrayOfArrayProc
<sal_Int32
>::processSequences( pDoc
, rArg
, aTokenArr
, nDocRow
, bArgErr
, bOverflow
);
572 else if ( aType
.equals( cppu::UnoType
<uno::Sequence
< uno::Sequence
<double> >>::get() ) )
574 ArrayOfArrayProc
<double>::processSequences( pDoc
, rArg
, aTokenArr
, nDocRow
, bArgErr
, bOverflow
);
576 else if ( aType
.equals( cppu::UnoType
<uno::Sequence
< uno::Sequence
<OUString
> >>::get() ) )
578 ArrayOfArrayProc
<OUString
>::processSequences( pDoc
, rArg
, aTokenArr
, nDocRow
, bArgErr
, bOverflow
);
580 else if ( aType
.equals( cppu::UnoType
<uno::Sequence
< uno::Sequence
<uno::Any
> >>::get() ) )
582 ArrayOfArrayProc
<uno::Any
>::processSequences( pDoc
, rArg
, aTokenArr
, nDocRow
, bArgErr
, bOverflow
);
584 else if (uno::Reference
<table::XCellRange
> xRange
; rArg
>>= xRange
)
586 // currently, only our own cell ranges are supported
588 ScCellRangesBase
* pImpl
= dynamic_cast<ScCellRangesBase
*>( xRange
.get() );
591 ScDocument
* pSrcDoc
= pImpl
->GetDocument();
592 const ScRangeList
& rRanges
= pImpl
->GetRangeList();
593 if ( pSrcDoc
&& rRanges
.size() == 1 )
595 ScRange
const & rSrcRange
= rRanges
[ 0 ];
597 sal_Int32 nStartRow
= nDocRow
;
598 sal_Int32 nColCount
= rSrcRange
.aEnd
.Col() - rSrcRange
.aStart
.Col() + 1;
599 sal_Int32 nRowCount
= rSrcRange
.aEnd
.Row() - rSrcRange
.aStart
.Row() + 1;
601 if ( nStartRow
+ nRowCount
> pDoc
->GetSheetLimits().GetMaxRowCount() )
606 if ( !lcl_CopyData( pSrcDoc
, rSrcRange
, pDoc
, ScAddress( 0, static_cast<SCROW
>(nDocRow
), 0 ) ) )
610 nDocRow
+= nRowCount
;
612 lcl_AddRef( aTokenArr
, nStartRow
, nColCount
, nRowCount
);
621 bArgErr
= true; // invalid type
623 aTokenArr
.AddOpCode(ocClose
);
624 aTokenArr
.AddOpCode(ocStop
);
629 if ( !bArgErr
&& !bOverflow
&& nDocRow
<= pDoc
->GetSheetLimits().GetMaxRowCount() )
631 ScAddress
aFormulaPos( 0, 0, nTempSheet
);
632 // GRAM_API doesn't really matter for the token array but fits with
633 // other API compatibility grammars.
634 ScFormulaCell
* pFormula
= new ScFormulaCell(
635 *pDoc
, aFormulaPos
, aTokenArr
, formula::FormulaGrammar::GRAM_API
,
636 mbArray
? ScMatrixMode::Formula
: ScMatrixMode::NONE
);
637 pFormula
= pDoc
->SetFormulaCell(aFormulaPos
, pFormula
);
638 if (mbArray
&& pFormula
)
639 pFormula
->SetMatColsRows(1,1); // the cell dimensions (only one cell)
641 // call GetMatrix before GetErrCode because GetMatrix always recalculates
642 // if there is no matrix result
644 const ScMatrix
* pMat
= (mbArray
&& pFormula
) ? pFormula
->GetMatrix() : nullptr;
645 FormulaError nErrCode
= pFormula
? pFormula
->GetErrCode() : FormulaError::IllegalArgument
;
646 if ( nErrCode
== FormulaError::NONE
)
651 ScRangeToSequence::FillMixedArray( aRet
, pMat
);
653 else if ( pFormula
->IsValue() )
656 aRet
<<= pFormula
->GetValue();
661 OUString aStrVal
= pFormula
->GetString().getString();
665 else if ( nErrCode
== FormulaError::NotAvailable
)
667 // #N/A: leave result empty, no exception
671 // any other error: IllegalArgumentException
675 pDoc
->DeleteAreaTab( 0, 0, pDoc
->MaxCol(), pDoc
->MaxRow(), 0, InsertDeleteFlags::ALL
);
676 pDoc
->DeleteAreaTab( 0, 0, 0, 0, nTempSheet
, InsertDeleteFlags::ALL
);
680 throw uno::RuntimeException();
683 throw lang::IllegalArgumentException();
688 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */