Date: prev next · Thread: first prev next last
2012 Archives by date, by thread · List index


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@dci-electronics.nl>


Context


Privacy Policy | Impressum (Legal Info) | Copyright information: Unless otherwise specified, all text and images on this website are licensed under the Creative Commons Attribution-Share Alike 3.0 License. This does not include the source code of LibreOffice, which is licensed under the Mozilla Public License (MPLv2). "LibreOffice" and "The Document Foundation" are registered trademarks of their corresponding registered owners or are in actual use as trademarks in one or more countries. Their respective logos and icons are also subject to international copyright laws. Use thereof is explained in our trademark policy.