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

Generated by: LCOV version 1.10