summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/xmloff/xmlnumfe.hxx2
-rw-r--r--include/xmloff/xmltoken.hxx1
-rw-r--r--sc/qa/unit/data/ods/tdf153993-Exponent-lower-case.odsbin0 -> 10442 bytes
-rw-r--r--sc/qa/unit/subsequent_export_test4.cxx14
-rw-r--r--schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng9
-rw-r--r--xmloff/source/core/xmltoken.cxx1
-rw-r--r--xmloff/source/style/xmlnumfe.cxx24
-rw-r--r--xmloff/source/style/xmlnumfi.cxx40
-rw-r--r--xmloff/source/token/tokens.txt1
9 files changed, 78 insertions, 14 deletions
diff --git a/include/xmloff/xmlnumfe.hxx b/include/xmloff/xmlnumfe.hxx
index 64a66a27ef05..8421c5f7e323 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 bGrouping, sal_Int32 nExp, sal_Int32 nExpInterval, bool bExpSign, bool bExponentLowercase,
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 066a55960e0b..62f3ebcd613d 100644
--- a/include/xmloff/xmltoken.hxx
+++ b/include/xmloff/xmltoken.hxx
@@ -3467,6 +3467,7 @@ namespace xmloff::token {
XML_EXTERNALDATA,
XML_EXPONENT_INTERVAL,
+ XML_EXPONENT_LOWERCASE,
XML_FORCED_EXPONENT_SIGN,
XML_MIN_DECIMAL_PLACES,
XML_MAX_DENOMINATOR_VALUE,
diff --git a/sc/qa/unit/data/ods/tdf153993-Exponent-lower-case.ods b/sc/qa/unit/data/ods/tdf153993-Exponent-lower-case.ods
new file mode 100644
index 000000000000..aaa07ca80342
--- /dev/null
+++ b/sc/qa/unit/data/ods/tdf153993-Exponent-lower-case.ods
Binary files differ
diff --git a/sc/qa/unit/subsequent_export_test4.cxx b/sc/qa/unit/subsequent_export_test4.cxx
index b611ceb5ba6f..2b4141425136 100644
--- a/sc/qa/unit/subsequent_export_test4.cxx
+++ b/sc/qa/unit/subsequent_export_test4.cxx
@@ -1503,6 +1503,20 @@ CPPUNIT_TEST_FIXTURE(ScExportTest4, testEmbeddedTextInDecimal)
lcl_TestNumberFormat(*getScDoc(), "#,##0.000\" \"###\" \"###");
}
+CPPUNIT_TEST_FIXTURE(ScExportTest4, testLowercaseExponent)
+{
+ createScDoc("ods/tdf153993-Exponent-lower-case.ods");
+
+ // save to ODS and reload
+ saveAndReload("calc8");
+ lcl_TestNumberFormat(*getScDoc(), "0.000\" \"000\" \"e+\" \"0");
+
+ // save to XLSX and reload
+ // lower case not preserve in XLSX
+ saveAndReload("Calc Office Open XML");
+ lcl_TestNumberFormat(*getScDoc(), "0.000 000 E+ 0");
+}
+
CPPUNIT_TEST_FIXTURE(ScExportTest4, testTotalsRowFunction)
{
createScDoc("xlsx/totalsRowFunction.xlsx");
diff --git a/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng b/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng
index b9fbcfc7ce4b..c9993768aa40 100644
--- a/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng
+++ b/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng
@@ -2845,6 +2845,15 @@ xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.
</rng:interleave>
</rng:define>
+ <!-- TODO no proposal, -->
+ <rng:define name="number-scientific-number-attlist" combine="interleave">
+ <rng:optional>
+ <rng:attribute name="loext:exponent-lowercase">
+ <rng:ref name="boolean"/>
+ </rng:attribute>
+ </rng:optional>
+ </rng:define>
+
<!-- TODO no proposal -->
<rng:define name="table-data-pilot-level-attlist" combine="interleave">
<rng:optional>
diff --git a/xmloff/source/core/xmltoken.cxx b/xmloff/source/core/xmltoken.cxx
index fa439f9f367b..00234904e7b4 100644
--- a/xmloff/source/core/xmltoken.cxx
+++ b/xmloff/source/core/xmltoken.cxx
@@ -3472,6 +3472,7 @@ namespace xmloff::token {
TOKEN( "external-data", XML_EXTERNALDATA),
TOKEN( "exponent-interval", XML_EXPONENT_INTERVAL ),
+ TOKEN( "exponent-lowercase", XML_EXPONENT_LOWERCASE ),
TOKEN( "forced-exponent-sign", XML_FORCED_EXPONENT_SIGN ),
TOKEN( "min-decimal-places", XML_MIN_DECIMAL_PLACES ),
TOKEN( "max-denominator-value", XML_MAX_DENOMINATOR_VALUE ),
diff --git a/xmloff/source/style/xmlnumfe.cxx b/xmloff/source/style/xmlnumfe.cxx
index 67675cf22ab3..ee09dd0b39d8 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 bGrouping, sal_Int32 nExp, sal_Int32 nExpInterval, bool bExpSign, bool bExponentLowercase,
const SvXMLEmbeddedTextEntryArr& rEmbeddedEntries )
{
FinishTextElement_Impl();
@@ -753,6 +753,13 @@ void SvXMLNumFmtExport::WriteScientificElement_Impl(
XML_FORCED_EXPONENT_SIGN,
bExpSign? XML_TRUE : XML_FALSE );
}
+ // exponent string
+ // Export only for 1.x with extensions
+ if (eVersion & SvtSaveOptions::ODFSVER_EXTENDED)
+ {
+ if (bExponentLowercase)
+ m_rExport.AddAttribute( XML_NAMESPACE_LO_EXT, XML_EXPONENT_LOWERCASE, XML_TRUE );
+ }
SvXMLElementExport aElem( m_rExport,
XML_NAMESPACE_NUMBER, XML_SCIENTIFIC_NUMBER,
@@ -1351,6 +1358,7 @@ void SvXMLNumFmtExport::ExportPart_Impl( const SvNumberformat& rFormat, sal_uInt
bool bCurrFound = false;
bool bInInteger = true;
bool bExpSign = true;
+ bool bExponentLowercase = false; // 'e' or 'E' for scientific notation
bool bDecAlign = false; // decimal alignment with "?"
sal_Int32 nExpDigits = 0;
sal_Int32 nIntegerSymbols = 0; // for embedded-text, including "#"
@@ -1421,6 +1429,8 @@ void SvXMLNumFmtExport::ExportPart_Impl( const SvNumberformat& rFormat, sal_uInt
if ( pElemStr && ( pElemStr->getLength() == 1
|| ( pElemStr->getLength() == 2 && (*pElemStr)[1] == '-' ) ) )
bExpSign = false; // for 0.00E0 or 0.00E-00
+ if ( pElemStr && (*pElemStr)[0] == 'e' )
+ bExponentLowercase = true; // for 0.00e+00
break;
case NF_SYMBOLTYPE_CURRENCY:
bCurrFound = true;
@@ -1459,8 +1469,12 @@ void SvXMLNumFmtExport::ExportPart_Impl( const SvNumberformat& rFormat, sal_uInt
// Enable embedded text in decimal part only if there's a decimal part
if ( nPrecision )
nEmbeddedPositionsMax += nPrecision + 1;
+ // Enable embedded text in exponent in scientific number
+ if ( nFmtType == SvNumFormatType::SCIENTIFIC )
+ nEmbeddedPositionsMax += 1 + nExpDigits;
nPos = 0;
bEnd = false;
+ bExpFound = false;
while (!bEnd)
{
short nElemType = rFormat.GetNumForType( nPart, nPos );
@@ -1475,6 +1489,9 @@ void SvXMLNumFmtExport::ExportPart_Impl( const SvNumberformat& rFormat, sal_uInt
if ( pElemStr )
nDigitsPassed += pElemStr->getLength();
break;
+ case NF_SYMBOLTYPE_EXP:
+ bExpFound = true;
+ [[fallthrough]];
case NF_SYMBOLTYPE_DECSEP:
nDigitsPassed++;
break;
@@ -1505,6 +1522,9 @@ void SvXMLNumFmtExport::ExportPart_Impl( const SvNumberformat& rFormat, sal_uInt
aEmbeddedEntries.push_back(
SvXMLEmbeddedTextEntry( nPos, nEmbedPos, aEmbeddedStr, bSaveBlankWidthSymbol ));
+ // exponent sign is required with embedded text in exponent
+ if ( bExpFound && !bExpSign )
+ bExpSign = true;
}
break;
}
@@ -1662,7 +1682,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,
- aEmbeddedEntries );
+ bExponentLowercase, aEmbeddedEntries );
bAnyContent = true;
break;
case SvNumFormatType::FRACTION:
diff --git a/xmloff/source/style/xmlnumfi.cxx b/xmloff/source/style/xmlnumfi.cxx
index f9f9bce5f675..d72914937eb3 100644
--- a/xmloff/source/style/xmlnumfi.cxx
+++ b/xmloff/source/style/xmlnumfi.cxx
@@ -103,6 +103,7 @@ struct SvXMLNumberInfo
bool bGrouping = false;
bool bDecReplace = false;
bool bExpSign = true;
+ bool bExponentLowercase = false; /// Exponent is 'e' instead of 'E'
bool bDecAlign = false;
double fDisplayFactor = 1.0;
OUString aIntegerFractionDelimiter;
@@ -722,6 +723,11 @@ SvXMLNumFmtElementContext::SvXMLNumFmtElementContext( SvXMLImport& rImport,
if (::sax::Converter::convertBool( bAttrBool, aIter.toView() ))
aNumInfo.bExpSign = bAttrBool;
break;
+ case XML_ELEMENT(NUMBER, XML_EXPONENT_LOWERCASE):
+ case XML_ELEMENT(LO_EXT, XML_EXPONENT_LOWERCASE):
+ if (::sax::Converter::convertBool( bAttrBool, aIter.toView() ))
+ aNumInfo.bExponentLowercase = bAttrBool;
+ break;
case XML_ELEMENT(NUMBER, XML_MIN_NUMERATOR_DIGITS):
if (::sax::Converter::convertNumber( nAttrVal, aIter.toView(), 0 ))
aNumInfo.nMinNumerDigits = nAttrVal;
@@ -1173,16 +1179,7 @@ void SvXMLNumFmtElementContext::endFastElement(sal_Int32 )
rParent.AddToCode( '#' );
}
}
- rParent.AddNumber( aNumInfo ); // simple number
-
- if ( aNumInfo.bExpSign )
- rParent.AddToCode( u"E+" );
- else
- rParent.AddToCode( u"E" );
- for (sal_Int32 i=0; i<aNumInfo.nExpDigits; i++)
- {
- rParent.AddToCode( '0' );
- }
+ rParent.AddNumber( aNumInfo ); // number and exponent
}
break;
@@ -1868,6 +1865,23 @@ void SvXMLNumFormatContext::AddNumber( const SvXMLNumberInfo& rInfo )
aNumStr.append( cAdd );
}
+ // Scientific number
+ sal_Int32 nExpPos = -1;
+ if ( rInfo.nExpDigits > 0 )
+ {
+ nExpPos = aNumStr.getLength();
+ aNumStr.append( rInfo.bExponentLowercase ? u"e" : u"E" );
+ // exponent sign is required with embedded text in exponent
+ if ( rInfo.bExpSign || ( nEmbeddedCount && ( rInfo.nDecimals + 1 < -rInfo.m_EmbeddedElements.begin()->first ) ) )
+ {
+ aNumStr.append( u"+" );
+ }
+ for (sal_Int32 i=0; i<rInfo.nExpDigits; i++)
+ {
+ aNumStr.append( '0' );
+ }
+ }
+
if ( nEmbeddedCount )
{
// insert embedded strings into number string
@@ -1893,6 +1907,8 @@ void SvXMLNumFormatContext::AddNumber( const SvXMLNumberInfo& rInfo )
aNumStr.insert(0, '#');
}
nZeroPos = nZeroPos + nAddCount;
+ if ( nExpPos > 0 )
+ nExpPos = nExpPos + nAddCount;
}
// m_EmbeddedElements is sorted with ascending positions - loop is from right to left
@@ -1900,7 +1916,9 @@ void SvXMLNumFormatContext::AddNumber( const SvXMLNumberInfo& rInfo )
{
sal_Int32 const nFormatPos = it.first;
sal_Int32 nInsertPos = nZeroPos - nFormatPos;
- if ( nInsertPos >= 0 )
+ if ( nExpPos > 0 && nInsertPos > nExpPos )
+ nInsertPos ++;
+ if ( 0 <= nInsertPos && nInsertPos <= aNumStr.getLength() )
{
aNumStr.insert( nInsertPos, it.second );
}
diff --git a/xmloff/source/token/tokens.txt b/xmloff/source/token/tokens.txt
index 85d947387e20..cdd387702531 100644
--- a/xmloff/source/token/tokens.txt
+++ b/xmloff/source/token/tokens.txt
@@ -3228,6 +3228,7 @@ display-units
display-units-built-in-unit
external-data
exponent-interval
+exponent-lowercase
forced-exponent-sign
min-decimal-places
max-denominator-value