[Libreoffice-commits] .: 34 commits - sc/inc sc/Library_sc.mk sc/source

Kohei Yoshida kohei at kemper.freedesktop.org
Fri Mar 9 08:13:32 PST 2012


 sc/Library_sc.mk                       |    1 
 sc/inc/dpdimsave.hxx                   |   36 +
 sc/inc/dpgroup.hxx                     |   40 -
 sc/inc/dpitemdata.hxx                  |  100 ++--
 sc/inc/dpnumgroupinfo.hxx              |   51 ++
 sc/inc/dpobject.hxx                    |   39 +
 sc/inc/dpsdbtab.hxx                    |    3 
 sc/inc/dpshttab.hxx                    |    3 
 sc/inc/dptabdat.hxx                    |    6 
 sc/inc/dptablecache.hxx                |  103 +++-
 sc/inc/dptabres.hxx                    |    2 
 sc/inc/dptabsrc.hxx                    |    1 
 sc/inc/dputil.hxx                      |   17 
 sc/inc/pivot.hxx                       |    1 
 sc/source/core/data/dpcachetable.cxx   |    2 
 sc/source/core/data/dpdimsave.cxx      |  303 +++++++++++++-
 sc/source/core/data/dpgroup.cxx        |  712 +++++----------------------------
 sc/source/core/data/dpitemdata.cxx     |  393 +++++++++++-------
 sc/source/core/data/dpnumgroupinfo.cxx |   48 ++
 sc/source/core/data/dpobject.cxx       |  185 +++++---
 sc/source/core/data/dpsdbtab.cxx       |    4 
 sc/source/core/data/dpshttab.cxx       |    6 
 sc/source/core/data/dptabdat.cxx       |   38 +
 sc/source/core/data/dptablecache.cxx   |  536 +++++++++++++++++-------
 sc/source/core/data/dptabres.cxx       |  131 +++---
 sc/source/core/data/dptabsrc.cxx       |   65 +--
 sc/source/core/data/dputil.cxx         |  308 ++++++++++++++
 sc/source/core/data/pivot2.cxx         |   12 
 sc/source/filter/excel/xepivot.cxx     |   11 
 sc/source/ui/view/cellsh1.cxx          |    7 
 sc/source/ui/view/dbfunc3.cxx          |  626 ++++++++++++++---------------
 sc/source/ui/view/gridwin2.cxx         |   17 
 32 files changed, 2255 insertions(+), 1552 deletions(-)

New commits:
commit 2d5c1a3f6de583629c29fc0eeea630c8f8a0eb89
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Fri Mar 9 11:08:16 2012 -0500

    Even more cleanup and fixing.

