20 #include <config_features.h>
25 #include <rtl/math.hxx>
40 #include <com/sun/star/table/XCellRange.hpp>
41 #include <com/sun/star/script/XInvocation.hpp>
42 #include <com/sun/star/sheet/XSheetCellRange.hpp>
49 #include <document.hxx>
65 #include <tokenarray.hxx>
66 #include <compiler.hxx>
76 using ::std::unique_ptr;
78 #define ADDIN_MAXSTRLEN 256
87 size_t ListSize = mrDoc.m_TableOpList.size();
88 for (
size_t i = 0;
i < ListSize; ++
i )
91 if ( rPos == pTOp->
aOld1 )
96 else if ( rPos == pTOp->
aOld2 )
110 size_t ListSize = mrDoc.m_TableOpList.size();
111 for (
size_t i = 0;
i < ListSize; ++
i )
114 if ( rRange.
In( pTOp->
aOld1 ) )
116 if ( rRange.
In( pTOp->
aOld2 ) )
128 nFormat = mrDoc.GetNumberFormat(
mrContext, rPos );
129 nErr = FormulaError::NONE;
136 nErr = FormulaError::NONE;
137 nFormat = mrDoc.GetNumberFormat(
mrContext, rPos );
147 if ( bCalcAsShown && fOrig != 0.0 )
149 sal_uInt32 nFormat = mrDoc.GetNumberFormat(
mrContext, rPos );
150 fOrig = mrDoc.RoundValueAsShown( fOrig, nFormat, &
mrContext );
164 pFormatter, nCurFmtType);
165 if (nError != FormulaError::NONE)
178 nGlobalError = FormulaError::NONE;
179 double nVal = GetCellValueOrZero(rPos, rCell);
180 if ( nGlobalError == FormulaError::NONE || nGlobalError == FormulaError::CellNoValue )
196 if( nErr == FormulaError::NONE )
201 mrDoc.GetNumberFormatInfo(
mrContext, nCurFmtType, nCurFmtIndex,
219 nCurFmtIndex = mrDoc.GetNumberFormat(
mrContext, rPos );
220 nCurFmtType =
mrContext.GetNumberFormatType( nCurFmtIndex );
221 if ( bCalcAsShown && fValue != 0.0 )
222 fValue = mrDoc.RoundValueAsShown( fValue, nCurFmtIndex, &
mrContext );
231 fValue = ConvertStringToValue( aStr );
250 rStr = mrStrPool.intern(rCell.
getString(&mrDoc));
258 rStr = GetStringFromDouble( pFCell->
GetValue() );
266 rStr = GetStringFromDouble( rCell.
mfValue );
282 static_assert(MAXCOLCOUNT <= SAL_MAX_UINT16, "Add check for columns >
SAL_MAX_UINT16!
");
283 if (nRow1 > SAL_MAX_UINT16 || nRow2 > SAL_MAX_UINT16)
286 sal_uInt16 nCount = 0;
287 sal_uInt16* p = reinterpret_cast<sal_uInt16*>(pCellArr);
288 *p++ = static_cast<sal_uInt16>(nCol1);
289 *p++ = static_cast<sal_uInt16>(nRow1);
290 *p++ = static_cast<sal_uInt16>(nTab1);
291 *p++ = static_cast<sal_uInt16>(nCol2);
292 *p++ = static_cast<sal_uInt16>(nRow2);
293 *p++ = static_cast<sal_uInt16>(nTab2);
294 sal_uInt16* pCount = p;
296 sal_uInt16 nPos = 14;
299 while (nTab <= nTab2)
303 while (nRow <= nRow2)
307 while (nCol <= nCol2)
311 ScRefCellValue aCell(mrDoc, aAdr);
312 if (!aCell.isEmpty())
314 FormulaError nErr = FormulaError::NONE;
317 switch (aCell.meType)
319 case CELLTYPE_VALUE :
320 nVal = GetValueCellValue(aAdr, aCell.mfValue);
322 case CELLTYPE_FORMULA :
323 if (aCell.mpFormula->IsValue())
325 nErr = aCell.mpFormula->GetErrCode();
326 nVal = aCell.mpFormula->GetValue();
337 if ((nPos + (4 * sizeof(sal_uInt16)) + sizeof(double)) > MAXARRSIZE)
339 *p++ = static_cast<sal_uInt16>(nCol);
340 *p++ = static_cast<sal_uInt16>(nRow);
341 *p++ = static_cast<sal_uInt16>(nTab);
342 *p++ = static_cast<sal_uInt16>(nErr);
343 memcpy( p, &nVal, sizeof(double));
344 nPos += 8 + sizeof(double);
345 p = reinterpret_cast<sal_uInt16*>( pCellArr + nPos );
359 bool ScInterpreter::CreateStringArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
360 SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
364 // Old Add-Ins are hard limited to sal_uInt16 values.
365 static_assert(MAXCOLCOUNT <= SAL_MAX_UINT16, "Add check
for columns > SAL_MAX_UINT16!
");
366 if (nRow1 > SAL_MAX_UINT16 || nRow2 > SAL_MAX_UINT16)
369 sal_uInt16 nCount = 0;
370 sal_uInt16* p = reinterpret_cast<sal_uInt16*>(pCellArr);
371 *p++ = static_cast<sal_uInt16>(nCol1);
372 *p++ = static_cast<sal_uInt16>(nRow1);
373 *p++ = static_cast<sal_uInt16>(nTab1);
374 *p++ = static_cast<sal_uInt16>(nCol2);
375 *p++ = static_cast<sal_uInt16>(nRow2);
376 *p++ = static_cast<sal_uInt16>(nTab2);
377 sal_uInt16* pCount = p;
379 sal_uInt16 nPos = 14;
381 while (nTab <= nTab2)
384 while (nRow <= nRow2)
387 while (nCol <= nCol2)
389 ScRefCellValue aCell(mrDoc, ScAddress(nCol, nRow, nTab));
390 if (!aCell.isEmpty())
393 FormulaError nErr = FormulaError::NONE;
395 switch (aCell.meType)
397 case CELLTYPE_STRING:
399 aStr = aCell.getString(&mrDoc);
401 case CELLTYPE_FORMULA:
402 if (!aCell.mpFormula->IsValue())
404 nErr = aCell.mpFormula->GetErrCode();
405 aStr = aCell.mpFormula->GetString().getString();
416 OString aTmp(OUStringToOString(aStr,
417 osl_getThreadTextEncoding()));
418 // Old Add-Ins are limited to sal_uInt16 string
419 // lengths, and room for pad byte check.
420 if ( aTmp.getLength() > SAL_MAX_UINT16 - 2 )
422 // Append a 0-pad-byte if string length is odd
423 // MUST be sal_uInt16
424 sal_uInt16 nStrLen = static_cast<sal_uInt16>(aTmp.getLength());
425 sal_uInt16 nLen = ( nStrLen + 2 ) & ~1;
427 if ((static_cast<sal_uLong>(nPos) + (5 * sizeof(sal_uInt16)) + nLen) > MAXARRSIZE)
429 *p++ = static_cast<sal_uInt16>(nCol);
430 *p++ = static_cast<sal_uInt16>(nRow);
431 *p++ = static_cast<sal_uInt16>(nTab);
432 *p++ = static_cast<sal_uInt16>(nErr);
434 memcpy( p, aTmp.getStr(), nStrLen + 1);
435 nPos += 10 + nStrLen + 1;
436 sal_uInt8* q = pCellArr + nPos;
437 if( (nStrLen & 1) == 0 )
442 p = reinterpret_cast<sal_uInt16*>( pCellArr + nPos );
456 bool ScInterpreter::CreateCellArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
457 SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
461 // Old Add-Ins are hard limited to sal_uInt16 values.
462 static_assert(MAXCOLCOUNT <= SAL_MAX_UINT16, "Add check
for columns > SAL_MAX_UINT16!
");
463 if (nRow1 > SAL_MAX_UINT16 || nRow2 > SAL_MAX_UINT16)
466 sal_uInt16 nCount = 0;
467 sal_uInt16* p = reinterpret_cast<sal_uInt16*>(pCellArr);
468 *p++ = static_cast<sal_uInt16>(nCol1);
469 *p++ = static_cast<sal_uInt16>(nRow1);
470 *p++ = static_cast<sal_uInt16>(nTab1);
471 *p++ = static_cast<sal_uInt16>(nCol2);
472 *p++ = static_cast<sal_uInt16>(nRow2);
473 *p++ = static_cast<sal_uInt16>(nTab2);
474 sal_uInt16* pCount = p;
476 sal_uInt16 nPos = 14;
479 while (nTab <= nTab2)
483 while (nRow <= nRow2)
487 while (nCol <= nCol2)
490 ScRefCellValue aCell(mrDoc, aAdr);
491 if (!aCell.isEmpty())
493 FormulaError nErr = FormulaError::NONE;
494 sal_uInt16 nType = 0; // 0 = number; 1 = string
498 switch (aCell.meType)
500 case CELLTYPE_STRING :
502 aStr = aCell.getString(&mrDoc);
505 case CELLTYPE_VALUE :
506 nVal = GetValueCellValue(aAdr, aCell.mfValue);
508 case CELLTYPE_FORMULA :
509 nErr = aCell.mpFormula->GetErrCode();
510 if (aCell.mpFormula->IsValue())
511 nVal = aCell.mpFormula->GetValue();
513 aStr = aCell.mpFormula->GetString().getString();
521 if ((nPos + (5 * sizeof(sal_uInt16))) > MAXARRSIZE)
523 *p++ = static_cast<sal_uInt16>(nCol);
524 *p++ = static_cast<sal_uInt16>(nRow);
525 *p++ = static_cast<sal_uInt16>(nTab);
526 *p++ = static_cast<sal_uInt16>(nErr);
531 if ((nPos + sizeof(double)) > MAXARRSIZE)
533 memcpy( p, &nVal, sizeof(double));
534 nPos += sizeof(double);
538 OString aTmp(OUStringToOString(aStr,
539 osl_getThreadTextEncoding()));
540 // Old Add-Ins are limited to sal_uInt16 string
541 // lengths, and room for pad byte check.
542 if ( aTmp.getLength() > SAL_MAX_UINT16 - 2 )
544 // Append a 0-pad-byte if string length is odd
545 // MUST be sal_uInt16
546 sal_uInt16 nStrLen = static_cast<sal_uInt16>(aTmp.getLength());
547 sal_uInt16 nLen = ( nStrLen + 2 ) & ~1;
548 if ( (static_cast<sal_uLong>(nPos) + 2 + nLen) > MAXARRSIZE)
551 memcpy( p, aTmp.getStr(), nStrLen + 1);
552 nPos += 2 + nStrLen + 1;
553 sal_uInt8* q = pCellArr + nPos;
554 if( (nStrLen & 1) == 0 )
561 p = reinterpret_cast<sal_uInt16*>( pCellArr + nPos );
576 // Also releases a TempToken if appropriate.
578 void ScInterpreter::PushWithoutError( const FormulaToken& r )
580 if ( sp >= MAXSTACK )
581 SetError( FormulaError::StackOverflow );
588 pStack[ sp ]->DecRef();
594 void ScInterpreter::Push( const FormulaToken& r )
596 if ( sp >= MAXSTACK )
597 SetError( FormulaError::StackOverflow );
600 if (nGlobalError != FormulaError::NONE)
602 if (r.GetType() == svError)
603 PushWithoutError( r);
605 PushTempTokenWithoutError( new FormulaErrorToken( nGlobalError));
608 PushWithoutError( r);
612 void ScInterpreter::PushTempToken( FormulaToken* p )
614 if ( sp >= MAXSTACK )
616 SetError( FormulaError::StackOverflow );
617 // p may be a dangling pointer hereafter!
618 p->DeleteIfZeroRef();
622 if (nGlobalError != FormulaError::NONE)
624 if (p->GetType() == svError)
626 p->SetError( nGlobalError);
627 PushTempTokenWithoutError( p);
631 // p may be a dangling pointer hereafter!
632 p->DeleteIfZeroRef();
633 PushTempTokenWithoutError( new FormulaErrorToken( nGlobalError));
637 PushTempTokenWithoutError( p);
641 void ScInterpreter::PushTempTokenWithoutError( const FormulaToken* p )
644 if ( sp >= MAXSTACK )
646 SetError( FormulaError::StackOverflow );
647 // p may be a dangling pointer hereafter!
655 pStack[ sp ]->DecRef();
661 void ScInterpreter::PushTokenRef( const formula::FormulaConstTokenRef& x )
663 if ( sp >= MAXSTACK )
665 SetError( FormulaError::StackOverflow );
669 if (nGlobalError != FormulaError::NONE)
671 if (x->GetType() == svError && x->GetError() == nGlobalError)
672 PushTempTokenWithoutError( x.get());
674 PushTempTokenWithoutError( new FormulaErrorToken( nGlobalError));
677 PushTempTokenWithoutError( x.get());
681 void ScInterpreter::PushCellResultToken( bool bDisplayEmptyAsString,
682 const ScAddress & rAddress, SvNumFormatType * pRetTypeExpr, sal_uInt32 * pRetIndexExpr, bool bFinalResult )
684 ScRefCellValue aCell(mrDoc, rAddress);
685 if (aCell.hasEmptyValue())
687 bool bInherited = (aCell.meType == CELLTYPE_FORMULA);
688 if (pRetTypeExpr && pRetIndexExpr)
689 mrDoc.GetNumberFormatInfo(mrContext, *pRetTypeExpr, *pRetIndexExpr, rAddress);
690 PushTempToken( new ScEmptyCellToken( bInherited, bDisplayEmptyAsString));
694 FormulaError nErr = FormulaError::NONE;
695 if (aCell.meType == CELLTYPE_FORMULA)
696 nErr = aCell.mpFormula->GetErrCode();
698 if (nErr != FormulaError::NONE)
702 *pRetTypeExpr = SvNumFormatType::UNDEFINED;
706 else if (aCell.hasString())
708 svl::SharedString aRes;
709 GetCellString( aRes, aCell);
712 *pRetTypeExpr = SvNumFormatType::TEXT;
718 double fVal = GetCellValue(rAddress, aCell);
721 TreatDoubleError( fVal);
722 if (!IfErrorPushError())
723 PushTempTokenWithoutError( CreateFormulaDoubleToken( fVal));
730 *pRetTypeExpr = nCurFmtType;
732 *pRetIndexExpr = nCurFmtIndex;
736 // Simply throw away TOS.
738 void ScInterpreter::Pop()
743 SetError(FormulaError::UnknownStackVariable);
746 // Simply throw away TOS and set error code, used with ocIsError et al.
748 void ScInterpreter::PopError()
753 if (pStack[sp]->GetType() == svError)
754 nGlobalError = pStack[sp]->GetError();
757 SetError(FormulaError::UnknownStackVariable);
760 FormulaConstTokenRef ScInterpreter::PopToken()
765 const FormulaToken* p = pStack[ sp ];
766 if (p->GetType() == svError)
767 nGlobalError = p->GetError();
771 SetError(FormulaError::UnknownStackVariable);
775 double ScInterpreter::PopDouble()
777 nCurFmtType = SvNumFormatType::NUMBER;
782 const FormulaToken* p = pStack[ sp ];
783 switch (p->GetType())
786 nGlobalError = p->GetError();
790 SvNumFormatType nType = static_cast<SvNumFormatType>(p->GetDoubleType());
791 if (nType != SvNumFormatType::ALL && nType != SvNumFormatType::UNDEFINED)
793 return p->GetDouble();
799 SetError( FormulaError::IllegalArgument);
803 SetError( FormulaError::UnknownStackVariable);
807 svl::SharedString ScInterpreter::PopString()
809 nCurFmtType = SvNumFormatType::TEXT;
814 const FormulaToken* p = pStack[ sp ];
815 switch (p->GetType())
818 nGlobalError = p->GetError();
821 return p->GetString();
824 return svl::SharedString::getEmptyString();
826 SetError( FormulaError::IllegalArgument);
830 SetError( FormulaError::UnknownStackVariable);
832 return svl::SharedString::getEmptyString();
835 void ScInterpreter::ValidateRef( const ScSingleRefData & rRef )
840 SingleRefToVars( rRef, nCol, nRow, nTab);
843 void ScInterpreter::ValidateRef( const ScComplexRefData & rRef )
845 ValidateRef( rRef.Ref1);
846 ValidateRef( rRef.Ref2);
849 void ScInterpreter::ValidateRef( const ScRefList & rRefList )
851 for (const auto& rRef : rRefList)
857 void ScInterpreter::SingleRefToVars( const ScSingleRefData & rRef,
858 SCCOL & rCol, SCROW & rRow, SCTAB & rTab )
860 if ( rRef.IsColRel() )
861 rCol = aPos.Col() + rRef.Col();
865 if ( rRef.IsRowRel() )
866 rRow = aPos.Row() + rRef.Row();
870 if ( rRef.IsTabRel() )
871 rTab = aPos.Tab() + rRef.Tab();
875 if( !mrDoc.ValidCol( rCol) || rRef.IsColDeleted() )
877 SetError( FormulaError::NoRef );
880 if( !mrDoc.ValidRow( rRow) || rRef.IsRowDeleted() )
882 SetError( FormulaError::NoRef );
885 if( !ValidTab( rTab, mrDoc.GetTableCount() - 1) || rRef.IsTabDeleted() )
887 SetError( FormulaError::NoRef );
892 void ScInterpreter::PopSingleRef(SCCOL& rCol, SCROW &rRow, SCTAB& rTab)
894 ScAddress aAddr(rCol, rRow, rTab);
901 void ScInterpreter::PopSingleRef( ScAddress& rAdr )
906 const FormulaToken* p = pStack[ sp ];
907 switch (p->GetType())
910 nGlobalError = p->GetError();
914 const ScSingleRefData* pRefData = p->GetSingleRef();
915 if (pRefData->IsDeleted())
917 SetError( FormulaError::NoRef);
924 SingleRefToVars( *pRefData, nCol, nRow, nTab);
925 rAdr.Set( nCol, nRow, nTab );
926 if (!mrDoc.m_TableOpList.empty())
931 SetError( FormulaError::IllegalParameter);
935 SetError( FormulaError::UnknownStackVariable);
938 void ScInterpreter::DoubleRefToVars( const formula::FormulaToken* p,
939 SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
940 SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2 )
942 const ScComplexRefData& rCRef = *p->GetDoubleRef();
943 SingleRefToVars( rCRef.Ref1, rCol1, rRow1, rTab1);
944 SingleRefToVars( rCRef.Ref2, rCol2, rRow2, rTab2);
946 std::swap( rCol2, rCol1);
948 std::swap( rRow2, rRow1);
950 std::swap( rTab2, rTab1);
951 if (!mrDoc.m_TableOpList.empty())
953 ScRange aRange( rCol1, rRow1, rTab1, rCol2, rRow2, rTab2 );
954 if ( IsTableOpInRange( aRange ) )
955 SetError( FormulaError::IllegalParameter );
959 ScDBRangeBase* ScInterpreter::PopDBDoubleRef()
961 StackVar eType = GetStackType();
965 SetError(FormulaError::UnknownStackVariable);
975 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
976 if (nGlobalError != FormulaError::NONE)
978 return new ScDBInternalRange(&mrDoc,
979 ScRange(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2));
982 case svExternalDoubleRef:
985 if (eType == svMatrix)
988 PopExternalDoubleRef(pMat);
989 if (nGlobalError != FormulaError::NONE)
991 return new ScDBExternalRange(&mrDoc, pMat);
994 SetError( FormulaError::IllegalParameter);
1000 void ScInterpreter::PopDoubleRef(SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
1001 SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2)
1006 const FormulaToken* p = pStack[ sp ];
1007 switch (p->GetType())
1010 nGlobalError = p->GetError();
1013 DoubleRefToVars( p, rCol1, rRow1, rTab1, rCol2, rRow2, rTab2);
1016 SetError( FormulaError::IllegalParameter);
1020 SetError( FormulaError::UnknownStackVariable);
1023 void ScInterpreter::DoubleRefToRange( const ScComplexRefData & rCRef,
1024 ScRange & rRange, bool bDontCheckForTableOp )
1029 SingleRefToVars( rCRef.Ref1, nCol, nRow, nTab);
1030 rRange.aStart.Set( nCol, nRow, nTab );
1031 SingleRefToVars( rCRef.Ref2, nCol, nRow, nTab);
1032 rRange.aEnd.Set( nCol, nRow, nTab );
1033 rRange.PutInOrder();
1034 if (!mrDoc.m_TableOpList.empty() && !bDontCheckForTableOp)
1036 if ( IsTableOpInRange( rRange ) )
1037 SetError( FormulaError::IllegalParameter );
1041 void ScInterpreter::PopDoubleRef( ScRange & rRange, short & rParam, size_t & rRefInList )
1045 const formula::FormulaToken* pToken = pStack[ sp-1 ];
1046 switch (pToken->GetType())
1049 nGlobalError = pToken->GetError();
1054 const ScComplexRefData* pRefData = pToken->GetDoubleRef();
1055 if (pRefData->IsDeleted())
1057 SetError( FormulaError::NoRef);
1060 DoubleRefToRange( *pRefData, rRange);
1065 const ScRefList* pList = pToken->GetRefList();
1066 if (rRefInList < pList->size())
1068 DoubleRefToRange( (*pList)[rRefInList], rRange);
1069 if (++rRefInList < pList->size())
1081 SetError( FormulaError::IllegalParameter);
1086 SetError( FormulaError::IllegalParameter);
1090 SetError( FormulaError::UnknownStackVariable);
1093 void ScInterpreter::PopDoubleRef( ScRange& rRange, bool bDontCheckForTableOp )
1098 const FormulaToken* p = pStack[ sp ];
1099 switch (p->GetType())
1102 nGlobalError = p->GetError();
1105 DoubleRefToRange( *p->GetDoubleRef(), rRange, bDontCheckForTableOp);
1108 SetError( FormulaError::IllegalParameter);
1112 SetError( FormulaError::UnknownStackVariable);
1115 void ScInterpreter::PopExternalSingleRef(sal_uInt16& rFileId, OUString& rTabName, ScSingleRefData& rRef)
1119 SetError(FormulaError::UnknownStackVariable);
1124 const FormulaToken* p = pStack[sp];
1125 StackVar eType = p->GetType();
1127 if (eType == svError)
1129 nGlobalError = p->GetError();
1133 if (eType != svExternalSingleRef)
1135 SetError( FormulaError::IllegalParameter);
1139 rFileId = p->GetIndex();
1140 rTabName = p->GetString().getString();
1141 rRef = *p->GetSingleRef();
1144 void ScInterpreter::PopExternalSingleRef(ScExternalRefCache::TokenRef& rToken, ScExternalRefCache::CellFormat* pFmt)
1148 ScSingleRefData aData;
1149 PopExternalSingleRef(nFileId, aTabName, aData, rToken, pFmt);
1152 void ScInterpreter::PopExternalSingleRef(
1153 sal_uInt16& rFileId, OUString& rTabName, ScSingleRefData& rRef,
1154 ScExternalRefCache::TokenRef& rToken, ScExternalRefCache::CellFormat* pFmt)
1156 PopExternalSingleRef(rFileId, rTabName, rRef);
1157 if (nGlobalError != FormulaError::NONE)
1160 ScExternalRefManager* pRefMgr = mrDoc.GetExternalRefManager();
1161 const OUString* pFile = pRefMgr->getExternalFileName(rFileId);
1164 SetError(FormulaError::NoName);
1168 if (rRef.IsTabRel())
1170 OSL_FAIL("ScCompiler::GetToken: external single reference must have an absolute table reference!
");
1171 SetError(FormulaError::NoRef);
1175 ScAddress aAddr = rRef.toAbs(mrDoc, aPos);
1176 ScExternalRefCache::CellFormat aFmt;
1177 ScExternalRefCache::TokenRef xNew = pRefMgr->getSingleRefToken(
1178 rFileId, rTabName, aAddr, &aPos, nullptr, &aFmt);
1182 SetError(FormulaError::NoRef);
1186 if (xNew->GetType() == svError)
1187 SetError( xNew->GetError());
1194 void ScInterpreter::PopExternalDoubleRef(sal_uInt16& rFileId, OUString& rTabName, ScComplexRefData& rRef)
1198 SetError(FormulaError::UnknownStackVariable);
1203 const FormulaToken* p = pStack[sp];
1204 StackVar eType = p->GetType();
1206 if (eType == svError)
1208 nGlobalError = p->GetError();
1212 if (eType != svExternalDoubleRef)
1214 SetError( FormulaError::IllegalParameter);
1218 rFileId = p->GetIndex();
1219 rTabName = p->GetString().getString();
1220 rRef = *p->GetDoubleRef();
1223 void ScInterpreter::PopExternalDoubleRef(ScExternalRefCache::TokenArrayRef& rArray)
1227 ScComplexRefData aData;
1228 PopExternalDoubleRef(nFileId, aTabName, aData);
1229 if (nGlobalError != FormulaError::NONE)
1232 GetExternalDoubleRef(nFileId, aTabName, aData, rArray);
1233 if (nGlobalError != FormulaError::NONE)
1237 void ScInterpreter::PopExternalDoubleRef(ScMatrixRef& rMat)
1239 ScExternalRefCache::TokenArrayRef pArray;
1240 PopExternalDoubleRef(pArray);
1241 if (nGlobalError != FormulaError::NONE)
1244 // For now, we only support single range data for external
1245 // references, which means the array should only contain a
1246 // single matrix token.
1247 formula::FormulaToken* p = pArray->FirstToken();
1248 if (!p || p->GetType() != svMatrix)
1249 SetError( FormulaError::IllegalParameter);
1252 rMat = p->GetMatrix();
1254 SetError( FormulaError::UnknownVariable);
1258 void ScInterpreter::GetExternalDoubleRef(
1259 sal_uInt16 nFileId, const OUString& rTabName, const ScComplexRefData& rData, ScExternalRefCache::TokenArrayRef& rArray)
1261 ScExternalRefManager* pRefMgr = mrDoc.GetExternalRefManager();
1262 const OUString* pFile = pRefMgr->getExternalFileName(nFileId);
1265 SetError(FormulaError::NoName);
1268 if (rData.Ref1.IsTabRel() || rData.Ref2.IsTabRel())
1270 OSL_FAIL("ScCompiler::GetToken: external
double reference must have an absolute table reference!
");
1271 SetError(FormulaError::NoRef);
1275 ScComplexRefData aData(rData);
1276 ScRange aRange = aData.toAbs(mrDoc, aPos);
1277 if (!mrDoc.ValidColRow(aRange.aStart.Col(), aRange.aStart.Row()) || !mrDoc.ValidColRow(aRange.aEnd.Col(), aRange.aEnd.Row()))
1279 SetError(FormulaError::NoRef);
1283 ScExternalRefCache::TokenArrayRef pArray = pRefMgr->getDoubleRefTokens(
1284 nFileId, rTabName, aRange, &aPos);
1288 SetError(FormulaError::IllegalArgument);
1292 formula::FormulaTokenArrayPlainIterator aIter(*pArray);
1293 formula::FormulaToken* pToken = aIter.First();
1295 if (pToken->GetType() == svError)
1297 SetError( pToken->GetError());
1300 if (pToken->GetType() != svMatrix)
1302 SetError(FormulaError::IllegalArgument);
1308 // Can't handle more than one matrix per parameter.
1309 SetError( FormulaError::IllegalArgument);
1316 bool ScInterpreter::PopDoubleRefOrSingleRef( ScAddress& rAdr )
1318 switch ( GetStackType() )
1323 PopDoubleRef( aRange, true );
1324 return DoubleRefToPosSingleRef( aRange, rAdr );
1328 PopSingleRef( rAdr );
1333 SetError( FormulaError::NoRef );
1338 void ScInterpreter::PopDoubleRefPushMatrix()
1340 if ( GetStackType() == svDoubleRef )
1342 ScMatrixRef pMat = GetMatrix();
1346 PushIllegalParameter();
1349 SetError( FormulaError::NoRef );
1352 void ScInterpreter::PopRefListPushMatrixOrRef()
1354 if ( GetStackType() == svRefList )
1356 FormulaConstTokenRef xTok = pStack[sp-1];
1357 const std::vector<ScComplexRefData>* pv = xTok->GetRefList();
1360 const size_t nEntries = pv->size();
1364 PushTempTokenWithoutError( new ScDoubleRefToken( mrDoc.GetSheetLimits(), (*pv)[0] ));
1366 else if (bMatrixFormula)
1368 // Only single cells can be stuffed into a column vector.
1369 // XXX NOTE: Excel doesn't do this but returns #VALUE! instead.
1370 // Though there's no compelling reason not to...
1371 for (const auto & rRef : *pv)
1373 if (rRef.Ref1 != rRef.Ref2)
1376 ScMatrixRef xMat = GetNewMat( 1, nEntries, true); // init empty
1379 for (size_t i=0; i < nEntries; ++i)
1381 SCCOL nCol; SCROW nRow; SCTAB nTab;
1382 SingleRefToVars( (*pv)[i].Ref1, nCol, nRow, nTab);
1383 if (nGlobalError == FormulaError::NONE)
1385 ScAddress aAdr( nCol, nRow, nTab);
1386 ScRefCellValue aCell(mrDoc, aAdr);
1387 if (aCell.hasError())
1388 xMat->PutError( aCell.mpFormula->GetErrCode(), 0, i);
1389 else if (aCell.hasEmptyValue())
1390 xMat->PutEmpty( 0, i);
1391 else if (aCell.hasString())
1392 xMat->PutString( mrStrPool.intern( aCell.getString(&mrDoc)), 0, i);
1394 xMat->PutDouble( aCell.getValue(), 0, i);
1398 xMat->PutError( nGlobalError, 0, i);
1399 nGlobalError = FormulaError::NONE;
1406 // else: keep token on stack, something will handle the error
1409 SetError( FormulaError::NoRef );
1412 void ScInterpreter::ConvertMatrixJumpConditionToMatrix()
1414 StackVar eStackType = GetStackType();
1415 if (eStackType == svUnknown)
1416 return; // can't do anything, some caller will catch that
1417 if (eStackType == svMatrix)
1418 return; // already matrix, nothing to do
1420 if (eStackType != svDoubleRef && GetStackType(2) != svJumpMatrix)
1421 return; // always convert svDoubleRef, others only in JumpMatrix context
1423 GetTokenMatrixMap(); // make sure it exists, create if not.
1424 ScMatrixRef pMat = GetMatrix();
1428 PushIllegalParameter();
1431 std::unique_ptr<ScTokenMatrixMap> ScInterpreter::CreateTokenMatrixMap()
1433 return std::make_unique<ScTokenMatrixMap>();
1436 bool ScInterpreter::ConvertMatrixParameters()
1438 sal_uInt16 nParams = pCur->GetParamCount();
1439 OSL_ENSURE( nParams <= sp, "ConvertMatrixParameters: stack/param count mismatch
");
1440 SCSIZE nJumpCols = 0, nJumpRows = 0;
1441 for ( sal_uInt16 i=1; i <= nParams && i <= sp; ++i )
1443 const FormulaToken* p = pStack[ sp - i ];
1444 if ( p->GetOpCode() != ocPush && p->GetOpCode() != ocMissing)
1446 OSL_FAIL( "ConvertMatrixParameters: not a push
");
1450 switch ( p->GetType() )
1455 case svExternalSingleRef:
1463 if ( ScParameterClassification::GetParameterType( pCur, nParams - i)
1464 == formula::ParamClass::Value )
1465 { // only if single value expected
1466 ScConstMatrixRef pMat = p->GetMatrix();
1468 SetError( FormulaError::UnknownVariable);
1471 SCSIZE nCols, nRows;
1472 pMat->GetDimensions( nCols, nRows);
1473 if ( nJumpCols < nCols )
1475 if ( nJumpRows < nRows )
1483 formula::ParamClass eType = ScParameterClassification::GetParameterType( pCur, nParams - i);
1484 if ( eType != formula::ParamClass::Reference &&
1485 eType != formula::ParamClass::ReferenceOrRefArray &&
1486 eType != formula::ParamClass::ReferenceOrForceArray &&
1487 // For scalar Value: convert to Array/JumpMatrix
1488 // only if in array formula context, else (function
1489 // has ForceArray or ReferenceOrForceArray
1490 // parameter *somewhere else*) pick a normal
1491 // position dependent implicit intersection later.
1492 (eType != formula::ParamClass::Value || IsInArrayContext()))
1497 DoubleRefToVars( p, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
1498 // Make sure the map exists, created if not.
1499 GetTokenMatrixMap();
1500 ScMatrixRef pMat = CreateMatrixFromDoubleRef( p,
1501 nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
1504 if ( eType == formula::ParamClass::Value )
1505 { // only if single value expected
1506 if ( nJumpCols < o3tl::make_unsigned(nCol2 - nCol1 + 1) )
1507 nJumpCols = static_cast<SCSIZE>(nCol2 - nCol1 + 1);
1508 if ( nJumpRows < o3tl::make_unsigned(nRow2 - nRow1 + 1) )
1509 nJumpRows = static_cast<SCSIZE>(nRow2 - nRow1 + 1);
1511 formula::FormulaToken* pNew = new ScMatrixToken( pMat);
1513 pStack[ sp - i ] = pNew;
1514 p->DecRef(); // p may be dead now!
1519 case svExternalDoubleRef:
1521 formula::ParamClass eType = ScParameterClassification::GetParameterType( pCur, nParams - i);
1522 if (eType == formula::ParamClass::Value || eType == formula::ParamClass::Array)
1524 sal_uInt16 nFileId = p->GetIndex();
1525 OUString aTabName = p->GetString().getString();
1526 const ScComplexRefData& rRef = *p->GetDoubleRef();
1527 ScExternalRefCache::TokenArrayRef pArray;
1528 GetExternalDoubleRef(nFileId, aTabName, rRef, pArray);
1529 if (nGlobalError != FormulaError::NONE || !pArray)
1531 formula::FormulaToken* pTemp = pArray->FirstToken();
1535 ScMatrixRef pMat = pTemp->GetMatrix();
1538 if (eType == formula::ParamClass::Value)
1539 { // only if single value expected
1541 pMat->GetDimensions( nC, nR);
1547 formula::FormulaToken* pNew = new ScMatrixToken( pMat);
1549 pStack[ sp - i ] = pNew;
1550 p->DecRef(); // p may be dead now!
1557 formula::ParamClass eType = ScParameterClassification::GetParameterType( pCur, nParams - i);
1558 if ( eType != formula::ParamClass::Reference &&
1559 eType != formula::ParamClass::ReferenceOrRefArray &&
1560 eType != formula::ParamClass::ReferenceOrForceArray &&
1561 eType != formula::ParamClass::ForceArray)
1563 // can't convert to matrix
1564 SetError( FormulaError::NoValue);
1566 // else: the consuming function has to decide if and how to
1567 // handle a reference list argument in array context.
1571 OSL_FAIL( "ConvertMatrixParameters: unknown parameter type
");
1575 if( nJumpCols && nJumpRows )
1577 short nPC = aCode.GetPC();
1578 short nStart = nPC - 1; // restart on current code (-1)
1579 short nNext = nPC; // next instruction after subroutine
1580 short nStop = nPC + 1; // stop subroutine before reaching that
1581 FormulaConstTokenRef xNew;
1582 ScTokenMatrixMap::const_iterator aMapIter;
1583 if (pTokenMatrixMap && ((aMapIter = pTokenMatrixMap->find( pCur)) != pTokenMatrixMap->end()))
1584 xNew = (*aMapIter).second;
1587 auto pJumpMat = std::make_shared<ScJumpMatrix>( pCur->GetOpCode(), nJumpCols, nJumpRows);
1588 pJumpMat->SetAllJumps( 1.0, nStart, nNext, nStop);
1589 // pop parameters and store in ScJumpMatrix, push in JumpMatrix()
1590 ScTokenVec aParams(nParams);
1591 for ( sal_uInt16 i=1; i <= nParams && sp > 0; ++i )
1593 const FormulaToken* p = pStack[ --sp ];
1595 // store in reverse order such that a push may simply iterate
1596 aParams[ nParams - i ] = p;
1598 pJumpMat->SetJumpParameters( std::move(aParams) );
1599 xNew = new ScJumpMatrixToken( std::move(pJumpMat) );
1600 GetTokenMatrixMap().emplace(pCur, xNew);
1602 PushTempTokenWithoutError( xNew.get());
1603 // set continuation point of path for main code line
1604 aCode.Jump( nNext, nNext);
1610 ScMatrixRef ScInterpreter::PopMatrix()
1615 const FormulaToken* p = pStack[ sp ];
1616 switch (p->GetType())
1619 nGlobalError = p->GetError();
1623 // ScMatrix itself maintains an im/mutable flag that should
1624 // be obeyed where necessary... so we can return ScMatrixRef
1625 // here instead of ScConstMatrixRef.
1626 ScMatrix* pMat = const_cast<FormulaToken*>(p)->GetMatrix();
1628 pMat->SetErrorInterpreter( this);
1630 SetError( FormulaError::UnknownVariable);
1634 SetError( FormulaError::IllegalParameter);
1638 SetError( FormulaError::UnknownStackVariable);
1642 sc::RangeMatrix ScInterpreter::PopRangeMatrix()
1644 sc::RangeMatrix aRet;
1647 switch (pStack[sp-1]->GetType())
1652 const FormulaToken* p = pStack[sp];
1653 aRet.mpMat = const_cast<FormulaToken*>(p)->GetMatrix();
1656 aRet.mpMat->SetErrorInterpreter(this);
1657 if (p->GetByte() == MATRIX_TOKEN_HAS_RANGE)
1659 const ScComplexRefData& rRef = *p->GetDoubleRef();
1660 if (!rRef.Ref1.IsColRel() && !rRef.Ref1.IsRowRel() && !rRef.Ref2.IsColRel() && !rRef.Ref2.IsRowRel())
1662 aRet.mnCol1 = rRef.Ref1.Col();
1663 aRet.mnRow1 = rRef.Ref1.Row();
1664 aRet.mnTab1 = rRef.Ref1.Tab();
1665 aRet.mnCol2 = rRef.Ref2.Col();
1666 aRet.mnRow2 = rRef.Ref2.Row();
1667 aRet.mnTab2 = rRef.Ref2.Tab();
1672 SetError( FormulaError::UnknownVariable);
1676 aRet.mpMat = PopMatrix();
1682 void ScInterpreter::QueryMatrixType(const ScMatrixRef& xMat, SvNumFormatType& rRetTypeExpr, sal_uInt32& rRetIndexExpr)
1686 SCSIZE nCols, nRows;
1687 xMat->GetDimensions(nCols, nRows);
1688 ScMatrixValue nMatVal = xMat->Get(0, 0);
1689 ScMatValType nMatValType = nMatVal.nType;
1690 if (ScMatrix::IsNonValueType( nMatValType))
1692 if ( xMat->IsEmptyPath( 0, 0))
1693 { // result of empty FALSE jump path
1694 FormulaTokenRef xRes = CreateFormulaDoubleToken( 0.0);
1695 PushTempToken( new ScMatrixFormulaCellToken(nCols, nRows, xMat, xRes.get()));
1696 rRetTypeExpr = SvNumFormatType::LOGICAL;
1698 else if ( xMat->IsEmptyResult( 0, 0))
1699 { // empty formula result
1700 FormulaTokenRef xRes = new ScEmptyCellToken( true, true); // inherited, display empty
1701 PushTempToken( new ScMatrixFormulaCellToken(nCols, nRows, xMat, xRes.get()));
1703 else if ( xMat->IsEmpty( 0, 0))
1704 { // empty or empty cell
1705 FormulaTokenRef xRes = new ScEmptyCellToken( false, true); // not inherited, display empty
1706 PushTempToken( new ScMatrixFormulaCellToken(nCols, nRows, xMat, xRes.get()));
1710 FormulaTokenRef xRes = new FormulaStringToken( nMatVal.GetString() );
1711 PushTempToken( new ScMatrixFormulaCellToken(nCols, nRows, xMat, xRes.get()));
1712 rRetTypeExpr = SvNumFormatType::TEXT;
1717 FormulaError nErr = GetDoubleErrorValue( nMatVal.fVal);
1718 FormulaTokenRef xRes;
1719 if (nErr != FormulaError::NONE)
1720 xRes = new FormulaErrorToken( nErr);
1722 xRes = CreateFormulaDoubleToken( nMatVal.fVal);
1723 PushTempToken( new ScMatrixFormulaCellToken(nCols, nRows, xMat, xRes.get()));
1724 if ( rRetTypeExpr != SvNumFormatType::LOGICAL )
1725 rRetTypeExpr = SvNumFormatType::NUMBER;
1728 xMat->SetErrorInterpreter( nullptr);
1731 SetError( FormulaError::UnknownStackVariable);
1734 formula::FormulaToken* ScInterpreter::CreateFormulaDoubleToken( double fVal, SvNumFormatType nFmt )
1736 assert( mrContext.maTokens.size() == TOKEN_CACHE_SIZE );
1738 // Find a spare token
1739 for ( auto p : mrContext.maTokens )
1741 if (p && p->GetRef() == 1)
1743 p->GetDoubleAsReference() = fVal;
1744 p->SetDoubleType( static_cast<sal_Int16>(nFmt) );
1749 // Allocate a new token
1750 auto p = new FormulaTypedDoubleToken( fVal, static_cast<sal_Int16>(nFmt) );
1751 if ( mrContext.maTokens[mrContext.mnTokenCachePos] )
1752 mrContext.maTokens[mrContext.mnTokenCachePos]->DecRef();
1753 mrContext.maTokens[mrContext.mnTokenCachePos] = p;
1755 mrContext.mnTokenCachePos = (mrContext.mnTokenCachePos + 1) % TOKEN_CACHE_SIZE;
1759 formula::FormulaToken* ScInterpreter::CreateDoubleOrTypedToken( double fVal )
1761 // NumberFormat::NUMBER is the default untyped double.
1762 if (nFuncFmtType != SvNumFormatType::ALL && nFuncFmtType != SvNumFormatType::NUMBER &&
1763 nFuncFmtType != SvNumFormatType::UNDEFINED)
1764 return CreateFormulaDoubleToken( fVal, nFuncFmtType);
1766 return CreateFormulaDoubleToken( fVal);
1769 void ScInterpreter::PushDouble(double nVal)
1771 TreatDoubleError( nVal );
1772 if (!IfErrorPushError())
1773 PushTempTokenWithoutError( CreateDoubleOrTypedToken( nVal));
1776 void ScInterpreter::PushInt(int nVal)
1778 if (!IfErrorPushError())
1779 PushTempTokenWithoutError( CreateDoubleOrTypedToken( nVal));
1782 void ScInterpreter::PushStringBuffer( const sal_Unicode* pString )
1786 svl::SharedString aSS = mrDoc.GetSharedStringPool().intern(OUString(pString));
1790 PushString(svl::SharedString::getEmptyString());
1793 void ScInterpreter::PushString( const OUString& rStr )
1795 PushString(mrDoc.GetSharedStringPool().intern(rStr));
1798 void ScInterpreter::PushString( const svl::SharedString& rString )
1800 if (!IfErrorPushError())
1801 PushTempTokenWithoutError( new FormulaStringToken( rString ) );
1804 void ScInterpreter::PushSingleRef(SCCOL nCol, SCROW nRow, SCTAB nTab)
1806 if (!IfErrorPushError())
1808 ScSingleRefData aRef;
1809 aRef.InitAddress(ScAddress(nCol,nRow,nTab));
1810 PushTempTokenWithoutError( new ScSingleRefToken( mrDoc.GetSheetLimits(), aRef ) );
1814 void ScInterpreter::PushDoubleRef(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
1815 SCCOL nCol2, SCROW nRow2, SCTAB nTab2)
1817 if (!IfErrorPushError())
1819 ScComplexRefData aRef;
1820 aRef.InitRange(ScRange(nCol1,nRow1,nTab1,nCol2,nRow2,nTab2));
1821 PushTempTokenWithoutError( new ScDoubleRefToken( mrDoc.GetSheetLimits(), aRef ) );
1825 void ScInterpreter::PushExternalSingleRef(
1826 sal_uInt16 nFileId, const OUString& rTabName, SCCOL nCol, SCROW nRow, SCTAB nTab)
1828 if (!IfErrorPushError())
1830 ScSingleRefData aRef;
1831 aRef.InitAddress(ScAddress(nCol,nRow,nTab));
1832 PushTempTokenWithoutError( new ScExternalSingleRefToken(nFileId,
1833 mrDoc.GetSharedStringPool().intern( rTabName), aRef)) ;
1837 void ScInterpreter::PushExternalDoubleRef(
1838 sal_uInt16 nFileId, const OUString& rTabName,
1839 SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2)
1841 if (!IfErrorPushError())
1843 ScComplexRefData aRef;
1844 aRef.InitRange(ScRange(nCol1,nRow1,nTab1,nCol2,nRow2,nTab2));
1845 PushTempTokenWithoutError( new ScExternalDoubleRefToken(nFileId,
1846 mrDoc.GetSharedStringPool().intern( rTabName), aRef) );
1850 void ScInterpreter::PushSingleRef( const ScRefAddress& rRef )
1852 if (!IfErrorPushError())
1854 ScSingleRefData aRef;
1855 aRef.InitFromRefAddress( mrDoc, rRef, aPos);
1856 PushTempTokenWithoutError( new ScSingleRefToken( mrDoc.GetSheetLimits(), aRef ) );
1860 void ScInterpreter::PushDoubleRef( const ScRefAddress& rRef1, const ScRefAddress& rRef2 )
1862 if (!IfErrorPushError())
1864 ScComplexRefData aRef;
1865 aRef.InitFromRefAddresses( mrDoc, rRef1, rRef2, aPos);
1866 PushTempTokenWithoutError( new ScDoubleRefToken( mrDoc.GetSheetLimits(), aRef ) );
1870 void ScInterpreter::PushMatrix( const sc::RangeMatrix& rMat )
1872 if (!rMat.isRangeValid())
1874 // Just push the matrix part only.
1875 PushMatrix(rMat.mpMat);
1879 rMat.mpMat->SetErrorInterpreter(nullptr);
1880 nGlobalError = FormulaError::NONE;
1881 PushTempTokenWithoutError(new ScMatrixRangeToken(rMat));
1884 void ScInterpreter::PushMatrix(const ScMatrixRef& pMat)
1886 pMat->SetErrorInterpreter( nullptr);
1887 // No if (!IfErrorPushError()) because ScMatrix stores errors itself,
1888 // but with notifying ScInterpreter via nGlobalError, substituting it would
1889 // mean to inherit the error on all array elements in all following
1891 nGlobalError = FormulaError::NONE;
1892 PushTempTokenWithoutError( new ScMatrixToken( pMat ) );
1895 void ScInterpreter::PushError( FormulaError nError )
1897 SetError( nError ); // only sets error if not already set
1898 PushTempTokenWithoutError( new FormulaErrorToken( nGlobalError));
1901 void ScInterpreter::PushParameterExpected()
1903 PushError( FormulaError::ParameterExpected);
1906 void ScInterpreter::PushIllegalParameter()
1908 PushError( FormulaError::IllegalParameter);
1911 void ScInterpreter::PushIllegalArgument()
1913 PushError( FormulaError::IllegalArgument);
1916 void ScInterpreter::PushNA()
1918 PushError( FormulaError::NotAvailable);
1921 void ScInterpreter::PushNoValue()
1923 PushError( FormulaError::NoValue);
1926 bool ScInterpreter::IsMissing() const
1928 return sp && pStack[sp - 1]->GetType() == svMissing;
1931 StackVar ScInterpreter::GetRawStackType()
1936 eRes = pStack[sp - 1]->GetType();
1940 SetError(FormulaError::UnknownStackVariable);
1946 StackVar ScInterpreter::GetStackType()
1951 eRes = pStack[sp - 1]->GetType();
1952 if( eRes == svMissing || eRes == svEmptyCell )
1953 eRes = svDouble; // default!
1957 SetError(FormulaError::UnknownStackVariable);
1963 StackVar ScInterpreter::GetStackType( sal_uInt8 nParam )
1968 eRes = pStack[sp - nParam]->GetType();
1969 if( eRes == svMissing || eRes == svEmptyCell )
1970 eRes = svDouble; // default!
1977 void ScInterpreter::ReverseStack( sal_uInt8 nParamCount )
1979 //reverse order of parameter stack
1980 assert( sp >= nParamCount && " less stack elements than parameters
");
1981 sal_uInt16 nStackParams = std::min<sal_uInt16>( sp, nParamCount);
1982 std::reverse( pStack+(sp-nStackParams), pStack+sp );
1985 bool ScInterpreter::DoubleRefToPosSingleRef( const ScRange& rRange, ScAddress& rAdr )
1987 // Check for a singleton first - no implicit intersection for them.
1988 if( rRange.aStart == rRange.aEnd )
1990 rAdr = rRange.aStart;
1998 bOk = rRange.aStart.Tab() == rRange.aEnd.Tab();
2000 SetError( FormulaError::IllegalArgument);
2004 pJumpMatrix->GetPos( nC, nR);
2005 rAdr.SetCol( sal::static_int_cast<SCCOL>( rRange.aStart.Col() + nC ) );
2006 rAdr.SetRow( sal::static_int_cast<SCROW>( rRange.aStart.Row() + nR ) );
2007 rAdr.SetTab( rRange.aStart.Tab());
2008 bOk = rRange.aStart.Col() <= rAdr.Col() && rAdr.Col() <=
2009 rRange.aEnd.Col() && rRange.aStart.Row() <= rAdr.Row() &&
2010 rAdr.Row() <= rRange.aEnd.Row();
2012 SetError( FormulaError::NoValue);
2017 bOk = ScCompiler::DoubleRefToPosSingleRefScalarCase(rRange, rAdr, aPos);
2020 SetError( FormulaError::NoValue );
2024 double ScInterpreter::GetDoubleFromMatrix(const ScMatrixRef& pMat)
2031 double fVal = pMat->GetDoubleWithStringConversion( 0, 0);
2032 FormulaError nErr = GetDoubleErrorValue( fVal);
2033 if (nErr != FormulaError::NONE)
2035 // Do not propagate the coded double error, but set nGlobalError in
2036 // case the matrix did not have an error interpreter set.
2043 SCSIZE nCols, nRows, nC, nR;
2044 pMat->GetDimensions( nCols, nRows);
2045 pJumpMatrix->GetPos( nC, nR);
2046 // Use vector replication for single row/column arrays.
2047 if ( (nC < nCols || nCols == 1) && (nR < nRows || nRows == 1) )
2049 double fVal = pMat->GetDoubleWithStringConversion( nC, nR);
2050 FormulaError nErr = GetDoubleErrorValue( fVal);
2051 if (nErr != FormulaError::NONE)
2053 // Do not propagate the coded double error, but set nGlobalError in
2054 // case the matrix did not have an error interpreter set.
2061 SetError( FormulaError::NoValue);
2065 double ScInterpreter::GetDouble()
2068 switch( GetRawStackType() )
2074 nVal = ConvertStringToValue( PopString().getString());
2079 PopSingleRef( aAdr );
2080 ScRefCellValue aCell(mrDoc, aAdr);
2081 nVal = GetCellValue(aAdr, aCell);
2085 { // generate position dependent SingleRef
2087 PopDoubleRef( aRange );
2089 if ( nGlobalError == FormulaError::NONE && DoubleRefToPosSingleRef( aRange, aAdr ) )
2091 ScRefCellValue aCell(mrDoc, aAdr);
2092 nVal = GetCellValue(aAdr, aCell);
2098 case svExternalSingleRef:
2100 ScExternalRefCache::TokenRef pToken;
2101 PopExternalSingleRef(pToken);
2102 if (nGlobalError == FormulaError::NONE)
2104 if (pToken->GetType() == svDouble || pToken->GetType() == svEmptyCell)
2105 nVal = pToken->GetDouble();
2107 nVal = ConvertStringToValue( pToken->GetString().getString());
2111 case svExternalDoubleRef:
2114 PopExternalDoubleRef(pMat);
2115 if (nGlobalError != FormulaError::NONE)
2118 nVal = GetDoubleFromMatrix(pMat);
2123 ScMatrixRef pMat = PopMatrix();
2124 nVal = GetDoubleFromMatrix(pMat);
2138 SetError( FormulaError::IllegalParameter);
2141 if ( nFuncFmtType == nCurFmtType )
2142 nFuncFmtIndex = nCurFmtIndex;
2146 double ScInterpreter::GetDoubleWithDefault(double nDefault)
2148 bool bMissing = IsMissing();
2149 double nResultVal = GetDouble();
2151 nResultVal = nDefault;
2155 sal_Int32 ScInterpreter::double_to_int32(double fVal)
2157 if (!std::isfinite(fVal))
2159 SetError( GetDoubleErrorValue( fVal));
2160 return SAL_MAX_INT32;
2164 fVal = rtl::math::approxFloor( fVal);
2165 if (fVal > SAL_MAX_INT32)
2167 SetError( FormulaError::IllegalArgument);
2168 return SAL_MAX_INT32;
2171 else if (fVal < 0.0)
2173 fVal = rtl::math::approxCeil( fVal);
2174 if (fVal < SAL_MIN_INT32)
2176 SetError( FormulaError::IllegalArgument);
2177 return SAL_MAX_INT32;
2180 return static_cast<sal_Int32>(fVal);
2183 sal_Int32 ScInterpreter::GetInt32()
2185 return double_to_int32(GetDouble());
2188 sal_Int32 ScInterpreter::GetInt32WithDefault( sal_Int32 nDefault )
2190 bool bMissing = IsMissing();
2191 double fVal = GetDouble();
2194 return double_to_int32(fVal);
2197 sal_Int16 ScInterpreter::GetInt16()
2199 double fVal = GetDouble();
2200 if (!std::isfinite(fVal))
2202 SetError( GetDoubleErrorValue( fVal));
2203 return SAL_MAX_INT16;
2207 fVal = rtl::math::approxFloor( fVal);
2208 if (fVal > SAL_MAX_INT16)
2210 SetError( FormulaError::IllegalArgument);
2211 return SAL_MAX_INT16;
2214 else if (fVal < 0.0)
2216 fVal = rtl::math::approxCeil( fVal);
2217 if (fVal < SAL_MIN_INT16)
2219 SetError( FormulaError::IllegalArgument);
2220 return SAL_MAX_INT16;
2223 return static_cast<sal_Int16>(fVal);
2226 sal_uInt32 ScInterpreter::GetUInt32()
2228 double fVal = rtl::math::approxFloor( GetDouble());
2229 if (!std::isfinite(fVal))
2231 SetError( GetDoubleErrorValue( fVal));
2232 return SAL_MAX_UINT32;
2234 if (fVal < 0.0 || fVal > SAL_MAX_UINT32)
2236 SetError( FormulaError::IllegalArgument);
2237 return SAL_MAX_UINT32;
2239 return static_cast<sal_uInt32>(fVal);
2242 bool ScInterpreter::GetDoubleOrString( double& rDouble, svl::SharedString& rString )
2244 bool bDouble = true;
2245 switch( GetRawStackType() )
2248 rDouble = PopDouble();
2251 rString = PopString();
2258 if (!PopDoubleRefOrSingleRef( aAdr))
2261 return true; // caller needs to check nGlobalError
2263 ScRefCellValue aCell( mrDoc, aAdr);
2264 if (aCell.hasNumeric())
2266 rDouble = GetCellValue( aAdr, aCell);
2270 GetCellString( rString, aCell);
2275 case svExternalSingleRef:
2276 case svExternalDoubleRef:
2279 ScMatValType nType = GetDoubleOrStringFromMatrix( rDouble, rString);
2280 bDouble = ScMatrix::IsValueType( nType);
2294 SetError( FormulaError::IllegalParameter);
2297 if ( nFuncFmtType == nCurFmtType )
2298 nFuncFmtIndex = nCurFmtIndex;
2302 svl::SharedString ScInterpreter::GetString()
2304 switch (GetRawStackType())
2308 return svl::SharedString::getEmptyString();
2312 return svl::SharedString::getEmptyString();
2315 return GetStringFromDouble( PopDouble() );
2322 PopSingleRef( aAdr );
2323 if (nGlobalError == FormulaError::NONE)
2325 ScRefCellValue aCell(mrDoc, aAdr);
2326 svl::SharedString aSS;
2327 GetCellString(aSS, aCell);
2331 return svl::SharedString::getEmptyString();
2334 { // generate position dependent SingleRef
2336 PopDoubleRef( aRange );
2338 if ( nGlobalError == FormulaError::NONE && DoubleRefToPosSingleRef( aRange, aAdr ) )
2340 ScRefCellValue aCell(mrDoc, aAdr);
2341 svl::SharedString aSS;
2342 GetCellString(aSS, aCell);
2346 return svl::SharedString::getEmptyString();
2348 case svExternalSingleRef:
2350 ScExternalRefCache::TokenRef pToken;
2351 PopExternalSingleRef(pToken);
2352 if (nGlobalError != FormulaError::NONE)
2353 return svl::SharedString::getEmptyString();
2355 if (pToken->GetType() == svDouble)
2357 return GetStringFromDouble( pToken->GetDouble() );
2359 else // svString or svEmpty
2360 return pToken->GetString();
2362 case svExternalDoubleRef:
2365 PopExternalDoubleRef(pMat);
2366 return GetStringFromMatrix(pMat);
2370 ScMatrixRef pMat = PopMatrix();
2371 return GetStringFromMatrix(pMat);
2376 SetError( FormulaError::IllegalArgument);
2378 return svl::SharedString::getEmptyString();
2381 svl::SharedString ScInterpreter::GetStringFromMatrix(const ScMatrixRef& pMat)
2385 else if ( !pJumpMatrix )
2387 return pMat->GetString( *pFormatter, 0, 0);
2391 SCSIZE nCols, nRows, nC, nR;
2392 pMat->GetDimensions( nCols, nRows);
2393 pJumpMatrix->GetPos( nC, nR);
2394 // Use vector replication for single row/column arrays.
2395 if ( (nC < nCols || nCols == 1) && (nR < nRows || nRows == 1) )
2396 return pMat->GetString( *pFormatter, nC, nR);
2398 SetError( FormulaError::NoValue);
2400 return svl::SharedString::getEmptyString();
2403 ScMatValType ScInterpreter::GetDoubleOrStringFromMatrix(
2404 double& rDouble, svl::SharedString& rString )
2408 rString = svl::SharedString::getEmptyString();
2409 ScMatValType nMatValType = ScMatValType::Empty;
2412 StackVar eType = GetStackType();
2413 if (eType == svExternalDoubleRef || eType == svExternalSingleRef || eType == svMatrix)
2420 SetError( FormulaError::IllegalParameter);
2424 ScMatrixValue nMatVal;
2429 else if (!pJumpMatrix)
2431 nMatVal = pMat->Get(0, 0);
2432 nMatValType = nMatVal.nType;
2436 SCSIZE nCols, nRows, nC, nR;
2437 pMat->GetDimensions( nCols, nRows);
2438 pJumpMatrix->GetPos( nC, nR);
2439 // Use vector replication for single row/column arrays.
2440 if ( (nC < nCols || nCols == 1) && (nR < nRows || nRows == 1) )
2442 nMatVal = pMat->Get( nC, nR);
2443 nMatValType = nMatVal.nType;
2446 SetError( FormulaError::NoValue);
2449 if (ScMatrix::IsValueType( nMatValType))
2451 rDouble = nMatVal.fVal;
2452 FormulaError nError = nMatVal.GetError();
2453 if (nError != FormulaError::NONE)
2458 rString = nMatVal.GetString();
2464 svl::SharedString ScInterpreter::GetStringFromDouble( double fVal )
2466 sal_uLong nIndex = pFormatter->GetStandardFormat(
2467 SvNumFormatType::NUMBER,
2470 pFormatter->GetInputLineString(fVal, nIndex, aStr);
2471 return mrStrPool.intern(aStr);
2474 void ScInterpreter::ScDBGet()
2476 bool bMissingField = false;
2477 unique_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) );
2480 // Failed to create query param.
2481 PushIllegalParameter();
2485 pQueryParam->mbSkipString = false;
2486 ScDBQueryDataIterator aValIter(mrDoc, mrContext, std::move(pQueryParam));
2487 ScDBQueryDataIterator::Value aValue;
2488 if (!aValIter.GetFirst(aValue) || aValue.mnError != FormulaError::NONE)
2495 ScDBQueryDataIterator::Value aValNext;
2496 if (aValIter.GetNext(aValNext) && aValNext.mnError == FormulaError::NONE)
2498 // There should be only one unique match.
2499 PushIllegalArgument();
2503 if (aValue.mbIsNumber)
2504 PushDouble(aValue.mfValue);
2506 PushString(aValue.maString);
2509 void ScInterpreter::ScExternal()
2511 sal_uInt8 nParamCount = GetByte();
2513 OUString aFuncName( ScGlobal::getCharClassPtr()->uppercase( pCur->GetExternal() ) );
2514 LegacyFuncData* pLegacyFuncData = ScGlobal::GetLegacyFuncCollection()->findByName(aFuncName);
2515 if (pLegacyFuncData)
2517 // Old binary non-UNO add-in function.
2518 // NOTE: parameter count is 1-based with the 0th "parameter
" being the
2519 // return value, included in pLegacyFuncDatat->GetParamCount()
2520 if (nParamCount < MAXFUNCPARAM && nParamCount == pLegacyFuncData->GetParamCount() - 1)
2522 ParamType eParamType[MAXFUNCPARAM];
2523 void* ppParam[MAXFUNCPARAM];
2524 double nVal[MAXFUNCPARAM];
2525 char* pStr[MAXFUNCPARAM];
2526 sal_uInt8* pCellArr[MAXFUNCPARAM];
2529 for (i = 0; i < MAXFUNCPARAM; i++)
2531 eParamType[i] = pLegacyFuncData->GetParamType(i);
2532 ppParam[i] = nullptr;
2535 pCellArr[i] = nullptr;
2538 for (i = nParamCount; (i > 0) && (nGlobalError == FormulaError::NONE); i--)
2542 // Old binary Add-In can't distinguish between missing
2543 // omitted argument and 0 (or any other value). Force
2545 SetError( FormulaError::ParameterExpected);
2548 switch (eParamType[i])
2550 case ParamType::PTR_DOUBLE :
2552 nVal[i-1] = GetDouble();
2553 ppParam[i] = &nVal[i-1];
2556 case ParamType::PTR_STRING :
2558 OString aStr(OUStringToOString(GetString().getString(),
2559 osl_getThreadTextEncoding()));
2560 if ( aStr.getLength() >= ADDIN_MAXSTRLEN )
2561 SetError( FormulaError::StringOverflow );
2564 pStr[i-1] = new char[ADDIN_MAXSTRLEN];
2565 strncpy( pStr[i-1], aStr.getStr(), ADDIN_MAXSTRLEN );
2566 pStr[i-1][ADDIN_MAXSTRLEN-1] = 0;
2567 ppParam[i] = pStr[i-1];
2571 case ParamType::PTR_DOUBLE_ARR :
2579 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2580 pCellArr[i-1] = new sal_uInt8[MAXARRSIZE];
2581 if (!CreateDoubleArr(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, pCellArr[i-1]))
2582 SetError(FormulaError::CodeOverflow);
2584 ppParam[i] = pCellArr[i-1];
2587 case ParamType::PTR_STRING_ARR :
2595 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2596 pCellArr[i-1] = new sal_uInt8[MAXARRSIZE];
2597 if (!CreateStringArr(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, pCellArr[i-1]))
2598 SetError(FormulaError::CodeOverflow);
2600 ppParam[i] = pCellArr[i-1];
2603 case ParamType::PTR_CELL_ARR :
2611 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2612 pCellArr[i-1] = new sal_uInt8[MAXARRSIZE];
2613 if (!CreateCellArr(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, pCellArr[i-1]))
2614 SetError(FormulaError::CodeOverflow);
2616 ppParam[i] = pCellArr[i-1];
2620 SetError(FormulaError::IllegalParameter);
2625 Pop(); // In case of error (otherwise i==0) pop all parameters
2627 if (nGlobalError == FormulaError::NONE)
2629 if ( pLegacyFuncData->GetAsyncType() == ParamType::NONE )
2631 switch ( eParamType[0] )
2633 case ParamType::PTR_DOUBLE :
2637 pLegacyFuncData->Call(ppParam);
2641 case ParamType::PTR_STRING :
2643 std::unique_ptr<char[]> pcErg(new char[ADDIN_MAXSTRLEN]);
2644 ppParam[0] = pcErg.get();
2645 pLegacyFuncData->Call(ppParam);
2646 OUString aUni( pcErg.get(), strlen(pcErg.get()), osl_getThreadTextEncoding() );
2651 PushError( FormulaError::UnknownState );
2656 // enable asyncs after loading
2657 pArr->AddRecalcMode( ScRecalcMode::ONLOAD_LENIENT );
2658 // assure identical handler with identical call?
2661 pLegacyFuncData->Call(ppParam);
2662 sal_uLong nHandle = sal_uLong( nErg );
2663 if ( nHandle >= 65536 )
2665 ScAddInAsync* pAs = ScAddInAsync::Get( nHandle );
2668 pAs = new ScAddInAsync(nHandle, pLegacyFuncData, &mrDoc);
2669 pMyFormulaCell->StartListening( *pAs );
2673 pMyFormulaCell->StartListening( *pAs );
2674 if ( !pAs->HasDocument( &mrDoc ) )
2675 pAs->AddDocument( &mrDoc );
2677 if ( pAs->IsValid() )
2679 switch ( pAs->GetType() )
2681 case ParamType::PTR_DOUBLE :
2682 PushDouble( pAs->GetValue() );
2684 case ParamType::PTR_STRING :
2685 PushString( pAs->GetString() );
2688 PushError( FormulaError::UnknownState );
2699 for (i = 0; i < MAXFUNCPARAM; i++)
2702 delete[] pCellArr[i];
2707 while( nParamCount-- > 0)
2709 PushIllegalParameter();
2712 else if ( !( aUnoName = ScGlobal::GetAddInCollection()->FindFunction(aFuncName, false) ).isEmpty() )
2714 // bLocalFirst=false in FindFunction, cFunc should be the stored
2717 ScUnoAddInCall aCall( *ScGlobal::GetAddInCollection(), aUnoName, nParamCount );
2719 if ( !aCall.ValidParamCount() )
2720 SetError( FormulaError::IllegalParameter );
2722 if ( aCall.NeedsCaller() && GetError() == FormulaError::NONE )
2724 SfxObjectShell* pShell = mrDoc.GetDocumentShell();
2726 aCall.SetCallerFromObjectShell( pShell );
2729 // use temporary model object (without document) to supply options
2730 aCall.SetCaller( static_cast<beans::XPropertySet*>(
2731 new ScDocOptionsObj( mrDoc.GetDocOptions() ) ) );
2735 short nPar = nParamCount;
2736 while ( nPar > 0 && GetError() == FormulaError::NONE )
2738 --nPar; // 0 .. (nParamCount-1)
2743 // Add-In has to explicitly handle an omitted empty missing
2744 // argument, do not default to anything like GetDouble() would
2747 aCall.SetParam( nPar, aParam );
2751 StackVar nStackType = GetStackType();
2752 ScAddInArgumentType eType = aCall.GetArgType( nPar );
2755 case SC_ADDINARG_INTEGER:
2757 sal_Int32 nVal = GetInt32();
2758 if (nGlobalError == FormulaError::NONE)
2763 case SC_ADDINARG_DOUBLE:
2764 aParam <<= GetDouble();
2767 case SC_ADDINARG_STRING:
2768 aParam <<= GetString().getString();
2771 case SC_ADDINARG_INTEGER_ARRAY:
2772 switch( nStackType )
2778 sal_Int32 nVal = GetInt32();
2779 if (nGlobalError == FormulaError::NONE)
2781 uno::Sequence<sal_Int32> aInner( &nVal, 1 );
2782 uno::Sequence< uno::Sequence<sal_Int32> > aOuter( &aInner, 1 );
2790 PopDoubleRef( aRange );
2791 if (!ScRangeToSequence::FillLongArray( aParam, mrDoc, aRange ))
2792 SetError(FormulaError::IllegalParameter);
2796 if (!ScRangeToSequence::FillLongArray( aParam, PopMatrix().get() ))
2797 SetError(FormulaError::IllegalParameter);
2801 SetError(FormulaError::IllegalParameter);
2805 case SC_ADDINARG_DOUBLE_ARRAY:
2806 switch( nStackType )
2812 double fVal = GetDouble();
2813 uno::Sequence<double> aInner( &fVal, 1 );
2814 uno::Sequence< uno::Sequence<double> > aOuter( &aInner, 1 );
2821 PopDoubleRef( aRange );
2822 if (!ScRangeToSequence::FillDoubleArray( aParam, mrDoc, aRange ))
2823 SetError(FormulaError::IllegalParameter);
2827 if (!ScRangeToSequence::FillDoubleArray( aParam, PopMatrix().get() ))
2828 SetError(FormulaError::IllegalParameter);
2832 SetError(FormulaError::IllegalParameter);
2836 case SC_ADDINARG_STRING_ARRAY:
2837 switch( nStackType )
2843 OUString aString = GetString().getString();
2844 uno::Sequence<OUString> aInner( &aString, 1 );
2845 uno::Sequence< uno::Sequence<OUString> > aOuter( &aInner, 1 );
2852 PopDoubleRef( aRange );
2853 if (!ScRangeToSequence::FillStringArray( aParam, mrDoc, aRange ))
2854 SetError(FormulaError::IllegalParameter);
2858 if (!ScRangeToSequence::FillStringArray( aParam, PopMatrix().get(), pFormatter ))
2859 SetError(FormulaError::IllegalParameter);
2863 SetError(FormulaError::IllegalParameter);
2867 case SC_ADDINARG_MIXED_ARRAY:
2868 switch( nStackType )
2875 if ( nStackType == svDouble )
2876 aElem <<= GetDouble();
2877 else if ( nStackType == svString )
2878 aElem <<= GetString().getString();
2882 if ( PopDoubleRefOrSingleRef( aAdr ) )
2884 ScRefCellValue aCell(mrDoc, aAdr);
2885 if (aCell.hasString())
2887 svl::SharedString aStr;
2888 GetCellString(aStr, aCell);
2889 aElem <<= aStr.getString();
2892 aElem <<= GetCellValue(aAdr, aCell);
2895 uno::Sequence<uno::Any> aInner( &aElem, 1 );
2896 uno::Sequence< uno::Sequence<uno::Any> > aOuter( &aInner, 1 );
2903 PopDoubleRef( aRange );
2904 if (!ScRangeToSequence::FillMixedArray( aParam, mrDoc, aRange ))
2905 SetError(FormulaError::IllegalParameter);
2909 if (!ScRangeToSequence::FillMixedArray( aParam, PopMatrix().get() ))
2910 SetError(FormulaError::IllegalParameter);
2914 SetError(FormulaError::IllegalParameter);
2918 case SC_ADDINARG_VALUE_OR_ARRAY:
2919 switch( nStackType )
2922 aParam <<= GetDouble();
2925 aParam <<= GetString().getString();
2930 if ( PopDoubleRefOrSingleRef( aAdr ) )
2932 ScRefCellValue aCell(mrDoc, aAdr);
2933 if (aCell.hasString())
2935 svl::SharedString aStr;
2936 GetCellString(aStr, aCell);
2937 aParam <<= aStr.getString();
2940 aParam <<= GetCellValue(aAdr, aCell);
2947 PopDoubleRef( aRange );
2948 if (!ScRangeToSequence::FillMixedArray( aParam, mrDoc, aRange ))
2949 SetError(FormulaError::IllegalParameter);
2953 if (!ScRangeToSequence::FillMixedArray( aParam, PopMatrix().get() ))
2954 SetError(FormulaError::IllegalParameter);
2958 SetError(FormulaError::IllegalParameter);
2962 case SC_ADDINARG_CELLRANGE:
2963 switch( nStackType )
2968 PopSingleRef( aAdr );
2969 ScRange aRange( aAdr );
2970 uno::Reference<table::XCellRange> xObj =
2971 ScCellRangeObj::CreateRangeFromDoc( mrDoc, aRange );
2975 SetError(FormulaError::IllegalParameter);
2981 PopDoubleRef( aRange );
2982 uno::Reference<table::XCellRange> xObj =
2983 ScCellRangeObj::CreateRangeFromDoc( mrDoc, aRange );
2990 SetError(FormulaError::IllegalParameter);
2996 SetError(FormulaError::IllegalParameter);
3002 SetError(FormulaError::IllegalParameter);
3004 aCall.SetParam( nPar, aParam );
3009 Pop(); // in case of error, remove remaining args
3011 if ( GetError() == FormulaError::NONE )
3013 aCall.ExecuteCall();
3015 if ( aCall.HasVarRes() ) // handle async functions
3017 pArr->AddRecalcMode( ScRecalcMode::ONLOAD_LENIENT );
3018 uno::Reference<sheet::XVolatileResult> xRes = aCall.GetVarRes();
3019 ScAddInListener* pLis = ScAddInListener::Get( xRes );
3020 // In case there is no pMyFormulaCell, i.e. while interpreting
3021 // temporarily from within the Function Wizard, try to obtain a
3022 // valid result from an existing listener for that volatile, or
3023 // create a new and hope for an immediate result. If none
3024 // available that should lead to a void result and thus #N/A.
3025 bool bTemporaryListener = false;
3028 pLis = ScAddInListener::CreateListener( xRes, &mrDoc );
3030 pMyFormulaCell->StartListening( *pLis );
3032 bTemporaryListener = true;
3034 else if (pMyFormulaCell)
3036 pMyFormulaCell->StartListening( *pLis );
3037 if ( !pLis->HasDocument( &mrDoc ) )
3039 pLis->AddDocument( &mrDoc );
3043 aCall.SetResult( pLis->GetResult() ); // use result from async
3045 if (bTemporaryListener)
3049 // EventObject can be any, not evaluated by
3050 // ScAddInListener::disposing()
3051 css::lang::EventObject aEvent;
3052 pLis->disposing(aEvent); // pLis is dead hereafter
3054 catch (const uno::Exception&)
3060 if ( aCall.GetErrCode() != FormulaError::NONE )
3062 PushError( aCall.GetErrCode() );
3064 else if ( aCall.HasMatrix() )
3066 PushMatrix( aCall.GetMatrix() );
3068 else if ( aCall.HasString() )
3070 PushString( aCall.GetString() );
3074 PushDouble( aCall.GetValue() );
3078 PushError( GetError());
3082 while( nParamCount-- > 0)
3086 PushError( FormulaError::NoAddin );
3090 void ScInterpreter::ScMissing()
3092 if ( aCode.IsEndOfPath() )
3093 PushTempToken( new ScEmptyCellToken( false, false ) );
3095 PushTempToken( new FormulaMissingToken );
3098 #if HAVE_FEATURE_SCRIPTING
3100 static uno::Any lcl_getSheetModule( const uno::Reference<table::XCellRange>& xCellRange, const ScDocument* pDok )
3102 uno::Reference< sheet::XSheetCellRange > xSheetRange( xCellRange, uno::UNO_QUERY_THROW );
3103 uno::Reference< beans::XPropertySet > xProps( xSheetRange->getSpreadsheet(), uno::UNO_QUERY_THROW );
3105 xProps->getPropertyValue("CodeName
") >>= sCodeName;
3106 // #TODO #FIXME ideally we should 'throw' here if we don't get a valid parent, but... it is possible
3107 // to create a module ( and use 'Option VBASupport 1' ) for a calc document, in this scenario there
3108 // are *NO* special document module objects ( of course being able to switch between vba/non vba mode at
3109 // the document in the future could fix this, especially IF the switching of the vba mode takes care to
3110 // create the special document module objects if they don't exist.
3111 BasicManager* pBasMgr = pDok->GetDocumentShell()->GetBasicManager();
3113 uno::Reference< uno::XInterface > xIf;
3114 if ( pBasMgr && !pBasMgr->GetName().isEmpty() )
3116 OUString sProj( "Standard
" );
3117 if ( !pDok->GetDocumentShell()->GetBasicManager()->GetName().isEmpty() )
3119 sProj = pDok->GetDocumentShell()->GetBasicManager()->GetName();
3121 StarBASIC* pBasic = pDok->GetDocumentShell()->GetBasicManager()->GetLib( sProj );
3124 SbModule* pMod = pBasic->FindModule( sCodeName );
3127 xIf = pMod->GetUnoModule();
3131 return uno::makeAny( xIf );
3134 static bool lcl_setVBARange( const ScRange& aRange, const ScDocument& rDok, SbxVariable* pPar )
3139 uno::Reference< uno::XInterface > xVBARange;
3140 uno::Reference<table::XCellRange> xCellRange = ScCellRangeObj::CreateRangeFromDoc( rDok, aRange );
3141 uno::Sequence< uno::Any > aArgs(2);
3142 aArgs[0] = lcl_getSheetModule( xCellRange, &rDok );
3143 aArgs[1] <<= xCellRange;
3144 xVBARange = ooo::vba::createVBAUnoAPIServiceWithArgs( rDok.GetDocumentShell(), "ooo.
vba.
excel.Range
", aArgs );
3145 if ( xVBARange.is() )
3147 SbxObjectRef aObj = GetSbUnoObject( "A-
Range", uno::Any( xVBARange ) );
3148 SetSbUnoObjectDfltPropName( aObj.get() );
3149 bOk = pPar->PutObject( aObj.get() );
3152 catch( uno::Exception& )
3158 static bool lcl_isNumericResult( double& fVal, const SbxVariable* pVar )
3160 switch (pVar->GetType())
3175 fVal = pVar->GetDouble();
3178 fVal = (pVar->GetBool() ? 1.0 : 0.0);
3188 void ScInterpreter::ScMacro()
3191 #if !HAVE_FEATURE_SCRIPTING
3192 PushNoValue(); // without DocShell no CallBasic
3195 SbxBase::ResetError();
3197 sal_uInt8 nParamCount = GetByte();
3198 OUString aMacro( pCur->GetExternal() );
3200 SfxObjectShell* pDocSh = mrDoc.GetDocumentShell();
3203 PushNoValue(); // without DocShell no CallBasic
3207 // no security queue beforehand (just CheckMacroWarn), moved to CallBasic
3209 // If the Dok was loaded during a Basic-Calls,
3210 // is the Sbx-object created(?)
3211 // pDocSh->GetSbxObject();
3213 // search function with the name,
3214 // then assemble SfxObjectShell::CallBasic from aBasicStr, aMacroStr
3220 pRoot = pDocSh->GetBasic();
3227 SbxVariable* pVar = pRoot ? pRoot->Find(aMacro, SbxClassType::Method) : nullptr;
3228 if( !pVar || pVar->GetType() == SbxVOID || dynamic_cast<const SbMethod*>( pVar) == nullptr )
3230 PushError( FormulaError::NoMacro );
3234 bool bVolatileMacro = false;
3235 SbMethod* pMethod = static_cast<SbMethod*>(pVar);
3237 SbModule* pModule = pMethod->GetModule();
3238 bool bUseVBAObjects = pModule->IsVBACompat();
3239 SbxObject* pObject = pModule->GetParent();
3240 OSL_ENSURE(dynamic_cast<const StarBASIC *>(pObject) != nullptr, "No Basic found!
");
3241 OUString aMacroStr = pObject->GetName() + ".
" + pModule->GetName() + ".
" + pMethod->GetName();
3243 if (pRoot && bUseVBAObjects)
3245 // just here to make sure the VBA objects when we run the macro during ODF import
3246 pRoot->getVBAGlobals();
3248 if (pObject->GetParent())
3250 aBasicStr = pObject->GetParent()->GetName(); // document BASIC
3254 aBasicStr = SfxGetpApp()->GetName(); // application BASIC
3256 // assemble a parameter array
3258 SbxArrayRef refPar = new SbxArray;
3260 for( sal_uInt32 i = nParamCount; i && bOk ; i-- )
3262 SbxVariable* pPar = refPar->Get32(i);
3263 switch( GetStackType() )
3266 pPar->PutDouble( GetDouble() );
3269 pPar->PutString( GetString().getString() );
3271 case svExternalSingleRef:
3273 ScExternalRefCache::TokenRef pToken;
3274 PopExternalSingleRef(pToken);
3275 if (nGlobalError != FormulaError::NONE)
3279 if ( pToken->GetType() == svString )
3280 pPar->PutString( pToken->GetString().getString() );
3281 else if ( pToken->GetType() == svDouble )
3282 pPar->PutDouble( pToken->GetDouble() );
3285 SetError( FormulaError::IllegalArgument );
3294 PopSingleRef( aAdr );
3295 if ( bUseVBAObjects )
3297 ScRange aRange( aAdr );
3298 bOk = lcl_setVBARange( aRange, mrDoc, pPar );
3302 bOk = SetSbxVariable( pPar, aAdr );
3314 PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
3315 if( nTab1 != nTab2 )
3317 SetError( FormulaError::IllegalParameter );
3322 if ( bUseVBAObjects )
3324 ScRange aRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
3325 bOk = lcl_setVBARange( aRange, mrDoc, pPar );
3329 SbxDimArrayRef refArray = new SbxDimArray;
3330 refArray->AddDim32( 1, nRow2 - nRow1 + 1 );
3331 refArray->AddDim32( 1, nCol2 - nCol1 + 1 );
3332 ScAddress aAdr( nCol1, nRow1, nTab1 );
3333 for( SCROW nRow = nRow1; bOk && nRow <= nRow2; nRow++ )
3335 aAdr.SetRow( nRow );
3336 sal_Int32 nIdx[ 2 ];
3337 nIdx[ 0 ] = nRow-nRow1+1;
3338 for( SCCOL nCol = nCol1; bOk && nCol <= nCol2; nCol++ )
3340 aAdr.SetCol( nCol );
3341 nIdx[ 1 ] = nCol-nCol1+1;
3342 SbxVariable* p = refArray->Get32( nIdx );
3343 bOk = SetSbxVariable( p, aAdr );
3346 pPar->PutObject( refArray.get() );
3351 case svExternalDoubleRef:
3354 ScMatrixRef pMat = GetMatrix();
3356 if (pMat && nGlobalError == FormulaError::NONE)
3358 pMat->GetDimensions(nC, nR);
3359 SbxDimArrayRef refArray = new SbxDimArray;
3360 refArray->AddDim32( 1, static_cast<sal_Int32>(nR) );
3361 refArray->AddDim32( 1, static_cast<sal_Int32>(nC) );
3362 for( SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++ )
3364 sal_Int32 nIdx[ 2 ];
3365 nIdx[ 0 ] = static_cast<sal_Int32>(nMatRow+1);
3366 for( SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++ )
3368 nIdx[ 1 ] = static_cast<sal_Int32>(nMatCol+1);
3369 SbxVariable* p = refArray->Get32( nIdx );
3370 if (pMat->IsStringOrEmpty(nMatCol, nMatRow))
3372 p->PutString( pMat->GetString(nMatCol, nMatRow).getString() );
3376 p->PutDouble( pMat->GetDouble(nMatCol, nMatRow));
3380 pPar->PutObject( refArray.get() );
3384 SetError( FormulaError::IllegalParameter );
3389 SetError( FormulaError::IllegalParameter );
3395 mrDoc.LockTable( aPos.Tab() );
3396 SbxVariableRef refRes = new SbxVariable;
3397 mrDoc.IncMacroInterpretLevel();
3398 ErrCode eRet = pDocSh->CallBasic( aMacroStr, aBasicStr, refPar.get(), refRes.get() );
3399 mrDoc.DecMacroInterpretLevel();
3400 mrDoc.UnlockTable( aPos.Tab() );
3402 ScMacroManager* pMacroMgr = mrDoc.GetMacroManager();
3405 bVolatileMacro = pMacroMgr->GetUserFuncVolatile( pMethod->GetName() );
3406 pMacroMgr->AddDependentCell(pModule->GetName(), pMyFormulaCell);
3410 SbxDataType eResType = refRes->GetType();
3411 if( SbxBase::GetError() )
3413 SetError( FormulaError::NoValue);
3415 if ( eRet != ERRCODE_NONE )
3419 else if (lcl_isNumericResult( fVal, refRes.get()))
3424 nFuncFmtType = SvNumFormatType::DATE;
3427 nFuncFmtType = SvNumFormatType::LOGICAL;
3429 // Do not add SbxCURRENCY, we don't know which currency.
3435 else if ( eResType & SbxARRAY )
3437 SbxBase* pElemObj = refRes->GetObject();
3438 SbxDimArray* pDimArray = dynamic_cast<SbxDimArray*>(pElemObj);
3439 sal_Int32 nDim = pDimArray ? pDimArray->GetDims32() : 0;
3440 if ( 1 <= nDim && nDim <= 2 )
3442 sal_Int32 nCs, nCe, nRs;
3447 { // array( cols ) one line, several columns
3448 pDimArray->GetDim32( 1, nCs, nCe );
3449 nC = static_cast<SCSIZE>(nCe - nCs + 1);
3456 { // array( rows, cols )
3458 pDimArray->GetDim32( 1, nRs, nRe );
3459 nR = static_cast<SCSIZE>(nRe - nRs + 1);
3460 pDimArray->GetDim32( 2, nCs, nCe );
3461 nC = static_cast<SCSIZE>(nCe - nCs + 1);
3465 ScMatrixRef pMat = GetNewMat( nC, nR);
3469 for ( SCSIZE j=0; j < nR; j++ )
3471 sal_Int32 nIdx[ 2 ];
3472 // in one-dimensional array( cols ) nIdx[1]
3473 // from SbxDimArray::Get is ignored
3474 nIdx[ nRowIdx ] = nRs + static_cast<sal_Int32>(j);
3475 for ( SCSIZE i=0; i < nC; i++ )
3477 nIdx[ nColIdx ] = nCs + static_cast<sal_Int32>(i);
3478 pV = pDimArray->Get32( nIdx );
3479 if ( lcl_isNumericResult( fVal, pV) )
3481 pMat->PutDouble( fVal, i, j );
3485 pMat->PutString(mrStrPool.intern(pV->GetOUString()), i, j);
3493 PushIllegalArgument();
3503 PushString( refRes->GetOUString() );
3507 if (bVolatileMacro && meVolatileType == NOT_VOLATILE)
3508 meVolatileType = VOLATILE_MACRO;
3512 #if HAVE_FEATURE_SCRIPTING
3514 bool ScInterpreter::SetSbxVariable( SbxVariable* pVar, const ScAddress& rPos )
3517 ScRefCellValue aCell(mrDoc, rPos);
3518 if (!aCell.isEmpty())
3522 switch (aCell.meType)
3524 case CELLTYPE_VALUE :
3525 nVal = GetValueCellValue(rPos, aCell.mfValue);
3526 pVar->PutDouble( nVal );
3528 case CELLTYPE_STRING :
3529 case CELLTYPE_EDIT :
3530 pVar->PutString(aCell.getString(&mrDoc));
3532 case CELLTYPE_FORMULA :
3533 nErr = aCell.mpFormula->GetErrCode();
3534 if( nErr == FormulaError::NONE )
3536 if (aCell.mpFormula->IsValue())
3538 nVal = aCell.mpFormula->GetValue();
3539 pVar->PutDouble( nVal );
3542 pVar->PutString(aCell.mpFormula->GetString().getString());
3562 void ScInterpreter::ScTableOp()
3564 sal_uInt8 nParamCount = GetByte();
3565 if (nParamCount != 3 && nParamCount != 5)
3567 PushIllegalParameter();
3570 std::unique_ptr<ScInterpreterTableOpParams> pTableOp(new ScInterpreterTableOpParams);
3571 if (nParamCount == 5)
3573 PopSingleRef( pTableOp->aNew2 );
3574 PopSingleRef( pTableOp->aOld2 );
3576 PopSingleRef( pTableOp->aNew1 );
3577 PopSingleRef( pTableOp->aOld1 );
3578 PopSingleRef( pTableOp->aFormulaPos );
3580 pTableOp->bValid = true;
3581 mrDoc.m_TableOpList.push_back(pTableOp.get());
3582 mrDoc.IncInterpreterTableOpLevel();
3584 bool bReuseLastParams = (mrDoc.aLastTableOpParams == *pTableOp);
3585 if ( bReuseLastParams )
3587 pTableOp->aNotifiedFormulaPos = mrDoc.aLastTableOpParams.aNotifiedFormulaPos;
3588 pTableOp->bRefresh = true;
3589 for ( const auto& rPos : pTableOp->aNotifiedFormulaPos )
3590 { // emulate broadcast and indirectly collect cell pointers
3591 ScRefCellValue aCell(mrDoc, rPos);
3592 if (aCell.meType == CELLTYPE_FORMULA)
3593 aCell.mpFormula->SetTableOpDirty();
3597 { // broadcast and indirectly collect cell pointers and positions
3598 mrDoc.SetTableOpDirty( pTableOp->aOld1 );
3599 if ( nParamCount == 5 )
3600 mrDoc.SetTableOpDirty( pTableOp->aOld2 );
3602 pTableOp->bCollectNotifications = false;
3604 ScRefCellValue aCell(mrDoc, pTableOp->aFormulaPos);
3605 if (aCell.meType == CELLTYPE_FORMULA)
3606 aCell.mpFormula->SetDirtyVar();
3607 if (aCell.hasNumeric())
3609 PushDouble(GetCellValue(pTableOp->aFormulaPos, aCell));
3613 svl::SharedString aCellString;
3614 GetCellString(aCellString, aCell);
3615 PushString( aCellString );
3619 ::std::find(mrDoc.m_TableOpList.begin(), mrDoc.m_TableOpList.end(), pTableOp.get());
3620 if (itr != mrDoc.m_TableOpList.end())
3622 mrDoc.m_TableOpList.erase(itr);
3625 // set dirty again once more to be able to recalculate original
3626 for ( const auto& pCell : pTableOp->aNotifiedFormulaCells )
3628 pCell->SetTableOpDirty();
3631 // save these params for next incarnation
3632 if ( !bReuseLastParams )
3633 mrDoc.aLastTableOpParams = *pTableOp;
3635 if (aCell.meType == CELLTYPE_FORMULA)
3637 aCell.mpFormula->SetDirtyVar();
3638 aCell.mpFormula->GetErrCode(); // recalculate original
3641 // Reset all dirty flags so next incarnation does really collect all cell
3642 // pointers during notifications and not just non-dirty ones, which may
3643 // happen if a formula cell is used by more than one TableOp block.
3644 for ( const auto& pCell : pTableOp->aNotifiedFormulaCells )
3646 pCell->ResetTableOpDirtyVar();
3650 mrDoc.DecInterpreterTableOpLevel();
3653 void ScInterpreter::ScDBArea()
3655 ScDBData* pDBData = mrDoc.GetDBCollection()->getNamedDBs().findByIndex(pCur->GetIndex());
3658 ScComplexRefData aRefData;
3659 aRefData.InitFlags();
3661 pDBData->GetArea(aRange);
3662 aRange.aEnd.SetTab(aRange.aStart.Tab());
3663 aRefData.SetRange(mrDoc.GetSheetLimits(), aRange, aPos);
3664 PushTempToken( new ScDoubleRefToken( mrDoc.GetSheetLimits(), aRefData ) );
3667 PushError( FormulaError::NoName);
3670 void ScInterpreter::ScColRowNameAuto()
3672 ScComplexRefData aRefData( *pCur->GetDoubleRef() );
3673 ScRange aAbs = aRefData.toAbs(mrDoc, aPos);
3674 if (!mrDoc.ValidRange(aAbs))
3676 PushError( FormulaError::NoRef );
3683 // maybe remember limit by using defined ColRowNameRange
3684 SCCOL nCol2 = aAbs.aEnd.Col();
3685 SCROW nRow2 = aAbs.aEnd.Row();
3686 // DataArea of the first cell
3687 nStartCol = aAbs.aStart.Col();
3688 nStartRow = aAbs.aStart.Row();
3689 aAbs.aEnd = aAbs.aStart; // Shrink to the top-left cell.
3692 // Expand to the data area. Only modify the end position.
3693 SCCOL nDACol1 = aAbs.aStart.Col(), nDACol2 = aAbs.aEnd.Col();
3694 SCROW nDARow1 = aAbs.aStart.Row(), nDARow2 = aAbs.aEnd.Row();
3695 mrDoc.GetDataArea(aAbs.aStart.Tab(), nDACol1, nDARow1, nDACol2, nDARow2, true, false);
3696 aAbs.aEnd.SetCol(nDACol2);
3697 aAbs.aEnd.SetRow(nDARow2);
3700 // corresponds with ScCompiler::GetToken
3701 if ( aRefData.Ref1.IsColRel() )
3703 aAbs.aEnd.SetCol(nStartCol);
3704 // maybe get previous limit by using defined ColRowNameRange
3705 if (aAbs.aEnd.Row() > nRow2)
3706 aAbs.aEnd.SetRow(nRow2);
3707 if ( aPos.Col() == nStartCol )
3709 SCROW nMyRow = aPos.Row();
3710 if ( nStartRow <= nMyRow && nMyRow <= aAbs.aEnd.Row())
3711 { //Formula in the same column and within the range
3712 if ( nMyRow == nStartRow )
3713 { // take the rest under the name
3715 if ( nStartRow > mrDoc.MaxRow() )
3716 nStartRow = mrDoc.MaxRow();
3717 aAbs.aStart.SetRow(nStartRow);
3720 { // below the name to the formula cell
3721 aAbs.aEnd.SetRow(nMyRow - 1);
3728 aAbs.aEnd.SetRow(nStartRow);
3729 // maybe get previous limit by using defined ColRowNameRange
3730 if (aAbs.aEnd.Col() > nCol2)
3731 aAbs.aEnd.SetCol(nCol2);
3732 if ( aPos.Row() == nStartRow )
3734 SCCOL nMyCol = aPos.Col();
3735 if (nStartCol <= nMyCol && nMyCol <= aAbs.aEnd.Col())
3736 { //Formula in the same column and within the range
3737 if ( nMyCol == nStartCol )
3738 { // take the rest under the name
3740 if ( nStartCol > mrDoc.MaxCol() )
3741 nStartCol = mrDoc.MaxCol();
3742 aAbs.aStart.SetCol(nStartCol);
3745 { // below the name to the formula cell
3746 aAbs.aEnd.SetCol(nMyCol - 1);
3751 aRefData.SetRange(mrDoc.GetSheetLimits(), aAbs, aPos);
3752 PushTempToken( new ScDoubleRefToken( mrDoc.GetSheetLimits(), aRefData ) );
3755 // --- internals ------------------------------------------------------------
3757 void ScInterpreter::ScTTT()
3758 { // temporary test, testing functions etc.
3759 sal_uInt8 nParamCount = GetByte();
3760 // do something, count down nParamCount with Pops!
3763 while ( nParamCount-- > 0)
3765 PushError(FormulaError::NoValue);
3768 ScInterpreter::ScInterpreter( ScFormulaCell* pCell, ScDocument& rDoc, ScInterpreterContext& rContext,
3769 const ScAddress& rPos, ScTokenArray& r, bool bForGroupThreading )
3773 , mrContext(rContext)
3775 , mpLinkManager(rDoc.GetLinkManager())
3776 , mrStrPool(rDoc.GetSharedStringPool())
3777 , pJumpMatrix(nullptr)
3778 , pMyFormulaCell(pCell)
3779 , pFormatter(rContext.GetFormatTable())
3781 , nGlobalError(FormulaError::NONE)
3787 , nFuncFmtType(SvNumFormatType::ALL)
3788 , nCurFmtType(SvNumFormatType::ALL)
3789 , nRetFmtType(SvNumFormatType::ALL)
3790 , mnStringNoValueError(FormulaError::NoValue)
3791 , mnSubTotalFlags(SubtotalFlags::NONE)
3793 , bCalcAsShown(rDoc.GetDocOptions().IsCalcAsShown())
3794 , meVolatileType(r.IsRecalcModeAlways() ? VOLATILE : NOT_VOLATILE)
3800 ScMatrixMode cMatFlag = pMyFormulaCell->GetMatrixFlag();
3801 bMatrixFormula = ( cMatFlag == ScMatrixMode::Formula );
3804 bMatrixFormula = false;
3806 // Lets not use the global stack while formula-group-threading.
3807 // as it complicates its life-cycle mgmt since for threading formula-groups,
3808 // ScInterpreter is preallocated (in main thread) for each worker thread.
3809 if (!bGlobalStackInUse && !bForGroupThreading)
3811 bGlobalStackInUse = true;
3813 pGlobalStack.reset(new ScTokenStack);
3814 pStackObj = pGlobalStack.get();
3818 pStackObj = new ScTokenStack;
3820 pStack = pStackObj->pPointer;
3823 ScInterpreter::~ScInterpreter()
3825 if ( pStackObj == pGlobalStack.get() )
3826 bGlobalStackInUse = false;
3831 void ScInterpreter::Init( ScFormulaCell* pCell, const ScAddress& rPos, ScTokenArray& rTokArray )
3833 aCode.ReInit(rTokArray);
3837 pJumpMatrix = nullptr;
3838 pTokenMatrixMap.reset();
3839 pMyFormulaCell = pCell;
3841 nGlobalError = FormulaError::NONE;
3847 nFuncFmtType = SvNumFormatType::ALL;
3848 nCurFmtType = SvNumFormatType::ALL;
3849 nRetFmtType = SvNumFormatType::ALL;
3850 mnStringNoValueError = FormulaError::NoValue;
3851 mnSubTotalFlags = SubtotalFlags::NONE;
3855 ScCalcConfig& ScInterpreter::GetOrCreateGlobalConfig()
3857 if (!mpGlobalConfig)
3858 mpGlobalConfig = new ScCalcConfig();
3859 return *mpGlobalConfig;
3862 void ScInterpreter::SetGlobalConfig(const ScCalcConfig& rConfig)
3864 GetOrCreateGlobalConfig() = rConfig;
3867 const ScCalcConfig& ScInterpreter::GetGlobalConfig()
3869 return GetOrCreateGlobalConfig();
3872 void ScInterpreter::MergeCalcConfig()
3874 maCalcConfig = GetOrCreateGlobalConfig();
3875 maCalcConfig.MergeDocumentSpecific( mrDoc.GetCalcConfig());
3878 void ScInterpreter::GlobalExit()
3880 OSL_ENSURE(!bGlobalStackInUse, "who is still
using the
TokenStack?
");
3881 pGlobalStack.reset();
3886 double applyImplicitIntersection(const sc::RangeMatrix& rMat, const ScAddress& rPos)
3888 if (rMat.mnRow1 <= rPos.Row() && rPos.Row() <= rMat.mnRow2 && rMat.mnCol1 == rMat.mnCol2)
3890 SCROW nOffset = rPos.Row() - rMat.mnRow1;
3891 return rMat.mpMat->GetDouble(0, nOffset);
3894 if (rMat.mnCol1 <= rPos.Col() && rPos.Col() <= rMat.mnCol2 && rMat.mnRow1 == rMat.mnRow2)
3896 SCROW nOffset = rPos.Col() - rMat.mnCol1;
3897 return rMat.mpMat->GetDouble(nOffset, 0);
3901 rtl::math::setNan(&fVal);
3905 // Test for Functions that evaluate an error code and directly set nGlobalError to 0
3906 bool IsErrFunc(OpCode oc)
3919 case ocIsNonString :
3927 case ocErrorType_ODF :
3928 case ocAggregate: // may ignore errors depending on option
3939 StackVar ScInterpreter::Interpret()
3941 SvNumFormatType nRetTypeExpr = SvNumFormatType::UNDEFINED;
3942 sal_uInt32 nRetIndexExpr = 0;
3943 sal_uInt16 nErrorFunction = 0;
3944 sal_uInt16 nErrorFunctionCount = 0;
3945 std::vector<sal_uInt16> aErrorFunctionStack;
3946 sal_uInt16 nStackBase;
3948 nGlobalError = FormulaError::NONE;
3949 nStackBase = sp = maxsp = 0;
3950 nRetFmtType = SvNumFormatType::UNDEFINED;
3951 nFuncFmtType = SvNumFormatType::UNDEFINED;
3952 nFuncFmtIndex = nCurFmtIndex = nRetFmtIndex = 0;
3954 pJumpMatrix = nullptr;
3955 mnSubTotalFlags = SubtotalFlags::NONE;
3956 ScTokenMatrixMap::const_iterator aTokenMatrixMapIter;
3958 // Once upon a time we used to have FP exceptions on, and there was a
3959 // Windows printer driver that kept switching off exceptions, so we had to
3960 // switch them back on again every time. Who knows if there isn't a driver
3961 // that keeps switching exceptions on, now that we run with exceptions off,
3962 // so reassure exceptions are really off.
3963 SAL_MATH_FPEXCEPTIONS_OFF();
3965 OpCode eOp = ocNone;
3969 pCur = aCode.Next();
3970 if (!pCur || (nGlobalError != FormulaError::NONE && nErrorFunction > nErrorFunctionCount) )
3972 eOp = pCur->GetOpCode();
3973 cPar = pCur->GetByte();
3974 if ( eOp == ocPush )
3976 // RPN code push without error
3977 PushWithoutError( *pCur );
3978 nCurFmtType = SvNumFormatType::UNDEFINED;
3980 else if (pTokenMatrixMap &&
3981 !FormulaCompiler::IsOpCodeJumpCommand( eOp ) &&
3982 ((aTokenMatrixMapIter = pTokenMatrixMap->find( pCur)) !=
3983 pTokenMatrixMap->end()) &&
3984 (*aTokenMatrixMapIter).second->GetType() != svJumpMatrix)
3986 // Path already calculated, reuse result.
3987 nStackBase = sp - pCur->GetParamCount();
3988 if ( nStackBase > sp )
3989 nStackBase = sp; // underflow?!?
3991 PushTokenRef( (*aTokenMatrixMapIter).second);
3995 // previous expression determines the current number format
3996 nCurFmtType = nRetTypeExpr;
3997 nCurFmtIndex = nRetIndexExpr;
3998 // default function's format, others are set if needed
3999 nFuncFmtType = SvNumFormatType::NUMBER;
4002 if (FormulaCompiler::IsOpCodeJumpCommand( eOp ))
4003 nStackBase = sp; // don't mess around with the jumps
4006 // Convert parameters to matrix if in array/matrix formula and
4007 // parameters of function indicate doing so. Create JumpMatrix
4009 if ( MatrixParameterConversion() )
4011 eOp = ocNone; // JumpMatrix created
4014 else if (sp >= pCur->GetParamCount())
4015 nStackBase = sp - pCur->GetParamCount();
4017 nStackBase = sp; // underflow?!?
4023 case ocClose: // pushed by the compiler
4024 case ocMissing : ScMissing(); break;
4025 case ocMacro : ScMacro(); break;
4026 case ocDBArea : ScDBArea(); break;
4027 case ocColRowNameAuto : ScColRowNameAuto(); break;
4028 case ocIf : ScIfJump(); break;
4029 case ocIfError : ScIfError( false ); break;
4030 case ocIfNA : ScIfError( true ); break;
4031 case ocChoose : ScChooseJump(); break;
4032 case ocAdd : ScAdd(); break;
4033 case ocSub : ScSub(); break;
4034 case ocMul : ScMul(); break;
4035 case ocDiv : ScDiv(); break;
4036 case ocAmpersand : ScAmpersand(); break;
4037 case ocPow : ScPow(); break;
4038 case ocEqual : ScEqual(); break;
4039 case ocNotEqual : ScNotEqual(); break;
4040 case ocLess : ScLess(); break;
4041 case ocGreater : ScGreater(); break;
4042 case ocLessEqual : ScLessEqual(); break;
4043 case ocGreaterEqual : ScGreaterEqual(); break;
4044 case ocAnd : ScAnd(); break;
4045 case ocOr : ScOr(); break;
4046 case ocXor : ScXor(); break;
4047 case ocIntersect : ScIntersect(); break;
4048 case ocRange : ScRangeFunc(); break;
4049 case ocUnion : ScUnionFunc(); break;
4050 case ocNot : ScNot(); break;
4052 case ocNeg : ScNeg(); break;
4053 case ocPercentSign : ScPercentSign(); break;
4054 case ocPi : ScPi(); break;
4055 case ocRandom : ScRandom(); break;
4056 case ocRandomNV : ScRandom(); break;
4057 case ocRandbetweenNV : ScRandbetween(); break;
4058 case ocTrue : ScTrue(); break;
4059 case ocFalse : ScFalse(); break;
4060 case ocGetActDate : ScGetActDate(); break;
4061 case ocGetActTime : ScGetActTime(); break;
4062 case ocNotAvail : PushError( FormulaError::NotAvailable); break;
4063 case ocDeg : ScDeg(); break;
4064 case ocRad : ScRad(); break;
4065 case ocSin : ScSin(); break;
4066 case ocCos : ScCos(); break;
4067 case ocTan : ScTan(); break;
4068 case ocCot : ScCot(); break;
4069 case ocArcSin : ScArcSin(); break;
4070 case ocArcCos : ScArcCos(); break;
4071 case ocArcTan : ScArcTan(); break;
4072 case ocArcCot : ScArcCot(); break;
4073 case ocSinHyp : ScSinHyp(); break;
4074 case ocCosHyp : ScCosHyp(); break;
4075 case ocTanHyp : ScTanHyp(); break;
4076 case ocCotHyp : ScCotHyp(); break;
4077 case ocArcSinHyp : ScArcSinHyp(); break;
4078 case ocArcCosHyp : ScArcCosHyp(); break;
4079 case ocArcTanHyp : ScArcTanHyp(); break;
4080 case ocArcCotHyp : ScArcCotHyp(); break;
4081 case ocCosecant : ScCosecant(); break;
4082 case ocSecant : ScSecant(); break;
4083 case ocCosecantHyp : ScCosecantHyp(); break;
4084 case ocSecantHyp : ScSecantHyp(); break;
4085 case ocExp : ScExp(); break;
4086 case ocLn : ScLn(); break;
4087 case ocLog10 : ScLog10(); break;
4088 case ocSqrt : ScSqrt(); break;
4089 case ocFact : ScFact(); break;
4090 case ocGetYear : ScGetYear(); break;
4091 case ocGetMonth : ScGetMonth(); break;
4092 case ocGetDay : ScGetDay(); break;
4093 case ocGetDayOfWeek : ScGetDayOfWeek(); break;
4094 case ocWeek : ScGetWeekOfYear(); break;
4095 case ocIsoWeeknum : ScGetIsoWeekOfYear(); break;
4096 case ocWeeknumOOo : ScWeeknumOOo(); break;
4097 case ocEasterSunday : ScEasterSunday(); break;
4098 case ocNetWorkdays : ScNetWorkdays( false); break;
4099 case ocNetWorkdays_MS : ScNetWorkdays( true ); break;
4100 case ocWorkday_MS : ScWorkday_MS(); break;
4101 case ocGetHour : ScGetHour(); break;
4102 case ocGetMin : ScGetMin(); break;
4103 case ocGetSec : ScGetSec(); break;
4104 case ocPlusMinus : ScPlusMinus(); break;
4105 case ocAbs : ScAbs(); break;
4106 case ocInt : ScInt(); break;
4107 case ocEven : ScEven(); break;
4108 case ocOdd : ScOdd(); break;
4109 case ocPhi : ScPhi(); break;
4110 case ocGauss : ScGauss(); break;
4111 case ocStdNormDist : ScStdNormDist(); break;
4112 case ocStdNormDist_MS : ScStdNormDist_MS(); break;
4113 case ocFisher : ScFisher(); break;
4114 case ocFisherInv : ScFisherInv(); break;
4115 case ocIsEmpty : ScIsEmpty(); break;
4116 case ocIsString : ScIsString(); break;
4117 case ocIsNonString : ScIsNonString(); break;
4118 case ocIsLogical : ScIsLogical(); break;
4119 case ocType : ScType(); break;
4120 case ocCell : ScCell(); break;
4121 case ocIsRef : ScIsRef(); break;
4122 case ocIsValue : ScIsValue(); break;
4123 case ocIsFormula : ScIsFormula(); break;
4124 case ocFormula : ScFormula(); break;
4125 case ocIsNA : ScIsNV(); break;
4126 case ocIsErr : ScIsErr(); break;
4127 case ocIsError : ScIsError(); break;
4128 case ocIsEven : ScIsEven(); break;
4129 case ocIsOdd : ScIsOdd(); break;
4130 case ocN : ScN(); break;
4131 case ocGetDateValue : ScGetDateValue(); break;
4132 case ocGetTimeValue : ScGetTimeValue(); break;
4133 case ocCode : ScCode(); break;
4134 case ocTrim : ScTrim(); break;
4135 case ocUpper : ScUpper(); break;
4136 case ocProper : ScProper(); break;
4137 case ocLower : ScLower(); break;
4138 case ocLen : ScLen(); break;
4139 case ocT : ScT(); break;
4140 case ocClean : ScClean(); break;
4141 case ocValue : ScValue(); break;
4142 case ocNumberValue : ScNumberValue(); break;
4143 case ocChar : ScChar(); break;
4144 case ocArcTan2 : ScArcTan2(); break;
4145 case ocMod : ScMod(); break;
4146 case ocPower : ScPower(); break;
4147 case ocRound : ScRound(); break;
4148 case ocRoundSig : ScRoundSignificant(); break;
4149 case ocRoundUp : ScRoundUp(); break;
4151 case ocRoundDown : ScRoundDown(); break;
4152 case ocCeil : ScCeil( true ); break;
4153 case ocCeil_MS : ScCeil_MS(); break;
4154 case ocCeil_Precise :
4155 case ocCeil_ISO : ScCeil_Precise(); break;
4156 case ocCeil_Math : ScCeil( false ); break;
4157 case ocFloor : ScFloor( true ); break;
4158 case ocFloor_MS : ScFloor_MS(); break;
4159 case ocFloor_Precise : ScFloor_Precise(); break;
4160 case ocFloor_Math : ScFloor( false ); break;
4161 case ocSumProduct : ScSumProduct(); break;
4162 case ocSumSQ : ScSumSQ(); break;
4163 case ocSumX2MY2 : ScSumX2MY2(); break;
4164 case ocSumX2DY2 : ScSumX2DY2(); break;
4165 case ocSumXMY2 : ScSumXMY2(); break;
4166 case ocRawSubtract : ScRawSubtract(); break;
4167 case ocLog : ScLog(); break;
4168 case ocGCD : ScGCD(); break;
4169 case ocLCM : ScLCM(); break;
4170 case ocGetDate : ScGetDate(); break;
4171 case ocGetTime : ScGetTime(); break;
4172 case ocGetDiffDate : ScGetDiffDate(); break;
4173 case ocGetDiffDate360 : ScGetDiffDate360(); break;
4174 case ocGetDateDif : ScGetDateDif(); break;
4175 case ocMin : ScMin() ; break;
4176 case ocMinA : ScMin( true ); break;
4177 case ocMax : ScMax(); break;
4178 case ocMaxA : ScMax( true ); break;
4179 case ocSum : ScSum(); break;
4180 case ocProduct : ScProduct(); break;
4181 case ocNPV : ScNPV(); break;
4182 case ocIRR : ScIRR(); break;
4183 case ocMIRR : ScMIRR(); break;
4184 case ocISPMT : ScISPMT(); break;
4185 case ocAverage : ScAverage() ; break;
4186 case ocAverageA : ScAverage( true ); break;
4187 case ocCount : ScCount(); break;
4188 case ocCount2 : ScCount2(); break;
4190 case ocVarS : ScVar(); break;
4191 case ocVarA : ScVar( true ); break;
4193 case ocVarP_MS : ScVarP(); break;
4194 case ocVarPA : ScVarP( true ); break;
4196 case ocStDevS : ScStDev(); break;
4197 case ocStDevA : ScStDev( true ); break;
4199 case ocStDevP_MS : ScStDevP(); break;
4200 case ocStDevPA : ScStDevP( true ); break;
4201 case ocPV : ScPV(); break;
4202 case ocSYD : ScSYD(); break;
4203 case ocDDB : ScDDB(); break;
4204 case ocDB : ScDB(); break;
4205 case ocVBD : ScVDB(); break;
4206 case ocPDuration : ScPDuration(); break;
4207 case ocSLN : ScSLN(); break;
4208 case ocPMT : ScPMT(); break;
4209 case ocColumns : ScColumns(); break;
4210 case ocRows : ScRows(); break;
4211 case ocSheets : ScSheets(); break;
4212 case ocColumn : ScColumn(); break;
4213 case ocRow : ScRow(); break;
4214 case ocSheet : ScSheet(); break;
4215 case ocRRI : ScRRI(); break;
4216 case ocFV : ScFV(); break;
4217 case ocNper : ScNper(); break;
4218 case ocRate : ScRate(); break;
4219 case ocFilterXML : ScFilterXML(); break;
4220 case ocWebservice : ScWebservice(); break;
4221 case ocEncodeURL : ScEncodeURL(); break;
4222 case ocColor : ScColor(); break;
4223 case ocErf_MS : ScErf(); break;
4224 case ocErfc_MS : ScErfc(); break;
4225 case ocIpmt : ScIpmt(); break;
4226 case ocPpmt : ScPpmt(); break;
4227 case ocCumIpmt : ScCumIpmt(); break;
4228 case ocCumPrinc : ScCumPrinc(); break;
4229 case ocEffect : ScEffect(); break;
4230 case ocNominal : ScNominal(); break;
4231 case ocSubTotal : ScSubTotal(); break;
4232 case ocAggregate : ScAggregate(); break;
4233 case ocDBSum : ScDBSum(); break;
4234 case ocDBCount : ScDBCount(); break;
4235 case ocDBCount2 : ScDBCount2(); break;
4236 case ocDBAverage : ScDBAverage(); break;
4237 case ocDBGet : ScDBGet(); break;
4238 case ocDBMax : ScDBMax(); break;
4239 case ocDBMin : ScDBMin(); break;
4240 case ocDBProduct : ScDBProduct(); break;
4241 case ocDBStdDev : ScDBStdDev(); break;
4242 case ocDBStdDevP : ScDBStdDevP(); break;
4243 case ocDBVar : ScDBVar(); break;
4244 case ocDBVarP : ScDBVarP(); break;
4245 case ocIndirect : ScIndirect(); break;
4246 case ocAddress : ScAddressFunc(); break;
4247 case ocMatch : ScMatch(); break;
4248 case ocCountEmptyCells : ScCountEmptyCells(); break;
4249 case ocCountIf : ScCountIf(); break;
4250 case ocSumIf : ScSumIf(); break;
4251 case ocAverageIf : ScAverageIf(); break;
4252 case ocSumIfs : ScSumIfs(); break;
4253 case ocAverageIfs : ScAverageIfs(); break;
4254 case ocCountIfs : ScCountIfs(); break;
4255 case ocLookup : ScLookup(); break;
4256 case ocVLookup : ScVLookup(); break;
4257 case ocHLookup : ScHLookup(); break;
4258 case ocIndex : ScIndex(); break;
4259 case ocMultiArea : ScMultiArea(); break;
4260 case ocOffset : ScOffset(); break;
4261 case ocAreas : ScAreas(); break;
4262 case ocCurrency : ScCurrency(); break;
4263 case ocReplace : ScReplace(); break;
4264 case ocFixed : ScFixed(); break;
4265 case ocFind : ScFind(); break;
4266 case ocExact : ScExact(); break;
4267 case ocLeft : ScLeft(); break;
4268 case ocRight : ScRight(); break;
4269 case ocSearch : ScSearch(); break;
4270 case ocMid : ScMid(); break;
4271 case ocText : ScText(); break;
4272 case ocSubstitute : ScSubstitute(); break;
4273 case ocRegex : ScRegex(); break;
4274 case ocRept : ScRept(); break;
4275 case ocConcat : ScConcat(); break;
4276 case ocConcat_MS : ScConcat_MS(); break;
4277 case ocTextJoin_MS : ScTextJoin_MS(); break;
4278 case ocIfs_MS : ScIfs_MS(); break;
4279 case ocSwitch_MS : ScSwitch_MS(); break;
4280 case ocMinIfs_MS : ScMinIfs_MS(); break;
4281 case ocMaxIfs_MS : ScMaxIfs_MS(); break;
4282 case ocMatValue : ScMatValue(); break;
4283 case ocMatrixUnit : ScEMat(); break;
4284 case ocMatDet : ScMatDet(); break;
4285 case ocMatInv : ScMatInv(); break;
4286 case ocMatMult : ScMatMult(); break;
4287 case ocMatTrans : ScMatTrans(); break;
4288 case ocMatRef : ScMatRef(); break;
4289 case ocB : ScB(); break;
4290 case ocNormDist : ScNormDist( 3 ); break;
4291 case ocNormDist_MS : ScNormDist( 4 ); break;
4293 case ocExpDist_MS : ScExpDist(); break;
4295 case ocBinomDist_MS : ScBinomDist(); break;
4296 case ocPoissonDist : ScPoissonDist( true ); break;
4297 case ocPoissonDist_MS : ScPoissonDist( false ); break;
4298 case ocCombin : ScCombin(); break;
4299 case ocCombinA : ScCombinA(); break;
4300 case ocPermut : ScPermut(); break;
4301 case ocPermutationA : ScPermutationA(); break;
4302 case ocHypGeomDist : ScHypGeomDist( 4 ); break;
4303 case ocHypGeomDist_MS : ScHypGeomDist( 5 ); break;
4304 case ocLogNormDist : ScLogNormDist( 1 ); break;
4305 case ocLogNormDist_MS : ScLogNormDist( 4 ); break;
4306 case ocTDist : ScTDist(); break;
4307 case ocTDist_MS : ScTDist_MS(); break;
4308 case ocTDist_RT : ScTDist_T( 1 ); break;
4309 case ocTDist_2T : ScTDist_T( 2 ); break;
4311 case ocFDist_RT : ScFDist(); break;
4312 case ocFDist_LT : ScFDist_LT(); break;
4313 case ocChiDist : ScChiDist( true ); break;
4314 case ocChiDist_MS : ScChiDist( false ); break;
4315 case ocChiSqDist : ScChiSqDist(); break;
4316 case ocChiSqDist_MS : ScChiSqDist_MS(); break;
4317 case ocStandard : ScStandard(); break;
4318 case ocAveDev : ScAveDev(); break;
4319 case ocDevSq : ScDevSq(); break;
4320 case ocKurt : ScKurt(); break;
4321 case ocSkew : ScSkew(); break;
4322 case ocSkewp : ScSkewp(); break;
4323 case ocModalValue : ScModalValue(); break;
4324 case ocModalValue_MS : ScModalValue_MS( true ); break;
4325 case ocModalValue_Multi : ScModalValue_MS( false ); break;
4326 case ocMedian : ScMedian(); break;
4327 case ocGeoMean : ScGeoMean(); break;
4328 case ocHarMean : ScHarMean(); break;
4330 case ocWeibull_MS : ScWeibull(); break;
4332 case ocCritBinom : ScCritBinom(); break;
4333 case ocNegBinomVert : ScNegBinomDist(); break;
4334 case ocNegBinomDist_MS : ScNegBinomDist_MS(); break;
4335 case ocNoName : ScNoName(); break;
4336 case ocBad : ScBadName(); break;
4338 case ocZTest_MS : ScZTest(); break;
4340 case ocTTest_MS : ScTTest(); break;
4342 case ocFTest_MS : ScFTest(); break;
4344 case ocRank_Eq : ScRank( false ); break;
4345 case ocRank_Avg : ScRank( true ); break;
4347 case ocPercentile_Inc : ScPercentile( true ); break;
4348 case ocPercentile_Exc : ScPercentile( false ); break;
4349 case ocPercentrank :
4350 case ocPercentrank_Inc : ScPercentrank( true ); break;
4351 case ocPercentrank_Exc : ScPercentrank( false ); break;
4352 case ocLarge : ScLarge(); break;
4353 case ocSmall : ScSmall(); break;
4354 case ocFrequency : ScFrequency(); break;
4356 case ocQuartile_Inc : ScQuartile( true ); break;
4357 case ocQuartile_Exc : ScQuartile( false ); break;
4359 case ocNormInv_MS : ScNormInv(); break;
4361 case ocSNormInv_MS : ScSNormInv(); break;
4363 case ocConfidence_N : ScConfidence(); break;
4364 case ocConfidence_T : ScConfidenceT(); break;
4365 case ocTrimMean : ScTrimMean(); break;
4366 case ocProb : ScProbability(); break;
4367 case ocCorrel : ScCorrel(); break;
4369 case ocCovarianceP : ScCovarianceP(); break;
4370 case ocCovarianceS : ScCovarianceS(); break;
4371 case ocPearson : ScPearson(); break;
4372 case ocRSQ : ScRSQ(); break;
4373 case ocSTEYX : ScSTEYX(); break;
4374 case ocSlope : ScSlope(); break;
4375 case ocIntercept : ScIntercept(); break;
4376 case ocTrend : ScTrend(); break;
4377 case ocGrowth : ScGrowth(); break;
4378 case ocLinest : ScLinest(); break;
4379 case ocLogest : ScLogest(); break;
4380 case ocForecast_LIN :
4381 case ocForecast : ScForecast(); break;
4382 case ocForecast_ETS_ADD : ScForecast_Ets( etsAdd ); break;
4383 case ocForecast_ETS_SEA : ScForecast_Ets( etsSeason ); break;
4384 case ocForecast_ETS_MUL : ScForecast_Ets( etsMult ); break;
4385 case ocForecast_ETS_PIA : ScForecast_Ets( etsPIAdd ); break;
4386 case ocForecast_ETS_PIM : ScForecast_Ets( etsPIMult ); break;
4387 case ocForecast_ETS_STA : ScForecast_Ets( etsStatAdd ); break;
4388 case ocForecast_ETS_STM : ScForecast_Ets( etsStatMult ); break;
4390 case ocGammaLn_MS : ScLogGamma(); break;
4391 case ocGamma : ScGamma(); break;
4392 case ocGammaDist : ScGammaDist( true ); break;
4393 case ocGammaDist_MS : ScGammaDist( false ); break;
4395 case ocGammaInv_MS : ScGammaInv(); break;
4397 case ocChiTest_MS : ScChiTest(); break;
4399 case ocChiInv_MS : ScChiInv(); break;
4401 case ocChiSqInv_MS : ScChiSqInv(); break;
4403 case ocTInv_2T : ScTInv( 2 ); break;
4404 case ocTInv_MS : ScTInv( 4 ); break;
4406 case ocFInv_RT : ScFInv(); break;
4407 case ocFInv_LT : ScFInv_LT(); break;
4409 case ocLogInv_MS : ScLogNormInv(); break;
4410 case ocBetaDist : ScBetaDist(); break;
4411 case ocBetaDist_MS : ScBetaDist_MS(); break;
4413 case ocBetaInv_MS : ScBetaInv(); break;
4414 case ocFourier : ScFourier(); break;
4415 case ocExternal : ScExternal(); break;
4416 case ocTableOp : ScTableOp(); break;
4417 case ocStop : break;
4418 case ocErrorType : ScErrorType(); break;
4419 case ocErrorType_ODF : ScErrorType_ODF(); break;
4420 case ocCurrent : ScCurrent(); break;
4421 case ocStyle : ScStyle(); break;
4422 case ocDde : ScDde(); break;
4423 case ocBase : ScBase(); break;
4424 case ocDecimal : ScDecimal(); break;
4425 case ocConvertOOo : ScConvertOOo(); break;
4426 case ocEuroConvert : ScEuroConvert(); break;
4427 case ocRoman : ScRoman(); break;
4428 case ocArabic : ScArabic(); break;
4429 case ocInfo : ScInfo(); break;
4430 case ocHyperLink : ScHyperLink(); break;
4431 case ocBahtText : ScBahtText(); break;
4432 case ocGetPivotData : ScGetPivotData(); break;
4433 case ocJis : ScJis(); break;
4434 case ocAsc : ScAsc(); break;
4435 case ocLenB : ScLenB(); break;
4436 case ocRightB : ScRightB(); break;
4437 case ocLeftB : ScLeftB(); break;
4438 case ocMidB : ScMidB(); break;
4439 case ocReplaceB : ScReplaceB(); break;
4440 case ocFindB : ScFindB(); break;
4441 case ocSearchB : ScSearchB(); break;
4442 case ocUnicode : ScUnicode(); break;
4443 case ocUnichar : ScUnichar(); break;
4444 case ocBitAnd : ScBitAnd(); break;
4445 case ocBitOr : ScBitOr(); break;
4446 case ocBitXor : ScBitXor(); break;
4447 case ocBitRshift : ScBitRshift(); break;
4448 case ocBitLshift : ScBitLshift(); break;
4449 case ocTTT : ScTTT(); break;
4450 case ocDebugVar : ScDebugVar(); break;
4451 case ocNone : nFuncFmtType = SvNumFormatType::UNDEFINED; break;
4452 default : PushError( FormulaError::UnknownOpCode); break;
4455 // If the function pushed a subroutine as result, continue with
4456 // execution of the subroutine.
4457 if (sp > nStackBase && pStack[sp-1]->GetOpCode() == ocCall)
4462 if (FormulaCompiler::IsOpCodeVolatile(eOp))
4463 meVolatileType = VOLATILE;
4465 // Remember result matrix in case it could be reused.
4466 if (pTokenMatrixMap && sp && GetStackType() == svMatrix)
4467 pTokenMatrixMap->emplace(pCur, pStack[sp-1]);
4469 // outer function determines format of an expression
4470 if ( nFuncFmtType != SvNumFormatType::UNDEFINED )
4472 nRetTypeExpr = nFuncFmtType;
4473 // Inherit the format index for currency, date or time formats.
4474 switch (nFuncFmtType)
4476 case SvNumFormatType::CURRENCY:
4477 case SvNumFormatType::DATE:
4478 case SvNumFormatType::TIME:
4479 case SvNumFormatType::DATETIME:
4480 case SvNumFormatType::DURATION:
4481 nRetIndexExpr = nFuncFmtIndex;
4489 // Need a clean stack environment for the JumpMatrix to work.
4490 if (nGlobalError != FormulaError::NONE && eOp != ocPush && sp > nStackBase + 1)
4492 // Not all functions pop all parameters in case an error is
4493 // generated. Clean up stack. Assumes that every function pushes a
4494 // result, may be arbitrary in case of error.
4495 FormulaConstTokenRef xLocalResult = pStack[ sp - 1 ];
4496 while (sp > nStackBase)
4498 PushTokenRef( xLocalResult );
4505 sal_uInt8 nLevel = 0;
4506 if ( GetStackType( ++nLevel ) == svJumpMatrix )
4508 else if ( GetStackType( ++nLevel ) == svJumpMatrix )
4512 if ( nLevel == 1 || (nLevel == 2 && aCode.IsEndOfPath()) )
4515 aErrorFunctionStack.push_back( nErrorFunction);
4516 bGotResult = JumpMatrix( nLevel );
4517 if (aErrorFunctionStack.empty())
4521 nErrorFunction = aErrorFunctionStack.back();
4523 aErrorFunctionStack.pop_back();
4527 pJumpMatrix = nullptr;
4528 } while ( bGotResult );
4530 if( IsErrFunc(eOp) )
4533 if ( nGlobalError != FormulaError::NONE )
4535 if ( !nErrorFunctionCount )
4536 { // count of errorcode functions in formula
4537 FormulaTokenArrayPlainIterator aIter(*pArr);
4538 for ( FormulaToken* t = aIter.FirstRPN(); t; t = aIter.NextRPN() )
4540 if ( IsErrFunc(t->GetOpCode()) )
4541 ++nErrorFunctionCount;
4544 if ( nErrorFunction >= nErrorFunctionCount )
4545 ++nErrorFunction; // that's it, error => terminate
4549 // End: obtain result
4551 bool bForcedResultType;
4554 case ocGetDateValue:
4555 case ocGetTimeValue:
4556 // Force final result of DATEVALUE and TIMEVALUE to number type,
4557 // which so far was date or time for calculations.
4558 nRetTypeExpr = nFuncFmtType = SvNumFormatType::NUMBER;
4559 nRetIndexExpr = nFuncFmtIndex = 0;
4560 bForcedResultType = true;
4563 bForcedResultType = false;
4568 pCur = pStack[ sp-1 ];
4569 if( pCur->GetOpCode() == ocPush )
4571 // An svRefList can be resolved if it a) contains just one
4572 // reference, or b) in array context contains an array of single
4574 if (pCur->GetType() == svRefList)
4576 PopRefListPushMatrixOrRef();
4577 pCur = pStack[ sp-1 ];
4579 switch( pCur->GetType() )
4585 nGlobalError = pCur->GetError();
4589 // If typed, pop token to obtain type information and
4590 // push a plain untyped double so the result token to
4591 // be transferred to the formula cell result does not
4592 // unnecessarily duplicate the information.
4593 if (pCur->GetDoubleType() != 0)
4595 double fVal = PopDouble();
4596 if (!bForcedResultType)
4598 if (nCurFmtType != nFuncFmtType)
4599 nRetIndexExpr = 0; // carry format index only for matching type
4600 nRetTypeExpr = nFuncFmtType = nCurFmtType;
4602 if (nRetTypeExpr == SvNumFormatType::DURATION)
4604 // Round the duration in case a wall clock time
4605 // display format is used instead of a duration
4606 // format. To micro seconds which then catches
4607 // the converted hh:mm:ss.9999997 cases.
4611 fVal = rtl::math::round( fVal, 6);
4615 PushTempToken( CreateFormulaDoubleToken( fVal));
4617 if ( nFuncFmtType == SvNumFormatType::UNDEFINED )
4619 nRetTypeExpr = SvNumFormatType::NUMBER;
4625 nRetTypeExpr = SvNumFormatType::TEXT;
4631 PopSingleRef( aAdr );
4632 if( nGlobalError == FormulaError::NONE)
4633 PushCellResultToken( false, aAdr, &nRetTypeExpr, &nRetIndexExpr, true);
4637 PopError(); // maybe #REF! takes precedence over #VALUE!
4638 PushError( FormulaError::NoValue);
4642 if ( bMatrixFormula )
4643 { // create matrix for {=A1:A5}
4644 PopDoubleRefPushMatrix();
4645 ScMatrixRef xMat = PopMatrix();
4646 QueryMatrixType(xMat, nRetTypeExpr, nRetIndexExpr);
4651 PopDoubleRef( aRange );
4653 if ( nGlobalError == FormulaError::NONE && DoubleRefToPosSingleRef( aRange, aAdr))
4654 PushCellResultToken( false, aAdr, &nRetTypeExpr, &nRetIndexExpr, true);
4658 case svExternalDoubleRef:
4661 PopExternalDoubleRef(xMat);
4662 QueryMatrixType(xMat, nRetTypeExpr, nRetIndexExpr);
4667 sc::RangeMatrix aMat = PopRangeMatrix();
4668 if (aMat.isRangeValid())
4670 // This matrix represents a range reference. Apply implicit intersection.
4671 double fVal = applyImplicitIntersection(aMat, aPos);
4672 if (std::isnan(fVal))
4678 // This is a normal matrix.
4679 QueryMatrixType(aMat.mpMat, nRetTypeExpr, nRetIndexExpr);
4682 case svExternalSingleRef:
4684 FormulaTokenRef xToken;
4685 ScExternalRefCache::CellFormat aFmt;
4686 PopExternalSingleRef(xToken, &aFmt);
4687 if (nGlobalError != FormulaError::NONE)
4690 PushTokenRef(xToken);
4694 nFuncFmtType = aFmt.mnType;
4695 nFuncFmtIndex = aFmt.mnIndex;
4700 SetError( FormulaError::UnknownStackVariable);
4704 SetError( FormulaError::UnknownStackVariable);
4707 SetError( FormulaError::OperatorExpected);
4709 SetError( FormulaError::NoCode);
4711 if (bForcedResultType || nRetTypeExpr != SvNumFormatType::UNDEFINED)
4713 nRetFmtType = nRetTypeExpr;
4714 nRetFmtIndex = nRetIndexExpr;
4716 else if( nFuncFmtType != SvNumFormatType::UNDEFINED )
4718 nRetFmtType = nFuncFmtType;
4719 nRetFmtIndex = nFuncFmtIndex;
4722 nRetFmtType = SvNumFormatType::NUMBER;
4724 if (nGlobalError != FormulaError::NONE && GetStackType() != svError )
4725 PushError( nGlobalError);
4727 // THE final result.
4728 xResult = PopToken();
4730 xResult = new FormulaErrorToken( FormulaError::UnknownStackVariable);
4732 // release tokens in expression stack
4733 const FormulaToken** p = pStack;
4737 StackVar eType = xResult->GetType();
4738 if (eType == svMatrix)
4739 // Results are immutable in case they would be reused as input for new
4741 xResult->GetMatrix()->SetImmutable();
4745 void ScInterpreter::AssertFormulaMatrix()
4747 bMatrixFormula = true;
4750 svl::SharedString ScInterpreter::GetStringResult() const
4752 return xResult->GetString();
4755 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
OUString getString() const
static SharedString getEmptyString()
OUString getString(const ScDocument *pDoc) const
Retrieve string value.
formula::StackVar Interpret()
double GetCellValueOrZero(const ScAddress &, ScRefCellValue &rCell)
static thread_local bool bGlobalStackInUse
static double ConvertStringToValue(const OUString &rStr, const ScCalcConfig &rConfig, FormulaError &rError, FormulaError nStringNoValueError, SvNumberFormatter *pFormatter, SvNumFormatType &rCurFmtType)
Convert string content to numeric value.
This is very similar to ScCellValue, except that it references the original value instead of copying ...
double GetCellValue(const ScAddress &, ScRefCellValue &rCell)
sal_uInt32 GetCellNumberFormat(const ScAddress &rPos, ScRefCellValue &rCell)
ScFormulaCell * mpFormula
double ConvertStringToValue(const OUString &)
bool IsTableOpInRange(const ScRange &)
static FormulaError GetCellErrCode(const ScRefCellValue &rCell)
void GetCellString(svl::SharedString &rStr, ScRefCellValue &rCell)
bool In(const ScAddress &) const
is Address& in Range?
void ReplaceCell(ScAddress &)
static thread_local std::unique_ptr< ScTokenStack > pGlobalStack
double GetValueCellValue(const ScAddress &, double fOrig)
Only ValueCell, formula cells already store the result rounded.
const NodeContext & mrContext
bool CreateDoubleArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2, sal_uInt8 *pCellArr)