32#include <osl/diagnose.h>
38#include <document.hxx>
40#include <unitconv.hxx>
43#include <tokenarray.hxx>
46#include <stlsheet.hxx>
49#include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
57#define SCdEpsilon 1.0E-7
64 if ( nYear < 100 && !bStrict )
79 nY = nYear + (nMonth-1) / 12;
80 nM = ((nMonth-1) % 12) + 1;
84 nY = nYear + (nMonth-12) / 12;
85 nM = 12 - (-nMonth) % 12;
89 Date aDate( nD, nM, nY);
118 PushDouble(
static_cast<double>(nDiff) + fTime );
144 sal_uInt16 nHour, nMinute, nSecond;
145 double fFractionOfSecond;
152 sal_uInt16 nHour, nMinute, nSecond;
153 double fFractionOfSecond;
155 if ( fFractionOfSecond >= 0.5 )
156 nSecond = ( nSecond + 1 ) % 60;
163 sal_uInt16 nHour, nMinute, nSecond;
164 double fFractionOfSecond;
172 sal_uInt32 nFIndex = 0;
177 if (
eType == SvNumFormatType::DATE ||
eType == SvNumFormatType::DATETIME)
196 if (nParamCount == 2)
225 if (nVal < nFlag - 11)
231 SetError( FormulaError::IllegalArgument);
254 sal_Int16 nFlag = ( nParamCount == 1 ) ? 1 :
GetInt16();
259 sal_Int32 nMinimumNumberOfDaysInWeek;
265 nMinimumNumberOfDaysInWeek = 1;
269 nMinimumNumberOfDaysInWeek = 1;
278 eFirstDayOfWeek =
static_cast<DayOfWeek>( nFlag - 11 );
279 nMinimumNumberOfDaysInWeek = 1;
285 nMinimumNumberOfDaysInWeek = 4;
291 PushInt(
static_cast<int>(aDate.
GetWeekOfYear( eFirstDayOfWeek, nMinimumNumberOfDaysInWeek )) );
318 if (nYear < 1583 || nYear > 9956)
325 int B,
C,
D,
E,
F,
G,
H,
I,K,L,
M,
N,O;
327 B =
int(nYear / 100);
331 F =
int((
B + 8) / 25);
333 H = (19 *
N +
B -
D -
G + 15) % 30;
336 L = (32 + 2 *
E + 2 *
I -
H - K) % 7;
337 M =
int((
N + 11 *
H + 22 * L) / 451);
338 O =
H + L - 7 *
M + 114;
339 sal_Int16 nDay = sal::static_int_cast<sal_Int16>( O % 31 + 1 );
340 sal_Int16 nMonth = sal::static_int_cast<sal_Int16>(
int(O / 31) );
345 const sal_uInt8 nParamCount,
const sal_uInt32 nNullDate, vector< double >& rSortArray,
346 bool bWeekendMask[ 7 ] )
348 if ( nParamCount == 4 )
350 vector< double > nWeekendDays;
356 if ( nWeekendDays.size() != 7 )
357 return FormulaError::IllegalArgument;
360 for (
int i = 0;
i < 7;
i++ )
361 bWeekendMask[
i ] =
static_cast<bool>(nWeekendDays[ (
i == 6 ? 0 :
i + 1 ) ]);
366 for (
int i = 0;
i < 7;
i++ )
367 bWeekendMask[
i] =
false;
370 bWeekendMask[
SUNDAY ] =
true;
373 if ( nParamCount >= 3 )
376 size_t nMax = rSortArray.size();
377 for (
size_t i = 0;
i < nMax;
i++ )
378 rSortArray.at(
i ) = ::rtl::math::approxFloor( rSortArray.at(
i ) ) + nNullDate;
385 const sal_uInt8 nParamCount,
const sal_uInt32 nNullDate, vector< double >& rSortArray,
386 bool bWeekendMask[ 7 ],
bool bWorkdayFunction )
389 OUString aWeekendDays;
390 if ( nParamCount == 4 )
393 size_t nMax = rSortArray.size();
394 for (
size_t i = 0;
i < nMax;
i++ )
395 rSortArray.at(
i ) = ::rtl::math::approxFloor( rSortArray.at(
i ) ) + nNullDate;
398 if ( nParamCount >= 3 )
408 return FormulaError::NoValue;
417 if ( fDouble >= 1.0 && fDouble <= 17 )
418 aWeekendDays = OUString::number( fDouble );
420 return FormulaError::NoValue;
425 ( bWorkdayFunction && aSharedString.
getString() ==
"1111111" ) )
426 return FormulaError::NoValue;
428 aWeekendDays = aSharedString.
getString();
436 for (
int i = 0;
i < 7;
i++ )
437 bWeekendMask[
i] =
false;
439 if ( aWeekendDays.isEmpty() )
442 bWeekendMask[
SUNDAY ] =
true;
446 switch ( aWeekendDays.getLength() )
450 switch ( aWeekendDays[ 0 ] )
452 case '1' : bWeekendMask[
SATURDAY ] =
true; bWeekendMask[
SUNDAY ] =
true;
break;
453 case '2' : bWeekendMask[
SUNDAY ] =
true; bWeekendMask[
MONDAY ] =
true;
break;
454 case '3' : bWeekendMask[
MONDAY ] =
true; bWeekendMask[
TUESDAY ] =
true;
break;
455 case '4' : bWeekendMask[
TUESDAY ] =
true; bWeekendMask[
WEDNESDAY ] =
true;
break;
456 case '5' : bWeekendMask[
WEDNESDAY ] =
true; bWeekendMask[
THURSDAY ] =
true;
break;
457 case '6' : bWeekendMask[
THURSDAY ] =
true; bWeekendMask[
FRIDAY ] =
true;
break;
458 case '7' : bWeekendMask[
FRIDAY ] =
true; bWeekendMask[
SATURDAY ] =
true;
break;
459 default : nErr = FormulaError::IllegalArgument;
break;
464 if ( aWeekendDays[ 0 ] ==
'1' )
466 switch ( aWeekendDays[ 1 ] )
468 case '1' : bWeekendMask[
SUNDAY ] =
true;
break;
469 case '2' : bWeekendMask[
MONDAY ] =
true;
break;
470 case '3' : bWeekendMask[
TUESDAY ] =
true;
break;
471 case '4' : bWeekendMask[
WEDNESDAY ] =
true;
break;
472 case '5' : bWeekendMask[
THURSDAY ] =
true;
break;
473 case '6' : bWeekendMask[
FRIDAY ] =
true;
break;
474 case '7' : bWeekendMask[
SATURDAY ] =
true;
break;
475 default : nErr = FormulaError::IllegalArgument;
break;
479 nErr = FormulaError::IllegalArgument;
483 for (
int i = 0;
i < 7 && nErr == FormulaError::NONE;
i++ )
485 switch ( aWeekendDays[
i ] )
487 case '0' : bWeekendMask[
i ] =
false;
break;
488 case '1' : bWeekendMask[
i ] =
true;
break;
489 default : nErr = FormulaError::IllegalArgument;
break;
494 nErr = FormulaError::IllegalArgument;
507 vector<double> nSortArray;
508 bool bWeekendMask[ 7 ];
512 if ( bOOXML_Version )
515 nSortArray, bWeekendMask,
false );
520 nSortArray, bWeekendMask );
522 if ( nErr != FormulaError::NONE )
538 bool bReverse = ( nDate1 > nDate2 );
540 std::swap( nDate1, nDate2 );
541 size_t nMax = nSortArray.size();
542 while ( nDate1 <= nDate2 )
546 while (
nRef < nMax && nSortArray.at(
nRef ) < nDate1 )
548 if (
nRef >= nMax || nSortArray.at(
nRef ) != nDate1 )
553 PushDouble(
static_cast<double>( bReverse ? -nCnt : nCnt ) );
564 vector<double> nSortArray;
565 bool bWeekendMask[ 7 ];
569 nSortArray, bWeekendMask,
true );
570 if ( nErr != FormulaError::NONE )
584 PushDouble(
static_cast<double>( nDate - nNullDate ) );
587 size_t nMax = nSortArray.size();
599 while (
nRef < nMax && nSortArray.at(
nRef ) < nDate )
602 if (
nRef >= nMax || nSortArray.at(
nRef ) != nDate ||
nRef >= nMax )
608 sal_Int16
nRef = nMax - 1;
617 while (
nRef >= 0 && nSortArray.at(
nRef ) > nDate )
620 if (
nRef < 0 || nSortArray.at(
nRef) != nDate)
624 PushDouble(
static_cast<double>( nDate - nNullDate ) );
638 SetError( FormulaError::ParameterExpected);
703 bool bFlag = nParamCount == 3 &&
GetBool();
713 if (bFlag && (nDate2 < nDate1))
726 if (aDate1.
GetDay() == 31)
732 switch ( aDate1.
GetDay() )
744 if (aDate2.
GetDay() == 31)
748 if (aDate1.
GetDay() == 30)
755 (
static_cast<double>(aDate2.
GetDay()) +
static_cast<double>(aDate2.
GetMonth()) * 30.0 +
756 static_cast<double>(aDate2.
GetYear()) * 360.0
757 -
static_cast<double>(aDate1.
GetDay()) -
static_cast<double>(aDate1.
GetMonth()) * 30.0
758 -
static_cast<double>(aDate1.
GetYear()) * 360.0) );
785 double dd = nDate2 - nDate1;
787 if (dd == 0.0 || aInterval.equalsIgnoreAsciiCase(
"d" ))
794 sal_uInt16 d1, m1, d2, m2;
808 if (y1 < 0 && y2 > 0)
810 else if (y1 > 0 && y2 < 0)
813 if ( aInterval.equalsIgnoreAsciiCase(
"m" ) )
816 int md = m2 - m1 + 12 * (y2 - y1);
821 else if ( aInterval.equalsIgnoreAsciiCase(
"y" ) )
827 if (m2 > m1 || (m2 == m1 && d2 >= d1))
840 else if ( aInterval.equalsIgnoreAsciiCase(
"md" ) )
865 aDate1.
SetYear( y2 == 1 ? -1 : y2 - 1 );
874 nd = aDate2 - aDate1;
878 else if ( aInterval.equalsIgnoreAsciiCase(
"ym" ) )
881 int md = m2 - m1 + 12 * (y2 - y1);
887 else if ( aInterval.equalsIgnoreAsciiCase(
"yd" ) )
892 if (m2 > m1 || (m2 == m1 && d2 >= d1))
905 double fd = aDate2 - aDate1;
915 sal_uInt32 nFIndex = 0;
920 if (
eType == SvNumFormatType::TIME ||
eType == SvNumFormatType::DATETIME)
923 double fDateVal = rtl::math::approxFloor(fVal);
924 double fTimeVal = fVal - fDateVal;
962 if (nParamCount == 1)
974 constexpr sal_Int16 kSigDig = 12;
976 if ( (
eMode == rtl_math_RoundingMode_Down ||
977 eMode == rtl_math_RoundingMode_Up ) &&
978 nDec < kSigDig && fmod( fX, 1.0 ) != 0.0 )
990 const double fTemp = floor( log10( std::abs(fRes))) + 1.0 - kSigDig;
993 fRes *= pow(10.0, -fTemp);
995 fRes /= pow(10.0, fTemp);
996 if (std::isfinite(fRes))
1002 if (
eMode == rtl_math_RoundingMode_Up)
1003 fRes = ::rtl::math::approxFloor(fRes);
1004 fVal = ::rtl::math::round( fRes, nDec + fTemp,
eMode );
1006 fVal /= pow(10.0, -fTemp);
1008 fVal *= pow(10.0, fTemp);
1013 fVal = ::rtl::math::round( fX, nDec,
eMode );
1017 fVal = ::rtl::math::round( fX, nDec,
eMode );
1040 double fTemp = floor( log10( std::abs(fX) ) ) + 1.0 - fDigits;
1044 fIn *= pow(10.0, -fTemp);
1046 fIn /= pow(10.0, fTemp);
1050 fRes = ::rtl::math::round(fIn);
1052 fRes /= pow(10.0, -fTemp);
1054 fRes *= pow(10.0, fTemp);
1063 double fDigits = ::rtl::math::approxFloor(
GetDouble() );
1065 if (
nGlobalError != FormulaError::NONE || fDigits < 1.0 )
1094 bool bAbs = nParamCount == 3 &&
GetBool();
1096 if ( nParamCount == 1 )
1099 fDec = ( fVal < 0 ? -1 : 1 );
1106 if ( bArgumentMissing )
1107 fDec = ( fVal < 0 ? -1 : 1 );
1109 if ( fVal == 0 || fDec == 0.0 )
1113 if ( bODFF && fVal * fDec < 0 )
1117 if ( fVal * fDec < 0.0 )
1120 if ( !bAbs && fVal < 0.0 )
1121 PushDouble(::rtl::math::approxFloor( fVal / fDec ) * fDec );
1123 PushDouble(::rtl::math::approxCeil( fVal / fDec ) * fDec );
1136 if ( fVal == 0 || fDec == 0.0 )
1138 else if ( fVal * fDec > 0 )
1139 PushDouble(::rtl::math::approxCeil( fVal / fDec ) * fDec );
1140 else if ( fVal < 0.0 )
1141 PushDouble(::rtl::math::approxFloor( fVal / -fDec ) * -fDec );
1153 if ( nParamCount == 1 )
1163 if ( fDec == 0.0 || fVal == 0.0 )
1166 PushDouble(::rtl::math::approxCeil( fVal / fDec ) * fDec );
1182 bool bAbs = ( nParamCount == 3 &&
GetBool() );
1184 if ( nParamCount == 1 )
1187 fDec = ( fVal < 0 ? -1 : 1 );
1194 if ( bArgumentMissing )
1195 fDec = ( fVal < 0 ? -1 : 1 );
1197 if ( fDec == 0.0 || fVal == 0.0 )
1201 if ( bODFF && ( fVal * fDec < 0.0 ) )
1205 if ( fVal * fDec < 0.0 )
1208 if ( !bAbs && fVal < 0.0 )
1209 PushDouble(::rtl::math::approxCeil( fVal / fDec ) * fDec );
1211 PushDouble(::rtl::math::approxFloor( fVal / fDec ) * fDec );
1227 else if ( fVal * fDec > 0 )
1228 PushDouble(::rtl::math::approxFloor( fVal / fDec ) * fDec );
1229 else if ( fDec == 0 )
1231 else if ( fVal < 0.0 )
1232 PushDouble(::rtl::math::approxCeil( fVal / -fDec ) * -fDec );
1245 if ( fDec == 0.0 || fVal == 0.0 )
1248 PushDouble(::rtl::math::approxFloor( fVal / fDec ) * fDec );
1255 PushDouble(::rtl::math::approxFloor(fVal/2.0) * 2.0);
1257 PushDouble(::rtl::math::approxCeil(fVal/2.0) * 2.0);
1265 fVal = ::rtl::math::approxCeil(fVal);
1266 if (fmod(fVal, 2.0) == 0.0)
1271 fVal = ::rtl::math::approxFloor(fVal);
1272 if (fmod(fVal, 2.0) == 0.0)
1294 double fBase = nParamCount == 2 ?
GetDouble() : 10.0;
1296 if (fVal > 0.0 && fBase > 0.0 && fBase != 1.0)
1323 short nParamCount =
GetByte();
1332 double fCount = 1.0;
1335 size_t nRefInList = 0;
1337 while (nParamCount-- > 0)
1343 fVal +=
GetDouble() / pow(1.0 + fRate, fCount);
1355 fVal += fCellVal / pow(1.0 + fRate, fCount);
1367 while ((nErr == FormulaError::NONE) && aValIter.
GetNext(fCellVal, nErr))
1369 fVal += fCellVal / pow(1.0 + fRate, fCount);
1372 if ( nErr != FormulaError::NONE )
1384 pMat->GetDimensions(nC, nR);
1385 if (nC == 0 || nR == 0)
1393 for (
SCSIZE j = 0; j < nC; j++ )
1395 for (
SCSIZE k = 0; k < nR; ++k)
1397 if (!pMat->IsValue(j,k))
1402 fx = pMat->GetDouble(j,k);
1403 fVal += fx / pow(1.0 + fRate, fCount);
1411 default :
SetError(FormulaError::IllegalParameter);
break;
1424 double fEstimated = nParamCount == 2 ?
GetDouble() : 0.1;
1427 double x = fEstimated == -1.0 ? 0.1 : fEstimated;
1434 bool bIsMatrix =
false;
1446 pMat->GetDimensions(nC, nR);
1447 if (nC == 0 || nR == 0)
1466 const sal_uInt16 nIterationsMax = 20;
1467 sal_uInt16 nItCount = 0;
1473 double fCount = 0.0;
1478 for (
SCSIZE k = 0; k < nR; k++)
1480 if (!pMat->IsValue(j, k))
1482 fValue = pMat->GetDouble(j, k);
1486 fNom += fValue / pow(1.0+
x,fCount);
1487 fDenom += -fCount * fValue / pow(1.0+
x,fCount+1.0);
1495 bool bLoop = aValIter.
GetFirst(fValue, nIterError);
1496 while (bLoop && nIterError == FormulaError::NONE)
1498 fNom += fValue / pow(1.0+
x,fCount);
1499 fDenom += -fCount * fValue / pow(1.0+
x,fCount+1.0);
1502 bLoop = aValIter.
GetNext(fValue, nIterError);
1506 double xNew =
x - fNom.
get() / fDenom.
get();
1508 fEps = std::abs(xNew -
x);
1511 if (fEstimated == 0.0 && std::abs(
x) <
SCdEpsilon)
1516 PushError( FormulaError::NoConvergence);
1525 double fRate1_reinvest =
GetDouble() + 1;
1532 bool bIsMatrix =
false;
1545 pMat->GetDimensions( nC, nR );
1546 if ( nC == 0 || nR == 0 )
1547 SetError( FormulaError::IllegalArgument );
1551 SetError( FormulaError::IllegalArgument );
1555 SetError( FormulaError::IllegalParameter );
1564 double fPow_reinvest = 1.0;
1566 double fPow_invest = 1.0;
1568 bool bHasPosValue =
false;
1569 bool bHasNegValue =
false;
1574 for (
SCSIZE j = 0; j < nC; j++ )
1576 for (
SCSIZE k = 0; k < nR; ++k )
1578 if ( !pMat->IsValue( j, k ) )
1580 fX = pMat->GetDouble( j, k );
1586 bHasPosValue =
true;
1587 fNPV_reinvest += fX * fPow_reinvest;
1589 else if ( fX < 0.0 )
1591 bHasNegValue =
true;
1592 fNPV_invest += fX * fPow_invest;
1594 fPow_reinvest /= fRate1_reinvest;
1595 fPow_invest /= fRate1_invest;
1606 bool bLoop = aValIter.
GetFirst( fCellValue, nIterError );
1609 if( fCellValue > 0.0 )
1611 bHasPosValue =
true;
1612 fNPV_reinvest += fCellValue * fPow_reinvest;
1614 else if( fCellValue < 0.0 )
1616 bHasNegValue =
true;
1617 fNPV_invest += fCellValue * fPow_invest;
1619 fPow_reinvest /= fRate1_reinvest;
1620 fPow_invest /= fRate1_invest;
1623 bLoop = aValIter.
GetNext( fCellValue, nIterError );
1626 if ( nIterError != FormulaError::NONE )
1629 if ( !( bHasPosValue && bHasNegValue ) )
1630 SetError( FormulaError::IllegalArgument );
1636 double fResult = -fNPV_reinvest.
get() / fNPV_invest.
get();
1637 fResult *= pow( fRate1_reinvest,
static_cast<double>(
nCount - 1 ) );
1638 fResult = pow( fResult,
div( 1.0, (
nCount - 1)) );
1656 PushDouble( fInvest * fRate * (fPeriod / fTotal - 1.0) );
1662 double fFv,
bool bPayInAdvance)
1666 fPv = fFv + fPmt * fNper;
1670 fPv = (fFv * pow(1.0 + fRate, -fNper))
1671 + (fPmt * (1.0 - pow(1.0 + fRate, -fNper + 1.0)) / fRate)
1674 fPv = (fFv * pow(1.0 + fRate, -fNper))
1675 + (fPmt * (1.0 - pow(1.0 + fRate, -fNper)) / fRate);
1687 bool bPayInAdvance = nParamCount == 5 &&
GetBool();
1688 double fFv = nParamCount >= 4 ?
GetDouble() : 0;
1704 double fSyd = ((fCost - fSalvage) * (fLife - fPer + 1.0)) /
1705 ((fLife * (fLife + 1.0)) / 2.0);
1711 double fPeriod,
double fFactor)
1713 double fDdb, fRate, fOldValue, fNewValue;
1714 fRate = fFactor / fLife;
1718 fOldValue = fPeriod == 1.0 ? fCost : 0;
1721 fOldValue = fCost * pow(1.0 - fRate, fPeriod - 1.0);
1722 fNewValue = fCost * pow(1.0 - fRate, fPeriod);
1724 fDdb = fNewValue < fSalvage ? fOldValue - fSalvage : fOldValue - fNewValue;
1725 return fDdb < 0 ? 0 : fDdb;
1735 double fFactor = nParamCount == 5 ?
GetDouble() : 2.0;
1740 if (fCost < 0.0 || fSalvage < 0.0 || fFactor <= 0.0 || fSalvage > fCost
1741 || fPeriod < 1.0 || fPeriod > fLife)
1753 double fMonths = nParamCount == 4 ? 12.0 : ::rtl::math::approxFloor(
GetDouble());
1758 if (fMonths < 1.0 || fMonths > 12.0 || fLife > 1200.0 || fSalvage < 0.0 ||
1759 fPeriod > (fLife + 1.0) || fSalvage > fCost || fCost <= 0.0 ||
1760 fLife <= 0 || fPeriod <= 0 )
1765 double fOffRate = 1.0 - pow(fSalvage / fCost, 1.0 / fLife);
1766 fOffRate = ::rtl::math::approxFloor((fOffRate * 1000.0) + 0.5) / 1000.0;
1767 double fFirstOffRate = fCost * fOffRate * fMonths / 12.0;
1769 if (::rtl::math::approxFloor(fPeriod) == 1)
1770 fDb = fFirstOffRate;
1773 KahanSum fSumOffRate = fFirstOffRate;
1774 double fMin = fLife;
1775 if (fMin > fPeriod) fMin = fPeriod;
1776 sal_uInt16 iMax =
static_cast<sal_uInt16
>(::rtl::math::approxFloor(fMin));
1777 for (sal_uInt16
i = 2;
i <= iMax;
i++)
1779 fDb = -(fSumOffRate - fCost).
get() * fOffRate;
1782 if (fPeriod > fLife)
1783 fDb = -(fSumOffRate - fCost).
get() * fOffRate * (12.0 - fMonths) / 12.0;
1789 double fLife1,
double fPeriod,
double fFactor)
1792 double fIntEnd = ::rtl::math::approxCeil(fPeriod);
1795 double fTerm, fSln = 0;
1796 double fSalvageValue = fCost - fSalvage;
1797 bool bNowSln =
false;
1801 for (
i = 1;
i <= nLoopEnd;
i++)
1805 fDdb =
ScGetDDB(fCost, fSalvage, fLife,
static_cast<double>(
i), fFactor);
1806 fSln = fSalvageValue/ (fLife1 -
static_cast<double>(
i-1));
1816 fSalvageValue -= fDdb;
1825 fTerm *= ( fPeriod + 1.0 - fIntEnd );
1840 bool bNoSwitch = nParamCount == 7 &&
GetBool();
1841 double fFactor = nParamCount >= 6 ?
GetDouble() : 2.0;
1847 if (fStart < 0.0 || fEnd < fStart || fEnd > fLife || fCost < 0.0
1848 || fSalvage > fCost || fFactor <= 0.0)
1852 double fIntStart = ::rtl::math::approxFloor(fStart);
1853 double fIntEnd = ::rtl::math::approxCeil(fEnd);
1861 double fTerm =
ScGetDDB(fCost, fSalvage, fLife,
static_cast<double>(
i), fFactor);
1864 if (
i == nLoopStart+1 )
1865 fTerm *= ( std::min( fEnd, fIntStart + 1.0 ) - fStart );
1866 else if (
i == nLoopEnd )
1867 fTerm *= ( fEnd + 1.0 - fIntEnd );
1876 if ( !::rtl::math::approxEqual( fStart, fIntStart ) ||
1877 !::rtl::math::approxEqual( fEnd, fIntEnd ) )
1879 if ( !::rtl::math::approxEqual( fStart, fIntStart ) )
1882 double fTempIntEnd = fIntStart + 1.0;
1883 double fTempValue = fCost -
1884 ScInterVDB( fCost, fSalvage, fLife, fLife, fIntStart, fFactor );
1885 fPart += ( fStart - fIntStart ) *
1886 ScInterVDB( fTempValue, fSalvage, fLife, fLife - fIntStart,
1887 fTempIntEnd - fIntStart, fFactor);
1889 if ( !::rtl::math::approxEqual( fEnd, fIntEnd ) )
1892 double fTempIntStart = fIntEnd - 1.0;
1893 double fTempValue = fCost -
1894 ScInterVDB( fCost, fSalvage, fLife, fLife, fTempIntStart, fFactor );
1895 fPart += ( fIntEnd - fEnd ) *
1896 ScInterVDB( fTempValue, fSalvage, fLife, fLife - fTempIntStart,
1897 fIntEnd - fTempIntStart, fFactor);
1901 fCost -=
ScInterVDB( fCost, fSalvage, fLife, fLife, fIntStart, fFactor );
1902 fVdb =
ScInterVDB( fCost, fSalvage, fLife, fLife - fIntStart,
1903 fIntEnd - fIntStart, fFactor);
1917 if ( fFuture <= 0.0 || fPresent <= 0.0 || fRate <= 0.0 )
1920 PushDouble( std::log( fFuture / fPresent ) / std::log1p( fRate ) );
1937 double fFv,
bool bPayInAdvance)
1941 fPayment = (fPv + fFv) / fNper;
1945 fPayment = (fFv + fPv * exp( fNper * ::std::log1p(fRate) ) ) * fRate /
1946 (std::expm1( (fNper + 1) * ::std::log1p(fRate) ) - fRate);
1948 fPayment = (fFv + fPv * exp(fNper * ::std::log1p(fRate) ) ) * fRate /
1949 std::expm1( fNper * ::std::log1p(fRate) );
1960 bool bPayInAdvance = nParamCount == 5 &&
GetBool();
1961 double fFv = nParamCount >= 4 ?
GetDouble() : 0;
1976 if ( fNrOfPeriods <= 0.0 || fPresentValue == 0.0 )
1979 PushDouble(pow(fFutureValue / fPresentValue, 1.0 / fNrOfPeriods) - 1.0);
1984 double fPv,
bool bPayInAdvance)
1988 fFv = fPv + fPmt * fNper;
1991 double fTerm = pow(1.0 + fRate, fNper);
1993 fFv = fPv * fTerm + fPmt*(1.0 + fRate)*(fTerm - 1.0)/fRate;
1995 fFv = fPv * fTerm + fPmt*(fTerm - 1.0)/fRate;
2006 bool bPayInAdvance = nParamCount == 5 &&
GetBool();
2007 double fPv = nParamCount >= 4 ?
GetDouble() : 0;
2019 bool bPayInAdvance = nParamCount == 5 &&
GetBool();
2020 double fFV = nParamCount >= 4 ?
GetDouble() : 0;
2026 if ( fPV + fFV == 0.0 )
2028 else if (fRate == 0.0)
2030 else if (bPayInAdvance)
2031 PushDouble(
log(-(fRate*fFV-fPmt*(1.0+fRate))/(fRate*fPV+fPmt*(1.0+fRate)))
2032 / std::log1p(fRate));
2034 PushDouble(
log(-(fRate*fFV-fPmt)/(fRate*fPV+fPmt)) / std::log1p(fRate));
2038 double fFv,
bool bPayType,
double & fGuess )
2045 bool bValid =
true, bFound =
false;
2046 double fX, fXnew, fTerm, fTermDerivation;
2047 double fGeoSeries, fGeoSeriesDerivation;
2048 const sal_uInt16 nIterationsMax = 150;
2050 const double fEpsilonSmall = 1.0E-14;
2054 fFv = fFv - fPayment;
2055 fPv = fPv + fPayment;
2057 if (fNper == ::rtl::math::round( fNper ))
2060 while (!bFound &&
nCount < nIterationsMax)
2062 double fPowN, fPowNminus1;
2063 fPowNminus1 = pow( 1.0+fX, fNper-1.0);
2064 fPowN = fPowNminus1 * (1.0+fX);
2068 fGeoSeriesDerivation = fNper * (fNper-1.0)/2.0;
2072 fGeoSeries = (fPowN-1.0)/fX;
2073 fGeoSeriesDerivation = fNper * fPowNminus1 / fX - fGeoSeries / fX;
2075 fTerm = fFv + fPv *fPowN+ fPayment * fGeoSeries;
2076 fTermDerivation = fPv * fNper * fPowNminus1 + fPayment * fGeoSeriesDerivation;
2077 if (std::abs(fTerm) < fEpsilonSmall)
2081 if (fTermDerivation == 0.0)
2084 fXnew = fX - fTerm / fTermDerivation;
2087 bFound = (std::abs(fXnew - fX) <
SCdEpsilon);
2097 bValid = (fX > -1.0);
2101 fX = (fGuess < -1.0) ? -1.0 : fGuess;
2102 while (bValid && !bFound &&
nCount < nIterationsMax)
2107 fGeoSeriesDerivation = fNper * (fNper-1.0)/2.0;
2111 fGeoSeries = (pow( 1.0+fX, fNper) - 1.0) / fX;
2112 fGeoSeriesDerivation = fNper * pow( 1.0+fX, fNper-1.0) / fX - fGeoSeries / fX;
2114 fTerm = fFv + fPv *pow(1.0 + fX,fNper)+ fPayment * fGeoSeries;
2115 fTermDerivation = fPv * fNper * pow( 1.0+fX, fNper-1.0) + fPayment * fGeoSeriesDerivation;
2116 if (std::abs(fTerm) < fEpsilonSmall)
2120 if (fTermDerivation == 0.0)
2123 fXnew = fX - fTerm / fTermDerivation;
2126 bFound = (std::abs(fXnew - fX) <
SCdEpsilon);
2128 bValid = (fX >= -1.0);
2133 return bValid && bFound;
2145 double fGuess = nParamCount == 6 ?
GetDouble() : 0.1;
2146 bool bDefaultGuess = nParamCount != 6;
2147 bool bPayType = nParamCount >= 5 &&
GetBool();
2148 double fFv = nParamCount >= 4 ?
GetDouble() : 0;
2152 double fOrigGuess = fGuess;
2159 bool bValid =
RateIteration(fNper, fPayment, fPv, fFv, bPayType, fGuess);
2174 double fX = fOrigGuess;
2175 for (
int nStep = 2; nStep <= 10 && !bValid; ++nStep)
2177 fGuess = fX * nStep;
2178 bValid =
RateIteration( fNper, fPayment, fPv, fFv, bPayType, fGuess);
2181 fGuess = fX / nStep;
2182 bValid =
RateIteration( fNper, fPayment, fPv, fFv, bPayType, fGuess);
2187 SetError(FormulaError::NoConvergence);
2193 double fFv,
bool bPayInAdvance,
double& fPmt)
2195 fPmt =
ScGetPMT(fRate, fNper, fPv, fFv, bPayInAdvance);
2199 fIpmt = bPayInAdvance ? 0.0 : -fPv;
2203 fIpmt =
ScGetFV(fRate, fPer-2.0, fPmt, fPv,
true) - fPmt;
2205 fIpmt =
ScGetFV(fRate, fPer-1.0, fPmt, fPv,
false);
2207 return fIpmt * fRate;
2216 bool bPayInAdvance = nParamCount == 6 &&
GetBool();
2217 double fFv = nParamCount >= 5 ?
GetDouble() : 0;
2222 if (fPer < 1.0 || fPer > fNper)
2237 bool bPayInAdvance = nParamCount == 6 &&
GetBool();
2238 double fFv = nParamCount >= 5 ?
GetDouble() : 0;
2243 if (fPer < 1.0 || fPer > fNper)
2248 double fInterestPer =
ScGetIpmt(fRate, fPer, fNper, fPv, fFv, bPayInAdvance, fPmt);
2260 double fEnd = ::rtl::math::approxFloor(
GetDouble());
2261 double fStart = ::rtl::math::approxFloor(
GetDouble());
2265 if (fStart < 1.0 || fEnd < fStart || fRate <= 0.0 ||
2266 fEnd > fNper || fNper <= 0.0 || fPv <= 0.0 ||
2267 ( fFlag != 0.0 && fFlag != 1.0 ))
2271 bool bPayInAdvance =
static_cast<bool>(fFlag);
2274 double fPmt =
ScGetPMT(fRate, fNper, fPv, 0.0, bPayInAdvance);
2285 fIpmt +=
ScGetFV(fRate,
static_cast<double>(
i-2), fPmt, fPv,
true) - fPmt;
2287 fIpmt +=
ScGetFV(fRate,
static_cast<double>(
i-1), fPmt, fPv,
false);
2301 double fEnd = ::rtl::math::approxFloor(
GetDouble());
2302 double fStart = ::rtl::math::approxFloor(
GetDouble());
2306 if (fStart < 1.0 || fEnd < fStart || fRate <= 0.0 ||
2307 fEnd > fNper || fNper <= 0.0 || fPv <= 0.0 ||
2308 ( fFlag != 0.0 && fFlag != 1.0 ))
2312 bool bPayInAdvance =
static_cast<bool>(fFlag);
2313 double fPmt =
ScGetPMT(fRate, fNper, fPv, 0.0, bPayInAdvance);
2319 fPpmt = bPayInAdvance ? fPmt : fPmt + fPv * fRate;
2325 fPpmt += fPmt - (
ScGetFV(fRate,
static_cast<double>(
i-2), fPmt, fPv,
true) - fPmt) * fRate;
2327 fPpmt += fPmt -
ScGetFV(fRate,
static_cast<double>(
i-1), fPmt, fPv,
false) * fRate;
2341 if (fPeriods < 1.0 || fNominal < 0.0)
2343 else if ( fNominal == 0.0 )
2347 fPeriods = ::rtl::math::approxFloor(fPeriods);
2348 PushDouble(pow(1.0 + fNominal/fPeriods, fPeriods) - 1.0);
2359 if (fPeriods < 1.0 || fEffective <= 0.0)
2363 fPeriods = ::rtl::math::approxFloor(fPeriods);
2364 PushDouble( (pow(fEffective + 1.0, 1.0 / fPeriods) - 1.0) * fPeriods );
2375 if ( fDenom == 0.0 )
2377 PushError(FormulaError::DivisionByZero);
2381 double fRes = ::rtl::math::approxSub( fNum,
2382 ::rtl::math::approxFloor( fNum / fDenom ) * fDenom );
2383 if ( ( fDenom > 0 && fRes >= 0 && fRes < fDenom ) ||
2384 ( fDenom < 0 && fRes <= 0 && fRes > fDenom ) )
2395 if (
nGlobalError != FormulaError::NONE || !p2nd || !p1st)
2421 std::unique_ptr<formula::FormulaToken>
p;
2422 for (
size_t i=0;
i<2; ++
i)
2429 p->GetRefList()->push_back( aRef);
2436 p->GetRefList()->push_back( aRef);
2459 if (nCol2 < nCol1 || nRow2 < nRow1 || nTab2 < nTab1)
2464 aRef.
InitRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2465 pRefList->push_back( aRef);
2469 size_t n = pRefList->size();
2487 SCCOL nC1[2], nC2[2];
2488 SCROW nR1[2], nR2[2];
2489 SCTAB nT1[2], nT2[2];
2490 for (
size_t i=0;
i<2; ++
i)
2522 SCCOL nCol1 = ::std::max( nC1[0], nC1[1]);
2523 SCROW nRow1 = ::std::max( nR1[0], nR1[1]);
2524 SCTAB nTab1 = ::std::max( nT1[0], nT1[1]);
2525 SCCOL nCol2 = ::std::min( nC2[0], nC2[1]);
2526 SCROW nRow2 = ::std::min( nR2[0], nR2[1]);
2527 SCTAB nTab2 = ::std::min( nT2[0], nT2[1]);
2528 if (nCol2 < nCol1 || nRow2 < nRow1 || nTab2 < nTab1)
2530 else if (nCol2 == nCol1 && nRow2 == nRow1 && nTab2 == nTab1)
2562 if (
nGlobalError != FormulaError::NONE || !p2nd || !p1st)
2597 for (
size_t i=0;
i<2; ++
i)
2607 pRes->push_back( aRef);
2611 pRes->push_back( *
pt[
i]->GetDoubleRef());
2616 for (
const auto& rRef : *
p)
2618 pRes->push_back( rRef);
2639 PushError( FormulaError::UnknownStackVariable);
2649 if (nParamCount >= 3)
2652 if (nParamCount >= 2)
2668 if (!aStyle1.isEmpty())
2670 if (
auto pNewStyle = pPool->FindAutoStyle(aStyle1))
2671 aStyle1 = pNewStyle->GetName();
2675 if (!aStyle2.isEmpty())
2677 if (
auto pNewStyle = pPool->FindAutoStyle(aStyle2))
2678 aStyle2 = pNewStyle->GetName();
2683 if (!aStyle1.isEmpty() || !aStyle2.isEmpty())
2687 const bool bNotify = !pStyle
2688 || (!aStyle1.isEmpty() && pStyle->
GetName() != aStyle1)
2689 || (!aStyle2.isEmpty() && pStyle->
GetName() != aStyle2);
2694 pShell->Broadcast(aHint);
2704 std::u16string_view rA, std::u16string_view rT, std::u16string_view rI,
sal_uInt8 nM )
2712 if (
pLink->GetAppl() == rA &&
2713 pLink->GetTopic() == rT &&
2714 pLink->GetItem() == rI &&
2715 pLink->GetMode() == nM )
2733 if (nParamCount == 4)
2845 '0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
2846 'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
2847 'N',
'O',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z',
2852 if ( nParamCount == 3 )
2854 double fLen = ::rtl::math::approxFloor(
GetDouble() );
2856 nMinLen =
static_cast<sal_Int32
>(fLen);
2858 nMinLen = fLen == 0.0 ? 1 : 0;
2862 double fBase = ::rtl::math::approxFloor(
GetDouble() );
2863 double fVal = ::rtl::math::approxFloor(
GetDouble() );
2864 double fChars = ((fVal > 0.0 && fBase > 0.0) ?
2865 (ceil(
log( fVal ) /
log( fBase ) ) + 2.0) :
2870 if (
nGlobalError == FormulaError::NONE && nMinLen && 2 <= fBase && fBase <= nDigits && 0 <= fVal )
2872 const sal_Int32 nConstBuf = 128;
2874 sal_Int32 nBuf = std::max<sal_Int32>( fChars, nMinLen + 1 );
2876 for ( sal_Int32 j = 0; j < nBuf; ++j )
2886 while ( nVal &&
p > pBuf )
2888 *--
p = pDigits[ nVal % nBase ];
2891 fVal =
static_cast<double>(nVal);
2896 while ( fVal &&
p > pBuf )
2901 double fInt = ::rtl::math::approxFloor( fVal / fBase );
2902 double fMult = fInt * fBase;
2907 double fDebug1 = fVal - fMult;
2912 double fDebug2 = ::rtl::math::approxSub( fVal, fMult );
2914 double fDebug3 = ( fInt ? fVal / fInt : 0.0 );
2920 (void)fDebug1; (void)fDebug2; (void)fDebug3;
2930 double fDig = ::rtl::math::approxFloor( ::rtl::math::approxSub( fVal, fMult ) );
2938 else if ( fDig >= fBase )
2939 nDig =
static_cast<size_t>(fBase) - 1;
2941 nDig =
static_cast<size_t>(fDig);
2943 *--
p = pDigits[ nDig ];
2948 PushError( FormulaError::StringOverflow );
2951 if ( nBuf - (
p - pBuf) <= nMinLen )
2952 p = pBuf + nBuf - 1 - nMinLen;
2967 double fBase = ::rtl::math::approxFloor(
GetDouble() );
2969 if (
nGlobalError == FormulaError::NONE && 2 <= fBase && fBase <= 36 )
2972 int nBase =
static_cast<int>(fBase);
2974 while ( *
p ==
' ' || *
p ==
'\t' )
2978 if ( *
p ==
'x' || *
p ==
'X' )
2980 else if ( *
p ==
'0' && (*(
p+1) ==
'x' || *(
p+1) ==
'X') )
2986 if (
'0' <= *
p && *
p <=
'9' )
2988 else if (
'A' <= *
p && *
p <=
'Z' )
2989 n = 10 + (*
p -
'A');
2990 else if (
'a' <= *
p && *
p <=
'z' )
2991 n = 10 + (*
p -
'a');
2997 ( (nBase == 2 && (*
p ==
'b' || *
p ==
'B'))
2998 ||(nBase == 16 && (*
p ==
'h' || *
p ==
'H')) )
3008 fVal = fVal * fBase +
n;
3047 double fMode = (nParamCount == 2) ? ::rtl::math::approxFloor(
GetDouble() ) : 0.0;
3048 double fVal = ::rtl::math::approxFloor(
GetDouble() );
3051 else if( (fMode >= 0.0) && (fMode < 5.0) && (fVal >= 0.0) && (fVal < 4000.0) )
3053 static const sal_Unicode pChars[] = {
'M',
'D',
'C',
'L',
'X',
'V',
'I' };
3054 static const sal_uInt16
pValues[] = { 1000, 500, 100, 50, 10, 5, 1 };
3057 OUStringBuffer aRoman;
3058 sal_uInt16 nVal =
static_cast<sal_uInt16
>(fVal);
3059 sal_uInt16 nMode =
static_cast<sal_uInt16
>(fMode);
3061 for( sal_uInt16
i = 0;
i <= nMaxIndex / 2;
i++ )
3066 if( (nDigit % 5) == 4 )
3069 assert( ((nDigit == 4) ? (
nIndex >= 1) : (
nIndex >= 2)));
3071 sal_uInt16 nIndex2 = (nDigit == 4) ?
nIndex - 1 :
nIndex - 2;
3072 sal_uInt16 nSteps = 0;
3073 while( (nSteps < nMode) && (
nIndex < nMaxIndex) )
3081 aRoman.append( OUStringChar(pChars[
nIndex ]) + OUStringChar(pChars[ nIndex2 ]) );
3082 nVal = sal::static_int_cast<sal_uInt16>( nVal +
pValues[
nIndex ] );
3083 nVal = sal::static_int_cast<sal_uInt16>( nVal -
pValues[ nIndex2 ] );
3091 aRoman.append( pChars[
nIndex - 1 ] );
3093 sal_Int32 nPad = nDigit % 5;
3113 case 'M': rnValue = 1000; rbIsDec =
true;
break;
3114 case 'D': rnValue = 500; rbIsDec =
false;
break;
3115 case 'C': rnValue = 100; rbIsDec =
true;
break;
3116 case 'L': rnValue = 50; rbIsDec =
false;
break;
3117 case 'X': rnValue = 10; rbIsDec =
true;
break;
3118 case 'V': rnValue = 5; rbIsDec =
false;
break;
3119 case 'I': rnValue = 1; rbIsDec =
true;
break;
3120 default:
return false;
3132 aRoman = aRoman.toAsciiUpperCase();
3135 sal_uInt16 nValidRest = 3999;
3136 sal_Int32 nCharIndex = 0;
3137 sal_Int32 nCharCount = aRoman.getLength();
3140 while( bValid && (nCharIndex < nCharCount) )
3142 sal_uInt16 nDigit1 = 0;
3143 sal_uInt16 nDigit2 = 0;
3144 bool bIsDec1 =
false;
3146 if( bValid && (nCharIndex + 1 < nCharCount) )
3148 bool bIsDec2 =
false;
3153 if( nDigit1 >= nDigit2 )
3155 nValue = sal::static_int_cast<sal_uInt16>(
nValue + nDigit1 );
3156 nValidRest %= (nDigit1 * (bIsDec1 ? 5 : 2));
3157 bValid = (nValidRest >= nDigit1);
3159 nValidRest = sal::static_int_cast<sal_uInt16>( nValidRest - nDigit1 );
3162 else if( nDigit1 * 2 != nDigit2 )
3164 sal_uInt16 nDiff = nDigit2 - nDigit1;
3165 nValue = sal::static_int_cast<sal_uInt16>(
nValue + nDiff );
3166 bValid = (nValidRest >= nDiff);
3168 nValidRest = nDigit1 - 1;
3192 if ( nParamCount == 2 )
3216 if (nErr != FormulaError::NONE)
3240 SetError( FormulaError::IllegalArgument);
3250 if (nParamCount == 2 ||
nGlobalError != FormulaError::NONE)
3253 pResMat->PutDouble( fVal, 0);
3255 pResMat->PutString(
aStr, 0);
3257 pResMat->PutDouble( 0.0, 0 );
3260 pResMat->PutString(aUrl, 0);
3261 pResMat->PutString(aUrl, 1);
3274 const char* pCurrText;
3278 static const ConvertInfo aConvertTable[] = {
3280 {
"ATS", 13.7603, 2 },
3281 {
"BEF", 40.3399, 0 },
3282 {
"DEM", 1.95583, 2 },
3283 {
"ESP", 166.386, 0 },
3284 {
"FIM", 5.94573, 2 },
3285 {
"FRF", 6.55957, 2 },
3286 {
"IEP", 0.787564, 2 },
3287 {
"ITL", 1936.27, 0 },
3288 {
"LUF", 40.3399, 0 },
3289 {
"NLG", 2.20371, 2 },
3290 {
"PTE", 200.482, 2 },
3291 {
"GRD", 340.750, 2 },
3292 {
"SIT", 239.640, 2 },
3293 {
"MTL", 0.429300, 2 },
3294 {
"CYP", 0.585274, 2 },
3295 {
"SKK", 30.1260, 2 },
3296 {
"EEK", 15.6466, 2 },
3297 {
"LVL", 0.702804, 2 },
3298 {
"LTL", 3.45280, 2 },
3299 {
"HRK", 7.53450, 2 }
3302 for (
const auto &
i : aConvertTable)
3318 double fPrecision = 0.0;
3319 if ( nParamCount == 5 )
3321 fPrecision = ::rtl::math::approxFloor(
GetDouble());
3322 if ( fPrecision < 3 )
3329 bool bFullPrecision = nParamCount >= 4 &&
GetBool();
3345 if ( aFromUnit.equalsIgnoreAsciiCase( aToUnit ) )
3349 if ( aFromUnit.equalsIgnoreAsciiCase(
"EUR" ) )
3350 fRes = fVal * fToRate;
3353 double fIntermediate = fVal / fFromRate;
3355 fIntermediate = ::rtl::math::round( fIntermediate,
3356 static_cast<int>(fPrecision) );
3357 fRes = fIntermediate * fToRate;
3359 if ( !bFullPrecision )
3360 fRes = ::rtl::math::round( fRes, nToDec );
3370#define UTF8_TH_0 "\340\270\250\340\270\271\340\270\231\340\270\242\340\271\214"
3371#define UTF8_TH_1 "\340\270\253\340\270\231\340\270\266\340\271\210\340\270\207"
3372#define UTF8_TH_2 "\340\270\252\340\270\255\340\270\207"
3373#define UTF8_TH_3 "\340\270\252\340\270\262\340\270\241"
3374#define UTF8_TH_4 "\340\270\252\340\270\265\340\271\210"
3375#define UTF8_TH_5 "\340\270\253\340\271\211\340\270\262"
3376#define UTF8_TH_6 "\340\270\253\340\270\201"
3377#define UTF8_TH_7 "\340\271\200\340\270\210\340\271\207\340\270\224"
3378#define UTF8_TH_8 "\340\271\201\340\270\233\340\270\224"
3379#define UTF8_TH_9 "\340\271\200\340\270\201\340\271\211\340\270\262"
3380#define UTF8_TH_10 "\340\270\252\340\270\264\340\270\232"
3381#define UTF8_TH_11 "\340\271\200\340\270\255\340\271\207\340\270\224"
3382#define UTF8_TH_20 "\340\270\242\340\270\265\340\271\210"
3383#define UTF8_TH_1E2 "\340\270\243\340\271\211\340\270\255\340\270\242"
3384#define UTF8_TH_1E3 "\340\270\236\340\270\261\340\270\231"
3385#define UTF8_TH_1E4 "\340\270\253\340\270\241\340\270\267\340\271\210\340\270\231"
3386#define UTF8_TH_1E5 "\340\271\201\340\270\252\340\270\231"
3387#define UTF8_TH_1E6 "\340\270\245\340\271\211\340\270\262\340\270\231"
3388#define UTF8_TH_DOT0 "\340\270\226\340\271\211\340\270\247\340\270\231"
3389#define UTF8_TH_BAHT "\340\270\232\340\270\262\340\270\227"
3390#define UTF8_TH_SATANG "\340\270\252\340\270\225\340\270\262\340\270\207\340\270\204\340\271\214"
3391#define UTF8_TH_MINUS "\340\270\245\340\270\232"
3396void lclSplitBlock(
double& rfInt, sal_Int32& rnBlock,
double fValue,
double fSize )
3398 rnBlock =
static_cast< sal_Int32
>( modf( (fValue + 0.1) / fSize, &rfInt ) * fSize + 0.1 );
3402void lclAppendDigit( OStringBuffer& rText, sal_Int32 nDigit )
3406 case 0: rText.append(
UTF8_TH_0 );
break;
3407 case 1: rText.append(
UTF8_TH_1 );
break;
3408 case 2: rText.append(
UTF8_TH_2 );
break;
3409 case 3: rText.append(
UTF8_TH_3 );
break;
3410 case 4: rText.append(
UTF8_TH_4 );
break;
3411 case 5: rText.append(
UTF8_TH_5 );
break;
3412 case 6: rText.append(
UTF8_TH_6 );
break;
3413 case 7: rText.append(
UTF8_TH_7 );
break;
3414 case 8: rText.append(
UTF8_TH_8 );
break;
3415 case 9: rText.append(
UTF8_TH_9 );
break;
3416 default: OSL_FAIL(
"lclAppendDigit - illegal digit" );
3424void lclAppendPow10( OStringBuffer& rText, sal_Int32 nDigit, sal_Int32 nPow10 )
3426 OSL_ENSURE( (1 <= nDigit) && (nDigit <= 9),
"lclAppendPow10 - illegal digit" );
3427 lclAppendDigit( rText, nDigit );
3434 default: OSL_FAIL(
"lclAppendPow10 - illegal power" );
3439void lclAppendBlock( OStringBuffer& rText, sal_Int32
nValue )
3441 OSL_ENSURE( (1 <=
nValue) && (
nValue <= 999999),
"lclAppendBlock - illegal value" );
3444 lclAppendPow10( rText,
nValue / 100000, 5 );
3449 lclAppendPow10( rText,
nValue / 10000, 4 );
3454 lclAppendPow10( rText,
nValue / 1000, 3 );
3459 lclAppendPow10( rText,
nValue / 100, 2 );
3465 sal_Int32 nTen =
nValue / 10;
3466 sal_Int32 nOne =
nValue % 10;
3470 lclAppendDigit( rText, nTen );
3471 else if( nTen == 2 )
3475 if( (nTen > 0) && (nOne == 1) )
3478 lclAppendDigit( rText, nOne );
3497 bool bMinus = fValue < 0.0;
3498 fValue = std::abs( fValue );
3501 fValue = ::rtl::math::approxFloor( fValue * 100.0 + 0.5 );
3505 sal_Int32 nSatang = 0;
3506 lclSplitBlock( fBaht, nSatang, fValue, 100.0 );
3508 OStringBuffer aText;
3516 else while( fBaht > 0.0 )
3518 OStringBuffer aBlock;
3519 sal_Int32 nBlock = 0;
3520 lclSplitBlock( fBaht, nBlock, fBaht, 1.0e6 );
3522 lclAppendBlock( aBlock, nBlock );
3527 aText.insert(0, aBlock);
3529 if (!aText.isEmpty())
3539 lclAppendBlock( aText, nSatang );
3547 PushString( OStringToOUString(aText, RTL_TEXTENCODING_UTF8) );
3560 bool bOldSyntax =
false;
3561 if (nParamCount == 2)
3569 std::vector<sheet::DataPilotFieldFilter> aFilters;
3570 OUString aDataFieldName;
3598 sal_uInt16 nFilterCount = nParamCount / 2 - 1;
3599 aFilters.resize(nFilterCount);
3601 sal_uInt16
i = nFilterCount;
3608 bool bEvaluateFormatIndex;
3613 bEvaluateFormatIndex =
true;
3616 bEvaluateFormatIndex =
false;
3630 sal_uInt32 nNumFormat;
3640 const Color* pColor;
3647 aFilters[
i].MatchValueName = aSharedString.
getString();
3651 sal_uInt32 nNumFormat = 0;
3657 aFilters[
i].MatchValue = aFilters[
i].MatchValueName;
3702 OUString aFilterStr = aDataFieldName;
3703 std::vector<sal_Int16> aFilterFuncs;
3704 if (!pDPObj->
ParseFilters(aDataFieldName, aFilters, aFilterFuncs, aFilterStr))
3715 double fVal = pDPObj->
GetPivotData(aDataFieldName, aFilters);
3716 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
SC_DLLPUBLIC ScStyleSheetPool * GetStyleSheetPool() 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 lclConvertMoney(std::u16string_view aSearchUnit, double &rfRate, int &rnDec)
Resources at the website of the European Commission: http://ec.europa.eu/economy_finance/euro/adoptio...
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)
#define SAL_N_ELEMENTS(arr)
OStringBuffer & padToLength(OStringBuffer &rBuffer, sal_Int32 nLength, char cFill='\0')
constexpr sal_Int64 md(U i, U)
bool equalsIgnoreAsciiCase(std::u16string_view s1, std::u16string_view s2)
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