LCOV - code coverage report
Current view: top level - libreoffice/sc/source/core/data - dptabres.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 1220 1946 62.7 %
Date: 2012-12-17 Functions: 135 174 77.6 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10