LCOV - code coverage report
Current view: top level - sc/source/filter/excel - xepivot.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 1 921 0.1 %
Date: 2012-08-25 Functions: 2 119 1.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 2 1240 0.2 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  *
       4                 :            :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5                 :            :  *
       6                 :            :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       7                 :            :  *
       8                 :            :  * OpenOffice.org - a multi-platform office productivity suite
       9                 :            :  *
      10                 :            :  * This file is part of OpenOffice.org.
      11                 :            :  *
      12                 :            :  * OpenOffice.org is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU Lesser General Public License version 3
      14                 :            :  * only, as published by the Free Software Foundation.
      15                 :            :  *
      16                 :            :  * OpenOffice.org is distributed in the hope that it will be useful,
      17                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19                 :            :  * GNU Lesser General Public License version 3 for more details
      20                 :            :  * (a copy is included in the LICENSE file that accompanied this code).
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU Lesser General Public License
      23                 :            :  * version 3 along with OpenOffice.org.  If not, see
      24                 :            :  * <http://www.openoffice.org/license.html>
      25                 :            :  * for a copy of the LGPLv3 License.
      26                 :            :  *
      27                 :            :  ************************************************************************/
      28                 :            : 
      29                 :            : #include "xepivot.hxx"
      30                 :            : #include <com/sun/star/sheet/DataPilotFieldSortInfo.hpp>
      31                 :            : #include <com/sun/star/sheet/DataPilotFieldAutoShowInfo.hpp>
      32                 :            : #include <com/sun/star/sheet/DataPilotFieldLayoutInfo.hpp>
      33                 :            : #include <com/sun/star/sheet/DataPilotFieldReference.hpp>
      34                 :            : #include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
      35                 :            : 
      36                 :            : #include <algorithm>
      37                 :            : #include <math.h>
      38                 :            : 
      39                 :            : #include <rtl/math.hxx>
      40                 :            : #include <tools/date.hxx>
      41                 :            : #include <svl/zformat.hxx>
      42                 :            : #include <sot/storage.hxx>
      43                 :            : #include "document.hxx"
      44                 :            : #include "dpobject.hxx"
      45                 :            : #include "dpsave.hxx"
      46                 :            : #include "dpdimsave.hxx"
      47                 :            : #include "dpshttab.hxx"
      48                 :            : #include "globstr.hrc"
      49                 :            : #include "fapihelper.hxx"
      50                 :            : #include "xestring.hxx"
      51                 :            : #include "xelink.hxx"
      52                 :            : #include "dputil.hxx"
      53                 :            : 
      54                 :            : using namespace ::oox;
      55                 :            : 
      56                 :            : using ::com::sun::star::sheet::DataPilotFieldOrientation;
      57                 :            : using ::com::sun::star::sheet::DataPilotFieldOrientation_HIDDEN;
      58                 :            : using ::com::sun::star::sheet::DataPilotFieldOrientation_ROW;
      59                 :            : using ::com::sun::star::sheet::DataPilotFieldOrientation_COLUMN;
      60                 :            : using ::com::sun::star::sheet::DataPilotFieldOrientation_PAGE;
      61                 :            : using ::com::sun::star::sheet::DataPilotFieldOrientation_DATA;
      62                 :            : using ::com::sun::star::sheet::GeneralFunction;
      63                 :            : using ::com::sun::star::sheet::DataPilotFieldSortInfo;
      64                 :            : using ::com::sun::star::sheet::DataPilotFieldAutoShowInfo;
      65                 :            : using ::com::sun::star::sheet::DataPilotFieldLayoutInfo;
      66                 :            : using ::com::sun::star::sheet::DataPilotFieldReference;
      67                 :            : using ::rtl::OUString;
      68                 :            : 
      69                 :            : using ::rtl::OString;
      70                 :            : using ::rtl::OUString;
      71                 :            : using ::rtl::OUStringBuffer;
      72                 :            : 
      73                 :            : // ============================================================================
      74                 :            : // Pivot cache
      75                 :            : // ============================================================================
      76                 :            : 
      77                 :            : namespace {
      78                 :            : 
      79                 :            : // constants to track occurrence of specific data types
      80                 :            : const sal_uInt16 EXC_PCITEM_DATA_STRING     = 0x0001;   /// String, empty, boolean, error.
      81                 :            : const sal_uInt16 EXC_PCITEM_DATA_DOUBLE     = 0x0002;   /// Double with fraction.
      82                 :            : const sal_uInt16 EXC_PCITEM_DATA_INTEGER    = 0x0004;   /// Integer, double without fraction.
      83                 :            : const sal_uInt16 EXC_PCITEM_DATA_DATE       = 0x0008;   /// Date, time, date/time.
      84                 :            : 
      85                 :            : /** Maps a bitfield consisting of EXC_PCITEM_DATA_* flags above to SXFIELD data type bitfield. */
      86                 :            : static const sal_uInt16 spnPCItemFlags[] =
      87                 :            : {                               // STR DBL INT DAT
      88                 :            :     EXC_SXFIELD_DATA_NONE,      //
      89                 :            :     EXC_SXFIELD_DATA_STR,       //  x
      90                 :            :     EXC_SXFIELD_DATA_INT,       //      x
      91                 :            :     EXC_SXFIELD_DATA_STR_INT,   //  x   x
      92                 :            :     EXC_SXFIELD_DATA_DBL,       //          x
      93                 :            :     EXC_SXFIELD_DATA_STR_DBL,   //  x       x
      94                 :            :     EXC_SXFIELD_DATA_INT,       //      x   x
      95                 :            :     EXC_SXFIELD_DATA_STR_INT,   //  x   x   x
      96                 :            :     EXC_SXFIELD_DATA_DATE,      //              x
      97                 :            :     EXC_SXFIELD_DATA_DATE_STR,  //  x           x
      98                 :            :     EXC_SXFIELD_DATA_DATE_NUM,  //      x       x
      99                 :            :     EXC_SXFIELD_DATA_DATE_STR,  //  x   x       x
     100                 :            :     EXC_SXFIELD_DATA_DATE_NUM,  //          x   x
     101                 :            :     EXC_SXFIELD_DATA_DATE_STR,  //  x       x   x
     102                 :            :     EXC_SXFIELD_DATA_DATE_NUM,  //      x   x   x
     103                 :            :     EXC_SXFIELD_DATA_DATE_STR   //  x   x   x   x
     104                 :            : };
     105                 :            : 
     106                 :            : } // namespace
     107                 :            : 
     108                 :            : // ----------------------------------------------------------------------------
     109                 :            : 
     110                 :          0 : XclExpPCItem::XclExpPCItem( const String& rText ) :
     111                 :          0 :     XclExpRecord( (rText.Len() > 0) ? EXC_ID_SXSTRING : EXC_ID_SXEMPTY, 0 ),
     112 [ #  # ][ #  # ]:          0 :     mnTypeFlag( EXC_PCITEM_DATA_STRING )
     113                 :            : {
     114         [ #  # ]:          0 :     if( rText.Len() )
     115 [ #  # ][ #  # ]:          0 :         SetText( rText );
     116                 :            :     else
     117         [ #  # ]:          0 :         SetEmpty();
     118                 :          0 : }
     119                 :            : 
     120                 :          0 : XclExpPCItem::XclExpPCItem( double fValue ) :
     121         [ #  # ]:          0 :     XclExpRecord( EXC_ID_SXDOUBLE, 8 )
     122                 :            : {
     123         [ #  # ]:          0 :     SetDouble( fValue );
     124                 :          0 :     mnTypeFlag = (fValue - floor( fValue ) == 0.0) ?
     125         [ #  # ]:          0 :         EXC_PCITEM_DATA_INTEGER : EXC_PCITEM_DATA_DOUBLE;
     126                 :          0 : }
     127                 :            : 
     128                 :          0 : XclExpPCItem::XclExpPCItem( const DateTime& rDateTime ) :
     129         [ #  # ]:          0 :     XclExpRecord( EXC_ID_SXDATETIME, 8 )
     130                 :            : {
     131         [ #  # ]:          0 :     SetDateTime( rDateTime );
     132                 :          0 :     mnTypeFlag = EXC_PCITEM_DATA_DATE;
     133                 :          0 : }
     134                 :            : 
     135                 :          0 : XclExpPCItem::XclExpPCItem( sal_Int16 nValue ) :
     136                 :            :     XclExpRecord( EXC_ID_SXINTEGER, 2 ),
     137         [ #  # ]:          0 :     mnTypeFlag( EXC_PCITEM_DATA_INTEGER )
     138                 :            : {
     139         [ #  # ]:          0 :     SetInteger( nValue );
     140                 :          0 : }
     141                 :            : 
     142                 :          0 : XclExpPCItem::XclExpPCItem( bool bValue ) :
     143                 :            :     XclExpRecord( EXC_ID_SXBOOLEAN, 2 ),
     144         [ #  # ]:          0 :     mnTypeFlag( EXC_PCITEM_DATA_STRING )
     145                 :            : {
     146         [ #  # ]:          0 :     SetBool( bValue );
     147                 :          0 : }
     148                 :            : 
     149                 :            : // ----------------------------------------------------------------------------
     150                 :            : 
     151                 :          0 : bool XclExpPCItem::EqualsText( const rtl::OUString& rText ) const
     152                 :            : {
     153 [ #  # ][ #  # ]:          0 :     return rText.isEmpty() ? IsEmpty() : (GetText() && (*GetText() == rText));
                 [ #  # ]
     154                 :            : }
     155                 :            : 
     156                 :          0 : bool XclExpPCItem::EqualsDouble( double fValue ) const
     157                 :            : {
     158 [ #  # ][ #  # ]:          0 :     return GetDouble() && (*GetDouble() == fValue);
     159                 :            : }
     160                 :            : 
     161                 :          0 : bool XclExpPCItem::EqualsDateTime( const DateTime& rDateTime ) const
     162                 :            : {
     163 [ #  # ][ #  # ]:          0 :     return GetDateTime() && (*GetDateTime() == rDateTime);
     164                 :            : }
     165                 :            : 
     166                 :          0 : bool XclExpPCItem::EqualsBool( bool bValue ) const
     167                 :            : {
     168 [ #  # ][ #  # ]:          0 :     return GetBool() && (*GetBool() == bValue);
     169                 :            : }
     170                 :            : 
     171                 :            : // ----------------------------------------------------------------------------
     172                 :            : 
     173                 :          0 : void XclExpPCItem::WriteBody( XclExpStream& rStrm )
     174                 :            : {
     175         [ #  # ]:          0 :     if( const rtl::OUString* pText = GetText() )
     176                 :            :     {
     177         [ #  # ]:          0 :         rStrm << XclExpString( *pText );
     178                 :            :     }
     179         [ #  # ]:          0 :     else if( const double* pfValue = GetDouble() )
     180                 :            :     {
     181                 :          0 :         rStrm << *pfValue;
     182                 :            :     }
     183         [ #  # ]:          0 :     else if( const sal_Int16* pnValue = GetInteger() )
     184                 :            :     {
     185                 :          0 :         rStrm << *pnValue;
     186                 :            :     }
     187         [ #  # ]:          0 :     else if( const DateTime* pDateTime = GetDateTime() )
     188                 :            :     {
     189                 :          0 :         sal_uInt16 nYear = static_cast< sal_uInt16 >( pDateTime->GetYear() );
     190                 :          0 :         sal_uInt16 nMonth = static_cast< sal_uInt16 >( pDateTime->GetMonth() );
     191                 :          0 :         sal_uInt8 nDay = static_cast< sal_uInt8 >( pDateTime->GetDay() );
     192                 :          0 :         sal_uInt8 nHour = static_cast< sal_uInt8 >( pDateTime->GetHour() );
     193                 :          0 :         sal_uInt8 nMin = static_cast< sal_uInt8 >( pDateTime->GetMin() );
     194                 :          0 :         sal_uInt8 nSec = static_cast< sal_uInt8 >( pDateTime->GetSec() );
     195         [ #  # ]:          0 :         if( nYear < 1900 ) { nYear = 1900; nMonth = 1; nDay = 0; }
     196                 :          0 :         rStrm << nYear << nMonth << nDay << nHour << nMin << nSec;
     197                 :            :     }
     198         [ #  # ]:          0 :     else if( const bool* pbValue = GetBool() )
     199                 :            :     {
     200         [ #  # ]:          0 :         rStrm << static_cast< sal_uInt16 >( *pbValue ? 1 : 0 );
     201                 :            :     }
     202                 :            :     else
     203                 :            :     {
     204                 :            :         // nothing to do for SXEMPTY
     205                 :            :         OSL_ENSURE( IsEmpty(), "XclExpPCItem::WriteBody - no data found" );
     206                 :            :     }
     207                 :          0 : }
     208                 :            : 
     209                 :            : // ============================================================================
     210                 :            : 
     211                 :          0 : XclExpPCField::XclExpPCField(
     212                 :            :         const XclExpRoot& rRoot, const XclExpPivotCache& rPCache, sal_uInt16 nFieldIdx,
     213                 :            :         const ScDPObject& rDPObj, const ScRange& rRange ) :
     214                 :            :     XclExpRecord( EXC_ID_SXFIELD ),
     215                 :            :     XclPCField( EXC_PCFIELD_STANDARD, nFieldIdx ),
     216                 :            :     XclExpRoot( rRoot ),
     217                 :            :     mrPCache( rPCache ),
     218 [ #  # ][ #  # ]:          0 :     mnTypeFlags( 0 )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     219                 :            : {
     220                 :            :     // general settings for the standard field, insert all items from source range
     221         [ #  # ]:          0 :     InitStandardField( rRange );
     222                 :            : 
     223                 :            :     // add special settings for inplace numeric grouping
     224         [ #  # ]:          0 :     if( const ScDPSaveData* pSaveData = rDPObj.GetSaveData() )
     225                 :            :     {
     226         [ #  # ]:          0 :         if( const ScDPDimensionSaveData* pSaveDimData = pSaveData->GetExistingDimensionData() )
     227                 :            :         {
     228 [ #  # ][ #  # ]:          0 :             if( const ScDPSaveNumGroupDimension* pNumGroupDim = pSaveDimData->GetNumGroupDim( GetFieldName() ) )
     229                 :            :             {
     230                 :          0 :                 const ScDPNumGroupInfo& rNumInfo = pNumGroupDim->GetInfo();
     231                 :          0 :                 const ScDPNumGroupInfo& rDateInfo = pNumGroupDim->GetDateInfo();
     232                 :            :                 OSL_ENSURE( !rNumInfo.mbEnable || !rDateInfo.mbEnable,
     233                 :            :                     "XclExpPCField::XclExpPCField - numeric and date grouping enabled" );
     234                 :            : 
     235         [ #  # ]:          0 :                 if( rNumInfo.mbEnable )
     236         [ #  # ]:          0 :                     InitNumGroupField( rDPObj, rNumInfo );
     237         [ #  # ]:          0 :                 else if( rDateInfo.mbEnable )
     238         [ #  # ]:          0 :                     InitDateGroupField( rDPObj, rDateInfo, pNumGroupDim->GetDatePart() );
     239                 :            :             }
     240                 :            :         }
     241                 :            :     }
     242                 :            : 
     243                 :            :     // final settings (flags, item numbers)
     244         [ #  # ]:          0 :     Finalize();
     245                 :          0 : }
     246                 :            : 
     247                 :          0 : XclExpPCField::XclExpPCField(
     248                 :            :         const XclExpRoot& rRoot, const XclExpPivotCache& rPCache, sal_uInt16 nFieldIdx,
     249                 :            :         const ScDPObject& rDPObj, const ScDPSaveGroupDimension& rGroupDim, const XclExpPCField& rBaseField ) :
     250                 :            :     XclExpRecord( EXC_ID_SXFIELD ),
     251                 :            :     XclPCField( EXC_PCFIELD_STDGROUP, nFieldIdx ),
     252                 :            :     XclExpRoot( rRoot ),
     253                 :            :     mrPCache( rPCache ),
     254 [ #  # ][ #  # ]:          0 :     mnTypeFlags( 0 )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     255                 :            : {
     256                 :            :     // add base field info (always using first base field, not predecessor of this field) ***
     257                 :            :     OSL_ENSURE( rBaseField.GetFieldName() == rGroupDim.GetSourceDimName(),
     258                 :            :         "XclExpPCField::FillFromGroup - wrong base cache field" );
     259                 :          0 :     maFieldInfo.maName = rGroupDim.GetGroupDimName();
     260                 :          0 :     maFieldInfo.mnGroupBase = rBaseField.GetFieldIndex();
     261                 :            : 
     262                 :            :     // add standard group info or date group info
     263                 :          0 :     const ScDPNumGroupInfo& rDateInfo = rGroupDim.GetDateInfo();
     264 [ #  # ][ #  # ]:          0 :     if( rDateInfo.mbEnable && (rGroupDim.GetDatePart() != 0) )
                 [ #  # ]
     265         [ #  # ]:          0 :         InitDateGroupField( rDPObj, rDateInfo, rGroupDim.GetDatePart() );
     266                 :            :     else
     267         [ #  # ]:          0 :         InitStdGroupField( rBaseField, rGroupDim );
     268                 :            : 
     269                 :            :     // final settings (flags, item numbers)
     270         [ #  # ]:          0 :     Finalize();
     271                 :          0 : }
     272                 :            : 
     273 [ #  # ][ #  # ]:          0 : XclExpPCField::~XclExpPCField()
         [ #  # ][ #  # ]
                 [ #  # ]
     274                 :            : {
     275         [ #  # ]:          0 : }
     276                 :            : 
     277                 :          0 : void XclExpPCField::SetGroupChildField( const XclExpPCField& rChildField )
     278                 :            : {
     279                 :            :     OSL_ENSURE( !::get_flag( maFieldInfo.mnFlags, EXC_SXFIELD_HASCHILD ),
     280                 :            :         "XclExpPCField::SetGroupChildIndex - field already has a grouping child field" );
     281                 :          0 :     ::set_flag( maFieldInfo.mnFlags, EXC_SXFIELD_HASCHILD );
     282                 :          0 :     maFieldInfo.mnGroupChild = rChildField.GetFieldIndex();
     283                 :          0 : }
     284                 :            : 
     285                 :          0 : sal_uInt16 XclExpPCField::GetItemCount() const
     286                 :            : {
     287                 :          0 :     return static_cast< sal_uInt16 >( GetVisItemList().GetSize() );
     288                 :            : }
     289                 :            : 
     290                 :          0 : const XclExpPCItem* XclExpPCField::GetItem( sal_uInt16 nItemIdx ) const
     291                 :            : {
     292                 :          0 :     return GetVisItemList().GetRecord( nItemIdx ).get();
     293                 :            : }
     294                 :            : 
     295                 :          0 : sal_uInt16 XclExpPCField::GetItemIndex( const rtl::OUString& rItemName ) const
     296                 :            : {
     297                 :          0 :     const XclExpPCItemList& rItemList = GetVisItemList();
     298         [ #  # ]:          0 :     for( size_t nPos = 0, nSize = rItemList.GetSize(); nPos < nSize; ++nPos )
     299         [ #  # ]:          0 :         if( rItemList.GetRecord( nPos )->ConvertToText() == rItemName )
     300                 :          0 :             return static_cast< sal_uInt16 >( nPos );
     301                 :          0 :     return EXC_PC_NOITEM;
     302                 :            : }
     303                 :            : 
     304                 :          0 : sal_Size XclExpPCField::GetIndexSize() const
     305                 :            : {
     306         [ #  # ]:          0 :     return Has16BitIndexes() ? 2 : 1;
     307                 :            : }
     308                 :            : 
     309                 :          0 : void XclExpPCField::WriteIndex( XclExpStream& rStrm, sal_uInt32 nSrcRow ) const
     310                 :            : {
     311                 :            :     // only standard fields write item indexes
     312         [ #  # ]:          0 :     if( nSrcRow < maIndexVec.size() )
     313                 :            :     {
     314                 :          0 :         sal_uInt16 nIndex = maIndexVec[ nSrcRow ];
     315         [ #  # ]:          0 :         if( Has16BitIndexes() )
     316                 :          0 :             rStrm << nIndex;
     317                 :            :         else
     318                 :          0 :             rStrm << static_cast< sal_uInt8 >( nIndex );
     319                 :            :     }
     320                 :          0 : }
     321                 :            : 
     322                 :          0 : void XclExpPCField::Save( XclExpStream& rStrm )
     323                 :            : {
     324                 :            :     OSL_ENSURE( IsSupportedField(), "XclExpPCField::Save - unknown field type" );
     325                 :            :     // SXFIELD
     326                 :          0 :     XclExpRecord::Save( rStrm );
     327                 :            :     // SXFDBTYPE
     328         [ #  # ]:          0 :     XclExpUInt16Record( EXC_ID_SXFDBTYPE, EXC_SXFDBTYPE_DEFAULT ).Save( rStrm );
     329                 :            :     // list of grouping items
     330                 :          0 :     maGroupItemList.Save( rStrm );
     331                 :            :     // SXGROUPINFO
     332                 :          0 :     WriteSxgroupinfo( rStrm );
     333                 :            :     // SXNUMGROUP and additional grouping items (grouping limit settings)
     334                 :          0 :     WriteSxnumgroup( rStrm );
     335                 :            :     // list of original items
     336                 :          0 :     maOrigItemList.Save( rStrm );
     337                 :          0 : }
     338                 :            : 
     339                 :            : // private --------------------------------------------------------------------
     340                 :            : 
     341                 :          0 : const XclExpPCField::XclExpPCItemList& XclExpPCField::GetVisItemList() const
     342                 :            : {
     343                 :            :     OSL_ENSURE( IsStandardField() == maGroupItemList.IsEmpty(),
     344                 :            :         "XclExpPCField::GetVisItemList - unexpected additional items in standard field" );
     345         [ #  # ]:          0 :     return IsStandardField() ? maOrigItemList : maGroupItemList;
     346                 :            : }
     347                 :            : 
     348                 :          0 : void XclExpPCField::InitStandardField( const ScRange& rRange )
     349                 :            : {
     350                 :            :     OSL_ENSURE( IsStandardField(), "XclExpPCField::InitStandardField - only for standard fields" );
     351                 :            :     OSL_ENSURE( rRange.aStart.Col() == rRange.aEnd.Col(), "XclExpPCField::InitStandardField - cell range with multiple columns" );
     352                 :            : 
     353                 :          0 :     ScDocument& rDoc = GetDoc();
     354         [ #  # ]:          0 :     SvNumberFormatter& rFormatter = GetFormatter();
     355                 :            : 
     356                 :            :     // field name is in top cell of the range
     357                 :          0 :     ScAddress aPos( rRange.aStart );
     358         [ #  # ]:          0 :     rDoc.GetString( aPos.Col(), aPos.Row(), aPos.Tab(), maFieldInfo.maName );
     359                 :            :     // #i76047# maximum field name length in pivot cache is 255
     360         [ #  # ]:          0 :     if (maFieldInfo.maName.getLength() > EXC_PC_MAXSTRLEN)
     361                 :          0 :         maFieldInfo.maName = maFieldInfo.maName.copy(0, EXC_PC_MAXSTRLEN);
     362                 :            : 
     363                 :            :     // loop over all cells, create pivot cache items
     364 [ #  # ][ #  # ]:          0 :     for( aPos.IncRow(); (aPos.Row() <= rRange.aEnd.Row()) && (maOrigItemList.GetSize() < EXC_PC_MAXITEMCOUNT); aPos.IncRow() )
         [ #  # ][ #  # ]
                 [ #  # ]
     365                 :            :     {
     366 [ #  # ][ #  # ]:          0 :         if( rDoc.HasValueData( aPos.Col(), aPos.Row(), aPos.Tab() ) )
     367                 :            :         {
     368         [ #  # ]:          0 :             double fValue = rDoc.GetValue( aPos );
     369 [ #  # ][ #  # ]:          0 :             short nFmtType = rFormatter.GetType( rDoc.GetNumberFormat( aPos ) );
     370         [ #  # ]:          0 :             if( nFmtType == NUMBERFORMAT_LOGICAL )
     371         [ #  # ]:          0 :                 InsertOrigBoolItem( fValue != 0 );
     372         [ #  # ]:          0 :             else if( nFmtType & NUMBERFORMAT_DATETIME )
     373 [ #  # ][ #  # ]:          0 :                 InsertOrigDateTimeItem( GetDateTimeFromDouble( ::std::max( fValue, 0.0 ) ) );
                 [ #  # ]
     374                 :            :             else
     375         [ #  # ]:          0 :                 InsertOrigDoubleItem( fValue );
     376                 :            :         }
     377                 :            :         else
     378                 :            :         {
     379         [ #  # ]:          0 :             String aText;
     380         [ #  # ]:          0 :             rDoc.GetString( aPos.Col(), aPos.Row(), aPos.Tab(), aText );
     381 [ #  # ][ #  # ]:          0 :             InsertOrigTextItem( aText );
     382                 :            :         }
     383                 :            :     }
     384                 :          0 : }
     385                 :            : 
     386                 :          0 : void XclExpPCField::InitStdGroupField( const XclExpPCField& rBaseField, const ScDPSaveGroupDimension& rGroupDim )
     387                 :            : {
     388                 :            :     OSL_ENSURE( IsGroupField(), "XclExpPCField::InitStdGroupField - only for standard grouping fields" );
     389                 :            : 
     390                 :          0 :     maFieldInfo.mnBaseItems = rBaseField.GetItemCount();
     391                 :          0 :     maGroupOrder.resize( maFieldInfo.mnBaseItems, EXC_PC_NOITEM );
     392                 :            : 
     393                 :            :     // loop over all groups of this field
     394         [ #  # ]:          0 :     for( long nGroupIdx = 0, nGroupCount = rGroupDim.GetGroupCount(); nGroupIdx < nGroupCount; ++nGroupIdx )
     395                 :            :     {
     396         [ #  # ]:          0 :         if( const ScDPSaveGroupItem* pGroupItem = rGroupDim.GetGroupByIndex( nGroupIdx ) )
     397                 :            :         {
     398                 :            :             // the index of the new item containing the grouping name
     399                 :          0 :             sal_uInt16 nGroupItemIdx = EXC_PC_NOITEM;
     400                 :            :             // loop over all elements of one group
     401         [ #  # ]:          0 :             for( size_t nElemIdx = 0, nElemCount = pGroupItem->GetElementCount(); nElemIdx < nElemCount; ++nElemIdx )
     402                 :            :             {
     403         [ #  # ]:          0 :                 if (const rtl::OUString* pElemName = pGroupItem->GetElementByIndex(nElemIdx))
     404                 :            :                 {
     405                 :            :                     // try to find the item that is part of the group in the base field
     406                 :          0 :                     sal_uInt16 nBaseItemIdx = rBaseField.GetItemIndex( *pElemName );
     407         [ #  # ]:          0 :                     if( nBaseItemIdx < maFieldInfo.mnBaseItems )
     408                 :            :                     {
     409                 :            :                         // add group name item only if there are any valid base items
     410         [ #  # ]:          0 :                         if( nGroupItemIdx == EXC_PC_NOITEM )
     411 [ #  # ][ #  # ]:          0 :                             nGroupItemIdx = InsertGroupItem( new XclExpPCItem( pGroupItem->GetGroupName() ) );
                 [ #  # ]
     412                 :          0 :                         maGroupOrder[ nBaseItemIdx ] = nGroupItemIdx;
     413                 :            :                     }
     414                 :            :                 }
     415                 :            :             }
     416                 :            :         }
     417                 :            :     }
     418                 :            : 
     419                 :            :     // add items and base item indexes of all ungrouped elements
     420         [ #  # ]:          0 :     for( sal_uInt16 nBaseItemIdx = 0; nBaseItemIdx < maFieldInfo.mnBaseItems; ++nBaseItemIdx )
     421                 :            :         // items that are not part of a group still have the EXC_PC_NOITEM entry
     422         [ #  # ]:          0 :         if( maGroupOrder[ nBaseItemIdx ] == EXC_PC_NOITEM )
     423                 :            :             // try to find the base item
     424         [ #  # ]:          0 :             if( const XclExpPCItem* pBaseItem = rBaseField.GetItem( nBaseItemIdx ) )
     425                 :            :                 // create a clone of the base item, insert its index into item order list
     426         [ #  # ]:          0 :                 maGroupOrder[ nBaseItemIdx ] = InsertGroupItem( new XclExpPCItem( *pBaseItem ) );
     427                 :          0 : }
     428                 :            : 
     429                 :          0 : void XclExpPCField::InitNumGroupField( const ScDPObject& rDPObj, const ScDPNumGroupInfo& rNumInfo )
     430                 :            : {
     431                 :            :     OSL_ENSURE( IsStandardField(), "XclExpPCField::InitNumGroupField - only for standard fields" );
     432                 :            :     OSL_ENSURE( rNumInfo.mbEnable, "XclExpPCField::InitNumGroupField - numeric grouping not enabled" );
     433                 :            : 
     434                 :            :     // new field type, date type, limit settings (min/max/step/auto)
     435         [ #  # ]:          0 :     if( rNumInfo.mbDateValues )
     436                 :            :     {
     437                 :            :         // special case: group by days with step count
     438                 :          0 :         meFieldType = EXC_PCFIELD_DATEGROUP;
     439                 :          0 :         maNumGroupInfo.SetScDateType( com::sun::star::sheet::DataPilotFieldGroupBy::DAYS );
     440                 :          0 :         SetDateGroupLimit( rNumInfo, true );
     441                 :            :     }
     442                 :            :     else
     443                 :            :     {
     444                 :          0 :         meFieldType = EXC_PCFIELD_NUMGROUP;
     445                 :          0 :         maNumGroupInfo.SetNumType();
     446                 :          0 :         SetNumGroupLimit( rNumInfo );
     447                 :            :     }
     448                 :            : 
     449                 :            :     // generate visible items
     450                 :          0 :     InsertNumDateGroupItems( rDPObj, rNumInfo );
     451                 :          0 : }
     452                 :            : 
     453                 :          0 : void XclExpPCField::InitDateGroupField( const ScDPObject& rDPObj, const ScDPNumGroupInfo& rDateInfo, sal_Int32 nDatePart )
     454                 :            : {
     455                 :            :     OSL_ENSURE( IsStandardField() || IsStdGroupField(), "XclExpPCField::InitDateGroupField - only for standard fields" );
     456                 :            :     OSL_ENSURE( rDateInfo.mbEnable, "XclExpPCField::InitDateGroupField - date grouping not enabled" );
     457                 :            : 
     458                 :            :     // new field type
     459         [ #  # ]:          0 :     meFieldType = IsStandardField() ? EXC_PCFIELD_DATEGROUP : EXC_PCFIELD_DATECHILD;
     460                 :            : 
     461                 :            :     // date type, limit settings (min/max/step/auto)
     462                 :          0 :     maNumGroupInfo.SetScDateType( nDatePart );
     463                 :          0 :     SetDateGroupLimit( rDateInfo, false );
     464                 :            : 
     465                 :            :     // generate visible items
     466                 :          0 :     InsertNumDateGroupItems( rDPObj, rDateInfo, nDatePart );
     467                 :          0 : }
     468                 :            : 
     469                 :          0 : void XclExpPCField::InsertItemArrayIndex( size_t nListPos )
     470                 :            : {
     471                 :            :     OSL_ENSURE( IsStandardField(), "XclExpPCField::InsertItemArrayIndex - only for standard fields" );
     472         [ #  # ]:          0 :     maIndexVec.push_back( static_cast< sal_uInt16 >( nListPos ) );
     473                 :          0 : }
     474                 :            : 
     475                 :          0 : void XclExpPCField::InsertOrigItem( XclExpPCItem* pNewItem )
     476                 :            : {
     477                 :          0 :     size_t nItemIdx = maOrigItemList.GetSize();
     478                 :          0 :     maOrigItemList.AppendNewRecord( pNewItem );
     479                 :          0 :     InsertItemArrayIndex( nItemIdx );
     480                 :          0 :     mnTypeFlags |= pNewItem->GetTypeFlag();
     481                 :          0 : }
     482                 :            : 
     483                 :          0 : void XclExpPCField::InsertOrigTextItem( const String& rText )
     484                 :            : {
     485                 :          0 :     size_t nPos = 0;
     486                 :          0 :     bool bFound = false;
     487                 :            :     // #i76047# maximum item text length in pivot cache is 255
     488 [ #  # ][ #  # ]:          0 :     String aShortText( rText, 0, ::std::min( rText.Len(), EXC_PC_MAXSTRLEN ) );
     489 [ #  # ][ #  # ]:          0 :     for( size_t nSize = maOrigItemList.GetSize(); !bFound && (nPos < nSize); ++nPos )
                 [ #  # ]
     490 [ #  # ][ #  # ]:          0 :         if( (bFound = maOrigItemList.GetRecord( nPos )->EqualsText( aShortText )) == true )
         [ #  # ][ #  # ]
                 [ #  # ]
     491         [ #  # ]:          0 :             InsertItemArrayIndex( nPos );
     492         [ #  # ]:          0 :     if( !bFound )
     493 [ #  # ][ #  # ]:          0 :         InsertOrigItem( new XclExpPCItem( aShortText ) );
         [ #  # ][ #  # ]
     494                 :          0 : }
     495                 :            : 
     496                 :          0 : void XclExpPCField::InsertOrigDoubleItem( double fValue )
     497                 :            : {
     498                 :          0 :     size_t nPos = 0;
     499                 :          0 :     bool bFound = false;
     500 [ #  # ][ #  # ]:          0 :     for( size_t nSize = maOrigItemList.GetSize(); !bFound && (nPos < nSize); ++nPos )
                 [ #  # ]
     501 [ #  # ][ #  # ]:          0 :         if( (bFound = maOrigItemList.GetRecord( nPos )->EqualsDouble( fValue )) == true )
     502                 :          0 :             InsertItemArrayIndex( nPos );
     503         [ #  # ]:          0 :     if( !bFound )
     504         [ #  # ]:          0 :         InsertOrigItem( new XclExpPCItem( fValue ) );
     505                 :          0 : }
     506                 :            : 
     507                 :          0 : void XclExpPCField::InsertOrigDateTimeItem( const DateTime& rDateTime )
     508                 :            : {
     509                 :          0 :     size_t nPos = 0;
     510                 :          0 :     bool bFound = false;
     511 [ #  # ][ #  # ]:          0 :     for( size_t nSize = maOrigItemList.GetSize(); !bFound && (nPos < nSize); ++nPos )
                 [ #  # ]
     512 [ #  # ][ #  # ]:          0 :         if( (bFound = maOrigItemList.GetRecord( nPos )->EqualsDateTime( rDateTime )) == true )
     513                 :          0 :             InsertItemArrayIndex( nPos );
     514         [ #  # ]:          0 :     if( !bFound )
     515         [ #  # ]:          0 :         InsertOrigItem( new XclExpPCItem( rDateTime ) );
     516                 :          0 : }
     517                 :            : 
     518                 :          0 : void XclExpPCField::InsertOrigBoolItem( bool bValue )
     519                 :            : {
     520                 :          0 :     size_t nPos = 0;
     521                 :          0 :     bool bFound = false;
     522 [ #  # ][ #  # ]:          0 :     for( size_t nSize = maOrigItemList.GetSize(); !bFound && (nPos < nSize); ++nPos )
                 [ #  # ]
     523 [ #  # ][ #  # ]:          0 :         if( (bFound = maOrigItemList.GetRecord( nPos )->EqualsBool( bValue )) == true )
     524                 :          0 :             InsertItemArrayIndex( nPos );
     525         [ #  # ]:          0 :     if( !bFound )
     526         [ #  # ]:          0 :         InsertOrigItem( new XclExpPCItem( bValue ) );
     527                 :          0 : }
     528                 :            : 
     529                 :          0 : sal_uInt16 XclExpPCField::InsertGroupItem( XclExpPCItem* pNewItem )
     530                 :            : {
     531                 :          0 :     maGroupItemList.AppendNewRecord( pNewItem );
     532                 :          0 :     return static_cast< sal_uInt16 >( maGroupItemList.GetSize() - 1 );
     533                 :            : }
     534                 :            : 
     535                 :          0 : void XclExpPCField::InsertNumDateGroupItems( const ScDPObject& rDPObj, const ScDPNumGroupInfo& rNumInfo, sal_Int32 nDatePart )
     536                 :            : {
     537                 :            :     OSL_ENSURE( rDPObj.GetSheetDesc(), "XclExpPCField::InsertNumDateGroupItems - cannot generate element list" );
     538         [ #  # ]:          0 :     if( const ScSheetSourceDesc* pSrcDesc = rDPObj.GetSheetDesc() )
     539                 :            :     {
     540                 :            :         // get the string collection with original source elements
     541                 :          0 :         const ScDPSaveData* pSaveData = rDPObj.GetSaveData();
     542                 :          0 :         const ScDPDimensionSaveData* pDimData = NULL;
     543         [ #  # ]:          0 :         if (pSaveData)
     544                 :          0 :             pDimData = pSaveData->GetExistingDimensionData();
     545                 :            : 
     546         [ #  # ]:          0 :         const ScDPCache* pCache = pSrcDesc->CreateCache(pDimData);
     547         [ #  # ]:          0 :         if (!pCache)
     548                 :          0 :             return;
     549                 :            : 
     550         [ #  # ]:          0 :         ScSheetDPData aDPData(GetDocPtr(), *pSrcDesc, pCache);
     551                 :          0 :         long nDim = GetFieldIndex();
     552 [ #  # ][ #  # ]:          0 :         const std::vector< SCROW > aOrignial = aDPData.GetColumnEntries(nDim);
     553                 :            :         // get the string collection with generated grouping elements
     554         [ #  # ]:          0 :         ScDPNumGroupDimension aTmpDim( rNumInfo );
     555         [ #  # ]:          0 :         if( nDatePart != 0 )
     556         [ #  # ]:          0 :             aTmpDim.SetDateDimension();
     557                 :            :         const std::vector<SCROW>& aMemberIds = aTmpDim.GetNumEntries(
     558         [ #  # ]:          0 :             static_cast<SCCOL>(nDim), pCache);
     559         [ #  # ]:          0 :         for ( size_t  nIdx = 0 ; nIdx < aMemberIds.size(); nIdx++ )
     560                 :            :         {
     561 [ #  # ][ #  # ]:          0 :             const ScDPItemData* pData = aDPData.GetMemberById(nDim , aMemberIds[nIdx]);
     562         [ #  # ]:          0 :             if ( pData )
     563                 :            :             {
     564         [ #  # ]:          0 :                 rtl::OUString aStr = pCache->GetFormattedString(nDim, *pData);
     565 [ #  # ][ #  # ]:          0 :                 InsertGroupItem(new XclExpPCItem(aStr));
         [ #  # ][ #  # ]
                 [ #  # ]
     566                 :            :             }
     567 [ #  # ][ #  # ]:          0 :         }
     568                 :            :     }
     569                 :            : }
     570                 :            : 
     571                 :          0 : void XclExpPCField::SetNumGroupLimit( const ScDPNumGroupInfo& rNumInfo )
     572                 :            : {
     573                 :          0 :     ::set_flag( maNumGroupInfo.mnFlags, EXC_SXNUMGROUP_AUTOMIN, rNumInfo.mbAutoStart );
     574                 :          0 :     ::set_flag( maNumGroupInfo.mnFlags, EXC_SXNUMGROUP_AUTOMAX, rNumInfo.mbAutoEnd );
     575         [ #  # ]:          0 :     maNumGroupLimits.AppendNewRecord( new XclExpPCItem( rNumInfo.mfStart ) );
     576         [ #  # ]:          0 :     maNumGroupLimits.AppendNewRecord( new XclExpPCItem( rNumInfo.mfEnd ) );
     577         [ #  # ]:          0 :     maNumGroupLimits.AppendNewRecord( new XclExpPCItem( rNumInfo.mfStep ) );
     578                 :          0 : }
     579                 :            : 
     580                 :          0 : void XclExpPCField::SetDateGroupLimit( const ScDPNumGroupInfo& rDateInfo, bool bUseStep )
     581                 :            : {
     582                 :          0 :     ::set_flag( maNumGroupInfo.mnFlags, EXC_SXNUMGROUP_AUTOMIN, rDateInfo.mbAutoStart );
     583                 :          0 :     ::set_flag( maNumGroupInfo.mnFlags, EXC_SXNUMGROUP_AUTOMAX, rDateInfo.mbAutoEnd );
     584 [ #  # ][ #  # ]:          0 :     maNumGroupLimits.AppendNewRecord( new XclExpPCItem( GetDateTimeFromDouble( rDateInfo.mfStart ) ) );
                 [ #  # ]
     585 [ #  # ][ #  # ]:          0 :     maNumGroupLimits.AppendNewRecord( new XclExpPCItem( GetDateTimeFromDouble( rDateInfo.mfEnd ) ) );
                 [ #  # ]
     586         [ #  # ]:          0 :     sal_Int16 nStep = bUseStep ? limit_cast< sal_Int16 >( rDateInfo.mfStep, 1, SAL_MAX_INT16 ) : 1;
     587         [ #  # ]:          0 :     maNumGroupLimits.AppendNewRecord( new XclExpPCItem( nStep ) );
     588                 :          0 : }
     589                 :            : 
     590                 :          0 : void XclExpPCField::Finalize()
     591                 :            : {
     592                 :            :     // flags
     593                 :          0 :     ::set_flag( maFieldInfo.mnFlags, EXC_SXFIELD_HASITEMS, !GetVisItemList().IsEmpty() );
     594                 :            :     // Excel writes long indexes even for 0x0100 items (indexes from 0x00 to 0xFF)
     595                 :          0 :     ::set_flag( maFieldInfo.mnFlags, EXC_SXFIELD_16BIT, maOrigItemList.GetSize() >= 0x0100 );
     596 [ #  # ][ #  # ]:          0 :     ::set_flag( maFieldInfo.mnFlags, EXC_SXFIELD_NUMGROUP, IsNumGroupField() || IsDateGroupField() );
     597                 :            :     /*  mnTypeFlags is updated in all Insert***Item() functions. Now the flags
     598                 :            :         for the current combination of item types is added to the flags. */
     599                 :          0 :     ::set_flag( maFieldInfo.mnFlags, spnPCItemFlags[ mnTypeFlags ] );
     600                 :            : 
     601                 :            :     // item count fields
     602                 :          0 :     maFieldInfo.mnVisItems = static_cast< sal_uInt16 >( GetVisItemList().GetSize() );
     603                 :          0 :     maFieldInfo.mnGroupItems = static_cast< sal_uInt16 >( maGroupItemList.GetSize() );
     604                 :            :     // maFieldInfo.mnBaseItems set in InitStdGroupField()
     605                 :          0 :     maFieldInfo.mnOrigItems = static_cast< sal_uInt16 >( maOrigItemList.GetSize() );
     606                 :          0 : }
     607                 :            : 
     608                 :          0 : void XclExpPCField::WriteSxnumgroup( XclExpStream& rStrm )
     609                 :            : {
     610 [ #  # ][ #  # ]:          0 :     if( IsNumGroupField() || IsDateGroupField() )
                 [ #  # ]
     611                 :            :     {
     612                 :            :         // SXNUMGROUP record
     613                 :          0 :         rStrm.StartRecord( EXC_ID_SXNUMGROUP, 2 );
     614                 :          0 :         rStrm << maNumGroupInfo;
     615                 :          0 :         rStrm.EndRecord();
     616                 :            : 
     617                 :            :         // limits (min/max/step) for numeric grouping
     618                 :            :         OSL_ENSURE( maNumGroupLimits.GetSize() == 3,
     619                 :            :             "XclExpPCField::WriteSxnumgroup - missing numeric grouping limits" );
     620                 :          0 :         maNumGroupLimits.Save( rStrm );
     621                 :            :     }
     622                 :          0 : }
     623                 :            : 
     624                 :          0 : void XclExpPCField::WriteSxgroupinfo( XclExpStream& rStrm )
     625                 :            : {
     626                 :            :     OSL_ENSURE( IsStdGroupField() != maGroupOrder.empty(),
     627                 :            :         "XclExpPCField::WriteSxgroupinfo - missing grouping info" );
     628 [ #  # ][ #  # ]:          0 :     if( IsStdGroupField() && !maGroupOrder.empty() )
                 [ #  # ]
     629                 :            :     {
     630                 :          0 :         rStrm.StartRecord( EXC_ID_SXGROUPINFO, 2 * maGroupOrder.size() );
     631 [ #  # ][ #  # ]:          0 :         for( ScfUInt16Vec::const_iterator aIt = maGroupOrder.begin(), aEnd = maGroupOrder.end(); aIt != aEnd; ++aIt )
         [ #  # ][ #  # ]
                 [ #  # ]
     632 [ #  # ][ #  # ]:          0 :             rStrm << *aIt;
     633                 :          0 :         rStrm.EndRecord();
     634                 :            :     }
     635                 :          0 : }
     636                 :            : 
     637                 :          0 : void XclExpPCField::WriteBody( XclExpStream& rStrm )
     638                 :            : {
     639                 :          0 :     rStrm << maFieldInfo;
     640                 :          0 : }
     641                 :            : 
     642                 :            : // ============================================================================
     643                 :            : 
     644                 :          0 : XclExpPivotCache::XclExpPivotCache( const XclExpRoot& rRoot, const ScDPObject& rDPObj, sal_uInt16 nListIdx ) :
     645                 :            :     XclExpRoot( rRoot ),
     646                 :            :     mnListIdx( nListIdx ),
     647 [ #  # ][ #  # ]:          0 :     mbValid( false )
     648                 :            : {
     649                 :            :     // source from sheet only
     650         [ #  # ]:          0 :     if( const ScSheetSourceDesc* pSrcDesc = rDPObj.GetSheetDesc() )
     651                 :            :     {
     652                 :            :         /*  maOrigSrcRange: Range received from the DataPilot object.
     653                 :            :             maExpSrcRange: Range written to the DCONREF record.
     654                 :            :             maDocSrcRange: Range used to get source data from Calc document.
     655                 :            :                 This range may be shorter than maExpSrcRange to improve export
     656                 :            :                 performance (#i22541#). */
     657         [ #  # ]:          0 :         maOrigSrcRange = maExpSrcRange = maDocSrcRange = pSrcDesc->GetSourceRange();
     658         [ #  # ]:          0 :         maSrcRangeName = pSrcDesc->GetRangeName();
     659                 :            : 
     660                 :            :         // internal sheet data only
     661                 :          0 :         SCTAB nScTab = maExpSrcRange.aStart.Tab();
     662 [ #  # ][ #  # ]:          0 :         if( (nScTab == maExpSrcRange.aEnd.Tab()) && GetTabInfo().IsExportTab( nScTab ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     663                 :            :         {
     664                 :            :             // ValidateRange() restricts source range to valid Excel limits
     665 [ #  # ][ #  # ]:          0 :             if( GetAddressConverter().ValidateRange( maExpSrcRange, true ) )
                 [ #  # ]
     666                 :            :             {
     667                 :            :                 // #i22541# skip empty cell areas (performance)
     668                 :            :                 SCCOL nDocCol1, nDocCol2;
     669                 :            :                 SCROW nDocRow1, nDocRow2;
     670         [ #  # ]:          0 :                 GetDoc().GetDataStart( nScTab, nDocCol1, nDocRow1 );
     671         [ #  # ]:          0 :                 GetDoc().GetPrintArea( nScTab, nDocCol2, nDocRow2, false );
     672                 :          0 :                 SCCOL nSrcCol1 = maExpSrcRange.aStart.Col();
     673                 :          0 :                 SCROW nSrcRow1 = maExpSrcRange.aStart.Row();
     674                 :          0 :                 SCCOL nSrcCol2 = maExpSrcRange.aEnd.Col();
     675                 :          0 :                 SCROW nSrcRow2 = maExpSrcRange.aEnd.Row();
     676                 :            : 
     677                 :            :                 // #i22541# do not store index list for too big ranges
     678         [ #  # ]:          0 :                 if( 2 * (nDocRow2 - nDocRow1) < (nSrcRow2 - nSrcRow1) )
     679                 :          0 :                     ::set_flag( maPCInfo.mnFlags, EXC_SXDB_SAVEDATA, false );
     680                 :            : 
     681                 :            :                 // adjust row indexes, keep one row of empty area to surely have the empty cache item
     682         [ #  # ]:          0 :                 if( nSrcRow1 < nDocRow1 )
     683                 :          0 :                     nSrcRow1 = nDocRow1 - 1;
     684         [ #  # ]:          0 :                 if( nSrcRow2 > nDocRow2 )
     685                 :          0 :                     nSrcRow2 = nDocRow2 + 1;
     686                 :            : 
     687         [ #  # ]:          0 :                 maDocSrcRange.aStart.SetCol( ::std::max( nDocCol1, nSrcCol1 ) );
     688                 :          0 :                 maDocSrcRange.aStart.SetRow( nSrcRow1 );
     689         [ #  # ]:          0 :                 maDocSrcRange.aEnd.SetCol( ::std::min( nDocCol2, nSrcCol2 ) );
     690                 :          0 :                 maDocSrcRange.aEnd.SetRow( nSrcRow2 );
     691                 :            : 
     692         [ #  # ]:          0 :                 GetDoc().GetName( nScTab, maTabName );
     693                 :          0 :                 maPCInfo.mnSrcRecs = static_cast< sal_uInt32 >( maExpSrcRange.aEnd.Row() - maExpSrcRange.aStart.Row() );
     694                 :          0 :                 maPCInfo.mnStrmId = nListIdx + 1;
     695                 :          0 :                 maPCInfo.mnSrcType = EXC_SXDB_SRC_SHEET;
     696                 :            : 
     697         [ #  # ]:          0 :                 AddFields( rDPObj );
     698                 :            : 
     699                 :          0 :                 mbValid = true;
     700                 :            :             }
     701                 :            :         }
     702                 :            :     }
     703                 :          0 : }
     704                 :            : 
     705                 :          0 : bool XclExpPivotCache::HasItemIndexList() const
     706                 :            : {
     707                 :          0 :     return ::get_flag( maPCInfo.mnFlags, EXC_SXDB_SAVEDATA );
     708                 :            : }
     709                 :            : 
     710                 :          0 : sal_uInt16 XclExpPivotCache::GetFieldCount() const
     711                 :            : {
     712                 :          0 :     return static_cast< sal_uInt16 >( maFieldList.GetSize() );
     713                 :            : }
     714                 :            : 
     715                 :          0 : const XclExpPCField* XclExpPivotCache::GetField( sal_uInt16 nFieldIdx ) const
     716                 :            : {
     717                 :          0 :     return maFieldList.GetRecord( nFieldIdx ).get();
     718                 :            : }
     719                 :            : 
     720                 :          0 : bool XclExpPivotCache::HasAddFields() const
     721                 :            : {
     722                 :            :     // pivot cache can be shared, if there are no additional cache fields
     723                 :          0 :     return maPCInfo.mnStdFields < maPCInfo.mnTotalFields;
     724                 :            : }
     725                 :            : 
     726                 :          0 : bool XclExpPivotCache::HasEqualDataSource( const ScDPObject& rDPObj ) const
     727                 :            : {
     728                 :            :     /*  For now, only sheet sources are supported, therefore it is enough to
     729                 :            :         compare the ScSheetSourceDesc. Later, there should be done more complicated
     730                 :            :         comparisons regarding the source type of rDPObj and this cache. */
     731         [ #  # ]:          0 :     if( const ScSheetSourceDesc* pSrcDesc = rDPObj.GetSheetDesc() )
     732                 :          0 :         return pSrcDesc->GetSourceRange() == maOrigSrcRange;
     733                 :          0 :     return false;
     734                 :            : }
     735                 :            : 
     736                 :          0 : void XclExpPivotCache::Save( XclExpStream& rStrm )
     737                 :            : {
     738                 :            :     OSL_ENSURE( mbValid, "XclExpPivotCache::Save - invalid pivot cache" );
     739                 :            :     // SXIDSTM
     740         [ #  # ]:          0 :     XclExpUInt16Record( EXC_ID_SXIDSTM, maPCInfo.mnStrmId ).Save( rStrm );
     741                 :            :     // SXVS
     742         [ #  # ]:          0 :     XclExpUInt16Record( EXC_ID_SXVS, EXC_SXVS_SHEET ).Save( rStrm );
     743                 :            : 
     744         [ #  # ]:          0 :     if (!maSrcRangeName.isEmpty())
     745                 :            :         // DCONNAME
     746                 :          0 :         WriteDConName(rStrm);
     747                 :            :     else
     748                 :            :         // DCONREF
     749                 :          0 :         WriteDconref(rStrm);
     750                 :            : 
     751                 :            :     // create the pivot cache storage stream
     752                 :          0 :     WriteCacheStream();
     753                 :          0 : }
     754                 :            : 
     755                 :          0 : void XclExpPivotCache::SaveXml( XclExpXmlStream&
     756                 :            : #ifdef XLSX_PIVOT_CACHE
     757                 :            :                                                  rStrm
     758                 :            : #endif
     759                 :            : )
     760                 :            : {
     761                 :            :     OSL_ENSURE( mbValid, "XclExpPivotCache::Save - invalid pivot cache" );
     762                 :            : #ifdef XLSX_PIVOT_CACHE /* <pivotCache> without xl/pivotCaches/ cacheStream
     763                 :            :                            results in a broken .xlsx */
     764                 :            :     sax_fastparser::FSHelperPtr& rWorkbook = rStrm.GetCurrentStream();
     765                 :            :     OUString sId = OUStringBuffer()
     766                 :            :         .appendAscii("rId")
     767                 :            :         .append( rStrm.GetUniqueIdOUString() )
     768                 :            :         .makeStringAndClear();
     769                 :            :     rWorkbook->startElement( XML_pivotCache,
     770                 :            :             XML_cacheId, OString::valueOf( (sal_Int32)maPCInfo.mnStrmId ).getStr(),
     771                 :            :             FSNS( XML_r, XML_id ), XclXmlUtils::ToOString( sId ).getStr(),
     772                 :            :             FSEND );
     773                 :            :     // SXIDSTM
     774                 :            :     XclExpUInt16Record( EXC_ID_SXIDSTM, maPCInfo.mnStrmId ).SaveXml( rStrm );
     775                 :            :     // SXVS
     776                 :            :     XclExpUInt16Record( EXC_ID_SXVS, EXC_SXVS_SHEET ).SaveXml( rStrm );
     777                 :            :     // DCONREF
     778                 :            :     // OOXTODO: WriteDconref( rStrm );
     779                 :            :     // create the pivot cache storage stream
     780                 :            :     // OOXTODO: WriteCacheStream();
     781                 :            :     rWorkbook->endElement( XML_pivotCache );
     782                 :            : #endif /* XLSX_PIVOT_CACHE */
     783                 :          0 : }
     784                 :            : 
     785                 :            : // private --------------------------------------------------------------------
     786                 :            : 
     787                 :          0 : XclExpPCField* XclExpPivotCache::GetFieldAcc( sal_uInt16 nFieldIdx )
     788                 :            : {
     789                 :          0 :     return maFieldList.GetRecord( nFieldIdx ).get();
     790                 :            : }
     791                 :            : 
     792                 :          0 : XclExpPCField* XclExpPivotCache::GetFieldAcc( const rtl::OUString& rFieldName )
     793                 :            : {
     794                 :          0 :     XclExpPCField* pField = 0;
     795 [ #  # ][ #  # ]:          0 :     for( size_t nPos = 0, nSize = maFieldList.GetSize(); !pField && (nPos < nSize); ++nPos )
                 [ #  # ]
     796         [ #  # ]:          0 :         if( maFieldList.GetRecord( nPos )->GetFieldName() == rFieldName )
     797                 :          0 :             pField = maFieldList.GetRecord( nPos ).get();
     798                 :          0 :     return pField;
     799                 :            : }
     800                 :            : 
     801                 :          0 : void XclExpPivotCache::AddFields( const ScDPObject& rDPObj )
     802                 :            : {
     803                 :          0 :     AddStdFields( rDPObj );
     804                 :          0 :     maPCInfo.mnStdFields = GetFieldCount();
     805                 :          0 :     AddGroupFields( rDPObj );
     806                 :          0 :     AddCalcFields( rDPObj );
     807                 :          0 :     maPCInfo.mnTotalFields = GetFieldCount();
     808                 :          0 : };
     809                 :            : 
     810                 :          0 : void XclExpPivotCache::AddStdFields( const ScDPObject& rDPObj )
     811                 :            : {
     812                 :            :     // if item index list is not written, used shortened source range (maDocSrcRange) for performance
     813         [ #  # ]:          0 :     const ScRange& rRange = HasItemIndexList() ? maExpSrcRange : maDocSrcRange;
     814                 :            :     // create a standard pivot cache field for each source column
     815         [ #  # ]:          0 :     for( SCCOL nScCol = rRange.aStart.Col(), nEndScCol = rRange.aEnd.Col(); nScCol <= nEndScCol; ++nScCol )
     816                 :            :     {
     817                 :          0 :         ScRange aColRange( rRange );
     818                 :          0 :         aColRange.aStart.SetCol( nScCol );
     819                 :          0 :         aColRange.aEnd.SetCol( nScCol );
     820                 :            :         maFieldList.AppendNewRecord( new XclExpPCField(
     821 [ #  # ][ #  # ]:          0 :             GetRoot(), *this, GetFieldCount(), rDPObj, aColRange ) );
         [ #  # ][ #  # ]
     822                 :            :     }
     823                 :          0 : }
     824                 :            : 
     825                 :          0 : void XclExpPivotCache::AddGroupFields( const ScDPObject& rDPObj )
     826                 :            : {
     827         [ #  # ]:          0 :     if( const ScDPSaveData* pSaveData = rDPObj.GetSaveData() )
     828                 :            :     {
     829         [ #  # ]:          0 :         if( const ScDPDimensionSaveData* pSaveDimData = pSaveData->GetExistingDimensionData() )
     830                 :            :         {
     831                 :            :             // loop over all existing standard fields to find their group fields
     832         [ #  # ]:          0 :             for( sal_uInt16 nFieldIdx = 0; nFieldIdx < maPCInfo.mnStdFields; ++nFieldIdx )
     833                 :            :             {
     834         [ #  # ]:          0 :                 if( XclExpPCField* pCurrStdField = GetFieldAcc( nFieldIdx ) )
     835                 :            :                 {
     836                 :          0 :                     const ScDPSaveGroupDimension* pGroupDim = pSaveDimData->GetGroupDimForBase( pCurrStdField->GetFieldName() );
     837                 :          0 :                     XclExpPCField* pLastGroupField = pCurrStdField;
     838         [ #  # ]:          0 :                     while( pGroupDim )
     839                 :            :                     {
     840                 :            :                         // insert the new grouping field
     841                 :            :                         XclExpPCFieldRef xNewGroupField( new XclExpPCField(
     842 [ #  # ][ #  # ]:          0 :                             GetRoot(), *this, GetFieldCount(), rDPObj, *pGroupDim, *pCurrStdField ) );
         [ #  # ][ #  # ]
     843 [ #  # ][ #  # ]:          0 :                         maFieldList.AppendRecord( xNewGroupField );
                 [ #  # ]
     844                 :            : 
     845                 :            :                         // register new grouping field at current grouping field, building a chain
     846         [ #  # ]:          0 :                         pLastGroupField->SetGroupChildField( *xNewGroupField );
     847                 :            : 
     848                 :            :                         // next grouping dimension
     849         [ #  # ]:          0 :                         pGroupDim = pSaveDimData->GetGroupDimForBase( pGroupDim->GetGroupDimName() );
     850                 :          0 :                         pLastGroupField = xNewGroupField.get();
     851         [ #  # ]:          0 :                     }
     852                 :            :                 }
     853                 :            :             }
     854                 :            :         }
     855                 :            :     }
     856                 :          0 : }
     857                 :            : 
     858                 :          0 : void XclExpPivotCache::AddCalcFields( const ScDPObject& /*rDPObj*/ )
     859                 :            : {
     860                 :            :     // not supported
     861                 :          0 : }
     862                 :            : 
     863                 :          0 : void XclExpPivotCache::WriteDconref( XclExpStream& rStrm ) const
     864                 :            : {
     865 [ #  # ][ #  # ]:          0 :     XclExpString aRef( XclExpUrlHelper::EncodeUrl( GetRoot(), EMPTY_STRING, &maTabName ) );
         [ #  # ][ #  # ]
     866 [ #  # ][ #  # ]:          0 :     rStrm.StartRecord( EXC_ID_DCONREF, 7 + aRef.GetSize() );
     867         [ #  # ]:          0 :     rStrm   << static_cast< sal_uInt16 >( maExpSrcRange.aStart.Row() )
     868         [ #  # ]:          0 :             << static_cast< sal_uInt16 >( maExpSrcRange.aEnd.Row() )
     869         [ #  # ]:          0 :             << static_cast< sal_uInt8 >( maExpSrcRange.aStart.Col() )
     870         [ #  # ]:          0 :             << static_cast< sal_uInt8 >( maExpSrcRange.aEnd.Col() )
     871         [ #  # ]:          0 :             << aRef
     872         [ #  # ]:          0 :             << sal_uInt8( 0 );
     873         [ #  # ]:          0 :     rStrm.EndRecord();
     874                 :          0 : }
     875                 :            : 
     876                 :          0 : void XclExpPivotCache::WriteDConName( XclExpStream& rStrm ) const
     877                 :            : {
     878         [ #  # ]:          0 :     XclExpString aName(maSrcRangeName);
     879 [ #  # ][ #  # ]:          0 :     rStrm.StartRecord(EXC_ID_DCONNAME, aName.GetSize() + 2);
     880 [ #  # ][ #  # ]:          0 :     rStrm << aName << sal_uInt16(0);
     881         [ #  # ]:          0 :     rStrm.EndRecord();
     882                 :          0 : }
     883                 :            : 
     884                 :          0 : void XclExpPivotCache::WriteCacheStream()
     885                 :            : {
     886 [ #  # ][ #  # ]:          0 :     SotStorageRef xSvStrg = OpenStorage( EXC_STORAGE_PTCACHE );
                 [ #  # ]
     887 [ #  # ][ #  # ]:          0 :     SotStorageStreamRef xSvStrm = OpenStream( xSvStrg, ScfTools::GetHexStr( maPCInfo.mnStrmId ) );
         [ #  # ][ #  # ]
     888         [ #  # ]:          0 :     if( xSvStrm.Is() )
     889                 :            :     {
     890         [ #  # ]:          0 :         XclExpStream aStrm( *xSvStrm, GetRoot() );
     891                 :            :         // SXDB
     892         [ #  # ]:          0 :         WriteSxdb( aStrm );
     893                 :            :         // SXDBEX
     894         [ #  # ]:          0 :         WriteSxdbex( aStrm );
     895                 :            :         // field list (SXFIELD and items)
     896         [ #  # ]:          0 :         maFieldList.Save( aStrm );
     897                 :            :         // index table (list of SXINDEXLIST)
     898         [ #  # ]:          0 :         WriteSxindexlistList( aStrm );
     899                 :            :         // EOF
     900 [ #  # ][ #  # ]:          0 :         XclExpEmptyRecord( EXC_ID_EOF ).Save( aStrm );
         [ #  # ][ #  # ]
     901 [ #  # ][ #  # ]:          0 :     }
     902                 :          0 : }
     903                 :            : 
     904                 :          0 : void XclExpPivotCache::WriteSxdb( XclExpStream& rStrm ) const
     905                 :            : {
     906                 :          0 :     rStrm.StartRecord( EXC_ID_SXDB, 21 );
     907                 :          0 :     rStrm << maPCInfo;
     908                 :          0 :     rStrm.EndRecord();
     909                 :          0 : }
     910                 :            : 
     911                 :          0 : void XclExpPivotCache::WriteSxdbex( XclExpStream& rStrm ) const
     912                 :            : {
     913                 :          0 :     rStrm.StartRecord( EXC_ID_SXDBEX, 12 );
     914                 :          0 :     rStrm   << EXC_SXDBEX_CREATION_DATE
     915                 :          0 :             << sal_uInt32( 0 );             // number of SXFORMULA records
     916                 :          0 :     rStrm.EndRecord();
     917                 :          0 : }
     918                 :            : 
     919                 :          0 : void XclExpPivotCache::WriteSxindexlistList( XclExpStream& rStrm ) const
     920                 :            : {
     921         [ #  # ]:          0 :     if( HasItemIndexList() )
     922                 :            :     {
     923                 :          0 :         sal_Size nRecSize = 0;
     924                 :          0 :         size_t nPos, nSize = maFieldList.GetSize();
     925         [ #  # ]:          0 :         for( nPos = 0; nPos < nSize; ++nPos )
     926         [ #  # ]:          0 :             nRecSize += maFieldList.GetRecord( nPos )->GetIndexSize();
     927                 :            : 
     928         [ #  # ]:          0 :         for( sal_uInt32 nSrcRow = 0; nSrcRow < maPCInfo.mnSrcRecs; ++nSrcRow )
     929                 :            :         {
     930                 :          0 :             rStrm.StartRecord( EXC_ID_SXINDEXLIST, nRecSize );
     931         [ #  # ]:          0 :             for( nPos = 0; nPos < nSize; ++nPos )
     932         [ #  # ]:          0 :                 maFieldList.GetRecord( nPos )->WriteIndex( rStrm, nSrcRow );
     933                 :          0 :             rStrm.EndRecord();
     934                 :            :         }
     935                 :            :     }
     936                 :          0 : }
     937                 :            : 
     938                 :            : // ============================================================================
     939                 :            : // Pivot table
     940                 :            : // ============================================================================
     941                 :            : 
     942                 :            : namespace {
     943                 :            : 
     944                 :            : // ----------------------------------------------------------------------------
     945                 :            : 
     946                 :            : /** Returns a display string for a data field containing the field name and aggregation function. */
     947                 :          0 : String lclGetDataFieldCaption( const String& rFieldName, GeneralFunction eFunc )
     948                 :            : {
     949                 :          0 :     String aCaption;
     950                 :            : 
     951                 :          0 :     sal_uInt16 nResIdx = 0;
     952                 :            :     using namespace ::com::sun::star::sheet;
     953   [ #  #  #  #  :          0 :     switch( eFunc )
          #  #  #  #  #  
                #  #  # ]
     954                 :            :     {
     955                 :          0 :         case GeneralFunction_SUM:       nResIdx = STR_FUN_TEXT_SUM;     break;
     956                 :          0 :         case GeneralFunction_COUNT:     nResIdx = STR_FUN_TEXT_COUNT;   break;
     957                 :          0 :         case GeneralFunction_AVERAGE:   nResIdx = STR_FUN_TEXT_AVG;     break;
     958                 :          0 :         case GeneralFunction_MAX:       nResIdx = STR_FUN_TEXT_MAX;     break;
     959                 :          0 :         case GeneralFunction_MIN:       nResIdx = STR_FUN_TEXT_MIN;     break;
     960                 :          0 :         case GeneralFunction_PRODUCT:   nResIdx = STR_FUN_TEXT_PRODUCT; break;
     961                 :          0 :         case GeneralFunction_COUNTNUMS: nResIdx = STR_FUN_TEXT_COUNT;   break;
     962                 :          0 :         case GeneralFunction_STDEV:     nResIdx = STR_FUN_TEXT_STDDEV;  break;
     963                 :          0 :         case GeneralFunction_STDEVP:    nResIdx = STR_FUN_TEXT_STDDEV;  break;
     964                 :          0 :         case GeneralFunction_VAR:       nResIdx = STR_FUN_TEXT_VAR;     break;
     965                 :          0 :         case GeneralFunction_VARP:      nResIdx = STR_FUN_TEXT_VAR;     break;
     966                 :            :         default:;
     967                 :            :     }
     968         [ #  # ]:          0 :     if( nResIdx )
     969 [ #  # ][ #  # ]:          0 :         aCaption.Assign( ScGlobal::GetRscString( nResIdx ) ).AppendAscii( RTL_CONSTASCII_STRINGPARAM( " - " ) );
                 [ #  # ]
     970         [ #  # ]:          0 :     aCaption.Append( rFieldName );
     971                 :          0 :     return aCaption;
     972                 :            : }
     973                 :            : 
     974                 :            : // ----------------------------------------------------------------------------
     975                 :            : 
     976                 :            : } // namespace
     977                 :            : 
     978                 :            : // ============================================================================
     979                 :            : 
     980                 :          0 : XclExpPTItem::XclExpPTItem( const XclExpPCField& rCacheField, sal_uInt16 nCacheIdx ) :
     981                 :            :     XclExpRecord( EXC_ID_SXVI, 8 ),
     982 [ #  # ][ #  # ]:          0 :     mpCacheItem( rCacheField.GetItem( nCacheIdx ) )
     983                 :            : {
     984                 :          0 :     maItemInfo.mnType = EXC_SXVI_TYPE_DATA;
     985                 :          0 :     maItemInfo.mnCacheIdx = nCacheIdx;
     986                 :          0 :     maItemInfo.maVisName.mbUseCache = mpCacheItem != 0;
     987                 :          0 : }
     988                 :            : 
     989                 :          0 : XclExpPTItem::XclExpPTItem( sal_uInt16 nItemType, sal_uInt16 nCacheIdx, bool bUseCache ) :
     990                 :            :     XclExpRecord( EXC_ID_SXVI, 8 ),
     991         [ #  # ]:          0 :     mpCacheItem( 0 )
     992                 :            : {
     993                 :          0 :     maItemInfo.mnType = nItemType;
     994                 :          0 :     maItemInfo.mnCacheIdx = nCacheIdx;
     995                 :          0 :     maItemInfo.maVisName.mbUseCache = bUseCache;
     996                 :          0 : }
     997                 :            : 
     998                 :          0 : rtl::OUString XclExpPTItem::GetItemName() const
     999                 :            : {
    1000         [ #  # ]:          0 :     return mpCacheItem ? mpCacheItem->ConvertToText() : rtl::OUString();
    1001                 :            : }
    1002                 :            : 
    1003                 :          0 : void XclExpPTItem::SetPropertiesFromMember( const ScDPSaveMember& rSaveMem )
    1004                 :            : {
    1005                 :            :     // #i115659# GetIsVisible() is not valid if HasIsVisible() returns false, default is 'visible' then
    1006 [ #  # ][ #  # ]:          0 :     ::set_flag( maItemInfo.mnFlags, EXC_SXVI_HIDDEN, rSaveMem.HasIsVisible() && !rSaveMem.GetIsVisible() );
    1007                 :            :     // #i115659# GetShowDetails() is not valid if HasShowDetails() returns false, default is 'show detail' then
    1008 [ #  # ][ #  # ]:          0 :     ::set_flag( maItemInfo.mnFlags, EXC_SXVI_HIDEDETAIL, rSaveMem.HasShowDetails() && !rSaveMem.GetShowDetails() );
    1009                 :            : 
    1010                 :            :     // visible name
    1011                 :          0 :     const OUString* pVisName = rSaveMem.GetLayoutName();
    1012 [ #  # ][ #  # ]:          0 :     if (pVisName && !pVisName->equals(GetItemName()))
         [ #  # ][ #  # ]
    1013                 :          0 :         maItemInfo.SetVisName(*pVisName);
    1014                 :          0 : }
    1015                 :            : 
    1016                 :          0 : void XclExpPTItem::WriteBody( XclExpStream& rStrm )
    1017                 :            : {
    1018                 :          0 :     rStrm << maItemInfo;
    1019                 :          0 : }
    1020                 :            : 
    1021                 :            : // ============================================================================
    1022                 :            : 
    1023                 :          0 : XclExpPTField::XclExpPTField( const XclExpPivotTable& rPTable, sal_uInt16 nCacheIdx ) :
    1024                 :            :     mrPTable( rPTable ),
    1025 [ #  # ][ #  # ]:          0 :     mpCacheField( rPTable.GetCacheField( nCacheIdx ) )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1026                 :            : {
    1027                 :          0 :     maFieldInfo.mnCacheIdx = nCacheIdx;
    1028                 :            : 
    1029                 :            :     // create field items
    1030         [ #  # ]:          0 :     if( mpCacheField )
    1031 [ #  # ][ #  # ]:          0 :         for( sal_uInt16 nItemIdx = 0, nItemCount = mpCacheField->GetItemCount(); nItemIdx < nItemCount; ++nItemIdx )
    1032 [ #  # ][ #  # ]:          0 :             maItemList.AppendNewRecord( new XclExpPTItem( *mpCacheField, nItemIdx ) );
                 [ #  # ]
    1033                 :          0 :     maFieldInfo.mnItemCount = static_cast< sal_uInt16 >( maItemList.GetSize() );
    1034                 :          0 : }
    1035                 :            : 
    1036                 :            : // data access ----------------------------------------------------------------
    1037                 :            : 
    1038                 :          0 : rtl::OUString XclExpPTField::GetFieldName() const
    1039                 :            : {
    1040         [ #  # ]:          0 :     return mpCacheField ? mpCacheField->GetFieldName() : rtl::OUString();
    1041                 :            : }
    1042                 :            : 
    1043                 :          0 : sal_uInt16 XclExpPTField::GetFieldIndex() const
    1044                 :            : {
    1045                 :            :     // field index always equal to cache index
    1046                 :          0 :     return maFieldInfo.mnCacheIdx;
    1047                 :            : }
    1048                 :            : 
    1049                 :          0 : sal_uInt16 XclExpPTField::GetLastDataInfoIndex() const
    1050                 :            : {
    1051                 :            :     OSL_ENSURE( !maDataInfoVec.empty(), "XclExpPTField::GetLastDataInfoIndex - no data info found" );
    1052                 :            :     // will return 0xFFFF for empty vector -> ok
    1053                 :          0 :     return static_cast< sal_uInt16 >( maDataInfoVec.size() - 1 );
    1054                 :            : }
    1055                 :            : 
    1056                 :          0 : sal_uInt16 XclExpPTField::GetItemIndex( const rtl::OUString& rName, sal_uInt16 nDefaultIdx ) const
    1057                 :            : {
    1058         [ #  # ]:          0 :     for( size_t nPos = 0, nSize = maItemList.GetSize(); nPos < nSize; ++nPos )
    1059         [ #  # ]:          0 :         if( maItemList.GetRecord( nPos )->GetItemName() == rName )
    1060                 :          0 :             return static_cast< sal_uInt16 >( nPos );
    1061                 :          0 :     return nDefaultIdx;
    1062                 :            : }
    1063                 :            : 
    1064                 :            : // fill data --------------------------------------------------------------
    1065                 :            : 
    1066                 :            : /**
    1067                 :            :  * Calc's subtotal names are escaped with backslashes ('\'), while Excel's
    1068                 :            :  * are not escaped at all.
    1069                 :            :  */
    1070                 :          0 : static OUString lcl_convertCalcSubtotalName(const OUString& rName)
    1071                 :            : {
    1072                 :          0 :     OUStringBuffer aBuf;
    1073                 :          0 :     const sal_Unicode* p = rName.getStr();
    1074                 :          0 :     sal_Int32 n = rName.getLength();
    1075                 :          0 :     bool bEscaped = false;
    1076         [ #  # ]:          0 :     for (sal_Int32 i = 0; i < n; ++i)
    1077                 :            :     {
    1078                 :          0 :         const sal_Unicode c = p[i];
    1079 [ #  # ][ #  # ]:          0 :         if (!bEscaped && c == sal_Unicode('\\'))
    1080                 :            :         {
    1081                 :          0 :             bEscaped = true;
    1082                 :          0 :             continue;
    1083                 :            :         }
    1084                 :            : 
    1085         [ #  # ]:          0 :         aBuf.append(c);
    1086                 :          0 :         bEscaped = false;
    1087                 :            :     }
    1088         [ #  # ]:          0 :     return aBuf.makeStringAndClear();
    1089                 :            : }
    1090                 :            : 
    1091                 :          0 : void XclExpPTField::SetPropertiesFromDim( const ScDPSaveDimension& rSaveDim )
    1092                 :            : {
    1093                 :            :     // orientation
    1094                 :          0 :     DataPilotFieldOrientation eOrient = static_cast< DataPilotFieldOrientation >( rSaveDim.GetOrientation() );
    1095                 :            :     OSL_ENSURE( eOrient != DataPilotFieldOrientation_DATA, "XclExpPTField::SetPropertiesFromDim - called for data field" );
    1096         [ #  # ]:          0 :     maFieldInfo.AddApiOrient( eOrient );
    1097                 :            : 
    1098                 :            :     // show empty items (#i115659# GetShowEmpty() is not valid if HasShowEmpty() returns false, default is false then)
    1099 [ #  # ][ #  # ]:          0 :     ::set_flag( maFieldExtInfo.mnFlags, EXC_SXVDEX_SHOWALL, rSaveDim.HasShowEmpty() && rSaveDim.GetShowEmpty() );
                 [ #  # ]
    1100                 :            : 
    1101                 :            :     // visible name
    1102         [ #  # ]:          0 :     const OUString* pLayoutName = rSaveDim.GetLayoutName();
    1103 [ #  # ][ #  # ]:          0 :     if (pLayoutName && !pLayoutName->equals(GetFieldName()))
         [ #  # ][ #  # ]
    1104         [ #  # ]:          0 :         maFieldInfo.SetVisName(*pLayoutName);
    1105                 :            : 
    1106         [ #  # ]:          0 :     const rtl::OUString* pSubtotalName = rSaveDim.GetSubtotalName();
    1107         [ #  # ]:          0 :     if (pSubtotalName)
    1108                 :            :     {
    1109         [ #  # ]:          0 :         OUString aSubName = lcl_convertCalcSubtotalName(*pSubtotalName);
    1110 [ #  # ][ #  # ]:          0 :         maFieldExtInfo.mpFieldTotalName.reset(new rtl::OUString(aSubName));
    1111                 :            :     }
    1112                 :            : 
    1113                 :            :     // subtotals
    1114         [ #  # ]:          0 :     XclPTSubtotalVec aSubtotals;
    1115         [ #  # ]:          0 :     aSubtotals.reserve( static_cast< size_t >( rSaveDim.GetSubTotalsCount() ) );
    1116         [ #  # ]:          0 :     for( long nSubtIdx = 0, nSubtCount = rSaveDim.GetSubTotalsCount(); nSubtIdx < nSubtCount; ++nSubtIdx )
    1117         [ #  # ]:          0 :         aSubtotals.push_back( rSaveDim.GetSubTotalFunc( nSubtIdx ) );
    1118         [ #  # ]:          0 :     maFieldInfo.SetSubtotals( aSubtotals );
    1119                 :            : 
    1120                 :            :     // sorting
    1121         [ #  # ]:          0 :     if( const DataPilotFieldSortInfo* pSortInfo = rSaveDim.GetSortInfo() )
    1122                 :            :     {
    1123         [ #  # ]:          0 :         maFieldExtInfo.SetApiSortMode( pSortInfo->Mode );
    1124         [ #  # ]:          0 :         if( pSortInfo->Mode == ::com::sun::star::sheet::DataPilotFieldSortMode::DATA )
    1125         [ #  # ]:          0 :             maFieldExtInfo.mnSortField = mrPTable.GetDataFieldIndex( pSortInfo->Field, EXC_SXVDEX_SORT_OWN );
    1126                 :          0 :         ::set_flag( maFieldExtInfo.mnFlags, EXC_SXVDEX_SORT_ASC, pSortInfo->IsAscending );
    1127                 :            :     }
    1128                 :            : 
    1129                 :            :     // auto show
    1130         [ #  # ]:          0 :     if( const DataPilotFieldAutoShowInfo* pShowInfo = rSaveDim.GetAutoShowInfo() )
    1131                 :            :     {
    1132                 :          0 :         ::set_flag( maFieldExtInfo.mnFlags, EXC_SXVDEX_AUTOSHOW, pShowInfo->IsEnabled );
    1133         [ #  # ]:          0 :         maFieldExtInfo.SetApiAutoShowMode( pShowInfo->ShowItemsMode );
    1134         [ #  # ]:          0 :         maFieldExtInfo.SetApiAutoShowCount( pShowInfo->ItemCount );
    1135         [ #  # ]:          0 :         maFieldExtInfo.mnShowField = mrPTable.GetDataFieldIndex( pShowInfo->DataField, EXC_SXVDEX_SHOW_NONE );
    1136                 :            :     }
    1137                 :            : 
    1138                 :            :     // layout
    1139         [ #  # ]:          0 :     if( const DataPilotFieldLayoutInfo* pLayoutInfo = rSaveDim.GetLayoutInfo() )
    1140                 :            :     {
    1141         [ #  # ]:          0 :         maFieldExtInfo.SetApiLayoutMode( pLayoutInfo->LayoutMode );
    1142                 :          0 :         ::set_flag( maFieldExtInfo.mnFlags, EXC_SXVDEX_LAYOUT_BLANK, pLayoutInfo->AddEmptyLines );
    1143                 :            :     }
    1144                 :            : 
    1145                 :            :     // special page field properties
    1146         [ #  # ]:          0 :     if( eOrient == DataPilotFieldOrientation_PAGE )
    1147                 :            :     {
    1148                 :          0 :         maPageInfo.mnField = GetFieldIndex();
    1149                 :            : 
    1150                 :            :         // selected item
    1151 [ #  # ][ #  # ]:          0 :         if( rSaveDim.HasCurrentPage() )
    1152 [ #  # ][ #  # ]:          0 :             maPageInfo.mnSelItem = GetItemIndex( rSaveDim.GetCurrentPage(), EXC_SXPI_ALLITEMS );
    1153                 :            :         else
    1154                 :          0 :             maPageInfo.mnSelItem = EXC_SXPI_ALLITEMS;
    1155                 :            :     }
    1156                 :            : 
    1157                 :            :     // item properties
    1158                 :          0 :     const ScDPSaveDimension::MemberList &rMembers = rSaveDim.GetMembers();
    1159         [ #  # ]:          0 :     for (ScDPSaveDimension::MemberList::const_iterator i=rMembers.begin(); i != rMembers.end() ; ++i)
    1160 [ #  # ][ #  # ]:          0 :         if( XclExpPTItem* pItem = GetItemAcc( (*i)->GetName() ) )
    1161         [ #  # ]:          0 :             pItem->SetPropertiesFromMember( **i );
    1162                 :          0 : }
    1163                 :            : 
    1164                 :          0 : void XclExpPTField::SetDataPropertiesFromDim( const ScDPSaveDimension& rSaveDim )
    1165                 :            : {
    1166         [ #  # ]:          0 :     maDataInfoVec.push_back( XclPTDataFieldInfo() );
    1167                 :          0 :     XclPTDataFieldInfo& rDataInfo = maDataInfoVec.back();
    1168                 :          0 :     rDataInfo.mnField = GetFieldIndex();
    1169                 :            : 
    1170                 :            :     // orientation
    1171                 :          0 :     maFieldInfo.AddApiOrient( DataPilotFieldOrientation_DATA );
    1172                 :            : 
    1173                 :            :     // aggregation function
    1174                 :          0 :     GeneralFunction eFunc = static_cast< GeneralFunction >( rSaveDim.GetFunction() );
    1175                 :          0 :     rDataInfo.SetApiAggFunc( eFunc );
    1176                 :            : 
    1177                 :            :     // visible name
    1178                 :          0 :     const rtl::OUString* pVisName = rSaveDim.GetLayoutName();
    1179         [ #  # ]:          0 :     if (pVisName)
    1180                 :          0 :         rDataInfo.SetVisName(*pVisName);
    1181                 :            :     else
    1182 [ #  # ][ #  # ]:          0 :         rDataInfo.SetVisName( lclGetDataFieldCaption( GetFieldName(), eFunc ) );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1183                 :            : 
    1184                 :            :     // result field reference
    1185         [ #  # ]:          0 :     if( const DataPilotFieldReference* pFieldRef = rSaveDim.GetReferenceValue() )
    1186                 :            :     {
    1187                 :          0 :         rDataInfo.SetApiRefType( pFieldRef->ReferenceType );
    1188                 :          0 :         rDataInfo.SetApiRefItemType( pFieldRef->ReferenceItemType );
    1189         [ #  # ]:          0 :         if( const XclExpPTField* pRefField = mrPTable.GetField( pFieldRef->ReferenceField ) )
    1190                 :            :         {
    1191                 :          0 :             rDataInfo.mnRefField = pRefField->GetFieldIndex();
    1192         [ #  # ]:          0 :             if( pFieldRef->ReferenceItemType == ::com::sun::star::sheet::DataPilotFieldReferenceItemType::NAMED )
    1193                 :          0 :                 rDataInfo.mnRefItem = pRefField->GetItemIndex( pFieldRef->ReferenceItemName, 0 );
    1194                 :            :         }
    1195                 :            :     }
    1196                 :          0 : }
    1197                 :            : 
    1198                 :          0 : void XclExpPTField::AppendSubtotalItems()
    1199                 :            : {
    1200         [ #  # ]:          0 :     if( maFieldInfo.mnSubtotals & EXC_SXVD_SUBT_DEFAULT )   AppendSubtotalItem( EXC_SXVI_TYPE_DEFAULT );
    1201         [ #  # ]:          0 :     if( maFieldInfo.mnSubtotals & EXC_SXVD_SUBT_SUM )       AppendSubtotalItem( EXC_SXVI_TYPE_SUM );
    1202         [ #  # ]:          0 :     if( maFieldInfo.mnSubtotals & EXC_SXVD_SUBT_COUNT )     AppendSubtotalItem( EXC_SXVI_TYPE_COUNT );
    1203         [ #  # ]:          0 :     if( maFieldInfo.mnSubtotals & EXC_SXVD_SUBT_AVERAGE )   AppendSubtotalItem( EXC_SXVI_TYPE_AVERAGE );
    1204         [ #  # ]:          0 :     if( maFieldInfo.mnSubtotals & EXC_SXVD_SUBT_MAX )       AppendSubtotalItem( EXC_SXVI_TYPE_MAX );
    1205         [ #  # ]:          0 :     if( maFieldInfo.mnSubtotals & EXC_SXVD_SUBT_MIN )       AppendSubtotalItem( EXC_SXVI_TYPE_MIN );
    1206         [ #  # ]:          0 :     if( maFieldInfo.mnSubtotals & EXC_SXVD_SUBT_PROD )      AppendSubtotalItem( EXC_SXVI_TYPE_PROD );
    1207         [ #  # ]:          0 :     if( maFieldInfo.mnSubtotals & EXC_SXVD_SUBT_COUNTNUM )  AppendSubtotalItem( EXC_SXVI_TYPE_COUNTNUM );
    1208         [ #  # ]:          0 :     if( maFieldInfo.mnSubtotals & EXC_SXVD_SUBT_STDDEV )    AppendSubtotalItem( EXC_SXVI_TYPE_STDDEV );
    1209         [ #  # ]:          0 :     if( maFieldInfo.mnSubtotals & EXC_SXVD_SUBT_STDDEVP )   AppendSubtotalItem( EXC_SXVI_TYPE_STDDEVP );
    1210         [ #  # ]:          0 :     if( maFieldInfo.mnSubtotals & EXC_SXVD_SUBT_VAR )       AppendSubtotalItem( EXC_SXVI_TYPE_VAR );
    1211         [ #  # ]:          0 :     if( maFieldInfo.mnSubtotals & EXC_SXVD_SUBT_VARP )      AppendSubtotalItem( EXC_SXVI_TYPE_VARP );
    1212                 :          0 : }
    1213                 :            : 
    1214                 :            : // records --------------------------------------------------------------------
    1215                 :            : 
    1216                 :          0 : void XclExpPTField::WriteSxpiEntry( XclExpStream& rStrm ) const
    1217                 :            : {
    1218                 :          0 :     rStrm << maPageInfo;
    1219                 :          0 : }
    1220                 :            : 
    1221                 :          0 : void XclExpPTField::WriteSxdi( XclExpStream& rStrm, sal_uInt16 nDataInfoIdx ) const
    1222                 :            : {
    1223                 :            :     OSL_ENSURE( nDataInfoIdx < maDataInfoVec.size(), "XclExpPTField::WriteSxdi - data field not found" );
    1224         [ #  # ]:          0 :     if( nDataInfoIdx < maDataInfoVec.size() )
    1225                 :            :     {
    1226                 :          0 :         rStrm.StartRecord( EXC_ID_SXDI, 12 );
    1227                 :          0 :         rStrm << maDataInfoVec[ nDataInfoIdx ];
    1228                 :          0 :         rStrm.EndRecord();
    1229                 :            :     }
    1230                 :          0 : }
    1231                 :            : 
    1232                 :          0 : void XclExpPTField::Save( XclExpStream& rStrm )
    1233                 :            : {
    1234                 :            :     // SXVD
    1235                 :          0 :     WriteSxvd( rStrm );
    1236                 :            :     // list of SXVI records
    1237                 :          0 :     maItemList.Save( rStrm );
    1238                 :            :     // SXVDEX
    1239                 :          0 :     WriteSxvdex( rStrm );
    1240                 :          0 : }
    1241                 :            : 
    1242                 :            : // private --------------------------------------------------------------------
    1243                 :            : 
    1244                 :          0 : XclExpPTItem* XclExpPTField::GetItemAcc( const rtl::OUString& rName )
    1245                 :            : {
    1246                 :          0 :     XclExpPTItem* pItem = 0;
    1247 [ #  # ][ #  # ]:          0 :     for( size_t nPos = 0, nSize = maItemList.GetSize(); !pItem && (nPos < nSize); ++nPos )
                 [ #  # ]
    1248         [ #  # ]:          0 :         if( maItemList.GetRecord( nPos )->GetItemName() == rName )
    1249                 :          0 :             pItem = maItemList.GetRecord( nPos ).get();
    1250                 :          0 :     return pItem;
    1251                 :            : }
    1252                 :            : 
    1253                 :          0 : void XclExpPTField::AppendSubtotalItem( sal_uInt16 nItemType )
    1254                 :            : {
    1255         [ #  # ]:          0 :     maItemList.AppendNewRecord( new XclExpPTItem( nItemType, EXC_SXVI_DEFAULT_CACHE, true ) );
    1256                 :          0 :     ++maFieldInfo.mnItemCount;
    1257                 :          0 : }
    1258                 :            : 
    1259                 :          0 : void XclExpPTField::WriteSxvd( XclExpStream& rStrm ) const
    1260                 :            : {
    1261                 :          0 :     rStrm.StartRecord( EXC_ID_SXVD, 10 );
    1262                 :          0 :     rStrm << maFieldInfo;
    1263                 :          0 :     rStrm.EndRecord();
    1264                 :          0 : }
    1265                 :            : 
    1266                 :          0 : void XclExpPTField::WriteSxvdex( XclExpStream& rStrm ) const
    1267                 :            : {
    1268                 :          0 :     rStrm.StartRecord( EXC_ID_SXVDEX, 20 );
    1269                 :          0 :     rStrm << maFieldExtInfo;
    1270                 :          0 :     rStrm.EndRecord();
    1271                 :          0 : }
    1272                 :            : 
    1273                 :            : // ============================================================================
    1274                 :            : 
    1275                 :          0 : XclExpPivotTable::XclExpPivotTable( const XclExpRoot& rRoot, const ScDPObject& rDPObj, const XclExpPivotCache& rPCache ) :
    1276                 :            :     XclExpRoot( rRoot ),
    1277                 :            :     mrPCache( rPCache ),
    1278                 :            :     maDataOrientField( *this, EXC_SXIVD_DATA ),
    1279                 :            :     mnOutScTab( 0 ),
    1280                 :            :     mbValid( false ),
    1281 [ #  # ][ #  # ]:          0 :     mbFilterBtn( false )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1282                 :            : {
    1283                 :          0 :     const ScRange& rOutScRange = rDPObj.GetOutRange();
    1284 [ #  # ][ #  # ]:          0 :     if( GetAddressConverter().ConvertRange( maPTInfo.maOutXclRange, rOutScRange, true ) )
                 [ #  # ]
    1285                 :            :     {
    1286                 :            :         // DataPilot properties -----------------------------------------------
    1287                 :            : 
    1288                 :            :         // pivot table properties from DP object
    1289                 :          0 :         mnOutScTab = rOutScRange.aStart.Tab();
    1290                 :          0 :         maPTInfo.maTableName = rDPObj.GetName();
    1291                 :          0 :         maPTInfo.mnCacheIdx = mrPCache.GetCacheIndex();
    1292                 :            : 
    1293         [ #  # ]:          0 :         maPTViewEx9Info.Init( rDPObj );
    1294                 :            : 
    1295         [ #  # ]:          0 :         if( const ScDPSaveData* pSaveData = rDPObj.GetSaveData() )
    1296                 :            :         {
    1297                 :            :             // additional properties from ScDPSaveData
    1298         [ #  # ]:          0 :             SetPropertiesFromDP( *pSaveData );
    1299                 :            : 
    1300                 :            :             // loop over all dimensions ---------------------------------------
    1301                 :            : 
    1302                 :            :             /*  1)  Default-construct all pivot table fields for all pivot cache fields. */
    1303 [ #  # ][ #  # ]:          0 :             for( sal_uInt16 nFieldIdx = 0, nFieldCount = mrPCache.GetFieldCount(); nFieldIdx < nFieldCount; ++nFieldIdx )
    1304 [ #  # ][ #  # ]:          0 :                 maFieldList.AppendNewRecord( new XclExpPTField( *this, nFieldIdx ) );
                 [ #  # ]
    1305                 :            : 
    1306         [ #  # ]:          0 :             boost::ptr_vector<ScDPSaveDimension>::const_iterator iter;
    1307         [ #  # ]:          0 :             const ScDPSaveData::DimsType& rDimList = pSaveData->GetDimensions();
    1308                 :            : 
    1309                 :            :             /*  2)  First process all data dimensions, they are needed for extended
    1310                 :            :                     settings of row/column/page fields (sorting/auto show). */
    1311 [ #  # ][ #  # ]:          0 :             for (iter = rDimList.begin(); iter != rDimList.end(); ++iter)
         [ #  # ][ #  # ]
                 [ #  # ]
    1312 [ #  # ][ #  # ]:          0 :                 if (iter->GetOrientation() == DataPilotFieldOrientation_DATA)
    1313 [ #  # ][ #  # ]:          0 :                     SetDataFieldPropertiesFromDim(*iter);
    1314                 :            : 
    1315                 :            :             /*  3)  Row/column/page/hidden fields. */
    1316 [ #  # ][ #  # ]:          0 :             for (iter = rDimList.begin(); iter != rDimList.end(); ++iter)
         [ #  # ][ #  # ]
                 [ #  # ]
    1317 [ #  # ][ #  # ]:          0 :                 if (iter->GetOrientation() != DataPilotFieldOrientation_DATA)
    1318 [ #  # ][ #  # ]:          0 :                     SetFieldPropertiesFromDim(*iter);
    1319                 :            : 
    1320                 :            :             // Finalize -------------------------------------------------------
    1321                 :            : 
    1322         [ #  # ]:          0 :             Finalize();
    1323                 :          0 :             mbValid = true;
    1324                 :            :         }
    1325                 :            :     }
    1326                 :          0 : }
    1327                 :            : 
    1328                 :          0 : const XclExpPCField* XclExpPivotTable::GetCacheField( sal_uInt16 nCacheIdx ) const
    1329                 :            : {
    1330                 :          0 :     return mrPCache.GetField( nCacheIdx );
    1331                 :            : }
    1332                 :            : 
    1333                 :          0 : const XclExpPTField* XclExpPivotTable::GetField( sal_uInt16 nFieldIdx ) const
    1334                 :            : {
    1335 [ #  # ][ #  # ]:          0 :     return (nFieldIdx == EXC_SXIVD_DATA) ? &maDataOrientField : maFieldList.GetRecord( nFieldIdx ).get();
         [ #  # ][ #  # ]
    1336                 :            : }
    1337                 :            : 
    1338                 :          0 : const XclExpPTField* XclExpPivotTable::GetField( const rtl::OUString& rName ) const
    1339                 :            : {
    1340                 :          0 :     return const_cast< XclExpPivotTable* >( this )->GetFieldAcc( rName );
    1341                 :            : }
    1342                 :            : 
    1343                 :          0 : sal_uInt16 XclExpPivotTable::GetDataFieldIndex( const rtl::OUString& rName, sal_uInt16 nDefaultIdx ) const
    1344                 :            : {
    1345 [ #  # ][ #  # ]:          0 :     for( XclPTDataFieldPosVec::const_iterator aIt = maDataFields.begin(), aEnd = maDataFields.end(); aIt != aEnd; ++aIt )
                 [ #  # ]
    1346 [ #  # ][ #  # ]:          0 :         if( const XclExpPTField* pField = GetField( aIt->first ) )
                 [ #  # ]
    1347         [ #  # ]:          0 :             if( pField->GetFieldName() == rName )
    1348         [ #  # ]:          0 :                 return static_cast< sal_uInt16 >( aIt - maDataFields.begin() );
    1349                 :          0 :     return nDefaultIdx;
    1350                 :            : }
    1351                 :            : 
    1352                 :          0 : void XclExpPivotTable::Save( XclExpStream& rStrm )
    1353                 :            : {
    1354         [ #  # ]:          0 :     if( mbValid )
    1355                 :            :     {
    1356                 :            :         // SXVIEW
    1357                 :          0 :         WriteSxview( rStrm );
    1358                 :            :         // pivot table fields (SXVD, SXVDEX, and item records)
    1359                 :          0 :         maFieldList.Save( rStrm );
    1360                 :            :         // SXIVD records for row and column fields
    1361                 :          0 :         WriteSxivd( rStrm, maRowFields );
    1362                 :          0 :         WriteSxivd( rStrm, maColFields );
    1363                 :            :         // SXPI
    1364                 :          0 :         WriteSxpi( rStrm );
    1365                 :            :         // list of SXDI records containing data field info
    1366                 :          0 :         WriteSxdiList( rStrm );
    1367                 :            :         // SXLI records
    1368                 :          0 :         WriteSxli( rStrm, maPTInfo.mnDataRows, maPTInfo.mnRowFields );
    1369                 :          0 :         WriteSxli( rStrm, maPTInfo.mnDataCols, maPTInfo.mnColFields );
    1370                 :            :         // SXEX
    1371                 :          0 :         WriteSxex( rStrm );
    1372                 :            :         // QSISXTAG
    1373                 :          0 :         WriteQsiSxTag( rStrm );
    1374                 :            :         // SXVIEWEX9
    1375                 :          0 :         WriteSxViewEx9( rStrm );
    1376                 :            :     }
    1377                 :          0 : }
    1378                 :            : 
    1379                 :          0 : void XclExpPivotTable::SaveXml( XclExpXmlStream& rStrm )
    1380                 :            : {
    1381         [ #  # ]:          0 :     if( !mbValid )
    1382                 :          0 :         return;
    1383                 :            :     sax_fastparser::FSHelperPtr aPivotTableDefinition = rStrm.CreateOutputStream(
    1384                 :            :             XclXmlUtils::GetStreamName( "xl/", "pivotTables/pivotTable", mnOutScTab+1),
    1385                 :            :             XclXmlUtils::GetStreamName( "../", "pivotTables/pivotTable", mnOutScTab+1),
    1386         [ #  # ]:          0 :             rStrm.GetCurrentStream()->getOutputStream(),
    1387                 :            :             "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml",
    1388 [ #  # ][ #  # ]:          0 :             "http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotTable");
         [ #  # ][ #  # ]
    1389 [ #  # ][ #  # ]:          0 :     rStrm.PushStream( aPivotTableDefinition );
                 [ #  # ]
    1390                 :            : 
    1391                 :            :     aPivotTableDefinition->startElement( XML_pivotTableDefinition,
    1392                 :            :             XML_xmlns,                      "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
    1393                 :            :             XML_name,                       XclXmlUtils::ToOString( maPTInfo.maTableName ).getStr(),
    1394                 :            :             XML_cacheId,                    OString::valueOf( (sal_Int32) maPTInfo.mnCacheIdx ).getStr(),
    1395                 :            :             XML_dataOnRows,                 XclXmlUtils::ToPsz( maPTInfo.mnDataAxis == EXC_SXVD_AXIS_COL ),
    1396                 :            :             XML_dataPosition,               OString::valueOf( (sal_Int32) maPTInfo.mnDataPos ).getStr(),
    1397                 :            :             XML_autoFormatId,               OString::valueOf( (sal_Int32) maPTInfo.mnAutoFmtIdx ).getStr(),
    1398                 :            :             // OOXTODO: XML_applyNumberFormats,         [ SXVIEW fAtrNum (maPTInfo.mnFlags) ]
    1399                 :            :             // OOXTODO: XML_applyBorderFormats,         [ SXVIEW fAtrBdr (maPTInfo.mnFlags) ]
    1400                 :            :             // OOXTODO: XML_applyFontFormats,           [ SXVIEW fAtrFnt (maPTInfo.mnFlags) ]
    1401                 :            :             // OOXTODO: XML_applyPatternFormats,        [ SXVIEW fAtrPat (maPTInfo.mnFlags) ]
    1402                 :            :             // OOXTODO: XML_applyAlignmentFormats,      [ SXVIEW fAtrAlc (maPTInfo.mnFlags) ]
    1403                 :            :             // OOXTODO: XML_applyWidthHeightFormats,    [ SXVIEW fAtrProc (maPTInfo.mnFlags) ]
    1404                 :            :             XML_dataCaption,                XclXmlUtils::ToOString( maPTInfo.maDataName ).getStr(),
    1405                 :            :             // OOXTODO: XML_grandTotalCaption,          [ SxViewEx9 chGrand ]
    1406                 :            :             // OOXTODO: XML_errorCaption,               [ SXEx stError ]
    1407                 :            :             // OOXTODO: XML_showError,                  [ SXEx fDisplayErrorString ]
    1408                 :            :             // OOXTODO: XML_missingCaption,             [ SXEx stDisplayNull ]
    1409                 :            :             // OOXTODO: XML_showMissing,                [ SXEx fDisplayNullString ]
    1410                 :            :             // OOXTODO: XML_pageStyle,                  [ SXEx stPageFieldStyle ]
    1411                 :            :             // OOXTODO: XML_pivotTableStyle,            [ SXEx stTableStyle ]
    1412                 :            :             // OOXTODO: XML_vacatedStyle,               [ SXEx stVacateStyle ]
    1413                 :            :             // OOXTODO: XML_tag,                        [ SXEx stTag ]
    1414                 :            :             // OOXTODO: XML_updatedVersion,             [ app-dependent ]
    1415                 :            :             // OOXTODO: XML_minRefreshableVersion,      [ app-dependent ]
    1416                 :            :             // OOXTODO: XML_asteriskTotals,             [ QsiSXTag/SXView9Save fHideTotAnnotation ]
    1417                 :            :             // OOXTODO: XML_showItems,                  [ ??? ]
    1418                 :            :             // OOXTODO: XML_editData,                   [ ??? ]
    1419                 :            :             // OOXTODO: XML_disableFieldList,           [ SXEx fEnableFieldDialog? ]
    1420                 :            :             // OOXTODO: XML_showCalcMbrs,               [ ??? ]
    1421                 :            :             // OOXTODO: XML_visualTotals,               [ ??? ]
    1422                 :            :             // OOXTODO: XML_showMultipleLabel,          [ SXEx fMergeLabels? ]
    1423                 :            :             // OOXTODO: XML_showDataDropDown,           [ SXEx fEnableDrillDown? ]
    1424                 :            :             // OOXTODO: XML_showDrill,                  [ ??? ]
    1425                 :            :             // OOXTODO: XML_printDrill,                 [ ??? ]
    1426                 :            :             // OOXTODO: XML_showMemberPropertyTips,
    1427                 :            :             // OOXTODO: XML_showDataTips,
    1428                 :            :             // OOXTODO: XML_enableWizard,
    1429                 :            :             XML_enableDrill,                XclXmlUtils::ToPsz( maPTExtInfo.mnFlags & EXC_SXEX_DRILLDOWN ), // ???
    1430                 :            :             // OOXTODO: XML_enableFieldProperties,      [ SXEx fEnableFieldDialog (maPTExtInfo.mnFlags) ]
    1431                 :            :             // OOXTODO: XML_preserveFormatting,         [ SXEx fPreserveFormatting (maPTExtInfo.mnFlags) ]
    1432                 :            :             // OOXTODO: XML_pageWrap,                   [ SXEx cWrapPage (maPTExtInfo.mnFlags) ]
    1433                 :            :             // OOXTODO: XML_pageOverThenDown,           [ SXEx fAcrossPageLay (maPTExtInfo.mnFlags) ]
    1434                 :            :             // OOXTODO: XML_subtotalHiddenItems,        [ SXEx fSubtotalHiddenPageItems (maPTExtInfo.mnFlags) ]
    1435                 :            :             XML_rowGrandTotals,             XclXmlUtils::ToPsz( maPTInfo.mnFlags & EXC_SXVIEW_ROWGRAND ),
    1436                 :            :             XML_colGrandTotals,             XclXmlUtils::ToPsz( maPTInfo.mnFlags & EXC_SXVIEW_COLGRAND ),
    1437                 :            :             // OOXTODO: XML_fieldPrintTitles,
    1438                 :            :             // OOXTODO: XML_itemPrintTitles,
    1439                 :            :             // OOXTODO: XML_mergeItem,
    1440                 :            :             // OOXTODO: XML_showDropZones,
    1441                 :            :             // OOXTODO: XML_createdVersion,
    1442                 :            :             // OOXTODO: XML_indent,
    1443                 :            :             // OOXTODO: XML_showEmptyRow,
    1444                 :            :             // OOXTODO: XML_showEmptyCol,
    1445                 :            :             // OOXTODO: XML_showHeaders,
    1446                 :            :             // OOXTODO: XML_compact,
    1447                 :            :             // OOXTODO: XML_outline,
    1448                 :            :             // OOXTODO: XML_outlineData,
    1449                 :            :             // OOXTODO: XML_compactData,
    1450                 :            :             // OOXTODO: XML_published,
    1451                 :            :             // OOXTODO: XML_gridDropZones,
    1452                 :            :             // OOXTODO: XML_immersive,
    1453                 :            :             // OOXTODO: XML_multipleFieldFilters,
    1454                 :            :             // OOXTODO: XML_chartFormat,
    1455                 :            :             // OOXTODO: XML_rowHeaderCaption,
    1456                 :            :             // OOXTODO: XML_colHeaderCaption,
    1457                 :            :             // OOXTODO: XML_fieldListSortAscending,
    1458                 :            :             // OOXTODO: XML_mdxSubqueries,
    1459                 :            :             // OOXTODO: XML_customListSort,
    1460 [ #  # ][ #  # ]:          0 :             FSEND );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1461                 :            : 
    1462                 :            :     aPivotTableDefinition->singleElement( XML_location,
    1463                 :            :             XML_ref,            XclXmlUtils::ToOString( maPTInfo.maOutXclRange ).getStr(),
    1464                 :            :             XML_firstHeaderRow, OString::valueOf( (sal_Int32) maPTInfo.mnFirstHeadRow ).getStr(),
    1465                 :            :             XML_firstDataRow,   OString::valueOf( (sal_Int32) maPTInfo.maDataXclPos.mnRow ).getStr(),
    1466                 :            :             XML_firstDataCol,   OString::valueOf( (sal_Int32) maPTInfo.maDataXclPos.mnCol ).getStr(),
    1467                 :            :             XML_rowPageCount,   OString::valueOf( (sal_Int32) maPTInfo.mnDataRows ).getStr(),   // OOXTODO?
    1468                 :            :             XML_colPageCount,   OString::valueOf( (sal_Int32) maPTInfo.mnDataCols ).getStr(),   // OOXTODO?
    1469 [ #  # ][ #  # ]:          0 :             FSEND );
    1470                 :            : 
    1471                 :            :     // OOXTODO: XML_pivotFields
    1472                 :            : 
    1473                 :            :     // maPTInfo.mnFields?
    1474         [ #  # ]:          0 :     if( maPTInfo.mnRowFields )
    1475                 :            :     {
    1476                 :            :         aPivotTableDefinition->startElement( XML_rowFields,
    1477                 :            :                 XML_count,  OString::valueOf( (sal_Int32) maPTInfo.mnRowFields ).getStr(),
    1478         [ #  # ]:          0 :                 FSEND );
    1479         [ #  # ]:          0 :         aPivotTableDefinition->endElement( XML_rowFields );
    1480                 :            :     }
    1481                 :            : 
    1482                 :            :     // OOXTODO: XML_rowItems
    1483                 :            : 
    1484         [ #  # ]:          0 :     if( maPTInfo.mnColFields )
    1485                 :            :     {
    1486                 :            :         aPivotTableDefinition->startElement( XML_colFields,
    1487                 :            :                 XML_count,  OString::valueOf( (sal_Int32) maPTInfo.mnColFields ).getStr(),
    1488         [ #  # ]:          0 :                 FSEND );
    1489         [ #  # ]:          0 :         aPivotTableDefinition->endElement( XML_colFields );
    1490                 :            :     }
    1491                 :            : 
    1492                 :            :     // OOXTODO: XML_colItems
    1493                 :            : 
    1494         [ #  # ]:          0 :     if( maPTInfo.mnPageFields )
    1495                 :            :     {
    1496                 :            :         aPivotTableDefinition->startElement( XML_pageFields,
    1497                 :            :                 XML_count,  OString::valueOf( (sal_Int32) maPTInfo.mnPageFields ).getStr(),
    1498         [ #  # ]:          0 :                 FSEND );
    1499         [ #  # ]:          0 :         aPivotTableDefinition->endElement( XML_pageFields );
    1500                 :            :     }
    1501                 :            : 
    1502         [ #  # ]:          0 :     if( maPTInfo.mnDataFields )
    1503                 :            :     {
    1504                 :            :         aPivotTableDefinition->startElement( XML_dataFields,
    1505                 :            :                 XML_count,  OString::valueOf( (sal_Int32) maPTInfo.mnDataFields ).getStr(),
    1506         [ #  # ]:          0 :                 FSEND );
    1507         [ #  # ]:          0 :         aPivotTableDefinition->endElement( XML_dataFields );
    1508                 :            :     }
    1509                 :            : 
    1510                 :            :     // OOXTODO: XML_formats, XML_conditionalFormats, XML_chartFormats,
    1511                 :            :     //          XML_pivotHierarchies, XML_pivotTableStyleInfo, XML_filters,
    1512                 :            :     //          XML_rowHierarchiesUsage, XML_colHierarchiesUsage, XML_ext
    1513                 :            : 
    1514         [ #  # ]:          0 :     aPivotTableDefinition->endElement( XML_pivotTableDefinition );
    1515                 :            : 
    1516 [ #  # ][ #  # ]:          0 :     rStrm.PopStream();
    1517                 :            : }
    1518                 :            : 
    1519                 :            : // private --------------------------------------------------------------------
    1520                 :            : 
    1521                 :          0 : XclExpPTField* XclExpPivotTable::GetFieldAcc( const rtl::OUString& rName )
    1522                 :            : {
    1523                 :          0 :     XclExpPTField* pField = 0;
    1524 [ #  # ][ #  # ]:          0 :     for( size_t nPos = 0, nSize = maFieldList.GetSize(); !pField && (nPos < nSize); ++nPos )
                 [ #  # ]
    1525         [ #  # ]:          0 :         if( maFieldList.GetRecord( nPos )->GetFieldName() == rName )
    1526                 :          0 :             pField = maFieldList.GetRecord( nPos ).get();
    1527                 :          0 :     return pField;
    1528                 :            : }
    1529                 :            : 
    1530                 :          0 : XclExpPTField* XclExpPivotTable::GetFieldAcc( const ScDPSaveDimension& rSaveDim )
    1531                 :            : {
    1532                 :            :     // data field orientation field?
    1533         [ #  # ]:          0 :     if( rSaveDim.IsDataLayout() )
    1534                 :          0 :         return &maDataOrientField;
    1535                 :            : 
    1536                 :            :     // a real dimension
    1537         [ #  # ]:          0 :     rtl::OUString aFieldName = ScDPUtil::getSourceDimensionName(rSaveDim.GetName());
    1538 [ #  # ][ #  # ]:          0 :     return aFieldName.isEmpty() ? NULL : GetFieldAcc(aFieldName);
    1539                 :            : }
    1540                 :            : 
    1541                 :            : // fill data --------------------------------------------------------------
    1542                 :            : 
    1543                 :          0 : void XclExpPivotTable::SetPropertiesFromDP( const ScDPSaveData& rSaveData )
    1544                 :            : {
    1545                 :          0 :     ::set_flag( maPTInfo.mnFlags, EXC_SXVIEW_ROWGRAND, rSaveData.GetRowGrand() );
    1546                 :          0 :     ::set_flag( maPTInfo.mnFlags, EXC_SXVIEW_COLGRAND, rSaveData.GetColumnGrand() );
    1547                 :          0 :     ::set_flag( maPTExtInfo.mnFlags, EXC_SXEX_DRILLDOWN, rSaveData.GetDrillDown() );
    1548                 :          0 :     mbFilterBtn = rSaveData.GetFilterButton();
    1549                 :          0 :     const ScDPSaveDimension* pDim = rSaveData.GetExistingDataLayoutDimension();
    1550         [ #  # ]:          0 :     if (!pDim)
    1551                 :          0 :         return;
    1552                 :            : 
    1553                 :          0 :     const rtl::OUString* pLayoutName = pDim->GetLayoutName();
    1554         [ #  # ]:          0 :     if (pLayoutName)
    1555                 :          0 :         maPTInfo.maDataName = *pLayoutName;
    1556                 :            :     else
    1557                 :          0 :         maPTInfo.maDataName = ScGlobal::GetRscString(STR_PIVOT_DATA);
    1558                 :            : }
    1559                 :            : 
    1560                 :          0 : void XclExpPivotTable::SetFieldPropertiesFromDim( const ScDPSaveDimension& rSaveDim )
    1561                 :            : {
    1562         [ #  # ]:          0 :     if( XclExpPTField* pField = GetFieldAcc( rSaveDim ) )
    1563                 :            :     {
    1564                 :            :         // field properties
    1565         [ #  # ]:          0 :         pField->SetPropertiesFromDim( rSaveDim );
    1566                 :            : 
    1567                 :            :         // update the corresponding field position list
    1568                 :          0 :         DataPilotFieldOrientation eOrient = static_cast< DataPilotFieldOrientation >( rSaveDim.GetOrientation() );
    1569                 :          0 :         sal_uInt16 nFieldIdx = pField->GetFieldIndex();
    1570                 :          0 :         bool bDataLayout = nFieldIdx == EXC_SXIVD_DATA;
    1571                 :          0 :         bool bMultiData = maDataFields.size() > 1;
    1572                 :            : 
    1573 [ #  # ][ #  #  :          0 :         if( !bDataLayout || bMultiData ) switch( eOrient )
                #  #  # ]
                 [ #  # ]
    1574                 :            :         {
    1575                 :            :             case DataPilotFieldOrientation_ROW:
    1576         [ #  # ]:          0 :                 maRowFields.push_back( nFieldIdx );
    1577         [ #  # ]:          0 :                 if( bDataLayout )
    1578                 :          0 :                     maPTInfo.mnDataAxis = EXC_SXVD_AXIS_ROW;
    1579                 :          0 :             break;
    1580                 :            :             case DataPilotFieldOrientation_COLUMN:
    1581         [ #  # ]:          0 :                 maColFields.push_back( nFieldIdx );
    1582         [ #  # ]:          0 :                 if( bDataLayout )
    1583                 :          0 :                     maPTInfo.mnDataAxis = EXC_SXVD_AXIS_COL;
    1584                 :          0 :             break;
    1585                 :            :             case DataPilotFieldOrientation_PAGE:
    1586         [ #  # ]:          0 :                 maPageFields.push_back( nFieldIdx );
    1587                 :            :                 OSL_ENSURE( !bDataLayout, "XclExpPivotTable::SetFieldPropertiesFromDim - wrong orientation for data fields" );
    1588                 :          0 :             break;
    1589                 :            :             case DataPilotFieldOrientation_DATA:
    1590                 :            :                 OSL_FAIL( "XclExpPivotTable::SetFieldPropertiesFromDim - called for data field" );
    1591                 :          0 :             break;
    1592                 :            :             default:;
    1593                 :            :         }
    1594                 :            :     }
    1595                 :          0 : }
    1596                 :            : 
    1597                 :          0 : void XclExpPivotTable::SetDataFieldPropertiesFromDim( const ScDPSaveDimension& rSaveDim )
    1598                 :            : {
    1599         [ #  # ]:          0 :     if( XclExpPTField* pField = GetFieldAcc( rSaveDim ) )
    1600                 :            :     {
    1601                 :            :         // field properties
    1602                 :          0 :         pField->SetDataPropertiesFromDim( rSaveDim );
    1603                 :            :         // update the data field position list
    1604 [ #  # ][ #  # ]:          0 :         maDataFields.push_back( XclPTDataFieldPos( pField->GetFieldIndex(), pField->GetLastDataInfoIndex() ) );
    1605                 :            :     }
    1606                 :          0 : }
    1607                 :            : 
    1608                 :          0 : void XclExpPivotTable::Finalize()
    1609                 :            : {
    1610                 :            :     // field numbers
    1611                 :          0 :     maPTInfo.mnFields = static_cast< sal_uInt16 >( maFieldList.GetSize() );
    1612                 :          0 :     maPTInfo.mnRowFields = static_cast< sal_uInt16 >( maRowFields.size() );
    1613                 :          0 :     maPTInfo.mnColFields = static_cast< sal_uInt16 >( maColFields.size() );
    1614                 :          0 :     maPTInfo.mnPageFields = static_cast< sal_uInt16 >( maPageFields.size() );
    1615                 :          0 :     maPTInfo.mnDataFields = static_cast< sal_uInt16 >( maDataFields.size() );
    1616                 :            : 
    1617                 :          0 :     maPTExtInfo.mnPagePerRow = maPTInfo.mnPageFields;
    1618         [ #  # ]:          0 :     maPTExtInfo.mnPagePerCol = (maPTInfo.mnPageFields > 0) ? 1 : 0;
    1619                 :            : 
    1620                 :            :     // subtotal items
    1621         [ #  # ]:          0 :     for( size_t nPos = 0, nSize = maFieldList.GetSize(); nPos < nSize; ++nPos )
    1622         [ #  # ]:          0 :         maFieldList.GetRecord( nPos )->AppendSubtotalItems();
    1623                 :            : 
    1624                 :            :     // find data field orientation field
    1625                 :          0 :     maPTInfo.mnDataPos = EXC_SXVIEW_DATALAST;
    1626                 :          0 :     const ScfUInt16Vec* pFieldVec = 0;
    1627      [ #  #  # ]:          0 :     switch( maPTInfo.mnDataAxis )
    1628                 :            :     {
    1629                 :          0 :         case EXC_SXVD_AXIS_ROW: pFieldVec = &maRowFields;   break;
    1630                 :          0 :         case EXC_SXVD_AXIS_COL: pFieldVec = &maColFields;   break;
    1631                 :            :     }
    1632                 :            : 
    1633 [ #  # ][ #  # ]:          0 :     if( pFieldVec && !pFieldVec->empty() && (pFieldVec->back() != EXC_SXIVD_DATA) )
         [ #  # ][ #  # ]
    1634                 :            :     {
    1635         [ #  # ]:          0 :         ScfUInt16Vec::const_iterator aIt = ::std::find( pFieldVec->begin(), pFieldVec->end(), EXC_SXIVD_DATA );
    1636 [ #  # ][ #  # ]:          0 :         if( aIt != pFieldVec->end() )
    1637         [ #  # ]:          0 :             maPTInfo.mnDataPos = static_cast< sal_uInt16 >( aIt - pFieldVec->begin() );
    1638                 :            :     }
    1639                 :            : 
    1640                 :            :     // single data field is always row oriented
    1641         [ #  # ]:          0 :     if( maPTInfo.mnDataAxis == EXC_SXVD_AXIS_NONE )
    1642                 :          0 :         maPTInfo.mnDataAxis = EXC_SXVD_AXIS_ROW;
    1643                 :            : 
    1644                 :            :     // update output range (initialized in ctor)
    1645                 :          0 :     sal_uInt16& rnXclCol1 = maPTInfo.maOutXclRange.maFirst.mnCol;
    1646                 :          0 :     sal_uInt32& rnXclRow1 = maPTInfo.maOutXclRange.maFirst.mnRow;
    1647                 :          0 :     sal_uInt16& rnXclCol2 = maPTInfo.maOutXclRange.maLast.mnCol;
    1648                 :          0 :     sal_uInt32& rnXclRow2 = maPTInfo.maOutXclRange.maLast.mnRow;
    1649                 :            :     // exclude page fields from output range
    1650                 :          0 :     rnXclRow1 = rnXclRow1 + maPTInfo.mnPageFields;
    1651                 :            :     // exclude filter button from output range
    1652         [ #  # ]:          0 :     if( mbFilterBtn )
    1653                 :          0 :         ++rnXclRow1;
    1654                 :            :     // exclude empty row between (filter button and/or page fields) and table
    1655 [ #  # ][ #  # ]:          0 :     if( mbFilterBtn || maPTInfo.mnPageFields )
    1656                 :          0 :         ++rnXclRow1;
    1657                 :            : 
    1658                 :            :     // data area
    1659                 :          0 :     sal_uInt16& rnDataXclCol = maPTInfo.maDataXclPos.mnCol;
    1660                 :          0 :     sal_uInt32& rnDataXclRow = maPTInfo.maDataXclPos.mnRow;
    1661                 :          0 :     rnDataXclCol = rnXclCol1 + maPTInfo.mnRowFields;
    1662                 :          0 :     rnDataXclRow = rnXclRow1 + maPTInfo.mnColFields + 1;
    1663         [ #  # ]:          0 :     if( maDataFields.empty() )
    1664                 :          0 :         ++rnDataXclRow;
    1665                 :            : 
    1666 [ #  # ][ #  # ]:          0 :     bool bExtraHeaderRow = (0 == maPTViewEx9Info.mnGridLayout && maPTInfo.mnColFields == 0);
    1667         [ #  # ]:          0 :     if (bExtraHeaderRow)
    1668                 :            :         // Insert an extra row only when there is no column field.
    1669                 :          0 :         ++rnDataXclRow;
    1670                 :            : 
    1671                 :          0 :     rnXclCol2 = ::std::max( rnXclCol2, rnDataXclCol );
    1672                 :          0 :     rnXclRow2 = ::std::max( rnXclRow2, rnDataXclRow );
    1673                 :          0 :     maPTInfo.mnDataCols = rnXclCol2 - rnDataXclCol + 1;
    1674                 :          0 :     maPTInfo.mnDataRows = rnXclRow2 - rnDataXclRow + 1;
    1675                 :            : 
    1676                 :            :     // first heading
    1677                 :          0 :     maPTInfo.mnFirstHeadRow = rnXclRow1;
    1678         [ #  # ]:          0 :     if (bExtraHeaderRow)
    1679                 :          0 :         maPTInfo.mnFirstHeadRow += 2;
    1680                 :          0 : }
    1681                 :            : 
    1682                 :            : // records ----------------------------------------------------------------
    1683                 :            : 
    1684                 :          0 : void XclExpPivotTable::WriteSxview( XclExpStream& rStrm ) const
    1685                 :            : {
    1686                 :          0 :     rStrm.StartRecord( EXC_ID_SXVIEW, 46 + maPTInfo.maTableName.getLength() + maPTInfo.maDataName.getLength() );
    1687                 :          0 :     rStrm << maPTInfo;
    1688                 :          0 :     rStrm.EndRecord();
    1689                 :          0 : }
    1690                 :            : 
    1691                 :          0 : void XclExpPivotTable::WriteSxivd( XclExpStream& rStrm, const ScfUInt16Vec& rFields ) const
    1692                 :            : {
    1693         [ #  # ]:          0 :     if( !rFields.empty() )
    1694                 :            :     {
    1695                 :          0 :         rStrm.StartRecord( EXC_ID_SXIVD, rFields.size() * 2 );
    1696 [ #  # ][ #  # ]:          0 :         for( ScfUInt16Vec::const_iterator aIt = rFields.begin(), aEnd = rFields.end(); aIt != aEnd; ++aIt )
                 [ #  # ]
    1697 [ #  # ][ #  # ]:          0 :             rStrm << *aIt;
    1698                 :          0 :         rStrm.EndRecord();
    1699                 :            :     }
    1700                 :          0 : }
    1701                 :            : 
    1702                 :          0 : void XclExpPivotTable::WriteSxpi( XclExpStream& rStrm ) const
    1703                 :            : {
    1704         [ #  # ]:          0 :     if( !maPageFields.empty() )
    1705                 :            :     {
    1706                 :          0 :         rStrm.StartRecord( EXC_ID_SXPI, maPageFields.size() * 6 );
    1707                 :          0 :         rStrm.SetSliceSize( 6 );
    1708 [ #  # ][ #  # ]:          0 :         for( ScfUInt16Vec::const_iterator aIt = maPageFields.begin(), aEnd = maPageFields.end(); aIt != aEnd; ++aIt )
                 [ #  # ]
    1709                 :            :         {
    1710 [ #  # ][ #  # ]:          0 :             XclExpPTFieldRef xField = maFieldList.GetRecord( *aIt );
    1711         [ #  # ]:          0 :             if( xField )
    1712         [ #  # ]:          0 :                 xField->WriteSxpiEntry( rStrm );
    1713         [ #  # ]:          0 :         }
    1714                 :          0 :         rStrm.EndRecord();
    1715                 :            :     }
    1716                 :          0 : }
    1717                 :            : 
    1718                 :          0 : void XclExpPivotTable::WriteSxdiList( XclExpStream& rStrm ) const
    1719                 :            : {
    1720 [ #  # ][ #  # ]:          0 :     for( XclPTDataFieldPosVec::const_iterator aIt = maDataFields.begin(), aEnd = maDataFields.end(); aIt != aEnd; ++aIt )
                 [ #  # ]
    1721                 :            :     {
    1722 [ #  # ][ #  # ]:          0 :         XclExpPTFieldRef xField = maFieldList.GetRecord( aIt->first );
    1723         [ #  # ]:          0 :         if( xField )
    1724 [ #  # ][ #  # ]:          0 :             xField->WriteSxdi( rStrm, aIt->second );
    1725         [ #  # ]:          0 :     }
    1726                 :          0 : }
    1727                 :            : 
    1728                 :          0 : void XclExpPivotTable::WriteSxli( XclExpStream& rStrm, sal_uInt16 nLineCount, sal_uInt16 nIndexCount ) const
    1729                 :            : {
    1730         [ #  # ]:          0 :     if( nLineCount > 0 )
    1731                 :            :     {
    1732                 :          0 :         sal_uInt16 nLineSize = 8 + 2 * nIndexCount;
    1733                 :          0 :         rStrm.StartRecord( EXC_ID_SXLI, nLineSize * nLineCount );
    1734                 :            : 
    1735                 :            :         /*  Excel expects the records to be filled completely, do not
    1736                 :            :             set a segment size... */
    1737                 :            : //        rStrm.SetSliceSize( nLineSize );
    1738                 :            : 
    1739         [ #  # ]:          0 :         for( sal_uInt16 nLine = 0; nLine < nLineCount; ++nLine )
    1740                 :            :         {
    1741                 :            :             // Excel XP needs a partly initialized SXLI record
    1742                 :          0 :             rStrm   << sal_uInt16( 0 )      // number of equal index entries
    1743                 :          0 :                     << EXC_SXVI_TYPE_DATA
    1744                 :          0 :                     << nIndexCount
    1745                 :          0 :                     << EXC_SXLI_DEFAULTFLAGS;
    1746                 :          0 :             rStrm.WriteZeroBytes( 2 * nIndexCount );
    1747                 :            :         }
    1748                 :          0 :         rStrm.EndRecord();
    1749                 :            :     }
    1750                 :          0 : }
    1751                 :            : 
    1752                 :          0 : void XclExpPivotTable::WriteSxex( XclExpStream& rStrm ) const
    1753                 :            : {
    1754                 :          0 :     rStrm.StartRecord( EXC_ID_SXEX, 24 );
    1755                 :          0 :     rStrm << maPTExtInfo;
    1756                 :          0 :     rStrm.EndRecord();
    1757                 :          0 : }
    1758                 :            : 
    1759                 :          0 : void XclExpPivotTable::WriteQsiSxTag( XclExpStream& rStrm ) const
    1760                 :            : {
    1761                 :          0 :     rStrm.StartRecord( 0x0802, 32 );
    1762                 :            : 
    1763                 :          0 :     sal_uInt16 nRecordType = 0x0802;
    1764                 :          0 :     sal_uInt16 nDummyFlags = 0x0000;
    1765                 :          0 :     sal_uInt16 nTableType  = 1; // 0 = query table : 1 = pivot table
    1766                 :            : 
    1767                 :          0 :     rStrm << nRecordType << nDummyFlags << nTableType;
    1768                 :            : 
    1769                 :            :     // General flags
    1770                 :          0 :     bool bEnableRefresh = true;
    1771                 :          0 :     bool bPCacheInvalid = false;
    1772                 :          0 :     bool bOlapPTReport  = false;
    1773                 :            : 
    1774                 :          0 :     sal_uInt16 nFlags = 0x0000;
    1775         [ #  # ]:          0 :     if (bEnableRefresh) nFlags |= 0x0001;
    1776         [ #  # ]:          0 :     if (bPCacheInvalid) nFlags |= 0x0002;
    1777         [ #  # ]:          0 :     if (bOlapPTReport)  nFlags |= 0x0004;
    1778                 :          0 :     rStrm << nFlags;
    1779                 :            : 
    1780                 :            :     // Feature-specific options.  The value differs depending on the table
    1781                 :            :     // type, but we assume the table type is always pivot table.
    1782                 :          0 :     sal_uInt32 nOptions = 0x00000000;
    1783                 :          0 :     bool bNoStencil = false;
    1784                 :          0 :     bool bHideTotal = false;
    1785                 :          0 :     bool bEmptyRows = false;
    1786                 :          0 :     bool bEmptyCols = false;
    1787         [ #  # ]:          0 :     if (bNoStencil) nOptions |= 0x00000001;
    1788         [ #  # ]:          0 :     if (bHideTotal) nOptions |= 0x00000002;
    1789         [ #  # ]:          0 :     if (bEmptyRows) nOptions |= 0x00000008;
    1790         [ #  # ]:          0 :     if (bEmptyCols) nOptions |= 0x00000010;
    1791                 :          0 :     rStrm << nOptions;
    1792                 :            : 
    1793                 :            :     enum ExcelVersion
    1794                 :            :     {
    1795                 :            :         Excel2000 = 0,
    1796                 :            :         ExcelXP   = 1,
    1797                 :            :         Excel2003 = 2,
    1798                 :            :         Excel2007 = 3
    1799                 :            :     };
    1800                 :          0 :     ExcelVersion eXclVer = Excel2000;
    1801                 :          0 :     sal_uInt8 nOffsetBytes = 16;
    1802                 :          0 :     rStrm << static_cast<sal_uInt8>(eXclVer)  // version table last refreshed
    1803                 :          0 :           << static_cast<sal_uInt8>(eXclVer)  // minimum version to refresh
    1804                 :          0 :           << nOffsetBytes
    1805                 :          0 :           << static_cast<sal_uInt8>(eXclVer); // first version created
    1806                 :            : 
    1807         [ #  # ]:          0 :     rStrm << XclExpString(maPTInfo.maTableName);
    1808                 :          0 :     rStrm << static_cast<sal_uInt16>(0x0001); // no idea what this is for.
    1809                 :            : 
    1810                 :          0 :     rStrm.EndRecord();
    1811                 :          0 : }
    1812                 :            : 
    1813                 :          0 : void XclExpPivotTable::WriteSxViewEx9( XclExpStream& rStrm ) const
    1814                 :            : {
    1815                 :            :     // Until we sync the autoformat ids only export if using grid header layout
    1816                 :            :     // That could only have been set via xls import so far.
    1817         [ #  # ]:          0 :     if ( 0 == maPTViewEx9Info.mnGridLayout )
    1818                 :            :     {
    1819                 :          0 :         rStrm.StartRecord( EXC_ID_SXVIEWEX9, 17 );
    1820                 :          0 :         rStrm << maPTViewEx9Info;
    1821                 :          0 :         rStrm.EndRecord();
    1822                 :            :     }
    1823                 :          0 : }
    1824                 :            : 
    1825                 :            : // ============================================================================
    1826                 :            : 
    1827                 :            : namespace {
    1828                 :            : 
    1829                 :            : const SCTAB EXC_PTMGR_PIVOTCACHES = SCTAB_MAX;
    1830                 :            : 
    1831                 :            : /** Record wrapper class to write the pivot caches or pivot tables. */
    1832         [ #  # ]:          0 : class XclExpPivotRecWrapper : public XclExpRecordBase
    1833                 :            : {
    1834                 :            : public:
    1835                 :            :     explicit            XclExpPivotRecWrapper( XclExpPivotTableManager& rPTMgr, SCTAB nScTab );
    1836                 :            :     virtual void        Save( XclExpStream& rStrm );
    1837                 :            :     virtual void        SaveXml( XclExpXmlStream& rStrm );
    1838                 :            : private:
    1839                 :            :     XclExpPivotTableManager& mrPTMgr;
    1840                 :            :     SCTAB               mnScTab;
    1841                 :            : };
    1842                 :            : 
    1843                 :          0 : XclExpPivotRecWrapper::XclExpPivotRecWrapper( XclExpPivotTableManager& rPTMgr, SCTAB nScTab ) :
    1844                 :            :     mrPTMgr( rPTMgr ),
    1845                 :          0 :     mnScTab( nScTab )
    1846                 :            : {
    1847                 :          0 : }
    1848                 :            : 
    1849                 :          0 : void XclExpPivotRecWrapper::Save( XclExpStream& rStrm )
    1850                 :            : {
    1851         [ #  # ]:          0 :     if( mnScTab == EXC_PTMGR_PIVOTCACHES )
    1852                 :          0 :         mrPTMgr.WritePivotCaches( rStrm );
    1853                 :            :     else
    1854                 :          0 :         mrPTMgr.WritePivotTables( rStrm, mnScTab );
    1855                 :          0 : }
    1856                 :            : 
    1857                 :          0 : void XclExpPivotRecWrapper::SaveXml( XclExpXmlStream& rStrm )
    1858                 :            : {
    1859         [ #  # ]:          0 :     if( mnScTab == EXC_PTMGR_PIVOTCACHES )
    1860                 :          0 :         mrPTMgr.WritePivotCachesXml( rStrm );
    1861                 :            :     else
    1862                 :          0 :         mrPTMgr.WritePivotTablesXml( rStrm, mnScTab );
    1863                 :          0 : }
    1864                 :            : 
    1865                 :            : } // namespace
    1866                 :            : 
    1867                 :            : // ----------------------------------------------------------------------------
    1868                 :            : 
    1869                 :          0 : XclExpPivotTableManager::XclExpPivotTableManager( const XclExpRoot& rRoot ) :
    1870                 :            :     XclExpRoot( rRoot ),
    1871 [ #  # ][ #  # ]:          0 :     mbShareCaches( true )
    1872                 :            : {
    1873                 :          0 : }
    1874                 :            : 
    1875                 :          0 : void XclExpPivotTableManager::CreatePivotTables()
    1876                 :            : {
    1877         [ #  # ]:          0 :     if( ScDPCollection* pDPColl = GetDoc().GetDPCollection() )
    1878         [ #  # ]:          0 :         for( size_t nDPObj = 0, nCount = pDPColl->GetCount(); nDPObj < nCount; ++nDPObj )
    1879         [ #  # ]:          0 :             if( ScDPObject* pDPObj = (*pDPColl)[ nDPObj ] )
    1880         [ #  # ]:          0 :                 if( const XclExpPivotCache* pPCache = CreatePivotCache( *pDPObj ) )
    1881         [ #  # ]:          0 :                     maPTableList.AppendNewRecord( new XclExpPivotTable( GetRoot(), *pDPObj, *pPCache ) );
    1882                 :          0 : }
    1883                 :            : 
    1884                 :          0 : XclExpRecordRef XclExpPivotTableManager::CreatePivotCachesRecord()
    1885                 :            : {
    1886         [ #  # ]:          0 :     return XclExpRecordRef( new XclExpPivotRecWrapper( *this, EXC_PTMGR_PIVOTCACHES ) );
    1887                 :            : }
    1888                 :            : 
    1889                 :          0 : XclExpRecordRef XclExpPivotTableManager::CreatePivotTablesRecord( SCTAB nScTab )
    1890                 :            : {
    1891         [ #  # ]:          0 :     return XclExpRecordRef( new XclExpPivotRecWrapper( *this, nScTab ) );
    1892                 :            : }
    1893                 :            : 
    1894                 :          0 : void XclExpPivotTableManager::WritePivotCaches( XclExpStream& rStrm )
    1895                 :            : {
    1896                 :          0 :     maPCacheList.Save( rStrm );
    1897                 :          0 : }
    1898                 :            : 
    1899                 :          0 : void XclExpPivotTableManager::WritePivotCachesXml( XclExpXmlStream&
    1900                 :            : #ifdef XLSX_PIVOT_CACHE
    1901                 :            :                                                                     rStrm
    1902                 :            : #endif
    1903                 :            : )
    1904                 :            : {
    1905                 :            : #ifdef XLSX_PIVOT_CACHE /* <pivotCache> without xl/pivotCaches/ cacheStream
    1906                 :            :                            results in a broken .xlsx */
    1907                 :            :     if( maPCacheList.IsEmpty() )
    1908                 :            :         return;
    1909                 :            :     sax_fastparser::FSHelperPtr& rWorkbook = rStrm.GetCurrentStream();
    1910                 :            :     rWorkbook->startElement( XML_pivotCaches, FSEND );
    1911                 :            :     maPCacheList.SaveXml( rStrm );
    1912                 :            :     rWorkbook->endElement( XML_pivotCaches );
    1913                 :            : #endif /* XLSX_PIVOT_CACHE */
    1914                 :          0 : }
    1915                 :            : 
    1916                 :          0 : void XclExpPivotTableManager::WritePivotTables( XclExpStream& rStrm, SCTAB nScTab )
    1917                 :            : {
    1918         [ #  # ]:          0 :     for( size_t nPos = 0, nSize = maPTableList.GetSize(); nPos < nSize; ++nPos )
    1919                 :            :     {
    1920         [ #  # ]:          0 :         XclExpPivotTableRef xPTable = maPTableList.GetRecord( nPos );
    1921         [ #  # ]:          0 :         if( xPTable->GetScTab() == nScTab )
    1922         [ #  # ]:          0 :             xPTable->Save( rStrm );
    1923         [ #  # ]:          0 :     }
    1924                 :          0 : }
    1925                 :            : 
    1926                 :          0 : void XclExpPivotTableManager::WritePivotTablesXml( XclExpXmlStream& rStrm, SCTAB nScTab )
    1927                 :            : {
    1928         [ #  # ]:          0 :     for( size_t nPos = 0, nSize = maPTableList.GetSize(); nPos < nSize; ++nPos )
    1929                 :            :     {
    1930         [ #  # ]:          0 :         XclExpPivotTableRef xPTable = maPTableList.GetRecord( nPos );
    1931         [ #  # ]:          0 :         if( xPTable->GetScTab() == nScTab )
    1932         [ #  # ]:          0 :             xPTable->SaveXml( rStrm );
    1933         [ #  # ]:          0 :     }
    1934                 :          0 : }
    1935                 :            : 
    1936                 :            : // private --------------------------------------------------------------------
    1937                 :            : 
    1938                 :          0 : const XclExpPivotCache* XclExpPivotTableManager::CreatePivotCache( const ScDPObject& rDPObj )
    1939                 :            : {
    1940                 :            :     // try to find a pivot cache with the same data source
    1941                 :            :     /*  #i25110# In Excel, the pivot cache contains additional fields
    1942                 :            :         (i.e. grouping info, calculated fields). If the passed DataPilot object
    1943                 :            :         or the found cache contains this data, do not share the cache with
    1944                 :            :         multiple pivot tables. */
    1945         [ #  # ]:          0 :     if( mbShareCaches )
    1946                 :            :     {
    1947         [ #  # ]:          0 :         if( const ScDPSaveData* pSaveData = rDPObj.GetSaveData() )
    1948                 :            :         {
    1949                 :          0 :             const ScDPDimensionSaveData* pDimSaveData = pSaveData->GetExistingDimensionData();
    1950                 :            :             // no dimension save data at all or save data does not contain grouping info
    1951 [ #  # ][ #  # ]:          0 :             if( !pDimSaveData || !pDimSaveData->HasGroupDimensions() )
         [ #  # ][ #  # ]
    1952                 :            :             {
    1953                 :            :                 // check all existing pivot caches
    1954         [ #  # ]:          0 :                 for( size_t nPos = 0, nSize = maPCacheList.GetSize(); nPos < nSize; ++nPos )
    1955                 :            :                 {
    1956         [ #  # ]:          0 :                     XclExpPivotCacheRef xPCache = maPCacheList.GetRecord( nPos );
    1957                 :            :                     // pivot cache does not have grouping info and source data is equal
    1958 [ #  # ][ #  # ]:          0 :                     if( !xPCache->HasAddFields() && xPCache->HasEqualDataSource( rDPObj ) )
         [ #  # ][ #  # ]
    1959                 :          0 :                         return xPCache.get();
    1960 [ #  # ][ #  # ]:          0 :                 }
    1961                 :            :             }
    1962                 :            :         }
    1963                 :            :     }
    1964                 :            : 
    1965                 :            :     // create a new pivot cache
    1966                 :          0 :     sal_uInt16 nNewCacheIdx = static_cast< sal_uInt16 >( maPCacheList.GetSize() );
    1967 [ #  # ][ #  # ]:          0 :     XclExpPivotCacheRef xNewPCache( new XclExpPivotCache( GetRoot(), rDPObj, nNewCacheIdx ) );
                 [ #  # ]
    1968         [ #  # ]:          0 :     if( xNewPCache->IsValid() )
    1969                 :            :     {
    1970 [ #  # ][ #  # ]:          0 :         maPCacheList.AppendRecord( xNewPCache );
                 [ #  # ]
    1971                 :          0 :         return xNewPCache.get();
    1972                 :            :     }
    1973                 :            : 
    1974         [ #  # ]:          0 :     return 0;
    1975 [ +  - ][ +  - ]:         24 : }
    1976                 :            : 
    1977                 :            : // ============================================================================
    1978                 :            : 
    1979                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10