[PATCH] fdo#56124 add functions IFERROR and IFNA to calc as in ODFF1...

Winfried Donkers (via Code Review) gerrit at gerrit.libreoffice.org
Mon Dec 31 06:43:21 PST 2012


Hi,

I have submitted a patch for review:

    https://gerrit.libreoffice.org/1522

To pull it, you can do:

    git pull ssh://gerrit.libreoffice.org:29418/core refs/changes/22/1522/1

fdo#56124 add functions IFERROR and IFNA to calc as in ODFF1.2

Change-Id: I6403b51ac8c710ad3b8d2625e1482971f50e6b1d
---
M dictionaries
M formula/inc/formula/compiler.hrc
M formula/inc/formula/opcode.hxx
M formula/source/core/api/FormulaCompiler.cxx
M formula/source/core/api/token.cxx
M formula/source/core/resource/core_resource.src
M helpcontent2
M sc/inc/helpids.h
M sc/qa/unit/ucalc.cxx
M sc/source/core/inc/interpre.hxx
M sc/source/core/tool/interpr1.cxx
M sc/source/core/tool/interpr4.cxx
M sc/source/core/tool/parclass.cxx
M sc/source/core/tool/token.cxx
M sc/source/ui/src/scfuncs.src
M sc/util/hidother.src
16 files changed, 284 insertions(+), 40 deletions(-)



diff --git a/dictionaries b/dictionaries
index f0c914a..1595bf1 160000
--- a/dictionaries
+++ b/dictionaries
-Subproject commit f0c914a43e7e6540300da25c935a77aebb672094
+Subproject commit 1595bf11e295d96123fcb327ba9919307aa5b127
diff --git a/formula/inc/formula/compiler.hrc b/formula/inc/formula/compiler.hrc
index 582e3a5..7f976ae 100644
--- a/formula/inc/formula/compiler.hrc
+++ b/formula/inc/formula/compiler.hrc
@@ -29,26 +29,28 @@
 #define SC_OPCODE_NAME                4
 #define SC_OPCODE_EXTERNAL_REF        5
 #define SC_OPCODE_IF                  6     /* jump commands */
-#define SC_OPCODE_CHOSE               7
-#define SC_OPCODE_OPEN                8     /* parentheses and separators */
-#define SC_OPCODE_CLOSE               9
-#define SC_OPCODE_SEP                10
-#define SC_OPCODE_MISSING            11     /* special OpCodes */
-#define SC_OPCODE_BAD                12
-#define SC_OPCODE_STRINGXML          13
-#define SC_OPCODE_SPACES             14
-#define SC_OPCODE_MAT_REF            15
-#define SC_OPCODE_DB_AREA            16     /* additional access operators */
-#define SC_OPCODE_MACRO              17
-#define SC_OPCODE_COL_ROW_NAME       18
-#define SC_OPCODE_COL_ROW_NAME_AUTO  19
-#define SC_OPCODE_PERCENT_SIGN       20     /* operator _follows_ value */
-#define SC_OPCODE_ARRAY_OPEN         21
-#define SC_OPCODE_ARRAY_CLOSE        22
-#define SC_OPCODE_ARRAY_ROW_SEP      23
-#define SC_OPCODE_ARRAY_COL_SEP      24     /* some convs use sep != col_sep */
-#define SC_OPCODE_STOP_DIV           25
-#define SC_OPCODE_SKIP               26     /* used to skip raw tokens during string compilation */
+#define SC_OPCODE_IF_ERROR            7
+#define SC_OPCODE_IF_NA               8
+#define SC_OPCODE_CHOSE               9
+#define SC_OPCODE_OPEN               10     /* parentheses and separators */
+#define SC_OPCODE_CLOSE              11
+#define SC_OPCODE_SEP                12
+#define SC_OPCODE_MISSING            13     /* special OpCodes */
+#define SC_OPCODE_BAD                14
+#define SC_OPCODE_STRINGXML          15
+#define SC_OPCODE_SPACES             16
+#define SC_OPCODE_MAT_REF            17
+#define SC_OPCODE_DB_AREA            18     /* additional access operators */
+#define SC_OPCODE_MACRO              19
+#define SC_OPCODE_COL_ROW_NAME       20
+#define SC_OPCODE_COL_ROW_NAME_AUTO  21
+#define SC_OPCODE_PERCENT_SIGN       22     /* operator _follows_ value */
+#define SC_OPCODE_ARRAY_OPEN         23
+#define SC_OPCODE_ARRAY_CLOSE        24
+#define SC_OPCODE_ARRAY_ROW_SEP      25
+#define SC_OPCODE_ARRAY_COL_SEP      26     /* some convs use sep != col_sep */
+#define SC_OPCODE_STOP_DIV           27
+#define SC_OPCODE_SKIP               28     /* used to skip raw tokens during string compilation */
 
 /*** error constants #... ***/
 #define SC_OPCODE_START_ERRORS       30
diff --git a/formula/inc/formula/opcode.hxx b/formula/inc/formula/opcode.hxx
index cd1831b..e37395e 100644
--- a/formula/inc/formula/opcode.hxx
+++ b/formula/inc/formula/opcode.hxx
@@ -34,6 +34,8 @@
         ocExternalRef       = SC_OPCODE_EXTERNAL_REF,
     // Jump commands
         ocIf                = SC_OPCODE_IF,
+        ocIfError           = SC_OPCODE_IF_ERROR,
+        ocIfNA              = SC_OPCODE_IF_NA,
         ocChose             = SC_OPCODE_CHOSE,
     // Parentheses and separators
         ocOpen              = SC_OPCODE_OPEN,
diff --git a/formula/source/core/api/FormulaCompiler.cxx b/formula/source/core/api/FormulaCompiler.cxx
index 29b6694..f51f606 100644
--- a/formula/source/core/api/FormulaCompiler.cxx
+++ b/formula/source/core/api/FormulaCompiler.cxx
@@ -824,7 +824,7 @@
     {
         switch ((*iLook).second)
         {
-            // Not all may make sense in a formula, but these we know as 
+            // Not all may make sense in a formula, but these we know as
             // opcodes.
             case ocErrNull:
                 nError = errNoCode;
@@ -1125,7 +1125,8 @@
                 || eOp == ocOr
                 || eOp == ocBad
                 || ( eOp >= ocInternalBegin && eOp <= ocInternalEnd )
-                || (bCompileForFAP && ((eOp == ocIf) || (eOp == ocChose)))
+                || ( bCompileForFAP
+                     && ( eOp == ocIf || eOp == ocIfError || eOp == ocIfNA || eOp == ocChose ) )
             )
         {
             pFacToken = mpToken;
@@ -1174,14 +1175,16 @@
                 pFacToken->SetByte( nSepCount );
             PutCode( pFacToken );
         }
-        else if (eOp == ocIf || eOp == ocChose)
+        else if (eOp == ocIf || eOp == ocIfError || eOp == ocIfNA || eOp == ocChose)
         {
             // the PC counters are -1
             pFacToken = mpToken;
             if ( eOp == ocIf )
                 pFacToken->GetJump()[ 0 ] = 3;  // if, else, behind
-            else
+            else if ( eOp == ocChose )
                 pFacToken->GetJump()[ 0 ] = MAXJUMPCOUNT+1;
+            else
+                pFacToken->GetJump()[ 0 ] = 2;  // if, else
             eOp = NextToken();
             if (eOp == ocOpen)
             {
@@ -1195,9 +1198,10 @@
             // during AutoCorrect (since pArr->GetCodeError() is
             // ignored) an unlimited ocIf would crash because
             // ScRawToken::Clone() allocates the JumpBuffer according to
-            // nJump[0]*2+2, which is 3*2+2 on ocIf.
-            const short nJumpMax =
-                (pFacToken->GetOpCode() == ocIf ? 3 : MAXJUMPCOUNT);
+            // nJump[0]*2+2, which is 3*2+2 on ocIf and 2*2+2 ocIfError and ocIfNA.
+            OpCode eFacOpCode = pFacToken->GetOpCode();
+            const short nJumpMax = ( eFacOpCode == ocIf ? 3 :
+                                       ( eFacOpCode == ocChose ? MAXJUMPCOUNT : 2 ) );
             while ( (nJumpCount < (MAXJUMPCOUNT - 1)) && (eOp == ocSep)
                     && (!pArr->GetCodeError() || bIgnoreErrors) )
             {
@@ -1216,8 +1220,10 @@
                 // always limit to nJumpMax, no arbitrary overwrites
                 if ( ++nJumpCount <= nJumpMax )
                     pFacToken->GetJump()[ nJumpCount ] = pc-1;
-                if ((pFacToken->GetOpCode() == ocIf && (nJumpCount > 3)) ||
-                                 (nJumpCount >= MAXJUMPCOUNT))
+                eFacOpCode = pFacToken->GetOpCode();
+                if ( ( eFacOpCode == ocIf && nJumpCount > 3) ||
+                     ( ( eFacOpCode == ocIfError || eFacOpCode == ocIfNA ) && nJumpCount > 2 ) ||
+                     ( nJumpCount >= MAXJUMPCOUNT ) )
                     SetError(errIllegalParameter);
                 else
                     pFacToken->GetJump()[ 0 ] = nJumpCount;
diff --git a/formula/source/core/api/token.cxx b/formula/source/core/api/token.cxx
index d187073..f6110e7c 100644
--- a/formula/source/core/api/token.cxx
+++ b/formula/source/core/api/token.cxx
@@ -76,7 +76,7 @@
             eOp != ocColRowNameAuto && eOp != ocName && eOp != ocDBArea &&
            (GetByte() != 0                                                  // x parameters
         || (SC_OPCODE_START_NO_PAR <= eOp && eOp < SC_OPCODE_STOP_NO_PAR)   // no parameter
-        || (ocIf == eOp ||  ocChose ==  eOp     )                           // @ jump commands
+        || (ocIf == eOp || ocIfError == eOp || ocIfNA == eOp || ocChose == eOp ) // @ jump commands
         || (SC_OPCODE_START_1_PAR <= eOp && eOp < SC_OPCODE_STOP_1_PAR)     // one parameter
         || (SC_OPCODE_START_2_PAR <= eOp && eOp < SC_OPCODE_STOP_2_PAR)     // x parameters (cByte==0 in
                                                                             // FuncAutoPilot)
@@ -91,9 +91,10 @@
 sal_uInt8 FormulaToken::GetParamCount() const
 {
     if ( eOp < SC_OPCODE_STOP_DIV && eOp != ocExternal && eOp != ocMacro &&
-            eOp != ocIf && eOp != ocChose && eOp != ocPercentSign )
+         eOp != ocIf && eOp != ocIfError && eOp != ocIfNA && eOp != ocChose &&
+         eOp != ocPercentSign )
         return 0;       // parameters and specials
-                        // ocIf and ocChose not for FAP, have cByte then
+                        // ocIf, ocIfError, ocIfNA and ocChose not for FAP, have cByte then
 //2do: bool parameter whether FAP or not?
     else if ( GetByte() )
         return GetByte();   // all functions, also ocExternal and ocMacro
@@ -106,7 +107,7 @@
         return 0;           // no parameter
     else if (SC_OPCODE_START_1_PAR <= eOp && eOp < SC_OPCODE_STOP_1_PAR)
         return 1;           // one parameter
-    else if ( eOp == ocIf || eOp == ocChose )
+    else if ( eOp == ocIf || eOp == ocIfError || eOp == ocIfNA || eOp == ocChose )
         return 1;           // only the condition counts as parameter
     else
         return 0;           // all the rest, no Parameter, or
@@ -842,8 +843,8 @@
             }
             if ( eOp == ocPush || lcl_IsReference( eOp, t->GetType() )  )
                 pStack[sp++] = t;
-            else if ( eOp == ocIf || eOp == ocChose )
-            {   // Jumps ignorieren, vorheriges Result (Condition) poppen
+            else if ( eOp == ocIf || eOp == ocIfError || eOp == ocIfNA || eOp == ocChose )
+            {   // ignore Jumps, pop previous Result (Condition)
                 if ( sp )
                     --sp;
             }
@@ -1178,10 +1179,17 @@
             pRet = new FormulaToken( svSep,eOp );
             break;
         case ocIf:
+        case ocIfError:
+        case ocIfNA:
         case ocChose:
             {
                 short nJump[MAXJUMPCOUNT + 1];
-                nJump[ 0 ] = ocIf == eOp ? 3 : MAXJUMPCOUNT+1;
+                if ( eOp == ocIf )
+                    nJump[ 0 ] = 3;
+                else if ( eOp == ocChose )
+                    nJump[ 0 ] = MAXJUMPCOUNT + 1;
+                else
+                    nJump[ 0 ] = 2;
                 pRet = new FormulaJumpToken( eOp, (short*)nJump );
             }
             break;
diff --git a/formula/source/core/resource/core_resource.src b/formula/source/core/resource/core_resource.src
index 8b0ee14..1852d58 100644
--- a/formula/source/core/resource/core_resource.src
+++ b/formula/source/core/resource/core_resource.src
@@ -24,6 +24,8 @@
 Resource RID_STRLIST_FUNCTION_NAMES_ENGLISH_ODFF
 {
     String SC_OPCODE_IF { Text = "IF" ; };
+    String SC_OPCODE_IF_NA { Text = "IFERROR" ; };
+    String SC_OPCODE_IF_ERROR { Text = "IFNA" ; };
     String SC_OPCODE_CHOSE { Text = "CHOOSE" ; };
     String SC_OPCODE_OPEN { Text = "(" ; };
     String SC_OPCODE_CLOSE { Text = ")" ; };
@@ -362,6 +364,8 @@
 Resource RID_STRLIST_FUNCTION_NAMES_ENGLISH
 {
     String SC_OPCODE_IF { Text = "IF" ; };
+    String SC_OPCODE_IF_ERROR { Text = "IFERROR" ; };
+    String SC_OPCODE_IF_NA { Text = "IFNA" ; };
     String SC_OPCODE_CHOSE { Text = "CHOOSE" ; };
     String SC_OPCODE_OPEN { Text = "(" ; };
     String SC_OPCODE_CLOSE { Text = ")" ; };
@@ -700,6 +704,14 @@
     {
         Text [ en-US ] = "IF" ;
     };
+    String SC_OPCODE_IF_ERROR
+    {
+        Text [ en-US ] = "IFERROR" ;
+    };
+    String SC_OPCODE_IF_NA
+    {
+        Text [ en-US ] = "IFNA" ;
+    };
     String SC_OPCODE_CHOSE
     {
         Text [ en-US ] = "CHOOSE" ;
diff --git a/helpcontent2 b/helpcontent2
index d5d84f0..1909df0 160000
--- a/helpcontent2
+++ b/helpcontent2
-Subproject commit d5d84f0ec4584e32147eeab355d0ab73e7dd9172
+Subproject commit 1909df07cbd54bf753514cc6dc4137b7b69af63c
diff --git a/sc/inc/helpids.h b/sc/inc/helpids.h
index 2e2aa4c..e273ce4 100644
--- a/sc/inc/helpids.h
+++ b/sc/inc/helpids.h
@@ -433,6 +433,8 @@
 #define HID_FUNC_NICHT                                          "SC_HID_FUNC_NICHT"
 #define HID_FUNC_WAHR                                           "SC_HID_FUNC_WAHR"
 #define HID_FUNC_WENN                                           "SC_HID_FUNC_WENN"
+#define HID_FUNC_IFERROR                                        "SC_HID_FUNC_IFERROR"
+#define HID_FUNC_IFNA                                           "SC_HID_FUNC_IFNA"
 #define HID_FUNC_ODER                                           "SC_HID_FUNC_ODER"
 #define HID_FUNC_UND                                            "SC_HID_FUNC_UND"
 #define HID_FUNC_XOR                                            "SC_HID_FUNC_XOR"
diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index 55b8b9c..b0dccf7 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -3932,6 +3932,8 @@
         "CELL",
         "CURRENT",
         "FORMULA",
+        "IFERROR",
+        "IFNA",
         "INFO",
         "ISBLANK",
         "ISERR",
diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx
index 762b818..267e659 100644
--- a/sc/source/core/inc/interpre.hxx
+++ b/sc/source/core/inc/interpre.hxx
@@ -368,6 +368,7 @@
         const ScQueryParam & rParam ) const;
 
 void ScIfJump();
+void ScIfError( bool bNAonly );
 void ScChoseJump();
 
 // Be sure to only call this if pStack[sp-nStackLevel] really contains a
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 0b86108..a022015 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -240,6 +240,138 @@
 }
 
 
+void ScInterpreter::ScIfError( bool bNAonly )
+{
+    RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIfError" );
+    const short* pJump = pCur->GetJump();
+    if ( !pJump )
+    {
+        PushIllegalParameter();
+        return;
+    }
+    short nJumpCount = pJump[ 0 ];
+    if ( nJumpCount != 2 )
+    {
+        PushIllegalArgument();
+        return;
+    }
+
+    if ( nGlobalError == 0 || ( bNAonly && nGlobalError != NOTAVAILABLE ) )
+    {
+        MatrixDoubleRefToMatrix();
+        switch ( GetStackType() )
+        {
+            case svDoubleRef:
+            case svSingleRef:
+            {
+                ScAddress aAdr;
+                if ( !PopDoubleRefOrSingleRef( aAdr ) )
+                {
+                    PushIllegalArgument();
+                    return;
+                }
+                ScBaseCell* pCell = GetCell( aAdr );
+                sal_uInt16 nErr = GetCellErrCode( pCell );
+                if ( nErr == 0 || ( bNAonly && nErr != NOTAVAILABLE ) )
+                {
+                    // no error, return 1st argument
+                    if ( pCell && pCell->HasValueData() )
+                    {
+                        PushDouble( GetCellValue(aAdr, pCell) );
+                        aCode.Jump( pJump[ nJumpCount  ], pJump[ nJumpCount ] );
+                        return;
+                    }
+                    else
+                    {
+                        String aInputString;
+                        GetCellString( aInputString, pCell );
+                        PushString( aInputString );
+                        aCode.Jump( pJump[ nJumpCount  ], pJump[ nJumpCount ] );
+                        return;
+                    }
+                }
+            }
+            break;
+            case svMatrix:
+            {
+                nFuncFmtType = NUMBERFORMAT_NUMBER;
+                ScMatrixRef pMat = PopMatrix();
+                if ( pMat && ( !nGlobalError || ( bNAonly && nGlobalError != NOTAVAILABLE ) ) )
+                {
+                    FormulaTokenRef xNew;
+                    ScTokenMatrixMap::const_iterator aMapIter;
+                    SCSIZE nCols, nRows;
+                    pMat->SetErrorInterpreter( NULL );
+                    pMat->GetDimensions( nCols, nRows );
+                    if ( nCols > 0 && nRows > 0 )
+                    {
+                        if ( pTokenMatrixMap &&
+                             ( ( aMapIter = pTokenMatrixMap->find( pCur ) ) != pTokenMatrixMap->end() ) )
+                        {
+                            xNew = (*aMapIter).second;
+                        }
+                        else
+                        {
+                            ScJumpMatrix* pJumpMat = new ScJumpMatrix( nCols, nRows );
+                            for ( SCSIZE nC = 0; nC < nCols; ++nC )
+                            {
+                                for ( SCSIZE nR = 0; nR < nRows; ++nR )
+                                {
+                                    double fVal;
+                                    sal_uInt16 nErr;
+                                    bool bIsValue = pMat->IsValue(nC, nR);
+                                    if ( bIsValue )
+                                    {
+                                        fVal = pMat->GetDouble( nC, nR );
+                                        nErr = !( pMat->GetError( nC, nR ) == 0 ||
+                                                  ( bNAonly &&
+                                                    pMat->GetError( nC, nR )!= NOTAVAILABLE ) );
+                                    }
+                                    else
+                                    {
+                                        fVal = 0.0;
+                                        nErr = 1;
+                                    }
+
+                                    if ( nErr == 0 )
+                                    {   // no error, return 1st argument
+                                        pJumpMat->SetJump( nC, nR, fVal,
+                                                pJump[ nJumpCount ], pJump[ nJumpCount ] );
+                                    }
+                                    else
+                                    {
+                                        // error, return 2nd argument
+                                        pJumpMat->SetJump( nC, nR, fVal,
+                                                pJump[ 1 ], pJump[ nJumpCount ] );
+                                    }
+                                }
+                            }
+                            xNew = new ScJumpMatrixToken( pJumpMat );
+                            GetTokenMatrixMap().insert( ScTokenMatrixMap::value_type( pCur, xNew ));
+                        }
+                    }
+                    PushTempToken( xNew.get() );
+                    // set endpoint of path for main code line
+                    aCode.Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
+                    return;
+                }
+            }
+            break;
+            default:
+            {
+                //other stacktypes, no error, return 1st argument
+                aCode.Jump( pJump[ nJumpCount  ], pJump[ nJumpCount ] );
+                return;
+            }
+        }
+    }
+
+    // error, return 2nd argument
+    nGlobalError = 0;
+    aCode.Jump( pJump[ 1 ], pJump[ nJumpCount ] );
+}
+
+
 void ScInterpreter::ScChoseJump()
 {
     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScChoseJump" );
diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index 7155445..2f3b5ac 100644
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -2712,7 +2712,7 @@
     }
     else if ( ( aUnoName = ScGlobal::GetAddInCollection()->FindFunction(aFuncName, false) ).Len()  )
     {
-        //  bLocalFirst=false in FindFunction, cFunc should be the stored 
+        //  bLocalFirst=false in FindFunction, cFunc should be the stored
         //  internal name
 
         ScUnoAddInCall aCall( *ScGlobal::GetAddInCollection(), aUnoName, nParamCount );
@@ -3815,7 +3815,8 @@
             // RPN code push without error
             PushWithoutError( (FormulaToken&) *pCur );
         }
-        else if (pTokenMatrixMap && !(eOp == ocIf || eOp == ocChose) &&
+        else if (pTokenMatrixMap &&
+                 !(eOp == ocIf || eOp == ocIfError || eOp == ocIfNA || eOp == ocChose) &&
                 ((aTokenMatrixMapIter = pTokenMatrixMap->find( pCur)) !=
                  pTokenMatrixMap->end()) &&
                 (*aTokenMatrixMapIter).second->GetType() != svJumpMatrix)
@@ -3836,7 +3837,7 @@
             nFuncFmtType = NUMBERFORMAT_NUMBER;
             nFuncFmtIndex = 0;
 
-            if ( eOp == ocIf || eOp == ocChose )
+            if ( eOp == ocIf || eOp == ocChose || eOp == ocIfError || eOp == ocIfNA )
                 nStackBase = sp;        // don't mess around with the jumps
             else
             {
@@ -3863,6 +3864,8 @@
                 case ocDBArea           : ScDBArea();                   break;
                 case ocColRowNameAuto   : ScColRowNameAuto();           break;
                 case ocIf               : ScIfJump();                   break;
+                case ocIfError          : ScIfError( false );           break;
+                case ocIfNA             : ScIfError( true );            break;
                 case ocChose            : ScChoseJump();                break;
                 case ocAdd              : ScAdd();                      break;
                 case ocSub              : ScSub();                      break;
@@ -4258,7 +4261,9 @@
     case ocIsString : \
     case ocIsValue : \
     case ocN : \
-    case ocType :
+    case ocType : \
+    case ocIfError : \
+    case ocIfNA :
 
         switch ( eOp )
         {
diff --git a/sc/source/core/tool/parclass.cxx b/sc/source/core/tool/parclass.cxx
index ebdbb4a..68144dd 100644
--- a/sc/source/core/tool/parclass.cxx
+++ b/sc/source/core/tool/parclass.cxx
@@ -55,6 +55,8 @@
     // created inside those functions and ConvertMatrixParameters() is not
     // called for them.
     { ocIf,              {{ Array, Reference, Reference                          }, 0 }},
+    { ocIfError,         {{ Array, Reference, Reference                          }, false }},
+    { ocIfNA,            {{ Array, Reference                                     }, false }},
     { ocChose,           {{ Array, Reference                                     }, 1 }},
     // Other specials.
     { ocOpen,            {{ Bounds                                               }, 0 }},
@@ -495,6 +497,8 @@
                     case ocIf:
                         aToken.SetByte(3);
                     break;
+                    case ocIfError:
+                    case ocIfNA:
                     case ocChose:
                         aToken.SetByte(2);
                     break;
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index 539cad0..c498eda 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -126,6 +126,8 @@
     switch (eOp)
     {
         case ocIf:
+        case ocIfError:
+        case ocIfNA:
             eType = svJump;
             nJump[ 0 ] = 3; // If, Else, Behind
             break;
diff --git a/sc/source/ui/src/scfuncs.src b/sc/source/ui/src/scfuncs.src
index 1b68b2e..6238fba 100644
--- a/sc/source/ui/src/scfuncs.src
+++ b/sc/source/ui/src/scfuncs.src
@@ -2651,6 +2651,70 @@
             Text [ en-US ] = "The result of the function if the logical test returns FALSE." ;
         };
     };
+     // -=*# Resource for function IFERROR #*=-
+    Resource SC_OPCODE_IF_ERROR
+    {
+        String 1 // Description
+        {
+            Text [ en-US ] = "Returns value if not an error value, else alternative." ;
+        };
+        ExtraData =
+        {
+            0;
+            ID_FUNCTION_GRP_INFO;
+            U2S( HID_FUNC_IFERROR );
+            2;  0;  1;
+            0;
+        };
+        String 2 // Name of Parameter 1
+        {
+            Text [ en-US ] = "value" ;
+        };
+        String 3 // Description of Parameter 1
+        {
+            Text [ en-US ] = "The value to be calculated." ;
+        };
+        String 4 // Name of Parameter 2
+        {
+            Text [ en-US ] = "else value" ;
+        };
+        String 5 // Description of Parameter 2
+        {
+            Text [ en-US ] = "The alternative to be returned, should value be an error value." ;
+        };
+    };
+     // -=*# Resource for function IFNA #*=-
+    Resource SC_OPCODE_IF_NA
+    {
+        String 1 // Description
+        {
+            Text [ en-US ] = "Returns value if not an NA, else alternative." ;
+        };
+        ExtraData =
+        {
+            0;
+            ID_FUNCTION_GRP_INFO;
+            U2S( HID_FUNC_IFNA );
+            2;  0;  0;
+            0;
+        };
+        String 2 // Name of Parameter 1
+        {
+            Text [ en-US ] = "value" ;
+        };
+        String 3 // Description of Parameter 1
+        {
+            Text [ en-US ] = "The value to be calculated." ;
+        };
+        String 4 // Name of Parameter 2
+        {
+            Text [ en-US ] = "else value" ;
+        };
+        String 5 // Description of Parameter 2
+        {
+            Text [ en-US ] = "The alternative to be returned, should value be an NA." ;
+      };
+    };
      // -=*# Resource for function ODER #*=-
     Resource SC_OPCODE_OR
     {
diff --git a/sc/util/hidother.src b/sc/util/hidother.src
index d339229..718dce2 100644
--- a/sc/util/hidother.src
+++ b/sc/util/hidother.src
@@ -149,6 +149,8 @@
 hidspecial HID_FUNC_NICHT        { HelpID = HID_FUNC_NICHT; };
 hidspecial HID_FUNC_WAHR         { HelpID = HID_FUNC_WAHR; };
 hidspecial HID_FUNC_WENN         { HelpID = HID_FUNC_WENN; };
+hidspecial HID_FUNC_IFERROR      { HelpID = HID_FUNC_IFERROR; };
+hidspecial HID_FUNC_IFNA         { HelpID = HID_FUNC_IFNA; };
 hidspecial HID_FUNC_ODER         { HelpID = HID_FUNC_ODER; };
 hidspecial HID_FUNC_UND      { HelpID = HID_FUNC_UND; };
 hidspecial HID_FUNC_XOR      { HelpID = HID_FUNC_XOR; };

-- 
To view, visit https://gerrit.libreoffice.org/1522
To unsubscribe, visit https://gerrit.libreoffice.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I6403b51ac8c710ad3b8d2625e1482971f50e6b1d
Gerrit-PatchSet: 1
Gerrit-Project: core
Gerrit-Branch: master
Gerrit-Owner: Winfried Donkers <osc at dci-electronics.nl>



More information about the LibreOffice mailing list