Kaydet (Commit) baca3632 authored tarafından Eike Rathke's avatar Eike Rathke

fdo#37391 write and read [#REF!] in ODFF for reference errors

* write [#REF!] to ODFF when any part of the reference is invalid
* read [#REF!] as reference error
* display #REF! in UI
+ parse #REF! in UI
+ implemented error constants defined in ODFF as error tokens
+ parse error constants from ODFF and in UI
* fixed SUM, AVERAGE, SUMSQ, PRODUCT to propagate error
üst 7e8e85ad
......@@ -211,6 +211,9 @@ public:
const ::com::sun::star::sheet::FormulaOpCodeMapEntry > & rMapping,
bool bEnglish );
/** Get current OpCodeMap in effect. */
inline OpCodeMapPtr GetCurrentOpCodeMap() const { return mxSymbols; }
/** Get OpCode for English symbol.
Used in XFunctionAccess to create token array.
@param rName
......@@ -272,6 +275,9 @@ protected:
virtual void LocalizeString( String& rName ); // modify rName - input: exact name
virtual sal_Bool IsImportingXML() const;
sal_uInt16 GetErrorConstant( const String& rName );
void AppendErrorConstant( rtl::OUStringBuffer& rBuffer, sal_uInt16 nError );
sal_Bool GetToken();
OpCode NextToken();
void PutCode( FormulaTokenRef& );
......
......@@ -824,6 +824,78 @@ void FormulaCompiler::OpCodeMap::copyFrom( const OpCodeMap& r )
// TODO: maybe copy the external maps too?
}
// -----------------------------------------------------------------------------
sal_uInt16 FormulaCompiler::GetErrorConstant( const String& rName )
{
sal_uInt16 nError = 0;
OpCodeHashMap::const_iterator iLook( mxSymbols->getHashMap()->find( rName));
if (iLook != mxSymbols->getHashMap()->end())
{
switch ((*iLook).second)
{
// Not all may make sense in a formula, but these we know as
// opcodes.
case ocErrNull:
nError = errNoCode;
break;
case ocErrDivZero:
nError = errDivisionByZero;
break;
case ocErrValue:
nError = errNoValue;
break;
case ocErrRef:
nError = errNoRef;
break;
case ocErrName:
nError = errNoName;
break;
case ocErrNum:
nError = errIllegalFPOperation;
break;
case ocErrNA:
nError = NOTAVAILABLE;
break;
default:
; // nothing
}
}
return nError;
}
void FormulaCompiler::AppendErrorConstant( rtl::OUStringBuffer& rBuffer, sal_uInt16 nError )
{
OpCode eOp;
switch (nError)
{
default:
case errNoCode:
eOp = ocErrNull;
break;
case errDivisionByZero:
eOp = ocErrDivZero;
break;
case errNoValue:
eOp = ocErrValue;
break;
case errNoRef:
eOp = ocErrRef;
break;
case errNoName:
eOp = ocErrName;
break;
case errIllegalFPOperation:
eOp = ocErrNum;
break;
case NOTAVAILABLE:
eOp = ocErrNA;
break;
}
rBuffer.append( mxSymbols->getSymbol( eOp));
}
// -----------------------------------------------------------------------------
sal_Int32 FormulaCompiler::OpCodeMap::getOpCodeUnknown()
{
......@@ -1646,6 +1718,9 @@ FormulaToken* FormulaCompiler::CreateStringFromToken( rtl::OUStringBuffer& rBuff
rBuffer.append(aAddIn);
}
break;
case svError:
AppendErrorConstant( rBuffer, t->GetError());
break;
case svByte:
case svJump:
case svFAP:
......
......@@ -87,6 +87,7 @@
#define SC_COMPILER_C_ODF_NAME_MARKER 0x00200000 // ODF '$$' marker that starts a defined (range) name
#define SC_COMPILER_C_CHAR_NAME 0x00400000 // start character of a defined name
#define SC_COMPILER_C_NAME 0x00800000 // continuation character of a defined name
#define SC_COMPILER_C_CHAR_ERRCONST 0x01000000 // start character of an error constant ('#')
#define SC_COMPILER_FILE_TAB_SEP '#' // 'Doc'#Tab
......@@ -159,6 +160,7 @@ public:
sal_uInt16 nIndex;
} name;
ScMatrix* pMat;
sal_uInt16 nError;
sal_Unicode cStr[ MAXSTRLEN+1 ]; // string (up to 255 characters + 0)
short nJump[MAXJUMPCOUNT+1]; // If/Chose token
};
......@@ -184,6 +186,7 @@ public:
void SetSingleReference( const ScSingleRefData& rRef );
void SetDoubleReference( const ScComplexRefData& rRef );
void SetDouble( double fVal );
void SetErrorConstant( sal_uInt16 nErr );
// These methods are ok to use, reference count not cleared.
void SetName(bool bGlobal, sal_uInt16 nIndex);
......@@ -349,6 +352,7 @@ private:
bool IsDBRange( const String& );
sal_Bool IsColRowName( const String& );
bool IsBoolean( const String& );
bool IsErrorConstant( const String& );
void AutoCorrectParsedSymbol();
void SetRelNameReference();
......
......@@ -3527,7 +3527,7 @@ double ScInterpreter::IterateParameters( ScIterFunc eFunc, sal_Bool bTextAsZero
break;
case svError:
{
Pop();
PopError();
if ( eFunc == ifCOUNT )
{
nGlobalError = 0;
......
......@@ -224,6 +224,14 @@ void ScRawToken::SetDouble(double rVal)
nRefCnt = 0;
}
void ScRawToken::SetErrorConstant( sal_uInt16 nErr )
{
eOp = ocPush;
eType = svError;
nError = nErr;
nRefCnt = 0;
}
void ScRawToken::SetName(bool bGlobal, sal_uInt16 nIndex)
{
eOp = ocName;
......@@ -320,6 +328,7 @@ ScRawToken* ScRawToken::Clone() const
case svSep: break;
case svByte: n += sizeof(ScRawToken::sbyte); break;
case svDouble: n += sizeof(double); break;
case svError: n += sizeof(nError); break;
case svString: n = sal::static_int_cast<sal_uInt16>( n + GetStrLenBytes( cStr ) + GetStrLenBytes( 1 ) ); break;
case svSingleRef:
case svDoubleRef: n += sizeof(aRef); break;
......@@ -406,6 +415,8 @@ FormulaToken* ScRawToken::CreateToken() const
return new FormulaMissingToken;
case svSep :
return new FormulaToken( svSep,eOp );
case svError :
return new FormulaErrorToken( nError );
case svUnknown :
return new FormulaUnknownToken( eOp );
default:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment