diff options
-rw-r--r-- | include/xmloff/xmlnumfe.hxx | 2 | ||||
-rw-r--r-- | include/xmloff/xmltoken.hxx | 1 | ||||
-rw-r--r-- | sc/qa/unit/data/ods/tdf153993-Exponent-lower-case.ods | bin | 0 -> 10442 bytes | |||
-rw-r--r-- | sc/qa/unit/subsequent_export_test4.cxx | 14 | ||||
-rw-r--r-- | schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng | 9 | ||||
-rw-r--r-- | xmloff/source/core/xmltoken.cxx | 1 | ||||
-rw-r--r-- | xmloff/source/style/xmlnumfe.cxx | 24 | ||||
-rw-r--r-- | xmloff/source/style/xmlnumfi.cxx | 40 | ||||
-rw-r--r-- | xmloff/source/token/tokens.txt | 1 |
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 Binary files differnew file mode 100644 index 000000000000..aaa07ca80342 --- /dev/null +++ b/sc/qa/unit/data/ods/tdf153993-Exponent-lower-case.ods 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 |