LCOV - code coverage report
Current view: top level - sc/source/core/data - dpobject.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 906 1876 48.3 %
Date: 2014-04-11 Functions: 100 173 57.8 %
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 "dpobject.hxx"
      21             : #include "dptabsrc.hxx"
      22             : #include "dpsave.hxx"
      23             : #include "dpdimsave.hxx"
      24             : #include "dpoutput.hxx"
      25             : #include "dpshttab.hxx"
      26             : #include "dpsdbtab.hxx"
      27             : #include "dpgroup.hxx"
      28             : #include "document.hxx"
      29             : #include "rechead.hxx"
      30             : #include "pivot.hxx"
      31             : #include "dapiuno.hxx"
      32             : #include "miscuno.hxx"
      33             : #include "scerrors.hxx"
      34             : #include "refupdat.hxx"
      35             : #include "scresid.hxx"
      36             : #include "sc.hrc"
      37             : #include "attrib.hxx"
      38             : #include "scitems.hxx"
      39             : #include "unonames.hxx"
      40             : #include "dpglobal.hxx"
      41             : #include "globstr.hrc"
      42             : #include "queryentry.hxx"
      43             : #include "dputil.hxx"
      44             : 
      45             : #include <com/sun/star/beans/XPropertySet.hpp>
      46             : #include <com/sun/star/sdb/XCompletedExecution.hpp>
      47             : #include <com/sun/star/sdbc/DataType.hpp>
      48             : #include <com/sun/star/sdbc/XResultSetMetaData.hpp>
      49             : #include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
      50             : #include <com/sun/star/sdbc/XRow.hpp>
      51             : #include <com/sun/star/sdbc/XRowSet.hpp>
      52             : #include <com/sun/star/sheet/GeneralFunction.hpp>
      53             : #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
      54             : #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
      55             : #include <com/sun/star/sheet/DataPilotFieldReferenceType.hpp>
      56             : #include <com/sun/star/sheet/DataPilotTableHeaderData.hpp>
      57             : #include <com/sun/star/sheet/DataPilotTablePositionData.hpp>
      58             : #include <com/sun/star/sheet/DataPilotTablePositionType.hpp>
      59             : #include <com/sun/star/sheet/DimensionFlags.hpp>
      60             : #include <com/sun/star/task/InteractionHandler.hpp>
      61             : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
      62             : #include <com/sun/star/lang/XSingleServiceFactory.hpp>
      63             : #include <com/sun/star/lang/XSingleComponentFactory.hpp>
      64             : #include <com/sun/star/lang/XInitialization.hpp>
      65             : #include <com/sun/star/container/XContentEnumerationAccess.hpp>
      66             : #include <com/sun/star/sheet/XDrillDownDataSupplier.hpp>
      67             : 
      68             : #include <comphelper/processfactory.hxx>
      69             : #include <comphelper/string.hxx>
      70             : #include <comphelper/types.hxx>
      71             : #include <sal/macros.h>
      72             : #include <tools/debug.hxx>
      73             : #include <tools/diagnose_ex.h>
      74             : #include <svl/zforlist.hxx>
      75             : #include <vcl/msgbox.hxx>
      76             : 
      77             : #include <vector>
      78             : #include <memory>
      79             : 
      80             : #include <boost/unordered_map.hpp>
      81             : 
      82             : using namespace com::sun::star;
      83             : using ::std::vector;
      84             : using ::std::unary_function;
      85             : using ::boost::shared_ptr;
      86             : using ::com::sun::star::uno::Sequence;
      87             : using ::com::sun::star::uno::Reference;
      88             : using ::com::sun::star::uno::UNO_QUERY;
      89             : using ::com::sun::star::uno::Any;
      90             : using ::com::sun::star::uno::Exception;
      91             : using ::com::sun::star::lang::XComponent;
      92             : using ::com::sun::star::sheet::DataPilotTableHeaderData;
      93             : using ::com::sun::star::sheet::DataPilotTablePositionData;
      94             : using ::com::sun::star::sheet::XDimensionsSupplier;
      95             : using ::com::sun::star::beans::XPropertySet;
      96             : 
      97             : #define SC_SERVICE_ROWSET           "com.sun.star.sdb.RowSet"
      98             : 
      99             : #define SC_DBPROP_DATASOURCENAME    "DataSourceName"
     100             : #define SC_DBPROP_COMMAND           "Command"
     101             : #define SC_DBPROP_COMMANDTYPE       "CommandType"
     102             : 
     103             : #define SCDPSOURCE_SERVICE  "com.sun.star.sheet.DataPilotSource"
     104             : 
     105             : namespace {
     106             : 
     107             : /**
     108             :  * Database connection implementation for UNO database API.  Note that in
     109             :  * the UNO database API, column index is 1-based, whereas the interface
     110             :  * requires that column index be 0-based.
     111             :  */
     112           0 : class DBConnector : public ScDPCache::DBConnector
     113             : {
     114             :     ScDPCache& mrCache;
     115             : 
     116             :     uno::Reference<sdbc::XRowSet> mxRowSet;
     117             :     uno::Reference<sdbc::XRow> mxRow;
     118             :     uno::Reference<sdbc::XResultSetMetaData> mxMetaData;
     119             :     Date maNullDate;
     120             : 
     121             : public:
     122             :     DBConnector(ScDPCache& rCache, const uno::Reference<sdbc::XRowSet>& xRowSet, const Date& rNullDate);
     123             : 
     124             :     bool isValid() const;
     125             : 
     126             :     virtual void getValue(long nCol, ScDPItemData &rData, short& rNumType) const SAL_OVERRIDE;
     127             :     virtual OUString getColumnLabel(long nCol) const SAL_OVERRIDE;
     128             :     virtual long getColumnCount() const SAL_OVERRIDE;
     129             :     virtual bool first() SAL_OVERRIDE;
     130             :     virtual bool next() SAL_OVERRIDE;
     131             :     virtual void finish() SAL_OVERRIDE;
     132             : };
     133             : 
     134           0 : DBConnector::DBConnector(ScDPCache& rCache, const uno::Reference<sdbc::XRowSet>& xRowSet, const Date& rNullDate) :
     135           0 :     mrCache(rCache), mxRowSet(xRowSet), maNullDate(rNullDate)
     136             : {
     137           0 :     Reference<sdbc::XResultSetMetaDataSupplier> xMetaSupp(mxRowSet, UNO_QUERY);
     138           0 :     if (xMetaSupp.is())
     139           0 :         mxMetaData = xMetaSupp->getMetaData();
     140             : 
     141           0 :     mxRow.set(mxRowSet, UNO_QUERY);
     142           0 : }
     143             : 
     144           0 : bool DBConnector::isValid() const
     145             : {
     146           0 :     return mxRowSet.is() && mxRow.is() && mxMetaData.is();
     147             : }
     148             : 
     149           0 : bool DBConnector::first()
     150             : {
     151           0 :     return mxRowSet->first();
     152             : }
     153             : 
     154           0 : bool DBConnector::next()
     155             : {
     156           0 :     return mxRowSet->next();
     157             : }
     158             : 
     159           0 : void DBConnector::finish()
     160             : {
     161           0 :     mxRowSet->beforeFirst();
     162           0 : }
     163             : 
     164           0 : long DBConnector::getColumnCount() const
     165             : {
     166           0 :     return mxMetaData->getColumnCount();
     167             : }
     168             : 
     169           0 : OUString DBConnector::getColumnLabel(long nCol) const
     170             : {
     171           0 :     return mxMetaData->getColumnLabel(nCol+1);
     172             : }
     173             : 
     174           0 : void DBConnector::getValue(long nCol, ScDPItemData &rData, short& rNumType) const
     175             : {
     176           0 :     rNumType = NUMBERFORMAT_NUMBER;
     177           0 :     sal_Int32 nType = mxMetaData->getColumnType(nCol+1);
     178             : 
     179             :     try
     180             :     {
     181           0 :         double fValue = 0.0;
     182           0 :         switch (nType)
     183             :         {
     184             :             case sdbc::DataType::BIT:
     185             :             case sdbc::DataType::BOOLEAN:
     186             :             {
     187           0 :                 rNumType = NUMBERFORMAT_LOGICAL;
     188           0 :                 fValue  = mxRow->getBoolean(nCol+1) ? 1 : 0;
     189           0 :                 rData.SetValue(fValue);
     190           0 :                 break;
     191             :             }
     192             :             case sdbc::DataType::TINYINT:
     193             :             case sdbc::DataType::SMALLINT:
     194             :             case sdbc::DataType::INTEGER:
     195             :             case sdbc::DataType::BIGINT:
     196             :             case sdbc::DataType::FLOAT:
     197             :             case sdbc::DataType::REAL:
     198             :             case sdbc::DataType::DOUBLE:
     199             :             case sdbc::DataType::NUMERIC:
     200             :             case sdbc::DataType::DECIMAL:
     201             :             {
     202             :                 //! do the conversion here?
     203           0 :                 fValue = mxRow->getDouble(nCol+1);
     204           0 :                 rData.SetValue(fValue);
     205           0 :                 break;
     206             :             }
     207             :             case sdbc::DataType::DATE:
     208             :             {
     209           0 :                 rNumType = NUMBERFORMAT_DATE;
     210             : 
     211           0 :                 util::Date aDate = mxRow->getDate(nCol+1);
     212           0 :                 fValue = Date(aDate.Day, aDate.Month, aDate.Year) - maNullDate;
     213           0 :                 rData.SetValue(fValue);
     214           0 :                 break;
     215             :             }
     216             :             case sdbc::DataType::TIME:
     217             :             {
     218           0 :                 rNumType = NUMBERFORMAT_TIME;
     219             : 
     220           0 :                 util::Time aTime = mxRow->getTime(nCol+1);
     221           0 :                 fValue = aTime.Hours       / static_cast<double>(::Time::hourPerDay)   +
     222           0 :                          aTime.Minutes     / static_cast<double>(::Time::minutePerDay) +
     223           0 :                          aTime.Seconds     / static_cast<double>(::Time::secondPerDay) +
     224           0 :                          aTime.NanoSeconds / static_cast<double>(::Time::nanoSecPerDay);
     225           0 :                 rData.SetValue(fValue);
     226           0 :                 break;
     227             :             }
     228             :             case sdbc::DataType::TIMESTAMP:
     229             :             {
     230           0 :                 rNumType = NUMBERFORMAT_DATETIME;
     231             : 
     232           0 :                 util::DateTime aStamp = mxRow->getTimestamp(nCol+1);
     233           0 :                 fValue = ( Date( aStamp.Day, aStamp.Month, aStamp.Year ) - maNullDate ) +
     234           0 :                          aStamp.Hours       / static_cast<double>(::Time::hourPerDay)   +
     235           0 :                          aStamp.Minutes     / static_cast<double>(::Time::minutePerDay) +
     236           0 :                          aStamp.Seconds     / static_cast<double>(::Time::secondPerDay) +
     237           0 :                          aStamp.NanoSeconds / static_cast<double>(::Time::nanoSecPerDay);
     238           0 :                 rData.SetValue(fValue);
     239           0 :                 break;
     240             :             }
     241             :             case sdbc::DataType::CHAR:
     242             :             case sdbc::DataType::VARCHAR:
     243             :             case sdbc::DataType::LONGVARCHAR:
     244             :             case sdbc::DataType::SQLNULL:
     245             :             case sdbc::DataType::BINARY:
     246             :             case sdbc::DataType::VARBINARY:
     247             :             case sdbc::DataType::LONGVARBINARY:
     248             :             default:
     249           0 :                 rData.SetString(mrCache.InternString(mxRow->getString(nCol+1)));
     250             :         }
     251             :     }
     252           0 :     catch (uno::Exception&)
     253             :     {
     254           0 :         rData.SetEmpty();
     255             :     }
     256           0 : }
     257             : 
     258             : }
     259             : 
     260           0 : sal_uInt16 lcl_GetDataGetOrientation( const uno::Reference<sheet::XDimensionsSupplier>& xSource )
     261             : {
     262           0 :     long nRet = sheet::DataPilotFieldOrientation_HIDDEN;
     263           0 :     if ( xSource.is() )
     264             :     {
     265           0 :         uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
     266           0 :         uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName );
     267           0 :         long nIntCount = xIntDims->getCount();
     268           0 :         sal_Bool bFound = false;
     269           0 :         for (long nIntDim=0; nIntDim<nIntCount && !bFound; nIntDim++)
     270             :         {
     271             :             uno::Reference<uno::XInterface> xIntDim =
     272           0 :                 ScUnoHelpFunctions::AnyToInterface( xIntDims->getByIndex(nIntDim) );
     273           0 :             uno::Reference<beans::XPropertySet> xDimProp( xIntDim, uno::UNO_QUERY );
     274           0 :             if ( xDimProp.is() )
     275             :             {
     276             :                 bFound = ScUnoHelpFunctions::GetBoolProperty( xDimProp,
     277           0 :                     OUString(SC_UNO_DP_ISDATALAYOUT) );
     278             :                 //! error checking -- is "IsDataLayoutDimension" property required??
     279           0 :                 if (bFound)
     280             :                     nRet = ScUnoHelpFunctions::GetEnumProperty(
     281             :                             xDimProp, OUString(SC_UNO_DP_ORIENTATION),
     282           0 :                             sheet::DataPilotFieldOrientation_HIDDEN );
     283             :             }
     284           0 :         }
     285             :     }
     286           0 :     return static_cast< sal_uInt16 >( nRet );
     287             : }
     288             : 
     289           0 : ScDPServiceDesc::ScDPServiceDesc(
     290             :     const OUString& rServ, const OUString& rSrc, const OUString& rNam,
     291             :     const OUString& rUser, const OUString& rPass ) :
     292             :     aServiceName( rServ ),
     293             :     aParSource( rSrc ),
     294             :     aParName( rNam ),
     295             :     aParUser( rUser ),
     296           0 :     aParPass( rPass ) {}
     297             : 
     298           0 : bool ScDPServiceDesc::operator== ( const ScDPServiceDesc& rOther ) const
     299             : {
     300           0 :     return aServiceName == rOther.aServiceName &&
     301           0 :         aParSource == rOther.aParSource &&
     302           0 :         aParName == rOther.aParName &&
     303           0 :         aParUser == rOther.aParUser &&
     304           0 :         aParPass == rOther.aParPass;
     305             : }
     306             : 
     307          44 : ScDPObject::ScDPObject( ScDocument* pD ) :
     308             :     pDoc( pD ),
     309             :     pSaveData( NULL ),
     310             :     pSheetDesc( NULL ),
     311             :     pImpDesc( NULL ),
     312             :     pServDesc( NULL ),
     313             :     mpTableData(static_cast<ScDPTableData*>(NULL)),
     314             :     pOutput( NULL ),
     315             :     mnAutoFormatIndex( 65535 ),
     316             :     nHeaderRows( 0 ),
     317             :     mbHeaderLayout(false),
     318             :     bAllowMove(false),
     319             :     bSettingsChanged(false),
     320          44 :     mbEnableGetPivotData(true)
     321             : {
     322          44 : }
     323             : 
     324         109 : ScDPObject::ScDPObject(const ScDPObject& r) :
     325             :     pDoc( r.pDoc ),
     326             :     pSaveData( NULL ),
     327             :     aTableName( r.aTableName ),
     328             :     aTableTag( r.aTableTag ),
     329             :     aOutRange( r.aOutRange ),
     330             :     pSheetDesc( NULL ),
     331             :     pImpDesc( NULL ),
     332             :     pServDesc( NULL ),
     333             :     mpTableData(static_cast<ScDPTableData*>(NULL)),
     334             :     pOutput( NULL ),
     335             :     mnAutoFormatIndex( r.mnAutoFormatIndex ),
     336             :     nHeaderRows( r.nHeaderRows ),
     337             :     mbHeaderLayout( r.mbHeaderLayout ),
     338             :     bAllowMove(false),
     339             :     bSettingsChanged(false),
     340         109 :     mbEnableGetPivotData(r.mbEnableGetPivotData)
     341             : {
     342         109 :     if (r.pSaveData)
     343         109 :         pSaveData = new ScDPSaveData(*r.pSaveData);
     344         109 :     if (r.pSheetDesc)
     345         109 :         pSheetDesc = new ScSheetSourceDesc(*r.pSheetDesc);
     346         109 :     if (r.pImpDesc)
     347           0 :         pImpDesc = new ScImportSourceDesc(*r.pImpDesc);
     348         109 :     if (r.pServDesc)
     349           0 :         pServDesc = new ScDPServiceDesc(*r.pServDesc);
     350             :     // xSource (and pOutput) is not copied
     351         109 : }
     352             : 
     353         302 : ScDPObject::~ScDPObject()
     354             : {
     355         151 :     Clear();
     356         151 : }
     357             : 
     358           0 : ScDPObject& ScDPObject::operator= (const ScDPObject& r)
     359             : {
     360           0 :     Clear();
     361             : 
     362           0 :     pDoc = r.pDoc;
     363           0 :     aTableName = r.aTableName;
     364           0 :     aTableTag = r.aTableTag;
     365           0 :     aOutRange = r.aOutRange;
     366           0 :     mnAutoFormatIndex = r.mnAutoFormatIndex;
     367           0 :     nHeaderRows = r.nHeaderRows;
     368           0 :     mbHeaderLayout = r.mbHeaderLayout;
     369           0 :     bAllowMove = false;
     370           0 :     bSettingsChanged = false;
     371           0 :     mbEnableGetPivotData = r.mbEnableGetPivotData;
     372             : 
     373           0 :     if (r.pSaveData)
     374           0 :         pSaveData = new ScDPSaveData(*r.pSaveData);
     375           0 :     if (r.pSheetDesc)
     376           0 :         pSheetDesc = new ScSheetSourceDesc(*r.pSheetDesc);
     377           0 :     if (r.pImpDesc)
     378           0 :         pImpDesc = new ScImportSourceDesc(*r.pImpDesc);
     379           0 :     if (r.pServDesc)
     380           0 :         pServDesc = new ScDPServiceDesc(*r.pServDesc);
     381             : 
     382           0 :     return *this;
     383             : }
     384             : 
     385         162 : void ScDPObject::EnableGetPivotData(bool b)
     386             : {
     387         162 :     mbEnableGetPivotData = b;
     388         162 : }
     389             : 
     390          29 : void ScDPObject::SetAllowMove(bool bSet)
     391             : {
     392          29 :     bAllowMove = bSet;
     393          29 : }
     394             : 
     395          63 : void ScDPObject::SetSaveData(const ScDPSaveData& rData)
     396             : {
     397          63 :     if ( pSaveData != &rData )      // API implementation modifies the original SaveData object
     398             :     {
     399          56 :         delete pSaveData;
     400          56 :         pSaveData = new ScDPSaveData( rData );
     401             :     }
     402             : 
     403          63 :     InvalidateData();       // re-init source from SaveData
     404          63 : }
     405             : 
     406           8 : void ScDPObject::SetHeaderLayout (bool bUseGrid)
     407             : {
     408           8 :     mbHeaderLayout = bUseGrid;
     409           8 : }
     410             : 
     411           0 : bool ScDPObject::GetHeaderLayout() const
     412             : {
     413           0 :     return mbHeaderLayout;
     414             : }
     415             : 
     416         110 : void ScDPObject::SetOutRange(const ScRange& rRange)
     417             : {
     418         110 :     aOutRange = rRange;
     419             : 
     420         110 :     if ( pOutput )
     421          66 :         pOutput->SetPosition( rRange.aStart );
     422         110 : }
     423             : 
     424          65 : void ScDPObject::SetSheetDesc(const ScSheetSourceDesc& rDesc, bool /*bFromRefUpdate*/)
     425             : {
     426          65 :     if ( pSheetDesc && rDesc == *pSheetDesc )
     427          65 :         return;             // nothing to do
     428             : 
     429          65 :     DELETEZ( pImpDesc );
     430          65 :     DELETEZ( pServDesc );
     431             : 
     432          65 :     delete pSheetDesc;
     433          65 :     pSheetDesc = new ScSheetSourceDesc(rDesc);
     434             : 
     435             :     //  make valid QueryParam
     436             : 
     437          65 :     const ScRange& rSrcRange = pSheetDesc->GetSourceRange();
     438          65 :     ScQueryParam aParam = pSheetDesc->GetQueryParam();
     439          65 :     aParam.nCol1 = rSrcRange.aStart.Col();
     440          65 :     aParam.nRow1 = rSrcRange.aStart.Row();
     441          65 :     aParam.nCol2 = rSrcRange.aEnd.Col();
     442          65 :     aParam.nRow2 = rSrcRange.aEnd.Row();
     443          65 :     aParam.bHasHeader = true;
     444          65 :     pSheetDesc->SetQueryParam(aParam);
     445             : 
     446          65 :     ClearTableData();      // new source must be created
     447             : }
     448             : 
     449           0 : void ScDPObject::SetImportDesc(const ScImportSourceDesc& rDesc)
     450             : {
     451           0 :     if ( pImpDesc && rDesc == *pImpDesc )
     452           0 :         return;             // nothing to do
     453             : 
     454           0 :     DELETEZ( pSheetDesc );
     455           0 :     DELETEZ( pServDesc );
     456             : 
     457           0 :     delete pImpDesc;
     458           0 :     pImpDesc = new ScImportSourceDesc(rDesc);
     459             : 
     460           0 :     ClearTableData();      // new source must be created
     461             : }
     462             : 
     463           0 : void ScDPObject::SetServiceData(const ScDPServiceDesc& rDesc)
     464             : {
     465           0 :     if ( pServDesc && rDesc == *pServDesc )
     466           0 :         return;             // nothing to do
     467             : 
     468           0 :     DELETEZ( pSheetDesc );
     469           0 :     DELETEZ( pImpDesc );
     470             : 
     471           0 :     delete pServDesc;
     472           0 :     pServDesc = new ScDPServiceDesc(rDesc);
     473             : 
     474           0 :     ClearTableData();      // new source must be created
     475             : }
     476             : 
     477           0 : void ScDPObject::WriteSourceDataTo( ScDPObject& rDest ) const
     478             : {
     479           0 :     if ( pSheetDesc )
     480           0 :         rDest.SetSheetDesc( *pSheetDesc );
     481           0 :     else if ( pImpDesc )
     482           0 :         rDest.SetImportDesc( *pImpDesc );
     483           0 :     else if ( pServDesc )
     484           0 :         rDest.SetServiceData( *pServDesc );
     485             : 
     486             :     //  name/tag are not source data, but needed along with source data
     487             : 
     488           0 :     rDest.aTableName = aTableName;
     489           0 :     rDest.aTableTag  = aTableTag;
     490           0 : }
     491             : 
     492           0 : void ScDPObject::WriteTempDataTo( ScDPObject& rDest ) const
     493             : {
     494           0 :     rDest.nHeaderRows = nHeaderRows;
     495           0 : }
     496             : 
     497         133 : bool ScDPObject::IsSheetData() const
     498             : {
     499         133 :     return ( pSheetDesc != NULL );
     500             : }
     501             : 
     502          47 : void ScDPObject::SetName(const OUString& rNew)
     503             : {
     504          47 :     aTableName = rNew;
     505          47 : }
     506             : 
     507          26 : void ScDPObject::SetTag(const OUString& rNew)
     508             : {
     509          26 :     aTableTag = rNew;
     510          26 : }
     511             : 
     512           0 : bool ScDPObject::IsDataDescriptionCell(const ScAddress& rPos)
     513             : {
     514           0 :     if (!pSaveData)
     515           0 :         return false;
     516             : 
     517           0 :     long nDataDimCount = pSaveData->GetDataDimensionCount();
     518           0 :     if (nDataDimCount != 1)
     519             :         // There has to be exactly one data dimension for the description to
     520             :         // appear at top-left corner.
     521           0 :         return false;
     522             : 
     523           0 :     CreateOutput();
     524           0 :     ScRange aTabRange = pOutput->GetOutputRange(sheet::DataPilotOutputRangeType::TABLE);
     525           0 :     return (rPos == aTabRange.aStart);
     526             : }
     527             : 
     528         360 : uno::Reference<sheet::XDimensionsSupplier> ScDPObject::GetSource()
     529             : {
     530         360 :     CreateObjects();
     531         360 :     return xSource;
     532             : }
     533             : 
     534         674 : void ScDPObject::CreateOutput()
     535             : {
     536         674 :     CreateObjects();
     537         674 :     if (!pOutput)
     538             :     {
     539          83 :         sal_Bool bFilterButton = IsSheetData() && pSaveData && pSaveData->GetFilterButton();
     540          83 :         pOutput = new ScDPOutput( pDoc, xSource, aOutRange.aStart, bFilterButton );
     541          83 :         pOutput->SetHeaderLayout ( mbHeaderLayout );
     542             : 
     543          83 :         long nOldRows = nHeaderRows;
     544          83 :         nHeaderRows = pOutput->GetHeaderRows();
     545             : 
     546          83 :         if ( bAllowMove && nHeaderRows != nOldRows )
     547             :         {
     548           0 :             long nDiff = nOldRows - nHeaderRows;
     549           0 :             if ( nOldRows == 0 )
     550           0 :                 --nDiff;
     551           0 :             if ( nHeaderRows == 0 )
     552           0 :                 ++nDiff;
     553             : 
     554           0 :             long nNewRow = aOutRange.aStart.Row() + nDiff;
     555           0 :             if ( nNewRow < 0 )
     556           0 :                 nNewRow = 0;
     557             : 
     558           0 :             ScAddress aStart( aOutRange.aStart );
     559           0 :             aStart.SetRow(nNewRow);
     560           0 :             pOutput->SetPosition( aStart );
     561             : 
     562             :             //! modify aOutRange?
     563             : 
     564           0 :             bAllowMove = false;     // use only once
     565             :         }
     566             :     }
     567         674 : }
     568             : 
     569             : namespace {
     570             : 
     571             : class DisableGetPivotData
     572             : {
     573             :     ScDPObject& mrDPObj;
     574             :     bool mbOldState;
     575             : public:
     576          81 :     DisableGetPivotData(ScDPObject& rObj, bool bOld) : mrDPObj(rObj), mbOldState(bOld)
     577             :     {
     578          81 :         mrDPObj.EnableGetPivotData(false);
     579          81 :     }
     580             : 
     581          81 :     ~DisableGetPivotData()
     582             :     {
     583          81 :         mrDPObj.EnableGetPivotData(mbOldState);
     584          81 :     }
     585             : };
     586             : 
     587           0 : class FindIntersectingTable : std::unary_function<ScDPObject, bool>
     588             : {
     589             :     ScRange maRange;
     590             : public:
     591           0 :     FindIntersectingTable(const ScRange& rRange) : maRange(rRange) {}
     592             : 
     593           0 :     bool operator() (const ScDPObject& rObj) const
     594             :     {
     595           0 :         return maRange.Intersects(rObj.GetOutRange());
     596             :     }
     597             : };
     598             : 
     599             : class FindIntersetingTableByColumns : std::unary_function<ScDPObject, bool>
     600             : {
     601             :     SCCOL mnCol1;
     602             :     SCCOL mnCol2;
     603             :     SCROW mnRow;
     604             :     SCTAB mnTab;
     605             : public:
     606           0 :     FindIntersetingTableByColumns(SCCOL nCol1, SCCOL nCol2, SCROW nRow, SCTAB nTab) :
     607           0 :         mnCol1(nCol1), mnCol2(nCol2), mnRow(nRow), mnTab(nTab) {}
     608             : 
     609           0 :     bool operator() (const ScDPObject& rObj) const
     610             :     {
     611           0 :         const ScRange& rRange = rObj.GetOutRange();
     612           0 :         if (mnTab != rRange.aStart.Tab())
     613             :             // Not on this sheet.
     614           0 :             return false;
     615             : 
     616           0 :         if (rRange.aEnd.Row() < mnRow)
     617             :             // This table is above the row.  It's safe.
     618           0 :             return false;
     619             : 
     620           0 :         if (mnCol1 <= rRange.aStart.Col() && rRange.aEnd.Col() <= mnCol2)
     621             :             // This table is fully enclosed in this column range.
     622           0 :             return false;
     623             : 
     624           0 :         if (rRange.aEnd.Col() < mnCol1 || mnCol2 < rRange.aStart.Col())
     625             :             // This table is entirely outside this column range.
     626           0 :             return false;
     627             : 
     628             :         // This table must be intersected by this column range.
     629           0 :         return true;
     630             :     }
     631             : };
     632             : 
     633             : class FindIntersectingTableByRows : std::unary_function<ScDPObject, bool>
     634             : {
     635             :     SCCOL mnCol;
     636             :     SCROW mnRow1;
     637             :     SCROW mnRow2;
     638             :     SCTAB mnTab;
     639             : public:
     640           0 :     FindIntersectingTableByRows(SCCOL nCol, SCROW nRow1, SCROW nRow2, SCTAB nTab) :
     641           0 :         mnCol(nCol), mnRow1(nRow1), mnRow2(nRow2), mnTab(nTab) {}
     642             : 
     643           0 :     bool operator() (const ScDPObject& rObj) const
     644             :     {
     645           0 :         const ScRange& rRange = rObj.GetOutRange();
     646           0 :         if (mnTab != rRange.aStart.Tab())
     647             :             // Not on this sheet.
     648           0 :             return false;
     649             : 
     650           0 :         if (rRange.aEnd.Col() < mnCol)
     651             :             // This table is to the left of the column.  It's safe.
     652           0 :             return false;
     653             : 
     654           0 :         if (mnRow1 <= rRange.aStart.Row() && rRange.aEnd.Row() <= mnRow2)
     655             :             // This table is fully enclosed in this row range.
     656           0 :             return false;
     657             : 
     658           0 :         if (rRange.aEnd.Row() < mnRow1 || mnRow2 < rRange.aStart.Row())
     659             :             // This table is entirely outside this row range.
     660           0 :             return false;
     661             : 
     662             :         // This table must be intersected by this row range.
     663           0 :         return true;
     664             :     }
     665             : };
     666             : 
     667         132 : class AccumulateOutputRanges : std::unary_function<ScDPObject, void>
     668             : {
     669             :     ScRangeList maRanges;
     670             :     SCTAB mnTab;
     671             : public:
     672          66 :     AccumulateOutputRanges(SCTAB nTab) : mnTab(nTab) {}
     673          66 :     AccumulateOutputRanges(const AccumulateOutputRanges& r) : maRanges(r.maRanges), mnTab(r.mnTab) {}
     674             : 
     675         132 :     void operator() (const ScDPObject& rObj)
     676             :     {
     677         132 :         const ScRange& rRange = rObj.GetOutRange();
     678         132 :         if (mnTab != rRange.aStart.Tab())
     679             :             // Not on this sheet.
     680         224 :             return;
     681             : 
     682          40 :         maRanges.Join(rRange);
     683             :     }
     684             : 
     685          66 :     ScRangeList getRanges() const { return maRanges; }
     686             : };
     687             : 
     688             : }
     689             : 
     690         158 : ScDPTableData* ScDPObject::GetTableData()
     691             : {
     692         158 :     if (!mpTableData)
     693             :     {
     694          81 :         shared_ptr<ScDPTableData> pData;
     695          81 :         const ScDPDimensionSaveData* pDimData = pSaveData ? pSaveData->GetExistingDimensionData() : NULL;
     696             : 
     697          81 :         if ( pImpDesc )
     698             :         {
     699             :             // database data
     700           0 :             const ScDPCache* pCache = pImpDesc->CreateCache(pDimData);
     701           0 :             if (pCache)
     702             :             {
     703           0 :                 pCache->AddReference(this);
     704           0 :                 pData.reset(new ScDatabaseDPData(pDoc, *pCache));
     705             :             }
     706             :         }
     707             :         else
     708             :         {
     709             :             // cell data
     710          81 :             if (!pSheetDesc)
     711             :             {
     712             :                 OSL_FAIL("no source descriptor");
     713           0 :                 pSheetDesc = new ScSheetSourceDesc(pDoc);     // dummy defaults
     714             :             }
     715             : 
     716             :             {
     717             :                 // Temporarily disable GETPIVOTDATA to avoid having
     718             :                 // GETPIVOTDATA called onto itself from within the source
     719             :                 // range.
     720          81 :                 DisableGetPivotData aSwitch(*this, mbEnableGetPivotData);
     721          81 :                 const ScDPCache* pCache = pSheetDesc->CreateCache(pDimData);
     722          81 :                 if (pCache)
     723             :                 {
     724          81 :                     pCache->AddReference(this);
     725          81 :                     pData.reset(new ScSheetDPData(pDoc, *pSheetDesc, *pCache));
     726          81 :                 }
     727             :             }
     728             :         }
     729             : 
     730             :         // grouping (for cell or database data)
     731          81 :         if (pData && pDimData)
     732             :         {
     733           4 :             shared_ptr<ScDPGroupTableData> pGroupData(new ScDPGroupTableData(pData, pDoc));
     734           4 :             pDimData->WriteToData(*pGroupData);
     735           4 :             pData = pGroupData;
     736             :         }
     737             : 
     738          81 :         mpTableData = pData;                        // after SetCacheId
     739             :     }
     740             : 
     741         158 :     return mpTableData.get();
     742             : }
     743             : 
     744        1078 : void ScDPObject::CreateObjects()
     745             : {
     746        1078 :     if (!xSource.is())
     747             :     {
     748         107 :         DELETEZ( pOutput );     // not valid when xSource is changed
     749             : 
     750         107 :         if ( pServDesc )
     751             :         {
     752           0 :             xSource = CreateSource( *pServDesc );
     753             :         }
     754             : 
     755         107 :         if ( !xSource.is() )    // database or sheet data, or error in CreateSource
     756             :         {
     757             :             OSL_ENSURE( !pServDesc, "DPSource could not be created" );
     758         107 :             ScDPTableData* pData = GetTableData();
     759         107 :             if (pData)
     760             :             {
     761         107 :                 if (pSaveData)
     762             :                     // Make sure to transfer these flags to the table data
     763             :                     // since they may have changed.
     764         107 :                     pData->SetEmptyFlags(pSaveData->GetIgnoreEmptyRows(), pSaveData->GetRepeatIfEmpty());
     765             : 
     766         107 :                 pData->ReloadCacheTable();
     767         107 :                 ScDPSource* pSource = new ScDPSource( pData );
     768         107 :                 xSource = pSource;
     769             :             }
     770             :         }
     771             : 
     772         107 :         if (pSaveData)
     773         107 :             pSaveData->WriteToSource( xSource );
     774             :     }
     775         971 :     else if (bSettingsChanged)
     776             :     {
     777           9 :         DELETEZ( pOutput );     // not valid when xSource is changed
     778             : 
     779           9 :         uno::Reference<util::XRefreshable> xRef( xSource, uno::UNO_QUERY );
     780           9 :         if (xRef.is())
     781             :         {
     782             :             try
     783             :             {
     784           9 :                 xRef->refresh();
     785             :             }
     786           0 :             catch(uno::Exception&)
     787             :             {
     788             :                 OSL_FAIL("exception in refresh");
     789             :             }
     790             :         }
     791             : 
     792           9 :         if (pSaveData)
     793           9 :             pSaveData->WriteToSource( xSource );
     794             :     }
     795        1078 :     bSettingsChanged = false;
     796        1078 : }
     797             : 
     798         131 : void ScDPObject::InvalidateData()
     799             : {
     800         131 :     bSettingsChanged = true;
     801         131 : }
     802             : 
     803         151 : void ScDPObject::Clear()
     804             : {
     805         151 :     delete pOutput;
     806         151 :     delete pSaveData;
     807         151 :     delete pSheetDesc;
     808         151 :     delete pImpDesc;
     809         151 :     delete pServDesc;
     810         151 :     pOutput = NULL;
     811         151 :     pSaveData = NULL;
     812         151 :     pSheetDesc = NULL;
     813         151 :     pImpDesc = NULL;
     814         151 :     pServDesc = NULL;
     815         151 :     ClearTableData();
     816         151 : }
     817             : 
     818         235 : void ScDPObject::ClearTableData()
     819             : {
     820         235 :     ClearSource();
     821             : 
     822         235 :     if (mpTableData)
     823          81 :         mpTableData->GetCacheTable().getCache()->RemoveReference(this);
     824         235 :     mpTableData.reset();
     825         235 : }
     826             : 
     827          53 : void ScDPObject::ReloadGroupTableData()
     828             : {
     829          53 :     ClearSource();
     830             : 
     831          53 :     if (!mpTableData)
     832             :         // Table data not built yet.  No need to reload the group data.
     833          25 :         return;
     834             : 
     835          28 :     if (!pSaveData)
     836             :         // How could it not have the save data... but whatever.
     837           0 :         return;
     838             : 
     839          28 :     const ScDPDimensionSaveData* pDimData = pSaveData->GetExistingDimensionData();
     840          28 :     if (!pDimData || !pDimData->HasGroupDimensions())
     841             :     {
     842             :         // No group dimensions exist.  Check if it currently has group
     843             :         // dimensions, and if so, remove all of them.
     844          21 :         ScDPGroupTableData* pData = dynamic_cast<ScDPGroupTableData*>(mpTableData.get());
     845          21 :         if (pData)
     846             :         {
     847             :             // Replace the existing group table data with the source data.
     848           1 :             shared_ptr<ScDPTableData> pSource = pData->GetSourceTableData();
     849           1 :             mpTableData = pSource;
     850             :         }
     851          21 :         return;
     852             :     }
     853             : 
     854           7 :     ScDPGroupTableData* pData = dynamic_cast<ScDPGroupTableData*>(mpTableData.get());
     855           7 :     if (pData)
     856             :     {
     857             :         // This is already a group table data. Salvage the source data and
     858             :         // re-create a new group data.
     859           2 :         shared_ptr<ScDPTableData> pSource = pData->GetSourceTableData();
     860           4 :         shared_ptr<ScDPGroupTableData> pGroupData(new ScDPGroupTableData(pSource, pDoc));
     861           2 :         pDimData->WriteToData(*pGroupData);
     862           4 :         mpTableData = pGroupData;
     863             :     }
     864             :     else
     865             :     {
     866             :         // This is a source data.  Create a group data based on it.
     867           5 :         shared_ptr<ScDPGroupTableData> pGroupData(new ScDPGroupTableData(mpTableData, pDoc));
     868           5 :         pDimData->WriteToData(*pGroupData);
     869           5 :         mpTableData = pGroupData;
     870             :     }
     871             : 
     872           7 :     bSettingsChanged = true;
     873             : }
     874             : 
     875         288 : void ScDPObject::ClearSource()
     876             : {
     877         288 :     Reference< XComponent > xObjectComp( xSource, UNO_QUERY );
     878         288 :     if (xObjectComp.is())
     879             :     {
     880             :         try
     881             :         {
     882           0 :             xObjectComp->dispose();
     883             :         }
     884           0 :         catch( const Exception& )
     885             :         {
     886             :             DBG_UNHANDLED_EXCEPTION();
     887             :         }
     888             :     }
     889         288 :     xSource = NULL;
     890         288 : }
     891             : 
     892          80 : ScRange ScDPObject::GetNewOutputRange( bool& rOverflow )
     893             : {
     894          80 :     CreateOutput();             // create xSource and pOutput if not already done
     895             : 
     896          80 :     rOverflow = pOutput->HasError();        // range overflow or exception from source
     897          80 :     if ( rOverflow )
     898           0 :         return ScRange( aOutRange.aStart );
     899             :     else
     900             :     {
     901             :         //  don't store the result in aOutRange, because nothing has been output yet
     902          80 :         return pOutput->GetOutputRange();
     903             :     }
     904             : }
     905             : 
     906          82 : void ScDPObject::Output( const ScAddress& rPos )
     907             : {
     908             :     //  clear old output area
     909          82 :     pDoc->DeleteAreaTab( aOutRange.aStart.Col(), aOutRange.aStart.Row(),
     910          82 :                          aOutRange.aEnd.Col(),   aOutRange.aEnd.Row(),
     911         246 :                          aOutRange.aStart.Tab(), IDF_ALL );
     912          82 :     pDoc->RemoveFlagsTab( aOutRange.aStart.Col(), aOutRange.aStart.Row(),
     913          82 :                           aOutRange.aEnd.Col(),   aOutRange.aEnd.Row(),
     914         246 :                           aOutRange.aStart.Tab(), SC_MF_AUTO );
     915             : 
     916          82 :     CreateOutput();             // create xSource and pOutput if not already done
     917             : 
     918          82 :     pOutput->SetPosition( rPos );
     919             : 
     920          82 :     pOutput->Output();
     921             : 
     922             :     //  aOutRange is always the range that was last output to the document
     923          82 :     aOutRange = pOutput->GetOutputRange();
     924          82 :     const ScAddress& s = aOutRange.aStart;
     925          82 :     const ScAddress& e = aOutRange.aEnd;
     926          82 :     pDoc->ApplyFlagsTab(s.Col(), s.Row(), e.Col(), e.Row(), s.Tab(), SC_MF_DP_TABLE);
     927          82 : }
     928             : 
     929          15 : const ScRange ScDPObject::GetOutputRangeByType( sal_Int32 nType )
     930             : {
     931          15 :     CreateOutput();
     932             : 
     933          15 :     if (pOutput->HasError())
     934           0 :         return ScRange(aOutRange.aStart);
     935             : 
     936          15 :     return pOutput->GetOutputRange(nType);
     937             : }
     938             : 
     939          20 : static sal_Bool lcl_HasButton( ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab )
     940             : {
     941          20 :     return ((const ScMergeFlagAttr*)pDoc->GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG ))->HasPivotButton();
     942             : }
     943             : 
     944           7 : void ScDPObject::RefreshAfterLoad()
     945             : {
     946             :     // apply drop-down attribute, initialize nHeaderRows, without accessing the source
     947             :     // (button attribute must be present)
     948             : 
     949             :     // simple test: block of button cells at the top, followed by an empty cell
     950             : 
     951           7 :     SCCOL nFirstCol = aOutRange.aStart.Col();
     952           7 :     SCROW nFirstRow = aOutRange.aStart.Row();
     953           7 :     SCTAB nTab = aOutRange.aStart.Tab();
     954             : 
     955           7 :     SCROW nInitial = 0;
     956           7 :     SCROW nOutRows = aOutRange.aEnd.Row() + 1 - aOutRange.aStart.Row();
     957          27 :     while ( nInitial + 1 < nOutRows && lcl_HasButton( pDoc, nFirstCol, nFirstRow + nInitial, nTab ) )
     958          13 :         ++nInitial;
     959             : 
     960          21 :     if ( nInitial + 1 < nOutRows &&
     961          14 :         pDoc->IsBlockEmpty( nTab, nFirstCol, nFirstRow + nInitial, nFirstCol, nFirstRow + nInitial ) &&
     962           7 :         aOutRange.aEnd.Col() > nFirstCol )
     963             :     {
     964           6 :         nHeaderRows = nInitial;
     965             :     }
     966             :     else
     967           1 :         nHeaderRows = 0;        // nothing found, no drop-down lists
     968           7 : }
     969             : 
     970           4 : void ScDPObject::BuildAllDimensionMembers()
     971             : {
     972           4 :     if (!pSaveData)
     973           0 :         return;
     974             : 
     975             :     // #i111857# don't always create empty mpTableData for external service.
     976           4 :     if (pServDesc)
     977           0 :         return;
     978             : 
     979           4 :     ScDPTableData* pTableData = GetTableData();
     980           4 :     if(pTableData)
     981           4 :         pSaveData->BuildAllDimensionMembers(pTableData);
     982             : }
     983             : 
     984          47 : bool ScDPObject::SyncAllDimensionMembers()
     985             : {
     986          47 :     if (!pSaveData)
     987           0 :         return false;
     988             : 
     989             :     // #i111857# don't always create empty mpTableData for external service.
     990             :     // Ideally, xSource should be used instead of mpTableData.
     991          47 :     if (pServDesc)
     992           0 :         return false;
     993             : 
     994          47 :     ScDPTableData* pData = GetTableData();
     995          47 :     if (!pData)
     996             :         // No table data exists.  This can happen when refreshing from an
     997             :         // external source which doesn't exist.
     998           0 :         return false;
     999             : 
    1000             :     // Refresh the cache wrapper since the cache may have changed.
    1001          47 :     pData->SetEmptyFlags(pSaveData->GetIgnoreEmptyRows(), pSaveData->GetRepeatIfEmpty());
    1002          47 :     pData->ReloadCacheTable();
    1003          47 :     pSaveData->SyncAllDimensionMembers(pData);
    1004          47 :     return true;
    1005             : }
    1006             : 
    1007           2 : bool ScDPObject::GetMemberNames( sal_Int32 nDim, Sequence<OUString>& rNames )
    1008             : {
    1009           2 :     vector<ScDPLabelData::Member> aMembers;
    1010           2 :     if (!GetMembers(nDim, GetUsedHierarchy(nDim), aMembers))
    1011           0 :         return false;
    1012             : 
    1013           2 :     size_t n = aMembers.size();
    1014           2 :     rNames.realloc(n);
    1015          12 :     for (size_t i = 0; i < n; ++i)
    1016          10 :         rNames[i] = aMembers[i].maName;
    1017             : 
    1018           2 :     return true;
    1019             : }
    1020             : 
    1021           5 : bool ScDPObject::GetMembers( sal_Int32 nDim, sal_Int32 nHier, vector<ScDPLabelData::Member>& rMembers )
    1022             : {
    1023           5 :     Reference< container::XNameAccess > xMembersNA;
    1024           5 :     if (!GetMembersNA( nDim, nHier, xMembersNA ))
    1025           0 :         return false;
    1026             : 
    1027          10 :     Reference<container::XIndexAccess> xMembersIA( new ScNameToIndexAccess(xMembersNA) );
    1028           5 :     sal_Int32 nCount = xMembersIA->getCount();
    1029          10 :     vector<ScDPLabelData::Member> aMembers;
    1030           5 :     aMembers.reserve(nCount);
    1031             : 
    1032          37 :     for (sal_Int32 i = 0; i < nCount; ++i)
    1033             :     {
    1034          32 :         Reference<container::XNamed> xMember(xMembersIA->getByIndex(i), UNO_QUERY);
    1035          64 :         ScDPLabelData::Member aMem;
    1036             : 
    1037          32 :         if (xMember.is())
    1038          32 :             aMem.maName = xMember->getName();
    1039             : 
    1040          64 :         Reference<beans::XPropertySet> xMemProp(xMember, UNO_QUERY);
    1041          32 :         if (xMemProp.is())
    1042             :         {
    1043          32 :             aMem.mbVisible     = ScUnoHelpFunctions::GetBoolProperty(xMemProp, OUString(SC_UNO_DP_ISVISIBLE));
    1044          32 :             aMem.mbShowDetails = ScUnoHelpFunctions::GetBoolProperty(xMemProp, OUString(SC_UNO_DP_SHOWDETAILS));
    1045             : 
    1046          64 :             aMem.maLayoutName = ScUnoHelpFunctions::GetStringProperty(
    1047          32 :                 xMemProp, OUString(SC_UNO_DP_LAYOUTNAME), OUString());
    1048             :         }
    1049             : 
    1050          32 :         aMembers.push_back(aMem);
    1051          32 :     }
    1052           5 :     rMembers.swap(aMembers);
    1053          10 :     return true;
    1054             : }
    1055             : 
    1056          66 : void ScDPObject::UpdateReference( UpdateRefMode eUpdateRefMode,
    1057             :                                      const ScRange& rRange, SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
    1058             : {
    1059             :     // Output area
    1060             : 
    1061          66 :     SCCOL nCol1 = aOutRange.aStart.Col();
    1062          66 :     SCROW nRow1 = aOutRange.aStart.Row();
    1063          66 :     SCTAB nTab1 = aOutRange.aStart.Tab();
    1064          66 :     SCCOL nCol2 = aOutRange.aEnd.Col();
    1065          66 :     SCROW nRow2 = aOutRange.aEnd.Row();
    1066          66 :     SCTAB nTab2 = aOutRange.aEnd.Tab();
    1067             : 
    1068             :     ScRefUpdateRes eRes =
    1069             :         ScRefUpdate::Update( pDoc, eUpdateRefMode,
    1070         132 :             rRange.aStart.Col(), rRange.aStart.Row(), rRange.aStart.Tab(),
    1071         132 :             rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aEnd.Tab(), nDx, nDy, nDz,
    1072         330 :             nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
    1073          66 :     if ( eRes != UR_NOTHING )
    1074          66 :         SetOutRange( ScRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 ) );
    1075             : 
    1076             :     // sheet source data
    1077             : 
    1078          66 :     if ( pSheetDesc )
    1079             :     {
    1080          66 :         const OUString& rRangeName = pSheetDesc->GetRangeName();
    1081          66 :         if (!rRangeName.isEmpty())
    1082             :             // Source range is a named range.  No need to update.
    1083           2 :             return;
    1084             : 
    1085          65 :         const ScRange& rSrcRange = pSheetDesc->GetSourceRange();
    1086          65 :         nCol1 = rSrcRange.aStart.Col();
    1087          65 :         nRow1 = rSrcRange.aStart.Row();
    1088          65 :         nTab1 = rSrcRange.aStart.Tab();
    1089          65 :         nCol2 = rSrcRange.aEnd.Col();
    1090          65 :         nRow2 = rSrcRange.aEnd.Row();
    1091          65 :         nTab2 = rSrcRange.aEnd.Tab();
    1092             : 
    1093             :         eRes = ScRefUpdate::Update( pDoc, eUpdateRefMode,
    1094         130 :                 rRange.aStart.Col(), rRange.aStart.Row(), rRange.aStart.Tab(),
    1095         130 :                 rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aEnd.Tab(), nDx, nDy, nDz,
    1096         325 :                 nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
    1097          65 :         if ( eRes != UR_NOTHING )
    1098             :         {
    1099          65 :             SCsCOL nDiffX = nCol1 - pSheetDesc->GetSourceRange().aStart.Col();
    1100          65 :             SCsROW nDiffY = nRow1 - pSheetDesc->GetSourceRange().aStart.Row();
    1101             : 
    1102          65 :             ScQueryParam aParam = pSheetDesc->GetQueryParam();
    1103          65 :             aParam.nCol1 = sal::static_int_cast<SCCOL>( aParam.nCol1 + nDiffX );
    1104          65 :             aParam.nCol2 = sal::static_int_cast<SCCOL>( aParam.nCol2 + nDiffX );
    1105          65 :             aParam.nRow1 += nDiffY; //! used?
    1106          65 :             aParam.nRow2 += nDiffY; //! used?
    1107          65 :             SCSIZE nEC = aParam.GetEntryCount();
    1108         585 :             for (SCSIZE i=0; i<nEC; i++)
    1109         520 :                 if (aParam.GetEntry(i).bDoQuery)
    1110          64 :                     aParam.GetEntry(i).nField += nDiffX;
    1111             : 
    1112          65 :             pSheetDesc->SetQueryParam(aParam);
    1113          65 :             pSheetDesc->SetSourceRange(ScRange(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2));
    1114             :         }
    1115             :     }
    1116             : }
    1117             : 
    1118           0 : bool ScDPObject::RefsEqual( const ScDPObject& r ) const
    1119             : {
    1120           0 :     if ( aOutRange != r.aOutRange )
    1121           0 :         return false;
    1122             : 
    1123           0 :     if ( pSheetDesc && r.pSheetDesc )
    1124             :     {
    1125           0 :         if ( pSheetDesc->GetSourceRange() != r.pSheetDesc->GetSourceRange() )
    1126           0 :             return false;
    1127             :     }
    1128           0 :     else if ( pSheetDesc || r.pSheetDesc )
    1129             :     {
    1130             :         OSL_FAIL("RefsEqual: SheetDesc set at only one object");
    1131           0 :         return false;
    1132             :     }
    1133             : 
    1134           0 :     return true;
    1135             : }
    1136             : 
    1137           0 : void ScDPObject::WriteRefsTo( ScDPObject& r ) const
    1138             : {
    1139           0 :     r.SetOutRange( aOutRange );
    1140           0 :     if ( pSheetDesc )
    1141           0 :         r.SetSheetDesc( *pSheetDesc, true );
    1142           0 : }
    1143             : 
    1144         266 : void ScDPObject::GetPositionData(const ScAddress& rPos, DataPilotTablePositionData& rPosData)
    1145             : {
    1146         266 :     CreateOutput();
    1147         266 :     pOutput->GetPositionData(rPos, rPosData);
    1148         266 : }
    1149             : 
    1150         133 : bool ScDPObject::GetDataFieldPositionData(
    1151             :     const ScAddress& rPos, Sequence<sheet::DataPilotFieldFilter>& rFilters)
    1152             : {
    1153         133 :     CreateOutput();
    1154             : 
    1155         133 :     vector<sheet::DataPilotFieldFilter> aFilters;
    1156         133 :     if (!pOutput->GetDataResultPositionData(aFilters, rPos))
    1157           0 :         return false;
    1158             : 
    1159         133 :     sal_Int32 n = static_cast<sal_Int32>(aFilters.size());
    1160         133 :     rFilters.realloc(n);
    1161         593 :     for (sal_Int32 i = 0; i < n; ++i)
    1162         460 :         rFilters[i] = aFilters[i];
    1163             : 
    1164         133 :     return true;
    1165             : }
    1166             : 
    1167          97 : void ScDPObject::GetDrillDownData(const ScAddress& rPos, Sequence< Sequence<Any> >& rTableData)
    1168             : {
    1169          97 :     CreateOutput();
    1170             : 
    1171          97 :     Reference<sheet::XDrillDownDataSupplier> xDrillDownData(xSource, UNO_QUERY);
    1172          97 :     if (!xDrillDownData.is())
    1173           0 :         return;
    1174             : 
    1175         194 :     Sequence<sheet::DataPilotFieldFilter> filters;
    1176          97 :     if (!GetDataFieldPositionData(rPos, filters))
    1177           0 :         return;
    1178             : 
    1179         194 :     rTableData = xDrillDownData->getDrillDownData(filters);
    1180             : }
    1181             : 
    1182          18 : bool ScDPObject::IsDimNameInUse(const OUString& rName) const
    1183             : {
    1184          18 :     if (!xSource.is())
    1185           2 :         return false;
    1186             : 
    1187          16 :     Reference<container::XNameAccess> xDims = xSource->getDimensions();
    1188          32 :     Sequence<OUString> aDimNames = xDims->getElementNames();
    1189          16 :     sal_Int32 n = aDimNames.getLength();
    1190          75 :     for (sal_Int32 i = 0; i < n; ++i)
    1191             :     {
    1192          68 :         const OUString& rDimName = aDimNames[i];
    1193          68 :         if (rDimName.equalsIgnoreAsciiCase(rName))
    1194          16 :             return true;
    1195             : 
    1196          61 :         Reference<beans::XPropertySet> xPropSet(xDims->getByName(rDimName), UNO_QUERY);
    1197          61 :         if (!xPropSet.is())
    1198           0 :             continue;
    1199             : 
    1200             :         OUString aLayoutName = ScUnoHelpFunctions::GetStringProperty(
    1201         120 :             xPropSet, OUString(SC_UNO_DP_LAYOUTNAME), OUString());
    1202          61 :         if (aLayoutName.equalsIgnoreAsciiCase(rName))
    1203           2 :             return true;
    1204          59 :     }
    1205          23 :     return false;
    1206             : }
    1207             : 
    1208          60 : OUString ScDPObject::GetDimName( long nDim, bool& rIsDataLayout, sal_Int32* pFlags )
    1209             : {
    1210          60 :     rIsDataLayout = false;
    1211          60 :     OUString aRet;
    1212             : 
    1213          60 :     if ( xSource.is() )
    1214             :     {
    1215          60 :         uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
    1216         120 :         uno::Reference<container::XIndexAccess> xDims = new ScNameToIndexAccess( xDimsName );
    1217          60 :         long nDimCount = xDims->getCount();
    1218          60 :         if ( nDim < nDimCount )
    1219             :         {
    1220             :             uno::Reference<uno::XInterface> xIntDim =
    1221          60 :                 ScUnoHelpFunctions::AnyToInterface( xDims->getByIndex(nDim) );
    1222         120 :             uno::Reference<container::XNamed> xDimName( xIntDim, uno::UNO_QUERY );
    1223         120 :             uno::Reference<beans::XPropertySet> xDimProp( xIntDim, uno::UNO_QUERY );
    1224          60 :             if ( xDimName.is() && xDimProp.is() )
    1225             :             {
    1226             :                 sal_Bool bData = ScUnoHelpFunctions::GetBoolProperty( xDimProp,
    1227          60 :                                 OUString(SC_UNO_DP_ISDATALAYOUT) );
    1228             :                 //! error checking -- is "IsDataLayoutDimension" property required??
    1229             : 
    1230          60 :                 OUString aName;
    1231             :                 try
    1232             :                 {
    1233          60 :                     aName = xDimName->getName();
    1234             :                 }
    1235           0 :                 catch(uno::Exception&)
    1236             :                 {
    1237             :                 }
    1238          60 :                 if ( bData )
    1239           0 :                     rIsDataLayout = true;
    1240             :                 else
    1241          60 :                     aRet = aName;
    1242             : 
    1243          60 :                 if (pFlags)
    1244             :                     *pFlags = ScUnoHelpFunctions::GetLongProperty( xDimProp,
    1245           0 :                                 OUString(SC_UNO_DP_FLAGS), 0 );
    1246          60 :             }
    1247          60 :         }
    1248             :     }
    1249             : 
    1250          60 :     return aRet;
    1251             : }
    1252             : 
    1253           0 : bool ScDPObject::IsDuplicated( long nDim )
    1254             : {
    1255           0 :     bool bDuplicated = false;
    1256           0 :     if ( xSource.is() )
    1257             :     {
    1258           0 :         uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
    1259           0 :         uno::Reference<container::XIndexAccess> xDims = new ScNameToIndexAccess( xDimsName );
    1260           0 :         long nDimCount = xDims->getCount();
    1261           0 :         if ( nDim < nDimCount )
    1262             :         {
    1263             :             uno::Reference<uno::XInterface> xIntDim =
    1264           0 :                 ScUnoHelpFunctions::AnyToInterface( xDims->getByIndex(nDim) );
    1265           0 :             uno::Reference<beans::XPropertySet> xDimProp( xIntDim, uno::UNO_QUERY );
    1266           0 :             if ( xDimProp.is() )
    1267             :             {
    1268             :                 try
    1269             :                 {
    1270           0 :                     uno::Any aOrigAny = xDimProp->getPropertyValue(
    1271           0 :                                 OUString(SC_UNO_DP_ORIGINAL) );
    1272           0 :                     uno::Reference<uno::XInterface> xIntOrig;
    1273           0 :                     if ( (aOrigAny >>= xIntOrig) && xIntOrig.is() )
    1274           0 :                         bDuplicated = true;
    1275             :                 }
    1276           0 :                 catch(uno::Exception&)
    1277             :                 {
    1278             :                 }
    1279           0 :             }
    1280           0 :         }
    1281             :     }
    1282           0 :     return bDuplicated;
    1283             : }
    1284             : 
    1285          60 : long ScDPObject::GetDimCount()
    1286             : {
    1287          60 :     long nRet = 0;
    1288          60 :     if ( xSource.is() )
    1289             :     {
    1290             :         try
    1291             :         {
    1292          60 :             uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
    1293          60 :             if ( xDimsName.is() )
    1294          60 :                 nRet = xDimsName->getElementNames().getLength();
    1295             :         }
    1296           0 :         catch(uno::Exception&)
    1297             :         {
    1298             :         }
    1299             :     }
    1300          60 :     return nRet;
    1301             : }
    1302             : 
    1303           0 : void ScDPObject::GetHeaderPositionData(const ScAddress& rPos, DataPilotTableHeaderData& rData)
    1304             : {
    1305             :     using namespace ::com::sun::star::sheet::DataPilotTablePositionType;
    1306             : 
    1307           0 :     CreateOutput();             // create xSource and pOutput if not already done
    1308             : 
    1309             :     // Reset member values to invalid state.
    1310           0 :     rData.Dimension = rData.Hierarchy = rData.Level = -1;
    1311           0 :     rData.Flags = 0;
    1312             : 
    1313           0 :     DataPilotTablePositionData aPosData;
    1314           0 :     pOutput->GetPositionData(rPos, aPosData);
    1315           0 :     const sal_Int32 nPosType = aPosData.PositionType;
    1316           0 :     if (nPosType == COLUMN_HEADER || nPosType == ROW_HEADER)
    1317           0 :         aPosData.PositionData >>= rData;
    1318           0 : }
    1319             : 
    1320             : namespace {
    1321             : 
    1322          93 : class FindByName : std::unary_function<const ScDPSaveDimension*, bool>
    1323             : {
    1324             :     OUString maName; // must be all uppercase.
    1325             : public:
    1326          31 :     FindByName(const OUString& rName) : maName(rName) {}
    1327          34 :     bool operator() (const ScDPSaveDimension* pDim) const
    1328             :     {
    1329             :         // Layout name takes precedence.
    1330          34 :         const OUString* pLayoutName = pDim->GetLayoutName();
    1331          34 :         if (pLayoutName && ScGlobal::pCharClass->uppercase(*pLayoutName) == maName)
    1332           2 :             return true;
    1333             : 
    1334          32 :         sheet::GeneralFunction eGenFunc = static_cast<sheet::GeneralFunction>(pDim->GetFunction());
    1335          32 :         ScSubTotalFunc eFunc = ScDPUtil::toSubTotalFunc(eGenFunc);
    1336          32 :         OUString aSrcName = ScDPUtil::getSourceDimensionName(pDim->GetName());
    1337          64 :         OUString aFuncName = ScDPUtil::getDisplayedMeasureName(aSrcName, eFunc);
    1338          32 :         if (maName == ScGlobal::pCharClass->uppercase(aFuncName))
    1339           6 :             return true;
    1340             : 
    1341          58 :         return maName == ScGlobal::pCharClass->uppercase(aSrcName);
    1342             :     }
    1343             : };
    1344             : 
    1345             : class LessByDimOrder : std::binary_function<sheet::DataPilotFieldFilter, sheet::DataPilotFieldFilter, bool>
    1346             : {
    1347             :     const ScDPSaveData::DimOrderType& mrDimOrder;
    1348             : 
    1349             : public:
    1350          31 :     LessByDimOrder(const ScDPSaveData::DimOrderType& rDimOrder) : mrDimOrder(rDimOrder) {}
    1351             : 
    1352           0 :     bool operator() (const sheet::DataPilotFieldFilter& r1, const sheet::DataPilotFieldFilter& r2) const
    1353             :     {
    1354           0 :         size_t nRank1 = mrDimOrder.size();
    1355           0 :         size_t nRank2 = mrDimOrder.size();
    1356           0 :         ScDPSaveData::DimOrderType::const_iterator it1 = mrDimOrder.find(r1.FieldName);
    1357           0 :         if (it1 != mrDimOrder.end())
    1358           0 :             nRank1 = it1->second;
    1359             : 
    1360           0 :         ScDPSaveData::DimOrderType::const_iterator it2 = mrDimOrder.find(r2.FieldName);
    1361           0 :         if (it2 != mrDimOrder.end())
    1362           0 :             nRank2 = it2->second;
    1363             : 
    1364           0 :         return nRank1 < nRank2;
    1365             :     }
    1366             : };
    1367             : 
    1368             : }
    1369             : 
    1370          31 : double ScDPObject::GetPivotData(const OUString& rDataFieldName, std::vector<sheet::DataPilotFieldFilter>& rFilters)
    1371             : {
    1372             :     double fRet;
    1373          31 :     rtl::math::setNan(&fRet);
    1374          31 :     if (!mbEnableGetPivotData)
    1375           0 :         return fRet;
    1376             : 
    1377          31 :     CreateObjects();
    1378             : 
    1379          31 :     std::vector<const ScDPSaveDimension*> aDataDims;
    1380          31 :     pSaveData->GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_DATA, aDataDims);
    1381          31 :     if (aDataDims.empty())
    1382           0 :         return fRet;
    1383             : 
    1384             :     std::vector<const ScDPSaveDimension*>::iterator it = std::find_if(
    1385             :         aDataDims.begin(), aDataDims.end(),
    1386          31 :         FindByName(ScGlobal::pCharClass->uppercase(rDataFieldName)));
    1387             : 
    1388          31 :     if (it == aDataDims.end())
    1389           0 :         return fRet;
    1390             : 
    1391          31 :     size_t nDataIndex = std::distance(aDataDims.begin(), it);
    1392             : 
    1393          62 :     uno::Reference<sheet::XDataPilotResults> xDPResults(xSource, uno::UNO_QUERY);
    1394          31 :     if (!xDPResults.is())
    1395           0 :         return fRet;
    1396             : 
    1397             :     // Dimensions must be sorted in order of appearance, and row dimensions
    1398             :     // must come before column dimensions.
    1399          31 :     std::sort(rFilters.begin(), rFilters.end(), LessByDimOrder(pSaveData->GetDimensionSortOrder()));
    1400             : 
    1401          31 :     size_t n = rFilters.size();
    1402          62 :     uno::Sequence<sheet::DataPilotFieldFilter> aFilters(n);
    1403          59 :     for (size_t i = 0; i < n; ++i)
    1404          28 :         aFilters[i] = rFilters[i];
    1405             : 
    1406          62 :     uno::Sequence<double> aRes = xDPResults->getFilteredResults(aFilters);
    1407          31 :     if (static_cast<sal_Int32>(nDataIndex) >= aRes.getLength())
    1408           0 :         return fRet;
    1409             : 
    1410          62 :     return aRes[nDataIndex];
    1411             : }
    1412             : 
    1413           0 : bool ScDPObject::IsFilterButton( const ScAddress& rPos )
    1414             : {
    1415           0 :     CreateOutput();             // create xSource and pOutput if not already done
    1416             : 
    1417           0 :     return pOutput->IsFilterButton( rPos );
    1418             : }
    1419             : 
    1420           1 : long ScDPObject::GetHeaderDim( const ScAddress& rPos, sal_uInt16& rOrient )
    1421             : {
    1422           1 :     CreateOutput();             // create xSource and pOutput if not already done
    1423             : 
    1424           1 :     return pOutput->GetHeaderDim( rPos, rOrient );
    1425             : }
    1426             : 
    1427           0 : bool ScDPObject::GetHeaderDrag( const ScAddress& rPos, bool bMouseLeft, bool bMouseTop, long nDragDim,
    1428             :                                 Rectangle& rPosRect, sal_uInt16& rOrient, long& rDimPos )
    1429             : {
    1430           0 :     CreateOutput();             // create xSource and pOutput if not already done
    1431             : 
    1432           0 :     return pOutput->GetHeaderDrag( rPos, bMouseLeft, bMouseTop, nDragDim, rPosRect, rOrient, rDimPos );
    1433             : }
    1434             : 
    1435           0 : void ScDPObject::GetMemberResultNames(ScDPUniqueStringSet& rNames, long nDimension)
    1436             : {
    1437           0 :     CreateOutput();             // create xSource and pOutput if not already done
    1438             : 
    1439           0 :     pOutput->GetMemberResultNames(rNames, nDimension);    // used only with table data -> level not needed
    1440           0 : }
    1441             : 
    1442             : namespace {
    1443             : 
    1444           0 : bool dequote( const OUString& rSource, sal_Int32 nStartPos, sal_Int32& rEndPos, OUString& rResult )
    1445             : {
    1446             :     // nStartPos has to point to opening quote
    1447             : 
    1448           0 :     bool bRet = false;
    1449           0 :     const sal_Unicode cQuote = '\'';
    1450             : 
    1451           0 :     if (rSource[nStartPos] == cQuote)
    1452             :     {
    1453           0 :         OUStringBuffer aBuffer;
    1454           0 :         sal_Int32 nPos = nStartPos + 1;
    1455           0 :         const sal_Int32 nLen = rSource.getLength();
    1456             : 
    1457           0 :         while ( nPos < nLen )
    1458             :         {
    1459           0 :             const sal_Unicode cNext = rSource[nPos];
    1460           0 :             if ( cNext == cQuote )
    1461             :             {
    1462           0 :                 if (nPos+1 < nLen && rSource[nPos+1] == cQuote)
    1463             :                 {
    1464             :                     // double quote is used for an embedded quote
    1465           0 :                     aBuffer.append( cNext );    // append one quote
    1466           0 :                     ++nPos;                     // skip the next one
    1467             :                 }
    1468             :                 else
    1469             :                 {
    1470             :                     // end of quoted string
    1471           0 :                     rResult = aBuffer.makeStringAndClear();
    1472           0 :                     rEndPos = nPos + 1;         // behind closing quote
    1473           0 :                     return true;
    1474             :                 }
    1475             :             }
    1476             :             else
    1477           0 :                 aBuffer.append( cNext );
    1478             : 
    1479           0 :             ++nPos;
    1480           0 :         }
    1481             :         // no closing quote before the end of the string -> error (bRet still false)
    1482             :     }
    1483             : 
    1484           0 :     return bRet;
    1485             : }
    1486             : 
    1487             : struct ScGetPivotDataFunctionEntry
    1488             : {
    1489             :     const sal_Char*         pName;
    1490             :     sheet::GeneralFunction  eFunc;
    1491             : };
    1492             : 
    1493           0 : bool parseFunction( const OUString& rList, sal_Int32 nStartPos, sal_Int32& rEndPos, sheet::GeneralFunction& rFunc )
    1494             : {
    1495             :     static const ScGetPivotDataFunctionEntry aFunctions[] =
    1496             :     {
    1497             :         // our names
    1498             :         { "Sum",        sheet::GeneralFunction_SUM       },
    1499             :         { "Count",      sheet::GeneralFunction_COUNT     },
    1500             :         { "Average",    sheet::GeneralFunction_AVERAGE   },
    1501             :         { "Max",        sheet::GeneralFunction_MAX       },
    1502             :         { "Min",        sheet::GeneralFunction_MIN       },
    1503             :         { "Product",    sheet::GeneralFunction_PRODUCT   },
    1504             :         { "CountNums",  sheet::GeneralFunction_COUNTNUMS },
    1505             :         { "StDev",      sheet::GeneralFunction_STDEV     },
    1506             :         { "StDevp",     sheet::GeneralFunction_STDEVP    },
    1507             :         { "Var",        sheet::GeneralFunction_VAR       },
    1508             :         { "VarP",       sheet::GeneralFunction_VARP      },
    1509             :         // compatibility names
    1510             :         { "Count Nums", sheet::GeneralFunction_COUNTNUMS },
    1511             :         { "StdDev",     sheet::GeneralFunction_STDEV     },
    1512             :         { "StdDevp",    sheet::GeneralFunction_STDEVP    }
    1513             :     };
    1514             : 
    1515           0 :     const sal_Int32 nListLen = rList.getLength();
    1516           0 :     while (nStartPos < nListLen && rList[nStartPos] == ' ')
    1517           0 :         ++nStartPos;
    1518             : 
    1519           0 :     bool bParsed = false;
    1520           0 :     bool bFound = false;
    1521           0 :     OUString aFuncStr;
    1522           0 :     sal_Int32 nFuncEnd = 0;
    1523           0 :     if (nStartPos < nListLen && rList[nStartPos] == '\'')
    1524           0 :         bParsed = dequote( rList, nStartPos, nFuncEnd, aFuncStr );
    1525             :     else
    1526             :     {
    1527           0 :         nFuncEnd = rList.indexOf(']', nStartPos);
    1528           0 :         if (nFuncEnd >= 0)
    1529             :         {
    1530           0 :             aFuncStr = rList.copy(nStartPos, nFuncEnd - nStartPos);
    1531           0 :             bParsed = true;
    1532             :         }
    1533             :     }
    1534             : 
    1535           0 :     if ( bParsed )
    1536             :     {
    1537           0 :         aFuncStr = comphelper::string::strip(aFuncStr, ' ');
    1538             : 
    1539           0 :         const sal_Int32 nFuncCount = sizeof(aFunctions) / sizeof(aFunctions[0]);
    1540           0 :         for ( sal_Int32 nFunc=0; nFunc<nFuncCount && !bFound; nFunc++ )
    1541             :         {
    1542           0 :             if (aFuncStr.equalsIgnoreAsciiCaseAscii(aFunctions[nFunc].pName))
    1543             :             {
    1544           0 :                 rFunc = aFunctions[nFunc].eFunc;
    1545           0 :                 bFound = true;
    1546             : 
    1547           0 :                 while (nFuncEnd < nListLen && rList[nFuncEnd] == ' ')
    1548           0 :                     ++nFuncEnd;
    1549           0 :                 rEndPos = nFuncEnd;
    1550             :             }
    1551             :         }
    1552             :     }
    1553             : 
    1554           0 :     return bFound;
    1555             : }
    1556             : 
    1557          96 : bool isAtStart(
    1558             :     const OUString& rList, const OUString& rSearch, sal_Int32& rMatched,
    1559             :     bool bAllowBracket, sheet::GeneralFunction* pFunc )
    1560             : {
    1561          96 :     sal_Int32 nMatchList = 0;
    1562          96 :     sal_Int32 nMatchSearch = 0;
    1563          96 :     sal_Unicode cFirst = rList[0];
    1564          96 :     if ( cFirst == '\'' || cFirst == '[' )
    1565             :     {
    1566             :         // quoted string or string in brackets must match completely
    1567             : 
    1568          48 :         OUString aDequoted;
    1569          48 :         sal_Int32 nQuoteEnd = 0;
    1570          48 :         bool bParsed = false;
    1571             : 
    1572          48 :         if ( cFirst == '\'' )
    1573           0 :             bParsed = dequote( rList, 0, nQuoteEnd, aDequoted );
    1574          48 :         else if ( cFirst == '[' )
    1575             :         {
    1576             :             // skip spaces after the opening bracket
    1577             : 
    1578          48 :             sal_Int32 nStartPos = 1;
    1579          48 :             const sal_Int32 nListLen = rList.getLength();
    1580          96 :             while (nStartPos < nListLen && rList[nStartPos] == ' ')
    1581           0 :                 ++nStartPos;
    1582             : 
    1583          48 :             if (nStartPos < nListLen && rList[nStartPos] == '\'')         // quoted within the brackets?
    1584             :             {
    1585           0 :                 if ( dequote( rList, nStartPos, nQuoteEnd, aDequoted ) )
    1586             :                 {
    1587             :                     // after the quoted string, there must be the closing bracket, optionally preceded by spaces,
    1588             :                     // and/or a function name
    1589           0 :                     while (nQuoteEnd < nListLen && rList[nQuoteEnd] == ' ')
    1590           0 :                         ++nQuoteEnd;
    1591             : 
    1592             :                     // semicolon separates function name
    1593           0 :                     if (nQuoteEnd < nListLen && rList[nQuoteEnd] == ';' && pFunc)
    1594             :                     {
    1595           0 :                         sal_Int32 nFuncEnd = 0;
    1596           0 :                         if ( parseFunction( rList, nQuoteEnd + 1, nFuncEnd, *pFunc ) )
    1597           0 :                             nQuoteEnd = nFuncEnd;
    1598             :                     }
    1599           0 :                     if (nQuoteEnd < nListLen && rList[nQuoteEnd] == ']')
    1600             :                     {
    1601           0 :                         ++nQuoteEnd;        // include the closing bracket for the matched length
    1602           0 :                         bParsed = true;
    1603             :                     }
    1604             :                 }
    1605             :             }
    1606             :             else
    1607             :             {
    1608             :                 // implicit quoting to the closing bracket
    1609             : 
    1610          48 :                 sal_Int32 nClosePos = rList.indexOf(']', nStartPos);
    1611          48 :                 if (nClosePos >= 0)
    1612             :                 {
    1613          48 :                     sal_Int32 nNameEnd = nClosePos;
    1614          48 :                     sal_Int32 nSemiPos = rList.indexOf(';', nStartPos);
    1615          48 :                     if (nSemiPos >= 0 && nSemiPos < nClosePos && pFunc)
    1616             :                     {
    1617           0 :                         sal_Int32 nFuncEnd = 0;
    1618           0 :                         if (parseFunction(rList, nSemiPos+1, nFuncEnd, *pFunc))
    1619           0 :                             nNameEnd = nSemiPos;
    1620             :                     }
    1621             : 
    1622          48 :                     aDequoted = rList.copy(nStartPos, nNameEnd - nStartPos);
    1623             :                     // spaces before the closing bracket or semicolon
    1624          48 :                     aDequoted = comphelper::string::stripEnd(aDequoted, ' ');
    1625          48 :                     nQuoteEnd = nClosePos + 1;
    1626          48 :                     bParsed = true;
    1627             :                 }
    1628             :             }
    1629             :         }
    1630             : 
    1631          48 :         if ( bParsed && ScGlobal::GetpTransliteration()->isEqual( aDequoted, rSearch ) )
    1632             :         {
    1633          12 :             nMatchList = nQuoteEnd;             // match count in the list string, including quotes
    1634          12 :             nMatchSearch = rSearch.getLength();
    1635          48 :         }
    1636             :     }
    1637             :     else
    1638             :     {
    1639             :         // otherwise look for search string at the start of rList
    1640             :         ScGlobal::GetpTransliteration()->equals(
    1641          48 :             rList, 0, rList.getLength(), nMatchList, rSearch, 0, rSearch.getLength(), nMatchSearch);
    1642             :     }
    1643             : 
    1644          96 :     if (nMatchSearch == rSearch.getLength())
    1645             :     {
    1646             :         // search string is at start of rList - look for following space or end of string
    1647             : 
    1648          24 :         bool bValid = false;
    1649          24 :         if ( sal::static_int_cast<sal_Int32>(nMatchList) >= rList.getLength() )
    1650          12 :             bValid = true;
    1651             :         else
    1652             :         {
    1653          12 :             sal_Unicode cNext = rList[nMatchList];
    1654          12 :             if ( cNext == ' ' || ( bAllowBracket && cNext == '[' ) )
    1655          12 :                 bValid = true;
    1656             :         }
    1657             : 
    1658          24 :         if ( bValid )
    1659             :         {
    1660          24 :             rMatched = nMatchList;
    1661          24 :             return true;
    1662             :         }
    1663             :     }
    1664             : 
    1665          72 :     return false;
    1666             : }
    1667             : 
    1668             : } // anonymous namespace
    1669             : 
    1670          12 : bool ScDPObject::ParseFilters(
    1671             :     OUString& rDataFieldName,
    1672             :     std::vector<sheet::DataPilotFieldFilter>& rFilters,
    1673             :     std::vector<sheet::GeneralFunction>& rFilterFuncs, const OUString& rFilterList )
    1674             : {
    1675             :     // parse the string rFilterList into parameters for GetPivotData
    1676             : 
    1677          12 :     CreateObjects();            // create xSource if not already done
    1678             : 
    1679          12 :     std::vector<OUString> aDataNames;     // data fields (source name)
    1680          24 :     std::vector<OUString> aGivenNames;    // data fields (compound name)
    1681          24 :     std::vector<OUString> aFieldNames;    // column/row/data fields
    1682          24 :     std::vector< uno::Sequence<OUString> > aFieldValues;
    1683             : 
    1684             : 
    1685             :     // get all the field and item names
    1686             : 
    1687             : 
    1688          24 :     uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
    1689          24 :     uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName );
    1690          12 :     sal_Int32 nDimCount = xIntDims->getCount();
    1691          60 :     for ( sal_Int32 nDim = 0; nDim<nDimCount; nDim++ )
    1692             :     {
    1693          48 :         uno::Reference<uno::XInterface> xIntDim = ScUnoHelpFunctions::AnyToInterface( xIntDims->getByIndex(nDim) );
    1694          96 :         uno::Reference<container::XNamed> xDim( xIntDim, uno::UNO_QUERY );
    1695          96 :         uno::Reference<beans::XPropertySet> xDimProp( xDim, uno::UNO_QUERY );
    1696          96 :         uno::Reference<sheet::XHierarchiesSupplier> xDimSupp( xDim, uno::UNO_QUERY );
    1697             :         sal_Bool bDataLayout = ScUnoHelpFunctions::GetBoolProperty( xDimProp,
    1698          48 :                             OUString(SC_UNO_DP_ISDATALAYOUT) );
    1699             :         sal_Int32 nOrient = ScUnoHelpFunctions::GetEnumProperty(
    1700             :                             xDimProp, OUString(SC_UNO_DP_ORIENTATION),
    1701          48 :                             sheet::DataPilotFieldOrientation_HIDDEN );
    1702          48 :         if ( !bDataLayout )
    1703             :         {
    1704          36 :             if ( nOrient == sheet::DataPilotFieldOrientation_DATA )
    1705             :             {
    1706          12 :                 OUString aSourceName;
    1707          24 :                 OUString aGivenName;
    1708          12 :                 ScDPOutput::GetDataDimensionNames( aSourceName, aGivenName, xIntDim );
    1709          12 :                 aDataNames.push_back( aSourceName );
    1710          24 :                 aGivenNames.push_back( aGivenName );
    1711             :             }
    1712          24 :             else if ( nOrient != sheet::DataPilotFieldOrientation_HIDDEN )
    1713             :             {
    1714             :                 // get level names, as in ScDPOutput
    1715             : 
    1716          24 :                 uno::Reference<container::XIndexAccess> xHiers = new ScNameToIndexAccess( xDimSupp->getHierarchies() );
    1717             :                 sal_Int32 nHierarchy = ScUnoHelpFunctions::GetLongProperty( xDimProp,
    1718          24 :                                                     OUString(SC_UNO_DP_USEDHIERARCHY) );
    1719          24 :                 if ( nHierarchy >= xHiers->getCount() )
    1720           0 :                     nHierarchy = 0;
    1721             : 
    1722             :                 uno::Reference<uno::XInterface> xHier = ScUnoHelpFunctions::AnyToInterface(
    1723          48 :                                                     xHiers->getByIndex(nHierarchy) );
    1724          48 :                 uno::Reference<sheet::XLevelsSupplier> xHierSupp( xHier, uno::UNO_QUERY );
    1725          24 :                 if ( xHierSupp.is() )
    1726             :                 {
    1727          24 :                     uno::Reference<container::XIndexAccess> xLevels = new ScNameToIndexAccess( xHierSupp->getLevels() );
    1728          24 :                     sal_Int32 nLevCount = xLevels->getCount();
    1729          48 :                     for (sal_Int32 nLev=0; nLev<nLevCount; nLev++)
    1730             :                     {
    1731             :                         uno::Reference<uno::XInterface> xLevel = ScUnoHelpFunctions::AnyToInterface(
    1732          24 :                                                             xLevels->getByIndex(nLev) );
    1733          48 :                         uno::Reference<container::XNamed> xLevNam( xLevel, uno::UNO_QUERY );
    1734          48 :                         uno::Reference<sheet::XMembersSupplier> xLevSupp( xLevel, uno::UNO_QUERY );
    1735          24 :                         if ( xLevNam.is() && xLevSupp.is() )
    1736             :                         {
    1737          24 :                             uno::Reference<container::XNameAccess> xMembers = xLevSupp->getMembers();
    1738             : 
    1739          48 :                             OUString aFieldName( xLevNam->getName() );
    1740          48 :                             uno::Sequence<OUString> aMemberNames( xMembers->getElementNames() );
    1741             : 
    1742          24 :                             aFieldNames.push_back( aFieldName );
    1743          48 :                             aFieldValues.push_back( aMemberNames );
    1744             :                         }
    1745          48 :                     }
    1746          24 :                 }
    1747             :             }
    1748             :         }
    1749          48 :     }
    1750             : 
    1751             : 
    1752             :     // compare and build filters
    1753             : 
    1754             : 
    1755          12 :     SCSIZE nDataFields = aDataNames.size();
    1756          12 :     SCSIZE nFieldCount = aFieldNames.size();
    1757             :     OSL_ENSURE( aGivenNames.size() == nDataFields && aFieldValues.size() == nFieldCount, "wrong count" );
    1758             : 
    1759          12 :     bool bError = false;
    1760          12 :     bool bHasData = false;
    1761          24 :     OUString aRemaining(comphelper::string::strip(rFilterList, ' '));
    1762          36 :     while (!aRemaining.isEmpty() && !bError)
    1763             :     {
    1764          12 :         bool bUsed = false;
    1765             : 
    1766             :         // look for data field name
    1767             : 
    1768          24 :         for ( SCSIZE nDataPos=0; nDataPos<nDataFields && !bUsed; nDataPos++ )
    1769             :         {
    1770          12 :             OUString aFound;
    1771          12 :             sal_Int32 nMatched = 0;
    1772          12 :             if (isAtStart(aRemaining, aDataNames[nDataPos], nMatched, false, NULL))
    1773           0 :                 aFound = aDataNames[nDataPos];
    1774          12 :             else if (isAtStart(aRemaining, aGivenNames[nDataPos], nMatched, false, NULL))
    1775           0 :                 aFound = aGivenNames[nDataPos];
    1776             : 
    1777          12 :             if (!aFound.isEmpty())
    1778             :             {
    1779           0 :                 rDataFieldName = aFound;
    1780           0 :                 aRemaining = aRemaining.copy(nMatched);
    1781           0 :                 bHasData = true;
    1782           0 :                 bUsed = true;
    1783             :             }
    1784          12 :         }
    1785             : 
    1786             :         // look for field name
    1787             : 
    1788          12 :         OUString aSpecField;
    1789          12 :         bool bHasFieldName = false;
    1790          12 :         if ( !bUsed )
    1791             :         {
    1792          12 :             sal_Int32 nMatched = 0;
    1793          36 :             for ( SCSIZE nField=0; nField<nFieldCount && !bHasFieldName; nField++ )
    1794             :             {
    1795          24 :                 if (isAtStart(aRemaining, aFieldNames[nField], nMatched, true, NULL))
    1796             :                 {
    1797          12 :                     aSpecField = aFieldNames[nField];
    1798          12 :                     aRemaining = aRemaining.copy(nMatched);
    1799          12 :                     aRemaining = comphelper::string::stripStart(aRemaining, ' ');
    1800             : 
    1801             :                     // field name has to be followed by item name in brackets
    1802          12 :                     if (aRemaining.startsWith("["))
    1803             :                     {
    1804          12 :                         bHasFieldName = true;
    1805             :                         // bUsed remains false - still need the item
    1806             :                     }
    1807             :                     else
    1808             :                     {
    1809           0 :                         bUsed = true;
    1810           0 :                         bError = true;
    1811             :                     }
    1812             :                 }
    1813             :             }
    1814             :         }
    1815             : 
    1816             :         // look for field item
    1817             : 
    1818          12 :         if ( !bUsed )
    1819             :         {
    1820          12 :             bool bItemFound = false;
    1821          12 :             sal_Int32 nMatched = 0;
    1822          12 :             OUString aFoundName;
    1823          24 :             OUString aFoundValue;
    1824          12 :             sheet::GeneralFunction eFunc = sheet::GeneralFunction_NONE;
    1825          12 :             sheet::GeneralFunction eFoundFunc = sheet::GeneralFunction_NONE;
    1826             : 
    1827          36 :             for ( SCSIZE nField=0; nField<nFieldCount; nField++ )
    1828             :             {
    1829             :                 // If a field name is given, look in that field only, otherwise in all fields.
    1830             :                 // aSpecField is initialized from aFieldNames array, so exact comparison can be used.
    1831          24 :                 if ( !bHasFieldName || aFieldNames[nField] == aSpecField )
    1832             :                 {
    1833          12 :                     const uno::Sequence<OUString>& rItems = aFieldValues[nField];
    1834          12 :                     sal_Int32 nItemCount = rItems.getLength();
    1835          12 :                     const OUString* pItemArr = rItems.getConstArray();
    1836          60 :                     for ( sal_Int32 nItem=0; nItem<nItemCount; nItem++ )
    1837             :                     {
    1838          48 :                         if ( isAtStart( aRemaining, pItemArr[nItem], nMatched, false, &eFunc ) )
    1839             :                         {
    1840          12 :                             if ( bItemFound )
    1841           0 :                                 bError = true;      // duplicate (also across fields)
    1842             :                             else
    1843             :                             {
    1844          12 :                                 aFoundName = aFieldNames[nField];
    1845          12 :                                 aFoundValue = pItemArr[nItem];
    1846          12 :                                 eFoundFunc = eFunc;
    1847          12 :                                 bItemFound = true;
    1848          12 :                                 bUsed = true;
    1849             :                             }
    1850             :                         }
    1851             :                     }
    1852             :                 }
    1853             :             }
    1854             : 
    1855          12 :             if ( bItemFound && !bError )
    1856             :             {
    1857          12 :                 sheet::DataPilotFieldFilter aField;
    1858          12 :                 aField.FieldName = aFoundName;
    1859          12 :                 aField.MatchValue = aFoundValue;
    1860          12 :                 rFilters.push_back(aField);
    1861          12 :                 rFilterFuncs.push_back(eFoundFunc);
    1862          12 :                 aRemaining = aRemaining.copy(nMatched);
    1863          12 :             }
    1864             :         }
    1865             : 
    1866          12 :         if ( !bUsed )
    1867           0 :             bError = true;
    1868             : 
    1869             :         // remove any number of spaces between entries
    1870          12 :         aRemaining = comphelper::string::stripStart(aRemaining, ' ');
    1871          12 :     }
    1872             : 
    1873          12 :     if ( !bError && !bHasData && aDataNames.size() == 1 )
    1874             :     {
    1875             :         // if there's only one data field, its name need not be specified
    1876          12 :         rDataFieldName = aDataNames[0];
    1877          12 :         bHasData = true;
    1878             :     }
    1879             : 
    1880          24 :     return bHasData && !bError;
    1881             : }
    1882             : 
    1883           0 : void ScDPObject::ToggleDetails(const DataPilotTableHeaderData& rElemDesc, ScDPObject* pDestObj)
    1884             : {
    1885           0 :     CreateObjects();            // create xSource if not already done
    1886             : 
    1887             :     //  find dimension name
    1888             : 
    1889           0 :     uno::Reference<container::XNamed> xDim;
    1890           0 :     uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
    1891           0 :     uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName );
    1892           0 :     long nIntCount = xIntDims->getCount();
    1893           0 :     if ( rElemDesc.Dimension < nIntCount )
    1894             :     {
    1895             :         uno::Reference<uno::XInterface> xIntDim = ScUnoHelpFunctions::AnyToInterface(
    1896           0 :                                     xIntDims->getByIndex(rElemDesc.Dimension) );
    1897           0 :         xDim = uno::Reference<container::XNamed>( xIntDim, uno::UNO_QUERY );
    1898             :     }
    1899             :     OSL_ENSURE( xDim.is(), "dimension not found" );
    1900           0 :     if ( !xDim.is() ) return;
    1901           0 :     OUString aDimName = xDim->getName();
    1902             : 
    1903           0 :     uno::Reference<beans::XPropertySet> xDimProp( xDim, uno::UNO_QUERY );
    1904             :     sal_Bool bDataLayout = ScUnoHelpFunctions::GetBoolProperty( xDimProp,
    1905           0 :                         OUString(SC_UNO_DP_ISDATALAYOUT) );
    1906           0 :     if (bDataLayout)
    1907             :     {
    1908             :         //  the elements of the data layout dimension can't be found by their names
    1909             :         //  -> don't change anything
    1910           0 :         return;
    1911             :     }
    1912             : 
    1913             :     //  query old state
    1914             : 
    1915           0 :     long nHierCount = 0;
    1916           0 :     uno::Reference<container::XIndexAccess> xHiers;
    1917           0 :     uno::Reference<sheet::XHierarchiesSupplier> xHierSupp( xDim, uno::UNO_QUERY );
    1918           0 :     if ( xHierSupp.is() )
    1919             :     {
    1920           0 :         uno::Reference<container::XNameAccess> xHiersName = xHierSupp->getHierarchies();
    1921           0 :         xHiers = new ScNameToIndexAccess( xHiersName );
    1922           0 :         nHierCount = xHiers->getCount();
    1923             :     }
    1924           0 :     uno::Reference<uno::XInterface> xHier;
    1925           0 :     if ( rElemDesc.Hierarchy < nHierCount )
    1926           0 :         xHier = ScUnoHelpFunctions::AnyToInterface( xHiers->getByIndex(rElemDesc.Hierarchy) );
    1927             :     OSL_ENSURE( xHier.is(), "hierarchy not found" );
    1928           0 :     if ( !xHier.is() ) return;
    1929             : 
    1930           0 :     long nLevCount = 0;
    1931           0 :     uno::Reference<container::XIndexAccess> xLevels;
    1932           0 :     uno::Reference<sheet::XLevelsSupplier> xLevSupp( xHier, uno::UNO_QUERY );
    1933           0 :     if ( xLevSupp.is() )
    1934             :     {
    1935           0 :         uno::Reference<container::XNameAccess> xLevsName = xLevSupp->getLevels();
    1936           0 :         xLevels = new ScNameToIndexAccess( xLevsName );
    1937           0 :         nLevCount = xLevels->getCount();
    1938             :     }
    1939           0 :     uno::Reference<uno::XInterface> xLevel;
    1940           0 :     if ( rElemDesc.Level < nLevCount )
    1941           0 :         xLevel = ScUnoHelpFunctions::AnyToInterface( xLevels->getByIndex(rElemDesc.Level) );
    1942             :     OSL_ENSURE( xLevel.is(), "level not found" );
    1943           0 :     if ( !xLevel.is() ) return;
    1944             : 
    1945           0 :     uno::Reference<container::XNameAccess> xMembers;
    1946           0 :     uno::Reference<sheet::XMembersSupplier> xMbrSupp( xLevel, uno::UNO_QUERY );
    1947           0 :     if ( xMbrSupp.is() )
    1948           0 :         xMembers = xMbrSupp->getMembers();
    1949             : 
    1950           0 :     sal_Bool bFound = false;
    1951           0 :     sal_Bool bShowDetails = sal_True;
    1952             : 
    1953           0 :     if ( xMembers.is() )
    1954             :     {
    1955           0 :         if ( xMembers->hasByName(rElemDesc.MemberName) )
    1956             :         {
    1957             :             uno::Reference<uno::XInterface> xMemberInt = ScUnoHelpFunctions::AnyToInterface(
    1958           0 :                                             xMembers->getByName(rElemDesc.MemberName) );
    1959           0 :             uno::Reference<beans::XPropertySet> xMbrProp( xMemberInt, uno::UNO_QUERY );
    1960           0 :             if ( xMbrProp.is() )
    1961             :             {
    1962             :                 bShowDetails = ScUnoHelpFunctions::GetBoolProperty( xMbrProp,
    1963           0 :                                     OUString(SC_UNO_DP_SHOWDETAILS) );
    1964             :                 //! don't set bFound if property is unknown?
    1965           0 :                 bFound = sal_True;
    1966           0 :             }
    1967             :         }
    1968             :     }
    1969             : 
    1970             :     OSL_ENSURE( bFound, "member not found" );
    1971             :     (void)bFound;
    1972             : 
    1973             :     //! use Hierarchy and Level in SaveData !!!!
    1974             : 
    1975             :     //  modify pDestObj if set, this object otherwise
    1976           0 :     ScDPSaveData* pModifyData = pDestObj ? ( pDestObj->pSaveData ) : pSaveData;
    1977             :     OSL_ENSURE( pModifyData, "no data?" );
    1978           0 :     if ( pModifyData )
    1979             :     {
    1980           0 :         const OUString aName = rElemDesc.MemberName;
    1981             :         pModifyData->GetDimensionByName(aDimName)->
    1982           0 :             GetMemberByName(aName)->SetShowDetails( !bShowDetails );    // toggle
    1983             : 
    1984           0 :         if ( pDestObj )
    1985           0 :             pDestObj->InvalidateData();     // re-init source from SaveData
    1986             :         else
    1987           0 :             InvalidateData();               // re-init source from SaveData
    1988           0 :     }
    1989             : }
    1990             : 
    1991           0 : static sal_uInt16 lcl_FirstSubTotal( const uno::Reference<beans::XPropertySet>& xDimProp )     // PIVOT_FUNC mask
    1992             : {
    1993           0 :     uno::Reference<sheet::XHierarchiesSupplier> xDimSupp( xDimProp, uno::UNO_QUERY );
    1994           0 :     if ( xDimProp.is() && xDimSupp.is() )
    1995             :     {
    1996           0 :         uno::Reference<container::XIndexAccess> xHiers = new ScNameToIndexAccess( xDimSupp->getHierarchies() );
    1997             :         long nHierarchy = ScUnoHelpFunctions::GetLongProperty( xDimProp,
    1998           0 :                                 OUString(SC_UNO_DP_USEDHIERARCHY) );
    1999           0 :         if ( nHierarchy >= xHiers->getCount() )
    2000           0 :             nHierarchy = 0;
    2001             : 
    2002             :         uno::Reference<uno::XInterface> xHier = ScUnoHelpFunctions::AnyToInterface(
    2003           0 :                                     xHiers->getByIndex(nHierarchy) );
    2004           0 :         uno::Reference<sheet::XLevelsSupplier> xHierSupp( xHier, uno::UNO_QUERY );
    2005           0 :         if ( xHierSupp.is() )
    2006             :         {
    2007           0 :             uno::Reference<container::XIndexAccess> xLevels = new ScNameToIndexAccess( xHierSupp->getLevels() );
    2008             :             uno::Reference<uno::XInterface> xLevel =
    2009           0 :                 ScUnoHelpFunctions::AnyToInterface( xLevels->getByIndex( 0 ) );
    2010           0 :             uno::Reference<beans::XPropertySet> xLevProp( xLevel, uno::UNO_QUERY );
    2011           0 :             if ( xLevProp.is() )
    2012             :             {
    2013           0 :                 uno::Any aSubAny;
    2014             :                 try
    2015             :                 {
    2016           0 :                     aSubAny = xLevProp->getPropertyValue(
    2017           0 :                             OUString(SC_UNO_DP_SUBTOTAL) );
    2018             :                 }
    2019           0 :                 catch(uno::Exception&)
    2020             :                 {
    2021             :                 }
    2022           0 :                 uno::Sequence<sheet::GeneralFunction> aSeq;
    2023           0 :                 if ( aSubAny >>= aSeq )
    2024             :                 {
    2025           0 :                     sal_uInt16 nMask = 0;
    2026           0 :                     const sheet::GeneralFunction* pArray = aSeq.getConstArray();
    2027           0 :                     long nCount = aSeq.getLength();
    2028           0 :                     for (long i=0; i<nCount; i++)
    2029           0 :                         nMask |= ScDataPilotConversion::FunctionBit(pArray[i]);
    2030           0 :                     return nMask;
    2031           0 :                 }
    2032           0 :             }
    2033           0 :         }
    2034             :     }
    2035             : 
    2036             :     OSL_FAIL("FirstSubTotal: NULL");
    2037           0 :     return 0;
    2038             : }
    2039             : 
    2040             : namespace {
    2041             : 
    2042             : class FindByColumn : public std::unary_function<ScPivotField, bool>
    2043             : {
    2044             :     SCsCOL mnCol;
    2045             :     sal_uInt16 mnMask;
    2046             : public:
    2047           0 :     FindByColumn(SCsCOL nCol, sal_uInt16 nMask) : mnCol(nCol), mnMask(nMask) {}
    2048           0 :     bool operator() (const ScPivotField& r) const
    2049             :     {
    2050           0 :         return r.nCol == mnCol && r.nFuncMask == mnMask;
    2051             :     }
    2052             : };
    2053             : 
    2054             : }
    2055             : 
    2056           0 : void lcl_FillOldFields( ScPivotFieldVector& rFields,
    2057             :     const uno::Reference<sheet::XDimensionsSupplier>& xSource,
    2058             :     sal_uInt16 nOrient, bool bAddData )
    2059             : {
    2060           0 :     ScPivotFieldVector aFields;
    2061             : 
    2062           0 :     bool bDataFound = false;
    2063             : 
    2064             :     //! merge multiple occurrences (data field with different functions)
    2065             :     //! force data field in one dimension
    2066             : 
    2067           0 :     vector<long> aPos;
    2068             : 
    2069           0 :     uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
    2070           0 :     uno::Reference<container::XIndexAccess> xDims = new ScNameToIndexAccess( xDimsName );
    2071           0 :     long nDimCount = xDims->getCount();
    2072           0 :     for (long nDim = 0; nDim < nDimCount; ++nDim)
    2073             :     {
    2074             :         // Get dimension object.
    2075             :         uno::Reference<uno::XInterface> xIntDim =
    2076           0 :             ScUnoHelpFunctions::AnyToInterface( xDims->getByIndex(nDim) );
    2077             : 
    2078             :         // dimension properties
    2079           0 :         uno::Reference<beans::XPropertySet> xDimProp( xIntDim, uno::UNO_QUERY );
    2080             : 
    2081             :         // dimension orientation, hidden by default.
    2082             :         long nDimOrient = ScUnoHelpFunctions::GetEnumProperty(
    2083             :                             xDimProp, OUString(SC_UNO_DP_ORIENTATION),
    2084           0 :                             sheet::DataPilotFieldOrientation_HIDDEN );
    2085             : 
    2086           0 :         if ( xDimProp.is() && nDimOrient == nOrient )
    2087             :         {
    2088             :             // Let's take this dimension.
    2089             : 
    2090             :             // function mask.
    2091           0 :             sal_uInt16 nMask = 0;
    2092           0 :             if ( nOrient == sheet::DataPilotFieldOrientation_DATA )
    2093             :             {
    2094             :                 sheet::GeneralFunction eFunc = (sheet::GeneralFunction)ScUnoHelpFunctions::GetEnumProperty(
    2095             :                                             xDimProp, OUString(SC_UNO_DP_FUNCTION),
    2096           0 :                                             sheet::GeneralFunction_NONE );
    2097           0 :                 if ( eFunc == sheet::GeneralFunction_AUTO )
    2098             :                 {
    2099             :                     //! test for numeric data
    2100           0 :                     eFunc = sheet::GeneralFunction_SUM;
    2101             :                 }
    2102           0 :                 nMask = ScDataPilotConversion::FunctionBit(eFunc);
    2103             :             }
    2104             :             else
    2105           0 :                 nMask = lcl_FirstSubTotal( xDimProp );      // from first hierarchy
    2106             : 
    2107             :             // is this data layout dimension?
    2108             :             bool bDataLayout = ScUnoHelpFunctions::GetBoolProperty(
    2109           0 :                 xDimProp, OUString(SC_UNO_DP_ISDATALAYOUT));
    2110             : 
    2111             :             // is this dimension cloned?
    2112           0 :             long nDupSource = -1;
    2113             :             try
    2114             :             {
    2115           0 :                 uno::Any aOrigAny = xDimProp->getPropertyValue(
    2116           0 :                     OUString(SC_UNO_DP_ORIGINAL_POS));
    2117           0 :                 sal_Int32 nTmp = 0;
    2118           0 :                 if (aOrigAny >>= nTmp)
    2119           0 :                     nDupSource = static_cast<sal_Int32>(nTmp);
    2120             :             }
    2121           0 :             catch(uno::Exception&)
    2122             :             {
    2123             :             }
    2124             : 
    2125           0 :             sal_uInt8 nDupCount = 0;
    2126           0 :             if (nDupSource >= 0)
    2127             :             {
    2128             :                 // this dimension is cloned.
    2129             : 
    2130             :                 SCsCOL nCompCol; // ID of the original dimension.
    2131           0 :                 if ( bDataLayout )
    2132           0 :                     nCompCol = PIVOT_DATA_FIELD;
    2133             :                 else
    2134           0 :                     nCompCol = static_cast<SCsCOL>(nDupSource);     //! seek source column from name
    2135             : 
    2136           0 :                 ScPivotFieldVector::iterator it = std::find_if(aFields.begin(), aFields.end(), FindByColumn(nCompCol, nMask));
    2137           0 :                 if (it != aFields.end())
    2138           0 :                     nDupCount = it->mnDupCount + 1;
    2139             :             }
    2140             : 
    2141           0 :             aFields.push_back(ScPivotField());
    2142           0 :             ScPivotField& rField = aFields.back();
    2143           0 :             if (bDataLayout)
    2144             :             {
    2145           0 :                 rField.nCol = PIVOT_DATA_FIELD;
    2146           0 :                 bDataFound = true;
    2147             :             }
    2148             :             else
    2149             :             {
    2150           0 :                 rField.mnOriginalDim = nDupSource;
    2151           0 :                 rField.nCol = static_cast<SCCOL>(nDim);    //! seek source column from name
    2152             :             }
    2153             : 
    2154           0 :             rField.nFuncMask = nMask;
    2155           0 :             rField.mnDupCount = nDupCount;
    2156             :             long nPos = ScUnoHelpFunctions::GetLongProperty(
    2157           0 :                 xDimProp, OUString(SC_UNO_DP_POSITION));
    2158           0 :             aPos.push_back(nPos);
    2159             : 
    2160             :             try
    2161             :             {
    2162           0 :                 if (nOrient == sheet::DataPilotFieldOrientation_DATA)
    2163           0 :                     xDimProp->getPropertyValue(OUString(SC_UNO_DP_REFVALUE))
    2164           0 :                         >>= rField.maFieldRef;
    2165             :             }
    2166           0 :             catch (uno::Exception&)
    2167             :             {
    2168             :             }
    2169             :         }
    2170           0 :     }
    2171             : 
    2172             :     //  sort by getPosition() value
    2173             : 
    2174           0 :     size_t nOutCount = aFields.size();
    2175           0 :     if (nOutCount >= 1)
    2176             :     {
    2177           0 :         for (size_t i = 0; i < nOutCount - 1; ++i)
    2178             :         {
    2179           0 :             for (size_t j = 0; j + i < nOutCount - 1; ++j)
    2180             :             {
    2181           0 :                 if ( aPos[j+1] < aPos[j] )
    2182             :                 {
    2183           0 :                     std::swap( aPos[j], aPos[j+1] );
    2184           0 :                     std::swap( aFields[j], aFields[j+1] );
    2185             :                 }
    2186             :             }
    2187             :         }
    2188             :     }
    2189             : 
    2190           0 :     if (bAddData && !bDataFound)
    2191           0 :         aFields.push_back(ScPivotField(PIVOT_DATA_FIELD, 0));
    2192             : 
    2193           0 :     rFields.swap(aFields);
    2194           0 : }
    2195             : 
    2196           0 : bool ScDPObject::FillOldParam(ScPivotParam& rParam) const
    2197             : {
    2198           0 :     ((ScDPObject*)this)->CreateObjects();       // xSource is needed for field numbers
    2199             : 
    2200           0 :     if (!xSource.is())
    2201           0 :         return false;
    2202             : 
    2203           0 :     rParam.nCol = aOutRange.aStart.Col();
    2204           0 :     rParam.nRow = aOutRange.aStart.Row();
    2205           0 :     rParam.nTab = aOutRange.aStart.Tab();
    2206             :     // ppLabelArr / nLabels is not changed
    2207             : 
    2208           0 :     bool bAddData = ( lcl_GetDataGetOrientation( xSource ) == sheet::DataPilotFieldOrientation_HIDDEN );
    2209             :     lcl_FillOldFields(
    2210           0 :         rParam.maPageFields, xSource, sheet::DataPilotFieldOrientation_PAGE, false);
    2211             :     lcl_FillOldFields(
    2212           0 :         rParam.maColFields, xSource, sheet::DataPilotFieldOrientation_COLUMN, bAddData);
    2213             :     lcl_FillOldFields(
    2214           0 :         rParam.maRowFields, xSource, sheet::DataPilotFieldOrientation_ROW, false);
    2215             :     lcl_FillOldFields(
    2216           0 :         rParam.maDataFields, xSource, sheet::DataPilotFieldOrientation_DATA, false);
    2217             : 
    2218           0 :     uno::Reference<beans::XPropertySet> xProp( xSource, uno::UNO_QUERY );
    2219           0 :     if (xProp.is())
    2220             :     {
    2221             :         try
    2222             :         {
    2223             :             rParam.bMakeTotalCol = ScUnoHelpFunctions::GetBoolProperty( xProp,
    2224           0 :                         OUString(SC_UNO_DP_COLGRAND), true );
    2225             :             rParam.bMakeTotalRow = ScUnoHelpFunctions::GetBoolProperty( xProp,
    2226           0 :                         OUString(SC_UNO_DP_ROWGRAND), true );
    2227             : 
    2228             :             // following properties may be missing for external sources
    2229             :             rParam.bIgnoreEmptyRows = ScUnoHelpFunctions::GetBoolProperty( xProp,
    2230           0 :                         OUString(SC_UNO_DP_IGNOREEMPTY) );
    2231             :             rParam.bDetectCategories = ScUnoHelpFunctions::GetBoolProperty( xProp,
    2232           0 :                         OUString(SC_UNO_DP_REPEATEMPTY) );
    2233             :         }
    2234           0 :         catch(uno::Exception&)
    2235             :         {
    2236             :             // no error
    2237             :         }
    2238             :     }
    2239           0 :     return true;
    2240             : }
    2241             : 
    2242           3 : static void lcl_FillLabelData( ScDPLabelData& rData, const uno::Reference< beans::XPropertySet >& xDimProp )
    2243             : {
    2244           3 :     uno::Reference<sheet::XHierarchiesSupplier> xDimSupp( xDimProp, uno::UNO_QUERY );
    2245           3 :     if (!xDimProp.is() || !xDimSupp.is())
    2246           0 :         return;
    2247             : 
    2248           6 :     uno::Reference<container::XIndexAccess> xHiers = new ScNameToIndexAccess( xDimSupp->getHierarchies() );
    2249             :     long nHierarchy = ScUnoHelpFunctions::GetLongProperty(
    2250           3 :         xDimProp, OUString(SC_UNO_DP_USEDHIERARCHY));
    2251           3 :     if ( nHierarchy >= xHiers->getCount() )
    2252           0 :         nHierarchy = 0;
    2253           3 :     rData.mnUsedHier = nHierarchy;
    2254             : 
    2255             :     uno::Reference<uno::XInterface> xHier =
    2256           6 :         ScUnoHelpFunctions::AnyToInterface(xHiers->getByIndex(nHierarchy));
    2257             : 
    2258           6 :     uno::Reference<sheet::XLevelsSupplier> xHierSupp( xHier, uno::UNO_QUERY );
    2259           3 :     if (!xHierSupp.is())
    2260           0 :         return;
    2261             : 
    2262             :     uno::Reference<container::XIndexAccess> xLevels =
    2263           6 :         new ScNameToIndexAccess( xHierSupp->getLevels() );
    2264             : 
    2265             :     uno::Reference<uno::XInterface> xLevel =
    2266           6 :         ScUnoHelpFunctions::AnyToInterface( xLevels->getByIndex(0) );
    2267           6 :     uno::Reference<beans::XPropertySet> xLevProp( xLevel, uno::UNO_QUERY );
    2268           3 :     if (!xLevProp.is())
    2269           0 :         return;
    2270             : 
    2271             :     rData.mbShowAll = ScUnoHelpFunctions::GetBoolProperty(
    2272           3 :         xLevProp, OUString(SC_UNO_DP_SHOWEMPTY));
    2273             : 
    2274             :     try
    2275             :     {
    2276           3 :         xLevProp->getPropertyValue( OUString( SC_UNO_DP_SORTING ) )
    2277           6 :             >>= rData.maSortInfo;
    2278           3 :         xLevProp->getPropertyValue( OUString( SC_UNO_DP_LAYOUT ) )
    2279           6 :             >>= rData.maLayoutInfo;
    2280           3 :         xLevProp->getPropertyValue( OUString( SC_UNO_DP_AUTOSHOW ) )
    2281           6 :             >>= rData.maShowInfo;
    2282             :     }
    2283           0 :     catch(uno::Exception&)
    2284             :     {
    2285           3 :     }
    2286             : }
    2287             : 
    2288           4 : bool ScDPObject::FillLabelDataForDimension(
    2289             :     const uno::Reference<container::XIndexAccess>& xDims, sal_Int32 nDim, ScDPLabelData& rLabelData)
    2290             : {
    2291             :     uno::Reference<uno::XInterface> xIntDim =
    2292           4 :         ScUnoHelpFunctions::AnyToInterface( xDims->getByIndex(nDim) );
    2293           8 :     uno::Reference<container::XNamed> xDimName( xIntDim, uno::UNO_QUERY );
    2294           8 :     uno::Reference<beans::XPropertySet> xDimProp( xIntDim, uno::UNO_QUERY );
    2295             : 
    2296           4 :     if (!xDimName.is() || !xDimProp.is())
    2297           0 :         return false;
    2298             : 
    2299             :     bool bData = ScUnoHelpFunctions::GetBoolProperty(
    2300           4 :         xDimProp, OUString(SC_UNO_DP_ISDATALAYOUT));
    2301             :     //! error checking -- is "IsDataLayoutDimension" property required??
    2302             : 
    2303           4 :     sal_Int32 nOrigPos = -1;
    2304           8 :     OUString aFieldName;
    2305             :     try
    2306             :     {
    2307           4 :         aFieldName = xDimName->getName();
    2308           4 :         uno::Any aOrigAny = xDimProp->getPropertyValue(
    2309           4 :                     OUString(SC_UNO_DP_ORIGINAL_POS));
    2310           4 :         aOrigAny >>= nOrigPos;
    2311             :     }
    2312           0 :     catch(uno::Exception&)
    2313             :     {
    2314             :     }
    2315             : 
    2316             :     OUString aLayoutName = ScUnoHelpFunctions::GetStringProperty(
    2317           8 :         xDimProp, OUString(SC_UNO_DP_LAYOUTNAME), OUString());
    2318             : 
    2319             :     OUString aSubtotalName = ScUnoHelpFunctions::GetStringProperty(
    2320           8 :         xDimProp, OUString(SC_UNO_DP_FIELD_SUBTOTALNAME), OUString());
    2321             : 
    2322           4 :     bool bIsValue = true;                               //! check
    2323             : 
    2324             :     // Name from the UNO dimension object may have trailing '*'s in which
    2325             :     // case it's a duplicate dimension. Convert that to a duplicate index.
    2326             : 
    2327           4 :     sal_uInt8 nDupCount = ScDPUtil::getDuplicateIndex(aFieldName);
    2328           4 :     aFieldName = ScDPUtil::getSourceDimensionName(aFieldName);
    2329             : 
    2330           4 :     rLabelData.maName = aFieldName;
    2331           4 :     rLabelData.mnCol = static_cast<SCCOL>(nDim);
    2332           4 :     rLabelData.mnDupCount = nDupCount;
    2333           4 :     rLabelData.mbDataLayout = bData;
    2334           4 :     rLabelData.mbIsValue = bIsValue;
    2335             : 
    2336           4 :     if (!bData)
    2337             :     {
    2338           3 :         rLabelData.mnOriginalDim = static_cast<long>(nOrigPos);
    2339           3 :         rLabelData.maLayoutName = aLayoutName;
    2340           3 :         rLabelData.maSubtotalName = aSubtotalName;
    2341           3 :         if (nOrigPos >= 0)
    2342             :             // This is a duplicated dimension. Use the original dimension index.
    2343           1 :             nDim = nOrigPos;
    2344           3 :         GetHierarchies(nDim, rLabelData.maHiers);
    2345           3 :         GetMembers(nDim, GetUsedHierarchy(nDim), rLabelData.maMembers);
    2346           3 :         lcl_FillLabelData(rLabelData, xDimProp);
    2347             :         rLabelData.mnFlags = ScUnoHelpFunctions::GetLongProperty(
    2348           3 :             xDimProp, OUString(SC_UNO_DP_FLAGS), 0);
    2349             :     }
    2350           8 :     return true;
    2351             : }
    2352             : 
    2353           0 : bool ScDPObject::FillLabelData(sal_Int32 nDim, ScDPLabelData& rLabels)
    2354             : {
    2355           0 :     CreateObjects();
    2356           0 :     if (!xSource.is())
    2357           0 :         return false;
    2358             : 
    2359           0 :     uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
    2360           0 :     uno::Reference<container::XIndexAccess> xDims = new ScNameToIndexAccess( xDimsName );
    2361           0 :     sal_Int32 nDimCount = xDims->getCount();
    2362           0 :     if (nDimCount <= 0 || nDim >= nDimCount)
    2363           0 :         return false;
    2364             : 
    2365           0 :     return FillLabelDataForDimension(xDims, nDim, rLabels);
    2366             : }
    2367             : 
    2368           1 : bool ScDPObject::FillLabelData(ScPivotParam& rParam)
    2369             : {
    2370           1 :     rParam.maLabelArray.clear();
    2371             : 
    2372           1 :     CreateObjects();
    2373           1 :     if (!xSource.is())
    2374           0 :         return false;
    2375             : 
    2376           1 :     uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
    2377           2 :     uno::Reference<container::XIndexAccess> xDims = new ScNameToIndexAccess( xDimsName );
    2378           1 :     sal_Int32 nDimCount = xDims->getCount();
    2379           1 :     if (nDimCount <= 0)
    2380           0 :         return false;
    2381             : 
    2382           5 :     for (sal_Int32 nDim = 0; nDim < nDimCount; ++nDim)
    2383             :     {
    2384           4 :         std::auto_ptr<ScDPLabelData> pNewLabel(new ScDPLabelData);
    2385           4 :         FillLabelDataForDimension(xDims, nDim, *pNewLabel);
    2386           4 :         rParam.maLabelArray.push_back(pNewLabel);
    2387           4 :     }
    2388             : 
    2389           2 :     return true;
    2390             : }
    2391             : 
    2392           3 : bool ScDPObject::GetHierarchiesNA( sal_Int32 nDim, uno::Reference< container::XNameAccess >& xHiers )
    2393             : {
    2394           3 :     bool bRet = false;
    2395           3 :     uno::Reference<container::XNameAccess> xDimsName( GetSource()->getDimensions() );
    2396           6 :     uno::Reference<container::XIndexAccess> xIntDims(new ScNameToIndexAccess( xDimsName ));
    2397           3 :     if( xIntDims.is() )
    2398             :     {
    2399           3 :         uno::Reference<sheet::XHierarchiesSupplier> xHierSup(xIntDims->getByIndex( nDim ), uno::UNO_QUERY);
    2400           3 :         if (xHierSup.is())
    2401             :         {
    2402           3 :             xHiers.set( xHierSup->getHierarchies() );
    2403           3 :             bRet = xHiers.is();
    2404           3 :         }
    2405             :     }
    2406           6 :     return bRet;
    2407             : }
    2408             : 
    2409           3 : bool ScDPObject::GetHierarchies( sal_Int32 nDim, uno::Sequence< OUString >& rHiers )
    2410             : {
    2411           3 :     bool bRet = false;
    2412           3 :     uno::Reference< container::XNameAccess > xHiersNA;
    2413           3 :     if( GetHierarchiesNA( nDim, xHiersNA ) )
    2414             :     {
    2415           3 :         rHiers = xHiersNA->getElementNames();
    2416           3 :         bRet = true;
    2417             :     }
    2418           3 :     return bRet;
    2419             : }
    2420             : 
    2421          63 : sal_Int32 ScDPObject::GetUsedHierarchy( sal_Int32 nDim )
    2422             : {
    2423          63 :     sal_Int32 nHier = 0;
    2424          63 :     uno::Reference<container::XNameAccess> xDimsName( GetSource()->getDimensions() );
    2425         126 :     uno::Reference<container::XIndexAccess> xIntDims(new ScNameToIndexAccess( xDimsName ));
    2426         126 :     uno::Reference<beans::XPropertySet> xDim(xIntDims->getByIndex( nDim ), uno::UNO_QUERY);
    2427          63 :     if (xDim.is())
    2428          63 :         nHier = ScUnoHelpFunctions::GetLongProperty( xDim, OUString( SC_UNO_DP_USEDHIERARCHY ) );
    2429         126 :     return nHier;
    2430             : }
    2431             : 
    2432          58 : bool ScDPObject::GetMembersNA( sal_Int32 nDim, uno::Reference< container::XNameAccess >& xMembers )
    2433             : {
    2434          58 :     return GetMembersNA( nDim, GetUsedHierarchy( nDim ), xMembers );
    2435             : }
    2436             : 
    2437          63 : bool ScDPObject::GetMembersNA( sal_Int32 nDim, sal_Int32 nHier, uno::Reference< container::XNameAccess >& xMembers )
    2438             : {
    2439          63 :     bool bRet = false;
    2440          63 :     uno::Reference<container::XNameAccess> xDimsName( GetSource()->getDimensions() );
    2441         126 :     uno::Reference<container::XIndexAccess> xIntDims(new ScNameToIndexAccess( xDimsName ));
    2442         126 :     uno::Reference<beans::XPropertySet> xDim(xIntDims->getByIndex( nDim ), uno::UNO_QUERY);
    2443          63 :     if (xDim.is())
    2444             :     {
    2445          63 :         uno::Reference<sheet::XHierarchiesSupplier> xHierSup(xDim, uno::UNO_QUERY);
    2446          63 :         if (xHierSup.is())
    2447             :         {
    2448          63 :             uno::Reference<container::XIndexAccess> xHiers(new ScNameToIndexAccess(xHierSup->getHierarchies()));
    2449         126 :             uno::Reference<sheet::XLevelsSupplier> xLevSupp( xHiers->getByIndex(nHier), uno::UNO_QUERY );
    2450          63 :             if ( xLevSupp.is() )
    2451             :             {
    2452          63 :                 uno::Reference<container::XIndexAccess> xLevels(new ScNameToIndexAccess( xLevSupp->getLevels()));
    2453          63 :                 if (xLevels.is())
    2454             :                 {
    2455          63 :                     sal_Int32 nLevCount = xLevels->getCount();
    2456          63 :                     if (nLevCount > 0)
    2457             :                     {
    2458          63 :                         uno::Reference<sheet::XMembersSupplier> xMembSupp( xLevels->getByIndex(0), uno::UNO_QUERY );
    2459          63 :                         if ( xMembSupp.is() )
    2460             :                         {
    2461          63 :                             xMembers.set(xMembSupp->getMembers());
    2462          63 :                             bRet = true;
    2463          63 :                         }
    2464             :                     }
    2465          63 :                 }
    2466          63 :             }
    2467          63 :         }
    2468             :     }
    2469         126 :     return bRet;
    2470             : }
    2471             : 
    2472             : 
    2473             : //  convert old pivot tables into new datapilot tables
    2474             : 
    2475             : namespace {
    2476             : 
    2477           0 : OUString lcl_GetDimName( const uno::Reference<sheet::XDimensionsSupplier>& xSource, long nDim )
    2478             : {
    2479           0 :     OUString aName;
    2480           0 :     if ( xSource.is() )
    2481             :     {
    2482           0 :         uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
    2483           0 :         uno::Reference<container::XIndexAccess> xDims = new ScNameToIndexAccess( xDimsName );
    2484           0 :         long nDimCount = xDims->getCount();
    2485           0 :         if ( nDim < nDimCount )
    2486             :         {
    2487             :             uno::Reference<uno::XInterface> xIntDim =
    2488           0 :                 ScUnoHelpFunctions::AnyToInterface( xDims->getByIndex(nDim) );
    2489           0 :             uno::Reference<container::XNamed> xDimName( xIntDim, uno::UNO_QUERY );
    2490           0 :             if (xDimName.is())
    2491             :             {
    2492             :                 try
    2493             :                 {
    2494           0 :                     aName = xDimName->getName();
    2495             :                 }
    2496           0 :                 catch(uno::Exception&)
    2497             :                 {
    2498             :                 }
    2499           0 :             }
    2500           0 :         }
    2501             :     }
    2502           0 :     return aName;
    2503             : }
    2504             : 
    2505           0 : bool hasFieldColumn(const vector<ScPivotField>* pRefFields, SCCOL nCol)
    2506             : {
    2507           0 :     if (!pRefFields)
    2508           0 :         return false;
    2509             : 
    2510           0 :     vector<ScPivotField>::const_iterator itr = pRefFields->begin(), itrEnd = pRefFields->end();
    2511           0 :     for (; itr != itrEnd; ++itr)
    2512             :     {
    2513           0 :         if (itr->nCol == nCol)
    2514             :             // This array of fields contains the specified column.
    2515           0 :             return true;
    2516             :     }
    2517           0 :     return false;
    2518             : }
    2519             : 
    2520             : class FindByOriginalDim : public std::unary_function<ScPivotField, bool>
    2521             : {
    2522             :     long mnDim;
    2523             : public:
    2524           0 :     FindByOriginalDim(long nDim) : mnDim(nDim) {}
    2525           0 :     bool operator() (const ScPivotField& r) const
    2526             :     {
    2527           0 :         return mnDim == r.getOriginalDim();
    2528             :     }
    2529             : };
    2530             : 
    2531             : }
    2532             : 
    2533           0 : void ScDPObject::ConvertOrientation(
    2534             :     ScDPSaveData& rSaveData, const ScPivotFieldVector& rFields, sal_uInt16 nOrient,
    2535             :     const Reference<XDimensionsSupplier>& xSource,
    2536             :     const ScDPLabelDataVector& rLabels,
    2537             :     const ScPivotFieldVector* pRefColFields,
    2538             :     const ScPivotFieldVector* pRefRowFields,
    2539             :     const ScPivotFieldVector* pRefPageFields )
    2540             : {
    2541           0 :     ScPivotFieldVector::const_iterator itr, itrBeg = rFields.begin(), itrEnd = rFields.end();
    2542           0 :     for (itr = itrBeg; itr != itrEnd; ++itr)
    2543             :     {
    2544           0 :         const ScPivotField& rField = *itr;
    2545             : 
    2546           0 :         long nCol = rField.getOriginalDim();
    2547           0 :         sal_uInt16 nFuncs = rField.nFuncMask;
    2548           0 :         const sheet::DataPilotFieldReference& rFieldRef = rField.maFieldRef;
    2549             : 
    2550           0 :         ScDPSaveDimension* pDim = NULL;
    2551           0 :         if ( nCol == PIVOT_DATA_FIELD )
    2552           0 :             pDim = rSaveData.GetDataLayoutDimension();
    2553             :         else
    2554             :         {
    2555           0 :             OUString aDocStr = lcl_GetDimName( xSource, nCol );   // cols must start at 0
    2556           0 :             if (!aDocStr.isEmpty())
    2557           0 :                 pDim = rSaveData.GetDimensionByName(aDocStr);
    2558             :             else
    2559           0 :                 pDim = NULL;
    2560             :         }
    2561             : 
    2562           0 :         if (!pDim)
    2563           0 :             continue;
    2564             : 
    2565           0 :         if ( nOrient == sheet::DataPilotFieldOrientation_DATA )     // set summary function
    2566             :         {
    2567             :             //  generate an individual entry for each function
    2568           0 :             bool bFirst = true;
    2569             : 
    2570             :             //  if a dimension is used for column/row/page and data,
    2571             :             //  use duplicated dimensions for all data occurrences
    2572           0 :             if (hasFieldColumn(pRefColFields, nCol))
    2573           0 :                 bFirst = false;
    2574             : 
    2575           0 :             if (bFirst && hasFieldColumn(pRefRowFields, nCol))
    2576           0 :                 bFirst = false;
    2577             : 
    2578           0 :             if (bFirst && hasFieldColumn(pRefPageFields, nCol))
    2579           0 :                 bFirst = false;
    2580             : 
    2581           0 :             if (bFirst)
    2582             :             {
    2583             :                 //  if set via api, a data column may occur several times
    2584             :                 //  (if the function hasn't been changed yet) -> also look for duplicate data column
    2585           0 :                 bFirst = std::find_if(itrBeg, itr, FindByOriginalDim(nCol)) == itr;
    2586             :             }
    2587             : 
    2588           0 :             sheet::GeneralFunction eFunc = ScDataPilotConversion::FirstFunc(rField.nFuncMask);
    2589           0 :             if (!bFirst)
    2590           0 :                 pDim = rSaveData.DuplicateDimension(pDim->GetName());
    2591           0 :             pDim->SetOrientation(nOrient);
    2592           0 :             pDim->SetFunction(sal::static_int_cast<sal_uInt16>(eFunc));
    2593             : 
    2594           0 :             if( rFieldRef.ReferenceType == sheet::DataPilotFieldReferenceType::NONE )
    2595           0 :                 pDim->SetReferenceValue(0);
    2596             :             else
    2597           0 :                 pDim->SetReferenceValue(&rFieldRef);
    2598             :         }
    2599             :         else                                            // set SubTotals
    2600             :         {
    2601           0 :             pDim->SetOrientation( nOrient );
    2602             : 
    2603             :             sal_uInt16 nFuncArray[16];
    2604           0 :             sal_uInt16 nFuncCount = 0;
    2605           0 :             sal_uInt16 nMask = 1;
    2606           0 :             for (sal_uInt16 nBit=0; nBit<16; nBit++)
    2607             :             {
    2608           0 :                 if ( nFuncs & nMask )
    2609           0 :                     nFuncArray[nFuncCount++] = sal::static_int_cast<sal_uInt16>(ScDataPilotConversion::FirstFunc( nMask ));
    2610           0 :                 nMask *= 2;
    2611             :             }
    2612           0 :             pDim->SetSubTotals( nFuncCount, nFuncArray );
    2613             : 
    2614             :             //  ShowEmpty was implicit in old tables,
    2615             :             //  must be set for data layout dimension (not accessible in dialog)
    2616           0 :             if ( nCol == PIVOT_DATA_FIELD )
    2617           0 :                 pDim->SetShowEmpty( true );
    2618             :         }
    2619             : 
    2620           0 :         size_t nDimIndex = rField.nCol;
    2621           0 :         pDim->RemoveLayoutName();
    2622           0 :         pDim->RemoveSubtotalName();
    2623           0 :         if (nDimIndex < rLabels.size())
    2624             :         {
    2625           0 :             const ScDPLabelData& rLabel = rLabels[nDimIndex];
    2626           0 :             if (!rLabel.maLayoutName.isEmpty())
    2627           0 :                 pDim->SetLayoutName(rLabel.maLayoutName);
    2628           0 :             if (!rLabel.maSubtotalName.isEmpty())
    2629           0 :                 pDim->SetSubtotalName(rLabel.maSubtotalName);
    2630             :         }
    2631             :     }
    2632           0 : }
    2633             : 
    2634           0 : bool ScDPObject::IsOrientationAllowed( sal_uInt16 nOrient, sal_Int32 nDimFlags )
    2635             : {
    2636           0 :     bool bAllowed = true;
    2637           0 :     switch (nOrient)
    2638             :     {
    2639             :         case sheet::DataPilotFieldOrientation_PAGE:
    2640           0 :             bAllowed = ( nDimFlags & sheet::DimensionFlags::NO_PAGE_ORIENTATION ) == 0;
    2641           0 :             break;
    2642             :         case sheet::DataPilotFieldOrientation_COLUMN:
    2643           0 :             bAllowed = ( nDimFlags & sheet::DimensionFlags::NO_COLUMN_ORIENTATION ) == 0;
    2644           0 :             break;
    2645             :         case sheet::DataPilotFieldOrientation_ROW:
    2646           0 :             bAllowed = ( nDimFlags & sheet::DimensionFlags::NO_ROW_ORIENTATION ) == 0;
    2647           0 :             break;
    2648             :         case sheet::DataPilotFieldOrientation_DATA:
    2649           0 :             bAllowed = ( nDimFlags & sheet::DimensionFlags::NO_DATA_ORIENTATION ) == 0;
    2650           0 :             break;
    2651             :         default:
    2652             :             {
    2653             :                 // allowed to remove from previous orientation
    2654             :             }
    2655             :     }
    2656           0 :     return bAllowed;
    2657             : }
    2658             : 
    2659           0 : bool ScDPObject::HasRegisteredSources()
    2660             : {
    2661           0 :     bool bFound = false;
    2662             : 
    2663           0 :     uno::Reference<lang::XMultiServiceFactory> xManager = comphelper::getProcessServiceFactory();
    2664           0 :     uno::Reference<container::XContentEnumerationAccess> xEnAc( xManager, uno::UNO_QUERY );
    2665           0 :     if ( xEnAc.is() )
    2666             :     {
    2667           0 :         uno::Reference<container::XEnumeration> xEnum = xEnAc->createContentEnumeration(
    2668           0 :                                         OUString( SCDPSOURCE_SERVICE ) );
    2669           0 :         if ( xEnum.is() && xEnum->hasMoreElements() )
    2670           0 :             bFound = true;
    2671             :     }
    2672             : 
    2673           0 :     return bFound;
    2674             : }
    2675             : 
    2676           0 : uno::Sequence<OUString> ScDPObject::GetRegisteredSources()
    2677             : {
    2678           0 :     uno::Sequence<OUString> aSeq(0);
    2679             : 
    2680             :     //  use implementation names...
    2681             : 
    2682           0 :     uno::Reference<lang::XMultiServiceFactory> xManager = comphelper::getProcessServiceFactory();
    2683           0 :     uno::Reference<container::XContentEnumerationAccess> xEnAc( xManager, uno::UNO_QUERY );
    2684           0 :     if ( xEnAc.is() )
    2685             :     {
    2686           0 :         uno::Reference<container::XEnumeration> xEnum = xEnAc->createContentEnumeration(
    2687           0 :                                         OUString( SCDPSOURCE_SERVICE ) );
    2688           0 :         if ( xEnum.is() )
    2689             :         {
    2690           0 :             long nCount = 0;
    2691           0 :             while ( xEnum->hasMoreElements() )
    2692             :             {
    2693           0 :                 uno::Any aAddInAny = xEnum->nextElement();
    2694             : //              if ( aAddInAny.getReflection()->getTypeClass() == TypeClass_INTERFACE )
    2695             :                 {
    2696           0 :                     uno::Reference<uno::XInterface> xIntFac;
    2697           0 :                     aAddInAny >>= xIntFac;
    2698           0 :                     if ( xIntFac.is() )
    2699             :                     {
    2700           0 :                         uno::Reference<lang::XServiceInfo> xInfo( xIntFac, uno::UNO_QUERY );
    2701           0 :                         if ( xInfo.is() )
    2702             :                         {
    2703           0 :                             OUString sName = xInfo->getImplementationName();
    2704             : 
    2705           0 :                             aSeq.realloc( nCount+1 );
    2706           0 :                             aSeq.getArray()[nCount] = sName;
    2707           0 :                             ++nCount;
    2708           0 :                         }
    2709           0 :                     }
    2710             :                 }
    2711           0 :             }
    2712           0 :         }
    2713             :     }
    2714             : 
    2715           0 :     return aSeq;
    2716             : }
    2717             : 
    2718           0 : uno::Reference<sheet::XDimensionsSupplier> ScDPObject::CreateSource( const ScDPServiceDesc& rDesc )
    2719             : {
    2720           0 :     OUString aImplName = rDesc.aServiceName;
    2721           0 :     uno::Reference<sheet::XDimensionsSupplier> xRet = NULL;
    2722             : 
    2723           0 :     uno::Reference<lang::XMultiServiceFactory> xManager = comphelper::getProcessServiceFactory();
    2724           0 :     uno::Reference<container::XContentEnumerationAccess> xEnAc(xManager, uno::UNO_QUERY);
    2725           0 :     if (!xEnAc.is())
    2726           0 :         return xRet;
    2727             : 
    2728             :     uno::Reference<container::XEnumeration> xEnum =
    2729           0 :         xEnAc->createContentEnumeration(OUString(SCDPSOURCE_SERVICE));
    2730           0 :     if (!xEnum.is())
    2731           0 :         return xRet;
    2732             : 
    2733           0 :     while (xEnum->hasMoreElements() && !xRet.is())
    2734             :     {
    2735           0 :         uno::Any aAddInAny = xEnum->nextElement();
    2736           0 :         uno::Reference<uno::XInterface> xIntFac;
    2737           0 :         aAddInAny >>= xIntFac;
    2738           0 :         if (!xIntFac.is())
    2739           0 :             continue;
    2740             : 
    2741           0 :         uno::Reference<lang::XServiceInfo> xInfo(xIntFac, uno::UNO_QUERY);
    2742           0 :         if (!xInfo.is() || xInfo->getImplementationName() != aImplName)
    2743           0 :             continue;
    2744             : 
    2745             :         try
    2746             :         {
    2747             :             // #i113160# try XSingleComponentFactory in addition to (old) XSingleServiceFactory,
    2748             :             // passing the context to the component (see ScUnoAddInCollection::Initialize)
    2749             : 
    2750           0 :             uno::Reference<uno::XInterface> xInterface;
    2751             :             uno::Reference<uno::XComponentContext> xCtx(
    2752           0 :                 comphelper::getComponentContext(xManager));
    2753           0 :             uno::Reference<lang::XSingleComponentFactory> xCFac( xIntFac, uno::UNO_QUERY );
    2754           0 :             if (xCFac.is())
    2755           0 :                 xInterface = xCFac->createInstanceWithContext(xCtx);
    2756             : 
    2757           0 :             if (!xInterface.is())
    2758             :             {
    2759           0 :                 uno::Reference<lang::XSingleServiceFactory> xFac( xIntFac, uno::UNO_QUERY );
    2760           0 :                 if ( xFac.is() )
    2761           0 :                     xInterface = xFac->createInstance();
    2762             :             }
    2763             : 
    2764           0 :             uno::Reference<lang::XInitialization> xInit( xInterface, uno::UNO_QUERY );
    2765           0 :             if (xInit.is())
    2766             :             {
    2767             :                 //  initialize
    2768           0 :                 uno::Sequence<uno::Any> aSeq(4);
    2769           0 :                 uno::Any* pArray = aSeq.getArray();
    2770           0 :                 pArray[0] <<= OUString( rDesc.aParSource );
    2771           0 :                 pArray[1] <<= OUString( rDesc.aParName );
    2772           0 :                 pArray[2] <<= OUString( rDesc.aParUser );
    2773           0 :                 pArray[3] <<= OUString( rDesc.aParPass );
    2774           0 :                 xInit->initialize( aSeq );
    2775             :             }
    2776           0 :             xRet = uno::Reference<sheet::XDimensionsSupplier>( xInterface, uno::UNO_QUERY );
    2777             :         }
    2778           0 :         catch(uno::Exception&)
    2779             :         {
    2780             :         }
    2781           0 :     }
    2782             : 
    2783           0 :     return xRet;
    2784             : }
    2785             : 
    2786             : #if DEBUG_PIVOT_TABLE
    2787             : void ScDPObject::DumpCache() const
    2788             : {
    2789             :     if (!mpTableData)
    2790             :         return;
    2791             : 
    2792             :     const ScDPCache* pCache = mpTableData->GetCacheTable().getCache();
    2793             :     if (!pCache)
    2794             :         return;
    2795             : 
    2796             :     pCache->Dump();
    2797             : }
    2798             : #endif
    2799             : 
    2800         225 : ScDPCollection::SheetCaches::SheetCaches(ScDocument* pDoc) : mpDoc(pDoc) {}
    2801             : 
    2802             : namespace {
    2803             : 
    2804             : struct FindInvalidRange : public std::unary_function<ScRange, bool>
    2805             : {
    2806          24 :     bool operator() (const ScRange& r) const
    2807             :     {
    2808          24 :         return !r.IsValid();
    2809             :     }
    2810             : };
    2811             : 
    2812           3 : void setGroupItemsToCache( ScDPCache& rCache, const std::set<ScDPObject*>& rRefs )
    2813             : {
    2814             :     // Go through all referencing pivot tables, and re-fill the group dimension info.
    2815           3 :     std::set<ScDPObject*>::const_iterator itRef = rRefs.begin(), itRefEnd = rRefs.end();
    2816           7 :     for (; itRef != itRefEnd; ++itRef)
    2817             :     {
    2818           4 :         const ScDPObject* pObj = *itRef;
    2819           4 :         const ScDPSaveData* pSave = pObj->GetSaveData();
    2820           4 :         if (!pSave)
    2821           0 :             continue;
    2822             : 
    2823           4 :         const ScDPDimensionSaveData* pGroupDims = pSave->GetExistingDimensionData();
    2824           4 :         if (!pGroupDims)
    2825           4 :             continue;
    2826             : 
    2827           0 :         pGroupDims->WriteToCache(rCache);
    2828             :     }
    2829           3 : }
    2830             : 
    2831             : }
    2832             : 
    2833          16 : bool ScDPCollection::SheetCaches::hasCache(const ScRange& rRange) const
    2834             : {
    2835          16 :     RangeIndexType::const_iterator it = std::find(maRanges.begin(), maRanges.end(), rRange);
    2836          16 :     if (it == maRanges.end())
    2837           5 :         return false;
    2838             : 
    2839             :     // Already cached.
    2840          11 :     size_t nIndex = std::distance(maRanges.begin(), it);
    2841          11 :     CachesType::const_iterator itCache = maCaches.find(nIndex);
    2842          11 :     return itCache != maCaches.end();
    2843             : }
    2844             : 
    2845          81 : const ScDPCache* ScDPCollection::SheetCaches::getCache(const ScRange& rRange, const ScDPDimensionSaveData* pDimData)
    2846             : {
    2847          81 :     RangeIndexType::iterator it = std::find(maRanges.begin(), maRanges.end(), rRange);
    2848          81 :     if (it != maRanges.end())
    2849             :     {
    2850             :         // Already cached.
    2851          22 :         size_t nIndex = std::distance(maRanges.begin(), it);
    2852          22 :         CachesType::iterator itCache = maCaches.find(nIndex);
    2853          22 :         if (itCache == maCaches.end())
    2854             :         {
    2855             :             OSL_FAIL("Cache pool and index pool out-of-sync !!!");
    2856           0 :             return NULL;
    2857             :         }
    2858             : 
    2859          22 :         if (pDimData)
    2860           3 :             pDimData->WriteToCache(*itCache->second);
    2861             : 
    2862          22 :         return itCache->second;
    2863             :     }
    2864             : 
    2865             :     // Not cached.  Create a new cache.
    2866             :     SAL_WNODEPRECATED_DECLARATIONS_PUSH
    2867          59 :     ::std::auto_ptr<ScDPCache> pCache(new ScDPCache(mpDoc));
    2868             :     SAL_WNODEPRECATED_DECLARATIONS_POP
    2869          59 :     pCache->InitFromDoc(mpDoc, rRange);
    2870          59 :     if (pDimData)
    2871           1 :         pDimData->WriteToCache(*pCache);
    2872             : 
    2873             :     // Get the smallest available range index.
    2874          59 :     it = std::find_if(maRanges.begin(), maRanges.end(), FindInvalidRange());
    2875             : 
    2876          59 :     size_t nIndex = maRanges.size();
    2877          59 :     if (it == maRanges.end())
    2878             :     {
    2879             :         // All range indices are valid.  Append a new index.
    2880          39 :         maRanges.push_back(rRange);
    2881             :     }
    2882             :     else
    2883             :     {
    2884             :         // Slot with invalid range.  Re-use this slot.
    2885          20 :         *it = rRange;
    2886          20 :         nIndex = std::distance(maRanges.begin(), it);
    2887             :     }
    2888             : 
    2889          59 :     const ScDPCache* p = pCache.get();
    2890          59 :     maCaches.insert(nIndex, pCache);
    2891          59 :     return p;
    2892             : }
    2893             : 
    2894           7 : ScDPCache* ScDPCollection::SheetCaches::getExistingCache(const ScRange& rRange)
    2895             : {
    2896           7 :     RangeIndexType::iterator it = std::find(maRanges.begin(), maRanges.end(), rRange);
    2897           7 :     if (it == maRanges.end())
    2898             :         // Not cached.
    2899           0 :         return NULL;
    2900             : 
    2901             :     // Already cached.
    2902           7 :     size_t nIndex = std::distance(maRanges.begin(), it);
    2903           7 :     CachesType::iterator itCache = maCaches.find(nIndex);
    2904           7 :     if (itCache == maCaches.end())
    2905             :     {
    2906             :         OSL_FAIL("Cache pool and index pool out-of-sync !!!");
    2907           0 :         return NULL;
    2908             :     }
    2909             : 
    2910           7 :     return itCache->second;
    2911             : }
    2912             : 
    2913          22 : size_t ScDPCollection::SheetCaches::size() const
    2914             : {
    2915          22 :     return maCaches.size();
    2916             : }
    2917             : 
    2918          90 : void ScDPCollection::SheetCaches::updateReference(
    2919             :     UpdateRefMode eMode, const ScRange& r, SCsCOL nDx, SCsROW nDy, SCsTAB nDz)
    2920             : {
    2921          90 :     if (maRanges.empty())
    2922             :         // No caches.
    2923         131 :         return;
    2924             : 
    2925          49 :     RangeIndexType::iterator it = maRanges.begin(), itEnd = maRanges.end();
    2926         130 :     for (; it != itEnd; ++it)
    2927             :     {
    2928          81 :         const ScRange& rKeyRange = *it;
    2929          81 :         SCCOL nCol1 = rKeyRange.aStart.Col();
    2930          81 :         SCROW nRow1 = rKeyRange.aStart.Row();
    2931          81 :         SCTAB nTab1 = rKeyRange.aStart.Tab();
    2932          81 :         SCCOL nCol2 = rKeyRange.aEnd.Col();
    2933          81 :         SCROW nRow2 = rKeyRange.aEnd.Row();
    2934          81 :         SCTAB nTab2 = rKeyRange.aEnd.Tab();
    2935             : 
    2936             :         ScRefUpdateRes eRes = ScRefUpdate::Update(
    2937             :             mpDoc, eMode,
    2938         162 :             r.aStart.Col(), r.aStart.Row(), r.aStart.Tab(),
    2939         162 :             r.aEnd.Col(), r.aEnd.Row(), r.aEnd.Tab(), nDx, nDy, nDz,
    2940         405 :             nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
    2941             : 
    2942          81 :         if (eRes != UR_NOTHING)
    2943             :         {
    2944             :             // range updated.
    2945          33 :             ScRange aNew(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
    2946          33 :             *it = aNew;
    2947             :         }
    2948             :     }
    2949             : }
    2950             : 
    2951           3 : void ScDPCollection::SheetCaches::updateCache(const ScRange& rRange, std::set<ScDPObject*>& rRefs)
    2952             : {
    2953           3 :     RangeIndexType::iterator it = std::find(maRanges.begin(), maRanges.end(), rRange);
    2954           3 :     if (it == maRanges.end())
    2955             :     {
    2956             :         // Not cached.  Nothing to do.
    2957           0 :         rRefs.clear();
    2958           0 :         return;
    2959             :     }
    2960             : 
    2961           3 :     size_t nIndex = std::distance(maRanges.begin(), it);
    2962           3 :     CachesType::iterator itCache = maCaches.find(nIndex);
    2963           3 :     if (itCache == maCaches.end())
    2964             :     {
    2965             :         OSL_FAIL("Cache pool and index pool out-of-sync !!!");
    2966           0 :         rRefs.clear();
    2967           0 :         return;
    2968             :     }
    2969             : 
    2970           3 :     ScDPCache& rCache = *itCache->second;
    2971             : 
    2972             :     // Update the cache with new cell values. This will clear all group dimension info.
    2973           3 :     rCache.InitFromDoc(mpDoc, rRange);
    2974             : 
    2975           3 :     std::set<ScDPObject*> aRefs(rCache.GetAllReferences());
    2976           3 :     rRefs.swap(aRefs);
    2977             : 
    2978             :     // Make sure to re-populate the group dimension info.
    2979           3 :     setGroupItemsToCache(rCache, rRefs);
    2980             : }
    2981             : 
    2982          47 : bool ScDPCollection::SheetCaches::remove(const ScDPCache* p)
    2983             : {
    2984          47 :     CachesType::iterator it = maCaches.begin(), itEnd = maCaches.end();
    2985          50 :     for (; it != itEnd; ++it)
    2986             :     {
    2987          48 :         if (it->second == p)
    2988             :         {
    2989          45 :             size_t idx = it->first;
    2990          45 :             maCaches.erase(it);
    2991          45 :             maRanges[idx].SetInvalid();
    2992          45 :             return true;
    2993             :         }
    2994             :     }
    2995           2 :     return false;
    2996             : }
    2997             : 
    2998         225 : ScDPCollection::NameCaches::NameCaches(ScDocument* pDoc) : mpDoc(pDoc) {}
    2999             : 
    3000           1 : bool ScDPCollection::NameCaches::hasCache(const OUString& rName) const
    3001             : {
    3002           1 :     return maCaches.count(rName) != 0;
    3003             : }
    3004             : 
    3005           2 : const ScDPCache* ScDPCollection::NameCaches::getCache(
    3006             :     const OUString& rName, const ScRange& rRange, const ScDPDimensionSaveData* pDimData)
    3007             : {
    3008           2 :     CachesType::const_iterator itr = maCaches.find(rName);
    3009           2 :     if (itr != maCaches.end())
    3010             :         // already cached.
    3011           0 :         return itr->second;
    3012             : 
    3013             :     SAL_WNODEPRECATED_DECLARATIONS_PUSH
    3014           2 :     ::std::auto_ptr<ScDPCache> pCache(new ScDPCache(mpDoc));
    3015             :     SAL_WNODEPRECATED_DECLARATIONS_POP
    3016           2 :     pCache->InitFromDoc(mpDoc, rRange);
    3017           2 :     if (pDimData)
    3018           0 :         pDimData->WriteToCache(*pCache);
    3019             : 
    3020           2 :     const ScDPCache* p = pCache.get();
    3021           2 :     maCaches.insert(rName, pCache);
    3022           2 :     return p;
    3023             : }
    3024             : 
    3025           0 : ScDPCache* ScDPCollection::NameCaches::getExistingCache(const OUString& rName)
    3026             : {
    3027           0 :     CachesType::iterator itr = maCaches.find(rName);
    3028           0 :     return itr != maCaches.end() ? itr->second : NULL;
    3029             : }
    3030             : 
    3031           3 : size_t ScDPCollection::NameCaches::size() const
    3032             : {
    3033           3 :     return maCaches.size();
    3034             : }
    3035             : 
    3036           0 : void ScDPCollection::NameCaches::updateCache(
    3037             :     const OUString& rName, const ScRange& rRange, std::set<ScDPObject*>& rRefs)
    3038             : {
    3039           0 :     CachesType::iterator itr = maCaches.find(rName);
    3040           0 :     if (itr == maCaches.end())
    3041             :     {
    3042           0 :         rRefs.clear();
    3043           0 :         return;
    3044             :     }
    3045             : 
    3046           0 :     ScDPCache& rCache = *itr->second;
    3047             :     // Update the cache with new cell values. This will clear all group dimension info.
    3048           0 :     rCache.InitFromDoc(mpDoc, rRange);
    3049             : 
    3050           0 :     std::set<ScDPObject*> aRefs(rCache.GetAllReferences());
    3051           0 :     rRefs.swap(aRefs);
    3052             : 
    3053             :     // Make sure to re-populate the group dimension info.
    3054           0 :     setGroupItemsToCache(rCache, rRefs);
    3055             : }
    3056             : 
    3057           2 : bool ScDPCollection::NameCaches::remove(const ScDPCache* p)
    3058             : {
    3059           2 :     CachesType::iterator it = maCaches.begin(), itEnd = maCaches.end();
    3060           2 :     for (; it != itEnd; ++it)
    3061             :     {
    3062           2 :         if (it->second == p)
    3063             :         {
    3064           2 :             maCaches.erase(it);
    3065           2 :             return true;
    3066             :         }
    3067             :     }
    3068           0 :     return false;
    3069             : }
    3070             : 
    3071           0 : ScDPCollection::DBType::DBType(sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand) :
    3072           0 :     mnSdbType(nSdbType), maDBName(rDBName), maCommand(rCommand) {}
    3073             : 
    3074           0 : bool ScDPCollection::DBType::less::operator() (const DBType& left, const DBType& right) const
    3075             : {
    3076           0 :     return left < right;
    3077             : }
    3078             : 
    3079         225 : ScDPCollection::DBCaches::DBCaches(ScDocument* pDoc) : mpDoc(pDoc) {}
    3080             : 
    3081           0 : bool ScDPCollection::DBCaches::hasCache(sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand) const
    3082             : {
    3083           0 :     DBType aType(nSdbType, rDBName, rCommand);
    3084           0 :     CachesType::const_iterator itr = maCaches.find(aType);
    3085           0 :     return itr != maCaches.end();
    3086             : }
    3087             : 
    3088           0 : const ScDPCache* ScDPCollection::DBCaches::getCache(
    3089             :     sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand,
    3090             :     const ScDPDimensionSaveData* pDimData)
    3091             : {
    3092           0 :     DBType aType(nSdbType, rDBName, rCommand);
    3093           0 :     CachesType::const_iterator itr = maCaches.find(aType);
    3094           0 :     if (itr != maCaches.end())
    3095             :         // already cached.
    3096           0 :         return itr->second;
    3097             : 
    3098           0 :     uno::Reference<sdbc::XRowSet> xRowSet = createRowSet(nSdbType, rDBName, rCommand);
    3099           0 :     if (!xRowSet.is())
    3100           0 :         return NULL;
    3101             : 
    3102             :     SAL_WNODEPRECATED_DECLARATIONS_PUSH
    3103           0 :     ::std::auto_ptr<ScDPCache> pCache(new ScDPCache(mpDoc));
    3104             :     SAL_WNODEPRECATED_DECLARATIONS_POP
    3105           0 :     SvNumberFormatter aFormat( comphelper::getProcessComponentContext(), ScGlobal::eLnge);
    3106           0 :     DBConnector aDB(*pCache, xRowSet, *aFormat.GetNullDate());
    3107           0 :     if (!aDB.isValid())
    3108           0 :         return NULL;
    3109             : 
    3110           0 :     if (!pCache->InitFromDataBase(aDB))
    3111             :     {
    3112             :         // initialization failed.
    3113           0 :         comphelper::disposeComponent(xRowSet);
    3114           0 :         return NULL;
    3115             :     }
    3116             : 
    3117           0 :     if (pDimData)
    3118           0 :         pDimData->WriteToCache(*pCache);
    3119             : 
    3120           0 :     ::comphelper::disposeComponent(xRowSet);
    3121           0 :     const ScDPCache* p = pCache.get();
    3122           0 :     maCaches.insert(aType, pCache);
    3123           0 :     return p;
    3124             : }
    3125             : 
    3126           0 : ScDPCache* ScDPCollection::DBCaches::getExistingCache(
    3127             :     sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand)
    3128             : {
    3129           0 :     DBType aType(nSdbType, rDBName, rCommand);
    3130           0 :     CachesType::iterator itr = maCaches.find(aType);
    3131           0 :     return itr != maCaches.end() ? itr->second : NULL;
    3132             : }
    3133             : 
    3134           0 : uno::Reference<sdbc::XRowSet> ScDPCollection::DBCaches::createRowSet(
    3135             :     sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand)
    3136             : {
    3137           0 :     uno::Reference<sdbc::XRowSet> xRowSet;
    3138             :     try
    3139             :     {
    3140           0 :         xRowSet = uno::Reference<sdbc::XRowSet>(
    3141           0 :             comphelper::getProcessServiceFactory()->createInstance(
    3142           0 :                 OUString(SC_SERVICE_ROWSET)),
    3143           0 :             UNO_QUERY);
    3144             : 
    3145           0 :         uno::Reference<beans::XPropertySet> xRowProp(xRowSet, UNO_QUERY);
    3146             :         OSL_ENSURE( xRowProp.is(), "can't get RowSet" );
    3147           0 :         if (!xRowProp.is())
    3148             :         {
    3149           0 :             xRowSet.set(NULL);
    3150           0 :             return xRowSet;
    3151             :         }
    3152             : 
    3153             : 
    3154             :         //  set source parameters
    3155             : 
    3156           0 :         uno::Any aAny;
    3157           0 :         aAny <<= rDBName;
    3158           0 :         xRowProp->setPropertyValue(
    3159           0 :             OUString(SC_DBPROP_DATASOURCENAME), aAny );
    3160             : 
    3161           0 :         aAny <<= rCommand;
    3162           0 :         xRowProp->setPropertyValue(
    3163           0 :             OUString(SC_DBPROP_COMMAND), aAny );
    3164             : 
    3165           0 :         aAny <<= nSdbType;
    3166           0 :         xRowProp->setPropertyValue(
    3167           0 :             OUString(SC_DBPROP_COMMANDTYPE), aAny );
    3168             : 
    3169           0 :         uno::Reference<sdb::XCompletedExecution> xExecute( xRowSet, uno::UNO_QUERY );
    3170           0 :         if ( xExecute.is() )
    3171             :         {
    3172             :             uno::Reference<task::XInteractionHandler> xHandler(
    3173             :                 task::InteractionHandler::createWithParent(comphelper::getProcessComponentContext(), 0),
    3174           0 :                 uno::UNO_QUERY_THROW);
    3175           0 :             xExecute->executeWithCompletion( xHandler );
    3176             :         }
    3177             :         else
    3178           0 :             xRowSet->execute();
    3179             : 
    3180           0 :         return xRowSet;
    3181             :     }
    3182           0 :     catch ( const sdbc::SQLException& rError )
    3183             :     {
    3184             :         //! store error message
    3185           0 :         InfoBox aInfoBox( 0, OUString(rError.Message) );
    3186           0 :         aInfoBox.Execute();
    3187             :     }
    3188           0 :     catch ( uno::Exception& )
    3189             :     {
    3190             :         OSL_FAIL("Unexpected exception in database");
    3191             :     }
    3192             : 
    3193           0 :     xRowSet.set(NULL);
    3194           0 :     return xRowSet;
    3195             : }
    3196             : 
    3197           0 : void ScDPCollection::DBCaches::updateCache(
    3198             :     sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand,
    3199             :     std::set<ScDPObject*>& rRefs)
    3200             : {
    3201           0 :     DBType aType(nSdbType, rDBName, rCommand);
    3202           0 :     CachesType::iterator it = maCaches.find(aType);
    3203           0 :     if (it == maCaches.end())
    3204             :     {
    3205             :         // not cached.
    3206           0 :         rRefs.clear();
    3207           0 :         return;
    3208             :     }
    3209             : 
    3210           0 :     ScDPCache& rCache = *it->second;
    3211             : 
    3212           0 :     uno::Reference<sdbc::XRowSet> xRowSet = createRowSet(nSdbType, rDBName, rCommand);
    3213           0 :     if (!xRowSet.is())
    3214             :     {
    3215           0 :         rRefs.clear();
    3216           0 :         return;
    3217             :     }
    3218             : 
    3219           0 :     SvNumberFormatter aFormat( comphelper::getProcessComponentContext(), ScGlobal::eLnge);
    3220           0 :     DBConnector aDB(rCache, xRowSet, *aFormat.GetNullDate());
    3221           0 :     if (!aDB.isValid())
    3222           0 :         return;
    3223             : 
    3224           0 :     if (!rCache.InitFromDataBase(aDB))
    3225             :     {
    3226             :         // initialization failed.
    3227           0 :         rRefs.clear();
    3228           0 :         comphelper::disposeComponent(xRowSet);
    3229           0 :         return;
    3230             :     }
    3231             : 
    3232           0 :     comphelper::disposeComponent(xRowSet);
    3233           0 :     std::set<ScDPObject*> aRefs(rCache.GetAllReferences());
    3234           0 :     aRefs.swap(rRefs);
    3235             : 
    3236             :     // Make sure to re-populate the group dimension info.
    3237           0 :     setGroupItemsToCache(rCache, rRefs);
    3238             : }
    3239             : 
    3240           0 : bool ScDPCollection::DBCaches::remove(const ScDPCache* p)
    3241             : {
    3242           0 :     CachesType::iterator it = maCaches.begin(), itEnd = maCaches.end();
    3243           0 :     for (; it != itEnd; ++it)
    3244             :     {
    3245           0 :         if (it->second == p)
    3246             :         {
    3247           0 :             maCaches.erase(it);
    3248           0 :             return true;
    3249             :         }
    3250             :     }
    3251           0 :     return false;
    3252             : }
    3253             : 
    3254         176 : ScDPCollection::ScDPCollection(ScDocument* pDocument) :
    3255             :     mpDoc( pDocument ),
    3256             :     maSheetCaches(pDocument),
    3257             :     maNameCaches(pDocument),
    3258         176 :     maDBCaches(pDocument)
    3259             : {
    3260         176 : }
    3261             : 
    3262          49 : ScDPCollection::ScDPCollection(const ScDPCollection& r) :
    3263             :     mpDoc(r.mpDoc),
    3264             :     maSheetCaches(r.mpDoc),
    3265             :     maNameCaches(r.mpDoc),
    3266          49 :     maDBCaches(r.mpDoc)
    3267             : {
    3268          49 : }
    3269             : 
    3270         384 : ScDPCollection::~ScDPCollection()
    3271             : {
    3272         192 :     maTables.clear();
    3273         192 : }
    3274             : 
    3275             : namespace {
    3276             : 
    3277             : /**
    3278             :  * Unary predicate to match DP objects by the table ID.
    3279             :  */
    3280             : class MatchByTable : public unary_function<ScDPObject, bool>
    3281             : {
    3282             :     SCTAB mnTab;
    3283             : public:
    3284          39 :     MatchByTable(SCTAB nTab) : mnTab(nTab) {}
    3285             : 
    3286          32 :     bool operator() (const ScDPObject& rObj) const
    3287             :     {
    3288          32 :         return rObj.GetOutRange().aStart.Tab() == mnTab;
    3289             :     }
    3290             : };
    3291             : 
    3292             : }
    3293             : 
    3294           5 : sal_uLong ScDPCollection::ReloadCache(ScDPObject* pDPObj, std::set<ScDPObject*>& rRefs)
    3295             : {
    3296           5 :     if (!pDPObj)
    3297           0 :         return STR_ERR_DATAPILOTSOURCE;
    3298             : 
    3299           5 :     if (pDPObj->IsSheetData())
    3300             :     {
    3301             :         // data source is internal sheet.
    3302           5 :         const ScSheetSourceDesc* pDesc = pDPObj->GetSheetDesc();
    3303           5 :         if (!pDesc)
    3304           0 :             return STR_ERR_DATAPILOTSOURCE;
    3305             : 
    3306           5 :         sal_uLong nErrId = pDesc->CheckSourceRange();
    3307           5 :         if (nErrId)
    3308           0 :             return nErrId;
    3309             : 
    3310           5 :         if (pDesc->HasRangeName())
    3311             :         {
    3312             :             // cache by named range
    3313           0 :             ScDPCollection::NameCaches& rCaches = GetNameCaches();
    3314           0 :             if (rCaches.hasCache(pDesc->GetRangeName()))
    3315           0 :                 rCaches.updateCache(pDesc->GetRangeName(), pDesc->GetSourceRange(), rRefs);
    3316             :             else
    3317             :             {
    3318             :                 // Not cached yet.  Collect all tables that use this named
    3319             :                 // range as data source.
    3320           0 :                 GetAllTables(pDesc->GetRangeName(), rRefs);
    3321             :             }
    3322             :         }
    3323             :         else
    3324             :         {
    3325             :             // cache by cell range
    3326           5 :             ScDPCollection::SheetCaches& rCaches = GetSheetCaches();
    3327           5 :             if (rCaches.hasCache(pDesc->GetSourceRange()))
    3328           3 :                 rCaches.updateCache(pDesc->GetSourceRange(), rRefs);
    3329             :             else
    3330             :             {
    3331             :                 // Not cached yet.  Collect all tables that use this range as
    3332             :                 // data source.
    3333           2 :                 GetAllTables(pDesc->GetSourceRange(), rRefs);
    3334             :             }
    3335             :         }
    3336             :     }
    3337           0 :     else if (pDPObj->IsImportData())
    3338             :     {
    3339             :         // data source is external database.
    3340           0 :         const ScImportSourceDesc* pDesc = pDPObj->GetImportSourceDesc();
    3341           0 :         if (!pDesc)
    3342           0 :             return STR_ERR_DATAPILOTSOURCE;
    3343             : 
    3344           0 :         ScDPCollection::DBCaches& rCaches = GetDBCaches();
    3345           0 :         if (rCaches.hasCache(pDesc->GetCommandType(), pDesc->aDBName, pDesc->aObject))
    3346             :             rCaches.updateCache(
    3347           0 :                 pDesc->GetCommandType(), pDesc->aDBName, pDesc->aObject, rRefs);
    3348             :         else
    3349             :         {
    3350             :             // Not cached yet.  Collect all tables that use this range as
    3351             :             // data source.
    3352           0 :             GetAllTables(pDesc->GetCommandType(), pDesc->aDBName, pDesc->aObject, rRefs);
    3353             :         }
    3354             :     }
    3355           5 :     return 0;
    3356             : }
    3357             : 
    3358           8 : bool ScDPCollection::ReloadGroupsInCache(ScDPObject* pDPObj, std::set<ScDPObject*>& rRefs)
    3359             : {
    3360           8 :     if (!pDPObj)
    3361           0 :         return false;
    3362             : 
    3363           8 :     const ScDPSaveData* pSaveData = pDPObj->GetSaveData();
    3364           8 :     if (!pSaveData)
    3365           0 :         return false;
    3366             : 
    3367             :     // Note: Unlike reloading cache, when modifying the group dimensions the
    3368             :     // cache may not have all its references when this method is called.
    3369             :     // Therefore, we need to always call GetAllTables to get its correct
    3370             :     // references even when the cache exists.  This may become a non-issue
    3371             :     // if/when we implement loading and saving of pivot caches.
    3372             : 
    3373           8 :     ScDPCache* pCache = NULL;
    3374             : 
    3375           8 :     if (pDPObj->IsSheetData())
    3376             :     {
    3377             :         // data source is internal sheet.
    3378           8 :         const ScSheetSourceDesc* pDesc = pDPObj->GetSheetDesc();
    3379           8 :         if (!pDesc)
    3380           0 :             return false;
    3381             : 
    3382           8 :         if (pDesc->HasRangeName())
    3383             :         {
    3384             :             // cache by named range
    3385           0 :             ScDPCollection::NameCaches& rCaches = GetNameCaches();
    3386           0 :             if (rCaches.hasCache(pDesc->GetRangeName()))
    3387           0 :                 pCache = rCaches.getExistingCache(pDesc->GetRangeName());
    3388             :             else
    3389             :             {
    3390             :                 // Not cached yet.  Cache the source dimensions.  Groups will
    3391             :                 // be added below.
    3392             :                 pCache = const_cast<ScDPCache*>(
    3393           0 :                     rCaches.getCache(pDesc->GetRangeName(), pDesc->GetSourceRange(), NULL));
    3394             :             }
    3395           0 :             GetAllTables(pDesc->GetRangeName(), rRefs);
    3396             :         }
    3397             :         else
    3398             :         {
    3399             :             // cache by cell range
    3400           8 :             ScDPCollection::SheetCaches& rCaches = GetSheetCaches();
    3401           8 :             if (rCaches.hasCache(pDesc->GetSourceRange()))
    3402           6 :                 pCache = rCaches.getExistingCache(pDesc->GetSourceRange());
    3403             :             else
    3404             :             {
    3405             :                 // Not cached yet.  Cache the source dimensions.  Groups will
    3406             :                 // be added below.
    3407             :                 pCache = const_cast<ScDPCache*>(
    3408           2 :                     rCaches.getCache(pDesc->GetSourceRange(), NULL));
    3409             :             }
    3410           8 :             GetAllTables(pDesc->GetSourceRange(), rRefs);
    3411             :         }
    3412             :     }
    3413           0 :     else if (pDPObj->IsImportData())
    3414             :     {
    3415             :         // data source is external database.
    3416           0 :         const ScImportSourceDesc* pDesc = pDPObj->GetImportSourceDesc();
    3417           0 :         if (!pDesc)
    3418           0 :             return false;
    3419             : 
    3420           0 :         ScDPCollection::DBCaches& rCaches = GetDBCaches();
    3421           0 :         if (rCaches.hasCache(pDesc->GetCommandType(), pDesc->aDBName, pDesc->aObject))
    3422             :             pCache = rCaches.getExistingCache(
    3423           0 :                 pDesc->GetCommandType(), pDesc->aDBName, pDesc->aObject);
    3424             :         else
    3425             :         {
    3426             :             // Not cached yet.  Cache the source dimensions.  Groups will
    3427             :             // be added below.
    3428             :             pCache = const_cast<ScDPCache*>(
    3429           0 :                 rCaches.getCache(pDesc->GetCommandType(), pDesc->aDBName, pDesc->aObject, NULL));
    3430             :         }
    3431           0 :         GetAllTables(pDesc->GetCommandType(), pDesc->aDBName, pDesc->aObject, rRefs);
    3432             :     }
    3433             : 
    3434           8 :     if (!pCache)
    3435           0 :         return false;
    3436             : 
    3437             :     // Clear the existing group data from the cache, and rebuild it from the
    3438             :     // dimension data.
    3439           8 :     pCache->ClearGroupFields();
    3440           8 :     const ScDPDimensionSaveData* pDimData = pSaveData->GetExistingDimensionData();
    3441           8 :     if (pDimData)
    3442           8 :         pDimData->WriteToCache(*pCache);
    3443           8 :     return true;
    3444             : }
    3445             : 
    3446          39 : void ScDPCollection::DeleteOnTab( SCTAB nTab )
    3447             : {
    3448          39 :     maTables.erase_if(MatchByTable(nTab));
    3449          39 : }
    3450             : 
    3451          90 : void ScDPCollection::UpdateReference( UpdateRefMode eUpdateRefMode,
    3452             :                                          const ScRange& r, SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
    3453             : {
    3454          90 :     TablesType::iterator itr = maTables.begin(), itrEnd = maTables.end();
    3455         156 :     for (; itr != itrEnd; ++itr)
    3456          66 :         itr->UpdateReference(eUpdateRefMode, r, nDx, nDy, nDz);
    3457             : 
    3458             :     // Update the source ranges of the caches.
    3459          90 :     maSheetCaches.updateReference(eUpdateRefMode, r, nDx, nDy, nDz);
    3460          90 : }
    3461             : 
    3462           0 : void ScDPCollection::CopyToTab( SCTAB nOld, SCTAB nNew )
    3463             : {
    3464           0 :     TablesType aAdded;
    3465           0 :     TablesType::const_iterator it = maTables.begin(), itEnd = maTables.end();
    3466           0 :     for (; it != itEnd; ++it)
    3467             :     {
    3468           0 :         const ScDPObject& rObj = *it;
    3469           0 :         ScRange aOutRange = rObj.GetOutRange();
    3470           0 :         if (aOutRange.aStart.Tab() != nOld)
    3471           0 :             continue;
    3472             : 
    3473           0 :         ScAddress& s = aOutRange.aStart;
    3474           0 :         ScAddress& e = aOutRange.aEnd;
    3475           0 :         s.SetTab(nNew);
    3476           0 :         e.SetTab(nNew);
    3477           0 :         std::auto_ptr<ScDPObject> pNew(new ScDPObject(rObj));
    3478           0 :         pNew->SetOutRange(aOutRange);
    3479           0 :         mpDoc->ApplyFlagsTab(s.Col(), s.Row(), e.Col(), e.Row(), s.Tab(), SC_MF_DP_TABLE);
    3480           0 :         aAdded.push_back(pNew);
    3481           0 :     }
    3482             : 
    3483           0 :     maTables.transfer(maTables.end(), aAdded.begin(), aAdded.end(), aAdded);
    3484           0 : }
    3485             : 
    3486          49 : bool ScDPCollection::RefsEqual( const ScDPCollection& r ) const
    3487             : {
    3488          49 :     if (maTables.size() != r.maTables.size())
    3489          16 :         return false;
    3490             : 
    3491          33 :     TablesType::const_iterator itr = maTables.begin(), itr2 = r.maTables.begin(), itrEnd = maTables.end();
    3492          33 :     for (; itr != itrEnd; ++itr, ++itr2)
    3493           0 :         if (!itr->RefsEqual(*itr2))
    3494           0 :             return false;
    3495             : 
    3496          33 :     return true;
    3497             : }
    3498             : 
    3499           0 : void ScDPCollection::WriteRefsTo( ScDPCollection& r ) const
    3500             : {
    3501           0 :     if ( maTables.size() == r.maTables.size() )
    3502             :     {
    3503             :         //! assert equal names?
    3504           0 :         TablesType::const_iterator itr = maTables.begin(), itrEnd = maTables.end();
    3505           0 :         TablesType::iterator itr2 = r.maTables.begin();
    3506           0 :         for (; itr != itrEnd; ++itr, ++itr2)
    3507           0 :             itr->WriteRefsTo(*itr2);
    3508             :     }
    3509             :     else
    3510             :     {
    3511             :         // #i8180# If data pilot tables were deleted with their sheet,
    3512             :         // this collection contains extra entries that must be restored.
    3513             :         // Matching objects are found by their names.
    3514           0 :         size_t nSrcSize = maTables.size();
    3515           0 :         size_t nDestSize = r.maTables.size();
    3516             :         OSL_ENSURE( nSrcSize >= nDestSize, "WriteRefsTo: missing entries in document" );
    3517           0 :         for (size_t nSrcPos = 0; nSrcPos < nSrcSize; ++nSrcPos)
    3518             :         {
    3519           0 :             const ScDPObject& rSrcObj = maTables[nSrcPos];
    3520           0 :             const OUString& aName = rSrcObj.GetName();
    3521           0 :             bool bFound = false;
    3522           0 :             for (size_t nDestPos = 0; nDestPos < nDestSize && !bFound; ++nDestPos)
    3523             :             {
    3524           0 :                 ScDPObject& rDestObj = r.maTables[nDestPos];
    3525           0 :                 if (rDestObj.GetName() == aName)
    3526             :                 {
    3527           0 :                     rSrcObj.WriteRefsTo(rDestObj);     // found object, copy refs
    3528           0 :                     bFound = true;
    3529             :                 }
    3530             :             }
    3531             : 
    3532           0 :             if (!bFound)
    3533             :             {
    3534             :                 // none found, re-insert deleted object (see ScUndoDataPilot::Undo)
    3535             : 
    3536           0 :                 ScDPObject* pDestObj = new ScDPObject(rSrcObj);
    3537           0 :                 r.InsertNewTable(pDestObj);
    3538             :             }
    3539             :         }
    3540             :         OSL_ENSURE( maTables.size() == r.maTables.size(), "WriteRefsTo: couldn't restore all entries" );
    3541             :     }
    3542           0 : }
    3543             : 
    3544        1313 : size_t ScDPCollection::GetCount() const
    3545             : {
    3546        1313 :     return maTables.size();
    3547             : }
    3548             : 
    3549        1335 : ScDPObject* ScDPCollection::operator [](size_t nIndex)
    3550             : {
    3551        1335 :     return &maTables[nIndex];
    3552             : }
    3553             : 
    3554           0 : const ScDPObject* ScDPCollection::operator [](size_t nIndex) const
    3555             : {
    3556           0 :     return &maTables[nIndex];
    3557             : }
    3558             : 
    3559          25 : const ScDPObject* ScDPCollection::GetByName(const OUString& rName) const
    3560             : {
    3561          25 :     TablesType::const_iterator itr = maTables.begin(), itrEnd = maTables.end();
    3562          29 :     for (; itr != itrEnd; ++itr)
    3563           4 :         if (itr->GetName() == rName)
    3564           0 :             return &(*itr);
    3565             : 
    3566          25 :     return NULL;
    3567             : }
    3568             : 
    3569          18 : OUString ScDPCollection::CreateNewName( sal_uInt16 nMin ) const
    3570             : {
    3571          18 :     OUString aBase("DataPilot");
    3572             : 
    3573          18 :     size_t n = maTables.size();
    3574          18 :     for (size_t nAdd = 0; nAdd <= n; ++nAdd)   //  nCount+1 tries
    3575             :     {
    3576          18 :         OUStringBuffer aBuf;
    3577          18 :         aBuf.append(aBase);
    3578          18 :         aBuf.append(static_cast<sal_Int32>(nMin + nAdd));
    3579          18 :         OUString aNewName = aBuf.makeStringAndClear();
    3580          18 :         bool bFound = false;
    3581          18 :         TablesType::const_iterator itr = maTables.begin(), itrEnd = maTables.end();
    3582          36 :         for (; itr != itrEnd; ++itr)
    3583             :         {
    3584          18 :             if (itr->GetName() == aNewName)
    3585             :             {
    3586           0 :                 bFound = true;
    3587           0 :                 break;
    3588             :             }
    3589             :         }
    3590          18 :         if (!bFound)
    3591          18 :             return aNewName;            // found unused Name
    3592           0 :     }
    3593           0 :     return OUString();                    // should not happen
    3594             : }
    3595             : 
    3596          21 : void ScDPCollection::FreeTable(ScDPObject* pDPObj)
    3597             : {
    3598          21 :     const ScRange& rOutRange = pDPObj->GetOutRange();
    3599          21 :     const ScAddress& s = rOutRange.aStart;
    3600          21 :     const ScAddress& e = rOutRange.aEnd;
    3601          21 :     mpDoc->RemoveFlagsTab(s.Col(), s.Row(), e.Col(), e.Row(), s.Tab(), SC_MF_DP_TABLE);
    3602          21 :     TablesType::iterator itr = maTables.begin(), itrEnd = maTables.end();
    3603          22 :     for (; itr != itrEnd; ++itr)
    3604             :     {
    3605          22 :         ScDPObject* p = &(*itr);
    3606          22 :         if (p == pDPObj)
    3607             :         {
    3608          21 :             maTables.erase(itr);
    3609          21 :             break;
    3610             :         }
    3611             :     }
    3612          21 : }
    3613             : 
    3614          45 : bool ScDPCollection::InsertNewTable(ScDPObject* pDPObj)
    3615             : {
    3616          45 :     const ScRange& rOutRange = pDPObj->GetOutRange();
    3617          45 :     const ScAddress& s = rOutRange.aStart;
    3618          45 :     const ScAddress& e = rOutRange.aEnd;
    3619          45 :     mpDoc->ApplyFlagsTab(s.Col(), s.Row(), e.Col(), e.Row(), s.Tab(), SC_MF_DP_TABLE);
    3620             : 
    3621          45 :     maTables.push_back(pDPObj);
    3622          45 :     return true;
    3623             : }
    3624             : 
    3625         117 : ScDPCollection::SheetCaches& ScDPCollection::GetSheetCaches()
    3626             : {
    3627         117 :     return maSheetCaches;
    3628             : }
    3629             : 
    3630           6 : ScDPCollection::NameCaches& ScDPCollection::GetNameCaches()
    3631             : {
    3632           6 :     return maNameCaches;
    3633             : }
    3634             : 
    3635           0 : ScDPCollection::DBCaches& ScDPCollection::GetDBCaches()
    3636             : {
    3637           0 :     return maDBCaches;
    3638             : }
    3639             : 
    3640          66 : ScRangeList ScDPCollection::GetAllTableRanges( SCTAB nTab ) const
    3641             : {
    3642          66 :     return std::for_each(maTables.begin(), maTables.end(), AccumulateOutputRanges(nTab)).getRanges();
    3643             : }
    3644             : 
    3645           0 : bool ScDPCollection::IntersectsTableByColumns( SCCOL nCol1, SCCOL nCol2, SCROW nRow, SCTAB nTab ) const
    3646             : {
    3647             :     return std::find_if(
    3648           0 :         maTables.begin(), maTables.end(), FindIntersetingTableByColumns(nCol1, nCol2, nRow, nTab)) != maTables.end();
    3649             : }
    3650             : 
    3651           0 : bool ScDPCollection::IntersectsTableByRows( SCCOL nCol, SCROW nRow1, SCROW nRow2, SCTAB nTab ) const
    3652             : {
    3653             :     return std::find_if(
    3654           0 :         maTables.begin(), maTables.end(), FindIntersectingTableByRows(nCol, nRow1, nRow2, nTab)) != maTables.end();
    3655             : }
    3656             : 
    3657           0 : bool ScDPCollection::HasTable( const ScRange& rRange ) const
    3658             : {
    3659             :     return std::find_if(
    3660           0 :         maTables.begin(), maTables.end(), FindIntersectingTable(rRange)) != maTables.end();
    3661             : }
    3662             : 
    3663             : #if DEBUG_PIVOT_TABLE
    3664             : 
    3665             : namespace {
    3666             : 
    3667             : struct DumpTable : std::unary_function<ScDPObject, void>
    3668             : {
    3669             :     void operator() (const ScDPObject& rObj) const
    3670             :     {
    3671             :         cout << "-- '" << rObj.GetName() << "'" << endl;
    3672             :         ScDPSaveData* pSaveData = rObj.GetSaveData();
    3673             :         if (!pSaveData)
    3674             :             return;
    3675             : 
    3676             :         pSaveData->Dump();
    3677             : 
    3678             :         cout << endl; // blank line
    3679             :     }
    3680             : };
    3681             : 
    3682             : }
    3683             : 
    3684             : void ScDPCollection::DumpTables() const
    3685             : {
    3686             :     std::for_each(maTables.begin(), maTables.end(), DumpTable());
    3687             : }
    3688             : 
    3689             : #endif
    3690             : 
    3691          47 : void ScDPCollection::RemoveCache(const ScDPCache* pCache)
    3692             : {
    3693          47 :     if (maSheetCaches.remove(pCache))
    3694             :         // sheet cache removed.
    3695          45 :         return;
    3696             : 
    3697           2 :     if (maNameCaches.remove(pCache))
    3698             :         // named range cache removed.
    3699           2 :         return;
    3700             : 
    3701           0 :     if (maDBCaches.remove(pCache))
    3702             :         // database cache removed.
    3703           0 :         return;
    3704             : }
    3705             : 
    3706          10 : void ScDPCollection::GetAllTables(const ScRange& rSrcRange, std::set<ScDPObject*>& rRefs) const
    3707             : {
    3708          10 :     std::set<ScDPObject*> aRefs;
    3709          10 :     TablesType::const_iterator it = maTables.begin(), itEnd = maTables.end();
    3710          21 :     for (; it != itEnd; ++it)
    3711             :     {
    3712          11 :         const ScDPObject& rObj = *it;
    3713          11 :         if (!rObj.IsSheetData())
    3714             :             // Source is not a sheet range.
    3715           0 :             continue;
    3716             : 
    3717          11 :         const ScSheetSourceDesc* pDesc = rObj.GetSheetDesc();
    3718          11 :         if (!pDesc)
    3719           0 :             continue;
    3720             : 
    3721          11 :         if (pDesc->HasRangeName())
    3722             :             // This table has a range name as its source.
    3723           0 :             continue;
    3724             : 
    3725          11 :         if (pDesc->GetSourceRange() != rSrcRange)
    3726             :             // Different source range.
    3727           0 :             continue;
    3728             : 
    3729          11 :         aRefs.insert(const_cast<ScDPObject*>(&rObj));
    3730             :     }
    3731             : 
    3732          10 :     rRefs.swap(aRefs);
    3733          10 : }
    3734             : 
    3735           0 : void ScDPCollection::GetAllTables(const OUString& rSrcName, std::set<ScDPObject*>& rRefs) const
    3736             : {
    3737           0 :     std::set<ScDPObject*> aRefs;
    3738           0 :     TablesType::const_iterator it = maTables.begin(), itEnd = maTables.end();
    3739           0 :     for (; it != itEnd; ++it)
    3740             :     {
    3741           0 :         const ScDPObject& rObj = *it;
    3742           0 :         if (!rObj.IsSheetData())
    3743             :             // Source is not a sheet range.
    3744           0 :             continue;
    3745             : 
    3746           0 :         const ScSheetSourceDesc* pDesc = rObj.GetSheetDesc();
    3747           0 :         if (!pDesc)
    3748           0 :             continue;
    3749             : 
    3750           0 :         if (!pDesc->HasRangeName())
    3751             :             // This table probably has a sheet range as its source.
    3752           0 :             continue;
    3753             : 
    3754           0 :         if (pDesc->GetRangeName() != rSrcName)
    3755             :             // Different source name.
    3756           0 :             continue;
    3757             : 
    3758           0 :         aRefs.insert(const_cast<ScDPObject*>(&rObj));
    3759             :     }
    3760             : 
    3761           0 :     rRefs.swap(aRefs);
    3762           0 : }
    3763             : 
    3764           0 : void ScDPCollection::GetAllTables(
    3765             :     sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand,
    3766             :     std::set<ScDPObject*>& rRefs) const
    3767             : {
    3768           0 :     std::set<ScDPObject*> aRefs;
    3769           0 :     TablesType::const_iterator it = maTables.begin(), itEnd = maTables.end();
    3770           0 :     for (; it != itEnd; ++it)
    3771             :     {
    3772           0 :         const ScDPObject& rObj = *it;
    3773           0 :         if (!rObj.IsImportData())
    3774             :             // Source data is not a database.
    3775           0 :             continue;
    3776             : 
    3777           0 :         const ScImportSourceDesc* pDesc = rObj.GetImportSourceDesc();
    3778           0 :         if (!pDesc)
    3779           0 :             continue;
    3780             : 
    3781           0 :         if (!pDesc->aDBName.equals(rDBName) || !pDesc->aObject.equals(rCommand) || pDesc->GetCommandType() != nSdbType)
    3782             :             // Different database source.
    3783           0 :             continue;
    3784             : 
    3785           0 :         aRefs.insert(const_cast<ScDPObject*>(&rObj));
    3786             :     }
    3787             : 
    3788           0 :     rRefs.swap(aRefs);
    3789           0 : }
    3790             : 
    3791           0 : bool operator<(const ScDPCollection::DBType& left, const ScDPCollection::DBType& right)
    3792             : {
    3793           0 :     if (left.mnSdbType != right.mnSdbType)
    3794           0 :         return left.mnSdbType < right.mnSdbType;
    3795             : 
    3796           0 :     if (!left.maDBName.equals(right.maDBName))
    3797           0 :         return left.maDBName < right.maDBName;
    3798             : 
    3799           0 :     return left.maCommand < right.maCommand;
    3800         102 : }
    3801             : 
    3802             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10