ooo-build r15085 - in branches/ooo-build-3-0-1: . patches/dev300



Author: kyoshida
Date: Thu Jan 15 21:29:26 2009
New Revision: 15085
URL: http://svn.gnome.org/viewvc/ooo-build?rev=15085&view=rev

Log:
2009-01-15  Kohei Yoshida  <kyoshida novell com>

	* patches/dev300/calc-dp-drilldown-hidden-items.diff:
	* patches/dev300/apply: ported from opensuse-11-1 branch.


Added:
   branches/ooo-build-3-0-1/patches/dev300/calc-dp-drilldown-hidden-items.diff
Modified:
   branches/ooo-build-3-0-1/ChangeLog
   branches/ooo-build-3-0-1/patches/dev300/apply

Modified: branches/ooo-build-3-0-1/patches/dev300/apply
==============================================================================
--- branches/ooo-build-3-0-1/patches/dev300/apply	(original)
+++ branches/ooo-build-3-0-1/patches/dev300/apply	Thu Jan 15 21:29:26 2009
@@ -1813,6 +1813,10 @@
 # strip the fraction part of a date-time value when using DATEVALUE.
 calc-formula-datevalue-strip-time.diff, i#94765, kohei
 
+# correctly evaluate the visibility of dimension members when generating a
+# drill-down sheet & also reduce memory use on cache tables.
+calc-dp-drilldown-hidden-items.diff i#93918, i#93998, kohei
+
 [ CalcExperimental ]
 
 # Implement external range names.

