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 <er...@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: _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits