xref: /AOO41X/main/sc/source/core/data/dptabres.cxx (revision b3f79822e811ac3493b185030a72c3c5a51f32d8)
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 <tools/debug.hxx>
32cdf0e10cSrcweir #include <rtl/math.hxx>
33cdf0e10cSrcweir 
34cdf0e10cSrcweir #include "dptabdat.hxx"
35cdf0e10cSrcweir #include "dptabres.hxx"
36cdf0e10cSrcweir #include "dptabsrc.hxx"
37cdf0e10cSrcweir #include "global.hxx"
38cdf0e10cSrcweir #include "subtotal.hxx"
39cdf0e10cSrcweir #include "globstr.hrc"
40cdf0e10cSrcweir #include "datauno.hxx"		// ScDataUnoConversion
41cdf0e10cSrcweir 
42cdf0e10cSrcweir #include "document.hxx"     // for DumpState only!
43cdf0e10cSrcweir 
44cdf0e10cSrcweir #include <math.h>
45cdf0e10cSrcweir #include <float.h>			//! Test !!!
46cdf0e10cSrcweir #include <algorithm>
47cdf0e10cSrcweir #include <hash_map>
48cdf0e10cSrcweir 
49cdf0e10cSrcweir #include <com/sun/star/sheet/DataResultFlags.hpp>
50cdf0e10cSrcweir #include <com/sun/star/sheet/MemberResultFlags.hpp>
51cdf0e10cSrcweir #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
52cdf0e10cSrcweir #include <com/sun/star/sheet/DataPilotFieldReferenceType.hpp>
53cdf0e10cSrcweir #include <com/sun/star/sheet/DataPilotFieldReferenceItemType.hpp>
54cdf0e10cSrcweir #include <com/sun/star/sheet/DataPilotFieldShowItemsMode.hpp>
55cdf0e10cSrcweir #include <com/sun/star/sheet/DataPilotFieldSortMode.hpp>
56cdf0e10cSrcweir #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
57cdf0e10cSrcweir 
58cdf0e10cSrcweir using namespace com::sun::star;
59cdf0e10cSrcweir using ::std::vector;
60cdf0e10cSrcweir using ::std::pair;
61cdf0e10cSrcweir using ::std::hash_map;
62cdf0e10cSrcweir using ::com::sun::star::uno::Sequence;
63cdf0e10cSrcweir using ::rtl::OUString;
64cdf0e10cSrcweir 
65cdf0e10cSrcweir // -----------------------------------------------------------------------
66cdf0e10cSrcweir 
67cdf0e10cSrcweir SV_IMPL_PTRARR( ScDPDataMembers, ScDPDataMemberPtr );
68cdf0e10cSrcweir 
69cdf0e10cSrcweir // -----------------------------------------------------------------------
70cdf0e10cSrcweir 
71cdf0e10cSrcweir static sal_uInt16 nFuncStrIds[12] =		// passend zum enum ScSubTotalFunc
72cdf0e10cSrcweir {
73cdf0e10cSrcweir 	0,								// SUBTOTAL_FUNC_NONE
74cdf0e10cSrcweir 	STR_FUN_TEXT_AVG,				// SUBTOTAL_FUNC_AVE
75cdf0e10cSrcweir 	STR_FUN_TEXT_COUNT,				// SUBTOTAL_FUNC_CNT
76cdf0e10cSrcweir 	STR_FUN_TEXT_COUNT,				// SUBTOTAL_FUNC_CNT2
77cdf0e10cSrcweir 	STR_FUN_TEXT_MAX,				// SUBTOTAL_FUNC_MAX
78cdf0e10cSrcweir 	STR_FUN_TEXT_MIN,				// SUBTOTAL_FUNC_MIN
79cdf0e10cSrcweir 	STR_FUN_TEXT_PRODUCT,			// SUBTOTAL_FUNC_PROD
80cdf0e10cSrcweir 	STR_FUN_TEXT_STDDEV,			// SUBTOTAL_FUNC_STD
81cdf0e10cSrcweir 	STR_FUN_TEXT_STDDEV,			// SUBTOTAL_FUNC_STDP
82cdf0e10cSrcweir 	STR_FUN_TEXT_SUM,				// SUBTOTAL_FUNC_SUM
83cdf0e10cSrcweir 	STR_FUN_TEXT_VAR,				// SUBTOTAL_FUNC_VAR
84cdf0e10cSrcweir 	STR_FUN_TEXT_VAR				// SUBTOTAL_FUNC_VARP
85cdf0e10cSrcweir };
86cdf0e10cSrcweir namespace {
87cdf0e10cSrcweir     template < typename T >
lcl_ResizePointVector(T & vec,size_t nSize)88cdf0e10cSrcweir     void lcl_ResizePointVector( T & vec, size_t nSize )
89cdf0e10cSrcweir     {
90cdf0e10cSrcweir 
91cdf0e10cSrcweir         for ( size_t i = 0 ; i < vec.size(); i++ )
92cdf0e10cSrcweir         {
93cdf0e10cSrcweir             if ( vec[i] )
94cdf0e10cSrcweir                 delete vec[i];
95cdf0e10cSrcweir         }
96cdf0e10cSrcweir         vec.resize( nSize, NULL );
97cdf0e10cSrcweir     }
lcl_SearchMember(const std::vector<ScDPResultMember * > & list,SCROW nOrder,SCROW & rIndex)98cdf0e10cSrcweir 	sal_Bool lcl_SearchMember( const std::vector <ScDPResultMember *>& list, SCROW nOrder, SCROW& rIndex)
99cdf0e10cSrcweir 	{
100cdf0e10cSrcweir 		rIndex = list.size();
101cdf0e10cSrcweir 		sal_Bool bFound = sal_False;
102cdf0e10cSrcweir 		SCROW  nLo = 0;
103cdf0e10cSrcweir 		SCROW nHi = list.size() - 1;
104cdf0e10cSrcweir 		SCROW nIndex;
105cdf0e10cSrcweir 		while (nLo <= nHi)
106cdf0e10cSrcweir 		{
107cdf0e10cSrcweir 			nIndex = (nLo + nHi) / 2;
108cdf0e10cSrcweir 			if ( list[nIndex]->GetOrder() < nOrder )
109cdf0e10cSrcweir 				nLo = nIndex + 1;
110cdf0e10cSrcweir 			else
111cdf0e10cSrcweir 			{
112cdf0e10cSrcweir 				nHi = nIndex - 1;
113cdf0e10cSrcweir 				if ( list[nIndex]->GetOrder() == nOrder )
114cdf0e10cSrcweir 				{
115cdf0e10cSrcweir 					bFound = sal_True;
116cdf0e10cSrcweir 					nLo = nIndex;
117cdf0e10cSrcweir 				}
118cdf0e10cSrcweir 			}
119cdf0e10cSrcweir 		}
120cdf0e10cSrcweir 		rIndex = nLo;
121cdf0e10cSrcweir 		return bFound;
122cdf0e10cSrcweir 	}
123cdf0e10cSrcweir }
124cdf0e10cSrcweir // -----------------------------------------------------------------------
125cdf0e10cSrcweir 
126cdf0e10cSrcweir //
127cdf0e10cSrcweir // function objects for sorting of the column and row members:
128cdf0e10cSrcweir //
129cdf0e10cSrcweir 
130cdf0e10cSrcweir class ScDPRowMembersOrder
131cdf0e10cSrcweir {
132cdf0e10cSrcweir     ScDPResultDimension& rDimension;
133cdf0e10cSrcweir     long                 nMeasure;
134cdf0e10cSrcweir     sal_Bool                 bAscending;
135cdf0e10cSrcweir 
136cdf0e10cSrcweir public:
ScDPRowMembersOrder(ScDPResultDimension & rDim,long nM,sal_Bool bAsc)137cdf0e10cSrcweir             ScDPRowMembersOrder( ScDPResultDimension& rDim, long nM, sal_Bool bAsc ) :
138cdf0e10cSrcweir                 rDimension(rDim),
139cdf0e10cSrcweir                 nMeasure(nM),
140cdf0e10cSrcweir                 bAscending(bAsc)
141cdf0e10cSrcweir             {}
~ScDPRowMembersOrder()142cdf0e10cSrcweir             ~ScDPRowMembersOrder() {}
143cdf0e10cSrcweir 
144cdf0e10cSrcweir     sal_Bool operator()( sal_Int32 nIndex1, sal_Int32 nIndex2 ) const;
145cdf0e10cSrcweir };
146cdf0e10cSrcweir 
147cdf0e10cSrcweir class ScDPColMembersOrder
148cdf0e10cSrcweir {
149cdf0e10cSrcweir     ScDPDataDimension& rDimension;
150cdf0e10cSrcweir     long               nMeasure;
151cdf0e10cSrcweir     sal_Bool               bAscending;
152cdf0e10cSrcweir 
153cdf0e10cSrcweir public:
ScDPColMembersOrder(ScDPDataDimension & rDim,long nM,sal_Bool bAsc)154cdf0e10cSrcweir             ScDPColMembersOrder( ScDPDataDimension& rDim, long nM, sal_Bool bAsc ) :
155cdf0e10cSrcweir                 rDimension(rDim),
156cdf0e10cSrcweir                 nMeasure(nM),
157cdf0e10cSrcweir                 bAscending(bAsc)
158cdf0e10cSrcweir             {}
~ScDPColMembersOrder()159cdf0e10cSrcweir             ~ScDPColMembersOrder() {}
160cdf0e10cSrcweir 
161cdf0e10cSrcweir     sal_Bool operator()( sal_Int32 nIndex1, sal_Int32 nIndex2 ) const;
162cdf0e10cSrcweir };
163cdf0e10cSrcweir 
lcl_IsLess(const ScDPDataMember * pDataMember1,const ScDPDataMember * pDataMember2,long nMeasure,sal_Bool bAscending)164cdf0e10cSrcweir static sal_Bool lcl_IsLess( const ScDPDataMember* pDataMember1, const ScDPDataMember* pDataMember2, long nMeasure, sal_Bool bAscending )
165cdf0e10cSrcweir {
166cdf0e10cSrcweir     // members can be NULL if used for rows
167cdf0e10cSrcweir 
168cdf0e10cSrcweir     ScDPSubTotalState aEmptyState;
169cdf0e10cSrcweir     const ScDPAggData* pAgg1 = pDataMember1 ? pDataMember1->GetConstAggData( nMeasure, aEmptyState ) : NULL;
170cdf0e10cSrcweir     const ScDPAggData* pAgg2 = pDataMember2 ? pDataMember2->GetConstAggData( nMeasure, aEmptyState ) : NULL;
171cdf0e10cSrcweir 
172cdf0e10cSrcweir     sal_Bool bError1 = pAgg1 && pAgg1->HasError();
173cdf0e10cSrcweir     sal_Bool bError2 = pAgg2 && pAgg2->HasError();
174cdf0e10cSrcweir     if ( bError1 )
175cdf0e10cSrcweir     {
176cdf0e10cSrcweir         if ( bError2 )
177cdf0e10cSrcweir             return sal_False;       // equal
178cdf0e10cSrcweir         else
179cdf0e10cSrcweir             return sal_False;       // errors are always sorted at the end
180cdf0e10cSrcweir     }
181cdf0e10cSrcweir     else if ( bError2 )
182cdf0e10cSrcweir         return sal_True;            // errors are always sorted at the end
183cdf0e10cSrcweir     else
184cdf0e10cSrcweir     {
185cdf0e10cSrcweir         double fVal1 = ( pAgg1 && pAgg1->HasData() ) ? pAgg1->GetResult() : 0.0;    // no data is sorted as 0
186cdf0e10cSrcweir         double fVal2 = ( pAgg2 && pAgg2->HasData() ) ? pAgg2->GetResult() : 0.0;
187cdf0e10cSrcweir 
188cdf0e10cSrcweir         // compare values
189cdf0e10cSrcweir         // don't have to check approxEqual, as this is the only sort criterion
190cdf0e10cSrcweir 
191cdf0e10cSrcweir         return bAscending ? ( fVal1 < fVal2 ) : ( fVal1 > fVal2 );
192cdf0e10cSrcweir     }
193cdf0e10cSrcweir }
194cdf0e10cSrcweir 
lcl_IsEqual(const ScDPDataMember * pDataMember1,const ScDPDataMember * pDataMember2,long nMeasure)195cdf0e10cSrcweir static sal_Bool lcl_IsEqual( const ScDPDataMember* pDataMember1, const ScDPDataMember* pDataMember2, long nMeasure )
196cdf0e10cSrcweir {
197cdf0e10cSrcweir     // members can be NULL if used for rows
198cdf0e10cSrcweir 
199cdf0e10cSrcweir     ScDPSubTotalState aEmptyState;
200cdf0e10cSrcweir     const ScDPAggData* pAgg1 = pDataMember1 ? pDataMember1->GetConstAggData( nMeasure, aEmptyState ) : NULL;
201cdf0e10cSrcweir     const ScDPAggData* pAgg2 = pDataMember2 ? pDataMember2->GetConstAggData( nMeasure, aEmptyState ) : NULL;
202cdf0e10cSrcweir 
203cdf0e10cSrcweir     sal_Bool bError1 = pAgg1 && pAgg1->HasError();
204cdf0e10cSrcweir     sal_Bool bError2 = pAgg2 && pAgg2->HasError();
205cdf0e10cSrcweir     if ( bError1 )
206cdf0e10cSrcweir     {
207cdf0e10cSrcweir         if ( bError2 )
208cdf0e10cSrcweir             return sal_True;        // equal
209cdf0e10cSrcweir         else
210cdf0e10cSrcweir             return sal_False;
211cdf0e10cSrcweir     }
212cdf0e10cSrcweir     else if ( bError2 )
213cdf0e10cSrcweir         return sal_False;
214cdf0e10cSrcweir     else
215cdf0e10cSrcweir     {
216cdf0e10cSrcweir         double fVal1 = ( pAgg1 && pAgg1->HasData() ) ? pAgg1->GetResult() : 0.0;    // no data is sorted as 0
217cdf0e10cSrcweir         double fVal2 = ( pAgg2 && pAgg2->HasData() ) ? pAgg2->GetResult() : 0.0;
218cdf0e10cSrcweir 
219cdf0e10cSrcweir         // compare values
220cdf0e10cSrcweir         // this is used to find equal data at the end of the AutoShow range, so approxEqual must be used
221cdf0e10cSrcweir 
222cdf0e10cSrcweir         return rtl::math::approxEqual( fVal1, fVal2 );
223cdf0e10cSrcweir     }
224cdf0e10cSrcweir }
225cdf0e10cSrcweir 
operator ()(sal_Int32 nIndex1,sal_Int32 nIndex2) const226cdf0e10cSrcweir sal_Bool ScDPRowMembersOrder::operator()( sal_Int32 nIndex1, sal_Int32 nIndex2 ) const
227cdf0e10cSrcweir {
228cdf0e10cSrcweir     const ScDPResultMember* pMember1 = rDimension.GetMember(nIndex1);
229cdf0e10cSrcweir     const ScDPResultMember* pMember2 = rDimension.GetMember(nIndex2);
230cdf0e10cSrcweir // Wang Xu Ming -- 3/17/2009
231cdf0e10cSrcweir 
232cdf0e10cSrcweir // make the hide item to the largest order.
233cdf0e10cSrcweir 	if ( !pMember1->IsVisible() || !pMember2->IsVisible() )
234cdf0e10cSrcweir 		return pMember1->IsVisible();
235cdf0e10cSrcweir     const ScDPDataMember* pDataMember1 =  pMember1->GetDataRoot() ;
236cdf0e10cSrcweir     const ScDPDataMember* pDataMember2 =  pMember2->GetDataRoot();
237cdf0e10cSrcweir // End Comments
238cdf0e10cSrcweir     //  GetDataRoot can be NULL if there was no data.
239cdf0e10cSrcweir     //  IsVisible == sal_False can happen after AutoShow.
240cdf0e10cSrcweir     return lcl_IsLess( pDataMember1, pDataMember2, nMeasure, bAscending );
241cdf0e10cSrcweir }
242cdf0e10cSrcweir 
operator ()(sal_Int32 nIndex1,sal_Int32 nIndex2) const243cdf0e10cSrcweir sal_Bool ScDPColMembersOrder::operator()( sal_Int32 nIndex1, sal_Int32 nIndex2 ) const
244cdf0e10cSrcweir {
245cdf0e10cSrcweir     ScDPDataMember* pDataMember1 = rDimension.GetMember(nIndex1);
246cdf0e10cSrcweir     ScDPDataMember* pDataMember2 = rDimension.GetMember(nIndex2);
247cdf0e10cSrcweir     // Wang Xu Ming -- 2009-6-17
248cdf0e10cSrcweir         sal_Bool bHide1 = pDataMember1 && !pDataMember1->IsVisible();
249cdf0e10cSrcweir         sal_Bool bHide2 =  pDataMember2 && !pDataMember2->IsVisible();
250cdf0e10cSrcweir         if ( bHide1 || bHide2 )
251cdf0e10cSrcweir             return !bHide1;
252cdf0e10cSrcweir     // End Comments
253cdf0e10cSrcweir     return lcl_IsLess( pDataMember1, pDataMember2, nMeasure, bAscending );
254cdf0e10cSrcweir }
255cdf0e10cSrcweir 
256cdf0e10cSrcweir // -----------------------------------------------------------------------
257cdf0e10cSrcweir 
ScDPInitState()258cdf0e10cSrcweir ScDPInitState::ScDPInitState() :
259cdf0e10cSrcweir     nCount( 0 )
260cdf0e10cSrcweir {
261cdf0e10cSrcweir     pIndex = new long[SC_DAPI_MAXFIELDS];
262cdf0e10cSrcweir     pData = new SCROW[SC_DAPI_MAXFIELDS];
263cdf0e10cSrcweir }
264cdf0e10cSrcweir 
~ScDPInitState()265cdf0e10cSrcweir ScDPInitState::~ScDPInitState()
266cdf0e10cSrcweir {
267cdf0e10cSrcweir     delete[] pIndex;
268cdf0e10cSrcweir     delete[] pData;
269cdf0e10cSrcweir }
270cdf0e10cSrcweir 
AddMember(long nSourceIndex,SCROW nMember)271cdf0e10cSrcweir void ScDPInitState::AddMember( long nSourceIndex, SCROW nMember )
272cdf0e10cSrcweir {
273cdf0e10cSrcweir     DBG_ASSERT( nCount < SC_DAPI_MAXFIELDS, "too many InitState members" );
274cdf0e10cSrcweir     if ( nCount < SC_DAPI_MAXFIELDS )
275cdf0e10cSrcweir     {
276cdf0e10cSrcweir         pIndex[nCount] = nSourceIndex;
277cdf0e10cSrcweir         pData[nCount] = nMember;
278cdf0e10cSrcweir         ++nCount;
279cdf0e10cSrcweir     }
280cdf0e10cSrcweir }
281cdf0e10cSrcweir 
RemoveMember()282cdf0e10cSrcweir void ScDPInitState::RemoveMember()
283cdf0e10cSrcweir {
284cdf0e10cSrcweir     DBG_ASSERT( nCount > 0, "RemoveColIndex without index" );
285cdf0e10cSrcweir     if ( nCount > 0 )
286cdf0e10cSrcweir         --nCount;
287cdf0e10cSrcweir }
288cdf0e10cSrcweir 
GetNameIdForIndex(long nIndexValue) const289cdf0e10cSrcweir SCROW ScDPInitState::GetNameIdForIndex( long nIndexValue ) const
290cdf0e10cSrcweir {
291cdf0e10cSrcweir     for (long i=0; i<nCount; i++)
292cdf0e10cSrcweir         if ( pIndex[i] == nIndexValue )
293cdf0e10cSrcweir             return pData[i];
294cdf0e10cSrcweir 
295cdf0e10cSrcweir     return -1;    // not found
296cdf0e10cSrcweir }
297cdf0e10cSrcweir 
298cdf0e10cSrcweir // -----------------------------------------------------------------------
299cdf0e10cSrcweir 
lcl_DumpRow(const String & rType,const String & rName,const ScDPAggData * pAggData,ScDocument * pDoc,ScAddress & rPos)300cdf0e10cSrcweir void lcl_DumpRow( const String& rType, const String& rName, const ScDPAggData* pAggData,
301cdf0e10cSrcweir                     ScDocument* pDoc, ScAddress& rPos )
302cdf0e10cSrcweir {
303cdf0e10cSrcweir     SCCOL nCol = rPos.Col();
304cdf0e10cSrcweir     SCROW nRow = rPos.Row();
305cdf0e10cSrcweir     SCTAB nTab = rPos.Tab();
306cdf0e10cSrcweir     pDoc->SetString( nCol++, nRow, nTab, rType );
307cdf0e10cSrcweir     pDoc->SetString( nCol++, nRow, nTab, rName );
308cdf0e10cSrcweir     while ( pAggData )
309cdf0e10cSrcweir     {
310cdf0e10cSrcweir         pDoc->SetValue( nCol++, nRow, nTab, pAggData->GetResult() );
311cdf0e10cSrcweir         pAggData = pAggData->GetExistingChild();
312cdf0e10cSrcweir     }
313cdf0e10cSrcweir     rPos.SetRow( nRow + 1 );
314cdf0e10cSrcweir }
315cdf0e10cSrcweir 
lcl_Indent(ScDocument * pDoc,SCROW nStartRow,const ScAddress & rPos)316cdf0e10cSrcweir void lcl_Indent( ScDocument* pDoc, SCROW nStartRow, const ScAddress& rPos )
317cdf0e10cSrcweir {
318cdf0e10cSrcweir     SCCOL nCol = rPos.Col();
319cdf0e10cSrcweir     SCTAB nTab = rPos.Tab();
320cdf0e10cSrcweir 
321cdf0e10cSrcweir     String aString;
322cdf0e10cSrcweir     for (SCROW nRow = nStartRow; nRow < rPos.Row(); nRow++)
323cdf0e10cSrcweir     {
324cdf0e10cSrcweir         pDoc->GetString( nCol, nRow, nTab, aString );
325cdf0e10cSrcweir         if ( aString.Len() )
326cdf0e10cSrcweir         {
327cdf0e10cSrcweir             aString.InsertAscii( "  ", 0 );
328cdf0e10cSrcweir             pDoc->SetString( nCol, nRow, nTab, aString );
329cdf0e10cSrcweir         }
330cdf0e10cSrcweir     }
331cdf0e10cSrcweir }
332cdf0e10cSrcweir 
333cdf0e10cSrcweir // -----------------------------------------------------------------------
334cdf0e10cSrcweir 
ScDPRunningTotalState(ScDPResultMember * pColRoot,ScDPResultMember * pRowRoot)335cdf0e10cSrcweir ScDPRunningTotalState::ScDPRunningTotalState( ScDPResultMember* pColRoot, ScDPResultMember* pRowRoot ) :
336cdf0e10cSrcweir     pColResRoot( pColRoot ),
337cdf0e10cSrcweir     pRowResRoot( pRowRoot ),
338cdf0e10cSrcweir     nColIndexPos( 0 ),
339cdf0e10cSrcweir     nRowIndexPos( 0 )
340cdf0e10cSrcweir {
341cdf0e10cSrcweir     pColVisible = new long[SC_DAPI_MAXFIELDS+1];
342cdf0e10cSrcweir     pColIndexes = new long[SC_DAPI_MAXFIELDS+1];
343cdf0e10cSrcweir     pRowVisible = new long[SC_DAPI_MAXFIELDS+1];
344cdf0e10cSrcweir     pRowIndexes = new long[SC_DAPI_MAXFIELDS+1];
345cdf0e10cSrcweir     pColIndexes[0] = -1;
346cdf0e10cSrcweir     pRowIndexes[0] = -1;
347cdf0e10cSrcweir }
348cdf0e10cSrcweir 
~ScDPRunningTotalState()349cdf0e10cSrcweir ScDPRunningTotalState::~ScDPRunningTotalState()
350cdf0e10cSrcweir {
351cdf0e10cSrcweir     delete[] pColVisible;
352cdf0e10cSrcweir     delete[] pColIndexes;
353cdf0e10cSrcweir     delete[] pRowVisible;
354cdf0e10cSrcweir     delete[] pRowIndexes;
355cdf0e10cSrcweir }
356cdf0e10cSrcweir 
AddColIndex(long nVisible,long nSorted)357cdf0e10cSrcweir void ScDPRunningTotalState::AddColIndex( long nVisible, long nSorted )
358cdf0e10cSrcweir {
359cdf0e10cSrcweir     DBG_ASSERT( nColIndexPos < SC_DAPI_MAXFIELDS, "too many column indexes" );
360cdf0e10cSrcweir     if ( nColIndexPos < SC_DAPI_MAXFIELDS )
361cdf0e10cSrcweir     {
362cdf0e10cSrcweir         pColVisible[nColIndexPos] = nVisible;
363cdf0e10cSrcweir         pColIndexes[nColIndexPos] = nSorted;
364cdf0e10cSrcweir         pColVisible[nColIndexPos+1] = -1;
365cdf0e10cSrcweir         pColIndexes[nColIndexPos+1] = -1;
366cdf0e10cSrcweir         ++nColIndexPos;
367cdf0e10cSrcweir     }
368cdf0e10cSrcweir }
369cdf0e10cSrcweir 
AddRowIndex(long nVisible,long nSorted)370cdf0e10cSrcweir void ScDPRunningTotalState::AddRowIndex( long nVisible, long nSorted )
371cdf0e10cSrcweir {
372cdf0e10cSrcweir     DBG_ASSERT( nRowIndexPos < SC_DAPI_MAXFIELDS, "too many row indexes" );
373cdf0e10cSrcweir     if ( nRowIndexPos < SC_DAPI_MAXFIELDS )
374cdf0e10cSrcweir     {
375cdf0e10cSrcweir         pRowVisible[nRowIndexPos] = nVisible;
376cdf0e10cSrcweir         pRowIndexes[nRowIndexPos] = nSorted;
377cdf0e10cSrcweir         pRowVisible[nRowIndexPos+1] = -1;
378cdf0e10cSrcweir         pRowIndexes[nRowIndexPos+1] = -1;
379cdf0e10cSrcweir         ++nRowIndexPos;
380cdf0e10cSrcweir     }
381cdf0e10cSrcweir }
382cdf0e10cSrcweir 
RemoveColIndex()383cdf0e10cSrcweir void ScDPRunningTotalState::RemoveColIndex()
384cdf0e10cSrcweir {
385cdf0e10cSrcweir     DBG_ASSERT( nColIndexPos > 0, "RemoveColIndex without index" );
386cdf0e10cSrcweir     if ( nColIndexPos > 0 )
387cdf0e10cSrcweir     {
388cdf0e10cSrcweir         --nColIndexPos;
389cdf0e10cSrcweir         pColVisible[nColIndexPos] = -1;
390cdf0e10cSrcweir         pColIndexes[nColIndexPos] = -1;
391cdf0e10cSrcweir     }
392cdf0e10cSrcweir }
393cdf0e10cSrcweir 
RemoveRowIndex()394cdf0e10cSrcweir void ScDPRunningTotalState::RemoveRowIndex()
395cdf0e10cSrcweir {
396cdf0e10cSrcweir     DBG_ASSERT( nRowIndexPos > 0, "RemoveRowIndex without index" );
397cdf0e10cSrcweir     if ( nRowIndexPos > 0 )
398cdf0e10cSrcweir     {
399cdf0e10cSrcweir         --nRowIndexPos;
400cdf0e10cSrcweir         pRowVisible[nRowIndexPos] = -1;
401cdf0e10cSrcweir         pRowIndexes[nRowIndexPos] = -1;
402cdf0e10cSrcweir     }
403cdf0e10cSrcweir }
404cdf0e10cSrcweir 
405cdf0e10cSrcweir // -----------------------------------------------------------------------
406cdf0e10cSrcweir 
ScDPRelativePos(long nBase,long nDir)407cdf0e10cSrcweir ScDPRelativePos::ScDPRelativePos( long nBase, long nDir ) :
408cdf0e10cSrcweir     nBasePos( nBase ),
409cdf0e10cSrcweir     nDirection( nDir )
410cdf0e10cSrcweir {
411cdf0e10cSrcweir }
412cdf0e10cSrcweir 
413cdf0e10cSrcweir // -----------------------------------------------------------------------
414cdf0e10cSrcweir 
Update(const ScDPValueData & rNext,ScSubTotalFunc eFunc,const ScDPSubTotalState & rSubState)415cdf0e10cSrcweir void ScDPAggData::Update( const ScDPValueData& rNext, ScSubTotalFunc eFunc, const ScDPSubTotalState& rSubState )
416cdf0e10cSrcweir {
417cdf0e10cSrcweir 	if (nCount<0)		// error?
418cdf0e10cSrcweir 		return;			// nothing more...
419cdf0e10cSrcweir 
420cdf0e10cSrcweir 	if ( rNext.nType == SC_VALTYPE_EMPTY )
421cdf0e10cSrcweir 		return;
422cdf0e10cSrcweir 
423cdf0e10cSrcweir 	if ( rSubState.eColForce != SUBTOTAL_FUNC_NONE && rSubState.eRowForce != SUBTOTAL_FUNC_NONE &&
424cdf0e10cSrcweir 														rSubState.eColForce != rSubState.eRowForce )
425cdf0e10cSrcweir 		return;
426cdf0e10cSrcweir 	if ( rSubState.eColForce != SUBTOTAL_FUNC_NONE ) eFunc = rSubState.eColForce;
427cdf0e10cSrcweir 	if ( rSubState.eRowForce != SUBTOTAL_FUNC_NONE ) eFunc = rSubState.eRowForce;
428cdf0e10cSrcweir 
429cdf0e10cSrcweir 	if ( eFunc == SUBTOTAL_FUNC_NONE )
430cdf0e10cSrcweir 		return;
431cdf0e10cSrcweir 
432cdf0e10cSrcweir 	if ( eFunc != SUBTOTAL_FUNC_CNT2 )			// CNT2 counts everything, incl. strings and errors
433cdf0e10cSrcweir 	{
434cdf0e10cSrcweir 		if ( rNext.nType == SC_VALTYPE_ERROR )
435cdf0e10cSrcweir 		{
436cdf0e10cSrcweir 			nCount = -1;		// -1 for error (not for CNT2)
437cdf0e10cSrcweir 			return;
438cdf0e10cSrcweir 		}
439cdf0e10cSrcweir 		if ( rNext.nType == SC_VALTYPE_STRING )
440cdf0e10cSrcweir 			return;				// ignore
441cdf0e10cSrcweir 	}
442cdf0e10cSrcweir 
443cdf0e10cSrcweir 	++nCount;			// for all functions
444cdf0e10cSrcweir 
445cdf0e10cSrcweir 	switch (eFunc)
446cdf0e10cSrcweir 	{
447cdf0e10cSrcweir 		case SUBTOTAL_FUNC_SUM:
448cdf0e10cSrcweir 		case SUBTOTAL_FUNC_AVE:
449cdf0e10cSrcweir 			if ( !SubTotal::SafePlus( fVal, rNext.fValue ) )
450cdf0e10cSrcweir 				nCount = -1;							// -1 for error
451cdf0e10cSrcweir 			break;
452cdf0e10cSrcweir 		case SUBTOTAL_FUNC_PROD:
453cdf0e10cSrcweir 			if ( nCount == 1 )			// copy first value (fVal is initialized to 0)
454cdf0e10cSrcweir 				fVal = rNext.fValue;
455cdf0e10cSrcweir 			else if ( !SubTotal::SafeMult( fVal, rNext.fValue ) )
456cdf0e10cSrcweir 				nCount = -1;							// -1 for error
457cdf0e10cSrcweir 			break;
458cdf0e10cSrcweir 		case SUBTOTAL_FUNC_CNT:
459cdf0e10cSrcweir 		case SUBTOTAL_FUNC_CNT2:
460cdf0e10cSrcweir 			//	nothing more than incrementing nCount
461cdf0e10cSrcweir 			break;
462cdf0e10cSrcweir 		case SUBTOTAL_FUNC_MAX:
463cdf0e10cSrcweir 			if ( nCount == 1 || rNext.fValue > fVal )
464cdf0e10cSrcweir 				fVal = rNext.fValue;
465cdf0e10cSrcweir 			break;
466cdf0e10cSrcweir 		case SUBTOTAL_FUNC_MIN:
467cdf0e10cSrcweir 			if ( nCount == 1 || rNext.fValue < fVal )
468cdf0e10cSrcweir 				fVal = rNext.fValue;
469cdf0e10cSrcweir 			break;
470cdf0e10cSrcweir 		case SUBTOTAL_FUNC_STD:
471cdf0e10cSrcweir 		case SUBTOTAL_FUNC_STDP:
472cdf0e10cSrcweir 		case SUBTOTAL_FUNC_VAR:
473cdf0e10cSrcweir 		case SUBTOTAL_FUNC_VARP:
474cdf0e10cSrcweir 			{
475cdf0e10cSrcweir 				// fAux is used to sum up squares
476cdf0e10cSrcweir 				if ( !SubTotal::SafePlus( fVal, rNext.fValue ) )
477cdf0e10cSrcweir 					nCount = -1;							// -1 for error
478cdf0e10cSrcweir 				double fAdd = rNext.fValue;
479cdf0e10cSrcweir 				if ( !SubTotal::SafeMult( fAdd, rNext.fValue ) ||
480cdf0e10cSrcweir 					 !SubTotal::SafePlus( fAux, fAdd ) )
481cdf0e10cSrcweir 					nCount = -1;							// -1 for error
482cdf0e10cSrcweir 			}
483cdf0e10cSrcweir 			break;
484cdf0e10cSrcweir 		default:
485cdf0e10cSrcweir 			DBG_ERROR("invalid function");
486cdf0e10cSrcweir 	}
487cdf0e10cSrcweir }
488cdf0e10cSrcweir 
Calculate(ScSubTotalFunc eFunc,const ScDPSubTotalState & rSubState)489cdf0e10cSrcweir void ScDPAggData::Calculate( ScSubTotalFunc eFunc, const ScDPSubTotalState& rSubState )
490cdf0e10cSrcweir {
491cdf0e10cSrcweir 	//	calculate the original result
492cdf0e10cSrcweir 	//	(without reference value, used as the basis for reference value calculation)
493cdf0e10cSrcweir 
494cdf0e10cSrcweir     //  called several times at the cross-section of several subtotals - don't calculate twice then
495cdf0e10cSrcweir     if ( IsCalculated() )
496cdf0e10cSrcweir         return;
497cdf0e10cSrcweir 
498cdf0e10cSrcweir 	if ( rSubState.eColForce != SUBTOTAL_FUNC_NONE ) eFunc = rSubState.eColForce;
499cdf0e10cSrcweir 	if ( rSubState.eRowForce != SUBTOTAL_FUNC_NONE ) eFunc = rSubState.eRowForce;
500cdf0e10cSrcweir 
501cdf0e10cSrcweir     if ( eFunc == SUBTOTAL_FUNC_NONE )      // this happens when there is no data dimension
502cdf0e10cSrcweir     {
503cdf0e10cSrcweir         nCount = SC_DPAGG_RESULT_EMPTY;     // make sure there's a valid state for HasData etc.
504cdf0e10cSrcweir         return;
505cdf0e10cSrcweir     }
506cdf0e10cSrcweir 
507cdf0e10cSrcweir 	//	check the error conditions for the selected function
508cdf0e10cSrcweir 
509cdf0e10cSrcweir 	sal_Bool bError = sal_False;
510cdf0e10cSrcweir 	switch (eFunc)
511cdf0e10cSrcweir 	{
512cdf0e10cSrcweir 		case SUBTOTAL_FUNC_SUM:
513cdf0e10cSrcweir 		case SUBTOTAL_FUNC_PROD:
514cdf0e10cSrcweir 		case SUBTOTAL_FUNC_CNT:
515cdf0e10cSrcweir 		case SUBTOTAL_FUNC_CNT2:
516cdf0e10cSrcweir 			bError = ( nCount < 0 );		// only real errors
517cdf0e10cSrcweir 			break;
518cdf0e10cSrcweir 
519cdf0e10cSrcweir 		case SUBTOTAL_FUNC_AVE:
520cdf0e10cSrcweir 		case SUBTOTAL_FUNC_MAX:
521cdf0e10cSrcweir 		case SUBTOTAL_FUNC_MIN:
522cdf0e10cSrcweir 		case SUBTOTAL_FUNC_STDP:
523cdf0e10cSrcweir 		case SUBTOTAL_FUNC_VARP:
524cdf0e10cSrcweir 			bError = ( nCount <= 0 );		// no data is an error
525cdf0e10cSrcweir 			break;
526cdf0e10cSrcweir 
527cdf0e10cSrcweir 		case SUBTOTAL_FUNC_STD:
528cdf0e10cSrcweir 		case SUBTOTAL_FUNC_VAR:
529cdf0e10cSrcweir 			bError = ( nCount < 2 );		// need at least 2 values
530cdf0e10cSrcweir 			break;
531cdf0e10cSrcweir 
532cdf0e10cSrcweir 		default:
533cdf0e10cSrcweir 			DBG_ERROR("invalid function");
534cdf0e10cSrcweir 	}
535cdf0e10cSrcweir 
536cdf0e10cSrcweir 	//	calculate the selected function
537cdf0e10cSrcweir 
538cdf0e10cSrcweir 	double fResult = 0.0;
539cdf0e10cSrcweir 	if ( !bError )
540cdf0e10cSrcweir 	{
541cdf0e10cSrcweir 		switch (eFunc)
542cdf0e10cSrcweir 		{
543cdf0e10cSrcweir 			case SUBTOTAL_FUNC_MAX:
544cdf0e10cSrcweir 			case SUBTOTAL_FUNC_MIN:
545cdf0e10cSrcweir 			case SUBTOTAL_FUNC_SUM:
546cdf0e10cSrcweir 			case SUBTOTAL_FUNC_PROD:
547cdf0e10cSrcweir 				//	different error conditions are handled above
548cdf0e10cSrcweir 				fResult = fVal;
549cdf0e10cSrcweir 				break;
550cdf0e10cSrcweir 
551cdf0e10cSrcweir 			case SUBTOTAL_FUNC_CNT:
552cdf0e10cSrcweir 			case SUBTOTAL_FUNC_CNT2:
553cdf0e10cSrcweir 				fResult = nCount;
554cdf0e10cSrcweir 				break;
555cdf0e10cSrcweir 
556cdf0e10cSrcweir 			case SUBTOTAL_FUNC_AVE:
557cdf0e10cSrcweir 				if ( nCount > 0 )
558cdf0e10cSrcweir 					fResult = fVal / (double) nCount;
559cdf0e10cSrcweir 				break;
560cdf0e10cSrcweir 
561cdf0e10cSrcweir 			//!	use safe mul for fVal * fVal
562cdf0e10cSrcweir 
563cdf0e10cSrcweir 			case SUBTOTAL_FUNC_STD:
564cdf0e10cSrcweir 				if ( nCount >= 2 )
565cdf0e10cSrcweir 					fResult = sqrt((fAux - fVal*fVal/(double)(nCount)) / (double)(nCount-1));
566cdf0e10cSrcweir 				break;
567cdf0e10cSrcweir 			case SUBTOTAL_FUNC_VAR:
568cdf0e10cSrcweir 				if ( nCount >= 2 )
569cdf0e10cSrcweir 					fResult = (fAux - fVal*fVal/(double)(nCount)) / (double)(nCount-1);
570cdf0e10cSrcweir 				break;
571cdf0e10cSrcweir 			case SUBTOTAL_FUNC_STDP:
572cdf0e10cSrcweir 				if ( nCount > 0 )
573cdf0e10cSrcweir 					fResult = sqrt((fAux - fVal*fVal/(double)(nCount)) / (double)nCount);
574cdf0e10cSrcweir 				break;
575cdf0e10cSrcweir 			case SUBTOTAL_FUNC_VARP:
576cdf0e10cSrcweir 				if ( nCount > 0 )
577cdf0e10cSrcweir 					fResult = (fAux - fVal*fVal/(double)(nCount)) / (double)nCount;
578cdf0e10cSrcweir 				break;
579cdf0e10cSrcweir 			default:
580cdf0e10cSrcweir 				DBG_ERROR("invalid function");
581cdf0e10cSrcweir 		}
582cdf0e10cSrcweir 	}
583cdf0e10cSrcweir 
584cdf0e10cSrcweir 	sal_Bool bEmpty = ( nCount == 0 );			// no data
585cdf0e10cSrcweir 
586cdf0e10cSrcweir 	//	store the result
587cdf0e10cSrcweir 	//	Empty is checked first, so empty results are shown empty even for "average" etc.
588cdf0e10cSrcweir 	//	If these results should be treated as errors in reference value calculations,
589cdf0e10cSrcweir 	//	a separate state value (EMPTY_ERROR) is needed.
590cdf0e10cSrcweir 	//	Now, for compatibility, empty "average" results are counted as 0.
591cdf0e10cSrcweir 
592cdf0e10cSrcweir 	if ( bEmpty )
593cdf0e10cSrcweir 		nCount = SC_DPAGG_RESULT_EMPTY;
594cdf0e10cSrcweir 	else if ( bError )
595cdf0e10cSrcweir 		nCount = SC_DPAGG_RESULT_ERROR;
596cdf0e10cSrcweir 	else
597cdf0e10cSrcweir 		nCount = SC_DPAGG_RESULT_VALID;
598cdf0e10cSrcweir 
599cdf0e10cSrcweir 	if ( bEmpty || bError )
600cdf0e10cSrcweir 		fResult = 0.0;		// default, in case the state is later modified
601cdf0e10cSrcweir 
602cdf0e10cSrcweir //  fprintf(stdout, "ScDPAggData::Calculate: result = %g\n", fResult);fflush(stdout);
603cdf0e10cSrcweir 	fVal = fResult;			// used directly from now on
604cdf0e10cSrcweir 	fAux = 0.0;				// used for running total or original result of reference value
605cdf0e10cSrcweir }
606cdf0e10cSrcweir 
IsCalculated() const607cdf0e10cSrcweir sal_Bool ScDPAggData::IsCalculated() const
608cdf0e10cSrcweir {
609cdf0e10cSrcweir     return ( nCount <= SC_DPAGG_RESULT_EMPTY );
610cdf0e10cSrcweir }
611cdf0e10cSrcweir 
GetResult() const612cdf0e10cSrcweir double ScDPAggData::GetResult() const
613cdf0e10cSrcweir {
614cdf0e10cSrcweir     DBG_ASSERT( IsCalculated(), "ScDPAggData not calculated" );
615cdf0e10cSrcweir 
616cdf0e10cSrcweir     return fVal;        // use calculated value
617cdf0e10cSrcweir }
618cdf0e10cSrcweir 
HasError() const619cdf0e10cSrcweir sal_Bool ScDPAggData::HasError() const
620cdf0e10cSrcweir {
621cdf0e10cSrcweir     DBG_ASSERT( IsCalculated(), "ScDPAggData not calculated" );
622cdf0e10cSrcweir 
623cdf0e10cSrcweir     return ( nCount == SC_DPAGG_RESULT_ERROR );
624cdf0e10cSrcweir }
625cdf0e10cSrcweir 
HasData() const626cdf0e10cSrcweir sal_Bool ScDPAggData::HasData() const
627cdf0e10cSrcweir {
628cdf0e10cSrcweir     DBG_ASSERT( IsCalculated(), "ScDPAggData not calculated" );
629cdf0e10cSrcweir 
630cdf0e10cSrcweir     return ( nCount != SC_DPAGG_RESULT_EMPTY );     // values or error
631cdf0e10cSrcweir }
632cdf0e10cSrcweir 
SetResult(double fNew)633cdf0e10cSrcweir void ScDPAggData::SetResult( double fNew )
634cdf0e10cSrcweir {
635cdf0e10cSrcweir     DBG_ASSERT( IsCalculated(), "ScDPAggData not calculated" );
636cdf0e10cSrcweir 
637cdf0e10cSrcweir     fVal = fNew;        // don't reset error flag
638cdf0e10cSrcweir }
639cdf0e10cSrcweir 
SetError()640cdf0e10cSrcweir void ScDPAggData::SetError()
641cdf0e10cSrcweir {
642cdf0e10cSrcweir     DBG_ASSERT( IsCalculated(), "ScDPAggData not calculated" );
643cdf0e10cSrcweir 
644cdf0e10cSrcweir     nCount = SC_DPAGG_RESULT_ERROR;
645cdf0e10cSrcweir }
646cdf0e10cSrcweir 
SetEmpty(sal_Bool bSet)647cdf0e10cSrcweir void ScDPAggData::SetEmpty( sal_Bool bSet )
648cdf0e10cSrcweir {
649cdf0e10cSrcweir     DBG_ASSERT( IsCalculated(), "ScDPAggData not calculated" );
650cdf0e10cSrcweir 
651cdf0e10cSrcweir     if ( bSet )
652cdf0e10cSrcweir         nCount = SC_DPAGG_RESULT_EMPTY;
653cdf0e10cSrcweir     else
654cdf0e10cSrcweir         nCount = SC_DPAGG_RESULT_VALID;
655cdf0e10cSrcweir }
656cdf0e10cSrcweir 
GetAuxiliary() const657cdf0e10cSrcweir double ScDPAggData::GetAuxiliary() const
658cdf0e10cSrcweir {
659cdf0e10cSrcweir     // after Calculate, fAux is used as auxiliary value for running totals and reference values
660cdf0e10cSrcweir     DBG_ASSERT( IsCalculated(), "ScDPAggData not calculated" );
661cdf0e10cSrcweir 
662cdf0e10cSrcweir     return fAux;
663cdf0e10cSrcweir }
664cdf0e10cSrcweir 
SetAuxiliary(double fNew)665cdf0e10cSrcweir void ScDPAggData::SetAuxiliary( double fNew )
666cdf0e10cSrcweir {
667cdf0e10cSrcweir     // after Calculate, fAux is used as auxiliary value for running totals and reference values
668cdf0e10cSrcweir     DBG_ASSERT( IsCalculated(), "ScDPAggData not calculated" );
669cdf0e10cSrcweir 
670cdf0e10cSrcweir     fAux = fNew;
671cdf0e10cSrcweir }
672cdf0e10cSrcweir 
GetChild()673cdf0e10cSrcweir ScDPAggData* ScDPAggData::GetChild()
674cdf0e10cSrcweir {
675cdf0e10cSrcweir     if (!pChild)
676cdf0e10cSrcweir         pChild = new ScDPAggData;
677cdf0e10cSrcweir     return pChild;
678cdf0e10cSrcweir }
679cdf0e10cSrcweir 
Reset()680cdf0e10cSrcweir void ScDPAggData::Reset()
681cdf0e10cSrcweir {
682cdf0e10cSrcweir 	fVal = 0.0;
683cdf0e10cSrcweir 	fAux = 0.0;
684cdf0e10cSrcweir 	nCount = SC_DPAGG_EMPTY;
685cdf0e10cSrcweir 	delete pChild;
686cdf0e10cSrcweir 	pChild = NULL;
687cdf0e10cSrcweir }
688cdf0e10cSrcweir 
689cdf0e10cSrcweir // -----------------------------------------------------------------------
690cdf0e10cSrcweir 
ScDPRowTotals()691cdf0e10cSrcweir ScDPRowTotals::ScDPRowTotals() :
692cdf0e10cSrcweir     bIsInColRoot( sal_False )
693cdf0e10cSrcweir {
694cdf0e10cSrcweir }
695cdf0e10cSrcweir 
~ScDPRowTotals()696cdf0e10cSrcweir ScDPRowTotals::~ScDPRowTotals()
697cdf0e10cSrcweir {
698cdf0e10cSrcweir }
699cdf0e10cSrcweir 
lcl_GetChildTotal(ScDPAggData * pFirst,long nMeasure)700cdf0e10cSrcweir ScDPAggData* lcl_GetChildTotal( ScDPAggData* pFirst, long nMeasure )
701cdf0e10cSrcweir {
702cdf0e10cSrcweir     DBG_ASSERT( nMeasure >= 0, "GetColTotal: no measure" );
703cdf0e10cSrcweir 
704cdf0e10cSrcweir     ScDPAggData* pAgg = pFirst;
705cdf0e10cSrcweir     long nSkip = nMeasure;
706cdf0e10cSrcweir 
707cdf0e10cSrcweir     // subtotal settings are ignored - colum/row totals exist once per measure
708cdf0e10cSrcweir 
709cdf0e10cSrcweir     for ( long nPos=0; nPos<nSkip; nPos++ )
710cdf0e10cSrcweir         pAgg = pAgg->GetChild();    // column total is constructed empty - children need to be created
711cdf0e10cSrcweir 
712cdf0e10cSrcweir     if ( !pAgg->IsCalculated() )
713cdf0e10cSrcweir     {
714cdf0e10cSrcweir         // for first use, simulate an empty calculation
715cdf0e10cSrcweir         ScDPSubTotalState aEmptyState;
716cdf0e10cSrcweir         pAgg->Calculate( SUBTOTAL_FUNC_SUM, aEmptyState );
717cdf0e10cSrcweir     }
718cdf0e10cSrcweir 
719cdf0e10cSrcweir     return pAgg;
720cdf0e10cSrcweir }
721cdf0e10cSrcweir 
GetRowTotal(long nMeasure)722cdf0e10cSrcweir ScDPAggData* ScDPRowTotals::GetRowTotal( long nMeasure )
723cdf0e10cSrcweir {
724cdf0e10cSrcweir     return lcl_GetChildTotal( &aRowTotal, nMeasure );
725cdf0e10cSrcweir }
726cdf0e10cSrcweir 
GetGrandTotal(long nMeasure)727cdf0e10cSrcweir ScDPAggData* ScDPRowTotals::GetGrandTotal( long nMeasure )
728cdf0e10cSrcweir {
729cdf0e10cSrcweir     return lcl_GetChildTotal( &aGrandTotal, nMeasure );
730cdf0e10cSrcweir }
731cdf0e10cSrcweir 
732cdf0e10cSrcweir // -----------------------------------------------------------------------
733cdf0e10cSrcweir 
lcl_GetForceFunc(const ScDPLevel * pLevel,long nFuncNo)734cdf0e10cSrcweir static ScSubTotalFunc lcl_GetForceFunc( const ScDPLevel* pLevel, long nFuncNo )
735cdf0e10cSrcweir {
736cdf0e10cSrcweir 	ScSubTotalFunc eRet = SUBTOTAL_FUNC_NONE;
737cdf0e10cSrcweir 	if ( pLevel )
738cdf0e10cSrcweir 	{
739cdf0e10cSrcweir 		//!	direct access via ScDPLevel
740cdf0e10cSrcweir 
741cdf0e10cSrcweir 		uno::Sequence<sheet::GeneralFunction> aSeq = pLevel->getSubTotals();
742cdf0e10cSrcweir         long nSequence = aSeq.getLength();
743cdf0e10cSrcweir         if ( nSequence && aSeq[0] != sheet::GeneralFunction_AUTO )
744cdf0e10cSrcweir         {
745cdf0e10cSrcweir             // For manual subtotals, "automatic" is added as first function.
746cdf0e10cSrcweir             // ScDPResultMember::GetSubTotalCount adds to the count, here NONE has to be
747cdf0e10cSrcweir             // returned as the first function then.
748cdf0e10cSrcweir 
749cdf0e10cSrcweir             --nFuncNo;      // keep NONE for first (check below), move the other entries
750cdf0e10cSrcweir         }
751cdf0e10cSrcweir 
752cdf0e10cSrcweir 		if ( nFuncNo >= 0 && nFuncNo < nSequence )
753cdf0e10cSrcweir 		{
754cdf0e10cSrcweir 			sheet::GeneralFunction eUser = aSeq.getConstArray()[nFuncNo];
755cdf0e10cSrcweir 			if (eUser != sheet::GeneralFunction_AUTO)
756cdf0e10cSrcweir 				eRet = ScDataUnoConversion::GeneralToSubTotal( eUser );
757cdf0e10cSrcweir 		}
758cdf0e10cSrcweir 	}
759cdf0e10cSrcweir 	return eRet;
760cdf0e10cSrcweir }
761cdf0e10cSrcweir 
762cdf0e10cSrcweir // -----------------------------------------------------------------------
763cdf0e10cSrcweir 
ScDPResultData(ScDPSource * pSrc)764cdf0e10cSrcweir ScDPResultData::ScDPResultData( ScDPSource* pSrc ) :		//! Ref
765cdf0e10cSrcweir 	pSource( pSrc ),
766cdf0e10cSrcweir 	nMeasCount( 0 ),
767cdf0e10cSrcweir 	pMeasFuncs( NULL ),
768cdf0e10cSrcweir 	pMeasRefs( NULL ),
769cdf0e10cSrcweir 	pMeasRefOrient( NULL ),
770cdf0e10cSrcweir 	pMeasNames( NULL ),
771cdf0e10cSrcweir 	bLateInit( sal_False ),
772cdf0e10cSrcweir 	bDataAtCol( sal_False ),
773cdf0e10cSrcweir 	bDataAtRow( sal_False )
774cdf0e10cSrcweir {
775cdf0e10cSrcweir 
776cdf0e10cSrcweir 	lcl_ResizePointVector( mpDimMembers , SC_DAPI_MAXFIELDS );
777cdf0e10cSrcweir }
778cdf0e10cSrcweir 
~ScDPResultData()779cdf0e10cSrcweir ScDPResultData::~ScDPResultData()
780cdf0e10cSrcweir {
781cdf0e10cSrcweir 	delete[] pMeasFuncs;
782cdf0e10cSrcweir 	delete[] pMeasRefs;
783cdf0e10cSrcweir 	delete[] pMeasRefOrient;
784cdf0e10cSrcweir 	delete[] pMeasNames;
785cdf0e10cSrcweir 
786cdf0e10cSrcweir       lcl_ResizePointVector( mpDimMembers , 0 );
787cdf0e10cSrcweir }
788cdf0e10cSrcweir 
SetMeasureData(long nCount,const ScSubTotalFunc * pFunctions,const sheet::DataPilotFieldReference * pRefs,const sal_uInt16 * pRefOrient,const String * pNames)789cdf0e10cSrcweir void ScDPResultData::SetMeasureData( long nCount, const ScSubTotalFunc* pFunctions,
790cdf0e10cSrcweir 									const sheet::DataPilotFieldReference* pRefs, const sal_uInt16* pRefOrient,
791cdf0e10cSrcweir 									const String* pNames )
792cdf0e10cSrcweir {
793cdf0e10cSrcweir 	delete[] pMeasFuncs;
794cdf0e10cSrcweir 	delete[] pMeasRefs;
795cdf0e10cSrcweir 	delete[] pMeasRefOrient;
796cdf0e10cSrcweir 	delete[] pMeasNames;
797cdf0e10cSrcweir 	if ( nCount )
798cdf0e10cSrcweir 	{
799cdf0e10cSrcweir 		nMeasCount = nCount;
800cdf0e10cSrcweir 		pMeasFuncs = new ScSubTotalFunc[nCount];
801cdf0e10cSrcweir 		pMeasRefs  = new sheet::DataPilotFieldReference[nCount];
802cdf0e10cSrcweir 		pMeasRefOrient = new sal_uInt16[nCount];
803cdf0e10cSrcweir 		pMeasNames = new String[nCount];
804cdf0e10cSrcweir 		for (long i=0; i<nCount; i++)
805cdf0e10cSrcweir 		{
806cdf0e10cSrcweir 			pMeasFuncs[i] = pFunctions[i];
807cdf0e10cSrcweir 			pMeasRefs[i]  = pRefs[i];
808cdf0e10cSrcweir 			pMeasRefOrient[i] = pRefOrient[i];
809cdf0e10cSrcweir 			pMeasNames[i] = pNames[i];
810cdf0e10cSrcweir 		}
811cdf0e10cSrcweir 	}
812cdf0e10cSrcweir 	else
813cdf0e10cSrcweir 	{
814cdf0e10cSrcweir 		//	use one dummy measure
815cdf0e10cSrcweir 		nMeasCount = 1;
816cdf0e10cSrcweir 		pMeasFuncs = new ScSubTotalFunc[1];
817cdf0e10cSrcweir 		pMeasFuncs[0] = SUBTOTAL_FUNC_NONE;
818cdf0e10cSrcweir 		pMeasRefs  = new sheet::DataPilotFieldReference[1];	// default ctor is ok
819cdf0e10cSrcweir 		pMeasRefOrient = new sal_uInt16[1];
820cdf0e10cSrcweir 		pMeasRefOrient[0] = sheet::DataPilotFieldOrientation_HIDDEN;
821cdf0e10cSrcweir 		pMeasNames = new String[1];
822cdf0e10cSrcweir 		pMeasNames[0] = ScGlobal::GetRscString( STR_EMPTYDATA );
823cdf0e10cSrcweir 	}
824cdf0e10cSrcweir }
825cdf0e10cSrcweir 
SetDataLayoutOrientation(sal_uInt16 nOrient)826cdf0e10cSrcweir void ScDPResultData::SetDataLayoutOrientation( sal_uInt16 nOrient )
827cdf0e10cSrcweir {
828cdf0e10cSrcweir 	bDataAtCol = ( nOrient == sheet::DataPilotFieldOrientation_COLUMN );
829cdf0e10cSrcweir 	bDataAtRow = ( nOrient == sheet::DataPilotFieldOrientation_ROW );
830cdf0e10cSrcweir }
831cdf0e10cSrcweir 
SetLateInit(sal_Bool bSet)832cdf0e10cSrcweir void ScDPResultData::SetLateInit( sal_Bool bSet )
833cdf0e10cSrcweir {
834cdf0e10cSrcweir 	bLateInit = bSet;
835cdf0e10cSrcweir }
836cdf0e10cSrcweir 
GetColStartMeasure() const837cdf0e10cSrcweir long ScDPResultData::GetColStartMeasure() const
838cdf0e10cSrcweir {
839cdf0e10cSrcweir 	if ( nMeasCount == 1 ) return 0;
840cdf0e10cSrcweir 	return bDataAtCol ? SC_DPMEASURE_ALL : SC_DPMEASURE_ANY;
841cdf0e10cSrcweir }
842cdf0e10cSrcweir 
GetRowStartMeasure() const843cdf0e10cSrcweir long ScDPResultData::GetRowStartMeasure() const
844cdf0e10cSrcweir {
845cdf0e10cSrcweir 	if ( nMeasCount == 1 ) return 0;
846cdf0e10cSrcweir 	return bDataAtRow ? SC_DPMEASURE_ALL : SC_DPMEASURE_ANY;
847cdf0e10cSrcweir }
848cdf0e10cSrcweir 
GetMeasureFunction(long nMeasure) const849cdf0e10cSrcweir ScSubTotalFunc ScDPResultData::GetMeasureFunction(long nMeasure) const
850cdf0e10cSrcweir {
851cdf0e10cSrcweir 	DBG_ASSERT( pMeasFuncs && nMeasure < nMeasCount, "bumm" );
852cdf0e10cSrcweir 	return pMeasFuncs[nMeasure];
853cdf0e10cSrcweir }
854cdf0e10cSrcweir 
GetMeasureRefVal(long nMeasure) const855cdf0e10cSrcweir const sheet::DataPilotFieldReference& ScDPResultData::GetMeasureRefVal(long nMeasure) const
856cdf0e10cSrcweir {
857cdf0e10cSrcweir     DBG_ASSERT( pMeasRefs && nMeasure < nMeasCount, "bumm" );
858cdf0e10cSrcweir     return pMeasRefs[nMeasure];
859cdf0e10cSrcweir }
860cdf0e10cSrcweir 
GetMeasureRefOrient(long nMeasure) const861cdf0e10cSrcweir sal_uInt16 ScDPResultData::GetMeasureRefOrient(long nMeasure) const
862cdf0e10cSrcweir {
863cdf0e10cSrcweir     DBG_ASSERT( pMeasRefOrient && nMeasure < nMeasCount, "bumm" );
864cdf0e10cSrcweir     return pMeasRefOrient[nMeasure];
865cdf0e10cSrcweir }
866cdf0e10cSrcweir 
GetMeasureString(long nMeasure,sal_Bool bForce,ScSubTotalFunc eForceFunc,bool & rbTotalResult) const867cdf0e10cSrcweir String ScDPResultData::GetMeasureString(long nMeasure, sal_Bool bForce, ScSubTotalFunc eForceFunc, bool& rbTotalResult) const
868cdf0e10cSrcweir {
869cdf0e10cSrcweir 	//	with bForce==sal_True, return function instead of "result" for single measure
870cdf0e10cSrcweir 	//	with eForceFunc != SUBTOTAL_FUNC_NONE, always use eForceFunc
871cdf0e10cSrcweir     rbTotalResult = false;
872cdf0e10cSrcweir 	if ( nMeasure < 0 || ( nMeasCount == 1 && !bForce && eForceFunc == SUBTOTAL_FUNC_NONE ) )
873cdf0e10cSrcweir 	{
874cdf0e10cSrcweir 		//	for user-specified subtotal function with all measures,
875cdf0e10cSrcweir 		//	display only function name
876cdf0e10cSrcweir 		if ( eForceFunc != SUBTOTAL_FUNC_NONE )
877cdf0e10cSrcweir 			return ScGlobal::GetRscString(nFuncStrIds[eForceFunc]);
878cdf0e10cSrcweir 
879cdf0e10cSrcweir         rbTotalResult = true;
880cdf0e10cSrcweir 		return ScGlobal::GetRscString(STR_TABLE_ERGEBNIS);
881cdf0e10cSrcweir 	}
882cdf0e10cSrcweir 	else
883cdf0e10cSrcweir 	{
884cdf0e10cSrcweir 		DBG_ASSERT( pMeasNames && nMeasure < nMeasCount, "bumm" );
885cdf0e10cSrcweir         ScDPDimension* pDataDim = pSource->GetDataDimension(nMeasure);
886cdf0e10cSrcweir         if (pDataDim)
887cdf0e10cSrcweir         {
888cdf0e10cSrcweir             const OUString* pLayoutName = pDataDim->GetLayoutName();
889cdf0e10cSrcweir             if (pLayoutName)
890cdf0e10cSrcweir                 return *pLayoutName;
891cdf0e10cSrcweir         }
892cdf0e10cSrcweir 		String aRet;
893cdf0e10cSrcweir 		ScSubTotalFunc eFunc = ( eForceFunc == SUBTOTAL_FUNC_NONE ) ?
894cdf0e10cSrcweir 									GetMeasureFunction(nMeasure) : eForceFunc;
895cdf0e10cSrcweir 		sal_uInt16 nId = nFuncStrIds[eFunc];
896cdf0e10cSrcweir 		if (nId)
897cdf0e10cSrcweir 		{
898cdf0e10cSrcweir 			aRet += ScGlobal::GetRscString(nId);		// function name
899cdf0e10cSrcweir 			aRet.AppendAscii(RTL_CONSTASCII_STRINGPARAM( " - " ));
900cdf0e10cSrcweir 		}
901cdf0e10cSrcweir 		aRet += pMeasNames[nMeasure];					// field name
902cdf0e10cSrcweir 
903cdf0e10cSrcweir 		return aRet;
904cdf0e10cSrcweir 	}
905cdf0e10cSrcweir }
906cdf0e10cSrcweir 
GetMeasureDimensionName(long nMeasure) const907cdf0e10cSrcweir String ScDPResultData::GetMeasureDimensionName(long nMeasure) const
908cdf0e10cSrcweir {
909cdf0e10cSrcweir 	if ( nMeasure < 0 )
910cdf0e10cSrcweir 	{
911cdf0e10cSrcweir 		DBG_ERROR("GetMeasureDimensionName: negative");
912cdf0e10cSrcweir 		return String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("***"));
913cdf0e10cSrcweir 	}
914cdf0e10cSrcweir 
915cdf0e10cSrcweir 	return pSource->GetDataDimName( nMeasure );
916cdf0e10cSrcweir }
917cdf0e10cSrcweir 
IsBaseForGroup(long nDim) const918cdf0e10cSrcweir sal_Bool ScDPResultData::IsBaseForGroup( long nDim ) const
919cdf0e10cSrcweir {
920cdf0e10cSrcweir     return pSource->GetData()->IsBaseForGroup( nDim );
921cdf0e10cSrcweir }
922cdf0e10cSrcweir 
GetGroupBase(long nGroupDim) const923cdf0e10cSrcweir long ScDPResultData::GetGroupBase( long nGroupDim ) const
924cdf0e10cSrcweir {
925cdf0e10cSrcweir     return pSource->GetData()->GetGroupBase( nGroupDim );
926cdf0e10cSrcweir }
927cdf0e10cSrcweir 
IsNumOrDateGroup(long nDim) const928cdf0e10cSrcweir sal_Bool ScDPResultData::IsNumOrDateGroup( long nDim ) const
929cdf0e10cSrcweir {
930cdf0e10cSrcweir     return pSource->GetData()->IsNumOrDateGroup( nDim );
931cdf0e10cSrcweir }
932cdf0e10cSrcweir 
IsInGroup(const ScDPItemData & rGroupData,long nGroupIndex,long nBaseDataId,long nBaseIndex) const933cdf0e10cSrcweir sal_Bool ScDPResultData::IsInGroup( const ScDPItemData& rGroupData, long nGroupIndex,
934cdf0e10cSrcweir                                 long nBaseDataId, long nBaseIndex ) const
935cdf0e10cSrcweir {
936cdf0e10cSrcweir     const ScDPItemData* pData = pSource->GetItemDataById( nGroupIndex , nBaseDataId);
937cdf0e10cSrcweir     if ( pData )
938cdf0e10cSrcweir          return pSource->GetData()->IsInGroup( rGroupData, nGroupIndex, *pData , nBaseIndex );
939cdf0e10cSrcweir     else
940cdf0e10cSrcweir         return sal_False;
941cdf0e10cSrcweir }
IsInGroup(SCROW nGroupDataId,long nGroupIndex,const ScDPItemData & rBaseData,long nBaseIndex) const942cdf0e10cSrcweir sal_Bool ScDPResultData::IsInGroup( SCROW nGroupDataId, long nGroupIndex,
943cdf0e10cSrcweir                                                                const ScDPItemData& rBaseData, long nBaseIndex ) const
944cdf0e10cSrcweir {
945cdf0e10cSrcweir     const ScDPItemData* pGroupData = pSource->GetItemDataById( nGroupIndex , nGroupDataId);
946cdf0e10cSrcweir     if ( pGroupData )
947cdf0e10cSrcweir         return pSource->GetData()->IsInGroup( *pGroupData, nGroupIndex, rBaseData , nBaseIndex );
948cdf0e10cSrcweir     else
949cdf0e10cSrcweir         return sal_False;
950cdf0e10cSrcweir }
951cdf0e10cSrcweir 
HasCommonElement(SCROW nFirstDataId,long nFirstIndex,const ScDPItemData & rSecondData,long nSecondIndex) const952cdf0e10cSrcweir sal_Bool ScDPResultData::HasCommonElement(/* const ScDPItemData& rFirstData*/SCROW nFirstDataId, long nFirstIndex,
953cdf0e10cSrcweir                                        const ScDPItemData& rSecondData, long nSecondIndex ) const
954cdf0e10cSrcweir {
955cdf0e10cSrcweir     const ScDPItemData* pFirstData = pSource->GetItemDataById( nFirstIndex , nFirstDataId);
956cdf0e10cSrcweir     if ( pFirstData )
957cdf0e10cSrcweir         return pSource->GetData()->HasCommonElement( *pFirstData, nFirstIndex, rSecondData, nSecondIndex );
958cdf0e10cSrcweir     else
959cdf0e10cSrcweir         return sal_False;
960cdf0e10cSrcweir }
961cdf0e10cSrcweir 
GetSource() const962cdf0e10cSrcweir const ScDPSource* ScDPResultData::GetSource() const
963cdf0e10cSrcweir {
964cdf0e10cSrcweir     return pSource;
965cdf0e10cSrcweir }
966cdf0e10cSrcweir 
GetDimResultMembers(long nDim,ScDPDimension * pDim,ScDPLevel * pLevel) const967cdf0e10cSrcweir ResultMembers* ScDPResultData::GetDimResultMembers( long nDim ,  ScDPDimension* pDim, ScDPLevel*   pLevel) const
968cdf0e10cSrcweir {
969cdf0e10cSrcweir  	 if ( mpDimMembers[ nDim ] == NULL )
970cdf0e10cSrcweir         {
971cdf0e10cSrcweir 
972cdf0e10cSrcweir                 //long nDimSource = pDim->GetDimension();
973cdf0e10cSrcweir 
974cdf0e10cSrcweir 	            ResultMembers* pResultMembers = new ResultMembers();
975cdf0e10cSrcweir 	            // global order is used to initialize aMembers, so it doesn't have to be looked at later
976cdf0e10cSrcweir 	            const ScMemberSortOrder& rGlobalOrder = pLevel->GetGlobalOrder();
977cdf0e10cSrcweir 
978cdf0e10cSrcweir 	            ScDPMembers* pMembers = pLevel->GetMembersObject();
979cdf0e10cSrcweir 	            long nMembCount = pMembers->getCount();
980cdf0e10cSrcweir 	            for ( long i=0; i<nMembCount; i++ )
981cdf0e10cSrcweir 	            {
982cdf0e10cSrcweir 		            long nSorted = rGlobalOrder.empty() ? i : rGlobalOrder[i];
983cdf0e10cSrcweir 		            ScDPMember* pMember = pMembers->getByIndex(nSorted);
984cdf0e10cSrcweir 		            if ( NULL == pResultMembers->FindMember( pMember->GetItemDataId() ) )
985cdf0e10cSrcweir 		            {
986cdf0e10cSrcweir 			                ScDPParentDimData* pNew = new ScDPParentDimData( i, pDim, pLevel, pMember );
987cdf0e10cSrcweir                           		  pResultMembers->InsertMember(  pNew );
988cdf0e10cSrcweir 		            }
989cdf0e10cSrcweir 	            }
990cdf0e10cSrcweir 
991cdf0e10cSrcweir                 mpDimMembers[ nDim ] = pResultMembers;
992cdf0e10cSrcweir         }
993cdf0e10cSrcweir         return   mpDimMembers[ nDim ];
994cdf0e10cSrcweir 
995cdf0e10cSrcweir }
996cdf0e10cSrcweir 
997cdf0e10cSrcweir // -----------------------------------------------------------------------
998cdf0e10cSrcweir 
999cdf0e10cSrcweir 
ScDPResultMember(const ScDPResultData * pData,const ScDPParentDimData & rParentDimData,sal_Bool bForceSub)1000cdf0e10cSrcweir ScDPResultMember::ScDPResultMember(  const ScDPResultData* pData, const ScDPParentDimData& rParentDimData ,
1001cdf0e10cSrcweir 									sal_Bool bForceSub ) :
1002cdf0e10cSrcweir 	pResultData( pData ),
1003cdf0e10cSrcweir    	aParentDimData( rParentDimData ),
1004cdf0e10cSrcweir 	pChildDimension( NULL ),
1005cdf0e10cSrcweir 	pDataRoot( NULL ),
1006cdf0e10cSrcweir 	bHasElements( sal_False ),
1007cdf0e10cSrcweir 	bForceSubTotal( bForceSub ),
1008cdf0e10cSrcweir 	bHasHiddenDetails( sal_False ),
1009cdf0e10cSrcweir 	bInitialized( sal_False ),
1010cdf0e10cSrcweir     bAutoHidden( sal_False ),
1011cdf0e10cSrcweir     nMemberStep( 1 )
1012cdf0e10cSrcweir {
1013cdf0e10cSrcweir 	// pParentLevel/pMemberDesc is 0 for root members
1014cdf0e10cSrcweir }
1015cdf0e10cSrcweir 
ScDPResultMember(const ScDPResultData * pData,sal_Bool bForceSub)1016cdf0e10cSrcweir ScDPResultMember::ScDPResultMember(  const ScDPResultData* pData,
1017cdf0e10cSrcweir 									sal_Bool bForceSub ) :
1018cdf0e10cSrcweir 	pResultData( pData ),
1019cdf0e10cSrcweir     	pChildDimension( NULL ),
1020cdf0e10cSrcweir 	pDataRoot( NULL ),
1021cdf0e10cSrcweir 	bHasElements( sal_False ),
1022cdf0e10cSrcweir 	bForceSubTotal( bForceSub ),
1023cdf0e10cSrcweir 	bHasHiddenDetails( sal_False ),
1024cdf0e10cSrcweir 	bInitialized( sal_False ),
1025cdf0e10cSrcweir     bAutoHidden( sal_False ),
1026cdf0e10cSrcweir     nMemberStep( 1 )
1027cdf0e10cSrcweir {
1028cdf0e10cSrcweir }
~ScDPResultMember()1029cdf0e10cSrcweir ScDPResultMember::~ScDPResultMember()
1030cdf0e10cSrcweir {
1031cdf0e10cSrcweir 	delete pChildDimension;
1032cdf0e10cSrcweir 	delete pDataRoot;
1033cdf0e10cSrcweir }
1034cdf0e10cSrcweir 
GetName() const1035cdf0e10cSrcweir String ScDPResultMember::GetName() const
1036cdf0e10cSrcweir {
1037cdf0e10cSrcweir   const ScDPMember*   pMemberDesc = GetDPMember();
1038cdf0e10cSrcweir 	if (pMemberDesc)
1039cdf0e10cSrcweir 		return pMemberDesc->GetNameStr();
1040cdf0e10cSrcweir 	else
1041cdf0e10cSrcweir 		return ScGlobal::GetRscString(STR_PIVOT_TOTAL);			// root member
1042cdf0e10cSrcweir }
1043cdf0e10cSrcweir 
FillItemData(ScDPItemData & rData) const1044cdf0e10cSrcweir void ScDPResultMember::FillItemData( ScDPItemData& rData ) const
1045cdf0e10cSrcweir {
1046cdf0e10cSrcweir     const ScDPMember*   pMemberDesc = GetDPMember();
1047cdf0e10cSrcweir     if (pMemberDesc)
1048cdf0e10cSrcweir         pMemberDesc->FillItemData( rData );
1049cdf0e10cSrcweir     else
1050cdf0e10cSrcweir         rData.SetString( ScGlobal::GetRscString(STR_PIVOT_TOTAL) );     // root member
1051cdf0e10cSrcweir }
1052cdf0e10cSrcweir 
IsNamedItem(SCROW nIndex) const1053cdf0e10cSrcweir sal_Bool ScDPResultMember::IsNamedItem( SCROW nIndex ) const
1054cdf0e10cSrcweir {
1055cdf0e10cSrcweir 	//!	store ScDPMember pointer instead of ScDPMember ???
1056cdf0e10cSrcweir   const ScDPMember*   pMemberDesc = GetDPMember();
1057cdf0e10cSrcweir 	if (pMemberDesc)
1058cdf0e10cSrcweir 		return ((ScDPMember*)pMemberDesc)->IsNamedItem( nIndex  );
1059cdf0e10cSrcweir 	return sal_False;
1060cdf0e10cSrcweir }
1061cdf0e10cSrcweir 
IsValidEntry(const vector<SCROW> & aMembers) const1062cdf0e10cSrcweir bool ScDPResultMember::IsValidEntry( const vector< SCROW >& aMembers ) const
1063cdf0e10cSrcweir {
1064cdf0e10cSrcweir     if ( !IsValid() )
1065cdf0e10cSrcweir         return false;
1066cdf0e10cSrcweir 
1067cdf0e10cSrcweir     const ScDPResultDimension* pChildDim = GetChildDimension();
1068cdf0e10cSrcweir     if (pChildDim)
1069cdf0e10cSrcweir     {
1070cdf0e10cSrcweir         if (aMembers.size() < 2)
1071cdf0e10cSrcweir             return false;
1072cdf0e10cSrcweir 
1073cdf0e10cSrcweir         vector<SCROW>::const_iterator itr = aMembers.begin();
1074cdf0e10cSrcweir         vector<SCROW> aChildMembers(++itr, aMembers.end());
1075cdf0e10cSrcweir         return pChildDim->IsValidEntry(aChildMembers);
1076cdf0e10cSrcweir     }
1077cdf0e10cSrcweir     else
1078cdf0e10cSrcweir         return true;
1079cdf0e10cSrcweir }
1080cdf0e10cSrcweir 
InitFrom(const vector<ScDPDimension * > & ppDim,const vector<ScDPLevel * > & ppLev,size_t nPos,ScDPInitState & rInitState,sal_Bool bInitChild)1081cdf0e10cSrcweir void ScDPResultMember::InitFrom( const vector<ScDPDimension*>& ppDim, const vector<ScDPLevel*>& ppLev,
1082cdf0e10cSrcweir                                  size_t nPos, ScDPInitState& rInitState ,
1083cdf0e10cSrcweir                                  sal_Bool bInitChild /*= sal_True */)
1084cdf0e10cSrcweir {
1085cdf0e10cSrcweir 	//	with LateInit, initialize only those members that have data
1086cdf0e10cSrcweir 	if ( pResultData->IsLateInit() )
1087cdf0e10cSrcweir 		return;
1088cdf0e10cSrcweir 
1089cdf0e10cSrcweir 	bInitialized = sal_True;
1090cdf0e10cSrcweir 
1091cdf0e10cSrcweir     if (nPos >= ppDim.size())
1092cdf0e10cSrcweir         return;
1093cdf0e10cSrcweir 
1094cdf0e10cSrcweir 	//	skip child dimension if details are not shown
1095cdf0e10cSrcweir 	if ( GetDPMember() && !GetDPMember()->getShowDetails() )
1096cdf0e10cSrcweir 	{
1097cdf0e10cSrcweir          // Wang Xu Ming -- 2009-6-16
1098cdf0e10cSrcweir         // Show DataLayout dimention
1099cdf0e10cSrcweir         nMemberStep = 1;
1100cdf0e10cSrcweir         while ( nPos < ppDim.size() )
1101cdf0e10cSrcweir         {
1102cdf0e10cSrcweir             if (  ppDim[nPos] ->getIsDataLayoutDimension() )
1103cdf0e10cSrcweir             {
1104cdf0e10cSrcweir                  if ( !pChildDimension )
1105cdf0e10cSrcweir                         pChildDimension = new ScDPResultDimension( pResultData );
1106cdf0e10cSrcweir                     pChildDimension->InitFrom( ppDim, ppLev, nPos, rInitState , sal_False );
1107cdf0e10cSrcweir 					return;
1108cdf0e10cSrcweir             }
1109cdf0e10cSrcweir             else
1110cdf0e10cSrcweir             { //find next dim
1111cdf0e10cSrcweir                 nPos ++;
1112cdf0e10cSrcweir                 nMemberStep ++;
1113cdf0e10cSrcweir             }
1114cdf0e10cSrcweir         }
1115cdf0e10cSrcweir         // End Comments
1116cdf0e10cSrcweir         bHasHiddenDetails = sal_True;	// only if there is a next dimension
1117cdf0e10cSrcweir 		return;
1118cdf0e10cSrcweir 	}
1119cdf0e10cSrcweir 
1120cdf0e10cSrcweir     if ( bInitChild )
1121cdf0e10cSrcweir     {
1122cdf0e10cSrcweir         pChildDimension = new ScDPResultDimension( pResultData );
1123cdf0e10cSrcweir         pChildDimension->InitFrom( ppDim, ppLev, nPos, rInitState, sal_True  );
1124cdf0e10cSrcweir     }
1125cdf0e10cSrcweir }
1126cdf0e10cSrcweir 
LateInitFrom(LateInitParams & rParams,const vector<SCROW> & pItemData,size_t nPos,ScDPInitState & rInitState)1127cdf0e10cSrcweir void ScDPResultMember::LateInitFrom( LateInitParams& rParams/*const vector<ScDPDimension*>& ppDim, const vector<ScDPLevel*>& ppLev*/,
1128cdf0e10cSrcweir                                      const vector< SCROW >& pItemData,   size_t nPos,
1129cdf0e10cSrcweir                                      ScDPInitState& rInitState )
1130cdf0e10cSrcweir {
1131cdf0e10cSrcweir 	//	without LateInit, everything has already been initialized
1132cdf0e10cSrcweir 	if ( !pResultData->IsLateInit() )
1133cdf0e10cSrcweir 		return;
1134cdf0e10cSrcweir 
1135cdf0e10cSrcweir 	bInitialized = sal_True;
1136cdf0e10cSrcweir 
1137cdf0e10cSrcweir     if ( rParams.IsEnd( nPos )  /*nPos >= ppDim.size()*/)
1138cdf0e10cSrcweir         // No next dimension.  Bail out.
1139cdf0e10cSrcweir         return;
1140cdf0e10cSrcweir 
1141cdf0e10cSrcweir     //	skip child dimension if details are not shown
1142cdf0e10cSrcweir     if ( GetDPMember() && !GetDPMember()->getShowDetails() )
1143cdf0e10cSrcweir     {
1144cdf0e10cSrcweir         // Wang Xu Ming -- 2009-6-16
1145cdf0e10cSrcweir         // DataPilot Migration
1146cdf0e10cSrcweir         // Show DataLayout dimention
1147cdf0e10cSrcweir         nMemberStep = 1;
1148cdf0e10cSrcweir         while ( !rParams.IsEnd( nPos ) )
1149cdf0e10cSrcweir         {
1150cdf0e10cSrcweir             if (  rParams.GetDim( nPos ) ->getIsDataLayoutDimension() )
1151cdf0e10cSrcweir             {
1152cdf0e10cSrcweir                 if ( !pChildDimension )
1153cdf0e10cSrcweir                     pChildDimension = new ScDPResultDimension( pResultData );
1154cdf0e10cSrcweir 
1155cdf0e10cSrcweir                 // #i111462# reset InitChild flag only for this child dimension's LateInitFrom call,
1156cdf0e10cSrcweir                 // not for following members of parent dimensions
1157cdf0e10cSrcweir                 sal_Bool bWasInitChild = rParams.GetInitChild();
1158cdf0e10cSrcweir                 rParams.SetInitChild( sal_False );
1159cdf0e10cSrcweir                 pChildDimension->LateInitFrom( rParams, pItemData, nPos, rInitState );
1160cdf0e10cSrcweir                 rParams.SetInitChild( bWasInitChild );
1161cdf0e10cSrcweir                 return;
1162cdf0e10cSrcweir             }
1163cdf0e10cSrcweir             else
1164cdf0e10cSrcweir             { //find next dim
1165cdf0e10cSrcweir                 nPos ++;
1166cdf0e10cSrcweir                 nMemberStep ++;
1167cdf0e10cSrcweir             }
1168cdf0e10cSrcweir         }
1169cdf0e10cSrcweir         // End Comments
1170cdf0e10cSrcweir         bHasHiddenDetails = sal_True;   // only if there is a next dimension
1171cdf0e10cSrcweir         return;
1172cdf0e10cSrcweir     }
1173cdf0e10cSrcweir 
1174cdf0e10cSrcweir     //	LateInitFrom is called several times...
1175cdf0e10cSrcweir     if ( rParams.GetInitChild() )
1176cdf0e10cSrcweir     {
1177cdf0e10cSrcweir         if ( !pChildDimension )
1178cdf0e10cSrcweir             pChildDimension = new ScDPResultDimension( pResultData );
1179cdf0e10cSrcweir         pChildDimension->LateInitFrom( rParams, pItemData, nPos, rInitState );
1180cdf0e10cSrcweir     }
1181cdf0e10cSrcweir }
1182cdf0e10cSrcweir 
IsSubTotalInTitle(long nMeasure) const1183cdf0e10cSrcweir sal_Bool ScDPResultMember::IsSubTotalInTitle(long nMeasure) const
1184cdf0e10cSrcweir {
1185cdf0e10cSrcweir     sal_Bool bRet = sal_False;
1186cdf0e10cSrcweir     if ( pChildDimension && /*pParentLevel*/GetParentLevel() &&
1187cdf0e10cSrcweir          /*pParentLevel*/GetParentLevel()->IsOutlineLayout() && /*pParentLevel*/GetParentLevel()->IsSubtotalsAtTop() )
1188cdf0e10cSrcweir     {
1189cdf0e10cSrcweir         long nUserSubStart;
1190cdf0e10cSrcweir         long nSubTotals = GetSubTotalCount( &nUserSubStart );
1191cdf0e10cSrcweir         nSubTotals -= nUserSubStart;            // visible count
1192cdf0e10cSrcweir         if ( nSubTotals )
1193cdf0e10cSrcweir         {
1194cdf0e10cSrcweir             if ( nMeasure == SC_DPMEASURE_ALL )
1195cdf0e10cSrcweir                 nSubTotals *= pResultData->GetMeasureCount();   // number of subtotals that will be inserted
1196cdf0e10cSrcweir 
1197cdf0e10cSrcweir             // only a single subtotal row will be shown in the outline title row
1198cdf0e10cSrcweir             if ( nSubTotals == 1 )
1199cdf0e10cSrcweir                 bRet = sal_True;
1200cdf0e10cSrcweir         }
1201cdf0e10cSrcweir     }
1202cdf0e10cSrcweir     return bRet;
1203cdf0e10cSrcweir }
1204cdf0e10cSrcweir 
GetSize(long nMeasure) const1205cdf0e10cSrcweir long ScDPResultMember::GetSize(long nMeasure) const
1206cdf0e10cSrcweir {
1207cdf0e10cSrcweir 	if ( !IsVisible() )
1208cdf0e10cSrcweir 		return 0;
1209cdf0e10cSrcweir     const ScDPLevel*	   pParentLevel = GetParentLevel();
1210cdf0e10cSrcweir     long nExtraSpace = 0;
1211cdf0e10cSrcweir     if ( pParentLevel && pParentLevel->IsAddEmpty() )
1212cdf0e10cSrcweir         ++nExtraSpace;
1213cdf0e10cSrcweir 
1214cdf0e10cSrcweir 	if ( pChildDimension )
1215cdf0e10cSrcweir 	{
1216cdf0e10cSrcweir         //  outline layout takes up an extra row for the title only if subtotals aren't shown in that row
1217cdf0e10cSrcweir         if ( pParentLevel && pParentLevel->IsOutlineLayout() && !IsSubTotalInTitle( nMeasure ) )
1218cdf0e10cSrcweir             ++nExtraSpace;
1219cdf0e10cSrcweir 
1220cdf0e10cSrcweir 		long nSize = pChildDimension->GetSize(nMeasure);
1221cdf0e10cSrcweir 		long nUserSubStart;
1222cdf0e10cSrcweir 		long nUserSubCount = GetSubTotalCount( &nUserSubStart );
1223cdf0e10cSrcweir 		nUserSubCount -= nUserSubStart;     // for output size, use visible count
1224cdf0e10cSrcweir 		if ( nUserSubCount )
1225cdf0e10cSrcweir 		{
1226cdf0e10cSrcweir 			if ( nMeasure == SC_DPMEASURE_ALL )
1227cdf0e10cSrcweir 				nSize += pResultData->GetMeasureCount() * nUserSubCount;
1228cdf0e10cSrcweir 			else
1229cdf0e10cSrcweir 				nSize += nUserSubCount;
1230cdf0e10cSrcweir 		}
1231cdf0e10cSrcweir 		return nSize + nExtraSpace;
1232cdf0e10cSrcweir 	}
1233cdf0e10cSrcweir 	else
1234cdf0e10cSrcweir 	{
1235cdf0e10cSrcweir 		if ( nMeasure == SC_DPMEASURE_ALL )
1236cdf0e10cSrcweir 			return pResultData->GetMeasureCount() + nExtraSpace;
1237cdf0e10cSrcweir 		else
1238cdf0e10cSrcweir 			return 1 + nExtraSpace;
1239cdf0e10cSrcweir 	}
1240cdf0e10cSrcweir }
1241cdf0e10cSrcweir 
IsVisible() const1242cdf0e10cSrcweir sal_Bool ScDPResultMember::IsVisible() const
1243cdf0e10cSrcweir {
1244cdf0e10cSrcweir 	//	not initialized -> shouldn't be there at all
1245cdf0e10cSrcweir 	//	(allocated only to preserve ordering)
1246cdf0e10cSrcweir    const ScDPLevel*	pParentLevel = GetParentLevel();
1247cdf0e10cSrcweir 	return ( bHasElements || ( pParentLevel && pParentLevel->getShowEmpty() ) ) && IsValid() && bInitialized;
1248cdf0e10cSrcweir }
1249cdf0e10cSrcweir 
IsValid() const1250cdf0e10cSrcweir sal_Bool ScDPResultMember::IsValid() const
1251cdf0e10cSrcweir {
1252cdf0e10cSrcweir 	//	non-Valid members are left out of calculation
1253cdf0e10cSrcweir 
1254cdf0e10cSrcweir 	//	was member set no invisible at the DataPilotSource?
1255cdf0e10cSrcweir   const ScDPMember*		pMemberDesc =GetDPMember();
1256cdf0e10cSrcweir 	if ( pMemberDesc && !pMemberDesc->getIsVisible() )
1257cdf0e10cSrcweir 		return sal_False;
1258cdf0e10cSrcweir 
1259cdf0e10cSrcweir     if ( bAutoHidden )
1260cdf0e10cSrcweir         return sal_False;
1261cdf0e10cSrcweir 
1262cdf0e10cSrcweir 	return sal_True;
1263cdf0e10cSrcweir }
1264cdf0e10cSrcweir 
HasHiddenDetails() const1265cdf0e10cSrcweir sal_Bool ScDPResultMember::HasHiddenDetails() const
1266cdf0e10cSrcweir {
1267cdf0e10cSrcweir     // bHasHiddenDetails is set only if the "show details" flag is off,
1268cdf0e10cSrcweir     // and there was a child dimension to skip
1269cdf0e10cSrcweir 
1270cdf0e10cSrcweir     return bHasHiddenDetails;
1271cdf0e10cSrcweir }
1272cdf0e10cSrcweir 
GetSubTotalCount(long * pUserSubStart) const1273cdf0e10cSrcweir long ScDPResultMember::GetSubTotalCount( long* pUserSubStart ) const
1274cdf0e10cSrcweir {
1275cdf0e10cSrcweir     if ( pUserSubStart )
1276cdf0e10cSrcweir         *pUserSubStart = 0;     // default
1277cdf0e10cSrcweir 
1278cdf0e10cSrcweir    const ScDPLevel*	pParentLevel = GetParentLevel();
1279cdf0e10cSrcweir 
1280cdf0e10cSrcweir 	if ( bForceSubTotal )		// set if needed for root members
1281cdf0e10cSrcweir 		return 1;				// grand total is always "automatic"
1282cdf0e10cSrcweir 	else if ( pParentLevel )
1283cdf0e10cSrcweir 	{
1284cdf0e10cSrcweir 		//!	direct access via ScDPLevel
1285cdf0e10cSrcweir 
1286cdf0e10cSrcweir         uno::Sequence<sheet::GeneralFunction> aSeq = pParentLevel->getSubTotals();
1287cdf0e10cSrcweir         long nSequence = aSeq.getLength();
1288cdf0e10cSrcweir         if ( nSequence && aSeq[0] != sheet::GeneralFunction_AUTO )
1289cdf0e10cSrcweir         {
1290cdf0e10cSrcweir             // For manual subtotals, always add "automatic" as first function
1291cdf0e10cSrcweir             // (used for calculation, but not for display, needed for sorting, see lcl_GetForceFunc)
1292cdf0e10cSrcweir 
1293cdf0e10cSrcweir             ++nSequence;
1294cdf0e10cSrcweir             if ( pUserSubStart )
1295cdf0e10cSrcweir                 *pUserSubStart = 1;     // visible subtotals start at 1
1296cdf0e10cSrcweir         }
1297cdf0e10cSrcweir         return nSequence;
1298cdf0e10cSrcweir 	}
1299cdf0e10cSrcweir 	else
1300cdf0e10cSrcweir 		return 0;
1301cdf0e10cSrcweir }
1302cdf0e10cSrcweir 
ProcessData(const vector<SCROW> & aChildMembers,const ScDPResultDimension * pDataDim,const vector<SCROW> & aDataMembers,const vector<ScDPValueData> & aValues)1303cdf0e10cSrcweir void ScDPResultMember::ProcessData( const vector< SCROW >& aChildMembers, const ScDPResultDimension* pDataDim,
1304cdf0e10cSrcweir                                     const vector< SCROW >& aDataMembers, const vector<ScDPValueData>& aValues )
1305cdf0e10cSrcweir {
1306cdf0e10cSrcweir     SetHasElements();
1307cdf0e10cSrcweir 
1308cdf0e10cSrcweir     if (pChildDimension)
1309cdf0e10cSrcweir         pChildDimension->ProcessData( aChildMembers, pDataDim, aDataMembers, aValues );
1310cdf0e10cSrcweir 
1311cdf0e10cSrcweir     if ( !pDataRoot )
1312cdf0e10cSrcweir     {
1313cdf0e10cSrcweir         pDataRoot = new ScDPDataMember( pResultData, NULL );
1314cdf0e10cSrcweir         if ( pDataDim )
1315cdf0e10cSrcweir             pDataRoot->InitFrom( pDataDim );            // recursive
1316cdf0e10cSrcweir     }
1317cdf0e10cSrcweir 
1318cdf0e10cSrcweir     ScDPSubTotalState aSubState;        // initial state
1319cdf0e10cSrcweir 
1320cdf0e10cSrcweir     long nUserSubCount = GetSubTotalCount();
1321cdf0e10cSrcweir 
1322cdf0e10cSrcweir     // Calculate at least automatic if no subtotals are selected,
1323cdf0e10cSrcweir     // show only own values if there's no child dimension (innermost).
1324cdf0e10cSrcweir     if ( !nUserSubCount || !pChildDimension )
1325cdf0e10cSrcweir         nUserSubCount = 1;
1326cdf0e10cSrcweir 
1327cdf0e10cSrcweir     const ScDPLevel*	pParentLevel = GetParentLevel();
1328cdf0e10cSrcweir 
1329cdf0e10cSrcweir     for (long nUserPos=0; nUserPos<nUserSubCount; nUserPos++)   // including hidden "automatic"
1330cdf0e10cSrcweir     {
1331cdf0e10cSrcweir         // #i68338# if nUserSubCount is 1 (automatic only), don't set nRowSubTotalFunc
1332cdf0e10cSrcweir         if ( pChildDimension && nUserSubCount > 1 )
1333cdf0e10cSrcweir         {
1334cdf0e10cSrcweir             aSubState.nRowSubTotalFunc = nUserPos;
1335cdf0e10cSrcweir             aSubState.eRowForce = lcl_GetForceFunc( pParentLevel, nUserPos );
1336cdf0e10cSrcweir         }
1337cdf0e10cSrcweir 
1338cdf0e10cSrcweir         pDataRoot->ProcessData( aDataMembers, aValues, aSubState );
1339cdf0e10cSrcweir     }
1340cdf0e10cSrcweir }
1341cdf0e10cSrcweir 
1342cdf0e10cSrcweir /**
1343cdf0e10cSrcweir  * Parse subtotal string and replace all occurrences of '?' with the caption
1344cdf0e10cSrcweir  * string.  Do ensure that escaped characters are not translated.
1345cdf0e10cSrcweir  */
lcl_parseSubtotalName(const String & rSubStr,const String & rCaption)1346cdf0e10cSrcweir static String lcl_parseSubtotalName(const String& rSubStr, const String& rCaption)
1347cdf0e10cSrcweir {
1348cdf0e10cSrcweir     String aNewStr;
1349cdf0e10cSrcweir     xub_StrLen n = rSubStr.Len();
1350cdf0e10cSrcweir     bool bEscaped = false;
1351cdf0e10cSrcweir     for (xub_StrLen i = 0; i < n; ++i)
1352cdf0e10cSrcweir     {
1353cdf0e10cSrcweir         sal_Unicode c = rSubStr.GetChar(i);
1354cdf0e10cSrcweir         if (!bEscaped && c == sal_Unicode('\\'))
1355cdf0e10cSrcweir         {
1356cdf0e10cSrcweir             bEscaped = true;
1357cdf0e10cSrcweir             continue;
1358cdf0e10cSrcweir         }
1359cdf0e10cSrcweir 
1360cdf0e10cSrcweir         if (!bEscaped && c == sal_Unicode('?'))
1361cdf0e10cSrcweir             aNewStr.Append(rCaption);
1362cdf0e10cSrcweir         else
1363cdf0e10cSrcweir             aNewStr.Append(c);
1364cdf0e10cSrcweir         bEscaped = false;
1365cdf0e10cSrcweir     }
1366cdf0e10cSrcweir     return aNewStr;
1367cdf0e10cSrcweir }
1368cdf0e10cSrcweir 
FillMemberResults(uno::Sequence<sheet::MemberResult> * pSequences,long & rPos,long nMeasure,sal_Bool bRoot,const String * pMemberName,const String * pMemberCaption)1369cdf0e10cSrcweir void ScDPResultMember::FillMemberResults( uno::Sequence<sheet::MemberResult>* pSequences,
1370cdf0e10cSrcweir 											long& rPos, long nMeasure, sal_Bool bRoot,
1371cdf0e10cSrcweir 											const String* pMemberName,
1372cdf0e10cSrcweir 											const String* pMemberCaption )
1373cdf0e10cSrcweir {
1374cdf0e10cSrcweir 	//	IsVisible() test is in ScDPResultDimension::FillMemberResults
1375cdf0e10cSrcweir 	//	(not on data layout dimension)
1376cdf0e10cSrcweir 
1377cdf0e10cSrcweir 	long nSize = GetSize(nMeasure);
1378cdf0e10cSrcweir 	sheet::MemberResult* pArray = pSequences->getArray();
1379cdf0e10cSrcweir 	DBG_ASSERT( rPos+nSize <= pSequences->getLength(), "bumm" );
1380cdf0e10cSrcweir 
1381cdf0e10cSrcweir     sal_Bool bIsNumeric = sal_False;
1382cdf0e10cSrcweir 	String aName;
1383cdf0e10cSrcweir 	if ( pMemberName )			// if pMemberName != NULL, use instead of real member name
1384cdf0e10cSrcweir 		aName = *pMemberName;
1385cdf0e10cSrcweir 	else
1386cdf0e10cSrcweir 	{
1387cdf0e10cSrcweir         ScDPItemData aItemData;
1388cdf0e10cSrcweir         FillItemData( aItemData );
1389cdf0e10cSrcweir         aName = aItemData.GetString();
1390cdf0e10cSrcweir         bIsNumeric = aItemData.IsValue();
1391cdf0e10cSrcweir 	}
1392cdf0e10cSrcweir     const ScDPDimension*		pParentDim = GetParentDim();
1393cdf0e10cSrcweir     if ( bIsNumeric && pParentDim && pResultData->IsNumOrDateGroup( pParentDim->GetDimension() ) )
1394cdf0e10cSrcweir     {
1395cdf0e10cSrcweir         // Numeric group dimensions use numeric entries for proper sorting,
1396cdf0e10cSrcweir         // but the group titles must be output as text.
1397cdf0e10cSrcweir         bIsNumeric = sal_False;
1398cdf0e10cSrcweir     }
1399cdf0e10cSrcweir 
1400cdf0e10cSrcweir 	String aCaption = aName;
1401cdf0e10cSrcweir     const ScDPMember* pMemberDesc = GetDPMember();
1402cdf0e10cSrcweir     if (pMemberDesc)
1403cdf0e10cSrcweir     {
1404cdf0e10cSrcweir         const OUString* pLayoutName = pMemberDesc->GetLayoutName();
1405cdf0e10cSrcweir         if (pLayoutName)
1406cdf0e10cSrcweir         {
1407cdf0e10cSrcweir             aCaption = *pLayoutName;
1408cdf0e10cSrcweir             bIsNumeric = false; // layout name is always non-numeric.
1409cdf0e10cSrcweir         }
1410cdf0e10cSrcweir     }
1411cdf0e10cSrcweir 
1412cdf0e10cSrcweir 	if ( pMemberCaption )					// use pMemberCaption if != NULL
1413cdf0e10cSrcweir 		aCaption = *pMemberCaption;
1414cdf0e10cSrcweir 	if (!aCaption.Len())
1415cdf0e10cSrcweir 		aCaption = ScGlobal::GetRscString(STR_EMPTYDATA);
1416cdf0e10cSrcweir 
1417cdf0e10cSrcweir     if (bIsNumeric)
1418cdf0e10cSrcweir         pArray[rPos].Flags |= sheet::MemberResultFlags::NUMERIC;
1419cdf0e10cSrcweir     else
1420cdf0e10cSrcweir         pArray[rPos].Flags &= ~sheet::MemberResultFlags::NUMERIC;
1421cdf0e10cSrcweir 
1422cdf0e10cSrcweir 	if ( nSize && !bRoot )					// root is overwritten by first dimension
1423cdf0e10cSrcweir 	{
1424cdf0e10cSrcweir 		pArray[rPos].Name    = rtl::OUString(aName);
1425cdf0e10cSrcweir 		pArray[rPos].Caption = rtl::OUString(aCaption);
1426cdf0e10cSrcweir 		pArray[rPos].Flags	|= sheet::MemberResultFlags::HASMEMBER;
1427cdf0e10cSrcweir 
1428cdf0e10cSrcweir 		//	set "continue" flag (removed for subtotals later)
1429cdf0e10cSrcweir 		for (long i=1; i<nSize; i++)
1430cdf0e10cSrcweir 			pArray[rPos+i].Flags |= sheet::MemberResultFlags::CONTINUE;
1431cdf0e10cSrcweir 	}
1432cdf0e10cSrcweir 
1433cdf0e10cSrcweir     const ScDPLevel*	pParentLevel = GetParentLevel();
1434cdf0e10cSrcweir     long nExtraSpace = 0;
1435cdf0e10cSrcweir     if ( pParentLevel && pParentLevel->IsAddEmpty() )
1436cdf0e10cSrcweir         ++nExtraSpace;
1437cdf0e10cSrcweir 
1438cdf0e10cSrcweir     sal_Bool bTitleLine = sal_False;
1439cdf0e10cSrcweir     if ( pParentLevel && pParentLevel->IsOutlineLayout() )
1440cdf0e10cSrcweir         bTitleLine = sal_True;
1441cdf0e10cSrcweir 
1442cdf0e10cSrcweir     // if the subtotals are shown at the top (title row) in outline layout,
1443cdf0e10cSrcweir 	// no extra row for the subtotals is needed
1444cdf0e10cSrcweir     sal_Bool bSubTotalInTitle = IsSubTotalInTitle( nMeasure );
1445cdf0e10cSrcweir 
1446cdf0e10cSrcweir 	sal_Bool bHasChild = ( pChildDimension != NULL );
1447cdf0e10cSrcweir 	if (bHasChild)
1448cdf0e10cSrcweir 	{
1449cdf0e10cSrcweir         if ( bTitleLine )           // in tabular layout the title is on a separate row
1450cdf0e10cSrcweir             ++rPos;                 // -> fill child dimension one row below
1451cdf0e10cSrcweir 
1452cdf0e10cSrcweir 		if (bRoot)		// same sequence for root member
1453cdf0e10cSrcweir 			pChildDimension->FillMemberResults( pSequences, rPos, nMeasure );
1454cdf0e10cSrcweir 		else
1455cdf0e10cSrcweir 			//pChildDimension->FillMemberResults( pSequences + 1, rPos, nMeasure );
1456cdf0e10cSrcweir             pChildDimension->FillMemberResults( pSequences + nMemberStep/*1*/, rPos, nMeasure );
1457cdf0e10cSrcweir 
1458cdf0e10cSrcweir         if ( bTitleLine )           // title row is included in GetSize, so the following
1459cdf0e10cSrcweir             --rPos;                 // positions are calculated with the normal values
1460cdf0e10cSrcweir 	}
1461cdf0e10cSrcweir 
1462cdf0e10cSrcweir 	rPos += nSize;
1463cdf0e10cSrcweir 
1464cdf0e10cSrcweir     long nUserSubStart;
1465cdf0e10cSrcweir 	long nUserSubCount = GetSubTotalCount(&nUserSubStart);
1466cdf0e10cSrcweir 	if ( nUserSubCount && pChildDimension && !bSubTotalInTitle )
1467cdf0e10cSrcweir 	{
1468cdf0e10cSrcweir 		long nMemberMeasure = nMeasure;
1469cdf0e10cSrcweir 		long nSubSize = pResultData->GetCountForMeasure(nMeasure);
1470cdf0e10cSrcweir 
1471cdf0e10cSrcweir 		rPos -= nSubSize * (nUserSubCount - nUserSubStart);     // GetSize includes space for SubTotal
1472cdf0e10cSrcweir         rPos -= nExtraSpace;                                    // GetSize includes the empty line
1473cdf0e10cSrcweir 
1474cdf0e10cSrcweir 		for (long nUserPos=nUserSubStart; nUserPos<nUserSubCount; nUserPos++)
1475cdf0e10cSrcweir 		{
1476cdf0e10cSrcweir 			for ( long nSubCount=0; nSubCount<nSubSize; nSubCount++ )
1477cdf0e10cSrcweir 			{
1478cdf0e10cSrcweir 				if ( nMeasure == SC_DPMEASURE_ALL )
1479cdf0e10cSrcweir 					nMemberMeasure = nSubCount;
1480cdf0e10cSrcweir 
1481cdf0e10cSrcweir 				ScSubTotalFunc eForce = SUBTOTAL_FUNC_NONE;
1482cdf0e10cSrcweir 				if (bHasChild)
1483cdf0e10cSrcweir 					eForce = lcl_GetForceFunc( pParentLevel, nUserPos );
1484cdf0e10cSrcweir 
1485cdf0e10cSrcweir                 bool bTotalResult = false;
1486cdf0e10cSrcweir 				String aSubStr = aCaption;
1487cdf0e10cSrcweir 				aSubStr += ' ';
1488cdf0e10cSrcweir 				aSubStr += pResultData->GetMeasureString(nMemberMeasure, sal_False, eForce, bTotalResult);
1489cdf0e10cSrcweir 
1490cdf0e10cSrcweir                 if (bTotalResult)
1491cdf0e10cSrcweir                 {
1492cdf0e10cSrcweir                     if (pMemberDesc)
1493cdf0e10cSrcweir                     {
1494cdf0e10cSrcweir                         // single data field layout.
1495cdf0e10cSrcweir                         const OUString* pSubtotalName = pParentDim->GetSubtotalName();
1496cdf0e10cSrcweir                         if (pSubtotalName)
1497cdf0e10cSrcweir                             aSubStr = lcl_parseSubtotalName(*pSubtotalName, aCaption);
1498cdf0e10cSrcweir                         pArray[rPos].Flags &= ~sheet::MemberResultFlags::GRANDTOTAL;
1499cdf0e10cSrcweir                     }
1500cdf0e10cSrcweir                     else
1501cdf0e10cSrcweir                     {
1502cdf0e10cSrcweir                         // root member - subtotal (grand total?) for multi-data field layout.
1503cdf0e10cSrcweir                         const rtl::OUString* pGrandTotalName = pResultData->GetSource()->GetGrandTotalName();
1504cdf0e10cSrcweir                         if (pGrandTotalName)
1505cdf0e10cSrcweir                             aSubStr = *pGrandTotalName;
1506cdf0e10cSrcweir                         pArray[rPos].Flags |= sheet::MemberResultFlags::GRANDTOTAL;
1507cdf0e10cSrcweir                     }
1508cdf0e10cSrcweir                 }
1509cdf0e10cSrcweir 
1510cdf0e10cSrcweir 				pArray[rPos].Name    = rtl::OUString(aName);
1511cdf0e10cSrcweir 				pArray[rPos].Caption = rtl::OUString(aSubStr);
1512cdf0e10cSrcweir 				pArray[rPos].Flags = ( pArray[rPos].Flags |
1513cdf0e10cSrcweir 									( sheet::MemberResultFlags::HASMEMBER | sheet::MemberResultFlags::SUBTOTAL) ) &
1514cdf0e10cSrcweir 									~sheet::MemberResultFlags::CONTINUE;
1515cdf0e10cSrcweir 
1516cdf0e10cSrcweir 				if ( nMeasure == SC_DPMEASURE_ALL )
1517cdf0e10cSrcweir 				{
1518cdf0e10cSrcweir 					//	data layout dimension is (direct/indirect) child of this.
1519cdf0e10cSrcweir 					//	data layout dimension must have name for all entries.
1520cdf0e10cSrcweir 
1521cdf0e10cSrcweir 					uno::Sequence<sheet::MemberResult>* pLayoutSeq = pSequences;
1522cdf0e10cSrcweir 					if (!bRoot)
1523cdf0e10cSrcweir 						++pLayoutSeq;
1524cdf0e10cSrcweir 					ScDPResultDimension* pLayoutDim = pChildDimension;
1525cdf0e10cSrcweir 					while ( pLayoutDim && !pLayoutDim->IsDataLayout() )
1526cdf0e10cSrcweir 					{
1527cdf0e10cSrcweir 						pLayoutDim = pLayoutDim->GetFirstChildDimension();
1528cdf0e10cSrcweir 						++pLayoutSeq;
1529cdf0e10cSrcweir 					}
1530cdf0e10cSrcweir 					if ( pLayoutDim )
1531cdf0e10cSrcweir 					{
1532cdf0e10cSrcweir 						sheet::MemberResult* pLayoutArray = pLayoutSeq->getArray();
1533cdf0e10cSrcweir 						String aDataName = pResultData->GetMeasureDimensionName(nMemberMeasure);
1534cdf0e10cSrcweir 						pLayoutArray[rPos].Name = rtl::OUString(aDataName);
1535cdf0e10cSrcweir 					}
1536cdf0e10cSrcweir 				}
1537cdf0e10cSrcweir 
1538cdf0e10cSrcweir 				rPos += 1;
1539cdf0e10cSrcweir 			}
1540cdf0e10cSrcweir 		}
1541cdf0e10cSrcweir 
1542cdf0e10cSrcweir         rPos += nExtraSpace;                                    // add again (subtracted above)
1543cdf0e10cSrcweir 	}
1544cdf0e10cSrcweir }
1545cdf0e10cSrcweir 
FillDataResults(const ScDPResultMember * pRefMember,uno::Sequence<uno::Sequence<sheet::DataResult>> & rSequence,long & rRow,long nMeasure) const1546cdf0e10cSrcweir void ScDPResultMember::FillDataResults( const ScDPResultMember* pRefMember,
1547cdf0e10cSrcweir 							uno::Sequence< uno::Sequence<sheet::DataResult> >& rSequence,
1548cdf0e10cSrcweir 							long& rRow, long nMeasure ) const
1549cdf0e10cSrcweir {
1550cdf0e10cSrcweir 	//	IsVisible() test is in ScDPResultDimension::FillDataResults
1551cdf0e10cSrcweir 	//	(not on data layout dimension)
1552cdf0e10cSrcweir     const ScDPLevel*	 pParentLevel = GetParentLevel();
1553cdf0e10cSrcweir     long nStartRow = rRow;
1554cdf0e10cSrcweir 
1555cdf0e10cSrcweir     long nExtraSpace = 0;
1556cdf0e10cSrcweir     if ( pParentLevel && pParentLevel->IsAddEmpty() )
1557cdf0e10cSrcweir         ++nExtraSpace;
1558cdf0e10cSrcweir 
1559cdf0e10cSrcweir     sal_Bool bTitleLine = sal_False;
1560cdf0e10cSrcweir     if ( pParentLevel && pParentLevel->IsOutlineLayout() )
1561cdf0e10cSrcweir         bTitleLine = sal_True;
1562cdf0e10cSrcweir 
1563cdf0e10cSrcweir     sal_Bool bSubTotalInTitle = IsSubTotalInTitle( nMeasure );
1564cdf0e10cSrcweir 
1565cdf0e10cSrcweir 	sal_Bool bHasChild = ( pChildDimension != NULL );
1566cdf0e10cSrcweir 	if (bHasChild)
1567cdf0e10cSrcweir 	{
1568cdf0e10cSrcweir         if ( bTitleLine )           // in tabular layout the title is on a separate row
1569cdf0e10cSrcweir             ++rRow;                 // -> fill child dimension one row below
1570cdf0e10cSrcweir 
1571cdf0e10cSrcweir 		pChildDimension->FillDataResults( pRefMember, rSequence, rRow, nMeasure );  // doesn't modify rRow
1572cdf0e10cSrcweir 		rRow += GetSize( nMeasure );
1573cdf0e10cSrcweir 
1574cdf0e10cSrcweir         if ( bTitleLine )           // title row is included in GetSize, so the following
1575cdf0e10cSrcweir             --rRow;                 // positions are calculated with the normal values
1576cdf0e10cSrcweir 	}
1577cdf0e10cSrcweir 
1578cdf0e10cSrcweir     long nUserSubStart;
1579cdf0e10cSrcweir 	long nUserSubCount = GetSubTotalCount(&nUserSubStart);
1580cdf0e10cSrcweir 	if ( nUserSubCount || !bHasChild )
1581cdf0e10cSrcweir 	{
1582cdf0e10cSrcweir         // Calculate at least automatic if no subtotals are selected,
1583cdf0e10cSrcweir         // show only own values if there's no child dimension (innermost).
1584cdf0e10cSrcweir 		if ( !nUserSubCount || !bHasChild )
1585cdf0e10cSrcweir 		{
1586cdf0e10cSrcweir 			nUserSubCount = 1;
1587cdf0e10cSrcweir 			nUserSubStart = 0;
1588cdf0e10cSrcweir 		}
1589cdf0e10cSrcweir 
1590cdf0e10cSrcweir 		long nMemberMeasure = nMeasure;
1591cdf0e10cSrcweir 		long nSubSize = pResultData->GetCountForMeasure(nMeasure);
1592cdf0e10cSrcweir 		if (bHasChild)
1593cdf0e10cSrcweir         {
1594cdf0e10cSrcweir 			rRow -= nSubSize * ( nUserSubCount - nUserSubStart );   // GetSize includes space for SubTotal
1595cdf0e10cSrcweir             rRow -= nExtraSpace;                                    // GetSize includes the empty line
1596cdf0e10cSrcweir         }
1597cdf0e10cSrcweir 
1598cdf0e10cSrcweir         long nMoveSubTotal = 0;
1599cdf0e10cSrcweir         if ( bSubTotalInTitle )
1600cdf0e10cSrcweir         {
1601cdf0e10cSrcweir             nMoveSubTotal = rRow - nStartRow;   // force to first (title) row
1602cdf0e10cSrcweir             rRow = nStartRow;
1603cdf0e10cSrcweir         }
1604cdf0e10cSrcweir 
1605cdf0e10cSrcweir 		if ( pDataRoot )
1606cdf0e10cSrcweir 		{
1607cdf0e10cSrcweir 			ScDPSubTotalState aSubState;		// initial state
1608cdf0e10cSrcweir 
1609cdf0e10cSrcweir 			for (long nUserPos=nUserSubStart; nUserPos<nUserSubCount; nUserPos++)
1610cdf0e10cSrcweir 			{
1611cdf0e10cSrcweir 				if ( bHasChild && nUserSubCount > 1 )
1612cdf0e10cSrcweir 				{
1613cdf0e10cSrcweir 					aSubState.nRowSubTotalFunc = nUserPos;
1614cdf0e10cSrcweir 					aSubState.eRowForce = lcl_GetForceFunc( /*pParentLevel*/GetParentLevel() , nUserPos );
1615cdf0e10cSrcweir 				}
1616cdf0e10cSrcweir 
1617cdf0e10cSrcweir 				for ( long nSubCount=0; nSubCount<nSubSize; nSubCount++ )
1618cdf0e10cSrcweir 				{
1619cdf0e10cSrcweir 					if ( nMeasure == SC_DPMEASURE_ALL )
1620cdf0e10cSrcweir 						nMemberMeasure = nSubCount;
1621cdf0e10cSrcweir 					else if ( pResultData->GetColStartMeasure() == SC_DPMEASURE_ALL )
1622cdf0e10cSrcweir 						nMemberMeasure = SC_DPMEASURE_ALL;
1623cdf0e10cSrcweir 
1624cdf0e10cSrcweir 					DBG_ASSERT( rRow < rSequence.getLength(), "bumm" );
1625cdf0e10cSrcweir 					uno::Sequence<sheet::DataResult>& rSubSeq = rSequence.getArray()[rRow];
1626cdf0e10cSrcweir 					long nSeqCol = 0;
1627cdf0e10cSrcweir 					pDataRoot->FillDataRow( pRefMember, rSubSeq, nSeqCol, nMemberMeasure, bHasChild, aSubState );
1628cdf0e10cSrcweir 
1629cdf0e10cSrcweir 					rRow += 1;
1630cdf0e10cSrcweir 				}
1631cdf0e10cSrcweir 			}
1632cdf0e10cSrcweir 		}
1633cdf0e10cSrcweir 		else
1634cdf0e10cSrcweir 			rRow += nSubSize * ( nUserSubCount - nUserSubStart );   // empty rows occur when ShowEmpty is true
1635cdf0e10cSrcweir 
1636cdf0e10cSrcweir         // add extra space again if subtracted from GetSize above,
1637cdf0e10cSrcweir         // add to own size if no children
1638cdf0e10cSrcweir         rRow += nExtraSpace;
1639cdf0e10cSrcweir 
1640cdf0e10cSrcweir         rRow += nMoveSubTotal;
1641cdf0e10cSrcweir 	}
1642cdf0e10cSrcweir }
1643cdf0e10cSrcweir 
UpdateDataResults(const ScDPResultMember * pRefMember,long nMeasure) const1644cdf0e10cSrcweir void ScDPResultMember::UpdateDataResults( const ScDPResultMember* pRefMember, long nMeasure ) const
1645cdf0e10cSrcweir {
1646cdf0e10cSrcweir     //  IsVisible() test is in ScDPResultDimension::FillDataResults
1647cdf0e10cSrcweir     //  (not on data layout dimension)
1648cdf0e10cSrcweir 
1649cdf0e10cSrcweir     sal_Bool bHasChild = ( pChildDimension != NULL );
1650cdf0e10cSrcweir 
1651cdf0e10cSrcweir     long nUserSubCount = GetSubTotalCount();
1652cdf0e10cSrcweir     // process subtotals even if not shown
1653cdf0e10cSrcweir //  if ( nUserSubCount || !bHasChild )
1654cdf0e10cSrcweir     {
1655cdf0e10cSrcweir         // Calculate at least automatic if no subtotals are selected,
1656cdf0e10cSrcweir         // show only own values if there's no child dimension (innermost).
1657cdf0e10cSrcweir         if ( !nUserSubCount || !bHasChild )
1658cdf0e10cSrcweir             nUserSubCount = 1;
1659cdf0e10cSrcweir 
1660cdf0e10cSrcweir         long nMemberMeasure = nMeasure;
1661cdf0e10cSrcweir         long nSubSize = pResultData->GetCountForMeasure(nMeasure);
1662cdf0e10cSrcweir 
1663cdf0e10cSrcweir         if ( pDataRoot )
1664cdf0e10cSrcweir         {
1665cdf0e10cSrcweir             ScDPSubTotalState aSubState;        // initial state
1666cdf0e10cSrcweir 
1667cdf0e10cSrcweir             for (long nUserPos=0; nUserPos<nUserSubCount; nUserPos++)   // including hidden "automatic"
1668cdf0e10cSrcweir             {
1669cdf0e10cSrcweir                 if ( bHasChild && nUserSubCount > 1 )
1670cdf0e10cSrcweir                 {
1671cdf0e10cSrcweir                     aSubState.nRowSubTotalFunc = nUserPos;
1672cdf0e10cSrcweir                     aSubState.eRowForce = lcl_GetForceFunc( /*pParentLevel*/GetParentLevel() , nUserPos );
1673cdf0e10cSrcweir                 }
1674cdf0e10cSrcweir 
1675cdf0e10cSrcweir                 for ( long nSubCount=0; nSubCount<nSubSize; nSubCount++ )
1676cdf0e10cSrcweir                 {
1677cdf0e10cSrcweir                     if ( nMeasure == SC_DPMEASURE_ALL )
1678cdf0e10cSrcweir                         nMemberMeasure = nSubCount;
1679cdf0e10cSrcweir                     else if ( pResultData->GetColStartMeasure() == SC_DPMEASURE_ALL )
1680cdf0e10cSrcweir                         nMemberMeasure = SC_DPMEASURE_ALL;
1681cdf0e10cSrcweir 
1682cdf0e10cSrcweir                     pDataRoot->UpdateDataRow( pRefMember, nMemberMeasure, bHasChild, aSubState );
1683cdf0e10cSrcweir                 }
1684cdf0e10cSrcweir             }
1685cdf0e10cSrcweir         }
1686cdf0e10cSrcweir     }
1687cdf0e10cSrcweir 
1688cdf0e10cSrcweir     if (bHasChild)  // child dimension must be processed last, so the column total is known
1689cdf0e10cSrcweir     {
1690cdf0e10cSrcweir         pChildDimension->UpdateDataResults( pRefMember, nMeasure );
1691cdf0e10cSrcweir     }
1692cdf0e10cSrcweir }
1693cdf0e10cSrcweir 
SortMembers(ScDPResultMember * pRefMember)1694cdf0e10cSrcweir void ScDPResultMember::SortMembers( ScDPResultMember* pRefMember )
1695cdf0e10cSrcweir {
1696cdf0e10cSrcweir     sal_Bool bHasChild = ( pChildDimension != NULL );
1697cdf0e10cSrcweir     if (bHasChild)
1698cdf0e10cSrcweir         pChildDimension->SortMembers( pRefMember );     // sorting is done at the dimension
1699cdf0e10cSrcweir 
1700cdf0e10cSrcweir     if ( IsRoot() && pDataRoot )
1701cdf0e10cSrcweir     {
1702cdf0e10cSrcweir         // use the row root member to sort columns
1703cdf0e10cSrcweir         // sub total count is always 1
1704cdf0e10cSrcweir 
1705cdf0e10cSrcweir         pDataRoot->SortMembers( pRefMember );
1706cdf0e10cSrcweir     }
1707cdf0e10cSrcweir }
1708cdf0e10cSrcweir 
DoAutoShow(ScDPResultMember * pRefMember)1709cdf0e10cSrcweir void ScDPResultMember::DoAutoShow( ScDPResultMember* pRefMember )
1710cdf0e10cSrcweir {
1711cdf0e10cSrcweir     sal_Bool bHasChild = ( pChildDimension != NULL );
1712cdf0e10cSrcweir     if (bHasChild)
1713cdf0e10cSrcweir         pChildDimension->DoAutoShow( pRefMember );     // sorting is done at the dimension
1714cdf0e10cSrcweir 
1715cdf0e10cSrcweir     if ( IsRoot()&& pDataRoot )
1716cdf0e10cSrcweir     {
1717cdf0e10cSrcweir         // use the row root member to sort columns
1718cdf0e10cSrcweir         // sub total count is always 1
1719cdf0e10cSrcweir 
1720cdf0e10cSrcweir         pDataRoot->DoAutoShow( pRefMember );
1721cdf0e10cSrcweir     }
1722cdf0e10cSrcweir }
1723cdf0e10cSrcweir 
ResetResults(sal_Bool)1724cdf0e10cSrcweir void ScDPResultMember::ResetResults( sal_Bool /*bRoot*/ )
1725cdf0e10cSrcweir {
1726cdf0e10cSrcweir     if (pDataRoot)
1727cdf0e10cSrcweir         pDataRoot->ResetResults();
1728cdf0e10cSrcweir 
1729cdf0e10cSrcweir     if (pChildDimension)
1730cdf0e10cSrcweir         pChildDimension->ResetResults();
1731cdf0e10cSrcweir 
1732cdf0e10cSrcweir  //   if (!bRoot)
1733cdf0e10cSrcweir  //       bHasElements = sal_False;
1734cdf0e10cSrcweir }
1735cdf0e10cSrcweir 
UpdateRunningTotals(const ScDPResultMember * pRefMember,long nMeasure,ScDPRunningTotalState & rRunning,ScDPRowTotals & rTotals) const1736cdf0e10cSrcweir void ScDPResultMember::UpdateRunningTotals( const ScDPResultMember* pRefMember, long nMeasure,
1737cdf0e10cSrcweir                                             ScDPRunningTotalState& rRunning, ScDPRowTotals& rTotals ) const
1738cdf0e10cSrcweir {
1739cdf0e10cSrcweir     //  IsVisible() test is in ScDPResultDimension::FillDataResults
1740cdf0e10cSrcweir     //  (not on data layout dimension)
1741cdf0e10cSrcweir 
1742cdf0e10cSrcweir     rTotals.SetInColRoot( IsRoot() );
1743cdf0e10cSrcweir 
1744cdf0e10cSrcweir     sal_Bool bHasChild = ( pChildDimension != NULL );
1745cdf0e10cSrcweir 
1746cdf0e10cSrcweir     long nUserSubCount = GetSubTotalCount();
1747cdf0e10cSrcweir 	//if ( nUserSubCount || !bHasChild )
1748cdf0e10cSrcweir     {
1749cdf0e10cSrcweir         // Calculate at least automatic if no subtotals are selected,
1750cdf0e10cSrcweir         // show only own values if there's no child dimension (innermost).
1751cdf0e10cSrcweir         if ( !nUserSubCount || !bHasChild )
1752cdf0e10cSrcweir             nUserSubCount = 1;
1753cdf0e10cSrcweir 
1754cdf0e10cSrcweir         long nMemberMeasure = nMeasure;
1755cdf0e10cSrcweir         long nSubSize = pResultData->GetCountForMeasure(nMeasure);
1756cdf0e10cSrcweir 
1757cdf0e10cSrcweir         if ( pDataRoot )
1758cdf0e10cSrcweir         {
1759cdf0e10cSrcweir             ScDPSubTotalState aSubState;        // initial state
1760cdf0e10cSrcweir 
1761cdf0e10cSrcweir             for (long nUserPos=0; nUserPos<nUserSubCount; nUserPos++)   // including hidden "automatic"
1762cdf0e10cSrcweir             {
1763cdf0e10cSrcweir                 if ( bHasChild && nUserSubCount > 1 )
1764cdf0e10cSrcweir                 {
1765cdf0e10cSrcweir                     aSubState.nRowSubTotalFunc = nUserPos;
1766cdf0e10cSrcweir                     aSubState.eRowForce = lcl_GetForceFunc( /*pParentLevel*/GetParentLevel(), nUserPos );
1767cdf0e10cSrcweir                 }
1768cdf0e10cSrcweir 
1769cdf0e10cSrcweir                 for ( long nSubCount=0; nSubCount<nSubSize; nSubCount++ )
1770cdf0e10cSrcweir                 {
1771cdf0e10cSrcweir                     if ( nMeasure == SC_DPMEASURE_ALL )
1772cdf0e10cSrcweir                         nMemberMeasure = nSubCount;
1773cdf0e10cSrcweir                     else if ( pResultData->GetColStartMeasure() == SC_DPMEASURE_ALL )
1774cdf0e10cSrcweir                         nMemberMeasure = SC_DPMEASURE_ALL;
1775cdf0e10cSrcweir 
1776cdf0e10cSrcweir                     pDataRoot->UpdateRunningTotals( pRefMember, nMemberMeasure,
1777cdf0e10cSrcweir                                         bHasChild, aSubState, rRunning, rTotals, *this );
1778cdf0e10cSrcweir                 }
1779cdf0e10cSrcweir             }
1780cdf0e10cSrcweir         }
1781cdf0e10cSrcweir     }
1782cdf0e10cSrcweir 
1783cdf0e10cSrcweir     if (bHasChild)  // child dimension must be processed last, so the column total is known
1784cdf0e10cSrcweir     {
1785cdf0e10cSrcweir         pChildDimension->UpdateRunningTotals( pRefMember, nMeasure, rRunning, rTotals );
1786cdf0e10cSrcweir     }
1787cdf0e10cSrcweir }
1788cdf0e10cSrcweir 
DumpState(const ScDPResultMember * pRefMember,ScDocument * pDoc,ScAddress & rPos) const1789cdf0e10cSrcweir void ScDPResultMember::DumpState( const ScDPResultMember* pRefMember, ScDocument* pDoc, ScAddress& rPos ) const
1790cdf0e10cSrcweir {
1791cdf0e10cSrcweir     lcl_DumpRow( String::CreateFromAscii("ScDPResultMember"), GetName(), NULL, pDoc, rPos );
1792cdf0e10cSrcweir     SCROW nStartRow = rPos.Row();
1793cdf0e10cSrcweir 
1794cdf0e10cSrcweir     if (pDataRoot)
1795cdf0e10cSrcweir         pDataRoot->DumpState( pRefMember, pDoc, rPos );
1796cdf0e10cSrcweir 
1797cdf0e10cSrcweir     if (pChildDimension)
1798cdf0e10cSrcweir         pChildDimension->DumpState( pRefMember, pDoc, rPos );
1799cdf0e10cSrcweir 
1800cdf0e10cSrcweir     lcl_Indent( pDoc, nStartRow, rPos );
1801cdf0e10cSrcweir }
1802cdf0e10cSrcweir 
GetColTotal(long nMeasure) const1803cdf0e10cSrcweir ScDPAggData* ScDPResultMember::GetColTotal( long nMeasure ) const
1804cdf0e10cSrcweir {
1805cdf0e10cSrcweir     return lcl_GetChildTotal( const_cast<ScDPAggData*>(&aColTotal), nMeasure );
1806cdf0e10cSrcweir }
1807cdf0e10cSrcweir 
FillVisibilityData(ScDPResultVisibilityData & rData) const1808cdf0e10cSrcweir void ScDPResultMember::FillVisibilityData(ScDPResultVisibilityData& rData) const
1809cdf0e10cSrcweir {
1810cdf0e10cSrcweir     if (pChildDimension)
1811cdf0e10cSrcweir         pChildDimension->FillVisibilityData(rData);
1812cdf0e10cSrcweir }
1813cdf0e10cSrcweir 
1814cdf0e10cSrcweir // -----------------------------------------------------------------------
1815cdf0e10cSrcweir 
ScDPDataMember(const ScDPResultData * pData,const ScDPResultMember * pRes)1816cdf0e10cSrcweir ScDPDataMember::ScDPDataMember( const ScDPResultData* pData, const ScDPResultMember* pRes ) :
1817cdf0e10cSrcweir 	pResultData( pData ),
1818cdf0e10cSrcweir 	pResultMember( pRes ),
1819cdf0e10cSrcweir 	pChildDimension( NULL )
1820cdf0e10cSrcweir {
1821cdf0e10cSrcweir 	// pResultMember is 0 for root members
1822cdf0e10cSrcweir }
1823cdf0e10cSrcweir 
~ScDPDataMember()1824cdf0e10cSrcweir ScDPDataMember::~ScDPDataMember()
1825cdf0e10cSrcweir {
1826cdf0e10cSrcweir 	delete pChildDimension;
1827cdf0e10cSrcweir }
1828cdf0e10cSrcweir 
GetName() const1829cdf0e10cSrcweir String ScDPDataMember::GetName() const
1830cdf0e10cSrcweir {
1831cdf0e10cSrcweir 	if (pResultMember)
1832cdf0e10cSrcweir 		return pResultMember->GetName();
1833cdf0e10cSrcweir 	else
1834cdf0e10cSrcweir 		return EMPTY_STRING;
1835cdf0e10cSrcweir }
1836cdf0e10cSrcweir 
IsVisible() const1837cdf0e10cSrcweir sal_Bool ScDPDataMember::IsVisible() const
1838cdf0e10cSrcweir {
1839cdf0e10cSrcweir 	if (pResultMember)
1840cdf0e10cSrcweir 		return pResultMember->IsVisible();
1841cdf0e10cSrcweir 	else
1842cdf0e10cSrcweir 		return sal_False;
1843cdf0e10cSrcweir }
1844cdf0e10cSrcweir 
IsNamedItem(SCROW r) const1845cdf0e10cSrcweir sal_Bool ScDPDataMember::IsNamedItem( /*const ScDPItemData& r*/SCROW r ) const
1846cdf0e10cSrcweir {
1847cdf0e10cSrcweir 	if (pResultMember)
1848cdf0e10cSrcweir 		return pResultMember->IsNamedItem(r);
1849cdf0e10cSrcweir 	else
1850cdf0e10cSrcweir 		return sal_False;
1851cdf0e10cSrcweir }
1852cdf0e10cSrcweir 
HasHiddenDetails() const1853cdf0e10cSrcweir sal_Bool ScDPDataMember::HasHiddenDetails() const
1854cdf0e10cSrcweir {
1855cdf0e10cSrcweir 	if (pResultMember)
1856cdf0e10cSrcweir 		return pResultMember->HasHiddenDetails();
1857cdf0e10cSrcweir 	else
1858cdf0e10cSrcweir 		return sal_False;
1859cdf0e10cSrcweir }
1860cdf0e10cSrcweir 
InitFrom(const ScDPResultDimension * pDim)1861cdf0e10cSrcweir void ScDPDataMember::InitFrom( const ScDPResultDimension* pDim )
1862cdf0e10cSrcweir {
1863cdf0e10cSrcweir 	if ( !pChildDimension )
1864cdf0e10cSrcweir 		pChildDimension = new ScDPDataDimension(pResultData);
1865cdf0e10cSrcweir 	pChildDimension->InitFrom(pDim);
1866cdf0e10cSrcweir }
1867cdf0e10cSrcweir 
1868cdf0e10cSrcweir const long SC_SUBTOTALPOS_AUTO = -1;    // default
1869cdf0e10cSrcweir const long SC_SUBTOTALPOS_SKIP = -2;    // don't use
1870cdf0e10cSrcweir 
lcl_GetSubTotalPos(const ScDPSubTotalState & rSubState)1871cdf0e10cSrcweir long lcl_GetSubTotalPos( const ScDPSubTotalState& rSubState )
1872cdf0e10cSrcweir {
1873cdf0e10cSrcweir     if ( rSubState.nColSubTotalFunc >= 0 && rSubState.nRowSubTotalFunc >= 0 &&
1874cdf0e10cSrcweir          rSubState.nColSubTotalFunc != rSubState.nRowSubTotalFunc )
1875cdf0e10cSrcweir     {
1876cdf0e10cSrcweir         // #i68338# don't return the same index for different combinations (leading to repeated updates),
1877cdf0e10cSrcweir         // return a "don't use" value instead
1878cdf0e10cSrcweir 
1879cdf0e10cSrcweir         return SC_SUBTOTALPOS_SKIP;
1880cdf0e10cSrcweir     }
1881cdf0e10cSrcweir 
1882cdf0e10cSrcweir 	long nRet = SC_SUBTOTALPOS_AUTO;
1883cdf0e10cSrcweir 	if ( rSubState.nColSubTotalFunc >= 0 ) nRet = rSubState.nColSubTotalFunc;
1884cdf0e10cSrcweir 	if ( rSubState.nRowSubTotalFunc >= 0 ) nRet = rSubState.nRowSubTotalFunc;
1885cdf0e10cSrcweir 	return nRet;
1886cdf0e10cSrcweir }
1887cdf0e10cSrcweir 
UpdateValues(const vector<ScDPValueData> & aValues,const ScDPSubTotalState & rSubState)1888cdf0e10cSrcweir void ScDPDataMember::UpdateValues( const vector<ScDPValueData>& aValues, const ScDPSubTotalState& rSubState )
1889cdf0e10cSrcweir {
1890cdf0e10cSrcweir     //!	find out how many and which subtotals are used
1891cdf0e10cSrcweir 
1892cdf0e10cSrcweir     ScDPAggData* pAgg = &aAggregate;
1893cdf0e10cSrcweir 
1894cdf0e10cSrcweir     long nSubPos = lcl_GetSubTotalPos(rSubState);
1895cdf0e10cSrcweir     if (nSubPos == SC_SUBTOTALPOS_SKIP)
1896cdf0e10cSrcweir         return;
1897cdf0e10cSrcweir     if (nSubPos > 0)
1898cdf0e10cSrcweir     {
1899cdf0e10cSrcweir         long nSkip = nSubPos * pResultData->GetMeasureCount();
1900cdf0e10cSrcweir         for (long i=0; i<nSkip; i++)
1901cdf0e10cSrcweir             pAgg = pAgg->GetChild();        // created if not there
1902cdf0e10cSrcweir     }
1903cdf0e10cSrcweir 
1904cdf0e10cSrcweir     size_t nCount = aValues.size();
1905cdf0e10cSrcweir     for (size_t nPos = 0; nPos < nCount; ++nPos)
1906cdf0e10cSrcweir     {
1907cdf0e10cSrcweir         pAgg->Update(aValues[nPos], pResultData->GetMeasureFunction(nPos), rSubState);
1908cdf0e10cSrcweir         pAgg = pAgg->GetChild();
1909cdf0e10cSrcweir     }
1910cdf0e10cSrcweir }
1911cdf0e10cSrcweir 
ProcessData(const vector<SCROW> & aChildMembers,const vector<ScDPValueData> & aValues,const ScDPSubTotalState & rSubState)1912cdf0e10cSrcweir void ScDPDataMember::ProcessData( const vector< SCROW >& aChildMembers, const vector<ScDPValueData>& aValues,
1913cdf0e10cSrcweir 									const ScDPSubTotalState& rSubState )
1914cdf0e10cSrcweir {
1915cdf0e10cSrcweir 	if ( pResultData->IsLateInit() && !pChildDimension && pResultMember && pResultMember->GetChildDimension() )
1916cdf0e10cSrcweir 	{
1917cdf0e10cSrcweir 		//	if this DataMember doesn't have a child dimension because the ResultMember's
1918cdf0e10cSrcweir 		//	child dimension wasn't there yet during this DataMembers's creation,
1919cdf0e10cSrcweir 		//	create the child dimension now
1920cdf0e10cSrcweir 		InitFrom( pResultMember->GetChildDimension() );
1921cdf0e10cSrcweir 	}
1922cdf0e10cSrcweir 
1923cdf0e10cSrcweir 	ScDPSubTotalState aLocalSubState(rSubState);		// keep row state, modify column
1924cdf0e10cSrcweir 
1925cdf0e10cSrcweir 	long nUserSubCount = pResultMember ? pResultMember->GetSubTotalCount() : 0;
1926cdf0e10cSrcweir 
1927cdf0e10cSrcweir     // Calculate at least automatic if no subtotals are selected,
1928cdf0e10cSrcweir     // show only own values if there's no child dimension (innermost).
1929cdf0e10cSrcweir 	if ( !nUserSubCount || !pChildDimension )
1930cdf0e10cSrcweir 		nUserSubCount = 1;
1931cdf0e10cSrcweir 
1932cdf0e10cSrcweir 	for (long nUserPos=0; nUserPos<nUserSubCount; nUserPos++)   // including hidden "automatic"
1933cdf0e10cSrcweir 	{
1934cdf0e10cSrcweir 		if ( pChildDimension && nUserSubCount > 1 )
1935cdf0e10cSrcweir 		{
1936cdf0e10cSrcweir 			const ScDPLevel* pForceLevel = pResultMember ? pResultMember->GetParentLevel() : NULL;
1937cdf0e10cSrcweir 			aLocalSubState.nColSubTotalFunc = nUserPos;
1938cdf0e10cSrcweir 			aLocalSubState.eColForce = lcl_GetForceFunc( pForceLevel, nUserPos );
1939cdf0e10cSrcweir 		}
1940cdf0e10cSrcweir 
1941cdf0e10cSrcweir 		UpdateValues( aValues, aLocalSubState );
1942cdf0e10cSrcweir 	}
1943cdf0e10cSrcweir 
1944cdf0e10cSrcweir 	if (pChildDimension)
1945cdf0e10cSrcweir 		pChildDimension->ProcessData( aChildMembers, aValues, rSubState );		// with unmodified subtotal state
1946cdf0e10cSrcweir }
1947cdf0e10cSrcweir 
HasData(long nMeasure,const ScDPSubTotalState & rSubState) const1948cdf0e10cSrcweir sal_Bool ScDPDataMember::HasData( long nMeasure, const ScDPSubTotalState& rSubState ) const
1949cdf0e10cSrcweir {
1950cdf0e10cSrcweir 	if ( rSubState.eColForce != SUBTOTAL_FUNC_NONE && rSubState.eRowForce != SUBTOTAL_FUNC_NONE &&
1951cdf0e10cSrcweir 														rSubState.eColForce != rSubState.eRowForce )
1952cdf0e10cSrcweir 		return sal_False;
1953cdf0e10cSrcweir 
1954cdf0e10cSrcweir 	//	#74542# HasData can be different between measures!
1955cdf0e10cSrcweir 
1956cdf0e10cSrcweir 	const ScDPAggData* pAgg = GetConstAggData( nMeasure, rSubState );
1957cdf0e10cSrcweir 	if (!pAgg)
1958cdf0e10cSrcweir 		return sal_False;			//! error?
1959cdf0e10cSrcweir 
1960cdf0e10cSrcweir 	return pAgg->HasData();
1961cdf0e10cSrcweir }
1962cdf0e10cSrcweir 
HasError(long nMeasure,const ScDPSubTotalState & rSubState) const1963cdf0e10cSrcweir sal_Bool ScDPDataMember::HasError( long nMeasure, const ScDPSubTotalState& rSubState ) const
1964cdf0e10cSrcweir {
1965cdf0e10cSrcweir 	const ScDPAggData* pAgg = GetConstAggData( nMeasure, rSubState );
1966cdf0e10cSrcweir 	if (!pAgg)
1967cdf0e10cSrcweir 		return sal_True;
1968cdf0e10cSrcweir 
1969cdf0e10cSrcweir 	return pAgg->HasError();
1970cdf0e10cSrcweir }
1971cdf0e10cSrcweir 
GetAggregate(long nMeasure,const ScDPSubTotalState & rSubState) const1972cdf0e10cSrcweir double ScDPDataMember::GetAggregate( long nMeasure, const ScDPSubTotalState& rSubState ) const
1973cdf0e10cSrcweir {
1974cdf0e10cSrcweir 	const ScDPAggData* pAgg = GetConstAggData( nMeasure, rSubState );
1975cdf0e10cSrcweir 	if (!pAgg)
1976cdf0e10cSrcweir 		return DBL_MAX;			//! error?
1977cdf0e10cSrcweir 
1978cdf0e10cSrcweir 	return pAgg->GetResult();
1979cdf0e10cSrcweir }
1980cdf0e10cSrcweir 
GetAggData(long nMeasure,const ScDPSubTotalState & rSubState)1981cdf0e10cSrcweir ScDPAggData* ScDPDataMember::GetAggData( long nMeasure, const ScDPSubTotalState& rSubState )
1982cdf0e10cSrcweir {
1983cdf0e10cSrcweir     DBG_ASSERT( nMeasure >= 0, "GetAggData: no measure" );
1984cdf0e10cSrcweir 
1985cdf0e10cSrcweir     ScDPAggData* pAgg = &aAggregate;
1986cdf0e10cSrcweir     long nSkip = nMeasure;
1987cdf0e10cSrcweir     long nSubPos = lcl_GetSubTotalPos(rSubState);
1988cdf0e10cSrcweir     if (nSubPos == SC_SUBTOTALPOS_SKIP)
1989cdf0e10cSrcweir         return NULL;
1990cdf0e10cSrcweir     if (nSubPos > 0)
1991cdf0e10cSrcweir         nSkip += nSubPos * pResultData->GetMeasureCount();
1992cdf0e10cSrcweir 
1993cdf0e10cSrcweir     for ( long nPos=0; nPos<nSkip; nPos++ )
1994cdf0e10cSrcweir         pAgg = pAgg->GetChild();        //! need to create children here?
1995cdf0e10cSrcweir 
1996cdf0e10cSrcweir     return pAgg;
1997cdf0e10cSrcweir }
1998cdf0e10cSrcweir 
GetConstAggData(long nMeasure,const ScDPSubTotalState & rSubState) const1999cdf0e10cSrcweir const ScDPAggData* ScDPDataMember::GetConstAggData( long nMeasure, const ScDPSubTotalState& rSubState ) const
2000cdf0e10cSrcweir {
2001cdf0e10cSrcweir     DBG_ASSERT( nMeasure >= 0, "GetConstAggData: no measure" );
2002cdf0e10cSrcweir 
2003cdf0e10cSrcweir     const ScDPAggData* pAgg = &aAggregate;
2004cdf0e10cSrcweir     long nSkip = nMeasure;
2005cdf0e10cSrcweir     long nSubPos = lcl_GetSubTotalPos(rSubState);
2006cdf0e10cSrcweir     if (nSubPos == SC_SUBTOTALPOS_SKIP)
2007cdf0e10cSrcweir         return NULL;
2008cdf0e10cSrcweir     if (nSubPos > 0)
2009cdf0e10cSrcweir         nSkip += nSubPos * pResultData->GetMeasureCount();
2010cdf0e10cSrcweir 
2011cdf0e10cSrcweir     for ( long nPos=0; nPos<nSkip; nPos++ )
2012cdf0e10cSrcweir     {
2013cdf0e10cSrcweir         pAgg = pAgg->GetExistingChild();
2014cdf0e10cSrcweir         if (!pAgg)
2015cdf0e10cSrcweir             return NULL;
2016cdf0e10cSrcweir     }
2017cdf0e10cSrcweir 
2018cdf0e10cSrcweir     return pAgg;
2019cdf0e10cSrcweir }
2020cdf0e10cSrcweir 
FillDataRow(const ScDPResultMember * pRefMember,uno::Sequence<sheet::DataResult> & rSequence,long & rCol,long nMeasure,sal_Bool bIsSubTotalRow,const ScDPSubTotalState & rSubState) const2021cdf0e10cSrcweir void ScDPDataMember::FillDataRow( const ScDPResultMember* pRefMember,
2022cdf0e10cSrcweir 									uno::Sequence<sheet::DataResult>& rSequence,
2023cdf0e10cSrcweir 									long& rCol, long nMeasure, sal_Bool bIsSubTotalRow,
2024cdf0e10cSrcweir 									const ScDPSubTotalState& rSubState ) const
2025cdf0e10cSrcweir {
2026cdf0e10cSrcweir 	DBG_ASSERT( pRefMember == pResultMember || !pResultMember, "bla" );
2027cdf0e10cSrcweir 
2028cdf0e10cSrcweir 	if ( pRefMember->IsVisible() )	//! here or in ScDPDataDimension::FillDataRow ???
2029cdf0e10cSrcweir 	{
2030cdf0e10cSrcweir         long nStartCol = rCol;
2031cdf0e10cSrcweir 
2032cdf0e10cSrcweir 		const ScDPDataDimension* pDataChild = GetChildDimension();
2033cdf0e10cSrcweir 		const ScDPResultDimension* pRefChild = pRefMember->GetChildDimension();
2034cdf0e10cSrcweir 
2035cdf0e10cSrcweir         const ScDPLevel* pRefParentLevel = const_cast<ScDPResultMember*>(pRefMember)->GetParentLevel();
2036cdf0e10cSrcweir 
2037cdf0e10cSrcweir         long nExtraSpace = 0;
2038cdf0e10cSrcweir         if ( pRefParentLevel && pRefParentLevel->IsAddEmpty() )
2039cdf0e10cSrcweir             ++nExtraSpace;
2040cdf0e10cSrcweir 
2041cdf0e10cSrcweir         sal_Bool bTitleLine = sal_False;
2042cdf0e10cSrcweir         if ( pRefParentLevel && pRefParentLevel->IsOutlineLayout() )
2043cdf0e10cSrcweir             bTitleLine = sal_True;
2044cdf0e10cSrcweir 
2045cdf0e10cSrcweir         sal_Bool bSubTotalInTitle = pRefMember->IsSubTotalInTitle( nMeasure );
2046cdf0e10cSrcweir 
2047cdf0e10cSrcweir 		//	leave space for children even if the DataMember hasn't been initialized
2048cdf0e10cSrcweir 		//	(pDataChild is null then, this happens when no values for it are in this row)
2049cdf0e10cSrcweir 		sal_Bool bHasChild = ( pRefChild != NULL );
2050cdf0e10cSrcweir 
2051cdf0e10cSrcweir 		if ( bHasChild )
2052cdf0e10cSrcweir 		{
2053cdf0e10cSrcweir             if ( bTitleLine )           // in tabular layout the title is on a separate column
2054cdf0e10cSrcweir                 ++rCol;                 // -> fill child dimension one column below
2055cdf0e10cSrcweir 
2056cdf0e10cSrcweir 			if ( pDataChild )
2057cdf0e10cSrcweir 				pDataChild->FillDataRow( pRefChild, rSequence, rCol, nMeasure, bIsSubTotalRow, rSubState );
2058cdf0e10cSrcweir 			rCol += (sal_uInt16)pRefMember->GetSize( nMeasure );
2059cdf0e10cSrcweir 
2060cdf0e10cSrcweir             if ( bTitleLine )           // title column is included in GetSize, so the following
2061cdf0e10cSrcweir                 --rCol;                 // positions are calculated with the normal values
2062cdf0e10cSrcweir 		}
2063cdf0e10cSrcweir 
2064cdf0e10cSrcweir         long nUserSubStart;
2065cdf0e10cSrcweir 		long nUserSubCount = pRefMember->GetSubTotalCount(&nUserSubStart);
2066cdf0e10cSrcweir 		if ( nUserSubCount || !bHasChild )
2067cdf0e10cSrcweir 		{
2068cdf0e10cSrcweir             // Calculate at least automatic if no subtotals are selected,
2069cdf0e10cSrcweir             // show only own values if there's no child dimension (innermost).
2070cdf0e10cSrcweir 			if ( !nUserSubCount || !bHasChild )
2071cdf0e10cSrcweir 			{
2072cdf0e10cSrcweir 				nUserSubCount = 1;
2073cdf0e10cSrcweir 				nUserSubStart = 0;
2074cdf0e10cSrcweir 			}
2075cdf0e10cSrcweir 
2076cdf0e10cSrcweir 			ScDPSubTotalState aLocalSubState(rSubState);		// keep row state, modify column
2077cdf0e10cSrcweir 
2078cdf0e10cSrcweir 			long nMemberMeasure = nMeasure;
2079cdf0e10cSrcweir 			long nSubSize = pResultData->GetCountForMeasure(nMeasure);
2080cdf0e10cSrcweir 			if (bHasChild)
2081cdf0e10cSrcweir             {
2082cdf0e10cSrcweir 				rCol -= nSubSize * ( nUserSubCount - nUserSubStart );   // GetSize includes space for SubTotal
2083cdf0e10cSrcweir                 rCol -= nExtraSpace;                                    // GetSize includes the empty line
2084cdf0e10cSrcweir             }
2085cdf0e10cSrcweir 
2086cdf0e10cSrcweir             long nMoveSubTotal = 0;
2087cdf0e10cSrcweir             if ( bSubTotalInTitle )
2088cdf0e10cSrcweir             {
2089cdf0e10cSrcweir                 nMoveSubTotal = rCol - nStartCol;   // force to first (title) column
2090cdf0e10cSrcweir                 rCol = nStartCol;
2091cdf0e10cSrcweir             }
2092cdf0e10cSrcweir 
2093cdf0e10cSrcweir 			for (long nUserPos=nUserSubStart; nUserPos<nUserSubCount; nUserPos++)
2094cdf0e10cSrcweir 			{
2095cdf0e10cSrcweir 				if ( pChildDimension && nUserSubCount > 1 )
2096cdf0e10cSrcweir 				{
2097cdf0e10cSrcweir 					const ScDPLevel* pForceLevel = pResultMember ? pResultMember->GetParentLevel() : NULL;
2098cdf0e10cSrcweir 					aLocalSubState.nColSubTotalFunc = nUserPos;
2099cdf0e10cSrcweir 					aLocalSubState.eColForce = lcl_GetForceFunc( pForceLevel, nUserPos );
2100cdf0e10cSrcweir 				}
2101cdf0e10cSrcweir 
2102cdf0e10cSrcweir 				for ( long nSubCount=0; nSubCount<nSubSize; nSubCount++ )
2103cdf0e10cSrcweir 				{
2104cdf0e10cSrcweir 					if ( nMeasure == SC_DPMEASURE_ALL )
2105cdf0e10cSrcweir 						nMemberMeasure = nSubCount;
2106cdf0e10cSrcweir 
2107cdf0e10cSrcweir 					DBG_ASSERT( rCol < rSequence.getLength(), "bumm" );
2108cdf0e10cSrcweir 					sheet::DataResult& rRes = rSequence.getArray()[rCol];
2109cdf0e10cSrcweir 
2110cdf0e10cSrcweir 					if ( HasData( nMemberMeasure, aLocalSubState ) )
2111cdf0e10cSrcweir 					{
2112cdf0e10cSrcweir 						if ( HasError( nMemberMeasure, aLocalSubState ) )
2113cdf0e10cSrcweir 						{
2114cdf0e10cSrcweir 							rRes.Value = 0;
2115cdf0e10cSrcweir 							rRes.Flags |= sheet::DataResultFlags::ERROR;
2116cdf0e10cSrcweir 						}
2117cdf0e10cSrcweir 						else
2118cdf0e10cSrcweir 						{
2119cdf0e10cSrcweir 							rRes.Value = GetAggregate( nMemberMeasure, aLocalSubState );
2120cdf0e10cSrcweir 							rRes.Flags |= sheet::DataResultFlags::HASDATA;
2121cdf0e10cSrcweir 						}
2122cdf0e10cSrcweir 					}
2123cdf0e10cSrcweir 
2124cdf0e10cSrcweir 					if ( bHasChild || bIsSubTotalRow )
2125cdf0e10cSrcweir 						rRes.Flags |= sheet::DataResultFlags::SUBTOTAL;
2126cdf0e10cSrcweir 
2127cdf0e10cSrcweir 					rCol += 1;
2128cdf0e10cSrcweir 				}
2129cdf0e10cSrcweir 			}
2130cdf0e10cSrcweir 
2131cdf0e10cSrcweir             // add extra space again if subtracted from GetSize above,
2132cdf0e10cSrcweir             // add to own size if no children
2133cdf0e10cSrcweir             rCol += nExtraSpace;
2134cdf0e10cSrcweir 
2135cdf0e10cSrcweir             rCol += nMoveSubTotal;
2136cdf0e10cSrcweir 		}
2137cdf0e10cSrcweir 	}
2138cdf0e10cSrcweir }
2139cdf0e10cSrcweir 
UpdateDataRow(const ScDPResultMember * pRefMember,long nMeasure,sal_Bool bIsSubTotalRow,const ScDPSubTotalState & rSubState)2140cdf0e10cSrcweir void ScDPDataMember::UpdateDataRow( const ScDPResultMember* pRefMember,
2141cdf0e10cSrcweir                                 long nMeasure, sal_Bool bIsSubTotalRow,
2142cdf0e10cSrcweir                                 const ScDPSubTotalState& rSubState )
2143cdf0e10cSrcweir {
2144cdf0e10cSrcweir     DBG_ASSERT( pRefMember == pResultMember || !pResultMember, "bla" );
2145cdf0e10cSrcweir 
2146cdf0e10cSrcweir     // Calculate must be called even if not visible (for use as reference value)
2147cdf0e10cSrcweir     const ScDPDataDimension* pDataChild = GetChildDimension();
2148cdf0e10cSrcweir     const ScDPResultDimension* pRefChild = pRefMember->GetChildDimension();
2149cdf0e10cSrcweir 
2150cdf0e10cSrcweir     //  leave space for children even if the DataMember hasn't been initialized
2151cdf0e10cSrcweir     //  (pDataChild is null then, this happens when no values for it are in this row)
2152cdf0e10cSrcweir     sal_Bool bHasChild = ( pRefChild != NULL );
2153cdf0e10cSrcweir 
2154cdf0e10cSrcweir     // process subtotals even if not shown
2155cdf0e10cSrcweir     long nUserSubCount = pRefMember->GetSubTotalCount();
2156cdf0e10cSrcweir 
2157cdf0e10cSrcweir     // Calculate at least automatic if no subtotals are selected,
2158cdf0e10cSrcweir     // show only own values if there's no child dimension (innermost).
2159cdf0e10cSrcweir     if ( !nUserSubCount || !bHasChild )
2160cdf0e10cSrcweir         nUserSubCount = 1;
2161cdf0e10cSrcweir 
2162cdf0e10cSrcweir     ScDPSubTotalState aLocalSubState(rSubState);        // keep row state, modify column
2163cdf0e10cSrcweir 
2164cdf0e10cSrcweir     long nMemberMeasure = nMeasure;
2165cdf0e10cSrcweir     long nSubSize = pResultData->GetCountForMeasure(nMeasure);
2166cdf0e10cSrcweir 
2167cdf0e10cSrcweir     for (long nUserPos=0; nUserPos<nUserSubCount; nUserPos++)   // including hidden "automatic"
2168cdf0e10cSrcweir     {
2169cdf0e10cSrcweir         if ( pChildDimension && nUserSubCount > 1 )
2170cdf0e10cSrcweir         {
2171cdf0e10cSrcweir             const ScDPLevel* pForceLevel = pResultMember ? pResultMember->GetParentLevel() : NULL;
2172cdf0e10cSrcweir             aLocalSubState.nColSubTotalFunc = nUserPos;
2173cdf0e10cSrcweir             aLocalSubState.eColForce = lcl_GetForceFunc( pForceLevel, nUserPos );
2174cdf0e10cSrcweir         }
2175cdf0e10cSrcweir 
2176cdf0e10cSrcweir         for ( long nSubCount=0; nSubCount<nSubSize; nSubCount++ )
2177cdf0e10cSrcweir         {
2178cdf0e10cSrcweir             if ( nMeasure == SC_DPMEASURE_ALL )
2179cdf0e10cSrcweir                 nMemberMeasure = nSubCount;
2180cdf0e10cSrcweir 
2181cdf0e10cSrcweir             // update data...
2182cdf0e10cSrcweir             ScDPAggData* pAggData = GetAggData( nMemberMeasure, aLocalSubState );
2183cdf0e10cSrcweir             if (pAggData)
2184cdf0e10cSrcweir             {
2185cdf0e10cSrcweir                 //! aLocalSubState?
2186cdf0e10cSrcweir                 ScSubTotalFunc eFunc = pResultData->GetMeasureFunction( nMemberMeasure );
2187cdf0e10cSrcweir                 sheet::DataPilotFieldReference aReferenceValue = pResultData->GetMeasureRefVal( nMemberMeasure );
2188cdf0e10cSrcweir                 sal_Int32 eRefType = aReferenceValue.ReferenceType;
2189cdf0e10cSrcweir 
2190cdf0e10cSrcweir                 // calculate the result first - for all members, regardless of reference value
2191cdf0e10cSrcweir                 pAggData->Calculate( eFunc, aLocalSubState );
2192cdf0e10cSrcweir 
2193cdf0e10cSrcweir                 if ( eRefType == sheet::DataPilotFieldReferenceType::ITEM_DIFFERENCE ||
2194cdf0e10cSrcweir                      eRefType == sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE ||
2195cdf0e10cSrcweir                      eRefType == sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE )
2196cdf0e10cSrcweir                 {
2197cdf0e10cSrcweir                     // copy the result into auxiliary value, so differences can be
2198cdf0e10cSrcweir                     // calculated in any order
2199cdf0e10cSrcweir                     pAggData->SetAuxiliary( pAggData->GetResult() );
2200cdf0e10cSrcweir                 }
2201cdf0e10cSrcweir                 // column/row percentage/index is now in UpdateRunningTotals, so it doesn't disturb sorting
2202cdf0e10cSrcweir             }
2203cdf0e10cSrcweir         }
2204cdf0e10cSrcweir     }
2205cdf0e10cSrcweir 
2206cdf0e10cSrcweir     if ( bHasChild )    // child dimension must be processed last, so the row total is known
2207cdf0e10cSrcweir     {
2208cdf0e10cSrcweir         if ( pDataChild )
2209cdf0e10cSrcweir             pDataChild->UpdateDataRow( pRefChild, nMeasure, bIsSubTotalRow, rSubState );
2210cdf0e10cSrcweir     }
2211cdf0e10cSrcweir }
2212cdf0e10cSrcweir 
SortMembers(ScDPResultMember * pRefMember)2213cdf0e10cSrcweir void ScDPDataMember::SortMembers( ScDPResultMember* pRefMember )
2214cdf0e10cSrcweir {
2215cdf0e10cSrcweir     DBG_ASSERT( pRefMember == pResultMember || !pResultMember, "bla" );
2216cdf0e10cSrcweir 
2217cdf0e10cSrcweir     if ( pRefMember->IsVisible() )  //! here or in ScDPDataDimension ???
2218cdf0e10cSrcweir     {
2219cdf0e10cSrcweir         ScDPDataDimension* pDataChild = GetChildDimension();
2220cdf0e10cSrcweir         ScDPResultDimension* pRefChild = pRefMember->GetChildDimension();
2221cdf0e10cSrcweir         if ( pRefChild && pDataChild )
2222cdf0e10cSrcweir             pDataChild->SortMembers( pRefChild );       // sorting is done at the dimension
2223cdf0e10cSrcweir     }
2224cdf0e10cSrcweir }
2225cdf0e10cSrcweir 
DoAutoShow(ScDPResultMember * pRefMember)2226cdf0e10cSrcweir void ScDPDataMember::DoAutoShow( ScDPResultMember* pRefMember )
2227cdf0e10cSrcweir {
2228cdf0e10cSrcweir     DBG_ASSERT( pRefMember == pResultMember || !pResultMember, "bla" );
2229cdf0e10cSrcweir 
2230cdf0e10cSrcweir     if ( pRefMember->IsVisible() )  //! here or in ScDPDataDimension ???
2231cdf0e10cSrcweir     {
2232cdf0e10cSrcweir         ScDPDataDimension* pDataChild = GetChildDimension();
2233cdf0e10cSrcweir         ScDPResultDimension* pRefChild = pRefMember->GetChildDimension();
2234cdf0e10cSrcweir         if ( pRefChild && pDataChild )
2235cdf0e10cSrcweir             pDataChild->DoAutoShow( pRefChild );       // sorting is done at the dimension
2236cdf0e10cSrcweir     }
2237cdf0e10cSrcweir }
2238cdf0e10cSrcweir 
ResetResults()2239cdf0e10cSrcweir void ScDPDataMember::ResetResults()
2240cdf0e10cSrcweir {
2241cdf0e10cSrcweir     aAggregate.Reset();
2242cdf0e10cSrcweir 
2243cdf0e10cSrcweir     ScDPDataDimension* pDataChild = GetChildDimension();
2244cdf0e10cSrcweir     if ( pDataChild )
2245cdf0e10cSrcweir         pDataChild->ResetResults();
2246cdf0e10cSrcweir }
2247cdf0e10cSrcweir 
UpdateRunningTotals(const ScDPResultMember * pRefMember,long nMeasure,sal_Bool bIsSubTotalRow,const ScDPSubTotalState & rSubState,ScDPRunningTotalState & rRunning,ScDPRowTotals & rTotals,const ScDPResultMember & rRowParent)2248cdf0e10cSrcweir void ScDPDataMember::UpdateRunningTotals( const ScDPResultMember* pRefMember,
2249cdf0e10cSrcweir 	                            long nMeasure, sal_Bool bIsSubTotalRow,
2250cdf0e10cSrcweir                                 const ScDPSubTotalState& rSubState, ScDPRunningTotalState& rRunning,
2251cdf0e10cSrcweir                                 ScDPRowTotals& rTotals, const ScDPResultMember& rRowParent )
2252cdf0e10cSrcweir {
2253cdf0e10cSrcweir     DBG_ASSERT( pRefMember == pResultMember || !pResultMember, "bla" );
2254cdf0e10cSrcweir 
2255cdf0e10cSrcweir     if ( pRefMember->IsVisible() )  //! here or in ScDPDataDimension::UpdateRunningTotals ???
2256cdf0e10cSrcweir     {
2257cdf0e10cSrcweir         const ScDPDataDimension* pDataChild = GetChildDimension();
2258cdf0e10cSrcweir         const ScDPResultDimension* pRefChild = pRefMember->GetChildDimension();
2259cdf0e10cSrcweir 
2260cdf0e10cSrcweir         sal_Bool bIsRoot = ( pResultMember == NULL || pResultMember->GetParentLevel() == NULL );
2261cdf0e10cSrcweir 
2262cdf0e10cSrcweir         //  leave space for children even if the DataMember hasn't been initialized
2263cdf0e10cSrcweir         //  (pDataChild is null then, this happens when no values for it are in this row)
2264cdf0e10cSrcweir         sal_Bool bHasChild = ( pRefChild != NULL );
2265cdf0e10cSrcweir 
2266cdf0e10cSrcweir         long nUserSubCount = pRefMember->GetSubTotalCount();
2267cdf0e10cSrcweir 		//if ( nUserSubCount || !bHasChild )
2268cdf0e10cSrcweir         {
2269cdf0e10cSrcweir             // Calculate at least automatic if no subtotals are selected,
2270cdf0e10cSrcweir             // show only own values if there's no child dimension (innermost).
2271cdf0e10cSrcweir             if ( !nUserSubCount || !bHasChild )
2272cdf0e10cSrcweir                 nUserSubCount = 1;
2273cdf0e10cSrcweir 
2274cdf0e10cSrcweir             ScDPSubTotalState aLocalSubState(rSubState);        // keep row state, modify column
2275cdf0e10cSrcweir 
2276cdf0e10cSrcweir             long nMemberMeasure = nMeasure;
2277cdf0e10cSrcweir             long nSubSize = pResultData->GetCountForMeasure(nMeasure);
2278cdf0e10cSrcweir 
2279cdf0e10cSrcweir             for (long nUserPos=0; nUserPos<nUserSubCount; nUserPos++)   // including hidden "automatic"
2280cdf0e10cSrcweir             {
2281cdf0e10cSrcweir                 if ( pChildDimension && nUserSubCount > 1 )
2282cdf0e10cSrcweir                 {
2283cdf0e10cSrcweir                     const ScDPLevel* pForceLevel = pResultMember ? pResultMember->GetParentLevel() : NULL;
2284cdf0e10cSrcweir                     aLocalSubState.nColSubTotalFunc = nUserPos;
2285cdf0e10cSrcweir                     aLocalSubState.eColForce = lcl_GetForceFunc( pForceLevel, nUserPos );
2286cdf0e10cSrcweir                 }
2287cdf0e10cSrcweir 
2288cdf0e10cSrcweir                 for ( long nSubCount=0; nSubCount<nSubSize; nSubCount++ )
2289cdf0e10cSrcweir                 {
2290cdf0e10cSrcweir                     if ( nMeasure == SC_DPMEASURE_ALL )
2291cdf0e10cSrcweir                         nMemberMeasure = nSubCount;
2292cdf0e10cSrcweir 
2293cdf0e10cSrcweir                     // update data...
2294cdf0e10cSrcweir                     ScDPAggData* pAggData = GetAggData( nMemberMeasure, aLocalSubState );
2295cdf0e10cSrcweir                     if (pAggData)
2296cdf0e10cSrcweir                     {
2297cdf0e10cSrcweir                         //! aLocalSubState?
2298cdf0e10cSrcweir                         sheet::DataPilotFieldReference aReferenceValue = pResultData->GetMeasureRefVal( nMemberMeasure );
2299cdf0e10cSrcweir                         sal_Int32 eRefType = aReferenceValue.ReferenceType;
2300cdf0e10cSrcweir 
2301cdf0e10cSrcweir                         if ( eRefType == sheet::DataPilotFieldReferenceType::RUNNING_TOTAL ||
2302cdf0e10cSrcweir                              eRefType == sheet::DataPilotFieldReferenceType::ITEM_DIFFERENCE ||
2303cdf0e10cSrcweir                              eRefType == sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE ||
2304cdf0e10cSrcweir                              eRefType == sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE )
2305cdf0e10cSrcweir                         {
2306cdf0e10cSrcweir                             sal_Bool bRunningTotal = ( eRefType == sheet::DataPilotFieldReferenceType::RUNNING_TOTAL );
2307cdf0e10cSrcweir                             sal_Bool bRelative =
2308cdf0e10cSrcweir                                 ( aReferenceValue.ReferenceItemType != sheet::DataPilotFieldReferenceItemType::NAMED && !bRunningTotal );
2309cdf0e10cSrcweir                             long nRelativeDir = bRelative ?
2310cdf0e10cSrcweir                                 ( ( aReferenceValue.ReferenceItemType == sheet::DataPilotFieldReferenceItemType::PREVIOUS ) ? -1 : 1 ) : 0;
2311cdf0e10cSrcweir 
2312cdf0e10cSrcweir                             const long* pColVisible = rRunning.GetColVisible();
2313cdf0e10cSrcweir                             const long* pColIndexes = rRunning.GetColIndexes();
2314cdf0e10cSrcweir                             const long* pRowVisible = rRunning.GetRowVisible();
2315cdf0e10cSrcweir                             const long* pRowIndexes = rRunning.GetRowIndexes();
2316cdf0e10cSrcweir 
2317cdf0e10cSrcweir                             String aRefFieldName = aReferenceValue.ReferenceField;
2318cdf0e10cSrcweir 
2319cdf0e10cSrcweir                             //! aLocalSubState?
2320cdf0e10cSrcweir                             sal_uInt16 nRefOrient = pResultData->GetMeasureRefOrient( nMemberMeasure );
2321cdf0e10cSrcweir                             sal_Bool bRefDimInCol = ( nRefOrient == sheet::DataPilotFieldOrientation_COLUMN );
2322cdf0e10cSrcweir                             sal_Bool bRefDimInRow = ( nRefOrient == sheet::DataPilotFieldOrientation_ROW );
2323cdf0e10cSrcweir 
2324cdf0e10cSrcweir                             const ScDPResultDimension* pSelectDim = NULL;
2325cdf0e10cSrcweir                             long nRowPos = 0;
2326cdf0e10cSrcweir                             long nColPos = 0;
2327cdf0e10cSrcweir 
2328cdf0e10cSrcweir                             //
2329cdf0e10cSrcweir                             //  find the reference field in column or row dimensions
2330cdf0e10cSrcweir                             //
2331cdf0e10cSrcweir 
2332cdf0e10cSrcweir                             if ( bRefDimInRow )     //  look in row dimensions
2333cdf0e10cSrcweir                             {
2334cdf0e10cSrcweir                                 pSelectDim = rRunning.GetRowResRoot()->GetChildDimension();
2335cdf0e10cSrcweir                                 while ( pSelectDim && pSelectDim->GetName() != aRefFieldName )
2336cdf0e10cSrcweir                                 {
2337cdf0e10cSrcweir                                     long nIndex = pRowIndexes[nRowPos];
2338cdf0e10cSrcweir                                     if ( nIndex >= 0 && nIndex < pSelectDim->GetMemberCount() )
2339cdf0e10cSrcweir                                         pSelectDim = pSelectDim->GetMember(nIndex)->GetChildDimension();
2340cdf0e10cSrcweir                                     else
2341cdf0e10cSrcweir                                         pSelectDim = NULL;
2342cdf0e10cSrcweir                                     ++nRowPos;
2343cdf0e10cSrcweir                                 }
2344cdf0e10cSrcweir                                 // child dimension of innermost member?
2345cdf0e10cSrcweir                                 if ( pSelectDim && pRowIndexes[nRowPos] < 0 )
2346cdf0e10cSrcweir                                     pSelectDim = NULL;
2347cdf0e10cSrcweir                             }
2348cdf0e10cSrcweir 
2349cdf0e10cSrcweir                             if ( bRefDimInCol )     //  look in column dimensions
2350cdf0e10cSrcweir                             {
2351cdf0e10cSrcweir                                 pSelectDim = rRunning.GetColResRoot()->GetChildDimension();
2352cdf0e10cSrcweir                                 while ( pSelectDim && pSelectDim->GetName() != aRefFieldName )
2353cdf0e10cSrcweir                                 {
2354cdf0e10cSrcweir                                     long nIndex = pColIndexes[nColPos];
2355cdf0e10cSrcweir                                     if ( nIndex >= 0 && nIndex < pSelectDim->GetMemberCount() )
2356cdf0e10cSrcweir                                         pSelectDim = pSelectDim->GetMember(nIndex)->GetChildDimension();
2357cdf0e10cSrcweir                                     else
2358cdf0e10cSrcweir                                         pSelectDim = NULL;
2359cdf0e10cSrcweir                                     ++nColPos;
2360cdf0e10cSrcweir                                 }
2361cdf0e10cSrcweir                                 // child dimension of innermost member?
2362cdf0e10cSrcweir                                 if ( pSelectDim && pColIndexes[nColPos] < 0 )
2363cdf0e10cSrcweir                                     pSelectDim = NULL;
2364cdf0e10cSrcweir                             }
2365cdf0e10cSrcweir 
2366cdf0e10cSrcweir                             sal_Bool bNoDetailsInRef = sal_False;
2367cdf0e10cSrcweir                             if ( pSelectDim && bRunningTotal )
2368cdf0e10cSrcweir                             {
2369cdf0e10cSrcweir                                 //  Running totals:
2370cdf0e10cSrcweir                                 //  If details are hidden for this member in the reference dimension,
2371cdf0e10cSrcweir                                 //  don't show or sum up the value. Otherwise, for following members,
2372cdf0e10cSrcweir                                 //  the running totals of details and subtotals wouldn't match.
2373cdf0e10cSrcweir 
2374cdf0e10cSrcweir                                 long nMyIndex = bRefDimInCol ? pColIndexes[nColPos] : pRowIndexes[nRowPos];
2375cdf0e10cSrcweir                                 if ( nMyIndex >= 0 && nMyIndex < pSelectDim->GetMemberCount() )
2376cdf0e10cSrcweir                                 {
2377cdf0e10cSrcweir                                     const ScDPResultMember* pMyRefMember = pSelectDim->GetMember(nMyIndex);
2378cdf0e10cSrcweir                                     if ( pMyRefMember && pMyRefMember->HasHiddenDetails() )
2379cdf0e10cSrcweir                                     {
2380cdf0e10cSrcweir                                         pSelectDim = NULL;          // don't calculate
2381cdf0e10cSrcweir                                         bNoDetailsInRef = sal_True;     // show error, not empty
2382cdf0e10cSrcweir                                     }
2383cdf0e10cSrcweir                                 }
2384cdf0e10cSrcweir                             }
2385cdf0e10cSrcweir 
2386cdf0e10cSrcweir                             if ( bRelative )
2387cdf0e10cSrcweir                             {
2388cdf0e10cSrcweir                                 //  Difference/Percentage from previous/next:
2389cdf0e10cSrcweir                                 //  If details are hidden for this member in the innermost column/row
2390cdf0e10cSrcweir                                 //  dimension (the orientation of the reference dimension), show an
2391cdf0e10cSrcweir                                 //  error value.
2392cdf0e10cSrcweir                                 //  - If the no-details dimension is the reference dimension, its
2393cdf0e10cSrcweir                                 //    members will be skipped when finding the previous/next member,
2394cdf0e10cSrcweir                                 //    so there must be no results for its members.
2395cdf0e10cSrcweir                                 //  - If the no-details dimension is outside of the reference dimension,
2396cdf0e10cSrcweir                                 //    no calculation in the reference dimension is possible.
2397cdf0e10cSrcweir                                 //  - Otherwise, the error isn't strictly necessary, but shown for
2398cdf0e10cSrcweir                                 //    consistency.
2399cdf0e10cSrcweir 
2400cdf0e10cSrcweir                                 sal_Bool bInnerNoDetails = bRefDimInCol ? HasHiddenDetails() :
2401cdf0e10cSrcweir                                                      ( bRefDimInRow ? rRowParent.HasHiddenDetails() : sal_True );
2402cdf0e10cSrcweir                                 if ( bInnerNoDetails )
2403cdf0e10cSrcweir                                 {
2404cdf0e10cSrcweir                                     pSelectDim = NULL;
2405cdf0e10cSrcweir                                     bNoDetailsInRef = sal_True;         // show error, not empty
2406cdf0e10cSrcweir                                 }
2407cdf0e10cSrcweir                             }
2408cdf0e10cSrcweir 
2409cdf0e10cSrcweir                             if ( !bRefDimInCol && !bRefDimInRow )   // invalid dimension specified
2410cdf0e10cSrcweir                                 bNoDetailsInRef = sal_True;             // pSelectDim is then already NULL
2411cdf0e10cSrcweir 
2412cdf0e10cSrcweir                             //
2413cdf0e10cSrcweir                             //  get the member for the reference item and do the calculation
2414cdf0e10cSrcweir                             //
2415cdf0e10cSrcweir 
2416cdf0e10cSrcweir                             if ( bRunningTotal )
2417cdf0e10cSrcweir                             {
2418cdf0e10cSrcweir                                 // running total in (dimension) -> find first existing member
2419cdf0e10cSrcweir 
2420cdf0e10cSrcweir                                 if ( pSelectDim )
2421cdf0e10cSrcweir                                 {
2422cdf0e10cSrcweir                                     ScDPDataMember* pSelectMember;
2423cdf0e10cSrcweir                                     if ( bRefDimInCol )
2424cdf0e10cSrcweir                                         pSelectMember = ScDPResultDimension::GetColReferenceMember( NULL, NULL,
2425cdf0e10cSrcweir                                                                         nColPos, rRunning );
2426cdf0e10cSrcweir                                     else
2427cdf0e10cSrcweir                                     {
2428cdf0e10cSrcweir                                         long nSkip = nRowPos + 1;   // including the reference dimension
2429cdf0e10cSrcweir                                         pSelectMember = pSelectDim->GetRowReferenceMember( NULL, NULL,
2430cdf0e10cSrcweir                                                                         pRowIndexes+nSkip, pColIndexes );
2431cdf0e10cSrcweir                                     }
2432cdf0e10cSrcweir 
2433cdf0e10cSrcweir                                     if ( pSelectMember )
2434cdf0e10cSrcweir                                     {
2435cdf0e10cSrcweir                                         // The running total is kept as the auxiliary value in
2436cdf0e10cSrcweir                                         // the first available member for the reference dimension.
2437cdf0e10cSrcweir                                         // Members are visited in final order, so each one's result
2438cdf0e10cSrcweir                                         // can be used and then modified.
2439cdf0e10cSrcweir 
2440cdf0e10cSrcweir                                         ScDPAggData* pSelectData = pSelectMember->
2441cdf0e10cSrcweir                                                         GetAggData( nMemberMeasure, aLocalSubState );
2442cdf0e10cSrcweir                                         if ( pSelectData )
2443cdf0e10cSrcweir                                         {
2444cdf0e10cSrcweir                                             double fTotal = pSelectData->GetAuxiliary();
2445cdf0e10cSrcweir                                             fTotal += pAggData->GetResult();
2446cdf0e10cSrcweir                                             pSelectData->SetAuxiliary( fTotal );
2447cdf0e10cSrcweir                                             pAggData->SetResult( fTotal );
2448cdf0e10cSrcweir                                             pAggData->SetEmpty(sal_False);              // always display
2449cdf0e10cSrcweir                                         }
2450cdf0e10cSrcweir                                     }
2451cdf0e10cSrcweir                                     else
2452cdf0e10cSrcweir                                         pAggData->SetError();
2453cdf0e10cSrcweir                                 }
2454cdf0e10cSrcweir                                 else if (bNoDetailsInRef)
2455cdf0e10cSrcweir                                     pAggData->SetError();
2456cdf0e10cSrcweir                                 else
2457cdf0e10cSrcweir                                     pAggData->SetEmpty(sal_True);                       // empty (dim set to 0 above)
2458cdf0e10cSrcweir                             }
2459cdf0e10cSrcweir                             else
2460cdf0e10cSrcweir                             {
2461cdf0e10cSrcweir                                 // difference/percentage -> find specified member
2462cdf0e10cSrcweir 
2463cdf0e10cSrcweir                                 if ( pSelectDim )
2464cdf0e10cSrcweir                                 {
2465cdf0e10cSrcweir                                     String aRefItemName = aReferenceValue.ReferenceItemName;
2466cdf0e10cSrcweir                                     ScDPRelativePos aRefItemPos( 0, nRelativeDir );     // nBasePos is modified later
2467cdf0e10cSrcweir 
2468cdf0e10cSrcweir                                     const String* pRefName = NULL;
2469cdf0e10cSrcweir                                     const ScDPRelativePos* pRefPos = NULL;
2470cdf0e10cSrcweir                                     if ( bRelative )
2471cdf0e10cSrcweir                                         pRefPos = &aRefItemPos;
2472cdf0e10cSrcweir                                     else
2473cdf0e10cSrcweir                                         pRefName = &aRefItemName;
2474cdf0e10cSrcweir 
2475cdf0e10cSrcweir                                     ScDPDataMember* pSelectMember;
2476cdf0e10cSrcweir                                     if ( bRefDimInCol )
2477cdf0e10cSrcweir                                     {
2478cdf0e10cSrcweir                                         aRefItemPos.nBasePos = pColVisible[nColPos];    // without sort order applied
2479cdf0e10cSrcweir                                         pSelectMember = ScDPResultDimension::GetColReferenceMember( pRefPos, pRefName,
2480cdf0e10cSrcweir                                                                         nColPos, rRunning );
2481cdf0e10cSrcweir                                     }
2482cdf0e10cSrcweir                                     else
2483cdf0e10cSrcweir                                     {
2484cdf0e10cSrcweir                                         aRefItemPos.nBasePos = pRowVisible[nRowPos];    // without sort order applied
2485cdf0e10cSrcweir                                         long nSkip = nRowPos + 1;   // including the reference dimension
2486cdf0e10cSrcweir                                         pSelectMember = pSelectDim->GetRowReferenceMember( pRefPos, pRefName,
2487cdf0e10cSrcweir                                                                         pRowIndexes+nSkip, pColIndexes );
2488cdf0e10cSrcweir                                     }
2489cdf0e10cSrcweir 
2490cdf0e10cSrcweir                                     // difference or perc.difference is empty for the reference item itself
2491cdf0e10cSrcweir                                     if ( pSelectMember == this &&
2492cdf0e10cSrcweir                                          eRefType != sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE )
2493cdf0e10cSrcweir                                     {
2494cdf0e10cSrcweir                                         pAggData->SetEmpty(sal_True);
2495cdf0e10cSrcweir                                     }
2496cdf0e10cSrcweir                                     else if ( pSelectMember )
2497cdf0e10cSrcweir                                     {
2498cdf0e10cSrcweir                                         const ScDPAggData* pOtherAggData = pSelectMember->
2499cdf0e10cSrcweir                                                             GetConstAggData( nMemberMeasure, aLocalSubState );
2500cdf0e10cSrcweir                                         DBG_ASSERT( pOtherAggData, "no agg data" );
2501cdf0e10cSrcweir                                         if ( pOtherAggData )
2502cdf0e10cSrcweir                                         {
2503cdf0e10cSrcweir                                             // Reference member may be visited before or after this one,
2504cdf0e10cSrcweir                                             // so the auxiliary value is used for the original result.
2505cdf0e10cSrcweir 
2506cdf0e10cSrcweir                                             double fOtherResult = pOtherAggData->GetAuxiliary();
2507cdf0e10cSrcweir                                             double fThisResult = pAggData->GetResult();
2508cdf0e10cSrcweir                                             sal_Bool bError = sal_False;
2509cdf0e10cSrcweir                                             switch ( eRefType )
2510cdf0e10cSrcweir                                             {
2511cdf0e10cSrcweir                                                 case sheet::DataPilotFieldReferenceType::ITEM_DIFFERENCE:
2512cdf0e10cSrcweir                                                     fThisResult = fThisResult - fOtherResult;
2513cdf0e10cSrcweir                                                     break;
2514cdf0e10cSrcweir                                                 case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE:
2515cdf0e10cSrcweir                                                     if ( fOtherResult == 0.0 )
2516cdf0e10cSrcweir                                                         bError = sal_True;
2517cdf0e10cSrcweir                                                     else
2518cdf0e10cSrcweir                                                         fThisResult = fThisResult / fOtherResult;
2519cdf0e10cSrcweir                                                     break;
2520cdf0e10cSrcweir                                                 case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE:
2521cdf0e10cSrcweir                                                     if ( fOtherResult == 0.0 )
2522cdf0e10cSrcweir                                                         bError = sal_True;
2523cdf0e10cSrcweir                                                     else
2524cdf0e10cSrcweir                                                         fThisResult = ( fThisResult - fOtherResult ) / fOtherResult;
2525cdf0e10cSrcweir                                                     break;
2526cdf0e10cSrcweir                                                 default:
2527cdf0e10cSrcweir                                                     DBG_ERROR("invalid calculation type");
2528cdf0e10cSrcweir                                             }
2529cdf0e10cSrcweir                                             if ( bError )
2530cdf0e10cSrcweir                                             {
2531cdf0e10cSrcweir                                                 pAggData->SetError();
2532cdf0e10cSrcweir                                             }
2533cdf0e10cSrcweir                                             else
2534cdf0e10cSrcweir                                             {
2535cdf0e10cSrcweir                                                 pAggData->SetResult(fThisResult);
2536cdf0e10cSrcweir                                                 pAggData->SetEmpty(sal_False);              // always display
2537cdf0e10cSrcweir                                             }
2538cdf0e10cSrcweir                                             //! errors in data?
2539cdf0e10cSrcweir                                         }
2540cdf0e10cSrcweir                                     }
2541cdf0e10cSrcweir                                     else if (bRelative && !bNoDetailsInRef)
2542cdf0e10cSrcweir                                         pAggData->SetEmpty(sal_True);                   // empty
2543cdf0e10cSrcweir                                     else
2544cdf0e10cSrcweir                                         pAggData->SetError();                       // error
2545cdf0e10cSrcweir                                 }
2546cdf0e10cSrcweir                                 else if (bNoDetailsInRef)
2547cdf0e10cSrcweir                                     pAggData->SetError();                           // error
2548cdf0e10cSrcweir                                 else
2549cdf0e10cSrcweir                                     pAggData->SetEmpty(sal_True);                       // empty
2550cdf0e10cSrcweir                             }
2551cdf0e10cSrcweir                         }
2552cdf0e10cSrcweir                         else if ( eRefType == sheet::DataPilotFieldReferenceType::ROW_PERCENTAGE ||
2553cdf0e10cSrcweir                                   eRefType == sheet::DataPilotFieldReferenceType::COLUMN_PERCENTAGE ||
2554cdf0e10cSrcweir                                   eRefType == sheet::DataPilotFieldReferenceType::TOTAL_PERCENTAGE ||
2555cdf0e10cSrcweir                                   eRefType == sheet::DataPilotFieldReferenceType::INDEX )
2556cdf0e10cSrcweir                         {
2557cdf0e10cSrcweir                             //
2558cdf0e10cSrcweir                             //  set total values when they are encountered (always before their use)
2559cdf0e10cSrcweir                             //
2560cdf0e10cSrcweir 
2561cdf0e10cSrcweir                             ScDPAggData* pColTotalData = pRefMember->GetColTotal( nMemberMeasure );
2562cdf0e10cSrcweir                             ScDPAggData* pRowTotalData = rTotals.GetRowTotal( nMemberMeasure );
2563cdf0e10cSrcweir                             ScDPAggData* pGrandTotalData = rTotals.GetGrandTotal( nMemberMeasure );
2564cdf0e10cSrcweir 
2565cdf0e10cSrcweir                             double fTotalValue = pAggData->HasError() ? 0 : pAggData->GetResult();
2566cdf0e10cSrcweir 
2567cdf0e10cSrcweir                             if ( bIsRoot && rTotals.IsInColRoot() && pGrandTotalData )
2568cdf0e10cSrcweir                                 pGrandTotalData->SetAuxiliary( fTotalValue );
2569cdf0e10cSrcweir 
2570cdf0e10cSrcweir                             if ( bIsRoot && pRowTotalData )
2571cdf0e10cSrcweir                                 pRowTotalData->SetAuxiliary( fTotalValue );
2572cdf0e10cSrcweir 
2573cdf0e10cSrcweir                             if ( rTotals.IsInColRoot() && pColTotalData )
2574cdf0e10cSrcweir                                 pColTotalData->SetAuxiliary( fTotalValue );
2575cdf0e10cSrcweir 
2576cdf0e10cSrcweir                             //
2577cdf0e10cSrcweir                             //  find relation to total values
2578cdf0e10cSrcweir                             //
2579cdf0e10cSrcweir 
2580cdf0e10cSrcweir                             switch ( eRefType )
2581cdf0e10cSrcweir                             {
2582cdf0e10cSrcweir                                 case sheet::DataPilotFieldReferenceType::ROW_PERCENTAGE:
2583cdf0e10cSrcweir                                 case sheet::DataPilotFieldReferenceType::COLUMN_PERCENTAGE:
2584cdf0e10cSrcweir                                 case sheet::DataPilotFieldReferenceType::TOTAL_PERCENTAGE:
2585cdf0e10cSrcweir                                     {
2586cdf0e10cSrcweir                                         double nTotal;
2587cdf0e10cSrcweir                                         if ( eRefType == sheet::DataPilotFieldReferenceType::ROW_PERCENTAGE )
2588cdf0e10cSrcweir                                             nTotal = pRowTotalData->GetAuxiliary();
2589cdf0e10cSrcweir                                         else if ( eRefType == sheet::DataPilotFieldReferenceType::COLUMN_PERCENTAGE )
2590cdf0e10cSrcweir                                             nTotal = pColTotalData->GetAuxiliary();
2591cdf0e10cSrcweir                                         else
2592cdf0e10cSrcweir                                             nTotal = pGrandTotalData->GetAuxiliary();
2593cdf0e10cSrcweir 
2594cdf0e10cSrcweir                                         if ( nTotal == 0.0 )
2595cdf0e10cSrcweir                                             pAggData->SetError();
2596cdf0e10cSrcweir                                         else
2597cdf0e10cSrcweir                                             pAggData->SetResult( pAggData->GetResult() / nTotal );
2598cdf0e10cSrcweir                                     }
2599cdf0e10cSrcweir                                     break;
2600cdf0e10cSrcweir                                 case sheet::DataPilotFieldReferenceType::INDEX:
2601cdf0e10cSrcweir                                     {
2602cdf0e10cSrcweir                                         double nColTotal = pColTotalData->GetAuxiliary();
2603cdf0e10cSrcweir                                         double nRowTotal = pRowTotalData->GetAuxiliary();
2604cdf0e10cSrcweir                                         double nGrandTotal = pGrandTotalData->GetAuxiliary();
2605cdf0e10cSrcweir                                         if ( nRowTotal == 0.0 || nColTotal == 0.0 )
2606cdf0e10cSrcweir                                             pAggData->SetError();
2607cdf0e10cSrcweir                                         else
2608cdf0e10cSrcweir                                             pAggData->SetResult(
2609cdf0e10cSrcweir                                                 ( pAggData->GetResult() * nGrandTotal ) /
2610cdf0e10cSrcweir                                                 ( nRowTotal * nColTotal ) );
2611cdf0e10cSrcweir                                     }
2612cdf0e10cSrcweir                                     break;
2613cdf0e10cSrcweir                             }
2614cdf0e10cSrcweir                         }
2615cdf0e10cSrcweir                     }
2616cdf0e10cSrcweir                 }
2617cdf0e10cSrcweir             }
2618cdf0e10cSrcweir         }
2619cdf0e10cSrcweir 
2620cdf0e10cSrcweir         if ( bHasChild )    // child dimension must be processed last, so the row total is known
2621cdf0e10cSrcweir         {
2622cdf0e10cSrcweir             if ( pDataChild )
2623cdf0e10cSrcweir                 pDataChild->UpdateRunningTotals( pRefChild, nMeasure,
2624cdf0e10cSrcweir                                                 bIsSubTotalRow, rSubState, rRunning, rTotals, rRowParent );
2625cdf0e10cSrcweir         }
2626cdf0e10cSrcweir     }
2627cdf0e10cSrcweir }
2628cdf0e10cSrcweir 
DumpState(const ScDPResultMember * pRefMember,ScDocument * pDoc,ScAddress & rPos) const2629cdf0e10cSrcweir void ScDPDataMember::DumpState( const ScDPResultMember* pRefMember, ScDocument* pDoc, ScAddress& rPos ) const
2630cdf0e10cSrcweir {
2631cdf0e10cSrcweir     lcl_DumpRow( String::CreateFromAscii("ScDPDataMember"), GetName(), &aAggregate, pDoc, rPos );
2632cdf0e10cSrcweir     SCROW nStartRow = rPos.Row();
2633cdf0e10cSrcweir 
2634cdf0e10cSrcweir     const ScDPDataDimension* pDataChild = GetChildDimension();
2635cdf0e10cSrcweir     const ScDPResultDimension* pRefChild = pRefMember->GetChildDimension();
2636cdf0e10cSrcweir     if ( pDataChild && pRefChild )
2637cdf0e10cSrcweir         pDataChild->DumpState( pRefChild, pDoc, rPos );
2638cdf0e10cSrcweir 
2639cdf0e10cSrcweir     lcl_Indent( pDoc, nStartRow, rPos );
2640cdf0e10cSrcweir }
2641cdf0e10cSrcweir 
2642cdf0e10cSrcweir // -----------------------------------------------------------------------
2643cdf0e10cSrcweir 
2644cdf0e10cSrcweir //  Helper class to select the members to include in
2645cdf0e10cSrcweir //  ScDPResultDimension::InitFrom or LateInitFrom if groups are used
2646cdf0e10cSrcweir 
2647cdf0e10cSrcweir class ScDPGroupCompare
2648cdf0e10cSrcweir {
2649cdf0e10cSrcweir private:
2650cdf0e10cSrcweir     const ScDPResultData* pResultData;
2651cdf0e10cSrcweir     const ScDPInitState& rInitState;
2652cdf0e10cSrcweir     long                 nDimSource;
2653cdf0e10cSrcweir     sal_Bool                 bIncludeAll;
2654cdf0e10cSrcweir     sal_Bool                 bIsBase;
2655cdf0e10cSrcweir     long                 nGroupBase;
2656cdf0e10cSrcweir     // Wang Xu Ming -- 2009-8-6
2657cdf0e10cSrcweir     // DataPilot Migration - Cache&&Performance
2658cdf0e10cSrcweir     SCROW          nBaseDataId;
2659cdf0e10cSrcweir     // End Comments
2660cdf0e10cSrcweir public:
2661cdf0e10cSrcweir             ScDPGroupCompare( const ScDPResultData* pData, const ScDPInitState& rState, long nDimension );
~ScDPGroupCompare()2662cdf0e10cSrcweir             ~ScDPGroupCompare() {}
2663cdf0e10cSrcweir 
IsIncluded(const ScDPMember & rMember)2664cdf0e10cSrcweir     sal_Bool    IsIncluded( const ScDPMember& rMember )     { return bIncludeAll || TestIncluded( rMember ); }
2665cdf0e10cSrcweir     sal_Bool    TestIncluded( const ScDPMember& rMember );
2666cdf0e10cSrcweir };
2667cdf0e10cSrcweir 
ScDPGroupCompare(const ScDPResultData * pData,const ScDPInitState & rState,long nDimension)2668cdf0e10cSrcweir ScDPGroupCompare::ScDPGroupCompare( const ScDPResultData* pData, const ScDPInitState& rState, long nDimension ) :
2669cdf0e10cSrcweir     pResultData( pData ),
2670cdf0e10cSrcweir     rInitState( rState ),
2671cdf0e10cSrcweir     nDimSource( nDimension ),
2672cdf0e10cSrcweir     nBaseDataId( -1 )
2673cdf0e10cSrcweir {
2674cdf0e10cSrcweir     bIsBase = pResultData->IsBaseForGroup( nDimSource );
2675cdf0e10cSrcweir     nGroupBase = pResultData->GetGroupBase( nDimSource );      //! get together in one call?
2676cdf0e10cSrcweir     if ( nGroupBase >= 0 )
2677cdf0e10cSrcweir         nBaseDataId = rInitState.GetNameIdForIndex( nGroupBase );
2678cdf0e10cSrcweir 
2679cdf0e10cSrcweir     // if bIncludeAll is set, TestIncluded doesn't need to be called
2680cdf0e10cSrcweir     bIncludeAll = !( bIsBase || nGroupBase >= 0 );
2681cdf0e10cSrcweir }
2682cdf0e10cSrcweir 
TestIncluded(const ScDPMember & rMember)2683cdf0e10cSrcweir sal_Bool ScDPGroupCompare::TestIncluded( const ScDPMember& rMember )
2684cdf0e10cSrcweir {
2685cdf0e10cSrcweir 	sal_Bool bInclude = sal_True;
2686cdf0e10cSrcweir 	if ( nBaseDataId >=0 )
2687cdf0e10cSrcweir 	{
2688cdf0e10cSrcweir         ScDPItemData aMemberData;
2689cdf0e10cSrcweir         rMember.FillItemData( aMemberData );
2690cdf0e10cSrcweir         bInclude = pResultData->IsInGroup( aMemberData, nDimSource, nBaseDataId, nGroupBase );
2691cdf0e10cSrcweir 	}
2692cdf0e10cSrcweir     else if ( bIsBase )
2693cdf0e10cSrcweir     {
2694cdf0e10cSrcweir         // need to check all previous groups
2695cdf0e10cSrcweir         //! get array of groups (or indexes) before loop?
2696cdf0e10cSrcweir         ScDPItemData aMemberData;
2697cdf0e10cSrcweir         rMember.FillItemData( aMemberData );
2698cdf0e10cSrcweir         long nInitCount = rInitState.GetCount();
2699cdf0e10cSrcweir         const long* pInitSource = rInitState.GetSource();
2700cdf0e10cSrcweir         /*const ScDPItemData* pInitNames = rInitState.GetNames();*/
2701cdf0e10cSrcweir         const SCROW* pInitNames = rInitState.GetNameIds();
2702cdf0e10cSrcweir         for (long nInitPos=0; nInitPos<nInitCount && bInclude; nInitPos++)
2703cdf0e10cSrcweir             if ( pResultData->GetGroupBase( pInitSource[nInitPos] ) == nDimSource )
2704cdf0e10cSrcweir             {
2705cdf0e10cSrcweir                 bInclude = pResultData->IsInGroup( pInitNames[nInitPos], pInitSource[nInitPos],
2706cdf0e10cSrcweir                                                     aMemberData, nDimSource );
2707cdf0e10cSrcweir             }
2708cdf0e10cSrcweir     }
2709cdf0e10cSrcweir     else if ( nGroupBase >= 0 )
2710cdf0e10cSrcweir     {
2711cdf0e10cSrcweir         // base isn't used in preceding fields
2712cdf0e10cSrcweir         // -> look for other groups using the same base
2713cdf0e10cSrcweir 
2714cdf0e10cSrcweir         //! get array of groups (or indexes) before loop?
2715cdf0e10cSrcweir         ScDPItemData aMemberData;
2716cdf0e10cSrcweir         rMember.FillItemData( aMemberData );
2717cdf0e10cSrcweir         long nInitCount = rInitState.GetCount();
2718cdf0e10cSrcweir         const long* pInitSource = rInitState.GetSource();
2719cdf0e10cSrcweir        /*const ScDPItemData* pInitNames = rInitState.GetNames();*/
2720cdf0e10cSrcweir         const SCROW* pInitNames = rInitState.GetNameIds();
2721cdf0e10cSrcweir         for (long nInitPos=0; nInitPos<nInitCount && bInclude; nInitPos++)
2722cdf0e10cSrcweir             if ( pResultData->GetGroupBase( pInitSource[nInitPos] ) == nGroupBase )
2723cdf0e10cSrcweir             {
2724cdf0e10cSrcweir                 // same base (hierarchy between the two groups is irrelevant)
2725cdf0e10cSrcweir                 bInclude = pResultData->HasCommonElement( pInitNames[nInitPos], pInitSource[nInitPos],
2726cdf0e10cSrcweir                                                         aMemberData, nDimSource );
2727cdf0e10cSrcweir             }
2728cdf0e10cSrcweir     }
2729cdf0e10cSrcweir 
2730cdf0e10cSrcweir     return bInclude;
2731cdf0e10cSrcweir }
2732cdf0e10cSrcweir 
2733cdf0e10cSrcweir // -----------------------------------------------------------------------
2734cdf0e10cSrcweir 
ScDPResultDimension(const ScDPResultData * pData)2735cdf0e10cSrcweir ScDPResultDimension::ScDPResultDimension( const ScDPResultData* pData ) :
2736cdf0e10cSrcweir 	pResultData( pData ),
2737cdf0e10cSrcweir 	bInitialized( sal_False ),
2738cdf0e10cSrcweir 	bIsDataLayout( sal_False ),
2739cdf0e10cSrcweir 	bSortByData( sal_False ),
2740cdf0e10cSrcweir 	bSortAscending( sal_False ),
2741cdf0e10cSrcweir 	nSortMeasure( 0 ),
2742cdf0e10cSrcweir 	bAutoShow( sal_False ),
2743cdf0e10cSrcweir 	bAutoTopItems( sal_False ),
2744cdf0e10cSrcweir 	nAutoMeasure( 0 ),
2745cdf0e10cSrcweir 	nAutoCount( 0 )
2746cdf0e10cSrcweir {
2747cdf0e10cSrcweir }
2748cdf0e10cSrcweir 
~ScDPResultDimension()2749cdf0e10cSrcweir ScDPResultDimension::~ScDPResultDimension()
2750cdf0e10cSrcweir {
2751cdf0e10cSrcweir 	for( int i = maMemberArray.size () ; i-- > 0 ; )
2752cdf0e10cSrcweir 		delete maMemberArray[i];
2753cdf0e10cSrcweir }
2754cdf0e10cSrcweir 
FindMember(SCROW iData) const2755cdf0e10cSrcweir ScDPResultMember *ScDPResultDimension::FindMember(  SCROW  iData ) const
2756cdf0e10cSrcweir {
2757cdf0e10cSrcweir 	if( bIsDataLayout )
2758cdf0e10cSrcweir 		return maMemberArray[0];
2759cdf0e10cSrcweir 
2760cdf0e10cSrcweir 	MemberHash::const_iterator aRes = maMemberHash.find( iData );
2761cdf0e10cSrcweir 	if( aRes != maMemberHash.end()) {
2762cdf0e10cSrcweir 	   	if ( aRes->second->IsNamedItem( iData ) )
2763cdf0e10cSrcweir 			return aRes->second;
2764cdf0e10cSrcweir         DBG_ERROR("problem!  hash result is not the same as IsNamedItem");
2765cdf0e10cSrcweir 	}
2766cdf0e10cSrcweir 
2767cdf0e10cSrcweir 	unsigned int i;
2768cdf0e10cSrcweir 	unsigned int nCount = maMemberArray.size();
2769cdf0e10cSrcweir 	ScDPResultMember* pResultMember;
2770cdf0e10cSrcweir 	for( i = 0; i < nCount ; i++ )
2771cdf0e10cSrcweir 	{
2772cdf0e10cSrcweir 		pResultMember = maMemberArray[i];
2773cdf0e10cSrcweir 		if ( pResultMember->IsNamedItem( iData ) )
2774cdf0e10cSrcweir 			return pResultMember;
2775cdf0e10cSrcweir 	}
2776cdf0e10cSrcweir 	return NULL;
2777cdf0e10cSrcweir }
2778cdf0e10cSrcweir 
InitFrom(const vector<ScDPDimension * > & ppDim,const vector<ScDPLevel * > & ppLev,size_t nPos,ScDPInitState & rInitState,sal_Bool bInitChild)2779cdf0e10cSrcweir void ScDPResultDimension::InitFrom( const vector<ScDPDimension*>& ppDim, const vector<ScDPLevel*>& ppLev,
2780cdf0e10cSrcweir                                     size_t nPos, ScDPInitState& rInitState,  sal_Bool bInitChild /*= sal_True */ )
2781cdf0e10cSrcweir {
2782cdf0e10cSrcweir     if (nPos >= ppDim.size() || nPos >= ppLev.size())
2783cdf0e10cSrcweir     {
2784cdf0e10cSrcweir         bInitialized = true;
2785cdf0e10cSrcweir         return;
2786cdf0e10cSrcweir     }
2787cdf0e10cSrcweir 
2788cdf0e10cSrcweir 	ScDPDimension* pThisDim = ppDim[nPos];
2789cdf0e10cSrcweir 	ScDPLevel* pThisLevel = ppLev[nPos];
2790cdf0e10cSrcweir 
2791cdf0e10cSrcweir     if (!pThisDim || !pThisLevel)
2792cdf0e10cSrcweir     {
2793cdf0e10cSrcweir         bInitialized = true;
2794cdf0e10cSrcweir         return;
2795cdf0e10cSrcweir     }
2796cdf0e10cSrcweir 
2797cdf0e10cSrcweir     bIsDataLayout = pThisDim->getIsDataLayoutDimension();   // member
2798cdf0e10cSrcweir     aDimensionName = pThisDim->getName();                   // member
2799cdf0e10cSrcweir 
2800cdf0e10cSrcweir     // Check the autoshow setting.  If it's enabled, store the settings.
2801cdf0e10cSrcweir     const sheet::DataPilotFieldAutoShowInfo& rAutoInfo = pThisLevel->GetAutoShow();
2802cdf0e10cSrcweir     if ( rAutoInfo.IsEnabled )
2803cdf0e10cSrcweir     {
2804cdf0e10cSrcweir         bAutoShow     = sal_True;
2805cdf0e10cSrcweir         bAutoTopItems = ( rAutoInfo.ShowItemsMode == sheet::DataPilotFieldShowItemsMode::FROM_TOP );
2806cdf0e10cSrcweir         nAutoMeasure  = pThisLevel->GetAutoMeasure();
2807cdf0e10cSrcweir         nAutoCount    = rAutoInfo.ItemCount;
2808cdf0e10cSrcweir     }
2809cdf0e10cSrcweir 
2810cdf0e10cSrcweir     // Check the sort info, and store the settings if appropriate.
2811cdf0e10cSrcweir     const sheet::DataPilotFieldSortInfo& rSortInfo = pThisLevel->GetSortInfo();
2812cdf0e10cSrcweir     if ( rSortInfo.Mode == sheet::DataPilotFieldSortMode::DATA )
2813cdf0e10cSrcweir     {
2814cdf0e10cSrcweir         bSortByData = sal_True;
2815cdf0e10cSrcweir         bSortAscending = rSortInfo.IsAscending;
2816cdf0e10cSrcweir         nSortMeasure = pThisLevel->GetSortMeasure();
2817cdf0e10cSrcweir     }
2818cdf0e10cSrcweir 
2819cdf0e10cSrcweir     // global order is used to initialize aMembers, so it doesn't have to be looked at later
2820cdf0e10cSrcweir     const ScMemberSortOrder& rGlobalOrder = pThisLevel->GetGlobalOrder();
2821cdf0e10cSrcweir 
2822cdf0e10cSrcweir     long nDimSource = pThisDim->GetDimension();     //! check GetSourceDim?
2823cdf0e10cSrcweir     ScDPGroupCompare aCompare( pResultData, rInitState, nDimSource );
2824cdf0e10cSrcweir 
2825cdf0e10cSrcweir     // Now, go through all members and initialize them.
2826cdf0e10cSrcweir     ScDPMembers* pMembers = pThisLevel->GetMembersObject();
2827cdf0e10cSrcweir     long nMembCount = pMembers->getCount();
2828cdf0e10cSrcweir     for ( long i=0; i<nMembCount; i++ )
2829cdf0e10cSrcweir     {
2830cdf0e10cSrcweir         long nSorted = rGlobalOrder.empty() ? i : rGlobalOrder[i];
2831cdf0e10cSrcweir 
2832cdf0e10cSrcweir         ScDPMember* pMember = pMembers->getByIndex(nSorted);
2833cdf0e10cSrcweir         if ( aCompare.IsIncluded( *pMember ) )
2834cdf0e10cSrcweir         {
2835cdf0e10cSrcweir         	ScDPParentDimData aData( i, pThisDim, pThisLevel, pMember);
2836cdf0e10cSrcweir     		ScDPResultMember* pNew = AddMember( aData );
2837cdf0e10cSrcweir 
2838cdf0e10cSrcweir             rInitState.AddMember( nDimSource, /*aMemberData*/pNew->GetDataId() );
2839cdf0e10cSrcweir             pNew->InitFrom( ppDim, ppLev, nPos+1, rInitState, bInitChild  );
2840cdf0e10cSrcweir             rInitState.RemoveMember();
2841cdf0e10cSrcweir         }
2842cdf0e10cSrcweir     }
2843cdf0e10cSrcweir 	bInitialized = sal_True;
2844cdf0e10cSrcweir }
2845cdf0e10cSrcweir 
LateInitFrom(LateInitParams & rParams,const vector<SCROW> & pItemData,size_t nPos,ScDPInitState & rInitState)2846cdf0e10cSrcweir void ScDPResultDimension::LateInitFrom( LateInitParams& rParams/* const vector<ScDPDimension*>& ppDim, const vector<ScDPLevel*>& ppLev*/,
2847cdf0e10cSrcweir                                         const vector<SCROW>& pItemData, size_t nPos,
2848cdf0e10cSrcweir                                         ScDPInitState& rInitState )
2849cdf0e10cSrcweir // End Comments
2850cdf0e10cSrcweir {
2851cdf0e10cSrcweir     if ( rParams.IsEnd( nPos ) )
2852cdf0e10cSrcweir         return;
2853cdf0e10cSrcweir #ifdef DBG_UTIL
2854cdf0e10cSrcweir     DBG_ASSERT( nPos <= pItemData.size(), ByteString::CreateFromInt32( pItemData.size()).GetBuffer() );
2855cdf0e10cSrcweir #endif
2856cdf0e10cSrcweir 	ScDPDimension* pThisDim = rParams.GetDim( nPos );
2857cdf0e10cSrcweir 	ScDPLevel* pThisLevel = rParams.GetLevel( nPos );
2858cdf0e10cSrcweir 	SCROW rThisData = pItemData[nPos];
2859cdf0e10cSrcweir 
2860cdf0e10cSrcweir     if (!pThisDim || !pThisLevel)
2861cdf0e10cSrcweir         return;
2862cdf0e10cSrcweir 
2863cdf0e10cSrcweir     long nDimSource = pThisDim->GetDimension();     //! check GetSourceDim?
2864cdf0e10cSrcweir 
2865cdf0e10cSrcweir     sal_Bool bShowEmpty = pThisLevel->getShowEmpty();
2866cdf0e10cSrcweir 
2867cdf0e10cSrcweir     if ( !bInitialized )
2868cdf0e10cSrcweir     { // init some values
2869cdf0e10cSrcweir         //	create all members at the first call (preserve order)
2870cdf0e10cSrcweir         bIsDataLayout = pThisDim->getIsDataLayoutDimension();
2871cdf0e10cSrcweir         aDimensionName = pThisDim->getName();
2872cdf0e10cSrcweir 
2873cdf0e10cSrcweir         const sheet::DataPilotFieldAutoShowInfo& rAutoInfo = pThisLevel->GetAutoShow();
2874cdf0e10cSrcweir         if ( rAutoInfo.IsEnabled )
2875cdf0e10cSrcweir         {
2876cdf0e10cSrcweir             bAutoShow     = sal_True;
2877cdf0e10cSrcweir             bAutoTopItems = ( rAutoInfo.ShowItemsMode == sheet::DataPilotFieldShowItemsMode::FROM_TOP );
2878cdf0e10cSrcweir             nAutoMeasure  = pThisLevel->GetAutoMeasure();
2879cdf0e10cSrcweir             nAutoCount    = rAutoInfo.ItemCount;
2880cdf0e10cSrcweir         }
2881cdf0e10cSrcweir 
2882cdf0e10cSrcweir         const sheet::DataPilotFieldSortInfo& rSortInfo = pThisLevel->GetSortInfo();
2883cdf0e10cSrcweir         if ( rSortInfo.Mode == sheet::DataPilotFieldSortMode::DATA )
2884cdf0e10cSrcweir         {
2885cdf0e10cSrcweir             bSortByData = sal_True;
2886cdf0e10cSrcweir             bSortAscending = rSortInfo.IsAscending;
2887cdf0e10cSrcweir             nSortMeasure = pThisLevel->GetSortMeasure();
2888cdf0e10cSrcweir         }
2889cdf0e10cSrcweir     }
2890cdf0e10cSrcweir 
2891cdf0e10cSrcweir     bool bLateInitAllMembers=  bIsDataLayout || rParams.GetInitAllChild() || bShowEmpty;
2892cdf0e10cSrcweir 
2893cdf0e10cSrcweir    if ( !bLateInitAllMembers )
2894cdf0e10cSrcweir     {
2895cdf0e10cSrcweir         ResultMembers* pMembers = pResultData->GetDimResultMembers(nDimSource, pThisDim, pThisLevel);
2896cdf0e10cSrcweir         bLateInitAllMembers = pMembers->IsHasHideDetailsMembers();
2897cdf0e10cSrcweir #ifdef DBG_UTIL
2898cdf0e10cSrcweir 	DBG_TRACESTR( aDimensionName )
2899cdf0e10cSrcweir 	if ( pMembers->IsHasHideDetailsMembers() )
2900cdf0e10cSrcweir 		DBG_TRACE ( "HasHideDetailsMembers" );
2901cdf0e10cSrcweir #endif
2902cdf0e10cSrcweir 	 pMembers->SetHasHideDetailsMembers( sal_False );
2903cdf0e10cSrcweir     }
2904cdf0e10cSrcweir 
2905cdf0e10cSrcweir     bool bNewAllMembers =(!rParams.IsRow()) ||  nPos == 0 || bLateInitAllMembers ;
2906cdf0e10cSrcweir 
2907cdf0e10cSrcweir     if (bNewAllMembers )
2908cdf0e10cSrcweir     {
2909cdf0e10cSrcweir       // global order is used to initialize aMembers, so it doesn't have to be looked at later
2910cdf0e10cSrcweir            if ( !bInitialized )
2911cdf0e10cSrcweir         { //init all members
2912cdf0e10cSrcweir             const ScMemberSortOrder& rGlobalOrder = pThisLevel->GetGlobalOrder();
2913cdf0e10cSrcweir 
2914cdf0e10cSrcweir             ScDPGroupCompare aCompare( pResultData, rInitState, nDimSource );
2915cdf0e10cSrcweir             ScDPMembers* pMembers = pThisLevel->GetMembersObject();
2916cdf0e10cSrcweir             long nMembCount = pMembers->getCount();
2917cdf0e10cSrcweir             for ( long i=0; i<nMembCount; i++ )
2918cdf0e10cSrcweir             {
2919cdf0e10cSrcweir                 long nSorted = rGlobalOrder.empty() ? i : rGlobalOrder[i];
2920cdf0e10cSrcweir 
2921cdf0e10cSrcweir                 ScDPMember* pMember = pMembers->getByIndex(nSorted);
2922cdf0e10cSrcweir                 if ( aCompare.IsIncluded( *pMember ) )
2923cdf0e10cSrcweir                 { // add all members
2924cdf0e10cSrcweir                     ScDPParentDimData aData( i, pThisDim, pThisLevel, pMember );
2925cdf0e10cSrcweir                     AddMember( aData );
2926cdf0e10cSrcweir                 }
2927cdf0e10cSrcweir             }
2928cdf0e10cSrcweir             bInitialized = sal_True;    // don't call again, even if no members were included
2929cdf0e10cSrcweir         }
2930cdf0e10cSrcweir         //	initialize only specific member (or all if "show empty" flag is set)
2931cdf0e10cSrcweir         if ( bLateInitAllMembers  )
2932cdf0e10cSrcweir         {
2933cdf0e10cSrcweir             long nCount = maMemberArray.size();
2934cdf0e10cSrcweir             for (long i=0; i<nCount; i++)
2935cdf0e10cSrcweir             {
2936cdf0e10cSrcweir                 ScDPResultMember* pResultMember = maMemberArray[i];
2937cdf0e10cSrcweir 
2938cdf0e10cSrcweir                 // check show empty
2939cdf0e10cSrcweir                 sal_Bool bAllChildren = sal_False;
2940cdf0e10cSrcweir                 if( bShowEmpty )
2941cdf0e10cSrcweir                 {
2942cdf0e10cSrcweir                     if (  pResultMember->IsNamedItem( rThisData ) )
2943cdf0e10cSrcweir                         bAllChildren = sal_False;
2944cdf0e10cSrcweir                     else
2945cdf0e10cSrcweir                         bAllChildren = sal_True;
2946cdf0e10cSrcweir                 }
2947cdf0e10cSrcweir                 rParams.SetInitAllChildren( bAllChildren );
2948cdf0e10cSrcweir                 rInitState.AddMember( nDimSource,  pResultMember->GetDataId() );
2949cdf0e10cSrcweir                 pResultMember->LateInitFrom( rParams, pItemData, nPos+1, rInitState );
2950cdf0e10cSrcweir                 rInitState.RemoveMember();
2951cdf0e10cSrcweir             }
2952cdf0e10cSrcweir         }
2953cdf0e10cSrcweir         else
2954cdf0e10cSrcweir         {
2955cdf0e10cSrcweir             ScDPResultMember* pResultMember = FindMember( rThisData );
2956cdf0e10cSrcweir             if( NULL != pResultMember )
2957cdf0e10cSrcweir             {
2958cdf0e10cSrcweir             	 //DBG_TRACE( "ScDPResultDimension::LateInitFrom");
2959cdf0e10cSrcweir             	 // DBG_TRACESTR( pResultMember->GetDPMember()->GetNameStr());
2960cdf0e10cSrcweir 
2961cdf0e10cSrcweir                 rInitState.AddMember( nDimSource,  pResultMember->GetDataId() );
2962cdf0e10cSrcweir                 pResultMember->LateInitFrom( rParams, pItemData, nPos+1, rInitState );
2963cdf0e10cSrcweir                 rInitState.RemoveMember();
2964cdf0e10cSrcweir             }
2965cdf0e10cSrcweir         }
2966cdf0e10cSrcweir     }
2967cdf0e10cSrcweir     else
2968cdf0e10cSrcweir         InitWithMembers( rParams, pItemData, nPos, rInitState );
2969cdf0e10cSrcweir }
2970cdf0e10cSrcweir 
GetSize(long nMeasure) const2971cdf0e10cSrcweir long ScDPResultDimension::GetSize(long nMeasure) const
2972cdf0e10cSrcweir {
2973cdf0e10cSrcweir 	long nTotal = 0;
2974cdf0e10cSrcweir 	long nMemberCount = maMemberArray.size();
2975cdf0e10cSrcweir 	if (bIsDataLayout)
2976cdf0e10cSrcweir 	{
2977cdf0e10cSrcweir 		DBG_ASSERT(nMeasure == SC_DPMEASURE_ALL || pResultData->GetMeasureCount() == 1,
2978cdf0e10cSrcweir 					"DataLayout dimension twice?");
2979cdf0e10cSrcweir 		//	repeat first member...
2980cdf0e10cSrcweir 		nTotal = nMemberCount * maMemberArray[0]->GetSize(0);	// all measures have equal size
2981cdf0e10cSrcweir 	}
2982cdf0e10cSrcweir 	else
2983cdf0e10cSrcweir 	{
2984cdf0e10cSrcweir 		//	add all members
2985cdf0e10cSrcweir 		for (long nMem=0; nMem<nMemberCount; nMem++)
2986cdf0e10cSrcweir 			nTotal += maMemberArray[nMem]->GetSize(nMeasure);
2987cdf0e10cSrcweir 	}
2988cdf0e10cSrcweir 	return nTotal;
2989cdf0e10cSrcweir }
2990cdf0e10cSrcweir 
IsValidEntry(const vector<SCROW> & aMembers) const2991cdf0e10cSrcweir bool ScDPResultDimension::IsValidEntry( const vector< SCROW >& aMembers ) const
2992cdf0e10cSrcweir {
2993cdf0e10cSrcweir     if (aMembers.empty())
2994cdf0e10cSrcweir         return false;
2995cdf0e10cSrcweir 
2996cdf0e10cSrcweir     const ScDPResultMember* pMember = FindMember( aMembers[0] );
2997cdf0e10cSrcweir     if ( NULL != pMember )
2998cdf0e10cSrcweir         return pMember->IsValidEntry( aMembers );
2999cdf0e10cSrcweir #ifdef DBG_UTIL
3000cdf0e10cSrcweir     ByteString strTemp ("IsValidEntry: Member not found, DimName = " );
3001cdf0e10cSrcweir     strTemp += ByteString( GetName(), RTL_TEXTENCODING_UTF8 );
3002cdf0e10cSrcweir     DBG_TRACE( strTemp.GetBuffer() );
3003cdf0e10cSrcweir     //    DBG_ERROR("IsValidEntry: Member not found");
3004cdf0e10cSrcweir #endif
3005cdf0e10cSrcweir     return false;
3006cdf0e10cSrcweir }
3007cdf0e10cSrcweir 
ProcessData(const vector<SCROW> & aMembers,const ScDPResultDimension * pDataDim,const vector<SCROW> & aDataMembers,const vector<ScDPValueData> & aValues) const3008cdf0e10cSrcweir void ScDPResultDimension::ProcessData( const vector< SCROW >& aMembers,
3009cdf0e10cSrcweir                                        const ScDPResultDimension* pDataDim,
3010cdf0e10cSrcweir                                        const vector< SCROW >& aDataMembers,
3011cdf0e10cSrcweir                                        const vector<ScDPValueData>& aValues ) const
3012cdf0e10cSrcweir {
3013cdf0e10cSrcweir     if (aMembers.empty())
3014cdf0e10cSrcweir         return;
3015cdf0e10cSrcweir 
3016cdf0e10cSrcweir 	ScDPResultMember* pMember = FindMember( aMembers[0] );
3017cdf0e10cSrcweir 	if ( NULL != pMember )
3018cdf0e10cSrcweir 	{
3019cdf0e10cSrcweir         vector</*ScDPItemData*/SCROW > aChildMembers;
3020cdf0e10cSrcweir         if (aMembers.size() > 1)
3021cdf0e10cSrcweir         {
3022cdf0e10cSrcweir             vector</*ScDPItemData*/SCROW >::const_iterator itr = aMembers.begin();
3023cdf0e10cSrcweir             aChildMembers.insert(aChildMembers.begin(), ++itr, aMembers.end());
3024cdf0e10cSrcweir         }
3025cdf0e10cSrcweir         pMember->ProcessData( aChildMembers, pDataDim, aDataMembers, aValues );
3026cdf0e10cSrcweir         return;
3027cdf0e10cSrcweir     }
3028cdf0e10cSrcweir 
3029cdf0e10cSrcweir 	DBG_ERROR("ProcessData: Member not found");
3030cdf0e10cSrcweir }
3031cdf0e10cSrcweir 
FillMemberResults(uno::Sequence<sheet::MemberResult> * pSequences,long nStart,long nMeasure)3032cdf0e10cSrcweir void ScDPResultDimension::FillMemberResults( uno::Sequence<sheet::MemberResult>* pSequences,
3033cdf0e10cSrcweir 												long nStart, long nMeasure )
3034cdf0e10cSrcweir {
3035cdf0e10cSrcweir 	long nPos = nStart;
3036cdf0e10cSrcweir 	long nCount = maMemberArray.size();
3037cdf0e10cSrcweir 
3038cdf0e10cSrcweir 	for (long i=0; i<nCount; i++)
3039cdf0e10cSrcweir 	{
3040cdf0e10cSrcweir 	    long nSorted = aMemberOrder.empty() ? i : aMemberOrder[i];
3041cdf0e10cSrcweir 
3042cdf0e10cSrcweir 		ScDPResultMember* pMember = maMemberArray[nSorted];
3043cdf0e10cSrcweir 		//	in data layout dimension, use first member with different measures/names
3044cdf0e10cSrcweir 		if ( bIsDataLayout )
3045cdf0e10cSrcweir 		{
3046cdf0e10cSrcweir             bool bTotalResult = false;
3047cdf0e10cSrcweir 			String aMbrName = pResultData->GetMeasureDimensionName( nSorted );
3048cdf0e10cSrcweir 			String aMbrCapt = pResultData->GetMeasureString( nSorted, sal_False, SUBTOTAL_FUNC_NONE, bTotalResult );
3049cdf0e10cSrcweir 			maMemberArray[0]->FillMemberResults( pSequences, nPos, nSorted, sal_False, &aMbrName, &aMbrCapt );
3050cdf0e10cSrcweir 		}
3051cdf0e10cSrcweir 		else if ( pMember->IsVisible() )
3052cdf0e10cSrcweir 			pMember->FillMemberResults( pSequences, nPos, nMeasure, sal_False, NULL, NULL );
3053cdf0e10cSrcweir 		// nPos is modified
3054cdf0e10cSrcweir 	}
3055cdf0e10cSrcweir }
3056cdf0e10cSrcweir 
FillDataResults(const ScDPResultMember * pRefMember,uno::Sequence<uno::Sequence<sheet::DataResult>> & rSequence,long nRow,long nMeasure) const3057cdf0e10cSrcweir void ScDPResultDimension::FillDataResults( const ScDPResultMember* pRefMember,
3058cdf0e10cSrcweir 							uno::Sequence< uno::Sequence<sheet::DataResult> >& rSequence,
3059cdf0e10cSrcweir 							long nRow, long nMeasure ) const
3060cdf0e10cSrcweir {
3061cdf0e10cSrcweir 	long nMemberRow = nRow;
3062cdf0e10cSrcweir 	long nMemberMeasure = nMeasure;
3063cdf0e10cSrcweir 	long nCount = maMemberArray.size();
3064cdf0e10cSrcweir 	for (long i=0; i<nCount; i++)
3065cdf0e10cSrcweir 	{
3066cdf0e10cSrcweir 	    long nSorted = aMemberOrder.empty() ? i : aMemberOrder[i];
3067cdf0e10cSrcweir 
3068cdf0e10cSrcweir 		const ScDPResultMember* pMember;
3069cdf0e10cSrcweir 		if (bIsDataLayout)
3070cdf0e10cSrcweir 		{
3071cdf0e10cSrcweir 			DBG_ASSERT(nMeasure == SC_DPMEASURE_ALL || pResultData->GetMeasureCount() == 1,
3072cdf0e10cSrcweir 						"DataLayout dimension twice?");
3073cdf0e10cSrcweir 			pMember = maMemberArray[0];
3074cdf0e10cSrcweir 			nMemberMeasure = nSorted;
3075cdf0e10cSrcweir 		}
3076cdf0e10cSrcweir 		else
3077cdf0e10cSrcweir 			pMember = maMemberArray[nSorted];
3078cdf0e10cSrcweir 
3079cdf0e10cSrcweir 		if ( pMember->IsVisible() )
3080cdf0e10cSrcweir 			pMember->FillDataResults( pRefMember, rSequence, nMemberRow, nMemberMeasure );
3081cdf0e10cSrcweir 			// nMemberRow is modified
3082cdf0e10cSrcweir 	}
3083cdf0e10cSrcweir }
3084cdf0e10cSrcweir 
UpdateDataResults(const ScDPResultMember * pRefMember,long nMeasure) const3085cdf0e10cSrcweir void ScDPResultDimension::UpdateDataResults( const ScDPResultMember* pRefMember, long nMeasure ) const
3086cdf0e10cSrcweir {
3087cdf0e10cSrcweir     long nMemberMeasure = nMeasure;
3088cdf0e10cSrcweir     long nCount = maMemberArray.size();
3089cdf0e10cSrcweir     for (long i=0; i<nCount; i++)
3090cdf0e10cSrcweir     {
3091cdf0e10cSrcweir         const ScDPResultMember* pMember;
3092cdf0e10cSrcweir         if (bIsDataLayout)
3093cdf0e10cSrcweir         {
3094cdf0e10cSrcweir             DBG_ASSERT(nMeasure == SC_DPMEASURE_ALL || pResultData->GetMeasureCount() == 1,
3095cdf0e10cSrcweir                         "DataLayout dimension twice?");
3096cdf0e10cSrcweir 			pMember = maMemberArray[0];
3097cdf0e10cSrcweir             nMemberMeasure = i;
3098cdf0e10cSrcweir         }
3099cdf0e10cSrcweir         else
3100cdf0e10cSrcweir 			pMember = maMemberArray[i];
3101cdf0e10cSrcweir 
3102cdf0e10cSrcweir         if ( pMember->IsVisible() )
3103cdf0e10cSrcweir             pMember->UpdateDataResults( pRefMember, nMemberMeasure );
3104cdf0e10cSrcweir     }
3105cdf0e10cSrcweir }
3106cdf0e10cSrcweir 
SortMembers(ScDPResultMember * pRefMember)3107cdf0e10cSrcweir void ScDPResultDimension::SortMembers( ScDPResultMember* pRefMember )
3108cdf0e10cSrcweir {
3109cdf0e10cSrcweir     long nCount = maMemberArray.size();
3110cdf0e10cSrcweir 
3111cdf0e10cSrcweir     if ( bSortByData )
3112cdf0e10cSrcweir     {
3113cdf0e10cSrcweir         // sort members
3114cdf0e10cSrcweir 
3115cdf0e10cSrcweir         DBG_ASSERT( aMemberOrder.empty(), "sort twice?" );
3116cdf0e10cSrcweir         aMemberOrder.resize( nCount );
3117cdf0e10cSrcweir         for (long nPos=0; nPos<nCount; nPos++)
3118cdf0e10cSrcweir             aMemberOrder[nPos] = nPos;
3119cdf0e10cSrcweir 
3120cdf0e10cSrcweir         ScDPRowMembersOrder aComp( *this, nSortMeasure, bSortAscending );
3121cdf0e10cSrcweir         ::std::sort( aMemberOrder.begin(), aMemberOrder.end(), aComp );
3122cdf0e10cSrcweir     }
3123cdf0e10cSrcweir 
3124cdf0e10cSrcweir     // handle children
3125cdf0e10cSrcweir 
3126cdf0e10cSrcweir     // for data layout, call only once - sorting measure is always taken from settings
3127cdf0e10cSrcweir     long nLoopCount = bIsDataLayout ? 1 : nCount;
3128cdf0e10cSrcweir     for (long i=0; i<nLoopCount; i++)
3129cdf0e10cSrcweir     {
3130cdf0e10cSrcweir         ScDPResultMember* pMember = maMemberArray[i];
3131cdf0e10cSrcweir         if ( pMember->IsVisible() )
3132cdf0e10cSrcweir             pMember->SortMembers( pRefMember );
3133cdf0e10cSrcweir     }
3134cdf0e10cSrcweir }
3135cdf0e10cSrcweir 
DoAutoShow(ScDPResultMember * pRefMember)3136cdf0e10cSrcweir void ScDPResultDimension::DoAutoShow( ScDPResultMember* pRefMember )
3137cdf0e10cSrcweir {
3138cdf0e10cSrcweir     long nCount = maMemberArray.size();
3139cdf0e10cSrcweir 
3140cdf0e10cSrcweir     // handle children first, before changing the visible state
3141cdf0e10cSrcweir 
3142cdf0e10cSrcweir     // for data layout, call only once - sorting measure is always taken from settings
3143cdf0e10cSrcweir     long nLoopCount = bIsDataLayout ? 1 : nCount;
3144cdf0e10cSrcweir     for (long i=0; i<nLoopCount; i++)
3145cdf0e10cSrcweir     {
3146cdf0e10cSrcweir         ScDPResultMember* pMember = maMemberArray[i];
3147cdf0e10cSrcweir         if ( pMember->IsVisible() )
3148cdf0e10cSrcweir             pMember->DoAutoShow( pRefMember );
3149cdf0e10cSrcweir     }
3150cdf0e10cSrcweir 
3151cdf0e10cSrcweir     if ( bAutoShow && nAutoCount > 0 && nAutoCount < nCount )
3152cdf0e10cSrcweir     {
3153cdf0e10cSrcweir         // establish temporary order, hide remaining members
3154cdf0e10cSrcweir 
3155cdf0e10cSrcweir         ScMemberSortOrder aAutoOrder;
3156cdf0e10cSrcweir         aAutoOrder.resize( nCount );
3157cdf0e10cSrcweir         long nPos;
3158cdf0e10cSrcweir         for (nPos=0; nPos<nCount; nPos++)
3159cdf0e10cSrcweir             aAutoOrder[nPos] = nPos;
3160cdf0e10cSrcweir 
3161cdf0e10cSrcweir         ScDPRowMembersOrder aComp( *this, nAutoMeasure, !bAutoTopItems );
3162cdf0e10cSrcweir         ::std::sort( aAutoOrder.begin(), aAutoOrder.end(), aComp );
3163cdf0e10cSrcweir 
3164cdf0e10cSrcweir         // look for equal values to the last included one
3165cdf0e10cSrcweir 
3166cdf0e10cSrcweir         long nIncluded = nAutoCount;
3167cdf0e10cSrcweir         const ScDPResultMember* pMember1 = maMemberArray[aAutoOrder[nIncluded - 1]];
3168cdf0e10cSrcweir         const ScDPDataMember* pDataMember1 = pMember1->IsVisible() ? pMember1->GetDataRoot() : NULL;
3169cdf0e10cSrcweir         sal_Bool bContinue = sal_True;
3170cdf0e10cSrcweir         while ( bContinue )
3171cdf0e10cSrcweir         {
3172cdf0e10cSrcweir             bContinue = sal_False;
3173cdf0e10cSrcweir             if ( nIncluded < nCount )
3174cdf0e10cSrcweir             {
3175cdf0e10cSrcweir                 const ScDPResultMember* pMember2 = maMemberArray[aAutoOrder[nIncluded]];
3176cdf0e10cSrcweir                 const ScDPDataMember* pDataMember2 = pMember2->IsVisible() ? pMember2->GetDataRoot() : NULL;
3177cdf0e10cSrcweir 
3178cdf0e10cSrcweir                 if ( lcl_IsEqual( pDataMember1, pDataMember2, nAutoMeasure ) )
3179cdf0e10cSrcweir                 {
3180cdf0e10cSrcweir                     ++nIncluded;                // include more members if values are equal
3181cdf0e10cSrcweir                     bContinue = sal_True;
3182cdf0e10cSrcweir                 }
3183cdf0e10cSrcweir             }
3184cdf0e10cSrcweir         }
3185cdf0e10cSrcweir 
3186cdf0e10cSrcweir         // hide the remaining members
3187cdf0e10cSrcweir 
3188cdf0e10cSrcweir         for (nPos = nIncluded; nPos < nCount; nPos++)
3189cdf0e10cSrcweir         {
3190cdf0e10cSrcweir             ScDPResultMember* pMember = maMemberArray[aAutoOrder[nPos]];
3191cdf0e10cSrcweir             pMember->SetAutoHidden();
3192cdf0e10cSrcweir         }
3193cdf0e10cSrcweir     }
3194cdf0e10cSrcweir }
3195cdf0e10cSrcweir 
ResetResults()3196cdf0e10cSrcweir void ScDPResultDimension::ResetResults()
3197cdf0e10cSrcweir {
3198cdf0e10cSrcweir     long nCount = maMemberArray.size();
3199cdf0e10cSrcweir     for (long i=0; i<nCount; i++)
3200cdf0e10cSrcweir     {
3201cdf0e10cSrcweir         // sort order doesn't matter
3202cdf0e10cSrcweir         ScDPResultMember* pMember = maMemberArray[bIsDataLayout ? 0 : i];
3203cdf0e10cSrcweir         pMember->ResetResults( sal_False );
3204cdf0e10cSrcweir     }
3205cdf0e10cSrcweir }
3206cdf0e10cSrcweir 
GetSortedIndex(long nUnsorted) const3207cdf0e10cSrcweir long ScDPResultDimension::GetSortedIndex( long nUnsorted ) const
3208cdf0e10cSrcweir {
3209cdf0e10cSrcweir     return aMemberOrder.empty() ? nUnsorted : aMemberOrder[nUnsorted];
3210cdf0e10cSrcweir }
3211cdf0e10cSrcweir 
UpdateRunningTotals(const ScDPResultMember * pRefMember,long nMeasure,ScDPRunningTotalState & rRunning,ScDPRowTotals & rTotals) const3212cdf0e10cSrcweir void ScDPResultDimension::UpdateRunningTotals( const ScDPResultMember* pRefMember, long nMeasure,
3213cdf0e10cSrcweir                                                 ScDPRunningTotalState& rRunning, ScDPRowTotals& rTotals ) const
3214cdf0e10cSrcweir {
3215cdf0e10cSrcweir 	const ScDPResultMember* pMember;
3216cdf0e10cSrcweir     long nMemberMeasure = nMeasure;
3217cdf0e10cSrcweir     long nCount = maMemberArray.size();
3218cdf0e10cSrcweir     for (long i=0; i<nCount; i++)
3219cdf0e10cSrcweir     {
3220cdf0e10cSrcweir 	    long nSorted = aMemberOrder.empty() ? i : aMemberOrder[i];
3221cdf0e10cSrcweir 
3222cdf0e10cSrcweir         if (bIsDataLayout)
3223cdf0e10cSrcweir         {
3224cdf0e10cSrcweir             DBG_ASSERT(nMeasure == SC_DPMEASURE_ALL || pResultData->GetMeasureCount() == 1,
3225cdf0e10cSrcweir                         "DataLayout dimension twice?");
3226cdf0e10cSrcweir             pMember = maMemberArray[0];
3227cdf0e10cSrcweir             nMemberMeasure = nSorted;
3228cdf0e10cSrcweir         }
3229cdf0e10cSrcweir         else
3230cdf0e10cSrcweir             pMember = maMemberArray[nSorted];
3231cdf0e10cSrcweir 
3232cdf0e10cSrcweir         if ( pMember->IsVisible() )
3233cdf0e10cSrcweir         {
3234cdf0e10cSrcweir             if ( bIsDataLayout )
3235cdf0e10cSrcweir                 rRunning.AddRowIndex( 0, 0 );
3236cdf0e10cSrcweir             else
3237cdf0e10cSrcweir                 rRunning.AddRowIndex( i, nSorted );
3238cdf0e10cSrcweir             pMember->UpdateRunningTotals( pRefMember, nMemberMeasure, rRunning, rTotals );
3239cdf0e10cSrcweir             rRunning.RemoveRowIndex();
3240cdf0e10cSrcweir         }
3241cdf0e10cSrcweir     }
3242cdf0e10cSrcweir }
3243cdf0e10cSrcweir 
GetRowReferenceMember(const ScDPRelativePos * pRelativePos,const String * pName,const long * pRowIndexes,const long * pColIndexes) const3244cdf0e10cSrcweir ScDPDataMember* ScDPResultDimension::GetRowReferenceMember( const ScDPRelativePos* pRelativePos, const String* pName,
3245cdf0e10cSrcweir                                     const long* pRowIndexes, const long* pColIndexes ) const
3246cdf0e10cSrcweir {
3247cdf0e10cSrcweir     // get named, previous/next, or first member of this dimension (first existing if pRelativePos and pName are NULL)
3248cdf0e10cSrcweir 
3249cdf0e10cSrcweir     DBG_ASSERT( pRelativePos == NULL || pName == NULL, "can't use position and name" );
3250cdf0e10cSrcweir 
3251cdf0e10cSrcweir     ScDPDataMember* pColMember = NULL;
3252cdf0e10cSrcweir 
3253cdf0e10cSrcweir     sal_Bool bFirstExisting = ( pRelativePos == NULL && pName == NULL );
3254cdf0e10cSrcweir     long nMemberCount = maMemberArray.size();
3255cdf0e10cSrcweir     long nMemberIndex = 0;      // unsorted
3256cdf0e10cSrcweir     long nDirection = 1;        // forward if no relative position is used
3257cdf0e10cSrcweir     if ( pRelativePos )
3258cdf0e10cSrcweir     {
3259cdf0e10cSrcweir         nDirection = pRelativePos->nDirection;
3260cdf0e10cSrcweir         nMemberIndex = pRelativePos->nBasePos + nDirection;     // bounds are handled below
3261cdf0e10cSrcweir 
3262cdf0e10cSrcweir         DBG_ASSERT( nDirection == 1 || nDirection == -1, "Direction must be 1 or -1" );
3263cdf0e10cSrcweir     }
3264cdf0e10cSrcweir     else if ( pName )
3265cdf0e10cSrcweir     {
3266cdf0e10cSrcweir         // search for named member
3267cdf0e10cSrcweir 
3268cdf0e10cSrcweir         const ScDPResultMember* pRowMember = maMemberArray[GetSortedIndex(nMemberIndex)];
3269cdf0e10cSrcweir 
3270cdf0e10cSrcweir         //! use ScDPItemData, as in ScDPDimension::IsValidPage?
3271cdf0e10cSrcweir         while ( pRowMember && pRowMember->GetName() != *pName )
3272cdf0e10cSrcweir         {
3273cdf0e10cSrcweir             ++nMemberIndex;
3274cdf0e10cSrcweir             if ( nMemberIndex < nMemberCount )
3275cdf0e10cSrcweir                 pRowMember = maMemberArray[GetSortedIndex(nMemberIndex)];
3276cdf0e10cSrcweir             else
3277cdf0e10cSrcweir                 pRowMember = NULL;
3278cdf0e10cSrcweir         }
3279cdf0e10cSrcweir     }
3280cdf0e10cSrcweir 
3281cdf0e10cSrcweir     sal_Bool bContinue = sal_True;
3282cdf0e10cSrcweir     while ( bContinue && nMemberIndex >= 0 && nMemberIndex < nMemberCount )
3283cdf0e10cSrcweir     {
3284cdf0e10cSrcweir         const ScDPResultMember* pRowMember = maMemberArray[GetSortedIndex(nMemberIndex)];
3285cdf0e10cSrcweir 
3286cdf0e10cSrcweir         // get child members by given indexes
3287cdf0e10cSrcweir 
3288cdf0e10cSrcweir         const long* pNextRowIndex = pRowIndexes;
3289cdf0e10cSrcweir         while ( *pNextRowIndex >= 0 && pRowMember )
3290cdf0e10cSrcweir         {
3291cdf0e10cSrcweir             const ScDPResultDimension* pRowChild = pRowMember->GetChildDimension();
3292cdf0e10cSrcweir             if ( pRowChild && *pNextRowIndex < pRowChild->GetMemberCount() )
3293cdf0e10cSrcweir                 pRowMember = pRowChild->GetMember( *pNextRowIndex );
3294cdf0e10cSrcweir             else
3295cdf0e10cSrcweir                 pRowMember = NULL;
3296cdf0e10cSrcweir             ++pNextRowIndex;
3297cdf0e10cSrcweir         }
3298cdf0e10cSrcweir 
3299cdf0e10cSrcweir         if ( pRowMember && pRelativePos )
3300cdf0e10cSrcweir         {
3301cdf0e10cSrcweir             //  Skip the member if it has hidden details
3302cdf0e10cSrcweir             //  (because when looking for the details, it is skipped, too).
3303cdf0e10cSrcweir             //  Also skip if the member is invisible because it has no data,
3304cdf0e10cSrcweir             //  for consistent ordering.
3305cdf0e10cSrcweir             if ( pRowMember->HasHiddenDetails() || !pRowMember->IsVisible() )
3306cdf0e10cSrcweir                 pRowMember = NULL;
3307cdf0e10cSrcweir         }
3308cdf0e10cSrcweir 
3309cdf0e10cSrcweir         if ( pRowMember )
3310cdf0e10cSrcweir         {
3311cdf0e10cSrcweir             pColMember = pRowMember->GetDataRoot();
3312cdf0e10cSrcweir 
3313cdf0e10cSrcweir             const long* pNextColIndex = pColIndexes;
3314cdf0e10cSrcweir             while ( *pNextColIndex >= 0 && pColMember )
3315cdf0e10cSrcweir             {
3316cdf0e10cSrcweir                 const ScDPDataDimension* pColChild = pColMember->GetChildDimension();
3317cdf0e10cSrcweir                 if ( pColChild && *pNextColIndex < pColChild->GetMemberCount() )
3318cdf0e10cSrcweir                     pColMember = pColChild->GetMember( *pNextColIndex );
3319cdf0e10cSrcweir                 else
3320cdf0e10cSrcweir                     pColMember = NULL;
3321cdf0e10cSrcweir                 ++pNextColIndex;
3322cdf0e10cSrcweir             }
3323cdf0e10cSrcweir         }
3324cdf0e10cSrcweir 
3325cdf0e10cSrcweir         // continue searching only if looking for first existing or relative position
3326cdf0e10cSrcweir         bContinue = ( pColMember == NULL && ( bFirstExisting || pRelativePos ) );
3327cdf0e10cSrcweir         nMemberIndex += nDirection;
3328cdf0e10cSrcweir     }
3329cdf0e10cSrcweir 
3330cdf0e10cSrcweir     return pColMember;
3331cdf0e10cSrcweir }
3332cdf0e10cSrcweir 
3333cdf0e10cSrcweir // static
GetColReferenceMember(const ScDPRelativePos * pRelativePos,const String * pName,long nRefDimPos,const ScDPRunningTotalState & rRunning)3334cdf0e10cSrcweir ScDPDataMember* ScDPResultDimension::GetColReferenceMember( const ScDPRelativePos* pRelativePos, const String* pName,
3335cdf0e10cSrcweir                             long nRefDimPos, const ScDPRunningTotalState& rRunning )
3336cdf0e10cSrcweir {
3337cdf0e10cSrcweir     DBG_ASSERT( pRelativePos == NULL || pName == NULL, "can't use position and name" );
3338cdf0e10cSrcweir 
3339cdf0e10cSrcweir     const long* pColIndexes = rRunning.GetColIndexes();
3340cdf0e10cSrcweir     const long* pRowIndexes = rRunning.GetRowIndexes();
3341cdf0e10cSrcweir 
3342cdf0e10cSrcweir     // get own row member using all indexes
3343cdf0e10cSrcweir 
3344cdf0e10cSrcweir     const ScDPResultMember* pRowMember = rRunning.GetRowResRoot();
3345cdf0e10cSrcweir     ScDPDataMember* pColMember = NULL;
3346cdf0e10cSrcweir 
3347cdf0e10cSrcweir     const long* pNextRowIndex = pRowIndexes;
3348cdf0e10cSrcweir     while ( *pNextRowIndex >= 0 && pRowMember )
3349cdf0e10cSrcweir     {
3350cdf0e10cSrcweir         const ScDPResultDimension* pRowChild = pRowMember->GetChildDimension();
3351cdf0e10cSrcweir         if ( pRowChild && *pNextRowIndex < pRowChild->GetMemberCount() )
3352cdf0e10cSrcweir             pRowMember = pRowChild->GetMember( *pNextRowIndex );
3353cdf0e10cSrcweir         else
3354cdf0e10cSrcweir             pRowMember = NULL;
3355cdf0e10cSrcweir         ++pNextRowIndex;
3356cdf0e10cSrcweir     }
3357cdf0e10cSrcweir 
3358cdf0e10cSrcweir     // get column (data) members before the reference field
3359cdf0e10cSrcweir     //! pass rRowParent from ScDPDataMember::UpdateRunningTotals instead
3360cdf0e10cSrcweir 
3361cdf0e10cSrcweir     if ( pRowMember )
3362cdf0e10cSrcweir     {
3363cdf0e10cSrcweir         pColMember = pRowMember->GetDataRoot();
3364cdf0e10cSrcweir 
3365cdf0e10cSrcweir         const long* pNextColIndex = pColIndexes;
3366cdf0e10cSrcweir         long nColSkipped = 0;
3367cdf0e10cSrcweir         while ( *pNextColIndex >= 0 && pColMember && nColSkipped < nRefDimPos )
3368cdf0e10cSrcweir         {
3369cdf0e10cSrcweir             const ScDPDataDimension* pColChild = pColMember->GetChildDimension();
3370cdf0e10cSrcweir             if ( pColChild && *pNextColIndex < pColChild->GetMemberCount() )
3371cdf0e10cSrcweir                 pColMember = pColChild->GetMember( *pNextColIndex );
3372cdf0e10cSrcweir             else
3373cdf0e10cSrcweir                 pColMember = NULL;
3374cdf0e10cSrcweir             ++pNextColIndex;
3375cdf0e10cSrcweir             ++nColSkipped;
3376cdf0e10cSrcweir         }
3377cdf0e10cSrcweir     }
3378cdf0e10cSrcweir 
3379cdf0e10cSrcweir     // get column member for the reference field
3380cdf0e10cSrcweir 
3381cdf0e10cSrcweir     if ( pColMember )
3382cdf0e10cSrcweir     {
3383cdf0e10cSrcweir         const ScDPDataDimension* pReferenceDim = pColMember->GetChildDimension();
3384cdf0e10cSrcweir         if ( pReferenceDim )
3385cdf0e10cSrcweir         {
3386cdf0e10cSrcweir             long nReferenceCount = pReferenceDim->GetMemberCount();
3387cdf0e10cSrcweir 
3388cdf0e10cSrcweir             sal_Bool bFirstExisting = ( pRelativePos == NULL && pName == NULL );
3389cdf0e10cSrcweir             long nMemberIndex = 0;      // unsorted
3390cdf0e10cSrcweir             long nDirection = 1;        // forward if no relative position is used
3391cdf0e10cSrcweir             pColMember = NULL;          // don't use parent dimension's member if none found
3392cdf0e10cSrcweir             if ( pRelativePos )
3393cdf0e10cSrcweir             {
3394cdf0e10cSrcweir                 nDirection = pRelativePos->nDirection;
3395cdf0e10cSrcweir                 nMemberIndex = pRelativePos->nBasePos + nDirection;     // bounds are handled below
3396cdf0e10cSrcweir             }
3397cdf0e10cSrcweir             else if ( pName )
3398cdf0e10cSrcweir             {
3399cdf0e10cSrcweir                 // search for named member
3400cdf0e10cSrcweir 
3401cdf0e10cSrcweir                 pColMember = pReferenceDim->GetMember( pReferenceDim->GetSortedIndex( nMemberIndex ) );
3402cdf0e10cSrcweir 
3403cdf0e10cSrcweir                 //! use ScDPItemData, as in ScDPDimension::IsValidPage?
3404cdf0e10cSrcweir                 while ( pColMember && pColMember->GetName() != *pName )
3405cdf0e10cSrcweir                 {
3406cdf0e10cSrcweir                     ++nMemberIndex;
3407cdf0e10cSrcweir                     if ( nMemberIndex < nReferenceCount )
3408cdf0e10cSrcweir                         pColMember = pReferenceDim->GetMember( pReferenceDim->GetSortedIndex( nMemberIndex ) );
3409cdf0e10cSrcweir                     else
3410cdf0e10cSrcweir                         pColMember = NULL;
3411cdf0e10cSrcweir                 }
3412cdf0e10cSrcweir             }
3413cdf0e10cSrcweir 
3414cdf0e10cSrcweir             sal_Bool bContinue = sal_True;
3415cdf0e10cSrcweir             while ( bContinue && nMemberIndex >= 0 && nMemberIndex < nReferenceCount )
3416cdf0e10cSrcweir             {
3417cdf0e10cSrcweir                 pColMember = pReferenceDim->GetMember( pReferenceDim->GetSortedIndex( nMemberIndex ) );
3418cdf0e10cSrcweir 
3419cdf0e10cSrcweir                 // get column members below the reference field
3420cdf0e10cSrcweir 
3421cdf0e10cSrcweir                 const long* pNextColIndex = pColIndexes + nRefDimPos + 1;
3422cdf0e10cSrcweir                 while ( *pNextColIndex >= 0 && pColMember )
3423cdf0e10cSrcweir                 {
3424cdf0e10cSrcweir                     const ScDPDataDimension* pColChild = pColMember->GetChildDimension();
3425cdf0e10cSrcweir                     if ( pColChild && *pNextColIndex < pColChild->GetMemberCount() )
3426cdf0e10cSrcweir                         pColMember = pColChild->GetMember( *pNextColIndex );
3427cdf0e10cSrcweir                     else
3428cdf0e10cSrcweir                         pColMember = NULL;
3429cdf0e10cSrcweir                     ++pNextColIndex;
3430cdf0e10cSrcweir                 }
3431cdf0e10cSrcweir 
3432cdf0e10cSrcweir                 if ( pColMember && pRelativePos )
3433cdf0e10cSrcweir                 {
3434cdf0e10cSrcweir                     //  Skip the member if it has hidden details
3435cdf0e10cSrcweir                     //  (because when looking for the details, it is skipped, too).
3436cdf0e10cSrcweir                     //  Also skip if the member is invisible because it has no data,
3437cdf0e10cSrcweir                     //  for consistent ordering.
3438cdf0e10cSrcweir                     if ( pColMember->HasHiddenDetails() || !pColMember->IsVisible() )
3439cdf0e10cSrcweir                         pColMember = NULL;
3440cdf0e10cSrcweir                 }
3441cdf0e10cSrcweir 
3442cdf0e10cSrcweir                 // continue searching only if looking for first existing or relative position
3443cdf0e10cSrcweir                 bContinue = ( pColMember == NULL && ( bFirstExisting || pRelativePos ) );
3444cdf0e10cSrcweir                 nMemberIndex += nDirection;
3445cdf0e10cSrcweir             }
3446cdf0e10cSrcweir         }
3447cdf0e10cSrcweir         else
3448cdf0e10cSrcweir             pColMember = NULL;
3449cdf0e10cSrcweir     }
3450cdf0e10cSrcweir 
3451cdf0e10cSrcweir     return pColMember;
3452cdf0e10cSrcweir }
3453cdf0e10cSrcweir 
DumpState(const ScDPResultMember * pRefMember,ScDocument * pDoc,ScAddress & rPos) const3454cdf0e10cSrcweir void ScDPResultDimension::DumpState( const ScDPResultMember* pRefMember, ScDocument* pDoc, ScAddress& rPos ) const
3455cdf0e10cSrcweir {
3456cdf0e10cSrcweir     String aDimName = bIsDataLayout ? String::CreateFromAscii("(data layout)") : GetName();
3457cdf0e10cSrcweir     lcl_DumpRow( String::CreateFromAscii("ScDPResultDimension"), aDimName, NULL, pDoc, rPos );
3458cdf0e10cSrcweir 
3459cdf0e10cSrcweir     SCROW nStartRow = rPos.Row();
3460cdf0e10cSrcweir 
3461cdf0e10cSrcweir     long nCount = bIsDataLayout ? 1 : maMemberArray.size();
3462cdf0e10cSrcweir     for (long i=0; i<nCount; i++)
3463cdf0e10cSrcweir     {
3464cdf0e10cSrcweir         const ScDPResultMember* pMember = maMemberArray[i];
3465cdf0e10cSrcweir         pMember->DumpState( pRefMember, pDoc, rPos );
3466cdf0e10cSrcweir     }
3467cdf0e10cSrcweir 
3468cdf0e10cSrcweir     lcl_Indent( pDoc, nStartRow, rPos );
3469cdf0e10cSrcweir }
3470cdf0e10cSrcweir 
GetMemberCount() const3471cdf0e10cSrcweir long ScDPResultDimension::GetMemberCount() const
3472cdf0e10cSrcweir {
3473cdf0e10cSrcweir 	return maMemberArray.size();
3474cdf0e10cSrcweir }
3475cdf0e10cSrcweir 
GetMember(long n) const3476cdf0e10cSrcweir const ScDPResultMember* ScDPResultDimension::GetMember(long n) const
3477cdf0e10cSrcweir {
3478cdf0e10cSrcweir 	return maMemberArray[n];
3479cdf0e10cSrcweir }
GetMember(long n)3480cdf0e10cSrcweir ScDPResultMember* ScDPResultDimension::GetMember(long n)
3481cdf0e10cSrcweir {
3482cdf0e10cSrcweir 	return maMemberArray[n];
3483cdf0e10cSrcweir }
3484cdf0e10cSrcweir 
GetFirstChildDimension() const3485cdf0e10cSrcweir ScDPResultDimension* ScDPResultDimension::GetFirstChildDimension() const
3486cdf0e10cSrcweir {
3487cdf0e10cSrcweir 	if ( maMemberArray.size() > 0 )
3488cdf0e10cSrcweir 		return maMemberArray[0]->GetChildDimension();
3489cdf0e10cSrcweir 	else
3490cdf0e10cSrcweir 		return NULL;
3491cdf0e10cSrcweir }
3492cdf0e10cSrcweir 
FillVisibilityData(ScDPResultVisibilityData & rData) const3493cdf0e10cSrcweir void ScDPResultDimension::FillVisibilityData(ScDPResultVisibilityData& rData) const
3494cdf0e10cSrcweir {
3495cdf0e10cSrcweir     if (IsDataLayout())
3496cdf0e10cSrcweir         return;
3497cdf0e10cSrcweir 
3498cdf0e10cSrcweir     MemberArray::const_iterator itr = maMemberArray.begin(), itrEnd = maMemberArray.end();
3499cdf0e10cSrcweir 
3500cdf0e10cSrcweir     for (;itr != itrEnd; ++itr)
3501cdf0e10cSrcweir     {
3502cdf0e10cSrcweir         ScDPResultMember* pMember = *itr;
3503cdf0e10cSrcweir         if (pMember->IsValid())
3504cdf0e10cSrcweir         {
3505cdf0e10cSrcweir             ScDPItemData aItem;
3506cdf0e10cSrcweir             pMember->FillItemData(aItem);
3507cdf0e10cSrcweir             rData.addVisibleMember(GetName(), aItem);
3508cdf0e10cSrcweir             pMember->FillVisibilityData(rData);
3509cdf0e10cSrcweir         }
3510cdf0e10cSrcweir     }
3511cdf0e10cSrcweir }
3512cdf0e10cSrcweir 
3513cdf0e10cSrcweir // -----------------------------------------------------------------------
3514cdf0e10cSrcweir 
ScDPDataDimension(const ScDPResultData * pData)3515cdf0e10cSrcweir ScDPDataDimension::ScDPDataDimension( const ScDPResultData* pData ) :
3516cdf0e10cSrcweir 	pResultData( pData ),
3517cdf0e10cSrcweir 	pResultDimension( NULL ),
3518cdf0e10cSrcweir 	bIsDataLayout( sal_False )
3519cdf0e10cSrcweir {
3520cdf0e10cSrcweir }
3521cdf0e10cSrcweir 
~ScDPDataDimension()3522cdf0e10cSrcweir ScDPDataDimension::~ScDPDataDimension()
3523cdf0e10cSrcweir {
3524cdf0e10cSrcweir }
3525cdf0e10cSrcweir 
InitFrom(const ScDPResultDimension * pDim)3526cdf0e10cSrcweir void ScDPDataDimension::InitFrom( const ScDPResultDimension* pDim )
3527cdf0e10cSrcweir {
3528cdf0e10cSrcweir 	if (!pDim)
3529cdf0e10cSrcweir 		return;
3530cdf0e10cSrcweir 
3531cdf0e10cSrcweir     pResultDimension = pDim;
3532cdf0e10cSrcweir 	bIsDataLayout = pDim->IsDataLayout();
3533cdf0e10cSrcweir 
3534cdf0e10cSrcweir     // Go through all result members under the given result dimension, and
3535cdf0e10cSrcweir     // create a new data member instance for each result member.
3536cdf0e10cSrcweir 	long nCount = pDim->GetMemberCount();
3537cdf0e10cSrcweir 	for (long i=0; i<nCount; i++)
3538cdf0e10cSrcweir 	{
3539cdf0e10cSrcweir 		const ScDPResultMember* pResMem = pDim->GetMember(i);
3540cdf0e10cSrcweir 
3541cdf0e10cSrcweir 		ScDPDataMember* pNew = new ScDPDataMember( pResultData, pResMem );
3542cdf0e10cSrcweir 		aMembers.Insert( pNew, aMembers.Count() );
3543cdf0e10cSrcweir 
3544cdf0e10cSrcweir 		if ( !pResultData->IsLateInit() )
3545cdf0e10cSrcweir 		{
3546cdf0e10cSrcweir 			//	with LateInit, pResMem hasn't necessarily been initialized yet,
3547cdf0e10cSrcweir 			//	so InitFrom for the new result member is called from its ProcessData method
3548cdf0e10cSrcweir 
3549cdf0e10cSrcweir 			const ScDPResultDimension* pChildDim = pResMem->GetChildDimension();
3550cdf0e10cSrcweir 			if ( pChildDim )
3551cdf0e10cSrcweir 				pNew->InitFrom( pChildDim );
3552cdf0e10cSrcweir 		}
3553cdf0e10cSrcweir 	}
3554cdf0e10cSrcweir }
3555cdf0e10cSrcweir 
ProcessData(const vector<SCROW> & aDataMembers,const vector<ScDPValueData> & aValues,const ScDPSubTotalState & rSubState)3556cdf0e10cSrcweir void ScDPDataDimension::ProcessData( const vector< SCROW >& aDataMembers, const vector<ScDPValueData>& aValues,
3557cdf0e10cSrcweir                                      const ScDPSubTotalState& rSubState )
3558cdf0e10cSrcweir {
3559cdf0e10cSrcweir     // the ScDPItemData array must contain enough entries for all dimensions - this isn't checked
3560cdf0e10cSrcweir 
3561cdf0e10cSrcweir     long nCount = aMembers.Count();
3562cdf0e10cSrcweir     for (long i=0; i<nCount; i++)
3563cdf0e10cSrcweir     {
3564cdf0e10cSrcweir         ScDPDataMember* pMember = aMembers[(sal_uInt16)i];
3565cdf0e10cSrcweir 
3566cdf0e10cSrcweir         // always first member for data layout dim
3567cdf0e10cSrcweir         if ( bIsDataLayout || ( !aDataMembers.empty() && pMember->IsNamedItem(aDataMembers[0]) ) )
3568cdf0e10cSrcweir         {
3569cdf0e10cSrcweir             vector</*ScDPItemData*/SCROW> aChildDataMembers;
3570cdf0e10cSrcweir             if (aDataMembers.size() > 1)
3571cdf0e10cSrcweir             {
3572cdf0e10cSrcweir                 vector</*ScDPItemData*/SCROW >::const_iterator itr = aDataMembers.begin();
3573cdf0e10cSrcweir                 aChildDataMembers.insert(aChildDataMembers.begin(), ++itr, aDataMembers.end());
3574cdf0e10cSrcweir             }
3575cdf0e10cSrcweir             pMember->ProcessData( aChildDataMembers, aValues, rSubState );
3576cdf0e10cSrcweir             return;
3577cdf0e10cSrcweir         }
3578cdf0e10cSrcweir     }
3579cdf0e10cSrcweir 
3580cdf0e10cSrcweir     DBG_ERROR("ProcessData: Member not found");
3581cdf0e10cSrcweir }
3582cdf0e10cSrcweir 
FillDataRow(const ScDPResultDimension * pRefDim,uno::Sequence<sheet::DataResult> & rSequence,long nCol,long nMeasure,sal_Bool bIsSubTotalRow,const ScDPSubTotalState & rSubState) const3583cdf0e10cSrcweir void ScDPDataDimension::FillDataRow( const ScDPResultDimension* pRefDim,
3584cdf0e10cSrcweir 									uno::Sequence<sheet::DataResult>& rSequence,
3585cdf0e10cSrcweir 									long nCol, long nMeasure, sal_Bool bIsSubTotalRow,
3586cdf0e10cSrcweir 									const ScDPSubTotalState& rSubState ) const
3587cdf0e10cSrcweir {
3588cdf0e10cSrcweir 	DBG_ASSERT( pRefDim && pRefDim->GetMemberCount() == aMembers.Count(), "dimensions don't match" );
3589cdf0e10cSrcweir     DBG_ASSERT( pRefDim == pResultDimension, "wrong dim" );
3590cdf0e10cSrcweir 
3591cdf0e10cSrcweir     const ScMemberSortOrder& rMemberOrder = pRefDim->GetMemberOrder();
3592cdf0e10cSrcweir 
3593cdf0e10cSrcweir 	long nMemberMeasure = nMeasure;
3594cdf0e10cSrcweir 	long nMemberCol = nCol;
3595cdf0e10cSrcweir 	long nCount = aMembers.Count();
3596cdf0e10cSrcweir 	for (long i=0; i<nCount; i++)
3597cdf0e10cSrcweir 	{
3598cdf0e10cSrcweir 	    long nSorted = rMemberOrder.empty() ? i : rMemberOrder[i];
3599cdf0e10cSrcweir 
3600cdf0e10cSrcweir 		long nMemberPos = nSorted;
3601cdf0e10cSrcweir 		if (bIsDataLayout)
3602cdf0e10cSrcweir 		{
3603cdf0e10cSrcweir 			DBG_ASSERT(nMeasure == SC_DPMEASURE_ALL || pResultData->GetMeasureCount() == 1,
3604cdf0e10cSrcweir 						"DataLayout dimension twice?");
3605cdf0e10cSrcweir 			nMemberPos = 0;
3606cdf0e10cSrcweir 			nMemberMeasure = nSorted;
3607cdf0e10cSrcweir 		}
3608cdf0e10cSrcweir 
3609cdf0e10cSrcweir 		const ScDPResultMember* pRefMember = pRefDim->GetMember(nMemberPos);
3610cdf0e10cSrcweir 		if ( pRefMember->IsVisible() )	//! here or in ScDPDataMember::FillDataRow ???
3611cdf0e10cSrcweir 		{
3612cdf0e10cSrcweir 			const ScDPDataMember* pDataMember = aMembers[(sal_uInt16)nMemberPos];
3613cdf0e10cSrcweir 			pDataMember->FillDataRow( pRefMember, rSequence, nMemberCol, nMemberMeasure, bIsSubTotalRow, rSubState );
3614cdf0e10cSrcweir 			// nMemberCol is modified
3615cdf0e10cSrcweir 		}
3616cdf0e10cSrcweir 	}
3617cdf0e10cSrcweir }
3618cdf0e10cSrcweir 
UpdateDataRow(const ScDPResultDimension * pRefDim,long nMeasure,sal_Bool bIsSubTotalRow,const ScDPSubTotalState & rSubState) const3619cdf0e10cSrcweir void ScDPDataDimension::UpdateDataRow( const ScDPResultDimension* pRefDim,
3620cdf0e10cSrcweir                                     long nMeasure, sal_Bool bIsSubTotalRow,
3621cdf0e10cSrcweir                                     const ScDPSubTotalState& rSubState ) const
3622cdf0e10cSrcweir {
3623cdf0e10cSrcweir     DBG_ASSERT( pRefDim && pRefDim->GetMemberCount() == aMembers.Count(), "dimensions don't match" );
3624cdf0e10cSrcweir     DBG_ASSERT( pRefDim == pResultDimension, "wrong dim" );
3625cdf0e10cSrcweir 
3626cdf0e10cSrcweir     long nMemberMeasure = nMeasure;
3627cdf0e10cSrcweir     long nCount = aMembers.Count();
3628cdf0e10cSrcweir     for (long i=0; i<nCount; i++)
3629cdf0e10cSrcweir     {
3630cdf0e10cSrcweir         long nMemberPos = i;
3631cdf0e10cSrcweir         if (bIsDataLayout)
3632cdf0e10cSrcweir         {
3633cdf0e10cSrcweir             DBG_ASSERT(nMeasure == SC_DPMEASURE_ALL || pResultData->GetMeasureCount() == 1,
3634cdf0e10cSrcweir                         "DataLayout dimension twice?");
3635cdf0e10cSrcweir             nMemberPos = 0;
3636cdf0e10cSrcweir             nMemberMeasure = i;
3637cdf0e10cSrcweir         }
3638cdf0e10cSrcweir 
3639cdf0e10cSrcweir         // Calculate must be called even if the member is not visible (for use as reference value)
3640cdf0e10cSrcweir         const ScDPResultMember* pRefMember = pRefDim->GetMember(nMemberPos);
3641cdf0e10cSrcweir         ScDPDataMember* pDataMember = aMembers[(sal_uInt16)nMemberPos];
3642cdf0e10cSrcweir         pDataMember->UpdateDataRow( pRefMember, nMemberMeasure, bIsSubTotalRow, rSubState );
3643cdf0e10cSrcweir     }
3644cdf0e10cSrcweir }
3645cdf0e10cSrcweir 
SortMembers(ScDPResultDimension * pRefDim)3646cdf0e10cSrcweir void ScDPDataDimension::SortMembers( ScDPResultDimension* pRefDim )
3647cdf0e10cSrcweir {
3648cdf0e10cSrcweir     long nCount = aMembers.Count();
3649cdf0e10cSrcweir 
3650cdf0e10cSrcweir     if ( pRefDim->IsSortByData() )
3651cdf0e10cSrcweir     {
3652cdf0e10cSrcweir         // sort members
3653cdf0e10cSrcweir 
3654cdf0e10cSrcweir         ScMemberSortOrder& rMemberOrder = pRefDim->GetMemberOrder();
3655cdf0e10cSrcweir         DBG_ASSERT( rMemberOrder.empty(), "sort twice?" );
3656cdf0e10cSrcweir         rMemberOrder.resize( nCount );
3657cdf0e10cSrcweir         for (long nPos=0; nPos<nCount; nPos++)
3658cdf0e10cSrcweir             rMemberOrder[nPos] = nPos;
3659cdf0e10cSrcweir 
3660cdf0e10cSrcweir         ScDPColMembersOrder aComp( *this, pRefDim->GetSortMeasure(), pRefDim->IsSortAscending() );
3661cdf0e10cSrcweir         ::std::sort( rMemberOrder.begin(), rMemberOrder.end(), aComp );
3662cdf0e10cSrcweir     }
3663cdf0e10cSrcweir 
3664cdf0e10cSrcweir     // handle children
3665cdf0e10cSrcweir 
3666cdf0e10cSrcweir     DBG_ASSERT( pRefDim && pRefDim->GetMemberCount() == aMembers.Count(), "dimensions don't match" );
3667cdf0e10cSrcweir     DBG_ASSERT( pRefDim == pResultDimension, "wrong dim" );
3668cdf0e10cSrcweir 
3669cdf0e10cSrcweir     // for data layout, call only once - sorting measure is always taken from settings
3670cdf0e10cSrcweir     long nLoopCount = bIsDataLayout ? 1 : nCount;
3671cdf0e10cSrcweir     for (long i=0; i<nLoopCount; i++)
3672cdf0e10cSrcweir     {
3673cdf0e10cSrcweir         ScDPResultMember* pRefMember = pRefDim->GetMember(i);
3674cdf0e10cSrcweir         if ( pRefMember->IsVisible() )  //! here or in ScDPDataMember ???
3675cdf0e10cSrcweir         {
3676cdf0e10cSrcweir             ScDPDataMember* pDataMember = aMembers[(sal_uInt16)i];
3677cdf0e10cSrcweir             pDataMember->SortMembers( pRefMember );
3678cdf0e10cSrcweir         }
3679cdf0e10cSrcweir     }
3680cdf0e10cSrcweir }
3681cdf0e10cSrcweir 
DoAutoShow(ScDPResultDimension * pRefDim)3682cdf0e10cSrcweir void ScDPDataDimension::DoAutoShow( ScDPResultDimension* pRefDim )
3683cdf0e10cSrcweir {
3684cdf0e10cSrcweir     long nCount = aMembers.Count();
3685cdf0e10cSrcweir 
3686cdf0e10cSrcweir     // handle children first, before changing the visible state
3687cdf0e10cSrcweir 
3688cdf0e10cSrcweir     DBG_ASSERT( pRefDim && pRefDim->GetMemberCount() == aMembers.Count(), "dimensions don't match" );
3689cdf0e10cSrcweir     DBG_ASSERT( pRefDim == pResultDimension, "wrong dim" );
3690cdf0e10cSrcweir 
3691cdf0e10cSrcweir     // for data layout, call only once - sorting measure is always taken from settings
3692cdf0e10cSrcweir     long nLoopCount = bIsDataLayout ? 1 : nCount;
3693cdf0e10cSrcweir     for (long i=0; i<nLoopCount; i++)
3694cdf0e10cSrcweir     {
3695cdf0e10cSrcweir         ScDPResultMember* pRefMember = pRefDim->GetMember(i);
3696cdf0e10cSrcweir         if ( pRefMember->IsVisible() )  //! here or in ScDPDataMember ???
3697cdf0e10cSrcweir         {
3698cdf0e10cSrcweir             ScDPDataMember* pDataMember = aMembers[(sal_uInt16)i];
3699cdf0e10cSrcweir             pDataMember->DoAutoShow( pRefMember );
3700cdf0e10cSrcweir         }
3701cdf0e10cSrcweir     }
3702cdf0e10cSrcweir 
3703cdf0e10cSrcweir     if ( pRefDim->IsAutoShow() && pRefDim->GetAutoCount() > 0 && pRefDim->GetAutoCount() < nCount )
3704cdf0e10cSrcweir     {
3705cdf0e10cSrcweir         // establish temporary order, hide remaining members
3706cdf0e10cSrcweir 
3707cdf0e10cSrcweir         ScMemberSortOrder aAutoOrder;
3708cdf0e10cSrcweir         aAutoOrder.resize( nCount );
3709cdf0e10cSrcweir         long nPos;
3710cdf0e10cSrcweir         for (nPos=0; nPos<nCount; nPos++)
3711cdf0e10cSrcweir             aAutoOrder[nPos] = nPos;
3712cdf0e10cSrcweir 
3713cdf0e10cSrcweir         ScDPColMembersOrder aComp( *this, pRefDim->GetAutoMeasure(), !pRefDim->IsAutoTopItems() );
3714cdf0e10cSrcweir         ::std::sort( aAutoOrder.begin(), aAutoOrder.end(), aComp );
3715cdf0e10cSrcweir 
3716cdf0e10cSrcweir         // look for equal values to the last included one
3717cdf0e10cSrcweir 
3718cdf0e10cSrcweir         long nIncluded = pRefDim->GetAutoCount();
3719cdf0e10cSrcweir         ScDPDataMember* pDataMember1 = aMembers[(sal_uInt16)aAutoOrder[nIncluded - 1]];
3720cdf0e10cSrcweir         if ( !pDataMember1->IsVisible() )
3721cdf0e10cSrcweir             pDataMember1 = NULL;
3722cdf0e10cSrcweir         sal_Bool bContinue = sal_True;
3723cdf0e10cSrcweir         while ( bContinue )
3724cdf0e10cSrcweir         {
3725cdf0e10cSrcweir             bContinue = sal_False;
3726cdf0e10cSrcweir             if ( nIncluded < nCount )
3727cdf0e10cSrcweir             {
3728cdf0e10cSrcweir                 ScDPDataMember* pDataMember2 = aMembers[(sal_uInt16)aAutoOrder[nIncluded]];
3729cdf0e10cSrcweir                 if ( !pDataMember2->IsVisible() )
3730cdf0e10cSrcweir                     pDataMember2 = NULL;
3731cdf0e10cSrcweir 
3732cdf0e10cSrcweir                 if ( lcl_IsEqual( pDataMember1, pDataMember2, pRefDim->GetAutoMeasure() ) )
3733cdf0e10cSrcweir                 {
3734cdf0e10cSrcweir                     ++nIncluded;                // include more members if values are equal
3735cdf0e10cSrcweir                     bContinue = sal_True;
3736cdf0e10cSrcweir                 }
3737cdf0e10cSrcweir             }
3738cdf0e10cSrcweir         }
3739cdf0e10cSrcweir 
3740cdf0e10cSrcweir         // hide the remaining members
3741cdf0e10cSrcweir 
3742cdf0e10cSrcweir         for (nPos = nIncluded; nPos < nCount; nPos++)
3743cdf0e10cSrcweir         {
3744cdf0e10cSrcweir             ScDPResultMember* pMember = pRefDim->GetMember(aAutoOrder[nPos]);
3745cdf0e10cSrcweir             pMember->SetAutoHidden();
3746cdf0e10cSrcweir         }
3747cdf0e10cSrcweir     }
3748cdf0e10cSrcweir }
3749cdf0e10cSrcweir 
ResetResults()3750cdf0e10cSrcweir void ScDPDataDimension::ResetResults()
3751cdf0e10cSrcweir {
3752cdf0e10cSrcweir     long nCount = aMembers.Count();
3753cdf0e10cSrcweir     for (long i=0; i<nCount; i++)
3754cdf0e10cSrcweir     {
3755cdf0e10cSrcweir         //  sort order doesn't matter
3756cdf0e10cSrcweir 
3757cdf0e10cSrcweir         long nMemberPos = bIsDataLayout ? 0 : i;
3758cdf0e10cSrcweir         ScDPDataMember* pDataMember = aMembers[(sal_uInt16)nMemberPos];
3759cdf0e10cSrcweir         pDataMember->ResetResults();
3760cdf0e10cSrcweir     }
3761cdf0e10cSrcweir }
3762cdf0e10cSrcweir 
GetSortedIndex(long nUnsorted) const3763cdf0e10cSrcweir long ScDPDataDimension::GetSortedIndex( long nUnsorted ) const
3764cdf0e10cSrcweir {
3765cdf0e10cSrcweir     if (!pResultDimension)
3766cdf0e10cSrcweir        return nUnsorted;
3767cdf0e10cSrcweir 
3768cdf0e10cSrcweir     const ScMemberSortOrder& rMemberOrder = pResultDimension->GetMemberOrder();
3769cdf0e10cSrcweir     return rMemberOrder.empty() ? nUnsorted : rMemberOrder[nUnsorted];
3770cdf0e10cSrcweir }
3771cdf0e10cSrcweir 
UpdateRunningTotals(const ScDPResultDimension * pRefDim,long nMeasure,sal_Bool bIsSubTotalRow,const ScDPSubTotalState & rSubState,ScDPRunningTotalState & rRunning,ScDPRowTotals & rTotals,const ScDPResultMember & rRowParent) const3772cdf0e10cSrcweir void ScDPDataDimension::UpdateRunningTotals( const ScDPResultDimension* pRefDim,
3773cdf0e10cSrcweir                                     long nMeasure, sal_Bool bIsSubTotalRow,
3774cdf0e10cSrcweir                                     const ScDPSubTotalState& rSubState, ScDPRunningTotalState& rRunning,
3775cdf0e10cSrcweir                                     ScDPRowTotals& rTotals, const ScDPResultMember& rRowParent ) const
3776cdf0e10cSrcweir {
3777cdf0e10cSrcweir     DBG_ASSERT( pRefDim && pRefDim->GetMemberCount() == aMembers.Count(), "dimensions don't match" );
3778cdf0e10cSrcweir     DBG_ASSERT( pRefDim == pResultDimension, "wrong dim" );
3779cdf0e10cSrcweir 
3780cdf0e10cSrcweir     long nMemberMeasure = nMeasure;
3781cdf0e10cSrcweir     long nCount = aMembers.Count();
3782cdf0e10cSrcweir     for (long i=0; i<nCount; i++)
3783cdf0e10cSrcweir     {
3784cdf0e10cSrcweir         const ScMemberSortOrder& rMemberOrder = pRefDim->GetMemberOrder();
3785cdf0e10cSrcweir 	    long nSorted = rMemberOrder.empty() ? i : rMemberOrder[i];
3786cdf0e10cSrcweir 
3787cdf0e10cSrcweir         long nMemberPos = nSorted;
3788cdf0e10cSrcweir         if (bIsDataLayout)
3789cdf0e10cSrcweir         {
3790cdf0e10cSrcweir             DBG_ASSERT(nMeasure == SC_DPMEASURE_ALL || pResultData->GetMeasureCount() == 1,
3791cdf0e10cSrcweir                         "DataLayout dimension twice?");
3792cdf0e10cSrcweir             nMemberPos = 0;
3793cdf0e10cSrcweir             nMemberMeasure = nSorted;
3794cdf0e10cSrcweir         }
3795cdf0e10cSrcweir 
3796cdf0e10cSrcweir         const ScDPResultMember* pRefMember = pRefDim->GetMember(nMemberPos);
3797cdf0e10cSrcweir         if ( pRefMember->IsVisible() )  //! here or in ScDPDataMember::UpdateRunningTotals ???
3798cdf0e10cSrcweir         {
3799cdf0e10cSrcweir             if ( bIsDataLayout )
3800cdf0e10cSrcweir                 rRunning.AddColIndex( 0, 0 );
3801cdf0e10cSrcweir             else
3802cdf0e10cSrcweir                 rRunning.AddColIndex( i, nSorted );
3803cdf0e10cSrcweir 
3804cdf0e10cSrcweir             ScDPDataMember* pDataMember = aMembers[(sal_uInt16)nMemberPos];
3805cdf0e10cSrcweir             pDataMember->UpdateRunningTotals( pRefMember, nMemberMeasure,
3806cdf0e10cSrcweir                                             bIsSubTotalRow, rSubState, rRunning, rTotals, rRowParent );
3807cdf0e10cSrcweir 
3808cdf0e10cSrcweir             rRunning.RemoveColIndex();
3809cdf0e10cSrcweir         }
3810cdf0e10cSrcweir     }
3811cdf0e10cSrcweir }
3812cdf0e10cSrcweir 
DumpState(const ScDPResultDimension * pRefDim,ScDocument * pDoc,ScAddress & rPos) const3813cdf0e10cSrcweir void ScDPDataDimension::DumpState( const ScDPResultDimension* pRefDim, ScDocument* pDoc, ScAddress& rPos ) const
3814cdf0e10cSrcweir {
3815cdf0e10cSrcweir     String aDimName = String::CreateFromAscii( bIsDataLayout ? "(data layout)" : "(unknown)" );
3816cdf0e10cSrcweir     lcl_DumpRow( String::CreateFromAscii("ScDPDataDimension"), aDimName, NULL, pDoc, rPos );
3817cdf0e10cSrcweir 
3818cdf0e10cSrcweir     SCROW nStartRow = rPos.Row();
3819cdf0e10cSrcweir 
3820cdf0e10cSrcweir     long nCount = bIsDataLayout ? 1 : aMembers.Count();
3821cdf0e10cSrcweir     for (long i=0; i<nCount; i++)
3822cdf0e10cSrcweir     {
3823cdf0e10cSrcweir         const ScDPResultMember* pRefMember = pRefDim->GetMember(i);
3824cdf0e10cSrcweir         const ScDPDataMember* pDataMember = aMembers[(sal_uInt16)i];
3825cdf0e10cSrcweir         pDataMember->DumpState( pRefMember, pDoc, rPos );
3826cdf0e10cSrcweir     }
3827cdf0e10cSrcweir 
3828cdf0e10cSrcweir     lcl_Indent( pDoc, nStartRow, rPos );
3829cdf0e10cSrcweir }
3830cdf0e10cSrcweir 
GetMemberCount() const3831cdf0e10cSrcweir long ScDPDataDimension::GetMemberCount() const
3832cdf0e10cSrcweir {
3833cdf0e10cSrcweir     return aMembers.Count();
3834cdf0e10cSrcweir }
3835cdf0e10cSrcweir 
GetMember(long n) const3836cdf0e10cSrcweir ScDPDataMember* ScDPDataDimension::GetMember(long n) const
3837cdf0e10cSrcweir {
3838cdf0e10cSrcweir     return aMembers[(sal_uInt16)n];
3839cdf0e10cSrcweir }
3840cdf0e10cSrcweir 
3841cdf0e10cSrcweir // ----------------------------------------------------------------------------
3842cdf0e10cSrcweir 
ScDPResultVisibilityData(ScDPSource * pSource)3843cdf0e10cSrcweir ScDPResultVisibilityData::ScDPResultVisibilityData(
3844cdf0e10cSrcweir  ScDPSource* pSource) :
3845cdf0e10cSrcweir     mpSource(pSource)
3846cdf0e10cSrcweir {
3847cdf0e10cSrcweir }
3848cdf0e10cSrcweir 
~ScDPResultVisibilityData()3849cdf0e10cSrcweir ScDPResultVisibilityData::~ScDPResultVisibilityData()
3850cdf0e10cSrcweir {
3851cdf0e10cSrcweir }
3852cdf0e10cSrcweir 
addVisibleMember(const String & rDimName,const ScDPItemData & rMemberItem)3853cdf0e10cSrcweir void ScDPResultVisibilityData::addVisibleMember(const String& rDimName, const ScDPItemData& rMemberItem)
3854cdf0e10cSrcweir {
3855cdf0e10cSrcweir     DimMemberType::iterator itr = maDimensions.find(rDimName);
3856cdf0e10cSrcweir     if (itr == maDimensions.end())
3857cdf0e10cSrcweir     {
3858cdf0e10cSrcweir         pair<DimMemberType::iterator, bool> r = maDimensions.insert(
3859cdf0e10cSrcweir             DimMemberType::value_type(rDimName, VisibleMemberType()));
3860cdf0e10cSrcweir 
3861cdf0e10cSrcweir         if (!r.second)
3862cdf0e10cSrcweir             // insertion failed.
3863cdf0e10cSrcweir             return;
3864cdf0e10cSrcweir 
3865cdf0e10cSrcweir         itr = r.first;
3866cdf0e10cSrcweir     }
3867cdf0e10cSrcweir     VisibleMemberType& rMem = itr->second;
3868cdf0e10cSrcweir     VisibleMemberType::iterator itrMem = rMem.find(rMemberItem);
3869cdf0e10cSrcweir     if (itrMem == rMem.end())
3870cdf0e10cSrcweir         rMem.insert(rMemberItem);
3871cdf0e10cSrcweir }
3872cdf0e10cSrcweir 
fillFieldFilters(vector<ScDPCacheTable::Criterion> & rFilters) const3873cdf0e10cSrcweir void ScDPResultVisibilityData::fillFieldFilters(vector<ScDPCacheTable::Criterion>& rFilters) const
3874cdf0e10cSrcweir {
3875cdf0e10cSrcweir     typedef hash_map<String, long, ScStringHashCode> FieldNameMapType;
3876cdf0e10cSrcweir     FieldNameMapType aFieldNames;
3877cdf0e10cSrcweir     ScDPTableData* pData = mpSource->GetData();
3878cdf0e10cSrcweir     long nColumnCount = pData->GetColumnCount();
3879cdf0e10cSrcweir     for (long i = 0; i < nColumnCount; ++i)
3880cdf0e10cSrcweir     {
3881cdf0e10cSrcweir         aFieldNames.insert(
3882cdf0e10cSrcweir             FieldNameMapType::value_type(pData->getDimensionName(i), i));
3883cdf0e10cSrcweir     }
3884cdf0e10cSrcweir 
3885cdf0e10cSrcweir     const ScDPDimensions* pDims = mpSource->GetDimensionsObject();
3886cdf0e10cSrcweir     for (DimMemberType::const_iterator itr = maDimensions.begin(), itrEnd = maDimensions.end();
3887cdf0e10cSrcweir           itr != itrEnd; ++itr)
3888cdf0e10cSrcweir     {
3889cdf0e10cSrcweir         const String& rDimName = itr->first;
3890cdf0e10cSrcweir         ScDPCacheTable::Criterion aCri;
3891cdf0e10cSrcweir         FieldNameMapType::const_iterator itrField = aFieldNames.find(rDimName);
3892cdf0e10cSrcweir         if (itrField == aFieldNames.end())
3893cdf0e10cSrcweir             // This should never happen!
3894cdf0e10cSrcweir             continue;
3895cdf0e10cSrcweir 
3896cdf0e10cSrcweir         long nDimIndex = itrField->second;
3897cdf0e10cSrcweir         aCri.mnFieldIndex = static_cast<sal_Int32>(nDimIndex);
3898cdf0e10cSrcweir         aCri.mpFilter.reset(new ScDPCacheTable::GroupFilter(/*mrSharedString*/));
3899cdf0e10cSrcweir 
3900cdf0e10cSrcweir         ScDPCacheTable::GroupFilter* pGrpFilter =
3901cdf0e10cSrcweir             static_cast<ScDPCacheTable::GroupFilter*>(aCri.mpFilter.get());
3902cdf0e10cSrcweir 
3903cdf0e10cSrcweir         const VisibleMemberType& rMem = itr->second;
3904cdf0e10cSrcweir         for (VisibleMemberType::const_iterator itrMem = rMem.begin(), itrMemEnd = rMem.end();
3905cdf0e10cSrcweir               itrMem != itrMemEnd; ++itrMem)
3906cdf0e10cSrcweir         {
3907cdf0e10cSrcweir             const ScDPItemData& rMemItem = *itrMem;
3908cdf0e10cSrcweir             pGrpFilter->addMatchItem(rMemItem.GetString(), rMemItem.GetValue(), rMemItem.IsValue());
3909cdf0e10cSrcweir         }
3910cdf0e10cSrcweir 
3911cdf0e10cSrcweir         ScDPDimension* pDim = pDims->getByIndex(nDimIndex);
3912cdf0e10cSrcweir         ScDPMembers* pMembers = pDim->GetHierarchiesObject()->getByIndex(0)->
3913cdf0e10cSrcweir             GetLevelsObject()->getByIndex(0)->GetMembersObject();
3914cdf0e10cSrcweir         if (pGrpFilter->getMatchItemCount() < static_cast<size_t>(pMembers->getCount()))
3915cdf0e10cSrcweir             rFilters.push_back(aCri);
3916cdf0e10cSrcweir     }
3917cdf0e10cSrcweir }
3918cdf0e10cSrcweir 
operator ()(const ScDPItemData & r) const3919cdf0e10cSrcweir size_t ScDPResultVisibilityData::MemberHash::operator() (const ScDPItemData& r) const
3920cdf0e10cSrcweir {
3921cdf0e10cSrcweir     if (r.IsValue())
3922cdf0e10cSrcweir         return static_cast<size_t>(::rtl::math::approxFloor(r.GetValue()));
3923cdf0e10cSrcweir     else
3924cdf0e10cSrcweir         return rtl_ustr_hashCode_WithLength(r.GetString().GetBuffer(), r.GetString().Len());
3925cdf0e10cSrcweir }
3926cdf0e10cSrcweir // Wang Xu Ming -- 2009-6-10
3927cdf0e10cSrcweir // DataPilot Migration
GetDataId() const3928cdf0e10cSrcweir SCROW ScDPResultMember::GetDataId( ) const
3929cdf0e10cSrcweir {
3930cdf0e10cSrcweir  const ScDPMember*   pMemberDesc = GetDPMember();
3931cdf0e10cSrcweir   if (pMemberDesc)
3932cdf0e10cSrcweir         return  pMemberDesc->GetItemDataId();
3933cdf0e10cSrcweir     return -1;
3934cdf0e10cSrcweir }
3935cdf0e10cSrcweir 
AddMember(const ScDPParentDimData & aData)3936cdf0e10cSrcweir ScDPResultMember* ScDPResultDimension::AddMember(const ScDPParentDimData &aData )
3937cdf0e10cSrcweir {
3938cdf0e10cSrcweir 	ScDPResultMember* pMember = new ScDPResultMember( pResultData, aData, sal_False );
3939cdf0e10cSrcweir 	SCROW	nDataIndex = pMember->GetDataId();
3940cdf0e10cSrcweir 	maMemberArray.push_back( pMember );
3941cdf0e10cSrcweir 
3942cdf0e10cSrcweir 	if ( maMemberHash.end() == maMemberHash.find( nDataIndex ) )
3943cdf0e10cSrcweir 		maMemberHash.insert( std::pair< SCROW, ScDPResultMember *>( nDataIndex, pMember ) );
3944cdf0e10cSrcweir 	return pMember;
3945cdf0e10cSrcweir }
3946cdf0e10cSrcweir 
GetResultMember(ScDPDimension * pThisDim,ScDPLevel * pThisLevel)3947cdf0e10cSrcweir ResultMembers* ScDPResultDimension::GetResultMember( ScDPDimension* pThisDim, ScDPLevel* pThisLevel )
3948cdf0e10cSrcweir {
3949cdf0e10cSrcweir 	 ResultMembers* pResultMembers = new ResultMembers();
3950cdf0e10cSrcweir 	 // global order is used to initialize aMembers, so it doesn't have to be looked at later
3951cdf0e10cSrcweir 	 const ScMemberSortOrder& rGlobalOrder = pThisLevel->GetGlobalOrder();
3952cdf0e10cSrcweir 
3953cdf0e10cSrcweir 	 ScDPMembers* pMembers = pThisLevel->GetMembersObject();
3954cdf0e10cSrcweir 	 long nMembCount = pMembers->getCount();
3955cdf0e10cSrcweir 	 for ( long i=0; i<nMembCount; i++ )
3956cdf0e10cSrcweir 	 {
3957cdf0e10cSrcweir 		 long nSorted = rGlobalOrder.empty() ? i : rGlobalOrder[i];
3958cdf0e10cSrcweir 		 ScDPMember* pMember = pMembers->getByIndex(nSorted);
3959cdf0e10cSrcweir 		 if ( NULL == pResultMembers->FindMember( pMember->GetItemDataId() ) )
3960cdf0e10cSrcweir 		 {
3961cdf0e10cSrcweir 			ScDPParentDimData* pNew = new ScDPParentDimData( i, pThisDim, pThisLevel, pMember );
3962cdf0e10cSrcweir 			pResultMembers->InsertMember(  pNew );
3963cdf0e10cSrcweir 		 }
3964cdf0e10cSrcweir 	 }
3965cdf0e10cSrcweir 	 return pResultMembers;
3966cdf0e10cSrcweir }
3967cdf0e10cSrcweir 
InsertMember(ScDPParentDimData * pMemberData)3968cdf0e10cSrcweir ScDPResultMember* ScDPResultDimension::InsertMember(ScDPParentDimData *pMemberData)
3969cdf0e10cSrcweir {
3970cdf0e10cSrcweir     SCROW  nInsert = 0;
3971cdf0e10cSrcweir     if ( !lcl_SearchMember( maMemberArray, pMemberData->mnOrder , nInsert ) )
3972cdf0e10cSrcweir     { //Member not exist
3973cdf0e10cSrcweir         ScDPResultMember* pNew = new ScDPResultMember( pResultData, *pMemberData, sal_False );
3974cdf0e10cSrcweir         maMemberArray.insert( maMemberArray.begin()+nInsert, pNew );
3975cdf0e10cSrcweir 
3976cdf0e10cSrcweir         SCROW	nDataIndex = pMemberData->mpMemberDesc->GetItemDataId();
3977cdf0e10cSrcweir         if ( maMemberHash.end() == maMemberHash.find( nDataIndex ) )
3978cdf0e10cSrcweir             maMemberHash.insert( std::pair< SCROW, ScDPResultMember *>( nDataIndex, pNew ) );
3979cdf0e10cSrcweir         return pNew;
3980cdf0e10cSrcweir     }
3981cdf0e10cSrcweir     return maMemberArray[ nInsert ];
3982cdf0e10cSrcweir }
3983cdf0e10cSrcweir 
InitWithMembers(LateInitParams & rParams,const::std::vector<SCROW> & pItemData,size_t nPos,ScDPInitState & rInitState)3984cdf0e10cSrcweir void ScDPResultDimension::  InitWithMembers(  LateInitParams& rParams,
3985cdf0e10cSrcweir         const ::std::vector< SCROW >&     pItemData,
3986cdf0e10cSrcweir         size_t  nPos,
3987cdf0e10cSrcweir         ScDPInitState& rInitState  )
3988cdf0e10cSrcweir {
3989cdf0e10cSrcweir     if ( rParams.IsEnd( nPos ) )
3990cdf0e10cSrcweir         return;
3991cdf0e10cSrcweir     ScDPDimension* pThisDim        = rParams.GetDim( nPos );
3992cdf0e10cSrcweir     ScDPLevel*        pThisLevel      = rParams.GetLevel( nPos );
3993cdf0e10cSrcweir     SCROW             nDataID         = pItemData[nPos];
3994cdf0e10cSrcweir 
3995cdf0e10cSrcweir     if (pThisDim && pThisLevel)
3996cdf0e10cSrcweir     {
3997cdf0e10cSrcweir         long nDimSource = pThisDim->GetDimension();     //! check GetSourceDim?
3998cdf0e10cSrcweir 
3999cdf0e10cSrcweir         //	create all members at the first call (preserve order)
4000cdf0e10cSrcweir         ResultMembers* pMembers = pResultData->GetDimResultMembers(nDimSource, pThisDim, pThisLevel);
4001cdf0e10cSrcweir         ScDPGroupCompare aCompare( pResultData, rInitState, nDimSource );
4002cdf0e10cSrcweir         //	initialize only specific member (or all if "show empty" flag is set)
4003cdf0e10cSrcweir         ScDPResultMember* pResultMember = NULL;
4004cdf0e10cSrcweir         if ( bInitialized  )
4005cdf0e10cSrcweir             pResultMember = FindMember( nDataID );
4006cdf0e10cSrcweir         else
4007cdf0e10cSrcweir             bInitialized = sal_True;
4008cdf0e10cSrcweir 
4009cdf0e10cSrcweir         if ( pResultMember == NULL )
4010cdf0e10cSrcweir         { //only insert found item
4011cdf0e10cSrcweir             ScDPParentDimData* pMemberData = pMembers->FindMember( nDataID );
4012cdf0e10cSrcweir             if ( pMemberData && aCompare.IsIncluded( *( pMemberData->mpMemberDesc ) ) )
4013cdf0e10cSrcweir                 pResultMember = InsertMember( pMemberData );
4014cdf0e10cSrcweir         }
4015cdf0e10cSrcweir         if ( pResultMember )
4016cdf0e10cSrcweir         {
4017cdf0e10cSrcweir  //           DBG_TRACE( "ScDPResultDimension::InitWithMembers");
4018cdf0e10cSrcweir  //           DBG_TRACESTR( pResultMember->GetDPMember()->GetNameStr());
4019cdf0e10cSrcweir             rInitState.AddMember( nDimSource, pResultMember->GetDataId()  );
4020cdf0e10cSrcweir             pResultMember->LateInitFrom( rParams /*ppDim, ppLev*/, pItemData, nPos+1 , rInitState );
4021cdf0e10cSrcweir             rInitState.RemoveMember();
4022cdf0e10cSrcweir         }
4023cdf0e10cSrcweir     }
4024cdf0e10cSrcweir }
4025cdf0e10cSrcweir 
FindMember(const SCROW & nIndex) const4026cdf0e10cSrcweir ScDPParentDimData* ResultMembers::FindMember( const SCROW& nIndex ) const
4027cdf0e10cSrcweir {
4028cdf0e10cSrcweir 	DimMemberHash::const_iterator aRes = maMemberHash.find( nIndex );
4029cdf0e10cSrcweir 	if( aRes != maMemberHash.end()) {
4030cdf0e10cSrcweir 	   	if (  aRes->second->mpMemberDesc && aRes->second->mpMemberDesc->GetItemDataId()==nIndex )
4031cdf0e10cSrcweir 			return aRes->second;
4032cdf0e10cSrcweir 	}
4033cdf0e10cSrcweir 	return NULL;
4034cdf0e10cSrcweir }
InsertMember(ScDPParentDimData * pNew)4035cdf0e10cSrcweir void  ResultMembers::InsertMember(  ScDPParentDimData* pNew )
4036cdf0e10cSrcweir {
4037cdf0e10cSrcweir     if ( !pNew->mpMemberDesc->getShowDetails() )
4038cdf0e10cSrcweir 		mbHasHideDetailsMember = sal_True;
4039cdf0e10cSrcweir     maMemberHash.insert( std::pair< const SCROW, ScDPParentDimData *>( pNew->mpMemberDesc->GetItemDataId(), pNew ) );
4040cdf0e10cSrcweir }
4041cdf0e10cSrcweir 
ResultMembers()4042cdf0e10cSrcweir ResultMembers::ResultMembers():
4043cdf0e10cSrcweir 	mbHasHideDetailsMember( sal_False )
4044cdf0e10cSrcweir {
4045cdf0e10cSrcweir }
~ResultMembers()4046cdf0e10cSrcweir ResultMembers::~ResultMembers()
4047cdf0e10cSrcweir {
4048cdf0e10cSrcweir 	for ( DimMemberHash::const_iterator iter = maMemberHash.begin(); iter != maMemberHash.end(); iter++ )
4049cdf0e10cSrcweir 		delete iter->second;
4050cdf0e10cSrcweir }
4051cdf0e10cSrcweir // -----------------------------------------------------------------------
LateInitParams(const vector<ScDPDimension * > & ppDim,const vector<ScDPLevel * > & ppLev,sal_Bool bRow,sal_Bool bInitChild,sal_Bool bAllChildren)4052cdf0e10cSrcweir LateInitParams::LateInitParams( const vector<ScDPDimension*>& ppDim, const vector<ScDPLevel*>& ppLev, sal_Bool bRow, sal_Bool bInitChild, sal_Bool bAllChildren ):
4053cdf0e10cSrcweir     mppDim( ppDim ),
4054cdf0e10cSrcweir     mppLev( ppLev ),
4055cdf0e10cSrcweir     mbRow( bRow ),
4056cdf0e10cSrcweir     mbInitChild( bInitChild ),
4057cdf0e10cSrcweir     mbAllChildren( bAllChildren )
4058cdf0e10cSrcweir {
4059cdf0e10cSrcweir }
4060cdf0e10cSrcweir 
~LateInitParams()4061cdf0e10cSrcweir LateInitParams::~LateInitParams()
4062cdf0e10cSrcweir {
4063cdf0e10cSrcweir }
4064cdf0e10cSrcweir 
IsEnd(size_t nPos) const4065cdf0e10cSrcweir sal_Bool LateInitParams::IsEnd( size_t nPos ) const
4066cdf0e10cSrcweir {
4067cdf0e10cSrcweir     return nPos >= mppDim.size();
4068cdf0e10cSrcweir }
4069cdf0e10cSrcweir 
4070cdf0e10cSrcweir // End Comments
4071cdf0e10cSrcweir // Wang Xu Ming -- 2009-8-4
4072cdf0e10cSrcweir // DataPilot Migration - old defects merge
CheckShowEmpty(sal_Bool bShow)4073cdf0e10cSrcweir void ScDPResultDimension::CheckShowEmpty( sal_Bool bShow )
4074cdf0e10cSrcweir {
4075cdf0e10cSrcweir         long nCount = maMemberArray.size();
4076cdf0e10cSrcweir 
4077cdf0e10cSrcweir             ScDPResultMember* pMember = NULL;
4078cdf0e10cSrcweir                 for (long i=0; i<nCount; i++)
4079cdf0e10cSrcweir                 {
4080cdf0e10cSrcweir                             pMember = maMemberArray.at(i);
4081cdf0e10cSrcweir                                     pMember->CheckShowEmpty( bShow );
4082cdf0e10cSrcweir                 }
4083cdf0e10cSrcweir 
4084cdf0e10cSrcweir }
4085cdf0e10cSrcweir 
CheckShowEmpty(sal_Bool bShow)4086cdf0e10cSrcweir void ScDPResultMember::CheckShowEmpty( sal_Bool bShow )
4087cdf0e10cSrcweir {
4088cdf0e10cSrcweir         if ( bHasElements )
4089cdf0e10cSrcweir         {
4090cdf0e10cSrcweir                     ScDPResultDimension* pChildDim = GetChildDimension();
4091cdf0e10cSrcweir                             if (pChildDim )
4092cdf0e10cSrcweir                                             pChildDim->CheckShowEmpty();
4093cdf0e10cSrcweir         }
4094cdf0e10cSrcweir         else if ( IsValid() && bInitialized )
4095cdf0e10cSrcweir         {
4096cdf0e10cSrcweir                     bShow = bShow ||  (  GetParentLevel() && GetParentLevel()->getShowEmpty() );
4097cdf0e10cSrcweir                             if ( bShow )
4098cdf0e10cSrcweir                             {
4099cdf0e10cSrcweir                                             SetHasElements();
4100cdf0e10cSrcweir                                                         ScDPResultDimension* pChildDim = GetChildDimension();
4101cdf0e10cSrcweir                                                                     if (pChildDim )
4102cdf0e10cSrcweir                                                                                         pChildDim->CheckShowEmpty( sal_True );
4103cdf0e10cSrcweir                             }
4104cdf0e10cSrcweir         }
4105cdf0e10cSrcweir }// End Comments
4106