summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEike Rathke <erack@redhat.com>2017-06-13 16:37:46 +0200
committerEike Rathke <erack@redhat.com>2017-06-13 16:47:53 +0200
commitf9cf614e7ea73e47a71cd2c0d1d53af9a6e48984 (patch)
tree6ec8c219ebc64b20016811188975fbefbdebe15e
parent7b67e3fc5566f4172c69fa8460aea0c006e97a4d (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.hxx1
-rw-r--r--sc/source/core/tool/interpr4.cxx68
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: