[Libreoffice-commits] .: Branch 'libreoffice-4-0' - 16 commits - formula/inc formula/source sc/inc sc/qa sc/source sc/util

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Sat Dec 15 15:01:01 PST 2012


 formula/inc/formula/compiler.hrc               |    8 
 formula/inc/formula/opcode.hxx                 |    4 
 formula/source/core/resource/core_resource.src |   25 
 formula/source/ui/dlg/parawin.cxx              |   45 
 sc/inc/helpids.h                               |    4 
 sc/inc/sc.hrc                                  |    1 
 sc/inc/scmatrix.hxx                            |    1 
 sc/qa/unit/ucalc.cxx                           |    4 
 sc/source/core/data/funcdesc.cxx               |   58 +
 sc/source/core/inc/interpre.hxx                |   19 
 sc/source/core/inc/parclass.hxx                |    6 
 sc/source/core/tool/interpr1.cxx               | 1233 ++++++++++++++++---------
 sc/source/core/tool/interpr4.cxx               |    4 
 sc/source/core/tool/parclass.cxx               |  321 +++---
 sc/source/core/tool/scmatrix.cxx               |   45 
 sc/source/filter/excel/excform.cxx             |    3 
 sc/source/filter/excel/xeformula.cxx           |    5 
 sc/source/filter/excel/xicontent.cxx           |    4 
 sc/source/filter/excel/xlformula.cxx           |   17 
 sc/source/filter/inc/xlformula.hxx             |    3 
 sc/source/filter/oox/formulabase.cxx           |   19 
 sc/source/ui/formdlg/dwfunctr.cxx              |   10 
 sc/source/ui/src/scfuncs.src                   |  162 +++
 sc/source/ui/unoobj/appluno.cxx                |    8 
 sc/source/ui/view/cellsh.cxx                   |    9 
 sc/util/hidother.src                           |   10 
 26 files changed, 1430 insertions(+), 598 deletions(-)

New commits:
commit 789ec89fceb949eee482ecb7731a3d7b1ac0660e
Author: Eike Rathke <erack at redhat.com>
Date:   Sat Dec 15 23:42:45 2012 +0100

    check conditions before checking for matrix fragment
    
    Was omitted in ab0096ed68cdc08906f518d3499a8e1afc5ba80c
    
    Change-Id: If3e1c141f02751ca7e6104ba21c246926fca843d
    (cherry picked from commit 63e10bf2383d22a5b3fafd95a688c2389f0076bc)

diff --git a/sc/source/ui/view/cellsh.cxx b/sc/source/ui/view/cellsh.cxx
index 6fbe22d..72c8be3 100644
--- a/sc/source/ui/view/cellsh.cxx
+++ b/sc/source/ui/view/cellsh.cxx
@@ -150,15 +150,18 @@ void ScCellShell::GetBlockState( SfxItemSet& rSet )
             case FID_FILL_TO_RIGHT:     // fill to left / right
             {
                 bDisable = !bSimpleArea || (nCol1 == 0 && nCol2 == 0);
-                bDisable = pDoc->HasSelectedBlockMatrixFragment(
-                    nCol1, nRow1, nCol1, nRow2, rMark );    // first column
+                if ( !bDisable && bEditable )
+                {   // do not damage matrix
+                    bDisable = pDoc->HasSelectedBlockMatrixFragment(
+                            nCol1, nRow1, nCol1, nRow2, rMark );    // first column
+                }
             }
             break;
             case FID_FILL_TO_LEFT:
             {
                 bDisable = (!bSimpleArea) || (nCol1 == MAXCOL && nCol2 == MAXCOL);
                 if ( !bDisable && bEditable )
-                {   // Matrix nicht zerreissen
+                {   // do not damage matrix
                     bDisable = pDoc->HasSelectedBlockMatrixFragment(
                         nCol2, nRow1, nCol2, nRow2, rMark );    // last column
                 }
commit a3588fefc9d50d7ff51f78859690fc30811259f4
Author: Eike Rathke <erack at redhat.com>
Date:   Sat Dec 15 23:29:35 2012 +0100

    add missing *IFS pieces to Excel filter
    
    These were omitted in ba950a50b0d0863e18ef781214eaaff9a8684790 because
    oox/source/xls/formulabase.cxx was moved to
    source/filter/oox/formulabase.cxx
    
    AVERAGEIF, AVERAGEIFS, COUNTIFS, SUMIFS
    
    Merged from Apache OO, parts of
    http://svn.apache.org/viewvc?rev=1381452&view=rev
    Original Apache OO committer: Andrew Rist <arist at apache.org>
    
    Original Author: Daniel Rentz [dr] <daniel.rentz at oracle.com>
    Original Committer: Daniel Rentz [dr] <daniel.rentz at oracle.com>
    
     # HG changeset patch
     # User Daniel Rentz [dr] <daniel.rentz at oracle.com>
     # Date 1299664669 -3600
     # Node ID 89feb2fb2947d76a15e2de8bc1def1edf20e4f88
     # Parent  1bf6d73db8a4ee709aa4d9d9d827efafc9c611d2
    
    Change-Id: I0756e1da4aa2acaefb86b5813e047b2768c192a1
    (cherry picked from commit 9a0bc6d06e30377d2ddf05bf5975dc8c850c8f97)

diff --git a/sc/source/filter/oox/formulabase.cxx b/sc/source/filter/oox/formulabase.cxx
index d8a1d26..a6f7e453 100644
--- a/sc/source/filter/oox/formulabase.cxx
+++ b/sc/source/filter/oox/formulabase.cxx
@@ -712,10 +712,10 @@ static const FunctionData saFuncTableOox[] =
     { 0,                        "CUBESET",              478,    NOID,   2,  5,  V, { VR, RX, VR }, 0 },
     { 0,                        "CUBESETCOUNT",         479,    NOID,   1,  1,  V, { VR }, 0 },
     { 0,                        "IFERROR",              480,    NOID,   2,  2,  V, { VO, RO }, 0 },
-    { 0,                        "COUNTIFS",             481,    NOID,   2,  MX, V, { RO, VR }, FUNCFLAG_PARAMPAIRS },
-    { 0,                        "SUMIFS",               482,    NOID,   3,  MX, V, { RO, RO, VR }, FUNCFLAG_PARAMPAIRS },
-    { 0,                        "AVERAGEIF",            483,    NOID,   2,  3,  V, { RO, VR, RO }, 0 },
-    { 0,                        "AVERAGEIFS",           484,    NOID,   3,  MX, V, { RO, RO, VR }, FUNCFLAG_PARAMPAIRS }
+    { "COUNTIFS",               "COUNTIFS",             481,    NOID,   2,  MX, V, { RO, VR }, FUNCFLAG_MACROCALL | FUNCFLAG_PARAMPAIRS },
+    { "SUMIFS",                 "SUMIFS",               482,    NOID,   3,  MX, V, { RO, RO, VR }, FUNCFLAG_MACROCALL | FUNCFLAG_PARAMPAIRS },
+    { "AVERAGEIF",              "AVERAGEIF",            483,    NOID,   2,  3,  V, { RO, VR, RO }, FUNCFLAG_MACROCALL },
+    { "AVERAGEIFS",             "AVERAGEIFS",           484,    NOID,   3,  MX, V, { RO, RO, VR }, FUNCFLAG_MACROCALL | FUNCFLAG_PARAMPAIRS }
 };
 
 /** Functions defined by OpenFormula, but not supported by Calc or by Excel. */
@@ -776,8 +776,6 @@ FunctionParamInfoIterator::FunctionParamInfoIterator( const FunctionInfo& rFuncI
     mpParamInfoEnd( rFuncInfo.mpParamInfos + FUNCINFO_PARAMINFOCOUNT ),
     mbParamPairs( rFuncInfo.mbParamPairs )
 {
-    OSL_ENSURE( !mbParamPairs || (mpParamInfo + 1 < mpParamInfoEnd),
-        "FunctionParamInfoIterator::FunctionParamInfoIterator - expecting at least 2 infos for paired parameters" );
 }
 
 bool FunctionParamInfoIterator::isCalcOnlyParam() const
@@ -797,12 +795,12 @@ FunctionParamInfoIterator& FunctionParamInfoIterator::operator++()
         // move pointer to next entry, if something explicit follows
         if( (mpParamInfo + 1 < mpParamInfoEnd) && (mpParamInfo[ 1 ].meValid != FUNC_PARAM_NONE) )
             ++mpParamInfo;
-        // points to last info, but parameter pairs expected, move to previous info
-        else if( mbParamPairs )
-            --mpParamInfo;
         // if last parameter type is 'Excel-only' or 'Calc-only', do not repeat it
         else if( isExcelOnlyParam() || isCalcOnlyParam() )
             mpParamInfo = 0;
+        // points to last info, but parameter pairs expected, move to previous info
+        else if( mbParamPairs )
+            --mpParamInfo;
         // otherwise: repeat last parameter class
     }
     return *this;
@@ -867,8 +865,7 @@ FunctionProviderImpl::FunctionProviderImpl( FilterType eFilter, BiffType eBiff,
         initFuncs( saFuncTableBiff5, STATIC_ARRAY_END( saFuncTableBiff5 ), nMaxParam, bImportFilter );
     if( eBiff >= BIFF8 )
         initFuncs( saFuncTableBiff8, STATIC_ARRAY_END( saFuncTableBiff8 ), nMaxParam, bImportFilter );
-    if( eFilter == FILTER_OOXML )
-        initFuncs( saFuncTableOox, STATIC_ARRAY_END( saFuncTableOox ), nMaxParam, bImportFilter );
+    initFuncs( saFuncTableOox, STATIC_ARRAY_END( saFuncTableOox ), nMaxParam, bImportFilter );
     initFuncs( saFuncTableOdf, STATIC_ARRAY_END( saFuncTableOdf ), nMaxParam, bImportFilter );
 }
 
commit b9e497bff826458970942483cad290d78597ef85
Author: Eike Rathke <erack at redhat.com>
Date:   Sat Dec 15 22:05:06 2012 +0100

    AVERAGEIFS with FUNCFLAG_PARAMPAIRS
    
    Change-Id: I51fa0259df84327db7dd07ae9ed5b109d40b6660
    (cherry picked from commit cc036a9b113c76cefba964cdac5a6f941c7a314c)

diff --git a/sc/source/filter/oox/formulabase.cxx b/sc/source/filter/oox/formulabase.cxx
index 3a9b742..d8a1d26 100644
--- a/sc/source/filter/oox/formulabase.cxx
+++ b/sc/source/filter/oox/formulabase.cxx
@@ -715,7 +715,7 @@ static const FunctionData saFuncTableOox[] =
     { 0,                        "COUNTIFS",             481,    NOID,   2,  MX, V, { RO, VR }, FUNCFLAG_PARAMPAIRS },
     { 0,                        "SUMIFS",               482,    NOID,   3,  MX, V, { RO, RO, VR }, FUNCFLAG_PARAMPAIRS },
     { 0,                        "AVERAGEIF",            483,    NOID,   2,  3,  V, { RO, VR, RO }, 0 },
-    { 0,                        "AVERAGEIFS",           484,    NOID,   3,  MX, V, { RO, RO, VR }, 0 }
+    { 0,                        "AVERAGEIFS",           484,    NOID,   3,  MX, V, { RO, RO, VR }, FUNCFLAG_PARAMPAIRS }
 };
 
 /** Functions defined by OpenFormula, but not supported by Calc or by Excel. */
commit 9578d05b9919115eeac2203d7b37746f0ce9540d
Author: Eike Rathke <erack at redhat.com>
Date:   Sat Dec 15 21:24:22 2012 +0100

    EvalMatrix<XorEvaluator> for Xor
    
    Change-Id: Ib0fdf7f8916a9d31fbcbedad925361d0cbe03b10
    (cherry picked from commit 98a4e4f2ad405b60484f033570e2d2164656007b)

diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx
index 810b8c2..66dcb2f 100644
--- a/sc/source/core/tool/scmatrix.cxx
+++ b/sc/source/core/tool/scmatrix.cxx
@@ -912,6 +912,14 @@ struct OrEvaluator
     OrEvaluator() : mbResult(false) {}
 };
 
+struct XorEvaluator
+{
+    bool mbResult;
+    void operate(double fVal) { mbResult ^= (fVal != 0.0); }
+    bool result() const { return mbResult; }
+    XorEvaluator() : mbResult(false) {}
+};
+
 // Do not short circuit logical operations, in case there are error values
 // these need to be propagated even if the result was determined earlier.
 template <typename _Evaluator>
@@ -959,26 +967,7 @@ double ScMatrixImpl::Xor() const
 {
     // All elements must be of value type.
     // True if an odd number of elements have a non-zero value.
-    bool bXor = false;
-    size_t nRows = maMat.size().row, nCols = maMat.size().column;
-    for (size_t i = 0; i < nRows; ++i)
-    {
-        for (size_t j = 0; j < nCols; ++j)
-        {
-            mdds::mtm::element_t eType = maMat.get_type(i, j);
-            if (eType != mdds::mtm::element_numeric && eType != mdds::mtm::element_boolean)
-                // assuming a CompareMat this is an error
-                return CreateDoubleError(errIllegalArgument);
-
-            double fVal = maMat.get_numeric(i, j);
-            if (!::rtl::math::isFinite(fVal))
-                // DoubleError
-                return fVal;
-
-            bXor ^= (fVal != 0.0);
-        }
-    }
-    return bXor;
+    return EvalMatrix<XorEvaluator>(maMat);
 }
 
 namespace {
commit a971c957757fe8bdf9b7c61b5c27b75b18dd67f5
Author: Eike Rathke <erack at redhat.com>
Date:   Sat Dec 15 20:46:41 2012 +0100

    EvalMatrix: do not short circuit, propagate errors
    
    Change-Id: I3118fb2a4d30e1626a05e9872b34a3c33bd487be
    (cherry picked from commit c86a9c4f045dfc8bbcad27cf36f1c6a8178a48a7)

diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx
index 259d747..810b8c2 100644
--- a/sc/source/core/tool/scmatrix.cxx
+++ b/sc/source/core/tool/scmatrix.cxx
@@ -296,6 +296,7 @@ void compareMatrix(MatrixImplType& rMat)
 
             double fVal = rMat.get_numeric(i, j);
             if (!::rtl::math::isFinite(fVal))
+                /* FIXME: this silently skips an error instead of propagating it! */
                 continue;
 
             bool b = aComp(fVal);
@@ -897,20 +898,24 @@ namespace {
 
 struct AndEvaluator
 {
-    bool isBadElem(double fVal) const { return fVal == 0; }
-    bool returnOnElem() const { return false; }
-    bool returnOnAllElems() const { return true; }
+    bool mbResult;
+    void operate(double fVal) { mbResult &= (fVal != 0.0); }
+    bool result() const { return mbResult; }
+    AndEvaluator() : mbResult(true) {}
 };
 
 struct OrEvaluator
 {
-    bool isBadElem(double fVal) const { return fVal != 0; }
-    bool returnOnElem() const { return true; }
-    bool returnOnAllElems() const { return false; }
+    bool mbResult;
+    void operate(double fVal) { mbResult |= (fVal != 0.0); }
+    bool result() const { return mbResult; }
+    OrEvaluator() : mbResult(false) {}
 };
 
+// Do not short circuit logical operations, in case there are error values
+// these need to be propagated even if the result was determined earlier.
 template <typename _Evaluator>
-bool EvalMatrix(const MatrixImplType& rMat)
+double EvalMatrix(const MatrixImplType& rMat)
 {
     _Evaluator aEval;
     size_t nRows = rMat.size().row, nCols = rMat.size().column;
@@ -928,11 +933,10 @@ bool EvalMatrix(const MatrixImplType& rMat)
                 // DoubleError
                 return fVal;
 
-            if (aEval.isBadElem(fVal))
-                return aEval.returnOnElem();
+            aEval.operate(fVal);
         }
     }
-    return aEval.returnOnAllElems();
+    return aEval.result();
 }
 
 }
commit d305e15265bc6e961bc1244e7cae6e99c2013f13
Author: Eike Rathke <erack at redhat.com>
Date:   Sat Dec 15 20:25:33 2012 +0100

    aString not rString
    
    Change-Id: Idb1f2db3377bbbf71067a27944b2f07865798972
    (cherry picked from commit cf309b04a0780c042393bcacf1666ce6053cdc2c)

diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 270236b..0b86108 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -5540,7 +5540,7 @@ void ScInterpreter::ScCountIf()
     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCountIf" );
     if ( MustHaveParamCount( GetByte(), 2 ) )
     {
-        String rString;
+        String aString;
         double fVal = 0.0;
         bool bIsString = true;
         switch ( GetStackType() )
@@ -5568,11 +5568,11 @@ void ScInterpreter::ScCountIf()
                             bIsString = false;
                         }
                         else
-                            GetCellString(rString, pCell);
+                            GetCellString(aString, pCell);
                         break;
                     case CELLTYPE_STRING :
                     case CELLTYPE_EDIT :
-                        GetCellString(rString, pCell);
+                        GetCellString(aString, pCell);
                         break;
                     default:
                         fVal = 0.0;
@@ -5585,12 +5585,12 @@ void ScInterpreter::ScCountIf()
             case svExternalDoubleRef:
             {
                 ScMatValType nType = GetDoubleOrStringFromMatrix( fVal,
-                        rString);
+                        aString);
                 bIsString = ScMatrix::IsNonValueType( nType);
             }
             break;
             case svString:
-                rString = GetString();
+                aString = GetString();
             break;
             default:
             {
@@ -5677,7 +5677,7 @@ void ScInterpreter::ScCountIf()
                 }
                 else
                 {
-                    rParam.FillInExcelSyntax(rString, 0);
+                    rParam.FillInExcelSyntax(aString, 0);
                     sal_uInt32 nIndex = 0;
                     bool bNumber = pFormatter->IsNumberFormat(
                             rItem.maString, nIndex, rItem.mfVal);
@@ -5762,7 +5762,7 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
         while (nParamCount > 1 && !nGlobalError)
         {
             // take criteria
-            String rString;
+            String aString;
             fVal = 0.0;
             bool bIsString = true;
             switch ( GetStackType() )
@@ -5788,11 +5788,11 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
                                     bIsString = false;
                                 }
                                 else
-                                    GetCellString(rString, pCell);
+                                    GetCellString(aString, pCell);
                                 break;
                             case CELLTYPE_STRING :
                             case CELLTYPE_EDIT :
-                                GetCellString(rString, pCell);
+                                GetCellString(aString, pCell);
                                 break;
                             default:
                                 fVal = 0.0;
@@ -5801,12 +5801,12 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
                     }
                     break;
                 case svString:
-                    rString = GetString();
+                    aString = GetString();
                     break;
                 case svMatrix :
                 case svExternalDoubleRef:
                     {
-                        ScMatValType nType = GetDoubleOrStringFromMatrix( fVal, rString);
+                        ScMatValType nType = GetDoubleOrStringFromMatrix( fVal, aString);
                         bIsString = ScMatrix::IsNonValueType( nType);
                     }
                     break;
@@ -5822,7 +5822,7 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
                                 bIsString = false;
                             }
                             else
-                                rString = pToken->GetString();
+                                aString = pToken->GetString();
                         }
                     }
                     break;
@@ -5928,7 +5928,7 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
                 }
                 else
                 {
-                    rParam.FillInExcelSyntax(rString, 0);
+                    rParam.FillInExcelSyntax(aString, 0);
                     sal_uInt32 nIndex = 0;
                     bool bNumber = pFormatter->IsNumberFormat(
                             rItem.maString, nIndex, rItem.mfVal);
commit 3d13d51660f9365b05df532d69f253561575c00b
Author: Eike Rathke <erack at redhat.com>
Date:   Sat Dec 15 20:18:57 2012 +0100

    ScInterpreter::IterateParametersIfs() with external references
    
    Added handling of svExternalSingleRef and svExternalDoubleRef for
    SUMIFS, AVERAGEIFS and COUNTIFS.
    
    Change-Id: I99bf6860f2bda5a99aeb85d4e4971032b1c7da0d
    (cherry picked from commit 470a581bcb7b1ffeecb434560ccd8ef0d1ba6d73)

diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index d2bc4a4..270236b 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -5804,11 +5804,28 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
                     rString = GetString();
                     break;
                 case svMatrix :
+                case svExternalDoubleRef:
                     {
                         ScMatValType nType = GetDoubleOrStringFromMatrix( fVal, rString);
                         bIsString = ScMatrix::IsNonValueType( nType);
                     }
                     break;
+                case svExternalSingleRef:
+                    {
+                        ScExternalRefCache::TokenRef pToken;
+                        PopExternalSingleRef(pToken);
+                        if (pToken)
+                        {
+                            if (pToken->GetType() == svDouble)
+                            {
+                                fVal = pToken->GetDouble();
+                                bIsString = false;
+                            }
+                            else
+                                rString = pToken->GetString();
+                        }
+                    }
+                    break;
                 default:
                     {
                         fVal = GetDouble();
@@ -5848,6 +5865,8 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
                     nTab2 = nTab1;
                     break;
                 case svMatrix:
+                case svExternalSingleRef:
+                case svExternalDoubleRef:
                     {
                         pQueryMatrix = PopMatrix();
                         if (!pQueryMatrix)
@@ -6002,6 +6021,8 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
                     nMainTab2 = nMainTab1;
                     break;
                 case svMatrix:
+                case svExternalSingleRef:
+                case svExternalDoubleRef:
                     {
                         pMainMatrix = PopMatrix();
                         if (!pMainMatrix)
commit c430d6117309c99364857b4470311d0a1b89d7bf
Author: Eike Rathke <erack at redhat.com>
Date:   Sat Dec 15 03:51:25 2012 +0100

    tabs to spaces
    
    Change-Id: Id832383518af0dd77e401e40512a890265b5d83e
    (cherry picked from commit 2a8470dca4726d512a33ac3af4ba140aed86909e)

diff --git a/formula/source/core/resource/core_resource.src b/formula/source/core/resource/core_resource.src
index b8fc214..8b0ee14 100644
--- a/formula/source/core/resource/core_resource.src
+++ b/formula/source/core/resource/core_resource.src
@@ -237,10 +237,10 @@ Resource RID_STRLIST_FUNCTION_NAMES_ENGLISH_ODFF
     String SC_OPCODE_COUNT_EMPTY_CELLS { Text = "COUNTBLANK" ; };
     String SC_OPCODE_COUNT_IF { Text = "COUNTIF" ; };
     String SC_OPCODE_SUM_IF { Text = "SUMIF" ; };
-	String SC_OPCODE_AVERAGE_IF { Text = "AVERAGEIF" ; };
-	String SC_OPCODE_SUM_IFS { Text = "SUMIFS" ; };
-	String SC_OPCODE_AVERAGE_IFS { Text = "AVERAGEIFS" ; };
-	String SC_OPCODE_COUNT_IFS { Text = "COUNTIFS" ; };
+    String SC_OPCODE_AVERAGE_IF { Text = "AVERAGEIF" ; };
+    String SC_OPCODE_SUM_IFS { Text = "SUMIFS" ; };
+    String SC_OPCODE_AVERAGE_IFS { Text = "AVERAGEIFS" ; };
+    String SC_OPCODE_COUNT_IFS { Text = "COUNTIFS" ; };
     String SC_OPCODE_LOOKUP { Text = "LOOKUP" ; };
     String SC_OPCODE_V_LOOKUP { Text = "VLOOKUP" ; };
     String SC_OPCODE_H_LOOKUP { Text = "HLOOKUP" ; };
@@ -575,10 +575,10 @@ Resource RID_STRLIST_FUNCTION_NAMES_ENGLISH
     String SC_OPCODE_COUNT_EMPTY_CELLS { Text = "COUNTBLANK" ; };
     String SC_OPCODE_COUNT_IF { Text = "COUNTIF" ; };
     String SC_OPCODE_SUM_IF { Text = "SUMIF" ; };
-	String SC_OPCODE_AVERAGE_IF { Text = "AVERAGEIF" ; };
-	String SC_OPCODE_SUM_IFS { Text = "SUMIFS" ; };
-	String SC_OPCODE_AVERAGE_IFS { Text = "AVERAGEIFS" ; };
-	String SC_OPCODE_COUNT_IFS { Text = "COUNTIFS" ; };
+    String SC_OPCODE_AVERAGE_IF { Text = "AVERAGEIF" ; };
+    String SC_OPCODE_SUM_IFS { Text = "SUMIFS" ; };
+    String SC_OPCODE_AVERAGE_IFS { Text = "AVERAGEIFS" ; };
+    String SC_OPCODE_COUNT_IFS { Text = "COUNTIFS" ; };
     String SC_OPCODE_LOOKUP { Text = "LOOKUP" ; };
     String SC_OPCODE_V_LOOKUP { Text = "VLOOKUP" ; };
     String SC_OPCODE_H_LOOKUP { Text = "HLOOKUP" ; };
@@ -1482,22 +1482,22 @@ Resource RID_STRLIST_FUNCTION_NAMES
     {
         Text [ en-US ] = "SUMIF" ;
     };
-	String SC_OPCODE_AVERAGE_IF
-	{
-		Text [ en-US ] = "AVERAGEIF" ;
-	};
-	String SC_OPCODE_SUM_IFS
-	{
-		Text [ en-US ] = "SUMIFS" ;
-	};
-	String SC_OPCODE_AVERAGE_IFS
-	{
-		Text [ en-US ] = "AVERAGEIFS" ;
-	};
-	String SC_OPCODE_COUNT_IFS
-	{
-		Text [ en-US ] = "COUNTIFS" ;
-	};
+    String SC_OPCODE_AVERAGE_IF
+    {
+        Text [ en-US ] = "AVERAGEIF" ;
+    };
+    String SC_OPCODE_SUM_IFS
+    {
+        Text [ en-US ] = "SUMIFS" ;
+    };
+    String SC_OPCODE_AVERAGE_IFS
+    {
+        Text [ en-US ] = "AVERAGEIFS" ;
+    };
+    String SC_OPCODE_COUNT_IFS
+    {
+        Text [ en-US ] = "COUNTIFS" ;
+    };
     String SC_OPCODE_LOOKUP
     {
         Text [ en-US ] = "LOOKUP" ;
commit 5a706356f23d35e699d696b58b7e30a313945bb7
Author: Marina Plakalovic <makkica at openoffice.org>
Date:   Sat Dec 15 03:41:47 2012 +0100

    calcishmakkica: #i114428# merge some XOR related code
    
    Merged from Apache OO with adaptions, parts of
    http://svn.apache.org/viewvc?rev=1381446&view=rev
    Original Apache OO committer: Andrew Rist <arist at apache.org>
    
    Original Author: Marina Plakalovic <makkica at openoffice.org>
    Original Committer: Eike Rathke [er] <eike.rathke at oracle.com>
    
     # HG changeset patch
     # User Eike Rathke [er] <eike.rathke at oracle.com>
     # Date 1284060031 -7200
     # Node ID 528da6bfd0daed4355d745590d5ac3a319b08fb4
     # Parent  237cb91dd986ff11eb100cc631206cda102e91f7
    
    Change-Id: If456792f23429a80582a48b022d268e6179316a1
    (cherry picked from commit 07df025a730be05d087559b939858260df003b97)

diff --git a/formula/source/core/resource/core_resource.src b/formula/source/core/resource/core_resource.src
index c552eb1..b8fc214 100644
--- a/formula/source/core/resource/core_resource.src
+++ b/formula/source/core/resource/core_resource.src
@@ -385,6 +385,7 @@ Resource RID_STRLIST_FUNCTION_NAMES_ENGLISH
     String SC_OPCODE_GREATER_EQUAL { Text = ">=" ; };
     String SC_OPCODE_AND { Text = "AND" ; };
     String SC_OPCODE_OR { Text = "OR" ; };
+    String SC_OPCODE_XOR { Text = "XOR" ; };
     String SC_OPCODE_INTERSECT { Text = "!" ; };
     String SC_OPCODE_UNION { Text = "~" ; };
     String SC_OPCODE_RANGE { Text = ":" ; };
diff --git a/sc/inc/scmatrix.hxx b/sc/inc/scmatrix.hxx
index 84d3e5a..bf1f15f 100644
--- a/sc/inc/scmatrix.hxx
+++ b/sc/inc/scmatrix.hxx
@@ -340,6 +340,7 @@ public:
 
     double And() const;       // logical AND of all matrix values, or NAN
     double Or() const;        // logical OR of all matrix values, or NAN
+    double Xor() const;       // logical XOR of all matrix values, or NAN
 
     IterateResult Sum(bool bTextAsZero) const;
     IterateResult SumSquare(bool bTextAsZero) const;
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 43109e1..d2bc4a4 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -1435,7 +1435,9 @@ void ScInterpreter::ScXor()
                                 bHaveValue = true;
                                 nRes ^= ( GetCellValue( aAdr, pCell ) != 0.0 );
                             }
-                            // else: Xcl raises no error here
+                            /* TODO: set error? Excel doesn't have XOR, but
+                             * doesn't set an error in this case for AND and
+                             * OR. */
                         }
                     }
                     break;
@@ -1471,11 +1473,12 @@ void ScInterpreter::ScXor()
                         if ( pMat )
                         {
                             bHaveValue = true;
-                            double fVal = pMat->Or();
+                            double fVal = pMat->Xor();
                             sal_uInt16 nErr = GetDoubleErrorValue( fVal );
                             if ( nErr )
                             {
                                 SetError( nErr );
+                                nRes = 0;
                             }
                             else
                                 nRes ^= ( fVal != 0.0 );
diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx
index cad0ab0..259d747 100644
--- a/sc/source/core/tool/scmatrix.cxx
+++ b/sc/source/core/tool/scmatrix.cxx
@@ -376,6 +376,7 @@ public:
     void CompareGreaterEqual();
     double And() const;
     double Or() const;
+    double Xor() const;
 
     ScMatrix::IterateResult Sum(bool bTextAsZero) const;
     ScMatrix::IterateResult SumSquare(bool bTextAsZero) const;
@@ -950,6 +951,32 @@ double ScMatrixImpl::Or() const
     return EvalMatrix<OrEvaluator>(maMat);
 }
 
+double ScMatrixImpl::Xor() const
+{
+    // All elements must be of value type.
+    // True if an odd number of elements have a non-zero value.
+    bool bXor = false;
+    size_t nRows = maMat.size().row, nCols = maMat.size().column;
+    for (size_t i = 0; i < nRows; ++i)
+    {
+        for (size_t j = 0; j < nCols; ++j)
+        {
+            mdds::mtm::element_t eType = maMat.get_type(i, j);
+            if (eType != mdds::mtm::element_numeric && eType != mdds::mtm::element_boolean)
+                // assuming a CompareMat this is an error
+                return CreateDoubleError(errIllegalArgument);
+
+            double fVal = maMat.get_numeric(i, j);
+            if (!::rtl::math::isFinite(fVal))
+                // DoubleError
+                return fVal;
+
+            bXor ^= (fVal != 0.0);
+        }
+    }
+    return bXor;
+}
+
 namespace {
 
 struct SumOp
@@ -1376,6 +1403,11 @@ double ScMatrix::Or() const
     return pImpl->Or();
 }
 
+double ScMatrix::Xor() const
+{
+    return pImpl->Xor();
+}
+
 ScMatrix::IterateResult ScMatrix::Sum(bool bTextAsZero) const
 {
     return pImpl->Sum(bTextAsZero);
diff --git a/sc/source/ui/src/scfuncs.src b/sc/source/ui/src/scfuncs.src
index 1080cc9..1b68b2e 100644
--- a/sc/source/ui/src/scfuncs.src
+++ b/sc/source/ui/src/scfuncs.src
@@ -2696,7 +2696,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS1
         };
         String 3 // Description of Parameter 1
         {
-            Text [ en-US ] = "Logical value 1, logical value 2, ... are 1 to 30 conditions to be tested and which returns either TRUE or FALSE." ;
+            Text [ en-US ] = "Logical value 1, logical value 2, ... are 1 to 30 conditions to be tested and which return either TRUE or FALSE." ;
         };
     };
      // -=*# Resource for function UND #*=-
commit be42c9c1087e18554940525231305a2c7e699acc
Author: Daniel Rentz [dr] <daniel.rentz at oracle.com>
Date:   Sat Dec 15 00:57:00 2012 +0100

    calcishmakkica: #i117283# support new functions in Excel filters
    
    AVERAGEIF, AVERAGEIFS, COUNTIFS, SUMIFS
    
    Merged from Apache OO with adaptions.
    http://svn.apache.org/viewvc?rev=1381452&view=rev
    Original Apache OO committer: Andrew Rist <arist at apache.org>
    
    Original Author: Daniel Rentz [dr] <daniel.rentz at oracle.com>
    Original Committer: Daniel Rentz [dr] <daniel.rentz at oracle.com>
    
     # HG changeset patch
     # User Daniel Rentz [dr] <daniel.rentz at oracle.com>
     # Date 1299664669 -3600
     # Node ID 89feb2fb2947d76a15e2de8bc1def1edf20e4f88
     # Parent  1bf6d73db8a4ee709aa4d9d9d827efafc9c611d2
    
    Change-Id: Ia70075284c5921faea58cae986e4e5eb090b1fab
    (cherry picked from commit ba950a50b0d0863e18ef781214eaaff9a8684790)

diff --git a/sc/source/filter/excel/excform.cxx b/sc/source/filter/excel/excform.cxx
index 822f8d1..b66b507 100644
--- a/sc/source/filter/excel/excform.cxx
+++ b/sc/source/filter/excel/excform.cxx
@@ -191,7 +191,8 @@ ConvErr ExcelToSc::Convert( const ScTokenArray*& pErgebnis, XclImpStream& aIn, s
     TokenId         nMerk0;
     const sal_Bool      bRangeName = eFT == FT_RangeName;
     const sal_Bool      bSharedFormula = eFT == FT_SharedFormula;
-    const sal_Bool      bRNorSF = bRangeName || bSharedFormula;
+    const sal_Bool      bConditional = eFT == FT_CondFormat;
+    const sal_Bool      bRNorSF = bRangeName || bSharedFormula || bConditional;
 
     ScSingleRefData     aSRD;
     ScComplexRefData        aCRD;
diff --git a/sc/source/filter/excel/xeformula.cxx b/sc/source/filter/excel/xeformula.cxx
index bc66024..d450dfe 100644
--- a/sc/source/filter/excel/xeformula.cxx
+++ b/sc/source/filter/excel/xeformula.cxx
@@ -202,11 +202,14 @@ void XclExpFuncData::IncParamInfoIdx()
     if( mpParamInfo )
     {
         // move pointer to next entry, if something explicit follows
-        if( (static_cast<size_t>(mpParamInfo - mrFuncInfo.mpParamInfos + 1) < EXC_FUNCINFO_PARAMINFO_COUNT) && (mpParamInfo[ 1 ].meValid != EXC_PARAM_NONE) )
+        if( (static_cast< size_t >( mpParamInfo - mrFuncInfo.mpParamInfos + 1 ) < EXC_FUNCINFO_PARAMINFO_COUNT) && (mpParamInfo[ 1 ].meValid != EXC_PARAM_NONE) )
             ++mpParamInfo;
         // if last parameter type is 'Excel-only' or 'Calc-only', do not repeat it
         else if( IsExcelOnlyParam() || IsCalcOnlyParam() )
             mpParamInfo = 0;
+        // points to last info, but parameter pairs expected, move to previous info
+        else if( mrFuncInfo.IsParamPairs() )
+            --mpParamInfo;
         // otherwise: repeat last parameter class
     }
 }
diff --git a/sc/source/filter/excel/xicontent.cxx b/sc/source/filter/excel/xicontent.cxx
index f35f530..7e09fb4 100644
--- a/sc/source/filter/excel/xicontent.cxx
+++ b/sc/source/filter/excel/xicontent.cxx
@@ -744,7 +744,7 @@ void XclImpValidationManager::ReadDV( XclImpStream& rStrm )
     {
         const ScTokenArray* pTokArr = 0;
         rFmlaConv.Reset();
-        rFmlaConv.Convert( pTokArr, rStrm, nLen, false, FT_RangeName );
+            rFmlaConv.Convert( pTokArr, rStrm, nLen, false, FT_CondFormat );
         // formula converter owns pTokArr -> create a copy of the token array
         if( pTokArr )
             xTokArr1.reset( pTokArr->Clone() );
@@ -763,7 +763,7 @@ void XclImpValidationManager::ReadDV( XclImpStream& rStrm )
     {
         const ScTokenArray* pTokArr = 0;
         rFmlaConv.Reset();
-        rFmlaConv.Convert( pTokArr, rStrm, nLen, false, FT_RangeName );
+            rFmlaConv.Convert( pTokArr, rStrm, nLen, false, FT_CondFormat );
         // formula converter owns pTokArr -> create a copy of the token array
         if( pTokArr )
             xTokArr2.reset( pTokArr->Clone() );
diff --git a/sc/source/filter/excel/xlformula.cxx b/sc/source/filter/excel/xlformula.cxx
index 24c8adb..58b3aa9 100644
--- a/sc/source/filter/excel/xlformula.cxx
+++ b/sc/source/filter/excel/xlformula.cxx
@@ -355,6 +355,19 @@ static const XclFunctionInfo saFuncTable_8[] =
     { ocEuroConvert,        255,    4,  6,  V, { RO_E, RO }, EXC_FUNCFLAG_EXPORTONLY, "EUROCONVERT" }
 };
 
+/** Functions new in OOXML. */
+static const XclFunctionInfo saFuncTable_Oox[] =
+{
+    { ocCountIfs,           NOID,   2,  MX, V, { RO, VR }, EXC_FUNCFLAG_IMPORTONLY|EXC_FUNCFLAG_PARAMPAIRS, EXC_FUNCNAME( "COUNTIFS" ) },
+    { ocCountIfs,           255,    3,  MX, V, { RO_E, RO, VR }, EXC_FUNCFLAG_EXPORTONLY|EXC_FUNCFLAG_PARAMPAIRS, EXC_FUNCNAME( "COUNTIFS" ) },
+    { ocSumIfs,             NOID,   3,  MX, V, { RO, RO, VR }, EXC_FUNCFLAG_IMPORTONLY|EXC_FUNCFLAG_PARAMPAIRS, EXC_FUNCNAME( "SUMIFS" ) },
+    { ocSumIfs,             255,    4,  MX, V, { RO_E, RO, RO, VR }, EXC_FUNCFLAG_EXPORTONLY|EXC_FUNCFLAG_PARAMPAIRS, EXC_FUNCNAME( "SUMIFS" ) },
+    { ocAverageIf,          NOID,   2,  3,  V, { RO, VR, RO }, EXC_FUNCFLAG_IMPORTONLY, EXC_FUNCNAME( "AVERAGEIF" ) },
+    { ocAverageIf,          255,    3,  4,  V, { RO_E, RO, VR, RO }, EXC_FUNCFLAG_EXPORTONLY, EXC_FUNCNAME( "AVERAGEIF" ) },
+    { ocAverageIfs,         NOID,   3,  MX, V, { RO, RO, VR }, EXC_FUNCFLAG_IMPORTONLY|EXC_FUNCFLAG_PARAMPAIRS, EXC_FUNCNAME( "AVERAGEIFS" ) },
+    { ocAverageIfs,         255,    4,  MX, V, { RO_E, RO, RO, VR }, EXC_FUNCFLAG_EXPORTONLY|EXC_FUNCFLAG_PARAMPAIRS, EXC_FUNCNAME( "AVERAGEIFS" ) }
+};
+
 #define EXC_FUNCENTRY_ODF( opcode, minparam, maxparam, flags, asciiname ) \
     { opcode, NOID, minparam,     maxparam,     V, { VR },       EXC_FUNCFLAG_IMPORTONLY|(flags), EXC_FUNCNAME_ODF( asciiname ) }, \
     { opcode,  255, (minparam)+1, (maxparam)+1, V, { RO_E, RO }, EXC_FUNCFLAG_EXPORTONLY|(flags), EXC_FUNCNAME_ODF( asciiname ) }
@@ -420,6 +433,7 @@ XclFunctionProvider::XclFunctionProvider( const XclRoot& rRoot )
         (this->*pFillFunc)( saFuncTable_5, STATIC_ARRAY_END( saFuncTable_5 ) );
     if( eBiff >= EXC_BIFF8 )
         (this->*pFillFunc)( saFuncTable_8, STATIC_ARRAY_END( saFuncTable_8 ) );
+    (this->*pFillFunc)( saFuncTable_Oox, STATIC_ARRAY_END( saFuncTable_Oox ) );
     (this->*pFillFunc)( saFuncTable_Odf, STATIC_ARRAY_END( saFuncTable_Odf ) );
 }
 
@@ -453,7 +467,8 @@ void XclFunctionProvider::FillXclFuncMap( const XclFunctionInfo* pBeg, const Xcl
     {
         if( !::get_flag( pIt->mnFlags, EXC_FUNCFLAG_EXPORTONLY ) )
         {
-            maXclFuncMap[ pIt->mnXclFunc ] = pIt;
+            if( pIt->mnXclFunc != NOID )
+                maXclFuncMap[ pIt->mnXclFunc ] = pIt;
             if( pIt->IsMacroFunc() )
                 maXclMacroNameMap[ pIt->GetMacroFuncName() ] = pIt;
         }
diff --git a/sc/source/filter/inc/xlformula.hxx b/sc/source/filter/inc/xlformula.hxx
index 62c93b6..7768769 100644
--- a/sc/source/filter/inc/xlformula.hxx
+++ b/sc/source/filter/inc/xlformula.hxx
@@ -284,6 +284,7 @@ const size_t EXC_FUNCINFO_PARAMINFO_COUNT   = 5;        /// Number of parameter
 const sal_uInt8 EXC_FUNCFLAG_VOLATILE       = 0x01;     /// Result is volatile (e.g. NOW() function).
 const sal_uInt8 EXC_FUNCFLAG_IMPORTONLY     = 0x02;     /// Only used in import filter.
 const sal_uInt8 EXC_FUNCFLAG_EXPORTONLY     = 0x04;     /// Only used in export filter.
+const sal_uInt8 EXC_FUNCFLAG_PARAMPAIRS     = 0x08;     /// Optional parameters are expected to appear in pairs.
 
 // selected function IDs
 const sal_uInt16 EXC_FUNCID_IF              = 1;
@@ -314,6 +315,8 @@ struct XclFunctionInfo
 
     /** Returns true, if the function is volatile. */
     inline bool         IsVolatile() const { return ::get_flag( mnFlags, EXC_FUNCFLAG_VOLATILE ); }
+    /** Returns true, if optional parameters are expected to appear in pairs. */
+    inline bool         IsParamPairs() const { return ::get_flag( mnFlags, EXC_FUNCFLAG_PARAMPAIRS ); }
     /** Returns true, if the function parameter count is fixed. */
     inline bool         IsFixedParamCount() const { return (mnXclFunc != EXC_FUNCID_EXTERNCALL) && (mnMinParamCount == mnMaxParamCount); }
     /** Returns true, if the function is simulated by a macro call. */
commit 5d5ab4368a0ad0d520ca1728282d9fbb8d9f32bd
Author: Eike Rathke [er] <eike.rathke at oracle.com>
Date:   Sat Dec 15 00:28:26 2012 +0100

    calcishmakkica: init vars
    
    Merged from Apache OO.
    http://svn.apache.org/viewvc?rev=1381450&view=rev
    Original Apache OO committer: Andrew Rist <arist at apache.org>
    
    Original Author: Eike Rathke [er] <eike.rathke at oracle.com>
    Original Committer: Eike Rathke [er] <eike.rathke at oracle.com>
    
     # HG changeset patch
     # User Eike Rathke [er] <eike.rathke at oracle.com>
     # Date 1298043566 -3600
     # Node ID 346e0beefed21519bbb6545bccfea022dd75ed66
     # Parent  2416febcae5c81a24b40439f09f91e40a686b911
    
    Change-Id: I5c2b6f9a34336a734bd96e067ec57a2f58d4488c
    (cherry picked from commit 65721e490a753178c9e90dbe9eecb70124d94117)

diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 435a509..43109e1 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -5600,12 +5600,12 @@ void ScInterpreter::ScCountIf()
         size_t nRefInList = 0;
         while (nParam-- > 0)
         {
-            SCCOL nCol1;
-            SCROW nRow1;
-            SCTAB nTab1;
-            SCCOL nCol2;
-            SCROW nRow2;
-            SCTAB nTab2;
+            SCCOL nCol1 = 0;
+            SCROW nRow1 = 0;
+            SCTAB nTab1 = 0;
+            SCCOL nCol2 = 0;
+            SCROW nRow2 = 0;
+            SCTAB nTab2 = 0;
             ScMatrixRef pQueryMatrix;
             switch ( GetStackType() )
             {
@@ -5819,12 +5819,12 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
             // take range
             nParam = 1;
             nRefInList = 0;
-            SCCOL nCol1;
-            SCROW nRow1;
-            SCTAB nTab1;
-            SCCOL nCol2;
-            SCROW nRow2;
-            SCTAB nTab2;
+            SCCOL nCol1 = 0;
+            SCROW nRow1 = 0;
+            SCTAB nTab1 = 0;
+            SCCOL nCol2 = 0;
+            SCROW nRow2 = 0;
+            SCTAB nTab2 = 0;
             ScMatrixRef pQueryMatrix;
             switch ( GetStackType() )
             {
@@ -5973,12 +5973,12 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
             nParam = 1;
             nRefInList = 0;
             bool bNull = true;
-            SCCOL nMainCol1;
-            SCROW nMainRow1;
-            SCTAB nMainTab1;
-            SCCOL nMainCol2;
-            SCROW nMainRow2;
-            SCTAB nMainTab2;
+            SCCOL nMainCol1 = 0;
+            SCROW nMainRow1 = 0;
+            SCTAB nMainTab1 = 0;
+            SCCOL nMainCol2 = 0;
+            SCROW nMainRow2 = 0;
+            SCTAB nMainTab2 = 0;
             ScMatrixRef pMainMatrix;
             switch ( GetStackType() )
             {
commit 5885fb33c383005af0ec72fb79b6b1af2375b8f4
Author: Eike Rathke [er] <eike.rathke at oracle.com>
Date:   Sat Dec 15 00:28:26 2012 +0100

    calcishmakkica: WaE wntmsci12
    
    Merged from Apache OO.
    http://svn.apache.org/viewvc?rev=1381449&view=rev
    Original Apache OO committer: Andrew Rist <arist at apache.org>
    
    Original Author: Eike Rathke [er] <eike.rathke at oracle.com>
    Original Committer: Eike Rathke [er] <eike.rathke at oracle.com>
    
     # HG changeset patch
     # User Eike Rathke [er] <eike.rathke at oracle.com>
     # Date 1297940971 -3600
     # Node ID 2416febcae5c81a24b40439f09f91e40a686b911
     # Parent  0d84fd3534ea7cda60f795f7dc5d99db58d8cc6e
    
    Change-Id: I46835f0cef9bf83b76e7501a5291f7724b23f871
    (cherry picked from commit f28cafdc1d637ffb1409fa104e867ffcf00580f4)

diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 7d7b867..435a509 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -6067,8 +6067,8 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
                     {
                         if (pResMat->GetDouble( nCol, nRow) == nQueryCount)
                         {
-                            aAdr.SetCol( nCol + nMainCol1);
-                            aAdr.SetRow( nRow + nMainRow1);
+                            aAdr.SetCol( static_cast<SCCOL>(nCol) + nMainCol1);
+                            aAdr.SetRow( static_cast<SCROW>(nRow) + nMainRow1);
                             ScBaseCell* pCell = GetCell( aAdr );
                             if ( HasCellValueData(pCell) )
                             {
commit d38c4abc5329ca673aef205ca704c965382301f7
Author: Eike Rathke [er] <eike.rathke at oracle.com>
Date:   Sat Dec 15 00:06:28 2012 +0100

    calcishmakkica: #i90269# #i95144# #i101466#
    
    * For SUMIFS, AVERAGEIFS and COUNTIFS:
      * All ranges must be of same dimension and size.
      * Bail out if error encountered for any parameter, without calculating
        remaining parameters.
    * Adapted ScParameterClassification to cope with paired repeated parameters.
    * In function resource have a trailing blank for repeated parameters so the
      number is appended with a blank between.
    
    Merged from Apache OO with adaptions.
    http://svn.apache.org/viewvc?rev=1381448&view=rev
    Original Apache OO committer: Andrew Rist <arist at apache.org>
    
    Original Author: Eike Rathke [er] <eike.rathke at oracle.com>
    Original Committer: Eike Rathke [er] <eike.rathke at oracle.com>
    
     # HG changeset patch
     # User Eike Rathke [er] <eike.rathke at oracle.com>
     # Date 1288820521 -3600
     # Node ID 79da8a1033b663c919f0dc48799f70256bffa497
     # Parent  02cf226fcde498f6fd926d45df497e9fb412fe0f
    
    Change-Id: Ica4faa4e7a46cd5f480cb898785daa51a50ec23b
    (cherry picked from commit 9d73ad60be888fd83551367712eb9c1f12f838ce)

diff --git a/sc/source/core/inc/parclass.hxx b/sc/source/core/inc/parclass.hxx
index 6037038..b2500ff 100644
--- a/sc/source/core/inc/parclass.hxx
+++ b/sc/source/core/inc/parclass.hxx
@@ -98,7 +98,7 @@ private:
         const static sal_Int32 nMaxParams = 7;
 
         Type        nParam[nMaxParams];
-        bool        bRepeatLast;
+        sal_uInt8   nRepeatLast;
     };
 
     // SUNWS7 needs a forward declared friend, otherwise members of the outer
@@ -159,11 +159,11 @@ private:
                                         return 0;
                                     }
 
-                                /** Whether last parameter type is repeated. */
+                                /** Whether last parameter types are repeated. */
     static  inline  bool        HasRepeatParameters( OpCode eOp)
                                     {
                                         return eOp <= SC_OPCODE_LAST_OPCODE_ID
-                                            && pData[eOp].aData.bRepeatLast;
+                                            && pData[eOp].aData.nRepeatLast > 0;
                                     }
 #endif // OSL_DEBUG_LEVEL
 };
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 8e59245..7d7b867 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -5753,6 +5753,8 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
         double fCount = 0.0;
         short nParam = 1;
         size_t nRefInList = 0;
+        SCCOL nDimensionCols = 0;
+        SCROW nDimensionRows = 0;
 
         while (nParamCount > 1 && !nGlobalError)
         {
@@ -5811,6 +5813,9 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
                     }
             }
 
+            if (nGlobalError)
+                continue;   // and bail out, no need to evaluate other arguments
+
             // take range
             nParam = 1;
             nRefInList = 0;
@@ -5860,28 +5865,32 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
                     SetError( errIllegalParameter);
             }
             if ( nTab1 != nTab2 )
+                SetError( errIllegalArgument);
+
+            // All reference ranges must be of same dimension and size.
+            if (!nDimensionCols)
+                nDimensionCols = nCol2 - nCol1 + 1;
+            if (!nDimensionRows)
+                nDimensionRows = nRow2 - nRow1 + 1;
+            if ((nDimensionCols != (nCol2 - nCol1 + 1)) || (nDimensionRows != (nRow2 - nRow1 + 1)))
+                SetError ( errIllegalArgument);
+
+            // recalculate matrix values
+            if (nGlobalError == 0)
             {
-                SetError( errIllegalParameter);
-            }
-            // initialize temporary result matrix
-            if (!pResMat)
-            {
-                SCSIZE nResC, nResR;
-                nResC = nCol2 - nCol1 + 1;
-                nResR = nRow2 - nRow1 + 1;
-                pResMat = GetNewMat(nResC, nResR);
+                // initialize temporary result matrix
                 if (!pResMat)
                 {
-                    SetError( errIllegalParameter);
-                }
-                else
-                {
-                    pResMat->FillDouble( 0.0, 0, 0, nResC-1, nResR-1);
+                    SCSIZE nResC, nResR;
+                    nResC = nCol2 - nCol1 + 1;
+                    nResR = nRow2 - nRow1 + 1;
+                    pResMat = GetNewMat(nResC, nResR);
+                    if (!pResMat)
+                        SetError( errIllegalParameter);
+                    else
+                        pResMat->FillDouble( 0.0, 0, 0, nResC-1, nResR-1);
                 }
-            }
-            // recalculate matrix values
-            if (nGlobalError == 0)
-            {
+
                 ScQueryParam rParam;
                 rParam.nRow1       = nRow1;
                 rParam.nRow2       = nRow2;
@@ -5952,13 +5961,12 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
                     }
                 }
             }
-            else
-            {
-                SetError( errIllegalParameter);
-            }
             nParamCount -= 2;
         }
 
+        if (nGlobalError)
+            return 0;   // bail out
+
         // main range - only for AVERAGEIFS and SUMIFS
         if (nParamCount == 1)
         {
@@ -6011,9 +6019,15 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
                     SetError( errIllegalParameter);
             }
             if ( nMainTab1 != nMainTab2 )
-            {
-                SetError( errIllegalParameter);
-            }
+                SetError( errIllegalArgument);
+
+            // All reference ranges must be of same dimension and size.
+            if ((nDimensionCols != (nMainCol2 - nMainCol1 + 1)) || (nDimensionRows != (nMainRow2 - nMainRow1 + 1)))
+                SetError ( errIllegalArgument);
+
+            if (nGlobalError)
+                return 0;   // bail out
+
             // end-result calculation
             ScAddress aAdr;
             aAdr.SetTab( nMainTab1 );
@@ -6084,7 +6098,7 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
                         ++fCount;
             }
         }
-        //
+
         switch( eFunc )
         {
             case ifSUMIFS:     fRes = ::rtl::math::approxAdd( fSum, fMem ); break;
diff --git a/sc/source/core/tool/parclass.cxx b/sc/source/core/tool/parclass.cxx
index d3ca7f9..ebdbb4a 100644
--- a/sc/source/core/tool/parclass.cxx
+++ b/sc/source/core/tool/parclass.cxx
@@ -42,151 +42,154 @@
  * - OpCodes not specified at all will have at least one and only parameters of
  *   type Value, no check is done on the count of parameters => no Bounds type
  *   is returned.
- * - For OpCodes with a variable number of parameters the type of the last
- *   parameter specified determines the type of all following parameters.
+ * - For OpCodes with a variable number of parameters the type(s) of the last
+ *   repeated parameter(s) specified determine(s) the type(s) of all following
+ *   parameters.
  */
 
 const ScParameterClassification::RawData ScParameterClassification::pRawData[] =
 {
+    // { OpCode, {{ Type, ... }, nRepeatLast }},
+
     // IF() and CHOOSE() are somewhat special, since the ScJumpMatrix is
     // created inside those functions and ConvertMatrixParameters() is not
     // called for them.
-    { ocIf,              {{ Array, Reference, Reference                          }, false }},
-    { ocChose,           {{ Array, Reference                                     }, true }},
+    { ocIf,              {{ Array, Reference, Reference                          }, 0 }},
+    { ocChose,           {{ Array, Reference                                     }, 1 }},
     // Other specials.
-    { ocOpen,            {{ Bounds                                               }, false }},
-    { ocClose,           {{ Bounds                                               }, false }},
-    { ocSep,             {{ Bounds                                               }, false }},
-    { ocNoName,          {{ Bounds                                               }, false }},
-    { ocErrCell,         {{ Bounds                                               }, false }},
-    { ocStop,            {{ Bounds                                               }, false }},
-    { ocUnion,           {{ Reference, Reference                                 }, false }},
-    { ocRange,           {{ Reference, Reference                                 }, false }},
+    { ocOpen,            {{ Bounds                                               }, 0 }},
+    { ocClose,           {{ Bounds                                               }, 0 }},
+    { ocSep,             {{ Bounds                                               }, 0 }},
+    { ocNoName,          {{ Bounds                                               }, 0 }},
+    { ocErrCell,         {{ Bounds                                               }, 0 }},
+    { ocStop,            {{ Bounds                                               }, 0 }},
+    { ocUnion,           {{ Reference, Reference                                 }, 0 }},
+    { ocRange,           {{ Reference, Reference                                 }, 0 }},
     // Functions with Value parameters only but not in resource.
-    { ocBackSolver,      {{ Value, Value, Value                                  }, false }},
-    { ocTableOp,         {{ Value, Value, Value, Value, Value                    }, false }},
+    { ocBackSolver,      {{ Value, Value, Value                                  }, 0 }},
+    { ocTableOp,         {{ Value, Value, Value, Value, Value                    }, 0 }},
     // Operators and functions.
-    { ocAdd,             {{ Array, Array                                         }, false }},
-    { ocAmpersand,       {{ Array, Array                                         }, false }},
-    { ocAnd,             {{ Reference                                            }, true }},
-    { ocAreas,           {{ Reference                                            }, false }},
-    { ocAveDev,          {{ Reference                                            }, true }},
-    { ocAverage,         {{ Reference                                            }, true }},
-    { ocAverageA,        {{ Reference                                            }, true }},
-    { ocAverageIf,       {{ Reference, Value, Reference                          }, false }},
-    { ocAverageIfs,      {{ Reference, Reference, Value                          }, true }},
-    { ocCell,            {{ Value, Reference                                     }, false }},
-    { ocColumn,          {{ Reference                                            }, false }},
-    { ocColumns,         {{ Reference                                            }, true }},
-    { ocCorrel,          {{ ForceArray, ForceArray                               }, false }},
-    { ocCount,           {{ Reference                                            }, true }},
-    { ocCount2,          {{ Reference                                            }, true }},
-    { ocCountEmptyCells, {{ Reference                                            }, false }},
-    { ocCountIf,         {{ Reference, Value                                     }, false }},
-    { ocCountIfs,        {{ Reference, Value                                     }, true }},
-    { ocCovar,           {{ ForceArray, ForceArray                               }, false }},
-    { ocDBAverage,       {{ Reference, Reference, Reference                      }, false }},
-    { ocDBCount,         {{ Reference, Reference, Reference                      }, false }},
-    { ocDBCount2,        {{ Reference, Reference, Reference                      }, false }},
-    { ocDBGet,           {{ Reference, Reference, Reference                      }, false }},
-    { ocDBMax,           {{ Reference, Reference, Reference                      }, false }},
-    { ocDBMin,           {{ Reference, Reference, Reference                      }, false }},
-    { ocDBProduct,       {{ Reference, Reference, Reference                      }, false }},
-    { ocDBStdDev,        {{ Reference, Reference, Reference                      }, false }},
-    { ocDBStdDevP,       {{ Reference, Reference, Reference                      }, false }},
-    { ocDBSum,           {{ Reference, Reference, Reference                      }, false }},
-    { ocDBVar,           {{ Reference, Reference, Reference                      }, false }},
-    { ocDBVarP,          {{ Reference, Reference, Reference                      }, false }},
-    { ocDevSq,           {{ Reference                                            }, true }},
-    { ocDiv,             {{ Array, Array                                         }, false }},
-    { ocEqual,           {{ Array, Array                                         }, false }},
-    { ocForecast,        {{ Value, ForceArray, ForceArray                        }, false }},
-    { ocFrequency,       {{ Reference, Reference                                 }, false }},
-    { ocFTest,           {{ ForceArray, ForceArray                               }, false }},
-    { ocGeoMean,         {{ Reference                                            }, true }},
-    { ocGCD,             {{ Reference                                            }, true }},
-    { ocGreater,         {{ Array, Array                                         }, false }},
-    { ocGreaterEqual,    {{ Array, Array                                         }, false }},
-    { ocGrowth,          {{ Reference, Reference, Reference, Value               }, false }},
-    { ocHarMean,         {{ Reference                                            }, true }},
-    { ocHLookup,         {{ Value, Reference, Value, Value                       }, false }},
-    { ocIRR,             {{ Reference, Value                                     }, false }},
-    { ocIndex,           {{ Reference, Value, Value, Value                       }, false }},
-    { ocIntercept,       {{ ForceArray, ForceArray                               }, false }},
-    { ocIntersect,       {{ Reference, Reference                                 }, false }},
-    { ocIsRef,           {{ Reference                                            }, false }},
-    { ocLCM,             {{ Reference                                            }, true }},
-    { ocKurt,            {{ Reference                                            }, true }},
-    { ocLarge,           {{ Reference, Value                                     }, false }},
-    { ocLess,            {{ Array, Array                                         }, false }},
-    { ocLessEqual,       {{ Array, Array                                         }, false }},
-    { ocLookup,          {{ Value, ReferenceOrForceArray, ReferenceOrForceArray  }, false }},
-    { ocMatch,           {{ Value, Reference, Reference                          }, false }},
-    { ocMatDet,          {{ ForceArray                                           }, false }},
-    { ocMatInv,          {{ ForceArray                                           }, false }},
-    { ocMatMult,         {{ ForceArray, ForceArray                               }, false }},
-    { ocMatTrans,        {{ Array                                                }, false }}, // strange, but Xcl doesn't force MatTrans array
-    { ocMatValue,        {{ Reference, Value, Value                              }, false }},
-    { ocMax,             {{ Reference                                            }, true }},
-    { ocMaxA,            {{ Reference                                            }, true }},
-    { ocMedian,          {{ Reference                                            }, true }},
-    { ocMin,             {{ Reference                                            }, true }},
-    { ocMinA,            {{ Reference                                            }, true }},
-    { ocMIRR,            {{ Reference, Value, Value                              }, false }},
-    { ocModalValue,      {{ ForceArray                                           }, true }},
-    { ocMul,             {{ Array, Array                                         }, false }},
-    { ocMultiArea,       {{ Reference                                            }, true }},
-    { ocNPV,             {{ Value, Reference                                     }, true }},
-    { ocNeg,             {{ Array                                                }, false }},
-    { ocNegSub,          {{ Array                                                }, false }},
-    { ocNot,             {{ Array                                                }, false }},
-    { ocNotEqual,        {{ Array, Array                                         }, false }},
-    { ocOffset,          {{ Reference, Value, Value, Value, Value                }, false }},
-    { ocOr,              {{ Reference                                            }, true }},
-    { ocPearson,         {{ ForceArray, ForceArray                               }, false }},
-    { ocPercentile,      {{ Reference, Value                                     }, false }},
-    { ocPercentrank,     {{ Reference, Value                                     }, false }},
-    { ocPow,             {{ Array, Array                                         }, false }},
-    { ocPower,           {{ Array, Array                                         }, false }},
-    { ocProb,            {{ ForceArray, ForceArray, Value, Value                 }, false }},
-    { ocProduct,         {{ Reference                                            }, true }},
-    { ocQuartile,        {{ Reference, Value                                     }, false }},
-    { ocRank,            {{ Value, Reference, Value                              }, false }},
-    { ocRGP,             {{ Reference, Reference, Value, Value                   }, false }},
-    { ocRKP,             {{ Reference, Reference, Value, Value                   }, false }},
-    { ocRow,             {{ Reference                                            }, false }},
-    { ocRows,            {{ Reference                                            }, true }},
-    { ocRSQ,             {{ ForceArray, ForceArray                               }, false }},
-    { ocSchiefe,         {{ Reference                                            }, true }},
-    { ocSlope,           {{ ForceArray, ForceArray                               }, false }},
-    { ocSmall,           {{ Reference, Value                                     }, false }},
-    { ocStDev,           {{ Reference                                            }, true }},
-    { ocStDevA,          {{ Reference                                            }, true }},
-    { ocStDevP,          {{ Reference                                            }, true }},
-    { ocStDevPA,         {{ Reference                                            }, true }},
-    { ocSTEYX,           {{ ForceArray, ForceArray                               }, false }},
-    { ocSub,             {{ Array, Array                                         }, false }},
-    { ocSubTotal,        {{ Value, Reference                                     }, true }},
-    { ocSum,             {{ Reference                                            }, true }},
-    { ocSumIf,           {{ Reference, Value, Reference                          }, false }},
-    { ocSumIfs,          {{ Reference, Reference, Value                          }, true }},
-    { ocSumProduct,      {{ ForceArray                                           }, true }},
-    { ocSumSQ,           {{ Reference                                            }, true }},
-    { ocSumX2MY2,        {{ ForceArray, ForceArray                               }, false }},
-    { ocSumX2DY2,        {{ ForceArray, ForceArray                               }, false }},
-    { ocSumXMY2,         {{ ForceArray, ForceArray                               }, false }},
-    { ocTable,           {{ Reference                                            }, false }},
-    { ocTables,          {{ Reference                                            }, true }},
-    { ocTrend,           {{ Reference, Reference, Reference, Value               }, false }},
-    { ocTrimMean,        {{ Reference, Value                                     }, false }},
-    { ocTTest,           {{ ForceArray, ForceArray, Value, Value                 }, false }},
-    { ocVar,             {{ Reference                                            }, true }},
-    { ocVarA,            {{ Reference                                            }, true }},
-    { ocVarP,            {{ Reference                                            }, true }},
-    { ocVarPA,           {{ Reference                                            }, true }},
-    { ocVLookup,         {{ Value, Reference, Value, Value                       }, false }},
-    { ocXor,             {{ Reference                                            }, true }},
-    { ocZTest,           {{ Reference, Value, Value                              }, false }},
+    { ocAdd,             {{ Array, Array                                         }, 0 }},
+    { ocAmpersand,       {{ Array, Array                                         }, 0 }},
+    { ocAnd,             {{ Reference                                            }, 1 }},
+    { ocAreas,           {{ Reference                                            }, 0 }},
+    { ocAveDev,          {{ Reference                                            }, 1 }},
+    { ocAverage,         {{ Reference                                            }, 1 }},
+    { ocAverageA,        {{ Reference                                            }, 1 }},
+    { ocAverageIf,       {{ Reference, Value, Reference                          }, 0 }},
+    { ocAverageIfs,      {{ Reference, Reference, Value                          }, 2 }},
+    { ocCell,            {{ Value, Reference                                     }, 0 }},
+    { ocColumn,          {{ Reference                                            }, 0 }},
+    { ocColumns,         {{ Reference                                            }, 1 }},
+    { ocCorrel,          {{ ForceArray, ForceArray                               }, 0 }},
+    { ocCount,           {{ Reference                                            }, 1 }},
+    { ocCount2,          {{ Reference                                            }, 1 }},
+    { ocCountEmptyCells, {{ Reference                                            }, 0 }},
+    { ocCountIf,         {{ Reference, Value                                     }, 0 }},
+    { ocCountIfs,        {{ Reference, Value                                     }, 2 }},
+    { ocCovar,           {{ ForceArray, ForceArray                               }, 0 }},
+    { ocDBAverage,       {{ Reference, Reference, Reference                      }, 0 }},
+    { ocDBCount,         {{ Reference, Reference, Reference                      }, 0 }},
+    { ocDBCount2,        {{ Reference, Reference, Reference                      }, 0 }},
+    { ocDBGet,           {{ Reference, Reference, Reference                      }, 0 }},
+    { ocDBMax,           {{ Reference, Reference, Reference                      }, 0 }},
+    { ocDBMin,           {{ Reference, Reference, Reference                      }, 0 }},
+    { ocDBProduct,       {{ Reference, Reference, Reference                      }, 0 }},
+    { ocDBStdDev,        {{ Reference, Reference, Reference                      }, 0 }},
+    { ocDBStdDevP,       {{ Reference, Reference, Reference                      }, 0 }},
+    { ocDBSum,           {{ Reference, Reference, Reference                      }, 0 }},
+    { ocDBVar,           {{ Reference, Reference, Reference                      }, 0 }},
+    { ocDBVarP,          {{ Reference, Reference, Reference                      }, 0 }},
+    { ocDevSq,           {{ Reference                                            }, 1 }},
+    { ocDiv,             {{ Array, Array                                         }, 0 }},
+    { ocEqual,           {{ Array, Array                                         }, 0 }},
+    { ocForecast,        {{ Value, ForceArray, ForceArray                        }, 0 }},
+    { ocFrequency,       {{ Reference, Reference                                 }, 0 }},
+    { ocFTest,           {{ ForceArray, ForceArray                               }, 0 }},
+    { ocGeoMean,         {{ Reference                                            }, 1 }},
+    { ocGCD,             {{ Reference                                            }, 1 }},
+    { ocGreater,         {{ Array, Array                                         }, 0 }},
+    { ocGreaterEqual,    {{ Array, Array                                         }, 0 }},
+    { ocGrowth,          {{ Reference, Reference, Reference, Value               }, 0 }},
+    { ocHarMean,         {{ Reference                                            }, 1 }},
+    { ocHLookup,         {{ Value, Reference, Value, Value                       }, 0 }},
+    { ocIRR,             {{ Reference, Value                                     }, 0 }},
+    { ocIndex,           {{ Reference, Value, Value, Value                       }, 0 }},
+    { ocIntercept,       {{ ForceArray, ForceArray                               }, 0 }},
+    { ocIntersect,       {{ Reference, Reference                                 }, 0 }},
+    { ocIsRef,           {{ Reference                                            }, 0 }},
+    { ocLCM,             {{ Reference                                            }, 1 }},
+    { ocKurt,            {{ Reference                                            }, 1 }},
+    { ocLarge,           {{ Reference, Value                                     }, 0 }},
+    { ocLess,            {{ Array, Array                                         }, 0 }},
+    { ocLessEqual,       {{ Array, Array                                         }, 0 }},
+    { ocLookup,          {{ Value, ReferenceOrForceArray, ReferenceOrForceArray  }, 0 }},
+    { ocMatch,           {{ Value, Reference, Reference                          }, 0 }},
+    { ocMatDet,          {{ ForceArray                                           }, 0 }},
+    { ocMatInv,          {{ ForceArray                                           }, 0 }},
+    { ocMatMult,         {{ ForceArray, ForceArray                               }, 0 }},
+    { ocMatTrans,        {{ Array                                                }, 0 }}, // strange, but Xcl doesn't force MatTrans array
+    { ocMatValue,        {{ Reference, Value, Value                              }, 0 }},
+    { ocMax,             {{ Reference                                            }, 1 }},
+    { ocMaxA,            {{ Reference                                            }, 1 }},
+    { ocMedian,          {{ Reference                                            }, 1 }},
+    { ocMin,             {{ Reference                                            }, 1 }},
+    { ocMinA,            {{ Reference                                            }, 1 }},
+    { ocMIRR,            {{ Reference, Value, Value                              }, 0 }},
+    { ocModalValue,      {{ ForceArray                                           }, 1 }},
+    { ocMul,             {{ Array, Array                                         }, 0 }},
+    { ocMultiArea,       {{ Reference                                            }, 1 }},
+    { ocNPV,             {{ Value, Reference                                     }, 1 }},
+    { ocNeg,             {{ Array                                                }, 0 }},
+    { ocNegSub,          {{ Array                                                }, 0 }},
+    { ocNot,             {{ Array                                                }, 0 }},
+    { ocNotEqual,        {{ Array, Array                                         }, 0 }},
+    { ocOffset,          {{ Reference, Value, Value, Value, Value                }, 0 }},
+    { ocOr,              {{ Reference                                            }, 1 }},
+    { ocPearson,         {{ ForceArray, ForceArray                               }, 0 }},
+    { ocPercentile,      {{ Reference, Value                                     }, 0 }},
+    { ocPercentrank,     {{ Reference, Value                                     }, 0 }},
+    { ocPow,             {{ Array, Array                                         }, 0 }},
+    { ocPower,           {{ Array, Array                                         }, 0 }},
+    { ocProb,            {{ ForceArray, ForceArray, Value, Value                 }, 0 }},
+    { ocProduct,         {{ Reference                                            }, 1 }},
+    { ocQuartile,        {{ Reference, Value                                     }, 0 }},
+    { ocRank,            {{ Value, Reference, Value                              }, 0 }},
+    { ocRGP,             {{ Reference, Reference, Value, Value                   }, 0 }},
+    { ocRKP,             {{ Reference, Reference, Value, Value                   }, 0 }},
+    { ocRow,             {{ Reference                                            }, 0 }},
+    { ocRows,            {{ Reference                                            }, 1 }},
+    { ocRSQ,             {{ ForceArray, ForceArray                               }, 0 }},
+    { ocSchiefe,         {{ Reference                                            }, 1 }},
+    { ocSlope,           {{ ForceArray, ForceArray                               }, 0 }},
+    { ocSmall,           {{ Reference, Value                                     }, 0 }},
+    { ocStDev,           {{ Reference                                            }, 1 }},
+    { ocStDevA,          {{ Reference                                            }, 1 }},
+    { ocStDevP,          {{ Reference                                            }, 1 }},
+    { ocStDevPA,         {{ Reference                                            }, 1 }},
+    { ocSTEYX,           {{ ForceArray, ForceArray                               }, 0 }},
+    { ocSub,             {{ Array, Array                                         }, 0 }},
+    { ocSubTotal,        {{ Value, Reference                                     }, 1 }},
+    { ocSum,             {{ Reference                                            }, 1 }},
+    { ocSumIf,           {{ Reference, Value, Reference                          }, 0 }},
+    { ocSumIfs,          {{ Reference, Reference, Value                          }, 2 }},
+    { ocSumProduct,      {{ ForceArray                                           }, 1 }},
+    { ocSumSQ,           {{ Reference                                            }, 1 }},
+    { ocSumX2MY2,        {{ ForceArray, ForceArray                               }, 0 }},
+    { ocSumX2DY2,        {{ ForceArray, ForceArray                               }, 0 }},
+    { ocSumXMY2,         {{ ForceArray, ForceArray                               }, 0 }},
+    { ocTable,           {{ Reference                                            }, 0 }},
+    { ocTables,          {{ Reference                                            }, 1 }},
+    { ocTrend,           {{ Reference, Reference, Reference, Value               }, 0 }},
+    { ocTrimMean,        {{ Reference, Value                                     }, 0 }},
+    { ocTTest,           {{ ForceArray, ForceArray, Value, Value                 }, 0 }},
+    { ocVar,             {{ Reference                                            }, 1 }},
+    { ocVarA,            {{ Reference                                            }, 1 }},
+    { ocVarP,            {{ Reference                                            }, 1 }},
+    { ocVarPA,           {{ Reference                                            }, 1 }},
+    { ocVLookup,         {{ Value, Reference, Value, Value                       }, 0 }},
+    { ocXor,             {{ Reference                                            }, 1 }},
+    { ocZTest,           {{ Reference, Value, Value                              }, 0 }},
     // Excel doubts:
     // ocN, ocT: Excel says (and handles) Reference, error? This means no
     // position dependent SingleRef if DoubleRef, and no array calculation,
@@ -194,10 +197,10 @@ const ScParameterClassification::RawData ScParameterClassification::pRawData[] =
     // for ocN (position dependent intersection worked before but array
     // didn't). No specifics in ODFF, so the general rule applies. Gnumeric
     // does the same.
-    { ocN, {{ Value }, false }},
-    { ocT, {{ Value }, false }},
+    { ocN, {{ Value }, 0 }},
+    { ocT, {{ Value }, 0 }},
     // The stopper.
-    { ocNone, {{ Bounds }, false } }
+    { ocNone, {{ Bounds }, 0 } }
 };
 
 ScParameterClassification::RunData * ScParameterClassification::pData = NULL;
@@ -229,18 +232,19 @@ void ScParameterClassification::Init()
 #endif
             memcpy( &(pRun->aData), &(pRaw->aData), sizeof(CommonData));
             // fill 0-initialized fields with real values
-            if ( pRun->aData.bRepeatLast )
+            if ( pRun->aData.nRepeatLast )
             {
-                Type eLast = Unknown;
                 for ( sal_Int32 j=0; j < CommonData::nMaxParams; ++j )
                 {
                     if ( pRun->aData.nParam[j] )
-                    {
-                        eLast = pRun->aData.nParam[j];
                         pRun->nMinParams = sal::static_int_cast<sal_uInt8>( j+1 );
-                    }
+                    else if (j >= pRun->aData.nRepeatLast)
+                        pRun->aData.nParam[j] =  pRun->aData.nParam[j - pRun->aData.nRepeatLast];
                     else
-                        pRun->aData.nParam[j] = eLast;
+                    {
+                        OSL_TRACE( "bad classification: eOp %d, repeated param %d negative offset", pRaw->eOp, j);
+                        pRun->aData.nParam[j] =  Unknown;
+                    }
                 }
             }
             else
@@ -301,15 +305,23 @@ ScParameterClassification::Type ScParameterClassification::GetParameterType(
     }
     if ( 0 <= (short)eOp && eOp <= SC_OPCODE_LAST_OPCODE_ID )
     {
+        sal_uInt8 nRepeat;
+        Type eType;
         if ( nParameter < CommonData::nMaxParams )
+            eType = pData[eOp].aData.nParam[nParameter];
+        else if ( (nRepeat = pData[eOp].aData.nRepeatLast) > 0 )
         {
-            Type eT = pData[eOp].aData.nParam[nParameter];
-            return eT == Unknown ? Value : eT;
+            // The usual case is 1 repeated parameter, we don't need to
+            // calculate that on each call.
+            sal_uInt16 nParam = (nRepeat > 1 ?
+                    (pData[eOp].nMinParams -
+                     ((nParameter - pData[eOp].nMinParams) % nRepeat)) :
+                    pData[eOp].nMinParams);
+            return pData[eOp].aData.nParam[nParam];
         }
-        else if ( pData[eOp].aData.bRepeatLast )
-            return pData[eOp].aData.nParam[CommonData::nMaxParams-1];
         else
-            return Bounds;
+            eType = Bounds;
+        return eType == Unknown ? Value : eType;
     }
     return Unknown;
 }
@@ -410,12 +422,12 @@ void ScParameterClassification::MergeArgumentsFromFunctionResource()
         if ( nArgs >= PAIRED_VAR_ARGS )
         {
             nArgs -= PAIRED_VAR_ARGS - 2;
-            pRun->aData.bRepeatLast = true;
+            pRun->aData.nRepeatLast = 2;
         }
         else if ( nArgs >= VAR_ARGS )
         {
             nArgs -= VAR_ARGS - 1;
-            pRun->aData.bRepeatLast = true;
+            pRun->aData.nRepeatLast = 1;
         }
         if ( nArgs > CommonData::nMaxParams )
         {
@@ -425,15 +437,15 @@ void ScParameterClassification::MergeArgumentsFromFunctionResource()
             aBuf.append(": ");
             aBuf.append(sal_Int32(nArgs));
             OSL_FAIL( aBuf.getStr());
-            nArgs = CommonData::nMaxParams;
-            pRun->aData.bRepeatLast = true;
+            nArgs = CommonData::nMaxParams - 1;
+            pRun->aData.nRepeatLast = 1;
         }
         pRun->nMinParams = static_cast< sal_uInt8 >( nArgs );
         for ( sal_Int32 j=0; j < nArgs; ++j )
         {
             pRun->aData.nParam[j] = Value;
         }
-        if ( pRun->aData.bRepeatLast )
+        if ( pRun->aData.nRepeatLast )
         {
             for ( sal_Int32 j = nArgs; j < CommonData::nMaxParams; ++j )
             {
diff --git a/sc/source/ui/src/scfuncs.src b/sc/source/ui/src/scfuncs.src
index b24b0b1..1080cc9 100644
--- a/sc/source/ui/src/scfuncs.src
+++ b/sc/source/ui/src/scfuncs.src
@@ -42,7 +42,9 @@
  *
  *          Number of parameters. VAR_ARGS if variable number, or
  *          VAR_ARGS+number if number of fixed parameters and variable
- *          arguments following.
+ *          arguments following. Or PAIRED_VAR_ARGS if variable number of
+ *          paired parameters, or PAIRED_VAR_ARGS+number if number of fixed
+ *          parameters and variable paired arguments following.
  *
  *          For every parameter:
  *
@@ -2995,7 +2997,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS1
 		};
 		String 4 // Name of Parameter 2
 		{
-			Text [ en-US ] = "range" ;
+			Text [ en-US ] = "range " ;
 		};
 		String 5 // Description of Parameter 2
 		{
@@ -3003,7 +3005,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS1
 		};
 		String 6 // Name of Parameter 3
 		{
-			Text [ en-US ] = "criteria" ;
+			Text [ en-US ] = "criteria " ;
 		};
 		String 7 // Description of Parameter 3
 		{
@@ -3036,7 +3038,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS1
 		};
 		String 4 // Name of Parameter 2
 		{
-			Text [ en-US ] = "range" ;
+			Text [ en-US ] = "range " ;
 		};
 		String 5 // Description of Parameter 2
 		{
@@ -3044,7 +3046,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS1
 		};
 		String 6 // Name of Parameter 3
 		{
-			Text [ en-US ] = "criteria" ;
+			Text [ en-US ] = "criteria " ;
 		};
 		String 7 // Description of Parameter 3
 		{
@@ -3069,7 +3071,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS1
 		};
 		String 2 // Name of Parameter 1
 		{
-			Text [ en-US ] = "range" ;
+			Text [ en-US ] = "range " ;
 		};
 		String 3 // Description of Parameter 1
 		{
@@ -3077,7 +3079,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS1
 		};
 		String 4 // Name of Parameter 2
 		{
-			Text [ en-US ] = "criteria" ;
+			Text [ en-US ] = "criteria " ;
 		};
 		String 5 // Description of Parameter 2
 		{
commit 69ae7b2a9a752faaa282a8fd5d38fce41ab2193a
Author: Marina Plakalovic <makkica at openoffice.org>
Date:   Fri Dec 14 23:40:18 2012 +0100

    calcishmakkica: #i90269# #i95144# #i101466# implement SUMIFS, AVERAGEIFS, COUNTIFS
    
    Merged from Apache OO with adaptions.
    http://svn.apache.org/viewvc?rev=1381447&view=rev
    Original Apache OO committer: Andrew Rist <arist at apache.org>
    
    Original Author: Marina Plakalovic <makkica at openoffice.org>
    Original Committer: Eike Rathke [er] <eike.rathke at oracle.com>
    
     # HG changeset patch
     # User Eike Rathke [er] <eike.rathke at oracle.com>
     # Date 1288810126 -3600
     # Node ID 02cf226fcde498f6fd926d45df497e9fb412fe0f
     # Parent  528da6bfd0daed4355d745590d5ac3a319b08fb4
    
    Change-Id: I08754653cd2ff20536ad3e9f260f747cb127ccdd
    (cherry picked from commit f2cb873631b8b21b54a55beaba532f4bd616a9c6)

diff --git a/formula/inc/formula/compiler.hrc b/formula/inc/formula/compiler.hrc
index 9ae1c18..582e3a5 100644
--- a/formula/inc/formula/compiler.hrc
+++ b/formula/inc/formula/compiler.hrc
@@ -393,8 +393,11 @@
 #define SC_OPCODE_GET_DATEDIF       400
 #define SC_OPCODE_XOR               401
 #define SC_OPCODE_AVERAGE_IF        402
-#define SC_OPCODE_STOP_2_PAR        403
-#define SC_OPCODE_LAST_OPCODE_ID    403     /* last OpCode */
+#define SC_OPCODE_SUM_IFS           403
+#define SC_OPCODE_AVERAGE_IFS       404
+#define SC_OPCODE_COUNT_IFS         405
+#define SC_OPCODE_STOP_2_PAR        406
+#define SC_OPCODE_LAST_OPCODE_ID    405     /* last OpCode */
 
 /*** Internal ***/
 #define SC_OPCODE_INTERNAL_BEGIN   9999
diff --git a/formula/inc/formula/opcode.hxx b/formula/inc/formula/opcode.hxx
index 046d25b..cd1831b 100644
--- a/formula/inc/formula/opcode.hxx
+++ b/formula/inc/formula/opcode.hxx
@@ -274,7 +274,10 @@ enum OpCodeEnum
         ocCountEmptyCells   = SC_OPCODE_COUNT_EMPTY_CELLS,
         ocCountIf           = SC_OPCODE_COUNT_IF,
         ocSumIf             = SC_OPCODE_SUM_IF,
-		ocAverageIf			= SC_OPCODE_AVERAGE_IF,
+        ocAverageIf         = SC_OPCODE_AVERAGE_IF,
+        ocSumIfs            = SC_OPCODE_SUM_IFS,
+        ocAverageIfs        = SC_OPCODE_AVERAGE_IFS,
+        ocCountIfs          = SC_OPCODE_COUNT_IFS,
         ocLookup            = SC_OPCODE_LOOKUP,
         ocVLookup           = SC_OPCODE_V_LOOKUP,
         ocHLookup           = SC_OPCODE_H_LOOKUP,
diff --git a/formula/source/core/resource/core_resource.src b/formula/source/core/resource/core_resource.src
index 1c165d0..c552eb1 100644
--- a/formula/source/core/resource/core_resource.src
+++ b/formula/source/core/resource/core_resource.src
@@ -238,6 +238,9 @@ Resource RID_STRLIST_FUNCTION_NAMES_ENGLISH_ODFF
     String SC_OPCODE_COUNT_IF { Text = "COUNTIF" ; };
     String SC_OPCODE_SUM_IF { Text = "SUMIF" ; };
 	String SC_OPCODE_AVERAGE_IF { Text = "AVERAGEIF" ; };
+	String SC_OPCODE_SUM_IFS { Text = "SUMIFS" ; };
+	String SC_OPCODE_AVERAGE_IFS { Text = "AVERAGEIFS" ; };
+	String SC_OPCODE_COUNT_IFS { Text = "COUNTIFS" ; };
     String SC_OPCODE_LOOKUP { Text = "LOOKUP" ; };
     String SC_OPCODE_V_LOOKUP { Text = "VLOOKUP" ; };
     String SC_OPCODE_H_LOOKUP { Text = "HLOOKUP" ; };
@@ -572,6 +575,9 @@ Resource RID_STRLIST_FUNCTION_NAMES_ENGLISH
     String SC_OPCODE_COUNT_IF { Text = "COUNTIF" ; };
     String SC_OPCODE_SUM_IF { Text = "SUMIF" ; };
 	String SC_OPCODE_AVERAGE_IF { Text = "AVERAGEIF" ; };
+	String SC_OPCODE_SUM_IFS { Text = "SUMIFS" ; };
+	String SC_OPCODE_AVERAGE_IFS { Text = "AVERAGEIFS" ; };
+	String SC_OPCODE_COUNT_IFS { Text = "COUNTIFS" ; };
     String SC_OPCODE_LOOKUP { Text = "LOOKUP" ; };
     String SC_OPCODE_V_LOOKUP { Text = "VLOOKUP" ; };
     String SC_OPCODE_H_LOOKUP { Text = "HLOOKUP" ; };
@@ -1479,6 +1485,18 @@ Resource RID_STRLIST_FUNCTION_NAMES
 	{
 		Text [ en-US ] = "AVERAGEIF" ;
 	};
+	String SC_OPCODE_SUM_IFS
+	{
+		Text [ en-US ] = "SUMIFS" ;
+	};
+	String SC_OPCODE_AVERAGE_IFS
+	{
+		Text [ en-US ] = "AVERAGEIFS" ;
+	};
+	String SC_OPCODE_COUNT_IFS
+	{
+		Text [ en-US ] = "COUNTIFS" ;
+	};
     String SC_OPCODE_LOOKUP
     {
         Text [ en-US ] = "LOOKUP" ;
diff --git a/formula/source/ui/dlg/parawin.cxx b/formula/source/ui/dlg/parawin.cxx
index d51f4dc..23d8ec8 100644
--- a/formula/source/ui/dlg/parawin.cxx
+++ b/formula/source/ui/dlg/parawin.cxx
@@ -30,6 +30,7 @@
 #include "ForResId.hrc"
 
 #define VAR_ARGS 30
+#define PAIRED_VAR_ARGS (VAR_ARGS + VAR_ARGS)
 namespace formula
 {
 //============================================================================
@@ -109,7 +110,7 @@ void ParaWin::UpdateArgDesc( sal_uInt16 nArg )
             aArgName += ' ';
             aArgName += (pFuncDesc->isParameterOptional(nRealArg)) ? m_sOptional : m_sRequired ;
         }
-        else
+        else if ( nArgs < PAIRED_VAR_ARGS )
         {
             sal_uInt16 nFix = nArgs - VAR_ARGS;
             sal_uInt16 nPos = ( nArg < nFix ? nArg : nFix );
@@ -123,6 +124,24 @@ void ParaWin::UpdateArgDesc( sal_uInt16 nArg )
 
             aArgName += (nArg > nFix || pFuncDesc->isParameterOptional(nRealArg)) ? m_sOptional : m_sRequired ;
         }
+        else
+        {
+            sal_uInt16 nFix = nArgs - PAIRED_VAR_ARGS;
+            sal_uInt16 nPos;
+            if ( nArg < nFix )
+                nPos = nArg;
+            else
+                nPos = nFix + ( (nArg-nFix) % 2);
+            sal_uInt16 nRealArg = (nPos < aVisibleArgMapping.size() ?
+                    aVisibleArgMapping[nPos] : aVisibleArgMapping.back());
+            aArgDesc  = pFuncDesc->getParameterDescription(nRealArg);
+            aArgName  = pFuncDesc->getParameterName(nRealArg);
+            if ( nArg >= nFix )
+                aArgName += String::CreateFromInt32((nArg-nFix)/2 + 1);
+            aArgName += ' ';
+
+            aArgName += (nArg > (nFix+1) || pFuncDesc->isParameterOptional(nRealArg)) ? m_sOptional : m_sRequired ;
+        }
 
         SetArgumentDesc(aArgDesc);
         SetArgumentText(aArgName);
@@ -142,7 +161,7 @@ void ParaWin::UpdateArgInput( sal_uInt16 nOffset, sal_uInt16 i )
             SetArgName      (i,pFuncDesc->getParameterName(nRealArg));
         }
     }
-    else
+    else if ( nArgs < PAIRED_VAR_ARGS)
     {
         sal_uInt16 nFix = nArgs - VAR_ARGS;
         sal_uInt16 nPos = ( nArg < nFix ? nArg : nFix );
@@ -160,6 +179,28 @@ void ParaWin::UpdateArgInput( sal_uInt16 nOffset, sal_uInt16 i )
         else
             SetArgName( i, pFuncDesc->getParameterName(nRealArg) );
     }
+    else
+    {
+        sal_uInt16 nFix = nArgs - PAIRED_VAR_ARGS;
+        sal_uInt16 nPos;
+        if ( nArg < nFix )
+            nPos = nArg;
+        else
+            nPos = nFix + ( (nArg-nFix) % 2);
+        sal_uInt16 nRealArg = (nPos < aVisibleArgMapping.size() ?
+                aVisibleArgMapping[nPos] : aVisibleArgMapping.back());
+        SetArgNameFont( i,
+                (nArg > (nFix+1) || pFuncDesc->isParameterOptional(nRealArg)) ?
+                aFntLight : aFntBold );
+        if ( nArg >= nFix )
+        {
+            String aArgName( pFuncDesc->getParameterName(nRealArg) );
+            aArgName += String::CreateFromInt32((nArg-nFix)/2 + 1);
+            SetArgName( i, aArgName );
+        }
+        else
+            SetArgName( i, pFuncDesc->getParameterName(nRealArg) );
+    }
     if(nArg<nArgs) SetArgVal(i,aParaArray[nArg]);
 
 }
diff --git a/sc/inc/helpids.h b/sc/inc/helpids.h
index 6615183..2e2aa4c 100644
--- a/sc/inc/helpids.h
+++ b/sc/inc/helpids.h
@@ -446,6 +446,9 @@
 #define HID_FUNC_PRODUKT                                        "SC_HID_FUNC_PRODUKT"
 #define HID_FUNC_SUMMEWENN                                      "SC_HID_FUNC_SUMMEWENN"
 #define HID_FUNC_AVERAGEIF                                      "SC_HID_FUNC_AVERAGEIF"
+#define HID_FUNC_SUMIFS                                         "SC_HID_FUNC_SUMIFS"
+#define HID_FUNC_AVERAGEIFS                                     "SC_HID_FUNC_AVERAGEIFS"
+#define HID_FUNC_COUNTIFS                                       "SC_HID_FUNC_COUNTIFS"
 #define HID_FUNC_ZAEHLENWENN                                    "SC_HID_FUNC_ZAEHLENWENN"
 #define HID_FUNC_WURZEL                                         "SC_HID_FUNC_WURZEL"
 #define HID_FUNC_ZUFALLSZAHL                                    "SC_HID_FUNC_ZUFALLSZAHL"
diff --git a/sc/inc/sc.hrc b/sc/inc/sc.hrc
index 2849c9f..9eaf61f 100644
--- a/sc/inc/sc.hrc
+++ b/sc/inc/sc.hrc
@@ -28,6 +28,7 @@
 #include "helpids.h"
 
 #define VAR_ARGS                30 // variable Parameter in scfuncs.src
+#define PAIRED_VAR_ARGS			(VAR_ARGS + VAR_ARGS)
 
 // areas
 
diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index aed60e7..55b8b9c 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -3972,6 +3972,7 @@ void Test::testFunctionLists()
         "ATAN2",
         "ATANH",
         "AVERAGEIF",
+        "AVERAGEIFS",
         "BITAND",
         "BITLSHIFT",
         "BITOR",
@@ -3987,6 +3988,7 @@ void Test::testFunctionLists()
         "COTH",
         "COUNTBLANK",
         "COUNTIF",
+        "COUNTIFS",
         "CSC",
         "CSCH",
         "DEGREES",
@@ -4022,6 +4024,7 @@ void Test::testFunctionLists()
         "SUBTOTAL",
         "SUM",
         "SUMIF",
+        "SUMIFS",
         "SUMSQ",
         "TAN",
         "TANH",
diff --git a/sc/source/core/data/funcdesc.cxx b/sc/source/core/data/funcdesc.cxx
index e34dd20..32500ee 100644
--- a/sc/source/core/data/funcdesc.cxx
+++ b/sc/source/core/data/funcdesc.cxx
@@ -84,7 +84,10 @@ ScFuncDesc::~ScFuncDesc()
 void ScFuncDesc::Clear()
 {
     sal_uInt16 nArgs = nArgCount;
-    if (nArgs >= VAR_ARGS) nArgs -= VAR_ARGS-1;
+    if (nArgs >= PAIRED_VAR_ARGS)
+        nArgs -= PAIRED_VAR_ARGS - 2;
+    else if (nArgs >= VAR_ARGS)
+        nArgs -= VAR_ARGS - 1;
     if (nArgs)
     {
         for (sal_uInt16 i=0; i<nArgs; i++ )
@@ -147,7 +150,7 @@ void ScFuncDesc::Clear()
                     aSig.getLength() >= 2)
                 aSig.setLength(aSig.getLength() - 2);
         }
-        else
+        else if ( nArgCount < PAIRED_VAR_ARGS)
         {
             sal_uInt16 nFix = nArgCount - VAR_ARGS;
             for ( sal_uInt16 nArg = 0; nArg < nFix; nArg++ )
@@ -172,6 +175,34 @@ void ScFuncDesc::Clear()
             aSig.append(sep);
             aSig.appendAscii(" ... ");
         }
+        else
+        {
+            sal_uInt16 nFix = nArgCount - PAIRED_VAR_ARGS;
+            for ( sal_uInt16 nArg = 0; nArg < nFix; nArg++ )
+            {
+                if (!pDefArgFlags[nArg].bSuppress)
+                {
+                    aSig.append(*(ppDefArgNames[nArg]));
+                    aSig.append(sep);
+                    aSig.appendAscii( " " );
+                }
+            }
+
+            aSig.append(*(ppDefArgNames[nFix]));
+            aSig.append(sal_Unicode('1'));
+            aSig.appendAscii( ", " );
+            aSig.append(*(ppDefArgNames[nFix+1]));
+            aSig.append(sal_Unicode('1'));
+            aSig.append(sep);
+            aSig.appendAscii( " " );
+            aSig.append(*(ppDefArgNames[nFix]));
+            aSig.append(sal_Unicode('2'));
+            aSig.appendAscii( ", " );
+            aSig.append(*(ppDefArgNames[nFix+1]));
+            aSig.append(sal_Unicode('2'));
+            aSig.append(sep);
+            aSig.appendAscii( " ... " );
+        }
     }
 
     return aSig.makeStringAndClear();
@@ -243,7 +274,9 @@ sal_uInt16 ScFuncDesc::GetSuppressedArgCount() const
         return nArgCount;
 
     sal_uInt16 nArgs = nArgCount;
-    if (nArgs >= VAR_ARGS)
+    if (nArgs >= PAIRED_VAR_ARGS)
+        nArgs -= PAIRED_VAR_ARGS - 2;
+    else if (nArgs >= VAR_ARGS)
         nArgs -= VAR_ARGS - 1;
     sal_uInt16 nCount = nArgs;
     for (sal_uInt16 i=0; i < nArgs; ++i)
@@ -251,7 +284,9 @@ sal_uInt16 ScFuncDesc::GetSuppressedArgCount() const
         if (pDefArgFlags[i].bSuppress)
             --nCount;
     }
-    if (nArgCount >= VAR_ARGS)
+    if (nArgCount >= PAIRED_VAR_ARGS)
+        nCount += PAIRED_VAR_ARGS - 2;
+    else if (nArgCount >= VAR_ARGS)
         nCount += VAR_ARGS - 1;
     return nCount;
 }
@@ -295,7 +330,9 @@ void ScFuncDesc::fillVisibleArgumentMapping(::std::vector<sal_uInt16>& _rArgumen
 
     _rArguments.reserve( nArgCount);
     sal_uInt16 nArgs = nArgCount;
-    if (nArgs >= VAR_ARGS)
+    if (nArgs >= PAIRED_VAR_ARGS)
+        nArgs -= PAIRED_VAR_ARGS - 2;
+    else if (nArgs >= VAR_ARGS)
         nArgs -= VAR_ARGS - 1;
     for (sal_uInt16 i=0; i < nArgs; ++i)
     {
@@ -809,7 +846,9 @@ ScFuncRes::ScFuncRes( ResId &aRes, ScFuncDesc* pDesc, bool & rbSuppressed )
     pDesc->sHelpId = ReadByteStringRes();
     pDesc->nArgCount = GetNum();
     sal_uInt16 nArgs = pDesc->nArgCount;
-    if (nArgs >= VAR_ARGS)
+    if (nArgs >= PAIRED_VAR_ARGS)
+        nArgs -= PAIRED_VAR_ARGS - 2;
+    else if (nArgs >= VAR_ARGS)
         nArgs -= VAR_ARGS - 1;
     if (nArgs)
     {
@@ -835,7 +874,12 @@ ScFuncRes::ScFuncRes( ResId &aRes, ScFuncDesc* pDesc, bool & rbSuppressed )
             sal_uInt16 nParam = GetNum();
             if (nParam < nArgs)
             {
-                if (pDesc->nArgCount >= VAR_ARGS && nParam == nArgs-1)
+                if (pDesc->nArgCount >= PAIRED_VAR_ARGS && nParam >= nArgs-2)
+                {
+                    OSL_TRACE( "ScFuncRes: PAIRED_VAR_ARGS parameters can't be suppressed, on OpCode %u: param %d >= arg %d-2",
+                            aRes.GetId(), (int)nParam, (int)nArgs);
+                }
+                else if (pDesc->nArgCount >= VAR_ARGS && nParam == nArgs-1)
                 {
                     OSL_TRACE( "ScFuncRes: VAR_ARGS parameters can't be suppressed, on OpCode %u: param %d == arg %d-1",
                             aRes.GetId(), (int)nParam, (int)nArgs);
diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx
index 1c408f8..762b818 100644
--- a/sc/source/core/inc/interpre.hxx
+++ b/sc/source/core/inc/interpre.hxx
@@ -74,6 +74,13 @@ enum ScIterFuncIf
     ifAVERAGEIF                         // Conditional average
 };
 
+enum ScIterFuncIfs
+{
+    ifSUMIFS,     // Multi-Conditional sum
+    ifAVERAGEIFS, // Multi-Conditional average
+    ifCOUNTIFS    // Multi-Conditional count
+};
+
 struct FormulaTokenRef_less
 {
     bool operator () ( const formula::FormulaConstTokenRef& r1, const formula::FormulaConstTokenRef& r2 ) const
@@ -483,6 +490,10 @@ double IterateParametersIf( ScIterFuncIf );
 void ScCountIf();
 void ScSumIf();
 void ScAverageIf();
+double IterateParametersIfs( ScIterFuncIfs );
+void ScSumIfs();
+void ScAverageIfs();
+void ScCountIfs();
 void ScCountEmptyCells();
 void ScLookup();
 void ScHLookup();
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index a27c367..8e59245 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -5728,6 +5728,392 @@ void ScInterpreter::ScCountIf()
     }
 }
 
+double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
+{
+    sal_uInt8 nParamCount = GetByte();
+    sal_uInt8 nQueryCount = nParamCount / 2;
+
+    bool bCheck;
+    if ( eFunc == ifCOUNTIFS )
+        bCheck = (nParamCount >= 2) && (nParamCount % 2 == 0);
+    else
+        bCheck = (nParamCount >= 3) && (nParamCount % 2 == 1);
+
+    if ( !bCheck )
+    {
+        SetError( errParameterExpected);
+    }
+    else
+    {
+        ScMatrixRef pResMat;
+        double fVal = 0.0;
+        double fSum = 0.0;
+        double fMem = 0.0;
+        double fRes = 0.0;
+        double fCount = 0.0;
+        short nParam = 1;
+        size_t nRefInList = 0;
+
+        while (nParamCount > 1 && !nGlobalError)
+        {
+            // take criteria
+            String rString;
+            fVal = 0.0;
+            bool bIsString = true;
+            switch ( GetStackType() )
+            {
+                case svDoubleRef :
+                case svSingleRef :
+                    {
+                        ScAddress aAdr;
+                        if ( !PopDoubleRefOrSingleRef( aAdr ) )
+                            return 0;
+
+                        ScBaseCell* pCell = GetCell( aAdr );
+                        switch ( GetCellType( pCell ) )
+                        {
+                            case CELLTYPE_VALUE :
+                                fVal = GetCellValue( aAdr, pCell );
+                                bIsString = false;
+                                break;
+                            case CELLTYPE_FORMULA :
+                                if( ((ScFormulaCell*)pCell)->IsValue() )
+                                {
+                                    fVal = GetCellValue( aAdr, pCell );
+                                    bIsString = false;
+                                }
+                                else
+                                    GetCellString(rString, pCell);
+                                break;
+                            case CELLTYPE_STRING :
+                            case CELLTYPE_EDIT :
+                                GetCellString(rString, pCell);
+                                break;
+                            default:
+                                fVal = 0.0;
+                                bIsString = false;
+                        }
+                    }
+                    break;
+                case svString:
+                    rString = GetString();
+                    break;
+                case svMatrix :
+                    {
+                        ScMatValType nType = GetDoubleOrStringFromMatrix( fVal, rString);
+                        bIsString = ScMatrix::IsNonValueType( nType);
+                    }
+                    break;
+                default:
+                    {
+                        fVal = GetDouble();
+                        bIsString = false;
+                    }
+            }
+
+            // take range
+            nParam = 1;
+            nRefInList = 0;
+            SCCOL nCol1;
+            SCROW nRow1;
+            SCTAB nTab1;
+            SCCOL nCol2;
+            SCROW nRow2;
+            SCTAB nTab2;
+            ScMatrixRef pQueryMatrix;
+            switch ( GetStackType() )
+            {
+                case svRefList :
+                    {
+                        ScRange aRange;
+                        PopDoubleRef( aRange, nParam, nRefInList);
+                        aRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
+                    }
+                    break;
+                case svDoubleRef :
+                    PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
+                    break;
+                case svSingleRef :
+                    PopSingleRef( nCol1, nRow1, nTab1 );
+                    nCol2 = nCol1;
+                    nRow2 = nRow1;
+                    nTab2 = nTab1;
+                    break;
+                case svMatrix:
+                    {
+                        pQueryMatrix = PopMatrix();
+                        if (!pQueryMatrix)
+                        {
+                            SetError( errIllegalParameter);
+                        }
+                        nCol1 = 0;
+                        nRow1 = 0;
+                        nTab1 = 0;
+                        SCSIZE nC, nR;
+                        pQueryMatrix->GetDimensions( nC, nR);
+                        nCol2 = static_cast<SCCOL>(nC - 1);
+                        nRow2 = static_cast<SCROW>(nR - 1);
+                        nTab2 = 0;
+                    }
+                    break;
+                default:
+                    SetError( errIllegalParameter);
+            }
+            if ( nTab1 != nTab2 )
+            {
+                SetError( errIllegalParameter);
+            }
+            // initialize temporary result matrix
+            if (!pResMat)
+            {
+                SCSIZE nResC, nResR;
+                nResC = nCol2 - nCol1 + 1;
+                nResR = nRow2 - nRow1 + 1;
+                pResMat = GetNewMat(nResC, nResR);
+                if (!pResMat)

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list