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 <config_features.h>
22 #include <interpre.hxx>
24 #include <sal/log.hxx>
25 #include <o3tl/safeint.hxx>
26 #include <rtl/math.hxx>
27 #include <sfx2/app.hxx>
28 #include <sfx2/objsh.hxx>
29 #include <basic/sbmeth.hxx>
30 #include <basic/sbmod.hxx>
31 #include <basic/sbstar.hxx>
32 #include <basic/sbx.hxx>
33 #include <basic/sbxobj.hxx>
34 #include <basic/sbuno.hxx>
35 #include <osl/thread.h>
36 #include <svl/numformat.hxx>
37 #include <svl/zforlist.hxx>
38 #include <svl/sharedstringpool.hxx>
39 #include <unotools/charclass.hxx>
43 #include <com/sun/star/table/XCellRange.hpp>
44 #include <com/sun/star/script/XInvocation.hpp>
45 #include <com/sun/star/sheet/XSheetCellRange.hpp>
49 #include <formulacell.hxx>
50 #include <callform.hxx>
51 #include <addincol.hxx>
52 #include <document.hxx>
53 #include <dociter.hxx>
55 #include <docoptio.hxx>
56 #include <scmatrix.hxx>
57 #include <adiasync.hxx>
58 #include <cellsuno.hxx>
60 #include <rangeseq.hxx>
61 #include <addinlis.hxx>
62 #include <jumpmatrix.hxx>
63 #include <parclass.hxx>
64 #include <externalrefmgr.hxx>
65 #include <formula/FormulaCompiler.hxx>
66 #include <macromgr.hxx>
67 #include <doubleref.hxx>
68 #include <queryparam.hxx>
69 #include <tokenarray.hxx>
70 #include <compiler.hxx>
74 #include <basic/basmgr.hxx>
75 #include <vbahelper/vbaaccesshelper.hxx>
78 using namespace com::sun::star
;
79 using namespace formula
;
80 using ::std::unique_ptr
;
82 #define ADDIN_MAXSTRLEN 256
84 thread_local
std::unique_ptr
<ScTokenStack
> ScInterpreter::pGlobalStack
;
85 thread_local
bool ScInterpreter::bGlobalStackInUse
= false;
87 // document access functions
89 void ScInterpreter::ReplaceCell( ScAddress
& rPos
)
91 size_t ListSize
= mrDoc
.m_TableOpList
.size();
92 for ( size_t i
= 0; i
< ListSize
; ++i
)
94 ScInterpreterTableOpParams
*const pTOp
= mrDoc
.m_TableOpList
[ i
];
95 if ( rPos
== pTOp
->aOld1
)
100 else if ( rPos
== pTOp
->aOld2
)
108 bool ScInterpreter::IsTableOpInRange( const ScRange
& rRange
)
110 if ( rRange
.aStart
== rRange
.aEnd
)
111 return false; // not considered to be a range in TableOp sense
113 // we can't replace a single cell in a range
114 size_t ListSize
= mrDoc
.m_TableOpList
.size();
115 for ( size_t i
= 0; i
< ListSize
; ++i
)
117 ScInterpreterTableOpParams
*const pTOp
= mrDoc
.m_TableOpList
[ i
];
118 if ( rRange
.Contains( pTOp
->aOld1
) )
120 if ( rRange
.Contains( pTOp
->aOld2
) )
126 sal_uInt32
ScInterpreter::GetCellNumberFormat( const ScAddress
& rPos
, ScRefCellValue
& rCell
)
132 nFormat
= mrDoc
.GetNumberFormat( mrContext
, rPos
);
133 nErr
= FormulaError::NONE
;
137 if (rCell
.getType() == CELLTYPE_FORMULA
)
138 nErr
= rCell
.getFormula()->GetErrCode();
140 nErr
= FormulaError::NONE
;
141 nFormat
= mrDoc
.GetNumberFormat( mrContext
, rPos
);
148 /// Only ValueCell, formula cells already store the result rounded.
149 double ScInterpreter::GetValueCellValue( const ScAddress
& rPos
, double fOrig
)
151 if ( bCalcAsShown
&& fOrig
!= 0.0 )
153 sal_uInt32 nFormat
= mrDoc
.GetNumberFormat( mrContext
, rPos
);
154 fOrig
= mrDoc
.RoundValueAsShown( fOrig
, nFormat
, &mrContext
);
159 FormulaError
ScInterpreter::GetCellErrCode( const ScRefCellValue
& rCell
)
161 return rCell
.getType() == CELLTYPE_FORMULA
? rCell
.getFormula()->GetErrCode() : FormulaError::NONE
;
164 double ScInterpreter::ConvertStringToValue( const OUString
& rStr
)
166 FormulaError nError
= FormulaError::NONE
;
167 double fValue
= ScGlobal::ConvertStringToValue( rStr
, maCalcConfig
, nError
, mnStringNoValueError
,
168 mrContext
, nCurFmtType
);
169 if (nError
!= FormulaError::NONE
)
174 double ScInterpreter::ConvertStringToValue( const OUString
& rStr
, FormulaError
& rError
, SvNumFormatType
& rCurFmtType
)
176 return ScGlobal::ConvertStringToValue( rStr
, maCalcConfig
, rError
, mnStringNoValueError
, mrContext
, rCurFmtType
);
179 double ScInterpreter::GetCellValue( const ScAddress
& rPos
, ScRefCellValue
& rCell
)
181 FormulaError nErr
= nGlobalError
;
182 nGlobalError
= FormulaError::NONE
;
183 double nVal
= GetCellValueOrZero(rPos
, rCell
);
184 // Propagate previous error, if any; nGlobalError==CellNoValue is not an
185 // error here, preserve previous error or non-error.
186 if (nErr
!= FormulaError::NONE
|| nGlobalError
== FormulaError::CellNoValue
)
191 double ScInterpreter::GetCellValueOrZero( const ScAddress
& rPos
, ScRefCellValue
& rCell
)
195 CellType eType
= rCell
.getType();
198 case CELLTYPE_FORMULA
:
200 ScFormulaCell
* pFCell
= rCell
.getFormula();
201 FormulaError nErr
= pFCell
->GetErrCode();
202 if( nErr
== FormulaError::NONE
)
204 if (pFCell
->IsValue())
206 fValue
= pFCell
->GetValue();
207 mrDoc
.GetNumberFormatInfo( mrContext
, nCurFmtType
, nCurFmtIndex
,
212 fValue
= ConvertStringToValue(pFCell
->GetString().getString());
224 fValue
= rCell
.getDouble();
225 nCurFmtIndex
= mrDoc
.GetNumberFormat( mrContext
, rPos
);
226 nCurFmtType
= mrContext
.NFGetType(nCurFmtIndex
);
227 if ( bCalcAsShown
&& fValue
!= 0.0 )
228 fValue
= mrDoc
.RoundValueAsShown( fValue
, nCurFmtIndex
, &mrContext
);
231 case CELLTYPE_STRING
:
234 // SUM(A1:A2) differs from A1+A2. No good. But people insist on
236 OUString aStr
= rCell
.getString(&mrDoc
);
237 fValue
= ConvertStringToValue( aStr
);
241 fValue
= 0.0; // empty or broadcaster cell
248 void ScInterpreter::GetCellString( svl::SharedString
& rStr
, ScRefCellValue
& rCell
)
250 FormulaError nErr
= FormulaError::NONE
;
252 switch (rCell
.getType())
254 case CELLTYPE_STRING
:
256 rStr
= rCell
.getSharedString(&mrDoc
, mrStrPool
);
258 case CELLTYPE_FORMULA
:
260 ScFormulaCell
* pFCell
= rCell
.getFormula();
261 nErr
= pFCell
->GetErrCode();
262 if (pFCell
->IsValue())
264 rStr
= GetStringFromDouble( pFCell
->GetValue() );
267 rStr
= pFCell
->GetString();
272 rStr
= GetStringFromDouble( rCell
.getDouble() );
276 rStr
= svl::SharedString::getEmptyString();
283 bool ScInterpreter::CreateDoubleArr(SCCOL nCol1
, SCROW nRow1
, SCTAB nTab1
,
284 SCCOL nCol2
, SCROW nRow2
, SCTAB nTab2
, sal_uInt8
* pCellArr
)
287 // Old Add-Ins are hard limited to sal_uInt16 values.
288 static_assert(MAXCOLCOUNT
<= SAL_MAX_UINT16
&& MAXCOLCOUNT_JUMBO
<= SAL_MAX_UINT16
,
289 "Add check for columns > SAL_MAX_UINT16!");
290 if (nRow1
> SAL_MAX_UINT16
|| nRow2
> SAL_MAX_UINT16
)
293 sal_uInt16 nCount
= 0;
294 sal_uInt16
* p
= reinterpret_cast<sal_uInt16
*>(pCellArr
);
295 *p
++ = static_cast<sal_uInt16
>(nCol1
);
296 *p
++ = static_cast<sal_uInt16
>(nRow1
);
297 *p
++ = static_cast<sal_uInt16
>(nTab1
);
298 *p
++ = static_cast<sal_uInt16
>(nCol2
);
299 *p
++ = static_cast<sal_uInt16
>(nRow2
);
300 *p
++ = static_cast<sal_uInt16
>(nTab2
);
301 sal_uInt16
* pCount
= p
;
303 sal_uInt16 nPos
= 14;
306 while (nTab
<= nTab2
)
310 while (nRow
<= nRow2
)
314 while (nCol
<= nCol2
)
318 ScRefCellValue
aCell(mrDoc
, aAdr
);
319 if (!aCell
.isEmpty())
321 FormulaError nErr
= FormulaError::NONE
;
324 switch (aCell
.getType())
326 case CELLTYPE_VALUE
:
327 nVal
= GetValueCellValue(aAdr
, aCell
.getDouble());
329 case CELLTYPE_FORMULA
:
330 if (aCell
.getFormula()->IsValue())
332 nErr
= aCell
.getFormula()->GetErrCode();
333 nVal
= aCell
.getFormula()->GetValue();
344 if ((nPos
+ (4 * sizeof(sal_uInt16
)) + sizeof(double)) > MAXARRSIZE
)
346 *p
++ = static_cast<sal_uInt16
>(nCol
);
347 *p
++ = static_cast<sal_uInt16
>(nRow
);
348 *p
++ = static_cast<sal_uInt16
>(nTab
);
349 *p
++ = static_cast<sal_uInt16
>(nErr
);
350 memcpy( p
, &nVal
, sizeof(double));
351 nPos
+= 8 + sizeof(double);
352 p
= reinterpret_cast<sal_uInt16
*>( pCellArr
+ nPos
);
366 bool ScInterpreter::CreateStringArr(SCCOL nCol1
, SCROW nRow1
, SCTAB nTab1
,
367 SCCOL nCol2
, SCROW nRow2
, SCTAB nTab2
,
371 // Old Add-Ins are hard limited to sal_uInt16 values.
372 static_assert(MAXCOLCOUNT
<= SAL_MAX_UINT16
&& MAXCOLCOUNT_JUMBO
<= SAL_MAX_UINT16
,
373 "Add check for columns > SAL_MAX_UINT16!");
374 if (nRow1
> SAL_MAX_UINT16
|| nRow2
> SAL_MAX_UINT16
)
377 sal_uInt16 nCount
= 0;
378 sal_uInt16
* p
= reinterpret_cast<sal_uInt16
*>(pCellArr
);
379 *p
++ = static_cast<sal_uInt16
>(nCol1
);
380 *p
++ = static_cast<sal_uInt16
>(nRow1
);
381 *p
++ = static_cast<sal_uInt16
>(nTab1
);
382 *p
++ = static_cast<sal_uInt16
>(nCol2
);
383 *p
++ = static_cast<sal_uInt16
>(nRow2
);
384 *p
++ = static_cast<sal_uInt16
>(nTab2
);
385 sal_uInt16
* pCount
= p
;
387 sal_uInt16 nPos
= 14;
389 while (nTab
<= nTab2
)
392 while (nRow
<= nRow2
)
395 while (nCol
<= nCol2
)
397 ScRefCellValue
aCell(mrDoc
, ScAddress(nCol
, nRow
, nTab
));
398 if (!aCell
.isEmpty())
401 FormulaError nErr
= FormulaError::NONE
;
403 switch (aCell
.getType())
405 case CELLTYPE_STRING
:
407 aStr
= aCell
.getString(&mrDoc
);
409 case CELLTYPE_FORMULA
:
410 if (!aCell
.getFormula()->IsValue())
412 nErr
= aCell
.getFormula()->GetErrCode();
413 aStr
= aCell
.getFormula()->GetString().getString();
424 OString
aTmp(OUStringToOString(aStr
,
425 osl_getThreadTextEncoding()));
426 // Old Add-Ins are limited to sal_uInt16 string
427 // lengths, and room for pad byte check.
428 if ( aTmp
.getLength() > SAL_MAX_UINT16
- 2 )
430 // Append a 0-pad-byte if string length is odd
431 // MUST be sal_uInt16
432 sal_uInt16 nStrLen
= static_cast<sal_uInt16
>(aTmp
.getLength());
433 sal_uInt16 nLen
= ( nStrLen
+ 2 ) & ~1;
435 if ((static_cast<sal_uLong
>(nPos
) + (5 * sizeof(sal_uInt16
)) + nLen
) > MAXARRSIZE
)
437 *p
++ = static_cast<sal_uInt16
>(nCol
);
438 *p
++ = static_cast<sal_uInt16
>(nRow
);
439 *p
++ = static_cast<sal_uInt16
>(nTab
);
440 *p
++ = static_cast<sal_uInt16
>(nErr
);
442 memcpy( p
, aTmp
.getStr(), nStrLen
+ 1);
443 nPos
+= 10 + nStrLen
+ 1;
444 sal_uInt8
* q
= pCellArr
+ nPos
;
445 if( (nStrLen
& 1) == 0 )
450 p
= reinterpret_cast<sal_uInt16
*>( pCellArr
+ nPos
);
464 bool ScInterpreter::CreateCellArr(SCCOL nCol1
, SCROW nRow1
, SCTAB nTab1
,
465 SCCOL nCol2
, SCROW nRow2
, SCTAB nTab2
,
469 // Old Add-Ins are hard limited to sal_uInt16 values.
470 static_assert(MAXCOLCOUNT
<= SAL_MAX_UINT16
&& MAXCOLCOUNT_JUMBO
<= SAL_MAX_UINT16
,
471 "Add check for columns > SAL_MAX_UINT16!");
472 if (nRow1
> SAL_MAX_UINT16
|| nRow2
> SAL_MAX_UINT16
)
475 sal_uInt16 nCount
= 0;
476 sal_uInt16
* p
= reinterpret_cast<sal_uInt16
*>(pCellArr
);
477 *p
++ = static_cast<sal_uInt16
>(nCol1
);
478 *p
++ = static_cast<sal_uInt16
>(nRow1
);
479 *p
++ = static_cast<sal_uInt16
>(nTab1
);
480 *p
++ = static_cast<sal_uInt16
>(nCol2
);
481 *p
++ = static_cast<sal_uInt16
>(nRow2
);
482 *p
++ = static_cast<sal_uInt16
>(nTab2
);
483 sal_uInt16
* pCount
= p
;
485 sal_uInt16 nPos
= 14;
488 while (nTab
<= nTab2
)
492 while (nRow
<= nRow2
)
496 while (nCol
<= nCol2
)
499 ScRefCellValue
aCell(mrDoc
, aAdr
);
500 if (!aCell
.isEmpty())
502 FormulaError nErr
= FormulaError::NONE
;
503 sal_uInt16 nType
= 0; // 0 = number; 1 = string
507 switch (aCell
.getType())
509 case CELLTYPE_STRING
:
511 aStr
= aCell
.getString(&mrDoc
);
514 case CELLTYPE_VALUE
:
515 nVal
= GetValueCellValue(aAdr
, aCell
.getDouble());
517 case CELLTYPE_FORMULA
:
518 nErr
= aCell
.getFormula()->GetErrCode();
519 if (aCell
.getFormula()->IsValue())
520 nVal
= aCell
.getFormula()->GetValue();
522 aStr
= aCell
.getFormula()->GetString().getString();
530 if ((nPos
+ (5 * sizeof(sal_uInt16
))) > MAXARRSIZE
)
532 *p
++ = static_cast<sal_uInt16
>(nCol
);
533 *p
++ = static_cast<sal_uInt16
>(nRow
);
534 *p
++ = static_cast<sal_uInt16
>(nTab
);
535 *p
++ = static_cast<sal_uInt16
>(nErr
);
540 if ((nPos
+ sizeof(double)) > MAXARRSIZE
)
542 memcpy( p
, &nVal
, sizeof(double));
543 nPos
+= sizeof(double);
547 OString
aTmp(OUStringToOString(aStr
,
548 osl_getThreadTextEncoding()));
549 // Old Add-Ins are limited to sal_uInt16 string
550 // lengths, and room for pad byte check.
551 if ( aTmp
.getLength() > SAL_MAX_UINT16
- 2 )
553 // Append a 0-pad-byte if string length is odd
554 // MUST be sal_uInt16
555 sal_uInt16 nStrLen
= static_cast<sal_uInt16
>(aTmp
.getLength());
556 sal_uInt16 nLen
= ( nStrLen
+ 2 ) & ~1;
557 if ( (static_cast<sal_uLong
>(nPos
) + 2 + nLen
) > MAXARRSIZE
)
560 memcpy( p
, aTmp
.getStr(), nStrLen
+ 1);
561 nPos
+= 2 + nStrLen
+ 1;
562 sal_uInt8
* q
= pCellArr
+ nPos
;
563 if( (nStrLen
& 1) == 0 )
570 p
= reinterpret_cast<sal_uInt16
*>( pCellArr
+ nPos
);
585 // Also releases a TempToken if appropriate.
587 void ScInterpreter::PushWithoutError( const FormulaToken
& r
)
589 if ( sp
>= MAXSTACK
)
590 SetError( FormulaError::StackOverflow
);
597 pStack
[ sp
]->DecRef();
603 void ScInterpreter::Push( const FormulaToken
& r
)
605 if ( sp
>= MAXSTACK
)
606 SetError( FormulaError::StackOverflow
);
609 if (nGlobalError
!= FormulaError::NONE
)
611 if (r
.GetType() == svError
)
612 PushWithoutError( r
);
614 PushTempTokenWithoutError( new FormulaErrorToken( nGlobalError
));
617 PushWithoutError( r
);
621 void ScInterpreter::PushTempToken( FormulaToken
* p
)
623 if ( sp
>= MAXSTACK
)
625 SetError( FormulaError::StackOverflow
);
626 // p may be a dangling pointer hereafter!
627 p
->DeleteIfZeroRef();
631 if (nGlobalError
!= FormulaError::NONE
)
633 if (p
->GetType() == svError
)
635 p
->SetError( nGlobalError
);
636 PushTempTokenWithoutError( p
);
640 // p may be a dangling pointer hereafter!
641 p
->DeleteIfZeroRef();
642 PushTempTokenWithoutError( new FormulaErrorToken( nGlobalError
));
646 PushTempTokenWithoutError( p
);
650 void ScInterpreter::PushTempTokenWithoutError( const FormulaToken
* p
)
653 if ( sp
>= MAXSTACK
)
655 SetError( FormulaError::StackOverflow
);
656 // p may be a dangling pointer hereafter!
664 pStack
[ sp
]->DecRef();
670 void ScInterpreter::PushTokenRef( const formula::FormulaConstTokenRef
& x
)
672 if ( sp
>= MAXSTACK
)
674 SetError( FormulaError::StackOverflow
);
678 if (nGlobalError
!= FormulaError::NONE
)
680 if (x
->GetType() == svError
&& x
->GetError() == nGlobalError
)
681 PushTempTokenWithoutError( x
.get());
683 PushTempTokenWithoutError( new FormulaErrorToken( nGlobalError
));
686 PushTempTokenWithoutError( x
.get());
690 void ScInterpreter::PushCellResultToken( bool bDisplayEmptyAsString
,
691 const ScAddress
& rAddress
, SvNumFormatType
* pRetTypeExpr
, sal_uInt32
* pRetIndexExpr
, bool bFinalResult
)
693 ScRefCellValue
aCell(mrDoc
, rAddress
);
694 if (aCell
.hasEmptyValue())
696 bool bInherited
= (aCell
.getType() == CELLTYPE_FORMULA
);
697 if (pRetTypeExpr
&& pRetIndexExpr
)
698 mrDoc
.GetNumberFormatInfo(mrContext
, *pRetTypeExpr
, *pRetIndexExpr
, rAddress
);
699 PushTempToken( new ScEmptyCellToken( bInherited
, bDisplayEmptyAsString
));
703 FormulaError nErr
= FormulaError::NONE
;
704 if (aCell
.getType() == CELLTYPE_FORMULA
)
705 nErr
= aCell
.getFormula()->GetErrCode();
707 if (nErr
!= FormulaError::NONE
)
711 *pRetTypeExpr
= SvNumFormatType::UNDEFINED
;
715 else if (aCell
.hasString())
717 svl::SharedString aRes
;
718 GetCellString( aRes
, aCell
);
721 *pRetTypeExpr
= SvNumFormatType::TEXT
;
727 double fVal
= GetCellValue(rAddress
, aCell
);
730 TreatDoubleError( fVal
);
731 if (!IfErrorPushError())
732 PushTempTokenWithoutError( CreateFormulaDoubleToken( fVal
));
739 *pRetTypeExpr
= nCurFmtType
;
741 *pRetIndexExpr
= nCurFmtIndex
;
745 // Simply throw away TOS.
747 void ScInterpreter::Pop()
752 SetError(FormulaError::UnknownStackVariable
);
755 // Simply throw away TOS and set error code, used with ocIsError et al.
757 void ScInterpreter::PopError()
762 if (pStack
[sp
]->GetType() == svError
)
763 nGlobalError
= pStack
[sp
]->GetError();
766 SetError(FormulaError::UnknownStackVariable
);
769 FormulaConstTokenRef
ScInterpreter::PopToken()
774 const FormulaToken
* p
= pStack
[ sp
];
775 if (p
->GetType() == svError
)
776 nGlobalError
= p
->GetError();
780 SetError(FormulaError::UnknownStackVariable
);
784 double ScInterpreter::PopDouble()
786 nCurFmtType
= SvNumFormatType::NUMBER
;
791 const FormulaToken
* p
= pStack
[ sp
];
792 switch (p
->GetType())
795 nGlobalError
= p
->GetError();
799 SvNumFormatType nType
= static_cast<SvNumFormatType
>(p
->GetDoubleType());
800 if (nType
!= SvNumFormatType::ALL
&& nType
!= SvNumFormatType::UNDEFINED
)
802 return p
->GetDouble();
808 SetError( FormulaError::IllegalArgument
);
812 SetError( FormulaError::UnknownStackVariable
);
816 const svl::SharedString
& ScInterpreter::PopString()
818 nCurFmtType
= SvNumFormatType::TEXT
;
823 const FormulaToken
* p
= pStack
[ sp
];
824 switch (p
->GetType())
827 nGlobalError
= p
->GetError();
830 return p
->GetString();
833 return svl::SharedString::getEmptyString();
835 SetError( FormulaError::IllegalArgument
);
839 SetError( FormulaError::UnknownStackVariable
);
841 return svl::SharedString::getEmptyString();
844 void ScInterpreter::ValidateRef( const ScSingleRefData
& rRef
)
849 SingleRefToVars( rRef
, nCol
, nRow
, nTab
);
852 void ScInterpreter::ValidateRef( const ScComplexRefData
& rRef
)
854 ValidateRef( rRef
.Ref1
);
855 ValidateRef( rRef
.Ref2
);
858 void ScInterpreter::ValidateRef( const ScRefList
& rRefList
)
860 for (const auto& rRef
: rRefList
)
866 void ScInterpreter::SingleRefToVars( const ScSingleRefData
& rRef
,
867 SCCOL
& rCol
, SCROW
& rRow
, SCTAB
& rTab
)
869 if ( rRef
.IsColRel() )
870 rCol
= aPos
.Col() + rRef
.Col();
874 if ( rRef
.IsRowRel() )
875 rRow
= aPos
.Row() + rRef
.Row();
879 if ( rRef
.IsTabRel() )
880 rTab
= aPos
.Tab() + rRef
.Tab();
884 if( !mrDoc
.ValidCol( rCol
) || rRef
.IsColDeleted() )
886 SetError( FormulaError::NoRef
);
889 if( !mrDoc
.ValidRow( rRow
) || rRef
.IsRowDeleted() )
891 SetError( FormulaError::NoRef
);
894 if( !ValidTab( rTab
, mrDoc
.GetTableCount() - 1) || rRef
.IsTabDeleted() )
896 SetError( FormulaError::NoRef
);
901 void ScInterpreter::PopSingleRef(SCCOL
& rCol
, SCROW
&rRow
, SCTAB
& rTab
)
903 ScAddress
aAddr(rCol
, rRow
, rTab
);
910 void ScInterpreter::PopSingleRef( ScAddress
& rAdr
)
915 const FormulaToken
* p
= pStack
[ sp
];
916 switch (p
->GetType())
919 nGlobalError
= p
->GetError();
923 const ScSingleRefData
* pRefData
= p
->GetSingleRef();
924 if (pRefData
->IsDeleted())
926 SetError( FormulaError::NoRef
);
933 SingleRefToVars( *pRefData
, nCol
, nRow
, nTab
);
934 rAdr
.Set( nCol
, nRow
, nTab
);
935 if (!mrDoc
.m_TableOpList
.empty())
940 SetError( FormulaError::IllegalParameter
);
944 SetError( FormulaError::UnknownStackVariable
);
947 void ScInterpreter::DoubleRefToVars( const formula::FormulaToken
* p
,
948 SCCOL
& rCol1
, SCROW
&rRow1
, SCTAB
& rTab1
,
949 SCCOL
& rCol2
, SCROW
&rRow2
, SCTAB
& rTab2
)
951 const ScComplexRefData
& rCRef
= *p
->GetDoubleRef();
952 SingleRefToVars( rCRef
.Ref1
, rCol1
, rRow1
, rTab1
);
953 SingleRefToVars( rCRef
.Ref2
, rCol2
, rRow2
, rTab2
);
954 PutInOrder(rCol1
, rCol2
);
955 PutInOrder(rRow1
, rRow2
);
956 PutInOrder(rTab1
, rTab2
);
957 if (!mrDoc
.m_TableOpList
.empty())
959 ScRange
aRange( rCol1
, rRow1
, rTab1
, rCol2
, rRow2
, rTab2
);
960 if ( IsTableOpInRange( aRange
) )
961 SetError( FormulaError::IllegalParameter
);
965 ScDBRangeBase
* ScInterpreter::PopDBDoubleRef()
967 StackVar eType
= GetStackType();
971 SetError(FormulaError::UnknownStackVariable
);
981 PopDoubleRef(nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
982 if (nGlobalError
!= FormulaError::NONE
)
984 return new ScDBInternalRange(&mrDoc
,
985 ScRange(nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
));
988 case svExternalDoubleRef
:
991 if (eType
== svMatrix
)
994 PopExternalDoubleRef(pMat
);
995 if (nGlobalError
!= FormulaError::NONE
)
997 return new ScDBExternalRange(&mrDoc
, std::move(pMat
));
1000 SetError( FormulaError::IllegalParameter
);
1006 void ScInterpreter::PopDoubleRef(SCCOL
& rCol1
, SCROW
&rRow1
, SCTAB
& rTab1
,
1007 SCCOL
& rCol2
, SCROW
&rRow2
, SCTAB
& rTab2
)
1012 const FormulaToken
* p
= pStack
[ sp
];
1013 switch (p
->GetType())
1016 nGlobalError
= p
->GetError();
1019 DoubleRefToVars( p
, rCol1
, rRow1
, rTab1
, rCol2
, rRow2
, rTab2
);
1022 SetError( FormulaError::IllegalParameter
);
1026 SetError( FormulaError::UnknownStackVariable
);
1029 void ScInterpreter::DoubleRefToRange( const ScComplexRefData
& rCRef
,
1030 ScRange
& rRange
, bool bDontCheckForTableOp
)
1035 SingleRefToVars( rCRef
.Ref1
, nCol
, nRow
, nTab
);
1036 rRange
.aStart
.Set( nCol
, nRow
, nTab
);
1037 SingleRefToVars( rCRef
.Ref2
, nCol
, nRow
, nTab
);
1038 rRange
.aEnd
.Set( nCol
, nRow
, nTab
);
1039 rRange
.PutInOrder();
1040 if (!mrDoc
.m_TableOpList
.empty() && !bDontCheckForTableOp
)
1042 if ( IsTableOpInRange( rRange
) )
1043 SetError( FormulaError::IllegalParameter
);
1047 void ScInterpreter::PopDoubleRef( ScRange
& rRange
, short & rParam
, size_t & rRefInList
)
1051 const formula::FormulaToken
* pToken
= pStack
[ sp
-1 ];
1052 switch (pToken
->GetType())
1055 nGlobalError
= pToken
->GetError();
1060 const ScComplexRefData
* pRefData
= pToken
->GetDoubleRef();
1061 if (pRefData
->IsDeleted())
1063 SetError( FormulaError::NoRef
);
1066 DoubleRefToRange( *pRefData
, rRange
);
1071 const ScRefList
* pList
= pToken
->GetRefList();
1072 if (rRefInList
< pList
->size())
1074 DoubleRefToRange( (*pList
)[rRefInList
], rRange
);
1075 if (++rRefInList
< pList
->size())
1087 SetError( FormulaError::IllegalParameter
);
1092 SetError( FormulaError::IllegalParameter
);
1096 SetError( FormulaError::UnknownStackVariable
);
1099 void ScInterpreter::PopDoubleRef( ScRange
& rRange
, bool bDontCheckForTableOp
)
1104 const FormulaToken
* p
= pStack
[ sp
];
1105 switch (p
->GetType())
1108 nGlobalError
= p
->GetError();
1111 DoubleRefToRange( *p
->GetDoubleRef(), rRange
, bDontCheckForTableOp
);
1114 SetError( FormulaError::IllegalParameter
);
1118 SetError( FormulaError::UnknownStackVariable
);
1121 const ScComplexRefData
* ScInterpreter::GetStackDoubleRef(size_t rRefInList
)
1125 const FormulaToken
* p
= pStack
[ sp
- 1 ];
1126 switch (p
->GetType())
1129 return p
->GetDoubleRef();
1132 const ScRefList
* pList
= p
->GetRefList();
1133 if (rRefInList
< pList
->size())
1134 return &(*pList
)[rRefInList
];
1144 void ScInterpreter::PopExternalSingleRef(sal_uInt16
& rFileId
, OUString
& rTabName
, ScSingleRefData
& rRef
)
1148 SetError(FormulaError::UnknownStackVariable
);
1153 const FormulaToken
* p
= pStack
[sp
];
1154 StackVar eType
= p
->GetType();
1156 if (eType
== svError
)
1158 nGlobalError
= p
->GetError();
1162 if (eType
!= svExternalSingleRef
)
1164 SetError( FormulaError::IllegalParameter
);
1168 rFileId
= p
->GetIndex();
1169 rTabName
= p
->GetString().getString();
1170 rRef
= *p
->GetSingleRef();
1173 void ScInterpreter::PopExternalSingleRef(ScExternalRefCache::TokenRef
& rToken
, ScExternalRefCache::CellFormat
* pFmt
)
1177 ScSingleRefData aData
;
1178 PopExternalSingleRef(nFileId
, aTabName
, aData
, rToken
, pFmt
);
1181 void ScInterpreter::PopExternalSingleRef(
1182 sal_uInt16
& rFileId
, OUString
& rTabName
, ScSingleRefData
& rRef
,
1183 ScExternalRefCache::TokenRef
& rToken
, ScExternalRefCache::CellFormat
* pFmt
)
1185 PopExternalSingleRef(rFileId
, rTabName
, rRef
);
1186 if (nGlobalError
!= FormulaError::NONE
)
1189 ScExternalRefManager
* pRefMgr
= mrDoc
.GetExternalRefManager();
1190 const OUString
* pFile
= pRefMgr
->getExternalFileName(rFileId
);
1193 SetError(FormulaError::NoName
);
1197 if (rRef
.IsTabRel())
1199 OSL_FAIL("ScCompiler::GetToken: external single reference must have an absolute table reference!");
1200 SetError(FormulaError::NoRef
);
1204 ScAddress aAddr
= rRef
.toAbs(mrDoc
, aPos
);
1205 ScExternalRefCache::CellFormat aFmt
;
1206 ScExternalRefCache::TokenRef xNew
= pRefMgr
->getSingleRefToken(
1207 rFileId
, rTabName
, aAddr
, &aPos
, nullptr, &aFmt
);
1211 SetError(FormulaError::NoRef
);
1215 if (xNew
->GetType() == svError
)
1216 SetError( xNew
->GetError());
1218 rToken
= std::move(xNew
);
1223 void ScInterpreter::PopExternalDoubleRef(sal_uInt16
& rFileId
, OUString
& rTabName
, ScComplexRefData
& rRef
)
1227 SetError(FormulaError::UnknownStackVariable
);
1232 const FormulaToken
* p
= pStack
[sp
];
1233 StackVar eType
= p
->GetType();
1235 if (eType
== svError
)
1237 nGlobalError
= p
->GetError();
1241 if (eType
!= svExternalDoubleRef
)
1243 SetError( FormulaError::IllegalParameter
);
1247 rFileId
= p
->GetIndex();
1248 rTabName
= p
->GetString().getString();
1249 rRef
= *p
->GetDoubleRef();
1252 void ScInterpreter::PopExternalDoubleRef(ScExternalRefCache::TokenArrayRef
& rArray
)
1256 ScComplexRefData aData
;
1257 PopExternalDoubleRef(nFileId
, aTabName
, aData
);
1258 if (nGlobalError
!= FormulaError::NONE
)
1261 GetExternalDoubleRef(nFileId
, aTabName
, aData
, rArray
);
1262 if (nGlobalError
!= FormulaError::NONE
)
1266 void ScInterpreter::PopExternalDoubleRef(ScMatrixRef
& rMat
)
1268 ScExternalRefCache::TokenArrayRef pArray
;
1269 PopExternalDoubleRef(pArray
);
1270 if (nGlobalError
!= FormulaError::NONE
)
1273 // For now, we only support single range data for external
1274 // references, which means the array should only contain a
1275 // single matrix token.
1276 formula::FormulaToken
* p
= pArray
->FirstToken();
1277 if (!p
|| p
->GetType() != svMatrix
)
1278 SetError( FormulaError::IllegalParameter
);
1281 rMat
= p
->GetMatrix();
1283 SetError( FormulaError::UnknownVariable
);
1287 void ScInterpreter::GetExternalDoubleRef(
1288 sal_uInt16 nFileId
, const OUString
& rTabName
, const ScComplexRefData
& rData
, ScExternalRefCache::TokenArrayRef
& rArray
)
1290 ScExternalRefManager
* pRefMgr
= mrDoc
.GetExternalRefManager();
1291 const OUString
* pFile
= pRefMgr
->getExternalFileName(nFileId
);
1294 SetError(FormulaError::NoName
);
1297 if (rData
.Ref1
.IsTabRel() || rData
.Ref2
.IsTabRel())
1299 OSL_FAIL("ScCompiler::GetToken: external double reference must have an absolute table reference!");
1300 SetError(FormulaError::NoRef
);
1304 ScComplexRefData
aData(rData
);
1305 ScRange aRange
= aData
.toAbs(mrDoc
, aPos
);
1306 if (!mrDoc
.ValidColRow(aRange
.aStart
.Col(), aRange
.aStart
.Row()) || !mrDoc
.ValidColRow(aRange
.aEnd
.Col(), aRange
.aEnd
.Row()))
1308 SetError(FormulaError::NoRef
);
1312 ScExternalRefCache::TokenArrayRef pArray
= pRefMgr
->getDoubleRefTokens(
1313 nFileId
, rTabName
, aRange
, &aPos
);
1317 SetError(FormulaError::IllegalArgument
);
1321 formula::FormulaTokenArrayPlainIterator
aIter(*pArray
);
1322 formula::FormulaToken
* pToken
= aIter
.First();
1324 if (pToken
->GetType() == svError
)
1326 SetError( pToken
->GetError());
1329 if (pToken
->GetType() != svMatrix
)
1331 SetError(FormulaError::IllegalArgument
);
1337 // Can't handle more than one matrix per parameter.
1338 SetError( FormulaError::IllegalArgument
);
1342 rArray
= std::move(pArray
);
1345 bool ScInterpreter::PopDoubleRefOrSingleRef( ScAddress
& rAdr
)
1347 switch ( GetStackType() )
1352 PopDoubleRef( aRange
, true );
1353 return DoubleRefToPosSingleRef( aRange
, rAdr
);
1357 PopSingleRef( rAdr
);
1362 SetError( FormulaError::NoRef
);
1367 void ScInterpreter::PopDoubleRefPushMatrix()
1369 if ( GetStackType() == svDoubleRef
)
1371 ScMatrixRef pMat
= GetMatrix();
1375 PushIllegalParameter();
1378 SetError( FormulaError::NoRef
);
1381 void ScInterpreter::PopRefListPushMatrixOrRef()
1383 if ( GetStackType() == svRefList
)
1385 FormulaConstTokenRef xTok
= pStack
[sp
-1];
1386 const std::vector
<ScComplexRefData
>* pv
= xTok
->GetRefList();
1389 const size_t nEntries
= pv
->size();
1393 PushTempTokenWithoutError( new ScDoubleRefToken( mrDoc
.GetSheetLimits(), (*pv
)[0] ));
1395 else if (bMatrixFormula
)
1397 // Only single cells can be stuffed into a column vector.
1398 // XXX NOTE: Excel doesn't do this but returns #VALUE! instead.
1399 // Though there's no compelling reason not to...
1400 for (const auto & rRef
: *pv
)
1402 if (rRef
.Ref1
!= rRef
.Ref2
)
1405 ScMatrixRef xMat
= GetNewMat( 1, nEntries
, true); // init empty
1408 for (size_t i
=0; i
< nEntries
; ++i
)
1410 SCCOL nCol
; SCROW nRow
; SCTAB nTab
;
1411 SingleRefToVars( (*pv
)[i
].Ref1
, nCol
, nRow
, nTab
);
1412 if (nGlobalError
== FormulaError::NONE
)
1414 ScAddress
aAdr( nCol
, nRow
, nTab
);
1415 ScRefCellValue
aCell(mrDoc
, aAdr
);
1416 if (aCell
.hasError())
1417 xMat
->PutError( aCell
.getFormula()->GetErrCode(), 0, i
);
1418 else if (aCell
.hasEmptyValue())
1419 xMat
->PutEmpty( 0, i
);
1420 else if (aCell
.hasString())
1421 xMat
->PutString( mrStrPool
.intern( aCell
.getString(&mrDoc
)), 0, i
);
1423 xMat
->PutDouble( aCell
.getValue(), 0, i
);
1427 xMat
->PutError( nGlobalError
, 0, i
);
1428 nGlobalError
= FormulaError::NONE
;
1435 // else: keep token on stack, something will handle the error
1438 SetError( FormulaError::NoRef
);
1441 void ScInterpreter::ConvertMatrixJumpConditionToMatrix()
1443 StackVar eStackType
= GetStackType();
1444 if (eStackType
== svUnknown
)
1445 return; // can't do anything, some caller will catch that
1446 if (eStackType
== svMatrix
)
1447 return; // already matrix, nothing to do
1449 if (eStackType
!= svDoubleRef
&& GetStackType(2) != svJumpMatrix
)
1450 return; // always convert svDoubleRef, others only in JumpMatrix context
1452 GetTokenMatrixMap(); // make sure it exists, create if not.
1453 ScMatrixRef pMat
= GetMatrix();
1457 PushIllegalParameter();
1460 bool ScInterpreter::ConvertMatrixParameters()
1462 sal_uInt16 nParams
= pCur
->GetParamCount();
1463 SAL_WARN_IF( nParams
> sp
, "sc.core", "ConvertMatrixParameters: stack/param count mismatch: eOp: "
1464 << static_cast<int>(pCur
->GetOpCode()) << " sp: " << sp
<< " nParams: " << nParams
);
1465 assert(nParams
<= sp
);
1466 SCSIZE nJumpCols
= 0, nJumpRows
= 0;
1467 for ( sal_uInt16 i
=1; i
<= nParams
&& i
<= sp
; ++i
)
1469 const FormulaToken
* p
= pStack
[ sp
- i
];
1470 if ( p
->GetOpCode() != ocPush
&& p
->GetOpCode() != ocMissing
)
1472 assert(!"ConvertMatrixParameters: not a push");
1476 switch ( p
->GetType() )
1481 case svExternalSingleRef
:
1489 if ( ScParameterClassification::GetParameterType( pCur
, nParams
- i
)
1490 == formula::ParamClass::Value
)
1491 { // only if single value expected
1492 ScConstMatrixRef pMat
= p
->GetMatrix();
1494 SetError( FormulaError::UnknownVariable
);
1497 SCSIZE nCols
, nRows
;
1498 pMat
->GetDimensions( nCols
, nRows
);
1499 if ( nJumpCols
< nCols
)
1501 if ( nJumpRows
< nRows
)
1509 formula::ParamClass eType
= ScParameterClassification::GetParameterType( pCur
, nParams
- i
);
1510 if ( eType
!= formula::ParamClass::Reference
&&
1511 eType
!= formula::ParamClass::ReferenceOrRefArray
&&
1512 eType
!= formula::ParamClass::ReferenceOrForceArray
&&
1513 // For scalar Value: convert to Array/JumpMatrix
1514 // only if in array formula context, else (function
1515 // has ForceArray or ReferenceOrForceArray
1516 // parameter *somewhere else*) pick a normal
1517 // position dependent implicit intersection later.
1518 (eType
!= formula::ParamClass::Value
|| IsInArrayContext()))
1523 DoubleRefToVars( p
, nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
1524 // Make sure the map exists, created if not.
1525 GetTokenMatrixMap();
1526 ScMatrixRef pMat
= CreateMatrixFromDoubleRef( p
,
1527 nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
1530 if ( eType
== formula::ParamClass::Value
)
1531 { // only if single value expected
1532 if ( nJumpCols
< o3tl::make_unsigned(nCol2
- nCol1
+ 1) )
1533 nJumpCols
= static_cast<SCSIZE
>(nCol2
- nCol1
+ 1);
1534 if ( nJumpRows
< o3tl::make_unsigned(nRow2
- nRow1
+ 1) )
1535 nJumpRows
= static_cast<SCSIZE
>(nRow2
- nRow1
+ 1);
1537 formula::FormulaToken
* pNew
= new ScMatrixToken( std::move(pMat
) );
1539 pStack
[ sp
- i
] = pNew
;
1540 p
->DecRef(); // p may be dead now!
1545 case svExternalDoubleRef
:
1547 formula::ParamClass eType
= ScParameterClassification::GetParameterType( pCur
, nParams
- i
);
1548 if (eType
== formula::ParamClass::Value
|| eType
== formula::ParamClass::Array
)
1550 sal_uInt16 nFileId
= p
->GetIndex();
1551 OUString aTabName
= p
->GetString().getString();
1552 const ScComplexRefData
& rRef
= *p
->GetDoubleRef();
1553 ScExternalRefCache::TokenArrayRef pArray
;
1554 GetExternalDoubleRef(nFileId
, aTabName
, rRef
, pArray
);
1555 if (nGlobalError
!= FormulaError::NONE
|| !pArray
)
1557 formula::FormulaToken
* pTemp
= pArray
->FirstToken();
1561 ScMatrixRef pMat
= pTemp
->GetMatrix();
1564 if (eType
== formula::ParamClass::Value
)
1565 { // only if single value expected
1567 pMat
->GetDimensions( nC
, nR
);
1573 formula::FormulaToken
* pNew
= new ScMatrixToken( std::move(pMat
) );
1575 pStack
[ sp
- i
] = pNew
;
1576 p
->DecRef(); // p may be dead now!
1583 formula::ParamClass eType
= ScParameterClassification::GetParameterType( pCur
, nParams
- i
);
1584 if ( eType
!= formula::ParamClass::Reference
&&
1585 eType
!= formula::ParamClass::ReferenceOrRefArray
&&
1586 eType
!= formula::ParamClass::ReferenceOrForceArray
&&
1587 eType
!= formula::ParamClass::ForceArray
)
1589 // can't convert to matrix
1590 SetError( FormulaError::NoRef
);
1592 // else: the consuming function has to decide if and how to
1593 // handle a reference list argument in array context.
1597 assert(!"ConvertMatrixParameters: unknown parameter type");
1601 if( nJumpCols
&& nJumpRows
)
1603 short nPC
= aCode
.GetPC();
1604 short nStart
= nPC
- 1; // restart on current code (-1)
1605 short nNext
= nPC
; // next instruction after subroutine
1606 short nStop
= nPC
+ 1; // stop subroutine before reaching that
1607 FormulaConstTokenRef xNew
;
1608 ScTokenMatrixMap::const_iterator aMapIter
;
1609 if ((aMapIter
= maTokenMatrixMap
.find( pCur
)) != maTokenMatrixMap
.end())
1610 xNew
= (*aMapIter
).second
;
1613 std::shared_ptr
<ScJumpMatrix
> pJumpMat
;
1616 pJumpMat
= std::make_shared
<ScJumpMatrix
>( pCur
->GetOpCode(), nJumpCols
, nJumpRows
);
1618 catch (const std::bad_alloc
&)
1620 SAL_WARN("sc.core", "std::bad_alloc in ScJumpMatrix ctor with " << nJumpCols
<< " columns and " << nJumpRows
<< " rows");
1623 pJumpMat
->SetAllJumps( 1.0, nStart
, nNext
, nStop
);
1624 // pop parameters and store in ScJumpMatrix, push in JumpMatrix()
1625 ScTokenVec
aParams(nParams
);
1626 for ( sal_uInt16 i
=1; i
<= nParams
&& sp
> 0; ++i
)
1628 const FormulaToken
* p
= pStack
[ --sp
];
1630 // store in reverse order such that a push may simply iterate
1631 aParams
[ nParams
- i
] = p
;
1633 pJumpMat
->SetJumpParameters( std::move(aParams
) );
1634 xNew
= new ScJumpMatrixToken( std::move(pJumpMat
) );
1635 GetTokenMatrixMap().emplace(pCur
, xNew
);
1637 PushTempTokenWithoutError( xNew
.get());
1638 // set continuation point of path for main code line
1639 aCode
.Jump( nNext
, nNext
);
1645 ScMatrixRef
ScInterpreter::PopMatrix()
1650 const FormulaToken
* p
= pStack
[ sp
];
1651 switch (p
->GetType())
1654 nGlobalError
= p
->GetError();
1658 // ScMatrix itself maintains an im/mutable flag that should
1659 // be obeyed where necessary... so we can return ScMatrixRef
1660 // here instead of ScConstMatrixRef.
1661 ScMatrix
* pMat
= const_cast<FormulaToken
*>(p
)->GetMatrix();
1663 pMat
->SetErrorInterpreter( this);
1665 SetError( FormulaError::UnknownVariable
);
1669 SetError( FormulaError::IllegalParameter
);
1673 SetError( FormulaError::UnknownStackVariable
);
1677 sc::RangeMatrix
ScInterpreter::PopRangeMatrix()
1679 sc::RangeMatrix aRet
;
1682 switch (pStack
[sp
-1]->GetType())
1687 const FormulaToken
* p
= pStack
[sp
];
1688 aRet
.mpMat
= const_cast<FormulaToken
*>(p
)->GetMatrix();
1691 aRet
.mpMat
->SetErrorInterpreter(this);
1692 if (p
->GetByte() == MATRIX_TOKEN_HAS_RANGE
)
1694 const ScComplexRefData
& rRef
= *p
->GetDoubleRef();
1695 if (!rRef
.Ref1
.IsColRel() && !rRef
.Ref1
.IsRowRel() && !rRef
.Ref2
.IsColRel() && !rRef
.Ref2
.IsRowRel())
1697 aRet
.mnCol1
= rRef
.Ref1
.Col();
1698 aRet
.mnRow1
= rRef
.Ref1
.Row();
1699 aRet
.mnTab1
= rRef
.Ref1
.Tab();
1700 aRet
.mnCol2
= rRef
.Ref2
.Col();
1701 aRet
.mnRow2
= rRef
.Ref2
.Row();
1702 aRet
.mnTab2
= rRef
.Ref2
.Tab();
1707 SetError( FormulaError::UnknownVariable
);
1711 aRet
.mpMat
= PopMatrix();
1717 void ScInterpreter::QueryMatrixType(const ScMatrixRef
& xMat
, SvNumFormatType
& rRetTypeExpr
, sal_uInt32
& rRetIndexExpr
)
1721 SCSIZE nCols
, nRows
;
1722 xMat
->GetDimensions(nCols
, nRows
);
1723 ScMatrixValue nMatVal
= xMat
->Get(0, 0);
1724 ScMatValType nMatValType
= nMatVal
.nType
;
1725 if (ScMatrix::IsNonValueType( nMatValType
))
1727 if ( xMat
->IsEmptyPath( 0, 0))
1728 { // result of empty FALSE jump path
1729 FormulaTokenRef xRes
= CreateFormulaDoubleToken( 0.0);
1730 PushTempToken( new ScMatrixFormulaCellToken(nCols
, nRows
, xMat
, xRes
.get()));
1731 rRetTypeExpr
= SvNumFormatType::LOGICAL
;
1733 else if ( xMat
->IsEmptyResult( 0, 0))
1734 { // empty formula result
1735 FormulaTokenRef xRes
= new ScEmptyCellToken( true, true); // inherited, display empty
1736 PushTempToken( new ScMatrixFormulaCellToken(nCols
, nRows
, xMat
, xRes
.get()));
1738 else if ( xMat
->IsEmpty( 0, 0))
1739 { // empty or empty cell
1740 FormulaTokenRef xRes
= new ScEmptyCellToken( false, true); // not inherited, display empty
1741 PushTempToken( new ScMatrixFormulaCellToken(nCols
, nRows
, xMat
, xRes
.get()));
1745 FormulaTokenRef xRes
= new FormulaStringToken( nMatVal
.GetString() );
1746 PushTempToken( new ScMatrixFormulaCellToken(nCols
, nRows
, xMat
, xRes
.get()));
1747 rRetTypeExpr
= SvNumFormatType::TEXT
;
1752 FormulaError nErr
= GetDoubleErrorValue( nMatVal
.fVal
);
1753 FormulaTokenRef xRes
;
1754 if (nErr
!= FormulaError::NONE
)
1755 xRes
= new FormulaErrorToken( nErr
);
1757 xRes
= CreateFormulaDoubleToken( nMatVal
.fVal
);
1758 PushTempToken( new ScMatrixFormulaCellToken(nCols
, nRows
, xMat
, xRes
.get()));
1759 if ( rRetTypeExpr
!= SvNumFormatType::LOGICAL
)
1760 rRetTypeExpr
= SvNumFormatType::NUMBER
;
1763 xMat
->SetErrorInterpreter( nullptr);
1766 SetError( FormulaError::UnknownStackVariable
);
1769 formula::FormulaToken
* ScInterpreter::CreateFormulaDoubleToken( double fVal
, SvNumFormatType nFmt
)
1771 assert( mrContext
.maTokens
.size() == TOKEN_CACHE_SIZE
);
1773 // Find a spare token
1774 for ( auto p
: mrContext
.maTokens
)
1776 if (p
&& p
->GetRef() == 1)
1779 p
->SetDoubleType( static_cast<sal_Int16
>(nFmt
) );
1784 // Allocate a new token
1785 auto p
= new FormulaTypedDoubleToken( fVal
, static_cast<sal_Int16
>(nFmt
) );
1786 p
->SetRefCntPolicy(RefCntPolicy::UnsafeRef
);
1787 if ( mrContext
.maTokens
[mrContext
.mnTokenCachePos
] )
1788 mrContext
.maTokens
[mrContext
.mnTokenCachePos
]->DecRef();
1789 mrContext
.maTokens
[mrContext
.mnTokenCachePos
] = p
;
1791 mrContext
.mnTokenCachePos
= (mrContext
.mnTokenCachePos
+ 1) % TOKEN_CACHE_SIZE
;
1795 formula::FormulaToken
* ScInterpreter::CreateDoubleOrTypedToken( double fVal
)
1797 // NumberFormat::NUMBER is the default untyped double.
1798 if (nFuncFmtType
!= SvNumFormatType::ALL
&& nFuncFmtType
!= SvNumFormatType::NUMBER
&&
1799 nFuncFmtType
!= SvNumFormatType::UNDEFINED
)
1800 return CreateFormulaDoubleToken( fVal
, nFuncFmtType
);
1802 return CreateFormulaDoubleToken( fVal
);
1805 void ScInterpreter::PushDouble(double nVal
)
1807 TreatDoubleError( nVal
);
1808 if (!IfErrorPushError())
1809 PushTempTokenWithoutError( CreateDoubleOrTypedToken( nVal
));
1812 void ScInterpreter::PushInt(int nVal
)
1814 if (!IfErrorPushError())
1815 PushTempTokenWithoutError( CreateDoubleOrTypedToken( nVal
));
1818 void ScInterpreter::PushStringBuffer( const sal_Unicode
* pString
)
1822 svl::SharedString aSS
= mrDoc
.GetSharedStringPool().intern(OUString(pString
));
1826 PushString(svl::SharedString::getEmptyString());
1829 void ScInterpreter::PushString( const OUString
& rStr
)
1831 PushString(mrDoc
.GetSharedStringPool().intern(rStr
));
1834 void ScInterpreter::PushString( const svl::SharedString
& rString
)
1836 if (!IfErrorPushError())
1837 PushTempTokenWithoutError( new FormulaStringToken( rString
) );
1840 void ScInterpreter::PushSingleRef(SCCOL nCol
, SCROW nRow
, SCTAB nTab
)
1842 if (!IfErrorPushError())
1844 ScSingleRefData aRef
;
1845 aRef
.InitAddress(ScAddress(nCol
,nRow
,nTab
));
1846 PushTempTokenWithoutError( new ScSingleRefToken( mrDoc
.GetSheetLimits(), aRef
) );
1850 void ScInterpreter::PushDoubleRef(SCCOL nCol1
, SCROW nRow1
, SCTAB nTab1
,
1851 SCCOL nCol2
, SCROW nRow2
, SCTAB nTab2
)
1853 if (!IfErrorPushError())
1855 ScComplexRefData aRef
;
1856 aRef
.InitRange(ScRange(nCol1
,nRow1
,nTab1
,nCol2
,nRow2
,nTab2
));
1857 PushTempTokenWithoutError( new ScDoubleRefToken( mrDoc
.GetSheetLimits(), aRef
) );
1861 void ScInterpreter::PushExternalSingleRef(
1862 sal_uInt16 nFileId
, const OUString
& rTabName
, SCCOL nCol
, SCROW nRow
, SCTAB nTab
)
1864 if (!IfErrorPushError())
1866 ScSingleRefData aRef
;
1867 aRef
.InitAddress(ScAddress(nCol
,nRow
,nTab
));
1868 PushTempTokenWithoutError( new ScExternalSingleRefToken(nFileId
,
1869 mrDoc
.GetSharedStringPool().intern( rTabName
), aRef
)) ;
1873 void ScInterpreter::PushExternalDoubleRef(
1874 sal_uInt16 nFileId
, const OUString
& rTabName
,
1875 SCCOL nCol1
, SCROW nRow1
, SCTAB nTab1
, SCCOL nCol2
, SCROW nRow2
, SCTAB nTab2
)
1877 if (!IfErrorPushError())
1879 ScComplexRefData aRef
;
1880 aRef
.InitRange(ScRange(nCol1
,nRow1
,nTab1
,nCol2
,nRow2
,nTab2
));
1881 PushTempTokenWithoutError( new ScExternalDoubleRefToken(nFileId
,
1882 mrDoc
.GetSharedStringPool().intern( rTabName
), aRef
) );
1886 void ScInterpreter::PushSingleRef( const ScRefAddress
& rRef
)
1888 if (!IfErrorPushError())
1890 ScSingleRefData aRef
;
1891 aRef
.InitFromRefAddress( mrDoc
, rRef
, aPos
);
1892 PushTempTokenWithoutError( new ScSingleRefToken( mrDoc
.GetSheetLimits(), aRef
) );
1896 void ScInterpreter::PushDoubleRef( const ScRefAddress
& rRef1
, const ScRefAddress
& rRef2
)
1898 if (!IfErrorPushError())
1900 ScComplexRefData aRef
;
1901 aRef
.InitFromRefAddresses( mrDoc
, rRef1
, rRef2
, aPos
);
1902 PushTempTokenWithoutError( new ScDoubleRefToken( mrDoc
.GetSheetLimits(), aRef
) );
1906 void ScInterpreter::PushMatrix( const sc::RangeMatrix
& rMat
)
1908 if (!rMat
.isRangeValid())
1910 // Just push the matrix part only.
1911 PushMatrix(rMat
.mpMat
);
1915 rMat
.mpMat
->SetErrorInterpreter(nullptr);
1916 nGlobalError
= FormulaError::NONE
;
1917 PushTempTokenWithoutError(new ScMatrixRangeToken(rMat
));
1920 void ScInterpreter::PushMatrix(const ScMatrixRef
& pMat
)
1922 pMat
->SetErrorInterpreter( nullptr);
1923 // No if (!IfErrorPushError()) because ScMatrix stores errors itself,
1924 // but with notifying ScInterpreter via nGlobalError, substituting it would
1925 // mean to inherit the error on all array elements in all following
1927 nGlobalError
= FormulaError::NONE
;
1928 PushTempTokenWithoutError( new ScMatrixToken( pMat
) );
1931 void ScInterpreter::PushError( FormulaError nError
)
1933 SetError( nError
); // only sets error if not already set
1934 PushTempTokenWithoutError( new FormulaErrorToken( nGlobalError
));
1937 void ScInterpreter::PushParameterExpected()
1939 PushError( FormulaError::ParameterExpected
);
1942 void ScInterpreter::PushIllegalParameter()
1944 PushError( FormulaError::IllegalParameter
);
1947 void ScInterpreter::PushIllegalArgument()
1949 PushError( FormulaError::IllegalArgument
);
1952 void ScInterpreter::PushNA()
1954 PushError( FormulaError::NotAvailable
);
1957 void ScInterpreter::PushNoValue()
1959 PushError( FormulaError::NoValue
);
1962 bool ScInterpreter::IsMissing() const
1964 return sp
&& pStack
[sp
- 1]->GetType() == svMissing
;
1967 StackVar
ScInterpreter::GetRawStackType()
1972 eRes
= pStack
[sp
- 1]->GetType();
1976 SetError(FormulaError::UnknownStackVariable
);
1982 StackVar
ScInterpreter::GetStackType()
1987 eRes
= pStack
[sp
- 1]->GetType();
1988 if( eRes
== svMissing
|| eRes
== svEmptyCell
)
1989 eRes
= svDouble
; // default!
1993 SetError(FormulaError::UnknownStackVariable
);
1999 StackVar
ScInterpreter::GetStackType( sal_uInt8 nParam
)
2004 eRes
= pStack
[sp
- nParam
]->GetType();
2005 if( eRes
== svMissing
|| eRes
== svEmptyCell
)
2006 eRes
= svDouble
; // default!
2013 void ScInterpreter::ReverseStack( sal_uInt8 nParamCount
)
2015 //reverse order of parameter stack
2016 assert( sp
>= nParamCount
&& " less stack elements than parameters");
2017 sal_uInt16 nStackParams
= std::min
<sal_uInt16
>( sp
, nParamCount
);
2018 std::reverse( pStack
+(sp
-nStackParams
), pStack
+sp
);
2021 bool ScInterpreter::DoubleRefToPosSingleRef( const ScRange
& rRange
, ScAddress
& rAdr
)
2023 // Check for a singleton first - no implicit intersection for them.
2024 if( rRange
.aStart
== rRange
.aEnd
)
2026 rAdr
= rRange
.aStart
;
2034 bOk
= rRange
.aStart
.Tab() == rRange
.aEnd
.Tab();
2036 SetError( FormulaError::IllegalArgument
);
2040 pJumpMatrix
->GetPos( nC
, nR
);
2041 rAdr
.SetCol( sal::static_int_cast
<SCCOL
>( rRange
.aStart
.Col() + nC
) );
2042 rAdr
.SetRow( sal::static_int_cast
<SCROW
>( rRange
.aStart
.Row() + nR
) );
2043 rAdr
.SetTab( rRange
.aStart
.Tab());
2044 bOk
= rRange
.aStart
.Col() <= rAdr
.Col() && rAdr
.Col() <=
2045 rRange
.aEnd
.Col() && rRange
.aStart
.Row() <= rAdr
.Row() &&
2046 rAdr
.Row() <= rRange
.aEnd
.Row();
2048 SetError( FormulaError::NoValue
);
2053 bOk
= ScCompiler::DoubleRefToPosSingleRefScalarCase(rRange
, rAdr
, aPos
);
2056 SetError( FormulaError::NoValue
);
2060 double ScInterpreter::GetDoubleFromMatrix(const ScMatrixRef
& pMat
)
2067 double fVal
= pMat
->GetDoubleWithStringConversion( 0, 0);
2068 FormulaError nErr
= GetDoubleErrorValue( fVal
);
2069 if (nErr
!= FormulaError::NONE
)
2071 // Do not propagate the coded double error, but set nGlobalError in
2072 // case the matrix did not have an error interpreter set.
2079 SCSIZE nCols
, nRows
, nC
, nR
;
2080 pMat
->GetDimensions( nCols
, nRows
);
2081 pJumpMatrix
->GetPos( nC
, nR
);
2082 // Use vector replication for single row/column arrays.
2083 if ( (nC
< nCols
|| nCols
== 1) && (nR
< nRows
|| nRows
== 1) )
2085 double fVal
= pMat
->GetDoubleWithStringConversion( nC
, nR
);
2086 FormulaError nErr
= GetDoubleErrorValue( fVal
);
2087 if (nErr
!= FormulaError::NONE
)
2089 // Do not propagate the coded double error, but set nGlobalError in
2090 // case the matrix did not have an error interpreter set.
2097 SetError( FormulaError::NoValue
);
2101 double ScInterpreter::GetDouble()
2104 switch( GetRawStackType() )
2110 nVal
= ConvertStringToValue( PopString().getString());
2115 PopSingleRef( aAdr
);
2116 ScRefCellValue
aCell(mrDoc
, aAdr
);
2117 nVal
= GetCellValue(aAdr
, aCell
);
2121 { // generate position dependent SingleRef
2123 PopDoubleRef( aRange
);
2125 if ( nGlobalError
== FormulaError::NONE
&& DoubleRefToPosSingleRef( aRange
, aAdr
) )
2127 ScRefCellValue
aCell(mrDoc
, aAdr
);
2128 nVal
= GetCellValue(aAdr
, aCell
);
2134 case svExternalSingleRef
:
2136 ScExternalRefCache::TokenRef pToken
;
2137 PopExternalSingleRef(pToken
);
2138 if (nGlobalError
!= FormulaError::NONE
)
2144 if (pToken
->GetType() == svDouble
|| pToken
->GetType() == svEmptyCell
)
2145 nVal
= pToken
->GetDouble();
2147 nVal
= ConvertStringToValue( pToken
->GetString().getString());
2150 case svExternalDoubleRef
:
2153 PopExternalDoubleRef(pMat
);
2154 if (nGlobalError
!= FormulaError::NONE
)
2160 nVal
= GetDoubleFromMatrix(pMat
);
2165 ScMatrixRef pMat
= PopMatrix();
2166 nVal
= GetDoubleFromMatrix(pMat
);
2180 SetError( FormulaError::IllegalParameter
);
2183 if ( nFuncFmtType
== nCurFmtType
)
2184 nFuncFmtIndex
= nCurFmtIndex
;
2188 double ScInterpreter::GetDoubleWithDefault(double nDefault
)
2190 bool bMissing
= IsMissing();
2191 double nResultVal
= GetDouble();
2193 nResultVal
= nDefault
;
2197 bool ScInterpreter::GetBoolWithDefault(bool bDefault
)
2199 bool bMissing
= IsMissing();
2200 bool bResultVal
= (GetDouble() != 0.0);
2202 bResultVal
= bDefault
;
2206 sal_Int32
ScInterpreter::double_to_int32(double fVal
)
2208 if (!std::isfinite(fVal
))
2210 SetError( GetDoubleErrorValue( fVal
));
2211 return SAL_MAX_INT32
;
2215 fVal
= rtl::math::approxFloor( fVal
);
2216 if (fVal
> SAL_MAX_INT32
)
2218 SetError( FormulaError::IllegalArgument
);
2219 return SAL_MAX_INT32
;
2222 else if (fVal
< 0.0)
2224 fVal
= rtl::math::approxCeil( fVal
);
2225 if (fVal
< SAL_MIN_INT32
)
2227 SetError( FormulaError::IllegalArgument
);
2228 return SAL_MAX_INT32
;
2231 return static_cast<sal_Int32
>(fVal
);
2234 sal_Int32
ScInterpreter::GetInt32()
2236 return double_to_int32(GetDouble());
2239 sal_Int32
ScInterpreter::GetInt32WithDefault( sal_Int32 nDefault
)
2241 bool bMissing
= IsMissing();
2242 double fVal
= GetDouble();
2245 return double_to_int32(fVal
);
2248 sal_Int32
ScInterpreter::GetFloor32()
2250 double fVal
= GetDouble();
2251 if (!std::isfinite(fVal
))
2253 SetError( GetDoubleErrorValue( fVal
));
2254 return SAL_MAX_INT32
;
2256 fVal
= rtl::math::approxFloor( fVal
);
2257 if (fVal
< SAL_MIN_INT32
|| SAL_MAX_INT32
< fVal
)
2259 SetError( FormulaError::IllegalArgument
);
2260 return SAL_MAX_INT32
;
2262 return static_cast<sal_Int32
>(fVal
);
2265 sal_Int16
ScInterpreter::GetInt16()
2267 double fVal
= GetDouble();
2268 if (!std::isfinite(fVal
))
2270 SetError( GetDoubleErrorValue( fVal
));
2271 return SAL_MAX_INT16
;
2275 fVal
= rtl::math::approxFloor( fVal
);
2276 if (fVal
> SAL_MAX_INT16
)
2278 SetError( FormulaError::IllegalArgument
);
2279 return SAL_MAX_INT16
;
2282 else if (fVal
< 0.0)
2284 fVal
= rtl::math::approxCeil( fVal
);
2285 if (fVal
< SAL_MIN_INT16
)
2287 SetError( FormulaError::IllegalArgument
);
2288 return SAL_MAX_INT16
;
2291 return static_cast<sal_Int16
>(fVal
);
2294 sal_uInt32
ScInterpreter::GetUInt32()
2296 double fVal
= rtl::math::approxFloor( GetDouble());
2297 if (!std::isfinite(fVal
))
2299 SetError( GetDoubleErrorValue( fVal
));
2300 return SAL_MAX_UINT32
;
2302 if (fVal
< 0.0 || fVal
> SAL_MAX_UINT32
)
2304 SetError( FormulaError::IllegalArgument
);
2305 return SAL_MAX_UINT32
;
2307 return static_cast<sal_uInt32
>(fVal
);
2310 bool ScInterpreter::GetDoubleOrString( double& rDouble
, svl::SharedString
& rString
)
2312 bool bDouble
= true;
2313 switch( GetRawStackType() )
2316 rDouble
= PopDouble();
2319 rString
= PopString();
2326 if (!PopDoubleRefOrSingleRef( aAdr
))
2329 return true; // caller needs to check nGlobalError
2331 ScRefCellValue
aCell( mrDoc
, aAdr
);
2332 if (aCell
.hasNumeric())
2334 rDouble
= GetCellValue( aAdr
, aCell
);
2338 GetCellString( rString
, aCell
);
2343 case svExternalSingleRef
:
2344 case svExternalDoubleRef
:
2347 ScMatValType nType
= GetDoubleOrStringFromMatrix( rDouble
, rString
);
2348 bDouble
= ScMatrix::IsValueType( nType
);
2362 SetError( FormulaError::IllegalParameter
);
2365 if ( nFuncFmtType
== nCurFmtType
)
2366 nFuncFmtIndex
= nCurFmtIndex
;
2370 svl::SharedString
ScInterpreter::GetString()
2372 switch (GetRawStackType())
2376 return svl::SharedString::getEmptyString();
2380 return svl::SharedString::getEmptyString();
2383 return GetStringFromDouble( PopDouble() );
2390 PopSingleRef( aAdr
);
2391 if (nGlobalError
== FormulaError::NONE
)
2393 ScRefCellValue
aCell(mrDoc
, aAdr
);
2394 svl::SharedString aSS
;
2395 GetCellString(aSS
, aCell
);
2399 return svl::SharedString::getEmptyString();
2402 { // generate position dependent SingleRef
2404 PopDoubleRef( aRange
);
2406 if ( nGlobalError
== FormulaError::NONE
&& DoubleRefToPosSingleRef( aRange
, aAdr
) )
2408 ScRefCellValue
aCell(mrDoc
, aAdr
);
2409 svl::SharedString aSS
;
2410 GetCellString(aSS
, aCell
);
2414 return svl::SharedString::getEmptyString();
2416 case svExternalSingleRef
:
2418 ScExternalRefCache::TokenRef pToken
;
2419 PopExternalSingleRef(pToken
);
2420 if (nGlobalError
!= FormulaError::NONE
)
2421 return svl::SharedString::getEmptyString();
2423 if (pToken
->GetType() == svDouble
)
2425 return GetStringFromDouble( pToken
->GetDouble() );
2427 else // svString or svEmpty
2428 return pToken
->GetString();
2430 case svExternalDoubleRef
:
2433 PopExternalDoubleRef(pMat
);
2434 return GetStringFromMatrix(pMat
);
2438 ScMatrixRef pMat
= PopMatrix();
2439 return GetStringFromMatrix(pMat
);
2444 SetError( FormulaError::IllegalArgument
);
2446 return svl::SharedString::getEmptyString();
2449 svl::SharedString
ScInterpreter::GetStringFromMatrix(const ScMatrixRef
& pMat
)
2453 else if ( !pJumpMatrix
)
2455 return pMat
->GetString( mrContext
, 0, 0);
2459 SCSIZE nCols
, nRows
, nC
, nR
;
2460 pMat
->GetDimensions( nCols
, nRows
);
2461 pJumpMatrix
->GetPos( nC
, nR
);
2462 // Use vector replication for single row/column arrays.
2463 if ( (nC
< nCols
|| nCols
== 1) && (nR
< nRows
|| nRows
== 1) )
2464 return pMat
->GetString( mrContext
, nC
, nR
);
2466 SetError( FormulaError::NoValue
);
2468 return svl::SharedString::getEmptyString();
2471 ScMatValType
ScInterpreter::GetDoubleOrStringFromMatrix(
2472 double& rDouble
, svl::SharedString
& rString
)
2476 rString
= svl::SharedString::getEmptyString();
2477 ScMatValType nMatValType
= ScMatValType::Empty
;
2480 StackVar eType
= GetStackType();
2481 if (eType
== svExternalDoubleRef
|| eType
== svExternalSingleRef
|| eType
== svMatrix
)
2488 SetError( FormulaError::IllegalParameter
);
2492 ScMatrixValue nMatVal
;
2497 else if (!pJumpMatrix
)
2499 nMatVal
= pMat
->Get(0, 0);
2500 nMatValType
= nMatVal
.nType
;
2504 SCSIZE nCols
, nRows
, nC
, nR
;
2505 pMat
->GetDimensions( nCols
, nRows
);
2506 pJumpMatrix
->GetPos( nC
, nR
);
2507 // Use vector replication for single row/column arrays.
2508 if ( (nC
< nCols
|| nCols
== 1) && (nR
< nRows
|| nRows
== 1) )
2510 nMatVal
= pMat
->Get( nC
, nR
);
2511 nMatValType
= nMatVal
.nType
;
2514 SetError( FormulaError::NoValue
);
2517 if (ScMatrix::IsValueType( nMatValType
))
2519 rDouble
= nMatVal
.fVal
;
2520 FormulaError nError
= nMatVal
.GetError();
2521 if (nError
!= FormulaError::NONE
)
2526 rString
= nMatVal
.GetString();
2532 svl::SharedString
ScInterpreter::GetStringFromDouble( double fVal
)
2534 sal_uLong nIndex
= mrContext
.NFGetStandardFormat(
2535 SvNumFormatType::NUMBER
,
2537 return mrStrPool
.intern(mrContext
.NFGetInputLineString(fVal
, nIndex
));
2540 void ScInterpreter::ScDBGet()
2542 bool bMissingField
= false;
2543 unique_ptr
<ScDBQueryParamBase
> pQueryParam( GetDBParams(bMissingField
) );
2546 // Failed to create query param.
2547 PushIllegalParameter();
2551 pQueryParam
->mbSkipString
= false;
2552 ScDBQueryDataIterator
aValIter(mrDoc
, mrContext
, std::move(pQueryParam
));
2553 ScDBQueryDataIterator::Value aValue
;
2554 if (!aValIter
.GetFirst(aValue
) || aValue
.mnError
!= FormulaError::NONE
)
2561 ScDBQueryDataIterator::Value aValNext
;
2562 if (aValIter
.GetNext(aValNext
) && aValNext
.mnError
== FormulaError::NONE
)
2564 // There should be only one unique match.
2565 PushIllegalArgument();
2569 if (aValue
.mbIsNumber
)
2570 PushDouble(aValue
.mfValue
);
2572 PushString(aValue
.maString
);
2575 void ScInterpreter::ScExternal()
2577 sal_uInt8 nParamCount
= GetByte();
2579 OUString
aFuncName( pCur
->GetExternal().toAsciiUpperCase()); // programmatic name
2580 LegacyFuncData
* pLegacyFuncData
= ScGlobal::GetLegacyFuncCollection()->findByName(aFuncName
);
2581 if (pLegacyFuncData
)
2583 // Old binary non-UNO add-in function.
2584 // NOTE: parameter count is 1-based with the 0th "parameter" being the
2585 // return value, included in pLegacyFuncDatat->GetParamCount()
2586 if (nParamCount
< MAXFUNCPARAM
&& nParamCount
== pLegacyFuncData
->GetParamCount() - 1)
2588 ParamType eParamType
[MAXFUNCPARAM
];
2589 void* ppParam
[MAXFUNCPARAM
];
2590 double nVal
[MAXFUNCPARAM
];
2591 char* pStr
[MAXFUNCPARAM
];
2592 sal_uInt8
* pCellArr
[MAXFUNCPARAM
];
2595 for (i
= 0; i
< MAXFUNCPARAM
; i
++)
2597 eParamType
[i
] = pLegacyFuncData
->GetParamType(i
);
2598 ppParam
[i
] = nullptr;
2601 pCellArr
[i
] = nullptr;
2604 for (i
= nParamCount
; (i
> 0) && (nGlobalError
== FormulaError::NONE
); i
--)
2608 // Old binary Add-In can't distinguish between missing
2609 // omitted argument and 0 (or any other value). Force
2611 SetError( FormulaError::ParameterExpected
);
2614 switch (eParamType
[i
])
2616 case ParamType::PTR_DOUBLE
:
2618 nVal
[i
-1] = GetDouble();
2619 ppParam
[i
] = &nVal
[i
-1];
2622 case ParamType::PTR_STRING
:
2624 OString
aStr(OUStringToOString(GetString().getString(),
2625 osl_getThreadTextEncoding()));
2626 if ( aStr
.getLength() >= ADDIN_MAXSTRLEN
)
2627 SetError( FormulaError::StringOverflow
);
2630 pStr
[i
-1] = new char[ADDIN_MAXSTRLEN
];
2631 strncpy( pStr
[i
-1], aStr
.getStr(), ADDIN_MAXSTRLEN
);
2632 pStr
[i
-1][ADDIN_MAXSTRLEN
-1] = 0;
2633 ppParam
[i
] = pStr
[i
-1];
2637 case ParamType::PTR_DOUBLE_ARR
:
2645 PopDoubleRef(nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
2646 pCellArr
[i
-1] = new sal_uInt8
[MAXARRSIZE
];
2647 if (!CreateDoubleArr(nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
, pCellArr
[i
-1]))
2648 SetError(FormulaError::CodeOverflow
);
2650 ppParam
[i
] = pCellArr
[i
-1];
2653 case ParamType::PTR_STRING_ARR
:
2661 PopDoubleRef(nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
2662 pCellArr
[i
-1] = new sal_uInt8
[MAXARRSIZE
];
2663 if (!CreateStringArr(nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
, pCellArr
[i
-1]))
2664 SetError(FormulaError::CodeOverflow
);
2666 ppParam
[i
] = pCellArr
[i
-1];
2669 case ParamType::PTR_CELL_ARR
:
2677 PopDoubleRef(nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
2678 pCellArr
[i
-1] = new sal_uInt8
[MAXARRSIZE
];
2679 if (!CreateCellArr(nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
, pCellArr
[i
-1]))
2680 SetError(FormulaError::CodeOverflow
);
2682 ppParam
[i
] = pCellArr
[i
-1];
2686 SetError(FormulaError::IllegalParameter
);
2691 Pop(); // In case of error (otherwise i==0) pop all parameters
2693 if (nGlobalError
== FormulaError::NONE
)
2695 if ( pLegacyFuncData
->GetAsyncType() == ParamType::NONE
)
2697 switch ( eParamType
[0] )
2699 case ParamType::PTR_DOUBLE
:
2703 pLegacyFuncData
->Call(ppParam
);
2707 case ParamType::PTR_STRING
:
2709 std::unique_ptr
<char[]> pcErg(new char[ADDIN_MAXSTRLEN
]);
2710 ppParam
[0] = pcErg
.get();
2711 pLegacyFuncData
->Call(ppParam
);
2712 OUString
aUni( pcErg
.get(), strlen(pcErg
.get()), osl_getThreadTextEncoding() );
2717 PushError( FormulaError::UnknownState
);
2722 // enable asyncs after loading
2723 pArr
->AddRecalcMode( ScRecalcMode::ONLOAD_LENIENT
);
2724 // assure identical handler with identical call?
2727 pLegacyFuncData
->Call(ppParam
);
2728 sal_uLong nHandle
= sal_uLong( nErg
);
2729 if ( nHandle
>= 65536 )
2731 ScAddInAsync
* pAs
= ScAddInAsync::Get( nHandle
);
2734 pAs
= new ScAddInAsync(nHandle
, pLegacyFuncData
, &mrDoc
);
2735 pMyFormulaCell
->StartListening( *pAs
);
2739 pMyFormulaCell
->StartListening( *pAs
);
2740 if ( !pAs
->HasDocument( &mrDoc
) )
2741 pAs
->AddDocument( &mrDoc
);
2743 if ( pAs
->IsValid() )
2745 switch ( pAs
->GetType() )
2747 case ParamType::PTR_DOUBLE
:
2748 PushDouble( pAs
->GetValue() );
2750 case ParamType::PTR_STRING
:
2751 PushString( pAs
->GetString() );
2754 PushError( FormulaError::UnknownState
);
2765 for (i
= 0; i
< MAXFUNCPARAM
; i
++)
2768 delete[] pCellArr
[i
];
2773 while( nParamCount
-- > 0)
2775 PushIllegalParameter();
2778 else if ( !( aUnoName
= ScGlobal::GetAddInCollection()->FindFunction(aFuncName
, false) ).isEmpty() )
2780 // bLocalFirst=false in FindFunction, cFunc should be the stored
2783 ScUnoAddInCall
aCall( mrDoc
, *ScGlobal::GetAddInCollection(), aUnoName
, nParamCount
);
2785 if ( !aCall
.ValidParamCount() )
2786 SetError( FormulaError::IllegalParameter
);
2788 if ( aCall
.NeedsCaller() && GetError() == FormulaError::NONE
)
2790 ScDocShell
* pShell
= mrDoc
.GetDocumentShell();
2792 aCall
.SetCallerFromObjectShell( pShell
);
2795 // use temporary model object (without document) to supply options
2796 aCall
.SetCaller( static_cast<beans::XPropertySet
*>(
2797 new ScDocOptionsObj( mrDoc
.GetDocOptions() ) ) );
2801 short nPar
= nParamCount
;
2802 while ( nPar
> 0 && GetError() == FormulaError::NONE
)
2804 --nPar
; // 0 .. (nParamCount-1)
2809 // Add-In has to explicitly handle an omitted empty missing
2810 // argument, do not default to anything like GetDouble() would
2813 aCall
.SetParam( nPar
, aParam
);
2817 StackVar nStackType
= GetStackType();
2818 ScAddInArgumentType eType
= aCall
.GetArgType( nPar
);
2821 case SC_ADDINARG_INTEGER
:
2823 sal_Int32 nVal
= GetInt32();
2824 if (nGlobalError
== FormulaError::NONE
)
2829 case SC_ADDINARG_DOUBLE
:
2830 aParam
<<= GetDouble();
2833 case SC_ADDINARG_STRING
:
2834 aParam
<<= GetString().getString();
2837 case SC_ADDINARG_INTEGER_ARRAY
:
2838 switch( nStackType
)
2844 sal_Int32 nVal
= GetInt32();
2845 if (nGlobalError
== FormulaError::NONE
)
2847 uno::Sequence
<sal_Int32
> aInner( &nVal
, 1 );
2848 uno::Sequence
< uno::Sequence
<sal_Int32
> > aOuter( &aInner
, 1 );
2856 PopDoubleRef( aRange
);
2857 if (!ScRangeToSequence::FillLongArray( aParam
, mrDoc
, aRange
))
2858 SetError(FormulaError::IllegalParameter
);
2862 if (!ScRangeToSequence::FillLongArray( aParam
, PopMatrix().get() ))
2863 SetError(FormulaError::IllegalParameter
);
2867 SetError(FormulaError::IllegalParameter
);
2871 case SC_ADDINARG_DOUBLE_ARRAY
:
2872 switch( nStackType
)
2878 double fVal
= GetDouble();
2879 uno::Sequence
<double> aInner( &fVal
, 1 );
2880 uno::Sequence
< uno::Sequence
<double> > aOuter( &aInner
, 1 );
2887 PopDoubleRef( aRange
);
2888 if (!ScRangeToSequence::FillDoubleArray( aParam
, mrDoc
, aRange
))
2889 SetError(FormulaError::IllegalParameter
);
2893 if (!ScRangeToSequence::FillDoubleArray( aParam
, PopMatrix().get() ))
2894 SetError(FormulaError::IllegalParameter
);
2898 SetError(FormulaError::IllegalParameter
);
2902 case SC_ADDINARG_STRING_ARRAY
:
2903 switch( nStackType
)
2909 OUString aString
= GetString().getString();
2910 uno::Sequence
<OUString
> aInner( &aString
, 1 );
2911 uno::Sequence
< uno::Sequence
<OUString
> > aOuter( &aInner
, 1 );
2918 PopDoubleRef( aRange
);
2919 if (!ScRangeToSequence::FillStringArray( aParam
, mrDoc
, aRange
))
2920 SetError(FormulaError::IllegalParameter
);
2924 if (!ScRangeToSequence::FillStringArray( aParam
, PopMatrix().get(), mrContext
))
2925 SetError(FormulaError::IllegalParameter
);
2929 SetError(FormulaError::IllegalParameter
);
2933 case SC_ADDINARG_MIXED_ARRAY
:
2934 switch( nStackType
)
2941 if ( nStackType
== svDouble
)
2942 aElem
<<= GetDouble();
2943 else if ( nStackType
== svString
)
2944 aElem
<<= GetString().getString();
2948 if ( PopDoubleRefOrSingleRef( aAdr
) )
2950 ScRefCellValue
aCell(mrDoc
, aAdr
);
2951 if (aCell
.hasString())
2953 svl::SharedString aStr
;
2954 GetCellString(aStr
, aCell
);
2955 aElem
<<= aStr
.getString();
2958 aElem
<<= GetCellValue(aAdr
, aCell
);
2961 uno::Sequence
<uno::Any
> aInner( &aElem
, 1 );
2962 uno::Sequence
< uno::Sequence
<uno::Any
> > aOuter( &aInner
, 1 );
2969 PopDoubleRef( aRange
);
2970 if (!ScRangeToSequence::FillMixedArray( aParam
, mrDoc
, aRange
))
2971 SetError(FormulaError::IllegalParameter
);
2975 if (!ScRangeToSequence::FillMixedArray( aParam
, PopMatrix().get() ))
2976 SetError(FormulaError::IllegalParameter
);
2980 SetError(FormulaError::IllegalParameter
);
2984 case SC_ADDINARG_VALUE_OR_ARRAY
:
2985 switch( nStackType
)
2988 aParam
<<= GetDouble();
2991 aParam
<<= GetString().getString();
2996 if ( PopDoubleRefOrSingleRef( aAdr
) )
2998 ScRefCellValue
aCell(mrDoc
, aAdr
);
2999 if (aCell
.hasString())
3001 svl::SharedString aStr
;
3002 GetCellString(aStr
, aCell
);
3003 aParam
<<= aStr
.getString();
3006 aParam
<<= GetCellValue(aAdr
, aCell
);
3013 PopDoubleRef( aRange
);
3014 if (!ScRangeToSequence::FillMixedArray( aParam
, mrDoc
, aRange
))
3015 SetError(FormulaError::IllegalParameter
);
3019 if (!ScRangeToSequence::FillMixedArray( aParam
, PopMatrix().get() ))
3020 SetError(FormulaError::IllegalParameter
);
3024 SetError(FormulaError::IllegalParameter
);
3028 case SC_ADDINARG_CELLRANGE
:
3029 switch( nStackType
)
3034 PopSingleRef( aAdr
);
3035 ScRange
aRange( aAdr
);
3036 uno::Reference
<table::XCellRange
> xObj
=
3037 ScCellRangeObj::CreateRangeFromDoc( mrDoc
, aRange
);
3041 SetError(FormulaError::IllegalParameter
);
3047 PopDoubleRef( aRange
);
3048 uno::Reference
<table::XCellRange
> xObj
=
3049 ScCellRangeObj::CreateRangeFromDoc( mrDoc
, aRange
);
3056 SetError(FormulaError::IllegalParameter
);
3062 SetError(FormulaError::IllegalParameter
);
3068 SetError(FormulaError::IllegalParameter
);
3070 aCall
.SetParam( nPar
, aParam
);
3075 Pop(); // in case of error, remove remaining args
3077 if ( GetError() == FormulaError::NONE
)
3079 aCall
.ExecuteCall();
3081 if ( aCall
.HasVarRes() ) // handle async functions
3083 pArr
->AddRecalcMode( ScRecalcMode::ONLOAD_LENIENT
);
3084 uno::Reference
<sheet::XVolatileResult
> xRes
= aCall
.GetVarRes();
3085 ScAddInListener
* pLis
= ScAddInListener::Get( xRes
);
3086 // In case there is no pMyFormulaCell, i.e. while interpreting
3087 // temporarily from within the Function Wizard, try to obtain a
3088 // valid result from an existing listener for that volatile, or
3089 // create a new and hope for an immediate result. If none
3090 // available that should lead to a void result and thus #N/A.
3091 bool bTemporaryListener
= false;
3094 pLis
= ScAddInListener::CreateListener( xRes
, &mrDoc
);
3096 pMyFormulaCell
->StartListening( *pLis
);
3098 bTemporaryListener
= true;
3100 else if (pMyFormulaCell
)
3102 pMyFormulaCell
->StartListening( *pLis
);
3103 if ( !pLis
->HasDocument( &mrDoc
) )
3105 pLis
->AddDocument( &mrDoc
);
3109 aCall
.SetResult( pLis
->GetResult() ); // use result from async
3111 if (bTemporaryListener
)
3115 // EventObject can be any, not evaluated by
3116 // ScAddInListener::disposing()
3117 css::lang::EventObject aEvent
;
3118 pLis
->disposing(aEvent
); // pLis is dead hereafter
3120 catch (const uno::Exception
&)
3126 if ( aCall
.GetErrCode() != FormulaError::NONE
)
3128 PushError( aCall
.GetErrCode() );
3130 else if ( aCall
.HasMatrix() )
3132 PushMatrix( aCall
.GetMatrix() );
3134 else if ( aCall
.HasString() )
3136 PushString( aCall
.GetString() );
3140 PushDouble( aCall
.GetValue() );
3144 PushError( GetError());
3148 while( nParamCount
-- > 0)
3152 PushError( FormulaError::NoAddin
);
3156 void ScInterpreter::ScMissing()
3158 if ( aCode
.IsEndOfPath() )
3159 PushTempToken( new ScEmptyCellToken( false, false ) );
3161 PushTempToken( new FormulaMissingToken
);
3164 #if HAVE_FEATURE_SCRIPTING
3166 static uno::Any
lcl_getSheetModule( const uno::Reference
<table::XCellRange
>& xCellRange
, const ScDocument
* pDok
)
3168 uno::Reference
< sheet::XSheetCellRange
> xSheetRange( xCellRange
, uno::UNO_QUERY_THROW
);
3169 uno::Reference
< beans::XPropertySet
> xProps( xSheetRange
->getSpreadsheet(), uno::UNO_QUERY_THROW
);
3171 xProps
->getPropertyValue(u
"CodeName"_ustr
) >>= sCodeName
;
3172 // #TODO #FIXME ideally we should 'throw' here if we don't get a valid parent, but... it is possible
3173 // to create a module ( and use 'Option VBASupport 1' ) for a calc document, in this scenario there
3174 // are *NO* special document module objects ( of course being able to switch between vba/non vba mode at
3175 // the document in the future could fix this, especially IF the switching of the vba mode takes care to
3176 // create the special document module objects if they don't exist.
3177 BasicManager
* pBasMgr
= pDok
->GetDocumentShell()->GetBasicManager();
3179 uno::Reference
< uno::XInterface
> xIf
;
3180 if ( pBasMgr
&& !pBasMgr
->GetName().isEmpty() )
3182 OUString
sProj( u
"Standard"_ustr
);
3183 if ( !pDok
->GetDocumentShell()->GetBasicManager()->GetName().isEmpty() )
3185 sProj
= pDok
->GetDocumentShell()->GetBasicManager()->GetName();
3187 StarBASIC
* pBasic
= pDok
->GetDocumentShell()->GetBasicManager()->GetLib( sProj
);
3190 SbModule
* pMod
= pBasic
->FindModule( sCodeName
);
3193 xIf
= pMod
->GetUnoModule();
3197 return uno::Any( xIf
);
3200 static bool lcl_setVBARange( const ScRange
& aRange
, const ScDocument
& rDok
, SbxVariable
* pPar
)
3205 uno::Reference
< uno::XInterface
> xVBARange
;
3206 uno::Reference
<table::XCellRange
> xCellRange
= ScCellRangeObj::CreateRangeFromDoc( rDok
, aRange
);
3207 uno::Sequence
< uno::Any
> aArgs
{ lcl_getSheetModule( xCellRange
, &rDok
),
3208 uno::Any(xCellRange
) };
3209 xVBARange
= ooo::vba::createVBAUnoAPIServiceWithArgs( rDok
.GetDocumentShell(), "ooo.vba.excel.Range", aArgs
);
3210 if ( xVBARange
.is() )
3212 SbxObjectRef aObj
= GetSbUnoObject( u
"A-Range"_ustr
, uno::Any( xVBARange
) );
3213 SetSbUnoObjectDfltPropName( aObj
.get() );
3214 bOk
= pPar
->PutObject( aObj
.get() );
3217 catch( uno::Exception
& )
3223 static bool lcl_isNumericResult( double& fVal
, const SbxVariable
* pVar
)
3225 switch (pVar
->GetType())
3240 fVal
= pVar
->GetDouble();
3243 fVal
= (pVar
->GetBool() ? 1.0 : 0.0);
3253 void ScInterpreter::ScMacro()
3256 #if !HAVE_FEATURE_SCRIPTING
3257 PushNoValue(); // without DocShell no CallBasic
3260 SbxBase::ResetError();
3262 sal_uInt8 nParamCount
= GetByte();
3263 OUString
aMacro( pCur
->GetExternal() );
3265 ScDocShell
* pDocSh
= mrDoc
.GetDocumentShell();
3268 PushNoValue(); // without DocShell no CallBasic
3272 // no security queue beforehand (just CheckMacroWarn), moved to CallBasic
3274 // If the Dok was loaded during a Basic-Calls,
3275 // is the Sbx-object created(?)
3276 // pDocSh->GetSbxObject();
3278 // search function with the name,
3279 // then assemble SfxObjectShell::CallBasic from aBasicStr, aMacroStr
3285 pRoot
= pDocSh
->GetBasic();
3292 SbxVariable
* pVar
= pRoot
? pRoot
->Find(aMacro
, SbxClassType::Method
) : nullptr;
3293 if( !pVar
|| pVar
->GetType() == SbxVOID
)
3295 PushError( FormulaError::NoMacro
);
3298 SbMethod
* pMethod
= dynamic_cast<SbMethod
*>(pVar
);
3301 PushError( FormulaError::NoMacro
);
3305 bool bVolatileMacro
= false;
3307 SbModule
* pModule
= pMethod
->GetModule();
3308 bool bUseVBAObjects
= pModule
->IsVBASupport();
3309 SbxObject
* pObject
= pModule
->GetParent();
3311 OSL_ENSURE(dynamic_cast<const StarBASIC
*>(pObject
) != nullptr, "No Basic found!");
3312 OUString aMacroStr
= pObject
->GetName() + "." + pModule
->GetName() + "." + pMethod
->GetName();
3314 if (pRoot
&& bUseVBAObjects
)
3316 // just here to make sure the VBA objects when we run the macro during ODF import
3317 pRoot
->getVBAGlobals();
3319 if (pObject
->GetParent())
3321 aBasicStr
= pObject
->GetParent()->GetName(); // document BASIC
3325 aBasicStr
= SfxGetpApp()->GetName(); // application BASIC
3327 // assemble a parameter array
3329 SbxArrayRef refPar
= new SbxArray
;
3331 for( sal_uInt32 i
= nParamCount
; i
&& bOk
; i
-- )
3333 SbxVariable
* pPar
= refPar
->Get(i
);
3334 switch( GetStackType() )
3337 pPar
->PutDouble( GetDouble() );
3340 pPar
->PutString( GetString().getString() );
3342 case svExternalSingleRef
:
3344 ScExternalRefCache::TokenRef pToken
;
3345 PopExternalSingleRef(pToken
);
3346 if (nGlobalError
!= FormulaError::NONE
)
3350 if ( pToken
->GetType() == svString
)
3351 pPar
->PutString( pToken
->GetString().getString() );
3352 else if ( pToken
->GetType() == svDouble
)
3353 pPar
->PutDouble( pToken
->GetDouble() );
3356 SetError( FormulaError::IllegalArgument
);
3365 PopSingleRef( aAdr
);
3366 if ( bUseVBAObjects
)
3368 ScRange
aRange( aAdr
);
3369 bOk
= lcl_setVBARange( aRange
, mrDoc
, pPar
);
3373 bOk
= SetSbxVariable( pPar
, aAdr
);
3385 PopDoubleRef( nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
3386 if( nTab1
!= nTab2
)
3388 SetError( FormulaError::IllegalParameter
);
3393 if ( bUseVBAObjects
)
3395 ScRange
aRange( nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
3396 bOk
= lcl_setVBARange( aRange
, mrDoc
, pPar
);
3400 SbxDimArrayRef refArray
= new SbxDimArray
;
3401 refArray
->AddDim(1, nRow2
- nRow1
+ 1);
3402 refArray
->AddDim(1, nCol2
- nCol1
+ 1);
3403 ScAddress
aAdr( nCol1
, nRow1
, nTab1
);
3404 for( SCROW nRow
= nRow1
; bOk
&& nRow
<= nRow2
; nRow
++ )
3406 aAdr
.SetRow( nRow
);
3407 sal_Int32 nIdx
[ 2 ];
3408 nIdx
[ 0 ] = nRow
-nRow1
+1;
3409 for( SCCOL nCol
= nCol1
; bOk
&& nCol
<= nCol2
; nCol
++ )
3411 aAdr
.SetCol( nCol
);
3412 nIdx
[ 1 ] = nCol
-nCol1
+1;
3413 SbxVariable
* p
= refArray
->Get(nIdx
);
3414 bOk
= SetSbxVariable( p
, aAdr
);
3417 pPar
->PutObject( refArray
.get() );
3422 case svExternalDoubleRef
:
3425 ScMatrixRef pMat
= GetMatrix();
3427 if (pMat
&& nGlobalError
== FormulaError::NONE
)
3429 pMat
->GetDimensions(nC
, nR
);
3430 SbxDimArrayRef refArray
= new SbxDimArray
;
3431 refArray
->AddDim(1, static_cast<sal_Int32
>(nR
));
3432 refArray
->AddDim(1, static_cast<sal_Int32
>(nC
));
3433 for( SCSIZE nMatRow
= 0; nMatRow
< nR
; nMatRow
++ )
3435 sal_Int32 nIdx
[ 2 ];
3436 nIdx
[ 0 ] = static_cast<sal_Int32
>(nMatRow
+1);
3437 for( SCSIZE nMatCol
= 0; nMatCol
< nC
; nMatCol
++ )
3439 nIdx
[ 1 ] = static_cast<sal_Int32
>(nMatCol
+1);
3440 SbxVariable
* p
= refArray
->Get(nIdx
);
3441 if (pMat
->IsStringOrEmpty(nMatCol
, nMatRow
))
3443 p
->PutString( pMat
->GetString(nMatCol
, nMatRow
).getString() );
3447 p
->PutDouble( pMat
->GetDouble(nMatCol
, nMatRow
));
3451 pPar
->PutObject( refArray
.get() );
3455 SetError( FormulaError::IllegalParameter
);
3460 SetError( FormulaError::IllegalParameter
);
3466 mrDoc
.LockTable( aPos
.Tab() );
3467 SbxVariableRef refRes
= new SbxVariable
;
3468 mrDoc
.IncMacroInterpretLevel();
3469 ErrCode eRet
= pDocSh
->CallBasic( aMacroStr
, aBasicStr
, refPar
.get(), refRes
.get() );
3470 mrDoc
.DecMacroInterpretLevel();
3471 mrDoc
.UnlockTable( aPos
.Tab() );
3473 ScMacroManager
* pMacroMgr
= mrDoc
.GetMacroManager();
3476 bVolatileMacro
= pMacroMgr
->GetUserFuncVolatile( pMethod
->GetName() );
3477 pMacroMgr
->AddDependentCell(pModule
->GetName(), pMyFormulaCell
);
3481 SbxDataType eResType
= refRes
->GetType();
3482 if( SbxBase::GetError() )
3484 SetError( FormulaError::NoValue
);
3486 if ( eRet
!= ERRCODE_NONE
)
3490 else if (lcl_isNumericResult( fVal
, refRes
.get()))
3495 nFuncFmtType
= SvNumFormatType::DATE
;
3498 nFuncFmtType
= SvNumFormatType::LOGICAL
;
3500 // Do not add SbxCURRENCY, we don't know which currency.
3506 else if ( eResType
& SbxARRAY
)
3508 SbxBase
* pElemObj
= refRes
->GetObject();
3509 SbxDimArray
* pDimArray
= dynamic_cast<SbxDimArray
*>(pElemObj
);
3510 sal_Int32 nDim
= pDimArray
? pDimArray
->GetDims() : 0;
3511 if ( 1 <= nDim
&& nDim
<= 2 )
3513 sal_Int32 nCs
, nCe
, nRs
;
3518 { // array( cols ) one line, several columns
3519 pDimArray
->GetDim(1, nCs
, nCe
);
3520 nC
= static_cast<SCSIZE
>(nCe
- nCs
+ 1);
3527 { // array( rows, cols )
3529 pDimArray
->GetDim(1, nRs
, nRe
);
3530 nR
= static_cast<SCSIZE
>(nRe
- nRs
+ 1);
3531 pDimArray
->GetDim(2, nCs
, nCe
);
3532 nC
= static_cast<SCSIZE
>(nCe
- nCs
+ 1);
3536 ScMatrixRef pMat
= GetNewMat( nC
, nR
, /*bEmpty*/true);
3540 for ( SCSIZE j
=0; j
< nR
; j
++ )
3542 sal_Int32 nIdx
[ 2 ];
3543 // in one-dimensional array( cols ) nIdx[1]
3544 // from SbxDimArray::Get is ignored
3545 nIdx
[ nRowIdx
] = nRs
+ static_cast<sal_Int32
>(j
);
3546 for ( SCSIZE i
=0; i
< nC
; i
++ )
3548 nIdx
[ nColIdx
] = nCs
+ static_cast<sal_Int32
>(i
);
3549 pV
= pDimArray
->Get(nIdx
);
3550 if ( lcl_isNumericResult( fVal
, pV
) )
3552 pMat
->PutDouble( fVal
, i
, j
);
3556 pMat
->PutString(mrStrPool
.intern(pV
->GetOUString()), i
, j
);
3564 PushIllegalArgument();
3574 PushString( refRes
->GetOUString() );
3578 if (bVolatileMacro
&& meVolatileType
== NOT_VOLATILE
)
3579 meVolatileType
= VOLATILE_MACRO
;
3583 #if HAVE_FEATURE_SCRIPTING
3585 bool ScInterpreter::SetSbxVariable( SbxVariable
* pVar
, const ScAddress
& rPos
)
3588 ScRefCellValue
aCell(mrDoc
, rPos
);
3589 if (!aCell
.isEmpty())
3593 switch (aCell
.getType())
3595 case CELLTYPE_VALUE
:
3596 nVal
= GetValueCellValue(rPos
, aCell
.getDouble());
3597 pVar
->PutDouble( nVal
);
3599 case CELLTYPE_STRING
:
3600 case CELLTYPE_EDIT
:
3601 pVar
->PutString(aCell
.getString(&mrDoc
));
3603 case CELLTYPE_FORMULA
:
3604 nErr
= aCell
.getFormula()->GetErrCode();
3605 if( nErr
== FormulaError::NONE
)
3607 if (aCell
.getFormula()->IsValue())
3609 nVal
= aCell
.getFormula()->GetValue();
3610 pVar
->PutDouble( nVal
);
3613 pVar
->PutString(aCell
.getFormula()->GetString().getString());
3633 void ScInterpreter::ScTableOp()
3635 sal_uInt8 nParamCount
= GetByte();
3636 if (nParamCount
!= 3 && nParamCount
!= 5)
3638 PushIllegalParameter();
3641 ScInterpreterTableOpParams aTableOp
;
3642 if (nParamCount
== 5)
3644 PopSingleRef( aTableOp
.aNew2
);
3645 PopSingleRef( aTableOp
.aOld2
);
3647 PopSingleRef( aTableOp
.aNew1
);
3648 PopSingleRef( aTableOp
.aOld1
);
3649 PopSingleRef( aTableOp
.aFormulaPos
);
3651 aTableOp
.bValid
= true;
3652 mrDoc
.m_TableOpList
.push_back(&aTableOp
);
3653 mrDoc
.IncInterpreterTableOpLevel();
3655 bool bReuseLastParams
= (mrDoc
.aLastTableOpParams
== aTableOp
);
3656 if ( bReuseLastParams
)
3658 aTableOp
.aNotifiedFormulaPos
= mrDoc
.aLastTableOpParams
.aNotifiedFormulaPos
;
3659 aTableOp
.bRefresh
= true;
3660 for ( const auto& rPos
: aTableOp
.aNotifiedFormulaPos
)
3661 { // emulate broadcast and indirectly collect cell pointers
3662 ScRefCellValue
aCell(mrDoc
, rPos
);
3663 if (aCell
.getType() == CELLTYPE_FORMULA
)
3664 aCell
.getFormula()->SetTableOpDirty();
3668 { // broadcast and indirectly collect cell pointers and positions
3669 mrDoc
.SetTableOpDirty( ScRange(aTableOp
.aOld1
) );
3670 if ( nParamCount
== 5 )
3671 mrDoc
.SetTableOpDirty( ScRange(aTableOp
.aOld2
) );
3673 aTableOp
.bCollectNotifications
= false;
3675 ScRefCellValue
aCell(mrDoc
, aTableOp
.aFormulaPos
);
3676 if (aCell
.getType() == CELLTYPE_FORMULA
)
3677 aCell
.getFormula()->SetDirtyVar();
3678 if (aCell
.hasNumeric())
3680 PushDouble(GetCellValue(aTableOp
.aFormulaPos
, aCell
));
3684 svl::SharedString aCellString
;
3685 GetCellString(aCellString
, aCell
);
3686 PushString( aCellString
);
3690 ::std::find(mrDoc
.m_TableOpList
.begin(), mrDoc
.m_TableOpList
.end(), &aTableOp
);
3691 if (itr
!= mrDoc
.m_TableOpList
.end())
3693 mrDoc
.m_TableOpList
.erase(itr
);
3696 // set dirty again once more to be able to recalculate original
3697 for ( const auto& pCell
: aTableOp
.aNotifiedFormulaCells
)
3699 pCell
->SetTableOpDirty();
3702 // save these params for next incarnation
3703 if ( !bReuseLastParams
)
3704 mrDoc
.aLastTableOpParams
= aTableOp
;
3706 if (aCell
.getType() == CELLTYPE_FORMULA
)
3708 aCell
.getFormula()->SetDirtyVar();
3709 aCell
.getFormula()->GetErrCode(); // recalculate original
3712 // Reset all dirty flags so next incarnation does really collect all cell
3713 // pointers during notifications and not just non-dirty ones, which may
3714 // happen if a formula cell is used by more than one TableOp block.
3715 for ( const auto& pCell
: aTableOp
.aNotifiedFormulaCells
)
3717 pCell
->ResetTableOpDirtyVar();
3720 mrDoc
.DecInterpreterTableOpLevel();
3723 void ScInterpreter::ScDBArea()
3725 ScDBData
* pDBData
= mrDoc
.GetDBCollection()->getNamedDBs().findByIndex(pCur
->GetIndex());
3728 ScComplexRefData aRefData
;
3729 aRefData
.InitFlags();
3731 pDBData
->GetArea(aRange
);
3732 aRange
.aEnd
.SetTab(aRange
.aStart
.Tab());
3733 aRefData
.SetRange(mrDoc
.GetSheetLimits(), aRange
, aPos
);
3734 PushTempToken( new ScDoubleRefToken( mrDoc
.GetSheetLimits(), aRefData
) );
3737 PushError( FormulaError::NoName
);
3740 void ScInterpreter::ScColRowNameAuto()
3742 ScComplexRefData
aRefData( *pCur
->GetDoubleRef() );
3743 ScRange aAbs
= aRefData
.toAbs(mrDoc
, aPos
);
3744 if (!mrDoc
.ValidRange(aAbs
))
3746 PushError( FormulaError::NoRef
);
3753 // maybe remember limit by using defined ColRowNameRange
3754 SCCOL nCol2
= aAbs
.aEnd
.Col();
3755 SCROW nRow2
= aAbs
.aEnd
.Row();
3756 // DataArea of the first cell
3757 nStartCol
= aAbs
.aStart
.Col();
3758 nStartRow
= aAbs
.aStart
.Row();
3759 aAbs
.aEnd
= aAbs
.aStart
; // Shrink to the top-left cell.
3762 // Expand to the data area. Only modify the end position.
3763 SCCOL nDACol1
= aAbs
.aStart
.Col(), nDACol2
= aAbs
.aEnd
.Col();
3764 SCROW nDARow1
= aAbs
.aStart
.Row(), nDARow2
= aAbs
.aEnd
.Row();
3765 mrDoc
.GetDataArea(aAbs
.aStart
.Tab(), nDACol1
, nDARow1
, nDACol2
, nDARow2
, true, false);
3766 aAbs
.aEnd
.SetCol(nDACol2
);
3767 aAbs
.aEnd
.SetRow(nDARow2
);
3770 // corresponds with ScCompiler::GetToken
3771 if ( aRefData
.Ref1
.IsColRel() )
3773 aAbs
.aEnd
.SetCol(nStartCol
);
3774 // maybe get previous limit by using defined ColRowNameRange
3775 if (aAbs
.aEnd
.Row() > nRow2
)
3776 aAbs
.aEnd
.SetRow(nRow2
);
3777 if ( aPos
.Col() == nStartCol
)
3779 SCROW nMyRow
= aPos
.Row();
3780 if ( nStartRow
<= nMyRow
&& nMyRow
<= aAbs
.aEnd
.Row())
3781 { //Formula in the same column and within the range
3782 if ( nMyRow
== nStartRow
)
3783 { // take the rest under the name
3785 if ( nStartRow
> mrDoc
.MaxRow() )
3786 nStartRow
= mrDoc
.MaxRow();
3787 aAbs
.aStart
.SetRow(nStartRow
);
3790 { // below the name to the formula cell
3791 aAbs
.aEnd
.SetRow(nMyRow
- 1);
3798 aAbs
.aEnd
.SetRow(nStartRow
);
3799 // maybe get previous limit by using defined ColRowNameRange
3800 if (aAbs
.aEnd
.Col() > nCol2
)
3801 aAbs
.aEnd
.SetCol(nCol2
);
3802 if ( aPos
.Row() == nStartRow
)
3804 SCCOL nMyCol
= aPos
.Col();
3805 if (nStartCol
<= nMyCol
&& nMyCol
<= aAbs
.aEnd
.Col())
3806 { //Formula in the same column and within the range
3807 if ( nMyCol
== nStartCol
)
3808 { // take the rest under the name
3810 if ( nStartCol
> mrDoc
.MaxCol() )
3811 nStartCol
= mrDoc
.MaxCol();
3812 aAbs
.aStart
.SetCol(nStartCol
);
3815 { // below the name to the formula cell
3816 aAbs
.aEnd
.SetCol(nMyCol
- 1);
3821 aRefData
.SetRange(mrDoc
.GetSheetLimits(), aAbs
, aPos
);
3822 PushTempToken( new ScDoubleRefToken( mrDoc
.GetSheetLimits(), aRefData
) );
3825 // --- internals ------------------------------------------------------------
3827 void ScInterpreter::ScTTT()
3828 { // temporary test, testing functions etc.
3829 sal_uInt8 nParamCount
= GetByte();
3830 // do something, count down nParamCount with Pops!
3833 while ( nParamCount
-- > 0)
3835 PushError(FormulaError::NoValue
);
3838 ScInterpreter::ScInterpreter( ScFormulaCell
* pCell
, ScDocument
& rDoc
, ScInterpreterContext
& rContext
,
3839 const ScAddress
& rPos
, ScTokenArray
& r
, bool bForGroupThreading
)
3843 , mrContext(rContext
)
3845 , mpLinkManager(rDoc
.GetLinkManager())
3846 , mrStrPool(rDoc
.GetSharedStringPool())
3847 , pJumpMatrix(nullptr)
3848 , pMyFormulaCell(pCell
)
3850 , nGlobalError(FormulaError::NONE
)
3856 , nFuncFmtType(SvNumFormatType::ALL
)
3857 , nCurFmtType(SvNumFormatType::ALL
)
3858 , nRetFmtType(SvNumFormatType::ALL
)
3859 , mnStringNoValueError(FormulaError::NoValue
)
3860 , mnSubTotalFlags(SubtotalFlags::NONE
)
3862 , bCalcAsShown(rDoc
.GetDocOptions().IsCalcAsShown())
3863 , meVolatileType(r
.IsRecalcModeAlways() ? VOLATILE
: NOT_VOLATILE
)
3869 ScMatrixMode cMatFlag
= pMyFormulaCell
->GetMatrixFlag();
3870 bMatrixFormula
= ( cMatFlag
== ScMatrixMode::Formula
);
3873 bMatrixFormula
= false;
3875 // Let's not use the global stack while formula-group-threading.
3876 // as it complicates its life-cycle mgmt since for threading formula-groups,
3877 // ScInterpreter is preallocated (in main thread) for each worker thread.
3878 if (!bGlobalStackInUse
&& !bForGroupThreading
)
3880 bGlobalStackInUse
= true;
3882 pGlobalStack
.reset(new ScTokenStack
);
3883 pStackObj
= pGlobalStack
.get();
3887 pStackObj
= new ScTokenStack
;
3889 pStack
= pStackObj
->pPointer
;
3892 ScInterpreter::~ScInterpreter()
3894 if ( pStackObj
== pGlobalStack
.get() )
3895 bGlobalStackInUse
= false;
3900 void ScInterpreter::Init( ScFormulaCell
* pCell
, const ScAddress
& rPos
, ScTokenArray
& rTokArray
)
3902 aCode
.ReInit(rTokArray
);
3905 pJumpMatrix
= nullptr;
3907 pMyFormulaCell
= pCell
;
3909 nGlobalError
= FormulaError::NONE
;
3915 nFuncFmtType
= SvNumFormatType::ALL
;
3916 nCurFmtType
= SvNumFormatType::ALL
;
3917 nRetFmtType
= SvNumFormatType::ALL
;
3918 mnStringNoValueError
= FormulaError::NoValue
;
3919 mnSubTotalFlags
= SubtotalFlags::NONE
;
3923 void ScInterpreter::DropTokenCaches()
3926 maTokenMatrixMap
.clear();
3929 ScCalcConfig
& ScInterpreter::GetOrCreateGlobalConfig()
3931 if (!mpGlobalConfig
)
3932 mpGlobalConfig
= new ScCalcConfig();
3933 return *mpGlobalConfig
;
3936 void ScInterpreter::SetGlobalConfig(const ScCalcConfig
& rConfig
)
3938 GetOrCreateGlobalConfig() = rConfig
;
3941 const ScCalcConfig
& ScInterpreter::GetGlobalConfig()
3943 return GetOrCreateGlobalConfig();
3946 void ScInterpreter::MergeCalcConfig()
3948 maCalcConfig
= GetOrCreateGlobalConfig();
3949 maCalcConfig
.MergeDocumentSpecific( mrDoc
.GetCalcConfig());
3952 void ScInterpreter::GlobalExit()
3954 OSL_ENSURE(!bGlobalStackInUse
, "who is still using the TokenStack?");
3955 pGlobalStack
.reset();
3960 double applyImplicitIntersection(const sc::RangeMatrix
& rMat
, const ScAddress
& rPos
)
3962 if (rMat
.mnRow1
<= rPos
.Row() && rPos
.Row() <= rMat
.mnRow2
&& rMat
.mnCol1
== rMat
.mnCol2
)
3964 SCROW nOffset
= rPos
.Row() - rMat
.mnRow1
;
3965 return rMat
.mpMat
->GetDouble(0, nOffset
);
3968 if (rMat
.mnCol1
<= rPos
.Col() && rPos
.Col() <= rMat
.mnCol2
&& rMat
.mnRow1
== rMat
.mnRow2
)
3970 SCROW nOffset
= rPos
.Col() - rMat
.mnCol1
;
3971 return rMat
.mpMat
->GetDouble(nOffset
, 0);
3974 return std::numeric_limits
<double>::quiet_NaN();
3977 // Test for Functions that evaluate an error code and directly set nGlobalError to 0
3978 bool IsErrFunc(OpCode oc
)
3991 case ocIsNonString
:
3999 case ocErrorType_ODF
:
4000 case ocAggregate
: // may ignore errors depending on option
4012 StackVar
ScInterpreter::Interpret()
4014 SvNumFormatType nRetTypeExpr
= SvNumFormatType::UNDEFINED
;
4015 sal_uInt32 nRetIndexExpr
= 0;
4016 sal_uInt16 nErrorFunction
= 0;
4017 sal_uInt16 nErrorFunctionCount
= 0;
4018 std::vector
<sal_uInt16
> aErrorFunctionStack
;
4019 sal_uInt16 nStackBase
;
4021 nGlobalError
= FormulaError::NONE
;
4022 nStackBase
= sp
= maxsp
= 0;
4023 nRetFmtType
= SvNumFormatType::UNDEFINED
;
4024 nFuncFmtType
= SvNumFormatType::UNDEFINED
;
4025 nFuncFmtIndex
= nCurFmtIndex
= nRetFmtIndex
= 0;
4027 pJumpMatrix
= nullptr;
4028 mnSubTotalFlags
= SubtotalFlags::NONE
;
4029 ScTokenMatrixMap::const_iterator aTokenMatrixMapIter
;
4031 // Once upon a time we used to have FP exceptions on, and there was a
4032 // Windows printer driver that kept switching off exceptions, so we had to
4033 // switch them back on again every time. Who knows if there isn't a driver
4034 // that keeps switching exceptions on, now that we run with exceptions off,
4035 // so reassure exceptions are really off.
4036 SAL_MATH_FPEXCEPTIONS_OFF();
4038 OpCode eOp
= ocNone
;
4042 pCur
= aCode
.Next();
4043 if (!pCur
|| (nGlobalError
!= FormulaError::NONE
&& nErrorFunction
> nErrorFunctionCount
) )
4045 eOp
= pCur
->GetOpCode();
4046 cPar
= pCur
->GetByte();
4047 if ( eOp
== ocPush
)
4049 // RPN code push without error
4050 PushWithoutError( *pCur
);
4051 nCurFmtType
= SvNumFormatType::UNDEFINED
;
4055 const bool bIsOpCodeJumpCommand
= FormulaCompiler::IsOpCodeJumpCommand(eOp
);
4056 if (!bIsOpCodeJumpCommand
&&
4057 ((aTokenMatrixMapIter
= maTokenMatrixMap
.find( pCur
)) !=
4058 maTokenMatrixMap
.end()) &&
4059 (*aTokenMatrixMapIter
).second
->GetType() != svJumpMatrix
)
4061 // Path already calculated, reuse result.
4062 const sal_uInt8 nParamCount
= pCur
->GetParamCount();
4063 if (sp
>= nParamCount
)
4064 nStackBase
= sp
- nParamCount
;
4067 SAL_WARN("sc.core", "Stack anomaly with calculated path at "
4068 << aPos
.Tab() << "," << aPos
.Col() << "," << aPos
.Row()
4069 << " " << aPos
.Format(
4070 ScRefFlags::VALID
| ScRefFlags::FORCE_DOC
| ScRefFlags::TAB_3D
, &mrDoc
)
4071 << " eOp: " << static_cast<int>(eOp
)
4072 << " params: " << static_cast<int>(nParamCount
)
4073 << " nStackBase: " << nStackBase
<< " sp: " << sp
);
4075 assert(!"underflow");
4078 PushTokenRef( (*aTokenMatrixMapIter
).second
);
4082 // previous expression determines the current number format
4083 nCurFmtType
= nRetTypeExpr
;
4084 nCurFmtIndex
= nRetIndexExpr
;
4085 // default function's format, others are set if needed
4086 nFuncFmtType
= SvNumFormatType::NUMBER
;
4089 if (bIsOpCodeJumpCommand
)
4090 nStackBase
= sp
; // don't mess around with the jumps
4093 // Convert parameters to matrix if in array/matrix formula and
4094 // parameters of function indicate doing so. Create JumpMatrix
4096 if ( MatrixParameterConversion() )
4098 eOp
= ocNone
; // JumpMatrix created
4103 const sal_uInt8 nParamCount
= pCur
->GetParamCount();
4104 if (sp
>= nParamCount
)
4105 nStackBase
= sp
- nParamCount
;
4108 SAL_WARN("sc.core", "Stack anomaly at " << aPos
.Tab() << "," << aPos
.Col() << "," << aPos
.Row()
4109 << " " << aPos
.Format(
4110 ScRefFlags::VALID
| ScRefFlags::FORCE_DOC
| ScRefFlags::TAB_3D
, &mrDoc
)
4111 << " eOp: " << static_cast<int>(eOp
)
4112 << " params: " << static_cast<int>(nParamCount
)
4113 << " nStackBase: " << nStackBase
<< " sp: " << sp
);
4115 assert(!"underflow");
4123 case ocClose
: // pushed by the compiler
4124 case ocMissing
: ScMissing(); break;
4125 case ocMacro
: ScMacro(); break;
4126 case ocDBArea
: ScDBArea(); break;
4127 case ocColRowNameAuto
: ScColRowNameAuto(); break;
4128 case ocIf
: ScIfJump(); break;
4129 case ocIfError
: ScIfError( false ); break;
4130 case ocIfNA
: ScIfError( true ); break;
4131 case ocChoose
: ScChooseJump(); break;
4132 case ocAdd
: ScAdd(); break;
4133 case ocSub
: ScSub(); break;
4134 case ocMul
: ScMul(); break;
4135 case ocDiv
: ScDiv(); break;
4136 case ocAmpersand
: ScAmpersand(); break;
4137 case ocPow
: ScPow(); break;
4138 case ocEqual
: ScEqual(); break;
4139 case ocNotEqual
: ScNotEqual(); break;
4140 case ocLess
: ScLess(); break;
4141 case ocGreater
: ScGreater(); break;
4142 case ocLessEqual
: ScLessEqual(); break;
4143 case ocGreaterEqual
: ScGreaterEqual(); break;
4144 case ocAnd
: ScAnd(); break;
4145 case ocOr
: ScOr(); break;
4146 case ocXor
: ScXor(); break;
4147 case ocIntersect
: ScIntersect(); break;
4148 case ocRange
: ScRangeFunc(); break;
4149 case ocUnion
: ScUnionFunc(); break;
4150 case ocNot
: ScNot(); break;
4152 case ocNeg
: ScNeg(); break;
4153 case ocPercentSign
: ScPercentSign(); break;
4154 case ocPi
: ScPi(); break;
4155 case ocRandom
: ScRandom(); break;
4156 case ocRandArray
: ScRandArray(); break;
4157 case ocRandomNV
: ScRandom(); break;
4158 case ocRandbetweenNV
: ScRandbetween(); break;
4159 case ocFilter
: ScFilter(); break;
4160 case ocSort
: ScSort(); break;
4161 case ocSortBy
: ScSortBy(); break;
4162 case ocUnique
: ScUnique(); break;
4163 case ocLet
: ScLet(); break;
4164 case ocTrue
: ScTrue(); break;
4165 case ocFalse
: ScFalse(); break;
4166 case ocGetActDate
: ScGetActDate(); break;
4167 case ocGetActTime
: ScGetActTime(); break;
4168 case ocNotAvail
: PushError( FormulaError::NotAvailable
); break;
4169 case ocDeg
: ScDeg(); break;
4170 case ocRad
: ScRad(); break;
4171 case ocSin
: ScSin(); break;
4172 case ocCos
: ScCos(); break;
4173 case ocTan
: ScTan(); break;
4174 case ocCot
: ScCot(); break;
4175 case ocArcSin
: ScArcSin(); break;
4176 case ocArcCos
: ScArcCos(); break;
4177 case ocArcTan
: ScArcTan(); break;
4178 case ocArcCot
: ScArcCot(); break;
4179 case ocSinHyp
: ScSinHyp(); break;
4180 case ocCosHyp
: ScCosHyp(); break;
4181 case ocTanHyp
: ScTanHyp(); break;
4182 case ocCotHyp
: ScCotHyp(); break;
4183 case ocArcSinHyp
: ScArcSinHyp(); break;
4184 case ocArcCosHyp
: ScArcCosHyp(); break;
4185 case ocArcTanHyp
: ScArcTanHyp(); break;
4186 case ocArcCotHyp
: ScArcCotHyp(); break;
4187 case ocCosecant
: ScCosecant(); break;
4188 case ocSecant
: ScSecant(); break;
4189 case ocCosecantHyp
: ScCosecantHyp(); break;
4190 case ocSecantHyp
: ScSecantHyp(); break;
4191 case ocExp
: ScExp(); break;
4192 case ocLn
: ScLn(); break;
4193 case ocLog10
: ScLog10(); break;
4194 case ocSqrt
: ScSqrt(); break;
4195 case ocFact
: ScFact(); break;
4196 case ocGetYear
: ScGetYear(); break;
4197 case ocGetMonth
: ScGetMonth(); break;
4198 case ocGetDay
: ScGetDay(); break;
4199 case ocGetDayOfWeek
: ScGetDayOfWeek(); break;
4200 case ocWeek
: ScGetWeekOfYear(); break;
4201 case ocIsoWeeknum
: ScGetIsoWeekOfYear(); break;
4202 case ocWeeknumOOo
: ScWeeknumOOo(); break;
4203 case ocEasterSunday
: ScEasterSunday(); break;
4204 case ocNetWorkdays
: ScNetWorkdays( false); break;
4205 case ocNetWorkdays_MS
: ScNetWorkdays( true ); break;
4206 case ocWorkday_MS
: ScWorkday_MS(); break;
4207 case ocGetHour
: ScGetHour(); break;
4208 case ocGetMin
: ScGetMin(); break;
4209 case ocGetSec
: ScGetSec(); break;
4210 case ocPlusMinus
: ScPlusMinus(); break;
4211 case ocAbs
: ScAbs(); break;
4212 case ocInt
: ScInt(); break;
4213 case ocEven
: ScEven(); break;
4214 case ocOdd
: ScOdd(); break;
4215 case ocPhi
: ScPhi(); break;
4216 case ocGauss
: ScGauss(); break;
4217 case ocStdNormDist
: ScStdNormDist(); break;
4218 case ocStdNormDist_MS
: ScStdNormDist_MS(); break;
4219 case ocFisher
: ScFisher(); break;
4220 case ocFisherInv
: ScFisherInv(); break;
4221 case ocIsEmpty
: ScIsEmpty(); break;
4222 case ocIsString
: ScIsString(); break;
4223 case ocIsNonString
: ScIsNonString(); break;
4224 case ocIsLogical
: ScIsLogical(); break;
4225 case ocType
: ScType(); break;
4226 case ocCell
: ScCell(); break;
4227 case ocIsRef
: ScIsRef(); break;
4228 case ocIsValue
: ScIsValue(); break;
4229 case ocIsFormula
: ScIsFormula(); break;
4230 case ocFormula
: ScFormula(); break;
4231 case ocIsNA
: ScIsNV(); break;
4232 case ocIsErr
: ScIsErr(); break;
4233 case ocIsError
: ScIsError(); break;
4234 case ocIsEven
: ScIsEven(); break;
4235 case ocIsOdd
: ScIsOdd(); break;
4236 case ocN
: ScN(); break;
4237 case ocGetDateValue
: ScGetDateValue(); break;
4238 case ocGetTimeValue
: ScGetTimeValue(); break;
4239 case ocCode
: ScCode(); break;
4240 case ocTrim
: ScTrim(); break;
4241 case ocUpper
: ScUpper(); break;
4242 case ocProper
: ScProper(); break;
4243 case ocLower
: ScLower(); break;
4244 case ocLen
: ScLen(); break;
4245 case ocT
: ScT(); break;
4246 case ocClean
: ScClean(); break;
4247 case ocValue
: ScValue(); break;
4248 case ocNumberValue
: ScNumberValue(); break;
4249 case ocChar
: ScChar(); break;
4250 case ocArcTan2
: ScArcTan2(); break;
4251 case ocMod
: ScMod(); break;
4252 case ocPower
: ScPower(); break;
4253 case ocRound
: ScRound(); break;
4254 case ocRoundSig
: ScRoundSignificant(); break;
4255 case ocRoundUp
: ScRoundUp(); break;
4257 case ocRoundDown
: ScRoundDown(); break;
4258 case ocCeil
: ScCeil( true ); break;
4259 case ocCeil_MS
: ScCeil_MS(); break;
4260 case ocCeil_Precise
:
4261 case ocCeil_ISO
: ScCeil_Precise(); break;
4262 case ocCeil_Math
: ScCeil( false ); break;
4263 case ocFloor
: ScFloor( true ); break;
4264 case ocFloor_MS
: ScFloor_MS(); break;
4265 case ocFloor_Precise
: ScFloor_Precise(); break;
4266 case ocFloor_Math
: ScFloor( false ); break;
4267 case ocSumProduct
: ScSumProduct(); break;
4268 case ocSumSQ
: ScSumSQ(); break;
4269 case ocSumX2MY2
: ScSumX2MY2(); break;
4270 case ocSumX2DY2
: ScSumX2DY2(); break;
4271 case ocSumXMY2
: ScSumXMY2(); break;
4272 case ocRawSubtract
: ScRawSubtract(); break;
4273 case ocLog
: ScLog(); break;
4274 case ocGCD
: ScGCD(); break;
4275 case ocLCM
: ScLCM(); break;
4276 case ocGetDate
: ScGetDate(); break;
4277 case ocGetTime
: ScGetTime(); break;
4278 case ocGetDiffDate
: ScGetDiffDate(); break;
4279 case ocGetDiffDate360
: ScGetDiffDate360(); break;
4280 case ocGetDateDif
: ScGetDateDif(); break;
4281 case ocMin
: ScMin() ; break;
4282 case ocMinA
: ScMin( true ); break;
4283 case ocMax
: ScMax(); break;
4284 case ocMaxA
: ScMax( true ); break;
4285 case ocSum
: ScSum(); break;
4286 case ocProduct
: ScProduct(); break;
4287 case ocNPV
: ScNPV(); break;
4288 case ocIRR
: ScIRR(); break;
4289 case ocMIRR
: ScMIRR(); break;
4290 case ocISPMT
: ScISPMT(); break;
4291 case ocAverage
: ScAverage() ; break;
4292 case ocAverageA
: ScAverage( true ); break;
4293 case ocCount
: ScCount(); break;
4294 case ocCount2
: ScCount2(); break;
4296 case ocVarS
: ScVar(); break;
4297 case ocVarA
: ScVar( true ); break;
4299 case ocVarP_MS
: ScVarP(); break;
4300 case ocVarPA
: ScVarP( true ); break;
4302 case ocStDevS
: ScStDev(); break;
4303 case ocStDevA
: ScStDev( true ); break;
4305 case ocStDevP_MS
: ScStDevP(); break;
4306 case ocStDevPA
: ScStDevP( true ); break;
4307 case ocPV
: ScPV(); break;
4308 case ocSYD
: ScSYD(); break;
4309 case ocDDB
: ScDDB(); break;
4310 case ocDB
: ScDB(); break;
4311 case ocVBD
: ScVDB(); break;
4312 case ocPDuration
: ScPDuration(); break;
4313 case ocSLN
: ScSLN(); break;
4314 case ocPMT
: ScPMT(); break;
4315 case ocColumns
: ScColumns(); break;
4316 case ocRows
: ScRows(); break;
4317 case ocSheets
: ScSheets(); break;
4318 case ocColumn
: ScColumn(); break;
4319 case ocRow
: ScRow(); break;
4320 case ocSheet
: ScSheet(); break;
4321 case ocRRI
: ScRRI(); break;
4322 case ocFV
: ScFV(); break;
4323 case ocNper
: ScNper(); break;
4324 case ocRate
: ScRate(); break;
4325 case ocFilterXML
: ScFilterXML(); break;
4326 case ocWebservice
: ScWebservice(); break;
4327 case ocEncodeURL
: ScEncodeURL(); break;
4328 case ocColor
: ScColor(); break;
4329 case ocErf_MS
: ScErf(); break;
4330 case ocErfc_MS
: ScErfc(); break;
4331 case ocIpmt
: ScIpmt(); break;
4332 case ocPpmt
: ScPpmt(); break;
4333 case ocCumIpmt
: ScCumIpmt(); break;
4334 case ocCumPrinc
: ScCumPrinc(); break;
4335 case ocEffect
: ScEffect(); break;
4336 case ocNominal
: ScNominal(); break;
4337 case ocSubTotal
: ScSubTotal(); break;
4338 case ocAggregate
: ScAggregate(); break;
4339 case ocDBSum
: ScDBSum(); break;
4340 case ocDBCount
: ScDBCount(); break;
4341 case ocDBCount2
: ScDBCount2(); break;
4342 case ocDBAverage
: ScDBAverage(); break;
4343 case ocDBGet
: ScDBGet(); break;
4344 case ocDBMax
: ScDBMax(); break;
4345 case ocDBMin
: ScDBMin(); break;
4346 case ocDBProduct
: ScDBProduct(); break;
4347 case ocDBStdDev
: ScDBStdDev(); break;
4348 case ocDBStdDevP
: ScDBStdDevP(); break;
4349 case ocDBVar
: ScDBVar(); break;
4350 case ocDBVarP
: ScDBVarP(); break;
4351 case ocIndirect
: ScIndirect(); break;
4352 case ocAddress
: ScAddressFunc(); break;
4353 case ocMatch
: ScMatch(); break;
4354 case ocXMatch
: ScXMatch(); break;
4355 case ocCountEmptyCells
: ScCountEmptyCells(); break;
4356 case ocCountIf
: ScCountIf(); break;
4357 case ocSumIf
: ScSumIf(); break;
4358 case ocAverageIf
: ScAverageIf(); break;
4359 case ocSumIfs
: ScSumIfs(); break;
4360 case ocAverageIfs
: ScAverageIfs(); break;
4361 case ocCountIfs
: ScCountIfs(); break;
4362 case ocLookup
: ScLookup(); break;
4363 case ocVLookup
: ScVLookup(); break;
4364 case ocXLookup
: ScXLookup(); break;
4365 case ocHLookup
: ScHLookup(); break;
4366 case ocIndex
: ScIndex(); break;
4367 case ocMultiArea
: ScMultiArea(); break;
4368 case ocOffset
: ScOffset(); break;
4369 case ocAreas
: ScAreas(); break;
4370 case ocCurrency
: ScCurrency(); break;
4371 case ocReplace
: ScReplace(); break;
4372 case ocFixed
: ScFixed(); break;
4373 case ocFind
: ScFind(); break;
4374 case ocExact
: ScExact(); break;
4375 case ocLeft
: ScLeft(); break;
4376 case ocRight
: ScRight(); break;
4377 case ocSearch
: ScSearch(); break;
4378 case ocMid
: ScMid(); break;
4379 case ocText
: ScText(); break;
4380 case ocSubstitute
: ScSubstitute(); break;
4381 case ocRegex
: ScRegex(); break;
4382 case ocRept
: ScRept(); break;
4383 case ocConcat
: ScConcat(); break;
4384 case ocConcat_MS
: ScConcat_MS(); break;
4385 case ocTextJoin_MS
: ScTextJoin_MS(); break;
4386 case ocIfs_MS
: ScIfs_MS(); break;
4387 case ocSwitch_MS
: ScSwitch_MS(); break;
4388 case ocMinIfs_MS
: ScMinIfs_MS(); break;
4389 case ocMaxIfs_MS
: ScMaxIfs_MS(); break;
4390 case ocMatValue
: ScMatValue(); break;
4391 case ocMatrixUnit
: ScEMat(); break;
4392 case ocMatDet
: ScMatDet(); break;
4393 case ocMatInv
: ScMatInv(); break;
4394 case ocMatMult
: ScMatMult(); break;
4395 case ocMatSequence
: ScMatSequence(); break;
4396 case ocMatTrans
: ScMatTrans(); break;
4397 case ocMatRef
: ScMatRef(); break;
4398 case ocB
: ScB(); break;
4399 case ocNormDist
: ScNormDist( 3 ); break;
4400 case ocNormDist_MS
: ScNormDist( 4 ); break;
4402 case ocExpDist_MS
: ScExpDist(); break;
4404 case ocBinomDist_MS
: ScBinomDist(); break;
4405 case ocPoissonDist
: ScPoissonDist( true ); break;
4406 case ocPoissonDist_MS
: ScPoissonDist( false ); break;
4407 case ocCombin
: ScCombin(); break;
4408 case ocCombinA
: ScCombinA(); break;
4409 case ocPermut
: ScPermut(); break;
4410 case ocPermutationA
: ScPermutationA(); break;
4411 case ocHypGeomDist
: ScHypGeomDist( 4 ); break;
4412 case ocHypGeomDist_MS
: ScHypGeomDist( 5 ); break;
4413 case ocLogNormDist
: ScLogNormDist( 1 ); break;
4414 case ocLogNormDist_MS
: ScLogNormDist( 4 ); break;
4415 case ocTDist
: ScTDist(); break;
4416 case ocTDist_MS
: ScTDist_MS(); break;
4417 case ocTDist_RT
: ScTDist_T( 1 ); break;
4418 case ocTDist_2T
: ScTDist_T( 2 ); break;
4420 case ocFDist_RT
: ScFDist(); break;
4421 case ocFDist_LT
: ScFDist_LT(); break;
4422 case ocChiDist
: ScChiDist( true ); break;
4423 case ocChiDist_MS
: ScChiDist( false ); break;
4424 case ocChiSqDist
: ScChiSqDist(); break;
4425 case ocChiSqDist_MS
: ScChiSqDist_MS(); break;
4426 case ocStandard
: ScStandard(); break;
4427 case ocAveDev
: ScAveDev(); break;
4428 case ocDevSq
: ScDevSq(); break;
4429 case ocKurt
: ScKurt(); break;
4430 case ocSkew
: ScSkew(); break;
4431 case ocSkewp
: ScSkewp(); break;
4432 case ocModalValue
: ScModalValue(); break;
4433 case ocModalValue_MS
: ScModalValue_MS( true ); break;
4434 case ocModalValue_Multi
: ScModalValue_MS( false ); break;
4435 case ocMedian
: ScMedian(); break;
4436 case ocGeoMean
: ScGeoMean(); break;
4437 case ocHarMean
: ScHarMean(); break;
4439 case ocWeibull_MS
: ScWeibull(); break;
4441 case ocCritBinom
: ScCritBinom(); break;
4442 case ocNegBinomVert
: ScNegBinomDist(); break;
4443 case ocNegBinomDist_MS
: ScNegBinomDist_MS(); break;
4444 case ocNoName
: ScNoName(); break;
4445 case ocBad
: ScBadName(); break;
4447 case ocZTest_MS
: ScZTest(); break;
4449 case ocTTest_MS
: ScTTest(); break;
4451 case ocFTest_MS
: ScFTest(); break;
4453 case ocRank_Eq
: ScRank( false ); break;
4454 case ocRank_Avg
: ScRank( true ); break;
4456 case ocPercentile_Inc
: ScPercentile( true ); break;
4457 case ocPercentile_Exc
: ScPercentile( false ); break;
4458 case ocPercentrank
:
4459 case ocPercentrank_Inc
: ScPercentrank( true ); break;
4460 case ocPercentrank_Exc
: ScPercentrank( false ); break;
4461 case ocLarge
: ScLarge(); break;
4462 case ocSmall
: ScSmall(); break;
4463 case ocFrequency
: ScFrequency(); break;
4465 case ocQuartile_Inc
: ScQuartile( true ); break;
4466 case ocQuartile_Exc
: ScQuartile( false ); break;
4468 case ocNormInv_MS
: ScNormInv(); break;
4470 case ocSNormInv_MS
: ScSNormInv(); break;
4472 case ocConfidence_N
: ScConfidence(); break;
4473 case ocConfidence_T
: ScConfidenceT(); break;
4474 case ocTrimMean
: ScTrimMean(); break;
4475 case ocProb
: ScProbability(); break;
4476 case ocCorrel
: ScCorrel(); break;
4478 case ocCovarianceP
: ScCovarianceP(); break;
4479 case ocCovarianceS
: ScCovarianceS(); break;
4480 case ocPearson
: ScPearson(); break;
4481 case ocRSQ
: ScRSQ(); break;
4482 case ocSTEYX
: ScSTEYX(); break;
4483 case ocSlope
: ScSlope(); break;
4484 case ocIntercept
: ScIntercept(); break;
4485 case ocTrend
: ScTrend(); break;
4486 case ocGrowth
: ScGrowth(); break;
4487 case ocLinest
: ScLinest(); break;
4488 case ocLogest
: ScLogest(); break;
4489 case ocForecast_LIN
:
4490 case ocForecast
: ScForecast(); break;
4491 case ocForecast_ETS_ADD
: ScForecast_Ets( etsAdd
); break;
4492 case ocForecast_ETS_SEA
: ScForecast_Ets( etsSeason
); break;
4493 case ocForecast_ETS_MUL
: ScForecast_Ets( etsMult
); break;
4494 case ocForecast_ETS_PIA
: ScForecast_Ets( etsPIAdd
); break;
4495 case ocForecast_ETS_PIM
: ScForecast_Ets( etsPIMult
); break;
4496 case ocForecast_ETS_STA
: ScForecast_Ets( etsStatAdd
); break;
4497 case ocForecast_ETS_STM
: ScForecast_Ets( etsStatMult
); break;
4499 case ocGammaLn_MS
: ScLogGamma(); break;
4500 case ocGamma
: ScGamma(); break;
4501 case ocGammaDist
: ScGammaDist( true ); break;
4502 case ocGammaDist_MS
: ScGammaDist( false ); break;
4504 case ocGammaInv_MS
: ScGammaInv(); break;
4506 case ocChiTest_MS
: ScChiTest(); break;
4508 case ocChiInv_MS
: ScChiInv(); break;
4510 case ocChiSqInv_MS
: ScChiSqInv(); break;
4512 case ocTInv_2T
: ScTInv( 2 ); break;
4513 case ocTInv_MS
: ScTInv( 4 ); break;
4515 case ocFInv_RT
: ScFInv(); break;
4516 case ocFInv_LT
: ScFInv_LT(); break;
4518 case ocLogInv_MS
: ScLogNormInv(); break;
4519 case ocBetaDist
: ScBetaDist(); break;
4520 case ocBetaDist_MS
: ScBetaDist_MS(); break;
4522 case ocBetaInv_MS
: ScBetaInv(); break;
4523 case ocFourier
: ScFourier(); break;
4524 case ocExternal
: ScExternal(); break;
4525 case ocTableOp
: ScTableOp(); break;
4526 case ocStop
: break;
4527 case ocErrorType
: ScErrorType(); break;
4528 case ocErrorType_ODF
: ScErrorType_ODF(); break;
4529 case ocCurrent
: ScCurrent(); break;
4530 case ocStyle
: ScStyle(); break;
4531 case ocDde
: ScDde(); break;
4532 case ocBase
: ScBase(); break;
4533 case ocDecimal
: ScDecimal(); break;
4534 case ocConvertOOo
: ScConvertOOo(); break;
4535 case ocEuroConvert
: ScEuroConvert(); break;
4536 case ocRoman
: ScRoman(); break;
4537 case ocArabic
: ScArabic(); break;
4538 case ocInfo
: ScInfo(); break;
4539 case ocHyperLink
: ScHyperLink(); break;
4540 case ocBahtText
: ScBahtText(); break;
4541 case ocGetPivotData
: ScGetPivotData(); break;
4542 case ocJis
: ScJis(); break;
4543 case ocAsc
: ScAsc(); break;
4544 case ocLenB
: ScLenB(); break;
4545 case ocRightB
: ScRightB(); break;
4546 case ocLeftB
: ScLeftB(); break;
4547 case ocMidB
: ScMidB(); break;
4548 case ocReplaceB
: ScReplaceB(); break;
4549 case ocFindB
: ScFindB(); break;
4550 case ocSearchB
: ScSearchB(); break;
4551 case ocUnicode
: ScUnicode(); break;
4552 case ocUnichar
: ScUnichar(); break;
4553 case ocBitAnd
: ScBitAnd(); break;
4554 case ocBitOr
: ScBitOr(); break;
4555 case ocBitXor
: ScBitXor(); break;
4556 case ocBitRshift
: ScBitRshift(); break;
4557 case ocBitLshift
: ScBitLshift(); break;
4558 case ocTTT
: ScTTT(); break;
4559 case ocDebugVar
: ScDebugVar(); break;
4560 case ocNone
: nFuncFmtType
= SvNumFormatType::UNDEFINED
; break;
4561 default : PushError( FormulaError::UnknownOpCode
); break;
4564 // If the function pushed a subroutine as result, continue with
4565 // execution of the subroutine.
4566 if (sp
> nStackBase
&& pStack
[sp
-1]->GetOpCode() == ocCall
)
4571 if (FormulaCompiler::IsOpCodeVolatile(eOp
))
4572 meVolatileType
= VOLATILE
;
4574 // Remember result matrix in case it could be reused.
4575 if (sp
&& GetStackType() == svMatrix
)
4576 maTokenMatrixMap
.emplace(pCur
, pStack
[sp
-1]);
4578 // outer function determines format of an expression
4579 if ( nFuncFmtType
!= SvNumFormatType::UNDEFINED
)
4581 nRetTypeExpr
= nFuncFmtType
;
4582 // Inherit the format index for currency, date or time formats.
4583 switch (nFuncFmtType
)
4585 case SvNumFormatType::CURRENCY
:
4586 case SvNumFormatType::DATE
:
4587 case SvNumFormatType::TIME
:
4588 case SvNumFormatType::DATETIME
:
4589 case SvNumFormatType::DURATION
:
4590 nRetIndexExpr
= nFuncFmtIndex
;
4599 // Need a clean stack environment for the JumpMatrix to work.
4600 if (nGlobalError
!= FormulaError::NONE
&& eOp
!= ocPush
&& sp
> nStackBase
+ 1)
4602 // Not all functions pop all parameters in case an error is
4603 // generated. Clean up stack. Assumes that every function pushes a
4604 // result, may be arbitrary in case of error.
4605 FormulaConstTokenRef xLocalResult
= pStack
[ sp
- 1 ];
4606 while (sp
> nStackBase
)
4608 PushTokenRef( xLocalResult
);
4615 sal_uInt8 nLevel
= 0;
4616 if ( GetStackType( ++nLevel
) == svJumpMatrix
)
4618 else if ( GetStackType( ++nLevel
) == svJumpMatrix
)
4622 if ( nLevel
== 1 || (nLevel
== 2 && aCode
.IsEndOfPath()) )
4625 aErrorFunctionStack
.push_back( nErrorFunction
);
4626 bGotResult
= JumpMatrix( nLevel
);
4627 if (aErrorFunctionStack
.empty())
4628 assert(!"ScInterpreter::Interpret - aErrorFunctionStack empty in JumpMatrix context");
4631 nErrorFunction
= aErrorFunctionStack
.back();
4633 aErrorFunctionStack
.pop_back();
4637 pJumpMatrix
= nullptr;
4638 } while ( bGotResult
);
4640 if( IsErrFunc(eOp
) )
4643 if ( nGlobalError
!= FormulaError::NONE
)
4645 if ( !nErrorFunctionCount
)
4646 { // count of errorcode functions in formula
4647 FormulaTokenArrayPlainIterator
aIter(*pArr
);
4648 for ( FormulaToken
* t
= aIter
.FirstRPN(); t
; t
= aIter
.NextRPN() )
4650 if ( IsErrFunc(t
->GetOpCode()) )
4651 ++nErrorFunctionCount
;
4654 if ( nErrorFunction
>= nErrorFunctionCount
)
4655 ++nErrorFunction
; // that's it, error => terminate
4656 else if (nErrorFunctionCount
&& sp
&& GetStackType() == svError
)
4658 // Clear global error if we have an individual error result, so
4659 // an error evaluating function can receive multiple arguments
4660 // and not all evaluated arguments inheriting the error.
4661 // This is important for at least IFS() and SWITCH() as long as
4662 // they are classified as error evaluating functions and not
4663 // implemented as short-cutting jump code paths, but also for
4664 // more than one evaluated argument to AGGREGATE() or COUNT()
4665 // that may ignore errors.
4666 nGlobalError
= FormulaError::NONE
;
4671 // End: obtain result
4673 bool bForcedResultType
;
4676 case ocGetDateValue
:
4677 case ocGetTimeValue
:
4678 // Force final result of DATEVALUE and TIMEVALUE to number type,
4679 // which so far was date or time for calculations.
4680 nRetTypeExpr
= nFuncFmtType
= SvNumFormatType::NUMBER
;
4681 nRetIndexExpr
= nFuncFmtIndex
= 0;
4682 bForcedResultType
= true;
4685 bForcedResultType
= false;
4690 pCur
= pStack
[ sp
-1 ];
4691 if( pCur
->GetOpCode() == ocPush
)
4693 // An svRefList can be resolved if it a) contains just one
4694 // reference, or b) in array context contains an array of single
4696 if (pCur
->GetType() == svRefList
)
4698 PopRefListPushMatrixOrRef();
4699 pCur
= pStack
[ sp
-1 ];
4701 switch( pCur
->GetType() )
4707 nGlobalError
= pCur
->GetError();
4711 // If typed, pop token to obtain type information and
4712 // push a plain untyped double so the result token to
4713 // be transferred to the formula cell result does not
4714 // unnecessarily duplicate the information.
4715 if (pCur
->GetDoubleType() != 0)
4717 double fVal
= PopDouble();
4718 if (!bForcedResultType
)
4720 if (nCurFmtType
!= nFuncFmtType
)
4721 nRetIndexExpr
= 0; // carry format index only for matching type
4722 nRetTypeExpr
= nFuncFmtType
= nCurFmtType
;
4724 if (nRetTypeExpr
== SvNumFormatType::DURATION
)
4726 // Round the duration in case a wall clock time
4727 // display format is used instead of a duration
4728 // format. To micro seconds which then catches
4729 // the converted hh:mm:ss.9999997 cases.
4733 fVal
= rtl::math::round( fVal
, 6);
4737 PushTempToken( CreateFormulaDoubleToken( fVal
));
4739 if ( nFuncFmtType
== SvNumFormatType::UNDEFINED
)
4741 nRetTypeExpr
= SvNumFormatType::NUMBER
;
4747 nRetTypeExpr
= SvNumFormatType::TEXT
;
4753 PopSingleRef( aAdr
);
4754 if( nGlobalError
== FormulaError::NONE
)
4755 PushCellResultToken( false, aAdr
, &nRetTypeExpr
, &nRetIndexExpr
, true);
4759 PopError(); // maybe #REF! takes precedence over #VALUE!
4760 PushError( FormulaError::NoValue
);
4764 if ( bMatrixFormula
)
4765 { // create matrix for {=A1:A5}
4766 PopDoubleRefPushMatrix();
4767 ScMatrixRef xMat
= PopMatrix();
4768 QueryMatrixType(xMat
, nRetTypeExpr
, nRetIndexExpr
);
4773 PopDoubleRef( aRange
);
4775 if ( nGlobalError
== FormulaError::NONE
&& DoubleRefToPosSingleRef( aRange
, aAdr
))
4776 PushCellResultToken( false, aAdr
, &nRetTypeExpr
, &nRetIndexExpr
, true);
4780 case svExternalDoubleRef
:
4783 PopExternalDoubleRef(xMat
);
4784 QueryMatrixType(xMat
, nRetTypeExpr
, nRetIndexExpr
);
4789 sc::RangeMatrix aMat
= PopRangeMatrix();
4790 if (aMat
.isRangeValid())
4792 // This matrix represents a range reference. Apply implicit intersection.
4793 double fVal
= applyImplicitIntersection(aMat
, aPos
);
4794 if (std::isnan(fVal
))
4800 // This is a normal matrix.
4801 QueryMatrixType(aMat
.mpMat
, nRetTypeExpr
, nRetIndexExpr
);
4804 case svExternalSingleRef
:
4806 FormulaTokenRef xToken
;
4807 ScExternalRefCache::CellFormat aFmt
;
4808 PopExternalSingleRef(xToken
, &aFmt
);
4809 if (nGlobalError
!= FormulaError::NONE
)
4812 PushTokenRef(xToken
);
4816 nFuncFmtType
= aFmt
.mnType
;
4817 nFuncFmtIndex
= aFmt
.mnIndex
;
4822 SetError( FormulaError::UnknownStackVariable
);
4826 SetError( FormulaError::UnknownStackVariable
);
4829 SetError( FormulaError::OperatorExpected
);
4831 SetError( FormulaError::NoCode
);
4833 if (bForcedResultType
|| nRetTypeExpr
!= SvNumFormatType::UNDEFINED
)
4835 nRetFmtType
= nRetTypeExpr
;
4836 nRetFmtIndex
= nRetIndexExpr
;
4838 else if( nFuncFmtType
!= SvNumFormatType::UNDEFINED
)
4840 nRetFmtType
= nFuncFmtType
;
4841 nRetFmtIndex
= nFuncFmtIndex
;
4844 nRetFmtType
= SvNumFormatType::NUMBER
;
4846 if (nGlobalError
!= FormulaError::NONE
&& GetStackType() != svError
)
4847 PushError( nGlobalError
);
4849 // THE final result.
4850 xResult
= PopToken();
4852 xResult
= new FormulaErrorToken( FormulaError::UnknownStackVariable
);
4854 // release tokens in expression stack
4855 const FormulaToken
** p
= pStack
;
4859 StackVar eType
= xResult
->GetType();
4860 if (eType
== svMatrix
)
4861 // Results are immutable in case they would be reused as input for new
4863 xResult
->GetMatrix()->SetImmutable();
4867 void ScInterpreter::AssertFormulaMatrix()
4869 bMatrixFormula
= true;
4872 const svl::SharedString
& ScInterpreter::GetStringResult() const
4874 return xResult
->GetString();
4877 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */