LCOV - code coverage report
Current view: top level - sc/source/core/data - dptabres.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 1235 1946 63.5 %
Date: 2012-08-25 Functions: 135 174 77.6 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 951 2324 40.9 %

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

Generated by: LCOV version 1.10