diff --git a/formula/inc/formula/compiler.hrc b/formula/inc/formula/compiler.hrc index 6b595ce..5e58cfd 100644 --- a/formula/inc/formula/compiler.hrc +++ b/formula/inc/formula/compiler.hrc @@ -392,8 +392,10 @@ #define SC_OPCODE_BITLSHIFT 399 #define SC_OPCODE_GET_DATEDIF 400 #define SC_OPCODE_XOR 401 -#define SC_OPCODE_STOP_2_PAR 402 -#define SC_OPCODE_LAST_OPCODE_ID 402 /* last OpCode */ +#define SC_OPCODE_IF_ERROR 402 +#define SC_OPCODE_IF_NA 403 +#define SC_OPCODE_STOP_2_PAR 404 +#define SC_OPCODE_LAST_OPCODE_ID 404 /* last OpCode */ /*** Internal ***/ #define SC_OPCODE_INTERNAL_BEGIN 9999 diff --git a/formula/inc/formula/opcode.hxx b/formula/inc/formula/opcode.hxx index 14f862f..c2db1e8 100644 --- a/formula/inc/formula/opcode.hxx +++ b/formula/inc/formula/opcode.hxx @@ -252,6 +252,8 @@ enum OpCodeEnum ocEffektiv = SC_OPCODE_EFFEKTIV, ocNominal = SC_OPCODE_NOMINAL, ocSubTotal = SC_OPCODE_SUB_TOTAL, + ocIfError = SC_OPCODE_IF_ERROR, + ocIfNA = SC_OPCODE_IF_NA, // Database functions ocDBSum = SC_OPCODE_DB_SUM, ocDBCount = SC_OPCODE_DB_COUNT, diff --git a/formula/source/core/resource/core_resource.src b/formula/source/core/resource/core_resource.src index 5d4615b..6f5ac54 100644 --- a/formula/source/core/resource/core_resource.src +++ b/formula/source/core/resource/core_resource.src @@ -111,6 +111,8 @@ Resource RID_STRLIST_FUNCTION_NAMES_ENGLISH_ODFF String SC_OPCODE_IS_NV { Text = "ISNA" ; }; String SC_OPCODE_IS_ERR { Text = "ISERR" ; }; String SC_OPCODE_IS_ERROR { Text = "ISERROR" ; }; + String SC_OPCODE_IF_NA { Text = "IFERROR" ; }; + String SC_OPCODE_IF_ERROR { Text = "IFNA" ; }; String SC_OPCODE_IS_EVEN { Text = "ISEVEN" ; }; String SC_OPCODE_IS_ODD { Text = "ISODD" ; }; String SC_OPCODE_N { Text = "N" ; }; @@ -444,6 +446,8 @@ Resource RID_STRLIST_FUNCTION_NAMES_ENGLISH String SC_OPCODE_IS_NV { Text = "ISNA" ; }; String SC_OPCODE_IS_ERR { Text = "ISERR" ; }; String SC_OPCODE_IS_ERROR { Text = "ISERROR" ; }; + String SC_OPCODE_IF_ERROR { Text = "IFERROR" ; }; + String SC_OPCODE_IF_NA { Text = "IFNA" ; }; String SC_OPCODE_IS_EVEN { Text = "ISEVEN" ; }; String SC_OPCODE_IS_ODD { Text = "ISODD" ; }; String SC_OPCODE_N { Text = "N" ; }; @@ -968,6 +972,14 @@ Resource RID_STRLIST_FUNCTION_NAMES { Text [ en-US ] = "ISERROR" ; }; + String SC_OPCODE_IF_ERROR + { + Text [ en-US ] = "IFERROR" ; + }; + String SC_OPCODE_IF_NA + { + Text [ en-US ] = "IFNA" ; + }; String SC_OPCODE_IS_EVEN { Text [ en-US ] = "ISEVEN" ; diff --git a/sc/inc/helpids.h b/sc/inc/helpids.h index 8695891..e3b46c8 100644 --- a/sc/inc/helpids.h +++ b/sc/inc/helpids.h @@ -425,6 +425,8 @@ #define HID_FUNC_ISTBEZUG "SC_HID_FUNC_ISTBEZUG" #define HID_FUNC_ISTFEHL "SC_HID_FUNC_ISTFEHL" #define HID_FUNC_ISTFEHLER "SC_HID_FUNC_ISTFEHLER" +#define HID_FUNC_IFERROR "SC_HID_FUNC_IFERROR" +#define HID_FUNC_IFNA "SC_HID_FUNC_IFNA" #define HID_FUNC_ISTLEER "SC_HID_FUNC_ISTLEER" #define HID_FUNC_ISTLOG "SC_HID_FUNC_ISTLOG" #define HID_FUNC_ISTNV "SC_HID_FUNC_ISTNV" diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx index 0606562..ac0cb78 100644 --- a/sc/qa/unit/ucalc.cxx +++ b/sc/qa/unit/ucalc.cxx @@ -3901,6 +3901,8 @@ void Test::testFunctionLists() "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 b0cfa6a..337488d 100644 --- a/sc/source/core/inc/interpre.hxx +++ b/sc/source/core/inc/interpre.hxx @@ -443,6 +443,9 @@ void ScArabic(); void ScIsNV(); void ScIsErr(); void ScIsError(); +void ScIfError(); +void ScIfNA(); +void ScEvaluate(); short IsEven(); void ScIsEven(); void ScIsOdd(); diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx index 3ff768e..823cd40 100644 --- a/sc/source/core/tool/interpr1.cxx +++ b/sc/source/core/tool/interpr1.cxx @@ -2852,6 +2852,133 @@ void ScInterpreter::ScIsError() } +void ScInterpreter::ScIfError() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIsError" ); + + //must have 2 parameters + //toDo: if one argument, make 2nd argument empty cell + if ( !MustHaveParamCount( GetByte(), 2 ) ) + return; + + FormulaToken* p; + + //first read the second argument and store + if ( sp ) + { + sp--; + p = pStack[ sp ]; + } + else + p = 0; + + //process 1st argument + ScEvaluate(); + + //if no error, return + if ( sp ) + { + if ( GetStackType() == svError ) + { + sp--; + nGlobalError = pStack[sp]->GetError(); + } + } + if ( !nGlobalError ) + return; + + nGlobalError = 0; + //return 2nd argument + if ( p ) + { + Push( *p ); + ScEvaluate(); + } + else + PushIllegalParameter(); +} + + +void ScInterpreter::ScEvaluate() +{ + String aInputString; + double fVal = 0.0; + + switch ( GetRawStackType() ) + { + case svMissing: + case svEmptyCell: + Pop(); + PushString( String( "" ) ); + return; + case svSingleRef: + case svDoubleRef: + { + ScAddress aAdr; + if ( !PopDoubleRefOrSingleRef( aAdr ) ) + { + PushString( String ( "" ) ); + return; + } + ScBaseCell* pCell = GetCell( aAdr ); + if ( pCell && pCell->HasStringData() ) + { + GetCellString( aInputString, pCell ); + PushString( aInputString ); + return; + } + else if ( pCell && pCell->HasValueData() ) + { + PushDouble( GetCellValue(aAdr, pCell) ); + return; + } + else + { + PushString( String( "" ) ); + return; + } + } + break; + case svMatrix: + { + ScMatValType nType = GetDoubleOrStringFromMatrix( fVal, aInputString ); + switch ( nType ) + { + case SC_MATVAL_EMPTY: + fVal = 0.0; + // fallthru + case SC_MATVAL_VALUE: + case SC_MATVAL_BOOLEAN: + PushDouble( fVal ); + break; + case SC_MATVAL_STRING: + { + sal_uInt32 nFIndex = 0; // 0 for default locale + if ( pFormatter->IsNumberFormat( aInputString, nFIndex, fVal ) ) + PushDouble( fVal ); + else + PushError( errNoValue ); + } + break; + default: + PushError( errNoValue ); + } + } + break; + default: + return; // leave on stack + } +} + + +void ScInterpreter::ScIfNA() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIfNA" ); +SAL_WARN( "ScIfNA()", "fdo56124; under construction." ); + PushError( errUnknownOpCode ); + return; +} + short ScInterpreter::IsEven() { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::IsEven" ); diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx index fc519c7..e7a7fbd 100644 --- a/sc/source/core/tool/interpr4.cxx +++ b/sc/source/core/tool/interpr4.cxx @@ -2721,7 +2721,7 @@ void ScInterpreter::ScExternal() } 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 ); @@ -3961,6 +3961,8 @@ StackVar ScInterpreter::Interpret() case ocIsNA : ScIsNV(); break; case ocIsErr : ScIsErr(); break; case ocIsError : ScIsError(); break; + case ocIfError : ScIfError(); break; + case ocIfNA : ScIfNA(); break; case ocIsEven : ScIsEven(); break; case ocIsOdd : ScIsOdd(); break; case ocN : ScN(); break; @@ -4256,6 +4258,8 @@ StackVar ScInterpreter::Interpret() case ocIsEmpty : \ case ocIsErr : \ case ocIsError : \ + case ocIfError : \ + case ocIfNA : \ case ocIsFormula : \ case ocIsLogical : \ case ocIsNA : \ diff --git a/sc/source/ui/src/scfuncs.src b/sc/source/ui/src/scfuncs.src index d05a075..59e4ee9 100644 --- a/sc/source/ui/src/scfuncs.src +++ b/sc/source/ui/src/scfuncs.src @@ -2258,6 +2258,70 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS1 Text [ en-US ] = "The value to be tested." ; }; }; + // -=*# 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; 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 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 ISTLEER #*=- Resource SC_OPCODE_IS_EMPTY { diff --git a/sc/util/hidother.src b/sc/util/hidother.src index 9b3c3fb..ba8d666 100644 --- a/sc/util/hidother.src +++ b/sc/util/hidother.src @@ -141,6 +141,8 @@ hidspecial HID_FUNC_ZGZ { HelpID = HID_FUNC_ZGZ; }; hidspecial HID_FUNC_ISTBEZUG { HelpID = HID_FUNC_ISTBEZUG; }; hidspecial HID_FUNC_ISTFEHL { HelpID = HID_FUNC_ISTFEHL; }; hidspecial HID_FUNC_ISTFEHLER { HelpID = HID_FUNC_ISTFEHLER; }; +hidspecial HID_FUNC_IFERROR { HelpID = HID_FUNC_IFERROR; }; +hidspecial HID_FUNC_IFNA { HelpID = HID_FUNC_IFNA; }; hidspecial HID_FUNC_ISTLEER { HelpID = HID_FUNC_ISTLEER; }; hidspecial HID_FUNC_ISTLOG { HelpID = HID_FUNC_ISTLOG; }; hidspecial HID_FUNC_ISTNV { HelpID = HID_FUNC_ISTNV; };