diff options
author | Vladimir Glazunov <vg@openoffice.org> | 2010-03-23 14:25:33 +0100 |
---|---|---|
committer | Vladimir Glazunov <vg@openoffice.org> | 2010-03-23 14:25:33 +0100 |
commit | 2fbd5327d5fda2e415557ed7b03bb181ae5ce2a1 (patch) | |
tree | e0681e3223891807ae37f4159366111207366ca7 | |
parent | 47bdfa3b1db5245485347851017a791fc193407c (diff) | |
parent | 79e1f10909b23774b042cfc3cd03b46a0e6b6d84 (diff) |
CWS-TOOLING: integrate CWS datapilotperf
43 files changed, 5590 insertions, 1836 deletions
diff --git a/sc/inc/collect.hxx b/sc/inc/collect.hxx index e8b9bed60865..167ab5929c6a 100644 --- a/sc/inc/collect.hxx +++ b/sc/inc/collect.hxx @@ -184,20 +184,18 @@ private: BOOL bCaseSensitive; public: - TypedScStrCollection( USHORT nLim = 4, USHORT nDel = 4, BOOL bDup = FALSE ) - : ScSortedCollection( nLim, nDel, bDup ) { bCaseSensitive = FALSE; } + TypedScStrCollection( USHORT nLim = 4, USHORT nDel = 4, BOOL bDup = FALSE ); - TypedScStrCollection( const TypedScStrCollection& rCpy ) - : ScSortedCollection( rCpy ) { bCaseSensitive = rCpy.bCaseSensitive; } - ~TypedScStrCollection(); + TypedScStrCollection( const TypedScStrCollection& rCpy ) + : ScSortedCollection( rCpy ) { bCaseSensitive = rCpy.bCaseSensitive; } + ~TypedScStrCollection(); virtual ScDataObject* Clone() const; virtual short Compare( ScDataObject* pKey1, ScDataObject* pKey2 ) const; - TypedStrData* operator[]( const USHORT nIndex) const - { return (TypedStrData*)At(nIndex); } + TypedStrData* operator[]( const USHORT nIndex) const; - void SetCaseSensitive( BOOL bSet ) { bCaseSensitive = bSet; } + void SetCaseSensitive( BOOL bSet ); BOOL FindText( const String& rStart, String& rResult, USHORT& rPos, BOOL bBack ) const; BOOL GetExactMatch( String& rString ) const; diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index 84c1eb9ce69f..1d92962a56db 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -45,6 +45,13 @@ #include <memory> #include <map> +// Wang Xu Ming -- 2009-8-17 +// DataPilot Migration - Cache&&Performance +#include <list> +#include "dpobject.hxx" +#include "dptabdat.hxx" +// End Comments + class KeyEvent; class OutputDevice; class SdrObject; @@ -256,6 +263,11 @@ private: ScRangeName* pRangeName; ScDBCollection* pDBCollection; ScDPCollection* pDPCollection; + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + std::list<ScDPObject> m_listDPObjectsInClip; + std::list<ScDPTableDataCache*> m_listDPObjectsCaches; + // End Comments ScChartCollection* pChartCollection; std::auto_ptr< ScTemporaryChartLock > apTemporaryChartLock; ScPatternAttr* pSelectionAttr; // Attribute eines Blocks @@ -492,6 +504,17 @@ public: SC_DLLPUBLIC ScDPCollection* GetDPCollection(); ScDPObject* GetDPAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab) const; ScDPObject* GetDPAtBlock( const ScRange& rBlock ) const; + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + SC_DLLPUBLIC ScDPTableDataCache* GetDPObjectCache( long nID ); + SC_DLLPUBLIC ScDPTableDataCache* GetUsedDPObjectCache ( ScRange rRange ); + SC_DLLPUBLIC long AddDPObjectCache( ScDPTableDataCache* pData ); + SC_DLLPUBLIC void RemoveDPObjectCache( long nID ); + SC_DLLPUBLIC void RemoveUnusedDPObjectCaches(); + SC_DLLPUBLIC void GetUsedDPObjectCache( std::list<ScDPTableDataCache*>& usedlist ); + SC_DLLPUBLIC long GetNewDPObjectCacheId (); + // End Comments + SC_DLLPUBLIC ScChartCollection* GetChartCollection() const; void StopTemporaryChartLock(); diff --git a/sc/inc/dpcachetable.hxx b/sc/inc/dpcachetable.hxx index 60dba0bc27db..eab01d078081 100644 --- a/sc/inc/dpcachetable.hxx +++ b/sc/inc/dpcachetable.hxx @@ -55,33 +55,38 @@ class ScRange; class ScDPDimension; class ScDPCollection; struct ScDPCacheCell; -struct ScDPItemData; struct ScQueryParam; +// Wang Xu Ming -- 2009-8-17 +// DataPilot Migration - Cache&&Performance +class ScDPItemData; +// End Comments class Date; +// Wang Xu Ming -- 2009-8-17 +// DataPilot Migration - Cache&&Performance +class ScDPTableDataCache; +struct ScDPValueData; +// End Comments // ---------------------------------------------------------------------------- -class ScDPCacheTable +class SC_DLLPUBLIC ScDPCacheTable { public: - - struct Cell - { - SCROW mnCategoryRef; - ScDPCacheCell* mpContent; - - Cell(); - ~Cell(); - }; - /** individual filter item used in SingleFilter and GroupFilter. */ struct FilterItem { - sal_Int32 mnMatchStrId; + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + String maString; + // End Comments double mfValue; bool mbHasValue; FilterItem(); +// Wang Xu Ming -- 2009-8-17 +// DataPilot Migration - Cache&&Performance + bool match( const ScDPItemData& rCellData ) const; +// End Comments }; /** interface class used for filtering of rows. */ @@ -90,19 +95,26 @@ public: public: /** returns true if the matching condition is met for a single cell value, or false otherwise. */ - virtual bool match(const ScDPCacheCell& rCell) const = 0; +// Wang Xu Ming -- 2009-8-17 +// DataPilot Migration - Cache&&Performance + virtual bool match( const ScDPItemData& rCellData ) const = 0; +// End Comments }; /** ordinary single-item filter. */ class SingleFilter : public FilterBase { public: - explicit SingleFilter(ScSimpleSharedString& rSharedString, - sal_Int32 nMatchStrId, double fValue, bool bHasValue); + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + explicit SingleFilter(String aString, double fValue, bool bHasValue); + // End Comments virtual ~SingleFilter(){} - virtual bool match(const ScDPCacheCell& rCell) const; - + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + virtual bool match(const ScDPItemData& rCellData) const; + // End Comments const String getMatchString(); double getMatchValue() const; bool hasValue() const; @@ -111,25 +123,27 @@ public: explicit SingleFilter(); FilterItem maItem; - ScSimpleSharedString mrSharedString; }; /** multi-item (group) filter. */ class GroupFilter : public FilterBase { public: - GroupFilter(ScSimpleSharedString& rSharedString); + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + GroupFilter(); + // End Comments virtual ~GroupFilter(){} - virtual bool match(const ScDPCacheCell& rCell) const; - + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + virtual bool match( const ScDPItemData& rCellData ) const; + // End Comments void addMatchItem(const String& rStr, double fVal, bool bHasValue); size_t getMatchItemCount() const; private: - GroupFilter(); ::std::vector<FilterItem> maItems; - ScSimpleSharedString mrSharedString; }; /** single filtering criterion. */ @@ -140,22 +154,26 @@ public: Criterion(); }; - - ScDPCacheTable(ScDPCollection* pCollection); + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + ScDPCacheTable( ScDocument* pDoc,long nId ); + // End Comments ~ScDPCacheTable(); sal_Int32 getRowSize() const; sal_Int32 getColSize() const; + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + ScDPTableDataCache* GetCache() const; /** Fill the internal table from the cell range provided. This function - assumes that the first row is the column header. */ - void fillTable(ScDocument* pDoc, const ScRange& rRange, const ScQueryParam& rQuery, BOOL* pSpecial, - bool bIgnoreEmptyRows); - + assumes that the first row is the column header. */ + void fillTable( const ScQueryParam& rQuery, BOOL* pSpecial, + bool bIgnoreEmptyRows, bool bRepeatIfEmpty ); /** Fill the internal table from database connection object. This function assumes that the first row is the column header. */ - void fillTable(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSet >& xRowSet, - const Date& rNullDate); + void fillTable(); + // End Comments /** Check whether a specified row is active or not. When a row is active, it is used in calculation of the results data. A row becomes inactive @@ -169,15 +187,23 @@ 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 ScDPCacheCell* getCell(SCCOL nCol, SCROW nRow, bool bRepeatIfEmpty) const; - - const String* getFieldName(sal_Int32 nIndex) const; - - /** Get the unique entries for a field specified by index. The caller must + const ScDPItemData* getCell(SCCOL nCol, SCROW nRow, bool bRepeatIfEmpty) const; + void getValue( ScDPValueData& rVal, SCCOL nCol, SCROW nRow, bool bRepeatIfEmpty) const; + String getFieldName( SCCOL nIndex) const; + //End Comments + + /** Get the field index (i.e. column ID in the original data source) based + on the string value that corresponds with the column title. It returns + -1 if no field matching the string value exists. */ + sal_Int32 getFieldIndex(const String& rStr) const; + + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + /** Get the unique entries for a field specified by index. The caller must make sure that the table is filled before calling function, or it will get an empty collection. */ - const TypedScStrCollection& getFieldEntries(sal_Int32 nIndex) const; - + const ::std::vector<SCROW>& getFieldEntries( sal_Int32 nColumn ) const; + // End Comments /** Filter the table based on the specified criteria, and copy the result to rTabData. This method is used, for example, to generate a drill-down data table. */ @@ -186,6 +212,7 @@ public: const ::std::hash_set<sal_Int32>& rRepeatIfEmptyDims); void clear(); + void swap(ScDPCacheTable& rOther); bool empty() const; private: @@ -200,26 +227,23 @@ private: */ bool isRowQualified(sal_Int32 nRow, const ::std::vector<Criterion>& rCriteria, const ::std::hash_set<sal_Int32>& rRepeatIfEmptyDims) const; void getValueData(ScDocument* pDoc, const ScAddress& rPos, ScDPCacheCell& rCell); - + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + void InitNoneCache( ScDocument* pDoc ); + // End Comments private: - typedef ::boost::shared_ptr<TypedScStrCollection> TypedScStrCollectionPtr; - - /** main data table. */ - ::std::vector< ::std::vector< ::ScDPCacheTable::Cell > > maTable; - - /** header string IDs */ - ::std::vector<sal_Int32> maHeader; - + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance /** unique field entires for each field (column). */ - ::std::vector<TypedScStrCollectionPtr> maFieldEntries; - + ::std::vector< ::std::vector<SCROW> > maFieldEntries; + // End Comments /** 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; + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + ScDPTableDataCache* mpCache; + ScDPTableDataCache* mpNoneCache; + // End Comments }; - - #endif diff --git a/sc/inc/dpglobal.hxx b/sc/inc/dpglobal.hxx new file mode 100755 index 000000000000..7de5947cc969 --- /dev/null +++ b/sc/inc/dpglobal.hxx @@ -0,0 +1,209 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright IBM Corporation 2009. + * Copyright 2009 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: dpglobal.hxx,v $ + * $Revision: 1.0 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +// Wang Xu Ming - DataPilot migration +// Buffer&&Performance +// +#ifndef _SC_DPGLOBAL_HXX +#define _SC_DPGLOBAL_HXX + +#include <algorithm> +#include <list> +#include <tools/gen.hxx> +#include <tools/debug.hxx> +#include <global.hxx> + +#include <com/sun/star/container/XNamed.hpp> +#include <com/sun/star/sheet/XDimensionsSupplier.hpp> + +#include <com/sun/star/sheet/DataPilotFieldFilter.hpp> +#include <com/sun/star/sheet/DataPilotFieldOrientation.hpp> +#include <com/sun/star/sheet/DataPilotTableHeaderData.hpp> +#include <com/sun/star/sheet/DataPilotTablePositionData.hpp> +#include <com/sun/star/sheet/DataPilotTablePositionType.hpp> +#include <com/sun/star/sheet/DataPilotTableResultData.hpp> +#include <com/sun/star/sheet/DataResultFlags.hpp> +#include <com/sun/star/sheet/GeneralFunction.hpp> +#include <com/sun/star/sheet/MemberResultFlags.hpp> +#include <com/sun/star/sheet/TableFilterField.hpp> +#include <com/sun/star/sheet/XDataPilotMemberResults.hpp> +#include <com/sun/star/sheet/XDataPilotResults.hpp> +#include <com/sun/star/sheet/XHierarchiesSupplier.hpp> +#include <com/sun/star/sheet/XLevelsSupplier.hpp> + + +// moved from fieldwnd.hxx, see also SC_DAPI_MAXFIELDS +#define MAX_LABELS 256 + +#define MAX_PAGEFIELDS 10 // maximum count of fields for page area + +#define PIVOT_MAXFUNC 11 +#define PIVOT_FUNC_NONE 0x0000 +#define PIVOT_FUNC_SUM 0x0001 +#define PIVOT_FUNC_COUNT 0x0002 +#define PIVOT_FUNC_AVERAGE 0x0004 +#define PIVOT_FUNC_MAX 0x0008 +#define PIVOT_FUNC_MIN 0x0010 +#define PIVOT_FUNC_PRODUCT 0x0020 +#define PIVOT_FUNC_COUNT_NUM 0x0040 +#define PIVOT_FUNC_STD_DEV 0x0080 +#define PIVOT_FUNC_STD_DEVP 0x0100 +#define PIVOT_FUNC_STD_VAR 0x0200 +#define PIVOT_FUNC_STD_VARP 0x0400 +#define PIVOT_FUNC_AUTO 0x1000 + +#define DATA_RENAME_SEPARATOR "_" +#define __MAX_NUM_LEN 64 +#define __DECIMALPLACE 18 + +#define DP_PROP_COLUMNGRAND "ColumnGrand" +#define DP_PROP_FUNCTION "Function" +#define DP_PROP_IGNOREEMPTY "IgnoreEmptyRows" +#define DP_PROP_ISDATALAYOUT "IsDataLayoutDimension" +#define DP_PROP_ISVISIBLE "IsVisible" +#define DP_PROP_ORIENTATION "Orientation" +#define DP_PROP_REPEATIFEMPTY "RepeatIfEmpty" +#define DP_PROP_ROWGRAND "RowGrand" +#define DP_PROP_SHOWDETAILS "ShowDetails" +#define DP_PROP_SHOWEMPTY "ShowEmpty" +#define DP_PROP_SUBTOTALS "SubTotals" +#define DP_PROP_USEDHIERARCHY "UsedHierarchy" +#define DP_PROP_FILTER "Filter" +#define DP_PROP_POSITION "Position" + +#define DBG_TRACESTR( x ) \ + {\ + ByteString aTemp( x , RTL_TEXTENCODING_UTF8 ); \ + DBG_TRACE( aTemp.GetBuffer() );\ + } + +class TypedStrData; +class ScDPObject; + +class SC_DLLPUBLIC ScDPItemData +{ +public: + enum { MK_VAL = 0x01, MK_DATA = MK_VAL<<1, MK_ERR = MK_DATA<<1, MK_DATE = MK_ERR<<1, MK_DATEPART = MK_DATE<<1 }; +private: + union + { + ULONG nNumFormat; + sal_Int32 mnDatePart; + }; + + String aString; + double fValue; + BYTE mbFlag; + //BOOL bHasValue: 1 ; + //BOOL bHasData: 1; + //BOOL bErr: 1; + + friend class ScDPTableDataCache; +public: + ScDPItemData() : nNumFormat( 0 ), fValue(0.0), mbFlag( 0 ){} + ScDPItemData( ULONG nNF, const String & rS, double fV, BYTE bF ):nNumFormat(nNF), aString(rS), fValue(fV), mbFlag( bF ){} + ScDPItemData( const String& rS, double fV = 0.0, BOOL bHV = FALSE, const ULONG nNumFormat = 0 , BOOL bData = TRUE) ; + ScDPItemData( ScDocument* pDoc, SCROW nRow, USHORT nCol, USHORT nDocTab ); + + void SetString( const String& rS ) { aString = rS; mbFlag &= ~(MK_VAL|MK_DATE); nNumFormat = 0; mbFlag |= MK_DATA; } +// void SetValue ( double value , ULONG nNumFormat = 0 ) { bHasValue = TRUE; nNumFormat = 0;bHasData = TRUE; bDate = FALSE; fValue = value ;} + BOOL IsCaseInsEqual( const ScDPItemData& r ) const; + + size_t Hash() const; + + // exact equality + BOOL operator==( const ScDPItemData& r ) const; + // case insensitive equality + static sal_Int32 Compare( const ScDPItemData& rA, const ScDPItemData& rB ); + +#ifdef DEBUG + void dump() const; +#endif + +public: + BOOL IsHasData() const ; + BOOL IsHasErr() const ; + BOOL IsValue() const; + String GetString() const ; + double GetValue() const ; + ULONG GetNumFormat() const ; + BOOL HasStringData() const ; + BOOL IsDate() const; + BOOL HasDatePart() const; + void SetDate( BOOL b ) ; + + TypedStrData* CreateTypeString( ); + sal_uInt8 GetType() const; + BYTE & GetFlag() throw() { return mbFlag; } + const BYTE & GetFlag() const throw() { return const_cast<ScDPItemData*>(this)->GetFlag(); } +}; + +class SC_DLLPUBLIC ScDPItemDataPool +{ +public: + // construct + ScDPItemDataPool(void); + ScDPItemDataPool(const ScDPItemDataPool& r); + + virtual ~ScDPItemDataPool(void); + virtual const ScDPItemData* getData( sal_Int32 nId ); + virtual sal_Int32 getDataId( const ScDPItemData& aData ); + virtual sal_Int32 insertData( const ScDPItemData& aData ); +protected: + struct DataHashFunc : public std::unary_function< const ScDPItemData &, size_t > + { + size_t operator() (const ScDPItemData &rData) const { return rData.Hash(); } + }; + + typedef ::std::hash_multimap< ScDPItemData, sal_Int32, DataHashFunc > DataHash; + + ::std::vector< ScDPItemData > maItems; + DataHash maItemIds; +}; + +class ScDPInfoWnd; +class ScDocShell; +class ScTabViewShell; +namespace ScDPGlobal +{ +// used for core data + String GetFieldFuncString( const String& rSourceName, USHORT &rFuncMask, BOOL bIsValue ); + String GetFuncString( const String &rString, const USHORT nIndex ); + com::sun::star::uno::Reference<com::sun::star::container::XNameAccess> DP_GetMembers( const com::sun::star::uno::Reference< + com::sun::star::sheet::XDimensionsSupplier>&rSrc, long nField ); +// common operation + String operator + ( const String & rL, const String &rR ); + Rectangle operator *( const Rectangle &rLeft, const std::pair<double,double> & rRight ); +// used for DataPilot Panel + ScDPInfoWnd* GetDPInfoWnd( ScTabViewShell *pViewShell ); + bool ChkDPTableOverlap( ScDocument *pDestDoc, std::list<ScDPObject> & rClipboard, SCCOL nClipStartCol, SCROW nClipStartRow, SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab, USHORT nEndTab, BOOL bExcludeClip = FALSE ); + +} +#endif diff --git a/sc/inc/dpgroup.hxx b/sc/inc/dpgroup.hxx index 39770d2adffd..2a66f8b45555 100644 --- a/sc/inc/dpgroup.hxx +++ b/sc/inc/dpgroup.hxx @@ -34,7 +34,10 @@ #include "dptabdat.hxx" #include "scdllapi.h" - +// Wang Xu Ming -- 2009-8-17 +// DataPilot Migration - Cache&&Performance +#include "dpglobal.hxx" +// End Comments class ScDocument; class SvNumberFormatter; @@ -73,8 +76,11 @@ public: sal_Int32 GetDatePart() const { return nDatePart; } const ScDPNumGroupInfo& GetNumInfo() const { return aNumInfo; } - void FillColumnEntries( TypedScStrCollection& rEntries, const TypedScStrCollection& rOriginal, - SvNumberFormatter* pFormatter ) const; + // Wang Xu Ming -- 2009-9-8 + // DataPilot Migration - Cache&&Performance + void FillColumnEntries( SCCOL nSourceDim, ScDPTableDataCache* pCahe , std::vector< SCROW >& rEntries, + const std::vector< SCROW >& rOriginal ) const; + // End Comments }; // -------------------------------------------------------------------- @@ -108,8 +114,10 @@ class ScDPGroupDimension String aGroupName; ScDPDateGroupHelper* pDateHelper; ScDPGroupItemVec aItems; - mutable TypedScStrCollection* pCollection; // collection of item names (cached) - + // Wang Xu Ming -- 2009-9-4 + // DataPilot Migration - Cache&&Performance + mutable ::std::vector< SCROW > maMemberEntries; + // End Comments public: ScDPGroupDimension( long nSource, const String& rNewName ); ScDPGroupDimension( const ScDPGroupDimension& rOther ); @@ -122,9 +130,12 @@ public: long GetSourceDim() const { return nSourceDim; } long GetGroupDim() const { return nGroupDim; } - const String& GetName() const { return aGroupName; } + const String& GetName() const { return aGroupName; } - const TypedScStrCollection& GetColumnEntries( const TypedScStrCollection& rOriginal, ScDocument* pDoc ) const; +// Wang Xu Ming -- 2009-9-2 +// DataPilot Migration - Cache&&Performance + const std::vector< SCROW >& GetColumnEntries( const ScDPCacheTable& rCacheTable, const std::vector< SCROW >& rOriginal ) const; +// End Comments const ScDPGroupItem* GetGroupForData( const ScDPItemData& rData ) const; // rData = entry in original dim. const ScDPGroupItem* GetGroupForName( const ScDPItemData& rName ) const; // rName = entry in group dim. const ScDPGroupItem* GetGroupByIndex( size_t nIndex ) const; @@ -146,7 +157,10 @@ class SC_DLLPUBLIC ScDPNumGroupDimension { ScDPNumGroupInfo aGroupInfo; // settings ScDPDateGroupHelper* pDateHelper; - mutable TypedScStrCollection* pCollection; // collection of item names (cached) +// Wang Xu Ming -- 2009-9-4 +// DataPilot Migration - Cache&&Performance + mutable ::std::vector< SCROW > maMemberEntries; +// End Comments mutable bool bHasNonInteger; // initialized in GetNumEntries mutable sal_Unicode cDecSeparator; // initialized in GetNumEntries @@ -158,14 +172,15 @@ public: ScDPNumGroupDimension& operator=( const ScDPNumGroupDimension& rOther ); - const TypedScStrCollection& GetNumEntries( const TypedScStrCollection& rOriginal, ScDocument* pDoc ) const; - const ScDPNumGroupInfo& GetInfo() const { return aGroupInfo; } bool HasNonInteger() const { return bHasNonInteger; } sal_Unicode GetDecSeparator() const { return cDecSeparator; } const ScDPDateGroupHelper* GetDateHelper() const { return pDateHelper; } + const std::vector< SCROW >& GetNumEntries( SCCOL nSourceDim, ScDPTableDataCache* pCache, + const std::vector< SCROW >& rOriginal ) const; + void MakeDateHelper( const ScDPNumGroupInfo& rInfo, sal_Int32 nPart ); void DisposeData(); @@ -187,7 +202,11 @@ class ScDPGroupTableData : public ScDPTableData ScDocument* pDoc; StringHashSet aGroupNames; - void FillGroupValues( ScDPItemData* pItemData, long nCount, const long* pDims ); +// Wang Xu Ming -- 2009-8-17 +// DataPilot Migration - Cache&&Performance + void FillGroupValues( SCROW* pItemDataIndex, long nCount, const long* pDims ); + virtual long GetSourceDim( long nDim ); +// End Comments void CopyFields(const ::std::vector<long>& rFieldDims, ::std::vector<long>& rNewFieldDims); bool IsNumGroupDimension( long nDimension ) const; @@ -208,11 +227,18 @@ public: ScDocument* GetDocument() { return pDoc; } virtual long GetColumnCount(); - virtual const TypedScStrCollection& GetColumnEntries(long nColumn); +// Wang Xu Ming -- 2009-8-17 +// DataPilot Migration - Cache&&Performance + virtual long GetMembersCount( long nDim ); + virtual const std::vector< SCROW >& GetColumnEntries( long nColumn ) ; + virtual const ScDPItemData* GetMemberById( long nDim, long nId); + virtual long Compare( long nDim, long nDataId1, long nDataId2); + +// End Comments virtual String getDimensionName(long nColumn); virtual BOOL getIsDataLayoutDimension(long nColumn); virtual BOOL IsDateDimension(long nDim); - virtual UINT32 GetNumberFormat(long nDim); + virtual ULONG GetNumberFormat(long nDim); virtual void DisposeData(); virtual void SetEmptyFlags( BOOL bIgnoreEmptyRows, BOOL bRepeatIfEmpty ); diff --git a/sc/inc/dpobject.hxx b/sc/inc/dpobject.hxx index 917d62f38bfe..65e89ec75d41 100644 --- a/sc/inc/dpobject.hxx +++ b/sc/inc/dpobject.hxx @@ -115,8 +115,18 @@ private: SC_DLLPRIVATE ScDPTableData* GetTableData(); SC_DLLPRIVATE void CreateObjects(); SC_DLLPRIVATE void CreateOutput(); + BOOL bRefresh; + long mnCacheId; public: + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + inline void SetRefresh() { bRefresh = TRUE; } + const ScDPTableDataCache* GetCache() const; + long GetCacheId() const; + void SetCacheId( long nCacheId ); + ULONG RefreshCache(); + // End Comments ScDPObject( ScDocument* pD ); ScDPObject(const ScDPObject& r); virtual ~ScDPObject(); @@ -251,19 +261,6 @@ 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(); -}; // ============================================================================ @@ -271,20 +268,6 @@ class ScDPCollection : public ScCollection { 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); ScDPCollection(const ScDPCollection& r); @@ -303,15 +286,10 @@ public: String CreateNewName( USHORT nMin = 1 ) const; - ScSimpleSharedString& GetSharedString(); - void FreeTable(ScDPObject* pDPObj); SC_DLLPUBLIC bool InsertNewTable(ScDPObject* pDPObj); bool HasDPTable(SCCOL nCol, SCROW nRow, SCTAB nTab) const; - - ScDPCacheCell* getCacheCellFromPool(const ScDPCacheCell& rCell); - void clearCacheCellPool(); }; diff --git a/sc/inc/dpsave.hxx b/sc/inc/dpsave.hxx index 587e23d8109b..bfff0b97a168 100644 --- a/sc/inc/dpsave.hxx +++ b/sc/inc/dpsave.hxx @@ -88,6 +88,9 @@ public: }; +bool operator == (const ::com::sun::star::sheet::DataPilotFieldSortInfo &l, const ::com::sun::star::sheet::DataPilotFieldSortInfo &r ); +bool operator == (const ::com::sun::star::sheet::DataPilotFieldAutoShowInfo &l, const ::com::sun::star::sheet::DataPilotFieldAutoShowInfo &r ); +bool operator == (const ::com::sun::star::sheet::DataPilotFieldReference &l, const ::com::sun::star::sheet::DataPilotFieldReference &r ); class SC_DLLPUBLIC ScDPSaveDimension { private: @@ -175,6 +178,9 @@ public: void WriteToSource( const com::sun::star::uno::Reference< com::sun::star::uno::XInterface>& xDim ); + void Refresh( const com::sun::star::uno::Reference< + com::sun::star::sheet::XDimensionsSupplier>& xSource , + const std::list<String> & deletedDims); void UpdateMemberVisibility(const ::std::hash_map< ::rtl::OUString, bool, ::rtl::OUStringHash>& rData); @@ -193,6 +199,10 @@ private: USHORT nRepeatEmptyMode; BOOL bFilterButton; // not passed to DataPilotSource BOOL bDrillDown; // not passed to DataPilotSource + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + long mnCacheId; + // End Comments /** if true, all dimensions already have all of their member instances * created. */ @@ -248,10 +258,15 @@ public: BOOL GetDrillDown() const { return bDrillDown; } void WriteToSource( const com::sun::star::uno::Reference< + com::sun::star::sheet::XDimensionsSupplier>& xSource ); + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + void Refresh( const com::sun::star::uno::Reference< com::sun::star::sheet::XDimensionsSupplier>& xSource ); - BOOL IsEmpty() const; - + inline long GetCacheId() const{ return mnCacheId; } + inline void SetCacheId( long nCacheId ){ mnCacheId = nCacheId; } + // End Comments const ScDPDimensionSaveData* GetExistingDimensionData() const { return pDimensionData; } SC_DLLPUBLIC ScDPDimensionSaveData* GetDimensionData(); // create if not there void SetDimensionData( const ScDPDimensionSaveData* pNew ); // copied diff --git a/sc/inc/dpsdbtab.hxx b/sc/inc/dpsdbtab.hxx index 21e23e883da9..732e3d30e8df 100644 --- a/sc/inc/dpsdbtab.hxx +++ b/sc/inc/dpsdbtab.hxx @@ -57,23 +57,25 @@ struct ScImportSourceDesc aObject == rOther.aObject && nType == rOther.nType && bNative == rOther.bNative; } -}; -class ScDatabaseDPData_Impl; + // Wang Xu Ming -- 2009-9-15 + // DataPilot Migration - Cache&&Performance + ScDPTableDataCache* GetExistDPObjectCache( ScDocument* pDoc ) const; + ScDPTableDataCache* CreateCache( ScDocument* pDoc , long nID ) const; + ScDPTableDataCache* GetCache( ScDocument* pDoc, long nID ) const; + long GetCacheId( ScDocument* pDoc, long nID ) const; + // End Comments +}; class ScDatabaseDPData : public ScDPTableData { private: - ScDatabaseDPData_Impl* pImpl; - - BOOL OpenDatabase(); - + ScDPCacheTable aCacheTable; public: - ScDatabaseDPData(ScDocument* pDoc, const ScImportSourceDesc& rImport); + ScDatabaseDPData(ScDocument* pDoc, const ScImportSourceDesc& rImport, long nCacheId = -1); virtual ~ScDatabaseDPData(); virtual long GetColumnCount(); - virtual const TypedScStrCollection& GetColumnEntries(long nColumn); virtual String getDimensionName(long nColumn); virtual BOOL getIsDataLayoutDimension(long nColumn); virtual BOOL IsDateDimension(long nDim); diff --git a/sc/inc/dpshttab.hxx b/sc/inc/dpshttab.hxx index a0e67371eff1..a8d80072c68a 100644 --- a/sc/inc/dpshttab.hxx +++ b/sc/inc/dpshttab.hxx @@ -41,8 +41,10 @@ namespace com { namespace sun { namespace star { namespace sheet { }}}} class ScDPDimension; -struct ScDPItemData; - +// Wang Xu Ming -- 2009-8-17 +// DataPilot Migration - Cache&&Performance +class ScDPItemData; +// End Comments // -------------------------------------------------------------------- // // implementation of ScDPTableData with sheet data @@ -56,25 +58,38 @@ struct ScSheetSourceDesc BOOL operator== ( const ScSheetSourceDesc& rOther ) const { return aSourceRange == rOther.aSourceRange && aQueryParam == rOther.aQueryParam; } +// Wang Xu Ming - DataPilot migration +// Buffer&&Performance + ScDPTableDataCache* CreateCache( ScDocument* pDoc, long nID = -1) const; + ULONG CheckValidate( ScDocument* pDoc ) const; + ScDPTableDataCache* GetCache( ScDocument* pDoc, long nID ) const; + ScDPTableDataCache* GetExistDPObjectCache ( ScDocument* pDoc ) const; + long GetCacheId( ScDocument* pDoc, long nID ) const; + +// End Comments }; -class ScSheetDPData_Impl; - class SC_DLLPUBLIC ScSheetDPData : public ScDPTableData { private: - ScSheetDPData_Impl* pImpl; + ScQueryParam aQuery; + BOOL* pSpecial; + BOOL bIgnoreEmptyRows; + BOOL bRepeatIfEmpty; + + ScDPCacheTable aCacheTable; public: - ScSheetDPData( ScDocument* pD, const ScSheetSourceDesc& rDesc ); + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + ScSheetDPData( ScDocument* pD, const ScSheetSourceDesc& rDesc, long nCacheId = -1 ); virtual ~ScSheetDPData(); - + // End Comments virtual long GetColumnCount(); - virtual const TypedScStrCollection& GetColumnEntries(long nColumn); virtual String getDimensionName(long nColumn); virtual BOOL getIsDataLayoutDimension(long nColumn); virtual BOOL IsDateDimension(long nDim); - virtual UINT32 GetNumberFormat(long nDim); + virtual ULONG GetNumberFormat(long nDim); virtual void DisposeData(); virtual void SetEmptyFlags( BOOL bIgnoreEmptyRows, BOOL bRepeatIfEmpty ); diff --git a/sc/inc/dptabdat.hxx b/sc/inc/dptabdat.hxx index 43c719e9ee16..6323434ca4ad 100644 --- a/sc/inc/dptabdat.hxx +++ b/sc/inc/dptabdat.hxx @@ -31,7 +31,10 @@ #include "address.hxx" #include "dpoutput.hxx" #include "dpcachetable.hxx" - +// Wang Xu Ming -- 2009-8-17 +// DataPilot Migration - Cache&&Performance +#include "dptablecache.hxx" +// End Comments #include <tools/string.hxx> #include <vector> @@ -43,8 +46,6 @@ namespace com { namespace sun { namespace star { namespace sheet { struct DataPilotFieldFilter; }}}} -class TypedScStrCollection; -class ScSimpleSharedString; // ----------------------------------------------------------------------- @@ -71,28 +72,6 @@ class ScSimpleSharedString; // base class ScDPTableData to allow implementation with tabular data // by deriving only of this // - -struct ScDPItemData -{ - String aString; - double fValue; - BOOL bHasValue; - - ScDPItemData() : fValue(0.0), bHasValue(FALSE) {} - ScDPItemData( const String& rS, double fV = 0.0, BOOL bHV = FALSE ) : - aString(rS), fValue(fV), bHasValue( bHV ) {} - - void SetString( const String& rS ) { aString = rS; bHasValue = FALSE; } - BOOL IsCaseInsEqual( const ScDPItemData& r ) const; - - size_t Hash() const; - - // exact equality - BOOL operator==( const ScDPItemData& r ) const; - // case insensitive equality - static sal_Int32 Compare( const ScDPItemData& rA, const ScDPItemData& rB ); -}; - #define SC_VALTYPE_EMPTY 0 #define SC_VALTYPE_VALUE 1 #define SC_VALTYPE_STRING 2 @@ -113,15 +92,18 @@ class ScDPInitState; class ScDPResultMember; class ScDocument; -class ScDPTableData + class SC_DLLPUBLIC ScDPTableData { // cached data for GetDatePart long nLastDateVal; long nLastHier; long nLastLevel; long nLastRet; - ScSimpleSharedString& mrSharedString; - + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + long mnCacheId; + const ScDocument* mpDoc; + // End Comments public: /** This structure stores dimension information used when calculating @@ -147,7 +129,10 @@ public: CalcInfo(); }; - ScDPTableData(ScDocument* pDoc); + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + ScDPTableData(ScDocument* pDoc, long nCacheId ); + // End Comments virtual ~ScDPTableData(); long GetDatePart( long nDateVal, long nHierarchy, long nLevel ); @@ -156,11 +141,16 @@ public: //! or separate Str and ValueCollection virtual long GetColumnCount() = 0; - virtual const TypedScStrCollection& GetColumnEntries(long nColumn) = 0; + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + virtual const std::vector< SCROW >& GetColumnEntries( long nColumn ) ; + long GetCacheId() const; + // End Comments virtual String getDimensionName(long nColumn) = 0; virtual BOOL getIsDataLayoutDimension(long nColumn) = 0; virtual BOOL IsDateDimension(long nDim) = 0; - virtual UINT32 GetNumberFormat(long nDim); + virtual ULONG GetNumberFormat(long nDim); + virtual UINT32 GetNumberFormatByIdx( NfIndexTableOffset ); virtual void DisposeData() = 0; virtual void SetEmptyFlags( BOOL bIgnoreEmptyRows, BOOL bRepeatIfEmpty ) = 0; @@ -176,23 +166,33 @@ public: // overloaded in ScDPGroupTableData: virtual BOOL IsBaseForGroup(long nDim) const; - virtual long GetGroupBase(long nGroupDim) const; + virtual long GetGroupBase(long nGroupDim) const; virtual BOOL IsNumOrDateGroup(long nDim) const; virtual BOOL IsInGroup( const ScDPItemData& rGroupData, long nGroupIndex, const ScDPItemData& rBaseData, long nBaseIndex ) const; virtual BOOL HasCommonElement( const ScDPItemData& rFirstData, long nFirstIndex, const ScDPItemData& rSecondData, long nSecondIndex ) const; - ScSimpleSharedString& GetSharedString(); - + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + virtual long GetMembersCount( long nDim ); + virtual const ScDPItemData* GetMemberByIndex( long nDim, long nIndex ); + virtual const ScDPItemData* GetMemberById( long nDim, long nId); + virtual SCROW GetIdOfItemData( long nDim, const ScDPItemData& rData ); + virtual long GetSourceDim( long nDim ); + virtual long Compare( long nDim, long nDataId1, long nDataId2); + // End Comments protected: /** This structure stores vector arrays that hold intermediate data for each row during cache table iteration. */ struct CalcRowData { - ::std::vector<ScDPItemData> aColData; - ::std::vector<ScDPItemData> aRowData; - ::std::vector<ScDPItemData> aPageData; + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + ::std::vector< SCROW > aColData; + ::std::vector< SCROW > aRowData; + ::std::vector< SCROW > aPageData; + // End Comments ::std::vector<ScDPValueData> aValues; }; @@ -201,10 +201,11 @@ protected: void CalcResultsFromCacheTable(const ScDPCacheTable& rCacheTable, CalcInfo& rInfo, bool bAutoShow); private: + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance void GetItemData(const ScDPCacheTable& rCacheTable, sal_Int32 nRow, - const ::std::vector<long>& rDims, ::std::vector<ScDPItemData>& rItemData); + const ::std::vector<long>& rDims, ::std::vector< SCROW >& rItemData); + // End Comments }; - - #endif diff --git a/sc/inc/dptablecache.hxx b/sc/inc/dptablecache.hxx new file mode 100644 index 000000000000..7b637bf04d6f --- /dev/null +++ b/sc/inc/dptablecache.hxx @@ -0,0 +1,120 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright IBM Corporation 2009. + * Copyright 2009 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: dptablecache.hxx,v $ + * $Revision: 1.0 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef DPTABLECACHE_HXX +#define DPTABLECACHE_HXX +// Wang Xu Ming -- 12/21/2008 +// Add Data Cache Support. +#ifndef SC_SCGLOB_HXX +#include "global.hxx" +#endif +//Added by PengYunQuan for SODC_16015 +#include <svl/zforlist.hxx> +//end +#include <vector> +#include "dpglobal.hxx" + +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/sdbc/XRowSet.hpp> + +class ScDPTableDataCache; +class TypedStrData; +// -------------------------------------------------------------------- +// +// base class ScDPTableData to allow implementation with tabular data +// by deriving only of this +// + +class SC_DLLPUBLIC ScDPTableDataCache +{ + long mnID; + ScDocument* mpDoc; + + long mnColumnCount; // Column count + + std::vector<ScDPItemData*>* mpTableDataValues; //Data Pilot Table's index - value map + std::vector<SCROW>* mpSourceData; //Data Pilot Table's Source data + std::vector<SCROW>* mpGlobalOrder; //Sorted members index + std::vector<SCROW>* mpIndexOrder; //Index the sorted number + std::vector<ScDPItemData*> mrLabelNames; //Source Label data + std::vector<BOOL> mbEmptyRow; //If empty row? + mutable ScDPItemDataPool maAdditionalDatas; +public: + SCROW GetOrder( long nDim, SCROW nIndex ) const; + SCROW GetIdByItemData( long nDim, String sItemData ) const; + SCROW GetIdByItemData( long nDim, const ScDPItemData& rData ) const; + + SCROW GetAdditionalItemID ( String sItemData ); + SCROW GetAdditionalItemID( const ScDPItemData& rData ); + + SCCOL GetDimensionIndex( String sName) const; + const ScDPItemData* GetSortedItemData( SCCOL nDim, SCROW nOrder ) const; + ULONG GetNumType ( ULONG nFormat ) const; + ULONG GetNumberFormat( long nDim ) const; + BOOL IsDateDimension( long nDim ) const ; + ULONG GetDimNumType( SCCOL nDim) const; + SCROW GetDimMemberCount( SCCOL nDim ) const; + + SCROW GetSortedItemDataId( SCCOL nDim, SCROW nOrder ) const; + const std::vector<ScDPItemData*>& GetDimMemberValues( SCCOL nDim )const; + void SetId( long nId ){ mnID = nId;} + void AddRow( ScDPItemData* pRow, USHORT nCount ); + bool InitFromDoc( ScDocument* pDoc, const ScRange& rRange ); + bool InitFromDataBase (const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSet>& xRowSet, const Date& rNullDate); + + SCROW GetRowCount() const; + SCROW GetItemDataId( USHORT nDim, SCROW nRow, BOOL bRepeatIfEmpty ) const; + String GetDimensionName( USHORT nColumn ) const; + bool IsEmptyMember( SCROW nRow, USHORT nColumn ) const; + bool IsRowEmpty( SCROW nRow ) const; + bool IsValid() const; + bool ValidQuery( SCROW nRow, const ScQueryParam& rQueryParam, BOOL* pSpecial ); + + ScDocument* GetDoc() const;//ms-cache-core + long GetColumnCount() const; + long GetId() const; + + const ScDPItemData* GetItemDataById( long nDim, SCROW nId ) const; + + BOOL operator== ( const ScDPTableDataCache& r ) const; + +//construction + ScDPTableDataCache( ScDocument* pDoc ); +//deconstruction + virtual ~ScDPTableDataCache(); + +protected: +private: + void AddLabel( ScDPItemData* pData); + BOOL AddData( long nDim, ScDPItemData* itemData ); +}; + +#endif //DPTABLECACHE_HXX diff --git a/sc/inc/dptabres.hxx b/sc/inc/dptabres.hxx index d4e8807d4a3b..e35975ab170f 100644 --- a/sc/inc/dptabres.hxx +++ b/sc/inc/dptabres.hxx @@ -57,8 +57,10 @@ class ScDPResultMember; class ScDPResultVisibilityData; struct ScDPValueData; -struct ScDPItemData; - +// Wang Xu Ming -- 2009-8-17 +// DataPilot Migration - Cache&&Performance +class ScDPItemData; +// End Comments // // Member names that are being processed for InitFrom/LateInitFrom // (needed for initialization of grouped items) @@ -67,21 +69,26 @@ struct ScDPItemData; class ScDPInitState { long* pIndex; // array - ScDPItemData* pData; // array +// Wang Xu Ming -- 2009-8-17 +// DataPilot Migration - Cache&&Performance + SCROW* pData; // array + // End Comments long nCount; public: ScDPInitState(); ~ScDPInitState(); - void AddMember( long nSourceIndex, const ScDPItemData& rName ); + void AddMember( long nSourceIndex,SCROW nMember); void RemoveMember(); long GetCount() const { return nCount; } const long* GetSource() const { return pIndex; } - const ScDPItemData* GetNames() const { return pData; } - - const ScDPItemData* GetNameForIndex( long nIndexValue ) const; +// Wang Xu Ming -- 2009-8-17 +// DataPilot Migration - Cache&&Performance + const SCROW* GetNameIds() const { return pData; } + const SCROW GetNameIdForIndex( long nIndexValue ) const; +// End Comments }; typedef ::std::vector<sal_Int32> ScMemberSortOrder; @@ -230,6 +237,68 @@ class ScDPDataMember; #define SC_DPMEASURE_ALL -1 #define SC_DPMEASURE_ANY -2 +// Wang Xu Ming -- 2009-8-17 +// DataPilot Migration - Cache&&Performance + +struct MemberHashIndexFunc : public std::unary_function< const SCROW &, size_t > +{ + size_t operator() (const SCROW &rDataIndex) const { return rDataIndex; } +}; + +class ScDPParentDimData +{ +public: + const SCROW mnOrder; //! Ref + const ScDPDimension* mpParentDim; //! Ref + const ScDPLevel* mpParentLevel; //! Ref + const ScDPMember* mpMemberDesc; //! Ref + + ScDPParentDimData():mnOrder(-1), mpParentDim( NULL), mpParentLevel( NULL ), mpMemberDesc( NULL ){} + ScDPParentDimData( const SCROW nIndex, ScDPDimension* pDim, const ScDPLevel* pLev, const ScDPMember* pMember ): mnOrder( nIndex ), mpParentDim( pDim), mpParentLevel( pLev ), mpMemberDesc( pMember ){} +}; + +typedef std::vector <ScDPParentDimData *> DimMemberArray; +typedef std::hash_map < SCROW, ScDPParentDimData *, MemberHashIndexFunc> DimMemberHash; + +class ResultMembers +{ + DimMemberHash maMemberHash; + BOOL mbHasHideDetailsMember; +public: + ScDPParentDimData* FindMember( const SCROW& nIndex ) const; + void InsertMember( ScDPParentDimData* pNew ); + BOOL IsHasHideDetailsMembers() const { return mbHasHideDetailsMember; } + void SetHasHideDetailsMembers( BOOL b ) { mbHasHideDetailsMember=b; } + ResultMembers(); + virtual ~ResultMembers(); +}; + +class LateInitParams +{ +private: + const ::std::vector<ScDPDimension*>& mppDim; + const ::std::vector<ScDPLevel*>& mppLev; + + BOOL mbRow; + BOOL mbInitChild; + BOOL mbAllChildren; +public: + LateInitParams( const ::std::vector<ScDPDimension*>& ppDim, const ::std::vector<ScDPLevel*>& ppLev, + BOOL bRow, BOOL bInitChild = TRUE , BOOL bAllChildren = FALSE); + ~LateInitParams(); + + void SetInitChild( BOOL b ) { mbInitChild = b; } + void SetInitAllChildren( BOOL b ) { mbAllChildren = b; } + + inline ScDPDimension* GetDim( size_t nPos ) const { return mppDim[nPos];} + inline ScDPLevel* GetLevel( size_t nPos ) const { return mppLev[nPos];} + + inline BOOL GetInitChild() const {return mbInitChild; } + inline BOOL GetInitAllChild() const { return mbAllChildren; } + inline BOOL IsRow() const { return mbRow; } + BOOL IsEnd( size_t nPos ) const ; +}; +// End Comments class ScDPResultData { @@ -247,7 +316,7 @@ private: BOOL bDataAtRow; //! add "displayed values" settings - + mutable std::vector< ResultMembers* > mpDimMembers; public: ScDPResultData( ScDPSource* pSrc ); //! Ref ~ScDPResultData(); @@ -278,11 +347,18 @@ public: BOOL IsBaseForGroup( long nDim ) const; // any group long GetGroupBase( long nGroupDim ) const; BOOL IsNumOrDateGroup( long nDim ) const; + // Wang Xu Ming -- 2009-8-17 +// DataPilot Migration - Cache&&Performance BOOL IsInGroup( const ScDPItemData& rGroupData, long nGroupIndex, - const ScDPItemData& rBaseData, long nBaseIndex ) const; - BOOL HasCommonElement( const ScDPItemData& rFirstData, long nFirstIndex, + long nBaseDataId, long nBaseIndex ) const; + BOOL IsInGroup( SCROW nGroupDataId, long nGroupIndex, + const ScDPItemData& rBaseData, long nBaseIndex ) const; + BOOL HasCommonElement( SCROW nFirstDataId, long nFirstIndex, const ScDPItemData& rSecondData, long nSecondIndex ) const; + ResultMembers* GetDimResultMembers( long nDim , ScDPDimension* pDim , ScDPLevel* pLevel) const ; + +// End Comments const ScDPSource* GetSource() const; }; @@ -291,9 +367,10 @@ class ScDPResultMember { private: const ScDPResultData* pResultData; - const ScDPDimension* pParentDim; //! Ref - const ScDPLevel* pParentLevel; //! Ref - const ScDPMember* pMemberDesc; //! Ref + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + ScDPParentDimData aParentDimData; + // End Comments ScDPResultDimension* pChildDimension; ScDPDataMember* pDataRoot; BOOL bHasElements; @@ -303,21 +380,30 @@ private: BOOL bAutoHidden; ScDPAggData aColTotal; // to store column totals + USHORT nMemberStep; // step to show details public: - ScDPResultMember( const ScDPResultData* pData, const ScDPDimension* pDim, - const ScDPLevel* pLev, const ScDPMember* pDesc, - BOOL bForceSub ); //! Ref - ~ScDPResultMember(); - + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + ScDPResultMember( const ScDPResultData* pData, const ScDPParentDimData& rParentDimData, + BOOL bForceSub ); //! Ref + ScDPResultMember( const ScDPResultData* pData, BOOL bForceSub ); + // End Comments + ~ScDPResultMember(); + + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance void InitFrom( const ::std::vector<ScDPDimension*>& ppDim, - const ::std::vector<ScDPLevel*>& ppLev, - size_t nPos, - ScDPInitState& rInitState ); - void LateInitFrom( const ::std::vector<ScDPDimension*>& ppDim, - const ::std::vector<ScDPLevel*>& ppLev, - const ::std::vector<ScDPItemData>& pItemData, - size_t nPos, - ScDPInitState& rInitState ); + const ::std::vector<ScDPLevel*>& ppLev, + size_t nPos, + ScDPInitState& rInitState, + BOOL bInitChild = TRUE ); + void LateInitFrom( + LateInitParams& rParams, + const ::std::vector< SCROW >& pItemData, + size_t nPos, + ScDPInitState& rInitState); + void CheckShowEmpty( BOOL bShow = FALSE ); + // End Comments String GetName() const; void FillItemData( ScDPItemData& rData ) const; BOOL IsValid() const; @@ -329,17 +415,22 @@ public: // BOOL SubTotalEnabled() const; long GetSubTotalCount( long* pUserSubStart = NULL ) const; - BOOL IsNamedItem( const ScDPItemData& r ) const; - bool IsValidEntry( const ::std::vector<ScDPItemData>& aMembers ) const; + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + BOOL IsNamedItem( SCROW nIndex ) const; + bool IsValidEntry( const ::std::vector< SCROW >& aMembers ) const; + // End Comments void SetHasElements() { bHasElements = TRUE; } void SetAutoHidden() { bAutoHidden = TRUE; } - void ProcessData( const ::std::vector<ScDPItemData>& aChildMembers, - const ScDPResultDimension* pDataDim, - const ::std::vector<ScDPItemData>& aDataMembers, - const ::std::vector<ScDPValueData>& aValues ); - + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + void ProcessData( const ::std::vector<SCROW>& aChildMembers, + const ScDPResultDimension* pDataDim, + const ::std::vector<SCROW>& aDataMembers, + const ::std::vector<ScDPValueData>& aValues ); + // End Comments void FillMemberResults( com::sun::star::uno::Sequence< com::sun::star::sheet::MemberResult>* pSequences, long& rPos, long nMeasure, BOOL bRoot, @@ -369,9 +460,15 @@ public: ScDPDataMember* GetDataRoot() const { return pDataRoot; } - const ScDPDimension* GetParentDim() const { return pParentDim; } //! Ref - const ScDPLevel* GetParentLevel() const { return pParentLevel; } //! Ref - + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + const ScDPDimension* GetParentDim() const { return aParentDimData.mpParentDim; } //! Ref + const ScDPLevel* GetParentLevel() const { return aParentDimData.mpParentLevel; } //! Ref + const ScDPMember* GetDPMember()const { return aParentDimData.mpMemberDesc; } //! Ref + inline SCROW GetOrder() const { return aParentDimData.mnOrder; } //! Ref + inline BOOL IsRoot() const { return GetParentLevel() == NULL; } + SCROW GetDataId( ) const ; + // End Comments ScDPAggData* GetColTotal( long nMeasure ) const; void FillVisibilityData(ScDPResultVisibilityData& rData) const; @@ -397,13 +494,17 @@ public: BOOL IsVisible() const; BOOL HasData( long nMeasure, const ScDPSubTotalState& rSubState ) const; - BOOL IsNamedItem( const ScDPItemData& r ) const; - + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + BOOL IsNamedItem( SCROW r ) const; + // End Comments BOOL HasHiddenDetails() const; - void ProcessData( const ::std::vector<ScDPItemData>& aChildMembers, const ::std::vector<ScDPValueData>& aValues, - const ScDPSubTotalState& rSubState ); - + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + void ProcessData( const ::std::vector< SCROW >& aChildMembers, const ::std::vector<ScDPValueData>& aValues, + const ScDPSubTotalState& rSubState ); + // End Comments BOOL HasError( long nMeasure, const ScDPSubTotalState& rSubState ) const; double GetAggregate( long nMeasure, const ScDPSubTotalState& rSubState ) const; const ScDPAggData* GetConstAggData( long nMeasure, const ScDPSubTotalState& rSubState ) const; @@ -443,15 +544,13 @@ SV_DECL_PTRARR_DEL(ScDPDataMembers, ScDPDataMemberPtr, SC_DP_RES_GROW, SC_DP_RES class ScDPResultDimension { public : - struct MemberHashFunc : public std::unary_function< const ScDPItemData &, size_t > - { - size_t operator() (const ScDPItemData &rData) const { return rData.Hash(); } - }; - typedef std::vector <ScDPResultMember *> MemberArray; - typedef std::hash_map <ScDPItemData, ScDPResultMember *, MemberHashFunc> MemberHash; - + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + typedef std::vector <ScDPResultMember *> MemberArray; + typedef std::map < SCROW , ScDPResultMember *> MemberHash; + // End Comments private: - const ScDPResultData* pResultData; + const ScDPResultData* pResultData; MemberArray maMemberArray; MemberHash maMemberHash; BOOL bInitialized; @@ -466,31 +565,47 @@ private: long nAutoMeasure; long nAutoCount; - ScDPResultMember* FindMember( const ScDPItemData& rData ) const; + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + ScDPResultMember* FindMember( SCROW iData ) const; + ScDPResultMember* AddMember( const ScDPParentDimData& aData ); + ScDPResultMember* InsertMember( ScDPParentDimData* pMemberData ); + ResultMembers* GetResultMember( ScDPDimension* pDim, ScDPLevel* pLevel ); + void InitWithMembers( LateInitParams& rParams, + const ::std::vector< SCROW >& pItemData, + size_t nPos, + ScDPInitState& rInitState ); + // End Comments public: - ScDPResultDimension( const ScDPResultData* pData ); - ~ScDPResultDimension(); + ScDPResultDimension( const ScDPResultData* pData ); + ~ScDPResultDimension(); // allocates new members + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance void InitFrom( const ::std::vector<ScDPDimension*>& ppDim, - const ::std::vector<ScDPLevel*>& ppLev, - size_t nPos, - ScDPInitState& rInitState ); - void LateInitFrom( const ::std::vector<ScDPDimension*>& ppDim, - const ::std::vector<ScDPLevel*>& ppLev, - const ::std::vector<ScDPItemData>& pItemData, - size_t nPos, - ScDPInitState& rInitState ); - + const ::std::vector<ScDPLevel*>& ppLev, + size_t nPos, + ScDPInitState& rInitState , BOOL bInitChild = TRUE ); + void LateInitFrom( LateInitParams& rParams, + const ::std::vector< SCROW >& pItemData, + size_t nPos, + ScDPInitState& rInitState ); + void CheckShowEmpty( BOOL bShow = FALSE ); + + // End Comments long GetSize(long nMeasure) const; - bool IsValidEntry( const ::std::vector<ScDPItemData>& aMembers ) const; - // modifies existing members, allocates data dimensions - void ProcessData( const ::std::vector<ScDPItemData>& aMembers, + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + bool IsValidEntry( const ::std::vector<SCROW>& aMembers ) const; + + // modifies existing members, allocates data dimensions + void ProcessData( const ::std::vector<SCROW>& aMembers, const ScDPResultDimension* pDataDim, - const ::std::vector<ScDPItemData>& aDataMembers, + const ::std::vector<SCROW>& aDataMembers, const ::std::vector<ScDPValueData>& aValues ) const; //! Test - + // End Comments void FillMemberResults( com::sun::star::uno::Sequence< com::sun::star::sheet::MemberResult>* pSequences, long nStart, long nMeasure ); @@ -560,9 +675,11 @@ public: ~ScDPDataDimension(); void InitFrom( const ScDPResultDimension* pDim ); // recursive - void ProcessData( const ::std::vector<ScDPItemData>& aDataMembers, const ::std::vector<ScDPValueData>& aValues, - const ScDPSubTotalState& rSubState ); - + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + void ProcessData( const ::std::vector< SCROW >& aDataMembers, const ::std::vector<ScDPValueData>& aValues, + const ScDPSubTotalState& rSubState ); + // End Comments void FillDataRow( const ScDPResultDimension* pRefDim, com::sun::star::uno::Sequence<com::sun::star::sheet::DataResult>& rSequence, long nCol, long nMeasure, BOOL bIsSubTotalRow, @@ -596,7 +713,10 @@ public: class ScDPResultVisibilityData { public: - ScDPResultVisibilityData(ScSimpleSharedString& rSharedString, ScDPSource* pSource); + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + ScDPResultVisibilityData( ScDPSource* pSource); + // End Comments ~ScDPResultVisibilityData(); void addVisibleMember(const String& rDimName, const ScDPItemData& rMemberItem); @@ -611,7 +731,6 @@ private: typedef ::std::hash_map<String, VisibleMemberType, ScStringHashCode> DimMemberType; DimMemberType maDimensions; - ScSimpleSharedString& mrSharedString; ScDPSource* mpSource; }; diff --git a/sc/inc/dptabsrc.hxx b/sc/inc/dptabsrc.hxx index d2884281e1b8..18210f38e80e 100644 --- a/sc/inc/dptabsrc.hxx +++ b/sc/inc/dptabsrc.hxx @@ -30,6 +30,10 @@ #include <vector> #include <hash_map> +// Wang Xu Ming -- 2009-8-17 +// DataPilot Migration - Cache&&Performance +#include <list> +// End Comments #include <memory> #include <tools/string.hxx> #include <tools/list.hxx> @@ -57,7 +61,10 @@ #include <cppuhelper/implbase3.hxx> #include <cppuhelper/implbase5.hxx> #include <cppuhelper/implbase6.hxx> - +// Wang Xu Ming -- 2009-8-17 +// DataPilot Migration - Cache&&Performance +#include "dpglobal.hxx" +// End Comments #include "dptabdat.hxx" namespace com { namespace sun { namespace star { @@ -71,7 +78,10 @@ namespace com { namespace sun { namespace star { class ScDPResultMember; class ScDPResultData; -struct ScDPItemData; +// Wang Xu Ming -- 2009-8-17 +// DataPilot Migration - Cache&&Performance +class ScDPItemData; +// End Comments class ScDPTableData; // ------------------------------------------------------------------------ @@ -172,10 +182,18 @@ public: long GetDataDimensionCount(); ScDPDimension* GetDataDimension(long nIndex); String GetDataDimName(long nIndex); + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + ScDPTableDataCache* GetCache(); + const ScDPItemData* GetItemDataById( long nDim, long nId ); + long GetDataLayoutDim(){ return pData->GetColumnCount(); } + SCROW GetMemberId( long nDim, const ScDPItemData& rData ); + // End Comments BOOL IsDataLayoutDimension(long nDim); USHORT GetDataLayoutOrientation(); BOOL IsDateDimension(long nDim); + UINT32 GetNumberFormat(long nDim); BOOL SubTotalAllowed(long nColumn); //! move to ScDPResultData @@ -439,6 +457,10 @@ public: const ::com::sun::star::sheet::DataPilotFieldReference& GetReferenceValue() const; //UNUSED2009-05 BOOL IsValidPage( const ScDPItemData& rData ); +// Wang Xu Ming -- 2009-8-17 +// DataPilot Migration - Cache&&Performance + BOOL IsVisible( const ScDPItemData& rData ); +// End Comments }; class ScDPHierarchies : public cppu::WeakImplHelper2< @@ -732,6 +754,12 @@ public: long getMinMembers() const; sal_Int32 GetIndexFromName( const ::rtl::OUString& rName ) const; // <0 if not found + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + const std::vector<sal_Int32>& GetGlobalOrder(); + const ScDPItemData* GetSrcItemDataByIndex( SCROW nIndex); + SCROW GetSrcItemsCount(); + // End Comments }; class ScDPMember : public cppu::WeakImplHelper3< @@ -745,7 +773,11 @@ private: long nHier; long nLev; - ScDPItemData maData; + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + SCROW mnDataId; + // End Comments +// String aCaption; // visible name (changeable by user) ::std::auto_ptr<rtl::OUString> mpLayoutName; sal_Int32 nPosition; // manual sorting @@ -753,13 +785,24 @@ private: BOOL bShowDet; public: - ScDPMember( ScDPSource* pSrc, long nD, long nH, long nL, - const String& rN, double fV, BOOL bHV ); + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + ScDPMember( ScDPSource* pSrc, long nD, long nH, long nL, + SCROW nIndex /*const String& rN, double fV, BOOL bHV */); + // End Comments virtual ~ScDPMember(); BOOL IsNamedItem( const ScDPItemData& r ) const; String GetNameStr() const; void FillItemData( ScDPItemData& rData ) const; + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + // const ScDPItemData& GetItemData() const{ return maData; } + const ScDPItemData& GetItemData() const; + inline SCROW GetItemDataId() const { return mnDataId; } + BOOL IsNamedItem( SCROW nIndex ) const; + // End Comments + SC_DLLPUBLIC const ::rtl::OUString* GetLayoutName() const; sal_Int32 Compare( const ScDPMember& rOther ) const; // visible order diff --git a/sc/inc/global.hxx b/sc/inc/global.hxx index 8bcbd50b0f3c..185113e77389 100644 --- a/sc/inc/global.hxx +++ b/sc/inc/global.hxx @@ -758,21 +758,6 @@ enum ScSubTotalFunc }; -#define PIVOT_MAXFUNC 11 -#define PIVOT_FUNC_NONE 0x0000 -#define PIVOT_FUNC_SUM 0x0001 -#define PIVOT_FUNC_COUNT 0x0002 -#define PIVOT_FUNC_AVERAGE 0x0004 -#define PIVOT_FUNC_MAX 0x0008 -#define PIVOT_FUNC_MIN 0x0010 -#define PIVOT_FUNC_PRODUCT 0x0020 -#define PIVOT_FUNC_COUNT_NUM 0x0040 -#define PIVOT_FUNC_STD_DEV 0x0080 -#define PIVOT_FUNC_STD_DEVP 0x0100 -#define PIVOT_FUNC_STD_VAR 0x0200 -#define PIVOT_FUNC_STD_VARP 0x0400 -#define PIVOT_FUNC_AUTO 0x1000 - // ----------------------------------------------------------------------- /* @@ -876,46 +861,6 @@ 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 a/sc/inc/globstr.hrc b/sc/inc/globstr.hrc index c635877e2ea2..bca93e7aa441 100644 --- a/sc/inc/globstr.hrc +++ b/sc/inc/globstr.hrc @@ -570,7 +570,10 @@ #define STR_STYLE_FAMILY_CELL 433 #define STR_STYLE_FAMILY_PAGE 434 -#define STR_COUNT 435 +#define STR_ERR_DATAPILOTSOURCE 435 +#define STR_PIVOT_FIRSTROWEMPTYERR 436 +#define STR_PIVOT_ONLYONEROWERR 437 +#define STR_COUNT 438 #endif diff --git a/sc/inc/pivot.hxx b/sc/inc/pivot.hxx index 2a1f17846afd..915a311411c4 100644 --- a/sc/inc/pivot.hxx +++ b/sc/inc/pivot.hxx @@ -48,6 +48,7 @@ #include "global.hxx" #include "address.hxx" +#include "dpglobal.hxx" #include <vector> #include <boost/shared_ptr.hpp> diff --git a/sc/source/core/data/documen3.cxx b/sc/source/core/data/documen3.cxx index cc06d7ac6b32..1bd5b101f691 100644 --- a/sc/source/core/data/documen3.cxx +++ b/sc/source/core/data/documen3.cxx @@ -75,6 +75,11 @@ #include "drwlayer.hxx" #include "unoreflist.hxx" #include "listenercalls.hxx" +// Wang Xu Ming -- 2009-8-17 +// DataPilot Migration - Cache&&Performance +#include "dpshttab.hxx" +#include "dptablecache.hxx" +// End Comments #include "tabprotection.hxx" #include "formulaparserpool.hxx" #include "clipparam.hxx" @@ -1901,6 +1906,119 @@ void ScDocument::DecSizeRecalcLevel( SCTAB nTab ) pTab[nTab]->DecRecalcLevel(); } +// Wang Xu Ming -- 2009-8-17 +// DataPilot Migration - Cache&&Performance +ScDPTableDataCache* ScDocument::GetDPObjectCache( long nID ) +{ + for ( std::list<ScDPTableDataCache*>::iterator iter = m_listDPObjectsCaches.begin(); iter!=m_listDPObjectsCaches.end(); iter++ ) + { // + if ( nID == (*iter)->GetId() ) + return *iter; + } + return NULL; +} + +ScDPTableDataCache* ScDocument::GetUsedDPObjectCache ( ScRange rRange ) +{ + ScDPTableDataCache* pCache = NULL; + USHORT nCount = GetDPCollection()->GetCount(); + for ( short i=nCount-1; i>=0 ; i--) + { + if ( const ScSheetSourceDesc* pUsedSheetDesc = (*pDPCollection)[i]->GetSheetDesc() ) + if ( rRange == pUsedSheetDesc->aSourceRange ) + { + long nID = (*pDPCollection)[i]->GetCacheId(); + if ( nID >= 0 ) + pCache= GetDPObjectCache( nID ); + if ( pCache ) + return pCache; + } + } + return pCache; +} +long ScDocument::AddDPObjectCache( ScDPTableDataCache* pData ) +{ + if ( pData->GetId() < 0 ) + { //create a id for it + pData->SetId( GetNewDPObjectCacheId() ); + } + m_listDPObjectsCaches.push_back( pData ); + return pData->GetId(); +} +long ScDocument::GetNewDPObjectCacheId() +{ + long nID = 0; + bool bFound = false; + std::list<ScDPTableDataCache*>::iterator iter; + do { + for ( iter = m_listDPObjectsCaches.begin(); iter!=m_listDPObjectsCaches.end(); iter++ ) + { //Get a new Id + if ( nID == (*iter)->GetId() ) + { + nID++; + bFound = true; + break; + } + } + if ( iter == m_listDPObjectsCaches.end() ) + bFound = false; + } while ( bFound ); + + return nID; +} + +void ScDocument::RemoveDPObjectCache( long nID ) +{ + for ( std::list<ScDPTableDataCache*>::iterator iter = m_listDPObjectsCaches.begin(); iter!=m_listDPObjectsCaches.end(); iter++ ) + { + if ( nID == (*iter)->GetId() ) + { + ScDPTableDataCache* pCache = *iter; + m_listDPObjectsCaches.erase( iter ); + delete pCache; + break; + } + } + +} + +void ScDocument::RemoveUnusedDPObjectCaches() +{ + for ( std::list<ScDPTableDataCache*>::iterator iter = m_listDPObjectsCaches.begin(); iter!=m_listDPObjectsCaches.end(); iter++ ) + { + long nID = (*iter)->GetId(); + USHORT nCount = GetDPCollection()->GetCount(); + USHORT i ; + for ( i=0; i<nCount; i++) + { + if ( nID == (*pDPCollection)[i]->GetCacheId() ) + break; + } + if ( i == nCount ) + { + ScDPTableDataCache* pCache = *iter; + m_listDPObjectsCaches.erase( iter ); + delete pCache; + continue; + } + } +} + +void ScDocument::GetUsedDPObjectCache( std::list<ScDPTableDataCache*>& usedlist ) +{ + for ( std::list<ScDPTableDataCache*>::iterator iter = m_listDPObjectsCaches.begin(); iter!=m_listDPObjectsCaches.end(); iter++ ) + { + long nID = (*iter)->GetId(); + USHORT nCount = GetDPCollection()->GetCount(); + USHORT i=0; + for ( i=0; i<nCount; i++) + if ( nID == (*pDPCollection)[i]->GetCacheId() ) + break; + if ( i != nCount ) + usedlist.push_back( *iter ); + } +} +// End Comments diff --git a/sc/source/core/data/dpcachetable.cxx b/sc/source/core/data/dpcachetable.cxx index 237d7ffd16db..cfd29b6bbe98 100644 --- a/sc/source/core/data/dpcachetable.cxx +++ b/sc/source/core/data/dpcachetable.cxx @@ -65,7 +65,6 @@ using ::com::sun::star::uno::UNO_QUERY; using ::com::sun::star::uno::UNO_QUERY_THROW; using ::com::sun::star::sheet::DataPilotFieldFilter; -const double D_TIMEFACTOR = 86400.0; static BOOL lcl_HasQueryEntry( const ScQueryParam& rParam ) { @@ -75,56 +74,35 @@ static BOOL lcl_HasQueryEntry( const ScQueryParam& rParam ) // ---------------------------------------------------------------------------- -static ScDPCacheCell EmptyCellContent = ScDPCacheCell(); - -// ---------------------------------------------------------------------------- - -ScDPCacheTable::Cell::Cell() : - mnCategoryRef(0), - mpContent(NULL) -{ -} - -ScDPCacheTable::Cell::~Cell() -{ -} - -// ---------------------------------------------------------------------------- - ScDPCacheTable::FilterItem::FilterItem() : - mnMatchStrId(ScSimpleSharedString::EMPTY), mfValue(0.0), mbHasValue(false) { } - +bool ScDPCacheTable::FilterItem::match( const ScDPItemData& rCellData ) const +{ + if (rCellData.GetString()!= maString && + (!rCellData.IsValue()|| rCellData.GetValue()!= mfValue)) + return false; + return true; +} // ---------------------------------------------------------------------------- -ScDPCacheTable::SingleFilter::SingleFilter(ScSimpleSharedString& rSharedString, - sal_Int32 nMatchStrId, double fValue, bool bHasValue) : - mrSharedString(rSharedString) +ScDPCacheTable::SingleFilter::SingleFilter(String aString, double fValue, bool bHasValue) { - maItem.mnMatchStrId = nMatchStrId; + maItem.maString = aString; maItem.mfValue = fValue; maItem.mbHasValue = bHasValue; } -bool ScDPCacheTable::SingleFilter::match(const ScDPCacheCell& rCell) const +bool ScDPCacheTable::SingleFilter::match( const ScDPItemData& rCellData ) const { - if (rCell.mnStrId != maItem.mnMatchStrId && - (!rCell.mbNumeric || rCell.mfValue != maItem.mfValue)) - return false; - - return true; + return maItem.match(rCellData); } const String ScDPCacheTable::SingleFilter::getMatchString() { - const String* pStr = mrSharedString.getString(maItem.mnMatchStrId); - if (pStr) - return *pStr; - - return String(); + return maItem.maString; } double ScDPCacheTable::SingleFilter::getMatchValue() const @@ -139,33 +117,26 @@ bool ScDPCacheTable::SingleFilter::hasValue() const // ---------------------------------------------------------------------------- -ScDPCacheTable::GroupFilter::GroupFilter(ScSimpleSharedString& rSharedString) : - mrSharedString(rSharedString) +ScDPCacheTable::GroupFilter::GroupFilter() { } -bool ScDPCacheTable::GroupFilter::match(const ScDPCacheCell& rCell) const +bool ScDPCacheTable::GroupFilter::match( const ScDPItemData& rCellData ) const { vector<FilterItem>::const_iterator itrEnd = maItems.end(); - for (vector<FilterItem>::const_iterator itr = maItems.begin(); itr != itrEnd; ++itr) - { - bool bMatch = false; - if (rCell.mbNumeric) - bMatch = (itr->mfValue == rCell.mfValue); - else - bMatch = (itr->mnMatchStrId == rCell.mnStrId); - - if (bMatch) - return true; - } - return false; + for (vector<FilterItem>::const_iterator itr = maItems.begin(); itr != itrEnd; ++itr) + { + bool bMatch = itr->match( rCellData); + if (bMatch) + return true; + } + return false; } void ScDPCacheTable::GroupFilter::addMatchItem(const String& rStr, double fVal, bool bHasValue) { - sal_Int32 nStrId = mrSharedString.getStringId(rStr); FilterItem aItem; - aItem.mnMatchStrId = nStrId; + aItem.maString = rStr; aItem.mfValue = fVal; aItem.mbHasValue = bHasValue; maItems.push_back(aItem); @@ -186,10 +157,16 @@ ScDPCacheTable::Criterion::Criterion() : // ---------------------------------------------------------------------------- -ScDPCacheTable::ScDPCacheTable(ScDPCollection* pCollection) : - mrSharedString(pCollection->GetSharedString()), - mpCollection(pCollection) +ScDPCacheTable::ScDPCacheTable( ScDocument* pDoc,long nId ) : + mpCache( NULL ), + mpNoneCache( NULL ) { + if ( nId >= 0 ) + mpCache = pDoc->GetDPObjectCache( nId ); + else + { //create a temp cache object + InitNoneCache( NULL ); + } } ScDPCacheTable::~ScDPCacheTable() @@ -198,12 +175,12 @@ ScDPCacheTable::~ScDPCacheTable() sal_Int32 ScDPCacheTable::getRowSize() const { - return maTable.size(); + return GetCache()->GetRowCount(); } sal_Int32 ScDPCacheTable::getColSize() const { - return maTable.empty() ? 0 : maTable[0].size(); + return GetCache()->GetColumnCount(); } namespace { @@ -230,8 +207,8 @@ private: } -void ScDPCacheTable::fillTable(ScDocument* pDoc, const ScRange& rRange, const ScQueryParam& rQuery, BOOL* pSpecial, - bool bIgnoreEmptyRows) +void ScDPCacheTable::fillTable( const ScQueryParam& rQuery, BOOL* pSpecial, + bool bIgnoreEmptyRows, bool bRepeatIfEmpty ) { // Make sure the formula cells within the data range are interpreted // during this call, for this method may be called from the interpretation @@ -239,267 +216,105 @@ void ScDPCacheTable::fillTable(ScDocument* pDoc, const ScRange& rRange, const Sc // increasing the macro level. MacroInterpretIncrementer aMacroInc(pDoc); - SCTAB nTab = rRange.aStart.Tab(); - SCCOL nStartCol = rRange.aStart.Col(); - SCROW nStartRow = rRange.aStart.Row(); - SCCOL nColCount = rRange.aEnd.Col() - rRange.aStart.Col() + 1; - SCROW nRowCount = rRange.aEnd.Row() - rRange.aStart.Row() + 1; - - if (nRowCount <= 1 || nColCount <= 0) + if ( mpCache == NULL ) + InitNoneCache( NULL ); +//check cache + const SCROW nRowCount = getRowSize(); + const SCCOL nColCount = (SCCOL) getColSize(); + if ( nRowCount <= 0 || nColCount <= 0) return; - maTable.clear(); - maTable.reserve(nRowCount); - maHeader.clear(); - maHeader.reserve(nColCount); maRowsVisible.clear(); maRowsVisible.reserve(nRowCount); - // Header row - for (SCCOL nCol = 0; nCol < nColCount; ++nCol) - { - String aStr; - pDoc->GetString(nCol + nStartCol, nStartRow, nTab, aStr); - sal_Int32 nStrId = mrSharedString.insertString(aStr); - maHeader.push_back(nStrId); - } // Initialize field entries container. maFieldEntries.clear(); maFieldEntries.reserve(nColCount); - for (SCCOL nCol = 0; nCol < nColCount; ++nCol) - { - TypedScStrCollectionPtr p(new TypedScStrCollection); - maFieldEntries.push_back(p); - } - - vector<SCROW> aLastNonEmptyRows(nColCount, 0); // Data rows - for (SCROW nRow = 1; nRow < nRowCount; ++nRow) + for (SCCOL nCol = 0; nCol < nColCount; ++nCol) { - if ( lcl_HasQueryEntry(rQuery) && !pDoc->ValidQuery(nRow + nStartRow, nTab, rQuery, pSpecial) ) - // filtered out by standard filter. - continue; - - if ( bIgnoreEmptyRows && - pDoc->IsBlockEmpty(nTab, nStartCol, nRow + nStartRow, - nStartCol + nColCount - 1, nRow + nStartRow) ) - // skip an empty row. - continue; - - // Insert a new row into cache table. - maRowsVisible.push_back(true); - maTable.push_back( vector<Cell>() ); - maTable.back().reserve(nColCount); - - for (SCCOL nCol = 0; nCol < nColCount; ++nCol) + SCROW nMemCount = GetCache()->GetDimMemberCount( nCol ); + if ( nMemCount ) { - maTable.back().push_back( ScDPCacheTable::Cell() ); - Cell& rCell = maTable.back().back(); - rCell.mnCategoryRef = maTable.size()-1; + std::vector< SCROW > pAdded( nMemCount, -1 ); - String aCellStr; - bool bReadCell = nRow == 0 || pDoc->HasData(nStartCol + nCol, nStartRow + nRow, nTab); - if (bReadCell) + for (SCROW nRow = 0; nRow < nRowCount; ++nRow ) { - 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); + SCROW nIndex = GetCache()->GetItemDataId( nCol, nRow, bRepeatIfEmpty ); + SCROW nOrder = GetCache()->GetOrder( nCol, nIndex ); + + if ( nCol == 0 ) + maRowsVisible.push_back(false); + + if ( lcl_HasQueryEntry(rQuery) && + !GetCache()->ValidQuery( nRow , rQuery, pSpecial ) ) + continue; + if ( bIgnoreEmptyRows && GetCache()->IsRowEmpty( nRow ) ) + continue; + // Insert a new row into cache table. + if ( nCol == 0 ) + maRowsVisible.back() = true; + + pAdded[nOrder] = nIndex; + } + maFieldEntries.push_back( vector<SCROW>() ); + for ( SCROW nRow = 0; nRow < nMemCount; nRow++ ) + { + if ( pAdded[nRow] != -1 ) + maFieldEntries.back().push_back( pAdded[nRow] ); } - else - rCell.mnCategoryRef = aLastNonEmptyRows[nCol]; - - TypedStrData* pNew; - if (rCell.mpContent && rCell.mpContent->mbNumeric) - pNew = new TypedStrData(aCellStr, rCell.mpContent->mfValue, SC_STRTYPE_VALUE); - else - pNew = new TypedStrData(aCellStr); - - if (!maFieldEntries[nCol]->Insert(pNew)) - delete pNew; } } } -void lcl_GetCellValue(const Reference<sdbc::XRow>& xRow, sal_Int32 nType, long nCol, - const Date& rNullDate, ScDPCacheCell& rCell, String& rStr, - ScSimpleSharedString& rSharedString) +void ScDPCacheTable::fillTable() { - short nNumType = NUMBERFORMAT_NUMBER; - BOOL bEmptyFlag = FALSE; - try - { - rStr = xRow->getString(nCol); - rCell.mnStrId = rSharedString.getStringId(rStr); - rCell.mnType = SC_VALTYPE_STRING; - - switch (nType) - { - case sdbc::DataType::BIT: - case sdbc::DataType::BOOLEAN: - { - nNumType = NUMBERFORMAT_LOGICAL; - rCell.mfValue = xRow->getBoolean(nCol) ? 1 : 0; - bEmptyFlag = (rCell.mfValue == 0.0 && xRow->wasNull()); - rCell.mbNumeric = true; - rCell.mnType = SC_VALTYPE_VALUE; - } - break; - - case sdbc::DataType::TINYINT: - case sdbc::DataType::SMALLINT: - case sdbc::DataType::INTEGER: - case sdbc::DataType::BIGINT: - case sdbc::DataType::FLOAT: - case sdbc::DataType::REAL: - case sdbc::DataType::DOUBLE: - case sdbc::DataType::NUMERIC: - case sdbc::DataType::DECIMAL: - { - //! do the conversion here? - rCell.mfValue = xRow->getDouble(nCol); - bEmptyFlag = (rCell.mfValue == 0.0 && xRow->wasNull()); - rCell.mbNumeric = true; - rCell.mnType = SC_VALTYPE_VALUE; - } - break; - - case sdbc::DataType::CHAR: - case sdbc::DataType::VARCHAR: - case sdbc::DataType::LONGVARCHAR: - bEmptyFlag = (rStr.Len() == 0 && xRow->wasNull()); - break; + if ( mpCache == NULL ) + InitNoneCache( NULL ); +//check cache + const SCROW nRowCount = getRowSize(); + const SCCOL nColCount = (SCCOL) getColSize(); + if ( nRowCount <= 0 || nColCount <= 0) + return; - case sdbc::DataType::DATE: - { - nNumType = NUMBERFORMAT_DATE; + maRowsVisible.clear(); + maRowsVisible.reserve(nRowCount); - util::Date aDate = xRow->getDate(nCol); - rCell.mfValue = Date(aDate.Day, aDate.Month, aDate.Year) - rNullDate; - bEmptyFlag = xRow->wasNull(); - rCell.mbNumeric = true; - rCell.mnType = SC_VALTYPE_VALUE; - } - break; - case sdbc::DataType::TIME: - { - nNumType = NUMBERFORMAT_TIME; - - util::Time aTime = xRow->getTime(nCol); - rCell.mfValue = ( aTime.Hours * 3600 + aTime.Minutes * 60 + - aTime.Seconds + aTime.HundredthSeconds / 100.0 ) / D_TIMEFACTOR; - bEmptyFlag = xRow->wasNull(); - rCell.mbNumeric = true; - rCell.mnType = SC_VALTYPE_VALUE; - } - break; + // Initialize field entries container. + maFieldEntries.clear(); + maFieldEntries.reserve(nColCount); - case sdbc::DataType::TIMESTAMP: - { - nNumType = NUMBERFORMAT_DATETIME; - - util::DateTime aStamp = xRow->getTimestamp(nCol); - rCell.mfValue = ( Date( aStamp.Day, aStamp.Month, aStamp.Year ) - rNullDate ) + - ( aStamp.Hours * 3600 + aStamp.Minutes * 60 + - aStamp.Seconds + aStamp.HundredthSeconds / 100.0 ) / D_TIMEFACTOR; - bEmptyFlag = xRow->wasNull(); - rCell.mbNumeric = true; - rCell.mnType = SC_VALTYPE_VALUE; - } - break; - - case sdbc::DataType::SQLNULL: - case sdbc::DataType::BINARY: - case sdbc::DataType::VARBINARY: - case sdbc::DataType::LONGVARBINARY: - default: - break; - } - } - catch (uno::Exception&) + // Data rows + for (SCCOL nCol = 0; nCol < nColCount; ++nCol) { - } -} + SCROW nMemCount = GetCache()->GetDimMemberCount( nCol ); + if ( nMemCount ) + { + std::vector< SCROW > pAdded( nMemCount, -1 ); -void ScDPCacheTable::fillTable(const Reference<sdbc::XRowSet>& xRowSet, const Date& rNullDate) -{ - if (!xRowSet.is()) - // Dont' even waste time to go any further. - return; + for (SCROW nRow = 0; nRow < nRowCount; ++nRow ) + { + SCROW nIndex = GetCache()->GetItemDataId( nCol, nRow, false ); + SCROW nOrder = GetCache()->GetOrder( nCol, nIndex ); - try - { - Reference<sdbc::XResultSetMetaDataSupplier> xMetaSupp(xRowSet, UNO_QUERY_THROW); - Reference<sdbc::XResultSetMetaData> xMeta = xMetaSupp->getMetaData(); - if (!xMeta.is()) - return; - - sal_Int32 nColCount = xMeta->getColumnCount(); - - // Get column titles and types. - vector<sal_Int32> aColTypes(nColCount); - maHeader.clear(); - maHeader.reserve(nColCount); - for (sal_Int32 nCol = 0; nCol < nColCount; ++nCol) - { - String aColTitle = xMeta->getColumnLabel(nCol+1); - aColTypes[nCol] = xMeta->getColumnType(nCol+1); - maHeader.push_back( mrSharedString.getStringId(aColTitle) ); - } + if ( nCol == 0 ) + maRowsVisible.push_back(true); - // Initialize field entries container. - maFieldEntries.clear(); - maFieldEntries.reserve(nColCount); - for (SCCOL nCol = 0; nCol < nColCount; ++nCol) - { - TypedScStrCollectionPtr p(new TypedScStrCollection); - maFieldEntries.push_back(p); - } - // Now get the data rows. - Reference<sdbc::XRow> xRow(xRowSet, UNO_QUERY_THROW); - xRowSet->first(); - maTable.clear(); - maRowsVisible.clear(); - do - { - maRowsVisible.push_back(true); - maTable.push_back( vector<Cell>() ); - maTable.back().reserve(nColCount); - for (sal_Int32 nCol = 0; nCol < nColCount; ++nCol) + pAdded[nOrder] = nIndex; + } + maFieldEntries.push_back( vector<SCROW>() ); + for ( SCROW nRow = 0; nRow < nMemCount; nRow++ ) { - maTable.back().push_back( Cell() ); - Cell& rCell = maTable.back().back(); - ScDPCacheCell aCellContent; - String aStr; - lcl_GetCellValue(xRow, aColTypes[nCol], nCol+1, rNullDate, aCellContent, aStr, mrSharedString); - rCell.mpContent = mpCollection->getCacheCellFromPool(aCellContent); - - TypedStrData* pNew; - if (rCell.mpContent->mbNumeric) - pNew = new TypedStrData(aStr, rCell.mpContent->mfValue, SC_STRTYPE_VALUE); - else - pNew = new TypedStrData(aStr); - - if (!maFieldEntries[nCol]->Insert(pNew)) - delete pNew; + if ( pAdded[nRow] != -1 ) + maFieldEntries.back().push_back( pAdded[nRow] ); } } - while (xRowSet->next()); - - xRowSet->beforeFirst(); - } - catch (const Exception&) - { } + return; } bool ScDPCacheTable::isRowActive(sal_Int32 nRow) const @@ -524,41 +339,43 @@ void ScDPCacheTable::filterByPageDimension(const vector<Criterion>& rCriteria, c maRowsVisible[nRow] = isRowQualified(nRow, rCriteria, rRepeatIfEmptyDims); } -const ScDPCacheCell* ScDPCacheTable::getCell(SCCOL nCol, SCROW nRow, bool bRepeatIfEmpty) const +const ScDPItemData* ScDPCacheTable::getCell(SCCOL nCol, SCROW nRow, bool bRepeatIfEmpty) const { - if ( nRow >= static_cast<SCROW>(maTable.size()) ) - return NULL; - - const vector<Cell>& rRow = maTable[nRow]; - if ( nCol < 0 || static_cast<size_t>(nCol) >= rRow.size() ) - return NULL; + SCROW nId= GetCache()->GetItemDataId(nCol, nRow, bRepeatIfEmpty); + return GetCache()->GetItemDataById( nCol, nId ); +} - const Cell& rCell = rRow[nCol]; - const ScDPCacheCell* pCell = rCell.mpContent; - if (bRepeatIfEmpty && !pCell) - pCell = getCell(nCol, rCell.mnCategoryRef, false); +void ScDPCacheTable::getValue( ScDPValueData& rVal, SCCOL nCol, SCROW nRow, bool bRepeatIfEmpty) const +{ + const ScDPItemData* pData = getCell( nCol, nRow, bRepeatIfEmpty ); - return pCell ? pCell : &EmptyCellContent; + if (pData) + { + rVal.fValue = pData->IsValue() ? pData->GetValue() : 0.0; + rVal.nType = pData->GetType(); + } + else + rVal.Set(0.0, SC_VALTYPE_EMPTY); } - -const String* ScDPCacheTable::getFieldName(sal_Int32 nIndex) const +String ScDPCacheTable::getFieldName(SCCOL nIndex) const { - if (nIndex >= static_cast<sal_Int32>(maHeader.size())) - return NULL; + return (GetCache()->GetDimensionName( nIndex )); +} - return mrSharedString.getString(maHeader[nIndex]); +sal_Int32 ScDPCacheTable::getFieldIndex(const String& rStr) const +{ + return GetCache()->GetDimensionIndex( rStr ); } -const TypedScStrCollection& ScDPCacheTable::getFieldEntries(sal_Int32 nIndex) const +const ::std::vector<SCROW>& ScDPCacheTable::getFieldEntries( sal_Int32 nColumn ) const { - if (nIndex < 0 || static_cast<size_t>(nIndex) >= maFieldEntries.size()) + if (nColumn < 0 || static_cast<size_t>(nColumn) >= maFieldEntries.size()) { // index out of bound. Hopefully this code will never be reached. - static const TypedScStrCollection emptyCollection; - return emptyCollection; + static const ::std::vector<SCROW> emptyEntries; + return emptyEntries; } - - return *maFieldEntries[nIndex].get(); + return maFieldEntries[nColumn]; } void ScDPCacheTable::filterTable(const vector<Criterion>& rCriteria, Sequence< Sequence<Any> >& rTabData, @@ -577,13 +394,10 @@ void ScDPCacheTable::filterTable(const vector<Criterion>& rCriteria, Sequence< S // Header first. Sequence<Any> headerRow(nColSize); - for (sal_Int32 nCol = 0; nCol < nColSize; ++nCol) + for (SCCOL nCol = 0; nCol < nColSize; ++nCol) { OUString str; - const String* pStr = mrSharedString.getString(maHeader[nCol]); - if (pStr) - str = *pStr; - + str = getFieldName( nCol); Any any; any <<= str; headerRow[nCol] = any; @@ -607,26 +421,14 @@ void ScDPCacheTable::filterTable(const vector<Criterion>& rCriteria, Sequence< S { Any any; bool bRepeatIfEmpty = rRepeatIfEmptyDims.count(nCol) > 0; - const ScDPCacheCell* pCell = getCell(nCol, nRow, bRepeatIfEmpty); - if (!pCell) - { - // This should never happen, but in case this happens, just - // stick in an empty string. - OUString str; - any <<= str; - row[nCol] = any; - continue; - } - - if (pCell->mbNumeric) - any <<= pCell->mfValue; + // Wang Xu Ming - DataPilot migration + const ScDPItemData* pData= getCell(nCol, nRow, bRepeatIfEmpty); + if ( pData->IsValue() ) + any <<= pData->GetValue(); else { - OUString str; - const String* pStr = mrSharedString.getString(pCell->mnStrId); - if (pStr) - str = *pStr; - any <<= str; + OUString string (pData->GetString() ); + any <<= string; } row[nCol] = any; } @@ -642,15 +444,19 @@ void ScDPCacheTable::filterTable(const vector<Criterion>& rCriteria, Sequence< S void ScDPCacheTable::clear() { - maTable.clear(); - maHeader.clear(); maFieldEntries.clear(); maRowsVisible.clear(); } +void ScDPCacheTable::swap(ScDPCacheTable& rOther) +{ + maFieldEntries.swap(rOther.maFieldEntries); + maRowsVisible.swap(rOther.maRowsVisible); +} + bool ScDPCacheTable::empty() const { - return maTable.empty(); + return ( mpCache == NULL&& mpNoneCache == NULL ) || maFieldEntries.size()==0; } bool ScDPCacheTable::isRowQualified(sal_Int32 nRow, const vector<Criterion>& rCriteria, @@ -667,52 +473,26 @@ bool ScDPCacheTable::isRowQualified(sal_Int32 nRow, const vector<Criterion>& rCr // Check if the 'repeat if empty' flag is set for this field. bool bRepeatIfEmpty = rRepeatIfEmptyDims.count(itr->mnFieldIndex) > 0; - const ScDPCacheCell* pCell = getCell(static_cast<SCCOL>(itr->mnFieldIndex), nRow, bRepeatIfEmpty); - if (!pCell) - // This should never happen, but just in case... - return false; - - if (!itr->mpFilter->match(*pCell)) + const ScDPItemData* pCellData = getCell(static_cast<SCCOL>(itr->mnFieldIndex), nRow, bRepeatIfEmpty); + if (!itr->mpFilter->match(*pCellData)) return false; } return true; } -void ScDPCacheTable::getValueData(ScDocument* pDoc, const ScAddress& rPos, ScDPCacheCell& rCell) -{ - ScBaseCell* pCell = pDoc->GetCell(rPos); - if (!pCell) - { - rCell.mnType = SC_VALTYPE_EMPTY; - return; - } - - CellType eType = pCell->GetCellType(); - if (eType == CELLTYPE_NOTE) - { - // note cell - rCell.mnType = SC_VALTYPE_EMPTY; - return; - } - if (eType == CELLTYPE_FORMULA && static_cast<ScFormulaCell*>(pCell)->GetErrCode()) - { - // formula cell with error - rCell.mnType = SC_VALTYPE_ERROR; - return; - } - - if ( pCell->HasValueData() ) - { - if (eType == CELLTYPE_VALUE) - // value cell - rCell.mfValue = static_cast<ScValueCell*>(pCell)->GetValue(); - else if (eType == CELLTYPE_FORMULA) - // formula cell - rCell.mfValue = static_cast<ScFormulaCell*>(pCell)->GetValue(); - - rCell.mbNumeric = true; - rCell.mnType = SC_VALTYPE_VALUE; - } +void ScDPCacheTable::InitNoneCache( ScDocument* pDoc ) +{ + mpCache = NULL; + if ( mpNoneCache ) + delete mpNoneCache; + mpNoneCache = new ScDPTableDataCache( pDoc ); } +ScDPTableDataCache* ScDPCacheTable::GetCache() const +{ + if ( mpCache ) + return mpCache; + return mpNoneCache; +} +// End Comments diff --git a/sc/source/core/data/dpglobal.cxx b/sc/source/core/data/dpglobal.cxx new file mode 100755 index 000000000000..6b84d37d8d0f --- /dev/null +++ b/sc/source/core/data/dpglobal.cxx @@ -0,0 +1,150 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright IBM Corporation 2009. + * Copyright 2009 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: dpglobal.cxx,v $ + * $Revision: 1.0 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +#include "dpglobal.hxx" +#include "document.hxx" + +#include <stdio.h> + +namespace ScDPGlobal +{ + Rectangle operator *( const Rectangle &rLeft, const std::pair<double,double> & rRight ) + { + Rectangle rcResult( rLeft ); + rcResult.Bottom() = rcResult.Top() + static_cast<long>( rcResult.GetHeight() * rRight.second ); + rcResult.Right() = rcResult.Left() + static_cast<long>( rcResult.GetWidth() * rRight.first); + return rcResult; + } + + String GetFuncString( const String &rString, const USHORT nIndex ) + { + if ( nIndex <= 1 ) return rString; + ULONG uch = rString.Len() ? rString.GetChar( rString.Len()-1 ) : (L'9'+1); + bool bEndWithDigital = ( L'0'<=uch && uch<=L'9'); + char szTemp[__MAX_NUM_LEN+1]; + int nLen = sprintf( szTemp, bEndWithDigital ? DATA_RENAME_SEPARATOR"%hu" : "%hu", nIndex ); + String strRet = rString; + strRet.Append( String::CreateFromAscii( szTemp, static_cast<USHORT>(nLen) )); + return strRet; + } + + bool ChkDPTableOverlap( ScDocument *pDestDoc, std::list<ScDPObject> & rClipboard, SCCOL nClipStartCol, SCROW nClipStartRow, SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab, USHORT nEndTab, BOOL bExcludeClip /*= FALSE*/ ) + { + if ( ScDPCollection* pDPCollection = pDestDoc->GetDPCollection() ) + { + USHORT nCount = pDPCollection->GetCount(); + SCsCOL nOffsetX = nStartCol - nClipStartCol; + SCsROW nOffsetY = nStartRow - nClipStartRow; + + for( std::list<ScDPObject>::iterator iter = rClipboard.begin(); iter!=rClipboard.end(); iter++ ) + { + ScRange aRange = iter->GetOutRange(); + + for( USHORT nCurrTab = nStartTab; nCurrTab<=nEndTab; nCurrTab++ ) + { + SCsTAB nOffsetZ = nCurrTab - aRange.aStart.Tab(); + aRange.Move( nOffsetX, nOffsetY, nOffsetZ ); + + for ( USHORT i = 0; i<nCount; i++) + { + if ( (*pDPCollection)[i] && aRange.Intersects( (*pDPCollection)[i]->GetOutRange())) + { + if ( bExcludeClip && iter->GetOutRange() == (*pDPCollection)[i]->GetOutRange() ) + { + continue; + } + return false; + } + } + } + } + } + return true; +} +//end + +} +// -------------------------------------------------------------------- +// ScDPItemDataPool +// Construct +ScDPItemDataPool::ScDPItemDataPool(void) +{ +} +// +ScDPItemDataPool::ScDPItemDataPool(const ScDPItemDataPool& r): + maItems(r.maItems), + maItemIds(r.maItemIds) +{ +} + +ScDPItemDataPool::~ScDPItemDataPool(void) +{ +} + + +const ScDPItemData* ScDPItemDataPool::getData( sal_Int32 nId ) +{ + if ( nId >= static_cast<sal_Int32>(maItems.size()) ) + return NULL; + else + return &(maItems[nId]); +} + +sal_Int32 ScDPItemDataPool::getDataId( const ScDPItemData& aData ) +{ + DataHash::const_iterator itr = maItemIds.find( aData), + itrEnd = maItemIds.end(); + if ( itr == itrEnd ) + // not exist + return -1; + + else //exist + return itr->second; + +} + +sal_Int32 ScDPItemDataPool::insertData( const ScDPItemData& aData ) +{ + sal_Int32 nResult = getDataId( aData ); + + if( nResult < 0 ) + { + maItemIds.insert( DataHash::value_type( aData, nResult = maItems.size() ) ); + maItems.push_back( aData ); + } + + return nResult; +} + + diff --git a/sc/source/core/data/dpgroup.cxx b/sc/source/core/data/dpgroup.cxx index 1bc888100a9f..e71ec5c8b82c 100644 --- a/sc/source/core/data/dpgroup.cxx +++ b/sc/source/core/data/dpgroup.cxx @@ -47,6 +47,7 @@ #include "dptabsrc.hxx" #include "dptabres.hxx" #include "dpobject.hxx" +#include "dpglobal.hxx" #include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp> #include <com/sun/star/sheet/DataPilotFieldFilter.hpp> @@ -78,6 +79,202 @@ const sal_Int32 SC_DP_DATE_FIRST = -1; const sal_Int32 SC_DP_DATE_LAST = 10000; // ============================================================================ +namespace +{ + BOOL lcl_Search( SCCOL nSourceDim, ScDPTableDataCache* pCache , const std::vector< SCROW >& vIdx, SCROW nNew , SCROW& rIndex) + { + rIndex = vIdx.size(); + 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 = TRUE; + nLo = nIndex; + } + } + } + rIndex = nLo; + return bFound; + } + + void lcl_Insert( SCCOL nSourceDim, ScDPTableDataCache* pCache , std::vector< SCROW >& vIdx, SCROW nNew ) + { + SCROW nIndex = 0; + if ( !lcl_Search( nSourceDim, pCache, vIdx, nNew ,nIndex ) ) + vIdx.insert( vIdx.begin()+nIndex, nNew ); + } + + template<bool bUpdateData> + SCROW lcl_InsertValue( SCCOL nSourceDim, ScDPTableDataCache* pCache , std::vector< SCROW >& vIdx, const ScDPItemData & rData ); + + template<> + SCROW lcl_InsertValue<false>( SCCOL nSourceDim, ScDPTableDataCache* pCache , std::vector< SCROW >& vIdx, const ScDPItemData & rData ) + { + SCROW nNewID = pCache->GetAdditionalItemID( rData ); + lcl_Insert( nSourceDim, pCache, vIdx, nNewID ); + return nNewID; + } + + template<> + SCROW lcl_InsertValue<true>( SCCOL nSourceDim, ScDPTableDataCache* pCache , std::vector< SCROW >& vIdx, const ScDPItemData & rData ) + { + SCROW nItemId = lcl_InsertValue<false>( nSourceDim, pCache, vIdx, rData ); + + if( const ScDPItemData *pData = pCache->GetItemDataById( nSourceDim, nItemId ) ) + const_cast<ScDPItemData&>(*pData) = rData; + + return nItemId; + } + + template<bool bUpdateData> + void lcl_InsertValue ( SCCOL nSourceDim, ScDPTableDataCache* pCache , std::vector< SCROW >& vIdx, const String& rString, const double& fValue ) + { + lcl_InsertValue<bUpdateData>( nSourceDim, pCache, vIdx, ScDPItemData( rString, fValue, TRUE ) ); + } + + template<bool bUpdateData> + void lcl_InsertValue ( SCCOL nSourceDim, ScDPTableDataCache* pCache , std::vector< SCROW >& vIdx, const String& rString, const double& fValue, sal_Int32 nDatePart ) + { + lcl_InsertValue<bUpdateData>( nSourceDim, pCache, vIdx, ScDPItemData( nDatePart, rString, fValue, ScDPItemData::MK_DATA|ScDPItemData::MK_VAL|ScDPItemData::MK_DATEPART ) ); + } + + void lcl_AppendDateStr( rtl::OUStringBuffer& rBuffer, double fValue, SvNumberFormatter* pFormatter ) + { + 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 ) + { + DBG_ASSERT( cDecSeparator != 0, "cDecSeparator not initialized" ); + + double fStep = rInfo.Step; + double fEndValue = fStartValue + fStep; + if ( !bHasNonInteger && ( rInfo.DateValues || !rtl::math::approxEqual( fEndValue, rInfo.End ) ) ) + { + // 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.End && !rInfo.AutoEnd ) + { + // limit the last group to the end value + + fEndValue = rInfo.End; + } + + rtl::OUStringBuffer aBuffer; + if ( rInfo.DateValues ) + { + 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 ) + { + DBG_ASSERT( 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.Start && !rtl::math::approxEqual( fValue, rInfo.Start ) ) + { + rGroupValue = rInfo.Start - rInfo.Step; + return lcl_GetSpecialNumGroupName( rInfo.Start, true, cDecSeparator, rInfo.DateValues, pFormatter ); + } + + if ( fValue > rInfo.End && !rtl::math::approxEqual( fValue, rInfo.End ) ) + { + rGroupValue = rInfo.End + rInfo.Step; + return lcl_GetSpecialNumGroupName( rInfo.End, false, cDecSeparator, rInfo.DateValues, pFormatter ); + } + + double fDiff = fValue - rInfo.Start; + double fDiv = rtl::math::approxFloor( fDiff / rInfo.Step ); + double fGroupStart = rInfo.Start + fDiv * rInfo.Step; + + if ( rtl::math::approxEqual( fGroupStart, rInfo.End ) && + !rtl::math::approxEqual( fGroupStart, rInfo.Start ) ) + { + if ( !rInfo.DateValues ) + { + // 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.Start + fDiv * rInfo.Step; + } + 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.End + rInfo.Step; + return lcl_GetSpecialNumGroupName( rInfo.End, false, cDecSeparator, rInfo.DateValues, pFormatter ); + } + } + + rGroupValue = fGroupStart; + + return lcl_GetNumGroupName( fGroupStart, rInfo, bHasNonInteger, cDecSeparator, pFormatter ); + } +} class ScDPGroupDateFilter : public ScDPCacheTable::FilterBase { @@ -85,7 +282,10 @@ public: ScDPGroupDateFilter(double fMatchValue, sal_Int32 nDatePart, const Date* pNullDate, const ScDPNumGroupInfo* pNumInfo); - virtual bool match(const ScDPCacheCell &rCell) const; + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + virtual bool match(const ScDPItemData & rCellData) const; + // End Comments private: ScDPGroupDateFilter(); // disabled @@ -108,26 +308,25 @@ ScDPGroupDateFilter::ScDPGroupDateFilter(double fMatchValue, sal_Int32 nDatePart // fprintf(stdout, "ScDPCacheTable:DateGroupFilter::DateGroupFilter: match value = %g; date part = %ld\n", // mfMatchValue, mnDatePart); } - -bool ScDPGroupDateFilter::match(const ScDPCacheCell& rCell) const +bool ScDPGroupDateFilter::match( const ScDPItemData & rCellData ) const { using namespace ::com::sun::star::sheet; using ::rtl::math::approxFloor; using ::rtl::math::approxEqual; - if (!rCell.mbNumeric) + if ( !rCellData.IsValue() ) return false; - +// ScDPCacheCell rCell( rCellData.fValue ); if (!mpNumInfo) return false; // Start and end dates are inclusive. (An end date without a time value // is included, while an end date with a time value is not.) - if ( rCell.mfValue < mpNumInfo->Start && !approxEqual(rCell.mfValue, mpNumInfo->Start) ) + if ( rCellData.GetValue() < mpNumInfo->Start && !approxEqual(rCellData.GetValue(), mpNumInfo->Start) ) return static_cast<sal_Int32>(mfMatchValue) == SC_DP_DATE_FIRST; - if ( rCell.mfValue > mpNumInfo->End && !approxEqual(rCell.mfValue, mpNumInfo->End) ) + if ( rCellData.GetValue() > mpNumInfo->End && !approxEqual(rCellData.GetValue(), mpNumInfo->End) ) return static_cast<sal_Int32>(mfMatchValue) == SC_DP_DATE_LAST; if (mnDatePart == DataPilotFieldGroupBy::HOURS || mnDatePart == DataPilotFieldGroupBy::MINUTES || @@ -136,7 +335,7 @@ bool ScDPGroupDateFilter::match(const ScDPCacheCell& rCell) const // handle time // (as in the cell functions, ScInterpreter::ScGetHour etc.: seconds are rounded) - double time = rCell.mfValue - approxFloor(rCell.mfValue); + double time = rCellData.GetValue() - approxFloor(rCellData.GetValue()); long seconds = static_cast<long>(approxFloor(time*D_TIMEFACTOR + 0.5)); switch (mnDatePart) @@ -165,7 +364,7 @@ bool ScDPGroupDateFilter::match(const ScDPCacheCell& rCell) const return false; } - Date date = *mpNullDate + static_cast<long>(approxFloor(rCell.mfValue)); + Date date = *mpNullDate + static_cast<long>(approxFloor(rCellData.GetValue())); switch (mnDatePart) { case DataPilotFieldGroupBy::YEARS: @@ -204,17 +403,6 @@ bool ScDPGroupDateFilter::match(const ScDPCacheCell& rCell) const return false; } - -// ============================================================================ - -void lcl_AppendDateStr( rtl::OUStringBuffer& rBuffer, double fValue, SvNumberFormatter* pFormatter ) -{ - ULONG nFormat = pFormatter->GetStandardFormat( NUMBERFORMAT_DATE, ScGlobal::eLnge ); - String aString; - pFormatter->GetInputLineString( fValue, nFormat, aString ); - rBuffer.append( aString ); -} - // ----------------------------------------------------------------------- ScDPDateGroupHelper::ScDPDateGroupHelper( const ScDPNumGroupInfo& rInfo, sal_Int32 nPart ) : @@ -354,15 +542,18 @@ sal_Int32 lcl_GetDatePartValue( double fValue, sal_Int32 nDatePart, SvNumberForm BOOL lcl_DateContained( sal_Int32 nGroupPart, const ScDPItemData& rGroupData, sal_Int32 nBasePart, const ScDPItemData& rBaseData ) { - if ( !rGroupData.bHasValue || !rBaseData.bHasValue ) + if ( !rGroupData.IsValue() || !rBaseData.IsValue() ) { // non-numeric entries involved: only match equal entries return rGroupData.IsCaseInsEqual( rBaseData ); } // no approxFloor needed, values were created from integers - sal_Int32 nGroupValue = (sal_Int32) rGroupData.fValue; - sal_Int32 nBaseValue = (sal_Int32) rBaseData.fValue; +// Wang Xu Ming -- 2009-8-17 +// DataPilot Migration - Cache&&Performance + sal_Int32 nGroupValue = (sal_Int32) rGroupData.GetValue(); + sal_Int32 nBaseValue = (sal_Int32) rBaseData.GetValue(); +// End Comments if ( nBasePart > nGroupPart ) { // switch, so the base part is the smaller (inner) part @@ -417,28 +608,25 @@ String lcl_GetSpecialDateName( double fValue, bool bFirst, SvNumberFormatter* pF return aBuffer.makeStringAndClear(); } -void ScDPDateGroupHelper::FillColumnEntries( TypedScStrCollection& rEntries, const TypedScStrCollection& rOriginal, - SvNumberFormatter* pFormatter ) const +void ScDPDateGroupHelper::FillColumnEntries( SCCOL nSourceDim, ScDPTableDataCache* pCache, std::vector< SCROW >& rEntries, const std::vector< SCROW >& rOriginal ) 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; - USHORT nOriginalCount = rOriginal.GetCount(); - for (USHORT nOriginalPos=0; nOriginalPos<nOriginalCount; nOriginalPos++) + size_t nOriginalCount = rOriginal.size(); + for (size_t nOriginalPos=0; nOriginalPos<nOriginalCount; nOriginalPos++) { - const TypedStrData& rStrData = *rOriginal[nOriginalPos]; - if ( rStrData.IsStrData() ) + const ScDPItemData* pItemData = pCache->GetItemDataById( nSourceDim, rOriginal[nOriginalPos] ); + if ( pItemData->HasStringData() ) { // string data: just copy - TypedStrData* pNew = new TypedStrData( rStrData ); - if ( !rEntries.Insert( pNew ) ) - delete pNew; + lcl_Insert( nSourceDim, pCache , rEntries, rOriginal[nOriginalPos] ); } else { - double fSourceValue = rStrData.GetValue(); + double fSourceValue = pItemData->GetValue(); if ( bFirst ) { fSourceMin = fSourceMax = fSourceValue; @@ -462,6 +650,7 @@ void ScDPDateGroupHelper::FillColumnEntries( TypedScStrCollection& rEntries, con const_cast<ScDPDateGroupHelper*>(this)->aNumInfo.End = 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 @@ -485,22 +674,15 @@ void ScDPDateGroupHelper::FillColumnEntries( TypedScStrCollection& rEntries, con for ( sal_Int32 nValue = nStart; nValue <= nEnd; nValue++ ) { String aName = lcl_GetDateGroupName( nDatePart, nValue, pFormatter ); - TypedStrData* pNew = new TypedStrData( aName, nValue, SC_STRTYPE_VALUE ); - if ( !rEntries.Insert( pNew ) ) - delete pNew; + lcl_InsertValue<false>( nSourceDim, pCache, rEntries, aName, nValue, nDatePart ); } // add first/last entry (min/max) - String aFirstName = lcl_GetSpecialDateName( aNumInfo.Start, true, pFormatter ); - TypedStrData* pFirstEntry = new TypedStrData( aFirstName, SC_DP_DATE_FIRST, SC_STRTYPE_VALUE ); - if ( !rEntries.Insert( pFirstEntry ) ) - delete pFirstEntry; + lcl_InsertValue<true>( nSourceDim, pCache, rEntries, aFirstName, SC_DP_DATE_FIRST, nDatePart ); String aLastName = lcl_GetSpecialDateName( aNumInfo.End, false, pFormatter ); - TypedStrData* pLastEntry = new TypedStrData( aLastName, SC_DP_DATE_LAST, SC_STRTYPE_VALUE ); - if ( !rEntries.Insert( pLastEntry ) ) - delete pLastEntry; + lcl_InsertValue<true>( nSourceDim, pCache, rEntries, aLastName, SC_DP_DATE_LAST, nDatePart ); } // ----------------------------------------------------------------------- @@ -541,7 +723,10 @@ void ScDPGroupItem::FillGroupFilter( ScDPCacheTable::GroupFilter& rFilter ) cons { ScDPItemDataVec::const_iterator itrEnd = aElements.end(); for (ScDPItemDataVec::const_iterator itr = aElements.begin(); itr != itrEnd; ++itr) - rFilter.addMatchItem(itr->aString, itr->fValue, itr->bHasValue); +// Wang Xu Ming -- 2009-8-17 +// DataPilot Migration - Cache&&Performance + rFilter.addMatchItem(itr->GetString(), itr->GetValue(), itr->IsValue()); +// End Comments } // ----------------------------------------------------------------------- @@ -550,15 +735,15 @@ ScDPGroupDimension::ScDPGroupDimension( long nSource, const String& rNewName ) : nSourceDim( nSource ), nGroupDim( -1 ), aGroupName( rNewName ), - pDateHelper( NULL ), - pCollection( NULL ) + pDateHelper( NULL )/*, + pCollection( NULL )*/ { } ScDPGroupDimension::~ScDPGroupDimension() { delete pDateHelper; - delete pCollection; + maMemberEntries.clear(); } ScDPGroupDimension::ScDPGroupDimension( const ScDPGroupDimension& rOther ) : @@ -566,8 +751,7 @@ ScDPGroupDimension::ScDPGroupDimension( const ScDPGroupDimension& rOther ) : nGroupDim( rOther.nGroupDim ), aGroupName( rOther.aGroupName ), pDateHelper( NULL ), - aItems( rOther.aItems ), - pCollection( NULL ) // collection isn't copied - allocated on demand + aItems( rOther.aItems ) { if ( rOther.pDateHelper ) pDateHelper = new ScDPDateGroupHelper( *rOther.pDateHelper ); @@ -586,8 +770,6 @@ ScDPGroupDimension& ScDPGroupDimension::operator=( const ScDPGroupDimension& rOt else pDateHelper = NULL; - delete pCollection; // collection isn't copied - allocated on demand - pCollection = NULL; return *this; } @@ -606,44 +788,42 @@ void ScDPGroupDimension::SetGroupDim( long nDim ) { nGroupDim = nDim; } - -const TypedScStrCollection& ScDPGroupDimension::GetColumnEntries( - const TypedScStrCollection& rOriginal, ScDocument* pDoc ) const +// Wang Xu Ming -- 2009-9-2 +// DataPilot Migration - Cache&&Performance +const std::vector< SCROW >& ScDPGroupDimension::GetColumnEntries( const ScDPCacheTable& rCacheTable, const std::vector< SCROW >& rOriginal ) const { - if ( !pCollection ) + if ( maMemberEntries.empty() ) { - pCollection = new TypedScStrCollection(); if ( pDateHelper ) - pDateHelper->FillColumnEntries( *pCollection, rOriginal, pDoc->GetFormatTable() ); + { + pDateHelper->FillColumnEntries( (SCCOL)GetSourceDim(), rCacheTable.GetCache(), maMemberEntries, rOriginal ); + } else { - long nCount = aItems.size(); - for (long i=0; i<nCount; i++) + for (size_t i =0; i < rOriginal.size( ); i ++) { - //! numeric entries? - TypedStrData* pNew = new TypedStrData( aItems[i].GetName().aString ); - if ( !pCollection->Insert( pNew ) ) - delete pNew; - } - - USHORT nOriginalCount = rOriginal.GetCount(); - for (USHORT nOriginalPos=0; nOriginalPos<nOriginalCount; nOriginalPos++) - { - const TypedStrData& rStrData = *rOriginal[nOriginalPos]; - ScDPItemData aItemData( rStrData.GetString(), rStrData.GetValue(), !rStrData.IsStrData() ); - if ( !GetGroupForData( aItemData ) ) + const ScDPItemData* pItemData = rCacheTable.GetCache()->GetItemDataById( (SCCOL)GetSourceDim(), rOriginal[i] ); + if ( !pItemData || !GetGroupForData( *pItemData ) ) { // not in any group -> add as its own group - TypedStrData* pNew = new TypedStrData( rStrData ); - if ( !pCollection->Insert( pNew ) ) - delete pNew; + 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 ); + } } } - return *pCollection; + return maMemberEntries; } +// End Comments + + const ScDPGroupItem* ScDPGroupDimension::GetGroupForData( const ScDPItemData& rData ) const { for ( ScDPGroupItemVec::const_iterator aIter(aItems.begin()); aIter != aItems.end(); aIter++ ) @@ -672,15 +852,13 @@ const ScDPGroupItem* ScDPGroupDimension::GetGroupByIndex( size_t nIndex ) const void ScDPGroupDimension::DisposeData() { - delete pCollection; - pCollection = NULL; + maMemberEntries.clear(); } // ----------------------------------------------------------------------- ScDPNumGroupDimension::ScDPNumGroupDimension() : pDateHelper( NULL ), - pCollection( NULL ), bHasNonInteger( false ), cDecSeparator( 0 ) { @@ -689,7 +867,6 @@ ScDPNumGroupDimension::ScDPNumGroupDimension() : ScDPNumGroupDimension::ScDPNumGroupDimension( const ScDPNumGroupInfo& rInfo ) : aGroupInfo( rInfo ), pDateHelper( NULL ), - pCollection( NULL ), bHasNonInteger( false ), cDecSeparator( 0 ) { @@ -698,7 +875,6 @@ ScDPNumGroupDimension::ScDPNumGroupDimension( const ScDPNumGroupInfo& rInfo ) : ScDPNumGroupDimension::ScDPNumGroupDimension( const ScDPNumGroupDimension& rOther ) : aGroupInfo( rOther.aGroupInfo ), pDateHelper( NULL ), - pCollection( NULL ), // collection isn't copied - allocated on demand bHasNonInteger( false ), cDecSeparator( 0 ) { @@ -716,23 +892,19 @@ ScDPNumGroupDimension& ScDPNumGroupDimension::operator=( const ScDPNumGroupDimen else pDateHelper = NULL; - delete pCollection; // collection isn't copied - allocated on demand - pCollection = NULL; bHasNonInteger = false; return *this; } void ScDPNumGroupDimension::DisposeData() { - delete pCollection; - pCollection = NULL; bHasNonInteger = false; + maMemberEntries.clear(); } ScDPNumGroupDimension::~ScDPNumGroupDimension() { delete pDateHelper; - delete pCollection; } void ScDPNumGroupDimension::MakeDateHelper( const ScDPNumGroupInfo& rInfo, sal_Int32 nPart ) @@ -743,80 +915,15 @@ void ScDPNumGroupDimension::MakeDateHelper( const ScDPNumGroupInfo& rInfo, sal_I aGroupInfo.Enable = sal_True; //! or query both? } -String lcl_GetNumGroupName( double fStartValue, const ScDPNumGroupInfo& rInfo, - bool bHasNonInteger, sal_Unicode cDecSeparator, SvNumberFormatter* pFormatter ) -{ - DBG_ASSERT( cDecSeparator != 0, "cDecSeparator not initialized" ); - - double fStep = rInfo.Step; - double fEndValue = fStartValue + fStep; - if ( !bHasNonInteger && ( rInfo.DateValues || !rtl::math::approxEqual( fEndValue, rInfo.End ) ) ) - { - // 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.End && !rInfo.AutoEnd ) - { - // limit the last group to the end value - - fEndValue = rInfo.End; - } - - rtl::OUStringBuffer aBuffer; - if ( rInfo.DateValues ) - { - 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 ) +const std::vector< SCROW >& ScDPNumGroupDimension::GetNumEntries( SCCOL nSourceDim, ScDPTableDataCache* pCache, + const std::vector< SCROW >& rOriginal ) const { - DBG_ASSERT( 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) ); -} - -const TypedScStrCollection& ScDPNumGroupDimension::GetNumEntries( - const TypedScStrCollection& rOriginal, ScDocument* pDoc ) const -{ - if ( !pCollection ) + if ( maMemberEntries.empty() ) { - SvNumberFormatter* pFormatter = pDoc->GetFormatTable(); + SvNumberFormatter* pFormatter = pCache->GetDoc()->GetFormatTable(); - pCollection = new TypedScStrCollection(); if ( pDateHelper ) - pDateHelper->FillColumnEntries( *pCollection, rOriginal, pFormatter ); + pDateHelper->FillColumnEntries( nSourceDim, pCache, maMemberEntries,rOriginal ); else { // Copy textual entries. @@ -835,39 +942,37 @@ const TypedScStrCollection& ScDPNumGroupDimension::GetNumEntries( double fSourceMax = 0.0; bool bFirst = true; - USHORT nOriginalCount = rOriginal.GetCount(); - for (USHORT nOriginalPos=0; nOriginalPos<nOriginalCount; nOriginalPos++) + size_t nOriginalCount = rOriginal.size(); + for (size_t nOriginalPos=0; nOriginalPos<nOriginalCount; nOriginalPos++) { - const TypedStrData& rStrData = *rOriginal[nOriginalPos]; - if ( rStrData.IsStrData() ) - { - // string data: just copy - TypedStrData* pNew = new TypedStrData( rStrData ); - if ( !pCollection->Insert( pNew ) ) - delete pNew; - } - else - { - double fSourceValue = rStrData.GetValue(); - if ( bFirst ) - { - fSourceMin = fSourceMax = fSourceValue; - bFirst = false; - } - else - { - if ( fSourceValue < fSourceMin ) - fSourceMin = fSourceValue; - if ( fSourceValue > fSourceMax ) - fSourceMax = fSourceValue; - } - if ( !bHasNonInteger && !IsInteger( fSourceValue ) ) - { - // if any non-integer numbers are involved, the group labels are - // shown including their upper limit - bHasNonInteger = true; - } - } + const ScDPItemData* pItemData = pCache->GetItemDataById( nSourceDim , rOriginal[nOriginalPos] ); + + if ( pItemData && pItemData ->HasStringData() ) + { + lcl_Insert( nSourceDim, pCache, maMemberEntries, rOriginal[nOriginalPos] ); + } + else + { + double fSourceValue = pItemData->GetValue(); + if ( bFirst ) + { + fSourceMin = fSourceMax = fSourceValue; + bFirst = false; + } + else + { + if ( fSourceValue < fSourceMin ) + fSourceMin = fSourceValue; + if ( fSourceValue > fSourceMax ) + fSourceMax = fSourceValue; + } + if ( !bHasNonInteger && !IsInteger( fSourceValue ) ) + { + // if any non-integer numbers are involved, the group labels are + // shown including their upper limit + bHasNonInteger = true; + } + } } if ( aGroupInfo.DateValues ) @@ -899,10 +1004,7 @@ const TypedScStrCollection& ScDPNumGroupDimension::GetNumEntries( String aName = lcl_GetNumGroupName( fLoop, aGroupInfo, bHasNonInteger, cDecSeparator, pFormatter ); // create a numerical entry to ensure proper sorting // (in FillMemberResults this needs special handling) - TypedStrData* pNew = new TypedStrData( aName, fLoop, SC_STRTYPE_VALUE ); - if ( !pCollection->Insert( pNew ) ) - delete pNew; - + lcl_InsertValue<true>( nSourceDim, pCache, maMemberEntries, aName, fLoop ); ++nLoopCount; fLoop = aGroupInfo.Start + nLoopCount * aGroupInfo.Step; bFirstGroup = false; @@ -911,72 +1013,17 @@ const TypedScStrCollection& ScDPNumGroupDimension::GetNumEntries( } String aFirstName = lcl_GetSpecialNumGroupName( aGroupInfo.Start, true, cDecSeparator, aGroupInfo.DateValues, pFormatter ); - TypedStrData* pFirstEntry = new TypedStrData( aFirstName, aGroupInfo.Start - aGroupInfo.Step, SC_STRTYPE_VALUE ); - if ( !pCollection->Insert( pFirstEntry ) ) - delete pFirstEntry; + lcl_InsertValue<true>( nSourceDim, pCache, maMemberEntries, aFirstName, aGroupInfo.Start - aGroupInfo.Step ); String aLastName = lcl_GetSpecialNumGroupName( aGroupInfo.End, false, cDecSeparator, aGroupInfo.DateValues, pFormatter ); - TypedStrData* pLastEntry = new TypedStrData( aLastName, aGroupInfo.End + aGroupInfo.Step, SC_STRTYPE_VALUE ); - if ( !pCollection->Insert( pLastEntry ) ) - delete pLastEntry; - } - } - return *pCollection; -} - -// ----------------------------------------------------------------------- - -String lcl_GetNumGroupForValue( double fValue, const ScDPNumGroupInfo& rInfo, bool bHasNonInteger, - sal_Unicode cDecSeparator, double& rGroupValue, ScDocument* pDoc ) -{ - SvNumberFormatter* pFormatter = pDoc->GetFormatTable(); - - if ( fValue < rInfo.Start && !rtl::math::approxEqual( fValue, rInfo.Start ) ) - { - rGroupValue = rInfo.Start - rInfo.Step; - return lcl_GetSpecialNumGroupName( rInfo.Start, true, cDecSeparator, rInfo.DateValues, pFormatter ); - } - - if ( fValue > rInfo.End && !rtl::math::approxEqual( fValue, rInfo.End ) ) - { - rGroupValue = rInfo.End + rInfo.Step; - return lcl_GetSpecialNumGroupName( rInfo.End, false, cDecSeparator, rInfo.DateValues, pFormatter ); - } - - double fDiff = fValue - rInfo.Start; - double fDiv = rtl::math::approxFloor( fDiff / rInfo.Step ); - double fGroupStart = rInfo.Start + fDiv * rInfo.Step; - - if ( rtl::math::approxEqual( fGroupStart, rInfo.End ) && - !rtl::math::approxEqual( fGroupStart, rInfo.Start ) ) - { - if ( !rInfo.DateValues ) - { - // 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.Start + fDiv * rInfo.Step; - } - 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.End + rInfo.Step; - return lcl_GetSpecialNumGroupName( rInfo.End, false, cDecSeparator, rInfo.DateValues, pFormatter ); + lcl_InsertValue<true>( nSourceDim, pCache, maMemberEntries, aLastName, aGroupInfo.End + aGroupInfo.Step ); } } - - rGroupValue = fGroupStart; - - return lcl_GetNumGroupName( fGroupStart, rInfo, bHasNonInteger, cDecSeparator, pFormatter ); + return maMemberEntries; } ScDPGroupTableData::ScDPGroupTableData( const shared_ptr<ScDPTableData>& pSource, ScDocument* pDocument ) : - ScDPTableData(pDocument), + ScDPTableData(pDocument, pSource->GetCacheId() ), pSourceData( pSource ), pDoc( pDocument ) { @@ -1015,7 +1062,6 @@ long ScDPGroupTableData::GetDimensionIndex( const String& rName ) for (long i=0; i<nSourceCount; i++) // nSourceCount excludes data layout if ( pSourceData->getDimensionName(i) == rName ) //! ignore case? return i; - return -1; // none } @@ -1039,36 +1085,53 @@ void ScDPGroupTableData::GetNumGroupInfo( long nDimension, ScDPNumGroupInfo& rIn rDecimal = pNumGroups[nDimension].GetDecSeparator(); } } - -const TypedScStrCollection& ScDPGroupTableData::GetColumnEntries(long nColumn) +// Wang Xu Ming - DataPilot migration +long ScDPGroupTableData::GetMembersCount( long nDim ) +{ + const std::vector< SCROW >& members = GetColumnEntries( nDim ); + return members.size(); +} +const std::vector< SCROW >& ScDPGroupTableData::GetColumnEntries( long nColumn ) { - // date handling is in ScDPGroupDimension::GetColumnEntries / ScDPNumGroupDimension::GetNumEntries - // (to use the pCollection members) - if ( nColumn >= nSourceCount ) { - if ( nColumn == sal::static_int_cast<long>( nSourceCount + aGroups.size() ) ) // data layout dimension? + if ( getIsDataLayoutDimension( nColumn) ) // data layout dimension? nColumn = nSourceCount; // index of data layout in source data else { const ScDPGroupDimension& rGroupDim = aGroups[nColumn - nSourceCount]; long nSourceDim = rGroupDim.GetSourceDim(); // collection is cached at pSourceData, GetColumnEntries can be called every time - const TypedScStrCollection& rOriginal = pSourceData->GetColumnEntries( nSourceDim ); - return rGroupDim.GetColumnEntries( rOriginal, pDoc ); + const std::vector< SCROW >& rOriginal = pSourceData->GetColumnEntries( nSourceDim ); + return rGroupDim.GetColumnEntries( GetCacheTable(), rOriginal ); } } if ( IsNumGroupDimension( nColumn ) ) { // dimension number is unchanged for numerical groups - const TypedScStrCollection& rOriginal = pSourceData->GetColumnEntries( nColumn ); - return pNumGroups[nColumn].GetNumEntries( rOriginal, pDoc ); + const std::vector< SCROW >& rOriginal = pSourceData->GetColumnEntries( nColumn ); + return pNumGroups[nColumn].GetNumEntries( (SCCOL)nColumn, GetCacheTable().GetCache(), rOriginal ); } return pSourceData->GetColumnEntries( nColumn ); } +const ScDPItemData* ScDPGroupTableData::GetMemberById( long nDim, long nId ) +{ + if ( nDim >= nSourceCount ) + { + if ( getIsDataLayoutDimension( nDim) ) + nDim = nSourceCount; + else + { + const ScDPGroupDimension& rGroupDim = aGroups[nDim - nSourceCount]; + nDim = rGroupDim.GetSourceDim(); + } + } + return pSourceData->GetMemberById( nDim, nId ); +} + String ScDPGroupTableData::getDimensionName(long nColumn) { if ( nColumn >= nSourceCount ) @@ -1101,7 +1164,7 @@ BOOL ScDPGroupTableData::IsDateDimension(long nDim) return pSourceData->IsDateDimension( nDim ); } -UINT32 ScDPGroupTableData::GetNumberFormat(long nDim) +ULONG ScDPGroupTableData::GetNumberFormat(long nDim) { if ( nDim >= nSourceCount ) { @@ -1220,16 +1283,19 @@ void ScDPGroupTableData::ModifyFilterCriteria(vector<ScDPCacheTable::Criterion>& for (size_t i = 0; i < nGroupItemCount; ++i) { const ScDPGroupItem* pGrpItem = pGrpDim->GetGroupByIndex(i); - ScDPItemData aName; - aName.aString = pFilter->getMatchString(); + // Wang Xu Ming -- 2009-6-9 + // DataPilot Migration + ScDPItemData aName( pFilter->getMatchString(),pFilter->getMatchValue(),pFilter->hasValue()) ; + /*aName.aString = pFilter->getMatchString(); aName.fValue = pFilter->getMatchValue(); - aName.bHasValue = pFilter->hasValue(); - if (!pGrpItem || !pGrpItem->GetName().IsCaseInsEqual(aName)) + aName.bHasValue = pFilter->hasValue();*/ + // End Comments + if (!pGrpItem || !pGrpItem->GetName().IsCaseInsEqual(aName)) continue; ScDPCacheTable::Criterion aCri; aCri.mnFieldIndex = nSrcDim; - aCri.mpFilter.reset(new ScDPCacheTable::GroupFilter(GetSharedString())); + aCri.mpFilter.reset(new ScDPCacheTable::GroupFilter()); ScDPCacheTable::GroupFilter* pGrpFilter = static_cast<ScDPCacheTable::GroupFilter*>(aCri.mpFilter.get()); @@ -1321,25 +1387,27 @@ void ScDPGroupTableData::CopyFields(const vector<long>& rFieldDims, vector<long> } } -void ScDPGroupTableData::FillGroupValues( ScDPItemData* pItemData, long nCount, const long* pDims ) +void ScDPGroupTableData::FillGroupValues( /*ScDPItemData* pItemData*/ SCROW* pItemDataIndex, long nCount, const long* pDims ) { long nGroupedColumns = aGroups.size(); + ScDPTableDataCache* pCache = GetCacheTable().GetCache(); for (long nDim=0; nDim<nCount; nDim++) { const ScDPDateGroupHelper* pDateHelper = NULL; long nColumn = pDims[nDim]; + long nSourceDim = nColumn; if ( nColumn >= nSourceCount && nColumn < nSourceCount + nGroupedColumns ) { const ScDPGroupDimension& rGroupDim = aGroups[nColumn - nSourceCount]; + nSourceDim= rGroupDim.GetSourceDim(); pDateHelper = rGroupDim.GetDateHelper(); if ( !pDateHelper ) // date is handled below { - const ScDPGroupItem* pGroupItem = rGroupDim.GetGroupForData( pItemData[nDim] ); - if ( pGroupItem ) - pItemData[nDim] = pGroupItem->GetName(); - // if no group is found, keep the original name + const ScDPGroupItem* pGroupItem = rGroupDim.GetGroupForData( *GetMemberById( nSourceDim, pItemDataIndex[nDim] )); + if ( pGroupItem ) + pItemDataIndex[nDim] = pCache->GetAdditionalItemID( pGroupItem->GetName() ); } } else if ( IsNumGroupDimension( nColumn ) ) @@ -1347,18 +1415,18 @@ void ScDPGroupTableData::FillGroupValues( ScDPItemData* pItemData, long nCount, pDateHelper = pNumGroups[nColumn].GetDateHelper(); if ( !pDateHelper ) // date is handled below { - if ( pItemData[nDim].bHasValue ) + const ScDPItemData* pData = pCache->GetItemDataById( (SCCOL)nSourceDim, pItemDataIndex[nDim]); + if ( pData ->IsValue() ) { ScDPNumGroupInfo aNumInfo; bool bHasNonInteger = false; sal_Unicode cDecSeparator = 0; GetNumGroupInfo( nColumn, aNumInfo, bHasNonInteger, cDecSeparator ); double fGroupValue; - String aGroupName = lcl_GetNumGroupForValue( pItemData[nDim].fValue, - aNumInfo, bHasNonInteger, cDecSeparator, fGroupValue, pDoc ); - - // consistent with TypedStrData in GetNumEntries - pItemData[nDim] = ScDPItemData( aGroupName, fGroupValue, TRUE ); + String aGroupName = lcl_GetNumGroupForValue( pData->GetValue(), + aNumInfo, bHasNonInteger, cDecSeparator, fGroupValue, pDoc ); + ScDPItemData aItemData ( aGroupName, fGroupValue, TRUE ) ; + pItemDataIndex[nDim] = pCache->GetAdditionalItemID( aItemData ); } // else (textual) keep original value } @@ -1366,12 +1434,18 @@ void ScDPGroupTableData::FillGroupValues( ScDPItemData* pItemData, long nCount, if ( pDateHelper ) { - if ( pItemData[nDim].bHasValue ) + const ScDPItemData* pData = GetCacheTable().GetCache()->GetItemDataById( (SCCOL)nSourceDim, pItemDataIndex[nDim]); + if ( pData ->IsValue() ) { sal_Int32 nPartValue = lcl_GetDatePartValue( - pItemData[nDim].fValue, pDateHelper->GetDatePart(), pDoc->GetFormatTable(), - &pDateHelper->GetNumInfo() ); - pItemData[nDim] = ScDPItemData( String(), nPartValue, TRUE ); + pData->GetValue(), pDateHelper->GetDatePart(), pDoc->GetFormatTable(), + &pDateHelper->GetNumInfo() ); +// Wang Xu Ming -- 2009-9-7 +// DataPilot Migration - Cache&&Performance + //String aName = lcl_GetDateGroupName( pDateHelper, nPartValue, pDoc->GetFormatTable() ); + ScDPItemData aItemData( pDateHelper->GetDatePart(), String(), nPartValue, ScDPItemData::MK_DATA|ScDPItemData::MK_VAL|ScDPItemData::MK_DATEPART ); + pItemDataIndex[nDim] = GetCacheTable().GetCache()->GetAdditionalItemID( aItemData ); +// End Comments } } } @@ -1527,5 +1601,22 @@ BOOL ScDPGroupTableData::HasCommonElement( const ScDPItemData& rFirstData, long return TRUE; } +long ScDPGroupTableData::GetSourceDim( long nDim ) +{ + if ( getIsDataLayoutDimension( nDim ) ) + return nSourceCount; + if ( nDim >= nSourceCount && nDim < nSourceCount +(long) aGroups.size() ) + { + const ScDPGroupDimension& rGroupDim = aGroups[nDim - nSourceCount]; + return rGroupDim.GetSourceDim(); + } + return nDim; +} + long ScDPGroupTableData::Compare( long nDim, long nDataId1, long nDataId2) +{ + if ( getIsDataLayoutDimension(nDim) ) + return 0; + return ScDPItemData::Compare( *GetMemberById(nDim, nDataId1),*GetMemberById(nDim, nDataId2) ); +} // ----------------------------------------------------------------------- diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx index 7d1dd85c0a25..44c998fb4ede 100644..100755 --- a/sc/source/core/data/dpobject.cxx +++ b/sc/source/core/data/dpobject.cxx @@ -52,7 +52,11 @@ #include "attrib.hxx" #include "scitems.hxx" #include "unonames.hxx" - +// Wang Xu Ming -- 2009-8-17 +// DataPilot Migration - Cache&&Performance +#include "dpglobal.hxx" +#include "globstr.hrc" +// End Comments #include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/sheet/GeneralFunction.hpp> #include <com/sun/star/sheet/DataPilotFieldFilter.hpp> @@ -86,9 +90,6 @@ using ::com::sun::star::sheet::DataPilotTablePositionData; using ::com::sun::star::beans::XPropertySet; using ::rtl::OUString; -// ----------------------------------------------------------------------- - -#define MAX_LABELS 256 //!!! from fieldwnd.hxx, must be moved to global.hxx // ----------------------------------------------------------------------- @@ -168,7 +169,9 @@ ScDPObject::ScDPObject( ScDocument* pD ) : mnAutoFormatIndex( 65535 ), bAllowMove( FALSE ), nHeaderRows( 0 ), - mbHeaderLayout(false) + mbHeaderLayout(false), + bRefresh( FALSE ), // Wang Xu Ming - DataPilot migration + mnCacheId( -1) // Wang Xu Ming - DataPilot migration { } @@ -189,7 +192,9 @@ ScDPObject::ScDPObject(const ScDPObject& r) : mnAutoFormatIndex( r.mnAutoFormatIndex ), bAllowMove( FALSE ), nHeaderRows( r.nHeaderRows ), - mbHeaderLayout( r.mbHeaderLayout ) + mbHeaderLayout( r.mbHeaderLayout ), + bRefresh( r.bRefresh ), // Wang Xu Ming - DataPilot migration + mnCacheId ( r.mnCacheId ) // Wang Xu Ming - DataPilot migration { if (r.pSaveData) pSaveData = new ScDPSaveData(*r.pSaveData); @@ -209,6 +214,7 @@ ScDPObject::~ScDPObject() delete pSheetDesc; delete pImpDesc; delete pServDesc; + mnCacheId = -1; // Wang Xu Ming - DataPilot migration } ScDataObject* ScDPObject::Clone() const @@ -232,6 +238,13 @@ void ScDPObject::SetSaveData(const ScDPSaveData& rData) { delete pSaveData; pSaveData = new ScDPSaveData( rData ); + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + if ( rData.GetCacheId() >= 0 ) + mnCacheId = rData.GetCacheId(); + else if ( mnCacheId >= 0 ) + pSaveData->SetCacheId( mnCacheId ); + // End Comments } InvalidateData(); // re-init source from SaveData @@ -411,10 +424,11 @@ ScDPTableData* ScDPObject::GetTableData() { if (!mpTableData) { + shared_ptr<ScDPTableData> pData; if ( pImpDesc ) { // database data - mpTableData.reset(new ScDatabaseDPData(pDoc, *pImpDesc)); + pData.reset(new ScDatabaseDPData(pDoc, *pImpDesc, GetCacheId())); } else { @@ -424,16 +438,27 @@ ScDPTableData* ScDPObject::GetTableData() DBG_ERROR("no source descriptor"); pSheetDesc = new ScSheetSourceDesc; // dummy defaults } - mpTableData.reset(new ScSheetDPData(pDoc, *pSheetDesc)); + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + pData.reset(new ScSheetDPData(pDoc, *pSheetDesc, GetCacheId())); + // End Comments } // grouping (for cell or database data) if ( pSaveData && pSaveData->GetExistingDimensionData() ) { - shared_ptr<ScDPGroupTableData> pGroupData(new ScDPGroupTableData(mpTableData, pDoc)); + shared_ptr<ScDPGroupTableData> pGroupData(new ScDPGroupTableData(pData, pDoc)); pSaveData->GetExistingDimensionData()->WriteToData(*pGroupData); - mpTableData = pGroupData; + pData = pGroupData; } + + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + if ( pData ) + SetCacheId( pData->GetCacheId()); // resets mpTableData + // End Comments + + mpTableData = pData; // after SetCacheId } return mpTableData.get(); @@ -462,11 +487,17 @@ void ScDPObject::CreateObjects() { DBG_ASSERT( !pServDesc, "DPSource could not be created" ); ScDPTableData* pData = GetTableData(); + ScDPSource* pSource = new ScDPSource( pData ); xSource = pSource; - } - if (pSaveData) + if ( pSaveData && bRefresh ) + { + pSaveData->Refresh( xSource ); + bRefresh = FALSE; + } + } + if (pSaveData ) pSaveData->WriteToSource( xSource ); } else if (bSettingsChanged) @@ -2298,48 +2329,6 @@ 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) : @@ -2349,15 +2338,12 @@ ScDPCollection::ScDPCollection(ScDocument* pDocument) : ScDPCollection::ScDPCollection(const ScDPCollection& r) : ScCollection(r), - pDoc(r.pDoc), - maSharedString(r.maSharedString), - maCacheCellPool() // #i101725# don't copy hash_set with pointers from the other collection + pDoc(r.pDoc) { } ScDPCollection::~ScDPCollection() { - clearCacheCellPool(); } ScDataObject* ScDPCollection::Clone() const @@ -2462,10 +2448,83 @@ String ScDPCollection::CreateNewName( USHORT nMin ) const return String(); // should not happen } -ScSimpleSharedString& ScDPCollection::GetSharedString() + + +// Wang Xu Ming -- 2009-8-17 +// DataPilot Migration - Cache&&Performance +long ScDPObject::GetCacheId() const +{ + if ( GetSaveData() ) + return GetSaveData()->GetCacheId(); + else + return mnCacheId; +} +ULONG ScDPObject::RefreshCache() +{ + if ( pServDesc ) + { + // cache table isn't used for external service - do nothing, no error + return 0; + } + + CreateObjects(); + ULONG nErrId = 0; + if ( pSheetDesc) + nErrId = pSheetDesc->CheckValidate( pDoc ); + if ( nErrId == 0 ) + { + long nOldId = GetCacheId(); + long nNewId = pDoc->GetNewDPObjectCacheId(); + if ( nOldId >= 0 ) + pDoc->RemoveDPObjectCache( nOldId ); + + ScDPTableDataCache* pCache = NULL; + if ( pSheetDesc ) + pCache = pSheetDesc->CreateCache( pDoc, nNewId ); + else if ( pImpDesc ) + pCache = pImpDesc->CreateCache( pDoc, nNewId ); + + if ( pCache == NULL ) + { + //cache failed + DBG_ASSERT( pCache , " pCache == NULL" ); + return STR_ERR_DATAPILOTSOURCE; + } + + nNewId = pCache->GetId(); + + bRefresh = TRUE; + ScDPCollection* pDPCollection = pDoc->GetDPCollection(); + USHORT nCount = pDPCollection->GetCount(); + for (USHORT i=0; i<nCount; i++) + { //set new cache id + if ( (*pDPCollection)[i]->GetCacheId() == nOldId ) + { + (*pDPCollection)[i]->SetCacheId( nNewId ); + (*pDPCollection)[i]->SetRefresh(); + + } + } + DBG_ASSERT( GetCacheId() >= 0, " GetCacheId() >= 0 " ); + } + return nErrId; +} +void ScDPObject::SetCacheId( long nCacheId ) +{ + if ( GetCacheId() != nCacheId ) + { + InvalidateSource(); + if ( GetSaveData() ) + GetSaveData()->SetCacheId( nCacheId ); + + mnCacheId = nCacheId; + } +} +const ScDPTableDataCache* ScDPObject::GetCache() const { - return maSharedString; + return pDoc->GetDPObjectCache( GetCacheId() ); } +// End Comments void ScDPCollection::FreeTable(ScDPObject* pDPObj) { @@ -2500,54 +2559,4 @@ bool ScDPCollection::HasDPTable(SCCOL nCol, SCROW nRow, SCTAB nTab) const return pMergeAttr->HasDPTable(); } -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 stored pointers to a vector first. For some unknown - // reason, deleting cell content instances by directly iterating through - // the hash set causes the iteration to return an identical pointer - // value twice, causing a double-delete. I have no idea why this happens. - - using ::std::copy; - using ::std::back_inserter; - - vector<ScDPCacheCell*> ps; - ps.reserve(maCacheCellPool.size()); - copy(maCacheCellPool.begin(), maCacheCellPool.end(), back_inserter(ps)); - maCacheCellPool.clear(); - // for correctness' sake, delete the elements after clearing the hash_set - for_each(ps.begin(), ps.end(), DeleteCacheCells()); -} diff --git a/sc/source/core/data/dpoutput.cxx b/sc/source/core/data/dpoutput.cxx index 401d9b396bc0..ec384874aa69 100644..100755 --- a/sc/source/core/data/dpoutput.cxx +++ b/sc/source/core/data/dpoutput.cxx @@ -56,22 +56,11 @@ #include "scresid.hxx" #include "unonames.hxx" #include "sc.hrc" - -#include <com/sun/star/container/XNamed.hpp> -#include <com/sun/star/sheet/DataPilotFieldFilter.hpp> -#include <com/sun/star/sheet/DataPilotFieldOrientation.hpp> -#include <com/sun/star/sheet/DataPilotTableHeaderData.hpp> -#include <com/sun/star/sheet/DataPilotTablePositionData.hpp> -#include <com/sun/star/sheet/DataPilotTablePositionType.hpp> -#include <com/sun/star/sheet/DataPilotTableResultData.hpp> -#include <com/sun/star/sheet/DataResultFlags.hpp> -#include <com/sun/star/sheet/GeneralFunction.hpp> -#include <com/sun/star/sheet/MemberResultFlags.hpp> -#include <com/sun/star/sheet/TableFilterField.hpp> -#include <com/sun/star/sheet/XDataPilotMemberResults.hpp> -#include <com/sun/star/sheet/XDataPilotResults.hpp> -#include <com/sun/star/sheet/XHierarchiesSupplier.hpp> -#include <com/sun/star/sheet/XLevelsSupplier.hpp> +// Wang Xu Ming -- 2009-8-17 +// DataPilot Migration - Cache&&Performance +#include "scdpoutputimpl.hxx" +#include "dpglobal.hxx" +// End Comments #include <com/sun/star/beans/XPropertySet.hpp> #include <vector> @@ -651,11 +640,21 @@ void ScDPOutput::HeaderCell( SCCOL nCol, SCROW nRow, SCTAB nTab, if ( nFlags & sheet::MemberResultFlags::SUBTOTAL ) { // SvxWeightItem aItem( WEIGHT_BOLD ); // weight is in the style - + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + OutputImpl outputimp( pDoc, nTab, + nTabStartCol, nTabStartRow, nMemberStartCol, nMemberStartRow, + nDataStartCol, nDataStartRow, nTabEndCol, nTabEndRow ); + // End Comments //! limit frames to horizontal or vertical? if (bColHeader) { - lcl_SetFrame( pDoc,nTab, nCol,nMemberStartRow+(SCROW)nLevel, nCol,nTabEndRow, 20 ); + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + //lcl_SetFrame( pDoc,nTab, nCol,nMemberStartRow+(SCROW)nLevel, nCol,nTabEndRow, SC_DP_FRAME_INNER_BOLD ); + outputimp.OutputBlockFrame( nCol,nMemberStartRow+(SCROW)nLevel, nCol,nDataStartRow-1 ); + // End Comments + lcl_SetStyleById( pDoc,nTab, nCol,nMemberStartRow+(SCROW)nLevel, nCol,nDataStartRow-1, STR_PIVOT_STYLE_TITLE ); lcl_SetStyleById( pDoc,nTab, nCol,nDataStartRow, nCol,nTabEndRow, @@ -663,7 +662,11 @@ void ScDPOutput::HeaderCell( SCCOL nCol, SCROW nRow, SCTAB nTab, } else { - lcl_SetFrame( pDoc,nTab, nMemberStartCol+(SCCOL)nLevel,nRow, nTabEndCol,nRow, 20 ); + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + //lcl_SetFrame( pDoc,nTab, nMemberStartCol+(USHORT)nLevel,nRow, nTabEndCol,nRow, SC_DP_FRAME_INNER_BOLD ); + outputimp.OutputBlockFrame( nMemberStartCol+(SCCOL)nLevel,nRow, nDataStartCol-1,nRow ); + // End Comments lcl_SetStyleById( pDoc,nTab, nMemberStartCol+(SCCOL)nLevel,nRow, nDataStartCol-1,nRow, STR_PIVOT_STYLE_TITLE ); lcl_SetStyleById( pDoc,nTab, nDataStartCol,nRow, nTabEndCol,nRow, @@ -812,6 +815,20 @@ void ScDPOutput::Output() if ( bDoFilter ) lcl_DoFilterButton( pDoc, aStartPos.Col(), aStartPos.Row(), nTab ); + // output data results: + + for (long nRow=0; nRow<nRowCount; nRow++) + { + SCROW nRowPos = nDataStartRow + (SCROW)nRow; //! check for overflow + const sheet::DataResult* pColAry = pRowAry[nRow].getConstArray(); + long nThisColCount = pRowAry[nRow].getLength(); + DBG_ASSERT( nThisColCount == nColCount, "count mismatch" ); //! ??? + for (long nCol=0; nCol<nThisColCount; nCol++) + { + SCCOL nColPos = nDataStartCol + (SCCOL)nCol; //! check for overflow + DataCell( nColPos, nRowPos, nTab, pColAry[nCol] ); + } + } // output page fields: for (nField=0; nField<nPageFieldCount; nField++) @@ -854,7 +871,12 @@ void ScDPOutput::Output() STR_PIVOT_STYLE_INNER ); // output column headers: - + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + OutputImpl outputimp( pDoc, nTab, + nTabStartCol, nTabStartRow, nMemberStartCol, nMemberStartRow, + nDataStartCol, nDataStartRow, nTabEndCol, nTabEndRow ); + // End Comments for (nField=0; nField<nColFieldCount; nField++) { SCCOL nHdrCol = nDataStartCol + (SCCOL)nField; //! check for overflow @@ -869,28 +891,44 @@ void ScDPOutput::Output() { SCCOL nColPos = nDataStartCol + (SCCOL)nCol; //! check for overflow HeaderCell( nColPos, nRowPos, nTab, pArray[nCol], TRUE, nField ); + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance if ( ( pArray[nCol].Flags & sheet::MemberResultFlags::HASMEMBER ) && !( pArray[nCol].Flags & sheet::MemberResultFlags::SUBTOTAL ) ) { + long nEnd = nCol; + while ( nEnd+1 < nThisColCount && ( pArray[nEnd+1].Flags & sheet::MemberResultFlags::CONTINUE ) ) + ++nEnd; + SCCOL nEndColPos = nDataStartCol + (SCCOL)nEnd; //! check for overflow if ( nField+1 < nColFieldCount ) { - long nEnd = nCol; - while ( nEnd+1 < nThisColCount && ( pArray[nEnd+1].Flags & sheet::MemberResultFlags::CONTINUE ) ) - ++nEnd; - SCCOL nEndColPos = nDataStartCol + (SCCOL)nEnd; //! check for overflow - lcl_SetFrame( pDoc,nTab, nColPos,nRowPos, nEndColPos,nRowPos, 20 ); - lcl_SetFrame( pDoc,nTab, nColPos,nRowPos, nEndColPos,nTabEndRow, 20 ); + // lcl_SetFrame( pDoc,nTab, nColPos,nRowPos, nEndColPos,nRowPos, SC_DP_FRAME_INNER_BOLD ); + // lcl_SetFrame( pDoc,nTab, nColPos,nRowPos, nEndColPos,nTabEndRow, SC_DP_FRAME_INNER_BOLD ); + if ( nField == nColFieldCount - 2 ) + { + outputimp.AddCol( nColPos ); + if ( nColPos + 1 == nEndColPos ) + outputimp.OutputBlockFrame( nColPos,nRowPos, nEndColPos,nRowPos+1, TRUE ); + } + else + outputimp.OutputBlockFrame( nColPos,nRowPos, nEndColPos,nRowPos ); lcl_SetStyleById( pDoc, nTab, nColPos,nRowPos, nEndColPos,nDataStartRow-1, STR_PIVOT_STYLE_CATEGORY ); } else lcl_SetStyleById( pDoc, nTab, nColPos,nRowPos, nColPos,nDataStartRow-1, STR_PIVOT_STYLE_CATEGORY ); } + else if ( pArray[nCol].Flags & sheet::MemberResultFlags::SUBTOTAL ) + outputimp.AddCol( nColPos ); } + if ( nField== 0 && nColFieldCount == 1 ) + outputimp.OutputBlockFrame( nDataStartCol,nTabStartRow, nTabEndCol,nRowPos-1 ); + // End Comments } // output row headers: - + std::vector<BOOL> vbSetBorder; + vbSetBorder.resize( nTabEndRow - nDataStartRow + 1, FALSE ); for (nField=0; nField<nRowFieldCount; nField++) { bool bDataLayout = mbHasDataLayout && (nField == nRowFieldCount-1); @@ -918,41 +956,39 @@ void ScDPOutput::Output() while ( nEnd+1 < nThisRowCount && ( pArray[nEnd+1].Flags & sheet::MemberResultFlags::CONTINUE ) ) ++nEnd; SCROW nEndRowPos = nDataStartRow + (SCROW)nEnd; //! check for overflow - lcl_SetFrame( pDoc,nTab, nColPos,nRowPos, nColPos,nEndRowPos, 20 ); - lcl_SetFrame( pDoc,nTab, nColPos,nRowPos, nTabEndCol,nEndRowPos, 20 ); + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + // lcl_SetFrame( pDoc,nTab, nColPos,nRowPos, nColPos,nEndRowPos, SC_DP_FRAME_INNER_BOLD ); + //lcl_SetFrame( pDoc,nTab, nColPos,nRowPos, nTabEndCol,nEndRowPos, SC_DP_FRAME_INNER_BOLD ); + outputimp.AddRow( nRowPos ); + if ( vbSetBorder[ nRow ] == FALSE ) + { + outputimp.OutputBlockFrame( nColPos, nRowPos, nTabEndCol, nEndRowPos ); + vbSetBorder[ nRow ] = TRUE; + } + outputimp.OutputBlockFrame( nColPos, nRowPos, nColPos, nEndRowPos ); + + if ( nField == nRowFieldCount - 2 ) + outputimp.OutputBlockFrame( nColPos+1, nRowPos, nColPos+1, nEndRowPos ); + // End Comments lcl_SetStyleById( pDoc, nTab, nColPos,nRowPos, nDataStartCol-1,nEndRowPos, STR_PIVOT_STYLE_CATEGORY ); } else lcl_SetStyleById( pDoc, nTab, nColPos,nRowPos, nDataStartCol-1,nRowPos, STR_PIVOT_STYLE_CATEGORY ); } + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + else if ( pArray[nRow].Flags & sheet::MemberResultFlags::SUBTOTAL ) + outputimp.AddRow( nRowPos ); + // End Comments } } - // output data results: - - for (long nRow=0; nRow<nRowCount; nRow++) - { - SCROW nRowPos = nDataStartRow + (SCROW)nRow; //! check for overflow - const sheet::DataResult* pColAry = pRowAry[nRow].getConstArray(); - long nThisColCount = pRowAry[nRow].getLength(); - DBG_ASSERT( nThisColCount == nColCount, "count mismatch" ); //! ??? - for (long nCol=0; nCol<nThisColCount; nCol++) - { - SCCOL nColPos = nDataStartCol + (SCCOL)nCol; //! check for overflow - DataCell( nColPos, nRowPos, nTab, pColAry[nCol] ); - } - } - - // frame around the whole table - - lcl_SetFrame( pDoc,nTab, nDataStartCol,nDataStartRow, nTabEndCol,nTabEndRow, 20 ); - if ( nDataStartCol > nMemberStartCol ) - lcl_SetFrame( pDoc,nTab, nMemberStartCol,nDataStartRow, nDataStartCol-1,nTabEndRow, 20 ); - if ( nDataStartRow > nMemberStartRow ) - lcl_SetFrame( pDoc,nTab, nDataStartCol,nMemberStartRow, nTabEndCol,nDataStartRow-1, 20 ); - - lcl_SetFrame( pDoc,nTab, nTabStartCol,nTabStartRow, nTabEndCol,nTabEndRow, 40 ); +// Wang Xu Ming -- 2009-8-17 +// DataPilot Migration - Cache&&Performance + outputimp.OutputDataArea(); +// End Comments } ScRange ScDPOutput::GetOutputRange( sal_Int32 nRegionType ) diff --git a/sc/source/core/data/dpsave.cxx b/sc/source/core/data/dpsave.cxx index 58a9e112ab7d..72cf15285310 100644 --- a/sc/source/core/data/dpsave.cxx +++ b/sc/source/core/data/dpsave.cxx @@ -54,6 +54,19 @@ #include <com/sun/star/sheet/XMembersSupplier.hpp> #include <com/sun/star/container/XNamed.hpp> #include <com/sun/star/util/XCloneable.hpp> +// Wang Xu Ming -- 2009-8-17 +// DataPilot Migration - Cache&&Performance +#include "dptabsrc.hxx" +#include "dpglobal.hxx" +using namespace ScDPGlobal; +#ifndef _COM_SUN_STAR_SHEET_DATAPILOTFIELDREFERENCETYPE_HPP_ +#include <com/sun/star/sheet/DataPilotFieldReferenceType.hpp> +#endif +#ifndef _COM_SUN_STAR_SHEET_DATAPILOTFIELDREFERENCEITEMTYPE_HPP_ +#include <com/sun/star/sheet/DataPilotFieldReferenceItemType.hpp> +#endif +using namespace com::sun::star::sheet; +// End Comments #include <hash_map> @@ -73,25 +86,6 @@ using ::std::auto_ptr; // ----------------------------------------------------------------------- -//! move to a header file -//! use names from unonames.hxx? -#define DP_PROP_COLUMNGRAND "ColumnGrand" -#define DP_PROP_FUNCTION "Function" -#define DP_PROP_IGNOREEMPTY "IgnoreEmptyRows" -#define DP_PROP_ISDATALAYOUT "IsDataLayoutDimension" -#define DP_PROP_ISVISIBLE "IsVisible" -#define DP_PROP_ORIENTATION "Orientation" -#define DP_PROP_REPEATIFEMPTY "RepeatIfEmpty" -#define DP_PROP_ROWGRAND "RowGrand" -#define DP_PROP_SHOWDETAILS "ShowDetails" -#define DP_PROP_SHOWEMPTY "ShowEmpty" -#define DP_PROP_SUBTOTALS "SubTotals" -#define DP_PROP_USEDHIERARCHY "UsedHierarchy" -#define DP_PROP_FILTER "Filter" -#define DP_PROP_POSITION "Position" - -// ----------------------------------------------------------------------- - void lcl_SetBoolProperty( const uno::Reference<beans::XPropertySet>& xProp, const rtl::OUString& rName, sal_Bool bValue ) { @@ -320,6 +314,51 @@ BOOL ScDPSaveDimension::operator== ( const ScDPSaveDimension& r ) const if (!(**a == **b)) return FALSE; + if ( this->HasCurrentPage() && r.HasCurrentPage() ) + { + if ( this->GetCurrentPage() != r.GetCurrentPage() ) + { + return FALSE; + } + } + else if ( this->HasCurrentPage() || r.HasCurrentPage() ) + { + return FALSE; + } + if( pReferenceValue && r.pReferenceValue ) + { + if ( !(*pReferenceValue == *r.pReferenceValue) ) + { + return FALSE; + } + } + else if ( pReferenceValue || r.pReferenceValue ) + { + return FALSE; + } + if( this->pSortInfo && r.pSortInfo ) + { + if ( !(*this->pSortInfo == *r.pSortInfo) ) + { + return FALSE; + } + } + else if ( this->pSortInfo || r.pSortInfo ) + { + return FALSE; + } + if( this->pAutoShowInfo && r.pAutoShowInfo ) + { + if ( !(*this->pAutoShowInfo == *r.pAutoShowInfo) ) + { + return FALSE; + } + } + else if ( this->pAutoShowInfo || r.pAutoShowInfo ) + { + return FALSE; + } + return TRUE; } @@ -709,6 +748,10 @@ ScDPSaveData::ScDPSaveData() : nRepeatEmptyMode( SC_DPSAVEMODE_DONTKNOW ), bFilterButton( TRUE ), bDrillDown( TRUE ), + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + mnCacheId( -1), + // End Comments mbDimensionMembersBuilt(false), mpGrandTotalName(NULL) { @@ -721,6 +764,10 @@ ScDPSaveData::ScDPSaveData(const ScDPSaveData& r) : nRepeatEmptyMode( r.nRepeatEmptyMode ), bFilterButton( r.bFilterButton ), bDrillDown( r.bDrillDown ), + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + mnCacheId( r.mnCacheId ), + // End Comments mbDimensionMembersBuilt(r.mbDimensionMembersBuilt), mpGrandTotalName(NULL) { @@ -744,40 +791,11 @@ ScDPSaveData& ScDPSaveData::operator= ( const ScDPSaveData& r ) { if ( &r != this ) { - delete pDimensionData; - if ( r.pDimensionData ) - pDimensionData = new ScDPDimensionSaveData( *r.pDimensionData ); - else - pDimensionData = NULL; - - nColumnGrandMode = r.nColumnGrandMode; - nRowGrandMode = r.nRowGrandMode; - nIgnoreEmptyMode = r.nIgnoreEmptyMode; - nRepeatEmptyMode = r.nRepeatEmptyMode; - bFilterButton = r.bFilterButton; - bDrillDown = r.bDrillDown; - mbDimensionMembersBuilt = r.mbDimensionMembersBuilt; - - // remove old dimensions - - long nCount = aDimList.Count(); - long i; - for (i=0; i<nCount; i++) - delete (ScDPSaveDimension*)aDimList.GetObject(i); - aDimList.Clear(); - - // copy new dimensions - - nCount = r.aDimList.Count(); - for (i=0; i<nCount; i++) - { - ScDPSaveDimension* pNew = - new ScDPSaveDimension( *(ScDPSaveDimension*)r.aDimList.GetObject(i) ); - aDimList.Insert( pNew, LIST_APPEND ); - } - - if (r.mpGrandTotalName.get()) - mpGrandTotalName.reset(new OUString(*r.mpGrandTotalName)); + // Wang Xu Ming -- 2009-8-17 + // DataPilot Migration - Cache&&Performance + this->~ScDPSaveData(); + new( this ) ScDPSaveData ( r ); + // End Comments } return *this; } @@ -789,6 +807,7 @@ BOOL ScDPSaveData::operator== ( const ScDPSaveData& r ) const nIgnoreEmptyMode != r.nIgnoreEmptyMode || nRepeatEmptyMode != r.nRepeatEmptyMode || bFilterButton != r.bFilterButton || + mnCacheId != r.mnCacheId ||/// Wang Xu Ming -- 2009-6-18 DataPilot Migration bDrillDown != r.bDrillDown || mbDimensionMembersBuilt != r.mbDimensionMembersBuilt) return FALSE; @@ -1089,6 +1108,7 @@ void ScDPSaveData::WriteToSource( const uno::Reference<sheet::XDimensionsSupplie // reset all orientations //! "forgetSettings" or similar at source ????? //! reset all duplicated dimensions, or reuse them below !!! + DBG_TRACE( "ScDPSaveData::WriteToSource" ); lcl_ResetOrient( xSource ); @@ -1097,6 +1117,9 @@ void ScDPSaveData::WriteToSource( const uno::Reference<sheet::XDimensionsSupplie { ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i); rtl::OUString aName = pDim->GetName(); + + DBG_TRACESTR(pDim->GetName()); + BOOL bData = pDim->IsDataLayout(); //! getByName for ScDPSource, including DataLayoutDimension !!!!!!!! @@ -1228,16 +1251,17 @@ void ScDPSaveData::BuildAllDimensionMembers(ScDPTableData* pData) continue; long nDimIndex = itr->second; - const TypedScStrCollection& rMembers = pData->GetColumnEntries(nDimIndex); - sal_uInt16 nMemberCount = rMembers.GetCount(); - for (sal_uInt16 j = 0; j < nMemberCount; ++j) + const std::vector<SCROW>& rMembers = pData->GetColumnEntries(nDimIndex); + size_t mMemberCount = rMembers.size(); + for (size_t j = 0; j < mMemberCount; ++j) { - const String& rMemName = rMembers[j]->GetString(); - if (pDim->GetExistingMemberByName(rMemName)) + const ScDPItemData* pMemberData = pData->GetMemberById( nDimIndex, rMembers[j] ); + String aMemName = pMemberData->GetString(); + if (pDim->GetExistingMemberByName(aMemName)) // this member instance already exists. nothing to do. continue; - auto_ptr<ScDPSaveMember> pNewMember(new ScDPSaveMember(rMemName)); + auto_ptr<ScDPSaveMember> pNewMember(new ScDPSaveMember(aMemName)); pNewMember->SetIsVisible(true); pDim->AddMember(pNewMember.release()); } @@ -1254,3 +1278,196 @@ bool ScDPSaveData::HasInvisibleMember(const OUString& rDimName) const return pDim->HasInvisibleMember(); } + +void ScDPSaveData::Refresh( const uno::Reference<sheet::XDimensionsSupplier>& xSource ) +{ + try + { + long nCount = aDimList.Count(); + std::list<String> deletedDims; + for (long i=nCount-1; i >=0 ; i--) + { + ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i); + + rtl::OUString aName = pDim->GetName(); + if ( pDim->IsDataLayout() ) + continue; + + uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions(); + uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName ); + long nIntCount = xIntDims->getCount(); + BOOL bFound = FALSE; + for (long nIntDim=0; nIntDim<nIntCount && !bFound; nIntDim++) + { + uno::Reference<uno::XInterface> xIntDim = ScUnoHelpFunctions::AnyToInterface( xIntDims->getByIndex(nIntDim) ); + uno::Reference<container::XNamed> xDimName( xIntDim, uno::UNO_QUERY ); + if ( xDimName.is() && xDimName->getName() == aName ) + bFound = TRUE; + } + if ( !bFound ) + { + deletedDims.push_back( aName ); + aDimList.Remove(i); + DBG_TRACE( "\n Remove dim: \t" ); + DBG_TRACESTR( String( aName ) ); + } + + } + + nCount = aDimList.Count(); + for (long i=nCount-1; i >=0 ; i--) //check every dimension ?? + { + ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i); + + rtl::OUString aName = pDim->GetName(); + if ( pDim->IsDataLayout() ) + continue; + pDim->Refresh( xSource, deletedDims ); + + } + } + catch(uno::Exception&) + { + DBG_ERROR("error in ScDPSaveData::Refresh"); + } + +} +void ScDPSaveDimension::Refresh( const com::sun::star::uno::Reference< + com::sun::star::sheet::XDimensionsSupplier>& xSource , + const std::list<String>& deletedDims) +{ + if ( xSource.is() ) + { + ScDPSource* pTabSource = static_cast<ScDPSource*>( xSource.get() ); + ScDPTableDataCache* pCache = pTabSource->GetCache(); + if ( pCache->GetId() == -1 ) + return; + + SCCOL nSrcDim = pCache->GetDimensionIndex( GetName() ); + + if ( nSrcDim == -1 ) + return; + if ( pSelectedPage ) + {//check pSelected page + DBG_TRACESTR( (*pSelectedPage) ); + if ( pCache->GetIdByItemData( nSrcDim, *pSelectedPage ) == -1 ) + { + delete pSelectedPage; + pSelectedPage = NULL; + } + + }; + + if ( pReferenceValue && pReferenceValue->ReferenceItemType == DataPilotFieldReferenceItemType::NAMED ) + {//check pReferenceValue +#ifdef DEBUG + switch( pReferenceValue->ReferenceType) + { + case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE: //both + DBG_TRACE( "\n sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE \n" ); + break; + case sheet::DataPilotFieldReferenceType::ITEM_DIFFERENCE: //both + DBG_TRACE( "\n sheet::DataPilotFieldReferenceType::ITEM_DIFFERENCE \n" ); + break; + case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE: //both + DBG_TRACE( "\n sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE \n" ); + break; + case sheet::DataPilotFieldReferenceType::RUNNING_TOTAL: + DBG_TRACE( "\n sheet::DataPilotFieldReferenceType::RUNNING_TOTAL \n" ); //enable name + break; + } +#endif + switch( pReferenceValue->ReferenceType) + { + case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE: + case sheet::DataPilotFieldReferenceType::ITEM_DIFFERENCE: + case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE: + case sheet::DataPilotFieldReferenceType::RUNNING_TOTAL: + { + if( pReferenceValue->ReferenceItemType == DataPilotFieldReferenceItemType::NAMED ) + { + const String& sReferenceFieldName = pReferenceValue->ReferenceField; + DBG_TRACESTR( sReferenceFieldName ); + SCCOL nRefDim = pCache->GetDimensionIndex( sReferenceFieldName ); + bool bValid = true; + if ( nRefDim == -1 ) + bValid = false; + else if ( pReferenceValue->ReferenceType != sheet::DataPilotFieldReferenceType::RUNNING_TOTAL ) + { //running total has not reference item + const String& sReferenceItemName = pReferenceValue->ReferenceItemName; + DBG_TRACESTR( sReferenceItemName ); + if ( pCache->GetIdByItemData( nRefDim, sReferenceItemName ) == -1 ) + bValid = false; + } + if ( !bValid ) + { + delete pReferenceValue; + pReferenceValue = NULL; + } + } + } + break; + } + + }; + + if ( pSortInfo ) + { //check sortinfo + if ( pSortInfo->Mode == DataPilotFieldSortMode::DATA ) + { + DBG_TRACE( "\n DataPilotFieldSortMode::DATA \n" ); + const String& sFieldDimName = pSortInfo->Field; + std::list<String>::const_iterator iter = std::find( deletedDims.begin(), deletedDims.end(), sFieldDimName ); + if ( iter != deletedDims.end() && pCache->GetDimensionIndex( sFieldDimName ) == -1 ) + { + pSortInfo->Mode = DataPilotFieldSortMode::MANUAL; + pSortInfo->Field = GetName(); + } + } + + }; + + if ( pAutoShowInfo ) + { //check autoshow + const String& sFieldDimName = pAutoShowInfo->DataField; + std::list<String>::const_iterator iter = std::find( deletedDims.begin(), deletedDims.end(), sFieldDimName ); + if ( iter != deletedDims.end() && pCache->GetDimensionIndex( sFieldDimName ) == -1 ) + { + delete pAutoShowInfo; + pAutoShowInfo = NULL; + } + + }; + + //remove unused members + //SODC_19124 + for (MemberList::iterator i=maMemberList.begin(); i != maMemberList.end() ; ) + { + rtl::OUString aMemberName = (*i)->GetName(); + if ( pCache->GetIdByItemData( nSrcDim, aMemberName ) == -1 ) + i = maMemberList.erase( i ); + else + i++; + } + } +} +// End Comments +bool operator == (const ::com::sun::star::sheet::DataPilotFieldSortInfo &l, const ::com::sun::star::sheet::DataPilotFieldSortInfo &r ) +{ + return l.Field == r.Field && l.IsAscending == r.IsAscending && l.Mode == r.Mode; +} +bool operator == (const ::com::sun::star::sheet::DataPilotFieldAutoShowInfo &l, const ::com::sun::star::sheet::DataPilotFieldAutoShowInfo &r ) +{ + return l.IsEnabled == r.IsEnabled && + l.ShowItemsMode == r.ShowItemsMode && + l.ItemCount == r.ItemCount && + l.DataField == r.DataField; +} +bool operator == (const ::com::sun::star::sheet::DataPilotFieldReference &l, const ::com::sun::star::sheet::DataPilotFieldReference &r ) +{ + return l.ReferenceType == r.ReferenceType && + l.ReferenceField == r.ReferenceField && + l.ReferenceItemType == r.ReferenceItemType && + l.ReferenceItemName == r.ReferenceItemName; +} + diff --git a/sc/source/core/data/dpsdbtab.cxx b/sc/source/core/data/dpsdbtab.cxx index c056f879545c..aae5797211b0 100644 --- a/sc/source/core/data/dpsdbtab.cxx +++ b/sc/source/core/data/dpsdbtab.cxx @@ -75,163 +75,175 @@ using ::com::sun::star::uno::UNO_QUERY; #define SC_DBPROP_DATASOURCENAME "DataSourceName" #define SC_DBPROP_COMMAND "Command" #define SC_DBPROP_COMMANDTYPE "CommandType" - // ----------------------------------------------------------------------- - -class ScDatabaseDPData_Impl +// Wang Xu Ming -- 2009-9-15 +// DataPilot Migration - Cache&&Performance + ScDPTableDataCache* ScImportSourceDesc::GetExistDPObjectCache( ScDocument* pDoc ) const { -public: - ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceManager; - ScImportSourceDesc aDesc; - long nColCount; - uno::Reference<sdbc::XRowSet> xRowSet; - sal_Int32* pTypes; - SvNumberFormatter* pFormatter; - - ScDPCacheTable aCacheTable; - - ScDatabaseDPData_Impl(ScDPCollection* p) : - aCacheTable(p) + ScDPTableDataCache* pCache = NULL; + ScDPCollection* pDPCollection= pDoc->GetDPCollection(); + USHORT nCount = pDPCollection->GetCount(); + + for ( short i=nCount-1; i>=0 ; i--) { + if ( const ScImportSourceDesc* pUsedDesc = (*pDPCollection)[i]->GetImportSourceDesc() ) + if ( *this == *pUsedDesc ) + { + long nID = (*pDPCollection)[i]->GetCacheId(); + if ( nID >= 0 ) + pCache= pDoc->GetDPObjectCache( nID ); + if ( pCache ) + return pCache; + } } -}; - -// ----------------------------------------------------------------------- - -ScDatabaseDPData::ScDatabaseDPData( - ScDocument* pDoc, - const ScImportSourceDesc& rImport ) : - ScDPTableData(pDoc) -{ - pImpl = new ScDatabaseDPData_Impl(pDoc->GetDPCollection()); - pImpl->xServiceManager = pDoc->GetServiceManager(); - pImpl->aDesc = rImport; - pImpl->nColCount = 0; - pImpl->pTypes = NULL; - pImpl->pFormatter = NULL; // created on demand - - OpenDatabase(); - CreateCacheTable(); -} - -ScDatabaseDPData::~ScDatabaseDPData() -{ - ::comphelper::disposeComponent( pImpl->xRowSet ); - - delete[] pImpl->pTypes; - delete pImpl->pFormatter; // NumberFormatter is local for this object - delete pImpl; + return NULL; } -void ScDatabaseDPData::DisposeData() +ScDPTableDataCache* ScImportSourceDesc::CreateCache( ScDocument* pDoc , long nID ) const { - //! use OpenDatabase here? - pImpl->aCacheTable.clear(); -} + if ( !pDoc ) + return NULL; -BOOL ScDatabaseDPData::OpenDatabase() -{ sal_Int32 nSdbType = -1; - switch ( pImpl->aDesc.nType ) + + switch ( nType ) { - case sheet::DataImportMode_SQL: nSdbType = sdb::CommandType::COMMAND; break; - case sheet::DataImportMode_TABLE: nSdbType = sdb::CommandType::TABLE; break; - case sheet::DataImportMode_QUERY: nSdbType = sdb::CommandType::QUERY; break; - default: - return FALSE; + case sheet::DataImportMode_SQL: nSdbType = sdb::CommandType::COMMAND; break; + case sheet::DataImportMode_TABLE: nSdbType = sdb::CommandType::TABLE; break; + case sheet::DataImportMode_QUERY: nSdbType = sdb::CommandType::QUERY; break; + default: + return NULL; } - BOOL bSuccess = FALSE; + + ScDPTableDataCache* pCache = GetExistDPObjectCache( pDoc ); + + if ( pCache && ( nID < 0 || nID == pCache->GetId() ) ) + return pCache; + + if ( pCache == NULL ) + pCache = new ScDPTableDataCache( pDoc ); + + uno::Reference<sdbc::XRowSet> xRowSet ; try { - pImpl->xRowSet = uno::Reference<sdbc::XRowSet>( - comphelper::getProcessServiceFactory()->createInstance( - rtl::OUString::createFromAscii( SC_SERVICE_ROWSET ) ), - uno::UNO_QUERY); - uno::Reference<beans::XPropertySet> xRowProp( pImpl->xRowSet, uno::UNO_QUERY ); + xRowSet = uno::Reference<sdbc::XRowSet>( + comphelper::getProcessServiceFactory()->createInstance( + rtl::OUString::createFromAscii( SC_SERVICE_ROWSET ) ), + uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xRowProp( xRowSet, uno::UNO_QUERY ); DBG_ASSERT( xRowProp.is(), "can't get RowSet" ); if ( xRowProp.is() ) { // // set source parameters // - uno::Any aAny; - - aAny <<= rtl::OUString( pImpl->aDesc.aDBName ); + aAny <<= rtl::OUString( aDBName ); xRowProp->setPropertyValue( - rtl::OUString::createFromAscii(SC_DBPROP_DATASOURCENAME), aAny ); + rtl::OUString::createFromAscii(SC_DBPROP_DATASOURCENAME), aAny ); - aAny <<= rtl::OUString( pImpl->aDesc.aObject ); + aAny <<= rtl::OUString( aObject ); xRowProp->setPropertyValue( - rtl::OUString::createFromAscii(SC_DBPROP_COMMAND), aAny ); + rtl::OUString::createFromAscii(SC_DBPROP_COMMAND), aAny ); aAny <<= nSdbType; xRowProp->setPropertyValue( - rtl::OUString::createFromAscii(SC_DBPROP_COMMANDTYPE), aAny ); + rtl::OUString::createFromAscii(SC_DBPROP_COMMANDTYPE), aAny ); - uno::Reference<sdb::XCompletedExecution> xExecute( pImpl->xRowSet, uno::UNO_QUERY ); + uno::Reference<sdb::XCompletedExecution> xExecute( xRowSet, uno::UNO_QUERY ); if ( xExecute.is() ) { uno::Reference<task::XInteractionHandler> xHandler( - comphelper::getProcessServiceFactory()->createInstance( - rtl::OUString::createFromAscii( SC_SERVICE_INTHANDLER ) ), - uno::UNO_QUERY); + comphelper::getProcessServiceFactory()->createInstance( + rtl::OUString::createFromAscii( SC_SERVICE_INTHANDLER ) ), + uno::UNO_QUERY); xExecute->executeWithCompletion( xHandler ); } else - pImpl->xRowSet->execute(); - - // - // get column descriptions - // - - pImpl->nColCount = 0; - uno::Reference<sdbc::XResultSetMetaData> xMeta; - uno::Reference<sdbc::XResultSetMetaDataSupplier> xMetaSupp( pImpl->xRowSet, uno::UNO_QUERY ); - if ( xMetaSupp.is() ) - xMeta = xMetaSupp->getMetaData(); - if ( xMeta.is() ) - pImpl->nColCount = xMeta->getColumnCount(); // this is the number of real columns - - uno::Reference<sdbc::XResultSet> xResSet( pImpl->xRowSet, uno::UNO_QUERY ); - if ( pImpl->nColCount > 0 && xResSet.is() ) - { - pImpl->pTypes = new sal_Int32[pImpl->nColCount]; - for (long nCol=0; nCol<pImpl->nColCount; nCol++) - pImpl->pTypes[nCol] = xMeta->getColumnType( nCol+1 ); - - bSuccess = TRUE; - } + xRowSet->execute(); + SvNumberFormatter aFormat( pDoc->GetServiceManager(), ScGlobal::eLnge); + pCache->InitFromDataBase( xRowSet, *aFormat.GetNullDate() ); + pCache->SetId( nID ); + pDoc->AddDPObjectCache( pCache ); + DBG_TRACE1("Create a cache id = %d \n", pCache->GetId() ); } } catch ( sdbc::SQLException& rError ) { //! store error message + delete pCache; + pCache = NULL; InfoBox aInfoBox( 0, String(rError.Message) ); aInfoBox.Execute(); } catch ( uno::Exception& ) { + delete pCache; + pCache = NULL; DBG_ERROR("Unexpected exception in database"); } - if (!bSuccess) - ::comphelper::disposeComponent( pImpl->xRowSet ); + ::comphelper::disposeComponent( xRowSet ); + return pCache; +} - return bSuccess; +ScDPTableDataCache* ScImportSourceDesc::GetCache( ScDocument* pDoc, long nID ) const +{ + ScDPTableDataCache* pCache = pDoc->GetDPObjectCache( nID ); + if ( NULL == pCache && pDoc ) + pCache = GetExistDPObjectCache( pDoc); + if ( NULL == pCache ) + pCache = CreateCache( pDoc , nID ); + return pCache; } -long ScDatabaseDPData::GetColumnCount() +long ScImportSourceDesc:: GetCacheId( ScDocument* pDoc, long nID ) const +{ + ScDPTableDataCache* pCache = GetCache( pDoc, nID); + if ( NULL == pCache ) + return -1; + else + return pCache->GetId(); +} + +// ----------------------------------------------------------------------- + +ScDatabaseDPData::ScDatabaseDPData( + ScDocument* pDoc, + const ScImportSourceDesc& rImport, long nCacheId /*=-1 */ ) : + ScDPTableData(pDoc, rImport.GetCacheId( pDoc, nCacheId) ), + aCacheTable( pDoc, rImport.GetCacheId( pDoc, nCacheId)) +{ + +} + +ScDatabaseDPData::~ScDatabaseDPData() +{ +} + +void ScDatabaseDPData::DisposeData() { - return pImpl->nColCount; + //! use OpenDatabase here? + aCacheTable.clear(); } -const TypedScStrCollection& ScDatabaseDPData::GetColumnEntries(long nColumn) +long ScDatabaseDPData::GetColumnCount() { CreateCacheTable(); - return pImpl->aCacheTable.getFieldEntries(nColumn); + return GetCacheTable().getColSize(); +} + +// End Comments + +void lcl_Reset( const uno::Reference<sdbc::XRowSet>& xRowSet ) + throw(sdbc::SQLException, uno::RuntimeException) +{ + // isBeforeFirst / beforeFirst is not always available + //! query if it is allowed + + xRowSet->execute(); // restart } String ScDatabaseDPData::getDimensionName(long nColumn) @@ -244,17 +256,12 @@ String ScDatabaseDPData::getDimensionName(long nColumn) } CreateCacheTable(); - const String* pStr = pImpl->aCacheTable.getFieldName(nColumn); - if (pStr) - return *pStr; - - DBG_ERROR("getDimensionName: invalid dimension"); - return String(); + return aCacheTable.getFieldName((SCCOL)nColumn); } BOOL ScDatabaseDPData::getIsDataLayoutDimension(long nColumn) { - return ( nColumn == pImpl->nColCount ); + return ( nColumn == GetCacheTable().getColSize()); } BOOL ScDatabaseDPData::IsDateDimension(long /* nDim */) @@ -271,43 +278,39 @@ void ScDatabaseDPData::SetEmptyFlags( BOOL /* bIgnoreEmptyRows */, BOOL /* bRepe void ScDatabaseDPData::CreateCacheTable() { - if (!pImpl->aCacheTable.empty()) + if (!aCacheTable.empty()) return; - // Get null date. - if (!pImpl->pFormatter) - pImpl->pFormatter = new SvNumberFormatter(pImpl->xServiceManager, ScGlobal::eLnge); - - pImpl->aCacheTable.fillTable(pImpl->xRowSet, *pImpl->pFormatter->GetNullDate()); + aCacheTable.fillTable(); } void ScDatabaseDPData::FilterCacheTable(const vector<ScDPCacheTable::Criterion>& rCriteria, const hash_set<sal_Int32>& rCatDims) { CreateCacheTable(); - pImpl->aCacheTable.filterByPageDimension( + aCacheTable.filterByPageDimension( rCriteria, (IsRepeatIfEmpty() ? rCatDims : hash_set<sal_Int32>())); } void ScDatabaseDPData::GetDrillDownData(const vector<ScDPCacheTable::Criterion>& rCriteria, const hash_set<sal_Int32>& rCatDims, Sequence< Sequence<Any> >& rData) { CreateCacheTable(); - sal_Int32 nRowSize = pImpl->aCacheTable.getRowSize(); + sal_Int32 nRowSize = aCacheTable.getRowSize(); if (!nRowSize) return; - pImpl->aCacheTable.filterTable( + aCacheTable.filterTable( rCriteria, rData, IsRepeatIfEmpty() ? rCatDims : hash_set<sal_Int32>()); } void ScDatabaseDPData::CalcResults(CalcInfo& rInfo, bool bAutoShow) { CreateCacheTable(); - CalcResultsFromCacheTable(pImpl->aCacheTable, rInfo, bAutoShow); + CalcResultsFromCacheTable( aCacheTable, rInfo, bAutoShow); } const ScDPCacheTable& ScDatabaseDPData::GetCacheTable() const { - return pImpl->aCacheTable; + return aCacheTable; } // ----------------------------------------------------------------------- diff --git a/sc/source/core/data/dpshttab.cxx b/sc/source/core/data/dpshttab.cxx index c7e75f438ce1..6254e3861db5 100644..100755 --- a/sc/source/core/data/dpshttab.cxx +++ b/sc/source/core/data/dpshttab.cxx @@ -43,7 +43,10 @@ #include "dpcachetable.hxx" #include "dpobject.hxx" #include "globstr.hrc" - +// Wang Xu Ming -- 2009-8-17 +// DataPilot Migration - Cache&&Performance +#include "dpglobal.hxx" +// End Comments #include <com/sun/star/sheet/DataPilotFieldFilter.hpp> #include <vector> @@ -58,55 +61,27 @@ using ::std::hash_set; // ----------------------------------------------------------------------- -class ScSheetDPData_Impl -{ -public: - ScDocument* pDoc; - ScRange aRange; - ScQueryParam aQuery; - BOOL* pSpecial; // to flag special handling of query parameters in ValidQuery. - BOOL bIgnoreEmptyRows; - BOOL bRepeatIfEmpty; - BOOL* pDateDim; - SCROW nNextRow; // for iterator, within range - - ScDPCacheTable aCacheTable; - - ScSheetDPData_Impl(ScDPCollection* p) : - pSpecial(NULL), - aCacheTable(p) - { - } -}; - -// ----------------------------------------------------------------------- - -ScSheetDPData::ScSheetDPData( ScDocument* pD, const ScSheetSourceDesc& rDesc ) : - ScDPTableData(pD) +ScSheetDPData::ScSheetDPData( ScDocument* pD, const ScSheetSourceDesc& rDesc , long nCacheId) : + ScDPTableData(pD, rDesc.GetCacheId( pD, nCacheId) ), // DataPilot Migration - Cache&&Performance + aQuery ( rDesc.aQueryParam ), + pSpecial(NULL), + bIgnoreEmptyRows( FALSE ), + bRepeatIfEmpty(FALSE), + aCacheTable( pD, rDesc.GetCacheId( pD, nCacheId)) { - pImpl = new ScSheetDPData_Impl(pD->GetDPCollection()); - pImpl->pDoc = pD; - pImpl->aRange = rDesc.aSourceRange; - pImpl->aQuery = rDesc.aQueryParam; - pImpl->bIgnoreEmptyRows = FALSE; - pImpl->bRepeatIfEmpty = FALSE; - pImpl->pDateDim = NULL; - - pImpl->nNextRow = pImpl->aRange.aStart.Row() + 1; - - SCSIZE nEntryCount(pImpl->aQuery.GetEntryCount()); - pImpl->pSpecial = new BOOL[nEntryCount]; + SCSIZE nEntryCount( aQuery.GetEntryCount()); + pSpecial = new BOOL[nEntryCount]; for (SCSIZE j = 0; j < nEntryCount; ++j ) { - ScQueryEntry& rEntry = pImpl->aQuery.GetEntry(j); + ScQueryEntry& rEntry = aQuery.GetEntry(j); if (rEntry.bDoQuery) { - pImpl->pSpecial[j] = false; + pSpecial[j] = false; if (!rEntry.bQueryByString) { if (*rEntry.pStr == EMPTY_STRING && ((rEntry.nVal == SC_EMPTYFIELDS) || (rEntry.nVal == SC_NONEMPTYFIELDS))) - pImpl->pSpecial[j] = true; + pSpecial[j] = true; } else { @@ -121,27 +96,24 @@ ScSheetDPData::ScSheetDPData( ScDocument* pD, const ScSheetSourceDesc& rDesc ) : ScSheetDPData::~ScSheetDPData() { - delete[] pImpl->pDateDim; - delete[] pImpl->pSpecial; - delete pImpl; + delete[] pSpecial; } void ScSheetDPData::DisposeData() { - pImpl->aCacheTable.clear(); + aCacheTable.clear(); } long ScSheetDPData::GetColumnCount() { CreateCacheTable(); - return pImpl->aCacheTable.getColSize(); + return aCacheTable.getColSize(); } -const TypedScStrCollection& ScSheetDPData::GetColumnEntries(long nColumn) +BOOL lcl_HasQuery( const ScQueryParam& rParam ) { - DBG_ASSERT(nColumn>=0 && nColumn < pImpl->aCacheTable.getColSize(), "ScSheetDPData: wrong column"); - CreateCacheTable(); - return pImpl->aCacheTable.getFieldEntries(nColumn); + return rParam.GetEntryCount() > 0 && + rParam.GetEntry(0).bDoQuery; } String ScSheetDPData::getDimensionName(long nColumn) @@ -153,35 +125,21 @@ String ScSheetDPData::getDimensionName(long nColumn) //return "Data"; return ScGlobal::GetRscString(STR_PIVOT_DATA); } - else if (nColumn >= pImpl->aCacheTable.getColSize()) + else if (nColumn >= aCacheTable.getColSize()) { DBG_ERROR("getDimensionName: invalid dimension"); return String(); } else { - const String* pStr = pImpl->aCacheTable.getFieldName(nColumn); - if (pStr) - return *pStr; - else return String(); + return aCacheTable.getFieldName((SCCOL)nColumn); } } -BOOL lcl_HasDateFormat( ScDocument* pDoc, const ScRange& rRange ) -{ - //! iterate formats in range? - - ScAddress aPos = rRange.aStart; - aPos.SetRow( aPos.Row() + 1 ); // below title - ULONG nFormat = pDoc->GetNumberFormat( aPos ); - SvNumberFormatter* pFormatter = pDoc->GetFormatTable(); - return ( pFormatter->GetType(nFormat) & NUMBERFORMAT_DATE ) != 0; -} - BOOL ScSheetDPData::IsDateDimension(long nDim) { CreateCacheTable(); - long nColCount = pImpl->aCacheTable.getColSize(); + long nColCount = aCacheTable.getColSize(); if (getIsDataLayoutDimension(nDim)) { return FALSE; @@ -193,101 +151,165 @@ BOOL ScSheetDPData::IsDateDimension(long nDim) } else { - if (!pImpl->pDateDim) - { - pImpl->pDateDim = new BOOL[nColCount]; - ScRange aTestRange = pImpl->aRange; - for (long i = 0; i < nColCount; ++i) - { - SCCOL nCol = (SCCOL)( pImpl->aRange.aStart.Col() + i ); - aTestRange.aStart.SetCol(nCol); - aTestRange.aEnd.SetCol(nCol); - pImpl->pDateDim[i] = lcl_HasDateFormat( pImpl->pDoc, aTestRange ); - } - } - return pImpl->pDateDim[nDim]; + return aCacheTable.GetCache()->IsDateDimension( nDim); } } -UINT32 ScSheetDPData::GetNumberFormat(long nDim) +ULONG ScSheetDPData::GetNumberFormat(long nDim) { CreateCacheTable(); if (getIsDataLayoutDimension(nDim)) { return 0; } - else if (nDim >= pImpl->aCacheTable.getColSize()) + else if (nDim >= GetCacheTable().getColSize()) { DBG_ERROR("GetNumberFormat: invalid dimension"); return 0; } else { - // is queried only once per dimension from ScDPOutput -> no need to cache - - ScAddress aPos = pImpl->aRange.aStart; - aPos.SetCol( sal::static_int_cast<SCCOL>( aPos.Col() + nDim ) ); - aPos.SetRow( aPos.Row() + 1 ); // below title - return pImpl->pDoc->GetNumberFormat( aPos ); + return GetCacheTable().GetCache()->GetNumberFormat( nDim ); } } +UINT32 ScDPTableData::GetNumberFormatByIdx( NfIndexTableOffset eIdx ) +{ + if( !mpDoc ) + return 0; + + if ( SvNumberFormatter* pFormatter = mpDoc->GetFormatTable() ) + return pFormatter->GetFormatIndex( eIdx, LANGUAGE_SYSTEM ); + + return 0; +} BOOL ScSheetDPData::getIsDataLayoutDimension(long nColumn) { CreateCacheTable(); - return (nColumn == pImpl->aCacheTable.getColSize()); + return (nColumn ==(long)( aCacheTable.getColSize())); } -void ScSheetDPData::SetEmptyFlags( BOOL bIgnoreEmptyRows, BOOL bRepeatIfEmpty ) +void ScSheetDPData::SetEmptyFlags( BOOL bIgnoreEmptyRowsP, BOOL bRepeatIfEmptyP ) { - pImpl->bIgnoreEmptyRows = bIgnoreEmptyRows; - pImpl->bRepeatIfEmpty = bRepeatIfEmpty; + bIgnoreEmptyRows = bIgnoreEmptyRowsP; + bRepeatIfEmpty = bRepeatIfEmptyP; } bool ScSheetDPData::IsRepeatIfEmpty() { - return pImpl->bRepeatIfEmpty; + return bRepeatIfEmpty; } void ScSheetDPData::CreateCacheTable() { // Scan and store the data from the source range. - if (!pImpl->aCacheTable.empty()) + if (!aCacheTable.empty()) // already cached. return; - pImpl->aCacheTable.fillTable(pImpl->pDoc, pImpl->aRange, pImpl->aQuery, pImpl->pSpecial, - pImpl->bIgnoreEmptyRows); + aCacheTable.fillTable( aQuery, pSpecial, + bIgnoreEmptyRows, bRepeatIfEmpty ); } void ScSheetDPData::FilterCacheTable(const vector<ScDPCacheTable::Criterion>& rCriteria, const hash_set<sal_Int32>& rCatDims) { CreateCacheTable(); - pImpl->aCacheTable.filterByPageDimension( + aCacheTable.filterByPageDimension( rCriteria, (IsRepeatIfEmpty() ? rCatDims : hash_set<sal_Int32>())); } void ScSheetDPData::GetDrillDownData(const vector<ScDPCacheTable::Criterion>& rCriteria, const hash_set<sal_Int32>& rCatDims, Sequence< Sequence<Any> >& rData) { CreateCacheTable(); - sal_Int32 nRowSize = pImpl->aCacheTable.getRowSize(); + sal_Int32 nRowSize = aCacheTable.getRowSize(); if (!nRowSize) return; - pImpl->aCacheTable.filterTable( + aCacheTable.filterTable( rCriteria, rData, IsRepeatIfEmpty() ? rCatDims : hash_set<sal_Int32>()); } void ScSheetDPData::CalcResults(CalcInfo& rInfo, bool bAutoShow) { CreateCacheTable(); - CalcResultsFromCacheTable(pImpl->aCacheTable, rInfo, bAutoShow); + CalcResultsFromCacheTable(aCacheTable, rInfo, bAutoShow); } const ScDPCacheTable& ScSheetDPData::GetCacheTable() const { - return pImpl->aCacheTable; + return aCacheTable; +} + + +// Wang Xu Ming -- 2009-8-5 +// DataPilot Migration - Cache&&Performance +ScDPTableDataCache* ScSheetSourceDesc::CreateCache( ScDocument* pDoc , long nID ) const +{ + if ( pDoc ) + { + ScDPTableDataCache* pCache = GetExistDPObjectCache( pDoc ); + if ( pCache && ( nID < 0 || nID == pCache->GetId() ) ) + return pCache; + + ULONG nErrId = CheckValidate( pDoc ); + if ( !nErrId ) + { + pCache = new ScDPTableDataCache( pDoc ); + + pCache->InitFromDoc( pDoc, aSourceRange ); + pCache->SetId( nID ); + pDoc->AddDPObjectCache( pCache ); + + DBG_TRACE1("Create a cache id = %d \n", pCache->GetId() ); + } + else + DBG_ERROR( "\n Error Create Cache" ); + return pCache; + } + return NULL; +} + +ScDPTableDataCache* ScSheetSourceDesc::GetExistDPObjectCache ( ScDocument* pDoc ) const +{ + return pDoc->GetUsedDPObjectCache( aSourceRange ); +} +ScDPTableDataCache* ScSheetSourceDesc::GetCache( ScDocument* pDoc, long nID ) const +{ + ScDPTableDataCache* pCache = pDoc->GetDPObjectCache( nID ); + if ( NULL == pCache && pDoc ) + pCache = GetExistDPObjectCache( pDoc ); + if ( NULL == pCache ) + pCache = CreateCache( pDoc ); + return pCache; +} + +long ScSheetSourceDesc:: GetCacheId( ScDocument* pDoc, long nID ) const +{ + ScDPTableDataCache* pCache = GetCache( pDoc, nID); + if ( NULL == pCache ) + return -1; + else + return pCache->GetId(); +} + +ULONG ScSheetSourceDesc::CheckValidate( ScDocument* pDoc ) const +{ + ScRange aSrcRange( aSourceRange); + if ( !pDoc ) + return STR_ERR_DATAPILOTSOURCE; + for(USHORT i= aSrcRange.aStart.Col();i <= aSrcRange.aEnd.Col();i++) + { + if ( pDoc->IsBlockEmpty( aSrcRange.aStart.Tab(), + i, aSrcRange.aStart.Row(),i, aSrcRange.aStart.Row())) + return STR_PIVOT_FIRSTROWEMPTYERR; + } + if( pDoc->IsBlockEmpty( aSrcRange.aStart.Tab(), aSrcRange.aStart.Col(), aSrcRange.aStart.Row()+1, aSrcRange.aEnd.Col(), aSrcRange.aEnd.Row() ) ) + { + return STR_PIVOT_ONLYONEROWERR; + } + return 0; } +// End Comments // ----------------------------------------------------------------------- diff --git a/sc/source/core/data/dptabdat.cxx b/sc/source/core/data/dptabdat.cxx index 530f1c44123f..cff18ef925d9 100644..100755 --- a/sc/source/core/data/dptabdat.cxx +++ b/sc/source/core/data/dptabdat.cxx @@ -52,69 +52,6 @@ using namespace ::com::sun::star; using ::com::sun::star::uno::Sequence; using ::com::sun::star::uno::Any; using ::std::vector; -using ::std::set; -using ::std::hash_map; - -// ----------------------------------------------------------------------- - -BOOL ScDPItemData::IsCaseInsEqual( const ScDPItemData& r ) const -{ - //! pass Transliteration? - //! inline? - return bHasValue ? ( r.bHasValue && rtl::math::approxEqual( fValue, r.fValue ) ) : - ( !r.bHasValue && - ScGlobal::GetpTransliteration()->isEqual( aString, r.aString ) ); -} - -size_t ScDPItemData::Hash() const -{ - if ( bHasValue ) - return (size_t) rtl::math::approxFloor( fValue ); - else - // If we do unicode safe case insensitive hash we can drop - // ScDPItemData::operator== and use ::IsCasInsEqual - return rtl_ustr_hashCode_WithLength( aString.GetBuffer(), aString.Len() ); -} - -BOOL ScDPItemData::operator==( const ScDPItemData& r ) const -{ - if ( bHasValue ) - { - if ( r.bHasValue ) - return rtl::math::approxEqual( fValue, r.fValue ); - else - return FALSE; - } - else if ( r.bHasValue ) - return FALSE; - else - // need exact equality until we have a safe case insensitive string hash - return aString == r.aString; -} - -sal_Int32 ScDPItemData::Compare( const ScDPItemData& rA, - const ScDPItemData& rB ) -{ - if ( rA.bHasValue ) - { - if ( rB.bHasValue ) - { - if ( rtl::math::approxEqual( rA.fValue, rB.fValue ) ) - return 0; - else if ( rA.fValue < rB.fValue ) - return -1; - else - return 1; - } - else - return -1; // values first - } - else if ( rB.bHasValue ) - return 1; // values first - else - return ScGlobal::GetCollator()->compareString( rA.aString, rB.aString ); -} - // --------------------------------------------------------------------------- ScDPTableData::CalcInfo::CalcInfo() : @@ -124,8 +61,9 @@ ScDPTableData::CalcInfo::CalcInfo() : // --------------------------------------------------------------------------- -ScDPTableData::ScDPTableData(ScDocument* pDoc) : - mrSharedString(pDoc->GetDPCollection()->GetSharedString()) +ScDPTableData::ScDPTableData(ScDocument* pDoc, long nCacheId ) : + mnCacheId( nCacheId ), + mpDoc ( pDoc ) { nLastDateVal = nLastHier = nLastLevel = nLastRet = -1; // invalid @@ -186,7 +124,7 @@ bool ScDPTableData::IsRepeatIfEmpty() return false; } -UINT32 ScDPTableData::GetNumberFormat(long) +ULONG ScDPTableData::GetNumberFormat(long) { return 0; // default format } @@ -219,12 +157,6 @@ BOOL ScDPTableData::HasCommonElement( const ScDPItemData&, long, DBG_ERROR("HasCommonElement shouldn't be called for non-group data"); return FALSE; } - -ScSimpleSharedString& ScDPTableData::GetSharedString() -{ - return mrSharedString; -} - void ScDPTableData::FillRowDataFromCacheTable(sal_Int32 nRow, const ScDPCacheTable& rCacheTable, const CalcInfo& rInfo, CalcRowData& rData) { @@ -243,25 +175,28 @@ void ScDPTableData::FillRowDataFromCacheTable(sal_Int32 nRow, const ScDPCacheTab long nDim = rInfo.aDataSrcCols[i]; rData.aValues.push_back( ScDPValueData() ); ScDPValueData& rVal = rData.aValues.back(); - const ScDPCacheCell* pCell = rCacheTable.getCell( - static_cast<SCCOL>(nDim), static_cast<SCROW>(nRow), false); - if (pCell) - { - rVal.fValue = pCell->mbNumeric ? pCell->mfValue : 0.0; - rVal.nType = pCell->mnType; - } - else - rVal.Set(0.0, SC_VALTYPE_EMPTY); + rCacheTable.getValue( rVal, static_cast<SCCOL>(nDim), static_cast<SCROW>(nRow), false); } } void ScDPTableData::ProcessRowData(CalcInfo& rInfo, CalcRowData& rData, bool bAutoShow) { + // Wang Xu Ming -- 2009-6-16 + // DataPilot Migration if (!bAutoShow) { - rInfo.pColRoot->LateInitFrom(rInfo.aColDims, rInfo.aColLevels, rData.aColData, 0, *rInfo.pInitState); - rInfo.pRowRoot->LateInitFrom(rInfo.aRowDims, rInfo.aRowLevels, rData.aRowData, 0, *rInfo.pInitState); + LateInitParams aColParams( rInfo.aColDims, rInfo.aColLevels, FALSE ); + LateInitParams aRowParams ( rInfo.aRowDims, rInfo.aRowLevels, TRUE ); + // root always init child + aColParams.SetInitChild( TRUE ); + aColParams.SetInitAllChildren( FALSE); + aRowParams.SetInitChild( TRUE ); + aRowParams.SetInitAllChildren( FALSE); + + rInfo.pColRoot->LateInitFrom( aColParams, rData.aColData,0, *rInfo.pInitState); + rInfo.pRowRoot->LateInitFrom( aRowParams, rData.aRowData, 0, *rInfo.pInitState); } + // End Comments if ( ( !rInfo.pColRoot->GetChildDimension() || rInfo.pColRoot->GetChildDimension()->IsValidEntry(rData.aColData) ) && ( !rInfo.pRowRoot->GetChildDimension() || rInfo.pRowRoot->GetChildDimension()->IsValidEntry(rData.aRowData) ) ) @@ -269,8 +204,11 @@ void ScDPTableData::ProcessRowData(CalcInfo& rInfo, CalcRowData& rData, bool bAu //! single process method with ColMembers, RowMembers and data !!! if (rInfo.pColRoot->GetChildDimension()) { - vector<ScDPItemData> aEmptyData; +// Wang Xu Ming -- 2009-6-10 +// DataPilot Migration + vector</*ScDPItemData*/ SCROW > aEmptyData; rInfo.pColRoot->GetChildDimension()->ProcessData(rData.aColData, NULL, aEmptyData, rData.aValues); +// End Comments } rInfo.pRowRoot->ProcessData(rData.aRowData, rInfo.pColRoot->GetChildDimension(), @@ -292,42 +230,94 @@ void ScDPTableData::CalcResultsFromCacheTable(const ScDPCacheTable& rCacheTable, } } +// Wang Xu Ming -- 2009-6-10 +// DataPilot Migration void ScDPTableData::GetItemData(const ScDPCacheTable& rCacheTable, sal_Int32 nRow, - const vector<long>& rDims, vector<ScDPItemData>& rItemData) + const vector<long>& rDims, vector< SCROW/*ScDPItemData*/>& rItemData) +// End Comments { sal_Int32 nDimSize = rDims.size(); for (sal_Int32 i = 0; i < nDimSize; ++i) { long nDim = rDims[i]; - rItemData.push_back( ScDPItemData() ); - ScDPItemData& rData = rItemData.back(); + if (getIsDataLayoutDimension(nDim)) { - rData.SetString(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("x"))); + rItemData.push_back( -1 ); continue; } - const ScDPCacheCell* pCell = rCacheTable.getCell( - static_cast<SCCOL>(nDim), static_cast<SCROW>(nRow), IsRepeatIfEmpty()); - if (!pCell || pCell->mnType == SC_VALTYPE_EMPTY) - continue; + nDim = GetSourceDim( nDim ); + if ( nDim >= rCacheTable.GetCache()->GetColumnCount() ) + continue; - const String* pString = GetSharedString().getString(pCell->mnStrId); - if (!pString) - continue; + SCROW nId= rCacheTable.GetCache()->GetItemDataId( static_cast<SCCOL>(nDim), static_cast<SCROW>(nRow), IsRepeatIfEmpty()); + rItemData.push_back( nId ); - rData.aString = *pString; - rData.bHasValue = false; - if (pCell->mbNumeric) - { - rData.bHasValue = true; - rData.fValue = pCell->mfValue; - } } } // ----------------------------------------------------------------------- +// Wang Xu Ming -- 2009-6-8 +// DataPilot Migration +long ScDPTableData::GetMembersCount( long nDim ) +{ + if ( nDim > MAXCOL ) + return 0; + return GetCacheTable().getFieldEntries( nDim ).size(); +} + +long ScDPTableData::GetCacheId() const +{ + return mnCacheId; +} + +const ScDPItemData* ScDPTableData::GetMemberByIndex( long nDim, long nIndex ) +{ + if ( nIndex >= GetMembersCount( nDim ) ) + return NULL; + + const ::std::vector<SCROW>& nMembers = GetCacheTable().getFieldEntries( nDim ); + + return GetCacheTable().GetCache()->GetItemDataById( (SCCOL) nDim, (SCROW)nMembers[nIndex] ); +} + +const ScDPItemData* ScDPTableData::GetMemberById( long nDim, long nId) +{ + + return GetCacheTable().GetCache()->GetItemDataById( (SCCOL) nDim, (SCROW)nId); +} +SCROW ScDPTableData::GetIdOfItemData( long nDim, const ScDPItemData& rData ) +{ + return GetCacheTable().GetCache()->GetIdByItemData((SCCOL) nDim, rData ); + } +const std::vector< SCROW >& ScDPTableData::GetColumnEntries( long nColumn ) +{ + return GetCacheTable().getFieldEntries( nColumn ); +} +long ScDPTableData::GetSourceDim( long nDim ) +{ + return nDim; + +} + + long ScDPTableData::Compare( long nDim, long nDataId1, long nDataId2) +{ + if ( getIsDataLayoutDimension(nDim) ) + return 0; + + long n1 = GetCacheTable().GetCache()->GetOrder( nDim, nDataId1); + long n2 = GetCacheTable().GetCache()->GetOrder( nDim, nDataId2); + if ( n1 > n2 ) + return 1; + else if ( n1 == n2 ) + return 0; + else + return -1; +} +// End Comments +// ----------------------------------------------------------------------- diff --git a/sc/source/core/data/dptablecache.cxx b/sc/source/core/data/dptablecache.cxx new file mode 100755 index 000000000000..a9761295a6d4 --- /dev/null +++ b/sc/source/core/data/dptablecache.cxx @@ -0,0 +1,1092 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright IBM Corporation 2009. + * Copyright 2009 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: dptablecache.cxx,v $ + * $Revision: 1.0 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + // MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" +// INCLUDE --------------------------------------------------------------- +#include "dptablecache.hxx" +#include "document.hxx" +#include "cell.hxx" +#include "globstr.hrc" + +#include <rtl/math.hxx> +#include "dpglobal.hxx" + +#include "docoptio.hxx" //for ValidQuery +#include <unotools/textsearch.hxx> //for ValidQuery + +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/sdbc/XRowSet.hpp> +#include <com/sun/star/sdbc/XResultSetMetaData.hpp> +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> +const double D_TIMEFACTOR = 86400.0; + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_QUERY_THROW; +// ----------------------------------------------------------------------- +namespace +{ + BOOL lcl_isDate( ULONG nNumType ) + { + return ( (nNumType & NUMBERFORMAT_DATE) != 0 )? 1:0 ; + } + + BOOL lcl_Search( const std::vector<ScDPItemData*>& list, const ::std::vector<SCROW>& rOrder, const ScDPItemData& item, SCROW& rIndex) + { + rIndex = list.size(); + BOOL bFound = FALSE; + SCROW nLo = 0; + SCROW nHi = list.size() - 1; + SCROW nIndex; + long nCompare; + while (nLo <= nHi) + { + nIndex = (nLo + nHi) / 2; + nCompare = ScDPItemData::Compare( *list[rOrder[nIndex]], item ); + if (nCompare < 0) + nLo = nIndex + 1; + else + { + nHi = nIndex - 1; + if (nCompare == 0) + { + bFound = TRUE; + nLo = nIndex; + } + } + } + rIndex = nLo; + return bFound; + } + + ScDPItemData* lcl_GetItemValue(const Reference<sdbc::XRow>& xRow, sal_Int32 nType, long nCol, + const Date& rNullDate ) + { + short nNumType = NUMBERFORMAT_NUMBER; + try + { + String rStr = xRow->getString(nCol); + double fValue = 0.0; + switch (nType) + { + case sdbc::DataType::BIT: + case sdbc::DataType::BOOLEAN: + { + nNumType = NUMBERFORMAT_LOGICAL; + fValue = xRow->getBoolean(nCol) ? 1 : 0; + return new ScDPItemData( rStr, fValue,TRUE,nNumType); + } + //break; + + case sdbc::DataType::TINYINT: + case sdbc::DataType::SMALLINT: + case sdbc::DataType::INTEGER: + case sdbc::DataType::BIGINT: + case sdbc::DataType::FLOAT: + case sdbc::DataType::REAL: + case sdbc::DataType::DOUBLE: + case sdbc::DataType::NUMERIC: + case sdbc::DataType::DECIMAL: + { + //! do the conversion here? + fValue = xRow->getDouble(nCol); + return new ScDPItemData( rStr, fValue,TRUE); + } + //break; + + case sdbc::DataType::DATE: + { + nNumType = NUMBERFORMAT_DATE; + + util::Date aDate = xRow->getDate(nCol); + fValue = Date(aDate.Day, aDate.Month, aDate.Year) - rNullDate; + return new ScDPItemData( rStr, fValue, TRUE, nNumType ); + } + //break; + + case sdbc::DataType::TIME: + { + nNumType = NUMBERFORMAT_TIME; + + util::Time aTime = xRow->getTime(nCol); + fValue = ( aTime.Hours * 3600 + aTime.Minutes * 60 + + aTime.Seconds + aTime.HundredthSeconds / 100.0 ) / D_TIMEFACTOR; + return new ScDPItemData( rStr,fValue, TRUE, nNumType ); + } + //break; + + case sdbc::DataType::TIMESTAMP: + { + nNumType = NUMBERFORMAT_DATETIME; + + util::DateTime aStamp = xRow->getTimestamp(nCol); + fValue = ( Date( aStamp.Day, aStamp.Month, aStamp.Year ) - rNullDate ) + + ( aStamp.Hours * 3600 + aStamp.Minutes * 60 + + aStamp.Seconds + aStamp.HundredthSeconds / 100.0 ) / D_TIMEFACTOR; + return new ScDPItemData( rStr,fValue, TRUE, nNumType ); + } + //break; + case sdbc::DataType::CHAR: + case sdbc::DataType::VARCHAR: + case sdbc::DataType::LONGVARCHAR: + case sdbc::DataType::SQLNULL: + case sdbc::DataType::BINARY: + case sdbc::DataType::VARBINARY: + case sdbc::DataType::LONGVARBINARY: + default: + return new ScDPItemData ( rStr ); + //break; + } + } + catch (uno::Exception&) + { + } + catch ( ... ) + { + + } + return NULL; + } +} +// Wang Xu Ming -- 12/23/2008 +//Refactor cache data +ScDPItemData::ScDPItemData( const String& rS, double fV/* = 0.0*/, BOOL bHV/* = FALSE*/, const ULONG nNumFormatP /*= 0*/ , BOOL bData/* = TRUE*/) : +nNumFormat( nNumFormatP ), aString(rS), fValue(fV), +mbFlag( (MK_VAL*!!bHV) | (MK_DATA*!!bData) | (MK_ERR*!!FALSE) | (MK_DATE*!!lcl_isDate( nNumFormat ) ) ) +{ +} + +ScDPItemData::ScDPItemData( ScDocument* pDoc, SCROW nRow, USHORT nCol, USHORT nDocTab ): + nNumFormat( 0 ), fValue(0.0), mbFlag( 0 ) +{ + String aDocStr; + pDoc->GetString( nCol, nRow, nDocTab, aDocStr ); + + SvNumberFormatter* pFormatter = pDoc->GetFormatTable(); + + ScAddress aPos( nCol, nRow, nDocTab ); + ScBaseCell* pCell = pDoc->GetCell( aPos ); + + if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA && ((ScFormulaCell*)pCell)->GetErrCode() ) + SetString ( aDocStr ); //[SODC_19347] add liyi + //bErr = TRUE; //[SODC_19347] del liyi + else if ( pDoc->HasValueData( nCol, nRow, nDocTab ) ) + { + double fVal = pDoc->GetValue(ScAddress(nCol, nRow, nDocTab)); + ULONG nFormat = NUMBERFORMAT_NUMBER; + if ( pFormatter ) + nFormat = pFormatter->GetType( pDoc->GetNumberFormat( ScAddress( nCol, nRow, nDocTab ) ) ); + aString = aDocStr; + fValue = fVal; + mbFlag |= MK_VAL|MK_DATA; + nNumFormat = pDoc->GetNumberFormat( ScAddress( nCol, nRow, nDocTab ) ); + lcl_isDate( nFormat ) ? ( mbFlag |= MK_DATE ) : (mbFlag &= ~MK_DATE); + } + else if ( pDoc->HasData( nCol,nRow, nDocTab ) ) + SetString ( aDocStr ); +} +// End Comments + +BOOL ScDPItemData::IsCaseInsEqual( const ScDPItemData& r ) const +{ //TODO: indified Date? + //! pass Transliteration? + //! inline? + return IsValue() ? ( r.IsValue() && rtl::math::approxEqual( fValue, r.fValue ) ) : + ( !r.IsValue() && + ScGlobal::GetpTransliteration()->isEqual( aString, r.aString ) ); +} + +size_t ScDPItemData::Hash() const +{ + if ( IsValue() ) + return (size_t) rtl::math::approxFloor( fValue ); + else + // If we do unicode safe case insensitive hash we can drop + // ScDPItemData::operator== and use ::IsCasInsEqual + return rtl_ustr_hashCode_WithLength( aString.GetBuffer(), aString.Len() ); +} + +BOOL ScDPItemData::operator==( const ScDPItemData& r ) const +{ + if ( IsValue() ) + { + if( HasDatePart() != r.HasDatePart() || HasDatePart() && mnDatePart != r.mnDatePart ) + return FALSE; + +// Wang Xu Ming -- 1/9/2009 +// Add Data Cache Support. +// Identify date + if ( IsDate() != r.IsDate() ) + return FALSE; + else + if ( r.IsValue() ) + return rtl::math::approxEqual( fValue, r.fValue ); + else + return FALSE; +// End Comments + } + else if ( r.IsValue() ) + return FALSE; + else + // need exact equality until we have a safe case insensitive string hash + return aString == r.aString; +} + +sal_Int32 ScDPItemData::Compare( const ScDPItemData& rA, + const ScDPItemData& rB ) +{ + if ( rA.IsValue() ) + { + if ( rB.IsValue() ) + { + if ( rtl::math::approxEqual( rA.fValue, rB.fValue ) ) + { +// Wang Xu Ming -- 1/9/2009 +// Add Data Cache Support. +// Date > number + if ( rA.IsDate() == rB.IsDate() ) + return 0; + else + return rA.IsDate() ? 1: -1; +// End Comments + } + else if ( rA.fValue < rB.fValue ) + return -1; + else + return 1; + } + else + return -1; // values first + } + else if ( rB.IsValue() ) + return 1; // values first + else + return ScGlobal::GetCollator()->compareString( rA.aString, rB.aString ); +} +// +//Wang Xu Ming SODC_17561 +#ifdef DEBUG +void ScDPItemData::dump() const +{ + DBG_TRACE1( "Numberformat= %o", nNumFormat ); + DBG_TRACESTR(aString ); + DBG_TRACE1( "fValue= %f", fValue ); + DBG_TRACE1( "bHasValue= %d", bHasValue ? 1:0); +} +#endif +//End + +TypedStrData* ScDPItemData::CreateTypeString( ) +{ + if ( IsValue() ) + return new TypedStrData( aString, fValue, SC_STRTYPE_VALUE ); + else + return new TypedStrData( aString ); +} + +sal_uInt8 ScDPItemData::GetType() const +{ + + if ( IsHasErr() ) + return SC_VALTYPE_ERROR; + else if ( !IsHasData() ) + return SC_VALTYPE_EMPTY; + else if ( IsValue()) + return SC_VALTYPE_VALUE; + else + return SC_VALTYPE_STRING; + +} + +BOOL ScDPItemData::IsHasData() const +{ + return !!(mbFlag&MK_DATA); +} + +BOOL ScDPItemData::IsHasErr() const +{ + return !!(mbFlag&MK_ERR); +} + +BOOL ScDPItemData::IsValue() const +{ + return !!(mbFlag&MK_VAL); +} + +String ScDPItemData::GetString() const +{ + + return aString; +} + +double ScDPItemData::GetValue() const +{ + return fValue; +} +ULONG ScDPItemData::GetNumFormat() const +{ + return nNumFormat; +} + +BOOL ScDPItemData::HasStringData() const + +{ + return IsHasData()&&!IsHasErr()&&!IsValue(); +} +BOOL ScDPItemData::IsDate() const +{ + return !!(mbFlag&MK_DATE); +} +BOOL ScDPItemData::HasDatePart() const +{ + return !!(mbFlag&MK_DATEPART); +} +void ScDPItemData::SetDate( BOOL b ) +{ + b ? ( mbFlag |= MK_DATE ) : ( mbFlag &= ~MK_DATE ); +} + +// ----------------------------------------------------------------------- +//class ScDPTableDataCache +//To cache the pivot table data source + +BOOL ScDPTableDataCache::operator== ( const ScDPTableDataCache& r ) const +{ + if ( GetColumnCount() == r.GetColumnCount() ) + { + for ( SCCOL i = 0 ; i < GetColumnCount(); i++ ) + { //check dim names + if ( GetDimensionName( i ) != r.GetDimensionName( i ) ) + return FALSE; + //check rows count + if ( GetRowCount() != r.GetRowCount() ) + return FALSE; + //check dim member values + size_t nMembersCount = GetDimMemberValues( i ).size(); + if ( GetDimMemberValues( i ).size() == r. GetDimMemberValues( i ).size() ) + { + for ( size_t j = 0; j < nMembersCount; j++ ) + { + if ( *( GetDimMemberValues( i )[j] ) == *( r.GetDimMemberValues( i )[j] ) ) + continue; + else + return FALSE; + } + } + else + return FALSE; + //check source table index + for ( SCROW k=0 ; k < GetRowCount(); k ++ ) + { + if ( GetItemDataId( i, k, FALSE ) == r.GetItemDataId( i,k,FALSE) ) + continue; + else + return FALSE; + } + } + } + return TRUE; +} + +ScDPTableDataCache::ScDPTableDataCache( ScDocument* pDoc ) : +mpDoc( pDoc ), +mnColumnCount ( 0 ), +mpTableDataValues ( NULL ), +mpSourceData ( NULL ), +mpGlobalOrder( NULL ), +mpIndexOrder( NULL) +{ + mnID = -1; +} + +ScDPTableDataCache::~ScDPTableDataCache() +{ + if ( IsValid() ) + { +// Wang Xu Ming -- 2/17/2009 +// Performance issue + USHORT nCol; + for ( nCol=0; nCol < GetColumnCount() ; nCol++ ) + { + for ( ULONG row = 0 ; row < mpTableDataValues[nCol].size(); row++ ) + delete mpTableDataValues[nCol][row]; + } + for ( nCol =0; nCol < mrLabelNames.size(); nCol++ ) + delete mrLabelNames[nCol]; +// End Comments + + mnColumnCount = 0; + delete [] mpTableDataValues; + mpTableDataValues = NULL; + delete [] mpSourceData; + mpSourceData = NULL; + delete [] mpGlobalOrder; + mpGlobalOrder = NULL; + delete [] mpIndexOrder; + mpIndexOrder = NULL; + } +} + +// ----------------------------------------------------------------------- +void ScDPTableDataCache::AddRow( ScDPItemData* pRow, USHORT nCount ) +{ + DBG_ASSERT( pRow , " empty pointer" ); + if ( !mrLabelNames.size() ) + { + mnColumnCount= nCount; + mpTableDataValues = new std::vector<ScDPItemData*>[ mnColumnCount ]; + mpSourceData = new std::vector<SCROW>[ mnColumnCount ]; + mpGlobalOrder = new std::vector<SCROW>[ mnColumnCount ]; + mpIndexOrder = new std::vector<SCROW>[ mnColumnCount ]; + + for ( USHORT i = 0; i < nCount ; i ++ ) + AddLabel( new ScDPItemData( pRow[i] ) ); + } + else + { + for ( USHORT i = 0; i < nCount && i < mnColumnCount; i ++ ) + AddData( i, new ScDPItemData( pRow[i] ) ); + } +} + +// ----------------------------------------------------------------------- +bool ScDPTableDataCache::IsValid() const +{ //TODO: continue check valid + return mpTableDataValues!=NULL && mpSourceData!= NULL && mnColumnCount>0; +} + +// ----------------------------------------------------------------------- +bool ScDPTableDataCache::InitFromDoc( ScDocument* pDoc, const ScRange& rRange ) +{ + // + SCROW nStartRow = rRange.aStart.Row(); // start of data + SCROW nEndRow = rRange.aEnd.Row(); + USHORT nStartCol = rRange.aStart.Col(); + USHORT nEndCol = rRange.aEnd.Col(); + USHORT nDocTab = rRange.aStart.Tab(); + + //init + long nOldColumCount = mnColumnCount; + mnColumnCount = nEndCol - nStartCol + 1; + if ( IsValid() ) + { + for ( USHORT nCol=0; nCol < nOldColumCount ; nCol++ ) + { + for ( ULONG row = 0 ; row < mpTableDataValues[nCol].size(); row++ ) + delete mpTableDataValues[nCol][row]; + delete mrLabelNames[nCol]; + } + delete [] mpTableDataValues; + delete [] mpSourceData; + delete [] mpGlobalOrder; + delete [] mpIndexOrder; + mrLabelNames.clear(); + } + + mpTableDataValues = new std::vector<ScDPItemData*>[ mnColumnCount ]; + mpSourceData = new std::vector<SCROW>[ mnColumnCount ]; + mpGlobalOrder = new std::vector<SCROW>[ mnColumnCount ]; + mpIndexOrder = new std::vector<SCROW>[ mnColumnCount ]; + //check valid + for ( SCROW nRow = nStartRow; nRow <= nEndRow; nRow ++ ) + { + for ( USHORT nCol = nStartCol; nCol <= nEndCol; nCol++ ) + { + if ( nRow == nStartRow ) + AddLabel( new ScDPItemData( pDoc, nRow, nCol, nDocTab ) ); + else + AddData( nCol - nStartCol, new ScDPItemData( pDoc, nRow, nCol, nDocTab ) ); + } + } + return TRUE; +} + +// ----------------------------------------------------------------------- +bool ScDPTableDataCache::InitFromDataBase (const Reference<sdbc::XRowSet>& xRowSet, const Date& rNullDate) +{ + if (!xRowSet.is()) + // Dont' even waste time to go any further. + return false; + try + { + Reference<sdbc::XResultSetMetaDataSupplier> xMetaSupp(xRowSet, UNO_QUERY_THROW); + Reference<sdbc::XResultSetMetaData> xMeta = xMetaSupp->getMetaData(); + if (!xMeta.is()) + return false; + + long nOldColumCount = mnColumnCount; + mnColumnCount = xMeta->getColumnCount(); + if ( IsValid() ) + { + for ( USHORT nCol=0; nCol < nOldColumCount ; nCol++ ) + { + for ( ULONG row = 0 ; row < mpTableDataValues[nCol].size(); row++ ) + delete mpTableDataValues[nCol][row]; + delete mrLabelNames[nCol]; + } + delete [] mpTableDataValues; + delete [] mpSourceData; + delete [] mpGlobalOrder; + delete [] mpIndexOrder; + mrLabelNames.clear(); + } + // Get column titles and types. + mrLabelNames.reserve(mnColumnCount); + mpTableDataValues = new std::vector<ScDPItemData*>[ mnColumnCount ]; + mpSourceData = new std::vector<SCROW>[ mnColumnCount ]; + mpGlobalOrder = new std::vector<SCROW>[ mnColumnCount ]; + mpIndexOrder = new std::vector<SCROW>[ mnColumnCount ]; + + std::vector<sal_Int32> aColTypes(mnColumnCount); + + for (sal_Int32 nCol = 0; nCol < mnColumnCount; ++nCol) + { + String aColTitle = xMeta->getColumnLabel(nCol+1); + aColTypes[nCol] = xMeta->getColumnType(nCol+1); + AddLabel( new ScDPItemData( aColTitle) ); + } + + // Now get the data rows. + Reference<sdbc::XRow> xRow(xRowSet, UNO_QUERY_THROW); + xRowSet->first(); + do + { + for (sal_Int32 nCol = 0; nCol < mnColumnCount; ++nCol) + { + ScDPItemData * pNew = lcl_GetItemValue( xRow, aColTypes[nCol], nCol+1, rNullDate ); + if ( pNew ) + AddData( nCol , pNew ); + } + } + while (xRowSet->next()); + + xRowSet->beforeFirst(); + + return true; + } + catch (const Exception&) + { + return false; + } +} +// ----------------------------------------------------------------------- +ULONG ScDPTableDataCache::GetDimNumType( SCCOL nDim) const +{ + DBG_ASSERT( IsValid(), " IsValid() == false " ); + DBG_ASSERT( nDim < mnColumnCount && nDim >=0, " dimention out of bound " ); + if ( mpTableDataValues[nDim].size()==0 ) + return NUMBERFORMAT_UNDEFINED; + else + return GetNumType(mpTableDataValues[nDim][0]->nNumFormat); +} + +// ----------------------------------------------------------------------- +bool ScDPTableDataCache::ValidQuery( SCROW nRow, const ScQueryParam &rParam, BOOL *pSpecial) +{ //Copied and modified from ScTable::ValidQuery + if (!rParam.GetEntry(0).bDoQuery) + return TRUE; + BOOL bMatchWholeCell = mpDoc->GetDocOptions().IsMatchWholeCell(); + + //--------------------------------------------------------------- + + const SCSIZE nFixedBools = 32; + BOOL aBool[nFixedBools]; + BOOL aTest[nFixedBools]; + SCSIZE nEntryCount = rParam.GetEntryCount(); + BOOL* pPasst = ( nEntryCount <= nFixedBools ? &aBool[0] : new BOOL[nEntryCount] ); + BOOL* pTest = ( nEntryCount <= nFixedBools ? &aTest[0] : new BOOL[nEntryCount] ); + + long nPos = -1; + SCSIZE i = 0; + CollatorWrapper* pCollator = (rParam.bCaseSens ? ScGlobal::GetCaseCollator() : + ScGlobal::GetCollator() ); + ::utl::TransliterationWrapper* pTransliteration = (rParam.bCaseSens ? + ScGlobal::GetCaseTransliteration() : ScGlobal::GetpTransliteration()); + + while ( (i < nEntryCount) && rParam.GetEntry(i).bDoQuery ) + { + ScQueryEntry& rEntry = rParam.GetEntry(i); + // we can only handle one single direct query + SCROW nId = GetItemDataId( (SCCOL)rEntry.nField, nRow, FALSE ); + const ScDPItemData* pCellData = GetItemDataById( (SCCOL)rEntry.nField, nId); + + BOOL bOk = FALSE; + BOOL bTestEqual = FALSE; + + if ( pSpecial && pSpecial[i] ) + { + if (rEntry.nVal == SC_EMPTYFIELDS) + bOk = ! pCellData->IsHasData(); + else // if (rEntry.nVal == SC_NONEMPTYFIELDS) + bOk = pCellData->IsHasData(); + } + else if ( !rEntry.bQueryByString && pCellData->IsValue() ) + { // by Value + double nCellVal = pCellData->GetValue(); + + switch (rEntry.eOp) + { + case SC_EQUAL : + bOk = ::rtl::math::approxEqual( nCellVal, rEntry.nVal ); + break; + case SC_LESS : + bOk = (nCellVal < rEntry.nVal) && !::rtl::math::approxEqual( nCellVal, rEntry.nVal ); + break; + case SC_GREATER : + bOk = (nCellVal > rEntry.nVal) && !::rtl::math::approxEqual( nCellVal, rEntry.nVal ); + break; + case SC_LESS_EQUAL : + bOk = (nCellVal < rEntry.nVal) || ::rtl::math::approxEqual( nCellVal, rEntry.nVal ); + break; + case SC_GREATER_EQUAL : + bOk = (nCellVal > rEntry.nVal) || ::rtl::math::approxEqual( nCellVal, rEntry.nVal ); + break; + case SC_NOT_EQUAL : + bOk = !::rtl::math::approxEqual( nCellVal, rEntry.nVal ); + break; + default: + bOk= FALSE; + break; + } + } + else if ( (rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL) + || (rEntry.bQueryByString + && pCellData->HasStringData() ) + ) + { // by String + String aCellStr = pCellData->GetString(); + + BOOL bRealRegExp = (rParam.bRegExp && ((rEntry.eOp == SC_EQUAL) + || (rEntry.eOp == SC_NOT_EQUAL))); + BOOL bTestRegExp = FALSE; + if ( bRealRegExp || bTestRegExp ) + { + xub_StrLen nStart = 0; + xub_StrLen nEnd = aCellStr.Len(); + BOOL bMatch = (BOOL) rEntry.GetSearchTextPtr( rParam.bCaseSens ) + ->SearchFrwrd( aCellStr, &nStart, &nEnd ); + // from 614 on, nEnd is behind the found text + if ( bMatch && bMatchWholeCell + && (nStart != 0 || nEnd != aCellStr.Len()) ) + bMatch = FALSE; // RegExp must match entire cell string + if ( bRealRegExp ) + bOk = ((rEntry.eOp == SC_NOT_EQUAL) ? !bMatch : bMatch); + else + bTestEqual = bMatch; + } + if ( !bRealRegExp ) + { + if ( rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL ) + { + if ( bMatchWholeCell ) + { + bOk = pTransliteration->isEqual( aCellStr, *rEntry.pStr ); + //Added by zhaosz,for sodc_2702,20060808 + String aStr = *rEntry.pStr;//"f*" + //modified by weihuaw,for SODC_16698 + //use another way to find "*" in aStr + sal_Bool bHasStar = sal_False; + xub_StrLen nIndex; + if( ( nIndex = aStr.Search('*') ) != STRING_NOTFOUND ) + bHasStar = sal_True; + if(bHasStar && (nIndex>0)) + { + for(i=0;(i<nIndex) && (i< aCellStr.Len()) ; i++) + { + if(aCellStr.GetChar( (USHORT)i ) == aStr.GetChar((USHORT) i )) + { + bOk=1; + } + else + { + bOk=0; + break; + } + } + } + //end modified + //Added end,20060808 + } + else + { + ::com::sun::star::uno::Sequence< sal_Int32 > xOff; + String aCell( pTransliteration->transliterate( + aCellStr, ScGlobal::eLnge, 0, aCellStr.Len(), + &xOff ) ); + String aQuer( pTransliteration->transliterate( + *rEntry.pStr, ScGlobal::eLnge, 0, rEntry.pStr->Len(), + &xOff ) ); + bOk = (aCell.Search( aQuer ) != STRING_NOTFOUND); + } + if ( rEntry.eOp == SC_NOT_EQUAL ) + bOk = !bOk; + } + else + { // use collator here because data was probably sorted + sal_Int32 nCompare = pCollator->compareString( + aCellStr, *rEntry.pStr ); + switch (rEntry.eOp) + { + case SC_LESS : + bOk = (nCompare < 0); + break; + case SC_GREATER : + bOk = (nCompare > 0); + break; + case SC_LESS_EQUAL : + bOk = (nCompare <= 0); + break; + case SC_GREATER_EQUAL : + bOk = (nCompare >= 0); + break; + case SC_NOT_EQUAL: + DBG_ASSERT( false , "SC_NOT_EQUAL"); + break; + case SC_TOPVAL: + case SC_BOTVAL: + case SC_TOPPERC: + case SC_BOTPERC: + default: + break; + } + } + } + } + + if (nPos == -1) + { + nPos++; + pPasst[nPos] = bOk; + pTest[nPos] = bTestEqual; + } + else + { + if (rEntry.eConnect == SC_AND) + { + pPasst[nPos] = pPasst[nPos] && bOk; + pTest[nPos] = pTest[nPos] && bTestEqual; + } + else + { + nPos++; + pPasst[nPos] = bOk; + pTest[nPos] = bTestEqual; + } + } + i++; + } + + for ( long j=1; j <= nPos; j++ ) + { + pPasst[0] = pPasst[0] || pPasst[j]; + pTest[0] = pTest[0] || pTest[j]; + } + + BOOL bRet = pPasst[0]; + if ( pPasst != &aBool[0] ) + delete [] pPasst; + if ( pTest != &aTest[0] ) + delete [] pTest; + + return bRet; +} + +// ----------------------------------------------------------------------- +bool ScDPTableDataCache::IsRowEmpty( SCROW nRow ) const +{ + return mbEmptyRow[ nRow ]; + +} + +// ----------------------------------------------------------------------- +bool ScDPTableDataCache::IsEmptyMember( SCROW nRow, USHORT nColumn ) const +{ + return !GetItemDataById( nColumn, GetItemDataId( nColumn, nRow, FALSE ) )->IsHasData(); +} + +BOOL ScDPTableDataCache::AddData(long nDim, ScDPItemData* pitemData) +{ + DBG_ASSERT( IsValid(), " IsValid() == false " ); + DBG_ASSERT( nDim < mnColumnCount && nDim >=0 , "dimension out of bound" ); + SCROW nIndex = 0; + + BOOL bInserted = FALSE; + + pitemData->SetDate( lcl_isDate( GetNumType( pitemData->nNumFormat ) ) ); + + if ( !lcl_Search( mpTableDataValues[nDim], mpGlobalOrder[nDim], *pitemData, nIndex ) ) + { + mpTableDataValues[nDim].push_back( pitemData ); + mpGlobalOrder[nDim].insert( mpGlobalOrder[nDim].begin()+nIndex, mpTableDataValues[nDim].size()-1 ); + DBG_ASSERT( (size_t) mpGlobalOrder[nDim][nIndex] == mpTableDataValues[nDim].size()-1 ,"ScDPTableDataCache::AddData "); + mpSourceData[nDim].push_back( mpTableDataValues[nDim].size()-1 ); + bInserted = TRUE; + } + else + mpSourceData[nDim].push_back( mpGlobalOrder[nDim][nIndex] ); +//init empty row tag + size_t nCurRow = mpSourceData[nDim].size() -1 ; + + while ( mbEmptyRow.size() <= nCurRow ) + mbEmptyRow.push_back( TRUE ); + + if ( pitemData->IsHasData() ) + mbEmptyRow[ nCurRow ] = FALSE; + + if ( !bInserted ) + delete pitemData; + + return TRUE; +} + + +String ScDPTableDataCache::GetDimensionName( USHORT nColumn ) const +{ + DBG_ASSERT( /* nColumn>=0 && */ nColumn < mrLabelNames.size()-1 , "ScDPTableDataCache::GetDimensionName"); + DBG_ASSERT( mrLabelNames.size() == static_cast <USHORT> (mnColumnCount+1), "ScDPTableDataCache::GetDimensionName"); + if ( static_cast<size_t>(nColumn+1) < mrLabelNames.size() ) + { + return mrLabelNames[nColumn+1]->aString; + } + else + return String(); +} + +void ScDPTableDataCache::AddLabel(ScDPItemData *pData) +{ + DBG_ASSERT( IsValid(), " IsValid() == false " ); + + if ( mrLabelNames.size() == 0 ) + mrLabelNames.push_back( new ScDPItemData( ScGlobal::GetRscString(STR_PIVOT_DATA) ) ); + + + //reset name if needed + String strNewName = pData->aString; + BOOL bFound = FALSE; + long nIndex = 1; + do + { + for ( long i= mrLabelNames.size()-1; i>=0; i-- ) + { + if( mrLabelNames[i]->aString == strNewName ) + { + strNewName = pData->aString; + strNewName += String::CreateFromInt32( nIndex ); + nIndex ++ ; + bFound = TRUE; + } + } + bFound = !bFound; + } + while ( !bFound ); + + pData->aString = strNewName; + mrLabelNames.push_back( pData ); +} + +SCROW ScDPTableDataCache::GetItemDataId(USHORT nDim, SCROW nRow, BOOL bRepeatIfEmpty) const +{ // + DBG_ASSERT( IsValid(), " IsValid() == false " ); + DBG_ASSERT( /* nDim >= 0 && */ nDim < mnColumnCount, "ScDPTableDataCache::GetItemDataId " ); + + if ( bRepeatIfEmpty ) + { + while ( nRow >0 && !mpTableDataValues[nDim][ mpSourceData[nDim][nRow] ]->IsHasData() ) + --nRow; + } + + return mpSourceData[nDim][nRow]; +} + +const ScDPItemData* ScDPTableDataCache::GetItemDataById(long nDim, SCROW nId) const +{ + if ( nId >= GetRowCount() ) + return maAdditionalDatas.getData( nId - GetRowCount() ); + + if ( (size_t)nId >= mpTableDataValues[nDim].size() || nDim >= mnColumnCount || nId < 0 ) + return NULL; + else + return mpTableDataValues[nDim][nId]; +} + +SCROW ScDPTableDataCache::GetRowCount() const +{ + if ( IsValid() ) + return mpSourceData[0].size(); + else + return 0; +} + +const std::vector<ScDPItemData*>& ScDPTableDataCache::GetDimMemberValues(SCCOL nDim) const +{ + DBG_ASSERT( nDim>=0 && nDim < mnColumnCount ," nDim < mnColumnCount "); + return mpTableDataValues[nDim]; +} + +SCROW ScDPTableDataCache::GetSortedItemDataId(SCCOL nDim, SCROW nOrder) const +{ + DBG_ASSERT ( IsValid(), "IsValid"); + DBG_ASSERT( nDim>=0 && nDim < mnColumnCount, "nDim < mnColumnCount"); + DBG_ASSERT( nOrder >= 0 && (size_t) nOrder < mpGlobalOrder[nDim].size(), "nOrder < mpGlobalOrder[nDim].size()" ); + + return mpGlobalOrder[nDim][nOrder]; +} + +ULONG ScDPTableDataCache::GetNumType(ULONG nFormat) const +{ + SvNumberFormatter* pFormatter = mpDoc->GetFormatTable(); + ULONG nType = NUMBERFORMAT_NUMBER; + if ( pFormatter ) + nType = pFormatter->GetType( nFormat ); + return nType; +} + +ULONG ScDPTableDataCache::GetNumberFormat( long nDim ) const +{ + if ( nDim >= mnColumnCount ) + return 0; + if ( mpTableDataValues[nDim].size()==0 ) + return 0; + else + return mpTableDataValues[nDim][0]->nNumFormat; +} + +BOOL ScDPTableDataCache::IsDateDimension( long nDim ) const +{ + if ( nDim >= mnColumnCount ) + return false; + else if ( mpTableDataValues[nDim].size()==0 ) + return false; + else + return mpTableDataValues[nDim][0]->IsDate(); + +} + +SCROW ScDPTableDataCache::GetDimMemberCount( SCCOL nDim ) const +{ + DBG_ASSERT( nDim>=0 && nDim < mnColumnCount ," ScDPTableDataCache::GetDimMemberCount : out of bound "); + return mpTableDataValues[nDim].size(); +} + +const ScDPItemData* ScDPTableDataCache::GetSortedItemData(SCCOL nDim, SCROW nOrder) const +{ + SCROW n = GetSortedItemDataId( nDim, nOrder ); + return GetItemDataById( nDim, n ); +} + +SCCOL ScDPTableDataCache::GetDimensionIndex(String sName) const +{ + for ( size_t n = 1; n < mrLabelNames.size(); n ++ ) //defects, label name map wrong SODC_17590, SODC_18932,SODC_18827,SODC_18960,SODC_18923 + { + if ( mrLabelNames[n]->GetString() == sName ) + return (SCCOL)(n-1); + } + return -1; +} + +SCROW ScDPTableDataCache::GetIdByItemData(long nDim, String sItemData ) const +{ + if ( nDim < mnColumnCount && nDim >=0 ) + { + for ( size_t n = 0; n< mpTableDataValues[nDim].size(); n++ ) + { + if ( mpTableDataValues[nDim][n]->GetString() == sItemData ) + return n; + } + } + + ScDPItemData rData ( sItemData ); + return GetRowCount() +maAdditionalDatas.getDataId(rData); +} + +SCROW ScDPTableDataCache::GetIdByItemData( long nDim, const ScDPItemData& rData ) const +{ + if ( nDim < mnColumnCount && nDim >=0 ) + { + for ( size_t n = 0; n< mpTableDataValues[nDim].size(); n++ ) + { + if ( *mpTableDataValues[nDim][n] == rData ) + return n; + } + } + return GetRowCount() + maAdditionalDatas.getDataId(rData); +} + +SCROW ScDPTableDataCache::GetAdditionalItemID ( String sItemData ) +{ + ScDPItemData rData ( sItemData ); + return GetAdditionalItemID( rData ); +} + +SCROW ScDPTableDataCache::GetAdditionalItemID( const ScDPItemData& rData ) +{ + return GetRowCount() + maAdditionalDatas.insertData( rData ); +} + + +SCROW ScDPTableDataCache::GetOrder(long nDim, SCROW nIndex) const +{ + DBG_ASSERT( IsValid(), " IsValid() == false " ); + DBG_ASSERT( nDim >=0 && nDim < mnColumnCount, "ScDPTableDataCache::GetOrder : out of bound" ); + + if ( mpIndexOrder[nDim].size() != mpGlobalOrder[nDim].size() ) + { //not inited + SCROW i = 0; + mpIndexOrder[nDim].resize( mpGlobalOrder[nDim].size(), 0 ); + for ( size_t n = 0 ; n< mpGlobalOrder[nDim].size(); n++ ) + { + i = mpGlobalOrder[nDim][n]; + mpIndexOrder[nDim][ i ] = n; + } + } + + DBG_ASSERT( nIndex>=0 && (size_t)nIndex < mpIndexOrder[nDim].size() , "ScDPTableDataCache::GetOrder"); + return mpIndexOrder[nDim][nIndex]; +} + +ScDocument* ScDPTableDataCache::GetDoc() const +{ + return mpDoc; +}; + +long ScDPTableDataCache::GetColumnCount() const +{ + return mnColumnCount; +} +long ScDPTableDataCache::GetId() const +{ + return mnID; +} + diff --git a/sc/source/core/data/dptabres.cxx b/sc/source/core/data/dptabres.cxx index 63f5da3290d7..55f9fb771061 100644..100755 --- a/sc/source/core/data/dptabres.cxx +++ b/sc/source/core/data/dptabres.cxx @@ -87,7 +87,44 @@ static USHORT nFuncStrIds[12] = // passend zum enum ScSubTotalFunc STR_FUN_TEXT_VAR, // SUBTOTAL_FUNC_VAR STR_FUN_TEXT_VAR // SUBTOTAL_FUNC_VARP }; +namespace { + template < typename T > + void lcl_ResizePointVector( T & vec, size_t nSize ) + { + for ( size_t i = 0 ; i < vec.size(); i++ ) + { + if ( vec[i] ) + delete vec[i]; + } + vec.resize( nSize, NULL ); + } + BOOL lcl_SearchMember( const std::vector <ScDPResultMember *>& list, SCROW nOrder, SCROW& rIndex) + { + rIndex = list.size(); + BOOL bFound = FALSE; + SCROW nLo = 0; + SCROW nHi = list.size() - 1; + SCROW nIndex; + while (nLo <= nHi) + { + nIndex = (nLo + nHi) / 2; + if ( list[nIndex]->GetOrder() < nOrder ) + nLo = nIndex + 1; + else + { + nHi = nIndex - 1; + if ( list[nIndex]->GetOrder() == nOrder ) + { + bFound = TRUE; + nLo = nIndex; + } + } + } + rIndex = nLo; + return bFound; + } +} // ----------------------------------------------------------------------- // @@ -194,12 +231,16 @@ BOOL ScDPRowMembersOrder::operator()( sal_Int32 nIndex1, sal_Int32 nIndex2 ) con { const ScDPResultMember* pMember1 = rDimension.GetMember(nIndex1); const ScDPResultMember* pMember2 = rDimension.GetMember(nIndex2); - +// Wang Xu Ming -- 3/17/2009 + +// make the hide item to the largest order. + if ( !pMember1->IsVisible() || !pMember2->IsVisible() ) + return pMember1->IsVisible(); + const ScDPDataMember* pDataMember1 = pMember1->GetDataRoot() ; + const ScDPDataMember* pDataMember2 = pMember2->GetDataRoot(); +// End Comments // GetDataRoot can be NULL if there was no data. // IsVisible == FALSE can happen after AutoShow. - const ScDPDataMember* pDataMember1 = pMember1->IsVisible() ? pMember1->GetDataRoot() : NULL; - const ScDPDataMember* pDataMember2 = pMember2->IsVisible() ? pMember2->GetDataRoot() : NULL; - return lcl_IsLess( pDataMember1, pDataMember2, nMeasure, bAscending ); } @@ -207,12 +248,12 @@ BOOL ScDPColMembersOrder::operator()( sal_Int32 nIndex1, sal_Int32 nIndex2 ) con { ScDPDataMember* pDataMember1 = rDimension.GetMember(nIndex1); ScDPDataMember* pDataMember2 = rDimension.GetMember(nIndex2); - - if ( pDataMember1 && !pDataMember1->IsVisible() ) //! IsColVisible? - pDataMember1 = NULL; - if ( pDataMember2 && !pDataMember2->IsVisible() ) - pDataMember2 = NULL; - + // Wang Xu Ming -- 2009-6-17 + BOOL bHide1 = pDataMember1 && !pDataMember1->IsVisible(); + BOOL bHide2 = pDataMember2 && !pDataMember2->IsVisible(); + if ( bHide1 || bHide2 ) + return !bHide1; + // End Comments return lcl_IsLess( pDataMember1, pDataMember2, nMeasure, bAscending ); } @@ -222,7 +263,7 @@ ScDPInitState::ScDPInitState() : nCount( 0 ) { pIndex = new long[SC_DAPI_MAXFIELDS]; - pData = new ScDPItemData[SC_DAPI_MAXFIELDS]; + pData = new SCROW[SC_DAPI_MAXFIELDS]; } ScDPInitState::~ScDPInitState() @@ -231,13 +272,13 @@ ScDPInitState::~ScDPInitState() delete[] pData; } -void ScDPInitState::AddMember( long nSourceIndex, const ScDPItemData& rName ) +void ScDPInitState::AddMember( long nSourceIndex, SCROW nMember ) { DBG_ASSERT( nCount < SC_DAPI_MAXFIELDS, "too many InitState members" ); if ( nCount < SC_DAPI_MAXFIELDS ) { pIndex[nCount] = nSourceIndex; - pData[nCount] = rName; + pData[nCount] = nMember; ++nCount; } } @@ -249,13 +290,13 @@ void ScDPInitState::RemoveMember() --nCount; } -const ScDPItemData* ScDPInitState::GetNameForIndex( long nIndexValue ) const +const SCROW ScDPInitState::GetNameIdForIndex( long nIndexValue ) const { for (long i=0; i<nCount; i++) if ( pIndex[i] == nIndexValue ) - return &pData[i]; + return pData[i]; - return NULL; // not found + return -1; // not found } // ----------------------------------------------------------------------- @@ -735,6 +776,8 @@ ScDPResultData::ScDPResultData( ScDPSource* pSrc ) : //! Ref bDataAtCol( FALSE ), bDataAtRow( FALSE ) { + + lcl_ResizePointVector( mpDimMembers , SC_DAPI_MAXFIELDS ); } ScDPResultData::~ScDPResultData() @@ -743,6 +786,8 @@ ScDPResultData::~ScDPResultData() delete[] pMeasRefs; delete[] pMeasRefOrient; delete[] pMeasNames; + + lcl_ResizePointVector( mpDimMembers , 0 ); } void ScDPResultData::SetMeasureData( long nCount, const ScSubTotalFunc* pFunctions, @@ -890,15 +935,32 @@ BOOL ScDPResultData::IsNumOrDateGroup( long nDim ) const } BOOL ScDPResultData::IsInGroup( const ScDPItemData& rGroupData, long nGroupIndex, - const ScDPItemData& rBaseData, long nBaseIndex ) const + long nBaseDataId, long nBaseIndex ) const { - return pSource->GetData()->IsInGroup( rGroupData, nGroupIndex, rBaseData, nBaseIndex ); + const ScDPItemData* pData = pSource->GetItemDataById( nGroupIndex , nBaseDataId); + if ( pData ) + return pSource->GetData()->IsInGroup( rGroupData, nGroupIndex, *pData , nBaseIndex ); + else + return FALSE; +} +BOOL ScDPResultData::IsInGroup( SCROW nGroupDataId, long nGroupIndex, + const ScDPItemData& rBaseData, long nBaseIndex ) const +{ + const ScDPItemData* pGroupData = pSource->GetItemDataById( nGroupIndex , nGroupDataId); + if ( pGroupData ) + return pSource->GetData()->IsInGroup( *pGroupData, nGroupIndex, rBaseData , nBaseIndex ); + else + return FALSE; } -BOOL ScDPResultData::HasCommonElement( const ScDPItemData& rFirstData, long nFirstIndex, +BOOL ScDPResultData::HasCommonElement(/* const ScDPItemData& rFirstData*/SCROW nFirstDataId, long nFirstIndex, const ScDPItemData& rSecondData, long nSecondIndex ) const { - return pSource->GetData()->HasCommonElement( rFirstData, nFirstIndex, rSecondData, nSecondIndex ); + const ScDPItemData* pFirstData = pSource->GetItemDataById( nFirstIndex , nFirstDataId); + if ( pFirstData ) + return pSource->GetData()->HasCommonElement( *pFirstData, nFirstIndex, rSecondData, nSecondIndex ); + else + return FALSE; } const ScDPSource* ScDPResultData::GetSource() const @@ -906,27 +968,68 @@ const ScDPSource* ScDPResultData::GetSource() const return pSource; } +ResultMembers* ScDPResultData::GetDimResultMembers( long nDim , ScDPDimension* pDim, ScDPLevel* pLevel) const +{ + if ( mpDimMembers[ nDim ] == NULL ) + { + + //long nDimSource = pDim->GetDimension(); + + ResultMembers* pResultMembers = new ResultMembers(); + // global order is used to initialize aMembers, so it doesn't have to be looked at later + const ScMemberSortOrder& rGlobalOrder = pLevel->GetGlobalOrder(); + + ScDPMembers* pMembers = pLevel->GetMembersObject(); + long nMembCount = pMembers->getCount(); + for ( long i=0; i<nMembCount; i++ ) + { + long nSorted = rGlobalOrder.empty() ? i : rGlobalOrder[i]; + ScDPMember* pMember = pMembers->getByIndex(nSorted); + if ( NULL == pResultMembers->FindMember( pMember->GetItemDataId() ) ) + { + ScDPParentDimData* pNew = new ScDPParentDimData( i, pDim, pLevel, pMember ); + pResultMembers->InsertMember( pNew ); + } + } + + mpDimMembers[ nDim ] = pResultMembers; + } + return mpDimMembers[ nDim ]; + +} + // ----------------------------------------------------------------------- -ScDPResultMember::ScDPResultMember( const ScDPResultData* pData, const ScDPDimension* pDim, - const ScDPLevel* pLev, const ScDPMember* pDesc, +ScDPResultMember::ScDPResultMember( const ScDPResultData* pData, const ScDPParentDimData& rParentDimData , BOOL bForceSub ) : pResultData( pData ), - pParentDim( pDim ), - pParentLevel( pLev ), - pMemberDesc( pDesc ), + aParentDimData( rParentDimData ), pChildDimension( NULL ), pDataRoot( NULL ), bHasElements( FALSE ), bForceSubTotal( bForceSub ), bHasHiddenDetails( FALSE ), bInitialized( FALSE ), - bAutoHidden( FALSE ) + bAutoHidden( FALSE ), + nMemberStep( 1 ) { // pParentLevel/pMemberDesc is 0 for root members } +ScDPResultMember::ScDPResultMember( const ScDPResultData* pData, + BOOL bForceSub ) : + pResultData( pData ), + pChildDimension( NULL ), + pDataRoot( NULL ), + bHasElements( FALSE ), + bForceSubTotal( bForceSub ), + bHasHiddenDetails( FALSE ), + bInitialized( FALSE ), + bAutoHidden( FALSE ), + nMemberStep( 1 ) +{ +} ScDPResultMember::~ScDPResultMember() { delete pChildDimension; @@ -935,6 +1038,7 @@ ScDPResultMember::~ScDPResultMember() String ScDPResultMember::GetName() const { + const ScDPMember* pMemberDesc = GetDPMember(); if (pMemberDesc) return pMemberDesc->GetNameStr(); else @@ -943,22 +1047,23 @@ String ScDPResultMember::GetName() const void ScDPResultMember::FillItemData( ScDPItemData& rData ) const { + const ScDPMember* pMemberDesc = GetDPMember(); if (pMemberDesc) pMemberDesc->FillItemData( rData ); else rData.SetString( ScGlobal::GetRscString(STR_PIVOT_TOTAL) ); // root member } -BOOL ScDPResultMember::IsNamedItem( const ScDPItemData& r ) const +BOOL ScDPResultMember::IsNamedItem( SCROW nIndex ) const { //! store ScDPMember pointer instead of ScDPMember ??? - + const ScDPMember* pMemberDesc = GetDPMember(); if (pMemberDesc) - return ((ScDPMember*)pMemberDesc)->IsNamedItem( r ); + return ((ScDPMember*)pMemberDesc)->IsNamedItem( nIndex ); return FALSE; } -bool ScDPResultMember::IsValidEntry( const vector<ScDPItemData>& aMembers ) const +bool ScDPResultMember::IsValidEntry( const vector< SCROW >& aMembers ) const { if ( !IsValid() ) return false; @@ -969,8 +1074,8 @@ bool ScDPResultMember::IsValidEntry( const vector<ScDPItemData>& aMembers ) cons if (aMembers.size() < 2) return false; - vector<ScDPItemData>::const_iterator itr = aMembers.begin(); - vector<ScDPItemData> aChildMembers(++itr, aMembers.end()); + vector<SCROW>::const_iterator itr = aMembers.begin(); + vector<SCROW> aChildMembers(++itr, aMembers.end()); return pChildDim->IsValidEntry(aChildMembers); } else @@ -978,7 +1083,8 @@ bool ScDPResultMember::IsValidEntry( const vector<ScDPItemData>& aMembers ) cons } void ScDPResultMember::InitFrom( const vector<ScDPDimension*>& ppDim, const vector<ScDPLevel*>& ppLev, - size_t nPos, ScDPInitState& rInitState ) + size_t nPos, ScDPInitState& rInitState , + BOOL bInitChild /*= TRUE */) { // with LateInit, initialize only those members that have data if ( pResultData->IsLateInit() ) @@ -990,18 +1096,40 @@ void ScDPResultMember::InitFrom( const vector<ScDPDimension*>& ppDim, const vect return; // skip child dimension if details are not shown - if ( pMemberDesc && !pMemberDesc->getShowDetails() ) + if ( GetDPMember() && !GetDPMember()->getShowDetails() ) { + // Wang Xu Ming -- 2009-6-16 + // Show DataLayout dimention + nMemberStep = 1; + while ( nPos < ppDim.size() ) + { + if ( ppDim[nPos] ->getIsDataLayoutDimension() ) + { + if ( !pChildDimension ) + pChildDimension = new ScDPResultDimension( pResultData ); + pChildDimension->InitFrom( ppDim, ppLev, nPos, rInitState , FALSE ); + return; + } + else + { //find next dim + nPos ++; + nMemberStep ++; + } + } + // End Comments bHasHiddenDetails = TRUE; // only if there is a next dimension return; } - pChildDimension = new ScDPResultDimension( pResultData ); - pChildDimension->InitFrom( ppDim, ppLev, nPos, rInitState ); + if ( bInitChild ) + { + pChildDimension = new ScDPResultDimension( pResultData ); + pChildDimension->InitFrom( ppDim, ppLev, nPos, rInitState, TRUE ); + } } -void ScDPResultMember::LateInitFrom( const vector<ScDPDimension*>& ppDim, const vector<ScDPLevel*>& ppLev, - const vector<ScDPItemData>& pItemData, size_t nPos, +void ScDPResultMember::LateInitFrom( LateInitParams& rParams/*const vector<ScDPDimension*>& ppDim, const vector<ScDPLevel*>& ppLev*/, + const vector< SCROW >& pItemData, size_t nPos, ScDPInitState& rInitState ) { // without LateInit, everything has already been initialized @@ -1010,29 +1138,52 @@ void ScDPResultMember::LateInitFrom( const vector<ScDPDimension*>& ppDim, const bInitialized = TRUE; - if (nPos >= ppDim.size()) + if ( rParams.IsEnd( nPos ) /*nPos >= ppDim.size()*/) // No next dimension. Bail out. return; // skip child dimension if details are not shown - if ( pMemberDesc && !pMemberDesc->getShowDetails() ) + if ( GetDPMember() && !GetDPMember()->getShowDetails() ) { + // Wang Xu Ming -- 2009-6-16 + // DataPilot Migration + // Show DataLayout dimention + nMemberStep = 1; + while ( !rParams.IsEnd( nPos ) ) + { + if ( rParams.GetDim( nPos ) ->getIsDataLayoutDimension() ) + { + if ( !pChildDimension ) + pChildDimension = new ScDPResultDimension( pResultData ); + rParams.SetInitChild( FALSE ); + pChildDimension->LateInitFrom( rParams, pItemData, nPos, rInitState ); + return; + } + else + { //find next dim + nPos ++; + nMemberStep ++; + } + } + // End Comments bHasHiddenDetails = TRUE; // only if there is a next dimension return; } // LateInitFrom is called several times... - if ( !pChildDimension ) - pChildDimension = new ScDPResultDimension( pResultData ); - - pChildDimension->LateInitFrom( ppDim, ppLev, pItemData, nPos, rInitState ); + if ( rParams.GetInitChild() ) + { + if ( !pChildDimension ) + pChildDimension = new ScDPResultDimension( pResultData ); + pChildDimension->LateInitFrom( rParams, pItemData, nPos, rInitState ); + } } BOOL ScDPResultMember::IsSubTotalInTitle(long nMeasure) const { BOOL bRet = FALSE; - if ( pChildDimension && pParentLevel && - pParentLevel->IsOutlineLayout() && pParentLevel->IsSubtotalsAtTop() ) + if ( pChildDimension && /*pParentLevel*/GetParentLevel() && + /*pParentLevel*/GetParentLevel()->IsOutlineLayout() && /*pParentLevel*/GetParentLevel()->IsSubtotalsAtTop() ) { long nUserSubStart; long nSubTotals = GetSubTotalCount( &nUserSubStart ); @@ -1054,7 +1205,7 @@ long ScDPResultMember::GetSize(long nMeasure) const { if ( !IsVisible() ) return 0; - + const ScDPLevel* pParentLevel = GetParentLevel(); long nExtraSpace = 0; if ( pParentLevel && pParentLevel->IsAddEmpty() ) ++nExtraSpace; @@ -1091,7 +1242,7 @@ BOOL ScDPResultMember::IsVisible() const { // not initialized -> shouldn't be there at all // (allocated only to preserve ordering) - + const ScDPLevel* pParentLevel = GetParentLevel(); return ( bHasElements || ( pParentLevel && pParentLevel->getShowEmpty() ) ) && IsValid() && bInitialized; } @@ -1100,6 +1251,7 @@ BOOL ScDPResultMember::IsValid() const // non-Valid members are left out of calculation // was member set no invisible at the DataPilotSource? + const ScDPMember* pMemberDesc =GetDPMember(); if ( pMemberDesc && !pMemberDesc->getIsVisible() ) return FALSE; @@ -1122,6 +1274,8 @@ long ScDPResultMember::GetSubTotalCount( long* pUserSubStart ) const if ( pUserSubStart ) *pUserSubStart = 0; // default + const ScDPLevel* pParentLevel = GetParentLevel(); + if ( bForceSubTotal ) // set if needed for root members return 1; // grand total is always "automatic" else if ( pParentLevel ) @@ -1145,8 +1299,8 @@ long ScDPResultMember::GetSubTotalCount( long* pUserSubStart ) const return 0; } -void ScDPResultMember::ProcessData( const vector<ScDPItemData>& aChildMembers, const ScDPResultDimension* pDataDim, - const vector<ScDPItemData>& aDataMembers, const vector<ScDPValueData>& aValues ) +void ScDPResultMember::ProcessData( const vector< SCROW >& aChildMembers, const ScDPResultDimension* pDataDim, + const vector< SCROW >& aDataMembers, const vector<ScDPValueData>& aValues ) { SetHasElements(); @@ -1169,6 +1323,8 @@ void ScDPResultMember::ProcessData( const vector<ScDPItemData>& aChildMembers, c if ( !nUserSubCount || !pChildDimension ) nUserSubCount = 1; + const ScDPLevel* pParentLevel = GetParentLevel(); + for (long nUserPos=0; nUserPos<nUserSubCount; nUserPos++) // including hidden "automatic" { // #i68338# if nUserSubCount is 1 (automatic only), don't set nRowSubTotalFunc @@ -1229,10 +1385,10 @@ void ScDPResultMember::FillMemberResults( uno::Sequence<sheet::MemberResult>* pS { ScDPItemData aItemData; FillItemData( aItemData ); - aName = aItemData.aString; - bIsNumeric = aItemData.bHasValue; + aName = aItemData.GetString(); + bIsNumeric = aItemData.IsValue(); } - + const ScDPDimension* pParentDim = GetParentDim(); if ( bIsNumeric && pParentDim && pResultData->IsNumOrDateGroup( pParentDim->GetDimension() ) ) { // Numeric group dimensions use numeric entries for proper sorting, @@ -1241,6 +1397,7 @@ void ScDPResultMember::FillMemberResults( uno::Sequence<sheet::MemberResult>* pS } String aCaption = aName; + const ScDPMember* pMemberDesc = GetDPMember(); if (pMemberDesc) { const OUString* pLayoutName = pMemberDesc->GetLayoutName(); @@ -1272,6 +1429,7 @@ void ScDPResultMember::FillMemberResults( uno::Sequence<sheet::MemberResult>* pS pArray[rPos+i].Flags |= sheet::MemberResultFlags::CONTINUE; } + const ScDPLevel* pParentLevel = GetParentLevel(); long nExtraSpace = 0; if ( pParentLevel && pParentLevel->IsAddEmpty() ) ++nExtraSpace; @@ -1293,7 +1451,8 @@ void ScDPResultMember::FillMemberResults( uno::Sequence<sheet::MemberResult>* pS if (bRoot) // same sequence for root member pChildDimension->FillMemberResults( pSequences, rPos, nMeasure ); else - pChildDimension->FillMemberResults( pSequences + 1, rPos, nMeasure ); + //pChildDimension->FillMemberResults( pSequences + 1, rPos, nMeasure ); + pChildDimension->FillMemberResults( pSequences + nMemberStep/*1*/, rPos, nMeasure ); if ( bTitleLine ) // title row is included in GetSize, so the following --rPos; // positions are calculated with the normal values @@ -1389,7 +1548,7 @@ void ScDPResultMember::FillDataResults( const ScDPResultMember* pRefMember, { // IsVisible() test is in ScDPResultDimension::FillDataResults // (not on data layout dimension) - + const ScDPLevel* pParentLevel = GetParentLevel(); long nStartRow = rRow; long nExtraSpace = 0; @@ -1409,7 +1568,7 @@ void ScDPResultMember::FillDataResults( const ScDPResultMember* pRefMember, ++rRow; // -> fill child dimension one row below pChildDimension->FillDataResults( pRefMember, rSequence, rRow, nMeasure ); // doesn't modify rRow - rRow += (USHORT) GetSize( nMeasure ); + rRow += GetSize( nMeasure ); if ( bTitleLine ) // title row is included in GetSize, so the following --rRow; // positions are calculated with the normal values @@ -1451,7 +1610,7 @@ void ScDPResultMember::FillDataResults( const ScDPResultMember* pRefMember, if ( bHasChild && nUserSubCount > 1 ) { aSubState.nRowSubTotalFunc = nUserPos; - aSubState.eRowForce = lcl_GetForceFunc( pParentLevel, nUserPos ); + aSubState.eRowForce = lcl_GetForceFunc( /*pParentLevel*/GetParentLevel() , nUserPos ); } for ( long nSubCount=0; nSubCount<nSubSize; nSubCount++ ) @@ -1509,7 +1668,7 @@ void ScDPResultMember::UpdateDataResults( const ScDPResultMember* pRefMember, lo if ( bHasChild && nUserSubCount > 1 ) { aSubState.nRowSubTotalFunc = nUserPos; - aSubState.eRowForce = lcl_GetForceFunc( pParentLevel, nUserPos ); + aSubState.eRowForce = lcl_GetForceFunc( /*pParentLevel*/GetParentLevel() , nUserPos ); } for ( long nSubCount=0; nSubCount<nSubSize; nSubCount++ ) @@ -1537,8 +1696,7 @@ void ScDPResultMember::SortMembers( ScDPResultMember* pRefMember ) if (bHasChild) pChildDimension->SortMembers( pRefMember ); // sorting is done at the dimension - BOOL bIsRoot = ( pParentLevel == NULL ); - if ( bIsRoot && pDataRoot ) + if ( IsRoot() && pDataRoot ) { // use the row root member to sort columns // sub total count is always 1 @@ -1553,8 +1711,7 @@ void ScDPResultMember::DoAutoShow( ScDPResultMember* pRefMember ) if (bHasChild) pChildDimension->DoAutoShow( pRefMember ); // sorting is done at the dimension - BOOL bIsRoot = ( pParentLevel == NULL ); - if ( bIsRoot && pDataRoot ) + if ( IsRoot()&& pDataRoot ) { // use the row root member to sort columns // sub total count is always 1 @@ -1563,7 +1720,7 @@ void ScDPResultMember::DoAutoShow( ScDPResultMember* pRefMember ) } } -void ScDPResultMember::ResetResults( BOOL bRoot ) +void ScDPResultMember::ResetResults( BOOL /*bRoot*/ ) { if (pDataRoot) pDataRoot->ResetResults(); @@ -1571,8 +1728,8 @@ void ScDPResultMember::ResetResults( BOOL bRoot ) if (pChildDimension) pChildDimension->ResetResults(); - if (!bRoot) - bHasElements = FALSE; + // if (!bRoot) + // bHasElements = FALSE; } void ScDPResultMember::UpdateRunningTotals( const ScDPResultMember* pRefMember, long nMeasure, @@ -1581,13 +1738,12 @@ void ScDPResultMember::UpdateRunningTotals( const ScDPResultMember* pRefMember, // IsVisible() test is in ScDPResultDimension::FillDataResults // (not on data layout dimension) - BOOL bIsRoot = ( pParentLevel == NULL ); - rTotals.SetInColRoot( bIsRoot ); + rTotals.SetInColRoot( IsRoot() ); BOOL bHasChild = ( pChildDimension != NULL ); long nUserSubCount = GetSubTotalCount(); - if ( nUserSubCount || !bHasChild ) + //if ( nUserSubCount || !bHasChild ) { // Calculate at least automatic if no subtotals are selected, // show only own values if there's no child dimension (innermost). @@ -1606,7 +1762,7 @@ void ScDPResultMember::UpdateRunningTotals( const ScDPResultMember* pRefMember, if ( bHasChild && nUserSubCount > 1 ) { aSubState.nRowSubTotalFunc = nUserPos; - aSubState.eRowForce = lcl_GetForceFunc( pParentLevel, nUserPos ); + aSubState.eRowForce = lcl_GetForceFunc( /*pParentLevel*/GetParentLevel(), nUserPos ); } for ( long nSubCount=0; nSubCount<nSubSize; nSubCount++ ) @@ -1685,7 +1841,7 @@ BOOL ScDPDataMember::IsVisible() const return FALSE; } -BOOL ScDPDataMember::IsNamedItem( const ScDPItemData& r ) const +BOOL ScDPDataMember::IsNamedItem( /*const ScDPItemData& r*/SCROW r ) const { if (pResultMember) return pResultMember->IsNamedItem(r); @@ -1752,7 +1908,7 @@ void ScDPDataMember::UpdateValues( const vector<ScDPValueData>& aValues, const S } } -void ScDPDataMember::ProcessData( const vector<ScDPItemData>& aChildMembers, const vector<ScDPValueData>& aValues, +void ScDPDataMember::ProcessData( const vector< SCROW >& aChildMembers, const vector<ScDPValueData>& aValues, const ScDPSubTotalState& rSubState ) { if ( pResultData->IsLateInit() && !pChildDimension && pResultMember && pResultMember->GetChildDimension() ) @@ -2107,7 +2263,7 @@ void ScDPDataMember::UpdateRunningTotals( const ScDPResultMember* pRefMember, BOOL bHasChild = ( pRefChild != NULL ); long nUserSubCount = pRefMember->GetSubTotalCount(); - if ( nUserSubCount || !bHasChild ) + //if ( nUserSubCount || !bHasChild ) { // Calculate at least automatic if no subtotals are selected, // show only own values if there's no child dimension (innermost). @@ -2496,8 +2652,10 @@ private: BOOL bIncludeAll; BOOL bIsBase; long nGroupBase; - const ScDPItemData* pBaseData; - + // Wang Xu Ming -- 2009-8-6 + // DataPilot Migration - Cache&&Performance + SCROW nBaseDataId; + // End Comments public: ScDPGroupCompare( const ScDPResultData* pData, const ScDPInitState& rState, long nDimension ); ~ScDPGroupCompare() {} @@ -2510,12 +2668,12 @@ ScDPGroupCompare::ScDPGroupCompare( const ScDPResultData* pData, const ScDPInitS pResultData( pData ), rInitState( rState ), nDimSource( nDimension ), - pBaseData( NULL ) + nBaseDataId( -1 ) { bIsBase = pResultData->IsBaseForGroup( nDimSource ); nGroupBase = pResultData->GetGroupBase( nDimSource ); //! get together in one call? if ( nGroupBase >= 0 ) - pBaseData = rInitState.GetNameForIndex( nGroupBase ); + nBaseDataId = rInitState.GetNameIdForIndex( nGroupBase ); // if bIncludeAll is set, TestIncluded doesn't need to be called bIncludeAll = !( bIsBase || nGroupBase >= 0 ); @@ -2524,11 +2682,11 @@ ScDPGroupCompare::ScDPGroupCompare( const ScDPResultData* pData, const ScDPInitS BOOL ScDPGroupCompare::TestIncluded( const ScDPMember& rMember ) { BOOL bInclude = TRUE; - if ( pBaseData ) + if ( nBaseDataId >=0 ) { ScDPItemData aMemberData; rMember.FillItemData( aMemberData ); - bInclude = pResultData->IsInGroup( aMemberData, nDimSource, *pBaseData, nGroupBase ); + bInclude = pResultData->IsInGroup( aMemberData, nDimSource, nBaseDataId, nGroupBase ); } else if ( bIsBase ) { @@ -2538,7 +2696,8 @@ BOOL ScDPGroupCompare::TestIncluded( const ScDPMember& rMember ) rMember.FillItemData( aMemberData ); long nInitCount = rInitState.GetCount(); const long* pInitSource = rInitState.GetSource(); - const ScDPItemData* pInitNames = rInitState.GetNames(); + /*const ScDPItemData* pInitNames = rInitState.GetNames();*/ + const SCROW* pInitNames = rInitState.GetNameIds(); for (long nInitPos=0; nInitPos<nInitCount && bInclude; nInitPos++) if ( pResultData->GetGroupBase( pInitSource[nInitPos] ) == nDimSource ) { @@ -2556,7 +2715,8 @@ BOOL ScDPGroupCompare::TestIncluded( const ScDPMember& rMember ) rMember.FillItemData( aMemberData ); long nInitCount = rInitState.GetCount(); const long* pInitSource = rInitState.GetSource(); - const ScDPItemData* pInitNames = rInitState.GetNames(); + /*const ScDPItemData* pInitNames = rInitState.GetNames();*/ + const SCROW* pInitNames = rInitState.GetNameIds(); for (long nInitPos=0; nInitPos<nInitCount && bInclude; nInitPos++) if ( pResultData->GetGroupBase( pInitSource[nInitPos] ) == nGroupBase ) { @@ -2591,14 +2751,14 @@ ScDPResultDimension::~ScDPResultDimension() delete maMemberArray[i]; } -ScDPResultMember *ScDPResultDimension::FindMember( const ScDPItemData& rData ) const +ScDPResultMember *ScDPResultDimension::FindMember( SCROW iData ) const { if( bIsDataLayout ) return maMemberArray[0]; - MemberHash::const_iterator aRes = maMemberHash.find( rData ); + MemberHash::const_iterator aRes = maMemberHash.find( iData ); if( aRes != maMemberHash.end()) { - if ( aRes->second->IsNamedItem( rData ) ) + if ( aRes->second->IsNamedItem( iData ) ) return aRes->second; DBG_ERROR("problem! hash result is not the same as IsNamedItem"); } @@ -2609,14 +2769,14 @@ ScDPResultMember *ScDPResultDimension::FindMember( const ScDPItemData& rData ) c for( i = 0; i < nCount ; i++ ) { pResultMember = maMemberArray[i]; - if ( pResultMember->IsNamedItem( rData ) ) + if ( pResultMember->IsNamedItem( iData ) ) return pResultMember; } return NULL; } void ScDPResultDimension::InitFrom( const vector<ScDPDimension*>& ppDim, const vector<ScDPLevel*>& ppLev, - size_t nPos, ScDPInitState& rInitState ) + size_t nPos, ScDPInitState& rInitState, BOOL bInitChild /*= TRUE */ ) { if (nPos >= ppDim.size() || nPos >= ppLev.size()) { @@ -2671,46 +2831,41 @@ void ScDPResultDimension::InitFrom( const vector<ScDPDimension*>& ppDim, const v ScDPMember* pMember = pMembers->getByIndex(nSorted); if ( aCompare.IsIncluded( *pMember ) ) { - ScDPResultMember* pNew = new ScDPResultMember( pResultData, pThisDim, - pThisLevel, pMember, FALSE ); - maMemberArray.push_back( pNew ); + ScDPParentDimData aData( i, pThisDim, pThisLevel, pMember); + ScDPResultMember* pNew = AddMember( aData ); - ScDPItemData aMemberData; - pMember->FillItemData( aMemberData ); - - // honour order of maMemberArray and only insert if it does not - // already exist - if ( maMemberHash.end() == maMemberHash.find( aMemberData ) ) - maMemberHash.insert( std::pair< const ScDPItemData, ScDPResultMember *>( aMemberData, pNew ) ); - - rInitState.AddMember( nDimSource, aMemberData ); - pNew->InitFrom( ppDim, ppLev, nPos+1, rInitState ); + rInitState.AddMember( nDimSource, /*aMemberData*/pNew->GetDataId() ); + pNew->InitFrom( ppDim, ppLev, nPos+1, rInitState, bInitChild ); rInitState.RemoveMember(); } } bInitialized = TRUE; } -void ScDPResultDimension::LateInitFrom( const vector<ScDPDimension*>& ppDim, const vector<ScDPLevel*>& ppLev, - const vector<ScDPItemData>& pItemData, size_t nPos, +void ScDPResultDimension::LateInitFrom( LateInitParams& rParams/* const vector<ScDPDimension*>& ppDim, const vector<ScDPLevel*>& ppLev*/, + const vector<SCROW>& pItemData, size_t nPos, ScDPInitState& rInitState ) +// End Comments { - if (nPos >= ppDim.size() || nPos >= ppLev.size() || nPos >= pItemData.size()) + if ( rParams.IsEnd( nPos ) ) return; - - ScDPDimension* pThisDim = ppDim[nPos]; - ScDPLevel* pThisLevel = ppLev[nPos]; - const ScDPItemData& rThisData = pItemData[nPos]; +#ifdef DBG_UTIL + DBG_ASSERT( nPos <= pItemData.size(), ByteString::CreateFromInt32( pItemData.size()).GetBuffer() ); +#endif + ScDPDimension* pThisDim = rParams.GetDim( nPos ); + ScDPLevel* pThisLevel = rParams.GetLevel( nPos ); + SCROW rThisData = pItemData[nPos]; if (!pThisDim || !pThisLevel) return; long nDimSource = pThisDim->GetDimension(); //! check GetSourceDim? - if ( !bInitialized ) - { - // create all members at the first call (preserve order) + BOOL bShowEmpty = pThisLevel->getShowEmpty(); + if ( !bInitialized ) + { // init some values + // create all members at the first call (preserve order) bIsDataLayout = pThisDim->getIsDataLayoutDimension(); aDimensionName = pThisDim->getName(); @@ -2730,65 +2885,86 @@ void ScDPResultDimension::LateInitFrom( const vector<ScDPDimension*>& ppDim, con bSortAscending = rSortInfo.IsAscending; nSortMeasure = pThisLevel->GetSortMeasure(); } + } - // global order is used to initialize aMembers, so it doesn't have to be looked at later - const ScMemberSortOrder& rGlobalOrder = pThisLevel->GetGlobalOrder(); + bool bLateInitAllMembers= bIsDataLayout || rParams.GetInitAllChild() || bShowEmpty; - ScDPGroupCompare aCompare( pResultData, rInitState, nDimSource ); + if ( !bLateInitAllMembers ) + { + ResultMembers* pMembers = pResultData->GetDimResultMembers(nDimSource, pThisDim, pThisLevel); + bLateInitAllMembers = pMembers->IsHasHideDetailsMembers(); +#ifdef DBG_UTIL + DBG_TRACESTR( aDimensionName ) + if ( pMembers->IsHasHideDetailsMembers() ) + DBG_TRACE ( "HasHideDetailsMembers" ); +#endif + pMembers->SetHasHideDetailsMembers( FALSE ); + } - ScDPMembers* pMembers = pThisLevel->GetMembersObject(); - long nMembCount = pMembers->getCount(); - for ( long i=0; i<nMembCount; i++ ) - { - long nSorted = rGlobalOrder.empty() ? i : rGlobalOrder[i]; + bool bNewAllMembers =(!rParams.IsRow()) || nPos == 0 || bLateInitAllMembers ; - ScDPMember* pMember = pMembers->getByIndex(nSorted); - if ( aCompare.IsIncluded( *pMember ) ) + if (bNewAllMembers ) + { + // global order is used to initialize aMembers, so it doesn't have to be looked at later + if ( !bInitialized ) + { //init all members + const ScMemberSortOrder& rGlobalOrder = pThisLevel->GetGlobalOrder(); + + ScDPGroupCompare aCompare( pResultData, rInitState, nDimSource ); + ScDPMembers* pMembers = pThisLevel->GetMembersObject(); + long nMembCount = pMembers->getCount(); + for ( long i=0; i<nMembCount; i++ ) { - ScDPResultMember* pNew = new ScDPResultMember( pResultData, pThisDim, - pThisLevel, pMember, FALSE ); - maMemberArray.push_back( pNew ); + long nSorted = rGlobalOrder.empty() ? i : rGlobalOrder[i]; - ScDPItemData aMemberData; - pMember->FillItemData( aMemberData ); - - // honour order of maMemberArray and only insert if it does not - // already exist - if ( maMemberHash.end() == maMemberHash.find( aMemberData ) ) - maMemberHash.insert( std::pair< const ScDPItemData, ScDPResultMember *>( aMemberData, pNew ) ); + ScDPMember* pMember = pMembers->getByIndex(nSorted); + if ( aCompare.IsIncluded( *pMember ) ) + { // add all members + ScDPParentDimData aData( i, pThisDim, pThisLevel, pMember ); + AddMember( aData ); + } } + bInitialized = TRUE; // don't call again, even if no members were included } - bInitialized = TRUE; // don't call again, even if no members were included - } - // initialize only specific member (or all if "show empty" flag is set) - - BOOL bShowEmpty = pThisLevel->getShowEmpty(); - if ( bIsDataLayout || bShowEmpty ) - { - long nCount = maMemberArray.size(); - for (long i=0; i<nCount; i++) + if ( bLateInitAllMembers ) { - ScDPResultMember* pResultMember = maMemberArray[i]; - ScDPItemData aMemberData; - pResultMember->FillItemData( aMemberData ); - rInitState.AddMember( nDimSource, aMemberData ); - pResultMember->LateInitFrom( ppDim, ppLev, pItemData, nPos+1, rInitState ); - rInitState.RemoveMember(); + long nCount = maMemberArray.size(); + for (long i=0; i<nCount; i++) + { + ScDPResultMember* pResultMember = maMemberArray[i]; + + // check show empty + BOOL bAllChildren = FALSE; + if( bShowEmpty ) + { + if ( pResultMember->IsNamedItem( rThisData ) ) + bAllChildren = FALSE; + else + bAllChildren = TRUE; + } + rParams.SetInitAllChildren( bAllChildren ); + rInitState.AddMember( nDimSource, pResultMember->GetDataId() ); + pResultMember->LateInitFrom( rParams, pItemData, nPos+1, rInitState ); + rInitState.RemoveMember(); + } } - } - else - { - ScDPResultMember* pResultMember = FindMember( rThisData ); - if( NULL != pResultMember ) + else { - ScDPItemData aMemberData; - pResultMember->FillItemData( aMemberData ); - rInitState.AddMember( nDimSource, aMemberData ); - pResultMember->LateInitFrom( ppDim, ppLev, pItemData, nPos+1, rInitState ); - rInitState.RemoveMember(); + ScDPResultMember* pResultMember = FindMember( rThisData ); + if( NULL != pResultMember ) + { + //DBG_TRACE( "ScDPResultDimension::LateInitFrom"); + // DBG_TRACESTR( pResultMember->GetDPMember()->GetNameStr()); + + rInitState.AddMember( nDimSource, pResultMember->GetDataId() ); + pResultMember->LateInitFrom( rParams, pItemData, nPos+1, rInitState ); + rInitState.RemoveMember(); + } } } + else + InitWithMembers( rParams, pItemData, nPos, rInitState ); } long ScDPResultDimension::GetSize(long nMeasure) const @@ -2811,7 +2987,7 @@ long ScDPResultDimension::GetSize(long nMeasure) const return nTotal; } -bool ScDPResultDimension::IsValidEntry( const vector<ScDPItemData>& aMembers ) const +bool ScDPResultDimension::IsValidEntry( const vector< SCROW >& aMembers ) const { if (aMembers.empty()) return false; @@ -2819,14 +2995,18 @@ bool ScDPResultDimension::IsValidEntry( const vector<ScDPItemData>& aMembers ) c const ScDPResultMember* pMember = FindMember( aMembers[0] ); if ( NULL != pMember ) return pMember->IsValidEntry( aMembers ); - - DBG_ERROR("IsValidEntry: Member not found"); +#ifdef DBG_UTIL + ByteString strTemp ("IsValidEntry: Member not found, DimName = " ); + strTemp += ByteString( GetName(), RTL_TEXTENCODING_UTF8 ); + DBG_TRACE( strTemp.GetBuffer() ); + // DBG_ERROR("IsValidEntry: Member not found"); +#endif return false; } -void ScDPResultDimension::ProcessData( const vector<ScDPItemData>& aMembers, +void ScDPResultDimension::ProcessData( const vector< SCROW >& aMembers, const ScDPResultDimension* pDataDim, - const vector<ScDPItemData>& aDataMembers, + const vector< SCROW >& aDataMembers, const vector<ScDPValueData>& aValues ) const { if (aMembers.empty()) @@ -2835,11 +3015,11 @@ void ScDPResultDimension::ProcessData( const vector<ScDPItemData>& aMembers, ScDPResultMember* pMember = FindMember( aMembers[0] ); if ( NULL != pMember ) { - vector<ScDPItemData> aChildMembers; + vector</*ScDPItemData*/SCROW > aChildMembers; if (aMembers.size() > 1) { - vector<ScDPItemData>::const_iterator itr = aMembers.begin(); - aChildMembers.assign(++itr, aMembers.end()); + vector</*ScDPItemData*/SCROW >::const_iterator itr = aMembers.begin(); + aChildMembers.insert(aChildMembers.begin(), ++itr, aMembers.end()); } pMember->ProcessData( aChildMembers, pDataDim, aDataMembers, aValues ); return; @@ -3372,7 +3552,7 @@ void ScDPDataDimension::InitFrom( const ScDPResultDimension* pDim ) } } -void ScDPDataDimension::ProcessData( const vector<ScDPItemData>& aDataMembers, const vector<ScDPValueData>& aValues, +void ScDPDataDimension::ProcessData( const vector< SCROW >& aDataMembers, const vector<ScDPValueData>& aValues, const ScDPSubTotalState& rSubState ) { // the ScDPItemData array must contain enough entries for all dimensions - this isn't checked @@ -3385,11 +3565,11 @@ void ScDPDataDimension::ProcessData( const vector<ScDPItemData>& aDataMembers, c // always first member for data layout dim if ( bIsDataLayout || ( !aDataMembers.empty() && pMember->IsNamedItem(aDataMembers[0]) ) ) { - vector<ScDPItemData> aChildDataMembers; + vector</*ScDPItemData*/SCROW> aChildDataMembers; if (aDataMembers.size() > 1) { - vector<ScDPItemData>::const_iterator itr = aDataMembers.begin(); - aChildDataMembers.assign(++itr, aDataMembers.end()); + vector</*ScDPItemData*/SCROW >::const_iterator itr = aDataMembers.begin(); + aChildDataMembers.insert(aChildDataMembers.begin(), ++itr, aDataMembers.end()); } pMember->ProcessData( aChildDataMembers, aValues, rSubState ); return; @@ -3660,8 +3840,7 @@ ScDPDataMember* ScDPDataDimension::GetMember(long n) const // ---------------------------------------------------------------------------- ScDPResultVisibilityData::ScDPResultVisibilityData( - ScSimpleSharedString& rSharedString, ScDPSource* pSource) : - mrSharedString(rSharedString), + ScDPSource* pSource) : mpSource(pSource) { } @@ -3715,7 +3894,8 @@ void ScDPResultVisibilityData::fillFieldFilters(vector<ScDPCacheTable::Criterion long nDimIndex = itrField->second; aCri.mnFieldIndex = static_cast<sal_Int32>(nDimIndex); - aCri.mpFilter.reset(new ScDPCacheTable::GroupFilter(mrSharedString)); + aCri.mpFilter.reset(new ScDPCacheTable::GroupFilter(/*mrSharedString*/)); + ScDPCacheTable::GroupFilter* pGrpFilter = static_cast<ScDPCacheTable::GroupFilter*>(aCri.mpFilter.get()); @@ -3724,7 +3904,7 @@ void ScDPResultVisibilityData::fillFieldFilters(vector<ScDPCacheTable::Criterion itrMem != itrMemEnd; ++itrMem) { const ScDPItemData& rMemItem = *itrMem; - pGrpFilter->addMatchItem(rMemItem.aString, rMemItem.fValue, rMemItem.bHasValue); + pGrpFilter->addMatchItem(rMemItem.GetString(), rMemItem.GetValue(), rMemItem.IsValue()); } ScDPDimension* pDim = pDims->getByIndex(nDimIndex); @@ -3737,8 +3917,188 @@ void ScDPResultVisibilityData::fillFieldFilters(vector<ScDPCacheTable::Criterion size_t ScDPResultVisibilityData::MemberHash::operator() (const ScDPItemData& r) const { - if (r.bHasValue) - return static_cast<size_t>(::rtl::math::approxFloor(r.fValue)); + if (r.IsValue()) + return static_cast<size_t>(::rtl::math::approxFloor(r.GetValue())); else - return rtl_ustr_hashCode_WithLength(r.aString.GetBuffer(), r.aString.Len()); + return rtl_ustr_hashCode_WithLength(r.GetString().GetBuffer(), r.GetString().Len()); +} +// Wang Xu Ming -- 2009-6-10 +// DataPilot Migration +SCROW ScDPResultMember::GetDataId( ) const +{ + const ScDPMember* pMemberDesc = GetDPMember(); + if (pMemberDesc) + return pMemberDesc->GetItemDataId(); + return -1; +} + +ScDPResultMember* ScDPResultDimension::AddMember(const ScDPParentDimData &aData ) +{ + ScDPResultMember* pMember = new ScDPResultMember( pResultData, aData, FALSE ); + SCROW nDataIndex = pMember->GetDataId(); + maMemberArray.push_back( pMember ); + + if ( maMemberHash.end() == maMemberHash.find( nDataIndex ) ) + maMemberHash.insert( std::pair< SCROW, ScDPResultMember *>( nDataIndex, pMember ) ); + return pMember; +} + +ResultMembers* ScDPResultDimension::GetResultMember( ScDPDimension* pThisDim, ScDPLevel* pThisLevel ) +{ + ResultMembers* pResultMembers = new ResultMembers(); + // global order is used to initialize aMembers, so it doesn't have to be looked at later + const ScMemberSortOrder& rGlobalOrder = pThisLevel->GetGlobalOrder(); + + ScDPMembers* pMembers = pThisLevel->GetMembersObject(); + long nMembCount = pMembers->getCount(); + for ( long i=0; i<nMembCount; i++ ) + { + long nSorted = rGlobalOrder.empty() ? i : rGlobalOrder[i]; + ScDPMember* pMember = pMembers->getByIndex(nSorted); + if ( NULL == pResultMembers->FindMember( pMember->GetItemDataId() ) ) + { + ScDPParentDimData* pNew = new ScDPParentDimData( i, pThisDim, pThisLevel, pMember ); + pResultMembers->InsertMember( pNew ); + } + } + return pResultMembers; } + +ScDPResultMember* ScDPResultDimension::InsertMember(ScDPParentDimData *pMemberData) +{ + SCROW nInsert = 0; + if ( !lcl_SearchMember( maMemberArray, pMemberData->mnOrder , nInsert ) ) + { //Member not exist + ScDPResultMember* pNew = new ScDPResultMember( pResultData, *pMemberData, FALSE ); + maMemberArray.insert( maMemberArray.begin()+nInsert, pNew ); + + SCROW nDataIndex = pMemberData->mpMemberDesc->GetItemDataId(); + if ( maMemberHash.end() == maMemberHash.find( nDataIndex ) ) + maMemberHash.insert( std::pair< SCROW, ScDPResultMember *>( nDataIndex, pNew ) ); + return pNew; + } + return maMemberArray[ nInsert ]; +} + +void ScDPResultDimension:: InitWithMembers( LateInitParams& rParams, + const ::std::vector< SCROW >& pItemData, + size_t nPos, + ScDPInitState& rInitState ) +{ + if ( rParams.IsEnd( nPos ) ) + return; + ScDPDimension* pThisDim = rParams.GetDim( nPos ); + ScDPLevel* pThisLevel = rParams.GetLevel( nPos ); + SCROW nDataID = pItemData[nPos]; + + if (pThisDim && pThisLevel) + { + long nDimSource = pThisDim->GetDimension(); //! check GetSourceDim? + + // create all members at the first call (preserve order) + ResultMembers* pMembers = pResultData->GetDimResultMembers(nDimSource, pThisDim, pThisLevel); + ScDPGroupCompare aCompare( pResultData, rInitState, nDimSource ); + // initialize only specific member (or all if "show empty" flag is set) + ScDPResultMember* pResultMember = NULL; + if ( bInitialized ) + pResultMember = FindMember( nDataID ); + else + bInitialized = TRUE; + + if ( pResultMember == NULL ) + { //only insert found item + ScDPParentDimData* pMemberData = pMembers->FindMember( nDataID ); + if ( pMemberData && aCompare.IsIncluded( *( pMemberData->mpMemberDesc ) ) ) + pResultMember = InsertMember( pMemberData ); + } + if ( pResultMember ) + { + // DBG_TRACE( "ScDPResultDimension::InitWithMembers"); + // DBG_TRACESTR( pResultMember->GetDPMember()->GetNameStr()); + rInitState.AddMember( nDimSource, pResultMember->GetDataId() ); + pResultMember->LateInitFrom( rParams /*ppDim, ppLev*/, pItemData, nPos+1 , rInitState ); + rInitState.RemoveMember(); + } + } +} + +ScDPParentDimData* ResultMembers::FindMember( const SCROW& nIndex ) const +{ + DimMemberHash::const_iterator aRes = maMemberHash.find( nIndex ); + if( aRes != maMemberHash.end()) { + if ( aRes->second->mpMemberDesc && aRes->second->mpMemberDesc->GetItemDataId()==nIndex ) + return aRes->second; + } + return NULL; +} +void ResultMembers::InsertMember( ScDPParentDimData* pNew ) +{ + if ( !pNew->mpMemberDesc->getShowDetails() ) + mbHasHideDetailsMember = TRUE; + maMemberHash.insert( std::pair< const SCROW, ScDPParentDimData *>( pNew->mpMemberDesc->GetItemDataId(), pNew ) ); +} + +ResultMembers::ResultMembers(): + mbHasHideDetailsMember( FALSE ) +{ +} +ResultMembers::~ResultMembers() +{ + for ( DimMemberHash::const_iterator iter = maMemberHash.begin(); iter != maMemberHash.end(); iter++ ) + delete iter->second; +} +// ----------------------------------------------------------------------- +LateInitParams::LateInitParams( const vector<ScDPDimension*>& ppDim, const vector<ScDPLevel*>& ppLev, BOOL bRow, BOOL bInitChild, BOOL bAllChildren ): + mppDim( ppDim ), + mppLev( ppLev ), + mbRow( bRow ), + mbInitChild( bInitChild ), + mbAllChildren( bAllChildren ) +{ +} + +LateInitParams::~LateInitParams() +{ +} + +BOOL LateInitParams::IsEnd( size_t nPos ) const +{ + return nPos >= mppDim.size(); +} + +// End Comments +// Wang Xu Ming -- 2009-8-4 +// DataPilot Migration - old defects merge +void ScDPResultDimension::CheckShowEmpty( BOOL bShow ) +{ + long nCount = maMemberArray.size(); + + ScDPResultMember* pMember = NULL; + for (long i=0; i<nCount; i++) + { + pMember = maMemberArray.at(i); + pMember->CheckShowEmpty( bShow ); + } + +} + +void ScDPResultMember::CheckShowEmpty( BOOL bShow ) +{ + if ( bHasElements ) + { + ScDPResultDimension* pChildDim = GetChildDimension(); + if (pChildDim ) + pChildDim->CheckShowEmpty(); + } + else if ( IsValid() && bInitialized ) + { + bShow = bShow || ( GetParentLevel() && GetParentLevel()->getShowEmpty() ); + if ( bShow ) + { + SetHasElements(); + ScDPResultDimension* pChildDim = GetChildDimension(); + if (pChildDim ) + pChildDim->CheckShowEmpty( TRUE ); + } + } +}// End Comments diff --git a/sc/source/core/data/dptabresmember.cxx b/sc/source/core/data/dptabresmember.cxx new file mode 100644 index 000000000000..8c3b7b164bc3 --- /dev/null +++ b/sc/source/core/data/dptabresmember.cxx @@ -0,0 +1,831 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright IBM Corporation 2009. + * Copyright 2009 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: dptabresmember.cxx,v $ + * $Revision: 1.0 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#include "dptabresmember.hxx" +// ----------------------------------------------------------------------- +ScDPResultMember( const ScDPResultData* pData, const ScDPParentDimData& rParentDimData , + BOOL bForceSub ) : + pResultData( pData ), + aParentDimData( rParentDimData ), + /* pParentDim( pDim ), + pParentLevel( pLev ), + pMemberDesc( pDesc ),*/ + pChildDimension( NULL ), + pDataRoot( NULL ), + bHasElements( FALSE ), + bForceSubTotal( bForceSub ), + bHasHiddenDetails( FALSE ), + bInitialized( FALSE ), + nMemberStep( 1 ), + bAutoHidden( FALSE ) +{ + // pParentLevel/pMemberDesc is 0 for root members +} + +ScDPNormalResultMember::ScDPNormalResultMember( const ScDPResultData* pData, + BOOL bForceSub ) : + pResultData( pData ), + pChildDimension( NULL ), + pDataRoot( NULL ), + bHasElements( FALSE ), + bForceSubTotal( bForceSub ), + bHasHiddenDetails( FALSE ), + bInitialized( FALSE ), + nMemberStep( 1 ), + bAutoHidden( FALSE ) +{ +} + +ScDPNormalResultMember::~ScDPNormalResultMember() +{ + delete pChildDimension; + delete pDataRoot; +} + +String ScDPNormalResultMember::GetName() const +{ +// Wang Xu Ming -- 2009-6-10 +// DataPilot Migration + const ScDPMember* pMemberDesc = GetDPMember(); + // End Comments + if (pMemberDesc) + return pMemberDesc->GetNameStr(); + else + return ScGlobal::GetRscString(STR_PIVOT_TOTAL); // root member +} + +void ScDPNormalResultMember::FillItemData( ScDPItemData& rData ) const +{ +// Wang Xu Ming -- 2009-6-10 +// DataPilot Migration + const ScDPMember* pMemberDesc = GetDPMember(); +// End Comments + if (pMemberDesc) + pMemberDesc->FillItemData( rData ); + else + rData.SetString( ScGlobal::GetRscString(STR_PIVOT_TOTAL) ); // root member +} + +BOOL ScDPNormalResultMember::IsNamedItem( /*const ScDPItemData& r */SCROW nIndex ) const +{ + //! store ScDPMember pointer instead of ScDPMember ??? + const ScDPMember* pMemberDesc = GetDPMember(); + if (pMemberDesc) + return ((ScDPMember*)pMemberDesc)->IsNamedItem(/* r*/ nIndex ); + return FALSE; +} + +// Wang Xu Ming -- 2009-5-27 +// DataPilot Migration +bool ScDPNormalResultMember::IsValidEntry( const vector< SCROW >& aMembers ) const +{ + return GetEntryStatus( aMembers ) != ENTRY_INVALID; +} +// End Comments + +ENTRYSTATUS ScDPNormalResultMember::GetEntryStatus( const vector< SCROW >& aMembers ) const +{ + if ( !IsValid() ) + return ENTRY_INVALID; + + const ScDPResultDimension* pChildDim = GetChildDimension(); + if (pChildDim) + { + if (aMembers.size() < 2) + return ENTRY_INVALID; + + vector</*ScDPItemData*/SCROW>::const_iterator itr = aMembers.begin(); + vector</*ScDPItemData*/SCROW> aChildMembers(++itr, aMembers.end()); + return pChildDim->GetEntryStatus(aChildMembers); + } + else if( bHasHiddenDetails ) + return ENTRY_HASHIDDENDETAIL; + else + return ENTRY_VALID; +} + +void ScDPNormalResultMember::InitFrom( const vector<ScDPDimension*>& ppDim, const vector<ScDPLevel*>& ppLev, + size_t nPos, ScDPInitState& rInitState , + BOOL bInitChild /*= TRUE */) + { + // with LateInit, initialize only those members that have data + if ( pResultData->IsLateInit() ) + return; + + bInitialized = TRUE; + + if (nPos >= ppDim.size() ) + return; + + // skip child dimension if details are not shown + if ( GetDPMember() && !GetDPMember()->getShowDetails() ) + { + // Wang Xu Ming -- 2009-6-16 + // Show DataLayout dimention + nMemberStep = 1; + while ( nPos < ppDim.size() ) + { + if ( ppDim[nPos] ->getIsDataLayoutDimension() ) + { + if ( !pChildDimension ) + pChildDimension = new ScDPResultDimension( pResultData ); + pChildDimension->InitFrom( ppDim, ppLev, nPos, rInitState , FALSE ); + return; + } + else + { //find next dim + nPos ++; + nMemberStep ++; + } + } + // End Comments + bHasHiddenDetails = TRUE; // only if there is a next dimension + return; + } + + if ( bInitChild ) + { + pChildDimension = new ScDPResultDimension( pResultData ); + pChildDimension->InitFrom( ppDim, ppLev, nPos, rInitState, TRUE ); + } +} + +// Wang Xu Ming -- 2009-6-10 +// DataPilot Migration +void ScDPNormalResultMember::LateInitFrom( LateInitParams& rParams/*const vector<ScDPDimension*>& ppDim, const vector<ScDPLevel*>& ppLev*/, + const vector< SCROW >& pItemData, size_t nPos, + ScDPInitState& rInitState ) +// End Comments +{ + // without LateInit, everything has already been initialized + if ( !pResultData->IsLateInit() ) + return; + + bInitialized = TRUE; + + if ( rParams.IsEnd( nPos ) /*nPos >= ppDim.size()*/) + // No next dimension. Bail out. + return; + + // skip child dimension if details are not shown + if ( GetDPMember() && !GetDPMember()->getShowDetails() ) + { + // Wang Xu Ming -- 2009-6-16 + // DataPilot Migration + // Show DataLayout dimention + nMemberStep = 1; + while ( !rParams.IsEnd( nPos ) ) + { + if ( rParams.GetDim( nPos ) ->getIsDataLayoutDimension() ) + { + if ( !pChildDimension ) + pChildDimension = new ScDPResultDimension( pResultData ); + rParams.SetInitChild( FALSE ); + pChildDimension->LateInitFrom( rParams, pItemData, nPos, rInitState ); + return; + } + else + { //find next dim + nPos ++; + nMemberStep ++; + } + } + // End Comments + bHasHiddenDetails = TRUE; // only if there is a next dimension + return; + } + + // LateInitFrom is called several times... + if ( rParams.GetInitChild() ) + { + if ( !pChildDimension ) + pChildDimension = new ScDPResultDimension( pResultData ); + pChildDimension->LateInitFrom( rParams, pItemData, nPos, rInitState ); + } +} + +BOOL ScDPNormalResultMember::IsSubTotalInTitle(long nMeasure) const +{ + BOOL bRet = FALSE; + if ( pChildDimension && /*pParentLevel*/GetParentLevel() && + /*pParentLevel*/GetParentLevel()->IsOutlineLayout() && /*pParentLevel*/GetParentLevel()->IsSubtotalsAtTop() ) + { + long nUserSubStart; + long nSubTotals = GetSubTotalCount( &nUserSubStart ); + nSubTotals -= nUserSubStart; // visible count + if ( nSubTotals ) + { + if ( nMeasure == SC_DPMEASURE_ALL ) + nSubTotals *= pResultData->GetMeasureCount(); // number of subtotals that will be inserted + + // only a single subtotal row will be shown in the outline title row + if ( nSubTotals == 1 ) + bRet = TRUE; + } + } + return bRet; +} + +long ScDPNormalResultMember::GetSize(long nMeasure) const +{ + if ( !IsVisible() ) + return 0; + const ScDPLevel* pParentLevel = GetParentLevel(); + long nExtraSpace = 0; + if ( pParentLevel && pParentLevel->IsAddEmpty() ) + ++nExtraSpace; + + if ( pChildDimension ) + { + // outline layout takes up an extra row for the title only if subtotals aren't shown in that row + if ( pParentLevel && pParentLevel->IsOutlineLayout() && !IsSubTotalInTitle( nMeasure ) ) + ++nExtraSpace; + + long nSize = pChildDimension->GetSize(nMeasure); + long nUserSubStart; + long nUserSubCount = GetSubTotalCount( &nUserSubStart ); + nUserSubCount -= nUserSubStart; // for output size, use visible count + if ( nUserSubCount ) + { + if ( nMeasure == SC_DPMEASURE_ALL ) + nSize += pResultData->GetMeasureCount() * nUserSubCount; + else + nSize += nUserSubCount; + } + return nSize + nExtraSpace; + } + else + { + if ( nMeasure == SC_DPMEASURE_ALL ) + return pResultData->GetMeasureCount() + nExtraSpace; + else + return 1 + nExtraSpace; + } +} + + +BOOL ScDPNormalResultMember::IsVisible() const +{ + // not initialized -> shouldn't be there at all + // (allocated only to preserve ordering) + const ScDPLevel* pParentLevel = GetParentLevel(); + return ( bHasElements || ( pParentLevel && pParentLevel->getShowEmpty() ) ) && IsValid() && bInitialized; +} + +BOOL ScDPNormalResultMember::IsValid() const +{ + // non-Valid members are left out of calculation + + // was member set no invisible at the DataPilotSource? + const ScDPMember* pMemberDesc =GetDPMember(); + if ( pMemberDesc && !pMemberDesc->getIsVisible() ) + return FALSE; + + if ( bAutoHidden ) + return FALSE; + + return TRUE; +} + +BOOL ScDPNormalResultMember::HasHiddenDetails() const +{ + // bHasHiddenDetails is set only if the "show details" flag is off, + // and there was a child dimension to skip + + return bHasHiddenDetails; +} + +long ScDPNormalResultMember::GetSubTotalCount( long* pUserSubStart ) const +{ + if ( pUserSubStart ) + *pUserSubStart = 0; // default + + const ScDPLevel* pParentLevel = GetParentLevel(); + + if ( bForceSubTotal ) // set if needed for root members + return 1; // grand total is always "automatic" + else if ( pParentLevel ) + { + //! direct access via ScDPLevel + + uno::Sequence<sheet::GeneralFunction> aSeq = pParentLevel->getSubTotals(); + long nSequence = aSeq.getLength(); + if ( nSequence && aSeq[0] != sheet::GeneralFunction_AUTO ) + { + // For manual subtotals, always add "automatic" as first function + // (used for calculation, but not for display, needed for sorting, see lcl_GetForceFunc) + + ++nSequence; + if ( pUserSubStart ) + *pUserSubStart = 1; // visible subtotals start at 1 + } + return nSequence; + } + else + return 0; +} + +void ScDPNormalResultMember::ProcessData( const vector< SCROW >& aChildMembers, const ScDPResultDimension* pDataDim, + const vector< SCROW >& aDataMembers, const vector<ScDPValueData>& aValues ) +{ + SetHasElements(); + + if (pChildDimension) + pChildDimension->ProcessData( aChildMembers, pDataDim, aDataMembers, aValues ); + + if ( !pDataRoot ) + { + pDataRoot = new ScDPDataMember( pResultData, NULL ); + if ( pDataDim ) + pDataRoot->InitFrom( pDataDim ); // recursive + } + + ScDPSubTotalState aSubState; // initial state + + long nUserSubCount = GetSubTotalCount(); + + // Calculate at least automatic if no subtotals are selected, + // show only own values if there's no child dimension (innermost). + if ( !nUserSubCount || !pChildDimension ) + nUserSubCount = 1; + + const ScDPLevel* pParentLevel = GetParentLevel(); + + for (long nUserPos=0; nUserPos<nUserSubCount; nUserPos++) // including hidden "automatic" + { + // #i68338# if nUserSubCount is 1 (automatic only), don't set nRowSubTotalFunc + if ( pChildDimension && nUserSubCount > 1 ) + { + aSubState.nRowSubTotalFunc = nUserPos; + aSubState.eRowForce = lcl_GetForceFunc( pParentLevel, nUserPos ); + } + + pDataRoot->ProcessData( aDataMembers, aValues, aSubState ); + } +} + +void ScDPNormalResultMember::FillMemberResults( uno::Sequence<sheet::MemberResult>* pSequences, + long& rPos, long nMeasure, BOOL bRoot, + const String* pMemberName, + const String* pMemberCaption ) +{ + // IsVisible() test is in ScDPResultDimension::FillMemberResults + // (not on data layout dimension) + + long nSize = GetSize(nMeasure); + sheet::MemberResult* pArray = pSequences->getArray(); + DBG_ASSERT( rPos+nSize <= pSequences->getLength(), "bumm" ); + + BOOL bIsNumeric = FALSE; + String aName; + if ( pMemberName ) // if pMemberName != NULL, use instead of real member name + aName = *pMemberName; + else + { + ScDPItemData aItemData; + FillItemData( aItemData ); + aName = aItemData.GetString(); + bIsNumeric = aItemData.IsValue(); + } + const ScDPDimension* pParentDim = GetParentDim(); + if ( bIsNumeric && pParentDim && pResultData->IsNumOrDateGroup( pParentDim->GetDimension() ) ) + { + // Numeric group dimensions use numeric entries for proper sorting, + // but the group titles must be output as text. + bIsNumeric = FALSE; + } + + String aCaption = aName; + if ( pMemberCaption ) // use pMemberCaption if != NULL + aCaption = *pMemberCaption; + if (!aCaption.Len()) + aCaption = ScGlobal::GetRscString(STR_EMPTYDATA); + + if ( !bIsNumeric ) + { + // add a "'" character so a string isn't parsed as value in the output cell + //! have a separate bit in Flags (MemberResultFlags) instead? + aCaption.Insert( (sal_Unicode) '\'', 0 ); + } + + if ( nSize && !bRoot ) // root is overwritten by first dimension + { + pArray[rPos].Name = rtl::OUString(aName); + pArray[rPos].Caption = rtl::OUString(aCaption); + pArray[rPos].Flags |= sheet::MemberResultFlags::HASMEMBER; + + // set "continue" flag (removed for subtotals later) + for (long i=1; i<nSize; i++) + pArray[rPos+i].Flags |= sheet::MemberResultFlags::CONTINUE; + } + + const ScDPLevel* pParentLevel = GetParentLevel(); + long nExtraSpace = 0; + if ( pParentLevel && pParentLevel->IsAddEmpty() ) + ++nExtraSpace; + + BOOL bTitleLine = FALSE; + if ( pParentLevel && pParentLevel->IsOutlineLayout() ) + bTitleLine = TRUE; + + // if the subtotals are shown at the top (title row) in outline layout, + // no extra row for the subtotals is needed + BOOL bSubTotalInTitle = IsSubTotalInTitle( nMeasure ); + + BOOL bHasChild = ( pChildDimension != NULL ); + if (bHasChild) + { + if ( bTitleLine ) // in tabular layout the title is on a separate row + ++rPos; // -> fill child dimension one row below + + if (bRoot) // same sequence for root member + pChildDimension->FillMemberResults( pSequences, rPos, nMeasure ); + else + // Wang Xu Ming -- 2009-6-16 + // DataPilot Migration + // for show details + pChildDimension->FillMemberResults( pSequences + nMemberStep/*1*/, rPos, nMeasure ); + // End Comments + + if ( bTitleLine ) // title row is included in GetSize, so the following + --rPos; // positions are calculated with the normal values + } + + rPos += nSize; + + long nUserSubStart; + long nUserSubCount = GetSubTotalCount(&nUserSubStart); + if ( nUserSubCount && pChildDimension && !bSubTotalInTitle ) + { + long nMemberMeasure = nMeasure; + long nSubSize = pResultData->GetCountForMeasure(nMeasure); + + rPos -= nSubSize * (nUserSubCount - nUserSubStart); // GetSize includes space for SubTotal + rPos -= nExtraSpace; // GetSize includes the empty line + + for (long nUserPos=nUserSubStart; nUserPos<nUserSubCount; nUserPos++) + { + for ( long nSubCount=0; nSubCount<nSubSize; nSubCount++ ) + { + if ( nMeasure == SC_DPMEASURE_ALL ) + nMemberMeasure = nSubCount; + + ScSubTotalFunc eForce = SUBTOTAL_FUNC_NONE; + if (bHasChild) + eForce = lcl_GetForceFunc( pParentLevel, nUserPos ); + + String aSubStr = aName; //! caption? + aSubStr += ' '; + aSubStr += pResultData->GetMeasureString(nMemberMeasure, FALSE, eForce); + + pArray[rPos].Name = rtl::OUString(aName); + pArray[rPos].Caption = rtl::OUString(aSubStr); + pArray[rPos].Flags = ( pArray[rPos].Flags | + ( sheet::MemberResultFlags::HASMEMBER | sheet::MemberResultFlags::SUBTOTAL) ) & + ~sheet::MemberResultFlags::CONTINUE; + + if ( nMeasure == SC_DPMEASURE_ALL ) + { + // data layout dimension is (direct/indirect) child of this. + // data layout dimension must have name for all entries. + + uno::Sequence<sheet::MemberResult>* pLayoutSeq = pSequences; + if (!bRoot) + ++pLayoutSeq; + ScDPResultDimension* pLayoutDim = pChildDimension; + while ( pLayoutDim && !pLayoutDim->IsDataLayout() ) + { + pLayoutDim = pLayoutDim->GetFirstChildDimension(); + ++pLayoutSeq; + } + if ( pLayoutDim ) + { + sheet::MemberResult* pLayoutArray = pLayoutSeq->getArray(); + String aDataName = pResultData->GetMeasureDimensionName(nMemberMeasure); + pLayoutArray[rPos].Name = rtl::OUString(aDataName); + } + } + + rPos += 1; + } + } + + rPos += nExtraSpace; // add again (subtracted above) + } +} + +void ScDPNormalResultMember::FillDataResults( const ScDPResultMember* pRefMember, + uno::Sequence< uno::Sequence<sheet::DataResult> >& rSequence, + long& rRow, long nMeasure ) const +{ + // IsVisible() test is in ScDPResultDimension::FillDataResults + // (not on data layout dimension) + const ScDPLevel* pParentLevel = GetParentLevel(); + long nStartRow = rRow; + + long nExtraSpace = 0; + if ( pParentLevel && pParentLevel->IsAddEmpty() ) + ++nExtraSpace; + + BOOL bTitleLine = FALSE; + if ( pParentLevel && pParentLevel->IsOutlineLayout() ) + bTitleLine = TRUE; + + BOOL bSubTotalInTitle = IsSubTotalInTitle( nMeasure ); + + BOOL bHasChild = ( pChildDimension != NULL ); + if (bHasChild) + { + if ( bTitleLine ) // in tabular layout the title is on a separate row + ++rRow; // -> fill child dimension one row below + + pChildDimension->FillDataResults( pRefMember, rSequence, rRow, nMeasure ); // doesn't modify rRow + rRow += (USHORT) GetSize( nMeasure ); + + if ( bTitleLine ) // title row is included in GetSize, so the following + --rRow; // positions are calculated with the normal values + } + + long nUserSubStart; + long nUserSubCount = GetSubTotalCount(&nUserSubStart); + if ( nUserSubCount || !bHasChild ) + { + // Calculate at least automatic if no subtotals are selected, + // show only own values if there's no child dimension (innermost). + if ( !nUserSubCount || !bHasChild ) + { + nUserSubCount = 1; + nUserSubStart = 0; + } + + long nMemberMeasure = nMeasure; + long nSubSize = pResultData->GetCountForMeasure(nMeasure); + if (bHasChild) + { + rRow -= nSubSize * ( nUserSubCount - nUserSubStart ); // GetSize includes space for SubTotal + rRow -= nExtraSpace; // GetSize includes the empty line + } + + long nMoveSubTotal = 0; + if ( bSubTotalInTitle ) + { + nMoveSubTotal = rRow - nStartRow; // force to first (title) row + rRow = nStartRow; + } + + if ( pDataRoot ) + { + ScDPSubTotalState aSubState; // initial state + + for (long nUserPos=nUserSubStart; nUserPos<nUserSubCount; nUserPos++) + { + if ( bHasChild && nUserSubCount > 1 ) + { + aSubState.nRowSubTotalFunc = nUserPos; + aSubState.eRowForce = lcl_GetForceFunc( /*pParentLevel*/GetParentLevel() , nUserPos ); + } + + for ( long nSubCount=0; nSubCount<nSubSize; nSubCount++ ) + { + if ( nMeasure == SC_DPMEASURE_ALL ) + nMemberMeasure = nSubCount; + else if ( pResultData->GetColStartMeasure() == SC_DPMEASURE_ALL ) + nMemberMeasure = SC_DPMEASURE_ALL; + + DBG_ASSERT( rRow < rSequence.getLength(), "bumm" ); + uno::Sequence<sheet::DataResult>& rSubSeq = rSequence.getArray()[rRow]; + long nSeqCol = 0; + pDataRoot->FillDataRow( pRefMember, rSubSeq, nSeqCol, nMemberMeasure, bHasChild, aSubState ); + + rRow += 1; + } + } + } + else + rRow += nSubSize * ( nUserSubCount - nUserSubStart ); // empty rows occur when ShowEmpty is true + + // add extra space again if subtracted from GetSize above, + // add to own size if no children + rRow += nExtraSpace; + + rRow += nMoveSubTotal; + } +} + +void ScDPNormalResultMember::UpdateDataResults( const ScDPResultMember* pRefMember, long nMeasure ) const +{ + // IsVisible() test is in ScDPResultDimension::FillDataResults + // (not on data layout dimension) + + BOOL bHasChild = ( pChildDimension != NULL ); + + long nUserSubCount = GetSubTotalCount(); + // process subtotals even if not shown +// if ( nUserSubCount || !bHasChild ) + { + // Calculate at least automatic if no subtotals are selected, + // show only own values if there's no child dimension (innermost). + if ( !nUserSubCount || !bHasChild ) + nUserSubCount = 1; + + long nMemberMeasure = nMeasure; + long nSubSize = pResultData->GetCountForMeasure(nMeasure); + + if ( pDataRoot ) + { + ScDPSubTotalState aSubState; // initial state + + for (long nUserPos=0; nUserPos<nUserSubCount; nUserPos++) // including hidden "automatic" + { + if ( bHasChild && nUserSubCount > 1 ) + { + aSubState.nRowSubTotalFunc = nUserPos; + aSubState.eRowForce = lcl_GetForceFunc( /*pParentLevel*/GetParentLevel() , nUserPos ); + } + + for ( long nSubCount=0; nSubCount<nSubSize; nSubCount++ ) + { + if ( nMeasure == SC_DPMEASURE_ALL ) + nMemberMeasure = nSubCount; + else if ( pResultData->GetColStartMeasure() == SC_DPMEASURE_ALL ) + nMemberMeasure = SC_DPMEASURE_ALL; + + pDataRoot->UpdateDataRow( pRefMember, nMemberMeasure, bHasChild, aSubState ); + } + } + } + } + + if (bHasChild) // child dimension must be processed last, so the column total is known + { + pChildDimension->UpdateDataResults( pRefMember, nMeasure ); + } +} + +void ScDPNormalResultMember::SortMembers( ScDPResultMember* pRefMember ) +{ + BOOL bHasChild = ( pChildDimension != NULL ); + if (bHasChild) + pChildDimension->SortMembers( pRefMember ); // sorting is done at the dimension + + if ( IsRoot() && pDataRoot ) + { + // use the row root member to sort columns + // sub total count is always 1 + + pDataRoot->SortMembers( pRefMember ); + } +} + +void ScDPNormalResultMember::DoAutoShow( ScDPResultMember* pRefMember ) +{ + BOOL bHasChild = ( pChildDimension != NULL ); + if (bHasChild) + pChildDimension->DoAutoShow( pRefMember ); // sorting is done at the dimension + + if ( IsRoot()&& pDataRoot ) + { + // use the row root member to sort columns + // sub total count is always 1 + + pDataRoot->DoAutoShow( pRefMember ); + } +} + +void ScDPNormalResultMember::ResetResults( BOOL bRoot ) +{ + if (pDataRoot) + pDataRoot->ResetResults(); + + if (pChildDimension) + pChildDimension->ResetResults(); + +// Wang Xu Ming -- 3/4/2009 +// Dim refresh and filter. SODC_19023 + // if (!bRoot) + // bHasElements = FALSE; +// End Comments +} + +void ScDPNormalResultMember::UpdateRunningTotals( const ScDPResultMember* pRefMember, long nMeasure, + ScDPRunningTotalState& rRunning, ScDPRowTotals& rTotals ) const +{ + // IsVisible() test is in ScDPResultDimension::FillDataResults + // (not on data layout dimension) + + rTotals.SetInColRoot( IsRoot() ); + + BOOL bHasChild = ( pChildDimension != NULL ); + + long nUserSubCount = GetSubTotalCount(); + if ( nUserSubCount || !bHasChild ) + { + // Calculate at least automatic if no subtotals are selected, + // show only own values if there's no child dimension (innermost). + if ( !nUserSubCount || !bHasChild ) + nUserSubCount = 1; + + long nMemberMeasure = nMeasure; + long nSubSize = pResultData->GetCountForMeasure(nMeasure); + + if ( pDataRoot ) + { + ScDPSubTotalState aSubState; // initial state + + for (long nUserPos=0; nUserPos<nUserSubCount; nUserPos++) // including hidden "automatic" + { + if ( bHasChild && nUserSubCount > 1 ) + { + aSubState.nRowSubTotalFunc = nUserPos; + aSubState.eRowForce = lcl_GetForceFunc( /*pParentLevel*/GetParentLevel(), nUserPos ); + } + + for ( long nSubCount=0; nSubCount<nSubSize; nSubCount++ ) + { + if ( nMeasure == SC_DPMEASURE_ALL ) + nMemberMeasure = nSubCount; + else if ( pResultData->GetColStartMeasure() == SC_DPMEASURE_ALL ) + nMemberMeasure = SC_DPMEASURE_ALL; + + pDataRoot->UpdateRunningTotals( pRefMember, nMemberMeasure, + bHasChild, aSubState, rRunning, rTotals, *this ); + } + } + } + } + + if (bHasChild) // child dimension must be processed last, so the column total is known + { + pChildDimension->UpdateRunningTotals( pRefMember, nMeasure, rRunning, rTotals ); + } +} + +void ScDPNormalResultMember::DumpState( const ScDPResultMember* pRefMember, ScDocument* pDoc, ScAddress& rPos ) const +{ + lcl_DumpRow( String::CreateFromAscii("ScDPResultMember"), GetName(), NULL, pDoc, rPos ); + SCROW nStartRow = rPos.Row(); + + if (pDataRoot) + pDataRoot->DumpState( pRefMember, pDoc, rPos ); + + if (pChildDimension) + pChildDimension->DumpState( pRefMember, pDoc, rPos ); + + lcl_Indent( pDoc, nStartRow, rPos ); +} + +ScDPAggData* ScDPNormalResultMember::GetColTotal( long nMeasure ) const +{ + return lcl_GetChildTotal( const_cast<ScDPAggData*>(&aColTotal), nMeasure ); +} + +void ScDPNormalResultMember::FillVisibilityData(ScDPResultVisibilityData& rData) const +{ + if (pChildDimension) + pChildDimension->FillVisibilityData(rData); +} +// Wang Xu Ming -- 2009-6-10 +// DataPilot Migration +SCROW ScDPNormalResultMember::GetDataId( ) const +{ +// TODO: + const ScDPMember* pMemberDesc = GetDPMember(); + if (pMemberDesc) + return pMemberDesc->GetItemDataId(); + return -1; +} + +// ----------------------------------------------------------------------- +ScDPHideDetailsMember:: ScDPHideDetailsMember( const ScDPResultData* pData, const ScDPParentDimData& rParentDimData, + BOOL bForceSub ):ScDPResultMember(pData,rParentDimData, bForceSub) +{ + pOrigMember = new ScDPNormalResultMember(pData,rParentDimData, bForceSub); + +}
\ No newline at end of file diff --git a/sc/source/core/data/dptabresmember.hxx b/sc/source/core/data/dptabresmember.hxx new file mode 100644 index 000000000000..72657167d07d --- /dev/null +++ b/sc/source/core/data/dptabresmember.hxx @@ -0,0 +1,161 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright IBM Corporation 2009. + * Copyright 2009 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: dptabresmember.hxx,v $ + * $Revision: 1.0 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef DPTABRESMEMBER_HXX +#define DPTABRESMEMBER_HXX + +class ScDPNormalResultMember: public ScDPResultMember +{ +private: + // Wang Xu Ming -- 2009-6-9 + // DataPilot Migration + ScDPParentDimData aParentDimData; + // End Comments + BOOL bHasElements:1; + BOOL bForceSubTotal:1; + BOOL bHasHiddenDetails:1; + BOOL bInitialized:1; + BOOL bAutoHidden:1; + ScDPAggData aColTotal; // to store column totals + +// Wang Xu Ming -- 2009-6-9 +// DataPilot Migration + USHORT nMemberStep; // step to show details +// End Comments +public: + // Wang Xu Ming -- 2009-6-9 + // DataPilot Migration + ScDPNormalResultMember( const ScDPResultData* pData, const ScDPParentDimData& rParentDimData, + BOOL bForceSub ); //! Ref + ScDPNormalResultMember( const ScDPResultData* pData, BOOL bForceSub ); + // End Comments + ~ScDPNormalResultMember(); + + // Wang Xu Ming -- 2009-6-9 + // DataPilot Migration + // Add parameter: BOOL bInitChild + void InitFrom( const ::std::vector<ScDPDimension*>& ppDim, + const ::std::vector<ScDPLevel*>& ppLev, + size_t nPos, + ScDPInitState& rInitState, + BOOL bInitChild = TRUE ); + // End Comments + // Wang Xu Ming -- 2009-6-9 + // DataPilot Migration + void LateInitFrom( + LateInitParams& rParams, + const ::std::vector< SCROW >& pItemData, + size_t nPos, + ScDPInitState& rInitState); + // End Comments + + String GetName() const; + void FillItemData( ScDPItemData& rData ) const; + BOOL IsValid() const; + BOOL IsVisible() const; + long GetSize(long nMeasure) const; + BOOL HasHiddenDetails() const; + BOOL IsSubTotalInTitle(long nMeasure) const; + +// BOOL SubTotalEnabled() const; + long GetSubTotalCount( long* pUserSubStart = NULL ) const; + +// Wang Xu Ming -- 2009-6-9 +// DataPilot Migration +// Use item index +// BOOL IsNamedItem( const ScDPItemData& r ) const; + BOOL IsNamedItem( SCROW nIndex ) const; +// End Comments + bool IsValidEntry( const ::std::vector< SCROW >& aMembers ) const; + ENTRYSTATUS GetEntryStatus( const ::std::vector<SCROW>& aMembers ) const; + + void SetHasElements() { bHasElements = TRUE; } + void SetAutoHidden() { bAutoHidden = TRUE; } + + void ProcessData( const ::std::vector<SCROW>& aChildMembers, + const ScDPResultDimension* pDataDim, + const ::std::vector<SCROW>& aDataMembers, + const ::std::vector<ScDPValueData>& aValues ); + + void FillMemberResults( com::sun::star::uno::Sequence< + com::sun::star::sheet::MemberResult>* pSequences, + long& rPos, long nMeasure, BOOL bRoot, + const String* pMemberName, + const String* pMemberCaption ); + + void FillDataResults( const ScDPResultMember* pRefMember, + com::sun::star::uno::Sequence< + com::sun::star::uno::Sequence< + com::sun::star::sheet::DataResult> >& rSequence, + long& rRow, long nMeasure ) const; + + void UpdateDataResults( const ScDPResultMember* pRefMember, long nMeasure ) const; + void UpdateRunningTotals( const ScDPResultMember* pRefMember, long nMeasure, + ScDPRunningTotalState& rRunning, ScDPRowTotals& rTotals ) const; + + void SortMembers( ScDPResultMember* pRefMember ); + void DoAutoShow( ScDPResultMember* pRefMember ); + + void ResetResults( BOOL bRoot ); + + void DumpState( const ScDPResultMember* pRefMember, ScDocument* pDoc, ScAddress& rPos ) const; + + // Wang Xu Ming -- 2009-6-9 + // DataPilot Migration + const ScDPDimension* GetParentDim() const { return aParentDimData.mpParentDim; } //! Ref + const ScDPLevel* GetParentLevel() const { return aParentDimData.mpParentLevel; } //! Ref + const ScDPMember* GetDPMember()const { return aParentDimData.mpMemberDesc; } //! Ref + inline SCROW GetOrder() const { return aParentDimData.mnOrder; } //! Ref + inline BOOL IsRoot() const { return GetParentLevel() == NULL; } + // End Comments + + ScDPAggData* GetColTotal( long nMeasure ) const; + + void FillVisibilityData(ScDPResultVisibilityData& rData) const; +// Wang Xu Ming -- 2009-6-10 +// DataPilot Migration + SCROW GetDataId( ) const ; +// End Comments +}; + +class ScDPHideDetailsMember: public ScDPResultMember +{ +private: + ScDPNormalResultMember * pOrigMember; +public: + ScDPHideDetailsMember( const ScDPResultData* pData, const ScDPParentDimData& rParentDimData, + BOOL bForceSub ); + + +}; + + +#endif //DPTABRESMEMBER_HXX diff --git a/sc/source/core/data/dptabsrc.cxx b/sc/source/core/data/dptabsrc.cxx index 205c14021444..da40e6e230c4 100644..100755 --- a/sc/source/core/data/dptabsrc.cxx +++ b/sc/source/core/data/dptabsrc.cxx @@ -300,10 +300,11 @@ void ScDPSource::SetOrientation(long nColumn, USHORT nNew) case sheet::DataPilotFieldOrientation_PAGE: nPageDims[nPageDimCount++] = nColumn; break; + // Wang Xu Ming -- 2009-9-1 + // DataPilot Migration - Cache&&Performance case sheet::DataPilotFieldOrientation_HIDDEN: - /* Do not assert HIDDEN as it occurs e.g. while using the - csss.XDataPilotTables.createDataPilotDescriptor() function. */ break; + // End Comments default: DBG_ERROR( "ScDPSource::SetOrientation: unexpected orientation" ); break; @@ -325,6 +326,11 @@ BOOL ScDPSource::IsDateDimension(long nDim) return pData->IsDateDimension(nDim); } +UINT32 ScDPSource::GetNumberFormat(long nDim) +{ + return pData->GetNumberFormat( nDim ); +} + ScDPDimensions* ScDPSource::GetDimensionsObject() { if (!pDimensions) @@ -442,7 +448,6 @@ 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; @@ -472,17 +477,16 @@ 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 = rSharedString.getStringId(aItem.aString); aFilterCriteria.back().mnFieldIndex = nCol; aFilterCriteria.back().mpFilter.reset( - new ScDPCacheTable::SingleFilter(rSharedString, nMatchStrId, aItem.fValue, aItem.bHasValue) ); + new ScDPCacheTable::SingleFilter(aItem.GetString()/*rSharedString, nMatchStrId*/, aItem.GetValue(), aItem.IsValue()) ); } } } } // Take into account the visibilities of field members. - ScDPResultVisibilityData aResVisData(rSharedString, this); + ScDPResultVisibilityData aResVisData(/*rSharedString, */this); pRowResRoot->FillVisibilityData(aResVisData); pColResRoot->FillVisibilityData(aResVisData); aResVisData.fillFieldFilters(aFilterCriteria); @@ -737,7 +741,6 @@ void ScDPSource::GetCategoryDimensionIndices(hash_set<sal_Int32>& rCatDims) void ScDPSource::FilterCacheTableByPageDimensions() { - ScSimpleSharedString& rSharedString = GetData()->GetSharedString(); // filter table by page dimensions. vector<ScDPCacheTable::Criterion> aCriteria; @@ -752,7 +755,7 @@ void ScDPSource::FilterCacheTableByPageDimensions() long nMemCount = pMems->getCount(); ScDPCacheTable::Criterion aFilter; aFilter.mnFieldIndex = static_cast<sal_Int32>(nField); - aFilter.mpFilter.reset(new ScDPCacheTable::GroupFilter(rSharedString)); + aFilter.mpFilter.reset(new ScDPCacheTable::GroupFilter(/*rSharedString*/)); ScDPCacheTable::GroupFilter* pGrpFilter = static_cast<ScDPCacheTable::GroupFilter*>(aFilter.mpFilter.get()); for (long j = 0; j < nMemCount; ++j) @@ -762,7 +765,7 @@ void ScDPSource::FilterCacheTableByPageDimensions() { ScDPItemData aData; pMem->FillItemData(aData); - pGrpFilter->addMatchItem(aData.aString, aData.fValue, aData.bHasValue); + pGrpFilter->addMatchItem(aData.GetString(), aData.GetValue(), aData.IsValue()); } } if (pGrpFilter->getMatchItemCount() < static_cast<size_t>(nMemCount)) @@ -776,9 +779,8 @@ void ScDPSource::FilterCacheTableByPageDimensions() aCriteria.push_back(ScDPCacheTable::Criterion()); ScDPCacheTable::Criterion& r = aCriteria.back(); r.mnFieldIndex = static_cast<sal_Int32>(nField); - sal_Int32 nStrId = rSharedString.getStringId(rData.aString); r.mpFilter.reset( - new ScDPCacheTable::SingleFilter(rSharedString, nStrId, rData.fValue, rData.bHasValue)); + new ScDPCacheTable::SingleFilter(rData.GetString()/*rSharedString, nStrId*/, rData.GetValue(), rData.IsValue())); } if (!aCriteria.empty()) { @@ -900,11 +902,11 @@ void ScDPSource::CreateRes_Impl() { ScDPDimension* pDim = GetDimensionsObject()->getByIndex( nPageDims[i] ); if ( pDim->HasSelectedPage() ) - aInitState.AddMember( nPageDims[i], pDim->GetSelectedData() ); + aInitState.AddMember( nPageDims[i], GetMemberId( nPageDims[i], pDim->GetSelectedData() ) ); } - pColResRoot = new ScDPResultMember( pResData, NULL, NULL, NULL, bColumnGrand ); - pRowResRoot = new ScDPResultMember( pResData, NULL, NULL, NULL, bRowGrand ); + pColResRoot = new ScDPResultMember( pResData, /*NULL, NULL, NULL, */bColumnGrand ); + pRowResRoot = new ScDPResultMember( pResData, /*NULL, NULL, NULL, */bRowGrand ); FillCalcInfo(false, aInfo, bHasAutoShow); long nColLevelCount = aInfo.aColLevels.size(); @@ -944,7 +946,7 @@ void ScDPSource::CreateRes_Impl() long nMinColMembers = lcl_CountMinMembers( aInfo.aColDims, aInfo.aColLevels, nColLevelCount ); long nMinRowMembers = lcl_CountMinMembers( aInfo.aRowDims, aInfo.aRowLevels, nRowLevelCount ); - if ( nMinColMembers > SC_MINCOUNT_LIMIT || nMinRowMembers > SC_MINCOUNT_LIMIT ) + if ( nMinColMembers > MAXCOLCOUNT/*SC_MINCOUNT_LIMIT*/ || nMinRowMembers > SC_MINCOUNT_LIMIT ) { // resulting table is too big -> abort before calculating // (this relies on late init, so no members are allocated in InitFrom above) @@ -964,6 +966,8 @@ void ScDPSource::CreateRes_Impl() aInfo.pRowRoot = pRowResRoot; pData->CalcResults(aInfo, false); + pColResRoot->CheckShowEmpty(); + pRowResRoot->CheckShowEmpty(); // ---------------------------------------------------------------- // With all data processed, calculate the final results: @@ -1549,6 +1553,19 @@ const ScDPItemData& ScDPDimension::GetSelectedData() //UNUSED2009-05 return TRUE; // no selection -> all data //UNUSED2009-05 } +BOOL ScDPDimension::IsVisible( const ScDPItemData& rData ) +{ + if( ScDPMembers* pMembers = this->GetHierarchiesObject()->getByIndex(0)-> + GetLevelsObject()->getByIndex(0)->GetMembersObject() ) + { + for( long i = pMembers->getCount()-1; i>=0; i-- ) + if( ScDPMember *pDPMbr = pMembers->getByIndex( i ) ) + if( rData.IsCaseInsEqual( pDPMbr->GetItemData() ) && !pDPMbr->getIsVisible() ) + return FALSE; + } + + return TRUE; +} // XPropertySet uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDPDimension::getPropertySetInfo() @@ -1692,6 +1709,23 @@ uno::Any SAL_CALL ScDPDimension::getPropertyValue( const rtl::OUString& aPropert // #i63745# don't use source format for "count" if ( eFunc != sheet::GeneralFunction_COUNT && eFunc != sheet::GeneralFunction_COUNTNUMS ) nFormat = pSource->GetData()->GetNumberFormat( ( nSourceDim >= 0 ) ? nSourceDim : nDim ); + + switch ( aReferenceValue.ReferenceType ) + { + case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE: + case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE: + case sheet::DataPilotFieldReferenceType::ROW_PERCENTAGE: + case sheet::DataPilotFieldReferenceType::COLUMN_PERCENTAGE: + case sheet::DataPilotFieldReferenceType::TOTAL_PERCENTAGE: + nFormat = pSource->GetData()->GetNumberFormatByIdx( (NfIndexTableOffset)NF_PERCENT_DEC2 ); + break; + case sheet::DataPilotFieldReferenceType::INDEX: + nFormat = pSource->GetData()->GetNumberFormatByIdx( (NfIndexTableOffset)NF_NUMBER_SYSTEM ); + break; + default: + break; + } + aRet <<= nFormat; } else if ( aNameStr.EqualsAscii( SC_UNO_ORIGINAL ) ) @@ -2355,15 +2389,6 @@ SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDPLevel ) // ----------------------------------------------------------------------- -USHORT lcl_GetFirstStringPos( const TypedScStrCollection& rColl ) -{ - USHORT nPos = 0; - USHORT nCount = rColl.GetCount(); - while ( nPos < nCount && !rColl[nPos]->IsStrData() ) - ++nPos; - return nPos; -} - ScDPMembers::ScDPMembers( ScDPSource* pSrc, long nD, long nH, long nL ) : pSource( pSrc ), nDim( nD ), @@ -2385,12 +2410,23 @@ ScDPMembers::ScDPMembers( ScDPSource* pSrc, long nD, long nH, long nL ) : { case SC_DAPI_LEVEL_YEAR: { - const TypedScStrCollection& rStrings = pSource->GetData()->GetColumnEntries(nSrcDim); - USHORT nFirstString = lcl_GetFirstStringPos( rStrings ); - if ( nFirstString > 0 ) + // Wang Xu Ming - DataPilot migration + const ScDPItemData* pLastNumData = NULL; + for ( SCROW n = 0 ;n <GetSrcItemsCount() ; n-- ) { - double fFirstVal = rStrings[0]->GetValue(); - double fLastVal = rStrings[nFirstString-1]->GetValue(); + const ScDPItemData* pData = GetSrcItemDataByIndex( n ); + if ( pData && pData->HasStringData() ) + break; + else + pLastNumData = pData; + } + // End Comments + + if ( pLastNumData ) + { + const ScDPItemData* pFirstData = GetSrcItemDataByIndex( 0 ); + double fFirstVal = pFirstData->GetValue(); + double fLastVal = pLastNumData->GetValue(); long nFirstYear = pSource->GetData()->GetDatePart( (long)::rtl::math::approxFloor( fFirstVal ), @@ -2427,11 +2463,7 @@ ScDPMembers::ScDPMembers( ScDPSource* pSrc, long nD, long nH, long nL ) : } } else - { - // StringCollection is cached at TableData - const TypedScStrCollection& rStrings = pSource->GetData()->GetColumnEntries(nSrcDim); - nMbrCount = rStrings.GetCount(); - } + nMbrCount = pSource->GetData()->GetMembersCount( nSrcDim ); } ScDPMembers::~ScDPMembers() @@ -2567,8 +2599,7 @@ ScDPMember* ScDPMembers::getByIndex(long nIndex) const if ( pSource->IsDataLayoutDimension(nSrcDim) ) { // empty name (never shown, not used for lookup) - pNew = new ScDPMember( pSource, nDim, nHier, nLev, - String(), 0.0, FALSE ); + pNew = new ScDPMember( pSource, nDim, nHier, nLev, 0 ); } else if ( nHier != SC_DAPI_HIERARCHY_FLAT && pSource->IsDateDimension( nSrcDim ) ) { @@ -2579,12 +2610,13 @@ ScDPMember* ScDPMembers::getByIndex(long nIndex) const { //! cache year range here! - const TypedScStrCollection& rStrings = pSource->GetData()->GetColumnEntries(nSrcDim); - double fFirstVal = rStrings[0]->GetValue(); + // Wang Xu Ming - DataPilot migration + double fFirstVal = pSource->GetData()->GetMemberByIndex( nSrcDim, 0 )->GetValue(); long nFirstYear = pSource->GetData()->GetDatePart( (long)::rtl::math::approxFloor( fFirstVal ), nHier, nLev ); + // End Comments nVal = nFirstYear + nIndex; } else if ( nHier == SC_DAPI_HIERARCHY_WEEK && nLev == SC_DAPI_LEVEL_WEEKDAY ) @@ -2607,19 +2639,20 @@ ScDPMember* ScDPMembers::getByIndex(long nIndex) const if ( !aName.Len() ) aName = String::CreateFromInt32(nVal); - pNew = new ScDPMember( pSource, nDim, nHier, nLev, aName, nVal, TRUE ); + ScDPItemData rData( aName, nVal, TRUE, 0 ) ; + pNew = new ScDPMember( pSource, nDim, nHier, nLev, pSource->GetCache()->GetAdditionalItemID(rData)); } else { - const TypedScStrCollection& rStrings = pSource->GetData()->GetColumnEntries(nSrcDim); - const TypedStrData* pData = rStrings[(USHORT)nIndex]; - pNew = new ScDPMember( pSource, nDim, nHier, nLev, - pData->GetString(), pData->GetValue(), !pData->IsStrData() ); + const std::vector< SCROW >& memberIndexs = pSource->GetData()->GetColumnEntries( nSrcDim ); + pNew = new ScDPMember( pSource, nDim, nHier, nLev, memberIndexs[nIndex] ); } pNew->acquire(); // ref-counted ppMbrs[nIndex] = pNew; } + DBG_ASSERT( ppMbrs[nIndex] ," member is not initialized " ); + return ppMbrs[nIndex]; } @@ -2629,12 +2662,12 @@ ScDPMember* ScDPMembers::getByIndex(long nIndex) const // ----------------------------------------------------------------------- ScDPMember::ScDPMember( ScDPSource* pSrc, long nD, long nH, long nL, - const String& rN, double fV, BOOL bHV ) : + SCROW nIndex /*const String& rN, double fV, BOOL bHV*/ ) : pSource( pSrc ), nDim( nD ), nHier( nH ), nLev( nL ), - maData( rN, fV, bHV ), + mnDataId( nIndex ), mpLayoutName(NULL), nPosition( -1 ), bVisible( TRUE ), @@ -2651,17 +2684,36 @@ ScDPMember::~ScDPMember() BOOL ScDPMember::IsNamedItem( const ScDPItemData& r ) const { long nSrcDim = pSource->GetSourceDim( nDim ); - if ( nHier != SC_DAPI_HIERARCHY_FLAT && pSource->IsDateDimension( nSrcDim ) && r.bHasValue ) + if ( nHier != SC_DAPI_HIERARCHY_FLAT && pSource->IsDateDimension( nSrcDim ) && r.IsValue() ) { long nComp = pSource->GetData()->GetDatePart( - (long)::rtl::math::approxFloor( r.fValue ), + (long)::rtl::math::approxFloor( r.GetValue() ), nHier, nLev ); // fValue is converted from integer, so simple comparison works - return nComp == maData.fValue; + return nComp == GetItemData().GetValue(); } - return r.IsCaseInsEqual( maData ); + return r.IsCaseInsEqual( GetItemData() ); +} + +BOOL ScDPMember::IsNamedItem( SCROW nIndex ) const +{ + long nSrcDim = pSource->GetSourceDim( nDim ); + if ( nHier != SC_DAPI_HIERARCHY_FLAT && pSource->IsDateDimension( nSrcDim ) ) + { + const ScDPItemData* pData = pSource->GetCache()->GetItemDataById( (SCCOL) nSrcDim, nIndex ); + if ( pData->IsValue() ) + { + long nComp = pSource->GetData()->GetDatePart( + (long)::rtl::math::approxFloor( pData->GetValue() ), + nHier, nLev ); + // fValue is converted from integer, so simple comparison works + return nComp == GetItemData().GetValue(); + } + } + + return nIndex == mnDataId; } sal_Int32 ScDPMember::Compare( const ScDPMember& rOther ) const @@ -2686,14 +2738,14 @@ sal_Int32 ScDPMember::Compare( const ScDPMember& rOther ) const } // no positions set - compare names - return ScDPItemData::Compare( maData, rOther.maData ); + return pSource->GetData()->Compare( pSource->GetSourceDim(nDim),mnDataId,rOther.GetItemDataId()); } void ScDPMember::FillItemData( ScDPItemData& rData ) const { //! handle date hierarchy... - rData = maData; + rData = GetItemData() ; } const OUString* ScDPMember::GetLayoutName() const @@ -2703,12 +2755,12 @@ const OUString* ScDPMember::GetLayoutName() const String ScDPMember::GetNameStr() const { - return maData.aString; + return GetItemData().GetString(); } ::rtl::OUString SAL_CALL ScDPMember::getName() throw(uno::RuntimeException) { - return maData.aString; + return GetItemData().GetString(); } void SAL_CALL ScDPMember::setName( const ::rtl::OUString& /* rNewName */ ) throw(uno::RuntimeException) @@ -2822,4 +2874,48 @@ uno::Any SAL_CALL ScDPMember::getPropertyValue( const rtl::OUString& aPropertyNa SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDPMember ) +ScDPTableDataCache* ScDPSource::GetCache() +{ + DBG_ASSERT( GetData() , "empty ScDPTableData pointer"); + return ( GetData()!=NULL) ? GetData()->GetCacheTable().GetCache() : NULL ; +} + +const ScDPItemData& ScDPMember::GetItemData() const +{ + return *pSource->GetItemDataById( (SCCOL)nDim, mnDataId );//ms-cache-core +} + +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; +} + +SCROW ScDPSource::GetMemberId( long nDim, const ScDPItemData& rData ) +{ + long nSrcDim = GetSourceDim( nDim ); + return GetCache()->GetIdByItemData( nSrcDim, rData ); +} + +const ScDPItemData* ScDPMembers::GetSrcItemDataByIndex( SCROW nIndex) +{ + const std::vector< SCROW >& memberIds = pSource->GetData()->GetColumnEntries( nDim ); + if ( nIndex >= (long )(memberIds.size()) || nIndex < 0 ) + return NULL; + SCROW nId = memberIds[ nIndex ]; + return pSource->GetItemDataById( nDim, nId ); +} + + SCROW ScDPMembers::GetSrcItemsCount() + { + return pSource->GetData()->GetColumnEntries( nDim ).size(); + } +// End Comments diff --git a/sc/source/core/data/global2.cxx b/sc/source/core/data/global2.cxx index 21c09688aeee..d32ebdafbf78 100644 --- a/sc/source/core/data/global2.cxx +++ b/sc/source/core/data/global2.cxx @@ -49,6 +49,10 @@ #include "rechead.hxx" #include "compiler.hxx" #include "paramisc.hxx" +// Wang Xu Ming -- 2009-5-18 +// DataPilot Migration +#include "dpglobal.hxx" +// End Comments #include "sc.hrc" #include "globstr.hrc" @@ -59,7 +63,6 @@ using ::std::vector; -#define MAX_LABELS 256 //!!! aus fieldwnd.hxx, muss noch nach global.hxx ??? //------------------------------------------------------------------------ // struct ScImportParam: @@ -905,90 +908,3 @@ 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); -} diff --git a/sc/source/core/data/makefile.mk b/sc/source/core/data/makefile.mk index 1dd60f75176e..ab2160a93219 100644..100755 --- a/sc/source/core/data/makefile.mk +++ b/sc/source/core/data/makefile.mk @@ -72,6 +72,7 @@ SLOFILES = \ $(SLO)$/document.obj \ $(SLO)$/dpcachetable.obj \ $(SLO)$/dpdimsave.obj \ + $(SLO)$/dpglobal.obj \ $(SLO)$/dpgroup.obj \ $(SLO)$/dpobject.obj \ $(SLO)$/dpoutput.obj \ @@ -82,6 +83,8 @@ SLOFILES = \ $(SLO)$/dptabdat.obj \ $(SLO)$/dptabres.obj \ $(SLO)$/dptabsrc.obj \ + $(SLO)$/dptablecache.obj\ + $(SLO)$/scdpoutputimpl.obj\ $(SLO)$/drawpage.obj \ $(SLO)$/drwlayer.obj \ $(SLO)$/fillinfo.obj \ @@ -121,6 +124,7 @@ EXCEPTIONSFILES= \ $(SLO)$/documen2.obj \ $(SLO)$/document.obj \ $(SLO)$/dpdimsave.obj \ + $(SLO)$/dpglobal.obj \ $(SLO)$/dpgroup.obj \ $(SLO)$/dpshttab.obj \ $(SLO)$/dptabres.obj \ @@ -135,7 +139,9 @@ EXCEPTIONSFILES= \ $(SLO)$/documen5.obj \ $(SLO)$/documen6.obj \ $(SLO)$/documen9.obj \ - $(SLO)$/dpcachetable.obj \ + $(SLO)$/dpcachetable.obj \ + $(SLO)$/dptablecache.obj \ + $(SLO)$/scdpoutputimpl.obj \ $(SLO)$/dpsdbtab.obj \ $(SLO)$/dpobject.obj \ $(SLO)$/dpoutput.obj \ diff --git a/sc/source/core/data/scdpoutputimpl.cxx b/sc/source/core/data/scdpoutputimpl.cxx new file mode 100644 index 000000000000..205c80f19c71 --- /dev/null +++ b/sc/source/core/data/scdpoutputimpl.cxx @@ -0,0 +1,187 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright IBM Corporation 2009. + * Copyright 2009 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: scdpoutputimpl.cxx,v $ + * $Revision: 1.0 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +// INCLUDE --------------------------------------------------------------- +#include "scdpoutputimpl.hxx" +#include "scitems.hxx" +#include <svx/boxitem.hxx> +// ----------------------------------------------------------------------- + +namespace +{ + bool lcl_compareColfuc ( SCCOL i, SCCOL j) { return (i<j); } + bool lcl_compareRowfuc ( SCROW i, SCROW j) { return (i<j); } +} + + +void OutputImpl::OutputDataArea() +{ + AddRow( mnDataStartRow ); + AddCol( mnDataStartCol ); + + mnCols.push_back( mnTabEndCol+1); //set last row bottom + mnRows.push_back( mnTabEndRow+1); //set last col bottom + + BOOL bAllRows = ( ( mnTabEndRow - mnDataStartRow + 2 ) == (SCROW) mnRows.size() ); + + std::sort( mnCols.begin(), mnCols.end(), lcl_compareColfuc ); + std::sort( mnRows.begin(), mnRows.end(), lcl_compareRowfuc ); + + for( SCCOL nCol = 0; nCol < (SCCOL)mnCols.size()-1; nCol ++ ) + { + if ( !bAllRows ) + { + if ( nCol < (SCCOL)mnCols.size()-2) + { + for ( SCROW i = nCol%2; i < (SCROW)mnRows.size()-2; i +=2 ) + OutputBlockFrame( mnCols[nCol], mnRows[i], mnCols[nCol+1]-1, mnRows[i+1]-1 ); + if ( mnRows.size()>=2 ) + OutputBlockFrame( mnCols[nCol], mnRows[mnRows.size()-2], mnCols[nCol+1]-1, mnRows[mnRows.size()-1]-1 ); + } + else + { + for ( SCROW i = 0 ; i < (SCROW)mnRows.size()-1; i++ ) + OutputBlockFrame( mnCols[nCol], mnRows[i], mnCols[nCol+1]-1, mnRows[i+1]-1 ); + } + } + else + OutputBlockFrame( mnCols[nCol], mnRows.front(), mnCols[nCol+1]-1, mnRows.back()-1, bAllRows ); + } + //out put rows area outer framer + if ( mnTabStartCol != mnDataStartCol ) + { + if ( mnTabStartRow != mnDataStartRow ) + OutputBlockFrame( mnTabStartCol, mnTabStartRow, mnDataStartCol-1, mnDataStartRow-1 ); + OutputBlockFrame( mnTabStartCol, mnDataStartRow, mnDataStartCol-1, mnTabEndRow ); + } + //out put cols area outer framer + OutputBlockFrame( mnDataStartCol, mnTabStartRow, mnTabEndCol, mnDataStartRow-1 ); +} + +OutputImpl::OutputImpl( ScDocument* pDoc, USHORT nTab, + SCCOL nTabStartCol, + SCROW nTabStartRow, + SCCOL nMemberStartCol, + SCROW nMemberStartRow, + SCCOL nDataStartCol, + SCROW nDataStartRow, + SCCOL nTabEndCol, + SCROW nTabEndRow ): + mpDoc( pDoc ), + mnTab( nTab ), + mnTabStartCol( nTabStartCol ), + mnTabStartRow( nTabStartRow ), + mnMemberStartCol( nMemberStartCol), + mnMemberStartRow( nMemberStartRow), + mnDataStartCol ( nDataStartCol ), + mnDataStartRow ( nDataStartRow ), + mnTabEndCol( nTabEndCol ), + mnTabEndRow( nTabEndRow ) +{ + mbNeedLineCols.resize( nTabEndCol-nDataStartCol+1, false ); + mbNeedLineRows.resize( nTabEndRow-nDataStartRow+1, false ); + +} + +BOOL OutputImpl::AddRow( SCROW nRow ) +{ + if ( !mbNeedLineRows[ nRow - mnDataStartRow ] ) + { + mbNeedLineRows[ nRow - mnDataStartRow ] = true; + mnRows.push_back( nRow ); + return TRUE; + } + else + return FALSE; +} + +BOOL OutputImpl::AddCol( SCCOL nCol ) +{ + + if ( !mbNeedLineCols[ nCol - mnDataStartCol ] ) + { + mbNeedLineCols[ nCol - mnDataStartCol ] = true; + mnCols.push_back( nCol ); + return TRUE; + } + else + return FALSE; +} + +void OutputImpl::OutputBlockFrame ( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, BOOL bHori ) +{ + + SvxBorderLine aLine, aOutLine; + aLine.SetColor( SC_DP_FRAME_COLOR ); + aLine.SetOutWidth( SC_DP_FRAME_INNER_BOLD ); + aOutLine.SetColor( SC_DP_FRAME_COLOR ); + aOutLine.SetOutWidth( SC_DP_FRAME_OUTER_BOLD ); + + SvxBoxItem aBox( ATTR_BORDER ); + + if ( nStartCol == mnTabStartCol ) + aBox.SetLine(&aOutLine, BOX_LINE_LEFT); + else + aBox.SetLine(&aLine, BOX_LINE_LEFT); + + if ( nStartRow == mnTabStartRow ) + aBox.SetLine(&aOutLine, BOX_LINE_TOP); + else + aBox.SetLine(&aLine, BOX_LINE_TOP); + + if ( nEndCol == mnTabEndCol ) //bottom row + aBox.SetLine(&aOutLine, BOX_LINE_RIGHT); + else + aBox.SetLine(&aLine, BOX_LINE_RIGHT); + + if ( nEndRow == mnTabEndRow ) //bottom + aBox.SetLine(&aOutLine, BOX_LINE_BOTTOM); + else + aBox.SetLine(&aLine, BOX_LINE_BOTTOM); + + + SvxBoxInfoItem aBoxInfo( ATTR_BORDER_INNER ); + aBoxInfo.SetValid(VALID_VERT,FALSE ); + if ( bHori ) + { + aBoxInfo.SetValid(VALID_HORI,TRUE); + aBoxInfo.SetLine( &aLine, BOXINFO_LINE_HORI ); + } + else + aBoxInfo.SetValid(VALID_HORI,FALSE ); + + aBoxInfo.SetValid(VALID_DISTANCE,FALSE); + + mpDoc->ApplyFrameAreaTab( ScRange( nStartCol, nStartRow, mnTab, nEndCol, nEndRow , mnTab ), &aBox, &aBoxInfo ); + +} diff --git a/sc/source/core/data/scdpoutputimpl.hxx b/sc/source/core/data/scdpoutputimpl.hxx new file mode 100755 index 000000000000..9148fe91ba02 --- /dev/null +++ b/sc/source/core/data/scdpoutputimpl.hxx @@ -0,0 +1,79 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright IBM Corporation 2009. + * Copyright 2009 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: scdpoutputimpl.hxx,v $ + * $Revision: 1.0 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef SCDPOUTPUTIMPL_HXX +#define SCDPOUTPUTIMPL_HXX + +#include "document.hxx" + +#define SC_DP_FRAME_INNER_BOLD 20 +#define SC_DP_FRAME_OUTER_BOLD 40 + +#define SC_DP_FRAME_COLOR Color(0,0,0) //( 0x20, 0x40, 0x68 ) + +class OutputImpl +{ + ScDocument* mpDoc; + USHORT mnTab; + ::std::vector< bool > mbNeedLineCols; + ::std::vector< SCCOL > mnCols; + + ::std::vector< bool > mbNeedLineRows; + ::std::vector< SCROW > mnRows; + + SCCOL mnTabStartCol; + SCROW mnTabStartRow; + SCCOL mnMemberStartCol; + SCROW mnMemberStartRow; + + SCCOL mnDataStartCol; + SCROW mnDataStartRow; + SCCOL mnTabEndCol; + SCROW mnTabEndRow; + +public: + OutputImpl( ScDocument* pDoc, USHORT nTab, + SCCOL nTabStartCol, + SCROW nTabStartRow, + SCCOL nMemberStartCol, + SCROW nMemberStartRow, + SCCOL nDataStartCol, + SCROW nDataStartRow, + SCCOL nTabEndCol, + SCROW nTabEndRow ); + BOOL AddRow( SCROW nRow ); + BOOL AddCol( SCCOL nCol ); + + void OutputDataArea(); + void OutputBlockFrame ( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, BOOL bHori = FALSE ); + +}; + +#endif diff --git a/sc/source/core/tool/collect.cxx b/sc/source/core/tool/collect.cxx index 13df9307bc11..c7aa72343fbb 100644 --- a/sc/source/core/tool/collect.cxx +++ b/sc/source/core/tool/collect.cxx @@ -352,10 +352,18 @@ ScDataObject* ScStrCollection::Clone() const //UNUSED2008-05 } //UNUSED2008-05 } + ScDataObject* TypedStrData::Clone() const { return new TypedStrData(*this); } + +TypedScStrCollection::TypedScStrCollection( USHORT nLim , USHORT nDel , BOOL bDup ) + : ScSortedCollection( nLim, nDel, bDup ) +{ + bCaseSensitive = FALSE; +} + TypedScStrCollection::~TypedScStrCollection() {} ScDataObject* TypedScStrCollection::Clone() const @@ -363,6 +371,16 @@ ScDataObject* TypedScStrCollection::Clone() const return new TypedScStrCollection(*this); } +TypedStrData* TypedScStrCollection::operator[]( const USHORT nIndex) const +{ + return (TypedStrData*)At(nIndex); +} + +void TypedScStrCollection::SetCaseSensitive( BOOL bSet ) +{ + bCaseSensitive = bSet; +} + short TypedScStrCollection::Compare( ScDataObject* pKey1, ScDataObject* pKey2 ) const { short nResult = 0; diff --git a/sc/source/filter/excel/xepivot.cxx b/sc/source/filter/excel/xepivot.cxx index cb248f0eaf76..ddcdb3243167 100644 --- a/sc/source/filter/excel/xepivot.cxx +++ b/sc/source/filter/excel/xepivot.cxx @@ -538,16 +538,21 @@ void XclExpPCField::InsertNumDateGroupItems( const ScDPObject& rDPObj, const ScD { // get the string collection with original source elements ScSheetDPData aDPData( GetDocPtr(), *pSrcDesc ); - const TypedScStrCollection& rOrigColl = aDPData.GetColumnEntries( static_cast< long >( GetBaseFieldIndex() ) ); - + // Wang Xu Ming - DataPilot migration + // 2009-05-08 + const std::vector< SCROW > aOrignial = aDPData.GetColumnEntries( static_cast< long >( GetBaseFieldIndex() ) ); // get the string collection with generated grouping elements ScDPNumGroupDimension aTmpDim( rNumInfo ); if( nDatePart != 0 ) aTmpDim.MakeDateHelper( rNumInfo, nDatePart ); - const TypedScStrCollection& rGroupColl = aTmpDim.GetNumEntries( rOrigColl, GetDocPtr() ); - for( USHORT nIdx = 0, nCount = rGroupColl.GetCount(); nIdx < nCount; ++nIdx ) - if( const TypedStrData* pStrData = rGroupColl[ nIdx ] ) - InsertGroupItem( new XclExpPCItem( pStrData->GetString() ) ); + const std::vector< SCROW > aMemberIds = aTmpDim.GetNumEntries( static_cast< SCCOL >( GetBaseFieldIndex() ), aDPData.GetCacheTable().GetCache(), aOrignial ); + for ( size_t nIdx = 0 ; nIdx < aMemberIds.size(); nIdx++ ) + { + const ScDPItemData* pData = aDPData.GetMemberById( static_cast< long >( GetBaseFieldIndex() ) , aMemberIds[ nIdx] ); + if ( pData ) + InsertGroupItem( new XclExpPCItem( pData->GetString() ) ); + } +// End Comments } } diff --git a/sc/source/filter/xml/xmldpimp.cxx b/sc/source/filter/xml/xmldpimp.cxx index 01dae48f6d84..93e529c4ceca 100644 --- a/sc/source/filter/xml/xmldpimp.cxx +++ b/sc/source/filter/xml/xmldpimp.cxx @@ -1453,6 +1453,7 @@ ScXMLDataPilotSubTotalContext::ScXMLDataPilotSubTotalContext( ScXMLImport& rImpo pDataPilotSubTotals->AddFunction( sal::static_int_cast<sal_Int16>( ScXMLConverter::GetFunctionFromString( sValue ) ) ); } + break; case XML_TOK_DATA_PILOT_SUBTOTAL_ATTR_DISPLAY_NAME: case XML_TOK_DATA_PILOT_SUBTOTAL_ATTR_DISPLAY_NAME_EXT: pDataPilotSubTotals->SetDisplayName(sValue); diff --git a/sc/source/ui/inc/dbfunc.hxx b/sc/source/ui/inc/dbfunc.hxx index 87df03b8ecd9..be206b396733 100644 --- a/sc/source/ui/inc/dbfunc.hxx +++ b/sc/source/ui/inc/dbfunc.hxx @@ -53,7 +53,7 @@ private: public: ScDBFunc( Window* pParent, ScDocShell& rDocSh, ScTabViewShell* pViewShell ); //UNUSED2008-05 ScDBFunc( Window* pParent, const ScDBFunc& rDBFunc, ScTabViewShell* pViewShell ); - ~ScDBFunc(); + virtual ~ScDBFunc(); // nur UISort wiederholt bei Bedarf die Teilergebnisse @@ -86,8 +86,10 @@ public: bool MakePivotTable( const ScDPSaveData& rData, const ScRange& rDest, BOOL bNewTable, const ScDPObject& rSource, BOOL bApi = FALSE ); void DeletePivotTable(); - void RecalcPivotTable(); - + // Wang Xu Ming -- 2009-6-17 + // DataPilot Migration + ULONG RecalcPivotTable(); + // End Comments BOOL HasSelectionForDateGroup( ScDPNumGroupInfo& rOldInfo, sal_Int32& rParts ); BOOL HasSelectionForNumGroup( ScDPNumGroupInfo& rOldInfo ); void GroupDataPilot(); diff --git a/sc/source/ui/inc/fieldwnd.hxx b/sc/source/ui/inc/fieldwnd.hxx index 45a573e72157..539dbe54e275 100644..100755 --- a/sc/source/ui/inc/fieldwnd.hxx +++ b/sc/source/ui/inc/fieldwnd.hxx @@ -34,7 +34,6 @@ #include <vcl/fixed.hxx> #include <cppuhelper/weakref.hxx> -#define MAX_LABELS 256 #define PAGE_SIZE 16 // count of visible fields for scrollbar #define LINE_SIZE 8 // count of fields per column for scrollbar #define MAX_FIELDS 8 // maximum count of fields for row/col/data area diff --git a/sc/source/ui/src/globstr.src b/sc/source/ui/src/globstr.src index edb2165daf32..b08676bbe3db 100644 --- a/sc/source/ui/src/globstr.src +++ b/sc/source/ui/src/globstr.src @@ -1722,5 +1722,17 @@ Resource RID_GLOBSTR { Text [ en-US ] = "Page Styles"; }; + String STR_ERR_DATAPILOTSOURCE + { + Text [ en-US ] = "DataPilot source data is invalid."; + }; + String STR_PIVOT_FIRSTROWEMPTYERR + { + Text [ en-US ] = "The field name cannot be empty. Check the first row of data source to make sure there are no empty cells." ; + }; + String STR_PIVOT_ONLYONEROWERR + { + Text [ en-US ] = "DataPilot table needs at least two rows of data to create or refresh." ; + }; }; diff --git a/sc/source/ui/unoobj/dapiuno.cxx b/sc/source/ui/unoobj/dapiuno.cxx index ab94be3052e0..7e23d6b2f9f5 100644..100755 --- a/sc/source/ui/unoobj/dapiuno.cxx +++ b/sc/source/ui/unoobj/dapiuno.cxx @@ -1274,17 +1274,21 @@ CellRangeAddress SAL_CALL ScDataPilotTableObj::getOutputRange() throw(RuntimeExc return aRet; } +ULONG RefreshDPObject( ScDPObject *pDPObj, ScDocument *pDoc, ScDocShell *pDocSh, BOOL bRecord, BOOL bApi ); + void SAL_CALL ScDataPilotTableObj::refresh() throw(RuntimeException) { ScUnoGuard aGuard; - ScDPObject* pDPObj = lcl_GetDPObject(GetDocShell(), nTab, aName); - if (pDPObj) - { - ScDPObject* pNew = new ScDPObject(*pDPObj); - ScDBDocFunc aFunc(*GetDocShell()); - aFunc.DataPilotUpdate( pDPObj, pNew, TRUE, TRUE ); - delete pNew; // DataPilotUpdate copies settings from "new" object - } + if( ScDPObject* pDPObj = lcl_GetDPObject(GetDocShell(), nTab, aName) ) + RefreshDPObject( pDPObj, NULL, GetDocShell(), TRUE, TRUE ); + //if (pDPObj) + //{ + // ScDPObject* pNew = new ScDPObject(*pDPObj); + // ScDBDocFunc aFunc(*GetDocShell()); + // aFunc.DataPilotUpdate( pDPObj, pNew, TRUE, TRUE ); + // delete pNew; // DataPilotUpdate copies settings from "new" object + //} + } Sequence< Sequence<Any> > SAL_CALL ScDataPilotTableObj::getDrillDownData(const CellAddress& aAddr) diff --git a/sc/source/ui/view/dbfunc3.cxx b/sc/source/ui/view/dbfunc3.cxx index 2ef65f596c34..406fdab9c824 100644..100755 --- a/sc/source/ui/view/dbfunc3.cxx +++ b/sc/source/ui/view/dbfunc3.cxx @@ -689,8 +689,41 @@ void ScDBFunc::DeletePivotTable() else ErrorMessage(STR_PIVOT_NOTFOUND); } +ULONG RefreshDPObject( ScDPObject *pDPObj, ScDocument *pDoc, ScDocShell *pDocSh, BOOL bRecord, BOOL bApi ) +{ + if( !pDPObj ) + return STR_PIVOT_NOTFOUND; + + if( !pDoc ) + return static_cast<ULONG>(-1); + + if( !pDocSh && ( pDocSh = PTR_CAST( ScDocShell, pDoc->GetDocumentShell() ) ) == NULL ) + return static_cast<ULONG>(-1); + + if( ULONG nErrId = pDPObj->RefreshCache() ) + return nErrId; + else if ( nErrId == 0 ) + { + //Refresh all dpobjects + ScDPCollection* pDPCollection = pDoc->GetDPCollection(); + USHORT nCount = pDPCollection->GetCount(); + for (USHORT i=0; i<nCount; i++) + { + if ( (*pDPCollection)[i]->GetCacheId() == pDPObj->GetCacheId() ) + { + ScDBDocFunc aFunc( * pDocSh ); + if ( !aFunc.DataPilotUpdate( (*pDPCollection)[i], (*pDPCollection)[i], bRecord, bApi ) ) + break; + } + } -void ScDBFunc::RecalcPivotTable() + return nErrId; + } + + return 0U; +} + +ULONG ScDBFunc::RecalcPivotTable() { ScDocShell* pDocSh = GetViewData()->GetDocShell(); ScDocument* pDoc = GetViewData()->GetDocument(); @@ -702,12 +735,26 @@ void ScDBFunc::RecalcPivotTable() GetViewData()->GetTabNo() ); if ( pDPObj ) { - ScDBDocFunc aFunc( *pDocSh ); - aFunc.DataPilotUpdate( pDPObj, pDPObj, TRUE, FALSE ); - CursorPosChanged(); // shells may be switched + // Wang Xu Ming -- 2009-6-17 + // DataPilot Migration + //ScDBDocFunc aFunc( *pDocSh ); + //aFunc.DataPilotUpdate( pDPObj, pDPObj, TRUE, FALSE ); + //CursorPosChanged(); // shells may be switched + ULONG nErrId = RefreshDPObject( pDPObj, pDoc, pDocSh, TRUE, FALSE );//pDPObj->RefreshCache(); + if ( nErrId == 0 ) + { + // There is no undo for the refresh of the cache table, but the undo history for cell changes + // remains valid and should be preserved, so the history isn't cleared here. + //GetViewData()->GetDocShell()->GetUndoManager()->Clear(); + } + else if (nErrId <= USHRT_MAX) + ErrorMessage(static_cast<USHORT>(nErrId)); + return nErrId; + // End Comments } else ErrorMessage(STR_PIVOT_NOTFOUND); + return STR_PIVOT_NOTFOUND; } void ScDBFunc::GetSelectedMemberList( ScStrCollection& rEntries, long& rDimension ) |