sc/source/core/tool/interpr3.cxx | 44 ++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 12 deletions(-)
New commits: commit 6e0c8a3dbdb83b634a30dad018e1ff5f9959d055 Author: Eike Rathke <er...@redhat.com> AuthorDate: Fri Mar 3 13:39:03 2023 +0100 Commit: Caolán McNamara <caol...@redhat.com> CommitDate: Sat Mar 4 20:53:42 2023 +0000 Resolves: tdf#153924 handle non-numeric and error values in rank array ... of LARGE()/SMALL() instead of yielding error value for all result elements. Fallout from commit e4c2d0bb57ab8ea8f5c400d103d01376b8140f22 CommitDate: Fri Nov 30 22:14:17 2018 +0100 i#32345 Support a matrix of rank argument for LARGE()/SMALL() that in ScInterpreter::GetTopNumberArray() required the entire rank array would have to be numeric, which with an empty cell or string it isn't. Change-Id: Ieaa1a68bb8f98614119550b1442665b6fbb4817a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/148178 Reviewed-by: Eike Rathke <er...@redhat.com> Tested-by: Jenkins (cherry picked from commit 019e751c71dcb2d34c6fd8bb9dda267c6ba2b48e) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/148218 Reviewed-by: Caolán McNamara <caol...@redhat.com> diff --git a/sc/source/core/tool/interpr3.cxx b/sc/source/core/tool/interpr3.cxx index e9100d76149d..1fa4500a9baf 100644 --- a/sc/source/core/tool/interpr3.cxx +++ b/sc/source/core/tool/interpr3.cxx @@ -3638,8 +3638,8 @@ void ScInterpreter::CalculateSmallLarge(bool bSmall) return; SCSIZE nCol = 0, nRow = 0; - auto aArray = GetTopNumberArray(nCol, nRow); - const auto nRankArraySize = aArray.size(); + const auto aArray = GetTopNumberArray(nCol, nRow); + const size_t nRankArraySize = aArray.size(); if (nRankArraySize == 0 || nGlobalError != FormulaError::NONE) { PushNoValue(); @@ -3667,7 +3667,12 @@ void ScInterpreter::CalculateSmallLarge(bool bSmall) { const SCSIZE k = aRankArray[0]; if (k < 1 || nSize < k) - PushNoValue(); + { + if (!std::isfinite(aArray[0])) + PushDouble(aArray[0]); // propagates error + else + PushNoValue(); + } else { vector<double>::iterator iPos = aSortArray.begin() + (bSmall ? k-1 : nSize-k); @@ -3699,15 +3704,19 @@ void ScInterpreter::CalculateSmallLarge(bool bSmall) else std::sort(aSortArray.begin(), aSortArray.end()); - aArray.clear(); - for (SCSIZE n : aRankArray) + std::vector<double> aResultArray; + aResultArray.reserve(nRankArraySize); + for (size_t i = 0; i < nRankArraySize; ++i) { + const SCSIZE n = aRankArray[i]; if (1 <= n && n <= nSize) - aArray.push_back( aSortArray[bSmall ? n-1 : nSize-n]); + aResultArray.push_back( aSortArray[bSmall ? n-1 : nSize-n]); + else if (!std::isfinite( aArray[i])) + aResultArray.push_back( aArray[i]); // propagate error else - aArray.push_back( CreateDoubleError( FormulaError::NoValue)); + aResultArray.push_back( CreateDoubleError( FormulaError::IllegalArgument)); } - ScMatrixRef pResult = GetNewMat(nCol, nRow, aArray); + ScMatrixRef pResult = GetNewMat(nCol, nRow, aResultArray); PushMatrix(pResult); } } @@ -3912,19 +3921,30 @@ std::vector<double> ScInterpreter::GetTopNumberArray( SCSIZE& rCol, SCSIZE& rRow if (!pMat) break; + const SCSIZE nCount = pMat->GetElementCount(); + aArray.reserve(nCount); + // Do not propagate errors from matrix elements as global error. + pMat->SetErrorInterpreter(nullptr); if (pMat->IsNumeric()) { - SCSIZE nCount = pMat->GetElementCount(); - aArray.reserve(nCount); for (SCSIZE i = 0; i < nCount; ++i) aArray.push_back(pMat->GetDouble(i)); - pMat->GetDimensions(rCol, rRow); } else - SetError(FormulaError::IllegalParameter); + { + for (SCSIZE i = 0; i < nCount; ++i) + { + if (pMat->IsValue(i)) + aArray.push_back( pMat->GetDouble(i)); + else + aArray.push_back( CreateDoubleError( FormulaError::NoValue)); + } + } + pMat->GetDimensions(rCol, rRow); } break; default: + PopError(); SetError(FormulaError::IllegalParameter); break; }