diff options
author | Kohei Yoshida <kohei.yoshida@suse.com> | 2012-03-02 16:52:14 -0500 |
---|---|---|
committer | Kohei Yoshida <kohei.yoshida@gmail.com> | 2012-03-09 11:13:28 -0500 |
commit | 246521c9578e3cb66e610850716ba72f1e9981bc (patch) | |
tree | 8ce6cba13a105c6732f6e3284577e31ee809dc63 | |
parent | 98b4beebce3720c55ff3302a43d482db8adbc6fe (diff) |
Massive rework to reduce the size of ScDPItemData.
Currently lots of things are broken.
-rw-r--r-- | sc/inc/dpdimsave.hxx | 13 | ||||
-rw-r--r-- | sc/inc/dpgroup.hxx | 9 | ||||
-rw-r--r-- | sc/inc/dpitemdata.hxx | 74 | ||||
-rw-r--r-- | sc/inc/dptablecache.hxx | 25 | ||||
-rw-r--r-- | sc/inc/dptabres.hxx | 2 | ||||
-rw-r--r-- | sc/inc/dputil.hxx | 5 | ||||
-rw-r--r-- | sc/source/core/data/dpcachetable.cxx | 2 | ||||
-rw-r--r-- | sc/source/core/data/dpdimsave.cxx | 49 | ||||
-rw-r--r-- | sc/source/core/data/dpgroup.cxx | 216 | ||||
-rw-r--r-- | sc/source/core/data/dpitemdata.cxx | 213 | ||||
-rw-r--r-- | sc/source/core/data/dptabdat.cxx | 58 | ||||
-rw-r--r-- | sc/source/core/data/dptablecache.cxx | 230 | ||||
-rw-r--r-- | sc/source/core/data/dptabres.cxx | 188 | ||||
-rw-r--r-- | sc/source/core/data/dptabsrc.cxx | 12 | ||||
-rw-r--r-- | sc/source/core/data/dputil.cxx | 69 | ||||
-rw-r--r-- | sc/source/filter/excel/xepivot.cxx | 2 |
16 files changed, 830 insertions, 337 deletions
diff --git a/sc/inc/dpdimsave.hxx b/sc/inc/dpdimsave.hxx index 847568ab173a..ea280a1b50fd 100644 --- a/sc/inc/dpdimsave.hxx +++ b/sc/inc/dpdimsave.hxx @@ -77,6 +77,10 @@ public: typedef ::std::vector<ScDPSaveGroupItem> ScDPSaveGroupItemVec; +/** + * Represents a new group dimension whose dimension ID is higher than the + * highest source dimension ID. + */ class SC_DLLPUBLIC ScDPSaveGroupDimension { rtl::OUString aSourceDim; // always the real source from the original data @@ -116,6 +120,11 @@ public: void Rename( const rtl::OUString& rNewName ); }; +/** + * Represents a group dimension that introduces a new hierarchy for an + * existing dimension. Unlike the ScDPSaveGroupDimension counterpart, it + * re-uses the source dimension. + */ class SC_DLLPUBLIC ScDPSaveNumGroupDimension { rtl::OUString aDimensionName; @@ -140,6 +149,10 @@ public: void SetDateInfo( const ScDPNumGroupInfo& rInfo, sal_Int32 nPart ); }; +/** + * This class has to do with handling exclusively grouped dimensions? TODO: + * Find out what this class does and document it here. + */ class SC_DLLPUBLIC ScDPDimensionSaveData { public: diff --git a/sc/inc/dpgroup.hxx b/sc/inc/dpgroup.hxx index f6be836c8567..76a3fcdd65c4 100644 --- a/sc/inc/dpgroup.hxx +++ b/sc/inc/dpgroup.hxx @@ -61,16 +61,19 @@ class ScDPDateGroupHelper { ScDPNumGroupInfo aNumInfo; // only start and end (incl. auto flags) are used sal_Int32 nDatePart; // single part + long mnGroupDim; public: - ScDPDateGroupHelper( const ScDPNumGroupInfo& rInfo, sal_Int32 nPart ); + ScDPDateGroupHelper( const ScDPNumGroupInfo& rInfo, long nDim, sal_Int32 nPart ); ~ScDPDateGroupHelper(); + void SetGroupDim(long nDim); + sal_Int32 GetDatePart() const { return nDatePart; } const ScDPNumGroupInfo& GetNumInfo() const { return aNumInfo; } void FillColumnEntries( - SCCOL nSourceDim, const ScDPCache* pCahe , std::vector<SCROW>& rEntries, + SCCOL nSourceDim, ScDPCache* pCahe , std::vector<SCROW>& rEntries, const std::vector<SCROW>& rOriginal) const; }; @@ -160,7 +163,7 @@ public: SCCOL nSourceDim, const ScDPCache* pCache, const std::vector< SCROW >& rOriginal) const; - void MakeDateHelper( const ScDPNumGroupInfo& rInfo, sal_Int32 nPart ); + void MakeDateHelper( const ScDPNumGroupInfo& rInfo, long nDim, sal_Int32 nPart ); void DisposeData(); }; diff --git a/sc/inc/dpitemdata.hxx b/sc/inc/dpitemdata.hxx index 7b26674e400e..ec95038b53af 100644 --- a/sc/inc/dpitemdata.hxx +++ b/sc/inc/dpitemdata.hxx @@ -45,69 +45,55 @@ class ScDocument; class SC_DLLPUBLIC ScDPItemData { friend class ScDPCache; + public: - enum { - MK_VAL = 0x01, - MK_DATA = 0x02, - MK_ERR = 0x04, - MK_DATE = 0x08 - }; + enum Type { String, Value, Error, Empty, GroupValue }; - static bool isDate( sal_uLong nNumType ); + struct GroupValueAttr + { + sal_Int32 mnGroupType; + sal_Int32 mnValue; + }; private: - rtl::OUString maString; - double mfValue; - sal_uInt8 mbFlag; + + union { + rtl::OUString* mpString; + GroupValueAttr maGroupValue; + double mfValue; + }; + + Type meType; public: + // case insensitive equality + static sal_Int32 Compare(const ScDPItemData& rA, const ScDPItemData& rB); + ScDPItemData(); - ScDPItemData(const rtl::OUString& rS, double fV, sal_uInt8 bF); - ScDPItemData(const rtl::OUString& rS, double fV = 0.0, bool bHV = false, bool bData = true); + ScDPItemData(const rtl::OUString& rStr); + ScDPItemData(double fVal); + ScDPItemData(sal_Int32 nGroupType, sal_Int32 nValue); + ~ScDPItemData(); - void Set(const rtl::OUString& rS, double fVal, sal_uInt8 nFlag); void SetString(const rtl::OUString& rS); + void SetValue(double fVal); + void SetGroupValue(sal_Int32 nGroupType, sal_Int32 nValue); void SetErrorString(const rtl::OUString& rS); 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 ); + bool operator==(const ScDPItemData& r) const; -public: - bool IsHasData() const ; - bool IsHasErr() const ; + bool IsEmpty() const; bool IsValue() const; - const rtl::OUString& GetString() const; - double GetValue() const ; + rtl::OUString GetString() const; + double GetValue() const; + GroupValueAttr GetGroupValue() const; bool HasStringData() const ; - sal_uInt8 GetType() const; -}; - -class SC_DLLPUBLIC ScDPItemDataPool -{ -public: - ScDPItemDataPool(); - ScDPItemDataPool(const ScDPItemDataPool& r); - - virtual ~ScDPItemDataPool(); - 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 ::boost::unordered_multimap< ScDPItemData, sal_Int32, DataHashFunc > DataHash; - - ::std::vector< ScDPItemData > maItems; - DataHash maItemIds; + sal_uInt8 GetCellType() const; }; #endif diff --git a/sc/inc/dptablecache.hxx b/sc/inc/dptablecache.hxx index 2a61b94b4f79..dac253768320 100644 --- a/sc/inc/dptablecache.hxx +++ b/sc/inc/dptablecache.hxx @@ -70,8 +70,18 @@ private: */ mutable ObjectSetType maRefObjects; + struct GroupItems : boost::noncopyable + { + DataListType maItems; + }; + struct Field : boost::noncopyable { + /** + * Optional items for grouped field. + */ + boost::scoped_ptr<GroupItems> mpGroup; + DataListType maItems; /// Unique values in the field. /** @@ -97,14 +107,20 @@ private: Field(); }; + struct GroupField : boost::noncopyable + { + DataListType maItems; /// Unique values in the field. + }; + typedef boost::ptr_vector<Field> FieldsType; + typedef boost::ptr_vector<GroupField> GroupFieldsType; + FieldsType maFields; + GroupFieldsType maGroupFields; LabelsType maLabelNames; // Stores dimension names. std::vector<bool> mbEmptyRow; // Keeps track of empty rows. - boost::scoped_ptr<ScDPItemDataPool> mpAdditionalData; - bool mbDisposing; public: @@ -115,6 +131,10 @@ public: SCROW GetIdByItemData(long nDim, const rtl::OUString& sItemData) const; SCROW GetIdByItemData(long nDim, const ScDPItemData& rData) const; + void AppendGroupField(); + void ResetGroupItems(long nDim); + SCROW SetGroupItem(long nDim, const ScDPItemData& rData); + SCROW GetAdditionalItemID( const ScDPItemData& rData ) const; SCCOL GetDimensionIndex(const rtl::OUString& sName) const; @@ -137,6 +157,7 @@ public: ScDocument* GetDoc() const;//ms-cache-core long GetColumnCount() const; + long GetGroupFieldCount() const; const ScDPItemData* GetItemDataById( long nDim, SCROW nId ) const; diff --git a/sc/inc/dptabres.hxx b/sc/inc/dptabres.hxx index 80e77cca99c7..bfdef7ff4411 100644 --- a/sc/inc/dptabres.hxx +++ b/sc/inc/dptabres.hxx @@ -506,7 +506,7 @@ public: typedef std::vector<ScDPResultMember*> MemberArray; typedef std::map<SCROW, ScDPResultMember*> MemberHash; private: - const ScDPResultData* pResultData; + const ScDPResultData* pResultData; MemberArray maMemberArray; MemberHash maMemberHash; sal_Bool bInitialized; diff --git a/sc/inc/dputil.hxx b/sc/inc/dputil.hxx index cf574c1e056e..0dfab31ee8aa 100644 --- a/sc/inc/dputil.hxx +++ b/sc/inc/dputil.hxx @@ -32,6 +32,8 @@ #include "rtl/ustring.hxx" #include "scdllapi.h" +class SvNumberFormatter; + class ScDPUtil { public: @@ -40,6 +42,9 @@ public: SC_DLLPUBLIC static rtl::OUString getSourceDimensionName(const rtl::OUString& rName); static rtl::OUString createDuplicateDimensionName(const rtl::OUString& rOriginal, size_t nDupCount); + + static rtl::OUString getDateGroupName( + sal_Int32 nDatePart, sal_Int32 nValue, SvNumberFormatter* pFormatter); }; #endif diff --git a/sc/source/core/data/dpcachetable.cxx b/sc/source/core/data/dpcachetable.cxx index 7db3ceb7101f..d751e39bc3a8 100644 --- a/sc/source/core/data/dpcachetable.cxx +++ b/sc/source/core/data/dpcachetable.cxx @@ -327,7 +327,7 @@ void ScDPCacheTable::getValue( ScDPValueData& rVal, SCCOL nCol, SCROW nRow, boo if (pData) { rVal.fValue = pData->IsValue() ? pData->GetValue() : 0.0; - rVal.nType = pData->GetType(); + rVal.nType = pData->GetCellType(); } else rVal.Set(0.0, SC_VALTYPE_EMPTY); diff --git a/sc/source/core/data/dpdimsave.cxx b/sc/source/core/data/dpdimsave.cxx index 362943d06a63..8bcb37e92323 100644 --- a/sc/source/core/data/dpdimsave.cxx +++ b/sc/source/core/data/dpdimsave.cxx @@ -38,6 +38,48 @@ #include <rtl/math.hxx> #include <algorithm> +#include <stdio.h> +#include <string> +#include <sys/time.h> + +namespace { + +class stack_printer +{ +public: + explicit stack_printer(const char* msg) : + msMsg(msg) + { + fprintf(stdout, "%s: --begin\n", msMsg.c_str()); + mfStartTime = getTime(); + } + + ~stack_printer() + { + double fEndTime = getTime(); + fprintf(stdout, "%s: --end (duration: %g sec)\n", msMsg.c_str(), (fEndTime-mfStartTime)); + } + + void printTime(int line) const + { + double fEndTime = getTime(); + fprintf(stdout, "%s: --(%d) (duration: %g sec)\n", msMsg.c_str(), line, (fEndTime-mfStartTime)); + } + +private: + double getTime() const + { + timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec + tv.tv_usec / 1000000.0; + } + + ::std::string msMsg; + double mfStartTime; +}; + +} + // ============================================================================ ScDPSaveGroupItem::ScDPSaveGroupItem( const rtl::OUString& rName ) : @@ -110,7 +152,7 @@ void ScDPSaveGroupItem::AddToData( ScDPGroupDimension& rDataDim, SvNumberFormatt sal_uInt32 nFormat = 0; //! ... double fValue; if ( pFormatter->IsNumberFormat( *aIter, nFormat, fValue ) ) - aData = ScDPItemData( *aIter, fValue, sal_True ); + aData.SetValue(fValue); else aData.SetString( *aIter ); @@ -309,12 +351,15 @@ ScDPSaveNumGroupDimension::~ScDPSaveNumGroupDimension() void ScDPSaveNumGroupDimension::AddToData( ScDPGroupTableData& rData ) const { + stack_printer __stack_printer__("ScDPSaveNumGroupDimension::AddToData"); + fprintf(stdout, "ScDPSaveNumGroupDimension::AddToData: dim name = '%s'\n", + rtl::OUStringToOString(aDimensionName, RTL_TEXTENCODING_UTF8).getStr()); long nSource = rData.GetDimensionIndex( aDimensionName ); if ( nSource >= 0 ) { ScDPNumGroupDimension aDim( aGroupInfo ); // aGroupInfo: value grouping if ( nDatePart ) - aDim.MakeDateHelper( aDateInfo, nDatePart ); // date grouping + aDim.MakeDateHelper( aDateInfo, nSource, nDatePart ); // date grouping rData.SetNumGroupDimension( nSource, aDim ); } diff --git a/sc/source/core/data/dpgroup.cxx b/sc/source/core/data/dpgroup.cxx index 3dc3e506252f..e3024b0229fb 100644 --- a/sc/source/core/data/dpgroup.cxx +++ b/sc/source/core/data/dpgroup.cxx @@ -31,13 +31,8 @@ // INCLUDE --------------------------------------------------------------- -#include <com/sun/star/i18n/CalendarDisplayIndex.hpp> - -#include <rtl/math.hxx> -#include <unotools/localedatawrapper.hxx> -#include <svl/zforlist.hxx> - #include "dpgroup.hxx" + #include "global.hxx" #include "document.hxx" #include "dpcachetable.hxx" @@ -45,9 +40,13 @@ #include "dptabres.hxx" #include "dpobject.hxx" #include "dpglobal.hxx" +#include "dputil.hxx" + +#include <rtl/math.hxx> #include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp> #include <com/sun/star/sheet/DataPilotFieldFilter.hpp> +#include <com/sun/star/i18n/CalendarDisplayIndex.hpp> #include <vector> #include <boost/unordered_map.hpp> @@ -65,6 +64,48 @@ using ::rtl::OUStringHash; using ::std::vector; using ::boost::shared_ptr; +#include <stdio.h> +#include <string> +#include <sys/time.h> + +namespace { + +class stack_printer +{ +public: + explicit stack_printer(const char* msg) : + msMsg(msg) + { + fprintf(stdout, "%s: --begin\n", msMsg.c_str()); + mfStartTime = getTime(); + } + + ~stack_printer() + { + double fEndTime = getTime(); + fprintf(stdout, "%s: --end (duration: %g sec)\n", msMsg.c_str(), (fEndTime-mfStartTime)); + } + + void printTime(int line) const + { + double fEndTime = getTime(); + fprintf(stdout, "%s: --(%d) (duration: %g sec)\n", msMsg.c_str(), line, (fEndTime-mfStartTime)); + } + +private: + double getTime() const + { + timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec + tv.tv_usec / 1000000.0; + } + + ::std::string msMsg; + double mfStartTime; +}; + +} + #define D_TIMEFACTOR 86400.0 const sal_uInt16 SC_DP_LEAPYEAR = 1648; // arbitrary leap year for date calculations @@ -143,7 +184,7 @@ SCROW lcl_InsertValue<true>(SCCOL nSourceDim, const ScDPCache* pCache, std::vect template<bool bUpdateData> void lcl_InsertValue ( SCCOL nSourceDim, const ScDPCache* pCache, std::vector< SCROW >& vIdx, const String& rString, const double& fValue ) { - lcl_InsertValue<bUpdateData>( nSourceDim, pCache, vIdx, ScDPItemData( rString, fValue, sal_True ) ); + lcl_InsertValue<bUpdateData>(nSourceDim, pCache, vIdx, ScDPItemData(fValue)); } void lcl_AppendDateStr( rtl::OUStringBuffer& rBuffer, double fValue, SvNumberFormatter* pFormatter ) @@ -395,9 +436,11 @@ bool ScDPGroupDateFilter::match( const ScDPItemData & rCellData ) const } // ----------------------------------------------------------------------- -ScDPDateGroupHelper::ScDPDateGroupHelper( const ScDPNumGroupInfo& rInfo, sal_Int32 nPart ) : +ScDPDateGroupHelper::ScDPDateGroupHelper( + const ScDPNumGroupInfo& rInfo, long nDim, sal_Int32 nPart ) : aNumInfo( rInfo ), - nDatePart( nPart ) + nDatePart( nPart ), + mnGroupDim(nDim) { } @@ -405,58 +448,6 @@ ScDPDateGroupHelper::~ScDPDateGroupHelper() { } -String lcl_GetTwoDigitString( sal_Int32 nValue ) -{ - String aRet = String::CreateFromInt32( nValue ); - if ( aRet.Len() < 2 ) - aRet.Insert( (sal_Unicode)'0', 0 ); - return aRet; -} - -String lcl_GetDateGroupName( sal_Int32 nDatePart, sal_Int32 nValue, SvNumberFormatter* pFormatter ) -{ - String aRet; - switch ( nDatePart ) - { - case com::sun::star::sheet::DataPilotFieldGroupBy::YEARS: - aRet = String::CreateFromInt32( nValue ); - break; - case com::sun::star::sheet::DataPilotFieldGroupBy::QUARTERS: - aRet = ScGlobal::pLocaleData->getQuarterAbbreviation( (sal_Int16)(nValue - 1) ); // nValue is 1-based - break; - case com::sun::star::sheet::DataPilotFieldGroupBy::MONTHS: - //! cache getMonths() result? - aRet = ScGlobal::GetCalendar()->getDisplayName( - ::com::sun::star::i18n::CalendarDisplayIndex::MONTH, - sal_Int16(nValue-1), 0 ); // 0-based, get short name - break; - case com::sun::star::sheet::DataPilotFieldGroupBy::DAYS: - { - Date aDate( 1, 1, SC_DP_LEAPYEAR ); - aDate += ( nValue - 1 ); // nValue is 1-based - Date aNullDate = *(pFormatter->GetNullDate()); - long nDays = aDate - aNullDate; - - sal_uLong nFormat = pFormatter->GetFormatIndex( NF_DATE_SYS_DDMMM, ScGlobal::eLnge ); - Color* pColor; - pFormatter->GetOutputString( nDays, nFormat, aRet, &pColor ); - } - break; - case com::sun::star::sheet::DataPilotFieldGroupBy::HOURS: - //! allow am/pm format? - aRet = lcl_GetTwoDigitString( nValue ); - break; - case com::sun::star::sheet::DataPilotFieldGroupBy::MINUTES: - case com::sun::star::sheet::DataPilotFieldGroupBy::SECONDS: - aRet = ScGlobal::pLocaleData->getTimeSep(); - aRet.Append( lcl_GetTwoDigitString( nValue ) ); - break; - default: - OSL_FAIL("invalid date part"); - } - return aRet; -} - sal_Int32 lcl_GetDatePartValue( double fValue, sal_Int32 nDatePart, SvNumberFormatter* pFormatter, const ScDPNumGroupInfo* pNumInfo ) { @@ -595,9 +586,15 @@ String lcl_GetSpecialDateName( double fValue, bool bFirst, SvNumberFormatter* pF return aBuffer.makeStringAndClear(); } +void ScDPDateGroupHelper::SetGroupDim(long nDim) +{ + mnGroupDim = nDim; +} + void ScDPDateGroupHelper::FillColumnEntries( - SCCOL nSourceDim, const ScDPCache* pCache, std::vector<SCROW>& rEntries, const std::vector<SCROW>& rOriginal) const + SCCOL nSourceDim, ScDPCache* pCache, std::vector<SCROW>& rEntries, const std::vector<SCROW>& rOriginal) const { + stack_printer __stack_printer__("ScDPDateGroupHelper::FillColumnEntries"); // auto min/max is only used for "Years" part, but the loop is always needed double fSourceMin = 0.0; double fSourceMax = 0.0; @@ -659,18 +656,35 @@ void ScDPDateGroupHelper::FillColumnEntries( OSL_FAIL("invalid date part"); } + pCache->ResetGroupItems(mnGroupDim); + + fprintf(stdout, "ScDPDateGroupHelper::FillColumnEntries: source dim = %d group dim = %d\n", + nSourceDim, mnGroupDim); for ( sal_Int32 nValue = nStart; nValue <= nEnd; nValue++ ) { - String aName = lcl_GetDateGroupName( nDatePart, nValue, pFormatter ); - lcl_InsertValue<false>( nSourceDim, pCache, rEntries, aName, nValue ); + rtl::OUString aName = ScDPUtil::getDateGroupName( nDatePart, nValue, pFormatter ); + fprintf(stdout, "ScDPDateGroupHelper::FillColumnEntries: name = '%s'\n", + rtl::OUStringToOString(aName, RTL_TEXTENCODING_UTF8).getStr()); + SCROW nId = pCache->SetGroupItem(mnGroupDim, ScDPItemData(aName)); + rEntries.push_back(nId); } // add first/last entry (min/max) - String aFirstName = lcl_GetSpecialDateName( aNumInfo.mfStart, true, pFormatter ); - lcl_InsertValue<true>( nSourceDim, pCache, rEntries, aFirstName, SC_DP_DATE_FIRST ); + rtl::OUString aFirstName = lcl_GetSpecialDateName( aNumInfo.mfStart, true, pFormatter ); + fprintf(stdout, "ScDPDateGroupHelper::FillColumnEntries: first = '%s'\n", + rtl::OUStringToOString(aFirstName, RTL_TEXTENCODING_UTF8).getStr()); + SCROW nId = pCache->SetGroupItem(mnGroupDim, ScDPItemData(aFirstName)); + rEntries.push_back(nId); + + rtl::OUString aLastName = lcl_GetSpecialDateName( aNumInfo.mfEnd, false, pFormatter ); + fprintf(stdout, "ScDPDateGroupHelper::FillColumnEntries: last = '%s'\n", + rtl::OUStringToOString(aLastName, RTL_TEXTENCODING_UTF8).getStr()); + nId = pCache->SetGroupItem(mnGroupDim, ScDPItemData(aLastName)); + rEntries.push_back(nId); - String aLastName = lcl_GetSpecialDateName( aNumInfo.mfEnd, false, pFormatter ); - lcl_InsertValue<true>( nSourceDim, pCache, rEntries, aLastName, SC_DP_DATE_LAST ); + std::vector<SCROW>::const_iterator it = rEntries.begin(), itEnd = rEntries.end(); + for (; it != itEnd; ++it) + fprintf(stdout, "ScDPDateGroupHelper::FillColumnEntries: id = %d\n", *it); } // ----------------------------------------------------------------------- @@ -760,7 +774,7 @@ ScDPGroupDimension& ScDPGroupDimension::operator=( const ScDPGroupDimension& rOt void ScDPGroupDimension::MakeDateHelper( const ScDPNumGroupInfo& rInfo, sal_Int32 nPart ) { delete pDateHelper; - pDateHelper = new ScDPDateGroupHelper( rInfo, nPart ); + pDateHelper = new ScDPDateGroupHelper(rInfo, nGroupDim, nPart); } void ScDPGroupDimension::AddItem( const ScDPGroupItem& rItem ) @@ -771,6 +785,8 @@ void ScDPGroupDimension::AddItem( const ScDPGroupItem& rItem ) void ScDPGroupDimension::SetGroupDim( long nDim ) { nGroupDim = nDim; + if (pDateHelper) + pDateHelper->SetGroupDim(nDim); } const std::vector< SCROW >& ScDPGroupDimension::GetColumnEntries( const ScDPCacheTable& rCacheTable, const std::vector< SCROW >& rOriginal ) const { @@ -778,7 +794,8 @@ const std::vector< SCROW >& ScDPGroupDimension::GetColumnEntries( const ScDPCac { if ( pDateHelper ) { - pDateHelper->FillColumnEntries( (SCCOL)GetSourceDim(), rCacheTable.getCache(), maMemberEntries, rOriginal ); + pDateHelper->FillColumnEntries( + GetSourceDim(), const_cast<ScDPCache*>(rCacheTable.getCache()), maMemberEntries, rOriginal); } else { @@ -888,10 +905,10 @@ ScDPNumGroupDimension::~ScDPNumGroupDimension() delete pDateHelper; } -void ScDPNumGroupDimension::MakeDateHelper( const ScDPNumGroupInfo& rInfo, sal_Int32 nPart ) +void ScDPNumGroupDimension::MakeDateHelper( const ScDPNumGroupInfo& rInfo, long nDim, sal_Int32 nPart ) { delete pDateHelper; - pDateHelper = new ScDPDateGroupHelper( rInfo, nPart ); + pDateHelper = new ScDPDateGroupHelper(rInfo, nDim, nPart); aGroupInfo.mbEnable = sal_True; //! or query both? } @@ -904,7 +921,8 @@ const std::vector<SCROW>& ScDPNumGroupDimension::GetNumEntries( SvNumberFormatter* pFormatter = pCache->GetDoc()->GetFormatTable(); if ( pDateHelper ) - pDateHelper->FillColumnEntries( nSourceDim, pCache, maMemberEntries,rOriginal ); + pDateHelper->FillColumnEntries( + nSourceDim, const_cast<ScDPCache*>(pCache), maMemberEntries, rOriginal); else { // Copy textual entries. @@ -998,6 +1016,8 @@ const std::vector<SCROW>& ScDPNumGroupDimension::GetNumEntries( String aLastName = lcl_GetSpecialNumGroupName( aGroupInfo.mfEnd, false, cDecSeparator, aGroupInfo.mbDateValues, pFormatter ); lcl_InsertValue<true>( nSourceDim, pCache, maMemberEntries, aLastName, aGroupInfo.mfEnd + aGroupInfo.mfStep ); + + fprintf(stdout, "ScDPNumGroupDimension::GetNumEntries: FIXME\n"); } } return maMemberEntries; @@ -1025,7 +1045,11 @@ void ScDPGroupTableData::AddGroupDimension( const ScDPGroupDimension& rGroup ) ScDPGroupDimension aNewGroup( rGroup ); aNewGroup.SetGroupDim( GetColumnCount() ); // new dimension will be at the end aGroups.push_back( aNewGroup ); - aGroupNames.insert( OUString(aNewGroup.GetName()) ); + aGroupNames.insert(aNewGroup.GetName()); + ScDPCache* pCache = const_cast<ScDPCache*>(GetCacheTable().getCache()); + pCache->AppendGroupField(); + fprintf(stdout, "ScDPGroupTableData::AddGroupDimension: name = '%s' group count = %d\n", + rtl::OUStringToOString(aNewGroup.GetName(), RTL_TEXTENCODING_UTF8).getStr(), aGroups.size()); } void ScDPGroupTableData::SetNumGroupDimension( long nIndex, const ScDPNumGroupDimension& rGroup ) @@ -1099,6 +1123,8 @@ const std::vector< SCROW >& ScDPGroupTableData::GetColumnEntries( long nColumn const ScDPItemData* ScDPGroupTableData::GetMemberById( long nDim, long nId ) { +// stack_printer __stack_printer__("ScDPGroupTableData::GetMemberById"); +// fprintf(stdout, "ScDPGroupTableData::GetMemberById: dim = %d id = %d\n", nDim, nId); if ( nDim >= nSourceCount ) { if ( getIsDataLayoutDimension( nDim) ) @@ -1263,9 +1289,13 @@ void ScDPGroupTableData::ModifyFilterCriteria(vector<ScDPCacheTable::Criterion>& for (size_t i = 0; i < nGroupItemCount; ++i) { const ScDPGroupItem* pGrpItem = pGrpDim->GetGroupByIndex(i); - ScDPItemData aName( pFilter->getMatchString(),pFilter->getMatchValue(),pFilter->hasValue()) ; + ScDPItemData aName; + if (pFilter->hasValue()) + aName.SetValue(pFilter->getMatchValue()); + else + aName.SetString(pFilter->getMatchString()); - if (!pGrpItem || !pGrpItem->GetName().IsCaseInsEqual(aName)) + if (!pGrpItem || !pGrpItem->GetName().IsCaseInsEqual(aName)) continue; ScDPCacheTable::Criterion aCri; @@ -1329,8 +1359,9 @@ const ScDPCacheTable& ScDPGroupTableData::GetCacheTable() const return pSourceData->GetCacheTable(); } -void ScDPGroupTableData::FillGroupValues( /*ScDPItemData* pItemData*/ SCROW* pItemDataIndex, long nCount, const long* pDims ) +void ScDPGroupTableData::FillGroupValues(SCROW* pItemDataIndex, long nCount, const long* pDims) { + stack_printer __stack_printer__("ScDPGroupTableData::FillGroupValues"); long nGroupedColumns = aGroups.size(); const ScDPCache* pCache = GetCacheTable().getCache(); @@ -1360,6 +1391,7 @@ void ScDPGroupTableData::FillGroupValues( /*ScDPItemData* pItemData*/ SCROW* pIt const ScDPItemData* pData = pCache->GetItemDataById( (SCCOL)nSourceDim, pItemDataIndex[nDim]); if ( pData ->IsValue() ) { + // TODO: This needs fixing. ScDPNumGroupInfo aNumInfo; bool bHasNonInteger = false; sal_Unicode cDecSeparator = 0; @@ -1367,8 +1399,8 @@ void ScDPGroupTableData::FillGroupValues( /*ScDPItemData* pItemData*/ SCROW* pIt double fGroupValue; String aGroupName = lcl_GetNumGroupForValue( pData->GetValue(), aNumInfo, bHasNonInteger, cDecSeparator, fGroupValue, pDoc ); - ScDPItemData aItemData ( aGroupName, fGroupValue, sal_True ) ; - pItemDataIndex[nDim] = pCache->GetAdditionalItemID( aItemData ); + ScDPItemData aItemData(aGroupName); + pItemDataIndex[nDim] = pCache->GetAdditionalItemID(aItemData); } // else (textual) keep original value } @@ -1377,14 +1409,26 @@ void ScDPGroupTableData::FillGroupValues( /*ScDPItemData* pItemData*/ SCROW* pIt if ( pDateHelper ) { const ScDPItemData* pData = GetCacheTable().getCache()->GetItemDataById( (SCCOL)nSourceDim, pItemDataIndex[nDim]); - if ( pData ->IsValue() ) + if ( pData ->IsValue() ) { + SvNumberFormatter* pFormatter = pDoc->GetFormatTable(); sal_Int32 nPartValue = lcl_GetDatePartValue( - pData->GetValue(), pDateHelper->GetDatePart(), pDoc->GetFormatTable(), + pData->GetValue(), pDateHelper->GetDatePart(), pFormatter, &pDateHelper->GetNumInfo() ); - sal_uInt8 nFlag = ScDPItemData::MK_DATA | ScDPItemData::MK_VAL; - ScDPItemData aItemData(rtl::OUString(), static_cast<double>(nPartValue), nFlag); - pItemDataIndex[nDim] = GetCacheTable().getCache()->GetAdditionalItemID( aItemData ); + rtl::OUString aName = ScDPUtil::getDateGroupName(pDateHelper->GetDatePart(), nPartValue, pFormatter); + fprintf(stdout, "ScDPGroupTableData::FillGroupValues: column = %d source dim = %d group by = %d value = %d name = '%s'\n", + nColumn, nSourceDim, + pDateHelper->GetDatePart(), nPartValue, + rtl::OUStringToOString(aName, RTL_TEXTENCODING_UTF8).getStr()); + ScDPItemData aItem(pDateHelper->GetDatePart(), nPartValue); + pItemDataIndex[nDim] = GetCacheTable().getCache()->GetIdByItemData(nColumn, aItem); + const ScDPItemData* pTest = GetCacheTable().getCache()->GetItemDataById(nColumn, pItemDataIndex[nDim]); + fprintf(stdout, "ScDPGroupTableData::FillGroupValues: id = %d\n", pItemDataIndex[nDim]); + if (pTest) + fprintf(stdout, "ScDPGroupTableData::FillGroupValues: test str = '%s'\n", rtl::OUStringToOString(pTest->GetString(), RTL_TEXTENCODING_UTF8).getStr()); +// sal_uInt8 nFlag = ScDPItemData::MK_DATA | ScDPItemData::MK_VAL; +// ScDPItemData aItemData(rtl::OUString(), static_cast<double>(nPartValue), nFlag); +// pItemDataIndex[nDim] = GetCacheTable().getCache()->GetAdditionalItemID( aItemData ); } } } @@ -1437,6 +1481,10 @@ sal_Bool ScDPGroupTableData::IsNumOrDateGroup(long nDimension) const sal_Bool ScDPGroupTableData::IsInGroup( const ScDPItemData& rGroupData, long nGroupIndex, const ScDPItemData& rBaseData, long nBaseIndex ) const { + stack_printer __stack_printer__("ScDPGroupTableData::IsInGroup"); + fprintf(stdout, "ScDPGroupTableData::IsInGroup: group = '%s' base = '%s' group id = %d base id = %d\n", + rtl::OUStringToOString(rGroupData.GetString(), RTL_TEXTENCODING_UTF8).getStr(), + rtl::OUStringToOString(rBaseData.GetString(), RTL_TEXTENCODING_UTF8).getStr(), nGroupIndex, nBaseIndex); for ( ScDPGroupDimensionVec::const_iterator aIter(aGroups.begin()); aIter != aGroups.end(); aIter++ ) { const ScDPGroupDimension& rDim = *aIter; diff --git a/sc/source/core/data/dpitemdata.cxx b/sc/source/core/data/dpitemdata.cxx index 1b7368bf82e6..579f98521ab2 100644 --- a/sc/source/core/data/dpitemdata.cxx +++ b/sc/source/core/data/dpitemdata.cxx @@ -34,99 +34,117 @@ #include "globstr.hrc" #include "dptabdat.hxx" -bool ScDPItemData::isDate( sal_uLong nNumType ) +sal_Int32 ScDPItemData::Compare(const ScDPItemData& rA, const ScDPItemData& rB) { - return ((nNumType & NUMBERFORMAT_DATE) != 0) ? 1 : 0; + if ( rA.IsValue() ) + { + if ( rB.IsValue() ) + return rA.mfValue < rB.mfValue ? -1 : 1; + else + return -1; // values first + } + else if ( rB.IsValue() ) + return 1; // values first + else + return ScGlobal::GetCollator()->compareString(rA.GetString(), rB.GetString()); } ScDPItemData::ScDPItemData() : - mfValue(0.0), mbFlag(0) {} + mfValue(0.0), meType(Empty) {} + +ScDPItemData::ScDPItemData(const rtl::OUString& rStr) : + mpString(new rtl::OUString(rStr)), meType(String) {} -ScDPItemData::ScDPItemData(const rtl::OUString & rS, double fV, sal_uInt8 bF) : - maString(rS), mfValue(fV), mbFlag(bF) {} +ScDPItemData::ScDPItemData(double fVal) : + mfValue(fVal), meType(Value) {} -ScDPItemData::ScDPItemData(const rtl::OUString& rS, double fV, bool bHV, bool bData) : - maString(rS), mfValue(fV), - mbFlag( (MK_VAL*!!bHV) | (MK_DATA*!!bData) | (MK_ERR*!!false) ) +ScDPItemData::ScDPItemData(sal_Int32 nGroupType, sal_Int32 nValue) : + meType(GroupValue) { + maGroupValue.mnGroupType = nGroupType; + maGroupValue.mnValue = nValue; } -void ScDPItemData::Set(const rtl::OUString& rS, double fVal, sal_uInt8 nFlag) +ScDPItemData::~ScDPItemData() { - maString = rS; - mfValue = fVal; - mbFlag = nFlag; + if (meType == String) + delete mpString; } void ScDPItemData::SetString(const rtl::OUString& rS) { - maString = rS; - mbFlag &= ~(MK_VAL|MK_DATE); - mbFlag |= MK_DATA; + if (meType == String) + delete mpString; + mpString = new rtl::OUString(rS); + meType = String; +} + +void ScDPItemData::SetValue(double fVal) +{ + if (meType == String) + delete mpString; + mfValue = fVal; + meType = Value; +} + +void ScDPItemData::SetGroupValue(sal_Int32 nGroupType, sal_Int32 nValue) +{ + if (meType == String) + delete mpString; + + maGroupValue.mnGroupType = nGroupType; + maGroupValue.mnValue = nValue; + meType = GroupValue; } void ScDPItemData::SetErrorString(const rtl::OUString& rS) { SetString(rS); - mbFlag |= MK_ERR; } -bool ScDPItemData::IsCaseInsEqual( const ScDPItemData& r ) const +bool ScDPItemData::IsCaseInsEqual(const ScDPItemData& r) const { - //! pass Transliteration? - //! inline? - return IsValue() ? ( r.IsValue() && rtl::math::approxEqual( mfValue, r.mfValue ) ) : - ( !r.IsValue() && - ScGlobal::GetpTransliteration()->isEqual( maString, r.maString ) ); + if (meType != r.meType) + return false; + + if (meType == Value) + return rtl::math::approxEqual(mfValue, r.mfValue); + + return ScGlobal::GetpTransliteration()->isEqual(GetString(), r.GetString()); } size_t ScDPItemData::Hash() const { - if ( IsValue() ) - return (size_t) rtl::math::approxFloor( mfValue ); - else - // If we do unicode safe case insensitive hash we can drop - // ScDPItemData::operator== and use ::IsCasInsEqual - return rtl_ustr_hashCode_WithLength(maString.getStr(), maString.getLength()); + if (meType == Value) + return static_cast<size_t>(rtl::math::approxFloor(mfValue)); + + // If we do unicode safe case insensitive hash we can drop + // ScDPItemData::operator== and use ::IsCasInsEqual + rtl::OUString aStr = GetString(); + return rtl_ustr_hashCode_WithLength(aStr.getStr(), aStr.getLength()); } -bool ScDPItemData::operator==( const ScDPItemData& r ) const +bool ScDPItemData::operator== (const ScDPItemData& r) const { - if ( IsValue() ) - { - if ( r.IsValue() ) - return rtl::math::approxEqual( mfValue, r.mfValue ); - else - return false; - } - else if ( r.IsValue() ) + if (meType != r.meType) return false; - else - // need exact equality until we have a safe case insensitive string hash - return maString == r.maString; -} -sal_Int32 ScDPItemData::Compare( const ScDPItemData& rA, - const ScDPItemData& rB ) -{ - if ( rA.IsValue() ) - { - if ( rB.IsValue() ) - return rA.mfValue < rB.mfValue ? -1 : 1; - else - return -1; // values first - } - else if ( rB.IsValue() ) - return 1; // values first - else - return ScGlobal::GetCollator()->compareString( rA.maString, rB.maString ); + if (meType == Value) + return (r.meType == Value) ? rtl::math::approxEqual(mfValue, r.mfValue) : false; + + if (meType == GroupValue) + return maGroupValue.mnGroupType == r.maGroupValue.mnGroupType && + maGroupValue.mnValue == r.maGroupValue.mnValue; + + // need exact equality until we have a safe case insensitive string hash + return GetString() == r.GetString(); } -sal_uInt8 ScDPItemData::GetType() const +sal_uInt8 ScDPItemData::GetCellType() const { - if ( IsHasErr() ) + if (meType == Error) return SC_VALTYPE_ERROR; - else if ( !IsHasData() ) + else if (meType == Empty) return SC_VALTYPE_EMPTY; else if ( IsValue()) return SC_VALTYPE_VALUE; @@ -134,83 +152,50 @@ sal_uInt8 ScDPItemData::GetType() const return SC_VALTYPE_STRING; } -bool ScDPItemData::IsHasData() const +bool ScDPItemData::IsEmpty() const { - return !!(mbFlag&MK_DATA); -} - -bool ScDPItemData::IsHasErr() const -{ - return !!(mbFlag&MK_ERR); + return meType == Empty; } bool ScDPItemData::IsValue() const { - return !!(mbFlag&MK_VAL); -} - -const rtl::OUString& ScDPItemData::GetString() const -{ - return maString; -} - -double ScDPItemData::GetValue() const -{ - return mfValue; + return meType == Value || meType == GroupValue; } -bool ScDPItemData::HasStringData() const +rtl::OUString ScDPItemData::GetString() const { - return IsHasData()&&!IsHasErr()&&!IsValue(); -} + if (meType == String) + return *mpString; -ScDPItemDataPool::ScDPItemDataPool() -{ + // TODO: Generate appropriate string. + return rtl::OUString(); } -ScDPItemDataPool::ScDPItemDataPool(const ScDPItemDataPool& r): - maItems(r.maItems), - maItemIds(r.maItemIds) -{ -} - -ScDPItemDataPool::~ScDPItemDataPool() +double ScDPItemData::GetValue() const { -} + if (meType == Value) + return mfValue; + if (meType == GroupValue) + return maGroupValue.mnValue; -const ScDPItemData* ScDPItemDataPool::getData( sal_Int32 nId ) -{ - if ( nId >= static_cast<sal_Int32>(maItems.size()) ) - return NULL; - else - return &(maItems[nId]); + return 0.0; } -sal_Int32 ScDPItemDataPool::getDataId( const ScDPItemData& aData ) +ScDPItemData::GroupValueAttr ScDPItemData::GetGroupValue() const { - DataHash::const_iterator itr = maItemIds.find( aData), - itrEnd = maItemIds.end(); - if ( itr == itrEnd ) - // not exist - return -1; - - else //exist - return itr->second; + if (meType == GroupValue) + return maGroupValue; + GroupValueAttr aGV; + aGV.mnGroupType = -1; + aGV.mnValue = -1; + return aGV; } -sal_Int32 ScDPItemDataPool::insertData( const ScDPItemData& aData ) +bool ScDPItemData::HasStringData() const { - sal_Int32 nResult = getDataId( aData ); - - if( nResult < 0 ) - { - maItemIds.insert( DataHash::value_type( aData, nResult = maItems.size() ) ); - maItems.push_back( aData ); - } - - return nResult; + return meType == String; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/core/data/dptabdat.cxx b/sc/source/core/data/dptabdat.cxx index dc76211608f9..4993207fc182 100644 --- a/sc/source/core/data/dptabdat.cxx +++ b/sc/source/core/data/dptabdat.cxx @@ -50,6 +50,49 @@ using namespace ::com::sun::star; using ::com::sun::star::uno::Sequence; using ::com::sun::star::uno::Any; using ::std::vector; + +#include <stdio.h> +#include <string> +#include <sys/time.h> + +namespace { + +class stack_printer +{ +public: + explicit stack_printer(const char* msg) : + msMsg(msg) + { + fprintf(stdout, "%s: --begin\n", msMsg.c_str()); + mfStartTime = getTime(); + } + + ~stack_printer() + { + double fEndTime = getTime(); + fprintf(stdout, "%s: --end (duration: %g sec)\n", msMsg.c_str(), (fEndTime-mfStartTime)); + } + + void printTime(int line) const + { + double fEndTime = getTime(); + fprintf(stdout, "%s: --(%d) (duration: %g sec)\n", msMsg.c_str(), line, (fEndTime-mfStartTime)); + } + +private: + double getTime() const + { + timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec + tv.tv_usec / 1000000.0; + } + + ::std::string msMsg; + double mfStartTime; +}; + +} + // --------------------------------------------------------------------------- ScDPTableData::CalcInfo::CalcInfo() : @@ -184,18 +227,19 @@ void ScDPTableData::FillRowDataFromCacheTable(sal_Int32 nRow, const ScDPCacheTab void ScDPTableData::ProcessRowData(CalcInfo& rInfo, CalcRowData& rData, bool bAutoShow) { + stack_printer __stack_printer__("ScDPTableData::ProcessRowData"); if (!bAutoShow) { - LateInitParams aColParams( rInfo.aColDims, rInfo.aColLevels, false ); - LateInitParams aRowParams ( rInfo.aRowDims, rInfo.aRowLevels, sal_True ); + LateInitParams aColParams(rInfo.aColDims, rInfo.aColLevels, false); + LateInitParams aRowParams(rInfo.aRowDims, rInfo.aRowLevels, true); // root always init child - aColParams.SetInitChild( sal_True ); + aColParams.SetInitChild(true); aColParams.SetInitAllChildren( false); - aRowParams.SetInitChild( sal_True ); + aRowParams.SetInitChild(true); aRowParams.SetInitAllChildren( false); - rInfo.pColRoot->LateInitFrom( aColParams, rData.aColData,0, *rInfo.pInitState); - rInfo.pRowRoot->LateInitFrom( aRowParams, rData.aRowData, 0, *rInfo.pInitState); + rInfo.pColRoot->LateInitFrom(aColParams, rData.aColData, 0, *rInfo.pInitState); + rInfo.pRowRoot->LateInitFrom(aRowParams, rData.aRowData, 0, *rInfo.pInitState); } if ( ( !rInfo.pColRoot->GetChildDimension() || rInfo.pColRoot->GetChildDimension()->IsValidEntry(rData.aColData) ) && @@ -204,7 +248,7 @@ void ScDPTableData::ProcessRowData(CalcInfo& rInfo, CalcRowData& rData, bool bAu //! single process method with ColMembers, RowMembers and data !!! if (rInfo.pColRoot->GetChildDimension()) { - vector</*ScDPItemData*/ SCROW > aEmptyData; + vector<SCROW> aEmptyData; rInfo.pColRoot->GetChildDimension()->ProcessData(rData.aColData, NULL, aEmptyData, rData.aValues); } diff --git a/sc/source/core/data/dptablecache.cxx b/sc/source/core/data/dptablecache.cxx index f4504e9063b1..372ca929f5fd 100644 --- a/sc/source/core/data/dptablecache.cxx +++ b/sc/source/core/data/dptablecache.cxx @@ -60,6 +60,48 @@ using ::com::sun::star::uno::UNO_QUERY_THROW; using ::std::vector; using ::std::auto_ptr; +#include <stdio.h> +#include <string> +#include <sys/time.h> + +namespace { + +class stack_printer +{ +public: + explicit stack_printer(const char* msg) : + msMsg(msg) + { + fprintf(stdout, "%s: --begin\n", msMsg.c_str()); + mfStartTime = getTime(); + } + + ~stack_printer() + { + double fEndTime = getTime(); + fprintf(stdout, "%s: --end (duration: %g sec)\n", msMsg.c_str(), (fEndTime-mfStartTime)); + } + + void printTime(int line) const + { + double fEndTime = getTime(); + fprintf(stdout, "%s: --(%d) (duration: %g sec)\n", msMsg.c_str(), line, (fEndTime-mfStartTime)); + } + +private: + double getTime() const + { + timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec + tv.tv_usec / 1000000.0; + } + + ::std::string msMsg; + double mfStartTime; +}; + +} + namespace { /** @@ -106,7 +148,6 @@ ScDPItemData* lcl_GetItemValue( rNumType = NUMBERFORMAT_NUMBER; try { - String rStr = xRow->getString(nCol); double fValue = 0.0; switch (nType) { @@ -115,7 +156,7 @@ ScDPItemData* lcl_GetItemValue( { rNumType = NUMBERFORMAT_LOGICAL; fValue = xRow->getBoolean(nCol) ? 1 : 0; - return new ScDPItemData(rStr, fValue, true); + return new ScDPItemData(fValue); } case sdbc::DataType::TINYINT: case sdbc::DataType::SMALLINT: @@ -129,7 +170,7 @@ ScDPItemData* lcl_GetItemValue( { //! do the conversion here? fValue = xRow->getDouble(nCol); - return new ScDPItemData(rStr, fValue, true); + return new ScDPItemData(fValue); } case sdbc::DataType::DATE: { @@ -137,7 +178,7 @@ ScDPItemData* lcl_GetItemValue( util::Date aDate = xRow->getDate(nCol); fValue = Date(aDate.Day, aDate.Month, aDate.Year) - rNullDate; - return new ScDPItemData(rStr, fValue, true); + return new ScDPItemData(fValue); } case sdbc::DataType::TIME: { @@ -146,7 +187,7 @@ ScDPItemData* lcl_GetItemValue( 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); + return new ScDPItemData(fValue); } case sdbc::DataType::TIMESTAMP: { @@ -156,7 +197,7 @@ ScDPItemData* lcl_GetItemValue( 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); + return new ScDPItemData(fValue); } case sdbc::DataType::CHAR: case sdbc::DataType::VARCHAR: @@ -166,7 +207,7 @@ ScDPItemData* lcl_GetItemValue( case sdbc::DataType::VARBINARY: case sdbc::DataType::LONGVARBINARY: default: - return new ScDPItemData(rStr); + return new ScDPItemData(xRow->getString(nCol)); } } catch (uno::Exception&) @@ -225,7 +266,6 @@ ScDPCache::Field::Field() {} ScDPCache::ScDPCache(ScDocument* pDoc) : mpDoc( pDoc ), mnColumnCount ( 0 ), - mpAdditionalData(new ScDPItemDataPool), mbDisposing(false) { } @@ -310,18 +350,8 @@ void initFromCell(ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab, ScDPItem else if (pDoc->HasValueData(nCol, nRow, nTab)) { double fVal = pDoc->GetValue(aPos); - sal_uLong nFormatType = NUMBERFORMAT_NUMBER; rNumFormat = pDoc->GetNumberFormat(aPos); - sal_uInt8 nFlag = ScDPItemData::MK_VAL | ScDPItemData::MK_DATA; - - SvNumberFormatter* pFormatter = pDoc->GetFormatTable(); - if (pFormatter) - nFormatType = pFormatter->GetType(rNumFormat); - - if (ScDPItemData::isDate(nFormatType)) - nFlag |= ScDPItemData::MK_DATE; - - rData.Set(aDocStr, fVal, nFlag); + rData.SetValue(fVal); } else if (pDoc->HasData(nCol, nRow, nTab)) { @@ -464,11 +494,11 @@ bool ScDPCache::ValidQuery( SCROW nRow, const ScQueryParam &rParam) const if (rEntry.GetQueryItem().meType == ScQueryEntry::ByEmpty) { if (rEntry.IsQueryByEmpty()) - bOk = !pCellData->IsHasData(); + bOk = pCellData->IsEmpty(); else { OSL_ASSERT(rEntry.IsQueryByNonEmpty()); - bOk = pCellData->IsHasData(); + bOk = !pCellData->IsEmpty(); } } else if (rEntry.GetQueryItem().meType != ScQueryEntry::ByString && pCellData->IsValue()) @@ -656,7 +686,7 @@ bool ScDPCache::AddData(long nDim, ScDPItemData* pData, sal_uLong nNumFormat) while ( mbEmptyRow.size() <= nCurRow ) mbEmptyRow.push_back( true ); - if ( pData->IsHasData() ) + if (!pData->IsEmpty()) mbEmptyRow[ nCurRow ] = false; return true; @@ -729,7 +759,7 @@ SCROW ScDPCache::GetItemDataId(sal_uInt16 nDim, SCROW nRow, bool bRepeatIfEmpty) const Field& rField = maFields[nDim]; if (bRepeatIfEmpty) { - while (nRow > 0 && !rField.maItems[rField.maData[nRow]].IsHasData()) + while (nRow > 0 && rField.maItems[rField.maData[nRow]].IsEmpty()) --nRow; } @@ -738,14 +768,61 @@ SCROW ScDPCache::GetItemDataId(sal_uInt16 nDim, SCROW nRow, bool bRepeatIfEmpty) const ScDPItemData* ScDPCache::GetItemDataById(long nDim, SCROW nId) const { - if ( nId >= GetRowCount() ) - return mpAdditionalData->getData(nId - GetRowCount()); +// stack_printer __stack_printer__("ScDPCache::GetItemDataById"); +// fprintf(stdout, "ScDPCache::GetItemDataById: dim = %d id = %d\n", nDim, nId); + if (nDim < 0) + { + fprintf(stdout, "ScDPCache::GetItemDataById: fail (%d)\n", __LINE__); + return NULL; + } - const Field& rField = maFields[nDim]; - if (static_cast<size_t>(nId) >= rField.maItems.size() || nDim >= mnColumnCount || nId < 0) + long nSourceCount = static_cast<long>(maFields.size()); + if (nDim < nSourceCount) + { + // source field. + const Field& rField = maFields[nDim]; + if (nId < rField.maItems.size()) + { +// fprintf(stdout, "ScDPCache::GetItemDataById: s = '%s' (source)\n", +// rtl::OUStringToOString(rField.maItems[nId].GetString(), RTL_TEXTENCODING_UTF8).getStr()); + return &rField.maItems[nId]; + } + + if (!rField.mpGroup) + { + fprintf(stdout, "ScDPCache::GetItemDataById: fail (%d)\n", __LINE__); + return NULL; + } + + nId -= rField.maItems.size(); + const DataListType& rGI = rField.mpGroup->maItems; + if (nId >= rGI.size()) + { + fprintf(stdout, "ScDPCache::GetItemDataById: fail (%d)\n", __LINE__); + return NULL; + } +// fprintf(stdout, "ScDPCache::GetItemDataById: s = '%s' (grouped source field)\n", +// rtl::OUStringToOString(rGI[nId].GetString(), RTL_TEXTENCODING_UTF8).getStr()); + return &rGI[nId]; + } + + // Try group fields. + nDim -= nSourceCount; + if (nDim >= maGroupFields.size()) + { + fprintf(stdout, "ScDPCache::GetItemDataById: fail (%d)\n", __LINE__); return NULL; - else - return &rField.maItems[nId]; + } + + const DataListType& rGI = maGroupFields[nDim].maItems; + if (nId >= rGI.size()) + { + fprintf(stdout, "ScDPCache::GetItemDataById: fail (%d)\n", __LINE__); + return NULL; + } +// fprintf(stdout, "ScDPCache::GetItemDataById: s = '%s' (group field)\n", +// rtl::OUStringToOString(rGI[nId].GetString(), RTL_TEXTENCODING_UTF8).getStr()); + return &rGI[nId]; } SCROW ScDPCache::GetRowCount() const @@ -841,23 +918,56 @@ const ScDPCache::ObjectSetType& ScDPCache::GetAllReferences() const SCROW ScDPCache::GetIdByItemData(long nDim, const rtl::OUString& sItemData) const { - if ( nDim < mnColumnCount && nDim >=0 ) +// stack_printer __stack_printer__("ScDPCache::GetIdByItemData"); +// fprintf(stdout, "ScDPCache::GetIdByItemData: dim = %ld s = '%s'\n", +// nDim, rtl::OUStringToOString(sItemData, RTL_TEXTENCODING_UTF8).getStr()); + if (nDim < 0) + return -1; + + if (nDim < mnColumnCount) { + // source field. const DataListType& rItems = maFields[nDim].maItems; for (size_t i = 0, n = rItems.size(); i < n; ++i) { +// fprintf(stdout, "ScDPCache::GetIdByItemData: source item = '%s'\n", rtl::OUStringToOString(rItems[i].GetString(), RTL_TEXTENCODING_UTF8).getStr()); if (rItems[i].GetString() == sItemData) return i; } + + if (!maFields[nDim].mpGroup) + return -1; + + // grouped source field. + const DataListType& rGI = maFields[nDim].mpGroup->maItems; + for (size_t i = 0, n = rGI.size(); i < n; ++i) + { +// fprintf(stdout, "ScDPCache::GetIdByItemData: grouped source item = '%s'\n", rtl::OUStringToOString(rGI[i].GetString(), RTL_TEXTENCODING_UTF8).getStr()); + if (rGI[i].GetString() == sItemData) + return rItems.size() + i; + } + return -1; } - ScDPItemData rData ( sItemData ); - return GetRowCount() + mpAdditionalData->getDataId(rData); + // group field. + nDim -= mnColumnCount; + if (nDim < maGroupFields.size()) + { + const DataListType& rGI = maGroupFields[nDim].maItems; + for (size_t i = 0, n = rGI.size(); i < n; ++i) + { +// fprintf(stdout, "ScDPCache::GetIdByItemData: grouped item = '%s'\n", rtl::OUStringToOString(rGI[i].GetString(), RTL_TEXTENCODING_UTF8).getStr()); + if (rGI[i].GetString() == sItemData) + return i; + } + } + return -1; } SCROW ScDPCache::GetIdByItemData(long nDim, const ScDPItemData& rData) const { + fprintf(stdout, "ScDPCache::GetIdByItemData: FIXME\n"); if ( nDim < mnColumnCount && nDim >=0 ) { const DataListType& rItems = maFields[nDim].maItems; @@ -867,12 +977,57 @@ SCROW ScDPCache::GetIdByItemData(long nDim, const ScDPItemData& rData) const return i; } } - return GetRowCount() + mpAdditionalData->getDataId(rData); + return -1; } -SCROW ScDPCache::GetAdditionalItemID( const ScDPItemData& rData ) const +void ScDPCache::AppendGroupField() { - return GetRowCount() + mpAdditionalData->insertData(rData); + maGroupFields.push_back(new GroupField); +} + +void ScDPCache::ResetGroupItems(long nDim) +{ + if (nDim < 0) + return; + + long nSourceCount = static_cast<long>(maFields.size()); + if (nDim < nSourceCount) + { + maFields.at(nDim).mpGroup.reset(new GroupItems); + return; + } + + nDim -= nSourceCount; + if (nDim < static_cast<long>(maGroupFields.size())) + maGroupFields[nDim].maItems.clear(); +} + +SCROW ScDPCache::SetGroupItem(long nDim, const ScDPItemData& rData) +{ + long nSourceCount = static_cast<long>(maFields.size()); + if (nDim < nSourceCount) + { + GroupItems& rGI = *maFields.at(nDim).mpGroup; + rGI.maItems.push_back(new ScDPItemData(rData)); + SCROW nId = maFields[nDim].maItems.size() + rGI.maItems.size() - 1; + return nId; + } + + nDim -= nSourceCount; + if (nDim < static_cast<long>(maGroupFields.size())) + { + DataListType& rItems = maGroupFields.at(nDim).maItems; + rItems.push_back(new ScDPItemData(rData)); + return rItems.size()-1; + } + + return -1; +} + +SCROW ScDPCache::GetAdditionalItemID(const ScDPItemData&) const +{ + fprintf(stdout, "ScDPCache::GetAdditionalItemID: FIXME\n"); + return -1; } @@ -907,4 +1062,9 @@ long ScDPCache::GetColumnCount() const return mnColumnCount; } +long ScDPCache::GetGroupFieldCount() const +{ + return maGroupFields.size(); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/core/data/dptabres.cxx b/sc/source/core/data/dptabres.cxx index 421c17d6647c..7a59b0ea4fef 100644 --- a/sc/source/core/data/dptabres.cxx +++ b/sc/source/core/data/dptabres.cxx @@ -68,6 +68,48 @@ using ::std::pair; using ::com::sun::star::uno::Sequence; using ::rtl::OUString; +#include <stdio.h> +#include <string> +#include <sys/time.h> + +namespace { + +class stack_printer +{ +public: + explicit stack_printer(const char* msg) : + msMsg(msg) + { + fprintf(stdout, "%s: --begin\n", msMsg.c_str()); + mfStartTime = getTime(); + } + + ~stack_printer() + { + double fEndTime = getTime(); + fprintf(stdout, "%s: --end (duration: %g sec)\n", msMsg.c_str(), (fEndTime-mfStartTime)); + } + + void printTime(int line) const + { + double fEndTime = getTime(); + fprintf(stdout, "%s: --(%d) (duration: %g sec)\n", msMsg.c_str(), line, (fEndTime-mfStartTime)); + } + +private: + double getTime() const + { + timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec + tv.tv_usec / 1000000.0; + } + + ::std::string msMsg; + double mfStartTime; +}; + +} + // ----------------------------------------------------------------------- static sal_uInt16 nFuncStrIds[12] = // passend zum enum ScSubTotalFunc @@ -932,6 +974,7 @@ bool ScDPResultData::IsInGroup( const ScDPItemData& rGroupData, long nGroupIndex bool ScDPResultData::IsInGroup( SCROW nGroupDataId, long nGroupIndex, const ScDPItemData& rBaseData, long nBaseIndex ) const { + fprintf(stdout, "ScDPResultData::IsInGroup: dim = %d id = %d\n", nGroupIndex, nGroupDataId); const ScDPItemData* pGroupData = pSource->GetItemDataById( nGroupIndex , nGroupDataId); if ( pGroupData ) return pSource->GetData()->IsInGroup( *pGroupData, nGroupIndex, rBaseData , nBaseIndex ); @@ -1112,9 +1155,8 @@ void ScDPResultMember::InitFrom( const vector<ScDPDimension*>& ppDim, const vect } } -void ScDPResultMember::LateInitFrom( LateInitParams& rParams/*const vector<ScDPDimension*>& ppDim, const vector<ScDPLevel*>& ppLev*/, - const vector< SCROW >& pItemData, size_t nPos, - ScDPInitState& rInitState ) +void ScDPResultMember::LateInitFrom( + LateInitParams& rParams, const vector<SCROW>& pItemData, size_t nPos, ScDPInitState& rInitState) { // without LateInit, everything has already been initialized if ( !pResultData->IsLateInit() ) @@ -1226,10 +1268,23 @@ long ScDPResultMember::GetSize(long nMeasure) const sal_Bool ScDPResultMember::IsVisible() const { +// fprintf(stdout, "ScDPResultMember::IsVisible: initialized = %d valid = %d has elements = %d\n", +// bInitialized, IsValid(), bHasElements); + + if (!bInitialized) + return false; + + if (!IsValid()) + return false; + + if (bHasElements) + return true; + // not initialized -> shouldn't be there at all // (allocated only to preserve ordering) - const ScDPLevel* pParentLevel = GetParentLevel(); - return ( bHasElements || ( pParentLevel && pParentLevel->getShowEmpty() ) ) && IsValid() && bInitialized; + const ScDPLevel* pParentLevel = GetParentLevel(); + + return (pParentLevel && pParentLevel->getShowEmpty()); } sal_Bool ScDPResultMember::IsValid() const @@ -1356,6 +1411,7 @@ void ScDPResultMember::FillMemberResults( uno::Sequence<sheet::MemberResult>* pS const String* pMemberName, const String* pMemberCaption ) { +// stack_printer __stack_printer__("ScDPResultMember::FillMemberResults"); // IsVisible() test is in ScDPResultDimension::FillMemberResults // (not on data layout dimension) @@ -1370,7 +1426,9 @@ void ScDPResultMember::FillMemberResults( uno::Sequence<sheet::MemberResult>* pS sal_Bool bIsNumeric = false; String aName; if ( pMemberName ) // if pMemberName != NULL, use instead of real member name + { aName = *pMemberName; + } else { ScDPItemData aItemData; @@ -1378,6 +1436,10 @@ void ScDPResultMember::FillMemberResults( uno::Sequence<sheet::MemberResult>* pS aName = aItemData.GetString(); bIsNumeric = aItemData.IsValue(); } + + fprintf(stdout, "ScDPResultMember::FillMemberResults: name = '%s' numeric = %d\n", + rtl::OUStringToOString(aName, RTL_TEXTENCODING_UTF8).getStr(), bIsNumeric); + const ScDPDimension* pParentDim = GetParentDim(); if ( bIsNumeric && pParentDim && pResultData->IsNumOrDateGroup( pParentDim->GetDimension() ) ) { @@ -2666,32 +2728,44 @@ ScDPGroupCompare::ScDPGroupCompare( const ScDPResultData* pData, const ScDPInitS sal_Bool ScDPGroupCompare::TestIncluded( const ScDPMember& rMember ) { - sal_Bool bInclude = sal_True; + stack_printer __stack_printer__("ScDPGroupCompare::TestIncluded"); + fprintf(stdout, "ScDPGroupCompare::TestIncluded: dim source = %d group base = %d, base data id = %d\n", + nDimSource, nGroupBase, nBaseDataId); + bool bInclude = true; if ( nBaseDataId >=0 ) { + fprintf(stdout, "ScDPGroupCompare::TestIncluded: case 1 (this should not happen)\n"); ScDPItemData aMemberData; rMember.FillItemData( aMemberData ); bInclude = pResultData->IsInGroup( aMemberData, nDimSource, nBaseDataId, nGroupBase ); } else if ( bIsBase ) { + fprintf(stdout, "ScDPGroupCompare::TestIncluded: case 2 (source dim)\n"); // need to check all previous groups //! get array of groups (or indexes) before loop? ScDPItemData aMemberData; rMember.FillItemData( aMemberData ); + fprintf(stdout, "ScDPGroupCompare::TestIncluded: s = '%s'\n", rtl::OUStringToOString(aMemberData.GetString(), RTL_TEXTENCODING_UTF8).getStr()); long nInitCount = rInitState.GetCount(); const long* pInitSource = rInitState.GetSource(); - /*const ScDPItemData* pInitNames = rInitState.GetNames();*/ const SCROW* pInitNames = rInitState.GetNameIds(); + for (long nInitPos=0; nInitPos<nInitCount; nInitPos++) + { + fprintf(stdout, "ScDPGroupCompare::TestIncluded: source = %d name id = %d\n", pInitSource[nInitPos], pInitNames[nInitPos]); + } for (long nInitPos=0; nInitPos<nInitCount && bInclude; nInitPos++) + { if ( pResultData->GetGroupBase( pInitSource[nInitPos] ) == nDimSource ) { bInclude = pResultData->IsInGroup( pInitNames[nInitPos], pInitSource[nInitPos], aMemberData, nDimSource ); } + } } else if ( nGroupBase >= 0 ) { + fprintf(stdout, "ScDPGroupCompare::TestIncluded: case 3 (group dim?)\n"); // base isn't used in preceding fields // -> look for other groups using the same base @@ -2738,11 +2812,23 @@ ScDPResultDimension::~ScDPResultDimension() ScDPResultMember *ScDPResultDimension::FindMember( SCROW iData ) const { +// stack_printer __stack_printer__("ScDPResultDimension::FindMember"); +// fprintf(stdout, "ScDPResultDimension::FindMember: iData = %d\n", iData); if( bIsDataLayout ) return maMemberArray[0]; +// fprintf(stdout, "ScDPResultDimension::FindMember: hash size = %d\n", maMemberHash.size()); +// { +// MemberHash::const_iterator i = maMemberHash.begin(), ie = maMemberHash.end(); +// for (; i != ie; ++i) +// { +// printf("%d ", i->first); +// } +// printf("\n"); +// } MemberHash::const_iterator aRes = maMemberHash.find( iData ); if( aRes != maMemberHash.end()) { +// fprintf(stdout, "ScDPResultDimension::FindMember: in hash\n"); if ( aRes->second->IsNamedItem( iData ) ) return aRes->second; OSL_FAIL("problem! hash result is not the same as IsNamedItem"); @@ -2750,13 +2836,19 @@ ScDPResultMember *ScDPResultDimension::FindMember( SCROW iData ) const unsigned int i; unsigned int nCount = maMemberArray.size(); +// fprintf(stdout, "ScDPResultDimension::FindMember: member size = %d\n", nCount); ScDPResultMember* pResultMember; for( i = 0; i < nCount ; i++ ) { pResultMember = maMemberArray[i]; +// fprintf(stdout, "ScDPResultDimension::FindMember: pResultMember = %p\n", pResultMember); if ( pResultMember->IsNamedItem( iData ) ) + { +// fprintf(stdout, "ScDPResultDimension::FindMember: not in hash but found it.\n"); return pResultMember; + } } +// fprintf(stdout, "ScDPResultDimension::FindMember: total fail\n"); return NULL; } @@ -2827,9 +2919,8 @@ void ScDPResultDimension::InitFrom( const vector<ScDPDimension*>& ppDim, const v bInitialized = sal_True; } -void ScDPResultDimension::LateInitFrom( LateInitParams& rParams/* const vector<ScDPDimension*>& ppDim, const vector<ScDPLevel*>& ppLev*/, - const vector<SCROW>& pItemData, size_t nPos, - ScDPInitState& rInitState ) +void ScDPResultDimension::LateInitFrom( + LateInitParams& rParams, const vector<SCROW>& pItemData, size_t nPos, ScDPInitState& rInitState) { if ( rParams.IsEnd( nPos ) ) return; @@ -2923,7 +3014,7 @@ void ScDPResultDimension::LateInitFrom( LateInitParams& rParams/* const vector<S if ( pResultMember->IsNamedItem( rThisData ) ) bAllChildren = false; else - bAllChildren = sal_True; + bAllChildren = true; } rParams.SetInitAllChildren( bAllChildren ); rInitState.AddMember( nDimSource, pResultMember->GetDataId() ); @@ -2965,13 +3056,18 @@ long ScDPResultDimension::GetSize(long nMeasure) const } return nTotal; } - +//#include <iostream> bool ScDPResultDimension::IsValidEntry( const vector< SCROW >& aMembers ) const { +// stack_printer __stack_printer__("ScDPResultDimension::IsValidEntry"); +// fprintf(stdout, "ScDPResultDimension::IsValidEntry: dim name = '%s'\n", rtl::OUStringToOString(aDimensionName, RTL_TEXTENCODING_UTF8).getStr()); if (aMembers.empty()) return false; +// std::copy(aMembers.begin(),aMembers.end(), std::ostream_iterator<SCROW>(std::cout, " "));std::cout << std::endl; + const ScDPResultMember* pMember = FindMember( aMembers[0] ); +// fprintf(stdout, "ScDPResultDimension::IsValidEntry: pMember = %p id = %d\n", pMember, aMembers[0]); if ( NULL != pMember ) return pMember->IsValidEntry( aMembers ); #if OSL_DEBUG_LEVEL > 1 @@ -3027,7 +3123,12 @@ void ScDPResultDimension::FillMemberResults( uno::Sequence<sheet::MemberResult>* maMemberArray[0]->FillMemberResults( pSequences, nPos, nSorted, false, &aMbrName, &aMbrCapt ); } else if ( pMember->IsVisible() ) + { + fprintf(stdout, "ScDPResultDimension::FillMemberResults: member visible\n"); pMember->FillMemberResults( pSequences, nPos, nMeasure, false, NULL, NULL ); + } + else + fprintf(stdout, "ScDPResultDimension::FillMemberResults: member not visible\n"); // nPos is modified } } @@ -3916,6 +4017,7 @@ SCROW ScDPResultMember::GetDataId( ) const ScDPResultMember* ScDPResultDimension::AddMember(const ScDPParentDimData &aData ) { + fprintf(stdout, "ScDPResultDimension::AddMember: dim name = '%s'\n", rtl::OUStringToOString(aDimensionName, RTL_TEXTENCODING_UTF8).getStr()); ScDPResultMember* pMember = new ScDPResultMember( pResultData, aData, false ); SCROW nDataIndex = pMember->GetDataId(); maMemberArray.push_back( pMember ); @@ -3927,9 +4029,11 @@ ScDPResultMember* ScDPResultDimension::AddMember(const ScDPParentDimData &aData ScDPResultMember* ScDPResultDimension::InsertMember(ScDPParentDimData *pMemberData) { + fprintf(stdout, "ScDPResultDimension::InsertMember: dim name = '%s'\n", rtl::OUStringToOString(aDimensionName, RTL_TEXTENCODING_UTF8).getStr()); SCROW nInsert = 0; if ( !lcl_SearchMember( maMemberArray, pMemberData->mnOrder , nInsert ) ) - { //Member not exist + { + fprintf(stdout, "ScDPResultDimension::InsertMember: member doesn't exist\n"); ScDPResultMember* pNew = new ScDPResultMember( pResultData, *pMemberData, false ); maMemberArray.insert( maMemberArray.begin()+nInsert, pNew ); @@ -3938,13 +4042,14 @@ ScDPResultMember* ScDPResultDimension::InsertMember(ScDPParentDimData *pMemberDa maMemberHash.insert( std::pair< SCROW, ScDPResultMember *>( nDataIndex, pNew ) ); return pNew; } + else + fprintf(stdout, "ScDPResultDimension::InsertMember: member exists. no insert.\n"); return maMemberArray[ nInsert ]; } -void ScDPResultDimension:: InitWithMembers( LateInitParams& rParams, - const ::std::vector< SCROW >& pItemData, - size_t nPos, - ScDPInitState& rInitState ) +void ScDPResultDimension::InitWithMembers( + LateInitParams& rParams, const std::vector<SCROW>& pItemData, size_t nPos, + ScDPInitState& rInitState) { if ( rParams.IsEnd( nPos ) ) return; @@ -3954,6 +4059,7 @@ void ScDPResultDimension:: InitWithMembers( LateInitParams& rParams, if (pThisDim && pThisLevel) { + stack_printer __stack_printer__("ScDPResultDimension::InitWithMembers"); long nDimSource = pThisDim->GetDimension(); //! check GetSourceDim? // create all members at the first call (preserve order) @@ -3968,7 +4074,11 @@ void ScDPResultDimension:: InitWithMembers( LateInitParams& rParams, if ( pResultMember == NULL ) { //only insert found item + fprintf(stdout, "ScDPResultDimension::InitWithMembers: insert (dim name = '%s'; id = %d)\n", + rtl::OUStringToOString(aDimensionName, RTL_TEXTENCODING_UTF8).getStr(), nDataID); ScDPParentDimData* pMemberData = pMembers->FindMember( nDataID ); + fprintf(stdout, "ScDPResultDimension::InitWithMembers: included = %d\n", + aCompare.IsIncluded(*pMemberData->mpMemberDesc)); if ( pMemberData && aCompare.IsIncluded( *( pMemberData->mpMemberDesc ) ) ) pResultMember = InsertMember( pMemberData ); } @@ -4027,36 +4137,36 @@ sal_Bool LateInitParams::IsEnd( size_t nPos ) const void ScDPResultDimension::CheckShowEmpty( sal_Bool bShow ) { - long nCount = maMemberArray.size(); + long nCount = maMemberArray.size(); - ScDPResultMember* pMember = NULL; - for (long i=0; i<nCount; i++) - { - pMember = maMemberArray.at(i); - pMember->CheckShowEmpty( bShow ); - } + ScDPResultMember* pMember = NULL; + for (long i=0; i<nCount; i++) + { + pMember = maMemberArray.at(i); + pMember->CheckShowEmpty(bShow); + } } void ScDPResultMember::CheckShowEmpty( sal_Bool bShow ) { - if ( bHasElements ) - { - ScDPResultDimension* pChildDim = GetChildDimension(); - if (pChildDim ) - pChildDim->CheckShowEmpty(); - } - else if ( IsValid() && bInitialized ) + if (bHasElements) + { + ScDPResultDimension* pChildDim = GetChildDimension(); + if (pChildDim) + pChildDim->CheckShowEmpty(); + } + else if (IsValid() && bInitialized) + { + bShow = bShow || (GetParentLevel() && GetParentLevel()->getShowEmpty()); + if (bShow) { - bShow = bShow || ( GetParentLevel() && GetParentLevel()->getShowEmpty() ); - if ( bShow ) - { - SetHasElements(); - ScDPResultDimension* pChildDim = GetChildDimension(); - if (pChildDim ) - pChildDim->CheckShowEmpty( sal_True ); - } + SetHasElements(); + ScDPResultDimension* pChildDim = GetChildDimension(); + if (pChildDim) + pChildDim->CheckShowEmpty(true); } + } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/core/data/dptabsrc.cxx b/sc/source/core/data/dptabsrc.cxx index 24dc55f4cfa0..e37654169919 100644 --- a/sc/source/core/data/dptabsrc.cxx +++ b/sc/source/core/data/dptabsrc.cxx @@ -1022,6 +1022,7 @@ void ScDPSource::FillLevelList( sal_uInt16 nOrientation, std::vector<ScDPLevel*> for (long nLev=0; nLev<nLevCount; nLev++) { ScDPLevel* pLevel = pLevels->getByIndex(nLev); +// fprintf(stdout, "ScDPSource::FillLevelList: level name = '%s'\n", rtl::OUStringToOString(pLevel->getName(), RTL_TEXTENCODING_UTF8).getStr()); rList.push_back(pLevel); } } @@ -1473,7 +1474,7 @@ const ScDPItemData& ScDPDimension::GetSelectedData() } if ( !pSelectedData ) - pSelectedData = new ScDPItemData( aSelectedPage, 0.0, false ); // default - name only + pSelectedData = new ScDPItemData(aSelectedPage); // default - name only } return *pSelectedData; @@ -2524,7 +2525,8 @@ ScDPMember* ScDPMembers::getByIndex(long nIndex) const if (aName.isEmpty()) aName = rtl::OUString::valueOf(nVal); - ScDPItemData aData(aName, nVal, true, 0); + // TODO: This needs fixing. + ScDPItemData aData(nVal); pNew = new ScDPMember( pSource, nDim, nHier, nLev, pSource->GetCache()->GetAdditionalItemID(aData)); } @@ -2570,10 +2572,11 @@ ScDPMember::~ScDPMember() bool ScDPMember::IsNamedItem(SCROW nIndex) const { long nSrcDim = pSource->GetSourceDim( nDim ); + fprintf(stdout, "ScDPMember::IsNamedItem: dim = %d src dim = %d\n", nDim, nSrcDim); if ( nHier != SC_DAPI_HIERARCHY_FLAT && pSource->IsDateDimension( nSrcDim ) ) { - const ScDPItemData* pData = pSource->GetCache()->GetItemDataById( (SCCOL) nSrcDim, nIndex ); - if ( pData->IsValue() ) + const ScDPItemData* pData = pSource->GetCache()->GetItemDataById(nDim, nIndex); + if (pData->IsValue()) { long nComp = pSource->GetData()->GetDatePart( (long)::rtl::math::approxFloor( pData->GetValue() ), @@ -2583,6 +2586,7 @@ bool ScDPMember::IsNamedItem(SCROW nIndex) const } } + fprintf(stdout, "ScDPMember::IsNamedItem: result = %d\n", nIndex == mnDataId); return nIndex == mnDataId; } diff --git a/sc/source/core/data/dputil.cxx b/sc/source/core/data/dputil.cxx index 65a1ee51d297..94e022359807 100644 --- a/sc/source/core/data/dputil.cxx +++ b/sc/source/core/data/dputil.cxx @@ -27,8 +27,31 @@ */ #include "dputil.hxx" +#include "global.hxx" #include "comphelper/string.hxx" +#include "unotools/localedatawrapper.hxx" +#include "unotools/calendarwrapper.hxx" +#include "svl/zforlist.hxx" + +#include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp> +#include <com/sun/star/i18n/CalendarDisplayIndex.hpp> + +using namespace com::sun::star; + +namespace { + +const sal_uInt16 SC_DP_LEAPYEAR = 1648; // arbitrary leap year for date calculations + +String getTwoDigitString( sal_Int32 nValue ) +{ + String aRet = String::CreateFromInt32( nValue ); + if ( aRet.Len() < 2 ) + aRet.Insert( (sal_Unicode)'0', 0 ); + return aRet; +} + +} bool ScDPUtil::isDuplicateDimension(const rtl::OUString& rName) { @@ -56,4 +79,50 @@ rtl::OUString ScDPUtil::createDuplicateDimensionName(const rtl::OUString& rOrigi return aBuf.makeStringAndClear(); } +rtl::OUString ScDPUtil::getDateGroupName( + sal_Int32 nDatePart, sal_Int32 nValue, SvNumberFormatter* pFormatter) +{ + switch ( nDatePart ) + { + case sheet::DataPilotFieldGroupBy::YEARS: + return rtl::OUString::valueOf(nValue); + case sheet::DataPilotFieldGroupBy::QUARTERS: + return ScGlobal::pLocaleData->getQuarterAbbreviation(sal_Int16(nValue-1)); // nValue is 1-based + case com::sun::star::sheet::DataPilotFieldGroupBy::MONTHS: + return ScGlobal::GetCalendar()->getDisplayName( + i18n::CalendarDisplayIndex::MONTH, sal_Int16(nValue-1), 0); // 0-based, get short name + case sheet::DataPilotFieldGroupBy::DAYS: + { + Date aDate(1, 1, SC_DP_LEAPYEAR); + aDate += (nValue - 1); // nValue is 1-based + Date aNullDate = *pFormatter->GetNullDate(); + long nDays = aDate - aNullDate; + + sal_uLong nFormat = pFormatter->GetFormatIndex(NF_DATE_SYS_DDMMM, ScGlobal::eLnge); + Color* pColor; + String aStr; + pFormatter->GetOutputString(nDays, nFormat, aStr, &pColor); + return aStr; + } + case sheet::DataPilotFieldGroupBy::HOURS: + { + //! allow am/pm format? + return getTwoDigitString(nValue); + } + break; + case sheet::DataPilotFieldGroupBy::MINUTES: + case sheet::DataPilotFieldGroupBy::SECONDS: + { + rtl::OUStringBuffer aBuf(ScGlobal::pLocaleData->getTimeSep()); + aBuf.append(getTwoDigitString(nValue)); + return aBuf.makeStringAndClear(); + } + break; + default: + OSL_FAIL("invalid date part"); + } + + return rtl::OUString(); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/excel/xepivot.cxx b/sc/source/filter/excel/xepivot.cxx index 234ecc065d50..3a07b0e2d1a3 100644 --- a/sc/source/filter/excel/xepivot.cxx +++ b/sc/source/filter/excel/xepivot.cxx @@ -547,7 +547,7 @@ void XclExpPCField::InsertNumDateGroupItems( const ScDPObject& rDPObj, const ScD // get the string collection with generated grouping elements ScDPNumGroupDimension aTmpDim( rNumInfo ); if( nDatePart != 0 ) - aTmpDim.MakeDateHelper( rNumInfo, nDatePart ); + aTmpDim.MakeDateHelper( rNumInfo, mnFieldIdx, nDatePart ); const std::vector<SCROW>& aMemberIds = aTmpDim.GetNumEntries( static_cast<SCCOL>( GetBaseFieldIndex() ), aDPData.GetCacheTable().getCache(), aOrignial); for ( size_t nIdx = 0 ; nIdx < aMemberIds.size(); nIdx++ ) |