diff options
author | Eike Rathke <erack@redhat.com> | 2017-06-13 16:37:46 +0200 |
---|---|---|
committer | Eike Rathke <erack@redhat.com> | 2017-06-13 16:47:53 +0200 |
commit | f9cf614e7ea73e47a71cd2c0d1d53af9a6e48984 (patch) | |
tree | 6ec8c219ebc64b20016811188975fbefbdebe15e | |
parent | 7b67e3fc5566f4172c69fa8460aea0c006e97a4d (diff) |
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
-rw-r--r-- | sc/source/core/inc/interpre.hxx | 1 | ||||
-rw-r--r-- | sc/source/core/tool/interpr4.cxx | 68 |
2 files changed, 69 insertions, 0 deletions
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: |