diff --git a/sc/inc/dptabdat.hxx b/sc/inc/dptabdat.hxx
index 8cd3c47..de323e6 100644
--- a/sc/inc/dptabdat.hxx
+++ b/sc/inc/dptabdat.hxx
@@ -60,8 +60,8 @@ namespace com { namespace sun { namespace star { namespace sheet {
 #define SC_DAPI_LEVEL_QUARTER   1
 #define SC_DAPI_LEVEL_MONTH     2
 #define SC_DAPI_LEVEL_DAY       3
-#define SC_DAPI_LEVEL_WEEK      1
-#define SC_DAPI_LEVEL_WEEKDAY   2
+#define SC_DAPI_LEVEL_WEEK      4
+#define SC_DAPI_LEVEL_WEEKDAY   5
 
 
 //
diff --git a/sc/inc/dptablecache.hxx b/sc/inc/dptablecache.hxx
index 8a32284..62af398 100644
--- a/sc/inc/dptablecache.hxx
+++ b/sc/inc/dptablecache.hxx
@@ -128,7 +128,6 @@ public:
     void RemoveReference(ScDPObject* pObj) const;
     const ObjectSetType& GetAllReferences() const;
 
-    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;
     long AppendGroupField();
@@ -138,8 +137,6 @@ public:
     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 GetNumberFormat( long nDim ) const;
     bool  IsDateDimension( long nDim ) const ;
diff --git a/sc/source/core/data/dptablecache.cxx b/sc/source/core/data/dptablecache.cxx
index 7109b91..ff12648 100644
--- a/sc/source/core/data/dptablecache.cxx
+++ b/sc/source/core/data/dptablecache.cxx
@@ -872,49 +872,6 @@ const ScDPCache::ObjectSetType& ScDPCache::GetAllReferences() const
     return maRefObjects;
 }
 
-SCROW ScDPCache::GetIdByItemData(long nDim, const rtl::OUString& sItemData) const
-{
-    if (nDim < 0)
-        return -1;
-
-    if (nDim < mnColumnCount)
-    {
-        // source field.
-        const DataListType& rItems = maFields[nDim].maItems;
-        for (size_t i = 0, n = rItems.size(); i < n; ++i)
-        {
-            if (rItems[i].GetString() == sItemData)
-                return i;
-        }
-
-        if (!maFields[nDim].mpGroup)
-            return -1;
-
-        // grouped source field.
-        const DataListType& rGI = maFields[nDim].mpGroup->maItems;
-        for (size_t i = 0, n = rGI.size(); i < n; ++i)
-        {
-            if (rGI[i].GetString() == sItemData)
-                return rItems.size() + i;
-        }
-        return -1;
-    }
-
-    // group field.
-    nDim -= mnColumnCount;
-    if (static_cast<size_t>(nDim) < maGroupFields.size())
-    {
-        const DataListType& rGI = maGroupFields[nDim].maItems;
-        for (size_t i = 0, n = rGI.size(); i < n; ++i)
-        {
-            if (rGI[i].GetString() == sItemData)
-                return i;
-        }
-    }
-
-    return -1;
-}
-
 SCROW ScDPCache::GetIdByItemData(long nDim, const ScDPItemData& rItem) const
 {
     if (nDim < 0)
@@ -1125,13 +1082,6 @@ void ScDPCache::ClearGroupFields()
     std::for_each(maFields.begin(), maFields.end(), ClearGroupItems());
 }
 
-SCROW ScDPCache::GetAdditionalItemID(const ScDPItemData&) const
-{
-    fprintf(stdout, "ScDPCache::GetAdditionalItemID:   FIXME\n");
-    return -1;
-}
-
-
 SCROW ScDPCache::GetOrder(long nDim, SCROW nIndex) const
 {
     OSL_ENSURE( IsValid(), "  IsValid() == false " );
diff --git a/sc/source/core/data/dptabsrc.cxx b/sc/source/core/data/dptabsrc.cxx
index 3f2de93..9514046 100644
--- a/sc/source/core/data/dptabsrc.cxx
+++ b/sc/source/core/data/dptabsrc.cxx
@@ -66,6 +66,7 @@
 #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
 #include <com/sun/star/sheet/DataPilotFieldReferenceType.hpp>
 #include <com/sun/star/sheet/DataPilotFieldSortMode.hpp>
+#include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
 #include <com/sun/star/sheet/DataPilotFieldAutoShowInfo.hpp>
 #include <com/sun/star/table/CellAddress.hpp>
 
@@ -2490,7 +2491,8 @@ ScDPMember* ScDPMembers::getByIndex(long nIndex) const
             }
             else if ( nHier != SC_DAPI_HIERARCHY_FLAT && pSource->IsDateDimension( nSrcDim ) )
             {
-                long nVal = 0;
+                sal_Int32 nGroupBy = 0;
+                sal_Int32 nVal = 0;
                 rtl::OUString aName;
 
                 if ( nLev == SC_DAPI_LEVEL_YEAR )   // YEAR is in both hierarchies
@@ -2521,14 +2523,33 @@ ScDPMember* ScDPMembers::getByIndex(long nIndex) const
                 else
                     nVal = nIndex + 1;          // Quarter, Day, Week are 1-based
 
+                switch (nLev)
+                {
+                    case SC_DAPI_LEVEL_YEAR:
+                        nGroupBy = sheet::DataPilotFieldGroupBy::YEARS;
+                    break;
+                    case SC_DAPI_LEVEL_QUARTER:
+                    case SC_DAPI_LEVEL_WEEK:
+                        nGroupBy = sheet::DataPilotFieldGroupBy::QUARTERS;
+                    break;
+                    case SC_DAPI_LEVEL_MONTH:
+                    case SC_DAPI_LEVEL_WEEKDAY:
+                        nGroupBy = sheet::DataPilotFieldGroupBy::MONTHS;
+                    break;
+                    case SC_DAPI_LEVEL_DAY:
+                        nGroupBy = sheet::DataPilotFieldGroupBy::DAYS;
+                    break;
+                        nGroupBy = sheet::DataPilotFieldGroupBy::YEARS;
+                    break;
+                    default:
+                        ;
+                }
                 if (aName.isEmpty())
                     aName = rtl::OUString::valueOf(nVal);
 
-                // TODO: This needs fixing.
-                fprintf(stdout, "ScDPMembers::getByIndex:   FIXME\n");
-                ScDPItemData aData(nVal);
-                pNew = new ScDPMember(
-                    pSource, nDim, nHier, nLev, pSource->GetCache()->GetAdditionalItemID(aData));
+                ScDPItemData aData(nGroupBy, nVal);
+                SCROW nId = pSource->GetCache()->GetIdByItemData(nDim, aData);
+                pNew = new ScDPMember(pSource, nDim, nHier, nLev, nId);
             }
             else
             {
commit d049b05a1a7ccdcccd5aeaafbabd43b8df48f8df
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Fri Mar 9 10:34:24 2012 -0500

    Cleaned up code.

diff --git a/sc/source/core/data/dpdimsave.cxx b/sc/source/core/data/dpdimsave.cxx
index 234f667..cc02b15 100644
--- a/sc/source/core/data/dpdimsave.cxx
+++ b/sc/source/core/data/dpdimsave.cxx
@@ -41,48 +41,6 @@
 
 using namespace com::sun::star;
 
-#include <stdio.h>
-#include <string>
-#include <sys/time.h>
-
-namespace {
-
-class stack_printer
-{
-public:
-    explicit stack_printer(const char* msg) :
-        msMsg(msg)
-    {
-        fprintf(stdout, "%s: --begin\n", msMsg.c_str());
-        mfStartTime = getTime();
-    }
-
-    ~stack_printer()
-    {
-        double fEndTime = getTime();
-        fprintf(stdout, "%s: --end (duration: %g sec)\n", msMsg.c_str(), (fEndTime-mfStartTime));
-    }
-
-    void printTime(int line) const
-    {
-        double fEndTime = getTime();
-        fprintf(stdout, "%s: --(%d) (duration: %g sec)\n", msMsg.c_str(), line, (fEndTime-mfStartTime));
-    }
-
-private:
-    double getTime() const
-    {
-        timeval tv;
-        gettimeofday(&tv, NULL);
-        return tv.tv_sec + tv.tv_usec / 1000000.0;
-    }
-
-    ::std::string msMsg;
-    double mfStartTime;
-};
-
-}
-
 // ============================================================================
 
 ScDPSaveGroupItem::ScDPSaveGroupItem( const rtl::OUString& rName ) :
diff --git a/sc/source/core/data/dpgroup.cxx b/sc/source/core/data/dpgroup.cxx
index 93c5cbb..a2eb282 100644
--- a/sc/source/core/data/dpgroup.cxx
+++ b/sc/source/core/data/dpgroup.cxx
@@ -64,48 +64,6 @@ using ::rtl::OUStringHash;
 using ::std::vector;
 using ::boost::shared_ptr;
 
-#include <stdio.h>
-#include <string>
-#include <sys/time.h>
-
-namespace {
-
-class stack_printer
-{
-public:
-    explicit stack_printer(const char* msg) :
-        msMsg(msg)
-    {
-        fprintf(stdout, "%s: --begin\n", msMsg.c_str());
-        mfStartTime = getTime();
-    }
-
-    ~stack_printer()
-    {
-        double fEndTime = getTime();
-        fprintf(stdout, "%s: --end (duration: %g sec)\n", msMsg.c_str(), (fEndTime-mfStartTime));
-    }
-
-    void printTime(int line) const
-    {
-        double fEndTime = getTime();
-        fprintf(stdout, "%s: --(%d) (duration: %g sec)\n", msMsg.c_str(), line, (fEndTime-mfStartTime));
-    }
-
-private:
-    double getTime() const
-    {
-        timeval tv;
-        gettimeofday(&tv, NULL);
-        return tv.tv_sec + tv.tv_usec / 1000000.0;
-    }
-
-    ::std::string msMsg;
-    double mfStartTime;
-};
-
-}
-
 #define D_TIMEFACTOR              86400.0
 
 const sal_uInt16 SC_DP_LEAPYEAR = 1648;     // arbitrary leap year for date calculations
diff --git a/sc/source/core/data/dptablecache.cxx b/sc/source/core/data/dptablecache.cxx
index a589164..7109b91 100644
--- a/sc/source/core/data/dptablecache.cxx
+++ b/sc/source/core/data/dptablecache.cxx
@@ -63,48 +63,6 @@ using ::com::sun::star::uno::UNO_QUERY_THROW;
 using ::std::vector;
 using ::std::auto_ptr;
 
-#include <stdio.h>
-#include <string>
-#include <sys/time.h>
-
-namespace {
-
-class stack_printer
-{
-public:
-    explicit stack_printer(const char* msg) :
-        msMsg(msg)
-    {
-        fprintf(stdout, "%s: --begin\n", msMsg.c_str());
-        mfStartTime = getTime();
-    }
-
-    ~stack_printer()
-    {
-        double fEndTime = getTime();
-        fprintf(stdout, "%s: --end (duration: %g sec)\n", msMsg.c_str(), (fEndTime-mfStartTime));
-    }
-
-    void printTime(int line) const
-    {
-        double fEndTime = getTime();
-        fprintf(stdout, "%s: --(%d) (duration: %g sec)\n", msMsg.c_str(), line, (fEndTime-mfStartTime));
-    }
-
-private:
-    double getTime() const
-    {
-        timeval tv;
-        gettimeofday(&tv, NULL);
-        return tv.tv_sec + tv.tv_usec / 1000000.0;
-    }
-
-    ::std::string msMsg;
-    double mfStartTime;
-};
-
-}
-
 namespace {
 
 /**
@@ -799,35 +757,37 @@ const ScDPItemData* ScDPCache::GetItemDataById(long nDim, SCROW nId) const
     if (nDim < 0 || nId < 0)
         return NULL;
 
-    long nSourceCount = static_cast<long>(maFields.size());
-    if (nDim < nSourceCount)
+    size_t nSourceCount = maFields.size();
+    size_t nDimPos = static_cast<size_t>(nDim);
+    size_t nItemId = static_cast<size_t>(nId);
+    if (nDimPos < nSourceCount)
     {
         // source field.
-        const Field& rField = maFields[nDim];
-        if (nId < rField.maItems.size())
-            return &rField.maItems[nId];
+        const Field& rField = maFields[nDimPos];
+        if (nItemId < rField.maItems.size())
+            return &rField.maItems[nItemId];
 
         if (!rField.mpGroup)
             return NULL;
 
-        nId -= rField.maItems.size();
+        nItemId -= rField.maItems.size();
         const DataListType& rGI = rField.mpGroup->maItems;
-        if (nId >= rGI.size())
+        if (nItemId >= rGI.size())
             return NULL;
 
-        return &rGI[nId];
+        return &rGI[nItemId];
     }
 
     // Try group fields.
-    nDim -= nSourceCount;
-    if (nDim >= maGroupFields.size())
+    nDimPos -= nSourceCount;
+    if (nDimPos >= maGroupFields.size())
         return NULL;
 
-    const DataListType& rGI = maGroupFields[nDim].maItems;
-    if (nId >= rGI.size())
+    const DataListType& rGI = maGroupFields[nDimPos].maItems;
+    if (nItemId >= rGI.size())
         return NULL;
 
-    return &rGI[nId];
+    return &rGI[nItemId];
 }
 
 SCROW ScDPCache::GetRowCount() const
@@ -942,7 +902,7 @@ SCROW ScDPCache::GetIdByItemData(long nDim, const rtl::OUString& sItemData) cons
 
     // group field.
     nDim -= mnColumnCount;
-    if (nDim < maGroupFields.size())
+    if (static_cast<size_t>(nDim) < maGroupFields.size())
     {
         const DataListType& rGI = maGroupFields[nDim].maItems;
         for (size_t i = 0, n = rGI.size(); i < n; ++i)
@@ -985,7 +945,7 @@ SCROW ScDPCache::GetIdByItemData(long nDim, const ScDPItemData& rItem) const
 
     // group field.
     nDim -= mnColumnCount;
-    if (nDim < maGroupFields.size())
+    if (static_cast<size_t>(nDim) < maGroupFields.size())
     {
         const DataListType& rGI = maGroupFields[nDim].maItems;
         for (size_t i = 0, n = rGI.size(); i < n; ++i)
diff --git a/sc/source/core/data/dptabres.cxx b/sc/source/core/data/dptabres.cxx
index f65bf33..a14c53a 100644
--- a/sc/source/core/data/dptabres.cxx
+++ b/sc/source/core/data/dptabres.cxx
@@ -68,48 +68,6 @@ using ::std::pair;
 using ::com::sun::star::uno::Sequence;
 using ::rtl::OUString;
 
-#include <stdio.h>
-#include <string>
-#include <sys/time.h>
-
-namespace {
-
-class stack_printer
-{
-public:
-    explicit stack_printer(const char* msg) :
-        msMsg(msg)
-    {
-        fprintf(stdout, "%s: --begin\n", msMsg.c_str());
-        mfStartTime = getTime();
-    }
-
-    ~stack_printer()
-    {
-        double fEndTime = getTime();
-        fprintf(stdout, "%s: --end (duration: %g sec)\n", msMsg.c_str(), (fEndTime-mfStartTime));
-    }
-
-    void printTime(int line) const
-    {
-        double fEndTime = getTime();
-        fprintf(stdout, "%s: --(%d) (duration: %g sec)\n", msMsg.c_str(), line, (fEndTime-mfStartTime));
-    }
-
-private:
-    double getTime() const
-    {
-        timeval tv;
-        gettimeofday(&tv, NULL);
-        return tv.tv_sec + tv.tv_usec / 1000000.0;
-    }
-
-    ::std::string msMsg;
-    double mfStartTime;
-};
-
-}
-
 // -----------------------------------------------------------------------
 
 static sal_uInt16 nFuncStrIds[12] =     // passend zum enum ScSubTotalFunc
diff --git a/sc/source/core/data/dptabsrc.cxx b/sc/source/core/data/dptabsrc.cxx
index 32bbb34..3f2de93 100644
--- a/sc/source/core/data/dptabsrc.cxx
+++ b/sc/source/core/data/dptabsrc.cxx
@@ -1022,7 +1022,6 @@ void ScDPSource::FillLevelList( sal_uInt16 nOrientation, std::vector<ScDPLevel*>
         for (long nLev=0; nLev<nLevCount; nLev++)
         {
             ScDPLevel* pLevel = pLevels->getByIndex(nLev);
-//          fprintf(stdout, "ScDPSource::FillLevelList:   level name = '%s'\n", rtl::OUStringToOString(pLevel->getName(), RTL_TEXTENCODING_UTF8).getStr());
             rList.push_back(pLevel);
         }
     }
commit 0637ca0aefed73b55154c15c8738c100f329a3a8
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Fri Mar 9 10:15:52 2012 -0500

    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.

diff --git a/sc/inc/dpdimsave.hxx b/sc/inc/dpdimsave.hxx
index 6858e8b..925cb94 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 b90c667..5340b70 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 b877130..8a32284 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 68414f3..4ed4e5c 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 34e87d5..234f667 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 ffe0430..93c5cbb 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 1c7f3a2..a589164 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 e12da8c..0e1803d 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 d1d5764..324f802 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] );
commit 593f6ac1064184f1faee60155c412b964f6f86a1
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Thu Mar 8 15:49:31 2012 -0500

    Added hook to create group field data at cache creation time.
    
    This is to avoid group data to be added multiple times in case of
    multiple pivot tables referencing the same pivot cache.

diff --git a/sc/inc/dpdimsave.hxx b/sc/inc/dpdimsave.hxx
index ea280a1..6858e8b 100644
--- a/sc/inc/dpdimsave.hxx
+++ b/sc/inc/dpdimsave.hxx
@@ -39,6 +39,7 @@
 class ScDPGroupTableData;
 class ScDPGroupDimension;
 class ScDPObject;
+class ScDPCache;
 class SvNumberFormatter;
 
 class ScDPSaveGroupDimension;
@@ -163,6 +164,8 @@ public:
 
     void    WriteToData( ScDPGroupTableData& rData ) const;
 
+    void WriteToCache(ScDPCache& rCache) const;
+
     rtl::OUString CreateGroupDimName(
         const rtl::OUString& rSourceName, const ScDPObject& rObject, bool bAllowSource,
         const ::std::vector<rtl::OUString>* pDeletedNames );
diff --git a/sc/inc/dpobject.hxx b/sc/inc/dpobject.hxx
index d77fbc1..5f3963d 100644
--- a/sc/inc/dpobject.hxx
+++ b/sc/inc/dpobject.hxx
@@ -70,6 +70,7 @@ class ScSheetSourceDesc;
 struct PivotField;
 class ScDPCacheTable;
 class ScDPTableData;
+class ScDPDimensionSaveData;
 
 struct ScDPServiceDesc
 {
@@ -276,14 +277,14 @@ public:
     public:
         SheetCaches(ScDocument* pDoc);
         bool hasCache(const ScRange& rRange) const;
-        const ScDPCache* getCache(const ScRange& rRange);
+        const ScDPCache* getCache(const ScRange& rRange, const ScDPDimensionSaveData* pDimData);
         size_t size() const;
 
         void updateReference(
             UpdateRefMode eMode, const ScRange& r, SCsCOL nDx, SCsROW nDy, SCsTAB nDz);
 
     private:
-        void updateCache(const ScRange& rRange, std::set<ScDPObject*>& rRefs);
+        void updateCache(const ScRange& rRange, const ScDPDimensionSaveData* pDimData, std::set<ScDPObject*>& rRefs);
         bool remove(const ScDPCache* p);
     };
 
@@ -299,10 +300,13 @@ public:
     public:
         NameCaches(ScDocument* pDoc);
         bool hasCache(const rtl::OUString& rName) const;
-        const ScDPCache* getCache(const ::rtl::OUString& rName, const ScRange& rRange);
+        const ScDPCache* getCache(
+            const ::rtl::OUString& rName, const ScRange& rRange, const ScDPDimensionSaveData* pDimData);
         size_t size() const;
     private:
-        void updateCache(const rtl::OUString& rName, const ScRange& rRange, std::set<ScDPObject*>& rRefs);
+        void updateCache(
+            const rtl::OUString& rName, const ScRange& rRange,
+            const ScDPDimensionSaveData* pDimData, std::set<ScDPObject*>& rRefs);
         bool remove(const ScDPCache* p);
     };
 
@@ -335,14 +339,16 @@ public:
     public:
         DBCaches(ScDocument* pDoc);
         bool hasCache(sal_Int32 nSdbType, const rtl::OUString& rDBName, const rtl::OUString& rCommand) const;
-        const ScDPCache* getCache(sal_Int32 nSdbType, const ::rtl::OUString& rDBName, const ::rtl::OUString& rCommand);
+        const ScDPCache* getCache(
+            sal_Int32 nSdbType, const ::rtl::OUString& rDBName, const ::rtl::OUString& rCommand,
+            const ScDPDimensionSaveData* pDimData);
 
     private:
         com::sun::star::uno::Reference<com::sun::star::sdbc::XRowSet> createRowSet(
             sal_Int32 nSdbType, const ::rtl::OUString& rDBName, const ::rtl::OUString& rCommand);
 
         void updateCache(sal_Int32 nSdbType, const ::rtl::OUString& rDBName, const ::rtl::OUString& rCommand,
-                         std::set<ScDPObject*>& rRefs);
+                         const ScDPDimensionSaveData* pDimData, std::set<ScDPObject*>& rRefs);
         bool remove(const ScDPCache* p);
     };
 
diff --git a/sc/inc/dpsdbtab.hxx b/sc/inc/dpsdbtab.hxx
index 81d198c..eba6da2 100644
--- a/sc/inc/dpsdbtab.hxx
+++ b/sc/inc/dpsdbtab.hxx
@@ -39,6 +39,7 @@
 class ScDPCacheTable;
 class ScDocument;
 class ScDPCache;
+class ScDPDimensionSaveData;
 
 struct ScImportSourceDesc
 {
@@ -58,7 +59,7 @@ struct ScImportSourceDesc
                 mpDoc == rOther.mpDoc; }
 
     sal_Int32 GetCommandType() const;
-    const ScDPCache* CreateCache() const;
+    const ScDPCache* CreateCache(const ScDPDimensionSaveData* pDimData) const;
 };
 
 /**
diff --git a/sc/inc/dpshttab.hxx b/sc/inc/dpshttab.hxx
index 9df0d72..38a0d58 100644
--- a/sc/inc/dpshttab.hxx
+++ b/sc/inc/dpshttab.hxx
@@ -44,6 +44,7 @@ namespace com { namespace sun { namespace star { namespace sheet {
 
 class ScDPDimension;
 class ScDPItemData;
+class ScDPDimensionSaveData;
 
 /**
  * This class contains authoritative information on the internal reference
@@ -78,7 +79,7 @@ public:
     const ScQueryParam& GetQueryParam() const;
 
     bool operator== ( const ScSheetSourceDesc& rOther ) const;
-    SC_DLLPUBLIC const ScDPCache* CreateCache() const;
+    SC_DLLPUBLIC const ScDPCache* CreateCache(const ScDPDimensionSaveData* pDimData) const;
 
     /**
      * Check the sanity of the data source range.
diff --git a/sc/source/core/data/dpdimsave.cxx b/sc/source/core/data/dpdimsave.cxx
index c8ddaff..34e87d5 100644
--- a/sc/source/core/data/dpdimsave.cxx
+++ b/sc/source/core/data/dpdimsave.cxx
@@ -468,6 +468,10 @@ void ScDPDimensionSaveData::WriteToData( ScDPGroupTableData& rData ) const
         aIt->second.AddToData( rData );
 }
 
+void ScDPDimensionSaveData::WriteToCache(ScDPCache& rCache) const
+{
+}
+
 const ScDPSaveGroupDimension* ScDPDimensionSaveData::GetGroupDimForBase( const rtl::OUString& rBaseDimName ) const
 {
     return const_cast< ScDPDimensionSaveData* >( this )->GetGroupDimAccForBase( rBaseDimName );
diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx
index 774a23b..8e1eff8 100644
--- a/sc/source/core/data/dpobject.cxx
+++ b/sc/source/core/data/dpobject.cxx
@@ -429,10 +429,14 @@ ScDPTableData* ScDPObject::GetTableData()
     if (!mpTableData)
     {
         shared_ptr<ScDPTableData> pData;
+        const ScDPDimensionSaveData* pDimData = NULL;
+        if (pSaveData)
+            pDimData = pSaveData->GetExistingDimensionData();
+
         if ( pImpDesc )
         {
             // database data
-            const ScDPCache* pCache = pImpDesc->CreateCache();
+            const ScDPCache* pCache = pImpDesc->CreateCache(pDimData);
             if (pCache)
             {
                 pCache->AddReference(this);
@@ -453,7 +457,7 @@ ScDPTableData* ScDPObject::GetTableData()
                 // GETPIVOTDATA called onto itself from within the source
                 // range.
                 DisableGetPivotData aSwitch(*this, mbEnableGetPivotData);
-                const ScDPCache* pCache = pSheetDesc->CreateCache();
+                const ScDPCache* pCache = pSheetDesc->CreateCache(pDimData);
                 if (pCache)
                 {
                     pCache->AddReference(this);
@@ -463,10 +467,10 @@ ScDPTableData* ScDPObject::GetTableData()
         }
 
         // grouping (for cell or database data)
-        if (pData && pSaveData && pSaveData->GetExistingDimensionData())
+        if (pData && pDimData)
         {
             shared_ptr<ScDPGroupTableData> pGroupData(new ScDPGroupTableData(pData, pDoc));
-            pSaveData->GetExistingDimensionData()->WriteToData(*pGroupData);
+            pDimData->WriteToData(*pGroupData);
             pData = pGroupData;
         }
 
@@ -2491,7 +2495,7 @@ bool ScDPCollection::SheetCaches::hasCache(const ScRange& rRange) const
     return itCache != maCaches.end();
 }
 
-const ScDPCache* ScDPCollection::SheetCaches::getCache(const ScRange& rRange)
+const ScDPCache* ScDPCollection::SheetCaches::getCache(const ScRange& rRange, const ScDPDimensionSaveData* pDimData)
 {
     RangeIndexType::iterator it = std::find(maRanges.begin(), maRanges.end(), rRange);
     if (it != maRanges.end())
@@ -2513,6 +2517,8 @@ const ScDPCache* ScDPCollection::SheetCaches::getCache(const ScRange& rRange)
     ::std::auto_ptr<ScDPCache> pCache(new ScDPCache(mpDoc));
     SAL_WNODEPRECATED_DECLARATIONS_POP
     pCache->InitFromDoc(mpDoc, rRange);
+    if (pDimData)
+        pDimData->WriteToCache(*pCache);
 
     // Get the smallest available range index.
     it = std::find_if(maRanges.begin(), maRanges.end(), FindInvalidRange());
@@ -2573,7 +2579,8 @@ void ScDPCollection::SheetCaches::updateReference(
     }
 }
 
-void ScDPCollection::SheetCaches::updateCache(const ScRange& rRange, std::set<ScDPObject*>& rRefs)
+void ScDPCollection::SheetCaches::updateCache(
+    const ScRange& rRange, const ScDPDimensionSaveData* pDimData, std::set<ScDPObject*>& rRefs)
 {
     RangeIndexType::iterator it = std::find(maRanges.begin(), maRanges.end(), rRange);
     if (it == maRanges.end())
@@ -2594,6 +2601,9 @@ void ScDPCollection::SheetCaches::updateCache(const ScRange& rRange, std::set<Sc
 
     ScDPCache& rCache = *itCache->second;
     rCache.InitFromDoc(mpDoc, rRange);
+    if (pDimData)
+        pDimData->WriteToCache(rCache);
+
     std::set<ScDPObject*> aRefs(rCache.GetAllReferences());
     rRefs.swap(aRefs);
 }
@@ -2621,7 +2631,8 @@ bool ScDPCollection::NameCaches::hasCache(const OUString& rName) const
     return maCaches.count(rName) != 0;
 }
 
-const ScDPCache* ScDPCollection::NameCaches::getCache(const OUString& rName, const ScRange& rRange)
+const ScDPCache* ScDPCollection::NameCaches::getCache(
+    const OUString& rName, const ScRange& rRange, const ScDPDimensionSaveData* pDimData)
 {
     CachesType::const_iterator itr = maCaches.find(rName);
     if (itr != maCaches.end())
@@ -2632,6 +2643,9 @@ const ScDPCache* ScDPCollection::NameCaches::getCache(const OUString& rName, con
     ::std::auto_ptr<ScDPCache> pCache(new ScDPCache(mpDoc));
     SAL_WNODEPRECATED_DECLARATIONS_POP
     pCache->InitFromDoc(mpDoc, rRange);
+    if (pDimData)
+        pDimData->WriteToCache(*pCache);
+
     const ScDPCache* p = pCache.get();
     maCaches.insert(rName, pCache);
     return p;
@@ -2642,7 +2656,9 @@ size_t ScDPCollection::NameCaches::size() const
     return maCaches.size();
 }
 
-void ScDPCollection::NameCaches::updateCache(const OUString& rName, const ScRange& rRange, std::set<ScDPObject*>& rRefs)
+void ScDPCollection::NameCaches::updateCache(
+    const OUString& rName, const ScRange& rRange, const ScDPDimensionSaveData* pDimData,
+    std::set<ScDPObject*>& rRefs)
 {
     CachesType::iterator itr = maCaches.find(rName);
     if (itr == maCaches.end())
@@ -2653,6 +2669,9 @@ void ScDPCollection::NameCaches::updateCache(const OUString& rName, const ScRang
 
     ScDPCache& rCache = *itr->second;
     rCache.InitFromDoc(mpDoc, rRange);
+    if (pDimData)
+        pDimData->WriteToCache(rCache);
+
     std::set<ScDPObject*> aRefs(rCache.GetAllReferences());
     rRefs.swap(aRefs);
 }
@@ -2688,7 +2707,9 @@ bool ScDPCollection::DBCaches::hasCache(sal_Int32 nSdbType, const OUString& rDBN
     return itr != maCaches.end();
 }
 
-const ScDPCache* ScDPCollection::DBCaches::getCache(sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand)
+const ScDPCache* ScDPCollection::DBCaches::getCache(
+    sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand,
+    const ScDPDimensionSaveData* pDimData)
 {
     DBType aType(nSdbType, rDBName, rCommand);
     CachesType::const_iterator itr = maCaches.find(aType);
@@ -2705,6 +2726,9 @@ const ScDPCache* ScDPCollection::DBCaches::getCache(sal_Int32 nSdbType, const OU
     SAL_WNODEPRECATED_DECLARATIONS_POP
     SvNumberFormatter aFormat(mpDoc->GetServiceManager(), ScGlobal::eLnge);
     pCache->InitFromDataBase(xRowSet, *aFormat.GetNullDate());
+    if (pDimData)
+        pDimData->WriteToCache(*pCache);
+
     ::comphelper::disposeComponent(xRowSet);
     const ScDPCache* p = pCache.get();
     maCaches.insert(aType, pCache);
@@ -2776,7 +2800,8 @@ uno::Reference<sdbc::XRowSet> ScDPCollection::DBCaches::createRowSet(
 }
 
 void ScDPCollection::DBCaches::updateCache(
-    sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand, std::set<ScDPObject*>& rRefs)
+    sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand,
+    const ScDPDimensionSaveData* pDimData, std::set<ScDPObject*>& rRefs)
 {
     DBType aType(nSdbType, rDBName, rCommand);
     CachesType::iterator it = maCaches.find(aType);
@@ -2803,6 +2828,8 @@ void ScDPCollection::DBCaches::updateCache(
         rRefs.clear();
         return;
     }
+    if (pDimData)
+        pDimData->WriteToCache(rCache);
 
     comphelper::disposeComponent(xRowSet);
     std::set<ScDPObject*> aRefs(rCache.GetAllReferences());
@@ -2865,6 +2892,14 @@ public:
 
 sal_uLong ScDPCollection::ReloadCache(ScDPObject* pDPObj, std::set<ScDPObject*>& rRefs)
 {
+    if (!pDPObj)
+        return STR_ERR_DATAPILOTSOURCE;
+
+    const ScDPSaveData* pSaveData = pDPObj->GetSaveData();
+    const ScDPDimensionSaveData* pDimData = NULL;
+    if (pSaveData)
+        pDimData = pSaveData->GetExistingDimensionData();
+
     if (pDPObj->IsSheetData())
     {
         // data source is internal sheet.
@@ -2881,7 +2916,7 @@ sal_uLong ScDPCollection::ReloadCache(ScDPObject* pDPObj, std::set<ScDPObject*>&
             // cache by named range
             ScDPCollection::NameCaches& rCaches = GetNameCaches();
             if (rCaches.hasCache(pDesc->GetRangeName()))
-                rCaches.updateCache(pDesc->GetRangeName(), pDesc->GetSourceRange(), rRefs);
+                rCaches.updateCache(pDesc->GetRangeName(), pDesc->GetSourceRange(), pDimData, rRefs);
             else
             {
                 // Not cached yet.  Collect all tables that use this named
@@ -2894,7 +2929,7 @@ sal_uLong ScDPCollection::ReloadCache(ScDPObject* pDPObj, std::set<ScDPObject*>&
             // cache by cell range
             ScDPCollection::SheetCaches& rCaches = GetSheetCaches();
             if (rCaches.hasCache(pDesc->GetSourceRange()))
-                rCaches.updateCache(pDesc->GetSourceRange(), rRefs);
+                rCaches.updateCache(pDesc->GetSourceRange(), pDimData, rRefs);
             else
             {
                 // Not cached yet.  Collect all tables that use this range as
@@ -2913,7 +2948,7 @@ sal_uLong ScDPCollection::ReloadCache(ScDPObject* pDPObj, std::set<ScDPObject*>&
         ScDPCollection::DBCaches& rCaches = GetDBCaches();
         if (rCaches.hasCache(pDesc->GetCommandType(), pDesc->aDBName, pDesc->aObject))
             rCaches.updateCache(
-                pDesc->GetCommandType(), pDesc->aDBName, pDesc->aObject, rRefs);
+                pDesc->GetCommandType(), pDesc->aDBName, pDesc->aObject, pDimData, rRefs);
         else
         {
             // Not cached yet.  Collect all tables that use this range as
diff --git a/sc/source/core/data/dpsdbtab.cxx b/sc/source/core/data/dpsdbtab.cxx
index a4e732b..b085473 100644
--- a/sc/source/core/data/dpsdbtab.cxx
+++ b/sc/source/core/data/dpsdbtab.cxx
@@ -63,7 +63,7 @@ sal_Int32 ScImportSourceDesc::GetCommandType() const
     return nSdbType;
 }
 
-const ScDPCache* ScImportSourceDesc::CreateCache() const
+const ScDPCache* ScImportSourceDesc::CreateCache(const ScDPDimensionSaveData* pDimData) const
 {
     if (!mpDoc)
         return NULL;
@@ -73,7 +73,7 @@ const ScDPCache* ScImportSourceDesc::CreateCache() const
         return NULL;
 
     ScDPCollection::DBCaches& rCaches = mpDoc->GetDPCollection()->GetDBCaches();
-    return rCaches.getCache(nSdbType, aDBName, aObject);
+    return rCaches.getCache(nSdbType, aDBName, aObject, pDimData);
 }
 
 ScDatabaseDPData::ScDatabaseDPData(
diff --git a/sc/source/core/data/dpshttab.cxx b/sc/source/core/data/dpshttab.cxx
index bde9ea0..43911c8 100644
--- a/sc/source/core/data/dpshttab.cxx
+++ b/sc/source/core/data/dpshttab.cxx
@@ -299,7 +299,7 @@ bool ScSheetSourceDesc::operator== (const ScSheetSourceDesc& rOther) const
         maQueryParam  == rOther.maQueryParam;
 }
 
-const ScDPCache* ScSheetSourceDesc::CreateCache() const
+const ScDPCache* ScSheetSourceDesc::CreateCache(const ScDPDimensionSaveData* pDimData) const
 {
     if (!mpDoc)
         return NULL;
@@ -317,11 +317,11 @@ const ScDPCache* ScSheetSourceDesc::CreateCache() const
     {
         // Name-based data source.
         ScDPCollection::NameCaches& rCaches = pDPs->GetNameCaches();
-        return rCaches.getCache(GetRangeName(), GetSourceRange());
+        return rCaches.getCache(GetRangeName(), GetSourceRange(), pDimData);
     }
 
     ScDPCollection::SheetCaches& rCaches = pDPs->GetSheetCaches();
-    return rCaches.getCache(GetSourceRange());
+    return rCaches.getCache(GetSourceRange(), pDimData);
 }
 
 sal_uLong ScSheetSourceDesc::CheckSourceRange() const
diff --git a/sc/source/core/data/dptablecache.cxx b/sc/source/core/data/dptablecache.cxx
index 7301146..1c7f3a2 100644
--- a/sc/source/core/data/dptablecache.cxx
+++ b/sc/source/core/data/dptablecache.cxx
@@ -1058,6 +1058,7 @@ rtl::OUString ScDPCache::GetFormattedString(long nDim, const ScDPItemData& rItem
 void ScDPCache::AppendGroupField()
 {
     maGroupFields.push_back(new GroupItems);
+    fprintf(stdout, "ScDPCache::AppendGroupField:   added; new count = %d\n", maGroupFields.size());
 }
 
 void ScDPCache::ResetGroupItems(long nDim, const ScDPNumGroupInfo& rNumInfo)
diff --git a/sc/source/filter/excel/xepivot.cxx b/sc/source/filter/excel/xepivot.cxx
index 9ec7f5a..d1d5764 100644
--- a/sc/source/filter/excel/xepivot.cxx
+++ b/sc/source/filter/excel/xepivot.cxx
@@ -538,7 +538,12 @@ void XclExpPCField::InsertNumDateGroupItems( const ScDPObject& rDPObj, const ScD
     if( const ScSheetSourceDesc* pSrcDesc = rDPObj.GetSheetDesc() )
     {
         // get the string collection with original source elements
-        const ScDPCache* pCache = pSrcDesc->CreateCache();
+        const ScDPSaveData* pSaveData = rDPObj.GetSaveData();
+        const ScDPDimensionSaveData* pDimData = NULL;
+        if (pSaveData)
+            pDimData = pSaveData->GetExistingDimensionData();
+
+        const ScDPCache* pCache = pSrcDesc->CreateCache(pDimData);
         if (!pCache)
             return;
 
diff --git a/sc/source/ui/view/cellsh1.cxx b/sc/source/ui/view/cellsh1.cxx
index 7fb77ed..bdcf456 100644
--- a/sc/source/ui/view/cellsh1.cxx
+++ b/sc/source/ui/view/cellsh1.cxx
@@ -2156,7 +2156,12 @@ bool isDPSourceValid(const ScDPObject& rDPObj)
         if (!pDesc)
             return false;
 
-        const ScDPCache* pCache = pDesc->CreateCache();
+        const ScDPSaveData* pSaveData = rDPObj.GetSaveData();
+        const ScDPDimensionSaveData* pDimData = NULL;
+        if (pSaveData)
+            pDimData = pSaveData->GetExistingDimensionData();
+
+        const ScDPCache* pCache = pDesc->CreateCache(pDimData);
         if (!pCache)
             // cashe creation failed, probably due to invalid connection.
             return false;
commit 32b61ed8931acd97e488bc73486244c385a3a974
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Thu Mar 8 00:18:50 2012 -0500

    Get normal grouping to work again.

diff --git a/sc/source/core/data/dpgroup.cxx b/sc/source/core/data/dpgroup.cxx
index 1edf051..ffe0430 100644
--- a/sc/source/core/data/dpgroup.cxx
+++ b/sc/source/core/data/dpgroup.cxx
@@ -112,45 +112,6 @@ const sal_uInt16 SC_DP_LEAPYEAR = 1648;     // arbitrary leap year for date calc
 
 namespace {
 
-sal_Bool lcl_Search( SCCOL nSourceDim, const ScDPCache* pCache , const std::vector< SCROW >& vIdx, SCROW nNew , SCROW& rIndex)
-{
-    rIndex = vIdx.size();
-    sal_Bool bFound = false;
-    SCROW nLo = 0;
-    SCROW nHi = vIdx.size() - 1;
-    SCROW nIndex;
-    long nCompare;
-    while (nLo <= nHi)
-    {
-        nIndex = (nLo + nHi) / 2;
-
-        const ScDPItemData* pData  = pCache->GetItemDataById( nSourceDim, vIdx[nIndex] );
-        const ScDPItemData* pDataInsert = pCache->GetItemDataById( nSourceDim, nNew );
-
-        nCompare = ScDPItemData::Compare( *pData, *pDataInsert );
-        if (nCompare < 0)
-            nLo = nIndex + 1;
-        else
-        {
-            nHi = nIndex - 1;
-            if (nCompare == 0)
-            {
-                bFound = sal_True;
-                nLo = nIndex;
-            }
-        }
-    }
-    rIndex = nLo;
-    return bFound;
-}
-
-void lcl_Insert( SCCOL nSourceDim, const ScDPCache* pCache ,  std::vector< SCROW >& vIdx, SCROW nNew )
-{
-    SCROW nIndex = 0;
-    if ( !lcl_Search( nSourceDim, pCache, vIdx, nNew ,nIndex ) )
-        vIdx.insert( vIdx.begin()+nIndex, nNew  );
-}
-
 inline bool IsInteger( double fValue )
 {
     return rtl::math::approxEqual( fValue, rtl::math::approxFloor(fValue) );
@@ -613,21 +574,28 @@ const std::vector<SCROW>& ScDPGroupDimension::GetColumnEntries(
         return maMemberEntries;
     }
 
+    ScDPCache* pCache = const_cast<ScDPCache*>(rCacheTable.getCache());
     for (size_t i = 0, n = rOriginal.size(); i < n;  ++i)
     {
-        const ScDPItemData* pItemData = rCacheTable.getCache()->GetItemDataById(nSourceDim, rOriginal[i]);
-        if (!pItemData || !GetGroupForData(*pItemData))
+        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
-            maMemberEntries.push_back(rOriginal[i]);
+            SCROW nId = pCache->SetGroupItem(nGroupDim, *pItemData);
+            maMemberEntries.push_back(nId);
         }
     }
 
     for (size_t i = 0, n = aItems.size(); i < n; ++i)
     {
-        SCROW nNew = rCacheTable.getCache()->GetAdditionalItemID(aItems[i].GetName());
-        lcl_Insert ( (SCCOL)GetSourceDim(), rCacheTable.getCache(), maMemberEntries, nNew  );
+        SCROW nId = pCache->SetGroupItem(nGroupDim, aItems[i].GetName());
+        maMemberEntries.push_back(nId);
     }
+
     return maMemberEntries;
 }
 
@@ -1157,12 +1125,15 @@ void ScDPGroupTableData::FillGroupValues(SCROW* pItemDataIndex, long nCount, con
             pDateHelper = rGroupDim.GetDateHelper();
             if (!pDateHelper)                         // date is handled below
             {
-                const ScDPGroupItem* pGroupItem =
-                    rGroupDim.GetGroupForData(*GetMemberById(nSourceDim, pItemDataIndex[nDim]));
-
+                const ScDPItemData& rItem = *GetMemberById(nSourceDim, pItemDataIndex[nDim]);
+                const ScDPGroupItem* pGroupItem = rGroupDim.GetGroupForData(rItem);
                 if (pGroupItem)
+                {
                     pItemDataIndex[nDim] =
-                        pCache->GetIdByItemData(nColumn, ScDPItemData(pGroupItem->GetName()));
+                        pCache->GetIdByItemData(nColumn, pGroupItem->GetName());
+                }
+                else
+                    pItemDataIndex[nDim] = pCache->GetIdByItemData(nColumn, rItem);
             }
         }
         else if ( IsNumGroupDimension( nColumn ) )
diff --git a/sc/source/core/data/dptabsrc.cxx b/sc/source/core/data/dptabsrc.cxx
index e22dda2..32bbb34 100644
--- a/sc/source/core/data/dptabsrc.cxx
+++ b/sc/source/core/data/dptabsrc.cxx
@@ -2526,6 +2526,7 @@ ScDPMember* ScDPMembers::getByIndex(long nIndex) const
                     aName = rtl::OUString::valueOf(nVal);
 
                 // TODO: This needs fixing.
+                fprintf(stdout, "ScDPMembers::getByIndex:   FIXME\n");
                 ScDPItemData aData(nVal);
                 pNew = new ScDPMember(
                     pSource, nDim, nHier, nLev, pSource->GetCache()->GetAdditionalItemID(aData));
commit 6553fc9dd2cd5986e5127804ba25ad7abf14235c
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Wed Mar 7 22:21:23 2012 -0500

    Some adjustments.

diff --git a/sc/source/core/data/dpgroup.cxx b/sc/source/core/data/dpgroup.cxx
index 2d175da..1edf051 100644
--- a/sc/source/core/data/dpgroup.cxx
+++ b/sc/source/core/data/dpgroup.cxx
@@ -599,34 +599,34 @@ void ScDPGroupDimension::SetGroupDim( long nDim )
     if (pDateHelper)
         pDateHelper->SetGroupDim(nDim);
 }
-const std::vector< SCROW >&  ScDPGroupDimension::GetColumnEntries( const ScDPCacheTable&  rCacheTable, const std::vector< SCROW >& rOriginal  )  const
+
+const std::vector<SCROW>& ScDPGroupDimension::GetColumnEntries(
+    const ScDPCacheTable& rCacheTable, const std::vector<SCROW>& rOriginal) const
 {
-    if ( maMemberEntries.empty() )
+    if (!maMemberEntries.empty())
+        return maMemberEntries;
+
+    if (pDateHelper)
     {
-        if ( pDateHelper )
+        pDateHelper->FillColumnEntries(
+            GetSourceDim(), const_cast<ScDPCache*>(rCacheTable.getCache()), maMemberEntries, rOriginal);
+        return maMemberEntries;
+    }
+
+    for (size_t i = 0, n = rOriginal.size(); i < n;  ++i)
+    {
+        const ScDPItemData* pItemData = rCacheTable.getCache()->GetItemDataById(nSourceDim, rOriginal[i]);
+        if (!pItemData || !GetGroupForData(*pItemData))
         {
-            pDateHelper->FillColumnEntries(
-                GetSourceDim(), const_cast<ScDPCache*>(rCacheTable.getCache()), maMemberEntries, rOriginal);
+            // not in any group -> add as its own group
+            maMemberEntries.push_back(rOriginal[i]);
         }
-        else
-        {
-            for (size_t  i =0; i < rOriginal.size( );  i ++)
-            {
-                const  ScDPItemData* pItemData = rCacheTable.getCache()->GetItemDataById( (SCCOL)GetSourceDim(), rOriginal[i] );
-                if ( !pItemData || !GetGroupForData( *pItemData ) )
-                {
-                    // not in any group -> add as its own group
-                    maMemberEntries.push_back( rOriginal[i] );
-                }
-            }
+    }
 
-            long nCount = aItems.size();
-            for (long i=0; i<nCount; i++)
-            {
-                SCROW nNew = rCacheTable.getCache()->GetAdditionalItemID(  aItems[i].GetName() );
-                lcl_Insert ( (SCCOL)GetSourceDim(), rCacheTable.getCache(), maMemberEntries, nNew  );
-            }
-        }
+    for (size_t i = 0, n = aItems.size(); i < n; ++i)
+    {
+        SCROW nNew = rCacheTable.getCache()->GetAdditionalItemID(aItems[i].GetName());
+        lcl_Insert ( (SCCOL)GetSourceDim(), rCacheTable.getCache(), maMemberEntries, nNew  );
     }
     return maMemberEntries;
 }
@@ -635,8 +635,8 @@ const std::vector< SCROW >&  ScDPGroupDimension::GetColumnEntries( const ScDPCac
 
 const ScDPGroupItem* ScDPGroupDimension::GetGroupForData( const ScDPItemData& rData ) const
 {
-    for ( ScDPGroupItemVec::const_iterator aIter(aItems.begin()); aIter != aItems.end(); aIter++ )
-        if ( aIter->HasElement( rData ) )
+    for (ScDPGroupItemVec::const_iterator aIter = aItems.begin(); aIter != aItems.end(); ++aIter)
+        if (aIter->HasElement(rData))
             return &*aIter;
 
     return NULL;
diff --git a/sc/source/core/data/dptabdat.cxx b/sc/source/core/data/dptabdat.cxx
index fd78b8b..0fd0f1f 100644
--- a/sc/source/core/data/dptabdat.cxx
+++ b/sc/source/core/data/dptabdat.cxx
@@ -281,7 +281,7 @@ const ScDPItemData* ScDPTableData::GetMemberByIndex( long nDim, long nIndex )
 const ScDPItemData* ScDPTableData::GetMemberById( long nDim, long nId)
 {
 
-    return GetCacheTable().getCache()->GetItemDataById( (SCCOL) nDim, (SCROW)nId);
+    return GetCacheTable().getCache()->GetItemDataById(nDim, static_cast<SCROW>(nId));
 }
 
 SCROW   ScDPTableData::GetIdOfItemData( long  nDim, const ScDPItemData& rData )
diff --git a/sc/source/core/data/dptabsrc.cxx b/sc/source/core/data/dptabsrc.cxx
index bece98c..e22dda2 100644
--- a/sc/source/core/data/dptabsrc.cxx
+++ b/sc/source/core/data/dptabsrc.cxx
@@ -2734,24 +2734,15 @@ const ScDPItemData& ScDPMember::GetItemData() const
 
 const ScDPItemData* ScDPSource::GetItemDataById(long nDim, long nId)
 {
-    long nSrcDim = GetSourceDim( nDim );
-    const ScDPItemData* pItemData = GetData()->GetMemberById(  nSrcDim,  nId );
-    if ( !pItemData )
-   { //todo:
-           ScDPItemData item;
-           nId = GetCache()->GetAdditionalItemID( item );
-        pItemData = GetData()->GetMemberById(  nSrcDim,  nId );
-    }
-   return pItemData;
+    return GetData()->GetMemberById(nDim, nId);
 }
 
-SCROW  ScDPSource::GetMemberId(  long  nDim, const ScDPItemData& rData )
+SCROW ScDPSource::GetMemberId(long nDim, const ScDPItemData& rData)
 {
-    long nSrcDim = GetSourceDim( nDim );
-       return  GetCache()->GetIdByItemData(  nSrcDim, rData );
+    return GetCache()->GetIdByItemData(nDim, rData);
 }
 
-const ScDPItemData* ScDPMembers::GetSrcItemDataByIndex( SCROW nIndex)
+const ScDPItemData* ScDPMembers::GetSrcItemDataByIndex(SCROW nIndex)
 {
     const std::vector< SCROW >& memberIds = pSource->GetData()->GetColumnEntries( nDim );
     if ( nIndex >= (long )(memberIds.size()) || nIndex < 0 )
commit 57c0ff6602dfbd0b7622a643e179923bf632cd87
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Wed Mar 7 22:07:09 2012 -0500

    Properly display grouped range values for range-based grouping.

diff --git a/sc/inc/dpgroup.hxx b/sc/inc/dpgroup.hxx
index cff5c4b..b90c667 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 00b7cd4..926ce7a 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 1d5d05d..2e0196d 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 cb2b9df..b877130 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 0aff4b2..68414f3 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 2e986ce..2d175da 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 01538a8..8f16a33 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;

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list