summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/svl/zforlist.hxx3
-rw-r--r--include/svl/zformat.hxx19
-rw-r--r--sc/source/core/data/documen4.cxx4
-rw-r--r--svl/source/numbers/zforlist.cxx9
-rw-r--r--svl/source/numbers/zformat.cxx147
5 files changed, 119 insertions, 63 deletions
diff --git a/include/svl/zforlist.hxx b/include/svl/zforlist.hxx
index ab7dd90f1426..36e468726a64 100644
--- a/include/svl/zforlist.hxx
+++ b/include/svl/zforlist.hxx
@@ -531,6 +531,9 @@ public:
sal_uInt16& nPrecision, sal_uInt16& nAnzLeading,
LanguageType eLnge = LANGUAGE_DONTKNOW );
+ /// Get round value with fraction representation
+ double GetRoundFractionValue( sal_uInt32 nFormat, double fValue ) const;
+
/// Check if format code string may be deleted by user
bool IsUserDefined( const OUString& sStr, LanguageType eLnge = LANGUAGE_DONTKNOW );
diff --git a/include/svl/zformat.hxx b/include/svl/zformat.hxx
index ceba6a4993ca..f798d4090638 100644
--- a/include/svl/zformat.hxx
+++ b/include/svl/zformat.hxx
@@ -212,6 +212,9 @@ public:
sal_uInt16& nPrecision,
sal_uInt16& nAnzLeading) const;
+ /// Get index of subformat (0..3) according to conditions and fNumber value
+ sal_uInt16 GetSubformatIndex( double fNumber ) const;
+
/// Count of decimal precision
sal_uInt16 GetFormatPrecision() const { return NumFor[0].Info().nCntPost; }
@@ -242,6 +245,9 @@ public:
OUString GetDenominatorString( sal_uInt16 nNumFor ) const;
OUString GetNumeratorString( sal_uInt16 nNumFor ) const;
OUString GetIntegerFractionDelimiterString( sal_uInt16 nNumFor ) const;
+ /// Round fNumber to its fraction representation
+ double GetRoundFractionValue ( double fNumber ) const;
+
/** If the count of string elements (substrings, ignoring [modifiers] and
so on) in a subformat code nNumFor (0..3) is equal to the given number.
Used by ImpSvNumberInputScan::IsNumberFormatMain() to detect a matched
@@ -580,6 +586,19 @@ private:
sal_uInt16 nIx,
bool bInteger );
+ /** Calculate each element of fraction:
+ * integer part, numerator part, denominator part
+ * @param fNumber value to be represented as fraction. Will contain absolute fractional part
+ * @param nIx subformat number 0..3
+ * @param fIntPart integral part of fraction
+ * @param nFrac numerator of fraction
+ * @param nDic denominator of fraction
+ */
+ SVL_DLLPRIVATE void ImpGetFractionElements( double& fNumber,
+ sal_uInt16 nIx,
+ double& fIntPart,
+ sal_uInt64& nFrac,
+ sal_uInt64& nDiv ) const;
SVL_DLLPRIVATE bool ImpGetFractionOutput(double fNumber,
sal_uInt16 nIx,
OUStringBuffer& OutString);
diff --git a/sc/source/core/data/documen4.cxx b/sc/source/core/data/documen4.cxx
index c503b2fa6137..09b7c543e7e8 100644
--- a/sc/source/core/data/documen4.cxx
+++ b/sc/source/core/data/documen4.cxx
@@ -672,6 +672,10 @@ double ScDocument::RoundValueAsShown( double fVal, sal_uInt32 nFormat ) const
nPrecision = sal::static_int_cast<short>( nPrecision - (short)floor( log10( -fVal ) ) );
break;
}
+ case css::util::NumberFormat::FRACTION: // get value of fraction representation
+ {
+ return GetFormatTable()->GetRoundFractionValue( nFormat, fVal );
+ }
}
}
else
diff --git a/svl/source/numbers/zforlist.cxx b/svl/source/numbers/zforlist.cxx
index c2617a534a4b..659e1b5b340d 100644
--- a/svl/source/numbers/zforlist.cxx
+++ b/svl/source/numbers/zforlist.cxx
@@ -1963,6 +1963,15 @@ void SvNumberFormatter::GetFormatSpecialInfo(sal_uInt32 nFormat,
}
}
+double SvNumberFormatter::GetRoundFractionValue( sal_uInt32 nFormat, double fValue ) const
+{
+ const SvNumberformat* pFormat = GetFormatEntry( nFormat );
+ if ( pFormat )
+ return pFormat->GetRoundFractionValue( fValue );
+ else
+ return fValue;
+}
+
sal_uInt16 SvNumberFormatter::GetFormatPrecision( sal_uInt32 nFormat ) const
{
const SvNumberformat* pFormat = GetFormatEntry( nFormat );
diff --git a/svl/source/numbers/zformat.cxx b/svl/source/numbers/zformat.cxx
index 2c018f662784..103da063321f 100644
--- a/svl/source/numbers/zformat.cxx
+++ b/svl/source/numbers/zformat.cxx
@@ -2349,6 +2349,31 @@ bool SvNumberformat::GetOutputString(double fNumber, sal_uInt16 nCharCount, OUSt
return true;
}
+sal_uInt16 SvNumberformat::GetSubformatIndex (double fNumber ) const
+{
+ sal_uInt16 nIx; // Index of the partial format
+ double fLimit_1 = fLimit1;
+ short nCheck = ImpCheckCondition(fNumber, fLimit_1, eOp1);
+ if (nCheck == -1 || nCheck == 1) // Only 1 String or True
+ {
+ nIx = 0;
+ }
+ else
+ {
+ double fLimit_2 = fLimit2;
+ nCheck = ImpCheckCondition(fNumber, fLimit_2, eOp2);
+ if (nCheck == -1 || nCheck == 1)
+ {
+ nIx = 1;
+ }
+ else
+ {
+ nIx = 2;
+ }
+ }
+ return nIx;
+}
+
bool SvNumberformat::GetOutputString(double fNumber,
OUString& OutString,
Color** ppColor)
@@ -2439,24 +2464,7 @@ bool SvNumberformat::GetOutputString(double fNumber,
}
if ( !bHadStandard )
{
- sal_uInt16 nIx; // Index of the partial format
- short nCheck = ImpCheckCondition(fNumber, fLimit1, eOp1);
- if (nCheck == -1 || nCheck == 1) // Only 1 String or True
- {
- nIx = 0;
- }
- else
- {
- nCheck = ImpCheckCondition(fNumber, fLimit2, eOp2);
- if (nCheck == -1 || nCheck == 1)
- {
- nIx = 1;
- }
- else
- {
- nIx = 2;
- }
- }
+ sal_uInt16 nIx = GetSubformatIndex ( fNumber ); // Index of the partial format
if (fNumber < 0.0 &&
((nIx == 0 && IsFirstSubformatRealNegative()) || // 1st, usually positive subformat
(nIx == 1 && IsSecondSubformatRealNegative()))) // 2nd, usually negative subformat
@@ -2679,45 +2687,31 @@ bool SvNumberformat::ImpGetScientificOutput(double fNumber,
return bRes;
}
-bool SvNumberformat::ImpGetFractionOutput(double fNumber,
- sal_uInt16 nIx,
- OUStringBuffer& sBuff)
+double SvNumberformat::GetRoundFractionValue ( double fNumber ) const
{
- bool bRes = false;
- const ImpSvNumberformatInfo& rInfo = NumFor[nIx].Info();
- const sal_uInt16 nAnz = NumFor[nIx].GetCount();
- OUStringBuffer sStr, sFrac, sDiv; // Strings, value for
- sal_uInt64 nFrac=0, nDiv=1; // Integral part
- bool bSign = false; // Numerator and denominator
- const OUString sIntegerFormat = lcl_GetFractionIntegerString(rInfo, nAnz);
- const OUString sNumeratorFormat = lcl_GetNumeratorString(rInfo, nAnz);
- const OUString sDenominatorFormat = lcl_GetDenominatorString(rInfo, nAnz);
+ sal_uInt16 nIx = GetSubformatIndex ( fNumber );
+ double fIntPart = 0.0; // integer part of fraction
+ sal_uInt64 nFrac = 0, nDiv = 1; // numerator and denominator
+ double fSign = (fNumber < 0.0) ? -1.0 : 1.0;
+ // fNumber is modified in ImpGetFractionElements to absolute fractional part
+ ImpGetFractionElements ( fNumber, nIx, fIntPart, nFrac, nDiv );
+ if ( nDiv > 0 )
+ return fSign * ( fIntPart + (double)nFrac / (double)nDiv );
+ else
+ return fSign * fIntPart;
+}
- if (fNumber < 0)
- {
- if (nIx == 0) // Not in the ones at the end
- bSign = true; // Formats
+void SvNumberformat::ImpGetFractionElements ( double& fNumber, sal_uInt16 nIx,
+ double& fIntPart, sal_uInt64& nFrac, sal_uInt64& nDiv ) const
+{
+ if ( fNumber < 0.0 )
fNumber = -fNumber;
- }
-
- double fNum = floor(fNumber); // Integral part
-
- fNumber -= fNum; // Fractional part
- if (fNum > D_MAX_U_INT32 || rInfo.nCntExp > 9) // Too large
- {
- sBuff = rScan.GetErrorString();
- return false;
- }
- if (rInfo.nCntExp == 0)
- {
- SAL_WARN( "svl.numbers", "SvNumberformat:: Fraction, nCntExp == 0");
- sBuff.truncate();
- return false;
- }
-
- if( sal_Int32 nForcedDiv = sDenominatorFormat.toInt32() )
+ fIntPart = floor(fNumber); // Integral part
+ fNumber -= fIntPart; // Fractional part
+ const ImpSvNumberformatInfo& rInfo = NumFor[nIx].Info();
+ nDiv = lcl_GetDenominatorString( rInfo, NumFor[nIx].GetCount() ).toInt32();
+ if( nDiv > 0 )
{ // Forced Denominator
- nDiv = (sal_uInt64) nForcedDiv;
nFrac = (sal_uInt64)floor ( fNumber * nDiv );
double fFracNew = (double)nFrac / (double)nDiv;
double fFracNew1 = (double)(nFrac + 1) / (double)nDiv;
@@ -2726,14 +2720,10 @@ bool SvNumberformat::ImpGetFractionOutput(double fNumber,
{
nFrac++;
}
- if( nFrac >= nDiv )
- {
- nFrac = nDiv = 0;
- fNum = fNum + 1.0;
- }
}
else // Calculated Denominator
{
+ nDiv = 1;
sal_uInt64 nBasis = ((sal_uInt64)floor( pow(10.0,rInfo.nCntExp))) - 1; // 9, 99, 999 ,...
sal_uInt64 nFracPrev = 1L, nDivPrev = 0, nFracNext, nDivNext, nPartialDenom;
double fRemainder = fNumber;
@@ -2771,12 +2761,43 @@ bool SvNumberformat::ImpGetFractionOutput(double fNumber,
fRemainder = 0.0; // exit while loop
}
}
- if (nFrac == nDiv)
- {
- ++fNum;
- nFrac = 0;
- }
}
+ if (nFrac >= nDiv)
+ {
+ ++fIntPart;
+ nFrac = nDiv = 0;
+ }
+}
+
+bool SvNumberformat::ImpGetFractionOutput(double fNumber,
+ sal_uInt16 nIx,
+ OUStringBuffer& sBuff)
+{
+ bool bRes = false;
+ const ImpSvNumberformatInfo& rInfo = NumFor[nIx].Info();
+ const sal_uInt16 nAnz = NumFor[nIx].GetCount();
+ OUStringBuffer sStr, sFrac, sDiv; // Strings, value for Integral part Numerator and denominator
+ bool bSign = ( (fNumber < 0) && (nIx == 0) ); // sign Not in the ones at the end
+ const OUString sIntegerFormat = lcl_GetFractionIntegerString(rInfo, nAnz);
+ const OUString sNumeratorFormat = lcl_GetNumeratorString(rInfo, nAnz);
+ const OUString sDenominatorFormat = lcl_GetDenominatorString(rInfo, nAnz);
+
+ sal_uInt64 nFrac = 0, nDiv = 1;
+ double fNum = floor(fNumber); // Integral part
+
+ if (fNum > D_MAX_U_INT32 || rInfo.nCntExp > 9) // Too large
+ {
+ sBuff = rScan.GetErrorString();
+ return false;
+ }
+ if (rInfo.nCntExp == 0)
+ {
+ SAL_WARN( "svl.numbers", "SvNumberformat:: Fraction, nCntExp == 0");
+ sBuff.truncate();
+ return false;
+ }
+
+ ImpGetFractionElements( fNumber, nIx, fNum, nFrac, nDiv);
if (rInfo.nCntPre == 0) // Improper fraction
{