summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--formula/source/core/api/FormulaCompiler.cxx33
-rw-r--r--formula/source/core/api/token.cxx3
-rw-r--r--formula/source/ui/dlg/formula.cxx1
-rw-r--r--include/formula/paramclass.hxx8
-rw-r--r--sc/source/core/tool/compiler.cxx3
-rw-r--r--sc/source/core/tool/interpr1.cxx6
-rw-r--r--sc/source/core/tool/interpr4.cxx2
-rw-r--r--sc/source/core/tool/parclass.cxx56
8 files changed, 76 insertions, 36 deletions
diff --git a/formula/source/core/api/FormulaCompiler.cxx b/formula/source/core/api/FormulaCompiler.cxx
index b0938aa630be..ccf4562fec9d 100644
--- a/formula/source/core/api/FormulaCompiler.cxx
+++ b/formula/source/core/api/FormulaCompiler.cxx
@@ -2693,6 +2693,13 @@ formula::ParamClass FormulaCompiler::GetForceArrayParameter( const FormulaToken*
void FormulaCompiler::ForceArrayOperator( FormulaTokenRef const & rCurr )
{
+ if (rCurr->GetInForceArray() != ParamClass::Unknown)
+ // Already set, unnecessary to evaluate again. This happens by calls to
+ // CurrentFactor::operator=() while descending through Factor() and
+ // then ascending back (and down and up, ...),
+ // CheckSetForceArrayParameter() and later PutCode().
+ return;
+
if (!pCurrentFactorToken || (pCurrentFactorToken.get() == rCurr.get()))
return;
@@ -2700,27 +2707,37 @@ void FormulaCompiler::ForceArrayOperator( FormulaTokenRef const & rCurr )
return;
// Inherited parameter class.
- formula::ParamClass eType = pCurrentFactorToken->GetInForceArray();
- if (eType == formula::ParamClass::ForceArray)
- {
- rCurr->SetInForceArray( eType);
+ const formula::ParamClass eForceType = pCurrentFactorToken->GetInForceArray();
+ if (eForceType == ParamClass::ForceArray || eForceType == ParamClass::ReferenceOrRefArray)
+ {
+ // ReferenceOrRefArray was set only if in ForceArray context already,
+ // it is valid for the one function only to indicate the preferred
+ // return type. Propagate as ForceArray if not another parameter
+ // handling ReferenceOrRefArray.
+ if (nCurrentFactorParam > 0
+ && (GetForceArrayParameter( pCurrentFactorToken.get(), static_cast<sal_uInt16>(nCurrentFactorParam - 1))
+ == ParamClass::ReferenceOrRefArray))
+ rCurr->SetInForceArray( ParamClass::ReferenceOrRefArray);
+ else
+ rCurr->SetInForceArray( ParamClass::ForceArray);
return;
}
- else if (eType == formula::ParamClass::ReferenceOrForceArray)
+ else if (eForceType == ParamClass::ReferenceOrForceArray)
{
// Inherit further only if the return class of the nested function is
// not Reference. Else flag as suppressed.
if (GetForceArrayParameter( rCurr.get(), SAL_MAX_UINT16) != ParamClass::Reference)
- rCurr->SetInForceArray( eType);
+ rCurr->SetInForceArray( eForceType);
else
- rCurr->SetInForceArray( formula::ParamClass::SuppressedReferenceOrForceArray);
+ rCurr->SetInForceArray( ParamClass::SuppressedReferenceOrForceArray);
return;
}
if (nCurrentFactorParam > 0)
{
// Actual current parameter's class.
- eType = GetForceArrayParameter( pCurrentFactorToken.get(), static_cast<sal_uInt16>(nCurrentFactorParam - 1));
+ const formula::ParamClass eType = GetForceArrayParameter(
+ pCurrentFactorToken.get(), static_cast<sal_uInt16>(nCurrentFactorParam - 1));
if (eType == ParamClass::ForceArray)
rCurr->SetInForceArray( eType);
else if (eType == ParamClass::ReferenceOrForceArray)
diff --git a/formula/source/core/api/token.cxx b/formula/source/core/api/token.cxx
index cefab324fd53..aa3dbec8c8ef 100644
--- a/formula/source/core/api/token.cxx
+++ b/formula/source/core/api/token.cxx
@@ -150,7 +150,8 @@ bool FormulaToken::IsRef() const
bool FormulaToken::IsInForceArray() const
{
ParamClass eParam = GetInForceArray();
- return eParam == ParamClass::ForceArray || eParam == ParamClass::ReferenceOrForceArray;
+ return eParam == ParamClass::ForceArray || eParam == ParamClass::ReferenceOrForceArray
+ || eParam == ParamClass::ReferenceOrRefArray;
}
bool FormulaToken::operator==( const FormulaToken& rToken ) const
diff --git a/formula/source/ui/dlg/formula.cxx b/formula/source/ui/dlg/formula.cxx
index c324be63a943..55135ebc11cf 100644
--- a/formula/source/ui/dlg/formula.cxx
+++ b/formula/source/ui/dlg/formula.cxx
@@ -753,6 +753,7 @@ void FormulaDlg_Impl::MakeTree( StructPage* _pTree, SvTreeListEntry* pParent, co
aUnforcedResult.clear();
break;
case ParamClass::Reference:
+ case ParamClass::ReferenceOrRefArray:
case ParamClass::Array:
case ParamClass::ForceArray:
case ParamClass::ReferenceOrForceArray:
diff --git a/include/formula/paramclass.hxx b/include/formula/paramclass.hxx
index a22854fc890c..a1e564819457 100644
--- a/include/formula/paramclass.hxx
+++ b/include/formula/paramclass.hxx
@@ -36,6 +36,14 @@ namespace formula
PopDoubleRefOrSingleRef() should not have this. */
Reference,
+ /** Like Reference but the function accepts also a list of references
+ (ocUnion svRefList) as one argument AND handles the special case of
+ an array of references in array mode. Then the resulting argument
+ for a parameter in JumpMatrix context may be an array of references
+ which then is to be preferred over a result matrix. This final
+ behaviour is the opposite of SuppressedReferenceOrForceArray. */
+ ReferenceOrRefArray,
+
/** In array formula: convert area reference to array. Function will be
called only once if no Value type is involved. Functions able to
handle a svMatrix parameter but not a formula::svDoubleRef parameter as area
diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx
index 3c86ad2f5591..556cd49b39c3 100644
--- a/sc/source/core/tool/compiler.cxx
+++ b/sc/source/core/tool/compiler.cxx
@@ -5809,7 +5809,8 @@ bool ScCompiler::SkipImplicitIntersectionOptimization(const FormulaToken* token)
formula::ParamClass paramClass = token->GetInForceArray();
if (paramClass == formula::ForceArray
|| paramClass == formula::ReferenceOrForceArray
- || paramClass == formula::SuppressedReferenceOrForceArray)
+ || paramClass == formula::SuppressedReferenceOrForceArray
+ || paramClass == formula::ReferenceOrRefArray)
{
return true;
}
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 38e56deb52f7..b83406223a17 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -835,8 +835,10 @@ bool ScInterpreter::JumpMatrix( short nStackLevel )
{ // We're done with it, throw away jump matrix, keep result.
// For an intermediate result of Reference use the array of references
// if there are more than one reference and the current ForceArray
- // context is not ForceArray or related, suppressed, ...,
- // else (also for a final result of Reference) use the matrix.
+ // context is not ForceArray or suppressed. Note that also
+ // ReferenceOrRefArray forces the array of references as result if
+ // there is more than one reference.
+ // Else (also for a final result of Reference) use the matrix.
// Treat the result of a jump command as final and use the matrix (see
// tdf#115493 for why).
ParamClass eParamClass;
diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index a1eb180683db..3bb3cf83c350 100644
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -1490,6 +1490,7 @@ bool ScInterpreter::ConvertMatrixParameters()
{
formula::ParamClass eType = ScParameterClassification::GetParameterType( pCur, nParams - i);
if ( eType != formula::ParamClass::Reference &&
+ eType != formula::ParamClass::ReferenceOrRefArray &&
eType != formula::ParamClass::ReferenceOrForceArray &&
// For scalar Value: convert to Array/JumpMatrix
// only if in array formula context, else (function
@@ -1554,6 +1555,7 @@ bool ScInterpreter::ConvertMatrixParameters()
{
formula::ParamClass eType = ScParameterClassification::GetParameterType( pCur, nParams - i);
if ( eType != formula::ParamClass::Reference &&
+ eType != formula::ParamClass::ReferenceOrRefArray &&
eType != formula::ParamClass::ReferenceOrForceArray &&
eType != formula::ParamClass::ForceArray)
{
diff --git a/sc/source/core/tool/parclass.cxx b/sc/source/core/tool/parclass.cxx
index 9f79da716a40..46179fe552f8 100644
--- a/sc/source/core/tool/parclass.cxx
+++ b/sc/source/core/tool/parclass.cxx
@@ -99,25 +99,25 @@ const ScParameterClassification::RawData ScParameterClassification::pRawData[] =
{ ocTableOp, {{ Value, Value, Value, Value, Value }, 0, Value }},
// Operators and functions.
{ ocAdd, {{ Array, Array }, 0, Value }},
- { ocAggregate, {{ Value, Value, Reference }, 1, Value }},
+ { ocAggregate, {{ Value, Value, ReferenceOrRefArray }, 1, Value }},
{ ocAmpersand, {{ Array, Array }, 0, Value }},
{ ocAnd, {{ Reference }, 1, Value }},
{ ocAreas, {{ Reference }, 0, Value }},
{ ocAveDev, {{ Reference }, 1, Value }},
- { ocAverage, {{ Reference }, 1, Value }},
- { ocAverageA, {{ Reference }, 1, Value }},
- { ocAverageIf, {{ Reference, Value, Reference }, 0, Value }},
- { ocAverageIfs, {{ Reference, Reference, Value }, 2, Value }},
+ { ocAverage, {{ ReferenceOrRefArray }, 1, Value }},
+ { ocAverageA, {{ ReferenceOrRefArray }, 1, Value }},
+ { ocAverageIf, {{ ReferenceOrRefArray, Value, Reference }, 0, Value }},
+ { ocAverageIfs, {{ ReferenceOrRefArray, ReferenceOrRefArray, Value }, 2, Value }},
{ ocCell, {{ Value, Reference }, 0, Value }},
{ ocColumn, {{ Reference }, 0, Value }},
{ ocColumns, {{ Reference }, 1, Value }},
{ ocConcat_MS, {{ Reference }, 1, Value }},
{ ocCorrel, {{ ForceArray, ForceArray }, 0, Value }},
- { ocCount, {{ Reference }, 1, Value }},
- { ocCount2, {{ Reference }, 1, Value }},
- { ocCountEmptyCells, {{ Reference }, 0, Value }},
- { ocCountIf, {{ Reference, Value }, 0, Value }},
- { ocCountIfs, {{ Reference, Value }, 2, Value }},
+ { ocCount, {{ ReferenceOrRefArray }, 1, Value }},
+ { ocCount2, {{ ReferenceOrRefArray }, 1, Value }},
+ { ocCountEmptyCells, {{ ReferenceOrRefArray }, 0, Value }},
+ { ocCountIf, {{ ReferenceOrRefArray, Value }, 0, Value }},
+ { ocCountIfs, {{ ReferenceOrRefArray, Value }, 2, Value }},
{ ocCovar, {{ ForceArray, ForceArray }, 0, Value }},
{ ocCovarianceP, {{ ForceArray, ForceArray }, 0, Value }},
{ ocCovarianceS, {{ ForceArray, ForceArray }, 0, Value }},
@@ -176,11 +176,13 @@ const ScParameterClassification::RawData ScParameterClassification::pRawData[] =
{ ocMatTrans, {{ Array }, 0, Value }}, // strange, but Xcl doesn't force MatTrans array
{ ocMatValue, {{ Reference, Value, Value }, 0, Value }},
{ ocMatch, {{ Value, ReferenceOrForceArray, Value }, 0, Value }},
- { ocMax, {{ Reference }, 1, Value }},
- { ocMaxA, {{ Reference }, 1, Value }},
+ { ocMax, {{ ReferenceOrRefArray }, 1, Value }},
+ { ocMaxA, {{ ReferenceOrRefArray }, 1, Value }},
+ { ocMaxIfs_MS, {{ ReferenceOrRefArray, ReferenceOrRefArray, Value }, 2, Value }},
{ ocMedian, {{ Reference }, 1, Value }},
- { ocMin, {{ Reference }, 1, Value }},
- { ocMinA, {{ Reference }, 1, Value }},
+ { ocMin, {{ ReferenceOrRefArray }, 1, Value }},
+ { ocMinA, {{ ReferenceOrRefArray }, 1, Value }},
+ { ocMinIfs_MS, {{ ReferenceOrRefArray, ReferenceOrRefArray, Value }, 2, Value }},
{ ocModalValue, {{ ForceArray }, 1, Value }},
{ ocModalValue_MS, {{ ForceArray }, 1, Value }},
{ ocModalValue_Multi,{{ ForceArray }, 1, Value }},
@@ -206,7 +208,7 @@ const ScParameterClassification::RawData ScParameterClassification::pRawData[] =
{ ocPow, {{ Array, Array }, 0, Value }},
{ ocPower, {{ Array, Array }, 0, Value }},
{ ocProb, {{ ForceArray, ForceArray, Value, Value }, 0, Value }},
- { ocProduct, {{ Reference }, 1, Value }},
+ { ocProduct, {{ ReferenceOrRefArray }, 1, Value }},
{ ocQuartile, {{ Reference, Value }, 0, Value }},
{ ocQuartile_Exc, {{ Reference, Value }, 0, Value }},
{ ocQuartile_Inc, {{ Reference, Value }, 0, Value }},
@@ -231,12 +233,12 @@ const ScParameterClassification::RawData ScParameterClassification::pRawData[] =
{ ocStDevP_MS, {{ Reference }, 1, Value }},
{ ocStDevS, {{ Reference }, 1, Value }},
{ ocSub, {{ Array, Array }, 0, Value }},
- { ocSubTotal, {{ Value, Reference }, 1, Value }},
- { ocSum, {{ Reference }, 1, Value }},
- { ocSumIf, {{ Reference, Value, Reference }, 0, Value }},
- { ocSumIfs, {{ Reference, Reference, Value }, 2, Value }},
+ { ocSubTotal, {{ Value, ReferenceOrRefArray }, 1, Value }},
+ { ocSum, {{ ReferenceOrRefArray }, 1, Value }},
+ { ocSumIf, {{ ReferenceOrRefArray, Value, Reference }, 0, Value }},
+ { ocSumIfs, {{ ReferenceOrRefArray, ReferenceOrRefArray, Value }, 2, Value }},
{ ocSumProduct, {{ ForceArray }, 1, Value }},
- { ocSumSQ, {{ Reference }, 1, Value }},
+ { ocSumSQ, {{ ReferenceOrRefArray }, 1, Value }},
{ ocSumX2DY2, {{ ForceArray, ForceArray }, 0, Value }},
{ ocSumX2MY2, {{ ForceArray, ForceArray }, 0, Value }},
{ ocSumXMY2, {{ ForceArray, ForceArray }, 0, Value }},
@@ -246,10 +248,10 @@ const ScParameterClassification::RawData ScParameterClassification::pRawData[] =
{ ocTrimMean, {{ Reference, Value }, 0, Value }},
{ ocUnion, {{ Reference, Reference }, 0, Reference }},
{ ocVLookup, {{ Value, ReferenceOrForceArray, Value, Value }, 0, Value }},
- { ocVar, {{ Reference }, 1, Value }},
- { ocVarA, {{ Reference }, 1, Value }},
- { ocVarP, {{ Reference }, 1, Value }},
- { ocVarPA, {{ Reference }, 1, Value }},
+ { ocVar, {{ ReferenceOrRefArray }, 1, Value }},
+ { ocVarA, {{ ReferenceOrRefArray }, 1, Value }},
+ { ocVarP, {{ ReferenceOrRefArray }, 1, Value }},
+ { ocVarPA, {{ ReferenceOrRefArray }, 1, Value }},
{ ocVarP_MS, {{ Reference }, 1, Value }},
{ ocVarS, {{ Reference }, 1, Value }},
{ ocWorkday_MS, {{ Value, Value, Value, Reference }, 0, Value }},
@@ -613,6 +615,9 @@ void ScParameterClassification::GenerateDocumentation()
case Reference :
aStr.append(" Reference");
break;
+ case ReferenceOrRefArray :
+ aStr.append(" ReferenceOrRefArray");
+ break;
case Array :
aStr.append(" Array");
break;
@@ -664,6 +669,9 @@ void ScParameterClassification::GenerateDocumentation()
case Reference :
aStr.append(" -> Reference");
break;
+ case ReferenceOrRefArray :
+ aStr.append(" -> ReferenceOrRefArray");
+ break;
case Array :
aStr.append(" -> Array");
break;