summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--basic/qa/vba_tests/format.vb2
-rw-r--r--include/xmloff/xmlnumfe.hxx2
-rw-r--r--include/xmloff/xmltoken.hxx1
-rw-r--r--sc/qa/unit/data/ods/tdf156449-Blank-In-Exponent.odsbin0 -> 9458 bytes
-rw-r--r--sc/qa/unit/subsequent_export_test4.cxx31
-rw-r--r--schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng9
-rw-r--r--svl/qa/unit/svl.cxx8
-rw-r--r--svl/source/numbers/zformat.cxx8
-rw-r--r--xmloff/source/core/xmltoken.cxx1
-rw-r--r--xmloff/source/style/xmlnumfe.cxx20
-rw-r--r--xmloff/source/style/xmlnumfi.cxx16
-rw-r--r--xmloff/source/token/tokens.txt1
12 files changed, 89 insertions, 10 deletions
diff --git a/basic/qa/vba_tests/format.vb b/basic/qa/vba_tests/format.vb
index 0e997ca824db..4e62e87e498e 100644
--- a/basic/qa/vba_tests/format.vb
+++ b/basic/qa/vba_tests/format.vb
@@ -135,7 +135,7 @@ Sub Custom_Number_Format_Sample()
TestUtil.AssertEqual(Format(12345.25, "#,###.##"), "12,345.25", "Format(12345.25, ""#,###.##"")")
TestUtil.AssertEqual(Format(0.25, "##.00%"), "25.00%", "Format(0.25, ""##.00%"")")
TestUtil.AssertEqual(Format(1000000, "#,###"), "1,000,000", "Format(1000000, ""#,###"")")
- TestUtil.AssertEqual(Format(1.09837555, "#.#####E+###"), "1.09838E+000", "Format(1.09837555, ""#.#####E+###"")")
+ TestUtil.AssertEqual(Format(1.09837555, "#.#####E+000"), "1.09838E+000", "Format(1.09837555, ""#.#####E+000"")")
TestUtil.AssertEqual(Format(1.09837555, "###.####E#"), "1.0984E0", "Format(1.09837555, ""###.####E#"")")
TestUtil.AssertEqual(Format(1098.37555, "###.####E#"), "1.0984E3", "Format(1098.37555, ""###.####E#"")")
TestUtil.AssertEqual(Format(1098375.55, "###.####E#"), "1.0984E6", "Format(1098375.55, ""###.####E#"")")
diff --git a/include/xmloff/xmlnumfe.hxx b/include/xmloff/xmlnumfe.hxx
index 8421c5f7e323..d96f40c53a04 100644
--- a/include/xmloff/xmlnumfe.hxx
+++ b/include/xmloff/xmlnumfe.hxx
@@ -71,7 +71,7 @@ private:
bool bGrouping, sal_Int32 nTrailingThousands,
const SvXMLEmbeddedTextEntryArr& rEmbeddedEntries );
SAL_DLLPRIVATE void WriteScientificElement_Impl( sal_Int32 nDecimals, sal_Int32 nMinDecimals, sal_Int32 nInteger, sal_Int32 nBlankInteger,
- bool bGrouping, sal_Int32 nExp, sal_Int32 nExpInterval, bool bExpSign, bool bExponentLowercase,
+ bool bGrouping, sal_Int32 nExp, sal_Int32 nExpInterval, bool bExpSign, bool bExponentLowercase, sal_Int32 nBlankExp,
const SvXMLEmbeddedTextEntryArr& rEmbeddedEntries );
SAL_DLLPRIVATE void WriteFractionElement_Impl( sal_Int32 nInteger, sal_Int32 nBlankInteger, bool bGrouping,
const SvNumberformat& rFormat, sal_uInt16 nPart );
diff --git a/include/xmloff/xmltoken.hxx b/include/xmloff/xmltoken.hxx
index 62f3ebcd613d..4e6441841774 100644
--- a/include/xmloff/xmltoken.hxx
+++ b/include/xmloff/xmltoken.hxx
@@ -3469,6 +3469,7 @@ namespace xmloff::token {
XML_EXPONENT_INTERVAL,
XML_EXPONENT_LOWERCASE,
XML_FORCED_EXPONENT_SIGN,
+ XML_BLANK_EXPONENT_DIGITS,
XML_MIN_DECIMAL_PLACES,
XML_MAX_DENOMINATOR_VALUE,
XML_MAX_NUMERATOR_DIGITS,
diff --git a/sc/qa/unit/data/ods/tdf156449-Blank-In-Exponent.ods b/sc/qa/unit/data/ods/tdf156449-Blank-In-Exponent.ods
new file mode 100644
index 000000000000..73647881e73d
--- /dev/null
+++ b/sc/qa/unit/data/ods/tdf156449-Blank-In-Exponent.ods
Binary files differ
diff --git a/sc/qa/unit/subsequent_export_test4.cxx b/sc/qa/unit/subsequent_export_test4.cxx
index 2b4141425136..390783131733 100644
--- a/sc/qa/unit/subsequent_export_test4.cxx
+++ b/sc/qa/unit/subsequent_export_test4.cxx
@@ -1468,6 +1468,37 @@ void lcl_TestNumberFormat(ScDocument& rDoc, const OUString& rFormatStrOK)
CPPUNIT_ASSERT_EQUAL(rFormatStrOK, rFormatStr);
}
+
+void lcl_SetNumberFormat(ScDocument& rDoc, const OUString& rFormat)
+{
+ sal_Int32 nCheckPos;
+ SvNumFormatType nType;
+ sal_uInt32 nFormat;
+ OUString aNewFormat = rFormat;
+ SvNumberFormatter* pFormatter = rDoc.GetFormatTable();
+ if (pFormatter)
+ {
+ pFormatter->PutEntry(aNewFormat, nCheckPos, nType, nFormat);
+ rDoc.SetNumberFormat(ScAddress(0, 0, 0), nFormat);
+ }
+}
+}
+
+CPPUNIT_TEST_FIXTURE(ScExportTest4, testBlankInExponent)
+{
+ createScDoc("ods/tdf156449-Blank-In-Exponent.ods");
+
+ // save to ODS and reload
+ saveAndReload("calc8");
+ lcl_TestNumberFormat(*getScDoc(), "0.00E+?0");
+ lcl_SetNumberFormat(*getScDoc(), "0.00E+??");
+ // at least one '0' in exponent
+ saveAndReload("calc8");
+ lcl_TestNumberFormat(*getScDoc(), "0.00E+?0");
+
+ // save to XLSX and reload
+ saveAndReload("Calc Office Open XML");
+ lcl_TestNumberFormat(*getScDoc(), "0.00E+?0");
}
CPPUNIT_TEST_FIXTURE(ScExportTest4, testSecondsWithoutTruncateAndDecimals)
diff --git a/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng b/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng
index c9993768aa40..aeb4c77ea40e 100644
--- a/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng
+++ b/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng
@@ -2854,6 +2854,15 @@ xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.
</rng:optional>
</rng:define>
+ <!-- TODO no proposal, -->
+ <rng:define name="number-scientific-number-attlist" combine="interleave">
+ <rng:optional>
+ <rng:attribute name="loext:blank-exponent-digits">
+ <rng:ref name="positiveInteger"/>
+ </rng:attribute>
+ </rng:optional>
+ </rng:define>
+
<!-- TODO no proposal -->
<rng:define name="table-data-pilot-level-attlist" combine="interleave">
<rng:optional>
diff --git a/svl/qa/unit/svl.cxx b/svl/qa/unit/svl.cxx
index f43cfb9e437e..4fa56f4bccd4 100644
--- a/svl/qa/unit/svl.cxx
+++ b/svl/qa/unit/svl.cxx
@@ -1743,6 +1743,14 @@ void Test::testUserDefinedNumberFormats()
sExpected = "271433.605";
checkPreviewString(aFormatter, sCode, M_PI, eLang, sExpected);
}
+ { // tdf#156449 Use '?' in exponent of scientific number
+ sCode = "0.00E+?0";
+ sExpected = "3.14E+ 0"; // before change it was "3.14E+00"
+ checkPreviewString(aFormatter, sCode, M_PI, eLang, sExpected);
+ // There should be at least one '0' in exponent
+ sCode = "0.00E+??";
+ checkPreviewString(aFormatter, sCode, M_PI, eLang, sExpected);
+ }
{ // tdf#33689 use English NfKeywords in non-English language
eLang = LANGUAGE_DUTCH;
sExpected = "Dutch: 1900/01/02 03:23:53";
diff --git a/svl/source/numbers/zformat.cxx b/svl/source/numbers/zformat.cxx
index 174ab1c15667..b5c8757ef2e6 100644
--- a/svl/source/numbers/zformat.cxx
+++ b/svl/source/numbers/zformat.cxx
@@ -2752,11 +2752,10 @@ bool SvNumberformat::ImpGetScientificOutput(double fNumber,
}
sal_uInt16 j = nCnt-1; // Last symbol
- sal_Int32 k; // Position in ExpStr
+ sal_Int32 k = ExpStr.getLength() - 1; // Position in ExpStr
sal_Int32 nZeros = 0; // Erase leading zeros
- bRes |= ImpNumberFill(ExpStr, fNumber, k, j, nIx, NF_SYMBOLTYPE_EXP);
-
+ // erase all leading zeros except last one
while (nZeros < k && ExpStr[nZeros] == '0')
{
++nZeros;
@@ -2766,6 +2765,9 @@ bool SvNumberformat::ImpGetScientificOutput(double fNumber,
ExpStr.remove( 0, nZeros);
}
+ // restore leading zeros or blanks according to format '0' or '?' tdf#156449
+ bRes |= ImpNumberFill(ExpStr, fNumber, k, j, nIx, NF_SYMBOLTYPE_EXP);
+
bool bCont = true;
if (rInfo.nTypeArray[j] == NF_SYMBOLTYPE_EXP)
diff --git a/xmloff/source/core/xmltoken.cxx b/xmloff/source/core/xmltoken.cxx
index 00234904e7b4..6879f37db295 100644
--- a/xmloff/source/core/xmltoken.cxx
+++ b/xmloff/source/core/xmltoken.cxx
@@ -3474,6 +3474,7 @@ namespace xmloff::token {
TOKEN( "exponent-interval", XML_EXPONENT_INTERVAL ),
TOKEN( "exponent-lowercase", XML_EXPONENT_LOWERCASE ),
TOKEN( "forced-exponent-sign", XML_FORCED_EXPONENT_SIGN ),
+ TOKEN( "blank-exponent-digits", XML_BLANK_EXPONENT_DIGITS ),
TOKEN( "min-decimal-places", XML_MIN_DECIMAL_PLACES ),
TOKEN( "max-denominator-value", XML_MAX_DENOMINATOR_VALUE ),
TOKEN( "max-numerator-digits", XML_MAX_NUMERATOR_DIGITS ),
diff --git a/xmloff/source/style/xmlnumfe.cxx b/xmloff/source/style/xmlnumfe.cxx
index ee09dd0b39d8..406c22236a71 100644
--- a/xmloff/source/style/xmlnumfe.cxx
+++ b/xmloff/source/style/xmlnumfe.cxx
@@ -695,7 +695,7 @@ void SvXMLNumFmtExport::WriteNumberElement_Impl(
void SvXMLNumFmtExport::WriteScientificElement_Impl(
sal_Int32 nDecimals, sal_Int32 nMinDecimals, sal_Int32 nInteger, sal_Int32 nBlankInteger,
- bool bGrouping, sal_Int32 nExp, sal_Int32 nExpInterval, bool bExpSign, bool bExponentLowercase,
+ bool bGrouping, sal_Int32 nExp, sal_Int32 nExpInterval, bool bExpSign, bool bExponentLowercase, sal_Int32 nBlankExp,
const SvXMLEmbeddedTextEntryArr& rEmbeddedEntries )
{
FinishTextElement_Impl();
@@ -759,6 +759,12 @@ void SvXMLNumFmtExport::WriteScientificElement_Impl(
{
if (bExponentLowercase)
m_rExport.AddAttribute( XML_NAMESPACE_LO_EXT, XML_EXPONENT_LOWERCASE, XML_TRUE );
+ if (nBlankExp > 0)
+ {
+ if (nBlankExp >= nExp)
+ nBlankExp = nExp - 1; // preserve at least one '0' in exponent
+ m_rExport.AddAttribute( XML_NAMESPACE_LO_EXT, XML_BLANK_EXPONENT_DIGITS, OUString::number( nBlankExp ) );
+ }
}
SvXMLElementExport aElem( m_rExport,
@@ -1360,7 +1366,8 @@ void SvXMLNumFmtExport::ExportPart_Impl( const SvNumberformat& rFormat, sal_uInt
bool bExpSign = true;
bool bExponentLowercase = false; // 'e' or 'E' for scientific notation
bool bDecAlign = false; // decimal alignment with "?"
- sal_Int32 nExpDigits = 0;
+ sal_Int32 nExpDigits = 0; // '0' and '?' in exponent
+ sal_Int32 nBlankExp = 0; // only '?' in exponent
sal_Int32 nIntegerSymbols = 0; // for embedded-text, including "#"
sal_Int32 nTrailingThousands = 0; // thousands-separators after all digits
sal_Int32 nMinDecimals = nPrecision;
@@ -1383,7 +1390,14 @@ void SvXMLNumFmtExport::ExportPart_Impl( const SvNumberformat& rFormat, sal_uInt
break;
case NF_SYMBOLTYPE_DIGIT:
if ( bExpFound && pElemStr )
+ {
nExpDigits += pElemStr->getLength();
+ for ( sal_Int32 i = pElemStr->getLength()-1; i >= 0 ; i-- )
+ {
+ if ( (*pElemStr)[i] == '?' )
+ nBlankExp ++;
+ }
+ }
else if ( !bDecDashes && pElemStr && (*pElemStr)[0] == '-' )
{
bDecDashes = true;
@@ -1682,7 +1696,7 @@ void SvXMLNumFmtExport::ExportPart_Impl( const SvNumberformat& rFormat, sal_uInt
// as integer digits: use nIntegerSymbols instead of nLeading
// nIntegerSymbols represents exponent interval (for engineering notation)
WriteScientificElement_Impl( nPrecision, nMinDecimals, nLeading, nBlankInteger, bThousand, nExpDigits, nIntegerSymbols, bExpSign,
- bExponentLowercase, aEmbeddedEntries );
+ bExponentLowercase, nBlankExp, aEmbeddedEntries );
bAnyContent = true;
break;
case SvNumFormatType::FRACTION:
diff --git a/xmloff/source/style/xmlnumfi.cxx b/xmloff/source/style/xmlnumfi.cxx
index d72914937eb3..f6d05e94c1bf 100644
--- a/xmloff/source/style/xmlnumfi.cxx
+++ b/xmloff/source/style/xmlnumfi.cxx
@@ -90,7 +90,8 @@ struct SvXMLNumberInfo
sal_Int32 nDecimals = -1;
sal_Int32 nInteger = -1; /// Total min number of digits in integer part ('0' + '?')
sal_Int32 nBlankInteger = -1; /// Number of '?' in integer part
- sal_Int32 nExpDigits = -1;
+ sal_Int32 nExpDigits = -1; /// Number of '0' and '?' in exponent
+ sal_Int32 nBlankExp = -1; /// Number of '?' in exponent
sal_Int32 nExpInterval = -1;
sal_Int32 nMinNumerDigits = -1;
sal_Int32 nMinDenomDigits = -1;
@@ -713,6 +714,11 @@ SvXMLNumFmtElementContext::SvXMLNumFmtElementContext( SvXMLImport& rImport,
if (::sax::Converter::convertNumber( nAttrVal, aIter.toView(), 0 ))
aNumInfo.nExpDigits = std::min<sal_Int32>(nAttrVal, NF_MAX_FORMAT_SYMBOLS);
break;
+ case XML_ELEMENT(NUMBER, XML_BLANK_EXPONENT_DIGITS):
+ case XML_ELEMENT(LO_EXT, XML_BLANK_EXPONENT_DIGITS):
+ if (::sax::Converter::convertNumber( nAttrVal, aIter.toView(), 0 ))
+ aNumInfo.nBlankExp = std::min<sal_Int32>(nAttrVal, NF_MAX_FORMAT_SYMBOLS);
+ break;
case XML_ELEMENT(NUMBER, XML_EXPONENT_INTERVAL):
case XML_ELEMENT(LO_EXT, XML_EXPONENT_INTERVAL):
if (::sax::Converter::convertNumber( nAttrVal, aIter.toView(), 0 ))
@@ -808,6 +814,9 @@ SvXMLNumFmtElementContext::SvXMLNumFmtElementContext( SvXMLImport& rImport,
else
aNumInfo.nMinDecimalDigits = aNumInfo.nDecimals;
}
+ if ( aNumInfo.nExpDigits > 0 && aNumInfo.nBlankExp >= aNumInfo.nExpDigits )
+ aNumInfo.nBlankExp = aNumInfo.nExpDigits - 1; // at least one '0' in exponent
+
if ( aNumInfo.nZerosDenomDigits > 0 )
{ // nMin = count of '0' and '?'
if ( aNumInfo.nMinDenomDigits < aNumInfo.nZerosDenomDigits )
@@ -1878,7 +1887,10 @@ void SvXMLNumFormatContext::AddNumber( const SvXMLNumberInfo& rInfo )
}
for (sal_Int32 i=0; i<rInfo.nExpDigits; i++)
{
- aNumStr.append( '0' );
+ if ( i < rInfo.nBlankExp )
+ aNumStr.append( '?' );
+ else
+ aNumStr.append( '0' );
}
}
diff --git a/xmloff/source/token/tokens.txt b/xmloff/source/token/tokens.txt
index cdd387702531..7eb09f6f2f9f 100644
--- a/xmloff/source/token/tokens.txt
+++ b/xmloff/source/token/tokens.txt
@@ -3230,6 +3230,7 @@ external-data
exponent-interval
exponent-lowercase
forced-exponent-sign
+blank-exponent-digits
min-decimal-places
max-denominator-value
max-numerator-digits