[Libreoffice-commits] core.git: sc/source

Eike Rathke erack at redhat.com
Tue Jun 13 14:48:16 UTC 2017


 sc/source/core/inc/interpre.hxx  |    1 
 sc/source/core/tool/interpr4.cxx |   68 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 69 insertions(+)

New commits:
commit f9cf614e7ea73e47a71cd2c0d1d53af9a6e48984
Author: Eike Rathke <erack at redhat.com>
Date:   Tue Jun 13 16:37:46 2017 +0200

    Final result of svRefList can be an array in some cases, tdf#58874 related
    
    Actually {=OFFSET(A1,{2;4},0)} worked already before the change for arrays of
    references, make it work again. Further there was a difference between that and
    {=OFFSET(A1,{2,4},0)} (row vector vs column vector in array context) which to
    reintroduce would need to treat a final Reference result differently (as
    matrix) from an intermediate Reference result (as array).
    
    Change-Id: I9240d0cb8ba2db8a0276640463da5f0cabec58cf

diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx
index 9b36afec2e05..d44d1141d73b 100644
--- a/sc/source/core/inc/interpre.hxx
+++ b/sc/source/core/inc/interpre.hxx
@@ -360,6 +360,7 @@ void PopExternalDoubleRef(ScMatrixRef& rMat);
 void GetExternalDoubleRef(sal_uInt16 nFileId, const OUString& rTabName, const ScComplexRefData& aData, ScExternalRefCache::TokenArrayRef& rArray);
 bool PopDoubleRefOrSingleRef( ScAddress& rAdr );
 void PopDoubleRefPushMatrix();
+void PopRefListPushMatrixOrRef();
 // If MatrixFormula: convert svDoubleRef to svMatrix, create JumpMatrix.
 // Else convert area reference parameters marked as ForceArray to array.
 // Returns true if JumpMatrix created.
diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index eb209c4be894..1af3a019f95a 100644
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -1354,6 +1354,66 @@ void ScInterpreter::PopDoubleRefPushMatrix()
         SetError( FormulaError::NoRef );
 }
 
+void ScInterpreter::PopRefListPushMatrixOrRef()
+{
+    if ( GetStackType() == svRefList )
+    {
+        FormulaConstTokenRef xTok = pStack[sp-1];
+        const std::vector<ScComplexRefData>* pv = xTok->GetRefList();
+        if (pv)
+        {
+            const size_t nEntries = pv->size();
+            if (nEntries == 1)
+            {
+                --sp;
+                PushTempTokenWithoutError( new ScDoubleRefToken( (*pv)[0] ));
+            }
+            else if (bMatrixFormula)
+            {
+                // Only single cells can be stuffed into a column vector.
+                // XXX NOTE: Excel doesn't do this but returns #VALUE! instead.
+                // Though there's no compelling reason not to..
+                for (const auto & rRef : *pv)
+                {
+                    if (rRef.Ref1 != rRef.Ref2)
+                        return;
+                }
+                ScMatrixRef xMat = GetNewMat( 1, nEntries, true);   // init empty
+                if (!xMat)
+                    return;
+                for (size_t i=0; i < nEntries; ++i)
+                {
+                    SCCOL nCol; SCROW nRow; SCTAB nTab;
+                    SingleRefToVars( (*pv)[i].Ref1, nCol, nRow, nTab);
+                    if (nGlobalError == FormulaError::NONE)
+                    {
+                        ScAddress aAdr( nCol, nRow, nTab);
+                        ScRefCellValue aCell( *pDok, aAdr);
+                        if (aCell.hasError())
+                            xMat->PutError( aCell.mpFormula->GetErrCode(), 0, i);
+                        else if (aCell.hasEmptyValue())
+                            xMat->PutEmpty( 0, i);
+                        else if (aCell.hasString())
+                            xMat->PutString( mrStrPool.intern( aCell.getString( pDok)), 0, i);
+                        else
+                            xMat->PutDouble( aCell.getValue(), 0, i);
+                    }
+                    else
+                    {
+                        xMat->PutError( nGlobalError, 0, i);
+                        nGlobalError = FormulaError::NONE;
+                    }
+                }
+                --sp;
+                PushMatrix( xMat);
+            }
+        }
+        // else: keep token on stack, something will handle the error
+    }
+    else
+        SetError( FormulaError::NoRef );
+}
+
 void ScInterpreter::ConvertMatrixJumpConditionToMatrix()
 {
     StackVar eStackType = GetStackType();
@@ -4487,6 +4547,14 @@ StackVar ScInterpreter::Interpret()
         pCur = pStack[ sp-1 ];
         if( pCur->GetOpCode() == ocPush )
         {
+            // An svRefList can be resolved if it a) contains just one
+            // reference, or b) in array context contains an array of single
+            // cell references.
+            if (pCur->GetType() == svRefList)
+            {
+                PopRefListPushMatrixOrRef();
+                pCur = pStack[ sp-1 ];
+            }
             switch( pCur->GetType() )
             {
                 case svEmptyCell:


More information about the Libreoffice-commits mailing list