sc/source/core/tool/interpr5.cxx |  103 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 102 insertions(+), 1 deletion(-)

New commits:
commit 2b591a40b0f6894531350ccb733abef3c3e1d9bf
Author:     Eike Rathke <er...@redhat.com>
AuthorDate: Fri Sep 6 16:44:28 2019 +0200
Commit:     Eike Rathke <er...@redhat.com>
CommitDate: Fri Sep 6 20:02:18 2019 +0200

    Related: tdf#98844 CreateMatrixFromDoubleRef() for bCalcAsShown 
ScCellIterator
    
    ... to cover ForceArray cases like SUMPRODUCT().
    
    Change-Id: I149ef4a9633f3237d48fc4f2b6011b03bccebc49
    Reviewed-on: https://gerrit.libreoffice.org/78721
    Reviewed-by: Eike Rathke <er...@redhat.com>
    Tested-by: Jenkins

diff --git a/sc/source/core/tool/interpr5.cxx b/sc/source/core/tool/interpr5.cxx
index e928b974d110..a2b8dc5a6fac 100644
--- a/sc/source/core/tool/interpr5.cxx
+++ b/sc/source/core/tool/interpr5.cxx
@@ -350,7 +350,108 @@ ScMatrixRef ScInterpreter::CreateMatrixFromDoubleRef( 
const FormulaToken* pToken
     if (!pMat || nGlobalError != FormulaError::NONE)
         return nullptr;
 
-    pDok->FillMatrix(*pMat, nTab1, nCol1, nRow1, nCol2, nRow2);
+    if (!bCalcAsShown)
+    {
+        // Use fast array fill.
+        pDok->FillMatrix(*pMat, nTab1, nCol1, nRow1, nCol2, nRow2);
+    }
+    else
+    {
+        // Use slower ScCellIterator to round values.
+
+        // TODO: this probably could use CellBucket for faster storage, see
+        // sc/source/core/data/column2.cxx and FillMatrixHandler, and then be
+        // moved to a function on its own, and/or squeeze the rounding into a
+        // similar FillMatrixHandler that would need to keep track of the cell
+        // position then.
+
+        // Set position where the next entry is expected.
+        SCROW nNextRow = nRow1;
+        SCCOL nNextCol = nCol1;
+        // Set last position as if there was a previous entry.
+        SCROW nThisRow = nRow2;
+        SCCOL nThisCol = nCol1 - 1;
+
+        ScCellIterator aCellIter( pDok, ScRange( nCol1, nRow1, nTab1, nCol2, 
nRow2, nTab2));
+        for (bool bHas = aCellIter.first(); bHas; bHas = aCellIter.next())
+        {
+            nThisCol = aCellIter.GetPos().Col();
+            nThisRow = aCellIter.GetPos().Row();
+            if (nThisCol != nNextCol || nThisRow != nNextRow)
+            {
+                // Fill empty between iterator's positions.
+                for ( ; nNextCol <= nThisCol; ++nNextCol)
+                {
+                    const SCSIZE nC = nNextCol - nCol1;
+                    const SCSIZE nMatStopRow = ((nNextCol < nThisCol) ? 
nMatRows : nThisRow - nRow1);
+                    for (SCSIZE nR = nNextRow - nRow1; nR < nMatStopRow; ++nR)
+                    {
+                        pMat->PutEmpty( nC, nR);
+                    }
+                    nNextRow = nRow1;
+                }
+            }
+            if (nThisRow == nRow2)
+            {
+                nNextCol = nThisCol + 1;
+                nNextRow = nRow1;
+            }
+            else
+            {
+                nNextCol = nThisCol;
+                nNextRow = nThisRow + 1;
+            }
+
+            const SCSIZE nMatCol = static_cast<SCSIZE>(nThisCol - nCol1);
+            const SCSIZE nMatRow = static_cast<SCSIZE>(nThisRow - nRow1);
+            ScRefCellValue aCell( aCellIter.getRefCellValue());
+            if (aCellIter.isEmpty() || aCell.hasEmptyValue())
+            {
+                pMat->PutEmpty( nMatCol, nMatRow);
+            }
+            else if (aCell.hasError())
+            {
+                pMat->PutError( aCell.mpFormula->GetErrCode(), nMatCol, 
nMatRow);
+            }
+            else if (aCell.hasNumeric())
+            {
+                double fVal = aCell.getValue();
+                // CELLTYPE_FORMULA already stores the rounded value.
+                if (aCell.meType == CELLTYPE_VALUE)
+                {
+                    // TODO: this could be moved to ScCellIterator to take
+                    // advantage of the faster ScAttrArray_IterGetNumberFormat.
+                    const ScAddress aAdr( nThisCol, nThisRow, nTab1);
+                    const sal_uInt32 nNumFormat = pDok->GetNumberFormat( 
mrContext, aAdr);
+                    fVal = pDok->RoundValueAsShown( fVal, nNumFormat, 
&mrContext);
+                }
+                pMat->PutDouble( fVal, nMatCol, nMatRow);
+            }
+            else if (aCell.hasString())
+            {
+                pMat->PutString( mrStrPool.intern( aCell.getString( pDok)), 
nMatCol, nMatRow);
+            }
+            else
+            {
+                assert(!"aCell.what?");
+                pMat->PutEmpty( nMatCol, nMatRow);
+            }
+        }
+
+        // Fill empty if iterator's last position wasn't the end.
+        if (nThisCol != nCol2 || nThisRow != nRow2)
+        {
+            for ( ; nNextCol <= nCol2; ++nNextCol)
+            {
+                SCSIZE nC = nNextCol - nCol1;
+                for (SCSIZE nR = nNextRow - nRow1; nR < nMatRows; ++nR)
+                {
+                    pMat->PutEmpty( nC, nR);
+                }
+                nNextRow = nRow1;
+            }
+        }
+    }
 
     if (pToken && pTokenMatrixMap)
         pTokenMatrixMap->emplace(pToken, new ScMatrixToken( pMat));
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to