diff options
author | Andreas Heinisch <andreas.heinisch@yahoo.de> | 2021-04-12 10:51:57 +0200 |
---|---|---|
committer | Eike Rathke <erack@redhat.com> | 2021-04-21 16:59:13 +0200 |
commit | a8216c210dbe83a7fe0c8b1a767c2ddf8b611e96 (patch) | |
tree | f4b69b82626782ea0b5fa0a4900fc81f6755f168 /sc | |
parent | 2056cdca53b694d8c27ef85e4a3679df4608f22c (diff) |
tdf#58585 - IRR function: support array argument for values
Text and empty cells in the value range are ignored.
Change-Id: I0790a83c79d3861afa855bf89a1c4eb39eb6d638
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/113971
Tested-by: Jenkins
Reviewed-by: Eike Rathke <erack@redhat.com>
Diffstat (limited to 'sc')
-rw-r--r-- | sc/qa/unit/data/functions/financial/fods/irr.fods | 45 | ||||
-rw-r--r-- | sc/source/core/tool/interpr2.cxx | 73 |
2 files changed, 77 insertions, 41 deletions
diff --git a/sc/qa/unit/data/functions/financial/fods/irr.fods b/sc/qa/unit/data/functions/financial/fods/irr.fods index ced44ffd0c49..4ecc9cb32581 100644 --- a/sc/qa/unit/data/functions/financial/fods/irr.fods +++ b/sc/qa/unit/data/functions/financial/fods/irr.fods @@ -1913,20 +1913,29 @@ <table:table-cell table:style-name="ce13" table:number-columns-repeated="2"/> <table:table-cell table:number-columns-repeated="9"/> </table:table-row> - <table:table-row table:style-name="ro7"> - <table:table-cell table:number-columns-repeated="2"/> - <table:table-cell table:style-name="ce16"/> - <table:table-cell/> - <table:table-cell table:style-name="ce24"/> - <table:table-cell/> + <table:table-row table:style-name="ro6"> + <table:table-cell table:style-name="ce11" table:formula="of:=IRR({-10000|5000|5000|5000})" office:value-type="percentage" office:value="0.233751928528259" calcext:value-type="percentage"> + <text:p>23,38%</text:p> + </table:table-cell> + <table:table-cell office:value-type="float" office:value="0.233751928528259" calcext:value-type="float"> + <text:p>0.233751928528259</text:p> + </table:table-cell> + <table:table-cell table:style-name="ce16" table:formula="of:=[.A13]=[.B13]" office:value-type="boolean" office:boolean-value="true" calcext:value-type="boolean"> + <text:p>TRUE</text:p> + </table:table-cell> + <table:table-cell table:style-name="ce24" table:formula="of:=FORMULA([.A13])" office:value-type="string" office:string-value="=IRR({-10000|5000|5000|5000})" calcext:value-type="string"> + <text:p>=IRR({-10000|5000|5000|5000})</text:p> + </table:table-cell> + <table:table-cell table:style-name="ce24" office:value-type="string" calcext:value-type="string"> + <text:p>Tdf#58585 enhancement</text:p> + </table:table-cell> + <table:table-cell table:number-columns-repeated="1"/> <table:table-cell office:value-type="float" office:value="20" calcext:value-type="float"> - <text:p>20</text:p> + <text:p>10</text:p> </table:table-cell> <table:table-cell table:number-columns-repeated="2"/> - <table:table-cell table:style-name="ce29"/> - <table:table-cell table:style-name="ce31"/> - <table:table-cell table:style-name="ce29" table:number-columns-repeated="3"/> - <table:table-cell table:number-columns-repeated="6"/> + <table:table-cell table:style-name="ce13" table:number-columns-repeated="2"/> + <table:table-cell table:number-columns-repeated="9"/> </table:table-row> <table:table-row table:style-name="ro7"> <table:table-cell table:style-name="ce12"/> @@ -2014,20 +2023,6 @@ </table:table-cell> <table:table-cell table:number-columns-repeated="15"/> </table:table-row> - <table:table-row table:style-name="ro7"> - <table:table-cell table:style-name="ce11" table:formula="of:=IRR( {-10000|5000|5000|5000})" office:value-type="string" office:string-value="" calcext:value-type="error"> - <text:p>Err:504</text:p> - </table:table-cell> - <table:table-cell/> - <table:table-cell table:style-name="ce19"/> - <table:table-cell table:style-name="ce24" table:formula="of:=FORMULA([.A23])" office:value-type="string" office:string-value="=IRR( {-10000;5000;5000;5000})" calcext:value-type="string"> - <text:p>=IRR( {-10000;5000;5000;5000})</text:p> - </table:table-cell> - <table:table-cell table:style-name="ce24" office:value-type="string" calcext:value-type="string"> - <text:p>Tdf#58585 enhancement</text:p> - </table:table-cell> - <table:table-cell table:number-columns-repeated="15"/> - </table:table-row> <table:table-row table:style-name="ro8"> <table:table-cell table:style-name="ce13"/> <table:table-cell/> diff --git a/sc/source/core/tool/interpr2.cxx b/sc/source/core/tool/interpr2.cxx index a14c84b69f92..7e0d3733538d 100644 --- a/sc/source/core/tool/interpr2.cxx +++ b/sc/source/core/tool/interpr2.cxx @@ -1410,17 +1410,43 @@ void ScInterpreter::ScIRR() fEstimated = GetDouble(); else fEstimated = 0.1; - sal_uInt16 sPos = sp; // memorize the position of the stack double fEps = 1.0; double x, fValue; if (fEstimated == -1.0) x = 0.1; // default result for division by zero else x = fEstimated; // startvalue + + ScRange aRange; + ScMatrixRef pMat; + SCSIZE nC = 0; + SCSIZE nR = 0; + bool bIsMatrix = false; switch (GetStackType()) { - case svDoubleRef : + case svDoubleRef: + PopDoubleRef(aRange); break; + case svMatrix: + case svExternalSingleRef: + case svExternalDoubleRef: + pMat = GetMatrix(); + if (pMat) + { + pMat->GetDimensions(nC, nR); + if (nC == 0 || nR == 0) + { + PushIllegalParameter(); + return; + } + bIsMatrix = true; + } + else + { + PushIllegalParameter(); + return; + } + break; default: { PushIllegalParameter(); @@ -1429,28 +1455,43 @@ void ScInterpreter::ScIRR() } const sal_uInt16 nIterationsMax = 20; sal_uInt16 nItCount = 0; - ScRange aRange; - while (fEps > SCdEpsilon && nItCount < nIterationsMax) + FormulaError nIterError = FormulaError::NONE; + while (fEps > SCdEpsilon && nItCount < nIterationsMax && nGlobalError == FormulaError::NONE) { // Newtons method: - sp = sPos; // reset stack double fNom = 0.0; double fDenom = 0.0; - FormulaError nErr = FormulaError::NONE; - PopDoubleRef( aRange ); - ScValueIterator aValIter(mrDoc, aRange, mnSubTotalFlags); - if (aValIter.GetFirst(fValue, nErr)) - { - double fCount = 0.0; - fNom += fValue / pow(1.0+x,fCount); - fDenom += -fCount * fValue / pow(1.0+x,fCount+1.0); - fCount++; - while ((nErr == FormulaError::NONE) && aValIter.GetNext(fValue, nErr)) + double fCount = 0.0; + if (bIsMatrix) + { + for (SCSIZE j = 0; j < nC && nGlobalError == FormulaError::NONE; j++) + { + for (SCSIZE k = 0; k < nR; k++) + { + if (!pMat->IsValue(j, k)) + continue; + fValue = pMat->GetDouble(j, k); + if (nGlobalError != FormulaError::NONE) + break; + + fNom += fValue / pow(1.0+x,fCount); + fDenom += -fCount * fValue / pow(1.0+x,fCount+1.0); + fCount++; + } + } + } + else + { + ScValueIterator aValIter(mrDoc, aRange, mnSubTotalFlags); + bool bLoop = aValIter.GetFirst(fValue, nIterError); + while (bLoop && nIterError == FormulaError::NONE) { fNom += fValue / pow(1.0+x,fCount); fDenom += -fCount * fValue / pow(1.0+x,fCount+1.0); fCount++; + + bLoop = aValIter.GetNext(fValue, nIterError); } - SetError(nErr); + SetError(nIterError); } double xNew = x - fNom / fDenom; // x(i+1) = x(i)-f(x(i))/f'(x(i)) nItCount++; |