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

Generated by: LCOV version 1.10