Added: branches/ooo-build-3-0-1/patches/dev300/calc-dp-drilldown-hidden-items.diff
==============================================================================
--- (empty file)
+++ branches/ooo-build-3-0-1/patches/dev300/calc-dp-drilldown-hidden-items.diff	Thu Jan 15 21:29:26 2009
@@ -0,0 +1,1604 @@
+diff --git sc/inc/dpcachetable.hxx sc/inc/dpcachetable.hxx
+index e894eed..deaa0f2 100644
+--- sc/inc/dpcachetable.hxx
++++ sc/inc/dpcachetable.hxx
+@@ -38,8 +38,8 @@
+ #include "collect.hxx"
+ 
+ #include <vector>
+-#include <set>
+ #include <hash_map>
++#include <hash_set>
+ #include <boost/shared_ptr.hpp>
+ #include <com/sun/star/uno/Reference.hxx>
+ 
+@@ -57,62 +57,24 @@ class Date;
+ class ScDocument;
+ class ScRange;
+ class ScDPDimension;
++class ScDPCollection;
++class ScDPCacheCell;
+ struct ScDPItemData;
+ class Date;
+ 
+ // ----------------------------------------------------------------------------
+ 
+-/** public interface for string-sharing */
+-class ScSharedString
+-{
+-public:
+-    static const sal_Int32 EMPTY = 0;
+-
+-    static const String*    getString(sal_Int32 nId);
+-    static sal_Int32        getStringId(const String& aStr);
+-    static sal_Int32        insertString(const String& aStr);
+-
+-private:
+-
+-    /** internal shared string table implementation */
+-    class StringTable
+-    {
+-    public:
+-        sal_Int32 insertString(const String& aStr);
+-        sal_Int32 getStringId(const String& aStr);
+-        const String* getString(sal_Int32 nId) const;
+-    
+-        StringTable();
+-        ~StringTable();
+-    
+-    private:
+-        typedef ::std::hash_map< String, sal_Int32, ScStringHashCode, ::std::equal_to< String > > SharedStrMap;
+-    
+-        ::std::vector<String> maSharedStrings;
+-        SharedStrMap maSharedStringIds;
+-        sal_Int32 mnStrCount;
+-    };
+-
+-    static ::osl::Mutex maStrMutex;
+-    static StringTable maStringTable;
+-};
+-
+-// ----------------------------------------------------------------------------
+-
+ class ScDPCacheTable
+ {
+ public:
+ 
+-    /** individual cell within table. */
+     struct Cell
+     {
+-        SCROW       mnCategoryRef;
+-        sal_Int32   mnStrId;
+-        sal_uInt8   mnType;
+-        double      mfValue;
+-        bool        mbNumeric;
++        SCROW           mnCategoryRef;
++        ScDPCacheCell*  mpContent;
+ 
+         Cell();
++        ~Cell();
+     };
+ 
+     /** individual filter item used in SingleFilter and GroupFilter. */
+@@ -131,38 +93,47 @@ public:
+     public:
+         /** returns true if the matching condition is met for a single cell
+             value, or false otherwise. */
+-        virtual bool match(const Cell& rCell) const = 0;
++        virtual bool match(const ScDPCacheCell& rCell) const = 0;
+     };
+ 
+     /** ordinary single-item filter. */
+     class SingleFilter : public FilterBase
+     {
+     public:
+-        explicit SingleFilter();
+-        explicit SingleFilter(sal_Int32 nMatchStrId, double fValue, bool bHasValue);
++        explicit SingleFilter(ScSimpleSharedString& rSharedString, 
++                              sal_Int32 nMatchStrId, double fValue, bool bHasValue);
+ 
+-        virtual bool match(const Cell& rCell) const;
++        virtual bool match(const ScDPCacheCell& rCell) const;
+ 
+-        const String    getMatchString() const;
++        const String    getMatchString();
+         double          getMatchValue() const;
+         bool            hasValue() const;
+ 
+     private:
++        explicit SingleFilter();
++
+         FilterItem  maItem;
++        ScSimpleSharedString mrSharedString;
+     };
+ 
+     /** multi-item (group) filter. */
+     class GroupFilter : public FilterBase
+     {
+     public:
+-        GroupFilter();
++        GroupFilter(ScSimpleSharedString& rSharedString);
+         virtual ~GroupFilter(){}
+-        virtual bool match(const Cell& rCell) const;
++        virtual bool match(const ScDPCacheCell& rCell) const;
+ 
++        void setMatchIfFound(bool b);
+         void addMatchItem(const String& rStr, double fVal, bool bHasValue);
++        size_t getMatchItemCount() const;
+ 
+     private:
++        GroupFilter();
++
+         ::std::vector<FilterItem> maItems;
++        ScSimpleSharedString mrSharedString;
++        bool mbMatchIfFound;
+     };
+ 
+     /** single filtering criterion. */
+@@ -174,7 +145,7 @@ public:
+         Criterion();
+     };
+ 
+-    ScDPCacheTable();
++    ScDPCacheTable(ScDPCollection* pCollection);
+     ~ScDPCacheTable();
+ 
+     sal_Int32 getHeaderSize() const;
+@@ -203,7 +174,7 @@ public:
+     /** Get the cell instance at specified location within the data grid. Note
+         that the data grid doesn't include the header row.  Don't delete the
+         returned object! */
+-    const ::ScDPCacheTable::Cell* getCell(SCCOL nCol, SCROW nRow, bool bRepeatIfEmpty = false) const;
++    const ScDPCacheCell* getCell(SCCOL nCol, SCROW nRow, bool bRepeatIfEmpty = false) const;
+ 
+     const String* getFieldName(sal_Int32 nIndex) const;
+ 
+@@ -229,12 +200,14 @@ public:
+     bool empty() const;
+ 
+ private:
++    ScDPCacheTable();
++    ScDPCacheTable(const ScDPCacheTable&);
++
+     /**
+      * Check if a given row meets all specified criteria. 
+      */
+     bool isRowQualified(sal_Int32 nRow, const ::std::vector<Criterion>& rCriteria, bool bRepeatIfEmpty) const;
+-    void getValueData(ScDocument* pDoc, const ScAddress& rPos, Cell& rCell);
+-    ScDPCacheTable::Cell getSelectedDimension(ScDPDimension* pDim) const;
++    void getValueData(ScDocument* pDoc, const ScAddress& rPos, ScDPCacheCell& rCell);
+ 
+ private:
+     typedef ::boost::shared_ptr<TypedStrCollection> TypedStrCollectionPtr;
+@@ -251,6 +224,9 @@ private:
+     /** used to track visibility of rows.  The first row below the header row
+         has the index of 0. */
+     ::std::vector<bool> maRowsVisible;
++
++    ScSimpleSharedString& mrSharedString;
++    ScDPCollection* mpCollection;
+ };
+ 
+ 
+diff --git sc/inc/dpgroup.hxx sc/inc/dpgroup.hxx
+index 391f5fb..1749a1a 100644
+--- sc/inc/dpgroup.hxx
++++ sc/inc/dpgroup.hxx
+@@ -196,7 +196,7 @@ class ScDPGroupTableData : public ScDPTableData
+     void        GetNumGroupInfo( long nDimension, ScDPNumGroupInfo& rInfo,
+                                     bool& rNonInteger, sal_Unicode& rDecimal );
+ 
+-    void        ModifyFilterCriteria(::std::vector<ScDPCacheTable::Criterion>& rCriteria) const;
++    void        ModifyFilterCriteria(::std::vector<ScDPCacheTable::Criterion>& rCriteria);
+ 
+ public:
+                 // takes ownership of pSource
+diff --git sc/inc/dpobject.hxx sc/inc/dpobject.hxx
+index fb62f81..6a2978b 100644
+--- sc/inc/dpobject.hxx
++++ sc/inc/dpobject.hxx
+@@ -250,11 +250,39 @@ public:
+                             PivotField* pRefPageFields = NULL, SCSIZE nRefPageCount = 0 );
+ };
+ 
++// ============================================================================
++
++struct ScDPCacheCell
++{
++    sal_Int32   mnStrId;
++    sal_uInt8   mnType;
++    double      mfValue;
++    bool        mbNumeric;
++
++    ScDPCacheCell();
++    ScDPCacheCell(const ScDPCacheCell& r);
++    ~ScDPCacheCell();
++};
++
++// ============================================================================
+ 
+ class ScDPCollection : public Collection
+ {
+ private:
+ 	ScDocument*	pDoc;
++    ScSimpleSharedString maSharedString;
++
++    struct CacheCellHash
++    {
++        size_t operator()(const ScDPCacheCell* pCell) const;
++    };
++    struct CacheCellEqual
++    {
++        bool operator()(const ScDPCacheCell* p1, const ScDPCacheCell* p2) const;
++    };
++    typedef ::std::hash_set<ScDPCacheCell*, CacheCellHash, CacheCellEqual> CacheCellPoolType;
++
++    CacheCellPoolType maCacheCellPool;
+ 
+ public:
+ 				ScDPCollection(ScDocument* pDocument);
+@@ -279,7 +307,12 @@ public:
+ 	void		WriteRefsTo( ScDPCollection& r ) const;
+ 
+ 	String 		CreateNewName( USHORT nMin = 1 ) const;
+-	void		EnsureNames();
++ 	void		EnsureNames();
++
++    ScSimpleSharedString& GetSharedString();
++
++    ScDPCacheCell* getCacheCellFromPool(const ScDPCacheCell& rCell);
++    void clearCacheCellPool();
+ };
+ 
+ 
+diff --git sc/inc/dpsdbtab.hxx sc/inc/dpsdbtab.hxx
+index c007658..788ad86 100644
+--- sc/inc/dpsdbtab.hxx
++++ sc/inc/dpsdbtab.hxx
+@@ -44,6 +44,7 @@ namespace com { namespace sun { namespace star {
+ #include <set>
+ 
+ class ScDPCacheTable;
++class ScDocument;
+ 
+ // --------------------------------------------------------------------
+ //
+@@ -75,6 +76,7 @@ private:
+ 
+ public:
+ 					ScDatabaseDPData(
++                        ScDocument* pDoc,
+ 						::com::sun::star::uno::Reference<
+ 							::com::sun::star::lang::XMultiServiceFactory > xSMgr,
+ 						const ScImportSourceDesc& rImport );
+diff --git sc/inc/dptabdat.hxx sc/inc/dptabdat.hxx
+index acb8ce0..4946df3 100644
+--- sc/inc/dptabdat.hxx
++++ sc/inc/dptabdat.hxx
+@@ -46,6 +46,7 @@ namespace com { namespace sun { namespace star { namespace sheet {
+ }}}}
+ 
+ class TypedStrCollection;
++class ScSimpleSharedString;
+ 
+ // -----------------------------------------------------------------------
+ 
+@@ -112,6 +113,7 @@ class ScDPDimension;
+ class ScDPLevel;
+ class ScDPInitState;
+ class ScDPResultMember;
++class ScDocument;
+ 
+ class ScDPTableData
+ {
+@@ -120,6 +122,7 @@ class ScDPTableData
+ 	long 	nLastHier;
+ 	long 	nLastLevel;
+ 	long 	nLastRet;
++    ScSimpleSharedString& mrSharedString;
+ 
+ public:
+ 
+@@ -146,7 +149,7 @@ public:
+         CalcInfo();
+     };
+ 
+-				ScDPTableData();
++				ScDPTableData(ScDocument* pDoc);
+ 	virtual		~ScDPTableData();
+ 
+ 	long		GetDatePart( long nDateVal, long nHierarchy, long nLevel );
+@@ -165,11 +168,11 @@ public:
+ 
+     virtual bool                    IsRepeatIfEmpty();
+ 
+-    virtual void                    CreateCacheTable();
+-    virtual void                    FilterCacheTable(const ::std::vector<ScDPCacheTable::Criterion>& rCriteria);
++    virtual void                    CreateCacheTable() = 0;
++    virtual void                    FilterCacheTable(const ::std::vector<ScDPCacheTable::Criterion>& rCriteria) = 0;
+     virtual void                    GetDrillDownData(const ::std::vector<ScDPCacheTable::Criterion>& rCriteria,
+-                                                     ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > >& rData);
+-    virtual void                    CalcResults(CalcInfo& rInfo, bool bAutoShow);
++                                                     ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > >& rData) = 0;
++    virtual void                    CalcResults(CalcInfo& rInfo, bool bAutoShow) = 0;
+     virtual const ScDPCacheTable&   GetCacheTable() const = 0;
+ 
+                                     // overloaded in ScDPGroupTableData:
+@@ -181,6 +184,8 @@ public:
+     virtual BOOL                    HasCommonElement( const ScDPItemData& rFirstData, long nFirstIndex,
+                                                       const ScDPItemData& rSecondData, long nSecondIndex ) const;
+ 
++    ScSimpleSharedString&           GetSharedString();
++
+ protected:
+     /** This structure stores vector arrays that hold intermediate data for
+         each row during cache table iteration. */
+diff --git sc/inc/dptabres.hxx sc/inc/dptabres.hxx
+index dbe1b35..3fb5ef8 100644
+--- sc/inc/dptabres.hxx
++++ sc/inc/dptabres.hxx
+@@ -31,14 +31,15 @@
+ #ifndef SC_DPTABRES_HXX
+ #define SC_DPTABRES_HXX
+ 
+-#include <vector>
+ #include <svtools/svarray.hxx>
+ #include <tools/string.hxx>
+ #include <com/sun/star/sheet/MemberResult.hpp>
+ #include <com/sun/star/sheet/DataResult.hpp>
+ #include <com/sun/star/uno/Sequence.hxx>
+ #include "global.hxx"		// enum ScSubTotalFunc
++#include "dpcachetable.hxx"
+ #include <hash_map>
++#include <hash_set>
+ #include <vector>
+ 
+ namespace com { namespace sun { namespace star { namespace sheet {
+@@ -50,10 +51,12 @@ class ScAddress;
+ class ScDocument;
+ class ScDPSource;
+ class ScDPDimension;
++class ScDPDimensions;
+ class ScDPLevel;
+ class ScDPMember;
+ class ScDPAggData;
+ class ScDPResultMember;
++class ScDPResultVisibilityData;
+ 
+ struct ScDPValueData;
+ struct ScDPItemData;
+@@ -370,6 +373,8 @@ public:
+ 	const ScDPLevel*				GetParentLevel() const			{ return pParentLevel; }	//! Ref
+ 
+ 	ScDPAggData*		GetColTotal( long nMeasure ) const;
++
++    void                FillVisibilityData(ScDPResultVisibilityData& rData) const;
+ };
+ 
+ class ScDPDataMember
+@@ -538,6 +543,8 @@ public:
+ 	long                GetAutoCount() const    { return nAutoCount; }
+ 
+ 	ScDPResultDimension* GetFirstChildDimension() const;
++
++    void                FillVisibilityData(ScDPResultVisibilityData& rData) const;
+ };
+ 
+ class ScDPDataDimension
+@@ -580,5 +587,33 @@ public:
+ 	ScDPDataMember*		GetMember(long n) const;
+ };
+ 
++// ----------------------------------------------------------------------------
++
++/** 
++ * This class collects visible members of each dimension and uses that
++ * information to create filtering criteria (e.g. for drill-down data).
++ */
++class ScDPResultVisibilityData
++{
++public:
++    ScDPResultVisibilityData(ScSimpleSharedString& rSharedString, ScDPSource* pSource);
++    ~ScDPResultVisibilityData();
++
++    void addVisibleMember(const String& rDimName, const ScDPItemData& rMemberItem);
++    void fillFieldFilters(::std::vector<ScDPCacheTable::Criterion>& rFilters) const;
++
++private:
++    struct MemberHash
++    {
++        size_t operator()(const ScDPItemData& r) const;
++    };
++    typedef ::std::hash_set<ScDPItemData, MemberHash> VisibleMemberType;
++    typedef ::std::hash_map<String, VisibleMemberType, ScStringHashCode> DimMemberType;
++    DimMemberType maDimensions;
++
++    ScSimpleSharedString& mrSharedString;
++    ScDPSource* mpSource;
++};
++
+ #endif
+ 
+diff --git sc/inc/global.hxx sc/inc/global.hxx
+index 7cd5b8b..f239322 100644
+--- sc/inc/global.hxx
++++ sc/inc/global.hxx
+@@ -38,6 +38,8 @@
+ #include <com/sun/star/uno/Reference.hxx>
+ #include "scdllapi.h"
+ 
++#include <hash_map>
++
+ class ImageList;
+ class Bitmap;
+ class SfxItemSet;
+@@ -895,6 +897,46 @@ struct ScConsolidateParam
+ };
+ 
+ // -----------------------------------------------------------------------
++
++class ScSimpleSharedString
++{
++public:
++    static const sal_Int32 EMPTY = 0;
++
++    ScSimpleSharedString();
++    ScSimpleSharedString(const ScSimpleSharedString& r);
++    ~ScSimpleSharedString();
++
++    const String*    getString(sal_Int32 nId);
++    sal_Int32        getStringId(const String& aStr);
++    sal_Int32        insertString(const String& aStr);
++
++private:
++
++    /** internal shared string table implementation */
++    class StringTable
++    {
++    public:
++        sal_Int32 insertString(const String& aStr);
++        sal_Int32 getStringId(const String& aStr);
++        const String* getString(sal_Int32 nId) const;
++    
++        StringTable();
++        StringTable(const StringTable& r);
++        ~StringTable();
++    
++    private:
++        typedef ::std::hash_map< String, sal_Int32, ScStringHashCode, ::std::equal_to< String > > SharedStrMap;
++    
++        ::std::vector<String> maSharedStrings;
++        SharedStrMap maSharedStringIds;
++        sal_Int32 mnStrCount;
++    };
++
++    StringTable maStringTable;
++};
++
++// -----------------------------------------------------------------------
+ extern ::utl::TransliterationWrapper* GetScGlobalpTransliteration();//CHINA001
+ extern const LocaleDataWrapper* GetScGlobalpLocaleData();
+ 
+diff --git sc/source/core/data/dpcachetable.cxx sc/source/core/data/dpcachetable.cxx
+index 1be291c..07a54f3 100644
+--- sc/source/core/data/dpcachetable.cxx
++++ sc/source/core/data/dpcachetable.cxx
+@@ -37,8 +37,7 @@
+ #include "cell.hxx"
+ #include "dptabdat.hxx"
+ #include "dptabsrc.hxx"
+-
+-#include <stdio.h>
++#include "dpobject.hxx"
+ 
+ #include <com/sun/star/i18n/LocaleDataItem.hpp>
+ #include <com/sun/star/sdbc/DataType.hpp>
+@@ -56,7 +55,7 @@ using namespace ::com::sun::star;
+ 
+ using ::rtl::OUString;
+ using ::std::vector;
+-using ::std::set;
++using ::std::pair;
+ using ::std::hash_map;
+ using ::std::auto_ptr;
+ using ::com::sun::star::i18n::LocaleDataItem;
+@@ -76,94 +75,26 @@ static BOOL lcl_HasQueryEntry( const ScQueryParam& rParam )
+             rParam.GetEntry(0).bDoQuery;
+ }
+ 
+-ScSharedString::StringTable::StringTable() :
+-    mnStrCount(0)
+-{
+-    // empty string (ID = 0)
+-    maSharedStrings.push_back(String());
+-    maSharedStringIds.insert( SharedStrMap::value_type(String(), mnStrCount++) );
+-}
+-
+-ScSharedString::StringTable::~StringTable()
+-{
+-}
+-
+-sal_Int32 ScSharedString::StringTable::insertString(const String& aStr)
+-{
+-    SharedStrMap::const_iterator itr = maSharedStringIds.find(aStr),
+-        itrEnd = maSharedStringIds.end();
+-
+-    if (itr == itrEnd)
+-    {
+-        // new string.
+-        maSharedStrings.push_back(aStr);
+-        maSharedStringIds.insert( SharedStrMap::value_type(aStr, mnStrCount) );
+-        return mnStrCount++;
+-    }
+-
+-    // existing string.
+-    return itr->second;
+-}
+-
+-sal_Int32 ScSharedString::StringTable::getStringId(const String& aStr)
+-{
+-    SharedStrMap::const_iterator itr = maSharedStringIds.find(aStr),
+-        itrEnd = maSharedStringIds.end();
+-    if (itr == itrEnd)
+-    {
+-        // string not found.
+-        return insertString(aStr);
+-    }
+-    return itr->second;
+-}
+-
+-const String* ScSharedString::StringTable::getString(sal_Int32 nId) const
+-{
+-    if (nId >= mnStrCount)
+-        return NULL;
+-
+-    return &maSharedStrings[nId];
+-}
+-
+ // ----------------------------------------------------------------------------
+ 
+-// static
+-::osl::Mutex ScSharedString::maStrMutex;
+-ScSharedString::StringTable ScSharedString::maStringTable;
+-
+-sal_Int32 ScSharedString::insertString(const String& aStr)
+-{
+-    ::osl::MutexGuard aGuard(maStrMutex);
+-    return maStringTable.insertString(aStr);
+-}
+-
+-const String* ScSharedString::getString(sal_Int32 nId)
+-{
+-    ::osl::MutexGuard aGuard(maStrMutex);
+-    return maStringTable.getString(nId);
+-}
+-
+-sal_Int32 ScSharedString::getStringId(const String& aStr)
+-{
+-    ::osl::MutexGuard aGuard(maStrMutex);
+-    return maStringTable.getStringId(aStr);
+-}
++static ScDPCacheCell EmptyCellContent = ScDPCacheCell();
+ 
+ // ----------------------------------------------------------------------------
+ 
+ ScDPCacheTable::Cell::Cell() :
+     mnCategoryRef(0),
+-    mnStrId(ScSharedString::EMPTY),
+-    mnType(SC_VALTYPE_EMPTY),
+-    mfValue(0.0),
+-    mbNumeric(false)
++    mpContent(NULL)
++{
++}
++
++ScDPCacheTable::Cell::~Cell()
+ {
+ }
+ 
+ // ----------------------------------------------------------------------------
+ 
+ ScDPCacheTable::FilterItem::FilterItem() :
+-    mnMatchStrId(ScSharedString::EMPTY),
++    mnMatchStrId(ScSimpleSharedString::EMPTY),
+     mfValue(0.0),
+     mbHasValue(false)
+ {
+@@ -171,18 +102,16 @@ ScDPCacheTable::FilterItem::FilterItem() :
+ 
+ // ----------------------------------------------------------------------------
+ 
+-ScDPCacheTable::SingleFilter::SingleFilter()
+-{
+-}
+-
+-ScDPCacheTable::SingleFilter::SingleFilter(sal_Int32 nMatchStrId, double fValue, bool bHasValue)
++ScDPCacheTable::SingleFilter::SingleFilter(ScSimpleSharedString& rSharedString,
++                                           sal_Int32 nMatchStrId, double fValue, bool bHasValue) :
++    mrSharedString(rSharedString)
+ {
+     maItem.mnMatchStrId = nMatchStrId;
+     maItem.mfValue      = fValue;
+     maItem.mbHasValue   = bHasValue;
+ }
+ 
+-bool ScDPCacheTable::SingleFilter::match(const Cell& rCell) const
++bool ScDPCacheTable::SingleFilter::match(const ScDPCacheCell& rCell) const
+ {
+     if (rCell.mnStrId != maItem.mnMatchStrId &&
+         (!rCell.mbNumeric || rCell.mfValue != maItem.mfValue))
+@@ -191,9 +120,9 @@ bool ScDPCacheTable::SingleFilter::match(const Cell& rCell) const
+     return true;
+ }
+ 
+-const String ScDPCacheTable::SingleFilter::getMatchString() const
++const String ScDPCacheTable::SingleFilter::getMatchString()
+ {
+-    const String* pStr = ScSharedString::getString(maItem.mnMatchStrId);
++    const String* pStr = mrSharedString.getString(maItem.mnMatchStrId);
+     if (pStr)
+         return *pStr;
+ 
+@@ -212,11 +141,13 @@ bool ScDPCacheTable::SingleFilter::hasValue() const
+ 
+ // ----------------------------------------------------------------------------
+ 
+-ScDPCacheTable::GroupFilter::GroupFilter()
++ScDPCacheTable::GroupFilter::GroupFilter(ScSimpleSharedString& rSharedString) :
++    mrSharedString(rSharedString),
++    mbMatchIfFound(true)
+ {
+ }
+ 
+-bool ScDPCacheTable::GroupFilter::match(const Cell& rCell) const
++bool ScDPCacheTable::GroupFilter::match(const ScDPCacheCell& rCell) const
+ {
+     vector<FilterItem>::const_iterator itrEnd = maItems.end();
+     for (vector<FilterItem>::const_iterator itr = maItems.begin(); itr != itrEnd; ++itr)
+@@ -228,14 +159,19 @@ bool ScDPCacheTable::GroupFilter::match(const Cell& rCell) const
+             bMatch = (itr->mnMatchStrId == rCell.mnStrId);
+ 
+         if (bMatch)
+-            return true;
++            return mbMatchIfFound ? true : false;
+     }
+-    return false;
++    return mbMatchIfFound ? false : true;
++}
++
++void ScDPCacheTable::GroupFilter::setMatchIfFound(bool b)
++{
++    mbMatchIfFound = b;
+ }
+ 
+ void ScDPCacheTable::GroupFilter::addMatchItem(const String& rStr, double fVal, bool bHasValue)
+ {
+-    sal_Int32 nStrId = ScSharedString::getStringId(rStr);
++    sal_Int32 nStrId = mrSharedString.getStringId(rStr);
+     FilterItem aItem;
+     aItem.mnMatchStrId = nStrId;
+     aItem.mfValue = fVal;
+@@ -243,6 +179,11 @@ void ScDPCacheTable::GroupFilter::addMatchItem(const String& rStr, double fVal,
+     maItems.push_back(aItem);
+ }
+ 
++size_t ScDPCacheTable::GroupFilter::getMatchItemCount() const
++{
++    return maItems.size();
++}
++
+ // ----------------------------------------------------------------------------
+ 
+ ScDPCacheTable::Criterion::Criterion() :
+@@ -253,7 +194,9 @@ ScDPCacheTable::Criterion::Criterion() :
+ 
+ // ----------------------------------------------------------------------------
+ 
+-ScDPCacheTable::ScDPCacheTable()
++ScDPCacheTable::ScDPCacheTable(ScDPCollection* pCollection) :
++    mrSharedString(pCollection->GetSharedString()),
++    mpCollection(pCollection)
+ {
+ }
+ 
+@@ -300,7 +243,7 @@ void ScDPCacheTable::fillTable(ScDocument* pDoc, const ScRange& rRange, const Sc
+     {
+         String aStr;
+         pDoc->GetString(nCol + nStartCol, nStartRow, nTab, aStr);
+-        sal_Int32 nStrId = ScSharedString::insertString(aStr);
++        sal_Int32 nStrId = mrSharedString.insertString(aStr);
+         maHeader.push_back(nStrId);
+     }
+ 
+@@ -339,24 +282,28 @@ void ScDPCacheTable::fillTable(ScDocument* pDoc, const ScRange& rRange, const Sc
+             Cell& rCell = maTable.back().back();
+             rCell.mnCategoryRef = maTable.size()-1;
+ 
+-            if (nRow == 0 || pDoc->HasData(nStartCol + nCol, nStartRow + nRow, nTab))
++            String aCellStr;
++            bool bReadCell = nRow == 0 || pDoc->HasData(nStartCol + nCol, nStartRow + nRow, nTab);
++            if (bReadCell)
++            {    
+                 aLastNonEmptyRows[nCol] = maTable.size()-1;
++                ScDPCacheCell aCell;
++                pDoc->GetString(nStartCol + nCol, nStartRow + nRow, nTab, aCellStr);
++                aCell.mnStrId = mrSharedString.insertString(aCellStr);
++                aCell.mnType = SC_VALTYPE_STRING;
++                aCell.mbNumeric = false;
++                ScAddress aPos(nStartCol + nCol, nStartRow + nRow, nTab);
++                getValueData(pDoc, aPos, aCell);
++                rCell.mpContent = mpCollection->getCacheCellFromPool(aCell);
++            }
+             else
+                 rCell.mnCategoryRef = aLastNonEmptyRows[nCol];
+ 
+-            String aStr;
+-            pDoc->GetString(nStartCol + nCol, nStartRow + nRow, nTab, aStr);
+-            rCell.mnStrId = ScSharedString::insertString(aStr);
+-            rCell.mnType = SC_VALTYPE_STRING;
+-            rCell.mbNumeric = false;
+-            ScAddress aPos(nStartCol + nCol, nStartRow + nRow, nTab);
+-            getValueData(pDoc, aPos, rCell);
+-
+             TypedStrData* pNew;
+-            if (rCell.mbNumeric)
+-                pNew = new TypedStrData(aStr, rCell.mfValue, SC_STRTYPE_VALUE);
++            if (rCell.mpContent && rCell.mpContent->mbNumeric)
++                pNew = new TypedStrData(aCellStr, rCell.mpContent->mfValue, SC_STRTYPE_VALUE);
+             else
+-                pNew = new TypedStrData(aStr);
++                pNew = new TypedStrData(aCellStr);
+ 
+             if (!maFieldEntries[nCol]->Insert(pNew))
+                 delete pNew;
+@@ -365,14 +312,15 @@ void ScDPCacheTable::fillTable(ScDocument* pDoc, const ScRange& rRange, const Sc
+ }
+ 
+ void lcl_GetCellValue(const Reference<sdbc::XRow>& xRow, sal_Int32 nType, long nCol,
+-             const Date& rNullDate, ScDPCacheTable::Cell& rCell, String& rStr)
++                      const Date& rNullDate, ScDPCacheCell& rCell, String& rStr, 
++                      ScSimpleSharedString& rSharedString)
+ {
+     short nNumType = NUMBERFORMAT_NUMBER;
+     BOOL bEmptyFlag = FALSE;
+     try
+     {
+         rStr = xRow->getString(nCol);
+-        rCell.mnStrId = ScSharedString::getStringId(rStr);
++        rCell.mnStrId = rSharedString.getStringId(rStr);
+         rCell.mnType = SC_VALTYPE_STRING;
+ 
+         switch (nType)
+@@ -487,7 +435,7 @@ void ScDPCacheTable::fillTable(const Reference<sdbc::XRowSet>& xRowSet, const Da
+         {
+             String aColTitle = xMeta->getColumnLabel(nCol+1);
+             aColTypes[nCol]  = xMeta->getColumnType(nCol+1);
+-            maHeader.push_back( ScSharedString::getStringId(aColTitle) );
++            maHeader.push_back( mrSharedString.getStringId(aColTitle) );
+         }
+ 
+         // Initialize field entries container.
+@@ -513,12 +461,14 @@ void ScDPCacheTable::fillTable(const Reference<sdbc::XRowSet>& xRowSet, const Da
+             {
+                 maTable.back().push_back( Cell() );
+                 Cell& rCell = maTable.back().back();
++                ScDPCacheCell aCellContent;
+                 String aStr;
+-                lcl_GetCellValue(xRow, aColTypes[nCol], nCol+1, rNullDate, rCell, aStr);
++                lcl_GetCellValue(xRow, aColTypes[nCol], nCol+1, rNullDate, aCellContent, aStr, mrSharedString);
++                rCell.mpContent = mpCollection->getCacheCellFromPool(aCellContent);
+ 
+                 TypedStrData* pNew;
+-                if (rCell.mbNumeric)
+-                    pNew = new TypedStrData(aStr, rCell.mfValue, SC_STRTYPE_VALUE);
++                if (rCell.mpContent->mbNumeric)
++                    pNew = new TypedStrData(aStr, rCell.mpContent->mfValue, SC_STRTYPE_VALUE);
+                 else
+                     pNew = new TypedStrData(aStr);
+ 
+@@ -557,20 +507,21 @@ void ScDPCacheTable::filterByPageDimension(const vector<Criterion>& rCriteria, b
+         maRowsVisible[nRow] = isRowQualified(nRow, rCriteria, bRepeatIfEmpty);
+ }
+ 
+-const ::ScDPCacheTable::Cell* ScDPCacheTable::getCell(SCCOL nCol, SCROW nRow, bool bRepeatIfEmpty) const
++const ScDPCacheCell* ScDPCacheTable::getCell(SCCOL nCol, SCROW nRow, bool bRepeatIfEmpty) const
+ {
+     if ( nRow >= static_cast<SCROW>(maTable.size()) )
+         return NULL;
+ 
+-    const vector<Cell>& rRow = maTable.at(nRow);
++    const vector<Cell>& rRow = maTable[nRow];
+     if ( nCol < 0 || static_cast<size_t>(nCol) >= rRow.size() )
+         return NULL;
+ 
+-    const Cell* pCell = &rRow.at(nCol);
+-    if (bRepeatIfEmpty && pCell && pCell->mnType == SC_VALTYPE_EMPTY)
+-        pCell = getCell(nCol, pCell->mnCategoryRef, false);
++    const Cell& rCell = rRow[nCol];
++    const ScDPCacheCell* pCell = rCell.mpContent;
++    if (bRepeatIfEmpty && !pCell)
++        pCell = getCell(nCol, rCell.mnCategoryRef, false);
+ 
+-    return pCell;
++    return pCell ? pCell : &EmptyCellContent;
+ }
+ 
+ const String* ScDPCacheTable::getFieldName(sal_Int32 nIndex) const
+@@ -578,12 +529,12 @@ const String* ScDPCacheTable::getFieldName(sal_Int32 nIndex) const
+     if (nIndex >= static_cast<sal_Int32>(maHeader.size()))
+         return NULL;
+ 
+-    return ScSharedString::getString(maHeader[nIndex]);
++    return mrSharedString.getString(maHeader[nIndex]);
+ }
+ 
+ sal_Int32 ScDPCacheTable::getFieldIndex(const String& rStr) const
+ {
+-    sal_Int32 nStrId = ScSharedString::getStringId(rStr);
++    sal_Int32 nStrId = mrSharedString.getStringId(rStr);
+     if (nStrId < 0)
+         // string not found.
+         return nStrId;
+@@ -628,7 +579,7 @@ void ScDPCacheTable::filterTable(const vector<Criterion>& rCriteria, Sequence< S
+     for (sal_Int32 nCol = 0; nCol < nColSize; ++nCol)
+     {
+         OUString str;
+-        const String* pStr = ScSharedString::getString(maHeader[nCol]);
++        const String* pStr = mrSharedString.getString(maHeader[nCol]);
+         if (pStr)
+             str = *pStr;
+ 
+@@ -654,7 +605,7 @@ void ScDPCacheTable::filterTable(const vector<Criterion>& rCriteria, Sequence< S
+         for (SCCOL nCol = 0; nCol < nColSize; ++nCol)
+         {
+             Any any;
+-            const Cell* pCell = getCell(nCol, nRow, bRepeatIfEmpty);
++            const ScDPCacheCell* pCell = getCell(nCol, nRow, bRepeatIfEmpty);
+             if (!pCell)
+             {
+                 // This should never happen, but in case this happens, just
+@@ -670,7 +621,7 @@ void ScDPCacheTable::filterTable(const vector<Criterion>& rCriteria, Sequence< S
+             else
+             {
+                 OUString str;
+-                const String* pStr = ScSharedString::getString(pCell->mnStrId);
++                const String* pStr = mrSharedString.getString(pCell->mnStrId);
+                 if (pStr)
+                     str = *pStr;
+                 any <<= str;
+@@ -719,7 +670,7 @@ bool ScDPCacheTable::isRowQualified(sal_Int32 nRow, const vector<Criterion>& rCr
+             // use this criterion.
+             continue;
+ 
+-        const Cell* pCell = getCell(static_cast<SCCOL>(itr->mnFieldIndex), nRow, bRepeatIfEmpty);
++        const ScDPCacheCell* pCell = getCell(static_cast<SCCOL>(itr->mnFieldIndex), nRow, bRepeatIfEmpty);
+         if (!pCell)
+             // This should never happen, but just in case...
+             return false;
+@@ -730,7 +681,7 @@ bool ScDPCacheTable::isRowQualified(sal_Int32 nRow, const vector<Criterion>& rCr
+     return true;
+ }
+ 
+-void ScDPCacheTable::getValueData(ScDocument* pDoc, const ScAddress& rPos, Cell& rCell)
++void ScDPCacheTable::getValueData(ScDocument* pDoc, const ScAddress& rPos, ScDPCacheCell& rCell)
+ {
+     ScBaseCell* pCell = pDoc->GetCell(rPos);
+     if (!pCell)
+@@ -768,12 +719,3 @@ void ScDPCacheTable::getValueData(ScDocument* pDoc, const ScAddress& rPos, Cell&
+     }
+ }
+ 
+-ScDPCacheTable::Cell ScDPCacheTable::getSelectedDimension(ScDPDimension* pDim) const
+-{
+-    const ScDPItemData& rData = pDim->GetSelectedData();
+-    Cell aCell;
+-    aCell.mfValue = rData.fValue;
+-    aCell.mbNumeric = rData.bHasValue;
+-    aCell.mnStrId = ScSharedString::getStringId(rData.aString);
+-    return aCell;
+-}
+diff --git sc/source/core/data/dpgroup.cxx sc/source/core/data/dpgroup.cxx
+index 5cc1893..2c60d1b 100644
+--- sc/source/core/data/dpgroup.cxx
++++ sc/source/core/data/dpgroup.cxx
+@@ -49,6 +49,7 @@
+ #include "dpcachetable.hxx"
+ #include "dptabsrc.hxx"
+ #include "dptabres.hxx"
++#include "dpobject.hxx"
+ 
+ #include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
+ #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
+@@ -86,7 +87,7 @@ public:
+     ScDPGroupDateFilter(double fMatchValue, sal_Int32 nDatePart, 
+                         const Date* pNullDate, const ScDPNumGroupInfo* pNumInfo);
+ 
+-    virtual bool match(const ScDPCacheTable::Cell &rCell) const;
++    virtual bool match(const ScDPCacheCell &rCell) const;
+ 
+ private:
+     ScDPGroupDateFilter(); // disabled
+@@ -110,7 +111,7 @@ ScDPGroupDateFilter::ScDPGroupDateFilter(double fMatchValue, sal_Int32 nDatePart
+ //          mfMatchValue, mnDatePart);
+ }
+ 
+-bool ScDPGroupDateFilter::match(const ScDPCacheTable::Cell& rCell) const
++bool ScDPGroupDateFilter::match(const ScDPCacheCell& rCell) const
+ {
+     using namespace ::com::sun::star::sheet;
+     using ::rtl::math::approxFloor;
+@@ -977,6 +978,7 @@ String lcl_GetNumGroupForValue( double fValue, const ScDPNumGroupInfo& rInfo, bo
+ }
+ 
+ ScDPGroupTableData::ScDPGroupTableData( ScDPTableData* pSource, ScDocument* pDocument ) :
++    ScDPTableData(pDocument),
+     pSourceData( pSource ),
+     pDoc( pDocument )
+ {
+@@ -1136,7 +1138,7 @@ void ScDPGroupTableData::CreateCacheTable()
+     pSourceData->CreateCacheTable();
+ }
+ 
+-void ScDPGroupTableData::ModifyFilterCriteria(vector<ScDPCacheTable::Criterion>& rCriteria) const
++void ScDPGroupTableData::ModifyFilterCriteria(vector<ScDPCacheTable::Criterion>& rCriteria)
+ {
+     typedef hash_map<long, const ScDPGroupDimension*> GroupFieldMapType;
+     GroupFieldMapType aGroupFieldIds;
+@@ -1225,7 +1227,7 @@ void ScDPGroupTableData::ModifyFilterCriteria(vector<ScDPCacheTable::Criterion>&
+     
+                     ScDPCacheTable::Criterion aCri;
+                     aCri.mnFieldIndex = nSrcDim;
+-                    aCri.mpFilter.reset(new ScDPCacheTable::GroupFilter);
++                    aCri.mpFilter.reset(new ScDPCacheTable::GroupFilter(GetSharedString()));
+                     ScDPCacheTable::GroupFilter* pGrpFilter = 
+                         static_cast<ScDPCacheTable::GroupFilter*>(aCri.mpFilter.get());
+     
+diff --git sc/source/core/data/dpobject.cxx sc/source/core/data/dpobject.cxx
+index 6e0392d..8e1c9b8 100644
+--- sc/source/core/data/dpobject.cxx
++++ sc/source/core/data/dpobject.cxx
+@@ -408,7 +408,7 @@ void ScDPObject::CreateObjects()
+ 			if ( pImpDesc )
+ 			{
+ 			    // database data
+-			    pData = new ScDatabaseDPData( pDoc->GetServiceManager(), *pImpDesc );
++			    pData = new ScDatabaseDPData( pDoc, pDoc->GetServiceManager(), *pImpDesc );
+ 			}
+ 			else
+ 			{
+@@ -2514,7 +2514,49 @@ uno::Reference<sheet::XDimensionsSupplier> ScDPObject::CreateSource( const ScDPS
+ 	return xRet;
+ }
+ 
+-// -----------------------------------------------------------------------
++// ============================================================================
++
++ScDPCacheCell::ScDPCacheCell() :
++    mnStrId(ScSimpleSharedString::EMPTY),
++    mnType(SC_VALTYPE_EMPTY),
++    mfValue(0.0),
++    mbNumeric(false)
++{
++}
++
++ScDPCacheCell::ScDPCacheCell(const ScDPCacheCell& r) :
++    mnStrId(r.mnStrId),
++    mnType(r.mnType),
++    mfValue(r.mfValue),
++    mbNumeric(r.mbNumeric)
++{
++}
++
++ScDPCacheCell::~ScDPCacheCell()
++{
++}
++
++// ============================================================================
++
++size_t ScDPCollection::CacheCellHash::operator()(const ScDPCacheCell* pCell) const
++{
++    return pCell->mnStrId + static_cast<size_t>(pCell->mnType) + 
++        static_cast<size_t>(pCell->mfValue) + static_cast<size_t>(pCell->mbNumeric);
++}
++
++bool ScDPCollection::CacheCellEqual::operator()(const ScDPCacheCell* p1, const ScDPCacheCell* p2) const
++{
++    if (!p1 && !p2)
++        return true;
++
++    if ((!p1 && p2) || (p1 && !p2))
++        return false;
++
++    return p1->mnStrId == p2->mnStrId && p1->mfValue == p2->mfValue && 
++        p1->mbNumeric == p2->mbNumeric && p1->mnType == p2->mnType;
++}
++
++// ----------------------------------------------------------------------------
+ 
+ ScDPCollection::ScDPCollection(ScDocument* pDocument) :
+ 	pDoc( pDocument )
+@@ -2523,12 +2565,15 @@ ScDPCollection::ScDPCollection(ScDocument* pDocument) :
+ 
+ ScDPCollection::ScDPCollection(const ScDPCollection& r) :
+ 	Collection(r),
+-	pDoc(r.pDoc)
++	pDoc(r.pDoc),
++    maSharedString(r.maSharedString),
++    maCacheCellPool(r.maCacheCellPool)
+ {
+ }
+ 
+ ScDPCollection::~ScDPCollection()
+ {
++    clearCacheCellPool();
+ }
+ 
+ DataObject* ScDPCollection::Clone() const
+@@ -2716,9 +2761,66 @@ void ScDPCollection::EnsureNames()
+ 			((ScDPObject*)At(i))->SetName( CreateNewName() );
+ }
+ 
++ScSimpleSharedString& ScDPCollection::GetSharedString()
++{
++    return maSharedString;
++}
++
++ScDPCacheCell* ScDPCollection::getCacheCellFromPool(const ScDPCacheCell& rCell)
++{
++    ScDPCacheCell aCell(rCell);
++    CacheCellPoolType::iterator itr = maCacheCellPool.find(&aCell);
++    if (itr == maCacheCellPool.end())
++    {
++        // Insert a new instance.
++        ScDPCacheCell* p = new ScDPCacheCell(rCell);
++        ::std::pair<CacheCellPoolType::iterator, bool> r =
++            maCacheCellPool.insert(p);
++        if (!r.second)
++            delete p;
++
++        ScDPCacheCell* p2 = r.second ? *r.first : NULL;
++        DBG_ASSERT(p == p2, "ScDPCollection::getCacheCellFromPool: pointer addresses differ");
++        return p2;
++    }
++    return *itr;
++}
++
++namespace {
++
++class DeleteCacheCells : public ::std::unary_function<ScDPCacheCell*, void>
++{
++public:
++    void operator()(ScDPCacheCell* p) const
++    {
++        delete p;
++    }
++};
++
++}
++
++void ScDPCollection::clearCacheCellPool()
++{
++    // Transferring all the pointers to a vector first.  For some reason,
++    // deleting the cell content instances directly by iterating through
++    // pointers stored in the hash set caused the iteration to return an
++    // identical pointer value twice, causing a double-delete.  I have no idea
++    // why.
++
++    using ::std::copy;
++    using ::std::back_inserter;
++
++    vector<ScDPCacheCell*> ps;
++    ps.reserve(maCacheCellPool.size());
++    copy(maCacheCellPool.begin(), maCacheCellPool.end(), back_inserter(ps));
++    for_each(ps.begin(), ps.end(), DeleteCacheCells());
++    maCacheCellPool.clear();
++}
++
+ //------------------------------------------------------------------------
+ //	convert old pivot tables into new datapilot tables
+ 
++#if OLD_PIVOT_IMPLEMENTATION
+ void ScDPCollection::ConvertOldTables( ScPivotCollection& rOldColl )
+ {
+ 	//	convert old pivot tables into new datapilot tables
+diff --git sc/source/core/data/dpsdbtab.cxx sc/source/core/data/dpsdbtab.cxx
+index 5ac8d6d..e8d0509 100644
+--- sc/source/core/data/dpsdbtab.cxx
++++ sc/source/core/data/dpsdbtab.cxx
+@@ -58,6 +58,8 @@
+ #include "globstr.hrc"
+ #include "dpcachetable.hxx"
+ #include "dptabres.hxx"
++#include "document.hxx"
++#include "dpobject.hxx"
+ 
+ using namespace com::sun::star;
+ 
+@@ -91,16 +93,21 @@ public:
+ 
+     ScDPCacheTable      aCacheTable;
+ 
+-	ScDatabaseDPData_Impl() {}
++	ScDatabaseDPData_Impl(ScDPCollection* p) :
++        aCacheTable(p)
++    {
++    }
+ };
+ 
+ // -----------------------------------------------------------------------
+ 
+ ScDatabaseDPData::ScDatabaseDPData(
++    ScDocument* pDoc,
+ 	::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xSMgr,
+-	const ScImportSourceDesc& rImport )
++	const ScImportSourceDesc& rImport ) :
++    ScDPTableData(pDoc)
+ {
+-	pImpl = new ScDatabaseDPData_Impl;
++	pImpl = new ScDatabaseDPData_Impl(pDoc->GetDPCollection());
+ 	pImpl->xServiceManager = xSMgr;
+ 	pImpl->aDesc = rImport;
+ 	pImpl->nColCount = 0;
+diff --git sc/source/core/data/dpshttab.cxx sc/source/core/data/dpshttab.cxx
+index 9dab27c..76410c6 100644
+--- sc/source/core/data/dpshttab.cxx
++++ sc/source/core/data/dpshttab.cxx
+@@ -44,6 +44,7 @@
+ #include "collect.hxx"
+ #include "cell.hxx"
+ #include "dpcachetable.hxx"
++#include "dpobject.hxx"
+ #include "globstr.hrc"
+ 
+ #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
+@@ -74,17 +75,19 @@ public:
+ 
+     ScDPCacheTable  aCacheTable;
+ 
+-	ScSheetDPData_Impl() :
+-        pSpecial(NULL)
++	ScSheetDPData_Impl(ScDPCollection* p) :
++        pSpecial(NULL),
++        aCacheTable(p)
+     {
+     }
+ };
+ 
+ // -----------------------------------------------------------------------
+ 
+-ScSheetDPData::ScSheetDPData( ScDocument* pD, const ScSheetSourceDesc& rDesc )
++ScSheetDPData::ScSheetDPData( ScDocument* pD, const ScSheetSourceDesc& rDesc ) :
++    ScDPTableData(pD)
+ {
+-	pImpl = new ScSheetDPData_Impl;
++	pImpl = new ScSheetDPData_Impl(pD->GetDPCollection());
+ 	pImpl->pDoc = pD;
+ 	pImpl->aRange = rDesc.aSourceRange;
+ 	pImpl->aQuery = rDesc.aQueryParam;
+diff --git sc/source/core/data/dptabdat.cxx sc/source/core/data/dptabdat.cxx
+index dc42601..77521a6 100644
+--- sc/source/core/data/dptabdat.cxx
++++ sc/source/core/data/dptabdat.cxx
+@@ -48,6 +48,8 @@
+ #include "global.hxx"
+ #include "dpcachetable.hxx"
+ #include "dptabres.hxx"
++#include "document.hxx"
++#include "dpobject.hxx"
+ 
+ using namespace ::com::sun::star;
+ using ::com::sun::star::uno::Sequence;
+@@ -125,7 +127,8 @@ ScDPTableData::CalcInfo::CalcInfo() :
+ 
+ // ---------------------------------------------------------------------------
+ 
+-ScDPTableData::ScDPTableData()
++ScDPTableData::ScDPTableData(ScDocument* pDoc) :
++    mrSharedString(pDoc->GetDPCollection()->GetSharedString())
+ {
+ 	nLastDateVal = nLastHier = nLastLevel = nLastRet = -1;		// invalid
+ 
+@@ -186,26 +189,6 @@ bool ScDPTableData::IsRepeatIfEmpty()
+     return false;
+ }
+ 
+-void ScDPTableData::CreateCacheTable()
+-{
+-    fprintf(stdout, "ScDPTableData::CreateCacheTable: un-implemented...\n");fflush(stdout);
+-}
+-
+-void ScDPTableData::FilterCacheTable(const vector<ScDPCacheTable::Criterion>&)
+-{
+-    fprintf(stdout, "ScDPTableData::FilterCacheTable: un-implemented...\n");
+-}
+-
+-void ScDPTableData::GetDrillDownData(const vector<ScDPCacheTable::Criterion>&, Sequence< Sequence<Any> >&)
+-{
+-    fprintf(stdout, "ScDPTableData::GetDrillDownData: un-implemented...\n");fflush(stdout);
+-}
+-
+-void ScDPTableData::CalcResults(CalcInfo&, bool)
+-{
+-    fprintf(stdout, "ScDPTableData::CalcResults: un-implemented...\n");fflush(stdout);
+-}
+-
+ UINT32 ScDPTableData::GetNumberFormat(long)
+ {
+ 	return 0;			// default format
+@@ -240,6 +223,11 @@ BOOL ScDPTableData::HasCommonElement( const ScDPItemData&, long,
+     return FALSE;
+ }
+ 
++ScSimpleSharedString& ScDPTableData::GetSharedString()
++{
++    return mrSharedString;
++}
++
+ void ScDPTableData::FillRowDataFromCacheTable(sal_Int32 nRow, const ScDPCacheTable& rCacheTable, 
+                                         const CalcInfo& rInfo, CalcRowData& rData)
+ {
+@@ -258,7 +246,8 @@ void ScDPTableData::FillRowDataFromCacheTable(sal_Int32 nRow, const ScDPCacheTab
+         long nDim = rInfo.aDataSrcCols[i];
+         rData.aValues.push_back( ScDPValueData() );
+         ScDPValueData& rVal = rData.aValues.back();
+-        const ScDPCacheTable::Cell* pCell = rCacheTable.getCell(static_cast<SCCOL>(nDim), static_cast<SCROW>(nRow));
++        const ScDPCacheCell* pCell = rCacheTable.getCell(
++            static_cast<SCCOL>(nDim), static_cast<SCROW>(nRow));
+         if (pCell)
+         {
+             rVal.fValue = pCell->mbNumeric ? pCell->mfValue : 0.0;
+@@ -321,11 +310,12 @@ void ScDPTableData::GetItemData(const ScDPCacheTable& rCacheTable, sal_Int32 nRo
+             continue;
+         }
+ 
+-        const ScDPCacheTable::Cell* pCell = rCacheTable.getCell(static_cast<SCCOL>(nDim), static_cast<SCROW>(nRow), IsRepeatIfEmpty());
++        const ScDPCacheCell* pCell = rCacheTable.getCell(
++            static_cast<SCCOL>(nDim), static_cast<SCROW>(nRow), IsRepeatIfEmpty());
+         if (!pCell || pCell->mnType == SC_VALTYPE_EMPTY)
+             continue;
+ 
+-        const String* pString = ScSharedString::getString(pCell->mnStrId);
++        const String* pString = GetSharedString().getString(pCell->mnStrId);
+         if (!pString)
+             continue;
+ 
+diff --git sc/source/core/data/dptabres.cxx sc/source/core/data/dptabres.cxx
+index bfbe34b..c52139c 100644
+--- sc/source/core/data/dptabres.cxx
++++ sc/source/core/data/dptabres.cxx
+@@ -41,6 +41,7 @@
+ #include <float.h>			//! Test !!!
+ 
+ #include <algorithm>
++#include <hash_map>
+ 
+ #include "dptabdat.hxx"
+ #include "dptabres.hxx"
+@@ -59,9 +60,13 @@
+ #include <com/sun/star/sheet/DataPilotFieldReferenceItemType.hpp>
+ #include <com/sun/star/sheet/DataPilotFieldShowItemsMode.hpp>
+ #include <com/sun/star/sheet/DataPilotFieldSortMode.hpp>
++#include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
+ 
+ using namespace com::sun::star;
+ using ::std::vector;
++using ::std::pair;
++using ::std::hash_map;
++using ::com::sun::star::uno::Sequence;
+ 
+ // -----------------------------------------------------------------------
+ 
+@@ -1577,6 +1582,12 @@ ScDPAggData* ScDPResultMember::GetColTotal( long nMeasure ) const
+     return lcl_GetChildTotal( const_cast<ScDPAggData*>(&aColTotal), nMeasure );
+ }
+ 
++void ScDPResultMember::FillVisibilityData(ScDPResultVisibilityData& rData) const
++{
++    if (pChildDimension)
++        pChildDimension->FillVisibilityData(rData);
++}
++
+ // -----------------------------------------------------------------------
+ 
+ ScDPDataMember::ScDPDataMember( const ScDPResultData* pData, const ScDPResultMember* pRes ) :
+@@ -3231,6 +3242,26 @@ ScDPResultDimension* ScDPResultDimension::GetFirstChildDimension() const
+ 		return NULL;
+ }
+ 
++void ScDPResultDimension::FillVisibilityData(ScDPResultVisibilityData& rData) const
++{
++    if (IsDataLayout())
++        return;
++
++    MemberArray::const_iterator itr = maMemberArray.begin(), itrEnd = maMemberArray.end();
++
++    for (;itr != itrEnd; ++itr)
++    {
++        ScDPResultMember* pMember = *itr;
++        if (pMember->IsValid())
++        {
++            ScDPItemData aItem;
++            pMember->FillItemData(aItem);
++            rData.addVisibleMember(GetName(), aItem);
++            pMember->FillVisibilityData(rData);
++        }
++    }
++}
++
+ // -----------------------------------------------------------------------
+ 
+ ScDPDataDimension::ScDPDataDimension( const ScDPResultData* pData ) :
+@@ -3559,3 +3590,88 @@ ScDPDataMember* ScDPDataDimension::GetMember(long n) const
+     return aMembers[(USHORT)n];
+ }
+ 
++// ----------------------------------------------------------------------------
++
++ScDPResultVisibilityData::ScDPResultVisibilityData(
++    ScSimpleSharedString& rSharedString, ScDPSource* pSource) :
++    mrSharedString(rSharedString),
++    mpSource(pSource)
++{
++}
++
++ScDPResultVisibilityData::~ScDPResultVisibilityData()
++{
++}
++
++void ScDPResultVisibilityData::addVisibleMember(const String& rDimName, const ScDPItemData& rMemberItem)
++{
++    DimMemberType::iterator itr = maDimensions.find(rDimName);
++    if (itr == maDimensions.end())
++    {
++        pair<DimMemberType::iterator, bool> r = maDimensions.insert(
++            DimMemberType::value_type(rDimName, VisibleMemberType()));
++
++        if (!r.second)
++            // insertion failed.
++            return;
++
++        itr = r.first;
++    }
++    VisibleMemberType& rMem = itr->second;
++    VisibleMemberType::iterator itrMem = rMem.find(rMemberItem);
++    if (itrMem == rMem.end())
++        rMem.insert(rMemberItem);
++}
++
++void ScDPResultVisibilityData::fillFieldFilters(vector<ScDPCacheTable::Criterion>& rFilters) const
++{
++    typedef hash_map<String, long, ScStringHashCode> FieldNameMapType;
++    FieldNameMapType aFieldNames;
++    ScDPTableData* pData = mpSource->GetData();
++    long nColumnCount = pData->GetColumnCount();
++    for (long i = 0; i < nColumnCount; ++i)
++    {
++        aFieldNames.insert(
++            FieldNameMapType::value_type(pData->getDimensionName(i), i));
++    }
++
++    const ScDPDimensions* pDims = mpSource->GetDimensionsObject();
++    for (DimMemberType::const_iterator itr = maDimensions.begin(), itrEnd = maDimensions.end();
++          itr != itrEnd; ++itr)
++    {
++        const String& rDimName = itr->first;
++        ScDPCacheTable::Criterion aCri;
++        FieldNameMapType::const_iterator itrField = aFieldNames.find(rDimName);
++        if (itrField == aFieldNames.end())
++            // This should never happen!
++            continue;
++
++        long nDimIndex = itrField->second;
++        aCri.mnFieldIndex = static_cast<sal_Int32>(nDimIndex);
++        aCri.mpFilter.reset(new ScDPCacheTable::GroupFilter(mrSharedString));
++        ScDPCacheTable::GroupFilter* pGrpFilter = 
++            static_cast<ScDPCacheTable::GroupFilter*>(aCri.mpFilter.get());
++
++        const VisibleMemberType& rMem = itr->second;
++        for (VisibleMemberType::const_iterator itrMem = rMem.begin(), itrMemEnd = rMem.end();
++              itrMem != itrMemEnd; ++itrMem)
++        {
++            const ScDPItemData& rMemItem = *itrMem;
++            pGrpFilter->addMatchItem(rMemItem.aString, rMemItem.fValue, rMemItem.bHasValue);
++        }
++
++        ScDPDimension* pDim = pDims->getByIndex(nDimIndex);
++        ScDPMembers* pMembers = pDim->GetHierarchiesObject()->getByIndex(0)->
++            GetLevelsObject()->getByIndex(0)->GetMembersObject();
++        if (pGrpFilter->getMatchItemCount() < static_cast<size_t>(pMembers->getCount()))
++            rFilters.push_back(aCri);
++    }
++}
++
++size_t ScDPResultVisibilityData::MemberHash::operator() (const ScDPItemData& r) const
++{
++    if (r.bHasValue)
++        return static_cast<size_t>(::rtl::math::approxFloor(r.fValue));
++    else
++        return rtl_ustr_hashCode_WithLength(r.aString.GetBuffer(), r.aString.Len());
++}
+diff --git sc/source/core/data/dptabsrc.cxx sc/source/core/data/dptabsrc.cxx
+index 6881c70..600eb7b 100644
+--- sc/source/core/data/dptabsrc.cxx
++++ sc/source/core/data/dptabsrc.cxx
+@@ -31,7 +31,7 @@
+ // MARKER(update_precomp.py): autogen include statement, do not remove
+ #include "precompiled_sc.hxx"
+ 
+-#include <stdio.h>
++
+ 
+ 
+ // INCLUDE ---------------------------------------------------------------
+@@ -68,6 +68,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/DataPilotFieldAutoShowInfo.hpp>
+ #include <com/sun/star/table/CellAddress.hpp>
+ 
+ #include <unotools/collatorwrapper.hxx>
+@@ -81,6 +82,7 @@ using ::std::hash_map;
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::Sequence;
+ using ::com::sun::star::uno::Any;
++using ::com::sun::star::sheet::DataPilotFieldAutoShowInfo;
+ 
+ // -----------------------------------------------------------------------
+ 
+@@ -422,6 +424,15 @@ Sequence< Sequence<Any> > SAL_CALL ScDPSource::getDrillDownData(const Sequence<s
+     throw (uno::RuntimeException)
+ {
+     long nColumnCount = GetData()->GetColumnCount();
++    ScSimpleSharedString& rSharedString = GetData()->GetSharedString();
++
++    typedef hash_map<String, long, ScStringHashCode> FieldNameMapType;
++    FieldNameMapType aFieldNames;
++    for (long i = 0; i < nColumnCount; ++i)
++    {
++        aFieldNames.insert(
++            FieldNameMapType::value_type(GetData()->getDimensionName(i), i));
++    }
+ 
+     // collect ScDPItemData for each filtered column
+     vector<ScDPCacheTable::Criterion> aFilterCriteria;
+@@ -443,15 +454,21 @@ Sequence< Sequence<Any> > SAL_CALL ScDPSource::getDrillDownData(const Sequence<s
+                     ScDPItemData aItem;
+                     pMembers->getByIndex(nIndex)->FillItemData( aItem );
+                     aFilterCriteria.push_back( ScDPCacheTable::Criterion() );
+-                    sal_Int32 nMatchStrId = ScSharedString::getStringId(aItem.aString);
++                    sal_Int32 nMatchStrId = rSharedString.getStringId(aItem.aString);
+                     aFilterCriteria.back().mnFieldIndex = nCol;
+                     aFilterCriteria.back().mpFilter.reset(
+-                        new ScDPCacheTable::SingleFilter(nMatchStrId, aItem.fValue, aItem.bHasValue) );
++                        new ScDPCacheTable::SingleFilter(rSharedString, nMatchStrId, aItem.fValue, aItem.bHasValue) );
+                 }
+             }
+         }
+     }
+ 
++    // Take into account the visibilities of field members.
++    ScDPResultVisibilityData aResVisData(rSharedString, this);
++    pRowResRoot->FillVisibilityData(aResVisData);
++    pColResRoot->FillVisibilityData(aResVisData);
++    aResVisData.fillFieldFilters(aFilterCriteria);
++
+     Sequence< Sequence<Any> > aTabData;
+     pData->GetDrillDownData(aFilterCriteria, aTabData);
+     return aTabData;
+@@ -834,6 +851,8 @@ void ScDPSource::CreateRes_Impl()
+ 		else
+ 		{
+             {
++                ScSimpleSharedString& rSharedString = GetData()->GetSharedString();
++
+                 // filter table by page dimensions.
+                 vector<ScDPCacheTable::Criterion> aCriteria;
+                 for (i = 0; i < nPageDimCount; ++i)
+@@ -847,9 +866,9 @@ void ScDPSource::CreateRes_Impl()
+                     aCriteria.push_back(ScDPCacheTable::Criterion());
+                     ScDPCacheTable::Criterion& r = aCriteria.back();
+                     r.mnFieldIndex = static_cast<sal_Int32>(nField);
+-                    sal_Int32 nStrId = ScSharedString::getStringId(rData.aString);
++                    sal_Int32 nStrId = rSharedString.getStringId(rData.aString);
+                     r.mpFilter.reset(
+-                        new ScDPCacheTable::SingleFilter(nStrId, rData.fValue, rData.bHasValue));
++                        new ScDPCacheTable::SingleFilter(rSharedString, nStrId, rData.fValue, rData.bHasValue));
+                 }
+                 if (!aCriteria.empty())
+                     pData->FilterCacheTable(aCriteria);
+diff --git sc/source/core/data/global2.cxx sc/source/core/data/global2.cxx
+index 2cbda72..abfae52 100644
+--- sc/source/core/data/global2.cxx
++++ sc/source/core/data/global2.cxx
+@@ -1311,4 +1311,90 @@ String ScGlobal::GetDocTabName( const String& rFileName,
+ 	return aDocTab;
+ }
+ 
++// ============================================================================
+ 
++ScSimpleSharedString::StringTable::StringTable() :
++    mnStrCount(0)
++{
++    // empty string (ID = 0)
++    maSharedStrings.push_back(String());
++    maSharedStringIds.insert( SharedStrMap::value_type(String(), mnStrCount++) );
++}
++
++ScSimpleSharedString::StringTable::StringTable(const ScSimpleSharedString::StringTable& r) :
++    maSharedStrings(r.maSharedStrings),
++    maSharedStringIds(r.maSharedStringIds),
++    mnStrCount(r.mnStrCount)
++{
++}
++
++ScSimpleSharedString::StringTable::~StringTable()
++{
++}
++
++sal_Int32 ScSimpleSharedString::StringTable::insertString(const String& aStr)
++{
++    SharedStrMap::const_iterator itr = maSharedStringIds.find(aStr),
++        itrEnd = maSharedStringIds.end();
++
++    if (itr == itrEnd)
++    {
++        // new string.
++        maSharedStrings.push_back(aStr);
++        maSharedStringIds.insert( SharedStrMap::value_type(aStr, mnStrCount) );
++        return mnStrCount++;
++    }
++
++    // existing string.
++    return itr->second;
++}
++
++sal_Int32 ScSimpleSharedString::StringTable::getStringId(const String& aStr)
++{
++    SharedStrMap::const_iterator itr = maSharedStringIds.find(aStr),
++        itrEnd = maSharedStringIds.end();
++    if (itr == itrEnd)
++    {
++        // string not found.
++        return insertString(aStr);
++    }
++    return itr->second;
++}
++
++const String* ScSimpleSharedString::StringTable::getString(sal_Int32 nId) const
++{
++    if (nId >= mnStrCount)
++        return NULL;
++
++    return &maSharedStrings[nId];
++}
++
++// ----------------------------------------------------------------------------
++
++ScSimpleSharedString::ScSimpleSharedString()
++{
++}
++
++ScSimpleSharedString::ScSimpleSharedString(const ScSimpleSharedString& r) :
++    maStringTable(r.maStringTable)
++{
++}
++
++ScSimpleSharedString::~ScSimpleSharedString()
++{
++}
++
++sal_Int32 ScSimpleSharedString::insertString(const String& aStr)
++{
++    return maStringTable.insertString(aStr);
++}
++
++const String* ScSimpleSharedString::getString(sal_Int32 nId)
++{
++    return maStringTable.getString(nId);
++}
++
++sal_Int32 ScSimpleSharedString::getStringId(const String& aStr)
++{
++    return maStringTable.getStringId(aStr);
++}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]