27#include <osl/thread.h>
38#include <rtl/character.hxx>
39#include <rtl/ustring.hxx>
41#include <osl/diagnose.h>
42#include <unicode/uchar.h>
43#include <unicode/regex.h>
48#include <document.hxx>
59#include <compiler.hxx>
65#include <tokenarray.hxx>
80const sal_uInt64
n2power48 = SAL_CONST_UINT64( 281474976710656);
85using ::std::unique_ptr;
90 short nJumpCount = pJump[ 0 ];
102 ScTokenMatrixMap::const_iterator aMapIter;
104 pMat->SetErrorInterpreter(
nullptr);
106 pMat->GetDimensions( nCols, nRows );
107 if ( nCols == 0 || nRows == 0 )
113 xNew = (*aMapIter).second;
116 std::shared_ptr<ScJumpMatrix> pJumpMat( std::make_shared<ScJumpMatrix>(
118 for (
SCSIZE nC=0; nC < nCols; ++nC )
120 for (
SCSIZE nR=0; nR < nRows; ++nR )
124 bool bIsValue = pMat->IsValue(nC, nR);
127 fVal = pMat->GetDouble(nC, nR);
128 bIsValue = std::isfinite(fVal);
129 bTrue = bIsValue && (fVal != 0.0);
139 bIsValue = pMat->IsValueOrEmpty(nC, nR);
145 if( nJumpCount >= 2 )
147 pJumpMat->SetJump( nC, nR, fVal,
149 pJump[ nJumpCount ]);
153 pJumpMat->SetJump( nC, nR, fVal,
155 pJump[ nJumpCount ]);
160 if( nJumpCount == 3 && bIsValue )
162 pJumpMat->SetJump( nC, nR, fVal,
164 pJump[ nJumpCount ]);
169 pJumpMat->SetJump( nC, nR, fVal,
171 pJump[ nJumpCount ]);
186 aCode.
Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
192 const bool bCondition =
GetBool();
196 aCode.
Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
198 else if ( bCondition )
200 if( nJumpCount >= 2 )
202 aCode.
Jump( pJump[ 1 ], pJump[ nJumpCount ] );
208 aCode.
Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
213 if( nJumpCount == 3 )
215 aCode.
Jump( pJump[ 2 ], pJump[ nJumpCount ] );
221 aCode.
Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
239 else if ( pMat->
IsEmpty( nC, nR ) )
252 short nJumpCount = pJump[ 0 ];
253 if (!
sp || nJumpCount != 2)
256 nGlobalError = (
sp ? FormulaError::ParameterExpected : FormulaError::UnknownStackVariable);
258 aCode.
Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
273 if (nOldGlobalError != FormulaError::NONE)
320 SCSIZE nErrorCol = ::std::numeric_limits<SCSIZE>::max(),
321 nErrorRow = ::std::numeric_limits<SCSIZE>::max();
323 pMat->GetDimensions( nCols, nRows );
324 if (nCols == 0 || nRows == 0)
329 for (
SCSIZE nC=0; nC < nCols && !bError; ++nC)
331 for (
SCSIZE nR=0; nR < nRows && !bError; ++nR)
334 if (nErr != FormulaError::NONE && (!bNAonly || nErr == FormulaError::NotAvailable))
346 ScTokenMatrixMap::const_iterator aMapIter;
349 xNew = (*aMapIter).second;
353 const ScMatrix* pMatPtr = pMat.get();
354 std::shared_ptr<ScJumpMatrix> pJumpMat( std::make_shared<ScJumpMatrix>(
359 pJumpMat->SetAllJumps( fFlagResult, pJump[ nJumpCount ], pJump[ nJumpCount ] );
363 for ( ; nC < nCols && (nC != nErrorCol || nR != nErrorRow); )
365 for (nR = 0 ; nR < nRows && (nC != nErrorCol || nR != nErrorRow); ++nR)
369 if (nC != nErrorCol && nR != nErrorRow)
373 for ( ; nC < nCols; ++nC)
375 for ( ; nR < nRows; ++nR)
378 if (nErr != FormulaError::NONE && (!bNAonly || nErr == FormulaError::NotAvailable))
380 pJumpMat->SetJump( nC, nR, 1.0, pJump[ 1 ], pJump[ nJumpCount ] );
395 aCode.
Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
401 if (bError && (!bNAonly ||
nGlobalError == FormulaError::NotAvailable))
405 aCode.
Jump( pJump[ 1 ], pJump[ nJumpCount ] );
412 aCode.
Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
420 bool bHaveJump =
false;
422 short nJumpCount = pJump[ 0 ];
434 ScTokenMatrixMap::const_iterator aMapIter;
436 pMat->SetErrorInterpreter(
nullptr);
438 pMat->GetDimensions( nCols, nRows );
439 if ( nCols == 0 || nRows == 0 )
443 xNew = (*aMapIter).second;
446 std::shared_ptr<ScJumpMatrix> pJumpMat( std::make_shared<ScJumpMatrix>(
448 for (
SCSIZE nC=0; nC < nCols; ++nC )
450 for (
SCSIZE nR=0; nR < nRows; ++nR )
453 bool bIsValue = pMat->IsValue(nC, nR);
456 fVal = pMat->GetDouble(nC, nR);
457 bIsValue = std::isfinite( fVal );
460 fVal = ::rtl::math::approxFloor( fVal);
461 if ( (fVal < 1) || (fVal >= nJumpCount))
465 FormulaError::IllegalArgument);
475 pJumpMat->SetJump( nC, nR, fVal,
476 pJump[
static_cast<short>(fVal) ],
477 pJump[ nJumpCount ]);
481 pJumpMat->SetJump( nC, nR, fVal,
483 pJump[ nJumpCount ]);
494 aCode.
Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
503 if (
nGlobalError == FormulaError::NONE && (nJumpIndex >= 1) && (nJumpIndex < nJumpCount))
505 aCode.
Jump( pJump[
static_cast<short>(nJumpIndex) ], pJump[ nJumpCount ] );
513 aCode.
Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
518 SCSIZE nJumpCols, nJumpRows;
519 SCSIZE nResCols, nResRows;
520 SCSIZE nAdjustCols, nAdjustRows;
523 if (!(( nJumpCols == 1 && nParmCols > nResCols ) ||
524 ( nJumpRows == 1 && nParmRows > nResRows )))
527 if ( nJumpCols == 1 && nJumpRows == 1 )
529 nAdjustCols = std::max(nParmCols, nResCols);
530 nAdjustRows = std::max(nParmRows, nResRows);
532 else if ( nJumpCols == 1 )
534 nAdjustCols = nParmCols;
535 nAdjustRows = nResRows;
539 nAdjustCols = nResCols;
540 nAdjustRows = nParmRows;
550 if ( nStackLevel == 2 )
556 assert(!
"pop goes the weasel");
562 SetError( FormulaError::UnknownStackVariable );
636 if (eReturnType == ParamClass::Reference)
641 aRef.
Ref1 = aRef.
Ref2 = *(xRef->GetSingleRef());
718 if (eReturnType == ParamClass::Reference)
737 switch (pToken->GetType())
752 assert(!
"unhandled svExternalSingleRef case");
754 FormulaError::UnknownStackVariable), nC, nR );
778 pMat->GetDimensions( nCols, nRows );
779 if ((nCols <= nC && nCols != 1) ||
780 (nRows <= nR && nRows != 1))
790 pMat->SetErrorInterpreter(
nullptr);
818 short nStart, nNext, nStop;
820 while ( bCont && nStart == nNext )
834 if ( bCont && nStart != nNext )
837 for (
auto const &
i : rParams )
890 for(
short i = 1;
i >= 0;
i-- )
937 SetError( FormulaError::IllegalParameter);
942 pMat->GetDimensions(nC, nR);
945 SetError( FormulaError::IllegalParameter);
948 if (pMat->IsEmpty(0, 0))
950 else if (pMat->IsStringOrEmpty(0, 0))
952 rCell.
maStr = pMat->GetString(0, 0);
957 rCell.
mfValue = pMat->GetDouble(0, 0);
972 SetError( FormulaError::IllegalParameter);
989 for(
short i = 1;
i >= 0;
i-- )
1034 SetError( FormulaError::IllegalParameter);
1036 aMat[
i].
mpMat->SetErrorInterpreter(
nullptr);
1041 SetError( FormulaError::IllegalParameter);
1054 if (aMat[0].mpMat && aMat[1].mpMat)
1058 aMat[0].
mpMat->GetDimensions(nC0, nR0);
1059 aMat[1].
mpMat->GetDimensions(nC1, nR1);
1060 SCSIZE nC = std::max( nC0, nC1 );
1061 SCSIZE nR = std::max( nR0, nR1 );
1065 for (
SCSIZE j=0; j<nC; j++ )
1067 for (
SCSIZE k=0; k<nR; k++ )
1069 SCSIZE nCol = j, nRow = k;
1070 if (aMat[0].mpMat->ValidColRowOrReplicated(nCol, nRow) &&
1071 aMat[1].
mpMat->ValidColRowOrReplicated(nCol, nRow))
1073 for (
short i=1;
i>=0;
i-- )
1077 if (aMat[
i].mpMat->IsStringOrEmpty(j, k))
1093 aRes.
mpMat->PutError( FormulaError::NoValue, j, k);
1100 aRes.
mpMat->CompareEqual();
1103 aRes.
mpMat->CompareLess();
1106 aRes.
mpMat->CompareGreater();
1109 aRes.
mpMat->CompareLessEqual();
1112 aRes.
mpMat->CompareGreaterEqual();
1115 aRes.
mpMat->CompareNotEqual();
1118 SAL_WARN(
"sc",
"ScInterpreter::QueryMat: unhandled comparison operator: " <<
static_cast<int>(eOp));
1123 else if (aMat[0].mpMat || aMat[1].mpMat)
1125 size_t i = ( aMat[0].
mpMat ? 0 : 1);
1157 if (
nGlobalError != FormulaError::NONE || !pResultMatrix)
1159 SetError( FormulaError::IllegalParameter);
1160 return pResultMatrix;
1163 return pResultMatrix;
1271 short nParamCount =
GetByte();
1275 bool bHaveValue =
false;
1277 size_t nRefInList = 0;
1278 while( nParamCount-- > 0)
1318 if ( aValIter.
GetFirst( fVal, nErr ) && nErr == FormulaError::NONE )
1323 bRes &= ( fVal != 0.0 );
1324 }
while ( (nErr == FormulaError::NONE) &&
1325 aValIter.
GetNext( fVal, nErr ) );
1339 double fVal = pMat->And();
1341 if ( nErr != FormulaError::NONE )
1347 bRes &= (fVal != 0.0);
1354 SetError( FormulaError::IllegalParameter);
1369 short nParamCount =
GetByte();
1373 bool bHaveValue =
false;
1375 size_t nRefInList = 0;
1376 while( nParamCount-- > 0)
1416 if ( aValIter.
GetFirst( fVal, nErr ) )
1421 bRes |= ( fVal != 0.0 );
1422 }
while ( (nErr == FormulaError::NONE) &&
1423 aValIter.
GetNext( fVal, nErr ) );
1438 double fVal = pMat->Or();
1440 if ( nErr != FormulaError::NONE )
1446 bRes |= (fVal != 0.0);
1453 SetError( FormulaError::IllegalParameter);
1469 short nParamCount =
GetByte();
1473 bool bHaveValue =
false;
1475 size_t nRefInList = 0;
1476 while( nParamCount-- > 0)
1518 if ( aValIter.
GetFirst( fVal, nErr ) )
1523 bRes ^= ( fVal != 0.0 );
1524 }
while ( (nErr == FormulaError::NONE) &&
1525 aValIter.
GetNext( fVal, nErr ) );
1540 double fVal = pMat->Xor();
1542 if ( nErr != FormulaError::NONE )
1548 bRes ^= ( fVal != 0.0 );
1555 SetError( FormulaError::IllegalParameter);
1582 pMat->GetDimensions( nC, nR );
1588 pMat->NegOp( *pResMat);
1626 pMat->GetDimensions( nC, nR );
1632 pMat->NotOp( *pResMat);
1649 double num1 = ::rtl::math::approxFloor(
GetDouble());
1650 double num2 = ::rtl::math::approxFloor(
GetDouble());
1651 if ( (num1 >=
n2power48) || (num1 < 0) ||
1655 PushDouble (
static_cast<sal_uInt64
>(num1) &
static_cast<sal_uInt64
>(num2));
1664 double num1 = ::rtl::math::approxFloor(
GetDouble());
1665 double num2 = ::rtl::math::approxFloor(
GetDouble());
1666 if ( (num1 >=
n2power48) || (num1 < 0) ||
1670 PushDouble (
static_cast<sal_uInt64
>(num1) |
static_cast<sal_uInt64
>(num2));
1679 double num1 = ::rtl::math::approxFloor(
GetDouble());
1680 double num2 = ::rtl::math::approxFloor(
GetDouble());
1681 if ( (num1 >=
n2power48) || (num1 < 0) ||
1685 PushDouble (
static_cast<sal_uInt64
>(num1) ^
static_cast<sal_uInt64
>(num2));
1694 double fShift = ::rtl::math::approxFloor(
GetDouble());
1695 double num = ::rtl::math::approxFloor(
GetDouble());
1702 fRes = ::rtl::math::approxFloor( num / pow( 2.0, -fShift));
1703 else if (fShift == 0)
1706 fRes = num * pow( 2.0, fShift);
1717 double fShift = ::rtl::math::approxFloor(
GetDouble());
1718 double num = ::rtl::math::approxFloor(
GetDouble());
1725 fRes = num * pow( 2.0, -fShift);
1726 else if (fShift == 0)
1729 fRes = ::rtl::math::approxFloor( num / pow( 2.0, fShift));
1740 double fFirst,
double fLast )
1753 nCols = std::max<SCCOL>(0,
static_cast<SCCOL>(nC));
1754 nRows = std::max<SCROW>(0,
static_cast<SCROW>(nR));
1759 if (nCols == 1 && nRows == 1)
1785 for (
SCROW j=0; j < nRows; ++j)
1787 pResMat->PutDouble( RandomFunc( fFirst, fLast),
1802 auto RandomFunc = []( double, double )
1816 double fMax = rtl::math::round(
GetDouble(), 0, rtl_math_RoundingMode_Up);
1817 double fMin = rtl::math::round(
GetDouble(), 0, rtl_math_RoundingMode_Up);
1823 fMax = std::nextafter( fMax+1, -DBL_MAX);
1824 auto RandomFunc = [](
double fFirst,
double fLast )
1930 if (fabs(fVal) >= 1.0)
1939 if (fabs(nVal) <= 1.0)
2014 nRes = pMat->IsEmptyCell( 0, 0) ? 1 : 0;
2017 SCSIZE nCols, nRows, nC, nR;
2018 pMat->GetDimensions( nCols, nRows);
2020 if ( nC < nCols && nR < nRows )
2021 nRes = pMat->IsEmptyCell( nC, nR) ? 1 : 0;
2083 bRes = pMat->IsStringOrEmpty(0, 0) && !pMat->IsEmpty(0, 0);
2086 SCSIZE nCols, nRows, nC, nR;
2087 pMat->GetDimensions( nCols, nRows);
2089 if ( nC < nCols && nR < nRows )
2090 bRes = pMat->IsStringOrEmpty( nC, nR) && !pMat->IsEmpty( nC, nR);
2145 bRes = (
nCurFmtType == SvNumFormatType::LOGICAL );
2235 return pFormat && pFormat->
GetColor( 1 );
2259 if( nParamCount == 2 )
2276 aCellPos = aRange.
aStart;
2297 if( aInfoType ==
"COL" )
2301 else if( aInfoType ==
"ROW" )
2305 else if( aInfoType ==
"SHEET" )
2309 else if( aInfoType ==
"ADDRESS" )
2322 case FormulaGrammar::CONV_OOO:
2323 case FormulaGrammar::CONV_XL_A1:
2324 case FormulaGrammar::CONV_XL_R1C1:
2333 else if( aInfoType ==
"FILENAME" )
2336 OUString aFuncResult;
2351 if (eConv == FormulaGrammar::CONV_UNSPECIFIED)
2354 if (eConv == FormulaGrammar::CONV_XL_A1 ||
2355 eConv == FormulaGrammar::CONV_XL_R1C1 ||
2356 eConv == FormulaGrammar::CONV_XL_OOX)
2375 else if( aInfoType ==
"COORD" )
2378 OUString aCellStr1 =
2381 OUString aCellStr2 =
2384 OUString aFuncResult = aCellStr1 +
":" + aCellStr2;
2389 else if( aInfoType ==
"CONTENTS" )
2400 else if( aInfoType ==
"TYPE" )
2409 else if( aInfoType ==
"WIDTH" )
2421 assert(nZeroWidth != 0);
2422 pPrinter->
SetFont( aOldFont );
2427 else if( aInfoType ==
"PREFIX" )
2433 switch( pJustAttr->GetValue() )
2435 case SvxCellHorJustify::Standard:
2436 case SvxCellHorJustify::Left:
2437 case SvxCellHorJustify::Block: c =
'\'';
break;
2438 case SvxCellHorJustify::Center: c =
'^';
break;
2439 case SvxCellHorJustify::Right: c =
'"';
break;
2440 case SvxCellHorJustify::Repeat: c =
'\\';
break;
2445 else if( aInfoType ==
"PROTECT" )
2452 else if( aInfoType ==
"FORMAT" )
2454 OUString aFuncResult;
2456 getFormatString(
pFormatter, nFormat, aFuncResult);
2459 else if( aInfoType ==
"COLOR" )
2464 else if( aInfoType ==
"PARENTHESES" )
2510 if ( aInfoType ==
"COL" )
2512 else if ( aInfoType ==
"ROW" )
2514 else if ( aInfoType ==
"SHEET" )
2524 else if ( aInfoType ==
"ADDRESS" )
2534 else if ( aInfoType ==
"FILENAME" )
2546 if (eConv == FormulaGrammar::CONV_UNSPECIFIED)
2549 if (eConv == FormulaGrammar::CONV_XL_A1 ||
2550 eConv == FormulaGrammar::CONV_XL_R1C1 ||
2551 eConv == FormulaGrammar::CONV_XL_OOX)
2554 sal_Int32
nPos =
p->lastIndexOf(
'/');
2555 aBuf = OUString::Concat(
p->subView(0,
nPos + 1))
2556 +
"[" +
p->subView(
nPos + 1) +
"]"
2562 aBuf =
"'" + *
p +
"'#$" + aTabName;
2567 else if ( aInfoType ==
"CONTENTS" )
2569 switch (pToken->GetType())
2575 PushString(OUString::number(pToken->GetDouble()));
2584 else if ( aInfoType ==
"TYPE" )
2587 switch (pToken->GetType())
2600 else if ( aInfoType ==
"FORMAT" )
2607 else if ( aInfoType ==
"COLOR" )
2618 else if ( aInfoType ==
"PARENTHESES" )
2659 bRes = !
x->GetRefList()->empty();
2735 if (pMat->GetErrorIfNotString( 0, 0) == FormulaError::NONE)
2736 bRes = pMat->IsValue( 0, 0);
2740 SCSIZE nCols, nRows, nC, nR;
2741 pMat->GetDimensions( nCols, nRows);
2743 if ( nC < nCols && nR < nRows )
2744 if (pMat->GetErrorIfNotString( nC, nR) == FormulaError::NONE)
2745 bRes = pMat->IsValue( nC, nR);
2768 PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2781 static_cast<SCSIZE>(nRow2 - nRow1 + 1),
true);
2791 for (
SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
2794 for (
SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
2836 PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2842 SetError( FormulaError::IllegalArgument);
2853 for (
SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
2856 for (
SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
2867 pResMat->PutError( FormulaError::NotAvailable,
i,j);
2892 SetError( FormulaError::NotAvailable );
2898 SetError( FormulaError::NotAvailable );
2920 bRes = (nErr == FormulaError::NotAvailable);
2929 (pToken && pToken->GetType() ==
svError && pToken->GetError() == FormulaError::NotAvailable))
2940 bRes = (pMat->GetErrorIfNotString( 0, 0) == FormulaError::NotAvailable);
2943 SCSIZE nCols, nRows, nC, nR;
2944 pMat->GetDimensions( nCols, nRows);
2946 if ( nC < nCols && nR < nRows )
2947 bRes = (pMat->GetErrorIfNotString( nC, nR) == FormulaError::NotAvailable);
2977 bRes = (nErr != FormulaError::NONE && nErr != FormulaError::NotAvailable);
2986 (pToken->GetType() ==
svError && pToken->GetError() != FormulaError::NotAvailable))
2999 bRes = (nErr != FormulaError::NONE && nErr != FormulaError::NotAvailable);
3003 SCSIZE nCols, nRows, nC, nR;
3004 pMat->GetDimensions( nCols, nRows);
3006 if ( nC < nCols && nR < nRows )
3008 FormulaError nErr = pMat->GetErrorIfNotString( nC, nR);
3009 bRes = (nErr != FormulaError::NONE && nErr != FormulaError::NotAvailable);
3062 bRes = (pMat->GetErrorIfNotString( 0, 0) != FormulaError::NONE);
3065 SCSIZE nCols, nRows, nC, nR;
3066 pMat->GetDimensions( nCols, nRows);
3068 if ( nC < nCols && nR < nRows )
3069 bRes = (pMat->GetErrorIfNotString( nC, nR) != FormulaError::NONE);
3098 if (nErr != FormulaError::NONE)
3133 fVal = pToken->GetDouble();
3146 bRes = pMat->IsValue( 0, 0);
3148 fVal = pMat->GetDouble( 0, 0);
3152 SCSIZE nCols, nRows, nC, nR;
3153 pMat->GetDimensions( nCols, nRows);
3155 if ( nC < nCols && nR < nRows )
3157 bRes = pMat->IsValue( nC, nR);
3159 fVal = pMat->GetDouble( nC, nR);
3170 SetError( FormulaError::IllegalParameter);
3172 bRes = ( fmod( ::rtl::math::approxFloor( fabs( fVal ) ), 2.0 ) < 0.5 );
3196 if (nErr != FormulaError::NONE)
3207 OUStringBuffer
aStr;
3212 if ( *
p !=
' ' ||
p[-1] !=
' ' )
3229 const sal_Int32 nLen =
aStr.getLength();
3236 while(
nPos < nLen )
3260 while ( nIdx <
aStr.getLength() )
3262 aStr.iterateCodePoints( &nIdx );
3281 bool bValue =
false;
3331 PushError( FormulaError::UnknownOpCode);
3337 OUString aInputString;
3406 sal_uInt32 nFIndex = 0;
3421 OUString aInputString;
3422 OUString aGroupSeparator;
3425 if ( nParamCount == 3 )
3428 if ( nParamCount >= 2 )
3431 if ( aDecimalSeparator.getLength() == 1 )
3432 cDecimalSeparator = aDecimalSeparator[ 0 ];
3440 if ( cDecimalSeparator && aGroupSeparator.indexOf( cDecimalSeparator ) != -1 )
3458 if ( aInputString.isEmpty() )
3467 sal_Int32 nDecSep = aInputString.indexOf( cDecimalSeparator );
3470 OUString aTemporary( nDecSep >= 0 ? aInputString.copy( 0, nDecSep ) : aInputString );
3472 while (
nIndex < aGroupSeparator.getLength())
3474 sal_uInt32 nChar = aGroupSeparator.iterateCodePoints( &
nIndex );
3475 aTemporary = aTemporary.replaceAll( OUString( &nChar, 1 ),
"" );
3478 aInputString = aTemporary + aInputString.subView( nDecSep );
3480 aInputString = aTemporary;
3483 for ( sal_Int32
i = aInputString.getLength(); --
i >= 0; )
3486 if ( c == 0x0020 || c == 0x0009 || c == 0x000A || c == 0x000D )
3487 aInputString = aInputString.replaceAt(
i, 1,
u"" );
3489 sal_Int32 nPercentCount = 0;
3490 for ( sal_Int32
i = aInputString.getLength() - 1;
i >= 0 && aInputString[
i ] == 0x0025;
i-- )
3492 aInputString = aInputString.replaceAt(
i, 1,
u"" );
3496 rtl_math_ConversionStatus eStatus;
3497 sal_Int32 nParseEnd;
3498 double fVal = ::rtl::math::stringToDouble( aInputString, cDecimalSeparator, 0, &eStatus, &nParseEnd );
3499 if ( eStatus == rtl_math_ConversionStatus_Ok && nParseEnd == aInputString.getLength() )
3502 fVal *= pow( 10.0, -(nPercentCount * 2));
3511 return ( !u_isISOControl(nCodePoint)
3512 && u_isdefined(nCodePoint) );
3520 OUStringBuffer
aBuf(
aStr.getLength() );
3522 while ( nIdx <
aStr.getLength() )
3524 sal_uInt32 c =
aStr.iterateCodePoints( &nIdx );
3526 aBuf.appendUtf32( c );
3541 const sal_uInt32 convertFlags =
3542 RTL_UNICODETOTEXT_FLAGS_NONSPACING_IGNORE |
3543 RTL_UNICODETOTEXT_FLAGS_CONTROL_IGNORE |
3544 RTL_UNICODETOTEXT_FLAGS_FLUSH |
3545 RTL_UNICODETOTEXT_FLAGS_UNDEFINED_DEFAULT |
3546 RTL_UNICODETOTEXT_FLAGS_INVALID_DEFAULT |
3547 RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACE;
3556 if (fVal < 0.0 || fVal >= 256.0)
3561 const sal_uInt32 convertFlags =
3562 RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_DEFAULT |
3563 RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_DEFAULT |
3564 RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT;
3566 char cEncodedChar =
static_cast<char>(fVal);
3567 OUString
aStr(&cEncodedChar, 1, osl_getThreadTextEncoding(), convertFlags);
3587 return aTrans.
transliterate( rStr, 0, sal_uInt16( rStr.getLength() ) );
3599 return aTrans.
transliterate( rStr, 0, sal_uInt16( rStr.getLength() ) );
3649 if (
nGlobalError != FormulaError::NONE || !rtl::isUnicodeCodePoint(nCodePoint))
3653 OUString
aStr( &nCodePoint, 1 );
3660 const std::function<
void(
SCSIZE i,
double fCurrent )>& MatOpFunc,
bool bDoMatOp )
3663 if (!
p || !
p->IsArrayResult())
3669 assert(nMatRows > 0);
3670 xResMat =
GetNewMat( 1, nMatRows,
true);
3671 xResMat->FillDouble( fCurrent, 0,0, 0,nMatRows-1);
3679 MatOpFunc(
i, fCurrent);
3687 short nParamCount =
GetByte();
3692 double nMin = ::std::numeric_limits<double>::max();
3693 auto MatOpFunc = [&xResMat](
SCSIZE i,
double fCurMin )
3695 double fVecRes = xResMat->GetDouble(0,
i);
3696 if (fVecRes > fCurMin)
3697 xResMat->PutDouble( fCurMin, 0,
i);
3700 size_t nRefArrayPos = std::numeric_limits<size_t>::max();
3705 size_t nRefInList = 0;
3706 while (nParamCount-- > 0)
3713 if (nMin > nVal) nMin = nVal;
3725 if (nMin > nVal) nMin = nVal;
3727 else if (bTextAsZero && aCell.
hasString())
3739 nRefArrayPos == std::numeric_limits<size_t>::max()))
3741 nRefArrayPos = nRefInList;
3755 while ((nErr == FormulaError::NONE) && aValIter.
GetNext(nVal, nErr))
3762 if (nRefArrayPos != std::numeric_limits<size_t>::max())
3765 MatOpFunc( nRefArrayPos, nMin);
3768 nMin = std::numeric_limits<double>::max();
3770 nRefArrayPos = std::numeric_limits<size_t>::max();
3797 SetError(FormulaError::IllegalParameter);
3802 SetError(FormulaError::IllegalParameter);
3809 if (nMin < std::numeric_limits<double>::max())
3813 MatOpFunc(
i, nMin);
3824 double fVecRes = xResMat->GetDouble(0,
i);
3825 if (fVecRes == std::numeric_limits<double>::max())
3826 xResMat->PutDouble( 0.0, 0,
i);
3833 if (!std::isfinite(nVal))
3835 else if ( nVal < nMin )
3844 short nParamCount =
GetByte();
3849 double nMax = std::numeric_limits<double>::lowest();
3850 auto MatOpFunc = [&xResMat](
SCSIZE i,
double fCurMax )
3852 double fVecRes = xResMat->GetDouble(0,
i);
3853 if (fVecRes < fCurMax)
3854 xResMat->PutDouble( fCurMax, 0,
i);
3857 size_t nRefArrayPos = std::numeric_limits<size_t>::max();
3862 size_t nRefInList = 0;
3863 while (nParamCount-- > 0)
3870 if (nMax < nVal) nMax = nVal;
3882 if (nMax < nVal) nMax = nVal;
3884 else if (bTextAsZero && aCell.
hasString())
3896 nRefArrayPos == std::numeric_limits<size_t>::max()))
3898 nRefArrayPos = nRefInList;
3912 while ((nErr == FormulaError::NONE) && aValIter.
GetNext(nVal, nErr))
3919 if (nRefArrayPos != std::numeric_limits<size_t>::max())
3922 MatOpFunc( nRefArrayPos, nMax);
3925 nMax = std::numeric_limits<double>::lowest();
3927 nRefArrayPos = std::numeric_limits<size_t>::max();
3954 SetError(FormulaError::IllegalParameter);
3959 SetError(FormulaError::IllegalParameter);
3966 if (nMax > std::numeric_limits<double>::lowest())
3970 MatOpFunc(
i, nMax);
3981 double fVecRes = xResMat->GetDouble(0,
i);
3982 if (fVecRes == -std::numeric_limits<double>::max())
3983 xResMat->PutDouble( 0.0, 0,
i);
3990 if (!std::isfinite(nVal))
3992 else if ( nVal > nMax )
4001 short nParamCount =
GetByte();
4004 struct ArrayRefListValue
4006 std::vector<double> mvValues;
4008 ArrayRefListValue() =
default;
4009 double get()
const {
return mfSum.
get(); }
4011 std::vector<ArrayRefListValue> vArrayValues;
4013 std::vector<double>
values;
4018 size_t nRefInList = 0;
4019 while (
nGlobalError == FormulaError::NONE && nParamCount-- > 0)
4046 else if (bTextAsZero && aCell.
hasString())
4055 if (
p &&
p->IsArrayResult())
4057 size_t nRefArrayPos = nRefInList;
4058 if (vArrayValues.empty())
4061 assert(nMatRows > 0);
4062 vArrayValues.resize(nMatRows);
4063 for (ArrayRefListValue & it : vArrayValues)
4073 for (ArrayRefListValue & it : vArrayValues)
4075 it.mvValues.insert( it.mvValues.end(),
values.begin(),
values.end());
4079 ArrayRefListValue& rArrayValue = vArrayValues[nRefArrayPos];
4087 rArrayValue.mvValues.push_back(fVal);
4088 rArrayValue.mfSum += fVal;
4090 while ((nErr == FormulaError::NONE) && aValIter.
GetNext(fVal, nErr));
4092 if ( nErr != FormulaError::NONE )
4097 std::vector<double>().swap(
values);
4115 while ((nErr == FormulaError::NONE) && aValIter.
GetNext(fVal, nErr));
4117 if ( nErr != FormulaError::NONE )
4132 pMat->GetDimensions(nC, nR);
4133 for (
SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++)
4135 for (
SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++)
4137 if (!pMat->IsStringOrEmpty(nMatCol,nMatRow))
4139 fVal= pMat->GetDouble(nMatCol,nMatRow);
4145 else if (bIgnoreErrVal)
4148 else if ( bTextAsZero )
4165 SetError(FormulaError::IllegalParameter);
4170 SetError(FormulaError::IllegalParameter);
4174 if (!vArrayValues.empty())
4179 for (
auto & it : vArrayValues)
4181 it.mvValues.insert( it.mvValues.end(),
values.begin(),
values.end());
4186 for (
SCSIZE r=0; r < nMatRows; ++r)
4188 ::std::vector<double>::size_type
n = vArrayValues[r].mvValues.size();
4190 xResMat->PutError( FormulaError::DivisionByZero, 0, r);
4193 ArrayRefListValue& rArrayValue = vArrayValues[r];
4195 const double vMean = rArrayValue.get() /
n;
4196 for (::std::vector<double>::size_type
i = 0;
i <
n;
i++)
4197 vSum += ::rtl::math::approxSub( rArrayValue.mvValues[
i], vMean) *
4198 ::rtl::math::approxSub( rArrayValue.mvValues[
i], vMean);
4199 xResMat->PutDouble( VarResult( vSum,
n), 0, r);
4206 ::std::vector<double>::size_type
n =
values.size();
4208 SetError( FormulaError::DivisionByZero);
4212 const double vMean = fSum.
get() /
n;
4213 for (::std::vector<double>::size_type
i = 0;
i <
n;
i++)
4214 vSum += ::rtl::math::approxSub(
values[
i], vMean) * ::rtl::math::approxSub(
values[
i], vMean);
4222 auto VarResult = [](
double fVal,
size_t nValCount )
4227 return fVal / (nValCount - 1);
4234 auto VarResult = [](
double fVal,
size_t nValCount )
4236 return sc::div( fVal, nValCount);
4244 auto VarResult = [](
double fVal,
size_t nValCount )
4249 return sqrt( fVal / (nValCount - 1));
4256 auto VarResult = [](
double fVal,
size_t nValCount )
4261 return sqrt( fVal / nValCount);
4293 while (nParamCount-- > 0)
4302 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
4303 nVal +=
static_cast<sal_uLong>(nTab2 - nTab1 + 1) *
4304 static_cast<sal_uLong>(nCol2 - nCol1 + 1);
4312 pMat->GetDimensions(nC, nR);
4334 SetError(FormulaError::IllegalParameter);
4350 while (nParamCount-- > 0)
4359 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
4360 nVal +=
static_cast<sal_uLong>(nTab2 - nTab1 + 1) *
4361 static_cast<sal_uLong>(nRow2 - nRow1 + 1);
4369 pMat->GetDimensions(nC, nR);
4391 SetError(FormulaError::IllegalParameter);
4401 if ( nParamCount == 0 )
4412 while (
nGlobalError == FormulaError::NONE && nParamCount-- > 0)
4422 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
4423 nVal +=
static_cast<sal_uLong>(nTab2 - nTab1 + 1);
4437 SetError( FormulaError::IllegalParameter );
4451 if (nParamCount == 0)
4467 bMayBeScalar =
false;
4471 bMayBeScalar =
true;
4473 if (!bMayBeScalar || nCols != 1 || nRows != 1)
4479 pResMat->PutDouble( nVal +
i,
static_cast<SCSIZE>(
i), 0);
4496 nVal =
static_cast<double>(nCol1 + 1);
4506 nVal =
static_cast<double>( aAbsRef.
Col() + 1 );
4521 PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
4536 static_cast<SCSIZE>(nCol2-nCol1+1), 1,
true);
4539 for (
SCCOL i = nCol1;
i <= nCol2;
i++)
4540 pResMat->PutDouble(
static_cast<double>(
i+1),
4541 static_cast<SCSIZE>(
i-nCol1), 0);
4547 nVal =
static_cast<double>(nCol1 + 1);
4551 SetError( FormulaError::IllegalParameter );
4564 if (nParamCount == 0)
4580 bMayBeScalar =
false;
4584 bMayBeScalar =
true;
4586 if (!bMayBeScalar || nCols != 1 || nRows != 1)
4592 pResMat->PutDouble( nVal +
i, 0,
static_cast<SCSIZE>(
i));
4609 nVal =
static_cast<double>(nRow1 + 1);
4619 nVal =
static_cast<double>( aAbsRef.
Row() + 1 );
4633 PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
4648 static_cast<SCSIZE>(nRow2-nRow1+1),
true);
4651 for (
SCROW i = nRow1;
i <= nRow2;
i++)
4652 pResMat->PutDouble(
static_cast<double>(
i+1), 0,
4653 static_cast<SCSIZE>(
i-nRow1));
4659 nVal =
static_cast<double>(nRow1 + 1);
4663 SetError( FormulaError::IllegalParameter );
4676 if ( nParamCount == 0 )
4688 SetError( FormulaError::IllegalArgument );
4708 PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
4713 SetError( FormulaError::IllegalParameter );
4723class VectorMatrixAccessor
4726 VectorMatrixAccessor(
const ScMatrix& rMat,
bool bColVec) :
4727 mrMat(rMat), mbColVec(bColVec) {}
4729 bool IsEmpty(
SCSIZE i)
const
4731 return mbColVec ? mrMat.IsEmpty(0, i) : mrMat.IsEmpty(i, 0);
4734 bool IsEmptyPath(
SCSIZE i)
const
4736 return mbColVec ? mrMat.IsEmptyPath(0, i) : mrMat.IsEmptyPath(i, 0);
4739 bool IsValue(
SCSIZE i)
const
4741 return mbColVec ? mrMat.IsValue(0, i) : mrMat.IsValue(i, 0);
4744 bool IsStringOrEmpty(
SCSIZE i)
const
4746 return mbColVec ? mrMat.IsStringOrEmpty(0, i) : mrMat.IsStringOrEmpty(i, 0);
4749 double GetDouble(
SCSIZE i)
const
4751 return mbColVec ? mrMat.GetDouble(0, i) : mrMat.GetDouble(i, 0);
4756 return mbColVec ? mrMat.GetString(0, i).getString() : mrMat.GetString(i, 0).getString();
4759 SCSIZE GetElementCount()
const
4762 mrMat.GetDimensions(nC, nR);
4763 return mbColVec ? nR : nC;
4774sal_Int32 lcl_CompareMatrix2Query(
4777 if (rMat.IsEmpty(i))
4788 if (rMat.IsValue(i))
4790 const double nVal1 = rMat.GetDouble(i);
4791 if (!std::isfinite(nVal1))
4807 return nVal1 < nVal2 ? -1 : 1;
4813 OUString aStr1 = rMat.GetString(i);
4821void lcl_GetLastMatch(
SCSIZE& rIndex,
const VectorMatrixAccessor& rMat,
4824 if (rMat.IsValue(rIndex))
4826 double nVal = rMat.GetDouble(rIndex);
4827 while (rIndex < nMatCount-1 && rMat.IsValue(rIndex+1) &&
4828 nVal == rMat.GetDouble(rIndex+1))
4832 else if (rMat.IsEmptyPath(rIndex))
4834 while (rIndex < nMatCount-1 && rMat.IsEmptyPath(rIndex+1))
4837 else if (rMat.IsEmpty(rIndex))
4839 while (rIndex < nMatCount-1 && rMat.IsEmpty(rIndex+1))
4842 else if (rMat.IsStringOrEmpty(rIndex))
4844 OUString
aStr( rMat.GetString(rIndex));
4845 while (rIndex < nMatCount-1 && rMat.IsStringOrEmpty(rIndex+1) &&
4846 aStr == rMat.GetString(rIndex+1))
4851 OSL_FAIL(
"lcl_GetLastMatch: unhandled matrix type");
4865 if (nParamCount == 3)
4886 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
4887 if (nTab1 != nTab2 || (nCol1 != nCol2 && nRow1 != nRow2))
4918 rParam.
nCol1 = nCol1;
4919 rParam.
nRow1 = nRow1;
4920 rParam.
nCol2 = nCol2;
4921 rParam.
nTab = nTab1;
4929 else if (fTyp > 0.0)
4983 rItem.
mfVal = pToken->GetDouble();
4988 rItem.
maString = pToken->GetString();
5022 pMatSrc->GetDimensions( nC, nR);
5023 if (nC > 1 && nR > 1)
5031 pMatSrc->SetErrorInterpreter(
nullptr);
5033 SCSIZE nMatCount = (nC == 1) ? nR : nC;
5034 VectorMatrixAccessor aMatAcc(*pMatSrc, nC == 1);
5043 if (lcl_CompareMatrix2Query(
i, aMatAcc, rEntry) == 0)
5057 SCSIZE nFirst = 0, nLast = nMatCount-1, nHitIndex = 0;
5058 for (
SCSIZE nLen = nLast-nFirst; nLen > 0; nLen = nLast-nFirst)
5060 SCSIZE nMid = nFirst + nLen/2;
5061 sal_Int32 nCmp = lcl_CompareMatrix2Query( nMid, aMatAcc, rEntry);
5065 lcl_GetLastMatch( nMid, aMatAcc, nMatCount);
5073 nHitIndex = bAscOrder ? nLast : nFirst;
5075 nHitIndex = bAscOrder ? nFirst : nLast;
5095 if (nHitIndex == nMatCount-1)
5097 sal_Int32 nCmp = lcl_CompareMatrix2Query( nHitIndex, aMatAcc, rEntry);
5098 if ((bAscOrder && nCmp <= 0) || (!bAscOrder && nCmp >= 0))
5125 rParam.
nRow2 = nRow2;
5127 ScAddress aResultPos( nCol1, nRow1, nTab1);
5133 nDelta = aResultPos.
Row() - nRow1;
5139 rParam.
nRow2 = nRow1;
5163 nDelta = nC - nCol1;
5224 if (!isCellContentEmpty(aCell))
5233 SCSIZE nRefListArrayPos = 0;
5234 size_t nRefInList = 0;
5235 while (nParam-- > 0)
5237 nRefListArrayPos = nRefInList;
5245 for (
bool bHas = aIter.
first(); bHas; bHas = aIter.
next())
5248 if (!isCellContentEmpty(rCell))
5253 xResMat->PutDouble( nMaxCount -
nCount, 0, nRefListArrayPos);
5265 SetError( FormulaError::IllegalParameter);
5269 xMat->GetDimensions( nC, nR);
5270 nMaxCount = nC * nR;
5275 nCount = xMat->Count(
true,
true,
true);
5279 default :
SetError(FormulaError::IllegalParameter);
break;
5298 bool bSumExtraRange = (nParamCount == 3);
5311 PopDoubleRef( nCol3, nRow3, nTab3, nColJunk, nRowJunk, nTabJunk );
5312 if ( nTabJunk != nTab3 )
5314 PushError( FormulaError::IllegalParameter);
5338 pSumExtraMatrix->PutDouble(pToken->GetDouble(), 0, 0);
5340 pSumExtraMatrix->PutString(pToken->GetString(), 0, 0);
5347 PushError( FormulaError::IllegalParameter);
5354 bool bIsString =
true;
5411 fVal = pToken->GetDouble();
5415 aString = pToken->GetString();
5428 double fCount = 0.0;
5433 SCSIZE nRefListArrayPos = 0;
5434 size_t nRefInList = 0;
5435 while (nParam-- > 0)
5450 SetError( FormulaError::IllegalParameter);
5454 nRefListArrayPos = nRefInList;
5457 aRange.
GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
5461 PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
5476 PushError( FormulaError::IllegalParameter);
5483 pQueryMatrix->GetDimensions( nC, nR);
5484 nCol2 =
static_cast<SCCOL>(nC - 1);
5485 nRow2 =
static_cast<SCROW>(nR - 1);
5490 SetError( FormulaError::IllegalParameter);
5492 if ( nTab1 != nTab2 )
5494 SetError( FormulaError::IllegalParameter);
5507 SCCOL nColDelta = nCol2 - nCol1;
5508 SCROW nRowDelta = nRow2 - nRow1;
5511 if (pSumExtraMatrix)
5514 pSumExtraMatrix->GetDimensions( nC, nR);
5515 nMaxCol =
static_cast<SCCOL>(nC - 1);
5516 nMaxRow =
static_cast<SCROW>(nR - 1);
5523 if (nCol3 + nColDelta > nMaxCol)
5525 SCCOL nNewDelta = nMaxCol - nCol3;
5526 nCol2 = nCol1 + nNewDelta;
5529 if (nRow3 + nRowDelta > nMaxRow)
5531 SCROW nNewDelta = nMaxRow - nRow3;
5532 nRow2 = nRow1 + nNewDelta;
5545 rParam.
nRow1 = nRow1;
5546 rParam.
nRow2 = nRow2;
5565 rParam.
nCol1 = nCol1;
5566 rParam.
nCol2 = nCol2;
5568 SCCOL nColDiff = nCol3 - nCol1;
5569 SCROW nRowDiff = nRow3 - nRow1;
5575 if (
nGlobalError != FormulaError::NONE || !pResultMatrix)
5577 SetError( FormulaError::IllegalParameter);
5580 if (pSumExtraMatrix)
5582 for (
SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
5584 for (
SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
5586 if (pResultMatrix->IsValue( nCol, nRow) &&
5587 pResultMatrix->GetDouble( nCol, nRow))
5589 SCSIZE nC = nCol + nColDiff;
5590 SCSIZE nR = nRow + nRowDiff;
5591 if (pSumExtraMatrix->IsValue( nC, nR))
5593 fVal = pSumExtraMatrix->GetDouble( nC, nR);
5603 for (
SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
5605 for (
SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
5607 if (pResultMatrix->GetDouble( nCol, nRow))
5609 aAdr.
SetCol( nCol + nColDiff);
5610 aAdr.
SetRow( nRow + nRowDiff);
5630 if (pSumExtraMatrix)
5636 if (pSumExtraMatrix->IsValue( nC, nR))
5638 fVal = pSumExtraMatrix->GetDouble( nC, nR);
5642 }
while ( aCellIter.
GetNext() );
5657 }
while ( aCellIter.
GetNext() );
5664 PushError( FormulaError::IllegalParameter);
5676 xResMat->PutDouble( fRes, 0, nRefListArrayPos);
5682 fRes = fCount = 0.0;
5709 bool bIsString =
true;
5764 double fCount = 0.0;
5769 SCSIZE nRefListArrayPos = 0;
5770 size_t nRefInList = 0;
5771 while (nParam-- > 0)
5784 nRefListArrayPos = nRefInList;
5791 aRange.
GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
5814 pQueryMatrix->GetDimensions( nC, nR);
5815 nCol2 =
static_cast<SCCOL>(nC - 1);
5816 nRow2 =
static_cast<SCROW>(nR - 1);
5825 if ( nTab1 != nTab2 )
5838 rParam.
nRow1 = nRow1;
5839 rParam.
nRow2 = nRow2;
5840 rParam.
nTab = nTab1;
5857 rParam.
nCol1 = nCol1;
5858 rParam.
nCol2 = nCol2;
5865 if (
nGlobalError != FormulaError::NONE || !pResultMatrix)
5871 SCSIZE nSize = pResultMatrix->GetElementCount();
5874 if (pResultMatrix->IsValue(
nIndex) &&
5875 pResultMatrix->GetDouble(
nIndex))
5901 xResMat->PutDouble( fCount, 0, nRefListArrayPos);
5914 sal_uInt8 nQueryCount = nParamCount / 2;
5921 vConditions.clear();
5924 SCCOL nStartColDiff = 0;
5925 SCCOL nEndColDiff = 0;
5926 SCROW nStartRowDiff = 0;
5927 SCROW nEndRowDiff = 0;
5928 bool bRangeReduce =
false;
5931 bool bHasDoubleRefCriteriaRanges =
true;
5936 for (sal_uInt16 nParamIdx = 2; nParamIdx < nParamCount; nParamIdx += 2 )
5941 bHasDoubleRefCriteriaRanges =
false;
5957 ScRange aSubRange = aMainRange;
5963 bRangeReduce = nStartColDiff || nStartRowDiff || nEndColDiff || nEndRowDiff;
5969 SCCOL nDimensionCols = 0;
5970 SCROW nDimensionRows = 0;
5972 std::vector<std::vector<sal_uInt8>> vRefArrayConditions;
5974 while (nParamCount > 1 &&
nGlobalError == FormulaError::NONE)
5979 bool bIsString =
true;
6036 fVal = pToken->GetDouble();
6040 aString = pToken->GetString();
6058 short nParam = nParamCount;
6059 size_t nRefInList = 0;
6060 size_t nRefArrayPos = std::numeric_limits<size_t>::max();
6068 while (nParam-- == nParamCount)
6076 if (
p &&
p->IsArrayResult())
6078 if (nRefInList == 0)
6080 if (vRefArrayConditions.empty())
6081 vRefArrayConditions.resize( nRefArrayRows);
6082 if (!vConditions.empty())
6087 for (
auto & rVec : vRefArrayConditions)
6093 assert(rVec.size() == vConditions.size());
6094 for (
size_t i=0,
n = rVec.size();
i <
n; ++
i)
6096 rVec[
i] += vConditions[
i];
6101 std::for_each( vConditions.begin(), vConditions.end(),
6105 nRefArrayPos = nRefInList;
6110 aRange.
GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
6115 PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
6130 PushError( FormulaError::IllegalParameter);
6137 pQueryMatrix->GetDimensions( nC, nR);
6138 nCol2 =
static_cast<SCCOL>(nC - 1);
6139 nRow2 =
static_cast<SCROW>(nR - 1);
6144 PushError( FormulaError::IllegalParameter);
6147 if ( nTab1 != nTab2 )
6149 PushError( FormulaError::IllegalArgument);
6172 const bool isCountIfs = (nParamCount % 2) == 0;
6175 bRangeReduce =
false;
6177 assert(vRefArrayConditions.empty());
6178 if(!vConditions.empty())
6180 std::vector<sal_uInt8> newConditions;
6181 SCCOL newDimensionCols = nCol2 - nCol1 + 1;
6182 SCROW newDimensionRows = nRow2 - nRow1 + 1;
6183 newConditions.reserve( newDimensionCols * newDimensionRows );
6185 for(;
col < nCol1 + nStartColDiff; ++
col)
6186 newConditions.insert( newConditions.end(), newDimensionRows, 0 );
6187 for(;
col <= nCol2 - nStartColDiff; ++
col)
6189 newConditions.insert( newConditions.end(), nStartRowDiff, 0 );
6190 SCCOL oldCol =
col - ( nCol1 + nStartColDiff );
6191 size_t nIndex = oldCol * nDimensionRows;
6192 if (
nIndex < vConditions.size())
6194 auto it = vConditions.begin() +
nIndex;
6195 newConditions.insert( newConditions.end(), it, it + nDimensionRows );
6198 newConditions.insert( newConditions.end(), nDimensionRows, 0 );
6199 newConditions.insert( newConditions.end(), -nEndRowDiff, 0 );
6201 for(;
col <= nCol2; ++
col)
6202 newConditions.insert( newConditions.end(), newDimensionRows, 0 );
6203 assert( newConditions.size() ==
o3tl::make_unsigned( newDimensionCols * newDimensionRows ));
6204 vConditions = std::move( newConditions );
6205 nDimensionCols = newDimensionCols;
6206 nDimensionRows = newDimensionRows;
6216 PushError ( FormulaError::IllegalArgument);
6219 nCol1 += nStartColDiff;
6220 nRow1 += nStartRowDiff;
6222 nCol2 += nEndColDiff;
6223 nRow2 += nEndRowDiff;
6227 if (!nDimensionCols)
6228 nDimensionCols = nCol2 - nCol1 + 1;
6229 if (!nDimensionRows)
6230 nDimensionRows = nRow2 - nRow1 + 1;
6231 if ((nDimensionCols != (nCol2 - nCol1 + 1)) || (nDimensionRows != (nRow2 - nRow1 + 1)))
6233 PushError ( FormulaError::IllegalArgument);
6245 if (vConditions.empty())
6246 vConditions.resize( nDimensionCols * nDimensionRows, 0);
6248 rParam.
nRow1 = nRow1;
6249 rParam.
nRow2 = nRow2;
6250 rParam.
nCol1 = nCol1;
6251 rParam.
nCol2 = nCol2;
6253 SCCOL nColDiff = -nCol1;
6254 SCROW nRowDiff = -nRow1;
6260 if (
nGlobalError != FormulaError::NONE || !pResultMatrix)
6262 PushError( FormulaError::IllegalParameter);
6267 std::vector<double> aResValues;
6268 pResultMatrix->GetDoubleArray(aResValues);
6269 if (vConditions.size() != aResValues.size())
6271 PushError( FormulaError::IllegalParameter);
6275 std::vector<double>::const_iterator itThisRes = aResValues.begin();
6276 for (
auto& rCondition : vConditions)
6278 rCondition += *itThisRes;
6294 size_t nC = aCellIter.
GetCol() + nColDiff;
6295 size_t nR = aCellIter.
GetRow() + nRowDiff;
6296 ++vConditions[nC * nDimensionRows + nR];
6297 }
while ( aCellIter.
GetNext() );
6309 size_t nC = aCellIter.
GetCol() + nColDiff;
6310 size_t nR = aCellIter.
GetRow() + nRowDiff;
6311 ++vConditions[nC * nDimensionRows + nR];
6312 }
while ( aCellIter.
GetNext() );
6316 if (nRefArrayPos != std::numeric_limits<size_t>::max())
6319 std::vector<sal_uInt8>& rVec = vRefArrayConditions[nRefArrayPos];
6324 assert(rVec.size() == vConditions.size());
6325 for (
size_t i=0,
n = rVec.size();
i <
n; ++
i)
6327 rVec[
i] += vConditions[
i];
6333 if (nRefInList == 0)
6334 std::vector<sal_uInt8>().swap( vConditions);
6336 std::for_each( vConditions.begin(), vConditions.end(), [](
sal_uInt8 & r){ r = 0; } );
6342 if (!vRefArrayConditions.empty() && !vConditions.empty())
6345 for (
auto & rVec : vRefArrayConditions)
6351 assert(rVec.size() == vConditions.size());
6352 for (
size_t i=0,
n = rVec.size();
i <
n; ++
i)
6354 rVec[
i] += vConditions[
i];
6370 if (nParamCount == 1)
6372 short nParam = nParamCount;
6373 size_t nRefInList = 0;
6374 size_t nRefArrayPos = std::numeric_limits<size_t>::max();
6375 bool bRefArrayMain =
false;
6376 while (nParam-- == nParamCount)
6378 SCCOL nMainCol1 = 0;
6379 SCROW nMainRow1 = 0;
6380 SCTAB nMainTab1 = 0;
6381 SCCOL nMainCol2 = 0;
6382 SCROW nMainRow2 = 0;
6383 SCTAB nMainTab2 = 0;
6390 if (
p &&
p->IsArrayResult())
6392 if (vRefArrayConditions.empty())
6397 vRefArrayConditions.resize( nRefArrayRows);
6398 for (
auto & rVec : vRefArrayConditions)
6404 bRefArrayMain =
true;
6405 nRefArrayPos = nRefInList;
6409 aRange.
GetVars( nMainCol1, nMainRow1, nMainTab1, nMainCol2, nMainRow2, nMainTab2);
6413 PopDoubleRef( nMainCol1, nMainRow1, nMainTab1, nMainCol2, nMainRow2, nMainTab2 );
6417 nMainCol2 = nMainCol1;
6418 nMainRow2 = nMainRow1;
6419 nMainTab2 = nMainTab1;
6428 PushError( FormulaError::IllegalParameter);
6435 pMainMatrix->GetDimensions( nC, nR);
6436 nMainCol2 =
static_cast<SCCOL>(nC - 1);
6437 nMainRow2 =
static_cast<SCROW>(nR - 1);
6444 nMainCol1 = nMainCol2 = 0;
6445 nMainRow1 = nMainRow2 = 0;
6446 nMainTab1 = nMainTab2 = 0;
6447 pMainMatrix->PutDouble(
GetDouble(), 0, 0);
6451 nMainCol1 = nMainCol2 = 0;
6452 nMainRow1 = nMainRow2 = 0;
6453 nMainTab1 = nMainTab2 = 0;
6454 pMainMatrix->PutString(
GetString(), 0, 0);
6458 PushError( FormulaError::IllegalParameter);
6461 if ( nMainTab1 != nMainTab2 )
6463 PushError( FormulaError::IllegalArgument);
6469 nMainCol1 += nStartColDiff;
6470 nMainRow1 += nStartRowDiff;
6472 nMainCol2 += nEndColDiff;
6473 nMainRow2 += nEndRowDiff;
6477 if ((nDimensionCols != (nMainCol2 - nMainCol1 + 1)) || (nDimensionRows != (nMainRow2 - nMainRow1 + 1)))
6479 PushError ( FormulaError::IllegalArgument);
6496 size_t nRefArrayMainPos = (bRefArrayMain ? nRefArrayPos :
6497 (vRefArrayConditions.empty() ? std::numeric_limits<size_t>::max() : 0));
6498 const bool bAppliedArray = (!bRefArrayMain && nRefArrayMainPos == 0);
6500 if (nRefArrayMainPos == 0)
6501 xResMat =
GetNewMat( 1, nRefArrayRows,
true );
6505 std::vector<double> aMainValues;
6506 pMainMatrix->GetDoubleArray(aMainValues,
false);
6510 if (nRefArrayMainPos < vRefArrayConditions.size())
6511 vConditions = vRefArrayConditions[nRefArrayMainPos];
6513 if (vConditions.size() != aMainValues.size())
6515 PushError( FormulaError::IllegalArgument);
6519 std::vector<sal_uInt8>::const_iterator itRes = vConditions.begin(), itResEnd = vConditions.end();
6520 std::vector<double>::const_iterator itMain = aMainValues.begin();
6521 for (; itRes != itResEnd; ++itRes, ++itMain)
6523 if (*itRes != nQueryCount)
6532 if ( aRes.
mfMin > fVal )
6534 if ( aRes.
mfMax < fVal )
6537 if (nRefArrayMainPos != std::numeric_limits<size_t>::max())
6539 xResMat->PutDouble( ResultFunc( aRes), 0, nRefArrayMainPos);
6543 while (bAppliedArray && ++nRefArrayMainPos < nRefArrayRows);
6548 aAdr.
SetTab( nMainTab1 );
6551 if (nRefArrayMainPos < vRefArrayConditions.size())
6552 vConditions = vRefArrayConditions[nRefArrayMainPos];
6554 SAL_WARN_IF(nDimensionCols && nDimensionRows && vConditions.empty(),
"sc",
"ScInterpreter::IterateParametersIfs vConditions is empty");
6555 if (!vConditions.empty())
6557 std::vector<sal_uInt8>::const_iterator itRes = vConditions.begin();
6558 for (
SCCOL nCol = 0; nCol < nDimensionCols; ++nCol)
6560 for (
SCROW nRow = 0; nRow < nDimensionRows; ++nRow, ++itRes)
6562 if (*itRes == nQueryCount)
6564 aAdr.
SetCol( nCol + nMainCol1);
6565 aAdr.
SetRow( nRow + nMainRow1);
6572 if ( aRes.
mfMin > fVal )
6574 if ( aRes.
mfMax < fVal )
6581 if (nRefArrayMainPos != std::numeric_limits<size_t>::max())
6583 xResMat->PutDouble( ResultFunc( aRes), 0, nRefArrayMainPos);
6587 while (bAppliedArray && ++nRefArrayMainPos < nRefArrayRows);
6594 if (vRefArrayConditions.empty())
6600 static_assert(
sizeof(vConditions[0]) == 1);
6606 if(
pos ==
nullptr )
6614 xResMat =
GetNewMat( 1, nRefArrayRows,
true );
6615 for (
size_t i=0,
n = vRefArrayConditions.size();
i <
n; ++
i)
6617 double fCount = 0.0;
6618 for (
auto const & rCond : vRefArrayConditions[
i])
6620 if (rCond == nQueryCount)
6623 xResMat->PutDouble( fCount, 0,
i);
6639 if (nParamCount < 3 || (nParamCount % 2 != 1))
6641 PushError( FormulaError::ParameterExpected);
6647 return rRes.mfSum.get();
6656 if (nParamCount < 3 || (nParamCount % 2 != 1))
6658 PushError( FormulaError::ParameterExpected);
6664 return sc::div( rRes.mfSum.get(), rRes.mfCount);
6673 if (nParamCount < 2 || (nParamCount % 2 != 0))
6675 PushError( FormulaError::ParameterExpected);
6681 return rRes.mfCount;
6690 if (nParamCount < 3 || (nParamCount % 2 != 1))
6692 PushError( FormulaError::ParameterExpected);
6698 return (rRes.mfMin < std::numeric_limits<double>::max()) ? rRes.mfMin : 0.0;
6708 if (nParamCount < 3 || (nParamCount % 2 != 1))
6710 PushError( FormulaError::ParameterExpected);
6716 return (rRes.mfMax > std::numeric_limits<double>::lowest()) ? rRes.mfMax : 0.0;
6727 ScMatrixRef pDataMat =
nullptr, pResMat =
nullptr;
6728 SCCOL nCol1 = 0, nCol2 = 0, nResCol1 = 0, nResCol2 = 0;
6729 SCROW nRow1 = 0, nRow2 = 0, nResRow1 = 0, nResRow2 = 0;
6730 SCTAB nTab1 = 0, nResTab = 0;
6732 bool bVertical =
true;
6735 double fResVal = 0.0;
6739 if (nParamCount == 3)
6742 switch (eResArrayType)
6748 nResCol2, nResRow2, nTabJunk);
6749 if (nResTab != nTabJunk ||
6750 ((nResRow2 - nResRow1) > 0 && (nResCol2 - nResCol1) > 0))
6760 nResCol2 = nResCol1;
6761 nResRow2 = nResRow1;
6774 pResMat->GetDimensions(nC, nR);
6775 if (nC != 1 && nR != 1)
6796 double fDataVal = 0.0;
6799 bool bValueData =
false;
6805 switch (eDataArrayType)
6810 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTabJunk);
6811 if (nTab1 != nTabJunk)
6816 bVertical = (nRow2 - nRow1) >= (nCol2 - nCol1);
6817 nLenMajor = bVertical ? nRow2 - nRow1 + 1 : nCol2 - nCol1 + 1;
6832 pDataMat->GetDimensions(nC, nR);
6833 bVertical = (nR >= nC);
6834 nLenMajor = bVertical ? nR : nC;
6855 SetError( FormulaError::NotAvailable);
6867 SetError( FormulaError::IllegalParameter);
6892 bool bFound =
false;
6900 bFound = (fDataVal <= rItem.
mfVal);
6918 if (pResMat->IsValue( 0, 0 ))
6923 else if (nParamCount == 3)
6925 switch (eResArrayType)
6938 assert(!
"ScInterpreter::ScLookup: unhandled eResArrayType, single value data");
6944 switch (eDataArrayType)
6956 assert(!
"ScInterpreter::ScLookup: unhandled eDataArrayType, single value data");
6970 bool bFound =
false;
6973 pDataMat->GetDimensions(nC, nR);
6976 pDataMat->SetErrorInterpreter(
nullptr);
6995 const bool bOmitErrorValues = (eDataArrayType ==
svMatrix && pDataMat->IsNumeric());
6999 std::vector<SCCOLROW> vIndex;
7000 if (bOmitErrorValues)
7002 std::vector<double> vArray;
7003 VectorMatrixAccessor aMatAcc(*pDataMat, bVertical);
7007 const double fVal = aMatAcc.GetDouble(
i);
7008 if (std::isfinite(fVal))
7010 vArray.push_back(fVal);
7011 vIndex.push_back(
i);
7019 const size_t nElems = vArray.size();
7023 pDataMat2 = pDataMat;
7024 std::vector<SCCOLROW>().swap( vIndex);
7032 pTempMat->PutDoubleVector( vArray, 0, 0);
7033 pDataMat2 = pTempMat;
7038 for (
size_t i=0;
i < nElems; ++
i)
7039 pTempMat->PutDouble( vArray[
i],
i, 0);
7040 pDataMat2 = pTempMat;
7047 pDataMat2 = pDataMat;
7051 pDataMat2->SetErrorInterpreter(
nullptr);
7053 VectorMatrixAccessor aMatAcc2(*pDataMat2, bVertical);
7060 SCSIZE nFirst = 0, nLast = nLenMajor-1;
7061 for (
SCSIZE nLen = nLast-nFirst; nLen > 0; nLen = nLast-nFirst)
7063 SCSIZE nMid = nFirst + nLen/2;
7064 sal_Int32 nCmp = lcl_CompareMatrix2Query( nMid, aMatAcc2, rEntry);
7068 lcl_GetLastMatch( nMid, aMatAcc2, nLenMajor);
7076 nDelta = nCmp < 0 ? nLast - 1 : nFirst - 1;
7078 bFound = (nDelta >= 0);
7088 if (nDelta ==
static_cast<SCCOLROW>(nLenMajor-2))
7090 sal_Int32 nCmp = lcl_CompareMatrix2Query(nDelta+1, aMatAcc2, rEntry);
7099 else if (nDelta > 0)
7111 if (!vIndex.empty())
7112 nDelta = vIndex[nDelta];
7114 VectorMatrixAccessor aMatAcc(*pDataMat, bVertical);
7116 SCSIZE n = aMatAcc.GetElementCount();
7120 if (bByString == aMatAcc.IsValue(
i))
7134 VectorMatrixAccessor aResMatAcc(*pResMat, bVertical);
7142 if (aResMatAcc.IsValue(nDelta))
7147 else if (nParamCount == 3)
7151 switch (eResArrayType)
7161 bool bResVertical = (nResRow2 - nResRow1) > 0;
7164 SCROW nTempRow =
static_cast<SCROW>(nResRow1 + nDelta);
7175 SCCOL nTempCol =
static_cast<SCCOL>(nResCol1 + nDelta);
7194 switch (eResArrayType)
7209 assert(!
"ScInterpreter::ScLookup: unhandled eResArrayType, array search");
7217 pDataMat->SetErrorInterpreter(
this);
7220 if (pDataMat->IsValue(nC-1, nDelta))
7221 PushDouble(pDataMat->GetDouble(nC-1, nDelta));
7223 PushString(pDataMat->GetString(nC-1, nDelta));
7227 if (pDataMat->IsValue(nDelta, nR-1))
7228 PushDouble(pDataMat->GetDouble(nDelta, nR-1));
7230 PushString(pDataMat->GetString(nDelta, nR-1));
7239 aParam.
nCol1 = nCol1;
7240 aParam.
nRow1 = nRow1;
7241 aParam.
nCol2 = bVertical ? nCol1 : nCol2;
7242 aParam.
nRow2 = bVertical ? nRow2 : nRow1;
7243 aParam.
bByRow = bVertical;
7268 VectorMatrixAccessor aResMatAcc(*pResMat, bVertical);
7276 if (aResMatAcc.IsValue(nDelta))
7281 else if (nParamCount == 3)
7285 switch (eResArrayType)
7295 bool bResVertical = (nResRow2 - nResRow1) > 0;
7298 SCROW nTempRow =
static_cast<SCROW>(nResRow1 + nDelta);
7309 SCCOL nTempCol =
static_cast<SCCOL>(nResCol1 + nDelta);
7328 switch (eResArrayType)
7343 assert(!
"ScInterpreter::ScLookup: unhandled eResArrayType, range search");
7356 SCROW nTempRow =
static_cast<SCROW>(nRow1 + nDelta);
7367 SCCOL nTempCol =
static_cast<SCCOL>(nCol1 + nDelta);
7392 bool bSorted =
true;
7393 if (nParamCount == 4)
7397 double fIndex = ::rtl::math::approxFloor(
GetDouble() ) - 1.0;
7412 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
7430 pMat->GetDimensions(nC, nR);
7443 if ( fIndex < 0.0 || (bHLookup ? (pMat ? (fIndex >= nR) : (fIndex+nRow1 > nRow2)) : (pMat ? (fIndex >= nC) : (fIndex+nCol1 > nCol2)) ) )
7455 nSpIndex = sal::static_int_cast<SCCOL>( nSpIndex + nCol1 );
7465 aParam.
nCol1 = nCol1;
7466 aParam.
nRow1 = nRow1;
7469 aParam.
nCol2 = nCol2;
7470 aParam.
nRow2 = nRow1;
7475 aParam.
nCol2 = nCol1;
7476 aParam.
nRow2 = nRow2;
7477 aParam.
nTab = nTab1;
7492 SCSIZE nMatCount = bHLookup ? nC : nR;
7505 if (bHLookup ? pMat->IsStringOrEmpty(
i, 0) : pMat->IsStringOrEmpty(0,
i))
7509 bHLookup ? pMat->GetString(
i,0).getString() : pMat->GetString(0,
i).getString(), aParamStr.
getString());
7525 if (pMat->IsStringOrEmpty(
i, 0))
7537 nDelta = pMat->MatchStringInColumns(aParamStr, 0, 0);
7548 if (!(bHLookup ? pMat->IsStringOrEmpty(
i, 0) : pMat->IsStringOrEmpty(0,
i)))
7550 if ((bHLookup ? pMat->GetDouble(
i,0) : pMat->GetDouble(0,
i)) <= rItem.
mfVal)
7563 if (! pMat->IsStringOrEmpty(
i, 0) )
7565 if ( pMat->GetDouble(
i,0) == rItem.
mfVal)
7575 nDelta = pMat->MatchDoubleInColumns(rItem.
mfVal, 0, 0);
7588 nY =
static_cast<SCSIZE>(nZIndex);
7592 assert( nX < nC && nY < nR );
7595 if (pMat->IsStringOrEmpty( nX, nY))
7596 PushString(pMat->GetString( nX, nY).getString());
7610 bool bFound =
false;
7628 nCol = aCellIter.
GetCol();
7634 ScAddress aResultPos( nCol1, nRow1, nTab1);
7636 nRow = aResultPos.
Row();
7733 if (
nGlobalError != FormulaError::NONE || nFunc < 1 || nFunc > 11 )
7737 cPar = nParamCount - 1;
7779 if (
nGlobalError != FormulaError::NONE || nFunc < 1 || nFunc > 19 )
7821 cPar = nParamCount - 2;
7859 bool bAllowMissingField =
false;
7860 if ( rMissingField )
7862 bAllowMissingField =
true;
7863 rMissingField =
false;
7876 bool bRangeFake =
false;
7880 nVal = ::rtl::math::approxFloor(
GetDouble() );
7881 if ( bAllowMissingField && nVal == 0.0 )
7882 rMissingField =
true;
7903 if ( bAllowMissingField )
7911 SetError( FormulaError::IllegalParameter );
7916 if ( bAllowMissingField )
7917 rMissingField =
true;
7919 SetError( FormulaError::IllegalParameter );
7923 SetError( FormulaError::IllegalParameter );
7937 if (pDBRef->isRangeEqual(aMissingRange))
7938 rMissingField =
true;
7940 SetError( FormulaError::IllegalParameter );
7946 SCCOL nField = pDBRef->getFirstFieldColumn();
7950 nField = pDBRef->findFieldColumn(
static_cast<SCCOL>(nVal));
7954 nField = pDBRef->findFieldColumn(
aStr.getString(), &nErr);
7961 unique_ptr<ScDBQueryParamBase> pParam( pDBRef->createQueryParam(pQueryRef.get()) );
7968 if ( rMissingField )
7969 nField =
static_cast<SCCOL>(pParam->GetEntry(0).nField);
7970 pParam->mnField = nField;
8000 bool bMissingField =
false;
8001 unique_ptr<ScDBQueryParamBase> pQueryParam(
GetDBParams(bMissingField) );
8004 if (!pQueryParam->IsValidFieldIndex())
8011 if ( aValIter.
GetFirst(aValue) && aValue.
mnError == FormulaError::NONE )
8045 while ( aValIter.
GetNext(aValue) && aValue.
mnError == FormulaError::NONE );
8050 SetError( FormulaError::IllegalParameter);
8054 case ifSUM: fRes = fErg.
get();
break;
8069 bool bMissingField =
true;
8070 unique_ptr<ScDBQueryParamBase> pQueryParam(
GetDBParams(bMissingField) );
8085 p->nCol2 =
p->nCol1;
8090 p->nCol1 =
p->nCol2 =
p->mnField;
8097 }
while ( aCellIter.
GetNext() );
8102 if (!pQueryParam->IsValidFieldIndex())
8109 if ( aValIter.
GetFirst(aValue) && aValue.
mnError == FormulaError::NONE )
8115 while ( aValIter.
GetNext(aValue) && aValue.
mnError == FormulaError::NONE );
8127 bool bMissingField =
true;
8128 unique_ptr<ScDBQueryParamBase> pQueryParam(
GetDBParams(bMissingField) );
8131 if (!pQueryParam->IsValidFieldIndex())
8137 pQueryParam->mbSkipString =
false;
8140 if ( aValIter.
GetFirst(aValue) && aValue.
mnError == FormulaError::NONE )
8146 while ( aValIter.
GetNext(aValue) && aValue.
mnError == FormulaError::NONE );
8177 std::vector<double>
values;
8182 bool bMissingField =
false;
8183 unique_ptr<ScDBQueryParamBase> pQueryParam(
GetDBParams(bMissingField) );
8186 if (!pQueryParam->IsValidFieldIndex())
8193 if (aValIter.
GetFirst(aValue) && aValue.
mnError == FormulaError::NONE)
8201 while ((aValue.
mnError == FormulaError::NONE) && aValIter.
GetNext(aValue));
8206 SetError( FormulaError::IllegalParameter);
8208 double vMean = fSum.
get() /
values.size();
8211 vSum += (
v - vMean) * (
v - vMean);
8218 double fVal, fCount;
8225 double fVal, fCount;
8232 double fVal, fCount;
8239 double fVal, fCount;
8258 if (eConv == FormulaGrammar::CONV_UNSPECIFIED)
8264 bool bTryXlA1 = (eConv == FormulaGrammar::CONV_A1_XL_A1);
8266 if (nParamCount == 2 && 0.0 ==
GetDouble() )
8269 eConv = FormulaGrammar::CONV_XL_R1C1;
8274 const OUString & sRefStr = sSharedRefStr.
getString();
8275 if (sRefStr.isEmpty())
8286 bool bTableRefNamed =
false;
8287 sal_Int32 nTableRefNamedIndex = -1;
8288 OUString sTabRefStr;
8299 pData->ValidateTabRefs();
8307 sTabRefStr =
pData->GetSymbol();
8339 pData->GetArea( aRange);
8344 if (
pData->HasHeader())
8346 if (
pData->HasTotals())
8367 if ( !bTableRefNamed &&
8370 aRefAd2, aDetailsXlA1, &aExtInfo) ) ) )
8376 aRefAd.
Col(), aRefAd.
Row(), aRefAd.
Tab(),
8377 aRefAd2.
Col(), aRefAd2.
Row(), aRefAd2.
Tab());
8382 else if ( !bTableRefNamed &&
8385 aDetailsXlA1, &aExtInfo) ) ) )
8401 sal_Int32
nIndex = bTableRefNamed ? nTableRefNamedIndex : -1;
8402 bool bTableRef = bTableRefNamed;
8403 if (!bTableRefNamed)
8405 bool bExternalName =
false;
8411 if (sRefStr[0] ==
'\'')
8415 if (bTryXlA1 || eConv == FormulaGrammar::CONV_OOO)
8420 bExternalName =
true;
8421 eConv = FormulaGrammar::CONV_OOO;
8424 if (!bExternalName && (bTryXlA1 || eConv != FormulaGrammar::CONV_OOO))
8429 bExternalName =
true;
8435 if (bExternalName || bTableRef)
8441 std::unique_ptr<ScTokenArray> pTokArr( aComp.
CompileString(bTableRefNamed ? sTabRefStr : sRefStr));
8443 if (pTokArr->GetCodeError() != FormulaError::NONE || !pTokArr->GetLen())
8461 if (pTokArr->GetCodeLen() != 1)
8468 switch (xTok->GetType())
8497 if( nParamCount >= 5 )
8502 eConv = FormulaGrammar::CONV_XL_R1C1;
8509 if (eForceConv == FormulaGrammar::CONV_UNSPECIFIED)
8511 if (eForceConv == FormulaGrammar::CONV_XL_A1 || eForceConv == FormulaGrammar::CONV_XL_R1C1)
8512 eConv = FormulaGrammar::CONV_XL_A1;
8516 if( nParamCount >= 3 )
8539 if( eConv == FormulaGrammar::CONV_XL_R1C1 )
8559 OUString aRefStr(aAdr.
Format(nFlags, &
mrDoc, aDetails));
8561 if( nParamCount >= 5 && !sTabStr.isEmpty() )
8564 if (eConv == FormulaGrammar::CONV_OOO)
8570 if (sTabStr[
nPos+1] ==
'$')
8572 aDoc = sTabStr.copy( 0,
nPos+1);
8573 sTabStr = sTabStr.copy(
nPos+1);
8578 if (sTabStr[0] !=
'\'' || !sTabStr.endsWith(
"'"))
8580 if (!aDoc.isEmpty())
8581 sTabStr = aDoc + sTabStr;
8582 sTabStr += (eConv == FormulaGrammar::CONV_XL_R1C1 || eConv == FormulaGrammar::CONV_XL_A1) ?
8583 std::u16string_view(
u"!") : std::u16string_view(
u".");
8597 bool bNewWidth =
false;
8598 bool bNewHeight =
false;
8599 sal_Int32 nColNew = 1, nRowNew = 1;
8600 if (nParamCount == 5)
8610 if (nParamCount >= 4)
8627 if (nColNew <= 0 || nRowNew <= 0)
8643 if (!bNewWidth && !bNewHeight)
8673 nCol1 = aAbsRef.
Col();
8674 nRow1 = aAbsRef.
Row();
8675 nTab1 = aAbsRef.
Tab();
8677 if (!bNewWidth && !bNewHeight)
8703 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
8705 nColNew = nCol2 - nCol1 + 1;
8707 nRowNew = nRow2 - nRow1 + 1;
8733 nColNew = nCol2 - nCol1 + 1;
8735 nRowNew = nRow2 - nRow1 + 1;
8763 if (nParamCount == 4)
8768 if (nParamCount >= 3)
8775 bColMissing =
false;
8778 if (nParamCount >= 2)
8783 nAreaCount = (
sp ?
pStack[
sp-1]->GetRefList()->size() : 0);
8786 if (
nGlobalError != FormulaError::NONE || nAreaCount == 0 ||
static_cast<size_t>(nArea) > nAreaCount)
8791 else if (nArea < 1 || nCol < 0 || nRow < 0)
8803 SetError(FormulaError::IllegalArgument);
8804 sal_uInt16 nOldSp =
sp;
8809 pMat->GetDimensions(nC, nR);
8826 const bool bRowVectorSpecial = (nParamCount == 2 || bColMissing);
8827 const bool bRowVectorElement = (nR == 1 && (nCol != 0 || (bRowVectorSpecial && nRow != 0)));
8828 const bool bVectorElement = (bRowVectorElement || (nC == 1 && nRow != 0));
8830 if (nC == 0 || nR == 0 ||
8834 else if (nCol == 0 && nRow == 0)
8836 else if (bVectorElement)
8839 SCSIZE nElement, nOtherDimension;
8840 if (bRowVectorElement && !bRowVectorSpecial)
8851 if (nElement == 0 || nElement > nC * nR || nOtherDimension > 1)
8856 if (pMat->IsStringOrEmpty( nElement))
8857 PushString( pMat->GetString(nElement).getString());
8869 if (!pMat->IsStringOrEmpty(
i, nRowMinus1))
8870 pResMat->PutDouble(pMat->GetDouble(
i,
8873 pResMat->PutString(pMat->GetString(
i, nRowMinus1),
i, 0);
8887 if (!pMat->IsStringOrEmpty(nColMinus1,
i))
8888 pResMat->PutDouble(pMat->GetDouble(nColMinus1,
8891 pResMat->PutString(pMat->GetString(nColMinus1,
i),
i);
8899 if (!pMat->IsStringOrEmpty(
static_cast<SCSIZE>(nCol-1),
8900 static_cast<SCSIZE>(nRow-1)))
8902 static_cast<SCSIZE>(nCol-1),
8903 static_cast<SCSIZE>(nRow-1)));
8906 static_cast<SCSIZE>(nCol-1),
8907 static_cast<SCSIZE>(nRow-1)).getString());
8918 if (nCol > 1 || nRow > 1)
8933 bool bRowArray =
false;
8944 aRange.
GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
8945 if ( nParamCount == 2 && nRow1 == nRow2 )
8950 PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
8951 if ( nParamCount == 2 && nRow1 == nRow2 )
8954 if ( nTab1 != nTab2 ||
8955 (nCol > 0 && nCol1+nCol-1 > nCol2) ||
8956 (nRow > 0 && nRow1+nRow-1 > nRow2 && !bRowArray ) ||
8957 ( nRow > nCol2 - nCol1 + 1 && bRowArray ))
8959 else if (nCol == 0 && nRow == 0)
8961 if ( nCol1 == nCol2 && nRow1 == nRow2 )
8968 if ( nRow1 == nRow2 )
8972 nCol1+nCol-1, nRow2, nTab1 );
8976 if ( nCol1 == nCol2 )
8978 else if ( bRowArray )
8980 nCol =
static_cast<SCCOL>(nRow);
8986 nCol2, nRow1+nRow-1, nTab1);
9004 while (
nGlobalError == FormulaError::NONE && nParamCount-- > 1)
9038 nCount += xT->GetRefList()->size();
9042 SetError( FormulaError::IllegalParameter);
9055 if (nParamCount == 2)
9057 fDec = ::rtl::math::approxFloor(
GetDouble());
9058 if (fDec < -15.0 || fDec > 15.0)
9069 fFac = pow(
double(10), fDec );
9073 fVal = ceil(fVal*fFac-0.5)/fFac;
9075 fVal = floor(fVal*fFac+0.5)/fFac;
9076 const Color* pColor =
nullptr;
9080 SvNumFormatType::CURRENCY,
9089 static_cast<sal_uInt16
>(fDec));
9095 SetError(FormulaError::IllegalArgument);
9117 sal_Int32 nLen = aOldStr.getLength();
9118 if (
nPos > nLen + 1)
9124 while ( nIdx < nLen && nPos > nCnt + 1 )
9126 aOldStr.iterateCodePoints( &nIdx );
9129 sal_Int32 nStart = nIdx;
9130 while ( nIdx < nLen && nPos + nCount - 1 > nCnt )
9132 aOldStr.iterateCodePoints( &nIdx );
9136 aOldStr = aOldStr.replaceAt( nStart, nIdx - nStart, aNewStr );
9150 if (nParamCount == 3)
9154 if (nParamCount >= 2)
9157 if (fDec < -15.0 || fDec > 15.0)
9168 fFac = pow(
double(10), fDec );
9172 fVal = ceil(fVal*fFac-0.5)/fFac;
9174 fVal = floor(fVal*fFac+0.5)/fFac;
9175 const Color* pColor =
nullptr;
9179 SvNumFormatType::NUMBER,
9186 static_cast<sal_uInt16
>(fDec));
9204 if (nParamCount == 3)
9209 if (nCnt < 1 || nCnt > sStr.getLength())
9220 while ( nIdx <
nPos )
9222 sStr.iterateCodePoints( &nIdx );
9248 if (nParamCount == 2)
9262 while ( nIdx <
aStr.getLength() &&
n > nCnt++ )
9263 aStr.iterateCodePoints( &nIdx );
9270struct UBlockScript {
9278 {UBLOCK_HANGUL_JAMO, UBLOCK_HANGUL_JAMO},
9279 {UBLOCK_CJK_RADICALS_SUPPLEMENT, UBLOCK_HANGUL_SYLLABLES},
9280 {UBLOCK_CJK_COMPATIBILITY_IDEOGRAPHS,UBLOCK_CJK_RADICALS_SUPPLEMENT },
9281 {UBLOCK_IDEOGRAPHIC_DESCRIPTION_CHARACTERS,UBLOCK_CJK_COMPATIBILITY_IDEOGRAPHS},
9282 {UBLOCK_CJK_COMPATIBILITY_FORMS, UBLOCK_CJK_COMPATIBILITY_FORMS},
9283 {UBLOCK_HALFWIDTH_AND_FULLWIDTH_FORMS, UBLOCK_HALFWIDTH_AND_FULLWIDTH_FORMS},
9284 {UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B, UBLOCK_CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT},
9285 {UBLOCK_CJK_STROKES, UBLOCK_CJK_STROKES}
9290 if( (currentChar == 0x005c || currentChar == 0x20ac) &&
9295 UBlockCode block = ublock_getCode(currentChar);
9304 sal_Int32
index = 0;
9331 OUStringBuffer
aBuf(rStr);
9343 aBuf.insert( 0,
" ");
9351 return aBuf.makeStringAndClear();
9362 if (nParamCount == 2)
9380 OUStringBuffer
aBuf(rStr);
9381 sal_Int32
index = -1;
9400 return aBuf.makeStringAndClear();
9411 if (nParamCount == 2)
9433 if (nStart < 1 ||
nCount < 0)
9455 if (nPos < 1.0 || nPos > nLen || nCount < 0.0 || nPos + nCount -1 > nLen)
9475 if ( nParamCount == 3 )
9483 if ( nStart < 1 || nStart > nLen - nsLen + 1 )
9490 sal_Int32
nPos =
aBuf.indexOf( asStr, 0 );
9509 if ( nParamCount == 3 )
9523 sal_Int32 nsLen = nStart - 1;
9532 sal_Int32 nEndPos = aSubStr.getLength();
9554 if (nParamCount == 2)
9566 sal_Int32 nLen =
aStr.getLength();
9571 sal_Int32 nIdx = nLen;
9573 while ( nIdx > 0 &&
n > nCnt )
9575 aStr.iterateCodePoints( &nIdx, -1 );
9578 aStr =
aStr.copy( nIdx, nLen - nIdx );
9590 if (nParamCount == 3)
9603 sal_Int32
nPos = nStart - 1;
9604 sal_Int32 nEndPos = sStr.getLength();
9605 if(
nPos >= nEndPos )
9619 while ( nIdx <
nPos )
9621 sStr.iterateCodePoints( &nIdx );
9638 bool bGlobalReplacement =
false;
9639 sal_Int32 nOccurrence = 1;
9640 if (nParamCount == 4)
9653 fOccurrence = nOccurrence;
9664 PushError( FormulaError::IllegalArgument);
9667 nOccurrence =
static_cast<sal_Int32
>(fOccurrence);
9671 const OUString aFlags( aFlagsString.
getString());
9673 if (aFlags.getLength() > 1)
9679 if (aFlags.getLength() == 1)
9681 if (aFlags.indexOf(
'g') >= 0)
9682 bGlobalReplacement =
true;
9693 bool bReplacement =
false;
9694 OUString aReplacement;
9695 if (nParamCount >= 3)
9705 bReplacement =
true;
9721 if (nOccurrence == 0)
9727 const icu::UnicodeString aIcuExpression(
9728 false,
reinterpret_cast<const UChar*
>(aExpression.getStr()), aExpression.getLength());
9729 UErrorCode status = U_ZERO_ERROR;
9730 icu::RegexMatcher aRegexMatcher( aIcuExpression, 0, status);
9731 if (U_FAILURE(status))
9739 aRegexMatcher.setTimeLimit( 23*1000, status);
9741 const icu::UnicodeString aIcuText(
false,
reinterpret_cast<const UChar*
>(aText.getStr()), aText.getLength());
9742 aRegexMatcher.reset( aIcuText);
9748 while (aRegexMatcher.find(status) && U_SUCCESS(status) && ++
nCount < nOccurrence)
9750 if (U_FAILURE(status))
9757 if (
nCount != nOccurrence)
9763 icu::UnicodeString aMatch( aRegexMatcher.group( status));
9764 if (U_FAILURE(status))
9770 OUString aResult(
reinterpret_cast<const sal_Unicode*
>(aMatch.getBuffer()), aMatch.length());
9775 const icu::UnicodeString aIcuReplacement(
9776 false,
reinterpret_cast<const UChar*
>(aReplacement.getStr()), aReplacement.getLength());
9777 icu::UnicodeString aReplaced;
9778 if (bGlobalReplacement)
9780 aReplaced = aRegexMatcher.replaceAll( aIcuReplacement, status);
9781 else if (nOccurrence == 1)
9783 aReplaced = aRegexMatcher.replaceFirst( aIcuReplacement, status);
9788 while (aRegexMatcher.find(status) && U_SUCCESS(status))
9795 if (++
nCount == nOccurrence)
9797 aRegexMatcher.appendReplacement( aReplaced, aIcuReplacement, status);
9801 aRegexMatcher.appendTail( aReplaced);
9803 if (U_FAILURE(status))
9809 OUString aResult(
reinterpret_cast<const sal_Unicode*
>(aReplaced.getBuffer()), aReplaced.length());
9821 if ( nStart < 1 || nSubLen < 0 )
9824 PushError(FormulaError::StringOverflow);
9827 sal_Int32 nLen =
aStr.getLength();
9830 while ( nIdx < nLen && nStart - 1 > nCnt )
9832 aStr.iterateCodePoints( &nIdx );
9835 sal_Int32 nIdx0 = nIdx;
9837 while ( nIdx < nLen && nStart + nSubLen - 1 > nCnt )
9839 aStr.iterateCodePoints( &nIdx );
9842 aStr =
aStr.copy( nIdx0, nIdx - nIdx0 );
9854 bool bString =
false;
9889 else if (sFormatString.isEmpty())
9904 const Color* pColor =
nullptr;
9915 aResult, &pColor, eCellLang))
9923 aResult, &pColor, eCellLang))
9938 if (nParamCount == 4)
9954 std::optional<OUStringBuffer> oResult;
9955 for (sal_Int32 nEnd = sStr.indexOf(sOldStr); nEnd >= 0; nEnd = sStr.indexOf(sOldStr, nEnd))
9957 if (nCnt == 0 || ++
nCount == nCnt)
9960 oResult.emplace(sStr.getLength() + sNewStr.getLength() - sOldStr.getLength());
9962 oResult->append(sStr.subView(
nPos, nEnd -
nPos));
9965 oResult->append(sNewStr);
9966 nPos = nEnd + sOldStr.getLength();
9970 nEnd += sOldStr.getLength();
9973 oResult->append(sStr.subView(
nPos, sStr.getLength() -
nPos));
9974 PushString(oResult ? oResult->makeStringAndClear() : sStr);
9988 PushError( FormulaError::StringOverflow );
9994 const sal_Int32 nLen =
aStr.getLength();
9995 OUStringBuffer aRes(nCnt*nLen);
10009 OUStringBuffer aRes;
10010 while( nParamCount-- > 0)
10035 const ScRefList* pRefList =
x->GetRefList();
10036 size_t n = pRefList->size();
10038 nErr = FormulaError::NoRef;
10040 nErr = FormulaError::NoValue;
10096 if ( nErr != FormulaError::NONE )
10110 sal_uInt16 nErrType;
10114 case FormulaError::NoCode :
10117 case FormulaError::DivisionByZero :
10120 case FormulaError::NoValue :
10123 case FormulaError::NoRef :
10126 case FormulaError::NoName :
10129 case FormulaError::IllegalFPOperation :
10132 case FormulaError::NotAvailable :
10165 if ( rStr.empty() || (rStr.size() == 1 && rStr[0] !=
'.') )
10168 std::u16string_view cre(
u"?*+.[]^$\\<>()|");
10169 return rStr.find_first_of(cre) != std::u16string_view::npos;
10177 std::u16string_view cw(
u"*?~");
10178 return rStr.find_first_of(cw) != std::u16string_view::npos;
10202 o_rResultPos.
SetCol( nCol);
10203 o_rResultPos.
SetRow( nRow);
10268 return rCache.
lookup( rCriteria );
10274 bool bFound =
false;
10276 bool bColumnsMatch = (rParam.
nCol1 == rEntry.
nField);
10277 OSL_ENSURE( bColumnsMatch,
"ScInterpreter::LookupQueryWithCache: columns don't match");
10301 if (nPrevRowWithEmptyValueLookup >= 0)
10306 aPosPrev.
SetRow(nPrevRowWithEmptyValueLookup);
10308 eCacheResult = rCache.
lookup( o_rResultPos, aCriteria, aPosPrev );
10312 switch (eCacheResult)
10318 rCache.
insert( o_rResultPos, aCriteria,
aPos, bFound);
bool ConvertSingleRef(const ScDocument &rDoc, const OUString &rRefString, SCTAB nDefTab, ScRefAddress &rRefAddress, const ScAddress::Details &rDetails, ScAddress::ExternalInfo *pExtInfo)
bool ConvertDoubleRef(const ScDocument &rDoc, const OUString &rRefString, SCTAB nDefTab, ScRefAddress &rStartRefAddress, ScRefAddress &rEndRefAddress, const ScAddress::Details &rDetails, ScAddress::ExternalInfo *pExtInfo)
size_t SCSIZE
size_t typedef to be able to find places where code was changed from USHORT to size_t and is used to ...
FILE * init(int, char **)
OUString uppercase(const OUString &rStr, sal_Int32 nPos, sal_Int32 nCount) const
OUString lowercase(const OUString &rStr, sal_Int32 nPos, sal_Int32 nCount) const
sal_Int32 compareString(const OUString &s1, const OUString &s2) const
OUString GetMainURL(DecodeMechanism eMechanism, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
OUString GetLastName(DecodeMechanism eMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
OUString GetPartBeforeLastName() const
This class provides LO with Kahan summation algorithm About this algorithm: https://en....
double get() const
Returns the final sum.
static LanguageType getConfiguredSystemLanguage()
const vcl::Font & GetFont() const
void SetFont(const vcl::Font &rNewFont)
tools::Long GetTextWidth(const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, vcl::text::TextLayoutCache const *=nullptr, SalLayoutGlyphs const *const pLayoutCache=nullptr) const
const MapMode & GetMapMode() const
SC_DLLPUBLIC void Format(OStringBuffer &r, ScRefFlags nFlags, const ScDocument *pDocument=nullptr, const Details &rDetails=detailsOOOa1) const
void IncRow(SCROW nDelta=1)
Walk through all cells in an area.
const ScRefCellValue & getRefCellValue() const
static void transKeyword(OUString &rName, const css::lang::Locale *pLocale, OpCode eOpCode)
static sal_Int32 GetDocTabPos(const OUString &rString)
Analyzes a string for a 'Doc'Tab construct, or 'Do''c'Tab etc...
static void CheckTabQuotes(OUString &aTabName, const formula::FormulaGrammar::AddressConvention eConv=formula::FormulaGrammar::CONV_OOO)
all
void SetRefConvention(const Convention *pConvP)
std::unique_ptr< ScTokenArray > CompileString(const OUString &rFormula)
Tokenize formula expression string into an array of tokens.
static bool CanBeUsed(ScDocument &rDoc, const ScQueryParam &aParam, SCTAB nTab, const ScFormulaCell *cell, const ScComplexRefData *refData, ScInterpreterContext &context)
Stores global named database ranges.
ScDBData * findByUpperName(const OUString &rName)
bool GetNext(Value &rValue)
Does NOT reset rValue if no value found!
bool GetFirst(Value &rValue)
Does NOT reset rValue if no value found!
bool IsIgnoreCase() const
utl::SearchParam::SearchType GetFormulaSearchType() const
SC_DLLPUBLIC sal_uInt32 GetNumberFormat(SCCOL nCol, SCROW nRow, SCTAB nTab) const
SC_DLLPUBLIC sal_uInt16 GetColWidth(SCCOL nCol, SCTAB nTab, bool bHiddenAsZero=true) const
SC_DLLPUBLIC ScPatternAttr * GetDefPattern() const
bool ValidRow(SCROW nRow) const
SC_DLLPUBLIC bool GetTable(const OUString &rName, SCTAB &rTab) const
SC_DLLPUBLIC SCCOL MaxCol() const
SC_DLLPUBLIC formula::FormulaGrammar::AddressConvention GetAddressConvention() const
SC_DLLPUBLIC SCROW MaxRow() const
ScLookupCache & GetLookupCache(const ScRange &rRange, ScInterpreterContext *pContext)
Creates a ScLookupCache cache for the range if it doesn't already exist.
SC_DLLPUBLIC ScExternalRefManager * GetExternalRefManager() const
FormulaError GetErrCode(const ScAddress &) const
SC_DLLPUBLIC ScLinkMode GetLinkMode(SCTAB nTab) const
SC_DLLPUBLIC formula::FormulaGrammar::Grammar GetGrammar() const
SC_DLLPUBLIC ScDBCollection * GetDBCollection() const
SfxObjectShell * GetDocumentShell() const
bool ValidCol(SCCOL nCol) const
bool GetDataAreaSubrange(ScRange &rRange) const
Returns true if there is a non-empty subrange in the range given as input.
SC_DLLPUBLIC svl::SharedStringPool & GetSharedStringPool()
SC_DLLPUBLIC CellType GetCellType(SCCOL nCol, SCROW nRow, SCTAB nTab) const
SfxPrinter * GetPrinter(bool bCreateIfNotExist=true)
SC_DLLPUBLIC bool GetName(SCTAB nTab, OUString &rName) const
SC_DLLPUBLIC const SfxPoolItem * GetAttr(SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt16 nWhich) const
SC_DLLPUBLIC const ScPatternAttr * GetPattern(SCCOL nCol, SCROW nRow, SCTAB nTab) const
SC_DLLPUBLIC const ScDocOptions & GetDocOptions() const
SC_DLLPUBLIC SCTAB GetTableCount() const
::formula::FormulaTokenRef TokenRef
std::shared_ptr< ScTokenArray > TokenArrayRef
ScExternalRefCache::TableTypeRef getCacheTable(sal_uInt16 nFileId, size_t nTabIndex) const
Get a cache table instance for specified table and table index.
const OUString * getExternalFileName(sal_uInt16 nFileId, bool bForceOriginal=false)
It returns a pointer to the name of the URI associated with a given external file ID.
static css::lang::Locale & GetLocale()
static SC_DLLPUBLIC CollatorWrapper & GetCollator()
case-insensitive collator
static SC_DLLPUBLIC LanguageType eLnge
static SC_DLLPUBLIC sal_Int32 FindUnquoted(const OUString &rString, sal_Unicode cChar, sal_Int32 nStart=0)
Finds an unquoted instance of cChar in rString, starting at offset nStart.
static OUString GetErrorString(FormulaError nErrNumber)
static SC_DLLPUBLIC const CharClass & getCharClass()
formula::FormulaConstTokenRef PopToken()
void ScStDev(bool bTextAsZero=false)
void SetError(FormulaError nError)
ScCalcConfig maCalcConfig
void CalculateLookup(bool bHLookup)
svl::SharedString GetString()
bool IsInArrayContext() const
static ScCalcConfig * mpGlobalConfig
static bool CheckStringPositionArgument(double &fVal)
Check if a double is suitable as string position or length argument.
bool MustHaveParamCount(short nAct, short nMust)
formula::FormulaTokenIterator aCode
void PopExternalSingleRef(sal_uInt16 &rFileId, OUString &rTabName, ScSingleRefData &rRef)
bool MustHaveParamCountMin(short nAct, short nMin)
sal_Int32 GetStringPositionArgument()
Obtain a sal_Int32 suitable as string position or length argument.
bool FillEntry(ScQueryEntry &rEntry)
static FormulaError GetCellErrCode(const ScRefCellValue &rCell)
void PushExternalDoubleRef(sal_uInt16 nFileId, const OUString &rTabName, SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2)
SubtotalFlags mnSubTotalFlags
ScDBRangeBase * PopDBDoubleRef()
void PushIllegalParameter()
bool JumpMatrix(short nStackLevel)
sc::RangeMatrix CompareMat(ScQueryOp eOp, sc::CompareOptions *pOptions=nullptr)
bool GetDoubleOrString(double &rValue, svl::SharedString &rString)
returns TRUE if double (or error, check nGlobalError), else FALSE
FormulaError nGlobalError
void PushIllegalArgument()
sal_Int16 GetInt16()
if GetDouble() not within int16 limits sets nGlobalError and returns SAL_MAX_INT16
void DoubleRefToRange(const ScComplexRefData &, ScRange &, bool bDontCheckForTableOp=false)
void ScMax(bool bTextAsZero=false)
void PushDoubleRef(SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2)
void PushExternalSingleRef(sal_uInt16 nFileId, const OUString &rTabName, SCCOL nCol, SCROW nRow, SCTAB nTab)
bool SwitchToArrayRefList(ScMatrixRef &xResMat, SCSIZE nMatRows, double fCurrent, const std::function< void(SCSIZE i, double fCurrent)> &MatOpFunc, bool bDoMatOp)
Switch to array reference list if current TOS is one and create/init or update matrix and return true...
formula::StackVar GetRawStackType()
Raw stack type without default replacements.
const formula::FormulaToken * pCur
ScInterpreterContext & mrContext
SvNumFormatType nFuncFmtType
bool DoubleRefToPosSingleRef(const ScRange &rRange, ScAddress &rAdr)
sal_uInt32 GetUInt32()
if GetDouble() not within uint32 limits sets nGlobalError and returns SAL_MAX_UINT32
std::unique_ptr< ScDBQueryParamBase > GetDBParams(bool &rMissingField)
size_t GetRefListArrayMaxSize(short nParamCount)
Check for array of references to determine the maximum size of a return column vector if in array con...
const svl::SharedString & PopString()
const ScComplexRefData * GetStackDoubleRef(size_t rRefInList=0)
void GetCellString(svl::SharedString &rStr, ScRefCellValue &rCell)
bool PopDoubleRefOrSingleRef(ScAddress &rAdr)
void ValidateRef(const ScSingleRefData &rRef)
void PushError(FormulaError nError)
sal_uInt8 GetByte() const
ScMatrixRef QueryMat(const ScMatrixRef &pMat, sc::CompareOptions &rOptions)
sal_Int32 GetInt32WithDefault(sal_Int32 nDefault)
if GetDoubleWithDefault() not within int32 limits sets nGlobalError and returns SAL_MAX_INT32
void PushWithoutError(const formula::FormulaToken &r)
Does not substitute with formula::FormulaErrorToken in case nGlobalError is set.
bool CheckStringResultLen(OUString &rResult, sal_Int32 nIncrease)
ScMatrixRef GetNewMat(SCSIZE nC, SCSIZE nR, bool bEmpty=false)
bool MustHaveParamCountMinWithStackCheck(short nAct, short nMin)
ScMatValType GetDoubleOrStringFromMatrix(double &rDouble, svl::SharedString &rString)
bool LookupQueryWithCache(ScAddress &o_rResultPos, const ScQueryParam &rParam, const ScComplexRefData *refData) const
void PushCellResultToken(bool bDisplayEmptyAsString, const ScAddress &rAddress, SvNumFormatType *pRetTypeExpr, sal_uInt32 *pRetIndexExpr, bool bFinalResult=false)
Obtain cell result / content from address and push as temp token.
void ScAverage(bool bTextAsZero=false)
void IterateParametersIfs(double(*ResultFunc)(const sc::ParamIfsResult &rRes))
ScTokenMatrixMap & GetTokenMatrixMap()
void PushDouble(double nVal)
void ScQuartile(bool bInclusive)
const formula::FormulaToken ** pStack
void PopSingleRef(ScAddress &)
void ReverseStack(sal_uInt8 nParamCount)
ScTokenMatrixMap maTokenMatrixMap
SvNumberFormatter * pFormatter
FormulaError mnStringNoValueError
double Compare(ScQueryOp eOp)
void ScVar(bool bTextAsZero=false)
static double div(const double &fNumerator, const double &fDenominator)
Fail safe division, returning a FormulaError::DivisionByZero coded into a double if denominator is 0....
void MatrixJumpConditionToMatrix()
void GetDBStVarParams(double &rVal, double &rValCount)
ScJumpMatrix * pJumpMatrix
void ScRandomImpl(const std::function< double(double fFirst, double fLast)> &RandomFunc, double fFirst, double fLast)
FormulaError GetError() const
sal_uInt32 GetCellNumberFormat(const ScAddress &rPos, ScRefCellValue &rCell)
void PopDoubleRef(ScRange &rRange, short &rParam, size_t &rRefInList)
If formula::StackVar formula::svDoubleRef pop ScDoubleRefToken and return values of ScComplexRefData.
void PushTokenRef(const formula::FormulaConstTokenRef &)
Pushes the token or substitutes with formula::FormulaErrorToken in case nGlobalError is set and the t...
void IterateParametersIf(ScIterFuncIf)
void ScPercentile(bool bInclusive)
void GetStVarParams(bool bTextAsZero, double(*VarResult)(double fVal, size_t nValCount))
void PushMatrix(const sc::RangeMatrix &rMat)
static utl::SearchParam::SearchType DetectSearchType(std::u16string_view rStr, const ScDocument &rDoc)
Detect if string should be used as regular expression or wildcard expression or literal string.
void ScVarP(bool bTextAsZero=false)
ScFormulaCell * pMyFormulaCell
void PopExternalDoubleRef(sal_uInt16 &rFileId, OUString &rTabName, ScComplexRefData &rRef)
double GetCellValue(const ScAddress &, ScRefCellValue &rCell)
void ScStDevP(bool bTextAsZero=false)
void PushSingleRef(SCCOL nCol, SCROW nRow, SCTAB nTab)
VolatileType GetVolatileType() const
sc::RangeMatrix GetRangeMatrix()
void ScMin(bool bTextAsZero=false)
void SingleRefToVars(const ScSingleRefData &rRef, SCCOL &rCol, SCROW &rRow, SCTAB &rTab)
double GetDoubleWithDefault(double nDefault)
void ScIfError(bool bNAonly)
sal_Int32 GetInt32()
if GetDouble() not within int32 limits sets nGlobalError and returns SAL_MAX_INT32
formula::StackVar GetStackType()
Stack type with replacement of defaults, e.g. svMissing and formula::svEmptyCell will result in formu...
svl::SharedStringPool & mrStrPool
SvNumFormatType nCurFmtType
void PushString(const OUString &rStr)
void DBIterator(ScIterFunc)
FormulaError GetErrorType()
void GetDimensions(SCSIZE &rCols, SCSIZE &rRows) const
void PutResultString(const svl::SharedString &rStr, SCSIZE nC, SCSIZE nR)
void PutResultDouble(double fVal, SCSIZE nC, SCSIZE nR)
void SetNewResMat(SCSIZE nNewCols, SCSIZE nNewRows)
bool Next(SCSIZE &rCol, SCSIZE &rRow)
void GetJump(SCSIZE nCol, SCSIZE nRow, double &rBool, short &rStart, short &rNext, short &rStop) const
ScMatrix * GetResultMatrix()
also applies pending buffered values
void GetPos(SCSIZE &rCol, SCSIZE &rRow) const
bool HasResultMatrix() const
void PutResultEmptyPath(SCSIZE nC, SCSIZE nR)
void GetResMatDimensions(SCSIZE &rCols, SCSIZE &rRows)
void PutResultEmpty(SCSIZE nC, SCSIZE nR)
const ScTokenVec & GetJumpParameters() const
bool isEmptyStringQuery() const
Lookup cache for one range used with interpreter functions such as VLOOKUP and MATCH.
bool insert(const ScAddress &rResultAddress, const QueryCriteria &rCriteria, const ScAddress &rQueryAddress, const bool bAvailable)
Insert query and result.
@ FOUND
Criteria not available in lookup range.
@ CRITERIA_DIFFERENT
Query not found in cache.
@ NOT_AVAILABLE
Different criteria for same query position exists.
Result lookup(ScAddress &o_rResultAddress, const QueryCriteria &rCriteria, const ScAddress &rQueryAddress) const
Matrix data type that can store values of mixed types.
svl::SharedString GetString(SCSIZE nC, SCSIZE nR) const
bool IsEmpty(SCSIZE nC, SCSIZE nR) const
double GetDouble(SCSIZE nC, SCSIZE nR) const
static bool IsValueType(ScMatValType nType)
Value or boolean.
static bool IsNonValueType(ScMatValType nType)
String, empty or empty path, but not value nor boolean.
ScMatrixRef CompareMatrix(sc::Compare &rComp, size_t nMatPos, sc::CompareOptions *pOptions) const
static bool IsRealStringType(ScMatValType nType)
String, but not empty or empty path or any other type.
bool IsValue(SCSIZE nIndex) const
static formula::ParamClass GetParameterType(const formula::FormulaToken *pToken, sal_uInt16 nParameter)
Get one parameter type for function eOp.
static void fillFontOnly(vcl::Font &rFont, const SfxItemSet &rItemSet, const OutputDevice *pOutDev=nullptr, const Fraction *pScale=nullptr, const SfxItemSet *pCondSet=nullptr, SvtScriptType nScript=SvtScriptType::NONE)
Static helper function to fill a font object from the passed item set.
const SfxPoolItem & GetItem(sal_uInt16 nWhichP) const
bool GetProtection() const
void SetAdvanceQueryParamEntryField(bool bVal)
static bool CanBeUsed(ScDocument &rDoc, const ScQueryParam &aParam, SCTAB nTab, const ScFormulaCell *cell, const ScComplexRefData *refData, ScInterpreterContext &context)
bool FindEqualOrSortedLastInRange(SCCOL &nFoundCol, SCROW &nFoundRow)
In a range assumed to be sorted find either the last of a sequence of equal entries or the last being...
static ScRangeData * GetRangeDataFromString(const OUString &rString, const SCTAB nTab, const ScDocument &rDoc, formula::FormulaGrammar::AddressConvention eConv)
String to RangeData core.
void GetVars(SCCOL &nCol1, SCROW &nRow1, SCTAB &nTab1, SCCOL &nCol2, SCROW &nRow2, SCTAB &nTab2) const
void AddExternalSingleReference(sal_uInt16 nFileId, const svl::SharedString &rTabName, const ScSingleRefData &rRef)
bool GetFirst(double &rValue, FormulaError &rErr)
Does NOT reset rValue if no value found!
void GetCurNumFmtInfo(SvNumFormatType &nType, sal_uInt32 &nIndex)
bool GetNext(double &rValue, FormulaError &rErr)
Does NOT reset rValue if no value found!
const INetURLObject & GetURLObject() const
SfxMedium * GetMedium() const
SharedString intern(const OUString &rStr)
const OUString & getString() const
rtl_uString * getDataIgnoreCase()
const OUString & getIgnoreCaseString() const
static const SharedString & getEmptyString()
bool SearchForward(const OUString &rStr, sal_Int32 *pStart, sal_Int32 *pEnd, css::util::SearchResult *pRes=nullptr)
void loadModuleByImplName(const OUString &rModuleName, LanguageType nLang)
OUString transliterate(const OUString &rStr, sal_Int32 nStart, sal_Int32 nLen) const
double CreateDoubleError(FormulaError nErr)
FormulaError GetDoubleErrorValue(double fVal)
static bool lcl_LookupQuery(ScAddress &o_rResultPos, ScDocument &rDoc, ScInterpreterContext &rContext, const ScQueryParam &rParam, const ScQueryEntry &rEntry, const ScFormulaCell *cell, const ScComplexRefData *refData)
static bool MayBeWildcard(std::u16string_view rStr)
static sal_Int32 lcl_getLengthB(std::u16string_view str, sal_Int32 nPos)
static OUString lcl_convertIntoHalfWidth(const OUString &rStr)
static bool MayBeRegExp(std::u16string_view rStr)
static bool lcl_FormatHasNegColor(const SvNumberformat *pFormat)
static OUString lcl_RightB(const OUString &rStr, sal_Int32 n)
static SCROW lcl_getPrevRowWithEmptyValueLookup(const ScLookupCache &rCache, const ScLookupCache::QueryCriteria &rCriteria, const ScQueryParam &rParam)
static sal_Int32 getLengthB(std::u16string_view str)
const sal_uInt64 n2power48
static OUString lcl_convertIntoFullWidth(const OUString &rStr)
static bool IsDBCS(sal_Unicode currentChar)
static bool lcl_IsTableStructuredRef(const OUString &sRefStr, sal_Int32 &nIndex)
static bool lcl_ScInterpreter_IsPrintable(sal_uInt32 nCodePoint)
static void lcl_storeJumpMatResult(const ScMatrix *pMat, ScJumpMatrix *pJumpMat, SCSIZE nC, SCSIZE nR)
Store a matrix value in another matrix in the context of that other matrix is the result matrix of a ...
static OUString lcl_LeftB(const OUString &rStr, sal_Int32 n)
const UBlockScript scriptList[]
static bool lcl_FormatHasOpenPar(const SvNumberformat *pFormat)
static void lcl_AdjustJumpMatrix(ScJumpMatrix *pJumpM, SCSIZE nParmCols, SCSIZE nParmRows)
constexpr sal_Int32 kScInterpreterMaxStrLen
Arbitrary 256MB result string length limit.
::std::vector< const formula::FormulaToken * > ScTokenVec
#define LANGUAGE_JAPANESE
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
#define SAL_N_ELEMENTS(arr)
std::unique_ptr< sal_Int32[]> pData
RttiCompleteObjectLocator col
bool isLetter(sal_Unicode c)
OUString GetString(int nId)
constexpr double rad2deg(double v)
constexpr double deg2rad(double v)
double uniform_real_distribution(double a=0.0, double b=1.0)
OString strip(const OString &rIn, char c)
OUString getString(const Any &_rAny)
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
constexpr T & temporary(T &&x)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
double CompareFunc(const Compare &rComp, CompareOptions *pOptions)
double div(const double &fNumerator, const double &fDenominator)
Return fNumerator/fDenominator if fDenominator!=0 else #DIV/0! error coded into double.
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
std::vector< char * > values
constexpr TypedWhichId< SvxLanguageItem > ATTR_LANGUAGE_FORMAT(147)
constexpr TypedWhichId< SvxHorJustifyItem > ATTR_HOR_JUSTIFY(129)
constexpr TypedWhichId< ScProtectionAttr > ATTR_PROTECTION(149)
Configuration options for formula interpreter.
formula::FormulaGrammar::AddressConvention meStringRefAddressSyntax
Complex reference (a range) into the sheet.
SC_DLLPUBLIC ScRange toAbs(const ScSheetLimits &rLimits, const ScAddress &rPos) const
std::vector< sal_uInt8 > maConditions
svl::SharedString maString
Each instance of this struct represents a single filtering criteria.
const Item & GetQueryItem() const
bool IsQueryByEmpty() const
QueryItemsType & GetQueryItems()
void FillInExcelSyntax(svl::SharedStringPool &rPool, const OUString &aCellStr, SCSIZE nIndex, SvNumberFormatter *pFormatter)
SC_DLLPUBLIC const ScQueryEntry & GetEntry(SCSIZE n) const
utl::SearchParam::SearchType eSearchType
This is very similar to ScCellValue, except that it references the original value instead of copying ...
ScFormulaCell * getFormula() const
Single reference (one address) into the sheet.
void SetAbsTab(SCTAB nVal)
ScAddress toAbs(const ScSheetLimits &rLimits, const ScAddress &rPos) const
::std::vector< ScComplexRefData > ScRefList
sal_Int32 SCCOLROW
a type capable of holding either SCCOL or SCROW
::boost::intrusive_ptr< ScMatrix > ScMatrixRef
::boost::intrusive_ptr< formula::FormulaToken > ScTokenRef