diff options
Diffstat (limited to 'sc/source')
-rw-r--r-- | sc/source/core/inc/interpre.hxx | 1 | ||||
-rw-r--r-- | sc/source/core/tool/interpr1.cxx | 98 | ||||
-rw-r--r-- | sc/source/core/tool/interpr4.cxx | 1 | ||||
-rw-r--r-- | sc/source/filter/oox/formulabase.cxx | 2 | ||||
-rw-r--r-- | sc/source/ui/src/scfuncs.src | 16 |
5 files changed, 113 insertions, 5 deletions
diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx index 267e65947d48..cd44780dbc62 100644 --- a/sc/source/core/inc/interpre.hxx +++ b/sc/source/core/inc/interpre.hxx @@ -460,6 +460,7 @@ void ScLower(); void ScLen(); void ScT(); void ScValue(); +void ScNumberValue(); void ScClean(); void ScChar(); void ScJis(); diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx index 74294675fef2..53cb552ce2d8 100644 --- a/sc/source/core/tool/interpr1.cxx +++ b/sc/source/core/tool/interpr1.cxx @@ -3378,6 +3378,104 @@ void ScInterpreter::ScValue() } +// fdo#57180 +void ScInterpreter::ScNumberValue() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScNumberValue" ); + + sal_uInt8 nParamCount = GetByte(); + if ( !MustHaveParamCount( nParamCount, 1, 3 ) ) + return; + + OUString aInputString; + OUString aDecimalSeparator, aGroupSeparator; + sal_Unicode cDecimalSeparator = 0; + + if ( nParamCount == 3 ) + aGroupSeparator = GetString(); + + if ( nParamCount >= 2 ) + { + aDecimalSeparator = GetString(); + if ( aDecimalSeparator.getLength() == 1 ) + cDecimalSeparator = aDecimalSeparator[ 0 ]; + else + { + PushIllegalArgument(); //if given, separator length must be 1 + return; + } + } + + if ( cDecimalSeparator && aGroupSeparator.indexOf( cDecimalSeparator ) != -1 ) + { + PushIllegalArgument(); //decimal separator cannot appear in group separator + return; + } + + switch (GetStackType()) + { + case svDouble: + return; // leave on stack + default: + aInputString = GetString(); + } + if ( nGlobalError ) + { + PushError( nGlobalError ); + return; + } + if ( aInputString.isEmpty() ) + { + if ( GetGlobalConfig().mbEmptyStringAsZero ) + PushDouble( 0.0 ); + else + PushNoValue(); + return; + } + + sal_Int32 nDecSep = aInputString.indexOf( cDecimalSeparator ); + if ( nDecSep != 0 ) + { + OUString aTemporary( nDecSep >= 0 ? aInputString.copy( 0, nDecSep ) : aInputString ); + sal_Int32 nIndex = 0; + do + { + sal_uInt32 nChar = aGroupSeparator.iterateCodePoints( &nIndex ); + aTemporary = aTemporary.replaceAll( OUString( &nChar, 1 ), "" ); + } while ( nIndex < aGroupSeparator.getLength() ); + if ( nDecSep >= 0 ) + aInputString = aTemporary + aInputString.copy( nDecSep ); + else + aInputString = aTemporary; + } + + for ( sal_Int32 i = aInputString.getLength(); --i >= 0; ) + { + sal_Unicode c = aInputString[ i ]; + if ( c == 0x0020 || c == 0x0009 || c == 0x000A || c == 0x000D ) + aInputString = aInputString.replaceAt( i, 1, "" ); // remove spaces etc. + } + sal_Int32 nPercentCount = 0; + for ( sal_Int32 i = aInputString.getLength() - 1; i >= 0 && aInputString[ i ] == 0x0025; i-- ) + { + aInputString = aInputString.replaceAt( i, 1, "" ); // remove and count trailing '%' + nPercentCount++; + } + + rtl_math_ConversionStatus eStatus; + sal_Int32 nParseEnd; + double fVal = ::rtl::math::stringToDouble( aInputString, cDecimalSeparator, 0, &eStatus, &nParseEnd ); + if ( eStatus == rtl_math_ConversionStatus_Ok && nParseEnd == aInputString.getLength() ) + { + if (nPercentCount) + fVal *= pow( 10.0, -(nPercentCount * 2)); // process '%' from input string + PushDouble(fVal); + return; + } + PushIllegalArgument(); +} + + //2do: this should be a proper unicode string method static inline bool lcl_ScInterpreter_IsPrintable( sal_Unicode c ) { diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx index 2f3b5ac65a49..bc7aa6fbfe14 100644 --- a/sc/source/core/tool/interpr4.cxx +++ b/sc/source/core/tool/interpr4.cxx @@ -3969,6 +3969,7 @@ StackVar ScInterpreter::Interpret() case ocT : ScT(); break; case ocClean : ScClean(); break; case ocValue : ScValue(); break; + case ocNumberValue : ScNumberValue(); break; case ocChar : ScChar(); break; case ocArcTan2 : ScArcTan2(); break; case ocMod : ScMod(); break; diff --git a/sc/source/filter/oox/formulabase.cxx b/sc/source/filter/oox/formulabase.cxx index 3b05290bb456..623b10548b8a 100644 --- a/sc/source/filter/oox/formulabase.cxx +++ b/sc/source/filter/oox/formulabase.cxx @@ -801,7 +801,7 @@ static const FunctionData saFuncTable2013[] = * import. */ { 0/*"ISOWEEKNUM"*/, "ISOWEEKNUM", NOID, NOID, 1, 2, V, { VR }, FUNCFLAG_MACROCALL_NEW }, { "MUNIT", "MUNIT", NOID, NOID, 1, 1, A, { VR }, FUNCFLAG_MACROCALL_NEW }, - { 0/*"NUMBERVALUE"*/, "NUMBERVALUE", NOID, NOID, 1, 3, V, { VR }, FUNCFLAG_MACROCALL_NEW }, + { "NUMBERVALUE", "NUMBERVALUE", NOID, NOID, 1, 3, V, { VR }, FUNCFLAG_MACROCALL_NEW }, { "PDURATION", "PDURATION", NOID, NOID, 3, 3, V, { VR }, FUNCFLAG_MACROCALL_NEW }, { "PERMUTATIONA", "PERMUTATIONA", NOID, NOID, 2, 2, V, { VR }, FUNCFLAG_MACROCALL_NEW }, { "PHI", "PHI", NOID, NOID, 1, 1, V, { VR }, FUNCFLAG_MACROCALL_NEW }, diff --git a/sc/source/ui/src/scfuncs.src b/sc/source/ui/src/scfuncs.src index d30c7dd47442..5f4c54024634 100644 --- a/sc/source/ui/src/scfuncs.src +++ b/sc/source/ui/src/scfuncs.src @@ -9396,10 +9396,10 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2 }; ExtraData = { - 1; // TODO: implementation and unsuppress + 0; ID_FUNCTION_GRP_TEXT; U2S( HID_FUNC_NUMBERVALUE ); - 2; 0; 0; + 3; 0; 1; 1; 0; }; String 2 // Name of Parameter 1 @@ -9412,11 +9412,19 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2 }; String 4 // Name of Parameter 2 { - Text [ en-US ] = "decimal_point" ; + Text [ en-US ] = "decimal_separator" ; }; String 5 // Description of Parameter 2 { - Text [ en-US ] = "Defines the character used as the decimal point." ; + Text [ en-US ] = "Defines the character used as the decimal separator." ; + }; + String 6 // Name of Parameter 3 + { + Text [ en-US ] = "group_separator" ; + }; + String 7 // Description of Parameter 3 + { + Text [ en-US ] = "Defines the character(s) used as the group separator." ; }; }; |