summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEike Rathke <erack@redhat.com>2013-01-11 16:50:48 +0100
committerEike Rathke <erack@redhat.com>2013-01-11 17:01:44 +0100
commit3914d00c32c4226d3a73ffdd8985c887016887e0 (patch)
tree214d06dd8f9a28e8196ba7d26275d4bd16179ae2
parent5fd9feafa5d73121636af9397d42e046cc394719 (diff)
fdo#56124 changes to "add functions IFERROR and IFNA"
* reimplemented actual ScIfError() function for matrix cases and simpler pop/push of non-error values * various smaller adaptions, see also inline comments of https://gerrit.libreoffice.org/1522 Change-Id: I80a8235a2cbb548c0ef993862e76741af46e30d2
-rw-r--r--formula/inc/formula/errorcodes.hxx3
-rw-r--r--formula/source/core/api/FormulaCompiler.cxx69
-rw-r--r--sc/qa/unit/ucalc.cxx44
-rw-r--r--sc/source/core/tool/interpr1.cxx266
-rw-r--r--sc/source/core/tool/parclass.cxx4
-rw-r--r--sc/source/core/tool/token.cxx5
-rw-r--r--sc/source/ui/src/scfuncs.src14
7 files changed, 247 insertions, 158 deletions
diff --git a/formula/inc/formula/errorcodes.hxx b/formula/inc/formula/errorcodes.hxx
index a99dc7b9d4e0..1e145e04132b 100644
--- a/formula/inc/formula/errorcodes.hxx
+++ b/formula/inc/formula/errorcodes.hxx
@@ -72,6 +72,9 @@ const sal_uInt16 errNestedArray = 533;
// be used to distinguish that condition from all other (inherited) errors. Do
// not use for anything else! Never push or inherit the error otherwise!
const sal_uInt16 errNotNumericString = 534;
+// ScInterpreter internal: jump matrix already has a result at this position,
+// do not overwrite in case of empty code path.
+const sal_uInt16 errJumpMatHasResult = 535;
// Interpreter: NA() not available condition, not a real error
const sal_uInt16 NOTAVAILABLE = 0x7fff;
diff --git a/formula/source/core/api/FormulaCompiler.cxx b/formula/source/core/api/FormulaCompiler.cxx
index e91912368a5c..d4d69ddbd84b 100644
--- a/formula/source/core/api/FormulaCompiler.cxx
+++ b/formula/source/core/api/FormulaCompiler.cxx
@@ -1179,12 +1179,21 @@ void FormulaCompiler::Factor()
{
// the PC counters are -1
pFacToken = mpToken;
- if ( eOp == ocIf )
- pFacToken->GetJump()[ 0 ] = 3; // if, else, behind
- else if ( eOp == ocChose )
- pFacToken->GetJump()[ 0 ] = MAXJUMPCOUNT+1;
- else
- pFacToken->GetJump()[ 0 ] = 2; // if, else
+ switch (eOp)
+ {
+ case ocIf:
+ pFacToken->GetJump()[ 0 ] = 3; // if, else, behind
+ break;
+ case ocChose:
+ pFacToken->GetJump()[ 0 ] = MAXJUMPCOUNT+1;
+ break;
+ case ocIfError:
+ case ocIfNA:
+ pFacToken->GetJump()[ 0 ] = 2; // if, behind
+ break;
+ default:
+ SAL_WARN( "formula.core", "FormulaCompiler::Factor: forgot to add a jump count case?");
+ }
eOp = NextToken();
if (eOp == ocOpen)
{
@@ -1193,15 +1202,30 @@ void FormulaCompiler::Factor()
}
else
SetError(errPairExpected);
- short nJumpCount = 0;
PutCode( pFacToken );
- // during AutoCorrect (since pArr->GetCodeError() is
+ // 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 and 2*2+2 ocIfError and ocIfNA.
+ short nJumpMax;
OpCode eFacOpCode = pFacToken->GetOpCode();
- const short nJumpMax = ( eFacOpCode == ocIf ? 3 :
- ( eFacOpCode == ocChose ? MAXJUMPCOUNT : 2 ) );
+ switch (eFacOpCode)
+ {
+ case ocIf:
+ nJumpMax = 3;
+ break;
+ case ocChose:
+ nJumpMax = MAXJUMPCOUNT;
+ break;
+ case ocIfError:
+ case ocIfNA:
+ nJumpMax = 2;
+ break;
+ default:
+ nJumpMax = 0;
+ SAL_WARN( "formula.core", "FormulaCompiler::Factor: forgot to add a jump max case?");
+ }
+ short nJumpCount = 0;
while ( (nJumpCount < (MAXJUMPCOUNT - 1)) && (eOp == ocSep)
&& (!pArr->GetCodeError() || bIgnoreErrors) )
{
@@ -1221,12 +1245,27 @@ void FormulaCompiler::Factor()
if ( ++nJumpCount <= nJumpMax )
pFacToken->GetJump()[ nJumpCount ] = pc-1;
eFacOpCode = pFacToken->GetOpCode();
- if ( ( eFacOpCode == ocIf && nJumpCount > 3) ||
- ( ( eFacOpCode == ocIfError || eFacOpCode == ocIfNA ) && nJumpCount > 2 ) ||
- ( nJumpCount >= MAXJUMPCOUNT ) )
- SetError(errIllegalParameter);
- else
+ bool bLimitOk;
+ switch (eFacOpCode)
+ {
+ case ocIf:
+ bLimitOk = (nJumpCount <= 3);
+ break;
+ case ocChose:
+ bLimitOk = (nJumpCount < MAXJUMPCOUNT); /* TODO: check, really <, not <=? */
+ break;
+ case ocIfError:
+ case ocIfNA:
+ bLimitOk = (nJumpCount <= 2);
+ break;
+ default:
+ bLimitOk = false;
+ SAL_WARN( "formula.core", "FormulaCompiler::Factor: forgot to add a jump limit case?");
+ }
+ if (bLimitOk)
pFacToken->GetJump()[ 0 ] = nJumpCount;
+ else
+ SetError(errIllegalParameter);
}
}
else if ( eOp == ocMissing )
diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index 01fe181899b0..fb2cb1be8c38 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -673,12 +673,12 @@ void testFuncCOUNTIF(ScDocument* pDoc)
void testFuncIFERROR(ScDocument* pDoc)
{
- // IFERROR/IFNA (fdo 56124)
+ // IFERROR/IFNA (fdo#56124)
// Empty A1:A39 first.
clearRange(pDoc, ScRange(0, 0, 0, 0, 40, 0));
- // Raw data (rows 1 through 9)
+ // Raw data (rows 1 through 10)
const char* aData[] = {
"1",
"e",
@@ -686,6 +686,7 @@ void testFuncIFERROR(ScDocument* pDoc)
"=SQRT(-2)",
"=A4",
"=1/0",
+ "=NA()",
"bar",
"4",
"gee"
@@ -699,18 +700,21 @@ void testFuncIFERROR(ScDocument* pDoc)
// formulas and results
struct {
- const char* pFormula; double fResult;
+ const char* pFormula; const char* pResult;
} aChecks[] = {
- { "=IFERROR(A1;-7)", 1 },
- { "{=IFERROR(3*A1:A2;2002)}", 3 },
- { "{=IFERROR(3*A1:A2;1998)}", 1998 },
- { "=IFERROR(A3;9)", 4 },
- { "=IFERROR(A4;9)", 9 },
- { "=IFERROR(A5;-7", -7 },
- { "=IFERROR(A6;-7)", -7 },
- { "=IFERROR(A2;-7)", -7 },
- { "=IFNA(VLOOKUP(\"4\",A7:A9;1;0);-2)", 4 },
- { "=IFNA(VLOOKUP(\"fop\",A7:A9;1;0);-2)", -2 }
+ { "=IFERROR(A1;9)", "1" },
+ { "{=IFERROR(3*A1:A2;2002)}", "3" },
+ { "{=IFERROR(3*A1:A2;1998)}", "1998" },
+ { "=IFERROR(A2;-7)", "-7" },
+ { "=IFERROR(A3;9)", "4" },
+ { "=IFERROR(A4;-7)", "-7" },
+ { "=IFERROR(A5;-7)", "-7" },
+ { "=IFERROR(A6;-7)", "-7" },
+ { "=IFERROR(A7;-7)", "-7" },
+ { "=IFNA(A6;9)", "#DIV/0!" },
+ { "=IFNA(A7;-7)", "-7" },
+ { "=IFNA(VLOOKUP(\"4\",A8:A10;1;0);-2)", "4" },
+ { "=IFNA(VLOOKUP(\"fop\",A8:A10;1;0);-2)", "-2" }
};
nRows = SAL_N_ELEMENTS(aChecks);
@@ -723,15 +727,15 @@ void testFuncIFERROR(ScDocument* pDoc)
for (SCROW i = 0; i < nRows; ++i)
{
- double result;
+ rtl::OUString aResult;
SCROW nRow = 20 + i;
- pDoc->GetValue(0, nRow, 0, result);
- bool bGood = result == aChecks[i].fResult;
+ pDoc->GetString(0, nRow, 0, aResult);
+ bool bGood = (aResult == rtl::OUString::createFromAscii( aChecks[i].pResult));
if (!bGood)
{
cerr << "row " << (nRow+1) << ": formula" << aChecks[i].pFormula
- << " expected=" << aChecks[i].fResult << " actual=" << result << endl;
- CPPUNIT_ASSERT_MESSAGE("Unexpected result for COUNTIF", false);
+ << " expected=" << aChecks[i].pResult << " actual=" << aResult << endl;
+ CPPUNIT_ASSERT_MESSAGE("Unexpected result for IFERROR/IFNA", false);
}
}
}
@@ -4219,8 +4223,6 @@ void Test::testFunctionLists()
"CELL",
"CURRENT",
"FORMULA",
- "IFERROR",
- "IFNA",
"INFO",
"ISBLANK",
"ISERR",
@@ -4242,6 +4244,8 @@ void Test::testFunctionLists()
"AND",
"FALSE",
"IF",
+ "IFERROR",
+ "IFNA",
"NOT",
"OR",
"TRUE",
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 0c7817b88450..0ef12c742ded 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -54,6 +54,7 @@
#include <math.h>
#include <vector>
#include <memory>
+#include <limits>
#include "cellkeytranslator.hxx"
#include "lookupcache.hxx"
#include "rangenam.hxx"
@@ -243,135 +244,185 @@ void ScInterpreter::ScIfJump()
}
-void ScInterpreter::ScIfError( bool bNAonly )
+/** Store a matrix value in another matrix in the context of that other matrix
+ is the result matrix of a jump matrix. All arguments must be valid and are
+ not checked. */
+static void lcl_storeJumpMatResult( const ScMatrix* pMat, ScMatrix* pResMat, SCSIZE nC, SCSIZE nR )
{
- RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIfError" );
- const short* pJump = pCur->GetJump();
- if ( !pJump )
+ if ( pMat->IsValue( nC, nR ) )
{
- PushIllegalParameter();
- return;
+ double fVal = pMat->GetDouble( nC, nR );
+ pResMat->PutDouble( fVal, nC, nR );
}
+ else if ( pMat->IsEmpty( nC, nR ) )
+ {
+ pResMat->PutEmpty( nC, nR );
+ }
+ else
+ {
+ const String& rStr = pMat->GetString( nC, nR );
+ pResMat->PutString( rStr, nC, nR );
+ }
+}
+
+
+void ScInterpreter::ScIfError( bool bNAonly )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Donkers/erAck", "ScInterpreter::ScIfError" );
+ const short* pJump = pCur->GetJump();
short nJumpCount = pJump[ 0 ];
- if ( nJumpCount != 2 )
+ if (!sp)
{
- PushIllegalArgument();
+ PushError( errUnknownStackVariable);
+ aCode.Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
return;
}
- if ( nGlobalError == 0 || ( bNAonly && nGlobalError != NOTAVAILABLE ) )
+ FormulaTokenRef xToken( pStack[ sp - 1 ] );
+ bool bError = false;
+ sal_uInt16 nOldGlobalError = nGlobalError;
+ nGlobalError = 0;
+
+ MatrixDoubleRefToMatrix();
+ switch (GetStackType())
{
- MatrixDoubleRefToMatrix();
- switch ( GetStackType() )
- {
- case svDoubleRef:
- case svSingleRef:
+ default:
+ Pop();
+ break;
+ case svError:
+ PopError();
+ bError = true;
+ break;
+ case svDoubleRef:
+ case svSingleRef:
{
ScAddress aAdr;
- if ( !PopDoubleRefOrSingleRef( aAdr ) )
+ if (!PopDoubleRefOrSingleRef( aAdr))
+ bError = true;
+ else
{
- PushIllegalArgument();
- return;
+ ScBaseCell* pCell = GetCell( aAdr);
+ nGlobalError = GetCellErrCode( pCell);
+ if (nGlobalError)
+ bError = true;
}
- ScBaseCell* pCell = GetCell( aAdr );
- sal_uInt16 nErr = GetCellErrCode( pCell );
- if ( nErr == 0 || ( bNAonly && nErr != NOTAVAILABLE ) )
+ }
+ break;
+ case svExternalSingleRef:
+ case svExternalDoubleRef:
+ {
+ double fVal;
+ String aStr;
+ // Handles also existing jump matrix case and sets error on
+ // elements.
+ GetDoubleOrStringFromMatrix( fVal, aStr);
+ if (nGlobalError)
+ bError = true;
+ }
+ break;
+ case svMatrix:
+ {
+ const ScMatrixRef pMat = PopMatrix();
+ if (!pMat || (nGlobalError && (!bNAonly || nGlobalError == NOTAVAILABLE)))
{
- // no error, return 1st argument
- if ( pCell && pCell->HasValueData() )
- {
- PushDouble( GetCellValue(aAdr, pCell) );
- aCode.Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
- return;
- }
- else
+ bError = true;
+ break; // switch
+ }
+ // If the matrix has no queried error at all we can simply use
+ // it as result and don't need to bother with jump matrix.
+ SCSIZE nErrorCol = ::std::numeric_limits<SCSIZE>::max(),
+ nErrorRow = ::std::numeric_limits<SCSIZE>::max();
+ SCSIZE nCols, nRows;
+ pMat->GetDimensions( nCols, nRows );
+ if (nCols == 0 || nRows == 0)
+ {
+ bError = true;
+ break; // switch
+ }
+ for (SCSIZE nC=0; nC < nCols && !bError; ++nC)
+ {
+ for (SCSIZE nR=0; nR < nRows && !bError; ++nR)
{
- String aInputString;
- GetCellString( aInputString, pCell );
- PushString( aInputString );
- aCode.Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
- return;
+ sal_uInt16 nErr = pMat->GetError( nC, nR );
+ if (nErr && (!bNAonly || nErr == NOTAVAILABLE))
+ {
+ bError = true;
+ nErrorCol = nC;
+ nErrorRow = nR;
+ }
}
}
- }
- 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 (!bError)
+ break; // switch, we're done and have the result
+
+ FormulaTokenRef xNew;
+ ScTokenMatrixMap::const_iterator aMapIter;
+ if (pTokenMatrixMap && ((aMapIter = pTokenMatrixMap->find( pCur)) != pTokenMatrixMap->end()))
+ {
+ xNew = (*aMapIter).second;
+ }
+ else
+ {
+ const ScMatrix* pMatPtr = pMat.get();
+ ScJumpMatrix* pJumpMat = new ScJumpMatrix( nCols, nRows );
+ ScMatrix* pResMatPtr = pJumpMat->GetResultMatrix();
+ // Init all jumps to no error to save single calls. Error
+ // is the exceptional condition.
+ const double fFlagResult = CreateDoubleError( errJumpMatHasResult);
+ pJumpMat->SetAllJumps( fFlagResult, pJump[ nJumpCount ], pJump[ nJumpCount ] );
+ // Up to first error position simply store results, no need
+ // to evaluate error conditions again.
+ SCSIZE nC = 0, nR = 0;
+ for ( ; nC < nCols && (nC != nErrorCol || nR != nErrorRow); /*nop*/ )
{
- if ( pTokenMatrixMap &&
- ( ( aMapIter = pTokenMatrixMap->find( pCur ) ) != pTokenMatrixMap->end() ) )
+ for ( ; nR < nRows && (nC != nErrorCol || nR != nErrorRow); ++nR)
{
- xNew = (*aMapIter).second;
+ lcl_storeJumpMatResult( pMatPtr, pResMatPtr, nC, nR);
}
- else
+ if (nC != nErrorCol || nR != nErrorRow)
+ ++nC;
+ }
+ // Now the mixed cases.
+ for ( ; nC < nCols; ++nC)
+ {
+ for ( ; nR < nRows; ++nR)
{
- 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 ] );
- }
- }
+ sal_uInt16 nErr = pMat->GetError( nC, nR );
+ if (nErr && (!bNAonly || nErr == NOTAVAILABLE))
+ { // TRUE, THEN path
+ pJumpMat->SetJump( nC, nR, 1.0, pJump[ 1 ], pJump[ nJumpCount ] );
+ }
+ else
+ { // FALSE, EMPTY path, store result instead
+ lcl_storeJumpMatResult( pMatPtr, pResMatPtr, nC, nR);
}
- 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;
+ xNew = new ScJumpMatrixToken( pJumpMat );
+ GetTokenMatrixMap().insert( ScTokenMatrixMap::value_type( pCur, xNew ));
}
- }
- break;
- default:
- {
- //other stacktypes, no error, return 1st argument
- aCode.Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
+ nGlobalError = nOldGlobalError;
+ PushTempToken( xNew.get() );
+ // set endpoint of path for main code line
+ aCode.Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
return;
}
- }
+ break;
}
- // error, return 2nd argument
- nGlobalError = 0;
- aCode.Jump( pJump[ 1 ], pJump[ nJumpCount ] );
+ if (bError && (!bNAonly || nGlobalError == NOTAVAILABLE))
+ {
+ // error, calculate 2nd argument
+ nGlobalError = 0;
+ aCode.Jump( pJump[ 1 ], pJump[ nJumpCount ] );
+ }
+ else
+ {
+ // no error, push 1st argument and continue
+ nGlobalError = nOldGlobalError;
+ PushTempToken( xToken.get());
+ aCode.Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
+ }
}
@@ -692,18 +743,7 @@ bool ScInterpreter::JumpMatrix( short nStackLevel )
}
else
{
- if ( pMat->IsValue( nC, nR ) )
- {
- fVal = pMat->GetDouble( nC, nR );
- pResMat->PutDouble( fVal, nC, nR );
- }
- else if ( pMat->IsEmpty( nC, nR ) )
- pResMat->PutEmpty( nC, nR );
- else
- {
- const String& rStr = pMat->GetString( nC, nR );
- pResMat->PutString( rStr, nC, nR );
- }
+ lcl_storeJumpMatResult( pMat.get(), pResMat.get(), nC, nR);
}
lcl_AdjustJumpMatrix( pJumpMatrix, pResMat, nCols, nRows );
}
@@ -734,7 +774,7 @@ bool ScInterpreter::JumpMatrix( short nStackLevel )
pJumpMatrix->GetJump( nC, nR, fBool, nStart, nNext, nStop );
while ( bCont && nStart == nNext )
{ // push all results that have no jump path
- if ( pResMat )
+ if ( pResMat && (GetDoubleErrorValue( fBool) != errJumpMatHasResult) )
{
// a false without path results in an empty path value
if ( fBool == 0.0 )
diff --git a/sc/source/core/tool/parclass.cxx b/sc/source/core/tool/parclass.cxx
index 68144ddcde24..6f3cae07861e 100644
--- a/sc/source/core/tool/parclass.cxx
+++ b/sc/source/core/tool/parclass.cxx
@@ -55,8 +55,8 @@ const ScParameterClassification::RawData ScParameterClassification::pRawData[] =
// 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 }},
+ { ocIfError, {{ Array, Reference }, 0 }},
+ { ocIfNA, {{ Array, Reference }, 0 }},
{ ocChose, {{ Array, Reference }, 1 }},
// Other specials.
{ ocOpen, {{ Bounds }, 0 }},
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index c498eda2576d..4ea3d4e056b6 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -126,10 +126,13 @@ void ScRawToken::SetOpCode( OpCode e )
switch (eOp)
{
case ocIf:
+ eType = svJump;
+ nJump[ 0 ] = 3; // If, Else, Behind
+ break;
case ocIfError:
case ocIfNA:
eType = svJump;
- nJump[ 0 ] = 3; // If, Else, Behind
+ nJump[ 0 ] = 2; // If, Behind
break;
case ocChose:
eType = svJump;
diff --git a/sc/source/ui/src/scfuncs.src b/sc/source/ui/src/scfuncs.src
index 6238fbaf0e90..ce354e692950 100644
--- a/sc/source/ui/src/scfuncs.src
+++ b/sc/source/ui/src/scfuncs.src
@@ -2661,9 +2661,9 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS1
ExtraData =
{
0;
- ID_FUNCTION_GRP_INFO;
+ ID_FUNCTION_GRP_LOGIC;
U2S( HID_FUNC_IFERROR );
- 2; 0; 1;
+ 2; 0; 0;
0;
};
String 2 // Name of Parameter 1
@@ -2676,7 +2676,7 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS1
};
String 4 // Name of Parameter 2
{
- Text [ en-US ] = "else value" ;
+ Text [ en-US ] = "alternative value" ;
};
String 5 // Description of Parameter 2
{
@@ -2688,12 +2688,12 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS1
{
String 1 // Description
{
- Text [ en-US ] = "Returns value if not an NA, else alternative." ;
+ Text [ en-US ] = "Returns value if not a #N/A error, else alternative." ;
};
ExtraData =
{
0;
- ID_FUNCTION_GRP_INFO;
+ ID_FUNCTION_GRP_LOGIC;
U2S( HID_FUNC_IFNA );
2; 0; 0;
0;
@@ -2708,11 +2708,11 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS1
};
String 4 // Name of Parameter 2
{
- Text [ en-US ] = "else value" ;
+ Text [ en-US ] = "alternative value" ;
};
String 5 // Description of Parameter 2
{
- Text [ en-US ] = "The alternative to be returned, should value be an NA." ;
+ Text [ en-US ] = "The alternative to be returned, should value be a #N/A error." ;
};
};
// -=*# Resource for function ODER #*=-