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

Generated by: LCOV version 1.10