summaryrefslogtreecommitdiffstats
path: root/sc
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@gmail.com>2012-03-07 22:07:09 -0500
committerKohei Yoshida <kohei.yoshida@gmail.com>2012-03-09 11:13:34 -0500
commit57c0ff6602dfbd0b7622a643e179923bf632cd87 (patch)
tree2d9f91bd3d2c3054ed3bdb56be7cb022ecd68800 /sc
parentThese functions are no longer used. (diff)
downloadcore-57c0ff6602dfbd0b7622a643e179923bf632cd87.tar.gz
core-57c0ff6602dfbd0b7622a643e179923bf632cd87.zip
Properly display grouped range values for range-based grouping.
Diffstat (limited to 'sc')
-rw-r--r--sc/inc/dpgroup.hxx7
-rw-r--r--sc/inc/dpitemdata.hxx7
-rw-r--r--sc/inc/dpnumgroupinfo.hxx2
-rw-r--r--sc/inc/dptablecache.hxx4
-rw-r--r--sc/inc/dputil.hxx6
-rw-r--r--sc/source/core/data/dpgroup.cxx188
-rw-r--r--sc/source/core/data/dpitemdata.cxx66
-rw-r--r--sc/source/core/data/dpnumgroupinfo.cxx15
-rw-r--r--sc/source/core/data/dptablecache.cxx24
-rw-r--r--sc/source/core/data/dputil.cxx142
10 files changed, 264 insertions, 197 deletions
diff --git a/sc/inc/dpgroup.hxx b/sc/inc/dpgroup.hxx
index cff5c4bed390..b90c667b7387 100644
--- a/sc/inc/dpgroup.hxx
+++ b/sc/inc/dpgroup.hxx
@@ -130,8 +130,6 @@ class SC_DLLPUBLIC ScDPNumGroupDimension
mutable ScDPNumGroupInfo aGroupInfo; // settings
ScDPDateGroupHelper* pDateHelper;
mutable std::vector<SCROW> maMemberEntries;
- mutable bool bHasNonInteger; // initialized in GetNumEntries
- mutable sal_Unicode cDecSeparator; // initialized in GetNumEntries
public:
ScDPNumGroupDimension();
@@ -142,8 +140,6 @@ public:
ScDPNumGroupDimension& operator=( const ScDPNumGroupDimension& rOther );
const ScDPNumGroupInfo& GetInfo() const { return aGroupInfo; }
- bool HasNonInteger() const { return bHasNonInteger; }
- sal_Unicode GetDecSeparator() const { return cDecSeparator; }
const ScDPDateGroupHelper* GetDateHelper() const { return pDateHelper; }
@@ -174,8 +170,7 @@ class ScDPGroupTableData : public ScDPTableData
virtual long GetSourceDim( long nDim );
bool IsNumGroupDimension( long nDimension ) const;
- void GetNumGroupInfo( long nDimension, ScDPNumGroupInfo& rInfo,
- bool& rNonInteger, sal_Unicode& rDecimal );
+ void GetNumGroupInfo(long nDimension, ScDPNumGroupInfo& rInfo);
void ModifyFilterCriteria(::std::vector<ScDPCacheTable::Criterion>& rCriteria);
diff --git a/sc/inc/dpitemdata.hxx b/sc/inc/dpitemdata.hxx
index 00b7cd4d6650..926ce7a986d8 100644
--- a/sc/inc/dpitemdata.hxx
+++ b/sc/inc/dpitemdata.hxx
@@ -49,7 +49,7 @@ class SC_DLLPUBLIC ScDPItemData
friend class ScDPCache;
public:
- enum Type { GroupValue = 0, Value = 1, String = 2, Error = 3, Empty = 4 };
+ enum Type { GroupValue = 0, RangeStart, Value, String, Error, Empty };
static const sal_Int32 DateFirst;
static const sal_Int32 DateLast;
@@ -70,6 +70,8 @@ private:
Type meType;
+ void DisposeString();
+
public:
// case insensitive equality
static sal_Int32 Compare(const ScDPItemData& rA, const ScDPItemData& rB);
@@ -84,6 +86,9 @@ public:
Type GetType() const;
void SetString(const rtl::OUString& rS);
void SetValue(double fVal);
+ void SetRangeStart(double fVal);
+ void SetRangeFirst();
+ void SetRangeLast();
void SetGroupValue(sal_Int32 nGroupType, sal_Int32 nValue);
void SetErrorString(const rtl::OUString& rS);
bool IsCaseInsEqual(const ScDPItemData& r) const;
diff --git a/sc/inc/dpnumgroupinfo.hxx b/sc/inc/dpnumgroupinfo.hxx
index 1d5d05d066c6..2e0196d5deaf 100644
--- a/sc/inc/dpnumgroupinfo.hxx
+++ b/sc/inc/dpnumgroupinfo.hxx
@@ -37,11 +37,13 @@ struct ScDPNumGroupInfo
bool mbDateValues:1;
bool mbAutoStart:1;
bool mbAutoEnd:1;
+ bool mbIntegerOnly:1;
double mfStart;
double mfEnd;
double mfStep;
SC_DLLPUBLIC ScDPNumGroupInfo();
+ ScDPNumGroupInfo(const ScDPNumGroupInfo& r);
};
#endif
diff --git a/sc/inc/dptablecache.hxx b/sc/inc/dptablecache.hxx
index cb2b9dfa8c58..b87713028543 100644
--- a/sc/inc/dptablecache.hxx
+++ b/sc/inc/dptablecache.hxx
@@ -30,6 +30,7 @@
#define SC_DPTABLECACHE_HXX
#include "global.hxx"
+#include "dpnumgroupinfo.hxx"
#include <svl/zforlist.hxx>
@@ -63,8 +64,7 @@ public:
struct GroupItems : boost::noncopyable
{
DataListType maItems;
- double mfStart;
- double mfEnd;
+ ScDPNumGroupInfo maInfo;
GroupItems();
GroupItems(const ScDPNumGroupInfo& rInfo);
diff --git a/sc/inc/dputil.hxx b/sc/inc/dputil.hxx
index 0aff4b273b2e..68414f3a45bf 100644
--- a/sc/inc/dputil.hxx
+++ b/sc/inc/dputil.hxx
@@ -33,6 +33,7 @@
#include "scdllapi.h"
class SvNumberFormatter;
+struct ScDPNumGroupInfo;
class ScDPUtil
{
@@ -46,6 +47,11 @@ public:
static rtl::OUString getDateGroupName(
sal_Int32 nDatePart, sal_Int32 nValue, SvNumberFormatter* pFormatter,
double fStart, double fEnd);
+
+ static double getNumGroupStartValue(double fValue, const ScDPNumGroupInfo& rInfo);
+
+ static rtl::OUString getNumGroupName(
+ double fValue, const ScDPNumGroupInfo& rInfo, sal_Unicode cDecSep, SvNumberFormatter* pFormatter);
};
#endif
diff --git a/sc/source/core/data/dpgroup.cxx b/sc/source/core/data/dpgroup.cxx
index 2e986ce8f572..2d175dae8e0e 100644
--- a/sc/source/core/data/dpgroup.cxx
+++ b/sc/source/core/data/dpgroup.cxx
@@ -151,127 +151,11 @@ void lcl_Insert( SCCOL nSourceDim, const ScDPCache* pCache , std::vector< SCROW
vIdx.insert( vIdx.begin()+nIndex, nNew );
}
-void lcl_AppendDateStr( rtl::OUStringBuffer& rBuffer, double fValue, SvNumberFormatter* pFormatter )
-{
- sal_uLong nFormat = pFormatter->GetStandardFormat( NUMBERFORMAT_DATE, ScGlobal::eLnge );
- String aString;
- pFormatter->GetInputLineString( fValue, nFormat, aString );
- rBuffer.append( aString );
-}
-
-String lcl_GetNumGroupName( double fStartValue, const ScDPNumGroupInfo& rInfo,
- bool bHasNonInteger, sal_Unicode cDecSeparator, SvNumberFormatter* pFormatter )
-{
- OSL_ENSURE( cDecSeparator != 0, "cDecSeparator not initialized" );
-
- double fStep = rInfo.mfStep;
- double fEndValue = fStartValue + fStep;
- if ( !bHasNonInteger && ( rInfo.mbDateValues || !rtl::math::approxEqual( fEndValue, rInfo.mfEnd ) ) )
- {
- // The second number of the group label is
- // (first number + size - 1) if there are only integer numbers,
- // (first number + size) if any non-integer numbers are involved.
- // Exception: The last group (containing the end value) is always
- // shown as including the end value (but not for dates).
-
- fEndValue -= 1.0;
- }
-
- if ( fEndValue > rInfo.mfEnd && !rInfo.mbAutoEnd )
- {
- // limit the last group to the end value
-
- fEndValue = rInfo.mfEnd;
- }
-
- rtl::OUStringBuffer aBuffer;
- if ( rInfo.mbDateValues )
- {
- lcl_AppendDateStr( aBuffer, fStartValue, pFormatter );
- aBuffer.appendAscii( " - " ); // with spaces
- lcl_AppendDateStr( aBuffer, fEndValue, pFormatter );
- }
- else
- {
- rtl::math::doubleToUStringBuffer( aBuffer, fStartValue, rtl_math_StringFormat_Automatic,
- rtl_math_DecimalPlaces_Max, cDecSeparator, true );
- aBuffer.append( (sal_Unicode) '-' );
- rtl::math::doubleToUStringBuffer( aBuffer, fEndValue, rtl_math_StringFormat_Automatic,
- rtl_math_DecimalPlaces_Max, cDecSeparator, true );
- }
-
- return aBuffer.makeStringAndClear();
-}
-
-String lcl_GetSpecialNumGroupName( double fValue, bool bFirst, sal_Unicode cDecSeparator,
- bool bDateValues, SvNumberFormatter* pFormatter )
-{
- OSL_ENSURE( cDecSeparator != 0, "cDecSeparator not initialized" );
-
- rtl::OUStringBuffer aBuffer;
- aBuffer.append((sal_Unicode)( bFirst ? '<' : '>' ));
- if ( bDateValues )
- lcl_AppendDateStr( aBuffer, fValue, pFormatter );
- else
- rtl::math::doubleToUStringBuffer( aBuffer, fValue, rtl_math_StringFormat_Automatic,
- rtl_math_DecimalPlaces_Max, cDecSeparator, true );
- return aBuffer.makeStringAndClear();
-}
-
inline bool IsInteger( double fValue )
{
return rtl::math::approxEqual( fValue, rtl::math::approxFloor(fValue) );
}
-String lcl_GetNumGroupForValue( double fValue, const ScDPNumGroupInfo& rInfo, bool bHasNonInteger,
- sal_Unicode cDecSeparator, double& rGroupValue, ScDocument* pDoc )
-{
- SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
-
- if ( fValue < rInfo.mfStart && !rtl::math::approxEqual( fValue, rInfo.mfStart ) )
- {
- rGroupValue = rInfo.mfStart - rInfo.mfStep;
- return lcl_GetSpecialNumGroupName( rInfo.mfStart, true, cDecSeparator, rInfo.mbDateValues, pFormatter );
- }
-
- if ( fValue > rInfo.mfEnd && !rtl::math::approxEqual( fValue, rInfo.mfEnd ) )
- {
- rGroupValue = rInfo.mfEnd + rInfo.mfStep;
- return lcl_GetSpecialNumGroupName( rInfo.mfEnd, false, cDecSeparator, rInfo.mbDateValues, pFormatter );
- }
-
- double fDiff = fValue - rInfo.mfStart;
- double fDiv = rtl::math::approxFloor( fDiff / rInfo.mfStep );
- double fGroupStart = rInfo.mfStart + fDiv * rInfo.mfStep;
-
- if ( rtl::math::approxEqual( fGroupStart, rInfo.mfEnd ) &&
- !rtl::math::approxEqual( fGroupStart, rInfo.mfStart ) )
- {
- if ( !rInfo.mbDateValues )
- {
- // A group that would consist only of the end value is not created,
- // instead the value is included in the last group before. So the
- // previous group is used if the calculated group start value is the
- // selected end value.
-
- fDiv -= 1.0;
- fGroupStart = rInfo.mfStart + fDiv * rInfo.mfStep;
- }
- else
- {
- // For date values, the end value is instead treated as above the limit
- // if it would be a group of its own.
-
- rGroupValue = rInfo.mfEnd + rInfo.mfStep;
- return lcl_GetSpecialNumGroupName( rInfo.mfEnd, false, cDecSeparator, rInfo.mbDateValues, pFormatter );
- }
- }
-
- rGroupValue = fGroupStart;
-
- return lcl_GetNumGroupName( fGroupStart, rInfo, bHasNonInteger, cDecSeparator, pFormatter );
-}
-
}
class ScDPGroupDateFilter : public ScDPCacheTable::FilterBase
@@ -301,8 +185,8 @@ ScDPGroupDateFilter::ScDPGroupDateFilter(double fMatchValue, sal_Int32 nDatePart
mfMatchValue(fMatchValue),
mnDatePart(nDatePart)
{
-
}
+
bool ScDPGroupDateFilter::match( const ScDPItemData & rCellData ) const
{
using namespace ::com::sun::star::sheet;
@@ -783,25 +667,14 @@ void ScDPGroupDimension::DisposeData()
// -----------------------------------------------------------------------
ScDPNumGroupDimension::ScDPNumGroupDimension() :
- pDateHelper( NULL ),
- bHasNonInteger( false ),
- cDecSeparator( 0 )
-{
-}
+ pDateHelper(NULL) {}
ScDPNumGroupDimension::ScDPNumGroupDimension( const ScDPNumGroupInfo& rInfo ) :
- aGroupInfo( rInfo ),
- pDateHelper( NULL ),
- bHasNonInteger( false ),
- cDecSeparator( 0 )
-{
-}
+ aGroupInfo(rInfo), pDateHelper(NULL) {}
ScDPNumGroupDimension::ScDPNumGroupDimension( const ScDPNumGroupDimension& rOther ) :
aGroupInfo( rOther.aGroupInfo ),
- pDateHelper( NULL ),
- bHasNonInteger( false ),
- cDecSeparator( 0 )
+ pDateHelper(NULL)
{
if ( rOther.pDateHelper )
pDateHelper = new ScDPDateGroupHelper( *rOther.pDateHelper );
@@ -817,13 +690,12 @@ ScDPNumGroupDimension& ScDPNumGroupDimension::operator=( const ScDPNumGroupDimen
else
pDateHelper = NULL;
- bHasNonInteger = false;
return *this;
}
void ScDPNumGroupDimension::DisposeData()
{
- bHasNonInteger = false;
+ aGroupInfo = ScDPNumGroupInfo();
maMemberEntries.clear();
}
@@ -860,12 +732,11 @@ const std::vector<SCROW>& ScDPNumGroupDimension::GetNumEntries(
// (this in ensured by calling ScDPLevel::GetMembersObject for all column/row/page
// dimensions before iterating over the values).
- cDecSeparator = ScGlobal::pLocaleData->getNumDecimalSep().GetChar(0);
-
// non-integer GroupInfo values count, too
- bHasNonInteger = ( !aGroupInfo.mbAutoStart && !IsInteger( aGroupInfo.mfStart ) ) ||
+ bool bHasNonInteger = ( !aGroupInfo.mbAutoStart && !IsInteger( aGroupInfo.mfStart ) ) ||
( !aGroupInfo.mbAutoEnd && !IsInteger( aGroupInfo.mfEnd ) ) ||
!IsInteger( aGroupInfo.mfStep );
+ aGroupInfo.mbIntegerOnly = !bHasNonInteger;
double fSourceMin = 0.0;
double fSourceMax = 0.0;
bool bFirst = true;
@@ -889,18 +760,18 @@ const std::vector<SCROW>& ScDPNumGroupDimension::GetNumEntries(
if (fSourceValue > fSourceMax)
fSourceMax = fSourceValue;
- if (!bHasNonInteger && !IsInteger(fSourceValue))
+ if (aGroupInfo.mbIntegerOnly && !IsInteger(fSourceValue))
{
// if any non-integer numbers are involved, the group labels are
// shown including their upper limit
- bHasNonInteger = true;
+ aGroupInfo.mbIntegerOnly = false;
}
}
if (aGroupInfo.mbDateValues)
{
// special handling for dates: always integer, round down limits
- bHasNonInteger = false;
+ aGroupInfo.mbIntegerOnly = true;
fSourceMin = rtl::math::approxFloor( fSourceMin );
fSourceMax = rtl::math::approxFloor( fSourceMax ) + 1;
}
@@ -924,13 +795,11 @@ const std::vector<SCROW>& ScDPNumGroupDimension::GetNumEntries(
// The first group has to be created nonetheless. GetNumGroupForValue has corresponding logic.
bool bFirstGroup = true;
- SvNumberFormatter* pFormatter = pCache->GetDoc()->GetFormatTable();
while (bFirstGroup || (fLoop < aGroupInfo.mfEnd && !rtl::math::approxEqual(fLoop, aGroupInfo.mfEnd)))
{
- rtl::OUString aName = lcl_GetNumGroupName(
- fLoop, aGroupInfo, bHasNonInteger, cDecSeparator, pFormatter);
- // TODO: create a numerical entry to ensure proper sorting
- SCROW nId = pCache->SetGroupItem(nSourceDim, ScDPItemData(aName));
+ ScDPItemData aItem;
+ aItem.SetRangeStart(fLoop);
+ SCROW nId = pCache->SetGroupItem(nSourceDim, aItem);
maMemberEntries.push_back(nId);
++nLoopCount;
fLoop = aGroupInfo.mfStart + nLoopCount * aGroupInfo.mfStep;
@@ -939,14 +808,13 @@ const std::vector<SCROW>& ScDPNumGroupDimension::GetNumEntries(
// ScDPItemData values are compared with approxEqual
}
- rtl::OUString aFirstName = lcl_GetSpecialNumGroupName(
- aGroupInfo.mfStart, true, cDecSeparator, aGroupInfo.mbDateValues, pFormatter);
- SCROW nId = pCache->SetGroupItem(nSourceDim, ScDPItemData(aFirstName));
+ ScDPItemData aItem;
+ aItem.SetRangeFirst();
+ SCROW nId = pCache->SetGroupItem(nSourceDim, aItem);
maMemberEntries.push_back(nId);
- rtl::OUString aLastName = lcl_GetSpecialNumGroupName(
- aGroupInfo.mfEnd, false, cDecSeparator, aGroupInfo.mbDateValues, pFormatter);
- nId = pCache->SetGroupItem(nSourceDim, ScDPItemData(aLastName));
+ aItem.SetRangeLast();
+ nId = pCache->SetGroupItem(nSourceDim, aItem);
maMemberEntries.push_back(nId);
return maMemberEntries;
@@ -1007,15 +875,10 @@ bool ScDPGroupTableData::IsNumGroupDimension( long nDimension ) const
return ( nDimension < nSourceCount && pNumGroups[nDimension].GetInfo().mbEnable );
}
-void ScDPGroupTableData::GetNumGroupInfo( long nDimension, ScDPNumGroupInfo& rInfo,
- bool& rNonInteger, sal_Unicode& rDecimal )
+void ScDPGroupTableData::GetNumGroupInfo(long nDimension, ScDPNumGroupInfo& rInfo)
{
if ( nDimension < nSourceCount )
- {
- rInfo = pNumGroups[nDimension].GetInfo();
- rNonInteger = pNumGroups[nDimension].HasNonInteger();
- rDecimal = pNumGroups[nDimension].GetDecSeparator();
- }
+ rInfo = pNumGroups[nDimension].GetInfo();
}
long ScDPGroupTableData::GetMembersCount( long nDim )
{
@@ -1311,13 +1174,10 @@ void ScDPGroupTableData::FillGroupValues(SCROW* pItemDataIndex, long nCount, con
if (pData->GetType() == ScDPItemData::Value)
{
ScDPNumGroupInfo aNumInfo;
- bool bHasNonInteger = false;
- sal_Unicode cDecSeparator = 0;
- GetNumGroupInfo( nColumn, aNumInfo, bHasNonInteger, cDecSeparator );
- double fGroupValue;
- rtl::OUString aGroupName = lcl_GetNumGroupForValue(
- pData->GetValue(), aNumInfo, bHasNonInteger, cDecSeparator, fGroupValue, pDoc);
- ScDPItemData aItemData(aGroupName);
+ GetNumGroupInfo(nColumn, aNumInfo);
+ double fGroupValue = ScDPUtil::getNumGroupStartValue(pData->GetValue(), aNumInfo);
+ ScDPItemData aItemData;
+ aItemData.SetRangeStart(fGroupValue);
pItemDataIndex[nDim] = pCache->GetIdByItemData(nSourceDim, aItemData);
}
// else (textual) keep original value
diff --git a/sc/source/core/data/dpitemdata.cxx b/sc/source/core/data/dpitemdata.cxx
index 01538a8ddba8..8f16a335908a 100644
--- a/sc/source/core/data/dpitemdata.cxx
+++ b/sc/source/core/data/dpitemdata.cxx
@@ -33,6 +33,7 @@
#include "cell.hxx"
#include "globstr.hrc"
#include "dptabdat.hxx"
+#include "rtl/math.hxx"
const sal_Int32 ScDPItemData::DateFirst = -1;
const sal_Int32 ScDPItemData::DateLast = 10000;
@@ -60,6 +61,7 @@ sal_Int32 ScDPItemData::Compare(const ScDPItemData& rA, const ScDPItemData& rB)
return rA.maGroupValue.mnGroupType < rB.maGroupValue.mnGroupType ? -1 : 1;
}
case Value:
+ case RangeStart:
{
if (rA.mfValue == rB.mfValue)
return 0;
@@ -88,6 +90,7 @@ ScDPItemData::ScDPItemData(const ScDPItemData& r) :
mpString = new rtl::OUString(*r.mpString);
break;
case Value:
+ case RangeStart:
mfValue = r.mfValue;
break;
case GroupValue:
@@ -100,6 +103,12 @@ ScDPItemData::ScDPItemData(const ScDPItemData& r) :
}
}
+void ScDPItemData::DisposeString()
+{
+ if (meType == String || meType == Error)
+ delete mpString;
+}
+
ScDPItemData::ScDPItemData(const rtl::OUString& rStr) :
mpString(new rtl::OUString(rStr)), meType(String) {}
@@ -115,8 +124,7 @@ ScDPItemData::ScDPItemData(sal_Int32 nGroupType, sal_Int32 nValue) :
ScDPItemData::~ScDPItemData()
{
- if (meType == String)
- delete mpString;
+ DisposeString();
}
ScDPItemData::Type ScDPItemData::GetType() const
@@ -126,25 +134,42 @@ ScDPItemData::Type ScDPItemData::GetType() const
void ScDPItemData::SetString(const rtl::OUString& rS)
{
- if (meType == String)
- delete mpString;
+ DisposeString();
mpString = new rtl::OUString(rS);
meType = String;
}
void ScDPItemData::SetValue(double fVal)
{
- if (meType == String)
- delete mpString;
+ DisposeString();
mfValue = fVal;
meType = Value;
}
-void ScDPItemData::SetGroupValue(sal_Int32 nGroupType, sal_Int32 nValue)
+void ScDPItemData::SetRangeStart(double fVal)
{
- if (meType == String)
- delete mpString;
+ DisposeString();
+ mfValue = fVal;
+ meType = RangeStart;
+}
+
+void ScDPItemData::SetRangeFirst()
+{
+ DisposeString();
+ rtl::math::setInf(&mfValue, true);
+ meType = RangeStart;
+}
+
+void ScDPItemData::SetRangeLast()
+{
+ DisposeString();
+ rtl::math::setInf(&mfValue, false);
+ meType = RangeStart;
+}
+void ScDPItemData::SetGroupValue(sal_Int32 nGroupType, sal_Int32 nValue)
+{
+ DisposeString();
maGroupValue.mnGroupType = nGroupType;
maGroupValue.mnValue = nValue;
meType = GroupValue;
@@ -186,12 +211,17 @@ bool ScDPItemData::operator== (const ScDPItemData& r) const
if (meType != r.meType)
return false;
- if (meType == Value)
- return (r.meType == Value) ? rtl::math::approxEqual(mfValue, r.mfValue) : false;
-
- if (meType == GroupValue)
- return maGroupValue.mnGroupType == r.maGroupValue.mnGroupType &&
- maGroupValue.mnValue == r.maGroupValue.mnValue;
+ switch (meType)
+ {
+ case Value:
+ case RangeStart:
+ return rtl::math::approxEqual(mfValue, r.mfValue);
+ case GroupValue:
+ return maGroupValue.mnGroupType == r.maGroupValue.mnGroupType &&
+ maGroupValue.mnValue == r.maGroupValue.mnValue;
+ default:
+ ;
+ }
// need exact equality until we have a safe case insensitive string hash
return GetString() == r.GetString();
@@ -207,6 +237,7 @@ ScDPItemData& ScDPItemData::operator= (const ScDPItemData& r)
mpString = new rtl::OUString(*r.mpString);
break;
case Value:
+ case RangeStart:
mfValue = r.mfValue;
break;
case GroupValue:
@@ -256,6 +287,8 @@ void ScDPItemData::Dump(const char* msg) const
case Value:
printf("value: %g\n", mfValue);
break;
+ case RangeStart:
+ printf("range start: %g\n", mfValue);
default:
printf("unknown type\n");
}
@@ -283,6 +316,7 @@ rtl::OUString ScDPItemData::GetString() const
case Value:
return rtl::OUString::valueOf(mfValue);
case GroupValue:
+ case RangeStart:
return rtl::OUString::createFromAscii("fail");
case Empty:
default:
@@ -294,7 +328,7 @@ rtl::OUString ScDPItemData::GetString() const
double ScDPItemData::GetValue() const
{
- if (meType == Value)
+ if (meType == Value || meType == RangeStart)
return mfValue;
return 0.0;
diff --git a/sc/source/core/data/dpnumgroupinfo.cxx b/sc/source/core/data/dpnumgroupinfo.cxx
index 6d4e4fa250ce..0b93bf48c2ea 100644
--- a/sc/source/core/data/dpnumgroupinfo.cxx
+++ b/sc/source/core/data/dpnumgroupinfo.cxx
@@ -29,7 +29,20 @@
#include "dpnumgroupinfo.hxx"
ScDPNumGroupInfo::ScDPNumGroupInfo() :
- mbEnable(false), mbDateValues(false), mbAutoStart(false), mbAutoEnd(false),
+ mbEnable(false),
+ mbDateValues(false),
+ mbAutoStart(false),
+ mbAutoEnd(false),
+ mbIntegerOnly(true),
mfStart(0.0), mfEnd(0.0), mfStep(0.0) {}
+ScDPNumGroupInfo::ScDPNumGroupInfo(const ScDPNumGroupInfo& r) :
+ mbEnable(r.mbEnable),
+ mbDateValues(r.mbDateValues),
+ mbAutoStart(r.mbAutoStart),
+ mbAutoEnd(r.mbAutoEnd),
+ mbIntegerOnly(r.mbIntegerOnly),
+ mfStart(r.mfStart),
+ mfEnd(r.mfEnd), mfStep(r.mfStep) {}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/dptablecache.cxx b/sc/source/core/data/dptablecache.cxx
index 78c66cee4523..730114672561 100644
--- a/sc/source/core/data/dptablecache.cxx
+++ b/sc/source/core/data/dptablecache.cxx
@@ -42,6 +42,7 @@
#include <rtl/math.hxx>
#include <unotools/textsearch.hxx>
+#include <unotools/localedatawrapper.hxx>
#include <com/sun/star/sdbc/DataType.hpp>
#include <com/sun/star/sdbc/XRow.hpp>
@@ -221,11 +222,10 @@ ScDPItemData* lcl_GetItemValue(
}
-ScDPCache::GroupItems::GroupItems() :
- mfStart(0.0), mfEnd(0.0) {}
+ScDPCache::GroupItems::GroupItems() {}
ScDPCache::GroupItems::GroupItems(const ScDPNumGroupInfo& rInfo) :
- mfStart(rInfo.mfStart), mfEnd(rInfo.mfEnd) {}
+ maInfo(rInfo) {}
bool ScDPCache::operator== ( const ScDPCache& r ) const
{
@@ -1034,13 +1034,24 @@ rtl::OUString ScDPCache::GetFormattedString(long nDim, const ScDPItemData& rItem
const GroupItems* p = GetGroupItems(nDim);
if (p)
{
- fStart = p->mfStart;
- fEnd = p->mfEnd;
+ fStart = p->maInfo.mfStart;
+ fEnd = p->maInfo.mfEnd;
}
return ScDPUtil::getDateGroupName(
aAttr.mnGroupType, aAttr.mnValue, mpDoc->GetFormatTable(), fStart, fEnd);
}
+ if (eType == ScDPItemData::RangeStart)
+ {
+ double fVal = rItem.GetValue();
+ const GroupItems* p = GetGroupItems(nDim);
+ if (!p)
+ return rItem.GetString();
+
+ sal_Unicode cDecSep = ScGlobal::pLocaleData->getNumDecimalSep().GetChar(0);
+ return ScDPUtil::getNumGroupName(fVal, p->maInfo, cDecSep, mpDoc->GetFormatTable());
+ }
+
return rItem.GetString();
}
@@ -1066,8 +1077,7 @@ void ScDPCache::ResetGroupItems(long nDim, const ScDPNumGroupInfo& rNumInfo)
{
GroupItems& rGI = maGroupFields[nDim];
rGI.maItems.clear();
- rGI.mfStart = rNumInfo.mfStart;
- rGI.mfEnd = rNumInfo.mfEnd;
+ rGI.maInfo = rNumInfo;
}
}
diff --git a/sc/source/core/data/dputil.cxx b/sc/source/core/data/dputil.cxx
index eb816d8ece5d..e12da8c7f32c 100644
--- a/sc/source/core/data/dputil.cxx
+++ b/sc/source/core/data/dputil.cxx
@@ -29,11 +29,13 @@
#include "dputil.hxx"
#include "global.hxx"
#include "dpitemdata.hxx"
+#include "dpnumgroupinfo.hxx"
#include "comphelper/string.hxx"
#include "unotools/localedatawrapper.hxx"
#include "unotools/calendarwrapper.hxx"
#include "svl/zforlist.hxx"
+#include "rtl/math.hxx"
#include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
#include <com/sun/star/i18n/CalendarDisplayIndex.hpp>
@@ -148,4 +150,144 @@ rtl::OUString ScDPUtil::getDateGroupName(
return rtl::OUString::createFromAscii("FIXME: unhandled value");
}
+double ScDPUtil::getNumGroupStartValue(double fValue, const ScDPNumGroupInfo& rInfo)
+{
+ if (fValue < rInfo.mfStart && !rtl::math::approxEqual(fValue, rInfo.mfStart))
+ {
+ rtl::math::setInf(&fValue, true);
+ return fValue;
+ }
+
+ if (fValue > rInfo.mfEnd && !rtl::math::approxEqual(fValue, rInfo.mfEnd))
+ {
+ rtl::math::setInf(&fValue, false);
+ return fValue;
+ }
+
+ double fDiff = fValue - rInfo.mfStart;
+ double fDiv = rtl::math::approxFloor( fDiff / rInfo.mfStep );
+ double fGroupStart = rInfo.mfStart + fDiv * rInfo.mfStep;
+
+ if (rtl::math::approxEqual(fGroupStart, rInfo.mfEnd) &&
+ !rtl::math::approxEqual(fGroupStart, rInfo.mfStart))
+ {
+ if (!rInfo.mbDateValues)
+ {
+ // A group that would consist only of the end value is not
+ // created, instead the value is included in the last group
+ // before. So the previous group is used if the calculated group
+ // start value is the selected end value.
+
+ fDiv -= 1.0;
+ return rInfo.mfStart + fDiv * rInfo.mfStep;
+ }
+
+ // For date values, the end value is instead treated as above the
+ // limit if it would be a group of its own.
+
+ return rInfo.mfEnd + rInfo.mfStep;
+ }
+
+ return fGroupStart;
+}
+
+namespace {
+
+void lcl_AppendDateStr( rtl::OUStringBuffer& rBuffer, double fValue, SvNumberFormatter* pFormatter )
+{
+ sal_uLong nFormat = pFormatter->GetStandardFormat( NUMBERFORMAT_DATE, ScGlobal::eLnge );
+ rtl::OUString aString;
+ pFormatter->GetInputLineString( fValue, nFormat, aString );
+ rBuffer.append( aString );
+}
+
+rtl::OUString lcl_GetSpecialNumGroupName( double fValue, bool bFirst, sal_Unicode cDecSeparator,
+ bool bDateValues, SvNumberFormatter* pFormatter )
+{
+ OSL_ENSURE( cDecSeparator != 0, "cDecSeparator not initialized" );
+
+ rtl::OUStringBuffer aBuffer;
+ aBuffer.append((sal_Unicode)( bFirst ? '<' : '>' ));
+ if ( bDateValues )
+ lcl_AppendDateStr( aBuffer, fValue, pFormatter );
+ else
+ rtl::math::doubleToUStringBuffer( aBuffer, fValue, rtl_math_StringFormat_Automatic,
+ rtl_math_DecimalPlaces_Max, cDecSeparator, true );
+ return aBuffer.makeStringAndClear();
+}
+
+rtl::OUString lcl_GetNumGroupName(
+ double fStartValue, const ScDPNumGroupInfo& rInfo, sal_Unicode cDecSep,
+ SvNumberFormatter* pFormatter)
+{
+ OSL_ENSURE( cDecSep != 0, "cDecSeparator not initialized" );
+
+ double fStep = rInfo.mfStep;
+ double fEndValue = fStartValue + fStep;
+ if (rInfo.mbIntegerOnly && (rInfo.mbDateValues || !rtl::math::approxEqual(fEndValue, rInfo.mfEnd)))
+ {
+ // The second number of the group label is
+ // (first number + size - 1) if there are only integer numbers,
+ // (first number + size) if any non-integer numbers are involved.
+ // Exception: The last group (containing the end value) is always
+ // shown as including the end value (but not for dates).
+
+ fEndValue -= 1.0;
+ }
+
+ if ( fEndValue > rInfo.mfEnd && !rInfo.mbAutoEnd )
+ {
+ // limit the last group to the end value
+
+ fEndValue = rInfo.mfEnd;
+ }
+
+ rtl::OUStringBuffer aBuffer;
+ if ( rInfo.mbDateValues )
+ {
+ lcl_AppendDateStr( aBuffer, fStartValue, pFormatter );
+ aBuffer.appendAscii( " - " ); // with spaces
+ lcl_AppendDateStr( aBuffer, fEndValue, pFormatter );
+ }
+ else
+ {
+ rtl::math::doubleToUStringBuffer( aBuffer, fStartValue, rtl_math_StringFormat_Automatic,
+ rtl_math_DecimalPlaces_Max, cDecSep, true );
+ aBuffer.append( (sal_Unicode) '-' );
+ rtl::math::doubleToUStringBuffer( aBuffer, fEndValue, rtl_math_StringFormat_Automatic,
+ rtl_math_DecimalPlaces_Max, cDecSep, true );
+ }
+
+ return aBuffer.makeStringAndClear();
+}
+
+}
+
+rtl::OUString ScDPUtil::getNumGroupName(
+ double fValue, const ScDPNumGroupInfo& rInfo, sal_Unicode cDecSep, SvNumberFormatter* pFormatter)
+{
+ if ( fValue < rInfo.mfStart && !rtl::math::approxEqual( fValue, rInfo.mfStart ) )
+ return lcl_GetSpecialNumGroupName( rInfo.mfStart, true, cDecSep, rInfo.mbDateValues, pFormatter );
+
+ if ( fValue > rInfo.mfEnd && !rtl::math::approxEqual( fValue, rInfo.mfEnd ) )
+ return lcl_GetSpecialNumGroupName( rInfo.mfEnd, false, cDecSep, rInfo.mbDateValues, pFormatter );
+
+ double fDiff = fValue - rInfo.mfStart;
+ double fDiv = rtl::math::approxFloor( fDiff / rInfo.mfStep );
+ double fGroupStart = rInfo.mfStart + fDiv * rInfo.mfStep;
+
+ if ( rtl::math::approxEqual( fGroupStart, rInfo.mfEnd ) &&
+ !rtl::math::approxEqual( fGroupStart, rInfo.mfStart ) )
+ {
+ if (rInfo.mbDateValues)
+ {
+ // For date values, the end value is instead treated as above the limit
+ // if it would be a group of its own.
+ return lcl_GetSpecialNumGroupName( rInfo.mfEnd, false, cDecSep, rInfo.mbDateValues, pFormatter );
+ }
+ }
+
+ return lcl_GetNumGroupName(fGroupStart, rInfo, cDecSep, pFormatter);
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */