summaryrefslogtreecommitdiffstats
path: root/sc
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@gmail.com>2012-03-09 10:15:52 -0500
committerKohei Yoshida <kohei.yoshida@gmail.com>2012-03-09 11:13:35 -0500
commit0637ca0aefed73b55154c15c8738c100f329a3a8 (patch)
tree551eca27ec05ddb5a6185115126d3c8bd8c9871b /sc
parentAdded hook to create group field data at cache creation time. (diff)
downloadcore-0637ca0aefed73b55154c15c8738c100f329a3a8.tar.gz
core-0637ca0aefed73b55154c15c8738c100f329a3a8.zip
Populate group dimensions directly to the cache.
This is to avoid populating them twice in case the same cache is referenced by multiple pivot tables.
Diffstat (limited to 'sc')
-rw-r--r--sc/inc/dpdimsave.hxx22
-rw-r--r--sc/inc/dpgroup.hxx7
-rw-r--r--sc/inc/dptablecache.hxx9
-rw-r--r--sc/inc/dputil.hxx7
-rw-r--r--sc/source/core/data/dpdimsave.cxx295
-rw-r--r--sc/source/core/data/dpgroup.cxx203
-rw-r--r--sc/source/core/data/dptablecache.cxx76
-rw-r--r--sc/source/core/data/dputil.cxx74
-rw-r--r--sc/source/filter/excel/xepivot.cxx3
9 files changed, 449 insertions, 247 deletions
diff --git a/sc/inc/dpdimsave.hxx b/sc/inc/dpdimsave.hxx
index 6858e8bf0f78..925cb9425918 100644
--- a/sc/inc/dpdimsave.hxx
+++ b/sc/inc/dpdimsave.hxx
@@ -52,13 +52,14 @@ class ScDPSaveGroupDimension;
class SC_DLLPUBLIC ScDPSaveGroupItem
{
rtl::OUString aGroupName; // name of group
- ::std::vector<rtl::OUString> aElements; // names of items in original dimension
+ std::vector<rtl::OUString> aElements; // names of items in original dimension
+ mutable std::vector<ScDPItemData> maItems; // items converted from the strings.
public:
ScDPSaveGroupItem( const rtl::OUString& rName );
~ScDPSaveGroupItem();
- void AddToData( ScDPGroupDimension& rDataDim, SvNumberFormatter* pFormatter ) const;
+ void AddToData(ScDPGroupDimension& rDataDim) const;
void AddElement( const rtl::OUString& rName );
void AddElementsFromGroup( const ScDPSaveGroupItem& rGroup );
@@ -74,6 +75,9 @@ public:
// remove this group's elements from their groups in rDimension
// (rDimension must be a different dimension from the one which contains this)
void RemoveElementsFromGroups( ScDPSaveGroupDimension& rDimension ) const;
+
+ void ConvertElementsToItems(SvNumberFormatter* pFormatter) const;
+ bool HasInGroup(const ScDPItemData& rItem) const;
};
typedef ::std::vector<ScDPSaveGroupItem> ScDPSaveGroupItemVec;
@@ -87,7 +91,7 @@ class SC_DLLPUBLIC ScDPSaveGroupDimension
rtl::OUString aSourceDim; // always the real source from the original data
rtl::OUString aGroupDimName;
ScDPSaveGroupItemVec aGroups;
- ScDPNumGroupInfo aDateInfo;
+ mutable ScDPNumGroupInfo aDateInfo;
sal_Int32 nDatePart;
public:
@@ -96,7 +100,7 @@ public:
~ScDPSaveGroupDimension();
void AddToData( ScDPGroupTableData& rData ) const;
-
+ void AddToCache(ScDPCache& rCache) const;
void SetDateInfo( const ScDPNumGroupInfo& rInfo, sal_Int32 nPart );
void AddGroupItem( const ScDPSaveGroupItem& rItem );
@@ -119,18 +123,21 @@ public:
ScDPSaveGroupItem* GetGroupAccByIndex( long nIndex );
void Rename( const rtl::OUString& rNewName );
+
+private:
+ bool IsInGroup(const ScDPItemData& rItem) const;
};
/**
* Represents a group dimension that introduces a new hierarchy for an
* existing dimension. Unlike the ScDPSaveGroupDimension counterpart, it
- * re-uses the source dimension.
+ * re-uses the source dimension name and ID.
*/
class SC_DLLPUBLIC ScDPSaveNumGroupDimension
{
rtl::OUString aDimensionName;
- ScDPNumGroupInfo aGroupInfo;
- ScDPNumGroupInfo aDateInfo;
+ mutable ScDPNumGroupInfo aGroupInfo;
+ mutable ScDPNumGroupInfo aDateInfo;
sal_Int32 nDatePart;
public:
@@ -139,6 +146,7 @@ public:
~ScDPSaveNumGroupDimension();
void AddToData( ScDPGroupTableData& rData ) const;
+ void AddToCache(ScDPCache& rCache) const;
const rtl::OUString& GetDimensionName() const { return aDimensionName; }
const ScDPNumGroupInfo& GetInfo() const { return aGroupInfo; }
diff --git a/sc/inc/dpgroup.hxx b/sc/inc/dpgroup.hxx
index b90c667b7387..5340b70d392b 100644
--- a/sc/inc/dpgroup.hxx
+++ b/sc/inc/dpgroup.hxx
@@ -60,9 +60,7 @@ public:
sal_Int32 GetDatePart() const { return nDatePart; }
const ScDPNumGroupInfo& GetNumInfo() const { return aNumInfo; }
- void FillColumnEntries(
- SCCOL nSourceDim, ScDPCache* pCahe , std::vector<SCROW>& rEntries,
- const std::vector<SCROW>& rOriginal) const;
+ void FillColumnEntries(const ScDPCache* pCache, std::vector<SCROW>& rEntries) const;
};
typedef ::std::vector<ScDPItemData> ScDPItemDataVec;
@@ -143,8 +141,7 @@ public:
const ScDPDateGroupHelper* GetDateHelper() const { return pDateHelper; }
- const std::vector<SCROW>& GetNumEntries(
- SCCOL nSourceDim, ScDPCache* pCache, const std::vector<SCROW>& rOriginal) const;
+ const std::vector<SCROW>& GetNumEntries(SCCOL nSourceDim, const ScDPCache* pCache) const;
void MakeDateHelper( const ScDPNumGroupInfo& rInfo, long nDim, sal_Int32 nPart );
diff --git a/sc/inc/dptablecache.hxx b/sc/inc/dptablecache.hxx
index b87713028543..8a322843dd92 100644
--- a/sc/inc/dptablecache.hxx
+++ b/sc/inc/dptablecache.hxx
@@ -131,15 +131,16 @@ public:
SCROW GetIdByItemData(long nDim, const rtl::OUString& sItemData) const;
SCROW GetIdByItemData(long nDim, const ScDPItemData& rItem) const;
rtl::OUString GetFormattedString(long nDim, const ScDPItemData& rItem) const;
- void AppendGroupField();
+ long AppendGroupField();
void ResetGroupItems(long nDim, const ScDPNumGroupInfo& rNumInfo);
SCROW SetGroupItem(long nDim, const ScDPItemData& rData);
+ const DataListType* GetGroupDimMemberValues(long nDim) const;
+ void GetGroupDimMemberIds(long nDim, std::vector<SCROW>& rIds) const;
void ClearGroupFields();
SCROW GetAdditionalItemID( const ScDPItemData& rData ) const;
SCCOL GetDimensionIndex(const rtl::OUString& sName) const;
- sal_uLong GetNumType ( sal_uLong nFormat ) const;
sal_uLong GetNumberFormat( long nDim ) const;
bool IsDateDimension( long nDim ) const ;
SCROW GetDimMemberCount( SCCOL nDim ) const;
@@ -151,12 +152,12 @@ public:
SCROW GetRowCount() const;
SCROW GetItemDataId( sal_uInt16 nDim, SCROW nRow, bool bRepeatIfEmpty ) const;
- rtl::OUString GetDimensionName( sal_uInt16 nColumn ) const;
+ rtl::OUString GetDimensionName(long nDim) const;
bool IsRowEmpty( SCROW nRow ) const;
bool IsValid() const;
bool ValidQuery(SCROW nRow, const ScQueryParam& rQueryParam) const;
- ScDocument* GetDoc() const;//ms-cache-core
+ ScDocument* GetDoc() const;
long GetColumnCount() const;
long GetGroupFieldCount() const;
diff --git a/sc/inc/dputil.hxx b/sc/inc/dputil.hxx
index 68414f3a45bf..4ed4e5c679ea 100644
--- a/sc/inc/dputil.hxx
+++ b/sc/inc/dputil.hxx
@@ -51,7 +51,12 @@ public:
static double getNumGroupStartValue(double fValue, const ScDPNumGroupInfo& rInfo);
static rtl::OUString getNumGroupName(
- double fValue, const ScDPNumGroupInfo& rInfo, sal_Unicode cDecSep, SvNumberFormatter* pFormatter);
+ double fValue, const ScDPNumGroupInfo& rInfo, sal_Unicode cDecSep,
+ SvNumberFormatter* pFormatter);
+
+ static sal_Int32 getDatePartValue(
+ double fValue, const ScDPNumGroupInfo& rInfo, sal_Int32 nDatePart,
+ SvNumberFormatter* pFormatter);
};
#endif
diff --git a/sc/source/core/data/dpdimsave.cxx b/sc/source/core/data/dpdimsave.cxx
index 34e87d5ee9c9..234f6676af1f 100644
--- a/sc/source/core/data/dpdimsave.cxx
+++ b/sc/source/core/data/dpdimsave.cxx
@@ -30,6 +30,7 @@
#include "dpdimsave.hxx"
#include "dpgroup.hxx"
#include "dpobject.hxx"
+#include "dputil.hxx"
#include "document.hxx"
#include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
@@ -38,6 +39,8 @@
#include <rtl/math.hxx>
#include <algorithm>
+using namespace com::sun::star;
+
#include <stdio.h>
#include <string>
#include <sys/time.h>
@@ -142,25 +145,37 @@ void ScDPSaveGroupItem::RemoveElementsFromGroups( ScDPSaveGroupDimension& rDimen
rDimension.RemoveFromGroups( *aIter );
}
-void ScDPSaveGroupItem::AddToData( ScDPGroupDimension& rDataDim, SvNumberFormatter* pFormatter ) const
+void ScDPSaveGroupItem::ConvertElementsToItems(SvNumberFormatter* pFormatter) const
{
- ScDPGroupItem aGroup(aGroupName);
- ScDPItemData aData;
-
- for ( std::vector<rtl::OUString>::const_iterator aIter(aElements.begin()); aIter != aElements.end(); aIter++ )
+ maItems.reserve(aElements.size());
+ std::vector<rtl::OUString>::const_iterator it = aElements.begin(), itEnd = aElements.end();
+ for (; it != itEnd; ++it)
{
- sal_uInt32 nFormat = 0; //! ...
+ sal_uInt32 nFormat = 0;
double fValue;
- if ( pFormatter->IsNumberFormat( *aIter, nFormat, fValue ) )
+ ScDPItemData aData;
+ if (pFormatter->IsNumberFormat(*it, nFormat, fValue))
aData.SetValue(fValue);
else
- aData.SetString( *aIter );
+ aData.SetString(*it);
- aGroup.AddElement( aData );
- //! for numeric data, look at source members?
+ maItems.push_back(aData);
}
+}
+
+bool ScDPSaveGroupItem::HasInGroup(const ScDPItemData& rItem) const
+{
+ return std::find(maItems.begin(), maItems.end(), rItem) != maItems.end();
+}
+
+void ScDPSaveGroupItem::AddToData(ScDPGroupDimension& rDataDim) const
+{
+ ScDPGroupItem aGroup(aGroupName);
+ std::vector<ScDPItemData>::const_iterator it = maItems.begin(), itEnd = maItems.end();
+ for (; it != itEnd; ++it)
+ aGroup.AddElement(*it);
- rDataDim.AddItem( aGroup );
+ rDataDim.AddItem(aGroup);
}
// ============================================================================
@@ -303,6 +318,99 @@ void ScDPSaveGroupDimension::Rename( const rtl::OUString& rNewName )
aGroupDimName = rNewName;
}
+bool ScDPSaveGroupDimension::IsInGroup(const ScDPItemData& rItem) const
+{
+ ScDPSaveGroupItemVec::const_iterator it = aGroups.begin(), itEnd = aGroups.end();
+ for (; it != itEnd; ++it)
+ {
+ if (it->HasInGroup(rItem))
+ return true;
+ }
+ return false;
+}
+
+namespace {
+
+inline bool isInteger(double fValue)
+{
+ return rtl::math::approxEqual(fValue, rtl::math::approxFloor(fValue));
+}
+
+void fillDateGroupDimension(
+ ScDPCache& rCache, ScDPNumGroupInfo& rDateInfo, long nSourceDim, long nGroupDim,
+ sal_Int32 nDatePart, SvNumberFormatter* pFormatter)
+{
+ // Auto min/max is only used for "Years" part, but the loop is always
+ // needed.
+ double fSourceMin = 0.0;
+ double fSourceMax = 0.0;
+ bool bFirst = true;
+
+ const ScDPCache::DataListType& rItems = rCache.GetDimMemberValues(nSourceDim);
+ ScDPCache::DataListType::const_iterator it = rItems.begin(), itEnd = rItems.end();
+ for (; it != itEnd; ++it)
+ {
+ const ScDPItemData& rItem = *it;
+ if (rItem.GetType() != ScDPItemData::Value)
+ continue;
+
+ double fVal = rItem.GetValue();
+ if (bFirst)
+ {
+ fSourceMin = fSourceMax = fVal;
+ bFirst = false;
+ }
+ else
+ {
+ if (fVal < fSourceMin)
+ fSourceMin = fVal;
+ if ( fVal > fSourceMax )
+ fSourceMax = fVal;
+ }
+ }
+
+ // For the start/end values, use the same date rounding as in
+ // ScDPNumGroupDimension::GetNumEntries (but not for the list of
+ // available years).
+ if (rDateInfo.mbAutoStart)
+ rDateInfo.mfStart = rtl::math::approxFloor(fSourceMin);
+ if (rDateInfo.mbAutoEnd)
+ rDateInfo.mfEnd = rtl::math::approxFloor(fSourceMax) + 1;
+
+ //! if not automatic, limit fSourceMin/fSourceMax for list of year values?
+
+ long nStart = 0, nEnd = 0; // end is inclusive
+
+ switch (nDatePart)
+ {
+ case sheet::DataPilotFieldGroupBy::YEARS:
+ nStart = ScDPUtil::getDatePartValue(
+ fSourceMin, rDateInfo, sheet::DataPilotFieldGroupBy::YEARS, pFormatter);
+ nEnd = ScDPUtil::getDatePartValue(fSourceMax, rDateInfo, sheet::DataPilotFieldGroupBy::YEARS, pFormatter);
+ break;
+ case sheet::DataPilotFieldGroupBy::QUARTERS: nStart = 1; nEnd = 4; break;
+ case sheet::DataPilotFieldGroupBy::MONTHS: nStart = 1; nEnd = 12; break;
+ case sheet::DataPilotFieldGroupBy::DAYS: nStart = 1; nEnd = 366; break;
+ case sheet::DataPilotFieldGroupBy::HOURS: nStart = 0; nEnd = 23; break;
+ case sheet::DataPilotFieldGroupBy::MINUTES: nStart = 0; nEnd = 59; break;
+ case sheet::DataPilotFieldGroupBy::SECONDS: nStart = 0; nEnd = 59; break;
+ default:
+ OSL_FAIL("invalid date part");
+ }
+
+ // Now, populate the group items in the cache.
+ rCache.ResetGroupItems(nGroupDim, rDateInfo);
+
+ for (sal_Int32 nValue = nStart; nValue <= nEnd; ++nValue)
+ rCache.SetGroupItem(nGroupDim, ScDPItemData(nDatePart, nValue));
+
+ // add first/last entry (min/max)
+ rCache.SetGroupItem(nGroupDim, ScDPItemData(nDatePart, ScDPItemData::DateFirst));
+ rCache.SetGroupItem(nGroupDim, ScDPItemData(nDatePart, ScDPItemData::DateLast));
+}
+
+}
+
void ScDPSaveGroupDimension::AddToData( ScDPGroupTableData& rData ) const
{
long nSourceIndex = rData.GetDimensionIndex( aSourceDim );
@@ -319,16 +427,51 @@ void ScDPSaveGroupDimension::AddToData( ScDPGroupTableData& rData ) const
{
// normal (manual) grouping
- SvNumberFormatter* pFormatter = rData.GetDocument()->GetFormatTable();
-
- for ( ScDPSaveGroupItemVec::const_iterator aIter(aGroups.begin()); aIter != aGroups.end(); aIter++ )
- aIter->AddToData( aDim, pFormatter );
+ for (ScDPSaveGroupItemVec::const_iterator aIter(aGroups.begin()); aIter != aGroups.end(); ++aIter)
+ aIter->AddToData(aDim);
}
rData.AddGroupDimension( aDim );
}
}
+void ScDPSaveGroupDimension::AddToCache(ScDPCache& rCache) const
+{
+ long nDim = rCache.AppendGroupField();
+ SvNumberFormatter* pFormatter = rCache.GetDoc()->GetFormatTable();
+
+ if (nDatePart)
+ {
+ long nSourceDim = rCache.GetDimensionIndex(aSourceDim);
+ fillDateGroupDimension(rCache, aDateInfo, nSourceDim, nDim, nDatePart, pFormatter);
+ return;
+ }
+
+ rCache.ResetGroupItems(nDim, aDateInfo);
+ {
+ ScDPSaveGroupItemVec::const_iterator it = aGroups.begin(), itEnd = aGroups.end();
+ for (; it != itEnd; ++it)
+ {
+ const ScDPSaveGroupItem& rGI = *it;
+ rGI.ConvertElementsToItems(pFormatter);
+ rCache.SetGroupItem(nDim, ScDPItemData(rGI.GetGroupName()));
+ }
+ }
+
+ long nSourceDim = rCache.GetDimensionIndex(aSourceDim);
+ const ScDPCache::DataListType& rItems = rCache.GetDimMemberValues(nSourceDim);
+ {
+ ScDPCache::DataListType::const_iterator it = rItems.begin(), itEnd = rItems.end();
+ for (; it != itEnd; ++it)
+ {
+ const ScDPItemData& rItem = *it;
+ if (!IsInGroup(rItem))
+ // Not in any group. Add as its own group.
+ rCache.SetGroupItem(nDim, rItem);
+ }
+ }
+}
+
// ============================================================================
ScDPSaveNumGroupDimension::ScDPSaveNumGroupDimension( const rtl::OUString& rName, const ScDPNumGroupInfo& rInfo ) :
@@ -362,6 +505,109 @@ void ScDPSaveNumGroupDimension::AddToData( ScDPGroupTableData& rData ) const
}
}
+void ScDPSaveNumGroupDimension::AddToCache(ScDPCache& rCache) const
+{
+ long nDim = rCache.GetDimensionIndex(aDimensionName);
+ if (aGroupInfo.mbEnable)
+ {
+ // Number-range grouping
+
+ // Look through the source entries for non-integer numbers, minimum
+ // and maximum.
+
+ // non-integer GroupInfo values count, too
+ aGroupInfo.mbIntegerOnly =
+ (aGroupInfo.mbAutoStart || isInteger(aGroupInfo.mfStart)) &&
+ (aGroupInfo.mbAutoEnd || isInteger(aGroupInfo.mfEnd)) &&
+ isInteger(aGroupInfo.mfStep);
+
+ double fSourceMin = 0.0;
+ double fSourceMax = 0.0;
+ bool bFirst = true;
+
+ const ScDPCache::DataListType& rItems = rCache.GetDimMemberValues(nDim);
+ ScDPCache::DataListType::const_iterator it = rItems.begin(), itEnd = rItems.end();
+ for (; it != itEnd; ++it)
+ {
+ const ScDPItemData& rItem = *it;
+ if (rItem.GetType() != ScDPItemData::Value)
+ continue;
+
+ double fValue = rItem.GetValue();
+ if (bFirst)
+ {
+ fSourceMin = fSourceMax = fValue;
+ bFirst = false;
+ continue;
+ }
+
+ if (fValue < fSourceMin)
+ fSourceMin = fValue;
+ if (fValue > fSourceMax)
+ fSourceMax = fValue;
+
+ if (aGroupInfo.mbIntegerOnly && !isInteger(fValue))
+ {
+ // If any non-integer numbers are involved, the group labels
+ // are shown including their upper limit.
+ aGroupInfo.mbIntegerOnly = false;
+ }
+ }
+
+ if (aGroupInfo.mbDateValues)
+ {
+ // special handling for dates: always integer, round down limits
+ aGroupInfo.mbIntegerOnly = true;
+ fSourceMin = rtl::math::approxFloor(fSourceMin);
+ fSourceMax = rtl::math::approxFloor(fSourceMax) + 1;
+ }
+
+ if (aGroupInfo.mbAutoStart)
+ aGroupInfo.mfStart = fSourceMin;
+ if (aGroupInfo.mbAutoEnd)
+ aGroupInfo.mfEnd = fSourceMax;
+
+ //! limit number of entries?
+
+ long nLoopCount = 0;
+ double fLoop = aGroupInfo.mfStart;
+
+ rCache.ResetGroupItems(nDim, aGroupInfo);
+
+ // Use "less than" instead of "less or equal" for the loop - don't
+ // create a group that consists only of the end value. Instead, the
+ // end value is then included in the last group (last group is bigger
+ // than the others). The first group has to be created nonetheless.
+ // GetNumGroupForValue has corresponding logic.
+
+ bool bFirstGroup = true;
+ while (bFirstGroup || (fLoop < aGroupInfo.mfEnd && !rtl::math::approxEqual(fLoop, aGroupInfo.mfEnd)))
+ {
+ ScDPItemData aItem;
+ aItem.SetRangeStart(fLoop);
+ rCache.SetGroupItem(nDim, aItem);
+ ++nLoopCount;
+ fLoop = aGroupInfo.mfStart + nLoopCount * aGroupInfo.mfStep;
+ bFirstGroup = false;
+
+ // ScDPItemData values are compared with approxEqual
+ }
+
+ ScDPItemData aItem;
+ aItem.SetRangeFirst();
+ rCache.SetGroupItem(nDim, aItem);
+
+ aItem.SetRangeLast();
+ rCache.SetGroupItem(nDim, aItem);
+ }
+ else if (aDateInfo.mbEnable)
+ {
+ // Date grouping
+ SvNumberFormatter* pFormatter = rCache.GetDoc()->GetFormatTable();
+ fillDateGroupDimension(rCache, aDateInfo, nDim, nDim, nDatePart, pFormatter);
+ }
+}
+
void ScDPSaveNumGroupDimension::SetGroupInfo( const ScDPNumGroupInfo& rNew )
{
aGroupInfo = rNew;
@@ -468,8 +714,27 @@ void ScDPDimensionSaveData::WriteToData( ScDPGroupTableData& rData ) const
aIt->second.AddToData( rData );
}
+namespace {
+
+class AddGroupDimToCache : std::unary_function<ScDPSaveGroupDimension, void>
+{
+ ScDPCache& mrCache;
+public:
+ AddGroupDimToCache(ScDPCache& rCache) : mrCache(rCache) {}
+ void operator() (const ScDPSaveGroupDimension& rDim)
+ {
+ rDim.AddToCache(mrCache);
+ }
+};
+
+}
+
void ScDPDimensionSaveData::WriteToCache(ScDPCache& rCache) const
{
+ std::for_each(maGroupDims.begin(), maGroupDims.end(), AddGroupDimToCache(rCache));
+ ScDPSaveNumGroupDimMap::const_iterator it = maNumGroupDims.begin(), itEnd = maNumGroupDims.end();
+ for (; it != itEnd; ++it)
+ it->second.AddToCache(rCache);
}
const ScDPSaveGroupDimension* ScDPDimensionSaveData::GetGroupDimForBase( const rtl::OUString& rBaseDimName ) const
diff --git a/sc/source/core/data/dpgroup.cxx b/sc/source/core/data/dpgroup.cxx
index ffe04309fc20..93c5cbb84a61 100644
--- a/sc/source/core/data/dpgroup.cxx
+++ b/sc/source/core/data/dpgroup.cxx
@@ -384,79 +384,9 @@ void ScDPDateGroupHelper::SetGroupDim(long nDim)
mnGroupDim = nDim;
}
-void ScDPDateGroupHelper::FillColumnEntries(
- SCCOL nSourceDim, ScDPCache* pCache, std::vector<SCROW>& rEntries, const std::vector<SCROW>& rOriginal) const
+void ScDPDateGroupHelper::FillColumnEntries(const ScDPCache* pCache, std::vector<SCROW>& rEntries) const
{
- // auto min/max is only used for "Years" part, but the loop is always needed
- double fSourceMin = 0.0;
- double fSourceMax = 0.0;
- bool bFirst = true;
-
- size_t nOriginalCount = rOriginal.size();
- for (size_t nOriginalPos=0; nOriginalPos<nOriginalCount; nOriginalPos++)
- {
- const ScDPItemData* pItemData = pCache->GetItemDataById( nSourceDim, rOriginal[nOriginalPos] );
- if (pItemData->GetType() == ScDPItemData::Value)
- {
- double fSourceValue = pItemData->GetValue();
- if ( bFirst )
- {
- fSourceMin = fSourceMax = fSourceValue;
- bFirst = false;
- }
- else
- {
- if ( fSourceValue < fSourceMin )
- fSourceMin = fSourceValue;
- if ( fSourceValue > fSourceMax )
- fSourceMax = fSourceValue;
- }
- }
- }
-
- // For the start/end values, use the same date rounding as in ScDPNumGroupDimension::GetNumEntries
- // (but not for the list of available years):
- if ( aNumInfo.mbAutoStart )
- const_cast<ScDPDateGroupHelper*>(this)->aNumInfo.mfStart = rtl::math::approxFloor( fSourceMin );
- if ( aNumInfo.mbAutoEnd )
- const_cast<ScDPDateGroupHelper*>(this)->aNumInfo.mfEnd = rtl::math::approxFloor( fSourceMax ) + 1;
-
- //! if not automatic, limit fSourceMin/fSourceMax for list of year values?
- SvNumberFormatter* pFormatter = pCache->GetDoc()->GetFormatTable();
-
- long nStart = 0;
- long nEnd = 0; // including
-
- switch ( nDatePart )
- {
- case com::sun::star::sheet::DataPilotFieldGroupBy::YEARS:
- nStart = lcl_GetDatePartValue( fSourceMin, com::sun::star::sheet::DataPilotFieldGroupBy::YEARS, pFormatter, NULL );
- nEnd = lcl_GetDatePartValue( fSourceMax, com::sun::star::sheet::DataPilotFieldGroupBy::YEARS, pFormatter, NULL );
- break;
- case com::sun::star::sheet::DataPilotFieldGroupBy::QUARTERS: nStart = 1; nEnd = 4; break;
- case com::sun::star::sheet::DataPilotFieldGroupBy::MONTHS: nStart = 1; nEnd = 12; break;
- case com::sun::star::sheet::DataPilotFieldGroupBy::DAYS: nStart = 1; nEnd = 366; break;
- case com::sun::star::sheet::DataPilotFieldGroupBy::HOURS: nStart = 0; nEnd = 23; break;
- case com::sun::star::sheet::DataPilotFieldGroupBy::MINUTES: nStart = 0; nEnd = 59; break;
- case com::sun::star::sheet::DataPilotFieldGroupBy::SECONDS: nStart = 0; nEnd = 59; break;
- default:
- OSL_FAIL("invalid date part");
- }
-
- pCache->ResetGroupItems(mnGroupDim, aNumInfo);
-
- for ( sal_Int32 nValue = nStart; nValue <= nEnd; nValue++ )
- {
- SCROW nId = pCache->SetGroupItem(mnGroupDim, ScDPItemData(nDatePart, nValue));
- rEntries.push_back(nId);
- }
-
- // add first/last entry (min/max)
- SCROW nId = pCache->SetGroupItem(mnGroupDim, ScDPItemData(nDatePart, ScDPItemData::DateFirst));
- rEntries.push_back(nId);
-
- nId = pCache->SetGroupItem(mnGroupDim, ScDPItemData(nDatePart, ScDPItemData::DateLast));
- rEntries.push_back(nId);
+ pCache->GetGroupDimMemberIds(mnGroupDim, rEntries);
}
// -----------------------------------------------------------------------
@@ -569,33 +499,11 @@ const std::vector<SCROW>& ScDPGroupDimension::GetColumnEntries(
if (pDateHelper)
{
- pDateHelper->FillColumnEntries(
- GetSourceDim(), const_cast<ScDPCache*>(rCacheTable.getCache()), maMemberEntries, rOriginal);
+ pDateHelper->FillColumnEntries(rCacheTable.getCache(), maMemberEntries);
return maMemberEntries;
}
- ScDPCache* pCache = const_cast<ScDPCache*>(rCacheTable.getCache());
- for (size_t i = 0, n = rOriginal.size(); i < n; ++i)
- {
- const ScDPItemData* pItemData = pCache->GetItemDataById(nSourceDim, rOriginal[i]);
- if (!pItemData)
- // This shouldn't happen. Something is terribly wrong.
- continue;
-
- if (!GetGroupForData(*pItemData))
- {
- // not in any group -> add as its own group
- SCROW nId = pCache->SetGroupItem(nGroupDim, *pItemData);
- maMemberEntries.push_back(nId);
- }
- }
-
- for (size_t i = 0, n = aItems.size(); i < n; ++i)
- {
- SCROW nId = pCache->SetGroupItem(nGroupDim, aItems[i].GetName());
- maMemberEntries.push_back(nId);
- }
-
+ rCacheTable.getCache()->GetGroupDimMemberIds(nGroupDim, maMemberEntries);
return maMemberEntries;
}
@@ -681,7 +589,7 @@ void ScDPNumGroupDimension::MakeDateHelper( const ScDPNumGroupInfo& rInfo, long
}
const std::vector<SCROW>& ScDPNumGroupDimension::GetNumEntries(
- SCCOL nSourceDim, ScDPCache* pCache, const std::vector<SCROW>& rOriginal) const
+ SCCOL nSourceDim, const ScDPCache* pCache) const
{
if (!maMemberEntries.empty())
return maMemberEntries;
@@ -689,102 +597,11 @@ const std::vector<SCROW>& ScDPNumGroupDimension::GetNumEntries(
if (pDateHelper)
{
// Grouped by dates.
- pDateHelper->FillColumnEntries(
- nSourceDim, const_cast<ScDPCache*>(pCache), maMemberEntries, rOriginal);
+ pDateHelper->FillColumnEntries(pCache, maMemberEntries);
return maMemberEntries;
}
- // Copy textual entries.
- // Also look through the source entries for non-integer numbers, minimum and maximum.
- // GetNumEntries (GetColumnEntries) must be called before accessing the groups
- // (this in ensured by calling ScDPLevel::GetMembersObject for all column/row/page
- // dimensions before iterating over the values).
-
- // non-integer GroupInfo values count, too
- 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;
-
- for (size_t i = 0, n = rOriginal.size(); i < n; ++i)
- {
- const ScDPItemData* pItemData = pCache->GetItemDataById(nSourceDim, rOriginal[i]);
- if (pItemData->GetType() != ScDPItemData::Value)
- continue;
-
- double fSourceValue = pItemData->GetValue();
- if (bFirst)
- {
- fSourceMin = fSourceMax = fSourceValue;
- bFirst = false;
- continue;
- }
-
- if (fSourceValue < fSourceMin)
- fSourceMin = fSourceValue;
- if (fSourceValue > fSourceMax)
- fSourceMax = fSourceValue;
-
- if (aGroupInfo.mbIntegerOnly && !IsInteger(fSourceValue))
- {
- // if any non-integer numbers are involved, the group labels are
- // shown including their upper limit
- aGroupInfo.mbIntegerOnly = false;
- }
- }
-
- if (aGroupInfo.mbDateValues)
- {
- // special handling for dates: always integer, round down limits
- aGroupInfo.mbIntegerOnly = true;
- fSourceMin = rtl::math::approxFloor( fSourceMin );
- fSourceMax = rtl::math::approxFloor( fSourceMax ) + 1;
- }
-
- if (aGroupInfo.mbAutoStart)
- aGroupInfo.mfStart = fSourceMin;
- if (aGroupInfo.mbAutoEnd)
- aGroupInfo.mfEnd = fSourceMax;
-
- //! limit number of entries?
-
- long nLoopCount = 0;
- double fLoop = aGroupInfo.mfStart;
-
- // Num group always share the same dimension ID as the source dimension.
- pCache->ResetGroupItems(nSourceDim, aGroupInfo);
-
- // Use "less than" instead of "less or equal" for the loop - don't create a group
- // that consists only of the end value. Instead, the end value is then included
- // in the last group (last group is bigger than the others).
- // The first group has to be created nonetheless. GetNumGroupForValue has corresponding logic.
-
- bool bFirstGroup = true;
- while (bFirstGroup || (fLoop < aGroupInfo.mfEnd && !rtl::math::approxEqual(fLoop, aGroupInfo.mfEnd)))
- {
- ScDPItemData aItem;
- aItem.SetRangeStart(fLoop);
- SCROW nId = pCache->SetGroupItem(nSourceDim, aItem);
- maMemberEntries.push_back(nId);
- ++nLoopCount;
- fLoop = aGroupInfo.mfStart + nLoopCount * aGroupInfo.mfStep;
- bFirstGroup = false;
-
- // ScDPItemData values are compared with approxEqual
- }
-
- ScDPItemData aItem;
- aItem.SetRangeFirst();
- SCROW nId = pCache->SetGroupItem(nSourceDim, aItem);
- maMemberEntries.push_back(nId);
-
- aItem.SetRangeLast();
- nId = pCache->SetGroupItem(nSourceDim, aItem);
- maMemberEntries.push_back(nId);
-
+ pCache->GetGroupDimMemberIds(nSourceDim, maMemberEntries);
return maMemberEntries;
}
@@ -811,8 +628,6 @@ void ScDPGroupTableData::AddGroupDimension( const ScDPGroupDimension& rGroup )
aNewGroup.SetGroupDim( GetColumnCount() ); // new dimension will be at the end
aGroups.push_back( aNewGroup );
aGroupNames.insert(aNewGroup.GetName());
- ScDPCache* pCache = const_cast<ScDPCache*>(GetCacheTable().getCache());
- pCache->AppendGroupField();
}
void ScDPGroupTableData::SetNumGroupDimension( long nIndex, const ScDPNumGroupDimension& rGroup )
@@ -872,10 +687,8 @@ const std::vector< SCROW >& ScDPGroupTableData::GetColumnEntries( long nColumn
if ( IsNumGroupDimension( nColumn ) )
{
// dimension number is unchanged for numerical groups
- const std::vector< SCROW >& rOriginal = pSourceData->GetColumnEntries( nColumn );
return pNumGroups[nColumn].GetNumEntries(
- static_cast<SCCOL>(nColumn),
- const_cast<ScDPCache*>(GetCacheTable().getCache()), rOriginal);
+ static_cast<SCCOL>(nColumn), GetCacheTable().getCache());
}
return pSourceData->GetColumnEntries( nColumn );
diff --git a/sc/source/core/data/dptablecache.cxx b/sc/source/core/data/dptablecache.cxx
index 1c7f3a2a4db4..a58916406ebf 100644
--- a/sc/source/core/data/dptablecache.cxx
+++ b/sc/source/core/data/dptablecache.cxx
@@ -386,7 +386,7 @@ bool ScDPCache::InitFromDoc(ScDocument* pDoc, const ScRange& rRange)
for (size_t i = 0; i < static_cast<size_t>(mnColumnCount); ++i)
maFields.push_back(new Field);
- maLabelNames.reserve(mnColumnCount);
+ maLabelNames.reserve(mnColumnCount+1);
for (sal_uInt16 nCol = nStartCol; nCol <= nEndCol; ++nCol)
{
@@ -423,7 +423,7 @@ bool ScDPCache::InitFromDataBase (const Reference<sdbc::XRowSet>& xRowSet, const
// Get column titles and types.
maLabelNames.clear();
- maLabelNames.reserve(mnColumnCount);
+ maLabelNames.reserve(mnColumnCount+1);
std::vector<sal_Int32> aColTypes(mnColumnCount);
@@ -713,14 +713,14 @@ const ScDPCache::GroupItems* ScDPCache::GetGroupItems(long nDim) const
return NULL;
}
-rtl::OUString ScDPCache::GetDimensionName( sal_uInt16 nColumn ) const
+rtl::OUString ScDPCache::GetDimensionName(long nDim) const
{
- OSL_ENSURE(nColumn < maLabelNames.size()-1 , "ScDPTableDataCache::GetDimensionName");
+ OSL_ENSURE(nDim < maLabelNames.size()-1 , "ScDPTableDataCache::GetDimensionName");
OSL_ENSURE(maLabelNames.size() == static_cast <sal_uInt16> (mnColumnCount+1), "ScDPTableDataCache::GetDimensionName");
- if ( static_cast<size_t>(nColumn+1) < maLabelNames.size() )
+ if ( static_cast<size_t>(nDim+1) < maLabelNames.size() )
{
- return maLabelNames[nColumn+1];
+ return maLabelNames[nDim+1];
}
else
return rtl::OUString();
@@ -844,15 +844,6 @@ const ScDPCache::DataListType& ScDPCache::GetDimMemberValues(SCCOL nDim) const
return maFields[nDim].maItems;
}
-sal_uLong ScDPCache::GetNumType(sal_uLong nFormat) const
-{
- SvNumberFormatter* pFormatter = mpDoc->GetFormatTable();
- sal_uLong nType = NUMBERFORMAT_NUMBER;
- if ( pFormatter )
- nType = pFormatter->GetType( nFormat );
- return nType;
-}
-
sal_uLong ScDPCache::GetNumberFormat( long nDim ) const
{
if ( nDim >= mnColumnCount )
@@ -895,7 +886,7 @@ SCCOL ScDPCache::GetDimensionIndex(const rtl::OUString& sName) const
for (size_t i = 1; i < maLabelNames.size(); ++i)
{
if (maLabelNames[i].equals(sName))
- return (SCCOL)(i-1);
+ return static_cast<SCCOL>(i-1);
}
return -1;
}
@@ -1055,10 +1046,10 @@ rtl::OUString ScDPCache::GetFormattedString(long nDim, const ScDPItemData& rItem
return rItem.GetString();
}
-void ScDPCache::AppendGroupField()
+long ScDPCache::AppendGroupField()
{
maGroupFields.push_back(new GroupItems);
- fprintf(stdout, "ScDPCache::AppendGroupField: added; new count = %d\n", maGroupFields.size());
+ return static_cast<long>(maFields.size() + maGroupFields.size() - 1);
}
void ScDPCache::ResetGroupItems(long nDim, const ScDPNumGroupInfo& rNumInfo)
@@ -1107,6 +1098,55 @@ SCROW ScDPCache::SetGroupItem(long nDim, const ScDPItemData& rData)
return -1;
}
+const ScDPCache::DataListType* ScDPCache::GetGroupDimMemberValues(long nDim) const
+{
+ if (nDim < 0)
+ return NULL;
+
+ long nSourceCount = static_cast<long>(maFields.size());
+ if (nDim < nSourceCount)
+ {
+ if (!maFields.at(nDim).mpGroup)
+ return NULL;
+
+ return &maFields[nDim].mpGroup->maItems;
+ }
+
+ nDim -= nSourceCount;
+ if (nDim < static_cast<long>(maGroupFields.size()))
+ return &maGroupFields.at(nDim).maItems;
+
+ return NULL;
+}
+
+void ScDPCache::GetGroupDimMemberIds(long nDim, std::vector<SCROW>& rIds) const
+{
+ if (nDim < 0)
+ return;
+
+ long nSourceCount = static_cast<long>(maFields.size());
+ if (nDim < nSourceCount)
+ {
+ if (!maFields.at(nDim).mpGroup)
+ return;
+
+ size_t nOffset = maFields[nDim].maItems.size();
+ const DataListType& rGI = maFields[nDim].mpGroup->maItems;
+ for (size_t i = 0, n = rGI.size(); i < n; ++i)
+ rIds.push_back(static_cast<SCROW>(i + nOffset));
+
+ return;
+ }
+
+ nDim -= nSourceCount;
+ if (nDim < static_cast<long>(maGroupFields.size()))
+ {
+ const DataListType& rGI = maGroupFields.at(nDim).maItems;
+ for (size_t i = 0, n = rGI.size(); i < n; ++i)
+ rIds.push_back(static_cast<SCROW>(i));
+ }
+}
+
namespace {
struct ClearGroupItems : std::unary_function<ScDPCache::Field, void>
diff --git a/sc/source/core/data/dputil.cxx b/sc/source/core/data/dputil.cxx
index e12da8c7f32c..0e1803d64bc2 100644
--- a/sc/source/core/data/dputil.cxx
+++ b/sc/source/core/data/dputil.cxx
@@ -40,6 +40,8 @@
#include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
#include <com/sun/star/i18n/CalendarDisplayIndex.hpp>
+#define D_TIMEFACTOR 86400.0
+
using namespace com::sun::star;
namespace {
@@ -290,4 +292,76 @@ rtl::OUString ScDPUtil::getNumGroupName(
return lcl_GetNumGroupName(fGroupStart, rInfo, cDecSep, pFormatter);
}
+sal_Int32 ScDPUtil::getDatePartValue(
+ double fValue, const ScDPNumGroupInfo& rInfo, sal_Int32 nDatePart,
+ SvNumberFormatter* pFormatter)
+{
+ // Start and end are inclusive
+ // (End date without a time value is included, with a time value it's not)
+
+ if (fValue < rInfo.mfStart && !rtl::math::approxEqual(fValue, rInfo.mfStart))
+ return ScDPItemData::DateFirst;
+ if (fValue > rInfo.mfEnd && !rtl::math::approxEqual(fValue, rInfo.mfEnd))
+ return ScDPItemData::DateLast;
+
+ sal_Int32 nResult = 0;
+
+ if (nDatePart == sheet::DataPilotFieldGroupBy::HOURS ||
+ nDatePart == sheet::DataPilotFieldGroupBy::MINUTES ||
+ nDatePart == sheet::DataPilotFieldGroupBy::SECONDS)
+ {
+ // handle time
+ // (as in the cell functions, ScInterpreter::ScGetHour etc.: seconds are rounded)
+
+ double fTime = fValue - rtl::math::approxFloor(fValue);
+ long nSeconds = (long)rtl::math::approxFloor(fTime*D_TIMEFACTOR+0.5);
+
+ switch (nDatePart)
+ {
+ case sheet::DataPilotFieldGroupBy::HOURS:
+ nResult = nSeconds / 3600;
+ break;
+ case sheet::DataPilotFieldGroupBy::MINUTES:
+ nResult = ( nSeconds % 3600 ) / 60;
+ break;
+ case sheet::DataPilotFieldGroupBy::SECONDS:
+ nResult = nSeconds % 60;
+ break;
+ }
+ }
+ else
+ {
+ Date aDate = *(pFormatter->GetNullDate());
+ aDate += (long)::rtl::math::approxFloor(fValue);
+
+ switch ( nDatePart )
+ {
+ case com::sun::star::sheet::DataPilotFieldGroupBy::YEARS:
+ nResult = aDate.GetYear();
+ break;
+ case com::sun::star::sheet::DataPilotFieldGroupBy::QUARTERS:
+ nResult = 1 + (aDate.GetMonth() - 1) / 3; // 1..4
+ break;
+ case com::sun::star::sheet::DataPilotFieldGroupBy::MONTHS:
+ nResult = aDate.GetMonth(); // 1..12
+ break;
+ case com::sun::star::sheet::DataPilotFieldGroupBy::DAYS:
+ {
+ Date aYearStart(1, 1, aDate.GetYear());
+ nResult = (aDate - aYearStart) + 1; // Jan 01 has value 1
+ if (nResult >= 60 && !aDate.IsLeapYear())
+ {
+ // days are counted from 1 to 366 - if not from a leap year, adjust
+ ++nResult;
+ }
+ }
+ break;
+ default:
+ OSL_FAIL("invalid date part");
+ }
+ }
+
+ return nResult;
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/excel/xepivot.cxx b/sc/source/filter/excel/xepivot.cxx
index d1d5764744bf..324f802a2e4c 100644
--- a/sc/source/filter/excel/xepivot.cxx
+++ b/sc/source/filter/excel/xepivot.cxx
@@ -554,8 +554,7 @@ void XclExpPCField::InsertNumDateGroupItems( const ScDPObject& rDPObj, const ScD
if( nDatePart != 0 )
aTmpDim.MakeDateHelper( rNumInfo, mnFieldIdx, nDatePart );
const std::vector<SCROW>& aMemberIds = aTmpDim.GetNumEntries(
- static_cast<SCCOL>(GetBaseFieldIndex()),
- const_cast<ScDPCache*>(aDPData.GetCacheTable().getCache()), aOrignial);
+ static_cast<SCCOL>(GetBaseFieldIndex()), aDPData.GetCacheTable().getCache());
for ( size_t nIdx = 0 ; nIdx < aMemberIds.size(); nIdx++ )
{
const ScDPItemData* pData = aDPData.GetMemberById( static_cast< long >( GetBaseFieldIndex() ) , aMemberIds[ nIdx] );