1*b3f79822SAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
3*b3f79822SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
4*b3f79822SAndrew Rist * or more contributor license agreements. See the NOTICE file
5*b3f79822SAndrew Rist * distributed with this work for additional information
6*b3f79822SAndrew Rist * regarding copyright ownership. The ASF licenses this file
7*b3f79822SAndrew Rist * to you under the Apache License, Version 2.0 (the
8*b3f79822SAndrew Rist * "License"); you may not use this file except in compliance
9*b3f79822SAndrew Rist * with the License. You may obtain a copy of the License at
10cdf0e10cSrcweir *
11*b3f79822SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir *
13*b3f79822SAndrew Rist * Unless required by applicable law or agreed to in writing,
14*b3f79822SAndrew Rist * software distributed under the License is distributed on an
15*b3f79822SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b3f79822SAndrew Rist * KIND, either express or implied. See the License for the
17*b3f79822SAndrew Rist * specific language governing permissions and limitations
18*b3f79822SAndrew Rist * under the License.
19cdf0e10cSrcweir *
20*b3f79822SAndrew Rist *************************************************************/
21*b3f79822SAndrew Rist
22*b3f79822SAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sc.hxx"
26cdf0e10cSrcweir
27cdf0e10cSrcweir
28cdf0e10cSrcweir
29cdf0e10cSrcweir // INCLUDE ---------------------------------------------------------------
30cdf0e10cSrcweir
31cdf0e10cSrcweir #include <com/sun/star/i18n/CalendarDisplayIndex.hpp>
32cdf0e10cSrcweir
33cdf0e10cSrcweir #include <tools/debug.hxx>
34cdf0e10cSrcweir #include <rtl/math.hxx>
35cdf0e10cSrcweir #include <unotools/localedatawrapper.hxx>
36cdf0e10cSrcweir #include <svl/zforlist.hxx>
37cdf0e10cSrcweir
38cdf0e10cSrcweir #include "dpgroup.hxx"
39cdf0e10cSrcweir #include "collect.hxx"
40cdf0e10cSrcweir #include "global.hxx"
41cdf0e10cSrcweir #include "document.hxx"
42cdf0e10cSrcweir #include "dpcachetable.hxx"
43cdf0e10cSrcweir #include "dptabsrc.hxx"
44cdf0e10cSrcweir #include "dptabres.hxx"
45cdf0e10cSrcweir #include "dpobject.hxx"
46cdf0e10cSrcweir #include "dpglobal.hxx"
47cdf0e10cSrcweir
48cdf0e10cSrcweir #include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
49cdf0e10cSrcweir #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
50cdf0e10cSrcweir
51cdf0e10cSrcweir #include <vector>
52cdf0e10cSrcweir #include <hash_set>
53cdf0e10cSrcweir #include <hash_map>
54cdf0e10cSrcweir
55cdf0e10cSrcweir using namespace ::com::sun::star;
56cdf0e10cSrcweir using ::com::sun::star::uno::Any;
57cdf0e10cSrcweir using ::com::sun::star::uno::Reference;
58cdf0e10cSrcweir using ::com::sun::star::uno::Sequence;
59cdf0e10cSrcweir using ::com::sun::star::uno::UNO_QUERY;
60cdf0e10cSrcweir using ::com::sun::star::uno::UNO_QUERY_THROW;
61cdf0e10cSrcweir using ::rtl::OUString;
62cdf0e10cSrcweir using ::rtl::OUStringHash;
63cdf0e10cSrcweir
64cdf0e10cSrcweir using ::std::vector;
65cdf0e10cSrcweir using ::std::hash_set;
66cdf0e10cSrcweir using ::std::hash_map;
67cdf0e10cSrcweir using ::boost::shared_ptr;
68cdf0e10cSrcweir
69cdf0e10cSrcweir #define D_TIMEFACTOR 86400.0
70cdf0e10cSrcweir
71cdf0e10cSrcweir const sal_uInt16 SC_DP_LEAPYEAR = 1648; // arbitrary leap year for date calculations
72cdf0e10cSrcweir
73cdf0e10cSrcweir // part values for the extra "<" and ">" entries (same for all parts)
74cdf0e10cSrcweir const sal_Int32 SC_DP_DATE_FIRST = -1;
75cdf0e10cSrcweir const sal_Int32 SC_DP_DATE_LAST = 10000;
76cdf0e10cSrcweir
77cdf0e10cSrcweir // ============================================================================
78cdf0e10cSrcweir namespace
79cdf0e10cSrcweir {
lcl_Search(SCCOL nSourceDim,ScDPTableDataCache * pCache,const std::vector<SCROW> & vIdx,SCROW nNew,SCROW & rIndex)80cdf0e10cSrcweir sal_Bool lcl_Search( SCCOL nSourceDim, ScDPTableDataCache* pCache , const std::vector< SCROW >& vIdx, SCROW nNew , SCROW& rIndex)
81cdf0e10cSrcweir {
82cdf0e10cSrcweir rIndex = vIdx.size();
83cdf0e10cSrcweir sal_Bool bFound = sal_False;
84cdf0e10cSrcweir SCROW nLo = 0;
85cdf0e10cSrcweir SCROW nHi = vIdx.size() - 1;
86cdf0e10cSrcweir SCROW nIndex;
87cdf0e10cSrcweir long nCompare;
88cdf0e10cSrcweir while (nLo <= nHi)
89cdf0e10cSrcweir {
90cdf0e10cSrcweir nIndex = (nLo + nHi) / 2;
91cdf0e10cSrcweir
92cdf0e10cSrcweir const ScDPItemData* pData = pCache->GetItemDataById( nSourceDim, vIdx[nIndex] );
93cdf0e10cSrcweir const ScDPItemData* pDataInsert = pCache->GetItemDataById( nSourceDim, nNew );
94cdf0e10cSrcweir
95cdf0e10cSrcweir nCompare = ScDPItemData::Compare( *pData, *pDataInsert );
96cdf0e10cSrcweir if (nCompare < 0)
97cdf0e10cSrcweir nLo = nIndex + 1;
98cdf0e10cSrcweir else
99cdf0e10cSrcweir {
100cdf0e10cSrcweir nHi = nIndex - 1;
101cdf0e10cSrcweir if (nCompare == 0)
102cdf0e10cSrcweir {
103cdf0e10cSrcweir bFound = sal_True;
104cdf0e10cSrcweir nLo = nIndex;
105cdf0e10cSrcweir }
106cdf0e10cSrcweir }
107cdf0e10cSrcweir }
108cdf0e10cSrcweir rIndex = nLo;
109cdf0e10cSrcweir return bFound;
110cdf0e10cSrcweir }
111cdf0e10cSrcweir
lcl_Insert(SCCOL nSourceDim,ScDPTableDataCache * pCache,std::vector<SCROW> & vIdx,SCROW nNew)112cdf0e10cSrcweir void lcl_Insert( SCCOL nSourceDim, ScDPTableDataCache* pCache , std::vector< SCROW >& vIdx, SCROW nNew )
113cdf0e10cSrcweir {
114cdf0e10cSrcweir SCROW nIndex = 0;
115cdf0e10cSrcweir if ( !lcl_Search( nSourceDim, pCache, vIdx, nNew ,nIndex ) )
116cdf0e10cSrcweir vIdx.insert( vIdx.begin()+nIndex, nNew );
117cdf0e10cSrcweir }
118cdf0e10cSrcweir
119cdf0e10cSrcweir template<bool bUpdateData>
120cdf0e10cSrcweir SCROW lcl_InsertValue( SCCOL nSourceDim, ScDPTableDataCache* pCache , std::vector< SCROW >& vIdx, const ScDPItemData & rData );
121cdf0e10cSrcweir
122cdf0e10cSrcweir template<>
lcl_InsertValue(SCCOL nSourceDim,ScDPTableDataCache * pCache,std::vector<SCROW> & vIdx,const ScDPItemData & rData)123cdf0e10cSrcweir SCROW lcl_InsertValue<false>( SCCOL nSourceDim, ScDPTableDataCache* pCache , std::vector< SCROW >& vIdx, const ScDPItemData & rData )
124cdf0e10cSrcweir {
125cdf0e10cSrcweir SCROW nNewID = pCache->GetAdditionalItemID( rData );
126cdf0e10cSrcweir lcl_Insert( nSourceDim, pCache, vIdx, nNewID );
127cdf0e10cSrcweir return nNewID;
128cdf0e10cSrcweir }
129cdf0e10cSrcweir
130cdf0e10cSrcweir template<>
lcl_InsertValue(SCCOL nSourceDim,ScDPTableDataCache * pCache,std::vector<SCROW> & vIdx,const ScDPItemData & rData)131cdf0e10cSrcweir SCROW lcl_InsertValue<true>( SCCOL nSourceDim, ScDPTableDataCache* pCache , std::vector< SCROW >& vIdx, const ScDPItemData & rData )
132cdf0e10cSrcweir {
133cdf0e10cSrcweir SCROW nItemId = lcl_InsertValue<false>( nSourceDim, pCache, vIdx, rData );
134cdf0e10cSrcweir
135cdf0e10cSrcweir if( const ScDPItemData *pData = pCache->GetItemDataById( nSourceDim, nItemId ) )
136cdf0e10cSrcweir const_cast<ScDPItemData&>(*pData) = rData;
137cdf0e10cSrcweir
138cdf0e10cSrcweir return nItemId;
139cdf0e10cSrcweir }
140cdf0e10cSrcweir
141cdf0e10cSrcweir template<bool bUpdateData>
lcl_InsertValue(SCCOL nSourceDim,ScDPTableDataCache * pCache,std::vector<SCROW> & vIdx,const String & rString,const double & fValue)142cdf0e10cSrcweir void lcl_InsertValue ( SCCOL nSourceDim, ScDPTableDataCache* pCache , std::vector< SCROW >& vIdx, const String& rString, const double& fValue )
143cdf0e10cSrcweir {
144cdf0e10cSrcweir lcl_InsertValue<bUpdateData>( nSourceDim, pCache, vIdx, ScDPItemData( rString, fValue, sal_True ) );
145cdf0e10cSrcweir }
146cdf0e10cSrcweir
147cdf0e10cSrcweir template<bool bUpdateData>
lcl_InsertValue(SCCOL nSourceDim,ScDPTableDataCache * pCache,std::vector<SCROW> & vIdx,const String & rString,const double & fValue,sal_Int32 nDatePart)148cdf0e10cSrcweir void lcl_InsertValue ( SCCOL nSourceDim, ScDPTableDataCache* pCache , std::vector< SCROW >& vIdx, const String& rString, const double& fValue, sal_Int32 nDatePart )
149cdf0e10cSrcweir {
150cdf0e10cSrcweir lcl_InsertValue<bUpdateData>( nSourceDim, pCache, vIdx, ScDPItemData( nDatePart, rString, fValue, ScDPItemData::MK_DATA|ScDPItemData::MK_VAL|ScDPItemData::MK_DATEPART ) );
151cdf0e10cSrcweir }
152cdf0e10cSrcweir
lcl_AppendDateStr(rtl::OUStringBuffer & rBuffer,double fValue,SvNumberFormatter * pFormatter)153cdf0e10cSrcweir void lcl_AppendDateStr( rtl::OUStringBuffer& rBuffer, double fValue, SvNumberFormatter* pFormatter )
154cdf0e10cSrcweir {
155cdf0e10cSrcweir sal_uLong nFormat = pFormatter->GetStandardFormat( NUMBERFORMAT_DATE, ScGlobal::eLnge );
156cdf0e10cSrcweir String aString;
157cdf0e10cSrcweir pFormatter->GetInputLineString( fValue, nFormat, aString );
158cdf0e10cSrcweir rBuffer.append( aString );
159cdf0e10cSrcweir }
160cdf0e10cSrcweir
lcl_GetNumGroupName(double fStartValue,const ScDPNumGroupInfo & rInfo,bool bHasNonInteger,sal_Unicode cDecSeparator,SvNumberFormatter * pFormatter)161cdf0e10cSrcweir String lcl_GetNumGroupName( double fStartValue, const ScDPNumGroupInfo& rInfo,
162cdf0e10cSrcweir bool bHasNonInteger, sal_Unicode cDecSeparator, SvNumberFormatter* pFormatter )
163cdf0e10cSrcweir {
164cdf0e10cSrcweir DBG_ASSERT( cDecSeparator != 0, "cDecSeparator not initialized" );
165cdf0e10cSrcweir
166cdf0e10cSrcweir double fStep = rInfo.Step;
167cdf0e10cSrcweir double fEndValue = fStartValue + fStep;
168cdf0e10cSrcweir if ( !bHasNonInteger && ( rInfo.DateValues || !rtl::math::approxEqual( fEndValue, rInfo.End ) ) )
169cdf0e10cSrcweir {
170cdf0e10cSrcweir // The second number of the group label is
171cdf0e10cSrcweir // (first number + size - 1) if there are only integer numbers,
172cdf0e10cSrcweir // (first number + size) if any non-integer numbers are involved.
173cdf0e10cSrcweir // Exception: The last group (containing the end value) is always
174cdf0e10cSrcweir // shown as including the end value (but not for dates).
175cdf0e10cSrcweir
176cdf0e10cSrcweir fEndValue -= 1.0;
177cdf0e10cSrcweir }
178cdf0e10cSrcweir
179cdf0e10cSrcweir if ( fEndValue > rInfo.End && !rInfo.AutoEnd )
180cdf0e10cSrcweir {
181cdf0e10cSrcweir // limit the last group to the end value
182cdf0e10cSrcweir
183cdf0e10cSrcweir fEndValue = rInfo.End;
184cdf0e10cSrcweir }
185cdf0e10cSrcweir
186cdf0e10cSrcweir rtl::OUStringBuffer aBuffer;
187cdf0e10cSrcweir if ( rInfo.DateValues )
188cdf0e10cSrcweir {
189cdf0e10cSrcweir lcl_AppendDateStr( aBuffer, fStartValue, pFormatter );
190cdf0e10cSrcweir aBuffer.appendAscii( " - " ); // with spaces
191cdf0e10cSrcweir lcl_AppendDateStr( aBuffer, fEndValue, pFormatter );
192cdf0e10cSrcweir }
193cdf0e10cSrcweir else
194cdf0e10cSrcweir {
195cdf0e10cSrcweir rtl::math::doubleToUStringBuffer( aBuffer, fStartValue, rtl_math_StringFormat_Automatic,
196cdf0e10cSrcweir rtl_math_DecimalPlaces_Max, cDecSeparator, true );
197cdf0e10cSrcweir aBuffer.append( (sal_Unicode) '-' );
198cdf0e10cSrcweir rtl::math::doubleToUStringBuffer( aBuffer, fEndValue, rtl_math_StringFormat_Automatic,
199cdf0e10cSrcweir rtl_math_DecimalPlaces_Max, cDecSeparator, true );
200cdf0e10cSrcweir }
201cdf0e10cSrcweir
202cdf0e10cSrcweir return aBuffer.makeStringAndClear();
203cdf0e10cSrcweir }
204cdf0e10cSrcweir
lcl_GetSpecialNumGroupName(double fValue,bool bFirst,sal_Unicode cDecSeparator,bool bDateValues,SvNumberFormatter * pFormatter)205cdf0e10cSrcweir String lcl_GetSpecialNumGroupName( double fValue, bool bFirst, sal_Unicode cDecSeparator,
206cdf0e10cSrcweir bool bDateValues, SvNumberFormatter* pFormatter )
207cdf0e10cSrcweir {
208cdf0e10cSrcweir DBG_ASSERT( cDecSeparator != 0, "cDecSeparator not initialized" );
209cdf0e10cSrcweir
210cdf0e10cSrcweir rtl::OUStringBuffer aBuffer;
211cdf0e10cSrcweir aBuffer.append((sal_Unicode)( bFirst ? '<' : '>' ));
212cdf0e10cSrcweir if ( bDateValues )
213cdf0e10cSrcweir lcl_AppendDateStr( aBuffer, fValue, pFormatter );
214cdf0e10cSrcweir else
215cdf0e10cSrcweir rtl::math::doubleToUStringBuffer( aBuffer, fValue, rtl_math_StringFormat_Automatic,
216cdf0e10cSrcweir rtl_math_DecimalPlaces_Max, cDecSeparator, true );
217cdf0e10cSrcweir return aBuffer.makeStringAndClear();
218cdf0e10cSrcweir }
219cdf0e10cSrcweir
IsInteger(double fValue)220cdf0e10cSrcweir inline bool IsInteger( double fValue )
221cdf0e10cSrcweir {
222cdf0e10cSrcweir return rtl::math::approxEqual( fValue, rtl::math::approxFloor(fValue) );
223cdf0e10cSrcweir }
224cdf0e10cSrcweir
lcl_GetNumGroupForValue(double fValue,const ScDPNumGroupInfo & rInfo,bool bHasNonInteger,sal_Unicode cDecSeparator,double & rGroupValue,ScDocument * pDoc)225cdf0e10cSrcweir String lcl_GetNumGroupForValue( double fValue, const ScDPNumGroupInfo& rInfo, bool bHasNonInteger,
226cdf0e10cSrcweir sal_Unicode cDecSeparator, double& rGroupValue, ScDocument* pDoc )
227cdf0e10cSrcweir {
228cdf0e10cSrcweir SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
229cdf0e10cSrcweir
230cdf0e10cSrcweir if ( fValue < rInfo.Start && !rtl::math::approxEqual( fValue, rInfo.Start ) )
231cdf0e10cSrcweir {
232cdf0e10cSrcweir rGroupValue = rInfo.Start - rInfo.Step;
233cdf0e10cSrcweir return lcl_GetSpecialNumGroupName( rInfo.Start, true, cDecSeparator, rInfo.DateValues, pFormatter );
234cdf0e10cSrcweir }
235cdf0e10cSrcweir
236cdf0e10cSrcweir if ( fValue > rInfo.End && !rtl::math::approxEqual( fValue, rInfo.End ) )
237cdf0e10cSrcweir {
238cdf0e10cSrcweir rGroupValue = rInfo.End + rInfo.Step;
239cdf0e10cSrcweir return lcl_GetSpecialNumGroupName( rInfo.End, false, cDecSeparator, rInfo.DateValues, pFormatter );
240cdf0e10cSrcweir }
241cdf0e10cSrcweir
242cdf0e10cSrcweir double fDiff = fValue - rInfo.Start;
243cdf0e10cSrcweir double fDiv = rtl::math::approxFloor( fDiff / rInfo.Step );
244cdf0e10cSrcweir double fGroupStart = rInfo.Start + fDiv * rInfo.Step;
245cdf0e10cSrcweir
246cdf0e10cSrcweir if ( rtl::math::approxEqual( fGroupStart, rInfo.End ) &&
247cdf0e10cSrcweir !rtl::math::approxEqual( fGroupStart, rInfo.Start ) )
248cdf0e10cSrcweir {
249cdf0e10cSrcweir if ( !rInfo.DateValues )
250cdf0e10cSrcweir {
251cdf0e10cSrcweir // A group that would consist only of the end value is not created,
252cdf0e10cSrcweir // instead the value is included in the last group before. So the
253cdf0e10cSrcweir // previous group is used if the calculated group start value is the
254cdf0e10cSrcweir // selected end value.
255cdf0e10cSrcweir
256cdf0e10cSrcweir fDiv -= 1.0;
257cdf0e10cSrcweir fGroupStart = rInfo.Start + fDiv * rInfo.Step;
258cdf0e10cSrcweir }
259cdf0e10cSrcweir else
260cdf0e10cSrcweir {
261cdf0e10cSrcweir // For date values, the end value is instead treated as above the limit
262cdf0e10cSrcweir // if it would be a group of its own.
263cdf0e10cSrcweir
264cdf0e10cSrcweir rGroupValue = rInfo.End + rInfo.Step;
265cdf0e10cSrcweir return lcl_GetSpecialNumGroupName( rInfo.End, false, cDecSeparator, rInfo.DateValues, pFormatter );
266cdf0e10cSrcweir }
267cdf0e10cSrcweir }
268cdf0e10cSrcweir
269cdf0e10cSrcweir rGroupValue = fGroupStart;
270cdf0e10cSrcweir
271cdf0e10cSrcweir return lcl_GetNumGroupName( fGroupStart, rInfo, bHasNonInteger, cDecSeparator, pFormatter );
272cdf0e10cSrcweir }
273cdf0e10cSrcweir }
274cdf0e10cSrcweir
275cdf0e10cSrcweir class ScDPGroupDateFilter : public ScDPCacheTable::FilterBase
276cdf0e10cSrcweir {
277cdf0e10cSrcweir public:
278cdf0e10cSrcweir ScDPGroupDateFilter(double fMatchValue, sal_Int32 nDatePart,
279cdf0e10cSrcweir const Date* pNullDate, const ScDPNumGroupInfo* pNumInfo);
280cdf0e10cSrcweir
281cdf0e10cSrcweir // Wang Xu Ming -- 2009-8-17
282cdf0e10cSrcweir // DataPilot Migration - Cache&&Performance
283cdf0e10cSrcweir virtual bool match(const ScDPItemData & rCellData) const;
284cdf0e10cSrcweir // End Comments
285cdf0e10cSrcweir
286cdf0e10cSrcweir private:
287cdf0e10cSrcweir ScDPGroupDateFilter(); // disabled
288cdf0e10cSrcweir
289cdf0e10cSrcweir const Date* mpNullDate;
290cdf0e10cSrcweir const ScDPNumGroupInfo* mpNumInfo;
291cdf0e10cSrcweir double mfMatchValue;
292cdf0e10cSrcweir sal_Int32 mnDatePart;
293cdf0e10cSrcweir };
294cdf0e10cSrcweir
295cdf0e10cSrcweir // ----------------------------------------------------------------------------
296cdf0e10cSrcweir
ScDPGroupDateFilter(double fMatchValue,sal_Int32 nDatePart,const Date * pNullDate,const ScDPNumGroupInfo * pNumInfo)297cdf0e10cSrcweir ScDPGroupDateFilter::ScDPGroupDateFilter(double fMatchValue, sal_Int32 nDatePart,
298cdf0e10cSrcweir const Date* pNullDate, const ScDPNumGroupInfo* pNumInfo) :
299cdf0e10cSrcweir mpNullDate(pNullDate),
300cdf0e10cSrcweir mpNumInfo(pNumInfo),
301cdf0e10cSrcweir mfMatchValue(fMatchValue),
302cdf0e10cSrcweir mnDatePart(nDatePart)
303cdf0e10cSrcweir {
304cdf0e10cSrcweir // fprintf(stdout, "ScDPCacheTable:DateGroupFilter::DateGroupFilter: match value = %g; date part = %ld\n",
305cdf0e10cSrcweir // mfMatchValue, mnDatePart);
306cdf0e10cSrcweir }
match(const ScDPItemData & rCellData) const307cdf0e10cSrcweir bool ScDPGroupDateFilter::match( const ScDPItemData & rCellData ) const
308cdf0e10cSrcweir {
309cdf0e10cSrcweir using namespace ::com::sun::star::sheet;
310cdf0e10cSrcweir using ::rtl::math::approxFloor;
311cdf0e10cSrcweir using ::rtl::math::approxEqual;
312cdf0e10cSrcweir
313cdf0e10cSrcweir if ( !rCellData.IsValue() )
314cdf0e10cSrcweir return false;
315cdf0e10cSrcweir // ScDPCacheCell rCell( rCellData.fValue );
316cdf0e10cSrcweir if (!mpNumInfo)
317cdf0e10cSrcweir return false;
318cdf0e10cSrcweir
319cdf0e10cSrcweir // Start and end dates are inclusive. (An end date without a time value
320cdf0e10cSrcweir // is included, while an end date with a time value is not.)
321cdf0e10cSrcweir
322cdf0e10cSrcweir if ( rCellData.GetValue() < mpNumInfo->Start && !approxEqual(rCellData.GetValue(), mpNumInfo->Start) )
323cdf0e10cSrcweir return static_cast<sal_Int32>(mfMatchValue) == SC_DP_DATE_FIRST;
324cdf0e10cSrcweir
325cdf0e10cSrcweir if ( rCellData.GetValue() > mpNumInfo->End && !approxEqual(rCellData.GetValue(), mpNumInfo->End) )
326cdf0e10cSrcweir return static_cast<sal_Int32>(mfMatchValue) == SC_DP_DATE_LAST;
327cdf0e10cSrcweir
328cdf0e10cSrcweir if (mnDatePart == DataPilotFieldGroupBy::HOURS || mnDatePart == DataPilotFieldGroupBy::MINUTES ||
329cdf0e10cSrcweir mnDatePart == DataPilotFieldGroupBy::SECONDS)
330cdf0e10cSrcweir {
331cdf0e10cSrcweir // handle time
332cdf0e10cSrcweir // (as in the cell functions, ScInterpreter::ScGetHour etc.: seconds are rounded)
333cdf0e10cSrcweir
334cdf0e10cSrcweir double time = rCellData.GetValue() - approxFloor(rCellData.GetValue());
335cdf0e10cSrcweir long seconds = static_cast<long>(approxFloor(time*D_TIMEFACTOR + 0.5));
336cdf0e10cSrcweir
337cdf0e10cSrcweir switch (mnDatePart)
338cdf0e10cSrcweir {
339cdf0e10cSrcweir case DataPilotFieldGroupBy::HOURS:
340cdf0e10cSrcweir {
341cdf0e10cSrcweir sal_Int32 hrs = seconds / 3600;
342cdf0e10cSrcweir sal_Int32 matchHrs = static_cast<sal_Int32>(mfMatchValue);
343cdf0e10cSrcweir return hrs == matchHrs;
344cdf0e10cSrcweir }
345cdf0e10cSrcweir case DataPilotFieldGroupBy::MINUTES:
346cdf0e10cSrcweir {
347cdf0e10cSrcweir sal_Int32 minutes = (seconds % 3600) / 60;
348cdf0e10cSrcweir sal_Int32 matchMinutes = static_cast<sal_Int32>(mfMatchValue);
349cdf0e10cSrcweir return minutes == matchMinutes;
350cdf0e10cSrcweir }
351cdf0e10cSrcweir case DataPilotFieldGroupBy::SECONDS:
352cdf0e10cSrcweir {
353cdf0e10cSrcweir sal_Int32 sec = seconds % 60;
354cdf0e10cSrcweir sal_Int32 matchSec = static_cast<sal_Int32>(mfMatchValue);
355cdf0e10cSrcweir return sec == matchSec;
356cdf0e10cSrcweir }
357cdf0e10cSrcweir default:
358cdf0e10cSrcweir DBG_ERROR("invalid time part");
359cdf0e10cSrcweir }
360cdf0e10cSrcweir return false;
361cdf0e10cSrcweir }
362cdf0e10cSrcweir
363cdf0e10cSrcweir Date date = *mpNullDate + static_cast<long>(approxFloor(rCellData.GetValue()));
364cdf0e10cSrcweir switch (mnDatePart)
365cdf0e10cSrcweir {
366cdf0e10cSrcweir case DataPilotFieldGroupBy::YEARS:
367cdf0e10cSrcweir {
368cdf0e10cSrcweir sal_Int32 year = static_cast<sal_Int32>(date.GetYear());
369cdf0e10cSrcweir sal_Int32 matchYear = static_cast<sal_Int32>(mfMatchValue);
370cdf0e10cSrcweir return year == matchYear;
371cdf0e10cSrcweir }
372cdf0e10cSrcweir case DataPilotFieldGroupBy::QUARTERS:
373cdf0e10cSrcweir {
374cdf0e10cSrcweir sal_Int32 qtr = 1 + (static_cast<sal_Int32>(date.GetMonth()) - 1) / 3;
375cdf0e10cSrcweir sal_Int32 matchQtr = static_cast<sal_Int32>(mfMatchValue);
376cdf0e10cSrcweir return qtr == matchQtr;
377cdf0e10cSrcweir }
378cdf0e10cSrcweir case DataPilotFieldGroupBy::MONTHS:
379cdf0e10cSrcweir {
380cdf0e10cSrcweir sal_Int32 month = static_cast<sal_Int32>(date.GetMonth());
381cdf0e10cSrcweir sal_Int32 matchMonth = static_cast<sal_Int32>(mfMatchValue);
382cdf0e10cSrcweir return month == matchMonth;
383cdf0e10cSrcweir }
384cdf0e10cSrcweir case DataPilotFieldGroupBy::DAYS:
385cdf0e10cSrcweir {
386cdf0e10cSrcweir Date yearStart(1, 1, date.GetYear());
387cdf0e10cSrcweir sal_Int32 days = (date - yearStart) + 1; // Jan 01 has value 1
388cdf0e10cSrcweir if (days >= 60 && !date.IsLeapYear())
389cdf0e10cSrcweir {
390cdf0e10cSrcweir // This is not a leap year. Adjust the value accordingly.
391cdf0e10cSrcweir ++days;
392cdf0e10cSrcweir }
393cdf0e10cSrcweir sal_Int32 matchDays = static_cast<sal_Int32>(mfMatchValue);
394cdf0e10cSrcweir return days == matchDays;
395cdf0e10cSrcweir }
396cdf0e10cSrcweir default:
397cdf0e10cSrcweir DBG_ERROR("invalid date part");
398cdf0e10cSrcweir }
399cdf0e10cSrcweir
400cdf0e10cSrcweir return false;
401cdf0e10cSrcweir }
402cdf0e10cSrcweir // -----------------------------------------------------------------------
403cdf0e10cSrcweir
ScDPDateGroupHelper(const ScDPNumGroupInfo & rInfo,sal_Int32 nPart)404cdf0e10cSrcweir ScDPDateGroupHelper::ScDPDateGroupHelper( const ScDPNumGroupInfo& rInfo, sal_Int32 nPart ) :
405cdf0e10cSrcweir aNumInfo( rInfo ),
406cdf0e10cSrcweir nDatePart( nPart )
407cdf0e10cSrcweir {
408cdf0e10cSrcweir }
409cdf0e10cSrcweir
~ScDPDateGroupHelper()410cdf0e10cSrcweir ScDPDateGroupHelper::~ScDPDateGroupHelper()
411cdf0e10cSrcweir {
412cdf0e10cSrcweir }
413cdf0e10cSrcweir
lcl_GetTwoDigitString(sal_Int32 nValue)414cdf0e10cSrcweir String lcl_GetTwoDigitString( sal_Int32 nValue )
415cdf0e10cSrcweir {
416cdf0e10cSrcweir String aRet = String::CreateFromInt32( nValue );
417cdf0e10cSrcweir if ( aRet.Len() < 2 )
418cdf0e10cSrcweir aRet.Insert( (sal_Unicode)'0', 0 );
419cdf0e10cSrcweir return aRet;
420cdf0e10cSrcweir }
421cdf0e10cSrcweir
lcl_GetDateGroupName(sal_Int32 nDatePart,sal_Int32 nValue,SvNumberFormatter * pFormatter)422cdf0e10cSrcweir String lcl_GetDateGroupName( sal_Int32 nDatePart, sal_Int32 nValue, SvNumberFormatter* pFormatter )
423cdf0e10cSrcweir {
424cdf0e10cSrcweir String aRet;
425cdf0e10cSrcweir switch ( nDatePart )
426cdf0e10cSrcweir {
427cdf0e10cSrcweir case com::sun::star::sheet::DataPilotFieldGroupBy::YEARS:
428cdf0e10cSrcweir aRet = String::CreateFromInt32( nValue );
429cdf0e10cSrcweir break;
430cdf0e10cSrcweir case com::sun::star::sheet::DataPilotFieldGroupBy::QUARTERS:
431cdf0e10cSrcweir aRet = ScGlobal::pLocaleData->getQuarterAbbreviation( (sal_Int16)(nValue - 1) ); // nValue is 1-based
432cdf0e10cSrcweir break;
433cdf0e10cSrcweir case com::sun::star::sheet::DataPilotFieldGroupBy::MONTHS:
434cdf0e10cSrcweir //! cache getMonths() result?
435cdf0e10cSrcweir aRet = ScGlobal::GetCalendar()->getDisplayName(
436cdf0e10cSrcweir ::com::sun::star::i18n::CalendarDisplayIndex::MONTH,
437cdf0e10cSrcweir sal_Int16(nValue-1), 0 ); // 0-based, get short name
438cdf0e10cSrcweir break;
439cdf0e10cSrcweir case com::sun::star::sheet::DataPilotFieldGroupBy::DAYS:
440cdf0e10cSrcweir {
441cdf0e10cSrcweir Date aDate( 1, 1, SC_DP_LEAPYEAR );
442cdf0e10cSrcweir aDate += ( nValue - 1 ); // nValue is 1-based
443cdf0e10cSrcweir Date aNullDate = *(pFormatter->GetNullDate());
444cdf0e10cSrcweir long nDays = aDate - aNullDate;
445cdf0e10cSrcweir
446cdf0e10cSrcweir sal_uLong nFormat = pFormatter->GetFormatIndex( NF_DATE_SYS_DDMMM, ScGlobal::eLnge );
447cdf0e10cSrcweir Color* pColor;
448cdf0e10cSrcweir pFormatter->GetOutputString( nDays, nFormat, aRet, &pColor );
449cdf0e10cSrcweir }
450cdf0e10cSrcweir break;
451cdf0e10cSrcweir case com::sun::star::sheet::DataPilotFieldGroupBy::HOURS:
452cdf0e10cSrcweir //! allow am/pm format?
453cdf0e10cSrcweir aRet = lcl_GetTwoDigitString( nValue );
454cdf0e10cSrcweir break;
455cdf0e10cSrcweir case com::sun::star::sheet::DataPilotFieldGroupBy::MINUTES:
456cdf0e10cSrcweir case com::sun::star::sheet::DataPilotFieldGroupBy::SECONDS:
457cdf0e10cSrcweir aRet = ScGlobal::pLocaleData->getTimeSep();
458cdf0e10cSrcweir aRet.Append( lcl_GetTwoDigitString( nValue ) );
459cdf0e10cSrcweir break;
460cdf0e10cSrcweir default:
461cdf0e10cSrcweir DBG_ERROR("invalid date part");
462cdf0e10cSrcweir }
463cdf0e10cSrcweir return aRet;
464cdf0e10cSrcweir }
465cdf0e10cSrcweir
lcl_GetDatePartValue(double fValue,sal_Int32 nDatePart,SvNumberFormatter * pFormatter,const ScDPNumGroupInfo * pNumInfo)466cdf0e10cSrcweir sal_Int32 lcl_GetDatePartValue( double fValue, sal_Int32 nDatePart, SvNumberFormatter* pFormatter,
467cdf0e10cSrcweir const ScDPNumGroupInfo* pNumInfo )
468cdf0e10cSrcweir {
469cdf0e10cSrcweir // Start and end are inclusive
470cdf0e10cSrcweir // (End date without a time value is included, with a time value it's not)
471cdf0e10cSrcweir
472cdf0e10cSrcweir if ( pNumInfo )
473cdf0e10cSrcweir {
474cdf0e10cSrcweir if ( fValue < pNumInfo->Start && !rtl::math::approxEqual( fValue, pNumInfo->Start ) )
475cdf0e10cSrcweir return SC_DP_DATE_FIRST;
476cdf0e10cSrcweir if ( fValue > pNumInfo->End && !rtl::math::approxEqual( fValue, pNumInfo->End ) )
477cdf0e10cSrcweir return SC_DP_DATE_LAST;
478cdf0e10cSrcweir }
479cdf0e10cSrcweir
480cdf0e10cSrcweir sal_Int32 nResult = 0;
481cdf0e10cSrcweir
482cdf0e10cSrcweir if ( nDatePart == com::sun::star::sheet::DataPilotFieldGroupBy::HOURS || nDatePart == com::sun::star::sheet::DataPilotFieldGroupBy::MINUTES || nDatePart == com::sun::star::sheet::DataPilotFieldGroupBy::SECONDS )
483cdf0e10cSrcweir {
484cdf0e10cSrcweir // handle time
485cdf0e10cSrcweir // (as in the cell functions, ScInterpreter::ScGetHour etc.: seconds are rounded)
486cdf0e10cSrcweir
487cdf0e10cSrcweir double fTime = fValue - ::rtl::math::approxFloor(fValue);
488cdf0e10cSrcweir long nSeconds = (long)::rtl::math::approxFloor(fTime*D_TIMEFACTOR+0.5);
489cdf0e10cSrcweir
490cdf0e10cSrcweir switch ( nDatePart )
491cdf0e10cSrcweir {
492cdf0e10cSrcweir case com::sun::star::sheet::DataPilotFieldGroupBy::HOURS:
493cdf0e10cSrcweir nResult = nSeconds / 3600;
494cdf0e10cSrcweir break;
495cdf0e10cSrcweir case com::sun::star::sheet::DataPilotFieldGroupBy::MINUTES:
496cdf0e10cSrcweir nResult = ( nSeconds % 3600 ) / 60;
497cdf0e10cSrcweir break;
498cdf0e10cSrcweir case com::sun::star::sheet::DataPilotFieldGroupBy::SECONDS:
499cdf0e10cSrcweir nResult = nSeconds % 60;
500cdf0e10cSrcweir break;
501cdf0e10cSrcweir }
502cdf0e10cSrcweir }
503cdf0e10cSrcweir else
504cdf0e10cSrcweir {
505cdf0e10cSrcweir Date aDate = *(pFormatter->GetNullDate());
506cdf0e10cSrcweir aDate += (long)::rtl::math::approxFloor( fValue );
507cdf0e10cSrcweir
508cdf0e10cSrcweir switch ( nDatePart )
509cdf0e10cSrcweir {
510cdf0e10cSrcweir case com::sun::star::sheet::DataPilotFieldGroupBy::YEARS:
511cdf0e10cSrcweir nResult = aDate.GetYear();
512cdf0e10cSrcweir break;
513cdf0e10cSrcweir case com::sun::star::sheet::DataPilotFieldGroupBy::QUARTERS:
514cdf0e10cSrcweir nResult = 1 + ( aDate.GetMonth() - 1 ) / 3; // 1..4
515cdf0e10cSrcweir break;
516cdf0e10cSrcweir case com::sun::star::sheet::DataPilotFieldGroupBy::MONTHS:
517cdf0e10cSrcweir nResult = aDate.GetMonth(); // 1..12
518cdf0e10cSrcweir break;
519cdf0e10cSrcweir case com::sun::star::sheet::DataPilotFieldGroupBy::DAYS:
520cdf0e10cSrcweir {
521cdf0e10cSrcweir Date aYearStart( 1, 1, aDate.GetYear() );
522cdf0e10cSrcweir nResult = ( aDate - aYearStart ) + 1; // Jan 01 has value 1
523cdf0e10cSrcweir if ( nResult >= 60 && !aDate.IsLeapYear() )
524cdf0e10cSrcweir {
525cdf0e10cSrcweir // days are counted from 1 to 366 - if not from a leap year, adjust
526cdf0e10cSrcweir ++nResult;
527cdf0e10cSrcweir }
528cdf0e10cSrcweir }
529cdf0e10cSrcweir break;
530cdf0e10cSrcweir default:
531cdf0e10cSrcweir DBG_ERROR("invalid date part");
532cdf0e10cSrcweir }
533cdf0e10cSrcweir }
534cdf0e10cSrcweir
535cdf0e10cSrcweir return nResult;
536cdf0e10cSrcweir }
537cdf0e10cSrcweir
lcl_DateContained(sal_Int32 nGroupPart,const ScDPItemData & rGroupData,sal_Int32 nBasePart,const ScDPItemData & rBaseData)538cdf0e10cSrcweir sal_Bool lcl_DateContained( sal_Int32 nGroupPart, const ScDPItemData& rGroupData,
539cdf0e10cSrcweir sal_Int32 nBasePart, const ScDPItemData& rBaseData )
540cdf0e10cSrcweir {
541cdf0e10cSrcweir if ( !rGroupData.IsValue() || !rBaseData.IsValue() )
542cdf0e10cSrcweir {
543cdf0e10cSrcweir // non-numeric entries involved: only match equal entries
544cdf0e10cSrcweir return rGroupData.IsCaseInsEqual( rBaseData );
545cdf0e10cSrcweir }
546cdf0e10cSrcweir
547cdf0e10cSrcweir // no approxFloor needed, values were created from integers
548cdf0e10cSrcweir // Wang Xu Ming -- 2009-8-17
549cdf0e10cSrcweir // DataPilot Migration - Cache&&Performance
550cdf0e10cSrcweir sal_Int32 nGroupValue = (sal_Int32) rGroupData.GetValue();
551cdf0e10cSrcweir sal_Int32 nBaseValue = (sal_Int32) rBaseData.GetValue();
552cdf0e10cSrcweir // End Comments
553cdf0e10cSrcweir if ( nBasePart > nGroupPart )
554cdf0e10cSrcweir {
555cdf0e10cSrcweir // switch, so the base part is the smaller (inner) part
556cdf0e10cSrcweir
557cdf0e10cSrcweir ::std::swap( nGroupPart, nBasePart );
558cdf0e10cSrcweir ::std::swap( nGroupValue, nBaseValue );
559cdf0e10cSrcweir }
560cdf0e10cSrcweir
561cdf0e10cSrcweir if ( nGroupValue == SC_DP_DATE_FIRST || nGroupValue == SC_DP_DATE_LAST ||
562cdf0e10cSrcweir nBaseValue == SC_DP_DATE_FIRST || nBaseValue == SC_DP_DATE_LAST )
563cdf0e10cSrcweir {
564cdf0e10cSrcweir // first/last entry matches only itself
565cdf0e10cSrcweir return ( nGroupValue == nBaseValue );
566cdf0e10cSrcweir }
567cdf0e10cSrcweir
568cdf0e10cSrcweir sal_Bool bContained = sal_True;
569cdf0e10cSrcweir switch ( nBasePart ) // inner part
570cdf0e10cSrcweir {
571cdf0e10cSrcweir case com::sun::star::sheet::DataPilotFieldGroupBy::MONTHS:
572cdf0e10cSrcweir // a month is only contained in its quarter
573cdf0e10cSrcweir if ( nGroupPart == com::sun::star::sheet::DataPilotFieldGroupBy::QUARTERS )
574cdf0e10cSrcweir {
575cdf0e10cSrcweir // months and quarters are both 1-based
576cdf0e10cSrcweir bContained = ( nGroupValue - 1 == ( nBaseValue - 1 ) / 3 );
577cdf0e10cSrcweir }
578cdf0e10cSrcweir break;
579cdf0e10cSrcweir case com::sun::star::sheet::DataPilotFieldGroupBy::DAYS:
580cdf0e10cSrcweir // a day is only contained in its quarter or month
581cdf0e10cSrcweir if ( nGroupPart == com::sun::star::sheet::DataPilotFieldGroupBy::MONTHS || nGroupPart == com::sun::star::sheet::DataPilotFieldGroupBy::QUARTERS )
582cdf0e10cSrcweir {
583cdf0e10cSrcweir Date aDate( 1, 1, SC_DP_LEAPYEAR );
584cdf0e10cSrcweir aDate += ( nBaseValue - 1 ); // days are 1-based
585cdf0e10cSrcweir sal_Int32 nCompare = aDate.GetMonth();
586cdf0e10cSrcweir if ( nGroupPart == com::sun::star::sheet::DataPilotFieldGroupBy::QUARTERS )
587cdf0e10cSrcweir nCompare = ( ( nCompare - 1 ) / 3 ) + 1; // get quarter from date
588cdf0e10cSrcweir
589cdf0e10cSrcweir bContained = ( nGroupValue == nCompare );
590cdf0e10cSrcweir }
591cdf0e10cSrcweir break;
592cdf0e10cSrcweir
593cdf0e10cSrcweir // other parts: everything is contained
594cdf0e10cSrcweir }
595cdf0e10cSrcweir
596cdf0e10cSrcweir return bContained;
597cdf0e10cSrcweir }
598cdf0e10cSrcweir
lcl_GetSpecialDateName(double fValue,bool bFirst,SvNumberFormatter * pFormatter)599cdf0e10cSrcweir String lcl_GetSpecialDateName( double fValue, bool bFirst, SvNumberFormatter* pFormatter )
600cdf0e10cSrcweir {
601cdf0e10cSrcweir rtl::OUStringBuffer aBuffer;
602cdf0e10cSrcweir aBuffer.append((sal_Unicode)( bFirst ? '<' : '>' ));
603cdf0e10cSrcweir lcl_AppendDateStr( aBuffer, fValue, pFormatter );
604cdf0e10cSrcweir return aBuffer.makeStringAndClear();
605cdf0e10cSrcweir }
606cdf0e10cSrcweir
FillColumnEntries(SCCOL nSourceDim,ScDPTableDataCache * pCache,std::vector<SCROW> & rEntries,const std::vector<SCROW> & rOriginal) const607cdf0e10cSrcweir void ScDPDateGroupHelper::FillColumnEntries( SCCOL nSourceDim, ScDPTableDataCache* pCache, std::vector< SCROW >& rEntries, const std::vector< SCROW >& rOriginal ) const
608cdf0e10cSrcweir {
609cdf0e10cSrcweir // auto min/max is only used for "Years" part, but the loop is always needed
610cdf0e10cSrcweir double fSourceMin = 0.0;
611cdf0e10cSrcweir double fSourceMax = 0.0;
612cdf0e10cSrcweir bool bFirst = true;
613cdf0e10cSrcweir
614cdf0e10cSrcweir size_t nOriginalCount = rOriginal.size();
615cdf0e10cSrcweir for (size_t nOriginalPos=0; nOriginalPos<nOriginalCount; nOriginalPos++)
616cdf0e10cSrcweir {
617cdf0e10cSrcweir const ScDPItemData* pItemData = pCache->GetItemDataById( nSourceDim, rOriginal[nOriginalPos] );
618cdf0e10cSrcweir if ( pItemData->HasStringData() )
619cdf0e10cSrcweir {
620cdf0e10cSrcweir // string data: just copy
621cdf0e10cSrcweir lcl_Insert( nSourceDim, pCache , rEntries, rOriginal[nOriginalPos] );
622cdf0e10cSrcweir }
623cdf0e10cSrcweir else
624cdf0e10cSrcweir {
625cdf0e10cSrcweir double fSourceValue = pItemData->GetValue();
626cdf0e10cSrcweir if ( bFirst )
627cdf0e10cSrcweir {
628cdf0e10cSrcweir fSourceMin = fSourceMax = fSourceValue;
629cdf0e10cSrcweir bFirst = false;
630cdf0e10cSrcweir }
631cdf0e10cSrcweir else
632cdf0e10cSrcweir {
633cdf0e10cSrcweir if ( fSourceValue < fSourceMin )
634cdf0e10cSrcweir fSourceMin = fSourceValue;
635cdf0e10cSrcweir if ( fSourceValue > fSourceMax )
636cdf0e10cSrcweir fSourceMax = fSourceValue;
637cdf0e10cSrcweir }
638cdf0e10cSrcweir }
639cdf0e10cSrcweir }
640cdf0e10cSrcweir
641cdf0e10cSrcweir // For the start/end values, use the same date rounding as in ScDPNumGroupDimension::GetNumEntries
642cdf0e10cSrcweir // (but not for the list of available years):
643cdf0e10cSrcweir if ( aNumInfo.AutoStart )
644cdf0e10cSrcweir const_cast<ScDPDateGroupHelper*>(this)->aNumInfo.Start = rtl::math::approxFloor( fSourceMin );
645cdf0e10cSrcweir if ( aNumInfo.AutoEnd )
646cdf0e10cSrcweir const_cast<ScDPDateGroupHelper*>(this)->aNumInfo.End = rtl::math::approxFloor( fSourceMax ) + 1;
647cdf0e10cSrcweir
648cdf0e10cSrcweir //! if not automatic, limit fSourceMin/fSourceMax for list of year values?
649cdf0e10cSrcweir SvNumberFormatter* pFormatter = pCache->GetDoc()->GetFormatTable();
650cdf0e10cSrcweir
651cdf0e10cSrcweir long nStart = 0;
652cdf0e10cSrcweir long nEnd = 0; // including
653cdf0e10cSrcweir
654cdf0e10cSrcweir switch ( nDatePart )
655cdf0e10cSrcweir {
656cdf0e10cSrcweir case com::sun::star::sheet::DataPilotFieldGroupBy::YEARS:
657cdf0e10cSrcweir nStart = lcl_GetDatePartValue( fSourceMin, com::sun::star::sheet::DataPilotFieldGroupBy::YEARS, pFormatter, NULL );
658cdf0e10cSrcweir nEnd = lcl_GetDatePartValue( fSourceMax, com::sun::star::sheet::DataPilotFieldGroupBy::YEARS, pFormatter, NULL );
659cdf0e10cSrcweir break;
660cdf0e10cSrcweir case com::sun::star::sheet::DataPilotFieldGroupBy::QUARTERS: nStart = 1; nEnd = 4; break;
661cdf0e10cSrcweir case com::sun::star::sheet::DataPilotFieldGroupBy::MONTHS: nStart = 1; nEnd = 12; break;
662cdf0e10cSrcweir case com::sun::star::sheet::DataPilotFieldGroupBy::DAYS: nStart = 1; nEnd = 366; break;
663cdf0e10cSrcweir case com::sun::star::sheet::DataPilotFieldGroupBy::HOURS: nStart = 0; nEnd = 23; break;
664cdf0e10cSrcweir case com::sun::star::sheet::DataPilotFieldGroupBy::MINUTES: nStart = 0; nEnd = 59; break;
665cdf0e10cSrcweir case com::sun::star::sheet::DataPilotFieldGroupBy::SECONDS: nStart = 0; nEnd = 59; break;
666cdf0e10cSrcweir default:
667cdf0e10cSrcweir DBG_ERROR("invalid date part");
668cdf0e10cSrcweir }
669cdf0e10cSrcweir
670cdf0e10cSrcweir for ( sal_Int32 nValue = nStart; nValue <= nEnd; nValue++ )
671cdf0e10cSrcweir {
672cdf0e10cSrcweir String aName = lcl_GetDateGroupName( nDatePart, nValue, pFormatter );
673cdf0e10cSrcweir lcl_InsertValue<false>( nSourceDim, pCache, rEntries, aName, nValue, nDatePart );
674cdf0e10cSrcweir }
675cdf0e10cSrcweir
676cdf0e10cSrcweir // add first/last entry (min/max)
677cdf0e10cSrcweir String aFirstName = lcl_GetSpecialDateName( aNumInfo.Start, true, pFormatter );
678cdf0e10cSrcweir lcl_InsertValue<true>( nSourceDim, pCache, rEntries, aFirstName, SC_DP_DATE_FIRST, nDatePart );
679cdf0e10cSrcweir
680cdf0e10cSrcweir String aLastName = lcl_GetSpecialDateName( aNumInfo.End, false, pFormatter );
681cdf0e10cSrcweir lcl_InsertValue<true>( nSourceDim, pCache, rEntries, aLastName, SC_DP_DATE_LAST, nDatePart );
682cdf0e10cSrcweir }
683cdf0e10cSrcweir
684cdf0e10cSrcweir // -----------------------------------------------------------------------
685cdf0e10cSrcweir
ScDPGroupItem(const ScDPItemData & rName)686cdf0e10cSrcweir ScDPGroupItem::ScDPGroupItem( const ScDPItemData& rName ) :
687cdf0e10cSrcweir aGroupName( rName )
688cdf0e10cSrcweir {
689cdf0e10cSrcweir }
690cdf0e10cSrcweir
~ScDPGroupItem()691cdf0e10cSrcweir ScDPGroupItem::~ScDPGroupItem()
692cdf0e10cSrcweir {
693cdf0e10cSrcweir }
694cdf0e10cSrcweir
AddElement(const ScDPItemData & rName)695cdf0e10cSrcweir void ScDPGroupItem::AddElement( const ScDPItemData& rName )
696cdf0e10cSrcweir {
697cdf0e10cSrcweir aElements.push_back( rName );
698cdf0e10cSrcweir }
699cdf0e10cSrcweir
HasElement(const ScDPItemData & rData) const700cdf0e10cSrcweir bool ScDPGroupItem::HasElement( const ScDPItemData& rData ) const
701cdf0e10cSrcweir {
702cdf0e10cSrcweir for ( ScDPItemDataVec::const_iterator aIter(aElements.begin()); aIter != aElements.end(); aIter++ )
703cdf0e10cSrcweir if ( aIter->IsCaseInsEqual( rData ) )
704cdf0e10cSrcweir return true;
705cdf0e10cSrcweir
706cdf0e10cSrcweir return false;
707cdf0e10cSrcweir }
708cdf0e10cSrcweir
HasCommonElement(const ScDPGroupItem & rOther) const709cdf0e10cSrcweir bool ScDPGroupItem::HasCommonElement( const ScDPGroupItem& rOther ) const
710cdf0e10cSrcweir {
711cdf0e10cSrcweir for ( ScDPItemDataVec::const_iterator aIter(aElements.begin()); aIter != aElements.end(); aIter++ )
712cdf0e10cSrcweir if ( rOther.HasElement( *aIter ) )
713cdf0e10cSrcweir return true;
714cdf0e10cSrcweir
715cdf0e10cSrcweir return false;
716cdf0e10cSrcweir }
717cdf0e10cSrcweir
FillGroupFilter(ScDPCacheTable::GroupFilter & rFilter) const718cdf0e10cSrcweir void ScDPGroupItem::FillGroupFilter( ScDPCacheTable::GroupFilter& rFilter ) const
719cdf0e10cSrcweir {
720cdf0e10cSrcweir ScDPItemDataVec::const_iterator itrEnd = aElements.end();
721cdf0e10cSrcweir for (ScDPItemDataVec::const_iterator itr = aElements.begin(); itr != itrEnd; ++itr)
722cdf0e10cSrcweir // Wang Xu Ming -- 2009-8-17
723cdf0e10cSrcweir // DataPilot Migration - Cache&&Performance
724cdf0e10cSrcweir rFilter.addMatchItem(itr->GetString(), itr->GetValue(), itr->IsValue());
725cdf0e10cSrcweir // End Comments
726cdf0e10cSrcweir }
727cdf0e10cSrcweir
728cdf0e10cSrcweir // -----------------------------------------------------------------------
729cdf0e10cSrcweir
ScDPGroupDimension(long nSource,const String & rNewName)730cdf0e10cSrcweir ScDPGroupDimension::ScDPGroupDimension( long nSource, const String& rNewName ) :
731cdf0e10cSrcweir nSourceDim( nSource ),
732cdf0e10cSrcweir nGroupDim( -1 ),
733cdf0e10cSrcweir aGroupName( rNewName ),
734cdf0e10cSrcweir pDateHelper( NULL )/*,
735cdf0e10cSrcweir pCollection( NULL )*/
736cdf0e10cSrcweir {
737cdf0e10cSrcweir }
738cdf0e10cSrcweir
~ScDPGroupDimension()739cdf0e10cSrcweir ScDPGroupDimension::~ScDPGroupDimension()
740cdf0e10cSrcweir {
741cdf0e10cSrcweir delete pDateHelper;
742cdf0e10cSrcweir maMemberEntries.clear();
743cdf0e10cSrcweir }
744cdf0e10cSrcweir
ScDPGroupDimension(const ScDPGroupDimension & rOther)745cdf0e10cSrcweir ScDPGroupDimension::ScDPGroupDimension( const ScDPGroupDimension& rOther ) :
746cdf0e10cSrcweir nSourceDim( rOther.nSourceDim ),
747cdf0e10cSrcweir nGroupDim( rOther.nGroupDim ),
748cdf0e10cSrcweir aGroupName( rOther.aGroupName ),
749cdf0e10cSrcweir pDateHelper( NULL ),
750cdf0e10cSrcweir aItems( rOther.aItems )
751cdf0e10cSrcweir {
752cdf0e10cSrcweir if ( rOther.pDateHelper )
753cdf0e10cSrcweir pDateHelper = new ScDPDateGroupHelper( *rOther.pDateHelper );
754cdf0e10cSrcweir }
755cdf0e10cSrcweir
operator =(const ScDPGroupDimension & rOther)756cdf0e10cSrcweir ScDPGroupDimension& ScDPGroupDimension::operator=( const ScDPGroupDimension& rOther )
757cdf0e10cSrcweir {
758cdf0e10cSrcweir nSourceDim = rOther.nSourceDim;
759cdf0e10cSrcweir nGroupDim = rOther.nGroupDim;
760cdf0e10cSrcweir aGroupName = rOther.aGroupName;
761cdf0e10cSrcweir aItems = rOther.aItems;
762cdf0e10cSrcweir
763cdf0e10cSrcweir delete pDateHelper;
764cdf0e10cSrcweir if ( rOther.pDateHelper )
765cdf0e10cSrcweir pDateHelper = new ScDPDateGroupHelper( *rOther.pDateHelper );
766cdf0e10cSrcweir else
767cdf0e10cSrcweir pDateHelper = NULL;
768cdf0e10cSrcweir
769cdf0e10cSrcweir return *this;
770cdf0e10cSrcweir }
771cdf0e10cSrcweir
MakeDateHelper(const ScDPNumGroupInfo & rInfo,sal_Int32 nPart)772cdf0e10cSrcweir void ScDPGroupDimension::MakeDateHelper( const ScDPNumGroupInfo& rInfo, sal_Int32 nPart )
773cdf0e10cSrcweir {
774cdf0e10cSrcweir delete pDateHelper;
775cdf0e10cSrcweir pDateHelper = new ScDPDateGroupHelper( rInfo, nPart );
776cdf0e10cSrcweir }
777cdf0e10cSrcweir
AddItem(const ScDPGroupItem & rItem)778cdf0e10cSrcweir void ScDPGroupDimension::AddItem( const ScDPGroupItem& rItem )
779cdf0e10cSrcweir {
780cdf0e10cSrcweir aItems.push_back( rItem );
781cdf0e10cSrcweir }
782cdf0e10cSrcweir
SetGroupDim(long nDim)783cdf0e10cSrcweir void ScDPGroupDimension::SetGroupDim( long nDim )
784cdf0e10cSrcweir {
785cdf0e10cSrcweir nGroupDim = nDim;
786cdf0e10cSrcweir }
787cdf0e10cSrcweir // Wang Xu Ming -- 2009-9-2
788cdf0e10cSrcweir // DataPilot Migration - Cache&&Performance
GetColumnEntries(const ScDPCacheTable & rCacheTable,const std::vector<SCROW> & rOriginal) const789cdf0e10cSrcweir const std::vector< SCROW >& ScDPGroupDimension::GetColumnEntries( const ScDPCacheTable& rCacheTable, const std::vector< SCROW >& rOriginal ) const
790cdf0e10cSrcweir {
791cdf0e10cSrcweir if ( maMemberEntries.empty() )
792cdf0e10cSrcweir {
793cdf0e10cSrcweir if ( pDateHelper )
794cdf0e10cSrcweir {
795cdf0e10cSrcweir pDateHelper->FillColumnEntries( (SCCOL)GetSourceDim(), rCacheTable.GetCache(), maMemberEntries, rOriginal );
796cdf0e10cSrcweir }
797cdf0e10cSrcweir else
798cdf0e10cSrcweir {
799cdf0e10cSrcweir for (size_t i =0; i < rOriginal.size( ); i ++)
800cdf0e10cSrcweir {
801cdf0e10cSrcweir const ScDPItemData* pItemData = rCacheTable.GetCache()->GetItemDataById( (SCCOL)GetSourceDim(), rOriginal[i] );
802cdf0e10cSrcweir if ( !pItemData || !GetGroupForData( *pItemData ) )
803cdf0e10cSrcweir {
804cdf0e10cSrcweir // not in any group -> add as its own group
805cdf0e10cSrcweir maMemberEntries.push_back( rOriginal[i] );
806cdf0e10cSrcweir }
807cdf0e10cSrcweir }
808cdf0e10cSrcweir
809cdf0e10cSrcweir long nCount = aItems.size();
810cdf0e10cSrcweir for (long i=0; i<nCount; i++)
811cdf0e10cSrcweir {
812cdf0e10cSrcweir SCROW nNew = rCacheTable.GetCache()->GetAdditionalItemID( aItems[i].GetName() );
813cdf0e10cSrcweir lcl_Insert ( (SCCOL)GetSourceDim(), rCacheTable.GetCache(), maMemberEntries, nNew );
814cdf0e10cSrcweir }
815cdf0e10cSrcweir }
816cdf0e10cSrcweir }
817cdf0e10cSrcweir return maMemberEntries;
818cdf0e10cSrcweir }
819cdf0e10cSrcweir
820cdf0e10cSrcweir // End Comments
821cdf0e10cSrcweir
822cdf0e10cSrcweir
GetGroupForData(const ScDPItemData & rData) const823cdf0e10cSrcweir const ScDPGroupItem* ScDPGroupDimension::GetGroupForData( const ScDPItemData& rData ) const
824cdf0e10cSrcweir {
825cdf0e10cSrcweir for ( ScDPGroupItemVec::const_iterator aIter(aItems.begin()); aIter != aItems.end(); aIter++ )
826cdf0e10cSrcweir if ( aIter->HasElement( rData ) )
827cdf0e10cSrcweir return &*aIter;
828cdf0e10cSrcweir
829cdf0e10cSrcweir return NULL;
830cdf0e10cSrcweir }
831cdf0e10cSrcweir
GetGroupForName(const ScDPItemData & rName) const832cdf0e10cSrcweir const ScDPGroupItem* ScDPGroupDimension::GetGroupForName( const ScDPItemData& rName ) const
833cdf0e10cSrcweir {
834cdf0e10cSrcweir for ( ScDPGroupItemVec::const_iterator aIter(aItems.begin()); aIter != aItems.end(); aIter++ )
835cdf0e10cSrcweir if ( aIter->GetName().IsCaseInsEqual( rName ) )
836cdf0e10cSrcweir return &*aIter;
837cdf0e10cSrcweir
838cdf0e10cSrcweir return NULL;
839cdf0e10cSrcweir }
840cdf0e10cSrcweir
GetGroupByIndex(size_t nIndex) const841cdf0e10cSrcweir const ScDPGroupItem* ScDPGroupDimension::GetGroupByIndex( size_t nIndex ) const
842cdf0e10cSrcweir {
843cdf0e10cSrcweir if (nIndex >= aItems.size())
844cdf0e10cSrcweir return NULL;
845cdf0e10cSrcweir
846cdf0e10cSrcweir return &aItems[nIndex];
847cdf0e10cSrcweir }
848cdf0e10cSrcweir
DisposeData()849cdf0e10cSrcweir void ScDPGroupDimension::DisposeData()
850cdf0e10cSrcweir {
851cdf0e10cSrcweir maMemberEntries.clear();
852cdf0e10cSrcweir }
853cdf0e10cSrcweir
854cdf0e10cSrcweir // -----------------------------------------------------------------------
855cdf0e10cSrcweir
ScDPNumGroupDimension()856cdf0e10cSrcweir ScDPNumGroupDimension::ScDPNumGroupDimension() :
857cdf0e10cSrcweir pDateHelper( NULL ),
858cdf0e10cSrcweir bHasNonInteger( false ),
859cdf0e10cSrcweir cDecSeparator( 0 )
860cdf0e10cSrcweir {
861cdf0e10cSrcweir }
862cdf0e10cSrcweir
ScDPNumGroupDimension(const ScDPNumGroupInfo & rInfo)863cdf0e10cSrcweir ScDPNumGroupDimension::ScDPNumGroupDimension( const ScDPNumGroupInfo& rInfo ) :
864cdf0e10cSrcweir aGroupInfo( rInfo ),
865cdf0e10cSrcweir pDateHelper( NULL ),
866cdf0e10cSrcweir bHasNonInteger( false ),
867cdf0e10cSrcweir cDecSeparator( 0 )
868cdf0e10cSrcweir {
869cdf0e10cSrcweir }
870cdf0e10cSrcweir
ScDPNumGroupDimension(const ScDPNumGroupDimension & rOther)871cdf0e10cSrcweir ScDPNumGroupDimension::ScDPNumGroupDimension( const ScDPNumGroupDimension& rOther ) :
872cdf0e10cSrcweir aGroupInfo( rOther.aGroupInfo ),
873cdf0e10cSrcweir pDateHelper( NULL ),
874cdf0e10cSrcweir bHasNonInteger( false ),
875cdf0e10cSrcweir cDecSeparator( 0 )
876cdf0e10cSrcweir {
877cdf0e10cSrcweir if ( rOther.pDateHelper )
878cdf0e10cSrcweir pDateHelper = new ScDPDateGroupHelper( *rOther.pDateHelper );
879cdf0e10cSrcweir }
880cdf0e10cSrcweir
operator =(const ScDPNumGroupDimension & rOther)881cdf0e10cSrcweir ScDPNumGroupDimension& ScDPNumGroupDimension::operator=( const ScDPNumGroupDimension& rOther )
882cdf0e10cSrcweir {
883cdf0e10cSrcweir aGroupInfo = rOther.aGroupInfo;
884cdf0e10cSrcweir
885cdf0e10cSrcweir delete pDateHelper;
886cdf0e10cSrcweir if ( rOther.pDateHelper )
887cdf0e10cSrcweir pDateHelper = new ScDPDateGroupHelper( *rOther.pDateHelper );
888cdf0e10cSrcweir else
889cdf0e10cSrcweir pDateHelper = NULL;
890cdf0e10cSrcweir
891cdf0e10cSrcweir bHasNonInteger = false;
892cdf0e10cSrcweir return *this;
893cdf0e10cSrcweir }
894cdf0e10cSrcweir
DisposeData()895cdf0e10cSrcweir void ScDPNumGroupDimension::DisposeData()
896cdf0e10cSrcweir {
897cdf0e10cSrcweir bHasNonInteger = false;
898cdf0e10cSrcweir maMemberEntries.clear();
899cdf0e10cSrcweir }
900cdf0e10cSrcweir
~ScDPNumGroupDimension()901cdf0e10cSrcweir ScDPNumGroupDimension::~ScDPNumGroupDimension()
902cdf0e10cSrcweir {
903cdf0e10cSrcweir delete pDateHelper;
904cdf0e10cSrcweir }
905cdf0e10cSrcweir
MakeDateHelper(const ScDPNumGroupInfo & rInfo,sal_Int32 nPart)906cdf0e10cSrcweir void ScDPNumGroupDimension::MakeDateHelper( const ScDPNumGroupInfo& rInfo, sal_Int32 nPart )
907cdf0e10cSrcweir {
908cdf0e10cSrcweir delete pDateHelper;
909cdf0e10cSrcweir pDateHelper = new ScDPDateGroupHelper( rInfo, nPart );
910cdf0e10cSrcweir
911cdf0e10cSrcweir aGroupInfo.Enable = sal_True; //! or query both?
912cdf0e10cSrcweir }
913cdf0e10cSrcweir
GetNumEntries(SCCOL nSourceDim,ScDPTableDataCache * pCache,const std::vector<SCROW> & rOriginal) const914cdf0e10cSrcweir const std::vector< SCROW >& ScDPNumGroupDimension::GetNumEntries( SCCOL nSourceDim, ScDPTableDataCache* pCache,
915cdf0e10cSrcweir const std::vector< SCROW >& rOriginal ) const
916cdf0e10cSrcweir {
917cdf0e10cSrcweir if ( maMemberEntries.empty() )
918cdf0e10cSrcweir {
919cdf0e10cSrcweir SvNumberFormatter* pFormatter = pCache->GetDoc()->GetFormatTable();
920cdf0e10cSrcweir
921cdf0e10cSrcweir if ( pDateHelper )
922cdf0e10cSrcweir pDateHelper->FillColumnEntries( nSourceDim, pCache, maMemberEntries,rOriginal );
923cdf0e10cSrcweir else
924cdf0e10cSrcweir {
925cdf0e10cSrcweir // Copy textual entries.
926cdf0e10cSrcweir // Also look through the source entries for non-integer numbers, minimum and maximum.
927cdf0e10cSrcweir // GetNumEntries (GetColumnEntries) must be called before accessing the groups
928cdf0e10cSrcweir // (this in ensured by calling ScDPLevel::GetMembersObject for all column/row/page
929cdf0e10cSrcweir // dimensions before iterating over the values).
930cdf0e10cSrcweir
931cdf0e10cSrcweir cDecSeparator = ScGlobal::pLocaleData->getNumDecimalSep().GetChar(0);
932cdf0e10cSrcweir
933cdf0e10cSrcweir // non-integer GroupInfo values count, too
934cdf0e10cSrcweir bHasNonInteger = ( !aGroupInfo.AutoStart && !IsInteger( aGroupInfo.Start ) ) ||
935cdf0e10cSrcweir ( !aGroupInfo.AutoEnd && !IsInteger( aGroupInfo.End ) ) ||
936cdf0e10cSrcweir !IsInteger( aGroupInfo.Step );
937cdf0e10cSrcweir double fSourceMin = 0.0;
938cdf0e10cSrcweir double fSourceMax = 0.0;
939cdf0e10cSrcweir bool bFirst = true;
940cdf0e10cSrcweir
941cdf0e10cSrcweir size_t nOriginalCount = rOriginal.size();
942cdf0e10cSrcweir for (size_t nOriginalPos=0; nOriginalPos<nOriginalCount; nOriginalPos++)
943cdf0e10cSrcweir {
944cdf0e10cSrcweir const ScDPItemData* pItemData = pCache->GetItemDataById( nSourceDim , rOriginal[nOriginalPos] );
945cdf0e10cSrcweir
946cdf0e10cSrcweir if ( pItemData && pItemData ->HasStringData() )
947cdf0e10cSrcweir {
948cdf0e10cSrcweir lcl_Insert( nSourceDim, pCache, maMemberEntries, rOriginal[nOriginalPos] );
949cdf0e10cSrcweir }
950cdf0e10cSrcweir else
951cdf0e10cSrcweir {
952cdf0e10cSrcweir double fSourceValue = pItemData->GetValue();
953cdf0e10cSrcweir if ( bFirst )
954cdf0e10cSrcweir {
955cdf0e10cSrcweir fSourceMin = fSourceMax = fSourceValue;
956cdf0e10cSrcweir bFirst = false;
957cdf0e10cSrcweir }
958cdf0e10cSrcweir else
959cdf0e10cSrcweir {
960cdf0e10cSrcweir if ( fSourceValue < fSourceMin )
961cdf0e10cSrcweir fSourceMin = fSourceValue;
962cdf0e10cSrcweir if ( fSourceValue > fSourceMax )
963cdf0e10cSrcweir fSourceMax = fSourceValue;
964cdf0e10cSrcweir }
965cdf0e10cSrcweir if ( !bHasNonInteger && !IsInteger( fSourceValue ) )
966cdf0e10cSrcweir {
967cdf0e10cSrcweir // if any non-integer numbers are involved, the group labels are
968cdf0e10cSrcweir // shown including their upper limit
969cdf0e10cSrcweir bHasNonInteger = true;
970cdf0e10cSrcweir }
971cdf0e10cSrcweir }
972cdf0e10cSrcweir }
973cdf0e10cSrcweir
974cdf0e10cSrcweir if ( aGroupInfo.DateValues )
975cdf0e10cSrcweir {
976cdf0e10cSrcweir // special handling for dates: always integer, round down limits
977cdf0e10cSrcweir bHasNonInteger = false;
978cdf0e10cSrcweir fSourceMin = rtl::math::approxFloor( fSourceMin );
979cdf0e10cSrcweir fSourceMax = rtl::math::approxFloor( fSourceMax ) + 1;
980cdf0e10cSrcweir }
981cdf0e10cSrcweir
982cdf0e10cSrcweir if ( aGroupInfo.AutoStart )
983cdf0e10cSrcweir const_cast<ScDPNumGroupDimension*>(this)->aGroupInfo.Start = fSourceMin;
984cdf0e10cSrcweir if ( aGroupInfo.AutoEnd )
985cdf0e10cSrcweir const_cast<ScDPNumGroupDimension*>(this)->aGroupInfo.End = fSourceMax;
986cdf0e10cSrcweir
987cdf0e10cSrcweir //! limit number of entries?
988cdf0e10cSrcweir
989cdf0e10cSrcweir long nLoopCount = 0;
990cdf0e10cSrcweir double fLoop = aGroupInfo.Start;
991cdf0e10cSrcweir
992cdf0e10cSrcweir // Use "less than" instead of "less or equal" for the loop - don't create a group
993cdf0e10cSrcweir // that consists only of the end value. Instead, the end value is then included
994cdf0e10cSrcweir // in the last group (last group is bigger than the others).
995cdf0e10cSrcweir // The first group has to be created nonetheless. GetNumGroupForValue has corresponding logic.
996cdf0e10cSrcweir
997cdf0e10cSrcweir bool bFirstGroup = true;
998cdf0e10cSrcweir while ( bFirstGroup || ( fLoop < aGroupInfo.End && !rtl::math::approxEqual( fLoop, aGroupInfo.End ) ) )
999cdf0e10cSrcweir {
1000cdf0e10cSrcweir String aName = lcl_GetNumGroupName( fLoop, aGroupInfo, bHasNonInteger, cDecSeparator, pFormatter );
1001cdf0e10cSrcweir // create a numerical entry to ensure proper sorting
1002cdf0e10cSrcweir // (in FillMemberResults this needs special handling)
1003cdf0e10cSrcweir lcl_InsertValue<true>( nSourceDim, pCache, maMemberEntries, aName, fLoop );
1004cdf0e10cSrcweir ++nLoopCount;
1005cdf0e10cSrcweir fLoop = aGroupInfo.Start + nLoopCount * aGroupInfo.Step;
1006cdf0e10cSrcweir bFirstGroup = false;
1007cdf0e10cSrcweir
1008cdf0e10cSrcweir // ScDPItemData values are compared with approxEqual
1009cdf0e10cSrcweir }
1010cdf0e10cSrcweir
1011cdf0e10cSrcweir String aFirstName = lcl_GetSpecialNumGroupName( aGroupInfo.Start, true, cDecSeparator, aGroupInfo.DateValues, pFormatter );
1012cdf0e10cSrcweir lcl_InsertValue<true>( nSourceDim, pCache, maMemberEntries, aFirstName, aGroupInfo.Start - aGroupInfo.Step );
1013cdf0e10cSrcweir
1014cdf0e10cSrcweir String aLastName = lcl_GetSpecialNumGroupName( aGroupInfo.End, false, cDecSeparator, aGroupInfo.DateValues, pFormatter );
1015cdf0e10cSrcweir lcl_InsertValue<true>( nSourceDim, pCache, maMemberEntries, aLastName, aGroupInfo.End + aGroupInfo.Step );
1016cdf0e10cSrcweir }
1017cdf0e10cSrcweir }
1018cdf0e10cSrcweir return maMemberEntries;
1019cdf0e10cSrcweir }
1020cdf0e10cSrcweir
ScDPGroupTableData(const shared_ptr<ScDPTableData> & pSource,ScDocument * pDocument)1021cdf0e10cSrcweir ScDPGroupTableData::ScDPGroupTableData( const shared_ptr<ScDPTableData>& pSource, ScDocument* pDocument ) :
1022cdf0e10cSrcweir ScDPTableData(pDocument, pSource->GetCacheId() ),
1023cdf0e10cSrcweir pSourceData( pSource ),
1024cdf0e10cSrcweir pDoc( pDocument )
1025cdf0e10cSrcweir {
1026cdf0e10cSrcweir DBG_ASSERT( pSource, "ScDPGroupTableData: pSource can't be NULL" );
1027cdf0e10cSrcweir
1028cdf0e10cSrcweir CreateCacheTable();
1029cdf0e10cSrcweir nSourceCount = pSource->GetColumnCount(); // real columns, excluding data layout
1030cdf0e10cSrcweir pNumGroups = new ScDPNumGroupDimension[nSourceCount];
1031cdf0e10cSrcweir }
1032cdf0e10cSrcweir
~ScDPGroupTableData()1033cdf0e10cSrcweir ScDPGroupTableData::~ScDPGroupTableData()
1034cdf0e10cSrcweir {
1035cdf0e10cSrcweir delete[] pNumGroups;
1036cdf0e10cSrcweir }
1037cdf0e10cSrcweir
AddGroupDimension(const ScDPGroupDimension & rGroup)1038cdf0e10cSrcweir void ScDPGroupTableData::AddGroupDimension( const ScDPGroupDimension& rGroup )
1039cdf0e10cSrcweir {
1040cdf0e10cSrcweir ScDPGroupDimension aNewGroup( rGroup );
1041cdf0e10cSrcweir aNewGroup.SetGroupDim( GetColumnCount() ); // new dimension will be at the end
1042cdf0e10cSrcweir aGroups.push_back( aNewGroup );
1043cdf0e10cSrcweir aGroupNames.insert( OUString(aNewGroup.GetName()) );
1044cdf0e10cSrcweir }
1045cdf0e10cSrcweir
SetNumGroupDimension(long nIndex,const ScDPNumGroupDimension & rGroup)1046cdf0e10cSrcweir void ScDPGroupTableData::SetNumGroupDimension( long nIndex, const ScDPNumGroupDimension& rGroup )
1047cdf0e10cSrcweir {
1048cdf0e10cSrcweir if ( nIndex < nSourceCount )
1049cdf0e10cSrcweir {
1050cdf0e10cSrcweir pNumGroups[nIndex] = rGroup;
1051cdf0e10cSrcweir
1052cdf0e10cSrcweir // automatic minimum / maximum is handled in GetNumEntries
1053cdf0e10cSrcweir }
1054cdf0e10cSrcweir }
1055cdf0e10cSrcweir
GetDimensionIndex(const String & rName)1056cdf0e10cSrcweir long ScDPGroupTableData::GetDimensionIndex( const String& rName )
1057cdf0e10cSrcweir {
1058cdf0e10cSrcweir for (long i=0; i<nSourceCount; i++) // nSourceCount excludes data layout
1059cdf0e10cSrcweir if ( pSourceData->getDimensionName(i) == rName ) //! ignore case?
1060cdf0e10cSrcweir return i;
1061cdf0e10cSrcweir return -1; // none
1062cdf0e10cSrcweir }
1063cdf0e10cSrcweir
GetColumnCount()1064cdf0e10cSrcweir long ScDPGroupTableData::GetColumnCount()
1065cdf0e10cSrcweir {
1066cdf0e10cSrcweir return nSourceCount + aGroups.size();
1067cdf0e10cSrcweir }
1068cdf0e10cSrcweir
IsNumGroupDimension(long nDimension) const1069cdf0e10cSrcweir bool ScDPGroupTableData::IsNumGroupDimension( long nDimension ) const
1070cdf0e10cSrcweir {
1071cdf0e10cSrcweir return ( nDimension < nSourceCount && pNumGroups[nDimension].GetInfo().Enable );
1072cdf0e10cSrcweir }
1073cdf0e10cSrcweir
GetNumGroupInfo(long nDimension,ScDPNumGroupInfo & rInfo,bool & rNonInteger,sal_Unicode & rDecimal)1074cdf0e10cSrcweir void ScDPGroupTableData::GetNumGroupInfo( long nDimension, ScDPNumGroupInfo& rInfo,
1075cdf0e10cSrcweir bool& rNonInteger, sal_Unicode& rDecimal )
1076cdf0e10cSrcweir {
1077cdf0e10cSrcweir if ( nDimension < nSourceCount )
1078cdf0e10cSrcweir {
1079cdf0e10cSrcweir rInfo = pNumGroups[nDimension].GetInfo();
1080cdf0e10cSrcweir rNonInteger = pNumGroups[nDimension].HasNonInteger();
1081cdf0e10cSrcweir rDecimal = pNumGroups[nDimension].GetDecSeparator();
1082cdf0e10cSrcweir }
1083cdf0e10cSrcweir }
1084cdf0e10cSrcweir // Wang Xu Ming - DataPilot migration
GetMembersCount(long nDim)1085cdf0e10cSrcweir long ScDPGroupTableData::GetMembersCount( long nDim )
1086cdf0e10cSrcweir {
1087cdf0e10cSrcweir const std::vector< SCROW >& members = GetColumnEntries( nDim );
1088cdf0e10cSrcweir return members.size();
1089cdf0e10cSrcweir }
GetColumnEntries(long nColumn)1090cdf0e10cSrcweir const std::vector< SCROW >& ScDPGroupTableData::GetColumnEntries( long nColumn )
1091cdf0e10cSrcweir {
1092cdf0e10cSrcweir if ( nColumn >= nSourceCount )
1093cdf0e10cSrcweir {
1094cdf0e10cSrcweir if ( getIsDataLayoutDimension( nColumn) ) // data layout dimension?
1095cdf0e10cSrcweir nColumn = nSourceCount; // index of data layout in source data
1096cdf0e10cSrcweir else
1097cdf0e10cSrcweir {
1098cdf0e10cSrcweir const ScDPGroupDimension& rGroupDim = aGroups[nColumn - nSourceCount];
1099cdf0e10cSrcweir long nSourceDim = rGroupDim.GetSourceDim();
1100cdf0e10cSrcweir // collection is cached at pSourceData, GetColumnEntries can be called every time
1101cdf0e10cSrcweir const std::vector< SCROW >& rOriginal = pSourceData->GetColumnEntries( nSourceDim );
1102cdf0e10cSrcweir return rGroupDim.GetColumnEntries( GetCacheTable(), rOriginal );
1103cdf0e10cSrcweir }
1104cdf0e10cSrcweir }
1105cdf0e10cSrcweir
1106cdf0e10cSrcweir if ( IsNumGroupDimension( nColumn ) )
1107cdf0e10cSrcweir {
1108cdf0e10cSrcweir // dimension number is unchanged for numerical groups
1109cdf0e10cSrcweir const std::vector< SCROW >& rOriginal = pSourceData->GetColumnEntries( nColumn );
1110cdf0e10cSrcweir return pNumGroups[nColumn].GetNumEntries( (SCCOL)nColumn, GetCacheTable().GetCache(), rOriginal );
1111cdf0e10cSrcweir }
1112cdf0e10cSrcweir
1113cdf0e10cSrcweir return pSourceData->GetColumnEntries( nColumn );
1114cdf0e10cSrcweir }
1115cdf0e10cSrcweir
GetMemberById(long nDim,long nId)1116cdf0e10cSrcweir const ScDPItemData* ScDPGroupTableData::GetMemberById( long nDim, long nId )
1117cdf0e10cSrcweir {
1118cdf0e10cSrcweir if ( nDim >= nSourceCount )
1119cdf0e10cSrcweir {
1120cdf0e10cSrcweir if ( getIsDataLayoutDimension( nDim) )
1121cdf0e10cSrcweir nDim = nSourceCount;
1122cdf0e10cSrcweir else
1123cdf0e10cSrcweir {
1124cdf0e10cSrcweir const ScDPGroupDimension& rGroupDim = aGroups[nDim - nSourceCount];
1125cdf0e10cSrcweir nDim = rGroupDim.GetSourceDim();
1126cdf0e10cSrcweir }
1127cdf0e10cSrcweir }
1128cdf0e10cSrcweir return pSourceData->GetMemberById( nDim, nId );
1129cdf0e10cSrcweir }
1130cdf0e10cSrcweir
getDimensionName(long nColumn)1131cdf0e10cSrcweir String ScDPGroupTableData::getDimensionName(long nColumn)
1132cdf0e10cSrcweir {
1133cdf0e10cSrcweir if ( nColumn >= nSourceCount )
1134cdf0e10cSrcweir {
1135cdf0e10cSrcweir if ( nColumn == sal::static_int_cast<long>( nSourceCount + aGroups.size() ) ) // data layout dimension?
1136cdf0e10cSrcweir nColumn = nSourceCount; // index of data layout in source data
1137cdf0e10cSrcweir else
1138cdf0e10cSrcweir return aGroups[nColumn - nSourceCount].GetName();
1139cdf0e10cSrcweir }
1140cdf0e10cSrcweir
1141cdf0e10cSrcweir return pSourceData->getDimensionName( nColumn );
1142cdf0e10cSrcweir }
1143cdf0e10cSrcweir
getIsDataLayoutDimension(long nColumn)1144cdf0e10cSrcweir sal_Bool ScDPGroupTableData::getIsDataLayoutDimension(long nColumn)
1145cdf0e10cSrcweir {
1146cdf0e10cSrcweir // position of data layout dimension is moved from source data
1147cdf0e10cSrcweir return ( nColumn == sal::static_int_cast<long>( nSourceCount + aGroups.size() ) ); // data layout dimension?
1148cdf0e10cSrcweir }
1149cdf0e10cSrcweir
IsDateDimension(long nDim)1150cdf0e10cSrcweir sal_Bool ScDPGroupTableData::IsDateDimension(long nDim)
1151cdf0e10cSrcweir {
1152cdf0e10cSrcweir if ( nDim >= nSourceCount )
1153cdf0e10cSrcweir {
1154cdf0e10cSrcweir if ( nDim == sal::static_int_cast<long>( nSourceCount + aGroups.size() ) ) // data layout dimension?
1155cdf0e10cSrcweir nDim = nSourceCount; // index of data layout in source data
1156cdf0e10cSrcweir else
1157cdf0e10cSrcweir nDim = aGroups[nDim - nSourceCount].GetSourceDim(); // look at original dimension
1158cdf0e10cSrcweir }
1159cdf0e10cSrcweir
1160cdf0e10cSrcweir return pSourceData->IsDateDimension( nDim );
1161cdf0e10cSrcweir }
1162cdf0e10cSrcweir
GetNumberFormat(long nDim)1163cdf0e10cSrcweir sal_uLong ScDPGroupTableData::GetNumberFormat(long nDim)
1164cdf0e10cSrcweir {
1165cdf0e10cSrcweir if ( nDim >= nSourceCount )
1166cdf0e10cSrcweir {
1167cdf0e10cSrcweir if ( nDim == sal::static_int_cast<long>( nSourceCount + aGroups.size() ) ) // data layout dimension?
1168cdf0e10cSrcweir nDim = nSourceCount; // index of data layout in source data
1169cdf0e10cSrcweir else
1170cdf0e10cSrcweir nDim = aGroups[nDim - nSourceCount].GetSourceDim(); // look at original dimension
1171cdf0e10cSrcweir }
1172cdf0e10cSrcweir
1173cdf0e10cSrcweir return pSourceData->GetNumberFormat( nDim );
1174cdf0e10cSrcweir }
1175cdf0e10cSrcweir
DisposeData()1176cdf0e10cSrcweir void ScDPGroupTableData::DisposeData()
1177cdf0e10cSrcweir {
1178cdf0e10cSrcweir for ( ScDPGroupDimensionVec::iterator aIter(aGroups.begin()); aIter != aGroups.end(); aIter++ )
1179cdf0e10cSrcweir aIter->DisposeData();
1180cdf0e10cSrcweir
1181cdf0e10cSrcweir for ( long i=0; i<nSourceCount; i++ )
1182cdf0e10cSrcweir pNumGroups[i].DisposeData();
1183cdf0e10cSrcweir
1184cdf0e10cSrcweir pSourceData->DisposeData();
1185cdf0e10cSrcweir }
1186cdf0e10cSrcweir
SetEmptyFlags(sal_Bool bIgnoreEmptyRows,sal_Bool bRepeatIfEmpty)1187cdf0e10cSrcweir void ScDPGroupTableData::SetEmptyFlags( sal_Bool bIgnoreEmptyRows, sal_Bool bRepeatIfEmpty )
1188cdf0e10cSrcweir {
1189cdf0e10cSrcweir pSourceData->SetEmptyFlags( bIgnoreEmptyRows, bRepeatIfEmpty );
1190cdf0e10cSrcweir }
1191cdf0e10cSrcweir
IsRepeatIfEmpty()1192cdf0e10cSrcweir bool ScDPGroupTableData::IsRepeatIfEmpty()
1193cdf0e10cSrcweir {
1194cdf0e10cSrcweir return pSourceData->IsRepeatIfEmpty();
1195cdf0e10cSrcweir }
1196cdf0e10cSrcweir
CreateCacheTable()1197cdf0e10cSrcweir void ScDPGroupTableData::CreateCacheTable()
1198cdf0e10cSrcweir {
1199cdf0e10cSrcweir pSourceData->CreateCacheTable();
1200cdf0e10cSrcweir }
1201cdf0e10cSrcweir
ModifyFilterCriteria(vector<ScDPCacheTable::Criterion> & rCriteria)1202cdf0e10cSrcweir void ScDPGroupTableData::ModifyFilterCriteria(vector<ScDPCacheTable::Criterion>& rCriteria)
1203cdf0e10cSrcweir {
1204cdf0e10cSrcweir typedef hash_map<long, const ScDPGroupDimension*> GroupFieldMapType;
1205cdf0e10cSrcweir GroupFieldMapType aGroupFieldIds;
1206cdf0e10cSrcweir {
1207cdf0e10cSrcweir ScDPGroupDimensionVec::const_iterator itr = aGroups.begin(), itrEnd = aGroups.end();
1208cdf0e10cSrcweir for (; itr != itrEnd; ++itr)
1209cdf0e10cSrcweir aGroupFieldIds.insert( hash_map<long, const ScDPGroupDimension*>::value_type(itr->GetGroupDim(), &(*itr)) );
1210cdf0e10cSrcweir }
1211cdf0e10cSrcweir
1212cdf0e10cSrcweir vector<ScDPCacheTable::Criterion> aNewCriteria;
1213cdf0e10cSrcweir aNewCriteria.reserve(rCriteria.size() + aGroups.size());
1214cdf0e10cSrcweir
1215cdf0e10cSrcweir // Go through all the filtered field names and process them appropriately.
1216cdf0e10cSrcweir
1217cdf0e10cSrcweir vector<ScDPCacheTable::Criterion>::const_iterator itrEnd = rCriteria.end();
1218cdf0e10cSrcweir GroupFieldMapType::const_iterator itrGrpEnd = aGroupFieldIds.end();
1219cdf0e10cSrcweir for (vector<ScDPCacheTable::Criterion>::const_iterator itr = rCriteria.begin(); itr != itrEnd; ++itr)
1220cdf0e10cSrcweir {
1221cdf0e10cSrcweir ScDPCacheTable::SingleFilter* pFilter = dynamic_cast<ScDPCacheTable::SingleFilter*>(itr->mpFilter.get());
1222cdf0e10cSrcweir if (!pFilter)
1223cdf0e10cSrcweir // We expect this to be a single filter.
1224cdf0e10cSrcweir continue;
1225cdf0e10cSrcweir
1226cdf0e10cSrcweir GroupFieldMapType::const_iterator itrGrp = aGroupFieldIds.find(itr->mnFieldIndex);
1227cdf0e10cSrcweir if (itrGrp == itrGrpEnd)
1228cdf0e10cSrcweir {
1229cdf0e10cSrcweir if (IsNumGroupDimension(itr->mnFieldIndex))
1230cdf0e10cSrcweir {
1231cdf0e10cSrcweir // internal number group field
1232cdf0e10cSrcweir const ScDPNumGroupDimension& rNumGrpDim = pNumGroups[itr->mnFieldIndex];
1233cdf0e10cSrcweir const ScDPDateGroupHelper* pDateHelper = rNumGrpDim.GetDateHelper();
1234cdf0e10cSrcweir if (!pDateHelper)
1235cdf0e10cSrcweir {
1236cdf0e10cSrcweir // What do we do here !?
1237cdf0e10cSrcweir continue;
1238cdf0e10cSrcweir }
1239cdf0e10cSrcweir
1240cdf0e10cSrcweir ScDPCacheTable::Criterion aCri;
1241cdf0e10cSrcweir aCri.mnFieldIndex = itr->mnFieldIndex;
1242cdf0e10cSrcweir aCri.mpFilter.reset(new ScDPGroupDateFilter(
1243cdf0e10cSrcweir pFilter->getMatchValue(), pDateHelper->GetDatePart(),
1244cdf0e10cSrcweir pDoc->GetFormatTable()->GetNullDate(), &pDateHelper->GetNumInfo()));
1245cdf0e10cSrcweir
1246cdf0e10cSrcweir aNewCriteria.push_back(aCri);
1247cdf0e10cSrcweir }
1248cdf0e10cSrcweir else
1249cdf0e10cSrcweir {
1250cdf0e10cSrcweir // This is a regular source field.
1251cdf0e10cSrcweir aNewCriteria.push_back(*itr);
1252cdf0e10cSrcweir }
1253cdf0e10cSrcweir }
1254cdf0e10cSrcweir else
1255cdf0e10cSrcweir {
1256cdf0e10cSrcweir // This is an ordinary group field or external number group field.
1257cdf0e10cSrcweir
1258cdf0e10cSrcweir const ScDPGroupDimension* pGrpDim = itrGrp->second;
1259cdf0e10cSrcweir long nSrcDim = pGrpDim->GetSourceDim();
1260cdf0e10cSrcweir const ScDPDateGroupHelper* pDateHelper = pGrpDim->GetDateHelper();
1261cdf0e10cSrcweir
1262cdf0e10cSrcweir if (pDateHelper)
1263cdf0e10cSrcweir {
1264cdf0e10cSrcweir // external number group
1265cdf0e10cSrcweir ScDPCacheTable::Criterion aCri;
1266cdf0e10cSrcweir aCri.mnFieldIndex = nSrcDim; // use the source dimension, not the group dimension.
1267cdf0e10cSrcweir aCri.mpFilter.reset(new ScDPGroupDateFilter(
1268cdf0e10cSrcweir pFilter->getMatchValue(), pDateHelper->GetDatePart(),
1269cdf0e10cSrcweir pDoc->GetFormatTable()->GetNullDate(), &pDateHelper->GetNumInfo()));
1270cdf0e10cSrcweir
1271cdf0e10cSrcweir aNewCriteria.push_back(aCri);
1272cdf0e10cSrcweir }
1273cdf0e10cSrcweir else
1274cdf0e10cSrcweir {
1275cdf0e10cSrcweir // normal group
1276cdf0e10cSrcweir
1277cdf0e10cSrcweir // Note that each group dimension may have multiple group names!
1278cdf0e10cSrcweir size_t nGroupItemCount = pGrpDim->GetItemCount();
1279cdf0e10cSrcweir for (size_t i = 0; i < nGroupItemCount; ++i)
1280cdf0e10cSrcweir {
1281cdf0e10cSrcweir const ScDPGroupItem* pGrpItem = pGrpDim->GetGroupByIndex(i);
1282cdf0e10cSrcweir // Wang Xu Ming -- 2009-6-9
1283cdf0e10cSrcweir // DataPilot Migration
1284cdf0e10cSrcweir ScDPItemData aName( pFilter->getMatchString(),pFilter->getMatchValue(),pFilter->hasValue()) ;
1285cdf0e10cSrcweir /*aName.aString = pFilter->getMatchString();
1286cdf0e10cSrcweir aName.fValue = pFilter->getMatchValue();
1287cdf0e10cSrcweir aName.bHasValue = pFilter->hasValue();*/
1288cdf0e10cSrcweir // End Comments
1289cdf0e10cSrcweir if (!pGrpItem || !pGrpItem->GetName().IsCaseInsEqual(aName))
1290cdf0e10cSrcweir continue;
1291cdf0e10cSrcweir
1292cdf0e10cSrcweir ScDPCacheTable::Criterion aCri;
1293cdf0e10cSrcweir aCri.mnFieldIndex = nSrcDim;
1294cdf0e10cSrcweir aCri.mpFilter.reset(new ScDPCacheTable::GroupFilter());
1295cdf0e10cSrcweir ScDPCacheTable::GroupFilter* pGrpFilter =
1296cdf0e10cSrcweir static_cast<ScDPCacheTable::GroupFilter*>(aCri.mpFilter.get());
1297cdf0e10cSrcweir
1298cdf0e10cSrcweir pGrpItem->FillGroupFilter(*pGrpFilter);
1299cdf0e10cSrcweir aNewCriteria.push_back(aCri);
1300cdf0e10cSrcweir }
1301cdf0e10cSrcweir }
1302cdf0e10cSrcweir }
1303cdf0e10cSrcweir }
1304cdf0e10cSrcweir rCriteria.swap(aNewCriteria);
1305cdf0e10cSrcweir }
1306cdf0e10cSrcweir
FilterCacheTable(const vector<ScDPCacheTable::Criterion> & rCriteria,const hash_set<sal_Int32> & rCatDims)1307cdf0e10cSrcweir void ScDPGroupTableData::FilterCacheTable(const vector<ScDPCacheTable::Criterion>& rCriteria, const hash_set<sal_Int32>& rCatDims)
1308cdf0e10cSrcweir {
1309cdf0e10cSrcweir vector<ScDPCacheTable::Criterion> aNewCriteria(rCriteria);
1310cdf0e10cSrcweir ModifyFilterCriteria(aNewCriteria);
1311cdf0e10cSrcweir pSourceData->FilterCacheTable(aNewCriteria, rCatDims);
1312cdf0e10cSrcweir }
1313cdf0e10cSrcweir
GetDrillDownData(const vector<ScDPCacheTable::Criterion> & rCriteria,const hash_set<sal_Int32> & rCatDims,Sequence<Sequence<Any>> & rData)1314cdf0e10cSrcweir void ScDPGroupTableData::GetDrillDownData(const vector<ScDPCacheTable::Criterion>& rCriteria, const hash_set<sal_Int32>& rCatDims, Sequence< Sequence<Any> >& rData)
1315cdf0e10cSrcweir {
1316cdf0e10cSrcweir vector<ScDPCacheTable::Criterion> aNewCriteria(rCriteria);
1317cdf0e10cSrcweir ModifyFilterCriteria(aNewCriteria);
1318cdf0e10cSrcweir pSourceData->GetDrillDownData(aNewCriteria, rCatDims, rData);
1319cdf0e10cSrcweir }
1320cdf0e10cSrcweir
CalcResults(CalcInfo & rInfo,bool bAutoShow)1321cdf0e10cSrcweir void ScDPGroupTableData::CalcResults(CalcInfo& rInfo, bool bAutoShow)
1322cdf0e10cSrcweir {
1323cdf0e10cSrcweir // #i111435# Inside FillRowDataFromCacheTable/GetItemData, virtual methods
1324cdf0e10cSrcweir // getIsDataLayoutDimension and GetSourceDim are used, so it has to be called
1325cdf0e10cSrcweir // with original rInfo, containing dimension indexes of the grouped data.
1326cdf0e10cSrcweir
1327cdf0e10cSrcweir const ScDPCacheTable& rCacheTable = pSourceData->GetCacheTable();
1328cdf0e10cSrcweir sal_Int32 nRowSize = rCacheTable.getRowSize();
1329cdf0e10cSrcweir for (sal_Int32 nRow = 0; nRow < nRowSize; ++nRow)
1330cdf0e10cSrcweir {
1331cdf0e10cSrcweir if (!rCacheTable.isRowActive(nRow))
1332cdf0e10cSrcweir continue;
1333cdf0e10cSrcweir
1334cdf0e10cSrcweir CalcRowData aData;
1335cdf0e10cSrcweir FillRowDataFromCacheTable(nRow, rCacheTable, rInfo, aData);
1336cdf0e10cSrcweir
1337cdf0e10cSrcweir if ( !rInfo.aColLevelDims.empty() )
1338cdf0e10cSrcweir FillGroupValues(&aData.aColData[0], rInfo.aColLevelDims.size(), &rInfo.aColLevelDims[0]);
1339cdf0e10cSrcweir if ( !rInfo.aRowLevelDims.empty() )
1340cdf0e10cSrcweir FillGroupValues(&aData.aRowData[0], rInfo.aRowLevelDims.size(), &rInfo.aRowLevelDims[0]);
1341cdf0e10cSrcweir if ( !rInfo.aPageDims.empty() )
1342cdf0e10cSrcweir FillGroupValues(&aData.aPageData[0], rInfo.aPageDims.size(), &rInfo.aPageDims[0]);
1343cdf0e10cSrcweir
1344cdf0e10cSrcweir ProcessRowData(rInfo, aData, bAutoShow);
1345cdf0e10cSrcweir }
1346cdf0e10cSrcweir }
1347cdf0e10cSrcweir
GetCacheTable() const1348cdf0e10cSrcweir const ScDPCacheTable& ScDPGroupTableData::GetCacheTable() const
1349cdf0e10cSrcweir {
1350cdf0e10cSrcweir return pSourceData->GetCacheTable();
1351cdf0e10cSrcweir }
1352cdf0e10cSrcweir
FillGroupValues(SCROW * pItemDataIndex,long nCount,const long * pDims)1353cdf0e10cSrcweir void ScDPGroupTableData::FillGroupValues( /*ScDPItemData* pItemData*/ SCROW* pItemDataIndex, long nCount, const long* pDims )
1354cdf0e10cSrcweir {
1355cdf0e10cSrcweir long nGroupedColumns = aGroups.size();
1356cdf0e10cSrcweir
1357cdf0e10cSrcweir ScDPTableDataCache* pCache = GetCacheTable().GetCache();
1358cdf0e10cSrcweir for (long nDim=0; nDim<nCount; nDim++)
1359cdf0e10cSrcweir {
1360cdf0e10cSrcweir const ScDPDateGroupHelper* pDateHelper = NULL;
1361cdf0e10cSrcweir
1362cdf0e10cSrcweir long nColumn = pDims[nDim];
1363cdf0e10cSrcweir long nSourceDim = nColumn;
1364cdf0e10cSrcweir if ( nColumn >= nSourceCount && nColumn < nSourceCount + nGroupedColumns )
1365cdf0e10cSrcweir {
1366cdf0e10cSrcweir const ScDPGroupDimension& rGroupDim = aGroups[nColumn - nSourceCount];
1367cdf0e10cSrcweir nSourceDim= rGroupDim.GetSourceDim();
1368cdf0e10cSrcweir pDateHelper = rGroupDim.GetDateHelper();
1369cdf0e10cSrcweir if ( !pDateHelper ) // date is handled below
1370cdf0e10cSrcweir {
1371cdf0e10cSrcweir const ScDPGroupItem* pGroupItem = rGroupDim.GetGroupForData( *GetMemberById( nSourceDim, pItemDataIndex[nDim] ));
1372cdf0e10cSrcweir if ( pGroupItem )
1373cdf0e10cSrcweir pItemDataIndex[nDim] = pCache->GetAdditionalItemID( pGroupItem->GetName() );
1374cdf0e10cSrcweir }
1375cdf0e10cSrcweir }
1376cdf0e10cSrcweir else if ( IsNumGroupDimension( nColumn ) )
1377cdf0e10cSrcweir {
1378cdf0e10cSrcweir pDateHelper = pNumGroups[nColumn].GetDateHelper();
1379cdf0e10cSrcweir if ( !pDateHelper ) // date is handled below
1380cdf0e10cSrcweir {
1381cdf0e10cSrcweir const ScDPItemData* pData = pCache->GetItemDataById( (SCCOL)nSourceDim, pItemDataIndex[nDim]);
1382cdf0e10cSrcweir if ( pData ->IsValue() )
1383cdf0e10cSrcweir {
1384cdf0e10cSrcweir ScDPNumGroupInfo aNumInfo;
1385cdf0e10cSrcweir bool bHasNonInteger = false;
1386cdf0e10cSrcweir sal_Unicode cDecSeparator = 0;
1387cdf0e10cSrcweir GetNumGroupInfo( nColumn, aNumInfo, bHasNonInteger, cDecSeparator );
1388cdf0e10cSrcweir double fGroupValue;
1389cdf0e10cSrcweir String aGroupName = lcl_GetNumGroupForValue( pData->GetValue(),
1390cdf0e10cSrcweir aNumInfo, bHasNonInteger, cDecSeparator, fGroupValue, pDoc );
1391cdf0e10cSrcweir ScDPItemData aItemData ( aGroupName, fGroupValue, sal_True ) ;
1392cdf0e10cSrcweir pItemDataIndex[nDim] = pCache->GetAdditionalItemID( aItemData );
1393cdf0e10cSrcweir }
1394cdf0e10cSrcweir // else (textual) keep original value
1395cdf0e10cSrcweir }
1396cdf0e10cSrcweir }
1397cdf0e10cSrcweir
1398cdf0e10cSrcweir if ( pDateHelper )
1399cdf0e10cSrcweir {
1400cdf0e10cSrcweir const ScDPItemData* pData = GetCacheTable().GetCache()->GetItemDataById( (SCCOL)nSourceDim, pItemDataIndex[nDim]);
1401cdf0e10cSrcweir if ( pData ->IsValue() )
1402cdf0e10cSrcweir {
1403cdf0e10cSrcweir sal_Int32 nPartValue = lcl_GetDatePartValue(
1404cdf0e10cSrcweir pData->GetValue(), pDateHelper->GetDatePart(), pDoc->GetFormatTable(),
1405cdf0e10cSrcweir &pDateHelper->GetNumInfo() );
1406cdf0e10cSrcweir // Wang Xu Ming -- 2009-9-7
1407cdf0e10cSrcweir // DataPilot Migration - Cache&&Performance
1408cdf0e10cSrcweir //String aName = lcl_GetDateGroupName( pDateHelper, nPartValue, pDoc->GetFormatTable() );
1409cdf0e10cSrcweir ScDPItemData aItemData( pDateHelper->GetDatePart(), String(), nPartValue, ScDPItemData::MK_DATA|ScDPItemData::MK_VAL|ScDPItemData::MK_DATEPART );
1410cdf0e10cSrcweir pItemDataIndex[nDim] = GetCacheTable().GetCache()->GetAdditionalItemID( aItemData );
1411cdf0e10cSrcweir // End Comments
1412cdf0e10cSrcweir }
1413cdf0e10cSrcweir }
1414cdf0e10cSrcweir }
1415cdf0e10cSrcweir }
1416cdf0e10cSrcweir
IsBaseForGroup(long nDim) const1417cdf0e10cSrcweir sal_Bool ScDPGroupTableData::IsBaseForGroup(long nDim) const
1418cdf0e10cSrcweir {
1419cdf0e10cSrcweir for ( ScDPGroupDimensionVec::const_iterator aIter(aGroups.begin()); aIter != aGroups.end(); aIter++ )
1420cdf0e10cSrcweir {
1421cdf0e10cSrcweir const ScDPGroupDimension& rDim = *aIter;
1422cdf0e10cSrcweir if ( rDim.GetSourceDim() == nDim )
1423cdf0e10cSrcweir return sal_True;
1424cdf0e10cSrcweir }
1425cdf0e10cSrcweir
1426cdf0e10cSrcweir return sal_False;
1427cdf0e10cSrcweir }
1428cdf0e10cSrcweir
GetGroupBase(long nGroupDim) const1429cdf0e10cSrcweir long ScDPGroupTableData::GetGroupBase(long nGroupDim) const
1430cdf0e10cSrcweir {
1431cdf0e10cSrcweir for ( ScDPGroupDimensionVec::const_iterator aIter(aGroups.begin()); aIter != aGroups.end(); aIter++ )
1432cdf0e10cSrcweir {
1433cdf0e10cSrcweir const ScDPGroupDimension& rDim = *aIter;
1434cdf0e10cSrcweir if ( rDim.GetGroupDim() == nGroupDim )
1435cdf0e10cSrcweir return rDim.GetSourceDim();
1436cdf0e10cSrcweir }
1437cdf0e10cSrcweir
1438cdf0e10cSrcweir return -1; // none
1439cdf0e10cSrcweir }
1440cdf0e10cSrcweir
IsNumOrDateGroup(long nDimension) const1441cdf0e10cSrcweir sal_Bool ScDPGroupTableData::IsNumOrDateGroup(long nDimension) const
1442cdf0e10cSrcweir {
1443cdf0e10cSrcweir // Virtual method from ScDPTableData, used in result data to force text labels.
1444cdf0e10cSrcweir
1445cdf0e10cSrcweir if ( nDimension < nSourceCount )
1446cdf0e10cSrcweir {
1447cdf0e10cSrcweir return pNumGroups[nDimension].GetInfo().Enable ||
1448cdf0e10cSrcweir pNumGroups[nDimension].GetDateHelper();
1449cdf0e10cSrcweir }
1450cdf0e10cSrcweir
1451cdf0e10cSrcweir for ( ScDPGroupDimensionVec::const_iterator aIter(aGroups.begin()); aIter != aGroups.end(); aIter++ )
1452cdf0e10cSrcweir {
1453cdf0e10cSrcweir const ScDPGroupDimension& rDim = *aIter;
1454cdf0e10cSrcweir if ( rDim.GetGroupDim() == nDimension )
1455cdf0e10cSrcweir return ( rDim.GetDateHelper() != NULL );
1456cdf0e10cSrcweir }
1457cdf0e10cSrcweir
1458cdf0e10cSrcweir return sal_False;
1459cdf0e10cSrcweir }
1460cdf0e10cSrcweir
IsInGroup(const ScDPItemData & rGroupData,long nGroupIndex,const ScDPItemData & rBaseData,long nBaseIndex) const1461cdf0e10cSrcweir sal_Bool ScDPGroupTableData::IsInGroup( const ScDPItemData& rGroupData, long nGroupIndex,
1462cdf0e10cSrcweir const ScDPItemData& rBaseData, long nBaseIndex ) const
1463cdf0e10cSrcweir {
1464cdf0e10cSrcweir for ( ScDPGroupDimensionVec::const_iterator aIter(aGroups.begin()); aIter != aGroups.end(); aIter++ )
1465cdf0e10cSrcweir {
1466cdf0e10cSrcweir const ScDPGroupDimension& rDim = *aIter;
1467cdf0e10cSrcweir if ( rDim.GetGroupDim() == nGroupIndex && rDim.GetSourceDim() == nBaseIndex )
1468cdf0e10cSrcweir {
1469cdf0e10cSrcweir const ScDPDateGroupHelper* pGroupDateHelper = rDim.GetDateHelper();
1470cdf0e10cSrcweir if ( pGroupDateHelper )
1471cdf0e10cSrcweir {
1472cdf0e10cSrcweir //! transform rBaseData (innermost date part)
1473cdf0e10cSrcweir //! -> always do "HasCommonElement" style comparison
1474cdf0e10cSrcweir //! (only Quarter, Month, Day affected)
1475cdf0e10cSrcweir
1476cdf0e10cSrcweir const ScDPDateGroupHelper* pBaseDateHelper = NULL;
1477cdf0e10cSrcweir if ( nBaseIndex < nSourceCount )
1478cdf0e10cSrcweir pBaseDateHelper = pNumGroups[nBaseIndex].GetDateHelper();
1479cdf0e10cSrcweir
1480cdf0e10cSrcweir // If there's a date group dimension, the base dimension must have
1481cdf0e10cSrcweir // date group information, too.
1482cdf0e10cSrcweir if ( !pBaseDateHelper )
1483cdf0e10cSrcweir {
1484cdf0e10cSrcweir DBG_ERROR( "mix of date and non-date groups" );
1485cdf0e10cSrcweir return sal_True;
1486cdf0e10cSrcweir }
1487cdf0e10cSrcweir
1488cdf0e10cSrcweir sal_Int32 nGroupPart = pGroupDateHelper->GetDatePart();
1489cdf0e10cSrcweir sal_Int32 nBasePart = pBaseDateHelper->GetDatePart();
1490cdf0e10cSrcweir return lcl_DateContained( nGroupPart, rGroupData, nBasePart, rBaseData );
1491cdf0e10cSrcweir }
1492cdf0e10cSrcweir else
1493cdf0e10cSrcweir {
1494cdf0e10cSrcweir // If the item is in a group, only that group is valid.
1495cdf0e10cSrcweir // If the item is not in any group, its own name is valid.
1496cdf0e10cSrcweir
1497cdf0e10cSrcweir const ScDPGroupItem* pGroup = rDim.GetGroupForData( rBaseData );
1498cdf0e10cSrcweir return pGroup ? pGroup->GetName().IsCaseInsEqual( rGroupData ) :
1499cdf0e10cSrcweir rGroupData.IsCaseInsEqual( rBaseData );
1500cdf0e10cSrcweir }
1501cdf0e10cSrcweir }
1502cdf0e10cSrcweir }
1503cdf0e10cSrcweir
1504cdf0e10cSrcweir DBG_ERROR("IsInGroup: no group dimension found");
1505cdf0e10cSrcweir return sal_True;
1506cdf0e10cSrcweir }
1507cdf0e10cSrcweir
HasCommonElement(const ScDPItemData & rFirstData,long nFirstIndex,const ScDPItemData & rSecondData,long nSecondIndex) const1508cdf0e10cSrcweir sal_Bool ScDPGroupTableData::HasCommonElement( const ScDPItemData& rFirstData, long nFirstIndex,
1509cdf0e10cSrcweir const ScDPItemData& rSecondData, long nSecondIndex ) const
1510cdf0e10cSrcweir {
1511cdf0e10cSrcweir const ScDPGroupDimension* pFirstDim = NULL;
1512cdf0e10cSrcweir const ScDPGroupDimension* pSecondDim = NULL;
1513cdf0e10cSrcweir for ( ScDPGroupDimensionVec::const_iterator aIter(aGroups.begin()); aIter != aGroups.end(); aIter++ )
1514cdf0e10cSrcweir {
1515cdf0e10cSrcweir const ScDPGroupDimension* pDim = &(*aIter);
1516cdf0e10cSrcweir if ( pDim->GetGroupDim() == nFirstIndex )
1517cdf0e10cSrcweir pFirstDim = pDim;
1518cdf0e10cSrcweir else if ( pDim->GetGroupDim() == nSecondIndex )
1519cdf0e10cSrcweir pSecondDim = pDim;
1520cdf0e10cSrcweir }
1521cdf0e10cSrcweir if ( pFirstDim && pSecondDim )
1522cdf0e10cSrcweir {
1523cdf0e10cSrcweir const ScDPDateGroupHelper* pFirstDateHelper = pFirstDim->GetDateHelper();
1524cdf0e10cSrcweir const ScDPDateGroupHelper* pSecondDateHelper = pSecondDim->GetDateHelper();
1525cdf0e10cSrcweir if ( pFirstDateHelper || pSecondDateHelper )
1526cdf0e10cSrcweir {
1527cdf0e10cSrcweir // If one is a date group dimension, the other one must be, too.
1528cdf0e10cSrcweir if ( !pFirstDateHelper || !pSecondDateHelper )
1529cdf0e10cSrcweir {
1530cdf0e10cSrcweir DBG_ERROR( "mix of date and non-date groups" );
1531cdf0e10cSrcweir return sal_True;
1532cdf0e10cSrcweir }
1533cdf0e10cSrcweir
1534cdf0e10cSrcweir sal_Int32 nFirstPart = pFirstDateHelper->GetDatePart();
1535cdf0e10cSrcweir sal_Int32 nSecondPart = pSecondDateHelper->GetDatePart();
1536cdf0e10cSrcweir return lcl_DateContained( nFirstPart, rFirstData, nSecondPart, rSecondData );
1537cdf0e10cSrcweir }
1538cdf0e10cSrcweir
1539cdf0e10cSrcweir const ScDPGroupItem* pFirstItem = pFirstDim->GetGroupForName( rFirstData );
1540cdf0e10cSrcweir const ScDPGroupItem* pSecondItem = pSecondDim->GetGroupForName( rSecondData );
1541cdf0e10cSrcweir if ( pFirstItem && pSecondItem )
1542cdf0e10cSrcweir {
1543cdf0e10cSrcweir // two existing groups -> sal_True if they have a common element
1544cdf0e10cSrcweir return pFirstItem->HasCommonElement( *pSecondItem );
1545cdf0e10cSrcweir }
1546cdf0e10cSrcweir else if ( pFirstItem )
1547cdf0e10cSrcweir {
1548cdf0e10cSrcweir // "automatic" group contains only its own name
1549cdf0e10cSrcweir return pFirstItem->HasElement( rSecondData );
1550cdf0e10cSrcweir }
1551cdf0e10cSrcweir else if ( pSecondItem )
1552cdf0e10cSrcweir {
1553cdf0e10cSrcweir // "automatic" group contains only its own name
1554cdf0e10cSrcweir return pSecondItem->HasElement( rFirstData );
1555cdf0e10cSrcweir }
1556cdf0e10cSrcweir else
1557cdf0e10cSrcweir {
1558cdf0e10cSrcweir // no groups -> sal_True if equal
1559cdf0e10cSrcweir return rFirstData.IsCaseInsEqual( rSecondData );
1560cdf0e10cSrcweir }
1561cdf0e10cSrcweir }
1562cdf0e10cSrcweir
1563cdf0e10cSrcweir DBG_ERROR("HasCommonElement: no group dimension found");
1564cdf0e10cSrcweir return sal_True;
1565cdf0e10cSrcweir }
1566cdf0e10cSrcweir
GetSourceDim(long nDim)1567cdf0e10cSrcweir long ScDPGroupTableData::GetSourceDim( long nDim )
1568cdf0e10cSrcweir {
1569cdf0e10cSrcweir if ( getIsDataLayoutDimension( nDim ) )
1570cdf0e10cSrcweir return nSourceCount;
1571cdf0e10cSrcweir if ( nDim >= nSourceCount && nDim < nSourceCount +(long) aGroups.size() )
1572cdf0e10cSrcweir {
1573cdf0e10cSrcweir const ScDPGroupDimension& rGroupDim = aGroups[nDim - nSourceCount];
1574cdf0e10cSrcweir return rGroupDim.GetSourceDim();
1575cdf0e10cSrcweir }
1576cdf0e10cSrcweir return nDim;
1577cdf0e10cSrcweir }
Compare(long nDim,long nDataId1,long nDataId2)1578cdf0e10cSrcweir long ScDPGroupTableData::Compare( long nDim, long nDataId1, long nDataId2)
1579cdf0e10cSrcweir {
1580cdf0e10cSrcweir if ( getIsDataLayoutDimension(nDim) )
1581cdf0e10cSrcweir return 0;
1582cdf0e10cSrcweir return ScDPItemData::Compare( *GetMemberById(nDim, nDataId1),*GetMemberById(nDim, nDataId2) );
1583cdf0e10cSrcweir }
1584cdf0e10cSrcweir // -----------------------------------------------------------------------
1585cdf0e10cSrcweir
1586