summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sc/inc/calcconfig.hxx10
-rw-r--r--sc/source/core/tool/calcconfig.cxx2
-rw-r--r--sc/source/core/tool/formulaopt.cxx66
-rw-r--r--sc/source/core/tool/interpr4.cxx99
-rw-r--r--sc/source/ui/optdlg/calcoptionsdlg.cxx164
-rw-r--r--sc/source/ui/optdlg/calcoptionsdlg.hxx11
-rw-r--r--sc/uiconfig/scalc/ui/formulacalculationoptions.ui104
7 files changed, 390 insertions, 66 deletions
diff --git a/sc/inc/calcconfig.hxx b/sc/inc/calcconfig.hxx
index 94a72cc8b6a9..c477e726410a 100644
--- a/sc/inc/calcconfig.hxx
+++ b/sc/inc/calcconfig.hxx
@@ -28,7 +28,17 @@ enum ScRecalcOptions
*/
struct SC_DLLPUBLIC ScCalcConfig
{
+ // from most stringent to most relaxed
+ enum StringConversion
+ {
+ STRING_CONVERSION_AS_ERROR = 0, ///< =1+"1" or =1+"x" give #VALUE!
+ STRING_CONVERSION_AS_ZERO, ///< =1+"1" or =1+"x" give 1
+ STRING_CONVERSION_UNAMBIGUOUS, ///< =1+"1" gives 2, but =1+"1.000" or =1+"x" give #VALUE!
+ STRING_CONVERSION_LOCALE_DEPENDENT ///< =1+"1.000" may be 2 or 1001 ... =1+"x" gives #VALUE!
+ };
+
formula::FormulaGrammar::AddressConvention meStringRefAddressSyntax;
+ StringConversion meStringConversion;
bool mbEmptyStringAsZero:1;
bool mbOpenCLEnabled:1;
bool mbOpenCLAutoSelect:1;
diff --git a/sc/source/core/tool/calcconfig.cxx b/sc/source/core/tool/calcconfig.cxx
index f910bb151a87..d33868f27de2 100644
--- a/sc/source/core/tool/calcconfig.cxx
+++ b/sc/source/core/tool/calcconfig.cxx
@@ -11,6 +11,7 @@
ScCalcConfig::ScCalcConfig() :
meStringRefAddressSyntax(formula::FormulaGrammar::CONV_UNSPECIFIED),
+ meStringConversion(STRING_CONVERSION_LOCALE_DEPENDENT), // old LibreOffice behavior
mbEmptyStringAsZero(false),
mbOpenCLEnabled(false),
mbOpenCLAutoSelect(true)
@@ -25,6 +26,7 @@ void ScCalcConfig::reset()
bool ScCalcConfig::operator== (const ScCalcConfig& r) const
{
return meStringRefAddressSyntax == r.meStringRefAddressSyntax &&
+ meStringConversion == r.meStringConversion &&
mbEmptyStringAsZero == r.mbEmptyStringAsZero &&
mbOpenCLEnabled == r.mbOpenCLEnabled &&
mbOpenCLAutoSelect == r.mbOpenCLAutoSelect &&
diff --git a/sc/source/core/tool/formulaopt.cxx b/sc/source/core/tool/formulaopt.cxx
index 12b9cec04d36..235a594034d5 100644
--- a/sc/source/core/tool/formulaopt.cxx
+++ b/sc/source/core/tool/formulaopt.cxx
@@ -193,13 +193,14 @@ SfxPoolItem* ScTpFormulaItem::Clone( SfxItemPool * ) const
#define SCFORMULAOPT_SEP_ARRAY_ROW 3
#define SCFORMULAOPT_SEP_ARRAY_COL 4
#define SCFORMULAOPT_STRING_REF_SYNTAX 5
-#define SCFORMULAOPT_EMPTY_OUSTRING_AS_ZERO 6
-#define SCFORMULAOPT_OOXML_RECALC 7
-#define SCFORMULAOPT_ODF_RECALC 8
-#define SCFORMULAOPT_OPENCL_ENABLED 9
-#define SCFORMULAOPT_OPENCL_AUTOSELECT 10
-#define SCFORMULAOPT_OPENCL_DEVICE 11
-#define SCFORMULAOPT_COUNT 12
+#define SCFORMULAOPT_STRING_CONVERSION 6
+#define SCFORMULAOPT_EMPTY_OUSTRING_AS_ZERO 7
+#define SCFORMULAOPT_OOXML_RECALC 8
+#define SCFORMULAOPT_ODF_RECALC 9
+#define SCFORMULAOPT_OPENCL_ENABLED 10
+#define SCFORMULAOPT_OPENCL_AUTOSELECT 11
+#define SCFORMULAOPT_OPENCL_DEVICE 12
+#define SCFORMULAOPT_COUNT 13
Sequence<OUString> ScFormulaCfg::GetPropertyNames()
{
@@ -211,6 +212,7 @@ Sequence<OUString> ScFormulaCfg::GetPropertyNames()
"Syntax/SeparatorArrayRow", // SCFORMULAOPT_SEP_ARRAY_ROW
"Syntax/SeparatorArrayCol", // SCFORMULAOPT_SEP_ARRAY_COL
"Syntax/StringRefAddressSyntax", // SCFORMULAOPT_STRING_REF_SYNTAX
+ "Syntax/StringConversion", // SCFORMULAOPT_STRING_CONVERSION
"Syntax/EmptyStringAsZero", // SCFORMULAOPT_EMPTY_OUSTRING_AS_ZERO
"Load/OOXMLRecalcMode", // SCFORMULAOPT_OOXML_RECALC
"Load/ODFRecalcMode", // SCFORMULAOPT_ODF_RECALC
@@ -229,7 +231,7 @@ Sequence<OUString> ScFormulaCfg::GetPropertyNames()
ScFormulaCfg::PropsToIds ScFormulaCfg::GetPropNamesToId()
{
Sequence<OUString> aPropNames = GetPropertyNames();
- static sal_uInt16 aVals[] = { SCFORMULAOPT_GRAMMAR, SCFORMULAOPT_ENGLISH_FUNCNAME, SCFORMULAOPT_SEP_ARG, SCFORMULAOPT_SEP_ARRAY_ROW, SCFORMULAOPT_SEP_ARRAY_COL, SCFORMULAOPT_STRING_REF_SYNTAX, SCFORMULAOPT_EMPTY_OUSTRING_AS_ZERO, SCFORMULAOPT_OOXML_RECALC, SCFORMULAOPT_ODF_RECALC, SCFORMULAOPT_OPENCL_ENABLED, SCFORMULAOPT_OPENCL_AUTOSELECT, SCFORMULAOPT_OPENCL_DEVICE };
+ static sal_uInt16 aVals[] = { SCFORMULAOPT_GRAMMAR, SCFORMULAOPT_ENGLISH_FUNCNAME, SCFORMULAOPT_SEP_ARG, SCFORMULAOPT_SEP_ARRAY_ROW, SCFORMULAOPT_SEP_ARRAY_COL, SCFORMULAOPT_STRING_REF_SYNTAX, SCFORMULAOPT_STRING_CONVERSION, SCFORMULAOPT_EMPTY_OUSTRING_AS_ZERO, SCFORMULAOPT_OOXML_RECALC, SCFORMULAOPT_ODF_RECALC, SCFORMULAOPT_OPENCL_ENABLED, SCFORMULAOPT_OPENCL_AUTOSELECT, SCFORMULAOPT_OPENCL_DEVICE };
OSL_ENSURE( SAL_N_ELEMENTS(aVals) == aPropNames.getLength(), "Properties and ids are out of Sync");
PropsToIds aPropIdMap;
for ( sal_uInt16 i=0; i<aPropNames.getLength(); ++i )
@@ -328,7 +330,7 @@ void ScFormulaCfg::UpdateFromProperties( const Sequence<OUString>& aNames )
do
{
if (!(pValues[nProp] >>= nIntVal))
- // extractino failed.
+ // extraction failed.
break;
switch (nIntVal)
@@ -353,6 +355,39 @@ void ScFormulaCfg::UpdateFromProperties( const Sequence<OUString>& aNames )
GetCalcConfig().meStringRefAddressSyntax = eConv;
}
break;
+ case SCFORMULAOPT_STRING_CONVERSION:
+ {
+ // Get default value in case this option is not set.
+ ScCalcConfig::StringConversion eConv = GetCalcConfig().meStringConversion;
+
+ do
+ {
+ if (!(pValues[nProp] >>= nIntVal))
+ // extraction failed.
+ break;
+
+ switch (nIntVal)
+ {
+ case 0:
+ eConv = ScCalcConfig::STRING_CONVERSION_AS_ERROR;
+ break;
+ case 1:
+ eConv = ScCalcConfig::STRING_CONVERSION_AS_ZERO;
+ break;
+ case 2:
+ eConv = ScCalcConfig::STRING_CONVERSION_UNAMBIGUOUS;
+ break;
+ case 3:
+ eConv = ScCalcConfig::STRING_CONVERSION_LOCALE_DEPENDENT;
+ break;
+ default:
+ SAL_WARN("sc", "unknown string conversion option!");
+ }
+ }
+ while (false);
+ GetCalcConfig().meStringConversion = eConv;
+ }
+ break;
case SCFORMULAOPT_EMPTY_OUSTRING_AS_ZERO:
{
sal_Bool bVal = GetCalcConfig().mbEmptyStringAsZero;
@@ -492,6 +527,19 @@ void ScFormulaCfg::Commit()
pValues[nProp] <<= nVal;
}
break;
+ case SCFORMULAOPT_STRING_CONVERSION:
+ {
+ sal_Int32 nVal = 3;
+ switch (GetCalcConfig().meStringConversion)
+ {
+ case ScCalcConfig::STRING_CONVERSION_AS_ERROR: nVal = 0; break;
+ case ScCalcConfig::STRING_CONVERSION_AS_ZERO: nVal = 1; break;
+ case ScCalcConfig::STRING_CONVERSION_UNAMBIGUOUS: nVal = 2; break;
+ case ScCalcConfig::STRING_CONVERSION_LOCALE_DEPENDENT: nVal = 3; break;
+ }
+ pValues[nProp] <<= nVal;
+ }
+ break;
case SCFORMULAOPT_EMPTY_OUSTRING_AS_ZERO:
{
sal_Bool bVal = GetCalcConfig().mbEmptyStringAsZero;
diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index 2f390f5119aa..232fcdb4d9f2 100644
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -189,6 +189,25 @@ sal_uInt16 ScInterpreter::GetCellErrCode( const ScRefCellValue& rCell )
return rCell.meType == CELLTYPE_FORMULA ? rCell.mpFormula->GetErrCode() : 0;
}
+namespace
+{
+bool isEmptyString( const OUString& rStr )
+{
+ if (rStr.isEmpty())
+ return true;
+ else if (rStr[0] == ' ')
+ {
+ const sal_Unicode* p = rStr.getStr() + 1;
+ const sal_Unicode* const pStop = p - 1 + rStr.getLength();
+ while (p < pStop && *p == ' ')
+ ++p;
+ if (p == pStop)
+ return true;
+ }
+ return false;
+}
+}
+
/** Convert string content to numeric value.
Converted are only integer numbers including exponent, and ISO 8601 dates
@@ -221,9 +240,9 @@ sal_uInt16 ScInterpreter::GetCellErrCode( const ScRefCellValue& rCell )
double ScInterpreter::ConvertStringToValue( const OUString& rStr )
{
-#if 1
- // We keep this code until we provide a friendly way to convert string
- // numbers into numbers in the UI.
+ // We keep ScCalcConfig::STRING_CONVERSION_LOCALE_DEPENDENT default until
+ // we provide a friendly way to convert string numbers into numbers in the UI.
+
double fValue = 0.0;
if (mnStringNoValueError == errCellNoValue)
{
@@ -232,40 +251,51 @@ double ScInterpreter::ConvertStringToValue( const OUString& rStr )
return fValue;
}
- if (GetGlobalConfig().mbEmptyStringAsZero)
+ switch (GetGlobalConfig().meStringConversion)
{
- // The number scanner does not accept empty strings or strings
- // containing only spaces, be on par in these cases with what was
- // accepted in OOo and is in AOO (see also the else branch below) and
- // convert to 0 to prevent interoperability nightmares.
- if (rStr.isEmpty())
+ case ScCalcConfig::STRING_CONVERSION_AS_ERROR:
+ SetError( mnStringNoValueError);
return fValue;
- else if (rStr[0] == ' ')
- {
- const sal_Unicode* p = rStr.getStr() + 1;
- const sal_Unicode* const pStop = p - 1 + rStr.getLength();
- while (p < pStop && *p == ' ')
- ++p;
- if (p == pStop)
+ case ScCalcConfig::STRING_CONVERSION_AS_ZERO:
+ return fValue;
+ case ScCalcConfig::STRING_CONVERSION_LOCALE_DEPENDENT:
+ {
+ if (GetGlobalConfig().mbEmptyStringAsZero)
+ {
+ // The number scanner does not accept empty strings or strings
+ // containing only spaces, be on par in these cases with what was
+ // accepted in OOo and is in AOO (see also the
+ // STRING_CONVERSION_UNAMBIGUOUS branch) and convert to 0 to prevent
+ // interoperability nightmares.
+
+ if (isEmptyString( rStr))
+ return fValue;
+ }
+
+ sal_uInt32 nFIndex = 0;
+ if (!pFormatter->IsNumberFormat(rStr, nFIndex, fValue))
+ {
+ SetError( mnStringNoValueError);
+ fValue = 0.0;
+ }
return fValue;
- }
+ }
+ break;
+ case ScCalcConfig::STRING_CONVERSION_UNAMBIGUOUS:
+ {
+ if (!GetGlobalConfig().mbEmptyStringAsZero)
+ {
+ if (isEmptyString( rStr))
+ {
+ SetError( mnStringNoValueError);
+ return fValue;
+ }
+ }
+ }
+ // continue below, pulled from switch case for better readability
+ break;
}
- sal_uInt32 nFIndex = 0;
- if (!pFormatter->IsNumberFormat(rStr, nFIndex, fValue))
- {
- SetError( mnStringNoValueError);
- fValue = 0.0;
- }
- return fValue;
-#else
- double fValue = 0.0;
- if (mnStringNoValueError == errCellNoValue)
- {
- // Requested that all strings result in 0, error handled by caller.
- SetError( mnStringNoValueError);
- return fValue;
- }
OUString aStr( rStr);
rtl_math_ConversionStatus eStatus;
sal_Int32 nParseEnd;
@@ -305,14 +335,14 @@ double ScInterpreter::ConvertStringToValue( const OUString& rStr )
p = pStart;
while (p < pStop && *p == ' ')
++p;
- if (p < pStop && !CharClass::isAsciiDigit(*p))
+ if (p < pStop && !rtl::isAsciiDigit(*p))
SetError( mnStringNoValueError);
p = pLastStart;
while (p < pStop && !nGlobalError && eState < blank)
{
if (eState == minute)
nCurFmtType |= NUMBERFORMAT_TIME;
- if (CharClass::isAsciiDigit(*p))
+ if (rtl::isAsciiDigit(*p))
{
// Maximum 2 digits per unit, except fractions.
if (p - pLastStart >= 2 && eState != fraction)
@@ -427,7 +457,6 @@ double ScInterpreter::ConvertStringToValue( const OUString& rStr )
fValue = 0.0;
}
return fValue;
-#endif
}
double ScInterpreter::GetCellValue( const ScAddress& rPos, ScRefCellValue& rCell )
diff --git a/sc/source/ui/optdlg/calcoptionsdlg.cxx b/sc/source/ui/optdlg/calcoptionsdlg.cxx
index 0b5fd4cf2db4..82083cc7dc9b 100644
--- a/sc/source/ui/optdlg/calcoptionsdlg.cxx
+++ b/sc/source/ui/optdlg/calcoptionsdlg.cxx
@@ -22,9 +22,10 @@
namespace {
typedef enum {
- CALC_OPTION_REF_SYNTAX = 0,
- CALC_OPTION_EMPTY_AS_ZERO = 1,
- CALC_OPTION_ENABLE_OPENCL = 2
+ CALC_OPTION_STRING_CONVERSION = 0,
+ CALC_OPTION_EMPTY_AS_ZERO = 1,
+ CALC_OPTION_REF_SYNTAX = 2,
+ CALC_OPTION_ENABLE_OPENCL = 3
} CalcOptionOrder;
class OptionString : public SvLBoxString
@@ -101,6 +102,23 @@ formula::FormulaGrammar::AddressConvention toAddressConvention(sal_Int32 nPos)
return formula::FormulaGrammar::CONV_UNSPECIFIED;
}
+ScCalcConfig::StringConversion toStringConversion(sal_Int32 nPos)
+{
+ switch (nPos)
+ {
+ case 0:
+ return ScCalcConfig::STRING_CONVERSION_AS_ERROR;
+ case 1:
+ return ScCalcConfig::STRING_CONVERSION_AS_ZERO;
+ case 2:
+ return ScCalcConfig::STRING_CONVERSION_UNAMBIGUOUS;
+ case 3:
+ return ScCalcConfig::STRING_CONVERSION_LOCALE_DEPENDENT;
+ }
+
+ return ScCalcConfig::STRING_CONVERSION_AS_ERROR;
+}
+
}
ScCalcOptionsDialog::ScCalcOptionsDialog(Window* pParent, const ScCalcConfig& rConfig)
@@ -110,6 +128,7 @@ ScCalcOptionsDialog::ScCalcOptionsDialog(Window* pParent, const ScCalcConfig& rC
, maExcelA1(ScResId(SCSTR_FORMULA_SYNTAX_XL_A1).toString())
, maExcelR1C1(ScResId(SCSTR_FORMULA_SYNTAX_XL_R1C1).toString())
, maConfig(rConfig)
+ , mbSelectedEmptyStringAsZero(rConfig.mbEmptyStringAsZero)
{
get(mpLbSettings, "settings");
get(mpLbOptionEdit, "edit");
@@ -134,8 +153,17 @@ ScCalcOptionsDialog::ScCalcOptionsDialog(Window* pParent, const ScCalcConfig& rC
maCaptionStringRefSyntax = get<Window>("ref_syntax_caption")->GetText();
maDescStringRefSyntax = get<Window>("ref_syntax_desc")->GetText();
maUseFormulaSyntax = get<Window>("use_formula_syntax")->GetText();
+
+ maCaptionStringConversion = get<Window>("string_conversion_caption")->GetText();
+ maDescStringConversion = get<Window>("string_conversion_desc")->GetText();
+ maStringConversionAsError = get<Window>("string_conversion_as_error")->GetText();
+ maStringConversionAsZero = get<Window>("string_conversion_as_zero")->GetText();
+ maStringConversionUnambiguous = get<Window>("string_conversion_unambiguous")->GetText();
+ maStringConversionLocaleDependent = get<Window>("string_conversion_locale_dependent")->GetText();
+
maCaptionEmptyStringAsZero = get<Window>("empty_str_as_zero_caption")->GetText();
maDescEmptyStringAsZero = get<Window>("empty_str_as_zero_desc")->GetText();
+
maCaptionOpenCLEnabled = get<Window>("opencl_enabled")->GetText();
maDescOpenCLEnabled = get<Window>("opencl_enabled_desc")->GetText();
maSoftware = get<Window>("software")->GetText();
@@ -237,6 +265,18 @@ void ScCalcOptionsDialog::fillOpenclList()
#endif
+
+namespace {
+void addOption( SvTreeList* pModel, OptionString* pItem )
+{
+ SvTreeListEntry* pEntry = new SvTreeListEntry;
+ pEntry->AddItem(new SvLBoxString(pEntry, 0, OUString()));
+ pEntry->AddItem(new SvLBoxContextBmp(pEntry, 0, Image(), Image(), false));
+ pEntry->AddItem(pItem);
+ pModel->Insert(pEntry);
+}
+}
+
void ScCalcOptionsDialog::FillOptionsList()
{
mpLbSettings->SetUpdateMode(false);
@@ -245,17 +285,21 @@ void ScCalcOptionsDialog::FillOptionsList()
SvTreeList* pModel = mpLbSettings->GetModel();
{
+ // String conversion for arithmetic operations.
+ OptionString* pItem = new OptionString(
+ maCaptionStringConversion, toString(maConfig.meStringConversion));
+ addOption( pModel, pItem);
+ }
+
+ pModel->Insert(createBoolItem(maCaptionEmptyStringAsZero,maConfig.mbEmptyStringAsZero));
+
+ {
// Syntax for INDIRECT function.
- SvTreeListEntry* pEntry = new SvTreeListEntry;
- pEntry->AddItem(new SvLBoxString(pEntry, 0, OUString()));
- pEntry->AddItem(new SvLBoxContextBmp(pEntry, 0, Image(), Image(), false));
OptionString* pItem = new OptionString(
maCaptionStringRefSyntax, toString(maConfig.meStringRefAddressSyntax));
- pEntry->AddItem(pItem);
- pModel->Insert(pEntry);
+ addOption( pModel, pItem);
}
- pModel->Insert(createBoolItem(maCaptionEmptyStringAsZero,maConfig.mbEmptyStringAsZero));
#if HAVE_FEATURE_OPENCL
pModel->Insert(createBoolItem(maCaptionOpenCLEnabled,maConfig.mbOpenCLEnabled));
fillOpenclList();
@@ -304,6 +348,38 @@ void ScCalcOptionsDialog::SelectionChanged()
}
break;
+ case CALC_OPTION_STRING_CONVERSION:
+ {
+ // String conversion for arithmetic operations.
+ mpBtnTrue->Hide();
+ mpBtnFalse->Hide();
+ mpLbOptionEdit->Show();
+ mpOpenclInfoList->GetParent()->Hide();
+
+ mpLbOptionEdit->Clear();
+ mpLbOptionEdit->InsertEntry(maStringConversionAsError);
+ mpLbOptionEdit->InsertEntry(maStringConversionAsZero);
+ mpLbOptionEdit->InsertEntry(maStringConversionUnambiguous);
+ mpLbOptionEdit->InsertEntry(maStringConversionLocaleDependent);
+ switch (maConfig.meStringConversion)
+ {
+ case ScCalcConfig::STRING_CONVERSION_AS_ERROR:
+ mpLbOptionEdit->SelectEntryPos(0);
+ break;
+ case ScCalcConfig::STRING_CONVERSION_AS_ZERO:
+ mpLbOptionEdit->SelectEntryPos(1);
+ break;
+ case ScCalcConfig::STRING_CONVERSION_UNAMBIGUOUS:
+ mpLbOptionEdit->SelectEntryPos(2);
+ break;
+ case ScCalcConfig::STRING_CONVERSION_LOCALE_DEPENDENT:
+ mpLbOptionEdit->SelectEntryPos(3);
+ break;
+ }
+ mpFtAnnotation->SetText(maDescStringConversion);
+ }
+ break;
+
// booleans
case CALC_OPTION_EMPTY_AS_ZERO:
case CALC_OPTION_ENABLE_OPENCL:
@@ -314,11 +390,22 @@ void ScCalcOptionsDialog::SelectionChanged()
mpBtnFalse->Show();
bool bValue = false;
+ bool bEnable = true;
if ( nSelectedPos == CALC_OPTION_EMPTY_AS_ZERO )
{
bValue = maConfig.mbEmptyStringAsZero;
mpFtAnnotation->SetText(maDescEmptyStringAsZero);
mpOpenclInfoList->GetParent()->Hide();
+ switch (maConfig.meStringConversion)
+ {
+ case ScCalcConfig::STRING_CONVERSION_AS_ERROR:
+ case ScCalcConfig::STRING_CONVERSION_AS_ZERO:
+ bEnable = false;
+ break;
+ case ScCalcConfig::STRING_CONVERSION_UNAMBIGUOUS:
+ case ScCalcConfig::STRING_CONVERSION_LOCALE_DEPENDENT:
+ break; // nothing
+ }
}
else
{
@@ -344,6 +431,16 @@ void ScCalcOptionsDialog::SelectionChanged()
mpBtnTrue->Check(false);
mpBtnFalse->Check(true);
}
+ if (bEnable)
+ {
+ mpBtnTrue->Enable();
+ mpBtnFalse->Enable();
+ }
+ else
+ {
+ mpBtnTrue->Disable();
+ mpBtnFalse->Disable();
+ }
}
break;
default:
@@ -366,6 +463,36 @@ void ScCalcOptionsDialog::ListOptionValueChanged()
}
break;
+ case CALC_OPTION_STRING_CONVERSION:
+ {
+ // String conversion for arithmetic operations.
+ sal_Int32 nPos = mpLbOptionEdit->GetSelectEntryPos();
+ maConfig.meStringConversion = toStringConversion(nPos);
+
+ setValueAt(nSelected, toString(maConfig.meStringConversion));
+
+ switch (maConfig.meStringConversion)
+ {
+ case ScCalcConfig::STRING_CONVERSION_AS_ERROR:
+ maConfig.mbEmptyStringAsZero = false;
+ setValueAt(CALC_OPTION_EMPTY_AS_ZERO, toString(maConfig.mbEmptyStringAsZero));
+ mpLbOptionEdit->SelectEntryPos(0);
+ break;
+ case ScCalcConfig::STRING_CONVERSION_AS_ZERO:
+ maConfig.mbEmptyStringAsZero = true;
+ setValueAt(CALC_OPTION_EMPTY_AS_ZERO, toString(maConfig.mbEmptyStringAsZero));
+ mpLbOptionEdit->SelectEntryPos(1);
+ break;
+ case ScCalcConfig::STRING_CONVERSION_UNAMBIGUOUS:
+ case ScCalcConfig::STRING_CONVERSION_LOCALE_DEPENDENT:
+ // Reset to the value the user selected before.
+ maConfig.mbEmptyStringAsZero = mbSelectedEmptyStringAsZero;
+ setValueAt(CALC_OPTION_EMPTY_AS_ZERO, toString(maConfig.mbEmptyStringAsZero));
+ break;
+ }
+ }
+ break;
+
case CALC_OPTION_EMPTY_AS_ZERO:
case CALC_OPTION_ENABLE_OPENCL:
break;
@@ -424,9 +551,10 @@ void ScCalcOptionsDialog::RadioValueChanged()
switch (nSelected)
{
case CALC_OPTION_REF_SYNTAX:
+ case CALC_OPTION_STRING_CONVERSION:
return;
case CALC_OPTION_EMPTY_AS_ZERO:
- maConfig.mbEmptyStringAsZero = bValue;
+ maConfig.mbEmptyStringAsZero = mbSelectedEmptyStringAsZero = bValue;
break;
case CALC_OPTION_ENABLE_OPENCL:
maConfig.mbOpenCLEnabled = bValue;
@@ -458,6 +586,22 @@ OUString ScCalcOptionsDialog::toString(formula::FormulaGrammar::AddressConventio
return maUseFormulaSyntax;
}
+OUString ScCalcOptionsDialog::toString(ScCalcConfig::StringConversion eConv) const
+{
+ switch (eConv)
+ {
+ case ScCalcConfig::STRING_CONVERSION_AS_ERROR:
+ return maStringConversionAsError;
+ case ScCalcConfig::STRING_CONVERSION_AS_ZERO:
+ return maStringConversionAsZero;
+ case ScCalcConfig::STRING_CONVERSION_UNAMBIGUOUS:
+ return maStringConversionUnambiguous;
+ case ScCalcConfig::STRING_CONVERSION_LOCALE_DEPENDENT:
+ return maStringConversionLocaleDependent;
+ }
+ return maStringConversionAsError;
+}
+
OUString ScCalcOptionsDialog::toString(bool bVal) const
{
return bVal ? maTrue : maFalse;
diff --git a/sc/source/ui/optdlg/calcoptionsdlg.hxx b/sc/source/ui/optdlg/calcoptionsdlg.hxx
index ae4f04358c76..c542caa00c89 100644
--- a/sc/source/ui/optdlg/calcoptionsdlg.hxx
+++ b/sc/source/ui/optdlg/calcoptionsdlg.hxx
@@ -50,6 +50,7 @@ private:
#endif
OUString toString(formula::FormulaGrammar::AddressConvention eConv) const;
+ OUString toString(ScCalcConfig::StringConversion eConv) const;
OUString toString(bool bVal) const;
SvTreeListEntry *createBoolItem(const OUString &rCaption, bool bValue) const;
void setValueAt(size_t nPos, const OUString &rString);
@@ -81,6 +82,14 @@ private:
OUString maDescStringRefSyntax;
OUString maUseFormulaSyntax;
+ OUString maStringConversionAsError;
+ OUString maStringConversionAsZero;
+ OUString maStringConversionUnambiguous;
+ OUString maStringConversionLocaleDependent;
+
+ OUString maCaptionStringConversion;
+ OUString maDescStringConversion;
+
OUString maCaptionEmptyStringAsZero;
OUString maDescEmptyStringAsZero;
@@ -93,6 +102,8 @@ private:
#if HAVE_FEATURE_OPENCL
std::vector<sc::OpenclPlatformInfo> maPlatformInfo;
#endif
+
+ bool mbSelectedEmptyStringAsZero;
};
#endif
diff --git a/sc/uiconfig/scalc/ui/formulacalculationoptions.ui b/sc/uiconfig/scalc/ui/formulacalculationoptions.ui
index 305e8e3e536d..b0442c26950d 100644
--- a/sc/uiconfig/scalc/ui/formulacalculationoptions.ui
+++ b/sc/uiconfig/scalc/ui/formulacalculationoptions.ui
@@ -188,10 +188,10 @@
</packing>
</child>
<child>
- <object class="GtkLabel" id="ref_syntax_caption">
+ <object class="GtkLabel" id="string_conversion_caption">
<property name="can_focus">False</property>
<property name="no_show_all">True</property>
- <property name="label" translatable="yes">Reference syntax for string reference</property>
+ <property name="label" translatable="yes">Conversion from text to number</property>
</object>
<packing>
<property name="left_attach">0</property>
@@ -201,10 +201,10 @@
</packing>
</child>
<child>
- <object class="GtkLabel" id="ref_syntax_desc">
+ <object class="GtkLabel" id="string_conversion_desc">
<property name="can_focus">False</property>
<property name="no_show_all">True</property>
- <property name="label" translatable="yes">Formula syntax to use when parsing references given in string parameters. This affects built-in functions such as INDIRECT that takes a reference as a string value.</property>
+ <property name="label" translatable="yes">How to treat text when encountered as operand in an arithmetic operation or as argument to a function that expects a number instead. Unambiguous conversion is possible for integer numbers including exponents and ISO 8601 dates and times in their extended formats with separators. Fractional numeric values with decimal separators or dates other than ISO 8601 are locale dependent. Note that in locale dependent conversions the resulting numeric value may differ between locales!</property>
<property name="wrap">True</property>
<property name="max_width_chars">56</property>
</object>
@@ -216,10 +216,10 @@
</packing>
</child>
<child>
- <object class="GtkLabel" id="use_formula_syntax">
+ <object class="GtkLabel" id="string_conversion_as_error">
<property name="can_focus">False</property>
<property name="no_show_all">True</property>
- <property name="label" translatable="yes">Use formula syntax</property>
+ <property name="label" translatable="yes">Generate #VALUE! error</property>
</object>
<packing>
<property name="left_attach">0</property>
@@ -229,6 +229,45 @@
</packing>
</child>
<child>
+ <object class="GtkLabel" id="string_conversion_as_zero">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="label" translatable="yes">Treat as zero</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">7</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="string_conversion_unambiguous">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="label" translatable="yes">Convert only unambiguous</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">8</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="string_conversion_locale_dependent">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="label" translatable="yes">Convert also locale dependent</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">9</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
<object class="GtkLabel" id="empty_str_as_zero_caption">
<property name="can_focus">False</property>
<property name="no_show_all">True</property>
@@ -236,7 +275,7 @@
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">7</property>
+ <property name="top_attach">10</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
@@ -245,13 +284,54 @@
<object class="GtkLabel" id="empty_str_as_zero_desc">
<property name="can_focus">False</property>
<property name="no_show_all">True</property>
- <property name="label" translatable="yes">This option determines whether or not an empty string is to be treated as having a value of zero when used in arithmetic.</property>
+ <property name="label" translatable="yes">This option determines whether an empty string is to be treated as having a value of zero when used in arithmetic or generates an error. It is disabled if conversion from text to number is set to always generate an error or always treat text as zero and then follows that value.</property>
<property name="wrap">True</property>
<property name="max_width_chars">56</property>
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">8</property>
+ <property name="top_attach">11</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="ref_syntax_caption">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="label" translatable="yes">Reference syntax for string reference</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">12</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="ref_syntax_desc">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="label" translatable="yes">Formula syntax to use when parsing references given in string parameters. This affects built-in functions such as INDIRECT that takes a reference as a string value.</property>
+ <property name="wrap">True</property>
+ <property name="max_width_chars">56</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">13</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="use_formula_syntax">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="label" translatable="yes">Use formula syntax</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">14</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
@@ -264,7 +344,7 @@
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">9</property>
+ <property name="top_attach">15</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
@@ -279,7 +359,7 @@
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">10</property>
+ <property name="top_attach">16</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
@@ -470,7 +550,7 @@
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">11</property>
+ <property name="top_attach">17</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>