31#include <osl/diagnose.h>
37#include <document.hxx>
39#include <unitconv.hxx>
42#include <tokenarray.hxx>
44#include <stlsheet.hxx>
47#include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
55#define SCdEpsilon 1.0E-7
62 if ( nYear < 100 && !bStrict )
77 nY = nYear + (nMonth-1) / 12;
78 nM = ((nMonth-1) % 12) + 1;
82 nY = nYear + (nMonth-12) / 12;
83 nM = 12 - (-nMonth) % 12;
87 Date aDate( nD, nM, nY);
116 PushDouble(
static_cast<double>(nDiff) + fTime );
142 sal_uInt16 nHour, nMinute, nSecond;
143 double fFractionOfSecond;
150 sal_uInt16 nHour, nMinute, nSecond;
151 double fFractionOfSecond;
153 if ( fFractionOfSecond >= 0.5 )
154 nSecond = ( nSecond + 1 ) % 60;
161 sal_uInt16 nHour, nMinute, nSecond;
162 double fFractionOfSecond;
170 sal_uInt32 nFIndex = 0;
175 if (
eType == SvNumFormatType::DATE ||
eType == SvNumFormatType::DATETIME)
194 if (nParamCount == 2)
223 if (nVal < nFlag - 11)
229 SetError( FormulaError::IllegalArgument);
252 sal_Int16 nFlag = ( nParamCount == 1 ) ? 1 :
GetInt16();
257 sal_Int32 nMinimumNumberOfDaysInWeek;
263 nMinimumNumberOfDaysInWeek = 1;
267 nMinimumNumberOfDaysInWeek = 1;
276 eFirstDayOfWeek =
static_cast<DayOfWeek>( nFlag - 11 );
277 nMinimumNumberOfDaysInWeek = 1;
283 nMinimumNumberOfDaysInWeek = 4;
289 PushInt(
static_cast<int>(aDate.
GetWeekOfYear( eFirstDayOfWeek, nMinimumNumberOfDaysInWeek )) );
316 if (nYear < 1583 || nYear > 9956)
323 int B,
C,
D,
E,
F,
G,
H,
I,K,L,
M,
N,O;
325 B =
int(nYear / 100);
329 F =
int((
B + 8) / 25);
331 H = (19 *
N +
B -
D -
G + 15) % 30;
334 L = (32 + 2 *
E + 2 *
I -
H - K) % 7;
335 M =
int((
N + 11 *
H + 22 * L) / 451);
336 O =
H + L - 7 *
M + 114;
337 sal_Int16 nDay = sal::static_int_cast<sal_Int16>( O % 31 + 1 );
338 sal_Int16 nMonth = sal::static_int_cast<sal_Int16>(
int(O / 31) );
343 const sal_uInt8 nParamCount,
const sal_uInt32 nNullDate, vector< double >& rSortArray,
344 bool bWeekendMask[ 7 ] )
346 if ( nParamCount == 4 )
348 vector< double > nWeekendDays;
354 if ( nWeekendDays.size() != 7 )
355 return FormulaError::IllegalArgument;
358 for (
int i = 0;
i < 7;
i++ )
359 bWeekendMask[
i ] =
static_cast<bool>(nWeekendDays[ (
i == 6 ? 0 :
i + 1 ) ]);
364 for (
int i = 0;
i < 7;
i++ )
365 bWeekendMask[
i] =
false;
368 bWeekendMask[
SUNDAY ] =
true;
371 if ( nParamCount >= 3 )
374 size_t nMax = rSortArray.size();
375 for (
size_t i = 0;
i < nMax;
i++ )
376 rSortArray.at(
i ) = ::rtl::math::approxFloor( rSortArray.at(
i ) ) + nNullDate;
383 const sal_uInt8 nParamCount,
const sal_uInt32 nNullDate, vector< double >& rSortArray,
384 bool bWeekendMask[ 7 ],
bool bWorkdayFunction )
387 OUString aWeekendDays;
388 if ( nParamCount == 4 )
391 size_t nMax = rSortArray.size();
392 for (
size_t i = 0;
i < nMax;
i++ )
393 rSortArray.at(
i ) = ::rtl::math::approxFloor( rSortArray.at(
i ) ) + nNullDate;
396 if ( nParamCount >= 3 )
406 return FormulaError::NoValue;
415 if ( fDouble >= 1.0 && fDouble <= 17 )
416 aWeekendDays = OUString::number( fDouble );
418 return FormulaError::NoValue;
423 ( bWorkdayFunction && aSharedString.
getString() ==
"1111111" ) )
424 return FormulaError::NoValue;
426 aWeekendDays = aSharedString.
getString();
434 for (
int i = 0;
i < 7;
i++ )
435 bWeekendMask[
i] =
false;
437 if ( aWeekendDays.isEmpty() )
440 bWeekendMask[
SUNDAY ] =
true;
444 switch ( aWeekendDays.getLength() )
448 switch ( aWeekendDays[ 0 ] )
450 case '1' : bWeekendMask[
SATURDAY ] =
true; bWeekendMask[
SUNDAY ] =
true;
break;
451 case '2' : bWeekendMask[
SUNDAY ] =
true; bWeekendMask[
MONDAY ] =
true;
break;
452 case '3' : bWeekendMask[
MONDAY ] =
true; bWeekendMask[
TUESDAY ] =
true;
break;
453 case '4' : bWeekendMask[
TUESDAY ] =
true; bWeekendMask[
WEDNESDAY ] =
true;
break;
454 case '5' : bWeekendMask[
WEDNESDAY ] =
true; bWeekendMask[
THURSDAY ] =
true;
break;
455 case '6' : bWeekendMask[
THURSDAY ] =
true; bWeekendMask[
FRIDAY ] =
true;
break;
456 case '7' : bWeekendMask[
FRIDAY ] =
true; bWeekendMask[
SATURDAY ] =
true;
break;
457 default : nErr = FormulaError::IllegalArgument;
break;
462 if ( aWeekendDays[ 0 ] ==
'1' )
464 switch ( aWeekendDays[ 1 ] )
466 case '1' : bWeekendMask[
SUNDAY ] =
true;
break;
467 case '2' : bWeekendMask[
MONDAY ] =
true;
break;
468 case '3' : bWeekendMask[
TUESDAY ] =
true;
break;
469 case '4' : bWeekendMask[
WEDNESDAY ] =
true;
break;
470 case '5' : bWeekendMask[
THURSDAY ] =
true;
break;
471 case '6' : bWeekendMask[
FRIDAY ] =
true;
break;
472 case '7' : bWeekendMask[
SATURDAY ] =
true;
break;
473 default : nErr = FormulaError::IllegalArgument;
break;
477 nErr = FormulaError::IllegalArgument;
481 for (
int i = 0;
i < 7 && nErr == FormulaError::NONE;
i++ )
483 switch ( aWeekendDays[
i ] )
485 case '0' : bWeekendMask[
i ] =
false;
break;
486 case '1' : bWeekendMask[
i ] =
true;
break;
487 default : nErr = FormulaError::IllegalArgument;
break;
492 nErr = FormulaError::IllegalArgument;
505 vector<double> nSortArray;
506 bool bWeekendMask[ 7 ];
510 if ( bOOXML_Version )
513 nSortArray, bWeekendMask,
false );
518 nSortArray, bWeekendMask );
520 if ( nErr != FormulaError::NONE )
536 bool bReverse = ( nDate1 > nDate2 );
538 std::swap( nDate1, nDate2 );
539 size_t nMax = nSortArray.size();
540 while ( nDate1 <= nDate2 )
544 while (
nRef < nMax && nSortArray.at(
nRef ) < nDate1 )
546 if (
nRef >= nMax || nSortArray.at(
nRef ) != nDate1 )
551 PushDouble(
static_cast<double>( bReverse ? -nCnt : nCnt ) );
562 vector<double> nSortArray;
563 bool bWeekendMask[ 7 ];
567 nSortArray, bWeekendMask,
true );
568 if ( nErr != FormulaError::NONE )
582 PushDouble(
static_cast<double>( nDate - nNullDate ) );
585 size_t nMax = nSortArray.size();
597 while (
nRef < nMax && nSortArray.at(
nRef ) < nDate )
600 if (
nRef >= nMax || nSortArray.at(
nRef ) != nDate ||
nRef >= nMax )
606 sal_Int16
nRef = nMax - 1;
615 while (
nRef >= 0 && nSortArray.at(
nRef ) > nDate )
618 if (
nRef < 0 || nSortArray.at(
nRef) != nDate)
622 PushDouble(
static_cast<double>( nDate - nNullDate ) );
636 SetError( FormulaError::ParameterExpected);
701 bool bFlag = nParamCount == 3 &&
GetBool();
711 if (bFlag && (nDate2 < nDate1))
724 if (aDate1.
GetDay() == 31)
730 switch ( aDate1.
GetDay() )
742 if (aDate2.
GetDay() == 31)
746 if (aDate1.
GetDay() == 30)
753 (
static_cast<double>(aDate2.
GetDay()) +
static_cast<double>(aDate2.
GetMonth()) * 30.0 +
754 static_cast<double>(aDate2.
GetYear()) * 360.0
755 -
static_cast<double>(aDate1.
GetDay()) -
static_cast<double>(aDate1.
GetMonth()) * 30.0
756 -
static_cast<double>(aDate1.
GetYear()) * 360.0) );
783 double dd = nDate2 - nDate1;
785 if (dd == 0.0 || aInterval.equalsIgnoreAsciiCase(
"d" ))
792 sal_uInt16 d1, m1, d2, m2;
806 if (y1 < 0 && y2 > 0)
808 else if (y1 > 0 && y2 < 0)
811 if ( aInterval.equalsIgnoreAsciiCase(
"m" ) )
814 int md = m2 - m1 + 12 * (y2 - y1);
819 else if ( aInterval.equalsIgnoreAsciiCase(
"y" ) )
825 if (m2 > m1 || (m2 == m1 && d2 >= d1))
838 else if ( aInterval.equalsIgnoreAsciiCase(
"md" ) )
863 aDate1.
SetYear( y2 == 1 ? -1 : y2 - 1 );
872 nd = aDate2 - aDate1;
876 else if ( aInterval.equalsIgnoreAsciiCase(
"ym" ) )
879 int md = m2 - m1 + 12 * (y2 - y1);
885 else if ( aInterval.equalsIgnoreAsciiCase(
"yd" ) )
890 if (m2 > m1 || (m2 == m1 && d2 >= d1))
903 double fd = aDate2 - aDate1;
913 sal_uInt32 nFIndex = 0;
918 if (
eType == SvNumFormatType::TIME ||
eType == SvNumFormatType::DATETIME)
921 double fDateVal = rtl::math::approxFloor(fVal);
922 double fTimeVal = fVal - fDateVal;
960 if (nParamCount == 1)
968 if ( (
eMode == rtl_math_RoundingMode_Down ||
969 eMode == rtl_math_RoundingMode_Up ) &&
970 nDec < 12 && fmod( fX, 1.0 ) != 0.0 )
977 fVal = ::rtl::math::round( fRes, nDec,
eMode );
980 fVal = ::rtl::math::round( fX, nDec,
eMode );
1003 double fTemp = ::rtl::math::approxFloor( log10( std::abs(fX) ) ) + 1.0 - fDigits;
1004 fRes = ::rtl::math::round( pow(10.0, -fTemp ) * fX ) * pow( 10.0, fTemp );
1013 double fDigits = ::rtl::math::approxFloor(
GetDouble() );
1015 if (
nGlobalError != FormulaError::NONE || fDigits < 1.0 )
1044 bool bAbs = nParamCount == 3 &&
GetBool();
1046 if ( nParamCount == 1 )
1049 fDec = ( fVal < 0 ? -1 : 1 );
1056 if ( bArgumentMissing )
1057 fDec = ( fVal < 0 ? -1 : 1 );
1059 if ( fVal == 0 || fDec == 0.0 )
1063 if ( bODFF && fVal * fDec < 0 )
1067 if ( fVal * fDec < 0.0 )
1070 if ( !bAbs && fVal < 0.0 )
1071 PushDouble(::rtl::math::approxFloor( fVal / fDec ) * fDec );
1073 PushDouble(::rtl::math::approxCeil( fVal / fDec ) * fDec );
1086 if ( fVal == 0 || fDec == 0.0 )
1088 else if ( fVal * fDec > 0 )
1089 PushDouble(::rtl::math::approxCeil( fVal / fDec ) * fDec );
1090 else if ( fVal < 0.0 )
1091 PushDouble(::rtl::math::approxFloor( fVal / -fDec ) * -fDec );
1103 if ( nParamCount == 1 )
1113 if ( fDec == 0.0 || fVal == 0.0 )
1116 PushDouble(::rtl::math::approxCeil( fVal / fDec ) * fDec );
1132 bool bAbs = ( nParamCount == 3 &&
GetBool() );
1134 if ( nParamCount == 1 )
1137 fDec = ( fVal < 0 ? -1 : 1 );
1144 if ( bArgumentMissing )
1145 fDec = ( fVal < 0 ? -1 : 1 );
1147 if ( fDec == 0.0 || fVal == 0.0 )
1151 if ( bODFF && ( fVal * fDec < 0.0 ) )
1155 if ( fVal * fDec < 0.0 )
1158 if ( !bAbs && fVal < 0.0 )
1159 PushDouble(::rtl::math::approxCeil( fVal / fDec ) * fDec );
1161 PushDouble(::rtl::math::approxFloor( fVal / fDec ) * fDec );
1177 else if ( fVal * fDec > 0 )
1178 PushDouble(::rtl::math::approxFloor( fVal / fDec ) * fDec );
1179 else if ( fDec == 0 )
1181 else if ( fVal < 0.0 )
1182 PushDouble(::rtl::math::approxCeil( fVal / -fDec ) * -fDec );
1195 if ( fDec == 0.0 || fVal == 0.0 )
1198 PushDouble(::rtl::math::approxFloor( fVal / fDec ) * fDec );
1205 PushDouble(::rtl::math::approxFloor(fVal/2.0) * 2.0);
1207 PushDouble(::rtl::math::approxCeil(fVal/2.0) * 2.0);
1215 fVal = ::rtl::math::approxCeil(fVal);
1216 if (fmod(fVal, 2.0) == 0.0)
1221 fVal = ::rtl::math::approxFloor(fVal);
1222 if (fmod(fVal, 2.0) == 0.0)
1244 double fBase = nParamCount == 2 ?
GetDouble() : 10.0;
1246 if (fVal > 0.0 && fBase > 0.0 && fBase != 1.0)
1273 short nParamCount =
GetByte();
1282 double fCount = 1.0;
1285 size_t nRefInList = 0;
1287 while (nParamCount-- > 0)
1293 fVal +=
GetDouble() / pow(1.0 + fRate, fCount);
1305 fVal += fCellVal / pow(1.0 + fRate, fCount);
1317 while ((nErr == FormulaError::NONE) && aValIter.
GetNext(fCellVal, nErr))
1319 fVal += fCellVal / pow(1.0 + fRate, fCount);
1322 if ( nErr != FormulaError::NONE )
1334 pMat->GetDimensions(nC, nR);
1335 if (nC == 0 || nR == 0)
1343 for (
SCSIZE j = 0; j < nC; j++ )
1345 for (
SCSIZE k = 0; k < nR; ++k)
1347 if (!pMat->IsValue(j,k))
1352 fx = pMat->GetDouble(j,k);
1353 fVal += fx / pow(1.0 + fRate, fCount);
1361 default :
SetError(FormulaError::IllegalParameter);
break;
1374 double fEstimated = nParamCount == 2 ?
GetDouble() : 0.1;
1377 double x = fEstimated == -1.0 ? 0.1 : fEstimated;
1384 bool bIsMatrix =
false;
1396 pMat->GetDimensions(nC, nR);
1397 if (nC == 0 || nR == 0)
1416 const sal_uInt16 nIterationsMax = 20;
1417 sal_uInt16 nItCount = 0;
1423 double fCount = 0.0;
1428 for (
SCSIZE k = 0; k < nR; k++)
1430 if (!pMat->IsValue(j, k))
1432 fValue = pMat->GetDouble(j, k);
1436 fNom += fValue / pow(1.0+
x,fCount);
1437 fDenom += -fCount * fValue / pow(1.0+
x,fCount+1.0);
1445 bool bLoop = aValIter.
GetFirst(fValue, nIterError);
1446 while (bLoop && nIterError == FormulaError::NONE)
1448 fNom += fValue / pow(1.0+
x,fCount);
1449 fDenom += -fCount * fValue / pow(1.0+
x,fCount+1.0);
1452 bLoop = aValIter.
GetNext(fValue, nIterError);
1456 double xNew =
x - fNom.
get() / fDenom.
get();
1458 fEps = std::abs(xNew -
x);
1461 if (fEstimated == 0.0 && std::abs(
x) <
SCdEpsilon)
1466 PushError( FormulaError::NoConvergence);
1475 double fRate1_reinvest =
GetDouble() + 1;
1482 bool bIsMatrix =
false;
1495 pMat->GetDimensions( nC, nR );
1496 if ( nC == 0 || nR == 0 )
1497 SetError( FormulaError::IllegalArgument );
1501 SetError( FormulaError::IllegalArgument );
1505 SetError( FormulaError::IllegalParameter );
1514 double fPow_reinvest = 1.0;
1516 double fPow_invest = 1.0;
1518 bool bHasPosValue =
false;
1519 bool bHasNegValue =
false;
1524 for (
SCSIZE j = 0; j < nC; j++ )
1526 for (
SCSIZE k = 0; k < nR; ++k )
1528 if ( !pMat->IsValue( j, k ) )
1530 fX = pMat->GetDouble( j, k );
1536 bHasPosValue =
true;
1537 fNPV_reinvest += fX * fPow_reinvest;
1539 else if ( fX < 0.0 )
1541 bHasNegValue =
true;
1542 fNPV_invest += fX * fPow_invest;
1544 fPow_reinvest /= fRate1_reinvest;
1545 fPow_invest /= fRate1_invest;
1556 bool bLoop = aValIter.
GetFirst( fCellValue, nIterError );
1559 if( fCellValue > 0.0 )
1561 bHasPosValue =
true;
1562 fNPV_reinvest += fCellValue * fPow_reinvest;
1564 else if( fCellValue < 0.0 )
1566 bHasNegValue =
true;
1567 fNPV_invest += fCellValue * fPow_invest;
1569 fPow_reinvest /= fRate1_reinvest;
1570 fPow_invest /= fRate1_invest;
1573 bLoop = aValIter.
GetNext( fCellValue, nIterError );
1576 if ( nIterError != FormulaError::NONE )
1579 if ( !( bHasPosValue && bHasNegValue ) )
1580 SetError( FormulaError::IllegalArgument );
1586 double fResult = -fNPV_reinvest.
get() / fNPV_invest.
get();
1587 fResult *= pow( fRate1_reinvest,
static_cast<double>(
nCount - 1 ) );
1588 fResult = pow( fResult,
div( 1.0, (
nCount - 1)) );
1606 PushDouble( fInvest * fRate * (fPeriod / fTotal - 1.0) );
1612 double fFv,
bool bPayInAdvance)
1616 fPv = fFv + fPmt * fNper;
1620 fPv = (fFv * pow(1.0 + fRate, -fNper))
1621 + (fPmt * (1.0 - pow(1.0 + fRate, -fNper + 1.0)) / fRate)
1624 fPv = (fFv * pow(1.0 + fRate, -fNper))
1625 + (fPmt * (1.0 - pow(1.0 + fRate, -fNper)) / fRate);
1637 bool bPayInAdvance = nParamCount == 5 &&
GetBool();
1638 double fFv = nParamCount >= 4 ?
GetDouble() : 0;
1654 double fSyd = ((fCost - fSalvage) * (fLife - fPer + 1.0)) /
1655 ((fLife * (fLife + 1.0)) / 2.0);
1661 double fPeriod,
double fFactor)
1663 double fDdb, fRate, fOldValue, fNewValue;
1664 fRate = fFactor / fLife;
1668 fOldValue = fPeriod == 1.0 ? fCost : 0;
1671 fOldValue = fCost * pow(1.0 - fRate, fPeriod - 1.0);
1672 fNewValue = fCost * pow(1.0 - fRate, fPeriod);
1674 fDdb = fNewValue < fSalvage ? fOldValue - fSalvage : fOldValue - fNewValue;
1675 return fDdb < 0 ? 0 : fDdb;
1685 double fFactor = nParamCount == 5 ?
GetDouble() : 2.0;
1690 if (fCost < 0.0 || fSalvage < 0.0 || fFactor <= 0.0 || fSalvage > fCost
1691 || fPeriod < 1.0 || fPeriod > fLife)
1703 double fMonths = nParamCount == 4 ? 12.0 : ::rtl::math::approxFloor(
GetDouble());
1708 if (fMonths < 1.0 || fMonths > 12.0 || fLife > 1200.0 || fSalvage < 0.0 ||
1709 fPeriod > (fLife + 1.0) || fSalvage > fCost || fCost <= 0.0 ||
1710 fLife <= 0 || fPeriod <= 0 )
1715 double fOffRate = 1.0 - pow(fSalvage / fCost, 1.0 / fLife);
1716 fOffRate = ::rtl::math::approxFloor((fOffRate * 1000.0) + 0.5) / 1000.0;
1717 double fFirstOffRate = fCost * fOffRate * fMonths / 12.0;
1719 if (::rtl::math::approxFloor(fPeriod) == 1)
1720 fDb = fFirstOffRate;
1723 KahanSum fSumOffRate = fFirstOffRate;
1724 double fMin = fLife;
1725 if (fMin > fPeriod) fMin = fPeriod;
1726 sal_uInt16 iMax =
static_cast<sal_uInt16
>(::rtl::math::approxFloor(fMin));
1727 for (sal_uInt16
i = 2;
i <= iMax;
i++)
1729 fDb = -(fSumOffRate - fCost).
get() * fOffRate;
1732 if (fPeriod > fLife)
1733 fDb = -(fSumOffRate - fCost).
get() * fOffRate * (12.0 - fMonths) / 12.0;
1739 double fLife1,
double fPeriod,
double fFactor)
1742 double fIntEnd = ::rtl::math::approxCeil(fPeriod);
1745 double fTerm, fSln = 0;
1746 double fSalvageValue = fCost - fSalvage;
1747 bool bNowSln =
false;
1751 for (
i = 1;
i <= nLoopEnd;
i++)
1755 fDdb =
ScGetDDB(fCost, fSalvage, fLife,
static_cast<double>(
i), fFactor);
1756 fSln = fSalvageValue/ (fLife1 -
static_cast<double>(
i-1));
1766 fSalvageValue -= fDdb;
1775 fTerm *= ( fPeriod + 1.0 - fIntEnd );
1790 bool bNoSwitch = nParamCount == 7 &&
GetBool();
1791 double fFactor = nParamCount >= 6 ?
GetDouble() : 2.0;
1797 if (fStart < 0.0 || fEnd < fStart || fEnd > fLife || fCost < 0.0
1798 || fSalvage > fCost || fFactor <= 0.0)
1802 double fIntStart = ::rtl::math::approxFloor(fStart);
1803 double fIntEnd = ::rtl::math::approxCeil(fEnd);
1811 double fTerm =
ScGetDDB(fCost, fSalvage, fLife,
static_cast<double>(
i), fFactor);
1814 if (
i == nLoopStart+1 )
1815 fTerm *= ( std::min( fEnd, fIntStart + 1.0 ) - fStart );
1816 else if (
i == nLoopEnd )
1817 fTerm *= ( fEnd + 1.0 - fIntEnd );
1826 if ( !::rtl::math::approxEqual( fStart, fIntStart ) ||
1827 !::rtl::math::approxEqual( fEnd, fIntEnd ) )
1829 if ( !::rtl::math::approxEqual( fStart, fIntStart ) )
1832 double fTempIntEnd = fIntStart + 1.0;
1833 double fTempValue = fCost -
1834 ScInterVDB( fCost, fSalvage, fLife, fLife, fIntStart, fFactor );
1835 fPart += ( fStart - fIntStart ) *
1836 ScInterVDB( fTempValue, fSalvage, fLife, fLife - fIntStart,
1837 fTempIntEnd - fIntStart, fFactor);
1839 if ( !::rtl::math::approxEqual( fEnd, fIntEnd ) )
1842 double fTempIntStart = fIntEnd - 1.0;
1843 double fTempValue = fCost -
1844 ScInterVDB( fCost, fSalvage, fLife, fLife, fTempIntStart, fFactor );
1845 fPart += ( fIntEnd - fEnd ) *
1846 ScInterVDB( fTempValue, fSalvage, fLife, fLife - fTempIntStart,
1847 fIntEnd - fTempIntStart, fFactor);
1851 fCost -=
ScInterVDB( fCost, fSalvage, fLife, fLife, fIntStart, fFactor );
1852 fVdb =
ScInterVDB( fCost, fSalvage, fLife, fLife - fIntStart,
1853 fIntEnd - fIntStart, fFactor);
1867 if ( fFuture <= 0.0 || fPresent <= 0.0 || fRate <= 0.0 )
1870 PushDouble( std::log( fFuture / fPresent ) / std::log1p( fRate ) );
1887 double fFv,
bool bPayInAdvance)
1891 fPayment = (fPv + fFv) / fNper;
1895 fPayment = (fFv + fPv * exp( fNper * ::std::log1p(fRate) ) ) * fRate /
1896 (std::expm1( (fNper + 1) * ::std::log1p(fRate) ) - fRate);
1898 fPayment = (fFv + fPv * exp(fNper * ::std::log1p(fRate) ) ) * fRate /
1899 std::expm1( fNper * ::std::log1p(fRate) );
1910 bool bPayInAdvance = nParamCount == 5 &&
GetBool();
1911 double fFv = nParamCount >= 4 ?
GetDouble() : 0;
1926 if ( fNrOfPeriods <= 0.0 || fPresentValue == 0.0 )
1929 PushDouble(pow(fFutureValue / fPresentValue, 1.0 / fNrOfPeriods) - 1.0);
1934 double fPv,
bool bPayInAdvance)
1938 fFv = fPv + fPmt * fNper;
1941 double fTerm = pow(1.0 + fRate, fNper);
1943 fFv = fPv * fTerm + fPmt*(1.0 + fRate)*(fTerm - 1.0)/fRate;
1945 fFv = fPv * fTerm + fPmt*(fTerm - 1.0)/fRate;
1956 bool bPayInAdvance = nParamCount == 5 &&
GetBool();
1957 double fPv = nParamCount >= 4 ?
GetDouble() : 0;
1969 bool bPayInAdvance = nParamCount == 5 &&
GetBool();
1970 double fFV = nParamCount >= 4 ?
GetDouble() : 0;
1976 if ( fPV + fFV == 0.0 )
1978 else if (fRate == 0.0)
1980 else if (bPayInAdvance)
1981 PushDouble(
log(-(fRate*fFV-fPmt*(1.0+fRate))/(fRate*fPV+fPmt*(1.0+fRate)))
1982 / std::log1p(fRate));
1984 PushDouble(
log(-(fRate*fFV-fPmt)/(fRate*fPV+fPmt)) / std::log1p(fRate));
1988 double fFv,
bool bPayType,
double & fGuess )
1995 bool bValid =
true, bFound =
false;
1996 double fX, fXnew, fTerm, fTermDerivation;
1997 double fGeoSeries, fGeoSeriesDerivation;
1998 const sal_uInt16 nIterationsMax = 150;
2000 const double fEpsilonSmall = 1.0E-14;
2004 fFv = fFv - fPayment;
2005 fPv = fPv + fPayment;
2007 if (fNper == ::rtl::math::round( fNper ))
2010 while (!bFound &&
nCount < nIterationsMax)
2012 double fPowN, fPowNminus1;
2013 fPowNminus1 = pow( 1.0+fX, fNper-1.0);
2014 fPowN = fPowNminus1 * (1.0+fX);
2018 fGeoSeriesDerivation = fNper * (fNper-1.0)/2.0;
2022 fGeoSeries = (fPowN-1.0)/fX;
2023 fGeoSeriesDerivation = fNper * fPowNminus1 / fX - fGeoSeries / fX;
2025 fTerm = fFv + fPv *fPowN+ fPayment * fGeoSeries;
2026 fTermDerivation = fPv * fNper * fPowNminus1 + fPayment * fGeoSeriesDerivation;
2027 if (std::abs(fTerm) < fEpsilonSmall)
2031 if (fTermDerivation == 0.0)
2034 fXnew = fX - fTerm / fTermDerivation;
2037 bFound = (std::abs(fXnew - fX) <
SCdEpsilon);
2047 bValid = (fX > -1.0);
2051 fX = (fGuess < -1.0) ? -1.0 : fGuess;
2052 while (bValid && !bFound &&
nCount < nIterationsMax)
2057 fGeoSeriesDerivation = fNper * (fNper-1.0)/2.0;
2061 fGeoSeries = (pow( 1.0+fX, fNper) - 1.0) / fX;
2062 fGeoSeriesDerivation = fNper * pow( 1.0+fX, fNper-1.0) / fX - fGeoSeries / fX;
2064 fTerm = fFv + fPv *pow(1.0 + fX,fNper)+ fPayment * fGeoSeries;
2065 fTermDerivation = fPv * fNper * pow( 1.0+fX, fNper-1.0) + fPayment * fGeoSeriesDerivation;
2066 if (std::abs(fTerm) < fEpsilonSmall)
2070 if (fTermDerivation == 0.0)
2073 fXnew = fX - fTerm / fTermDerivation;
2076 bFound = (std::abs(fXnew - fX) <
SCdEpsilon);
2078 bValid = (fX >= -1.0);
2083 return bValid && bFound;
2095 double fGuess = nParamCount == 6 ?
GetDouble() : 0.1;
2096 bool bDefaultGuess = nParamCount != 6;
2097 bool bPayType = nParamCount >= 5 &&
GetBool();
2098 double fFv = nParamCount >= 4 ?
GetDouble() : 0;
2102 double fOrigGuess = fGuess;
2109 bool bValid =
RateIteration(fNper, fPayment, fPv, fFv, bPayType, fGuess);
2124 double fX = fOrigGuess;
2125 for (
int nStep = 2; nStep <= 10 && !bValid; ++nStep)
2127 fGuess = fX * nStep;
2128 bValid =
RateIteration( fNper, fPayment, fPv, fFv, bPayType, fGuess);
2131 fGuess = fX / nStep;
2132 bValid =
RateIteration( fNper, fPayment, fPv, fFv, bPayType, fGuess);
2137 SetError(FormulaError::NoConvergence);
2143 double fFv,
bool bPayInAdvance,
double& fPmt)
2145 fPmt =
ScGetPMT(fRate, fNper, fPv, fFv, bPayInAdvance);
2149 fIpmt = bPayInAdvance ? 0.0 : -fPv;
2153 fIpmt =
ScGetFV(fRate, fPer-2.0, fPmt, fPv,
true) - fPmt;
2155 fIpmt =
ScGetFV(fRate, fPer-1.0, fPmt, fPv,
false);
2157 return fIpmt * fRate;
2166 bool bPayInAdvance = nParamCount == 6 &&
GetBool();
2167 double fFv = nParamCount >= 5 ?
GetDouble() : 0;
2172 if (fPer < 1.0 || fPer > fNper)
2187 bool bPayInAdvance = nParamCount == 6 &&
GetBool();
2188 double fFv = nParamCount >= 5 ?
GetDouble() : 0;
2193 if (fPer < 1.0 || fPer > fNper)
2198 double fInterestPer =
ScGetIpmt(fRate, fPer, fNper, fPv, fFv, bPayInAdvance, fPmt);
2210 double fEnd = ::rtl::math::approxFloor(
GetDouble());
2211 double fStart = ::rtl::math::approxFloor(
GetDouble());
2215 if (fStart < 1.0 || fEnd < fStart || fRate <= 0.0 ||
2216 fEnd > fNper || fNper <= 0.0 || fPv <= 0.0 ||
2217 ( fFlag != 0.0 && fFlag != 1.0 ))
2221 bool bPayInAdvance =
static_cast<bool>(fFlag);
2224 double fPmt =
ScGetPMT(fRate, fNper, fPv, 0.0, bPayInAdvance);
2235 fIpmt +=
ScGetFV(fRate,
static_cast<double>(
i-2), fPmt, fPv,
true) - fPmt;
2237 fIpmt +=
ScGetFV(fRate,
static_cast<double>(
i-1), fPmt, fPv,
false);
2251 double fEnd = ::rtl::math::approxFloor(
GetDouble());
2252 double fStart = ::rtl::math::approxFloor(
GetDouble());
2256 if (fStart < 1.0 || fEnd < fStart || fRate <= 0.0 ||
2257 fEnd > fNper || fNper <= 0.0 || fPv <= 0.0 ||
2258 ( fFlag != 0.0 && fFlag != 1.0 ))
2262 bool bPayInAdvance =
static_cast<bool>(fFlag);
2263 double fPmt =
ScGetPMT(fRate, fNper, fPv, 0.0, bPayInAdvance);
2269 fPpmt = bPayInAdvance ? fPmt : fPmt + fPv * fRate;
2275 fPpmt += fPmt - (
ScGetFV(fRate,
static_cast<double>(
i-2), fPmt, fPv,
true) - fPmt) * fRate;
2277 fPpmt += fPmt -
ScGetFV(fRate,
static_cast<double>(
i-1), fPmt, fPv,
false) * fRate;
2291 if (fPeriods < 1.0 || fNominal < 0.0)
2293 else if ( fNominal == 0.0 )
2297 fPeriods = ::rtl::math::approxFloor(fPeriods);
2298 PushDouble(pow(1.0 + fNominal/fPeriods, fPeriods) - 1.0);
2309 if (fPeriods < 1.0 || fEffective <= 0.0)
2313 fPeriods = ::rtl::math::approxFloor(fPeriods);
2314 PushDouble( (pow(fEffective + 1.0, 1.0 / fPeriods) - 1.0) * fPeriods );
2325 if ( fDenom == 0.0 )
2327 PushError(FormulaError::DivisionByZero);
2331 double fRes = ::rtl::math::approxSub( fNum,
2332 ::rtl::math::approxFloor( fNum / fDenom ) * fDenom );
2333 if ( ( fDenom > 0 && fRes >= 0 && fRes < fDenom ) ||
2334 ( fDenom < 0 && fRes <= 0 && fRes > fDenom ) )
2345 if (
nGlobalError != FormulaError::NONE || !p2nd || !p1st)
2371 std::unique_ptr<formula::FormulaToken>
p;
2372 for (
size_t i=0;
i<2; ++
i)
2379 p->GetRefList()->push_back( aRef);
2386 p->GetRefList()->push_back( aRef);
2409 if (nCol2 < nCol1 || nRow2 < nRow1 || nTab2 < nTab1)
2414 aRef.
InitRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2415 pRefList->push_back( aRef);
2419 size_t n = pRefList->size();
2437 SCCOL nC1[2], nC2[2];
2438 SCROW nR1[2], nR2[2];
2439 SCTAB nT1[2], nT2[2];
2440 for (
size_t i=0;
i<2; ++
i)
2472 SCCOL nCol1 = ::std::max( nC1[0], nC1[1]);
2473 SCROW nRow1 = ::std::max( nR1[0], nR1[1]);
2474 SCTAB nTab1 = ::std::max( nT1[0], nT1[1]);
2475 SCCOL nCol2 = ::std::min( nC2[0], nC2[1]);
2476 SCROW nRow2 = ::std::min( nR2[0], nR2[1]);
2477 SCTAB nTab2 = ::std::min( nT2[0], nT2[1]);
2478 if (nCol2 < nCol1 || nRow2 < nRow1 || nTab2 < nTab1)
2480 else if (nCol2 == nCol1 && nRow2 == nRow1 && nTab2 == nTab1)
2512 if (
nGlobalError != FormulaError::NONE || !p2nd || !p1st)
2547 for (
size_t i=0;
i<2; ++
i)
2557 pRes->push_back( aRef);
2561 pRes->push_back( *
pt[
i]->GetDoubleRef());
2566 for (
const auto& rRef : *
p)
2568 pRes->push_back( rRef);
2589 PushError( FormulaError::UnknownStackVariable);
2595 if (nParamCount >= 1 && nParamCount <= 3)
2598 if (nParamCount >= 3)
2601 if (nParamCount >= 2)
2615 bool bNotify =
true;
2616 if (aStyle2.isEmpty())
2620 if (pStyle && pStyle->
GetName() == aStyle1)
2628 pShell->Broadcast( aHint );
2640 std::u16string_view rA, std::u16string_view rT, std::u16string_view rI,
sal_uInt8 nM )
2648 if (
pLink->GetAppl() == rA &&
2649 pLink->GetTopic() == rT &&
2650 pLink->GetItem() == rI &&
2651 pLink->GetMode() == nM )
2669 if (nParamCount == 4)
2781 '0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
2782 'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
2783 'N',
'O',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z',
2788 if ( nParamCount == 3 )
2790 double fLen = ::rtl::math::approxFloor(
GetDouble() );
2792 nMinLen =
static_cast<sal_Int32
>(fLen);
2794 nMinLen = fLen == 0.0 ? 1 : 0;
2798 double fBase = ::rtl::math::approxFloor(
GetDouble() );
2799 double fVal = ::rtl::math::approxFloor(
GetDouble() );
2800 double fChars = ((fVal > 0.0 && fBase > 0.0) ?
2801 (ceil(
log( fVal ) /
log( fBase ) ) + 2.0) :
2806 if (
nGlobalError == FormulaError::NONE && nMinLen && 2 <= fBase && fBase <= nDigits && 0 <= fVal )
2808 const sal_Int32 nConstBuf = 128;
2810 sal_Int32 nBuf = std::max<sal_Int32>( fChars, nMinLen + 1 );
2812 for ( sal_Int32 j = 0; j < nBuf; ++j )
2822 while ( nVal &&
p > pBuf )
2824 *--
p = pDigits[ nVal % nBase ];
2827 fVal =
static_cast<double>(nVal);
2832 while ( fVal &&
p > pBuf )
2837 double fInt = ::rtl::math::approxFloor( fVal / fBase );
2838 double fMult = fInt * fBase;
2843 double fDebug1 = fVal - fMult;
2848 double fDebug2 = ::rtl::math::approxSub( fVal, fMult );
2850 double fDebug3 = ( fInt ? fVal / fInt : 0.0 );
2856 (void)fDebug1; (void)fDebug2; (void)fDebug3;
2866 double fDig = ::rtl::math::approxFloor( ::rtl::math::approxSub( fVal, fMult ) );
2874 else if ( fDig >= fBase )
2875 nDig =
static_cast<size_t>(fBase) - 1;
2877 nDig =
static_cast<size_t>(fDig);
2879 *--
p = pDigits[ nDig ];
2884 PushError( FormulaError::StringOverflow );
2887 if ( nBuf - (
p - pBuf) <= nMinLen )
2888 p = pBuf + nBuf - 1 - nMinLen;
2903 double fBase = ::rtl::math::approxFloor(
GetDouble() );
2905 if (
nGlobalError == FormulaError::NONE && 2 <= fBase && fBase <= 36 )
2908 int nBase =
static_cast<int>(fBase);
2910 while ( *
p ==
' ' || *
p ==
'\t' )
2914 if ( *
p ==
'x' || *
p ==
'X' )
2916 else if ( *
p ==
'0' && (*(
p+1) ==
'x' || *(
p+1) ==
'X') )
2922 if (
'0' <= *
p && *
p <=
'9' )
2924 else if (
'A' <= *
p && *
p <=
'Z' )
2925 n = 10 + (*
p -
'A');
2926 else if (
'a' <= *
p && *
p <=
'z' )
2927 n = 10 + (*
p -
'a');
2933 ( (nBase == 2 && (*
p ==
'b' || *
p ==
'B'))
2934 ||(nBase == 16 && (*
p ==
'h' || *
p ==
'H')) )
2944 fVal = fVal * fBase +
n;
2983 double fMode = (nParamCount == 2) ? ::rtl::math::approxFloor(
GetDouble() ) : 0.0;
2984 double fVal = ::rtl::math::approxFloor(
GetDouble() );
2987 else if( (fMode >= 0.0) && (fMode < 5.0) && (fVal >= 0.0) && (fVal < 4000.0) )
2989 static const sal_Unicode pChars[] = {
'M',
'D',
'C',
'L',
'X',
'V',
'I' };
2990 static const sal_uInt16
pValues[] = { 1000, 500, 100, 50, 10, 5, 1 };
2993 OUStringBuffer aRoman;
2994 sal_uInt16 nVal =
static_cast<sal_uInt16
>(fVal);
2995 sal_uInt16 nMode =
static_cast<sal_uInt16
>(fMode);
2997 for( sal_uInt16
i = 0;
i <= nMaxIndex / 2;
i++ )
3002 if( (nDigit % 5) == 4 )
3005 assert( ((nDigit == 4) ? (
nIndex >= 1) : (
nIndex >= 2)));
3007 sal_uInt16 nIndex2 = (nDigit == 4) ?
nIndex - 1 :
nIndex - 2;
3008 sal_uInt16 nSteps = 0;
3009 while( (nSteps < nMode) && (
nIndex < nMaxIndex) )
3017 aRoman.append( pChars[
nIndex ] ).append( pChars[ nIndex2 ] );
3018 nVal = sal::static_int_cast<sal_uInt16>( nVal +
pValues[
nIndex ] );
3019 nVal = sal::static_int_cast<sal_uInt16>( nVal -
pValues[ nIndex2 ] );
3027 aRoman.append( pChars[
nIndex - 1 ] );
3029 sal_Int32 nPad = nDigit % 5;
3049 case 'M': rnValue = 1000; rbIsDec =
true;
break;
3050 case 'D': rnValue = 500; rbIsDec =
false;
break;
3051 case 'C': rnValue = 100; rbIsDec =
true;
break;
3052 case 'L': rnValue = 50; rbIsDec =
false;
break;
3053 case 'X': rnValue = 10; rbIsDec =
true;
break;
3054 case 'V': rnValue = 5; rbIsDec =
false;
break;
3055 case 'I': rnValue = 1; rbIsDec =
true;
break;
3056 default:
return false;
3068 aRoman = aRoman.toAsciiUpperCase();
3071 sal_uInt16 nValidRest = 3999;
3072 sal_Int32 nCharIndex = 0;
3073 sal_Int32 nCharCount = aRoman.getLength();
3076 while( bValid && (nCharIndex < nCharCount) )
3078 sal_uInt16 nDigit1 = 0;
3079 sal_uInt16 nDigit2 = 0;
3080 bool bIsDec1 =
false;
3082 if( bValid && (nCharIndex + 1 < nCharCount) )
3084 bool bIsDec2 =
false;
3089 if( nDigit1 >= nDigit2 )
3091 nValue = sal::static_int_cast<sal_uInt16>(
nValue + nDigit1 );
3092 nValidRest %= (nDigit1 * (bIsDec1 ? 5 : 2));
3093 bValid = (nValidRest >= nDigit1);
3095 nValidRest = sal::static_int_cast<sal_uInt16>( nValidRest - nDigit1 );
3098 else if( nDigit1 * 2 != nDigit2 )
3100 sal_uInt16 nDiff = nDigit2 - nDigit1;
3101 nValue = sal::static_int_cast<sal_uInt16>(
nValue + nDiff );
3102 bValid = (nValidRest >= nDiff);
3104 nValidRest = nDigit1 - 1;
3128 if ( nParamCount == 2 )
3152 if (nErr != FormulaError::NONE)
3176 SetError( FormulaError::IllegalArgument);
3186 if (nParamCount == 2 ||
nGlobalError != FormulaError::NONE)
3189 pResMat->PutDouble( fVal, 0);
3191 pResMat->PutString(
aStr, 0);
3193 pResMat->PutDouble( 0.0, 0 );
3196 pResMat->PutString(aUrl, 0);
3197 pResMat->PutString(aUrl, 1);
3210 const char* pCurrText;
3214 static const ConvertInfo aConvertTable[] = {
3216 {
"ATS", 13.7603, 2 },
3217 {
"BEF", 40.3399, 0 },
3218 {
"DEM", 1.95583, 2 },
3219 {
"ESP", 166.386, 0 },
3220 {
"FIM", 5.94573, 2 },
3221 {
"FRF", 6.55957, 2 },
3222 {
"IEP", 0.787564, 2 },
3223 {
"ITL", 1936.27, 0 },
3224 {
"LUF", 40.3399, 0 },
3225 {
"NLG", 2.20371, 2 },
3226 {
"PTE", 200.482, 2 },
3227 {
"GRD", 340.750, 2 },
3228 {
"SIT", 239.640, 2 },
3229 {
"MTL", 0.429300, 2 },
3230 {
"CYP", 0.585274, 2 },
3231 {
"SKK", 30.1260, 2 },
3232 {
"EEK", 15.6466, 2 },
3233 {
"LVL", 0.702804, 2 },
3234 {
"LTL", 3.45280, 2 },
3235 {
"HRK", 7.53450, 2 }
3238 for (
const auto &
i : aConvertTable)
3239 if ( aSearchUnit.equalsIgnoreAsciiCaseAscii(
i.pCurrText ) )
3254 double fPrecision = 0.0;
3255 if ( nParamCount == 5 )
3257 fPrecision = ::rtl::math::approxFloor(
GetDouble());
3258 if ( fPrecision < 3 )
3265 bool bFullPrecision = nParamCount >= 4 &&
GetBool();
3281 if ( aFromUnit.equalsIgnoreAsciiCase( aToUnit ) )
3285 if ( aFromUnit.equalsIgnoreAsciiCase(
"EUR" ) )
3286 fRes = fVal * fToRate;
3289 double fIntermediate = fVal / fFromRate;
3291 fIntermediate = ::rtl::math::round( fIntermediate,
3292 static_cast<int>(fPrecision) );
3293 fRes = fIntermediate * fToRate;
3295 if ( !bFullPrecision )
3296 fRes = ::rtl::math::round( fRes, nToDec );
3306#define UTF8_TH_0 "\340\270\250\340\270\271\340\270\231\340\270\242\340\271\214"
3307#define UTF8_TH_1 "\340\270\253\340\270\231\340\270\266\340\271\210\340\270\207"
3308#define UTF8_TH_2 "\340\270\252\340\270\255\340\270\207"
3309#define UTF8_TH_3 "\340\270\252\340\270\262\340\270\241"
3310#define UTF8_TH_4 "\340\270\252\340\270\265\340\271\210"
3311#define UTF8_TH_5 "\340\270\253\340\271\211\340\270\262"
3312#define UTF8_TH_6 "\340\270\253\340\270\201"
3313#define UTF8_TH_7 "\340\271\200\340\270\210\340\271\207\340\270\224"
3314#define UTF8_TH_8 "\340\271\201\340\270\233\340\270\224"
3315#define UTF8_TH_9 "\340\271\200\340\270\201\340\271\211\340\270\262"
3316#define UTF8_TH_10 "\340\270\252\340\270\264\340\270\232"
3317#define UTF8_TH_11 "\340\271\200\340\270\255\340\271\207\340\270\224"
3318#define UTF8_TH_20 "\340\270\242\340\270\265\340\271\210"
3319#define UTF8_TH_1E2 "\340\270\243\340\271\211\340\270\255\340\270\242"
3320#define UTF8_TH_1E3 "\340\270\236\340\270\261\340\270\231"
3321#define UTF8_TH_1E4 "\340\270\253\340\270\241\340\270\267\340\271\210\340\270\231"
3322#define UTF8_TH_1E5 "\340\271\201\340\270\252\340\270\231"
3323#define UTF8_TH_1E6 "\340\270\245\340\271\211\340\270\262\340\270\231"
3324#define UTF8_TH_DOT0 "\340\270\226\340\271\211\340\270\247\340\270\231"
3325#define UTF8_TH_BAHT "\340\270\232\340\270\262\340\270\227"
3326#define UTF8_TH_SATANG "\340\270\252\340\270\225\340\270\262\340\270\207\340\270\204\340\271\214"
3327#define UTF8_TH_MINUS "\340\270\245\340\270\232"
3332void lclSplitBlock(
double& rfInt, sal_Int32& rnBlock,
double fValue,
double fSize )
3334 rnBlock =
static_cast< sal_Int32
>( modf( (fValue + 0.1) / fSize, &rfInt ) * fSize + 0.1 );
3338void lclAppendDigit( OStringBuffer& rText, sal_Int32 nDigit )
3342 case 0: rText.append(
UTF8_TH_0 );
break;
3343 case 1: rText.append(
UTF8_TH_1 );
break;
3344 case 2: rText.append(
UTF8_TH_2 );
break;
3345 case 3: rText.append(
UTF8_TH_3 );
break;
3346 case 4: rText.append(
UTF8_TH_4 );
break;
3347 case 5: rText.append(
UTF8_TH_5 );
break;
3348 case 6: rText.append(
UTF8_TH_6 );
break;
3349 case 7: rText.append(
UTF8_TH_7 );
break;
3350 case 8: rText.append(
UTF8_TH_8 );
break;
3351 case 9: rText.append(
UTF8_TH_9 );
break;
3352 default: OSL_FAIL(
"lclAppendDigit - illegal digit" );
3360void lclAppendPow10( OStringBuffer& rText, sal_Int32 nDigit, sal_Int32 nPow10 )
3362 OSL_ENSURE( (1 <= nDigit) && (nDigit <= 9),
"lclAppendPow10 - illegal digit" );
3363 lclAppendDigit( rText, nDigit );
3370 default: OSL_FAIL(
"lclAppendPow10 - illegal power" );
3375void lclAppendBlock( OStringBuffer& rText, sal_Int32
nValue )
3377 OSL_ENSURE( (1 <=
nValue) && (
nValue <= 999999),
"lclAppendBlock - illegal value" );
3380 lclAppendPow10( rText,
nValue / 100000, 5 );
3385 lclAppendPow10( rText,
nValue / 10000, 4 );
3390 lclAppendPow10( rText,
nValue / 1000, 3 );
3395 lclAppendPow10( rText,
nValue / 100, 2 );
3401 sal_Int32 nTen =
nValue / 10;
3402 sal_Int32 nOne =
nValue % 10;
3406 lclAppendDigit( rText, nTen );
3407 else if( nTen == 2 )
3411 if( (nTen > 0) && (nOne == 1) )
3414 lclAppendDigit( rText, nOne );
3433 bool bMinus = fValue < 0.0;
3434 fValue = std::abs( fValue );
3437 fValue = ::rtl::math::approxFloor( fValue * 100.0 + 0.5 );
3441 sal_Int32 nSatang = 0;
3442 lclSplitBlock( fBaht, nSatang, fValue, 100.0 );
3444 OStringBuffer aText;
3452 else while( fBaht > 0.0 )
3454 OStringBuffer aBlock;
3455 sal_Int32 nBlock = 0;
3456 lclSplitBlock( fBaht, nBlock, fBaht, 1.0e6 );
3458 lclAppendBlock( aBlock, nBlock );
3463 aText.insert(0, aBlock);
3465 if (!aText.isEmpty())
3475 lclAppendBlock( aText, nSatang );
3483 PushString( OStringToOUString(aText, RTL_TEXTENCODING_UTF8) );
3496 bool bOldSyntax =
false;
3497 if (nParamCount == 2)
3505 std::vector<sheet::DataPilotFieldFilter> aFilters;
3506 OUString aDataFieldName;
3534 sal_uInt16 nFilterCount = nParamCount / 2 - 1;
3535 aFilters.resize(nFilterCount);
3537 sal_uInt16
i = nFilterCount;
3544 bool bEvaluateFormatIndex;
3549 bEvaluateFormatIndex =
true;
3552 bEvaluateFormatIndex =
false;
3566 sal_uInt32 nNumFormat;
3576 const Color* pColor;
3583 aFilters[
i].MatchValueName = aSharedString.
getString();
3587 sal_uInt32 nNumFormat = 0;
3593 aFilters[
i].MatchValue = aFilters[
i].MatchValueName;
3638 OUString aFilterStr = aDataFieldName;
3639 std::vector<sal_Int16> aFilterFuncs;
3640 if (!pDPObj->
ParseFilters(aDataFieldName, aFilters, aFilterFuncs, aFilterStr))
3651 double fVal = pDPObj->
GetPivotData(aDataFieldName, aFilters);
3652 if (std::isnan(fVal))
const PropertyValue * pValues
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 ...
sal_uInt16 GetWeekOfYear(DayOfWeek eStartDay=MONDAY, sal_Int16 nMinimumNumberOfDaysInWeek=4) const
void AddDays(sal_Int32 nAddDays)
bool IsValidAndGregorian() const
sal_Int16 GetYear() const
sal_uInt16 GetDay() const
void SetMonth(sal_uInt16 nNewMonth)
void SetYear(sal_Int16 nNewYear)
static sal_Int32 DateToDays(sal_uInt16 nDay, sal_uInt16 nMonth, sal_Int16 nYear)
DayOfWeek GetDayOfWeek() const
void SetDay(sal_uInt16 nNewDay)
sal_uInt16 GetMonth() const
This class provides LO with Kahan summation algorithm About this algorithm: https://en....
double get() const
Returns the final sum.
move ScAutoStyleHint to a different file?
static OUString GetLocaleIndependentFormattedString(double fValue, SvNumberFormatter &rFormatter, sal_uInt32 nNumFormat)
bool ParseFilters(OUString &rDataFieldName, std::vector< css::sheet::DataPilotFieldFilter > &rFilters, std::vector< sal_Int16 > &rFilterFuncs, std::u16string_view rFilterList)
double GetPivotData(const OUString &rDataFieldName, std::vector< css::sheet::DataPilotFieldFilter > &rFilters)
ScSheetLimits & GetSheetLimits() const
bool IsIdleEnabled() const
ScDPObject * GetDPAtBlock(const ScRange &rBlock) const
const ScStyleSheet * GetStyle(SCCOL nCol, SCROW nRow, SCTAB nTab) const
SfxBindings * GetViewBindings()
bool HasLinkFormulaNeedingCheck() const
bool IsClipOrUndo() const
void EnableIdle(bool bDo)
SfxObjectShell * GetDocumentShell() const
static SC_DLLPUBLIC LanguageType eLnge
static ScUnitConverter * GetUnitConverter()
bool GetNext(double &rValue, FormulaError &rErr)
Does NOT reset rValue if no value found!
formula::FormulaConstTokenRef PopToken()
void SetError(FormulaError nError)
double GetDateSerial(sal_Int16 nYear, sal_Int16 nMonth, sal_Int16 nDay, bool bStrict)
Obtain the date serial number for a given date.
svl::SharedString GetString()
static double ScGetPV(double fRate, double fNper, double fPmt, double fFv, bool bPayInAdvance)
void ScGetIsoWeekOfYear()
static bool RateIteration(double fNper, double fPayment, double fPv, double fFv, bool bPayType, double &fGuess)
FormulaError GetWeekendAndHolidayMasks(const sal_uInt8 nParamCount, const sal_uInt32 nNullDate, ::std::vector< double > &rSortArray, bool bWeekendMask[7])
bool MustHaveParamCount(short nAct, short nMust)
bool MustHaveParamCountMin(short nAct, short nMin)
static FormulaError GetCellErrCode(const ScRefCellValue &rCell)
SubtotalFlags mnSubTotalFlags
void PushIllegalParameter()
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 PushDoubleRef(SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2)
static void RoundSignificant(double fX, double fDigits, double &fRes)
formula::StackVar GetRawStackType()
Raw stack type without default replacements.
ScInterpreterContext & mrContext
double ScGetIpmt(double fRate, double fPer, double fNper, double fPv, double fFv, bool bPayInAdvance, double &fPmt)
SvNumFormatType nFuncFmtType
sal_uInt32 GetUInt32()
if GetDouble() not within uint32 limits sets nGlobalError and returns SAL_MAX_UINT32
void GetCellString(svl::SharedString &rStr, ScRefCellValue &rCell)
bool PopDoubleRefOrSingleRef(ScAddress &rAdr)
void ValidateRef(const ScSingleRefData &rRef)
void PushError(FormulaError nError)
sal_uInt8 GetByte() const
FormulaError GetWeekendAndHolidayMasks_MS(const sal_uInt8 nParamCount, const sal_uInt32 nNullDate, ::std::vector< double > &rSortArray, bool bWeekendMask[7], bool bWorkdayFunction)
ScMatrixRef GetNewMat(SCSIZE nC, SCSIZE nR, bool bEmpty=false)
static double ScGetPMT(double fRate, double fNper, double fPv, double fFv, bool bPayInAdvance)
ScMatValType GetDoubleOrStringFromMatrix(double &rDouble, svl::SharedString &rString)
static double ScGetDDB(double fCost, double fSalvage, double fLife, double fPeriod, double fFactor)
void PushDouble(double nVal)
void PopSingleRef(ScAddress &)
void ReverseStack(sal_uInt8 nParamCount)
SvNumberFormatter * pFormatter
static double div(const double &fNumerator, const double &fDenominator)
Fail safe division, returning a FormulaError::DivisionByZero coded into a double if denominator is 0....
static sal_Int16 GetDayOfWeek(sal_Int32 n)
static double ScInterVDB(double fCost, double fSalvage, double fLife, double fLife1, double fPeriod, double fFactor)
sfx2::LinkManager * mpLinkManager
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 PushMatrix(const sc::RangeMatrix &rMat)
void GetNumberSequenceArray(sal_uInt8 nParamCount, ::std::vector< double > &rArray, bool bConvertTextInArray)
static double ScGetFV(double fRate, double fNper, double fPmt, double fPv, bool bPayInAdvance)
void ScCeil(bool bODFF)
tdf69552 ODFF1.2 function CEILING and Excel function CEILING.MATH In essence, the difference between ...
ScFormulaCell * pMyFormulaCell
double GetCellValue(const ScAddress &, ScRefCellValue &rCell)
void PushTempToken(formula::FormulaToken *)
Does substitute with formula::FormulaErrorToken in case nGlobalError is set and the token passed is n...
void PushSingleRef(SCCOL nCol, SCROW nRow, SCTAB nTab)
void ScNetWorkdays(bool bOOXML_Version)
void GetSortArray(sal_uInt8 nParamCount, ::std::vector< double > &rSortArray, ::std::vector< tools::Long > *pIndexOrder, bool bConvertTextInArray, bool bAllowEmptyArray)
double GetDoubleWithDefault(double nDefault)
void ScFloor(bool bODFF)
tdf69552 ODFF1.2 function FLOOR and Excel function FLOOR.MATH In essence, the difference between the ...
void ScRoundSignificant()
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...
SvNumFormatType nCurFmtType
void PushString(const OUString &rStr)
void RoundNumber(rtl_math_RoundingMode eMode)
void PushStringBuffer(const sal_Unicode *pString)
Matrix data type that can store values of mixed types.
void MatCopy(const ScMatrix &mRes) const
static bool IsValueType(ScMatValType nType)
Value or boolean.
static bool IsRealStringType(ScMatValType nType)
String, but not empty or empty path or any other type.
void GetDimensions(SCSIZE &rC, SCSIZE &rR) const
virtual const ScRefList * GetRefList() const override
bool GetFirst(double &rValue, FormulaError &rErr)
Does NOT reset rValue if no value found!
bool GetNext(double &rValue, FormulaError &rErr)
Does NOT reset rValue if no value found!
void Invalidate(sal_uInt16 nId)
const OUString & GetName() const
bool StartListening(SvtBroadcaster &rBroadcaster)
void InsertDDELink(SvBaseLink *, const OUString &rServer, std::u16string_view rTopic, std::u16string_view rItem)
const SvBaseLinks & GetLinks() const
const OUString & getString() const
sal_Int32 getLength() const
const sal_uInt8 SC_DDE_TEXT
const sal_uInt8 SC_DDE_DEFAULT
double CreateDoubleError(FormulaError nErr)
static bool lcl_GetArabicValue(sal_Unicode cChar, sal_uInt16 &rnValue, bool &rbIsDec)
static ScDdeLink * lcl_GetDdeLink(const sfx2::LinkManager *pLinkMgr, std::u16string_view rA, std::u16string_view rT, std::u16string_view rI, sal_uInt8 nM)
static bool lclConvertMoney(const OUString &aSearchUnit, double &rfRate, int &rnDec)
Resources at the website of the European Commission: http://ec.europa.eu/economy_finance/euro/adoptio...
#define SAL_N_ELEMENTS(arr)
OStringBuffer & padToLength(OStringBuffer &rBuffer, sal_Int32 nLength, char cFill='\0')
constexpr sal_Int64 md(U i, U)
constexpr std::enable_if_t< std::is_floating_point_v< F > &&std::is_integral_v< I >, bool > convertsToAtMost(F value, I max)
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
const wchar_t *typedef int(__stdcall *DllNativeUnregProc)(int
Complex reference (a range) into the sheet.
void InitRange(const ScRange &rRange)
This is very similar to ScCellValue, except that it references the original value instead of copying ...
FormulaTokenRef extendRangeReference(ScSheetLimits &rLimits, FormulaToken &rTok1, FormulaToken &rTok2, const ScAddress &rPos, bool bReuseDoubleRef)
If rTok1 and rTok2 both are SingleRef or DoubleRef tokens, extend/merge ranges as needed for ocRange.
::std::vector< ScComplexRefData > ScRefList
::boost::intrusive_ptr< ScMatrix > ScMatrixRef
::boost::intrusive_ptr< formula::FormulaToken > ScTokenRef