LCOV - code coverage report
Current view: top level - sc/source/core/data - dptabsrc.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 999 1341 74.5 %
Date: 2014-11-03 Functions: 129 202 63.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "dptabsrc.hxx"
      21             : 
      22             : #include <algorithm>
      23             : #include <vector>
      24             : #include <set>
      25             : #include <boost/unordered_set.hpp>
      26             : #include <boost/unordered_map.hpp>
      27             : 
      28             : #include <rtl/math.hxx>
      29             : #include <svl/itemprop.hxx>
      30             : #include <svl/intitem.hxx>
      31             : #include <vcl/svapp.hxx>
      32             : 
      33             : #include "scitems.hxx"
      34             : #include "document.hxx"
      35             : #include "docpool.hxx"
      36             : #include "patattr.hxx"
      37             : #include "formulacell.hxx"
      38             : 
      39             : #include "dptabres.hxx"
      40             : #include "dptabdat.hxx"
      41             : #include "global.hxx"
      42             : #include "datauno.hxx"
      43             : #include "miscuno.hxx"
      44             : #include "unonames.hxx"
      45             : #include "dpitemdata.hxx"
      46             : #include "dputil.hxx"
      47             : #include "dpresfilter.hxx"
      48             : #include "calcmacros.hxx"
      49             : 
      50             : #include <com/sun/star/beans/PropertyAttribute.hpp>
      51             : #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
      52             : #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
      53             : #include <com/sun/star/sheet/DataPilotFieldReferenceType.hpp>
      54             : #include <com/sun/star/sheet/DataPilotFieldSortMode.hpp>
      55             : #include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
      56             : #include <com/sun/star/sheet/DataPilotFieldAutoShowInfo.hpp>
      57             : #include <com/sun/star/table/CellAddress.hpp>
      58             : 
      59             : #include <comphelper/string.hxx>
      60             : #include <unotools/collatorwrapper.hxx>
      61             : #include <unotools/calendarwrapper.hxx>
      62             : #include <com/sun/star/i18n/CalendarDisplayIndex.hpp>
      63             : 
      64             : using namespace com::sun::star;
      65             : using ::std::vector;
      66             : using ::std::set;
      67             : using ::com::sun::star::uno::Reference;
      68             : using ::com::sun::star::uno::Sequence;
      69             : using ::com::sun::star::uno::Any;
      70             : using ::com::sun::star::sheet::DataPilotFieldAutoShowInfo;
      71             : 
      72             : #define SC_MINCOUNT_LIMIT   1000000
      73             : 
      74           0 : SC_SIMPLE_SERVICE_INFO( ScDPSource,      "ScDPSource",      "com.sun.star.sheet.DataPilotSource" )
      75           0 : SC_SIMPLE_SERVICE_INFO( ScDPDimensions,  "ScDPDimensions",  "com.sun.star.sheet.DataPilotSourceDimensions" )
      76           0 : SC_SIMPLE_SERVICE_INFO( ScDPDimension,   "ScDPDimension",   "com.sun.star.sheet.DataPilotSourceDimension" )
      77           0 : SC_SIMPLE_SERVICE_INFO( ScDPHierarchies, "ScDPHierarchies", "com.sun.star.sheet.DataPilotSourceHierarcies" )
      78           0 : SC_SIMPLE_SERVICE_INFO( ScDPHierarchy,   "ScDPHierarchy",   "com.sun.star.sheet.DataPilotSourceHierarcy" )
      79           0 : SC_SIMPLE_SERVICE_INFO( ScDPLevels,      "ScDPLevels",      "com.sun.star.sheet.DataPilotSourceLevels" )
      80           0 : SC_SIMPLE_SERVICE_INFO( ScDPLevel,       "ScDPLevel",       "com.sun.star.sheet.DataPilotSourceLevel" )
      81           0 : SC_SIMPLE_SERVICE_INFO( ScDPMembers,     "ScDPMembers",     "com.sun.star.sheet.DataPilotSourceMembers" )
      82           0 : SC_SIMPLE_SERVICE_INFO( ScDPMember,      "ScDPMember",      "com.sun.star.sheet.DataPilotSourceMember" )
      83             : 
      84             : // property maps for PropertySetInfo
      85             : //  DataDescription / NumberFormat are internal
      86             : 
      87             : //! move to a header?
      88        2278 : static bool lcl_GetBoolFromAny( const uno::Any& aAny )
      89             : {
      90        2278 :     if ( aAny.getValueTypeClass() == uno::TypeClass_BOOLEAN )
      91        2278 :         return *(sal_Bool*)aAny.getValue();
      92           0 :     return false;
      93             : }
      94             : 
      95        7410 : static void lcl_SetBoolInAny( uno::Any& rAny, bool bValue )
      96             : {
      97        7410 :     rAny.setValue( &bValue, getBooleanCppuType() );
      98        7410 : }
      99             : 
     100         238 : ScDPSource::ScDPSource( ScDPTableData* pD ) :
     101             :     pData( pD ),
     102             :     pDimensions( NULL ),
     103             :     bColumnGrand( true ),       // default is true
     104             :     bRowGrand( true ),
     105             :     bIgnoreEmptyRows( false ),
     106             :     bRepeatIfEmpty( false ),
     107             :     nDupCount( 0 ),
     108             :     pResData( NULL ),
     109             :     pColResRoot( NULL ),
     110             :     pRowResRoot( NULL ),
     111             :     pColResults( NULL ),
     112             :     pRowResults( NULL ),
     113             :     bResultOverflow( false ),
     114         238 :     bPageFiltered( false )
     115             : {
     116         238 :     pData->SetEmptyFlags( bIgnoreEmptyRows, bRepeatIfEmpty );
     117         238 : }
     118             : 
     119         714 : ScDPSource::~ScDPSource()
     120             : {
     121         238 :     if (pDimensions)
     122         238 :         pDimensions->release();     // ref-counted
     123             : 
     124             :     //! free lists
     125             : 
     126         238 :     delete[] pColResults;
     127         238 :     delete[] pRowResults;
     128             : 
     129         238 :     delete pColResRoot;
     130         238 :     delete pRowResRoot;
     131         238 :     delete pResData;
     132         476 : }
     133             : 
     134         216 : const OUString* ScDPSource::GetGrandTotalName() const
     135             : {
     136         216 :     return mpGrandTotalName.get();
     137             : }
     138             : 
     139        6500 : sal_uInt16 ScDPSource::GetOrientation(long nColumn)
     140             : {
     141        6500 :     if (std::find(maColDims.begin(), maColDims.end(), nColumn) != maColDims.end())
     142        1594 :         return sheet::DataPilotFieldOrientation_COLUMN;
     143             : 
     144        4906 :     if (std::find(maRowDims.begin(), maRowDims.end(), nColumn) != maRowDims.end())
     145        2190 :         return sheet::DataPilotFieldOrientation_ROW;
     146             : 
     147        2716 :     if (std::find(maDataDims.begin(), maDataDims.end(), nColumn) != maDataDims.end())
     148        1102 :         return sheet::DataPilotFieldOrientation_DATA;
     149             : 
     150        1614 :     if (std::find(maPageDims.begin(), maPageDims.end(), nColumn) != maPageDims.end())
     151         128 :         return sheet::DataPilotFieldOrientation_PAGE;
     152             : 
     153        1486 :     return sheet::DataPilotFieldOrientation_HIDDEN;
     154             : }
     155             : 
     156          20 : long ScDPSource::GetDataDimensionCount()
     157             : {
     158          20 :     return maDataDims.size();
     159             : }
     160             : 
     161         262 : ScDPDimension* ScDPSource::GetDataDimension(long nIndex)
     162             : {
     163         262 :     if (nIndex < 0 || static_cast<size_t>(nIndex) >= maDataDims.size())
     164          22 :         return NULL;
     165             : 
     166         240 :     long nDimIndex = maDataDims[nIndex];
     167         240 :     return GetDimensionsObject()->getByIndex(nDimIndex);
     168             : }
     169             : 
     170          54 : OUString ScDPSource::GetDataDimName(long nIndex)
     171             : {
     172          54 :     OUString aRet;
     173          54 :     ScDPDimension* pDim = GetDataDimension(nIndex);
     174          54 :     if (pDim)
     175          54 :         aRet = pDim->getName();
     176          54 :     return aRet;
     177             : }
     178             : 
     179         894 : long ScDPSource::GetPosition(long nColumn)
     180             : {
     181         894 :     std::vector<long>::const_iterator it, itBeg = maColDims.begin(), itEnd = maColDims.end();
     182         894 :     it = std::find(itBeg, itEnd, nColumn);
     183         894 :     if (it != itEnd)
     184          98 :         return std::distance(itBeg, it);
     185             : 
     186         796 :     itBeg = maRowDims.begin();
     187         796 :     itEnd = maRowDims.end();
     188         796 :     it = std::find(itBeg, itEnd, nColumn);
     189         796 :     if (it != itEnd)
     190         252 :         return std::distance(itBeg, it);
     191             : 
     192         544 :     itBeg = maDataDims.begin();
     193         544 :     itEnd = maDataDims.end();
     194         544 :     it = std::find(itBeg, itEnd, nColumn);
     195         544 :     if (it != itEnd)
     196         170 :         return std::distance(itBeg, it);
     197             : 
     198         374 :     itBeg = maPageDims.begin();
     199         374 :     itEnd = maPageDims.end();
     200         374 :     it = std::find(itBeg, itEnd, nColumn);
     201         374 :     if (it != itEnd)
     202          54 :         return std::distance(itBeg, it);
     203             : 
     204         320 :     return 0;
     205             : }
     206             : 
     207             : namespace {
     208             : 
     209       19072 : bool testSubTotal( bool& rAllowed, long nColumn, const std::vector<long>& rDims, ScDPSource* pSource )
     210             : {
     211       19072 :     rAllowed = true;
     212       19072 :     std::vector<long>::const_iterator it = rDims.begin(), itEnd = rDims.end();
     213       24098 :     for (; it != itEnd; ++it)
     214             :     {
     215       19548 :         if (*it != nColumn)
     216        5026 :             continue;
     217             : 
     218       14522 :         if ( pSource->IsDataLayoutDimension(nColumn) )
     219             :         {
     220             :             //  no subtotals for data layout dim, no matter where
     221         580 :             rAllowed = false;
     222         580 :             return true;
     223             :         }
     224             : 
     225             :         //  no subtotals if no other dim but data layout follows
     226       13942 :         ++it;
     227       13942 :         if (it != itEnd && pSource->IsDataLayoutDimension(*it))
     228        1988 :             ++it;
     229       13942 :         if (it == itEnd)
     230       11316 :             rAllowed = false;
     231             : 
     232       13942 :         return true;    // found
     233             :     }
     234             : 
     235        4550 :     return false;
     236             : }
     237             : 
     238        7272 : void removeDim( long nRemove, std::vector<long>& rDims )
     239             : {
     240        7272 :     std::vector<long>::iterator it = std::find(rDims.begin(), rDims.end(), nRemove);
     241        7272 :     if (it != rDims.end())
     242           0 :         rDims.erase(it);
     243        7272 : }
     244             : 
     245             : }
     246             : 
     247       14522 : bool ScDPSource::SubTotalAllowed(long nColumn)
     248             : {
     249             :     //! cache this at ScDPResultData
     250       14522 :     bool bAllowed = true;
     251       14522 :     if ( testSubTotal(bAllowed, nColumn, maColDims, this) )
     252        9972 :         return bAllowed;
     253        4550 :     if ( testSubTotal(bAllowed, nColumn, maRowDims, this) )
     254        4550 :         return bAllowed;
     255           0 :     return bAllowed;
     256             : }
     257             : 
     258        1818 : void ScDPSource::SetOrientation(long nColumn, sal_uInt16 nNew)
     259             : {
     260             :     //! change to no-op if new orientation is equal to old?
     261             : 
     262             :     // remove from old list
     263        1818 :     removeDim(nColumn, maColDims);
     264        1818 :     removeDim(nColumn, maRowDims);
     265        1818 :     removeDim(nColumn, maDataDims);
     266        1818 :     removeDim(nColumn, maPageDims);
     267             : 
     268             :     // add to new list
     269        1818 :     switch (nNew)
     270             :     {
     271             :         case sheet::DataPilotFieldOrientation_COLUMN:
     272         100 :             maColDims.push_back(nColumn);
     273         100 :             break;
     274             :         case sheet::DataPilotFieldOrientation_ROW:
     275         260 :             maRowDims.push_back(nColumn);
     276         260 :             break;
     277             :         case sheet::DataPilotFieldOrientation_DATA:
     278         174 :             maDataDims.push_back(nColumn);
     279         174 :             break;
     280             :         case sheet::DataPilotFieldOrientation_PAGE:
     281          56 :             maPageDims.push_back(nColumn);
     282          56 :             break;
     283             :             // DataPilot Migration - Cache&&Performance
     284             :         case sheet::DataPilotFieldOrientation_HIDDEN:
     285        1228 :             break;
     286             :         default:
     287             :             OSL_FAIL( "ScDPSource::SetOrientation: unexpected orientation" );
     288           0 :             break;
     289             :     }
     290        1818 : }
     291             : 
     292       22298 : bool ScDPSource::IsDataLayoutDimension(long nDim)
     293             : {
     294       22298 :     return nDim == pData->GetColumnCount();
     295             : }
     296             : 
     297         352 : sal_uInt16 ScDPSource::GetDataLayoutOrientation()
     298             : {
     299         352 :     return GetOrientation(pData->GetColumnCount());
     300             : }
     301             : 
     302        4082 : bool ScDPSource::IsDateDimension(long nDim)
     303             : {
     304        4082 :     return pData->IsDateDimension(nDim);
     305             : }
     306             : 
     307        9052 : ScDPDimensions* ScDPSource::GetDimensionsObject()
     308             : {
     309        9052 :     if (!pDimensions)
     310             :     {
     311         256 :         pDimensions = new ScDPDimensions(this);
     312         256 :         pDimensions->acquire();                     // ref-counted
     313             :     }
     314        9052 :     return pDimensions;
     315             : }
     316             : 
     317        2410 : uno::Reference<container::XNameAccess> SAL_CALL ScDPSource::getDimensions() throw(uno::RuntimeException, std::exception)
     318             : {
     319        2410 :     return GetDimensionsObject();
     320             : }
     321             : 
     322          28 : void ScDPSource::SetDupCount( long nNew )
     323             : {
     324          28 :     nDupCount = nNew;
     325          28 : }
     326             : 
     327          10 : ScDPDimension* ScDPSource::AddDuplicated(long /* nSource */, const OUString& rNewName)
     328             : {
     329             :     OSL_ENSURE( pDimensions, "AddDuplicated without dimensions?" );
     330             : 
     331             :     //  re-use
     332             : 
     333          10 :     long nOldDimCount = pDimensions->getCount();
     334          40 :     for (long i=0; i<nOldDimCount; i++)
     335             :     {
     336          30 :         ScDPDimension* pDim = pDimensions->getByIndex(i);
     337          30 :         if (pDim && pDim->getName().equals(rNewName))
     338             :         {
     339             :             //! test if pDim is a duplicate of source
     340           0 :             return pDim;
     341             :         }
     342             :     }
     343             : 
     344          10 :     SetDupCount( nDupCount + 1 );
     345          10 :     pDimensions->CountChanged();        // uses nDupCount
     346             : 
     347          10 :     return pDimensions->getByIndex( pDimensions->getCount() - 1 );
     348             : }
     349             : 
     350       31114 : long ScDPSource::GetSourceDim(long nDim)
     351             : {
     352             :     //  original source dimension or data layout dimension?
     353       31114 :     if ( nDim <= pData->GetColumnCount() )
     354       31040 :         return nDim;
     355             : 
     356          74 :     if ( nDim < pDimensions->getCount() )
     357             :     {
     358          74 :         ScDPDimension* pDimObj = pDimensions->getByIndex( nDim );
     359          74 :         if ( pDimObj )
     360             :         {
     361          74 :             long nSource = pDimObj->GetSourceDim();
     362          74 :             if ( nSource >= 0 )
     363          74 :                 return nSource;
     364             :         }
     365             :     }
     366             : 
     367             :     OSL_FAIL("GetSourceDim: wrong dim");
     368           0 :     return nDim;
     369             : }
     370             : 
     371         176 : uno::Sequence< uno::Sequence<sheet::DataResult> > SAL_CALL ScDPSource::getResults()
     372             :                                                             throw(uno::RuntimeException, std::exception)
     373             : {
     374         176 :     CreateRes_Impl();       // create pColResRoot and pRowResRoot
     375             : 
     376         176 :     if ( bResultOverflow )      // set in CreateRes_Impl
     377             :     {
     378             :         //  no results available
     379           0 :         throw uno::RuntimeException();
     380             :     }
     381             : 
     382         176 :     long nColCount = pColResRoot->GetSize(pResData->GetColStartMeasure());
     383         176 :     long nRowCount = pRowResRoot->GetSize(pResData->GetRowStartMeasure());
     384             : 
     385             :     //  allocate full sequence
     386             :     //! leave out empty rows???
     387             : 
     388         176 :     uno::Sequence< uno::Sequence<sheet::DataResult> > aSeq( nRowCount );
     389         176 :     uno::Sequence<sheet::DataResult>* pRowAry = aSeq.getArray();
     390         994 :     for (long nRow = 0; nRow < nRowCount; nRow++)
     391             :     {
     392         818 :         uno::Sequence<sheet::DataResult> aColSeq( nColCount );
     393             :         //  use default values of DataResult
     394         818 :         pRowAry[nRow] = aColSeq;
     395         818 :     }
     396             : 
     397         352 :     ScDPResultFilterContext aFilterCxt;
     398             :     pRowResRoot->FillDataResults(
     399         176 :         pColResRoot, aFilterCxt, aSeq, pResData->GetRowStartMeasure());
     400             : 
     401         176 :     maResFilterSet.swap(aFilterCxt.maFilterSet); // Keep this data for GETPIVOTDATA.
     402             : 
     403         352 :     return aSeq;
     404             : }
     405             : 
     406          62 : uno::Sequence<double> ScDPSource::getFilteredResults(
     407             :             const uno::Sequence<sheet::DataPilotFieldFilter>& aFilters )
     408             :                 throw (uno::RuntimeException, std::exception)
     409             : {
     410          62 :     if (maResFilterSet.empty())
     411           2 :         getResults(); // Build result tree first.
     412             : 
     413             :     // Get result values from the tree.
     414          62 :     const ScDPResultTree::ValuesType* pVals = maResFilterSet.getResults(aFilters);
     415          62 :     if (pVals)
     416             :     {
     417          22 :         size_t n = pVals->size();
     418          22 :         uno::Sequence<double> aRet(n);
     419          56 :         for (size_t i = 0; i < n; ++i)
     420          34 :             aRet[i] = (*pVals)[i];
     421             : 
     422          22 :         return aRet;
     423             :     }
     424             : 
     425          40 :     if (aFilters.getLength() == 1)
     426             :     {
     427             :         // Try to get result from the leaf nodes.
     428          40 :         double fVal = maResFilterSet.getLeafResult(aFilters[0]);
     429          40 :         if (!rtl::math::isNan(fVal))
     430             :         {
     431          40 :             uno::Sequence<double> aRet(1);
     432          40 :             aRet[0] = fVal;
     433          40 :             return aRet;
     434             :         }
     435             :     }
     436             : 
     437           0 :     return uno::Sequence<double>();
     438             : }
     439             : 
     440          18 : void SAL_CALL ScDPSource::refresh() throw(uno::RuntimeException, std::exception)
     441             : {
     442          18 :     disposeData();
     443          18 : }
     444             : 
     445           0 : void SAL_CALL ScDPSource::addRefreshListener( const uno::Reference<util::XRefreshListener >& )
     446             :                                                 throw(uno::RuntimeException, std::exception)
     447             : {
     448             :     OSL_FAIL("not implemented");    //! exception?
     449           0 : }
     450             : 
     451           0 : void SAL_CALL ScDPSource::removeRefreshListener( const uno::Reference<util::XRefreshListener >& )
     452             :                                                 throw(uno::RuntimeException, std::exception)
     453             : {
     454             :     OSL_FAIL("not implemented");    //! exception?
     455           0 : }
     456             : 
     457         266 : Sequence< Sequence<Any> > SAL_CALL ScDPSource::getDrillDownData(const Sequence<sheet::DataPilotFieldFilter>& aFilters)
     458             :     throw (uno::RuntimeException, std::exception)
     459             : {
     460         266 :     long nColumnCount = GetData()->GetColumnCount();
     461             : 
     462         266 :     vector<ScDPFilteredCache::Criterion> aFilterCriteria;
     463         266 :     sal_Int32 nFilterCount = aFilters.getLength();
     464        1186 :     for (sal_Int32 i = 0; i < nFilterCount; ++i)
     465             :     {
     466         920 :         const sheet::DataPilotFieldFilter& rFilter = aFilters[i];
     467         920 :         const OUString& aFieldName = rFilter.FieldName;
     468        5520 :         for (long nCol = 0; nCol < nColumnCount; ++nCol)
     469             :         {
     470        4600 :             if (aFieldName.equals(pData->getDimensionName(nCol)))
     471             :             {
     472         920 :                 ScDPDimension* pDim = GetDimensionsObject()->getByIndex( nCol );
     473         920 :                 ScDPMembers* pMembers = pDim->GetHierarchiesObject()->getByIndex(0)->
     474         920 :                                         GetLevelsObject()->getByIndex(0)->GetMembersObject();
     475         920 :                 sal_Int32 nIndex = pMembers->GetIndexFromName( rFilter.MatchValue );
     476         920 :                 if ( nIndex >= 0 )
     477             :                 {
     478         920 :                     ScDPItemData aItem;
     479         920 :                     pMembers->getByIndex(nIndex)->FillItemData( aItem );
     480         920 :                     aFilterCriteria.push_back( ScDPFilteredCache::Criterion() );
     481         920 :                     aFilterCriteria.back().mnFieldIndex = nCol;
     482         920 :                     aFilterCriteria.back().mpFilter.reset(
     483        1840 :                         new ScDPFilteredCache::SingleFilter(aItem));
     484             :                 }
     485             :             }
     486             :         }
     487             :     }
     488             : 
     489             :     // Take into account the visibilities of field members.
     490         532 :     ScDPResultVisibilityData aResVisData(this);
     491         266 :     pRowResRoot->FillVisibilityData(aResVisData);
     492         266 :     pColResRoot->FillVisibilityData(aResVisData);
     493         266 :     aResVisData.fillFieldFilters(aFilterCriteria);
     494             : 
     495         266 :     Sequence< Sequence<Any> > aTabData;
     496         532 :     boost::unordered_set<sal_Int32> aCatDims;
     497         266 :     GetCategoryDimensionIndices(aCatDims);
     498         266 :     pData->GetDrillDownData(aFilterCriteria, aCatDims, aTabData);
     499         532 :     return aTabData;
     500             : }
     501             : 
     502         174 : OUString ScDPSource::getDataDescription()
     503             : {
     504         174 :     CreateRes_Impl();       // create pResData
     505             : 
     506         174 :     OUString aRet;
     507         174 :     if ( pResData->GetMeasureCount() == 1 )
     508             :     {
     509         156 :         bool bTotalResult = false;
     510         156 :         aRet = pResData->GetMeasureString(0, true, SUBTOTAL_FUNC_NONE, bTotalResult);
     511             :     }
     512             : 
     513             :     //  empty for more than one measure
     514             : 
     515         174 :     return aRet;
     516             : }
     517             : 
     518         254 : void ScDPSource::setIgnoreEmptyRows(bool bSet)
     519             : {
     520         254 :     bIgnoreEmptyRows = bSet;
     521         254 :     pData->SetEmptyFlags( bIgnoreEmptyRows, bRepeatIfEmpty );
     522         254 : }
     523             : 
     524         254 : void ScDPSource::setRepeatIfEmpty(bool bSet)
     525             : {
     526         254 :     bRepeatIfEmpty = bSet;
     527         254 :     pData->SetEmptyFlags( bIgnoreEmptyRows, bRepeatIfEmpty );
     528         254 : }
     529             : 
     530          18 : void ScDPSource::disposeData()
     531             : {
     532          18 :     maResFilterSet.clear();
     533             : 
     534          18 :     if ( pResData )
     535             :     {
     536             :         //  reset all data...
     537             : 
     538          18 :         DELETEZ(pColResRoot);
     539          18 :         DELETEZ(pRowResRoot);
     540          18 :         DELETEZ(pResData);
     541          18 :         delete[] pColResults;
     542          18 :         delete[] pRowResults;
     543          18 :         pColResults = NULL;
     544          18 :         pRowResults = NULL;
     545          18 :         aColLevelList.clear();
     546          18 :         aRowLevelList.clear();
     547             :     }
     548             : 
     549          18 :     if ( pDimensions )
     550             :     {
     551          18 :         pDimensions->release(); // ref-counted
     552          18 :         pDimensions = NULL;     //  settings have to be applied (from SaveData) again!
     553             :     }
     554          18 :     SetDupCount( 0 );
     555             : 
     556          18 :     maColDims.clear();
     557          18 :     maRowDims.clear();
     558          18 :     maDataDims.clear();
     559          18 :     maPageDims.clear();
     560             : 
     561          18 :     pData->DisposeData();   // cached entries etc.
     562          18 :     bPageFiltered = false;
     563          18 :     bResultOverflow = false;
     564          18 : }
     565             : 
     566         352 : static long lcl_CountMinMembers(const vector<ScDPDimension*>& ppDim, const vector<ScDPLevel*>& ppLevel, long nLevels )
     567             : {
     568             :     //  Calculate the product of the member count for those consecutive levels that
     569             :     //  have the "show all" flag, one following level, and the data layout dimension.
     570             : 
     571         352 :     long nTotal = 1;
     572         352 :     long nDataCount = 1;
     573         352 :     bool bWasShowAll = true;
     574         352 :     long nPos = nLevels;
     575         980 :     while ( nPos > 0 )
     576             :     {
     577         276 :         --nPos;
     578             : 
     579         276 :         if ( nPos+1 < nLevels && ppDim[nPos] == ppDim[nPos+1] )
     580             :         {
     581             :             OSL_FAIL("lcl_CountMinMembers: multiple levels from one dimension not implemented");
     582           0 :             return 0;
     583             :         }
     584             : 
     585         276 :         bool bDo = false;
     586         276 :         if ( ppDim[nPos]->getIsDataLayoutDimension() )
     587             :         {
     588             :             //  data layout dim doesn't interfere with "show all" flags
     589          18 :             nDataCount = ppLevel[nPos]->GetMembersObject()->getCount();
     590          18 :             if ( nDataCount == 0 )
     591           0 :                 nDataCount = 1;
     592             :         }
     593         258 :         else if ( bWasShowAll )     // "show all" set for all following levels?
     594             :         {
     595         222 :             bDo = true;
     596         222 :             if ( !ppLevel[nPos]->getShowEmpty() )
     597             :             {
     598             :                 //  this level is counted, following ones are not
     599         222 :                 bWasShowAll = false;
     600             :             }
     601             :         }
     602         276 :         if ( bDo )
     603             :         {
     604         222 :             long nThisCount = ppLevel[nPos]->GetMembersObject()->getMinMembers();
     605         222 :             if ( nThisCount == 0 )
     606             :             {
     607           0 :                 nTotal = 1;         //  empty level -> start counting from here
     608             :                                     //! start with visible elements in this level?
     609             :             }
     610             :             else
     611             :             {
     612         222 :                 if ( nTotal >= LONG_MAX / nThisCount )
     613           0 :                     return LONG_MAX;                        //  overflow
     614         222 :                 nTotal *= nThisCount;
     615             :             }
     616             :         }
     617             :     }
     618             : 
     619             :     //  always include data layout dim, even after restarting
     620         352 :     if ( nTotal >= LONG_MAX / nDataCount )
     621           0 :         return LONG_MAX;                        //  overflow
     622         352 :     nTotal *= nDataCount;
     623             : 
     624         352 :     return nTotal;
     625             : }
     626             : 
     627           8 : static long lcl_GetIndexFromName( const OUString& rName, const uno::Sequence<OUString>& rElements )
     628             : {
     629           8 :     long nCount = rElements.getLength();
     630           8 :     const OUString* pArray = rElements.getConstArray();
     631           8 :     for (long nPos=0; nPos<nCount; nPos++)
     632           8 :         if (pArray[nPos] == rName)
     633           8 :             return nPos;
     634             : 
     635           0 :     return -1;  // not found
     636             : }
     637             : 
     638         352 : void ScDPSource::FillCalcInfo(bool bIsRow, ScDPTableData::CalcInfo& rInfo, bool &rHasAutoShow)
     639             : {
     640         352 :     const std::vector<long>& rDims = bIsRow ? maRowDims : maColDims;
     641         352 :     std::vector<long>::const_iterator it = rDims.begin(), itEnd = rDims.end();
     642         706 :     for (; it != itEnd; ++it)
     643             :     {
     644         354 :         ScDPDimension* pDim = GetDimensionsObject()->getByIndex(*it);
     645         354 :         long nHierarchy = pDim->getUsedHierarchy();
     646         354 :         if ( nHierarchy >= pDim->GetHierarchiesObject()->getCount() )
     647           0 :             nHierarchy = 0;
     648         354 :         ScDPLevels* pLevels = pDim->GetHierarchiesObject()->getByIndex(nHierarchy)->GetLevelsObject();
     649         354 :         long nCount = pLevels->getCount();
     650             : 
     651             :         //! Test
     652         354 :         if (pDim->getIsDataLayoutDimension() && maDataDims.size() < 2)
     653          78 :             nCount = 0;
     654             :         //! Test
     655             : 
     656         630 :         for (long j = 0; j < nCount; ++j)
     657             :         {
     658         276 :             ScDPLevel* pLevel = pLevels->getByIndex(j);
     659         276 :             pLevel->EvaluateSortOrder();
     660             : 
     661             :             // no layout flags for column fields, only for row fields
     662         276 :             pLevel->SetEnableLayout( bIsRow );
     663             : 
     664         276 :             if ( pLevel->GetAutoShow().IsEnabled )
     665           2 :                 rHasAutoShow = true;
     666             : 
     667         276 :             if (bIsRow)
     668             :             {
     669         178 :                 rInfo.aRowLevelDims.push_back(*it);
     670         178 :                 rInfo.aRowDims.push_back(pDim);
     671         178 :                 rInfo.aRowLevels.push_back(pLevel);
     672             :             }
     673             :             else
     674             :             {
     675          98 :                 rInfo.aColLevelDims.push_back(*it);
     676          98 :                 rInfo.aColDims.push_back(pDim);
     677          98 :                 rInfo.aColLevels.push_back(pLevel);
     678             :             }
     679             : 
     680         276 :             pLevel->GetMembersObject();                 // initialize for groups
     681             :         }
     682             :     }
     683         352 : }
     684             : 
     685             : namespace {
     686             : 
     687             : class CategoryDimInserter : std::unary_function<long, void>
     688             : {
     689             :     ScDPSource& mrSource;
     690             :     boost::unordered_set<sal_Int32>& mrCatDims;
     691             : public:
     692         274 :     CategoryDimInserter(ScDPSource& rSource, boost::unordered_set<sal_Int32>& rCatDims) :
     693             :         mrSource(rSource),
     694         274 :         mrCatDims(rCatDims) {}
     695             : 
     696        1082 :     void operator() (long nDim)
     697             :     {
     698        1082 :         if (!mrSource.IsDataLayoutDimension(nDim))
     699        1074 :             mrCatDims.insert(nDim);
     700        1082 :     }
     701             : };
     702             : 
     703             : }
     704             : 
     705         274 : void ScDPSource::GetCategoryDimensionIndices(boost::unordered_set<sal_Int32>& rCatDims)
     706             : {
     707         274 :     boost::unordered_set<sal_Int32> aCatDims;
     708             : 
     709         274 :     CategoryDimInserter aInserter(*this, aCatDims);
     710         274 :     std::for_each(maColDims.begin(), maColDims.end(), aInserter);
     711         274 :     std::for_each(maRowDims.begin(), maRowDims.end(), aInserter);
     712         274 :     std::for_each(maPageDims.begin(), maPageDims.end(), aInserter);
     713             : 
     714         274 :     rCatDims.swap(aCatDims);
     715         274 : }
     716             : 
     717         176 : void ScDPSource::FilterCacheByPageDimensions()
     718             : {
     719             :     // #i117661# Repeated calls to ScDPFilteredCache::filterByPageDimension
     720             :     // are invalid because rows are only hidden, never shown again. If
     721             :     // FilterCacheByPageDimensions is called again, the cache table must
     722             :     // be re-initialized. Currently, CreateRes_Impl always uses a fresh cache
     723             :     // because ScDBDocFunc::DataPilotUpdate calls InvalidateData.
     724             : 
     725         176 :     if (bPageFiltered)
     726             :     {
     727             :         SAL_WARN( "sc.core","tried to apply page field filters several times");
     728             : 
     729           0 :         pData->DisposeData();
     730           0 :         pData->CreateCacheTable();  // re-initialize the cache table
     731           0 :         bPageFiltered = false;
     732             :     }
     733             : 
     734             :     // filter table by page dimensions.
     735         176 :     vector<ScDPFilteredCache::Criterion> aCriteria;
     736         176 :     vector<long>::const_iterator it = maPageDims.begin(), itEnd = maPageDims.end();
     737         230 :     for (; it != itEnd; ++it)
     738             :     {
     739          54 :         ScDPDimension* pDim = GetDimensionsObject()->getByIndex(*it);
     740          54 :         long nField = pDim->GetDimension();
     741             : 
     742          54 :         ScDPMembers* pMems = pDim->GetHierarchiesObject()->getByIndex(0)->
     743          54 :             GetLevelsObject()->getByIndex(0)->GetMembersObject();
     744             : 
     745          54 :         long nMemCount = pMems->getCount();
     746          54 :         ScDPFilteredCache::Criterion aFilter;
     747          54 :         aFilter.mnFieldIndex = static_cast<sal_Int32>(nField);
     748          54 :         aFilter.mpFilter.reset(new ScDPFilteredCache::GroupFilter);
     749             :         ScDPFilteredCache::GroupFilter* pGrpFilter =
     750          54 :             static_cast<ScDPFilteredCache::GroupFilter*>(aFilter.mpFilter.get());
     751         276 :         for (long j = 0; j < nMemCount; ++j)
     752             :         {
     753         222 :             ScDPMember* pMem = pMems->getByIndex(j);
     754         222 :             if (pMem->isVisible())
     755             :             {
     756         206 :                 ScDPItemData aData;
     757         206 :                 pMem->FillItemData(aData);
     758         206 :                 pGrpFilter->addMatchItem(aData);
     759             :             }
     760             :         }
     761          54 :         if (pGrpFilter->getMatchItemCount() < static_cast<size_t>(nMemCount))
     762             :             // there is at least one invisible item.  Add this filter criterion to the mix.
     763           8 :             aCriteria.push_back(aFilter);
     764             : 
     765          54 :         if (!pDim->HasSelectedPage())
     766          54 :             continue;
     767             : 
     768           0 :         const ScDPItemData& rData = pDim->GetSelectedData();
     769           0 :         aCriteria.push_back(ScDPFilteredCache::Criterion());
     770           0 :         ScDPFilteredCache::Criterion& r = aCriteria.back();
     771           0 :         r.mnFieldIndex = static_cast<sal_Int32>(nField);
     772           0 :         r.mpFilter.reset(new ScDPFilteredCache::SingleFilter(rData));
     773           0 :     }
     774         176 :     if (!aCriteria.empty())
     775             :     {
     776           8 :         boost::unordered_set<sal_Int32> aCatDims;
     777           8 :         GetCategoryDimensionIndices(aCatDims);
     778           8 :         pData->FilterCacheTable(aCriteria, aCatDims);
     779           8 :         bPageFiltered = true;
     780         176 :     }
     781         176 : }
     782             : 
     783         500 : void ScDPSource::CreateRes_Impl()
     784             : {
     785         500 :     if (pResData)
     786         648 :         return;
     787             : 
     788         176 :     sal_uInt16 nDataOrient = GetDataLayoutOrientation();
     789         176 :     if (maDataDims.size() > 1 && ( nDataOrient != sheet::DataPilotFieldOrientation_COLUMN &&
     790             :                                 nDataOrient != sheet::DataPilotFieldOrientation_ROW ) )
     791             :     {
     792             :         //  if more than one data dimension, data layout orientation must be set
     793           0 :         SetOrientation( pData->GetColumnCount(), sheet::DataPilotFieldOrientation_ROW );
     794           0 :         nDataOrient = sheet::DataPilotFieldOrientation_ROW;
     795             :     }
     796             : 
     797             :     // TODO: Aggreate pDataNames, pDataRefValues, nDataRefOrient, and
     798             :     // eDataFunctions into a structure and use vector instead of static
     799             :     // or pointer arrays.
     800         176 :     vector<OUString> aDataNames;
     801         352 :     vector<sheet::DataPilotFieldReference> aDataRefValues;
     802         352 :     vector<ScSubTotalFunc> aDataFunctions;
     803         352 :     vector<sal_uInt16> aDataRefOrient;
     804             : 
     805         352 :     ScDPTableData::CalcInfo aInfo;
     806             : 
     807             :     //  LateInit (initialize only those rows/children that are used) can be used unless
     808             :     //  any data dimension needs reference values from column/row dimensions
     809         176 :     bool bLateInit = true;
     810             : 
     811             :     // Go through all data dimensions (i.e. fields) and build their meta data
     812             :     // so that they can be passed on to ScDPResultData instance later.
     813             :     // TODO: aggregate all of data dimension info into a structure.
     814         176 :     vector<long>::const_iterator it = maDataDims.begin(), itEnd = maDataDims.end();
     815         348 :     for (; it != itEnd; ++it)
     816             :     {
     817             :         // Get function for each data field.
     818         172 :         long nDimIndex = *it;
     819         172 :         ScDPDimension* pDim = GetDimensionsObject()->getByIndex(nDimIndex);
     820         172 :         sheet::GeneralFunction eUser = (sheet::GeneralFunction)pDim->getFunction();
     821         172 :         if (eUser == sheet::GeneralFunction_AUTO)
     822             :         {
     823             :             //! test for numeric data
     824          54 :             eUser = sheet::GeneralFunction_SUM;
     825             :         }
     826             : 
     827             :         // Map UNO's enum to internal enum ScSubTotalFunc.
     828         172 :         aDataFunctions.push_back(ScDPUtil::toSubTotalFunc(eUser));
     829             : 
     830             :         // Get reference field/item information.
     831         172 :         aDataRefValues.push_back(pDim->GetReferenceValue());
     832         172 :         sal_uInt16 nDataRefOrient = sheet::DataPilotFieldOrientation_HIDDEN;    // default if not used
     833         172 :         sal_Int32 eRefType = aDataRefValues.back().ReferenceType;
     834         172 :         if ( eRefType == sheet::DataPilotFieldReferenceType::ITEM_DIFFERENCE ||
     835         168 :              eRefType == sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE ||
     836         166 :              eRefType == sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE ||
     837             :              eRefType == sheet::DataPilotFieldReferenceType::RUNNING_TOTAL )
     838             :         {
     839             :             long nColumn = lcl_GetIndexFromName(
     840           8 :                 aDataRefValues.back().ReferenceField, GetDimensionsObject()->getElementNames());
     841           8 :             if ( nColumn >= 0 )
     842             :             {
     843           8 :                 nDataRefOrient = GetOrientation(nColumn);
     844             :                 //  need fully initialized results to find reference values
     845             :                 //  (both in column or row dimensions), so updated values or
     846             :                 //  differences to 0 can be displayed even for empty results.
     847           8 :                 bLateInit = false;
     848             :             }
     849             :         }
     850             : 
     851         172 :         aDataRefOrient.push_back(nDataRefOrient);
     852             : 
     853         172 :         aDataNames.push_back(pDim->getName());
     854             : 
     855             :         //! modify user visible strings as in ScDPResultData::GetMeasureString instead!
     856             : 
     857         172 :         aDataNames.back() = ScDPUtil::getSourceDimensionName(aDataNames.back());
     858             : 
     859             :         //! if the name is overridden by user, a flag must be set
     860             :         //! so the user defined name replaces the function string and field name.
     861             : 
     862             :         //! the complete name (function and field) must be stored at the dimension
     863             : 
     864         172 :         long nSource = pDim->GetSourceDim();
     865         172 :         if (nSource >= 0)
     866          10 :             aInfo.aDataSrcCols.push_back(nSource);
     867             :         else
     868         162 :             aInfo.aDataSrcCols.push_back(nDimIndex);
     869             :     }
     870             : 
     871         176 :     pResData = new ScDPResultData(*this);
     872         176 :     pResData->SetMeasureData(aDataFunctions, aDataRefValues, aDataRefOrient, aDataNames);
     873         176 :     pResData->SetDataLayoutOrientation(nDataOrient);
     874         176 :     pResData->SetLateInit( bLateInit );
     875             : 
     876         176 :     bool bHasAutoShow = false;
     877             : 
     878         352 :     ScDPInitState aInitState;
     879             : 
     880             :     // Page field selections restrict the members shown in related fields
     881             :     // (both in column and row fields). aInitState is filled with the page
     882             :     // field selections, they are kept across the data iterator loop.
     883             : 
     884         230 :     for (it = maPageDims.begin(), itEnd = maPageDims.end(); it != itEnd; ++it)
     885             :     {
     886          54 :         ScDPDimension* pDim = GetDimensionsObject()->getByIndex(*it);
     887          54 :         if ( pDim->HasSelectedPage() )
     888           0 :             aInitState.AddMember(*it, GetMemberId(*it, pDim->GetSelectedData()));
     889             :     }
     890             : 
     891             :     // Show grand total columns only when the option is set *and* there is at
     892             :     // least one column field.  Same for the grand total rows.
     893         176 :     sal_uInt16 nDataLayoutOrient = GetDataLayoutOrientation();
     894         176 :     long nColDimCount2 = maColDims.size() - (nDataLayoutOrient == sheet::DataPilotFieldOrientation_COLUMN ? 1 : 0);
     895         176 :     long nRowDimCount2 = maRowDims.size() - (nDataLayoutOrient == sheet::DataPilotFieldOrientation_ROW ? 1 : 0);
     896         176 :     bool bShowColGrand = bColumnGrand && nColDimCount2 > 0;
     897         176 :     bool bShowRowGrand = bRowGrand && nRowDimCount2 > 0;
     898         176 :     pColResRoot = new ScDPResultMember(pResData, bShowColGrand);
     899         176 :     pRowResRoot = new ScDPResultMember(pResData, bShowRowGrand);
     900             : 
     901         176 :     FillCalcInfo(false, aInfo, bHasAutoShow);
     902         176 :     long nColLevelCount = aInfo.aColLevels.size();
     903             : 
     904         176 :     pColResRoot->InitFrom( aInfo.aColDims, aInfo.aColLevels, 0, aInitState );
     905         176 :     pColResRoot->SetHasElements();
     906             : 
     907         176 :     FillCalcInfo(true, aInfo, bHasAutoShow);
     908         176 :     long nRowLevelCount = aInfo.aRowLevels.size();
     909             : 
     910         176 :     if ( nRowLevelCount > 0 )
     911             :     {
     912             :         // disable layout flags for the innermost row field (level)
     913         146 :         aInfo.aRowLevels[nRowLevelCount-1]->SetEnableLayout( false );
     914             :     }
     915             : 
     916         176 :     pRowResRoot->InitFrom( aInfo.aRowDims, aInfo.aRowLevels, 0, aInitState );
     917         176 :     pRowResRoot->SetHasElements();
     918             : 
     919             :     // initialize members object also for all page dimensions (needed for numeric groups)
     920         230 :     for (it = maPageDims.begin(), itEnd = maPageDims.end(); it != itEnd; ++it)
     921             :     {
     922          54 :         ScDPDimension* pDim = GetDimensionsObject()->getByIndex(*it);
     923          54 :         long nHierarchy = pDim->getUsedHierarchy();
     924          54 :         if ( nHierarchy >= pDim->GetHierarchiesObject()->getCount() )
     925           0 :             nHierarchy = 0;
     926             : 
     927          54 :         ScDPLevels* pLevels = pDim->GetHierarchiesObject()->getByIndex(nHierarchy)->GetLevelsObject();
     928          54 :         long nCount = pLevels->getCount();
     929         108 :         for (long j=0; j<nCount; j++)
     930          54 :             pLevels->getByIndex(j)->GetMembersObject();             // initialize for groups
     931             :     }
     932             : 
     933             :     //  pre-check: calculate minimum number of result columns / rows from
     934             :     //  levels that have the "show all" flag set
     935             : 
     936         176 :     long nMinColMembers = lcl_CountMinMembers( aInfo.aColDims, aInfo.aColLevels, nColLevelCount );
     937         176 :     long nMinRowMembers = lcl_CountMinMembers( aInfo.aRowDims, aInfo.aRowLevels, nRowLevelCount );
     938             : 
     939         176 :     if ( nMinColMembers > MAXCOLCOUNT/*SC_MINCOUNT_LIMIT*/ || nMinRowMembers > SC_MINCOUNT_LIMIT )
     940             :     {
     941             :         //  resulting table is too big -> abort before calculating
     942             :         //  (this relies on late init, so no members are allocated in InitFrom above)
     943             : 
     944           0 :         bResultOverflow = true;
     945           0 :         return;
     946             :     }
     947             : 
     948         176 :     FilterCacheByPageDimensions();
     949             : 
     950         176 :     aInfo.aPageDims.reserve(maPageDims.size());
     951         230 :     for (it = maPageDims.begin(), itEnd = maPageDims.end(); it != itEnd; ++it)
     952          54 :         aInfo.aPageDims.push_back(*it);
     953             : 
     954         176 :     aInfo.pInitState = &aInitState;
     955         176 :     aInfo.pColRoot   = pColResRoot;
     956         176 :     aInfo.pRowRoot   = pRowResRoot;
     957         176 :     pData->CalcResults(aInfo, false);
     958             : 
     959         176 :     pColResRoot->CheckShowEmpty();
     960         176 :     pRowResRoot->CheckShowEmpty();
     961             : 
     962             :     //  With all data processed, calculate the final results:
     963             : 
     964             :     //  UpdateDataResults calculates all original results from the collected values,
     965             :     //  and stores them as reference values if needed.
     966         176 :     pRowResRoot->UpdateDataResults( pColResRoot, pResData->GetRowStartMeasure() );
     967             : 
     968         176 :     if ( bHasAutoShow )     // do the double calculation only if AutoShow is used
     969             :     {
     970             :         //  Find the desired members and set bAutoHidden flag for the others
     971           2 :         pRowResRoot->DoAutoShow( pColResRoot );
     972             : 
     973             :         //  Reset all results to empty, so they can be built again with data for the
     974             :         //  desired members only.
     975           2 :         pColResRoot->ResetResults();
     976           2 :         pRowResRoot->ResetResults();
     977           2 :         pData->CalcResults(aInfo, true);
     978             : 
     979             :         //  Call UpdateDataResults again, with the new (limited) values.
     980           2 :         pRowResRoot->UpdateDataResults( pColResRoot, pResData->GetRowStartMeasure() );
     981             :     }
     982             : 
     983             :     //  SortMembers does the sorting by a result dimension, using the original results,
     984             :     //  but not running totals etc.
     985         176 :     pRowResRoot->SortMembers( pColResRoot );
     986             : 
     987             :     //  UpdateRunningTotals calculates running totals along column/row dimensions,
     988             :     //  differences from other members (named or relative), and column/row percentages
     989             :     //  or index values.
     990             :     //  Running totals and relative differences need to be done using the sorted values.
     991             :     //  Column/row percentages and index values must be done after sorting, because the
     992             :     //  results may no longer be in the right order (row total for percentage of row is
     993             :     //  always 1).
     994         352 :     ScDPRunningTotalState aRunning( pColResRoot, pRowResRoot );
     995         352 :     ScDPRowTotals aTotals;
     996         352 :     pRowResRoot->UpdateRunningTotals( pColResRoot, pResData->GetRowStartMeasure(), aRunning, aTotals );
     997             : }
     998             : 
     999         300 : void ScDPSource::FillLevelList( sal_uInt16 nOrientation, std::vector<ScDPLevel*> &rList )
    1000             : {
    1001         300 :     rList.clear();
    1002             : 
    1003         300 :     std::vector<long>* pDimIndex = NULL;
    1004         300 :     switch (nOrientation)
    1005             :     {
    1006             :         case sheet::DataPilotFieldOrientation_COLUMN:
    1007         150 :             pDimIndex = &maColDims;
    1008         150 :             break;
    1009             :         case sheet::DataPilotFieldOrientation_ROW:
    1010         150 :             pDimIndex = &maRowDims;
    1011         150 :             break;
    1012             :         case sheet::DataPilotFieldOrientation_DATA:
    1013           0 :             pDimIndex = &maDataDims;
    1014           0 :             break;
    1015             :         case sheet::DataPilotFieldOrientation_PAGE:
    1016           0 :             pDimIndex = &maPageDims;
    1017           0 :             break;
    1018             :         default:
    1019             :             OSL_FAIL( "ScDPSource::FillLevelList: unexpected orientation" );
    1020           0 :             break;
    1021             :     }
    1022         300 :     if (!pDimIndex)
    1023             :     {
    1024             :         OSL_FAIL("invalid orientation");
    1025         300 :         return;
    1026             :     }
    1027             : 
    1028         300 :     ScDPDimensions* pDims = GetDimensionsObject();
    1029         300 :     std::vector<long>::const_iterator it = pDimIndex->begin(), itEnd = pDimIndex->end();
    1030         650 :     for (; it != itEnd; ++it)
    1031             :     {
    1032         350 :         ScDPDimension* pDim = pDims->getByIndex(*it);
    1033             :         OSL_ENSURE( pDim->getOrientation() == nOrientation, "orientations are wrong" );
    1034             : 
    1035         350 :         ScDPHierarchies* pHiers = pDim->GetHierarchiesObject();
    1036         350 :         long nHierarchy = pDim->getUsedHierarchy();
    1037         350 :         if ( nHierarchy >= pHiers->getCount() )
    1038           0 :             nHierarchy = 0;
    1039         350 :         ScDPHierarchy* pHier = pHiers->getByIndex(nHierarchy);
    1040         350 :         ScDPLevels* pLevels = pHier->GetLevelsObject();
    1041         350 :         long nLevCount = pLevels->getCount();
    1042         700 :         for (long nLev=0; nLev<nLevCount; nLev++)
    1043             :         {
    1044         350 :             ScDPLevel* pLevel = pLevels->getByIndex(nLev);
    1045         350 :             rList.push_back(pLevel);
    1046             :         }
    1047             :     }
    1048             : }
    1049             : 
    1050         446 : void ScDPSource::FillMemberResults()
    1051             : {
    1052         446 :     if ( !pColResults && !pRowResults )
    1053             :     {
    1054         150 :         CreateRes_Impl();
    1055             : 
    1056         150 :         if ( bResultOverflow )      // set in CreateRes_Impl
    1057             :         {
    1058             :             //  no results available -> abort (leave empty)
    1059             :             //  exception is thrown in ScDPSource::getResults
    1060         446 :             return;
    1061             :         }
    1062             : 
    1063         150 :         FillLevelList( sheet::DataPilotFieldOrientation_COLUMN, aColLevelList );
    1064         150 :         long nColLevelCount = aColLevelList.size();
    1065         150 :         if (nColLevelCount)
    1066             :         {
    1067          90 :             long nColDimSize = pColResRoot->GetSize(pResData->GetColStartMeasure());
    1068          90 :             pColResults = new uno::Sequence<sheet::MemberResult>[nColLevelCount];
    1069         188 :             for (long i=0; i<nColLevelCount; i++)
    1070          98 :                 pColResults[i].realloc(nColDimSize);
    1071             : 
    1072          90 :             long nPos = 0;
    1073             :             pColResRoot->FillMemberResults( pColResults, nPos, pResData->GetColStartMeasure(),
    1074          90 :                                             true, NULL, NULL );
    1075             :         }
    1076             : 
    1077         150 :         FillLevelList( sheet::DataPilotFieldOrientation_ROW, aRowLevelList );
    1078         150 :         long nRowLevelCount = aRowLevelList.size();
    1079         150 :         if (nRowLevelCount)
    1080             :         {
    1081         146 :             long nRowDimSize = pRowResRoot->GetSize(pResData->GetRowStartMeasure());
    1082         146 :             pRowResults = new uno::Sequence<sheet::MemberResult>[nRowLevelCount];
    1083         398 :             for (long i=0; i<nRowLevelCount; i++)
    1084         252 :                 pRowResults[i].realloc(nRowDimSize);
    1085             : 
    1086         146 :             long nPos = 0;
    1087             :             pRowResRoot->FillMemberResults( pRowResults, nPos, pResData->GetRowStartMeasure(),
    1088         146 :                                             true, NULL, NULL );
    1089             :         }
    1090             :     }
    1091             : }
    1092             : 
    1093         446 : const uno::Sequence<sheet::MemberResult>* ScDPSource::GetMemberResults( ScDPLevel* pLevel )
    1094             : {
    1095         446 :     FillMemberResults();
    1096             : 
    1097         446 :     long i = 0;
    1098         446 :     long nColCount = aColLevelList.size();
    1099         630 :     for (i=0; i<nColCount; i++)
    1100             :     {
    1101         288 :         ScDPLevel* pColLevel = aColLevelList[i];
    1102         288 :         if ( pColLevel == pLevel )
    1103         104 :             return pColResults+i;
    1104             :     }
    1105         342 :     long nRowCount = aRowLevelList.size();
    1106         560 :     for (i=0; i<nRowCount; i++)
    1107             :     {
    1108         560 :         ScDPLevel* pRowLevel = aRowLevelList[i];
    1109         560 :         if ( pRowLevel == pLevel )
    1110         342 :             return pRowResults+i;
    1111             :     }
    1112           0 :     return NULL;
    1113             : }
    1114             : 
    1115             : // XPropertySet
    1116             : 
    1117           0 : uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDPSource::getPropertySetInfo()
    1118             :                                                         throw(uno::RuntimeException, std::exception)
    1119             : {
    1120           0 :     SolarMutexGuard aGuard;
    1121             :     using beans::PropertyAttribute::READONLY;
    1122             : 
    1123             :     static const SfxItemPropertyMapEntry aDPSourceMap_Impl[] =
    1124             :     {
    1125           0 :         { OUString(SC_UNO_DP_COLGRAND), 0,  getBooleanCppuType(),              0, 0 },
    1126           0 :         { OUString(SC_UNO_DP_DATADESC), 0,  cppu::UnoType<OUString>::get(),    beans::PropertyAttribute::READONLY, 0 },
    1127           0 :         { OUString(SC_UNO_DP_IGNOREEMPTY), 0,  getBooleanCppuType(),              0, 0 },     // for sheet data only
    1128           0 :         { OUString(SC_UNO_DP_REPEATEMPTY), 0,  getBooleanCppuType(),              0, 0 },     // for sheet data only
    1129           0 :         { OUString(SC_UNO_DP_ROWGRAND), 0,  getBooleanCppuType(),              0, 0 },
    1130           0 :         { OUString(SC_UNO_DP_ROWFIELDCOUNT),    0, cppu::UnoType<sal_Int32>::get(), READONLY, 0 },
    1131           0 :         { OUString(SC_UNO_DP_COLUMNFIELDCOUNT), 0, cppu::UnoType<sal_Int32>::get(), READONLY, 0 },
    1132           0 :         { OUString(SC_UNO_DP_DATAFIELDCOUNT),   0, cppu::UnoType<sal_Int32>::get(), READONLY, 0 },
    1133           0 :         { OUString(SC_UNO_DP_GRANDTOTAL_NAME),  0, cppu::UnoType<OUString>::get(), 0, 0 },
    1134             :         { OUString(), 0, css::uno::Type(), 0, 0 }
    1135           0 :     };
    1136             :     static uno::Reference<beans::XPropertySetInfo> aRef =
    1137           0 :         new SfxItemPropertySetInfo( aDPSourceMap_Impl );
    1138           0 :     return aRef;
    1139             : }
    1140             : 
    1141        1020 : void SAL_CALL ScDPSource::setPropertyValue( const OUString& aPropertyName, const uno::Any& aValue )
    1142             :                 throw(beans::UnknownPropertyException, beans::PropertyVetoException,
    1143             :                         lang::IllegalArgumentException, lang::WrappedTargetException,
    1144             :                         uno::RuntimeException, std::exception)
    1145             : {
    1146        1020 :     if (aPropertyName.equalsAscii(SC_UNO_DP_COLGRAND))
    1147         256 :         bColumnGrand = lcl_GetBoolFromAny(aValue);
    1148         764 :     else if (aPropertyName.equalsAscii(SC_UNO_DP_ROWGRAND))
    1149         256 :         bRowGrand = lcl_GetBoolFromAny(aValue);
    1150         508 :     else if (aPropertyName.equalsAscii(SC_UNO_DP_IGNOREEMPTY))
    1151         254 :         setIgnoreEmptyRows( lcl_GetBoolFromAny( aValue ) );
    1152         254 :     else if (aPropertyName.equalsAscii(SC_UNO_DP_REPEATEMPTY))
    1153         254 :         setRepeatIfEmpty( lcl_GetBoolFromAny( aValue ) );
    1154           0 :     else if (aPropertyName.equalsAscii(SC_UNO_DP_GRANDTOTAL_NAME))
    1155             :     {
    1156           0 :         OUString aName;
    1157           0 :         if (aValue >>= aName)
    1158           0 :             mpGrandTotalName.reset(new OUString(aName));
    1159             :     }
    1160             :     else
    1161             :     {
    1162             :         OSL_FAIL("unknown property");
    1163             :         //! THROW( UnknownPropertyException() );
    1164             :     }
    1165        1020 : }
    1166             : 
    1167        2524 : uno::Any SAL_CALL ScDPSource::getPropertyValue( const OUString& aPropertyName )
    1168             :                 throw(beans::UnknownPropertyException, lang::WrappedTargetException,
    1169             :                         uno::RuntimeException, std::exception)
    1170             : {
    1171        2524 :     uno::Any aRet;
    1172        2524 :     if ( aPropertyName.equalsAscii( SC_UNO_DP_COLGRAND ) )
    1173         654 :         lcl_SetBoolInAny(aRet, bColumnGrand);
    1174        1870 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_ROWGRAND ) )
    1175         654 :         lcl_SetBoolInAny(aRet, bRowGrand);
    1176        1216 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_IGNOREEMPTY ) )
    1177           0 :         lcl_SetBoolInAny(aRet, bIgnoreEmptyRows);
    1178        1216 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_REPEATEMPTY ) )
    1179           0 :         lcl_SetBoolInAny(aRet, bRepeatIfEmpty);
    1180        1216 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_DATADESC ) )             // read-only
    1181         174 :         aRet <<= getDataDescription();
    1182        1042 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_ROWFIELDCOUNT ) )        // read-only
    1183           0 :         aRet <<= static_cast<sal_Int32>(maRowDims.size());
    1184        1042 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_COLUMNFIELDCOUNT ) )     // read-only
    1185           0 :         aRet <<= static_cast<sal_Int32>(maColDims.size());
    1186        1042 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_DATAFIELDCOUNT ) )       // read-only
    1187        1042 :         aRet <<= static_cast<sal_Int32>(maDataDims.size());
    1188           0 :     else if (aPropertyName.equalsAscii(SC_UNO_DP_GRANDTOTAL_NAME))
    1189             :     {
    1190           0 :         if (mpGrandTotalName.get())
    1191           0 :             aRet <<= *mpGrandTotalName;
    1192             :     }
    1193             :     else
    1194             :     {
    1195             :         OSL_FAIL("unknown property");
    1196             :         //! THROW( UnknownPropertyException() );
    1197             :     }
    1198        2524 :     return aRet;
    1199             : }
    1200             : 
    1201             : #if DEBUG_PIVOT_TABLE
    1202             : void ScDPSource::DumpResults() const
    1203             : {
    1204             :     std::cout << "+++++ column root" << std::endl;
    1205             :     pColResRoot->Dump(1);
    1206             :     std::cout << "+++++ row root" << std::endl;
    1207             :     pRowResRoot->Dump(1);
    1208             : }
    1209             : #endif
    1210             : 
    1211           0 : SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDPSource )
    1212             : 
    1213         256 : ScDPDimensions::ScDPDimensions( ScDPSource* pSrc ) :
    1214             :     pSource( pSrc ),
    1215         256 :     ppDims( NULL )
    1216             : {
    1217             :     //! hold pSource
    1218             : 
    1219             :     // include data layout dimension and duplicated dimensions
    1220         256 :     nDimCount = pSource->GetData()->GetColumnCount() + 1 + pSource->GetDupCount();
    1221         256 : }
    1222             : 
    1223         768 : ScDPDimensions::~ScDPDimensions()
    1224             : {
    1225             :     //! release pSource
    1226             : 
    1227         256 :     if (ppDims)
    1228             :     {
    1229        1436 :         for (long i=0; i<nDimCount; i++)
    1230        1180 :             if ( ppDims[i] )
    1231        1180 :                 ppDims[i]->release();           // ref-counted
    1232         256 :         delete[] ppDims;
    1233             :     }
    1234         512 : }
    1235             : 
    1236          10 : void ScDPDimensions::CountChanged()
    1237             : {
    1238             :     // include data layout dimension and duplicated dimensions
    1239          10 :     long nNewCount = pSource->GetData()->GetColumnCount() + 1 + pSource->GetDupCount();
    1240          10 :     if ( ppDims )
    1241             :     {
    1242             :         long i;
    1243          10 :         long nCopy = std::min( nNewCount, nDimCount );
    1244          10 :         ScDPDimension** ppNew = new ScDPDimension*[nNewCount];
    1245             : 
    1246          40 :         for (i=0; i<nCopy; i++)             // copy existing dims
    1247          30 :             ppNew[i] = ppDims[i];
    1248          20 :         for (i=nCopy; i<nNewCount; i++)     // clear additional pointers
    1249          10 :             ppNew[i] = NULL;
    1250          10 :         for (i=nCopy; i<nDimCount; i++)     // delete old dims if count is decreased
    1251           0 :             if ( ppDims[i] )
    1252           0 :                 ppDims[i]->release();       // ref-counted
    1253             : 
    1254          10 :         delete[] ppDims;
    1255          10 :         ppDims = ppNew;
    1256             :     }
    1257          10 :     nDimCount = nNewCount;
    1258          10 : }
    1259             : 
    1260             : // very simple XNameAccess implementation using getCount/getByIndex
    1261             : 
    1262       11320 : uno::Any SAL_CALL ScDPDimensions::getByName( const OUString& aName )
    1263             :             throw(container::NoSuchElementException,
    1264             :                     lang::WrappedTargetException, uno::RuntimeException, std::exception)
    1265             : {
    1266       11320 :     long nCount = getCount();
    1267       35242 :     for (long i=0; i<nCount; i++)
    1268       35242 :         if ( getByIndex(i)->getName() == aName )
    1269             :         {
    1270       11320 :             uno::Reference<container::XNamed> xNamed = getByIndex(i);
    1271       22640 :             uno::Any aRet;
    1272       11320 :             aRet <<= xNamed;
    1273       33960 :             return aRet;
    1274             :         }
    1275             : 
    1276           0 :     throw container::NoSuchElementException();
    1277             : //    return uno::Any();
    1278             : }
    1279             : 
    1280        2346 : uno::Sequence<OUString> SAL_CALL ScDPDimensions::getElementNames() throw(uno::RuntimeException, std::exception)
    1281             : {
    1282        2346 :     long nCount = getCount();
    1283        2346 :     uno::Sequence<OUString> aSeq(nCount);
    1284        2346 :     OUString* pArr = aSeq.getArray();
    1285       15832 :     for (long i=0; i<nCount; i++)
    1286       13486 :         pArr[i] = getByIndex(i)->getName();
    1287        2346 :     return aSeq;
    1288             : }
    1289             : 
    1290           0 : sal_Bool SAL_CALL ScDPDimensions::hasByName( const OUString& aName ) throw(uno::RuntimeException, std::exception)
    1291             : {
    1292           0 :     long nCount = getCount();
    1293           0 :     for (long i=0; i<nCount; i++)
    1294           0 :         if ( getByIndex(i)->getName() == aName )
    1295           0 :             return sal_True;
    1296           0 :     return false;
    1297             : }
    1298             : 
    1299           0 : uno::Type SAL_CALL ScDPDimensions::getElementType() throw(uno::RuntimeException, std::exception)
    1300             : {
    1301           0 :     return cppu::UnoType<container::XNamed>::get();
    1302             : }
    1303             : 
    1304           0 : sal_Bool SAL_CALL ScDPDimensions::hasElements() throw(uno::RuntimeException, std::exception)
    1305             : {
    1306           0 :     return ( getCount() > 0 );
    1307             : }
    1308             : 
    1309             : // end of XNameAccess implementation
    1310             : 
    1311       13760 : long ScDPDimensions::getCount() const
    1312             : {
    1313             :     //  in tabular data, every column of source data is a dimension
    1314             : 
    1315       13760 :     return nDimCount;
    1316             : }
    1317             : 
    1318       67644 : ScDPDimension* ScDPDimensions::getByIndex(long nIndex) const
    1319             : {
    1320       67644 :     if ( nIndex >= 0 && nIndex < nDimCount )
    1321             :     {
    1322       67644 :         if ( !ppDims )
    1323             :         {
    1324         256 :             ((ScDPDimensions*)this)->ppDims = new ScDPDimension*[nDimCount];
    1325        1426 :             for (long i=0; i<nDimCount; i++)
    1326        1170 :                 ppDims[i] = NULL;
    1327             :         }
    1328       67644 :         if ( !ppDims[nIndex] )
    1329             :         {
    1330        1180 :             ppDims[nIndex] = new ScDPDimension( pSource, nIndex );
    1331        1180 :             ppDims[nIndex]->acquire();      // ref-counted
    1332             :         }
    1333             : 
    1334       67644 :         return ppDims[nIndex];
    1335             :     }
    1336             : 
    1337           0 :     return NULL;    //! exception?
    1338             : }
    1339             : 
    1340        1180 : ScDPDimension::ScDPDimension( ScDPSource* pSrc, long nD ) :
    1341             :     pSource( pSrc ),
    1342             :     nDim( nD ),
    1343             :     pHierarchies( NULL ),
    1344             :     nUsedHier( 0 ),
    1345             :     nFunction( SUBTOTAL_FUNC_SUM ),     // sum is default
    1346             :     mpLayoutName(NULL),
    1347             :     mpSubtotalName(NULL),
    1348             :     nSourceDim( -1 ),
    1349             :     bHasSelectedPage( false ),
    1350             :     pSelectedData( NULL ),
    1351        1180 :     mbHasHiddenMember(false)
    1352             : {
    1353             :     //! hold pSource
    1354        1180 : }
    1355             : 
    1356        3540 : ScDPDimension::~ScDPDimension()
    1357             : {
    1358             :     //! release pSource
    1359             : 
    1360        1180 :     if ( pHierarchies )
    1361         656 :         pHierarchies->release();    // ref-counted
    1362             : 
    1363        1180 :     delete pSelectedData;
    1364        2360 : }
    1365             : 
    1366        4832 : ScDPHierarchies* ScDPDimension::GetHierarchiesObject()
    1367             : {
    1368        4832 :     if (!pHierarchies)
    1369             :     {
    1370         656 :         pHierarchies = new ScDPHierarchies( pSource, nDim );
    1371         656 :         pHierarchies->acquire();        // ref-counted
    1372             :     }
    1373        4832 :     return pHierarchies;
    1374             : }
    1375             : 
    1376         760 : const OUString* ScDPDimension::GetLayoutName() const
    1377             : {
    1378         760 :     return mpLayoutName.get();
    1379             : }
    1380             : 
    1381           0 : const OUString* ScDPDimension::GetSubtotalName() const
    1382             : {
    1383           0 :     return mpSubtotalName.get();
    1384             : }
    1385             : 
    1386        1408 : uno::Reference<container::XNameAccess> SAL_CALL ScDPDimension::getHierarchies()
    1387             :                                                     throw(uno::RuntimeException, std::exception)
    1388             : {
    1389        1408 :     return GetHierarchiesObject();
    1390             : }
    1391             : 
    1392       55434 : OUString SAL_CALL ScDPDimension::getName() throw(uno::RuntimeException, std::exception)
    1393             : {
    1394       55434 :     if (!aName.isEmpty())
    1395          92 :         return aName;
    1396             :     else
    1397       55342 :         return pSource->GetData()->getDimensionName( nDim );
    1398             : }
    1399             : 
    1400          10 : void SAL_CALL ScDPDimension::setName( const OUString& rNewName ) throw(uno::RuntimeException, std::exception)
    1401             : {
    1402             :     //  used after cloning
    1403          10 :     aName = rNewName;
    1404          10 : }
    1405             : 
    1406        6140 : sal_uInt16 ScDPDimension::getOrientation() const
    1407             : {
    1408        6140 :     return pSource->GetOrientation( nDim );
    1409             : }
    1410             : 
    1411        1818 : void ScDPDimension::setOrientation(sal_uInt16 nNew)
    1412             : {
    1413        1818 :     pSource->SetOrientation( nDim, nNew );
    1414        1818 : }
    1415             : 
    1416         894 : long ScDPDimension::getPosition() const
    1417             : {
    1418         894 :     return pSource->GetPosition( nDim );
    1419             : }
    1420             : 
    1421        6744 : bool ScDPDimension::getIsDataLayoutDimension() const
    1422             : {
    1423        6744 :     return pSource->GetData()->getIsDataLayoutDimension( nDim );
    1424             : }
    1425             : 
    1426         648 : void ScDPDimension::setFunction(sal_uInt16 nNew)
    1427             : {
    1428         648 :     nFunction = nNew;
    1429         648 : }
    1430             : 
    1431         272 : void ScDPDimension::setUsedHierarchy(long /* nNew */)
    1432             : {
    1433             :     // #i52547# don't use the incomplete date hierarchy implementation - ignore the call
    1434         272 : }
    1435             : 
    1436          10 : ScDPDimension* ScDPDimension::CreateCloneObject()
    1437             : {
    1438             :     OSL_ENSURE( nSourceDim < 0, "recursive duplicate - not implemented" );
    1439             : 
    1440             :     //! set new name here, or temporary name ???
    1441          10 :     OUString aNewName = aName;
    1442             : 
    1443          10 :     ScDPDimension* pNew = pSource->AddDuplicated( nDim, aNewName );
    1444             : 
    1445          10 :     pNew->aName = aNewName;             //! here or in source?
    1446          10 :     pNew->nSourceDim = nDim;            //! recursive?
    1447             : 
    1448          10 :     return pNew;
    1449             : }
    1450             : 
    1451          10 : uno::Reference<util::XCloneable> SAL_CALL ScDPDimension::createClone() throw(uno::RuntimeException, std::exception)
    1452             : {
    1453          10 :     return CreateCloneObject();
    1454             : }
    1455             : 
    1456           0 : const ScDPItemData& ScDPDimension::GetSelectedData()
    1457             : {
    1458           0 :     if ( !pSelectedData )
    1459             :     {
    1460             :         // find the named member to initialize pSelectedData from it, with name and value
    1461             : 
    1462           0 :         long nLevel = 0;
    1463             : 
    1464           0 :         long nHierarchy = getUsedHierarchy();
    1465           0 :         if ( nHierarchy >= GetHierarchiesObject()->getCount() )
    1466           0 :             nHierarchy = 0;
    1467           0 :         ScDPLevels* pLevels = GetHierarchiesObject()->getByIndex(nHierarchy)->GetLevelsObject();
    1468           0 :         long nLevCount = pLevels->getCount();
    1469           0 :         if ( nLevel < nLevCount )
    1470             :         {
    1471           0 :             ScDPMembers* pMembers = pLevels->getByIndex(nLevel)->GetMembersObject();
    1472             : 
    1473             :             //! merge with ScDPMembers::getByName
    1474           0 :             long nCount = pMembers->getCount();
    1475           0 :             for (long i=0; i<nCount && !pSelectedData; i++)
    1476             :             {
    1477           0 :                 ScDPMember* pMember = pMembers->getByIndex(i);
    1478           0 :                 if (aSelectedPage.equals(pMember->GetNameStr()))
    1479             :                 {
    1480           0 :                     pSelectedData = new ScDPItemData();
    1481           0 :                     pMember->FillItemData( *pSelectedData );
    1482             :                 }
    1483             :             }
    1484             :         }
    1485             : 
    1486           0 :         if ( !pSelectedData )
    1487           0 :             pSelectedData = new ScDPItemData(aSelectedPage);      // default - name only
    1488             :     }
    1489             : 
    1490           0 :     return *pSelectedData;
    1491             : }
    1492             : 
    1493             : // XPropertySet
    1494             : 
    1495           0 : uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDPDimension::getPropertySetInfo()
    1496             :                                                         throw(uno::RuntimeException, std::exception)
    1497             : {
    1498           0 :     SolarMutexGuard aGuard;
    1499             : 
    1500             :     static const SfxItemPropertyMapEntry aDPDimensionMap_Impl[] =
    1501             :     {
    1502           0 :         { OUString(SC_UNO_DP_FILTER),   0,  getCppuType((uno::Sequence<sheet::TableFilterField>*)0), 0, 0 },
    1503           0 :         { OUString(SC_UNO_DP_FLAGS),    0,  cppu::UnoType<sal_Int32>::get(),                beans::PropertyAttribute::READONLY, 0 },
    1504           0 :         { OUString(SC_UNO_DP_FUNCTION), 0,  cppu::UnoType<sheet::GeneralFunction>::get(),   0, 0 },
    1505           0 :         { OUString(SC_UNO_DP_ISDATALAYOUT), 0,  getBooleanCppuType(),                      beans::PropertyAttribute::READONLY, 0 },
    1506           0 :         { OUString(SC_UNO_DP_NUMBERFO), 0,  cppu::UnoType<sal_Int32>::get(),                beans::PropertyAttribute::READONLY, 0 },
    1507           0 :         { OUString(SC_UNO_DP_ORIENTATION), 0,  cppu::UnoType<sheet::DataPilotFieldOrientation>::get(), 0, 0 },
    1508           0 :         { OUString(SC_UNO_DP_ORIGINAL), 0,  cppu::UnoType<container::XNamed>::get(), beans::PropertyAttribute::READONLY, 0 },
    1509           0 :         { OUString(SC_UNO_DP_ORIGINAL_POS), 0, cppu::UnoType<sal_Int32>::get(),             0, 0 },
    1510           0 :         { OUString(SC_UNO_DP_POSITION), 0,  cppu::UnoType<sal_Int32>::get(),                0, 0 },
    1511           0 :         { OUString(SC_UNO_DP_REFVALUE), 0,  cppu::UnoType<sheet::DataPilotFieldReference>::get(), 0, 0 },
    1512           0 :         { OUString(SC_UNO_DP_USEDHIERARCHY), 0,  cppu::UnoType<sal_Int32>::get(),                0, 0 },
    1513           0 :         { OUString(SC_UNO_DP_LAYOUTNAME), 0, cppu::UnoType<OUString>::get(), 0, 0 },
    1514           0 :         { OUString(SC_UNO_DP_FIELD_SUBTOTALNAME), 0, cppu::UnoType<OUString>::get(), 0, 0 },
    1515           0 :         { OUString(SC_UNO_DP_HAS_HIDDEN_MEMBER), 0, getBooleanCppuType(), 0, 0 },
    1516             :         { OUString(), 0, css::uno::Type(), 0, 0 }
    1517           0 :     };
    1518             :     static uno::Reference<beans::XPropertySetInfo> aRef =
    1519           0 :         new SfxItemPropertySetInfo( aDPDimensionMap_Impl );
    1520           0 :     return aRef;
    1521             : }
    1522             : 
    1523        3404 : void SAL_CALL ScDPDimension::setPropertyValue( const OUString& aPropertyName, const uno::Any& aValue )
    1524             :                 throw(beans::UnknownPropertyException, beans::PropertyVetoException,
    1525             :                         lang::IllegalArgumentException, lang::WrappedTargetException,
    1526             :                         uno::RuntimeException, std::exception)
    1527             : {
    1528        3404 :     if ( aPropertyName.equalsAscii( SC_UNO_DP_USEDHIERARCHY ) )
    1529             :     {
    1530         272 :         sal_Int32 nInt = 0;
    1531         272 :         if (aValue >>= nInt)
    1532         272 :             setUsedHierarchy( nInt );
    1533             :     }
    1534        3132 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_ORIENTATION ) )
    1535             :     {
    1536             :         sheet::DataPilotFieldOrientation eEnum;
    1537        1818 :         if (aValue >>= eEnum)
    1538        1818 :             setOrientation( sal::static_int_cast<sal_uInt16>(eEnum) );
    1539             :     }
    1540        1314 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_FUNCTION ) )
    1541             :     {
    1542             :         sheet::GeneralFunction eEnum;
    1543         648 :         if (aValue >>= eEnum)
    1544         648 :             setFunction( sal::static_int_cast<sal_uInt16>(eEnum) );
    1545             :     }
    1546         666 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_REFVALUE ) )
    1547          14 :         aValue >>= aReferenceValue;
    1548         652 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_FILTER ) )
    1549             :     {
    1550           0 :         bool bDone = false;
    1551           0 :         uno::Sequence<sheet::TableFilterField> aSeq;
    1552           0 :         if (aValue >>= aSeq)
    1553             :         {
    1554           0 :             sal_Int32 nLength = aSeq.getLength();
    1555           0 :             if ( nLength == 0 )
    1556             :             {
    1557           0 :                 aSelectedPage = "";
    1558           0 :                 bHasSelectedPage = false;
    1559           0 :                 bDone = true;
    1560             :             }
    1561           0 :             else if ( nLength == 1 )
    1562             :             {
    1563           0 :                 const sheet::TableFilterField& rField = aSeq[0];
    1564           0 :                 if ( rField.Field == 0 && rField.Operator == sheet::FilterOperator_EQUAL && !rField.IsNumeric )
    1565             :                 {
    1566           0 :                     aSelectedPage = rField.StringValue;
    1567           0 :                     bHasSelectedPage = true;
    1568           0 :                     bDone = true;
    1569             :                 }
    1570             :             }
    1571             :         }
    1572           0 :         if ( !bDone )
    1573             :         {
    1574             :             OSL_FAIL("Filter property is not a single string");
    1575           0 :             throw lang::IllegalArgumentException();
    1576             :         }
    1577           0 :         DELETEZ( pSelectedData );       // invalid after changing aSelectedPage
    1578             :     }
    1579         652 :     else if (aPropertyName.equalsAscii(SC_UNO_DP_LAYOUTNAME))
    1580             :     {
    1581           4 :         OUString aTmpName;
    1582           4 :         if (aValue >>= aTmpName)
    1583           4 :             mpLayoutName.reset(new OUString(aTmpName));
    1584             :     }
    1585         648 :     else if (aPropertyName.equalsAscii(SC_UNO_DP_FIELD_SUBTOTALNAME))
    1586             :     {
    1587           0 :         OUString aTmpName;
    1588           0 :         if (aValue >>= aTmpName)
    1589           0 :             mpSubtotalName.reset(new OUString(aTmpName));
    1590             :     }
    1591         648 :     else if (aPropertyName.equalsAscii(SC_UNO_DP_HAS_HIDDEN_MEMBER))
    1592             :     {
    1593         648 :         bool b = false;
    1594         648 :         aValue >>= b;
    1595         648 :         mbHasHiddenMember = b;
    1596             :     }
    1597             :     else
    1598             :     {
    1599             :         OSL_FAIL("unknown property");
    1600             :         //! THROW( UnknownPropertyException() );
    1601             :     }
    1602        3404 : }
    1603             : 
    1604       18656 : uno::Any SAL_CALL ScDPDimension::getPropertyValue( const OUString& aPropertyName )
    1605             :                 throw(beans::UnknownPropertyException, lang::WrappedTargetException,
    1606             :                         uno::RuntimeException, std::exception)
    1607             : {
    1608       18656 :     uno::Any aRet;
    1609       18656 :     if ( aPropertyName.equalsAscii( SC_UNO_DP_POSITION ) )
    1610         894 :         aRet <<= (sal_Int32) getPosition();
    1611       17762 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_USEDHIERARCHY ) )
    1612         754 :         aRet <<= (sal_Int32) getUsedHierarchy();
    1613       17008 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_ORIENTATION ) )
    1614             :     {
    1615        6140 :         sheet::DataPilotFieldOrientation eVal = (sheet::DataPilotFieldOrientation)getOrientation();
    1616        6140 :         aRet <<= eVal;
    1617             :     }
    1618       10868 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_FUNCTION ) )
    1619             :     {
    1620         678 :         sheet::GeneralFunction eVal = (sheet::GeneralFunction)getFunction();
    1621         678 :         aRet <<= eVal;
    1622             :     }
    1623       10190 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_REFVALUE ) )
    1624           0 :         aRet <<= aReferenceValue;
    1625       10190 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_ISDATALAYOUT ) )                 // read-only properties
    1626        5742 :         lcl_SetBoolInAny( aRet, getIsDataLayoutDimension() );
    1627        4448 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_NUMBERFO ) )
    1628             :     {
    1629        1224 :         sal_Int32 nFormat = 0;
    1630        1224 :         sheet::GeneralFunction eFunc = (sheet::GeneralFunction)getFunction();
    1631             :         // #i63745# don't use source format for "count"
    1632        1224 :         if ( eFunc != sheet::GeneralFunction_COUNT && eFunc != sheet::GeneralFunction_COUNTNUMS )
    1633        1204 :             nFormat = pSource->GetData()->GetNumberFormat( ( nSourceDim >= 0 ) ? nSourceDim : nDim );
    1634             : 
    1635        1224 :         switch ( aReferenceValue.ReferenceType )
    1636             :         {
    1637             :         case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE:
    1638             :         case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE:
    1639             :         case sheet::DataPilotFieldReferenceType::ROW_PERCENTAGE:
    1640             :         case sheet::DataPilotFieldReferenceType::COLUMN_PERCENTAGE:
    1641             :         case sheet::DataPilotFieldReferenceType::TOTAL_PERCENTAGE:
    1642          12 :             nFormat = pSource->GetData()->GetNumberFormatByIdx( (NfIndexTableOffset)NF_PERCENT_DEC2 );
    1643          12 :             break;
    1644             :         case sheet::DataPilotFieldReferenceType::INDEX:
    1645           0 :             nFormat = pSource->GetData()->GetNumberFormatByIdx( (NfIndexTableOffset)NF_NUMBER_SYSTEM );
    1646           0 :             break;
    1647             :         default:
    1648        1212 :             break;
    1649             :         }
    1650             : 
    1651        1224 :         aRet <<= nFormat;
    1652             :     }
    1653        3224 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_ORIGINAL ) )
    1654             :     {
    1655        1296 :         uno::Reference<container::XNamed> xOriginal;
    1656        1296 :         if (nSourceDim >= 0)
    1657           0 :             xOriginal = pSource->GetDimensionsObject()->getByIndex(nSourceDim);
    1658        1296 :         aRet <<= xOriginal;
    1659             :     }
    1660        1928 :     else if (aPropertyName.equalsAscii(SC_UNO_DP_ORIGINAL_POS))
    1661             :     {
    1662           8 :         sal_Int32 nPos = static_cast<sal_Int32>(nSourceDim);
    1663           8 :         aRet <<= nPos;
    1664             :     }
    1665        1920 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_FILTER ) )
    1666             :     {
    1667           0 :         if ( bHasSelectedPage )
    1668             :         {
    1669             :             // single filter field: first field equal to selected string
    1670             :             sheet::TableFilterField aField( sheet::FilterConnection_AND, 0,
    1671           0 :                     sheet::FilterOperator_EQUAL, false, 0.0, aSelectedPage );
    1672           0 :             aRet <<= uno::Sequence<sheet::TableFilterField>( &aField, 1 );
    1673             :         }
    1674             :         else
    1675           0 :             aRet <<= uno::Sequence<sheet::TableFilterField>(0);
    1676             :     }
    1677        1920 :     else if (aPropertyName.equalsAscii(SC_UNO_DP_LAYOUTNAME))
    1678        1012 :         aRet <<= mpLayoutName.get() ? *mpLayoutName : OUString("");
    1679         908 :     else if (aPropertyName.equalsAscii(SC_UNO_DP_FIELD_SUBTOTALNAME))
    1680           8 :         aRet <<= mpSubtotalName.get() ? *mpSubtotalName : OUString("");
    1681         900 :     else if (aPropertyName.equalsAscii(SC_UNO_DP_HAS_HIDDEN_MEMBER))
    1682         894 :         aRet <<= mbHasHiddenMember;
    1683           6 :     else if (aPropertyName.equalsAscii(SC_UNO_DP_FLAGS))
    1684             :     {
    1685           6 :         sal_Int32 nFlags = 0;       // tabular data: all orientations are possible
    1686           6 :         aRet <<= nFlags;
    1687             :     }
    1688             :     else
    1689             :     {
    1690             :         OSL_FAIL("unknown property");
    1691             :         //! THROW( UnknownPropertyException() );
    1692             :     }
    1693       18656 :     return aRet;
    1694             : }
    1695             : 
    1696           0 : SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDPDimension )
    1697             : 
    1698         656 : ScDPHierarchies::ScDPHierarchies( ScDPSource* pSrc, long nD ) :
    1699             :     pSource( pSrc ),
    1700             :     nDim( nD ),
    1701         656 :     ppHiers( NULL )
    1702             : {
    1703             :     //! hold pSource
    1704             : 
    1705             :     //  date columns have 3 hierarchies (flat/quarter/week), other columns only one
    1706             : 
    1707             :     // #i52547# don't offer the incomplete date hierarchy implementation
    1708         656 :     nHierCount = 1;
    1709         656 : }
    1710             : 
    1711        1968 : ScDPHierarchies::~ScDPHierarchies()
    1712             : {
    1713             :     //! release pSource
    1714             : 
    1715         656 :     if (ppHiers)
    1716             :     {
    1717        1312 :         for (long i=0; i<nHierCount; i++)
    1718         656 :             if ( ppHiers[i] )
    1719         656 :                 ppHiers[i]->release();      // ref-counted
    1720         656 :         delete[] ppHiers;
    1721             :     }
    1722        1312 : }
    1723             : 
    1724             : // very simple XNameAccess implementation using getCount/getByIndex
    1725             : 
    1726        1402 : uno::Any SAL_CALL ScDPHierarchies::getByName( const OUString& aName )
    1727             :             throw(container::NoSuchElementException,
    1728             :                     lang::WrappedTargetException, uno::RuntimeException, std::exception)
    1729             : {
    1730        1402 :     long nCount = getCount();
    1731        1402 :     for (long i=0; i<nCount; i++)
    1732        1402 :         if ( getByIndex(i)->getName() == aName )
    1733             :         {
    1734        1402 :             uno::Reference<container::XNamed> xNamed = getByIndex(i);
    1735        2804 :             uno::Any aRet;
    1736        1402 :             aRet <<= xNamed;
    1737        4206 :             return aRet;
    1738             :         }
    1739             : 
    1740           0 :     throw container::NoSuchElementException();
    1741             : }
    1742             : 
    1743        1408 : uno::Sequence<OUString> SAL_CALL ScDPHierarchies::getElementNames() throw(uno::RuntimeException, std::exception)
    1744             : {
    1745        1408 :     long nCount = getCount();
    1746        1408 :     uno::Sequence<OUString> aSeq(nCount);
    1747        1408 :     OUString* pArr = aSeq.getArray();
    1748        2816 :     for (long i=0; i<nCount; i++)
    1749        1408 :         pArr[i] = getByIndex(i)->getName();
    1750        1408 :     return aSeq;
    1751             : }
    1752             : 
    1753           0 : sal_Bool SAL_CALL ScDPHierarchies::hasByName( const OUString& aName ) throw(uno::RuntimeException, std::exception)
    1754             : {
    1755           0 :     long nCount = getCount();
    1756           0 :     for (long i=0; i<nCount; i++)
    1757           0 :         if ( getByIndex(i)->getName() == aName )
    1758           0 :             return sal_True;
    1759           0 :     return false;
    1760             : }
    1761             : 
    1762           0 : uno::Type SAL_CALL ScDPHierarchies::getElementType() throw(uno::RuntimeException, std::exception)
    1763             : {
    1764           0 :     return cppu::UnoType<container::XNamed>::get();
    1765             : }
    1766             : 
    1767           0 : sal_Bool SAL_CALL ScDPHierarchies::hasElements() throw(uno::RuntimeException, std::exception)
    1768             : {
    1769           0 :     return ( getCount() > 0 );
    1770             : }
    1771             : 
    1772             : // end of XNameAccess implementation
    1773             : 
    1774        3568 : long ScDPHierarchies::getCount() const
    1775             : {
    1776        3568 :     return nHierCount;
    1777             : }
    1778             : 
    1779        7228 : ScDPHierarchy* ScDPHierarchies::getByIndex(long nIndex) const
    1780             : {
    1781             :     //  pass hierarchy index to new object in case the implementation
    1782             :     //  will be extended to more than one hierarchy
    1783             : 
    1784        7228 :     if ( nIndex >= 0 && nIndex < nHierCount )
    1785             :     {
    1786        7228 :         if ( !ppHiers )
    1787             :         {
    1788         656 :             ((ScDPHierarchies*)this)->ppHiers = new ScDPHierarchy*[nHierCount];
    1789        1312 :             for (long i=0; i<nHierCount; i++)
    1790         656 :                 ppHiers[i] = NULL;
    1791             :         }
    1792        7228 :         if ( !ppHiers[nIndex] )
    1793             :         {
    1794         656 :             ppHiers[nIndex] = new ScDPHierarchy( pSource, nDim, nIndex );
    1795         656 :             ppHiers[nIndex]->acquire();         // ref-counted
    1796             :         }
    1797             : 
    1798        7228 :         return ppHiers[nIndex];
    1799             :     }
    1800             : 
    1801           0 :     return NULL;    //! exception?
    1802             : }
    1803             : 
    1804         656 : ScDPHierarchy::ScDPHierarchy( ScDPSource* pSrc, long nD, long nH ) :
    1805             :     pSource( pSrc ),
    1806             :     nDim( nD ),
    1807             :     nHier( nH ),
    1808         656 :     pLevels( NULL )
    1809             : {
    1810             :     //! hold pSource
    1811         656 : }
    1812             : 
    1813        1968 : ScDPHierarchy::~ScDPHierarchy()
    1814             : {
    1815             :     //! release pSource
    1816             : 
    1817         656 :     if (pLevels)
    1818         656 :         pLevels->release();     // ref-counted
    1819        1312 : }
    1820             : 
    1821        4418 : ScDPLevels* ScDPHierarchy::GetLevelsObject()
    1822             : {
    1823        4418 :     if (!pLevels)
    1824             :     {
    1825         656 :         pLevels = new ScDPLevels( pSource, nDim, nHier );
    1826         656 :         pLevels->acquire();     // ref-counted
    1827             :     }
    1828        4418 :     return pLevels;
    1829             : }
    1830             : 
    1831        1402 : uno::Reference<container::XNameAccess> SAL_CALL ScDPHierarchy::getLevels()
    1832             :                                                     throw(uno::RuntimeException, std::exception)
    1833             : {
    1834        1402 :     return GetLevelsObject();
    1835             : }
    1836             : 
    1837        2810 : OUString SAL_CALL ScDPHierarchy::getName() throw(uno::RuntimeException, std::exception)
    1838             : {
    1839        2810 :     OUString aRet;        //! globstr-ID !!!!
    1840        2810 :     switch (nHier)
    1841             :     {
    1842             :         case SC_DAPI_HIERARCHY_FLAT:
    1843        2810 :             aRet = "flat";
    1844        2810 :             break;  //! name ???????
    1845             :         case SC_DAPI_HIERARCHY_QUARTER:
    1846           0 :             aRet = "Quarter";
    1847           0 :             break;  //! name ???????
    1848             :         case SC_DAPI_HIERARCHY_WEEK:
    1849           0 :             aRet = "Week";
    1850           0 :             break;  //! name ???????
    1851             :         default:
    1852             :             OSL_FAIL( "ScDPHierarchy::getName: unexpected hierarchy" );
    1853           0 :             break;
    1854             :     }
    1855        2810 :     return aRet;
    1856             : }
    1857             : 
    1858           0 : void SAL_CALL ScDPHierarchy::setName( const OUString& /* rNewName */ ) throw(uno::RuntimeException, std::exception)
    1859             : {
    1860             :     OSL_FAIL("not implemented");        //! exception?
    1861           0 : }
    1862             : 
    1863         656 : ScDPLevels::ScDPLevels( ScDPSource* pSrc, long nD, long nH ) :
    1864             :     pSource( pSrc ),
    1865             :     nDim( nD ),
    1866             :     nHier( nH ),
    1867         656 :     ppLevs( NULL )
    1868             : {
    1869             :     //! hold pSource
    1870             : 
    1871             :     //  text columns have only one level
    1872             : 
    1873         656 :     long nSrcDim = pSource->GetSourceDim( nDim );
    1874         656 :     if ( pSource->IsDateDimension( nSrcDim ) )
    1875             :     {
    1876          16 :         switch ( nHier )
    1877             :         {
    1878          16 :             case SC_DAPI_HIERARCHY_FLAT:    nLevCount = SC_DAPI_FLAT_LEVELS;    break;
    1879           0 :             case SC_DAPI_HIERARCHY_QUARTER: nLevCount = SC_DAPI_QUARTER_LEVELS; break;
    1880           0 :             case SC_DAPI_HIERARCHY_WEEK:    nLevCount = SC_DAPI_WEEK_LEVELS;    break;
    1881             :             default:
    1882             :                 OSL_FAIL("wrong hierarchy");
    1883           0 :                 nLevCount = 0;
    1884             :         }
    1885             :     }
    1886             :     else
    1887         640 :         nLevCount = 1;
    1888         656 : }
    1889             : 
    1890        1968 : ScDPLevels::~ScDPLevels()
    1891             : {
    1892             :     //! release pSource
    1893             : 
    1894         656 :     if (ppLevs)
    1895             :     {
    1896        1312 :         for (long i=0; i<nLevCount; i++)
    1897         656 :             if ( ppLevs[i] )
    1898         656 :                 ppLevs[i]->release();   // ref-counted
    1899         656 :         delete[] ppLevs;
    1900             :     }
    1901        1312 : }
    1902             : 
    1903             : // very simple XNameAccess implementation using getCount/getByIndex
    1904             : 
    1905        1402 : uno::Any SAL_CALL ScDPLevels::getByName( const OUString& aName )
    1906             :             throw(container::NoSuchElementException,
    1907             :                     lang::WrappedTargetException, uno::RuntimeException, std::exception)
    1908             : {
    1909        1402 :     long nCount = getCount();
    1910        1402 :     for (long i=0; i<nCount; i++)
    1911        1402 :         if ( getByIndex(i)->getName() == aName )
    1912             :         {
    1913        1402 :             uno::Reference<container::XNamed> xNamed = getByIndex(i);
    1914        2804 :             uno::Any aRet;
    1915        1402 :             aRet <<= xNamed;
    1916        4206 :             return aRet;
    1917             :         }
    1918             : 
    1919           0 :     throw container::NoSuchElementException();
    1920             : }
    1921             : 
    1922        1402 : uno::Sequence<OUString> SAL_CALL ScDPLevels::getElementNames() throw(uno::RuntimeException, std::exception)
    1923             : {
    1924        1402 :     long nCount = getCount();
    1925        1402 :     uno::Sequence<OUString> aSeq(nCount);
    1926        1402 :     OUString* pArr = aSeq.getArray();
    1927        2804 :     for (long i=0; i<nCount; i++)
    1928        1402 :         pArr[i] = getByIndex(i)->getName();
    1929        1402 :     return aSeq;
    1930             : }
    1931             : 
    1932           0 : sal_Bool SAL_CALL ScDPLevels::hasByName( const OUString& aName ) throw(uno::RuntimeException, std::exception)
    1933             : {
    1934           0 :     long nCount = getCount();
    1935           0 :     for (long i=0; i<nCount; i++)
    1936           0 :         if ( getByIndex(i)->getName() == aName )
    1937           0 :             return sal_True;
    1938           0 :     return false;
    1939             : }
    1940             : 
    1941           0 : uno::Type SAL_CALL ScDPLevels::getElementType() throw(uno::RuntimeException, std::exception)
    1942             : {
    1943           0 :     return cppu::UnoType<container::XNamed>::get();
    1944             : }
    1945             : 
    1946           0 : sal_Bool SAL_CALL ScDPLevels::hasElements() throw(uno::RuntimeException, std::exception)
    1947             : {
    1948           0 :     return ( getCount() > 0 );
    1949             : }
    1950             : 
    1951             : // end of XNameAccess implementation
    1952             : 
    1953        3562 : long ScDPLevels::getCount() const
    1954             : {
    1955        3562 :     return nLevCount;
    1956             : }
    1957             : 
    1958        7144 : ScDPLevel* ScDPLevels::getByIndex(long nIndex) const
    1959             : {
    1960        7144 :     if ( nIndex >= 0 && nIndex < nLevCount )
    1961             :     {
    1962        7144 :         if ( !ppLevs )
    1963             :         {
    1964         656 :             ((ScDPLevels*)this)->ppLevs = new ScDPLevel*[nLevCount];
    1965        1312 :             for (long i=0; i<nLevCount; i++)
    1966         656 :                 ppLevs[i] = NULL;
    1967             :         }
    1968        7144 :         if ( !ppLevs[nIndex] )
    1969             :         {
    1970         656 :             ppLevs[nIndex] = new ScDPLevel( pSource, nDim, nHier, nIndex );
    1971         656 :             ppLevs[nIndex]->acquire();      // ref-counted
    1972             :         }
    1973             : 
    1974        7144 :         return ppLevs[nIndex];
    1975             :     }
    1976             : 
    1977           0 :     return NULL;    //! exception?
    1978             : }
    1979             : 
    1980             : class ScDPGlobalMembersOrder
    1981             : {
    1982             :     ScDPLevel&  rLevel;
    1983             :     bool        bAscending;
    1984             : 
    1985             : public:
    1986         496 :             ScDPGlobalMembersOrder( ScDPLevel& rLev, bool bAsc ) :
    1987             :                 rLevel(rLev),
    1988         496 :                 bAscending(bAsc)
    1989         496 :             {}
    1990        8984 :             ~ScDPGlobalMembersOrder() {}
    1991             : 
    1992             :     bool operator()( sal_Int32 nIndex1, sal_Int32 nIndex2 ) const;
    1993             : };
    1994             : 
    1995        3370 : bool ScDPGlobalMembersOrder::operator()( sal_Int32 nIndex1, sal_Int32 nIndex2 ) const
    1996             : {
    1997        3370 :     sal_Int32 nCompare = 0;
    1998             :     // seems that some ::std::sort() implementations pass the same index twice
    1999        3370 :     if( nIndex1 != nIndex2 )
    2000             :     {
    2001        3370 :         ScDPMembers* pMembers = rLevel.GetMembersObject();
    2002        3370 :         ScDPMember* pMember1 = pMembers->getByIndex(nIndex1);
    2003        3370 :         ScDPMember* pMember2 = pMembers->getByIndex(nIndex2);
    2004        3370 :         nCompare = pMember1->Compare( *pMember2 );
    2005             :     }
    2006        3370 :     return bAscending ? (nCompare < 0) : (nCompare > 0);
    2007             : }
    2008             : 
    2009         656 : ScDPLevel::ScDPLevel( ScDPSource* pSrc, long nD, long nH, long nL ) :
    2010             :     pSource( pSrc ),
    2011             :     nDim( nD ),
    2012             :     nHier( nH ),
    2013             :     nLev( nL ),
    2014             :     pMembers( NULL ),
    2015         656 :     aSortInfo( EMPTY_OUSTRING, sal_True, sheet::DataPilotFieldSortMode::NAME ),   // default: sort by name
    2016             :     nSortMeasure( 0 ),
    2017             :     nAutoMeasure( 0 ),
    2018             :     bShowEmpty( false ),
    2019        1312 :     bEnableLayout( false )
    2020             : {
    2021             :     //! hold pSource
    2022             :     //  aSubTotals is empty
    2023         656 : }
    2024             : 
    2025        1968 : ScDPLevel::~ScDPLevel()
    2026             : {
    2027             :     //! release pSource
    2028             : 
    2029         656 :     if ( pMembers )
    2030         392 :         pMembers->release();    // ref-counted
    2031        1312 : }
    2032             : 
    2033         496 : void ScDPLevel::EvaluateSortOrder()
    2034             : {
    2035         496 :     switch (aSortInfo.Mode)
    2036             :     {
    2037             :         case sheet::DataPilotFieldSortMode::DATA:
    2038             :             {
    2039             :                 // find index of measure (index among data dimensions)
    2040             : 
    2041           0 :                 long nMeasureCount = pSource->GetDataDimensionCount();
    2042           0 :                 for (long nMeasure=0; nMeasure<nMeasureCount; nMeasure++)
    2043             :                 {
    2044           0 :                     if (pSource->GetDataDimName(nMeasure).equals(aSortInfo.Field))
    2045             :                     {
    2046           0 :                         nSortMeasure = nMeasure;
    2047           0 :                         break;
    2048             :                     }
    2049             :                 }
    2050             : 
    2051             :                 //! error if not found?
    2052             :             }
    2053           0 :             break;
    2054             :         case sheet::DataPilotFieldSortMode::MANUAL:
    2055             :         case sheet::DataPilotFieldSortMode::NAME:
    2056             :             {
    2057         496 :                 ScDPMembers* pLocalMembers = GetMembersObject();
    2058         496 :                 long nCount = pLocalMembers->getCount();
    2059             : 
    2060         496 :                 aGlobalOrder.resize( nCount );
    2061        2682 :                 for (long nPos=0; nPos<nCount; nPos++)
    2062        2186 :                     aGlobalOrder[nPos] = nPos;
    2063             : 
    2064             :                 // allow manual or name (manual is always ascending)
    2065         496 :                 bool bAscending = ( aSortInfo.Mode == sheet::DataPilotFieldSortMode::MANUAL || aSortInfo.IsAscending );
    2066         496 :                 ScDPGlobalMembersOrder aComp( *this, bAscending );
    2067         496 :                 ::std::sort( aGlobalOrder.begin(), aGlobalOrder.end(), aComp );
    2068             :             }
    2069         496 :             break;
    2070             :     }
    2071             : 
    2072         496 :     if ( aAutoShowInfo.IsEnabled )
    2073             :     {
    2074             :         // find index of measure (index among data dimensions)
    2075             : 
    2076           2 :         long nMeasureCount = pSource->GetDataDimensionCount();
    2077           4 :         for (long nMeasure=0; nMeasure<nMeasureCount; nMeasure++)
    2078             :         {
    2079           2 :             if (pSource->GetDataDimName(nMeasure).equals(aAutoShowInfo.DataField))
    2080             :             {
    2081           0 :                 nAutoMeasure = nMeasure;
    2082           0 :                 break;
    2083             :             }
    2084             :         }
    2085             : 
    2086             :         //! error if not found?
    2087             :     }
    2088         496 : }
    2089             : 
    2090         422 : void ScDPLevel::SetEnableLayout(bool bSet)
    2091             : {
    2092         422 :     bEnableLayout = bSet;
    2093         422 : }
    2094             : 
    2095        7426 : ScDPMembers* ScDPLevel::GetMembersObject()
    2096             : {
    2097        7426 :     if (!pMembers)
    2098             :     {
    2099         392 :         pMembers = new ScDPMembers( pSource, nDim, nHier, nLev );
    2100         392 :         pMembers->acquire();    // ref-counted
    2101             :     }
    2102        7426 :     return pMembers;
    2103             : }
    2104             : 
    2105         362 : uno::Reference<container::XNameAccess> SAL_CALL ScDPLevel::getMembers() throw(uno::RuntimeException, std::exception)
    2106             : {
    2107         362 :     return GetMembersObject();
    2108             : }
    2109             : 
    2110         446 : uno::Sequence<sheet::MemberResult> SAL_CALL ScDPLevel::getResults() throw(uno::RuntimeException, std::exception)
    2111             : {
    2112         446 :     const uno::Sequence<sheet::MemberResult>* pRes = pSource->GetMemberResults( this );
    2113         446 :     if (pRes)
    2114         446 :         return *pRes;
    2115             : 
    2116           0 :     return uno::Sequence<sheet::MemberResult>(0);       //! Error?
    2117             : }
    2118             : 
    2119        3426 : OUString SAL_CALL ScDPLevel::getName() throw(uno::RuntimeException, std::exception)
    2120             : {
    2121        3426 :     long nSrcDim = pSource->GetSourceDim( nDim );
    2122        3426 :     if ( pSource->IsDateDimension( nSrcDim ) )
    2123             :     {
    2124          80 :         OUString aRet;        //! globstr-ID !!!!
    2125             : 
    2126          80 :         if ( nHier == SC_DAPI_HIERARCHY_QUARTER )
    2127             :         {
    2128           0 :             switch ( nLev )
    2129             :             {
    2130             :                 case SC_DAPI_LEVEL_YEAR:
    2131           0 :                     aRet = "Year";
    2132           0 :                     break;
    2133             :                 case SC_DAPI_LEVEL_QUARTER:
    2134           0 :                     aRet = "Quarter";
    2135           0 :                     break;
    2136             :                 case SC_DAPI_LEVEL_MONTH:
    2137           0 :                     aRet = "Month";
    2138           0 :                     break;
    2139             :                 case SC_DAPI_LEVEL_DAY:
    2140           0 :                     aRet = "Day";
    2141           0 :                     break;
    2142             :                 default:
    2143             :                     OSL_FAIL( "ScDPLevel::getName: unexpected level" );
    2144           0 :                     break;
    2145             :             }
    2146             :         }
    2147          80 :         else if ( nHier == SC_DAPI_HIERARCHY_WEEK )
    2148             :         {
    2149           0 :             switch ( nLev )
    2150             :             {
    2151             :                 case SC_DAPI_LEVEL_YEAR:
    2152           0 :                     aRet = "Year";
    2153           0 :                     break;
    2154             :                 case SC_DAPI_LEVEL_WEEK:
    2155           0 :                     aRet = "Week";
    2156           0 :                     break;
    2157             :                 case SC_DAPI_LEVEL_WEEKDAY:
    2158           0 :                     aRet = "Weekday";
    2159           0 :                     break;
    2160             :                 default:
    2161             :                     OSL_FAIL( "ScDPLevel::getName: unexpected level" );
    2162           0 :                     break;
    2163             :             }
    2164             :         }
    2165          80 :         if (!aRet.isEmpty())
    2166           0 :             return aRet;
    2167             :     }
    2168             : 
    2169        3426 :     ScDPDimension* pDim = pSource->GetDimensionsObject()->getByIndex(nSrcDim);
    2170        3426 :     if (!pDim)
    2171           0 :         return OUString();
    2172             : 
    2173        3426 :     return pDim->getName();
    2174             : }
    2175             : 
    2176           0 : void SAL_CALL ScDPLevel::setName( const OUString& /* rNewName */ ) throw(uno::RuntimeException, std::exception)
    2177             : {
    2178             :     OSL_FAIL("not implemented");        //! exception?
    2179           0 : }
    2180             : 
    2181       14522 : uno::Sequence<sheet::GeneralFunction> ScDPLevel::getSubTotals() const
    2182             : {
    2183             :     //! separate functions for settings and evaluation?
    2184             : 
    2185       14522 :     long nSrcDim = pSource->GetSourceDim( nDim );
    2186       14522 :     if ( !pSource->SubTotalAllowed( nSrcDim ) )
    2187       11896 :         return uno::Sequence<sheet::GeneralFunction>(0);
    2188             : 
    2189        2626 :     return aSubTotals;
    2190             : }
    2191             : 
    2192             : // XPropertySet
    2193             : 
    2194           0 : uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDPLevel::getPropertySetInfo()
    2195             :                                                         throw(uno::RuntimeException, std::exception)
    2196             : {
    2197           0 :     SolarMutexGuard aGuard;
    2198             : 
    2199             :     static const SfxItemPropertyMapEntry aDPLevelMap_Impl[] =
    2200             :     {
    2201             :         //! change type of AutoShow/Layout/Sorting to API struct when available
    2202           0 :         { OUString(SC_UNO_DP_AUTOSHOW), 0,  cppu::UnoType<sheet::DataPilotFieldAutoShowInfo>::get(),     0, 0 },
    2203           0 :         { OUString(SC_UNO_DP_LAYOUT),   0,  cppu::UnoType<sheet::DataPilotFieldLayoutInfo>::get(),       0, 0 },
    2204           0 :         { OUString(SC_UNO_DP_SHOWEMPTY), 0, getBooleanCppuType(),                                   0, 0 },
    2205           0 :         { OUString(SC_UNO_DP_SORTING),  0,  cppu::UnoType<sheet::DataPilotFieldSortInfo>::get(),         0, 0 },
    2206           0 :         { OUString(SC_UNO_DP_SUBTOTAL), 0,  getCppuType((uno::Sequence<sheet::GeneralFunction>*)0), 0, 0 },
    2207             :         { OUString(), 0, css::uno::Type(), 0, 0 }
    2208           0 :     };
    2209             :     static uno::Reference<beans::XPropertySetInfo> aRef =
    2210           0 :         new SfxItemPropertySetInfo( aDPLevelMap_Impl );
    2211           0 :     return aRef;
    2212             : }
    2213             : 
    2214        1012 : void SAL_CALL ScDPLevel::setPropertyValue( const OUString& aPropertyName, const uno::Any& aValue )
    2215             :                 throw(beans::UnknownPropertyException, beans::PropertyVetoException,
    2216             :                         lang::IllegalArgumentException, lang::WrappedTargetException,
    2217             :                         uno::RuntimeException, std::exception)
    2218             : {
    2219        1012 :     if ( aPropertyName.equalsAscii( SC_UNO_DP_SHOWEMPTY ) )
    2220         236 :         bShowEmpty = lcl_GetBoolFromAny(aValue);
    2221         776 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_SUBTOTAL ) )
    2222         138 :         aValue >>= aSubTotals;
    2223         638 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_SORTING ) )
    2224         226 :         aValue >>= aSortInfo;
    2225         412 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_AUTOSHOW ) )
    2226         182 :         aValue >>= aAutoShowInfo;
    2227         230 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_LAYOUT ) )
    2228         230 :         aValue >>= aLayoutInfo;
    2229             :     else
    2230             :     {
    2231             :         OSL_FAIL("unknown property");
    2232             :     }
    2233        1012 : }
    2234             : 
    2235         598 : uno::Any SAL_CALL ScDPLevel::getPropertyValue( const OUString& aPropertyName )
    2236             :                 throw(beans::UnknownPropertyException, lang::WrappedTargetException,
    2237             :                         uno::RuntimeException, std::exception)
    2238             : {
    2239         598 :     uno::Any aRet;
    2240         598 :     if ( aPropertyName.equalsAscii( SC_UNO_DP_SHOWEMPTY ) )
    2241           6 :         lcl_SetBoolInAny(aRet, bShowEmpty);
    2242         592 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_SUBTOTAL ) )
    2243             :     {
    2244           0 :         uno::Sequence<sheet::GeneralFunction> aSeq = getSubTotals();        //! avoid extra copy?
    2245           0 :         aRet <<= aSeq;
    2246             :     }
    2247         592 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_SORTING ) )
    2248           6 :         aRet <<= aSortInfo;
    2249         586 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_AUTOSHOW ) )
    2250           6 :         aRet <<= aAutoShowInfo;
    2251         580 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_LAYOUT ) )
    2252           6 :         aRet <<= aLayoutInfo;
    2253         574 :     else if (aPropertyName.equalsAscii(SC_UNO_DP_LAYOUTNAME))
    2254             :     {
    2255             :         // read only property
    2256         574 :         long nSrcDim = pSource->GetSourceDim(nDim);
    2257         574 :         ScDPDimension* pDim = pSource->GetDimensionsObject()->getByIndex(nSrcDim);
    2258         574 :         if (!pDim)
    2259           0 :             return aRet;
    2260             : 
    2261         574 :         const OUString* pLayoutName = pDim->GetLayoutName();
    2262         574 :         if (!pLayoutName)
    2263         574 :             return aRet;
    2264             : 
    2265           0 :         aRet <<= *pLayoutName;
    2266             :     }
    2267             :     else
    2268             :     {
    2269             :         OSL_FAIL("unknown property");
    2270             :     }
    2271          24 :     return aRet;
    2272             : }
    2273             : 
    2274           0 : SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDPLevel )
    2275             : 
    2276         392 : ScDPMembers::ScDPMembers( ScDPSource* pSrc, long nD, long nH, long nL ) :
    2277             :     pSource( pSrc ),
    2278             :     nDim( nD ),
    2279             :     nHier( nH ),
    2280         392 :     nLev( nL )
    2281             : {
    2282             :     //! hold pSource
    2283             : 
    2284         392 :     long nSrcDim = pSource->GetSourceDim( nDim );
    2285         392 :     if ( pSource->IsDataLayoutDimension(nSrcDim) )
    2286          18 :         nMbrCount = pSource->GetDataDimensionCount();
    2287         374 :     else if ( nHier != SC_DAPI_HIERARCHY_FLAT && pSource->IsDateDimension( nSrcDim ) )
    2288             :     {
    2289           0 :         nMbrCount = 0;
    2290           0 :         if ( nHier == SC_DAPI_HIERARCHY_QUARTER )
    2291             :         {
    2292           0 :             switch (nLev)
    2293             :             {
    2294             :                 case SC_DAPI_LEVEL_YEAR:
    2295             :                     {
    2296           0 :                         const ScDPItemData* pLastNumData = NULL;
    2297           0 :                         for ( SCROW n = 0 ;n <GetSrcItemsCount() ; n-- )
    2298             :                         {
    2299           0 :                             const ScDPItemData* pData  = GetSrcItemDataByIndex( n );
    2300           0 :                             if ( pData && pData->HasStringData() )
    2301           0 :                                 break;
    2302             :                             else
    2303           0 :                                 pLastNumData = pData;
    2304             :                         }
    2305             : 
    2306           0 :                         if ( pLastNumData )
    2307             :                         {
    2308           0 :                             const ScDPItemData*  pFirstData = GetSrcItemDataByIndex( 0 );
    2309           0 :                             double fFirstVal = pFirstData->GetValue();
    2310           0 :                             double fLastVal = pLastNumData->GetValue();
    2311             : 
    2312             :                             long nFirstYear = pSource->GetData()->GetDatePart(
    2313           0 :                                         (long)::rtl::math::approxFloor( fFirstVal ),
    2314           0 :                                         nHier, nLev );
    2315             :                             long nLastYear = pSource->GetData()->GetDatePart(
    2316           0 :                                         (long)::rtl::math::approxFloor( fLastVal ),
    2317           0 :                                         nHier, nLev );
    2318             : 
    2319           0 :                             nMbrCount = nLastYear + 1 - nFirstYear;
    2320             :                         }
    2321             :                         else
    2322           0 :                             nMbrCount = 0;      // no values
    2323             :                     }
    2324           0 :                     break;
    2325           0 :                 case SC_DAPI_LEVEL_QUARTER: nMbrCount = 4;  break;
    2326           0 :                 case SC_DAPI_LEVEL_MONTH:   nMbrCount = 12; break;
    2327           0 :                 case SC_DAPI_LEVEL_DAY:     nMbrCount = 31; break;
    2328             :                 default:
    2329             :                     OSL_FAIL( "ScDPMembers::ScDPMembers: unexpected level" );
    2330           0 :                     break;
    2331             :             }
    2332             :         }
    2333           0 :         else if ( nHier == SC_DAPI_HIERARCHY_WEEK )
    2334             :         {
    2335           0 :             switch (nLev)
    2336             :             {
    2337           0 :                 case SC_DAPI_LEVEL_YEAR:    nMbrCount = 1;  break;      //! get years from source
    2338           0 :                 case SC_DAPI_LEVEL_WEEK:    nMbrCount = 53; break;
    2339           0 :                 case SC_DAPI_LEVEL_WEEKDAY: nMbrCount = 7;  break;
    2340             :                 default:
    2341             :                     OSL_FAIL( "ScDPMembers::ScDPMembers: unexpected level" );
    2342           0 :                     break;
    2343             :             }
    2344             :         }
    2345             :     }
    2346             :     else
    2347         374 :         nMbrCount = pSource->GetData()->GetMembersCount( nSrcDim );
    2348         392 : }
    2349             : 
    2350         784 : ScDPMembers::~ScDPMembers()
    2351             : {
    2352         784 : }
    2353             : 
    2354             : // XNameAccess implementation using getCount/getByIndex
    2355             : 
    2356        2646 : sal_Int32 ScDPMembers::GetIndexFromName( const OUString& rName ) const
    2357             : {
    2358        2646 :     if ( aHashMap.empty() )
    2359             :     {
    2360             :         // store the index for each name
    2361             : 
    2362         186 :         sal_Int32 nCount = getCount();
    2363         982 :         for (sal_Int32 i=0; i<nCount; i++)
    2364         796 :             aHashMap[ getByIndex(i)->getName() ] = i;
    2365             :     }
    2366             : 
    2367        2646 :     ScDPMembersHashMap::const_iterator aIter = aHashMap.find( rName );
    2368        2646 :     if ( aIter != aHashMap.end() )
    2369        2624 :         return aIter->second;           // found index
    2370             :     else
    2371          22 :         return -1;                      // not found
    2372             : }
    2373             : 
    2374        1130 : uno::Any SAL_CALL ScDPMembers::getByName( const OUString& aName )
    2375             :             throw(container::NoSuchElementException,
    2376             :                     lang::WrappedTargetException, uno::RuntimeException, std::exception)
    2377             : {
    2378        1130 :     sal_Int32 nIndex = GetIndexFromName( aName );
    2379        1130 :     if ( nIndex >= 0 )
    2380             :     {
    2381        1130 :         uno::Reference<container::XNamed> xNamed = getByIndex(nIndex);
    2382        2260 :         uno::Any aRet;
    2383        1130 :         aRet <<= xNamed;
    2384        3390 :         return aRet;
    2385             :     }
    2386             : 
    2387           0 :     throw container::NoSuchElementException();
    2388             : }
    2389             : 
    2390         220 : uno::Sequence<OUString> SAL_CALL ScDPMembers::getElementNames() throw(uno::RuntimeException, std::exception)
    2391             : {
    2392             :     // Return list of names in sorted order,
    2393             :     // so it's displayed in that order in the field options dialog.
    2394             :     // Sorting is done at the level object (parent of this).
    2395             : 
    2396         220 :     ScDPLevel* pLevel = pSource->GetDimensionsObject()->getByIndex(nDim)->
    2397         220 :         GetHierarchiesObject()->getByIndex(nHier)->GetLevelsObject()->getByIndex(nLev);
    2398         220 :     pLevel->EvaluateSortOrder();
    2399         220 :     const std::vector<sal_Int32>& rGlobalOrder = pLevel->GetGlobalOrder();
    2400         220 :     bool bSort = !rGlobalOrder.empty();
    2401             : 
    2402         220 :     long nCount = getCount();
    2403         220 :     uno::Sequence<OUString> aSeq(nCount);
    2404         220 :     OUString* pArr = aSeq.getArray();
    2405        1190 :     for (long i=0; i<nCount; i++)
    2406         970 :         pArr[i] = getByIndex(bSort ? rGlobalOrder[i] : i)->getName();
    2407         220 :     return aSeq;
    2408             : }
    2409             : 
    2410         596 : sal_Bool SAL_CALL ScDPMembers::hasByName( const OUString& aName ) throw(uno::RuntimeException, std::exception)
    2411             : {
    2412         596 :     return ( GetIndexFromName( aName ) >= 0 );
    2413             : }
    2414             : 
    2415           0 : uno::Type SAL_CALL ScDPMembers::getElementType() throw(uno::RuntimeException, std::exception)
    2416             : {
    2417           0 :     return cppu::UnoType<container::XNamed>::get();
    2418             : }
    2419             : 
    2420           0 : sal_Bool SAL_CALL ScDPMembers::hasElements() throw(uno::RuntimeException, std::exception)
    2421             : {
    2422           0 :     return ( getCount() > 0 );
    2423             : }
    2424             : 
    2425             : // end of XNameAccess implementation
    2426             : 
    2427         222 : long ScDPMembers::getMinMembers() const
    2428             : {
    2429             :     // used in lcl_CountMinMembers
    2430             : 
    2431         222 :     long nVisCount = 0;
    2432         222 :     if (!maMembers.empty())
    2433             :     {
    2434         218 :         MembersType::const_iterator it = maMembers.begin(), itEnd = maMembers.end();
    2435        1250 :         for (; it != itEnd; ++it)
    2436             :         {
    2437             :             //  count only visible with details (default is true for both)
    2438        1032 :             const rtl::Reference<ScDPMember>& pMbr = *it;
    2439        1032 :             if (!pMbr.get() || (pMbr->isVisible() && pMbr->getShowDetails()))
    2440        1032 :                 ++nVisCount;
    2441             :         }
    2442             :     }
    2443             :     else
    2444           4 :         nVisCount = nMbrCount;      // default for all
    2445             : 
    2446         222 :     return nVisCount;
    2447             : }
    2448             : 
    2449       13348 : ScDPMember* ScDPMembers::getByIndex(long nIndex) const
    2450             : {
    2451             :     //  result of GetColumnEntries must not change between ScDPMembers ctor
    2452             :     //  and all calls to getByIndex
    2453             : 
    2454       13348 :     if ( nIndex >= 0 && nIndex < nMbrCount )
    2455             :     {
    2456       13348 :         if (maMembers.empty())
    2457         392 :             maMembers.resize(nMbrCount);
    2458             : 
    2459       13348 :         if (!maMembers[nIndex].get())
    2460             :         {
    2461        1688 :             rtl::Reference<ScDPMember> pNew;
    2462        1688 :             long nSrcDim = pSource->GetSourceDim( nDim );
    2463        1688 :             if ( pSource->IsDataLayoutDimension(nSrcDim) )
    2464             :             {
    2465             :                 // empty name (never shown, not used for lookup)
    2466          36 :                 pNew.set(new ScDPMember(pSource, nDim, nHier, nLev, 0));
    2467             :             }
    2468        1652 :             else if ( nHier != SC_DAPI_HIERARCHY_FLAT && pSource->IsDateDimension( nSrcDim ) )
    2469             :             {
    2470           0 :                 sal_Int32 nGroupBy = 0;
    2471           0 :                 sal_Int32 nVal = 0;
    2472           0 :                 OUString aName;
    2473             : 
    2474           0 :                 if ( nLev == SC_DAPI_LEVEL_YEAR )   // YEAR is in both hierarchies
    2475             :                 {
    2476             :                     //! cache year range here!
    2477             : 
    2478           0 :                     double fFirstVal = pSource->GetData()->GetMemberByIndex( nSrcDim, 0 )->GetValue();
    2479             :                     long nFirstYear = pSource->GetData()->GetDatePart(
    2480           0 :                                         (long)::rtl::math::approxFloor( fFirstVal ),
    2481           0 :                                         nHier, nLev );
    2482             : 
    2483           0 :                     nVal = nFirstYear + nIndex;
    2484             :                 }
    2485           0 :                 else if ( nHier == SC_DAPI_HIERARCHY_WEEK && nLev == SC_DAPI_LEVEL_WEEKDAY )
    2486             :                 {
    2487           0 :                     nVal = nIndex;              // DayOfWeek is 0-based
    2488           0 :                     aName = ScGlobal::GetCalendar()->getDisplayName(
    2489             :                         ::com::sun::star::i18n::CalendarDisplayIndex::DAY,
    2490           0 :                         sal::static_int_cast<sal_Int16>(nVal), 0 );
    2491             :                 }
    2492           0 :                 else if ( nHier == SC_DAPI_HIERARCHY_QUARTER && nLev == SC_DAPI_LEVEL_MONTH )
    2493             :                 {
    2494           0 :                     nVal = nIndex;              // Month is 0-based
    2495           0 :                     aName = ScGlobal::GetCalendar()->getDisplayName(
    2496             :                         ::com::sun::star::i18n::CalendarDisplayIndex::MONTH,
    2497           0 :                         sal::static_int_cast<sal_Int16>(nVal), 0 );
    2498             :                 }
    2499             :                 else
    2500           0 :                     nVal = nIndex + 1;          // Quarter, Day, Week are 1-based
    2501             : 
    2502           0 :                 switch (nLev)
    2503             :                 {
    2504             :                     case SC_DAPI_LEVEL_YEAR:
    2505           0 :                         nGroupBy = sheet::DataPilotFieldGroupBy::YEARS;
    2506           0 :                     break;
    2507             :                     case SC_DAPI_LEVEL_QUARTER:
    2508             :                     case SC_DAPI_LEVEL_WEEK:
    2509           0 :                         nGroupBy = sheet::DataPilotFieldGroupBy::QUARTERS;
    2510           0 :                     break;
    2511             :                     case SC_DAPI_LEVEL_MONTH:
    2512             :                     case SC_DAPI_LEVEL_WEEKDAY:
    2513           0 :                         nGroupBy = sheet::DataPilotFieldGroupBy::MONTHS;
    2514           0 :                     break;
    2515             :                     case SC_DAPI_LEVEL_DAY:
    2516           0 :                         nGroupBy = sheet::DataPilotFieldGroupBy::DAYS;
    2517           0 :                     break;
    2518             :                     default:
    2519             :                         ;
    2520             :                 }
    2521           0 :                 if (aName.isEmpty())
    2522           0 :                     aName = OUString::number(nVal);
    2523             : 
    2524           0 :                 ScDPItemData aData(nGroupBy, nVal);
    2525           0 :                 SCROW nId = pSource->GetCache()->GetIdByItemData(nDim, aData);
    2526           0 :                 pNew.set(new ScDPMember(pSource, nDim, nHier, nLev, nId));
    2527             :             }
    2528             :             else
    2529             :             {
    2530        1652 :                 const std::vector<SCROW>& memberIndexs = pSource->GetData()->GetColumnEntries(nSrcDim);
    2531        1652 :                 pNew.set(new ScDPMember(pSource, nDim, nHier, nLev, memberIndexs[nIndex]));
    2532             :             }
    2533        1688 :             maMembers[nIndex] = pNew;
    2534             :         }
    2535             : 
    2536       13348 :         return maMembers[nIndex].get();
    2537             :     }
    2538             : 
    2539           0 :     return NULL;    //! exception?
    2540             : }
    2541             : 
    2542        1688 : ScDPMember::ScDPMember(
    2543             :     ScDPSource* pSrc, long nD, long nH, long nL, SCROW nIndex) :
    2544             :     pSource( pSrc ),
    2545             :     nDim( nD ),
    2546             :     nHier( nH ),
    2547             :     nLev( nL ),
    2548             :     mnDataId( nIndex ),
    2549             :     mpLayoutName(NULL),
    2550             :     nPosition( -1 ),
    2551             :     bVisible( true ),
    2552        1688 :     bShowDet( true )
    2553             : {
    2554             :     //! hold pSource
    2555        1688 : }
    2556             : 
    2557        3376 : ScDPMember::~ScDPMember()
    2558             : {
    2559             :     //! release pSource
    2560        3376 : }
    2561             : 
    2562        6854 : bool ScDPMember::IsNamedItem(SCROW nIndex) const
    2563             : {
    2564        6854 :     long nSrcDim = pSource->GetSourceDim( nDim );
    2565        6854 :     if ( nHier != SC_DAPI_HIERARCHY_FLAT && pSource->IsDateDimension( nSrcDim ) )
    2566             :     {
    2567           0 :         const ScDPItemData* pData = pSource->GetCache()->GetItemDataById(nDim, nIndex);
    2568           0 :         if (pData->IsValue())
    2569             :         {
    2570             :             long nComp = pSource->GetData()->GetDatePart(
    2571           0 :                 (long)::rtl::math::approxFloor( pData->GetValue() ),
    2572           0 :                 nHier, nLev );
    2573             :             //  fValue is converted from integer, so simple comparison works
    2574           0 :             const ScDPItemData* pData2 = GetItemData();
    2575           0 :             return pData2 && nComp == pData2->GetValue();
    2576             :         }
    2577             :     }
    2578             : 
    2579        6854 :     return  nIndex == mnDataId;
    2580             : }
    2581             : 
    2582        3370 : sal_Int32 ScDPMember::Compare( const ScDPMember& rOther ) const
    2583             : {
    2584        3370 :     if ( nPosition >= 0 )
    2585             :     {
    2586         362 :         if ( rOther.nPosition >= 0 )
    2587             :         {
    2588             :             OSL_ENSURE( nPosition != rOther.nPosition, "same position for two members" );
    2589         360 :             return ( nPosition < rOther.nPosition ) ? -1 : 1;
    2590             :         }
    2591             :         else
    2592             :         {
    2593             :             // only this has a position - members with specified positions come before those without
    2594           2 :             return -1;
    2595             :         }
    2596             :     }
    2597        3008 :     else if ( rOther.nPosition >= 0 )
    2598             :     {
    2599             :         // only rOther has a position
    2600           6 :         return 1;
    2601             :     }
    2602             : 
    2603             :     // no positions set - compare names
    2604        3002 :    return pSource->GetData()->Compare( pSource->GetSourceDim(nDim),mnDataId,rOther.GetItemDataId());
    2605             : }
    2606             : 
    2607       15944 : void ScDPMember::FillItemData( ScDPItemData& rData ) const
    2608             : {
    2609             :     //! handle date hierarchy...
    2610             : 
    2611       15944 :     const ScDPItemData* pData = GetItemData();
    2612       15944 :     rData = (pData ? *pData : ScDPItemData());
    2613       15944 : }
    2614             : 
    2615        1148 : const OUString* ScDPMember::GetLayoutName() const
    2616             : {
    2617        1148 :     return mpLayoutName.get();
    2618             : }
    2619             : 
    2620        1924 : OUString ScDPMember::GetNameStr() const
    2621             : {
    2622        1924 :     const ScDPItemData* pData = GetItemData();
    2623        1924 :     if (pData)
    2624        1924 :         return pSource->GetData()->GetFormattedString(nDim, *pData);
    2625           0 :     return OUString();
    2626             : }
    2627             : 
    2628        1900 : OUString SAL_CALL ScDPMember::getName() throw(uno::RuntimeException, std::exception)
    2629             : {
    2630        1900 :     return GetNameStr();
    2631             : }
    2632             : 
    2633           0 : void SAL_CALL ScDPMember::setName( const OUString& /* rNewName */ ) throw(uno::RuntimeException, std::exception)
    2634             : {
    2635             :     OSL_FAIL("not implemented");        //! exception?
    2636           0 : }
    2637             : 
    2638             : // XPropertySet
    2639             : 
    2640           0 : uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDPMember::getPropertySetInfo()
    2641             :                                                         throw(uno::RuntimeException, std::exception)
    2642             : {
    2643           0 :     SolarMutexGuard aGuard;
    2644             : 
    2645             :     static const SfxItemPropertyMapEntry aDPMemberMap_Impl[] =
    2646             :     {
    2647           0 :         { OUString(SC_UNO_DP_ISVISIBLE), 0,  getBooleanCppuType(),              0, 0 },
    2648           0 :         { OUString(SC_UNO_DP_POSITION), 0,  cppu::UnoType<sal_Int32>::get(),        0, 0 },
    2649           0 :         { OUString(SC_UNO_DP_SHOWDETAILS), 0,  getBooleanCppuType(),              0, 0 },
    2650           0 :         { OUString(SC_UNO_DP_LAYOUTNAME), 0, cppu::UnoType<OUString>::get(), 0, 0 },
    2651             :         { OUString(), 0, css::uno::Type(), 0, 0 }
    2652           0 :     };
    2653             :     static uno::Reference<beans::XPropertySetInfo> aRef =
    2654           0 :         new SfxItemPropertySetInfo( aDPMemberMap_Impl );
    2655           0 :     return aRef;
    2656             : }
    2657             : 
    2658        1176 : void SAL_CALL ScDPMember::setPropertyValue( const OUString& aPropertyName, const uno::Any& aValue )
    2659             :                 throw(beans::UnknownPropertyException, beans::PropertyVetoException,
    2660             :                         lang::IllegalArgumentException, lang::WrappedTargetException,
    2661             :                         uno::RuntimeException, std::exception)
    2662             : {
    2663        1176 :     if ( aPropertyName.equalsAscii( SC_UNO_DP_ISVISIBLE ) )
    2664         552 :         bVisible = lcl_GetBoolFromAny(aValue);
    2665         624 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_SHOWDETAILS ) )
    2666         470 :         bShowDet = lcl_GetBoolFromAny(aValue);
    2667         154 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_POSITION ) )
    2668         154 :         aValue >>= nPosition;
    2669           0 :     else if (aPropertyName.equalsAscii(SC_UNO_DP_LAYOUTNAME))
    2670             :     {
    2671           0 :         OUString aName;
    2672           0 :         if (aValue >>= aName)
    2673           0 :             mpLayoutName.reset(new OUString(aName));
    2674             :     }
    2675             :     else
    2676             :     {
    2677             :         OSL_FAIL("unknown property");
    2678             :     }
    2679        1176 : }
    2680             : 
    2681         640 : uno::Any SAL_CALL ScDPMember::getPropertyValue( const OUString& aPropertyName )
    2682             :                 throw(beans::UnknownPropertyException, lang::WrappedTargetException,
    2683             :                         uno::RuntimeException, std::exception)
    2684             : {
    2685         640 :     uno::Any aRet;
    2686         640 :     if ( aPropertyName.equalsAscii( SC_UNO_DP_ISVISIBLE ) )
    2687         288 :         lcl_SetBoolInAny(aRet, bVisible);
    2688         352 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_SHOWDETAILS ) )
    2689          66 :         lcl_SetBoolInAny(aRet, bShowDet);
    2690         286 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_POSITION ) )
    2691           0 :         aRet <<= nPosition;
    2692         286 :     else if (aPropertyName.equalsAscii(SC_UNO_DP_LAYOUTNAME))
    2693         286 :         aRet <<= mpLayoutName.get() ? *mpLayoutName : OUString();
    2694             :     else
    2695             :     {
    2696             :         OSL_FAIL("unknown property");
    2697             :     }
    2698         640 :     return aRet;
    2699             : }
    2700             : 
    2701           0 : SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDPMember )
    2702             : 
    2703           0 : const ScDPCache* ScDPSource::GetCache()
    2704             : {
    2705             :     OSL_ENSURE( GetData() , "empty ScDPTableData pointer");
    2706           0 :     return ( GetData()!=NULL ) ? &GetData()->GetCacheTable().getCache() : NULL ;
    2707             : }
    2708             : 
    2709       17868 : const ScDPItemData* ScDPMember::GetItemData() const
    2710             : {
    2711       17868 :     const ScDPItemData* pData = pSource->GetItemDataById(nDim, mnDataId);
    2712             :     SAL_WARN_IF( !pData, "sc", "ScDPMember::GetItemData: what data? nDim " << nDim << ", mnDataId " << mnDataId);
    2713       17868 :     return pData;
    2714             : }
    2715             : 
    2716       18002 : const ScDPItemData* ScDPSource::GetItemDataById(long nDim, long nId)
    2717             : {
    2718       18002 :     return GetData()->GetMemberById(nDim, nId);
    2719             : }
    2720             : 
    2721           0 : SCROW ScDPSource::GetMemberId(long nDim, const ScDPItemData& rData)
    2722             : {
    2723           0 :     return GetCache()->GetIdByItemData(nDim, rData);
    2724             : }
    2725             : 
    2726           0 : const ScDPItemData* ScDPMembers::GetSrcItemDataByIndex(SCROW nIndex)
    2727             : {
    2728           0 :     const std::vector< SCROW >& memberIds = pSource->GetData()->GetColumnEntries( nDim );
    2729           0 :     if ( nIndex >= (long )(memberIds.size()) || nIndex < 0 )
    2730           0 :         return NULL;
    2731           0 :     SCROW nId =  memberIds[ nIndex ];
    2732           0 :     return pSource->GetItemDataById( nDim, nId );
    2733             : }
    2734             : 
    2735           0 : SCROW ScDPMembers::GetSrcItemsCount()
    2736             : {
    2737           0 :     return pSource->GetData()->GetColumnEntries(nDim).size();
    2738         228 : }
    2739             : 
    2740             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10