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

Generated by: LCOV version 1.10