LCOV - code coverage report
Current view: top level - libreoffice/sc/source/filter/excel - xipivot.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 267 816 32.7 %
Date: 2012-12-27 Functions: 56 114 49.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : 
      21             : #include "xipivot.hxx"
      22             : 
      23             : #include <com/sun/star/sheet/DataPilotFieldSortInfo.hpp>
      24             : #include <com/sun/star/sheet/DataPilotFieldAutoShowInfo.hpp>
      25             : #include <com/sun/star/sheet/DataPilotFieldLayoutInfo.hpp>
      26             : #include <com/sun/star/sheet/DataPilotFieldReference.hpp>
      27             : 
      28             : #include <tools/datetime.hxx>
      29             : #include <svl/zformat.hxx>
      30             : #include <svl/intitem.hxx>
      31             : 
      32             : #include "document.hxx"
      33             : #include "cell.hxx"
      34             : #include "dpsave.hxx"
      35             : #include "dpdimsave.hxx"
      36             : #include "dpobject.hxx"
      37             : #include "dpshttab.hxx"
      38             : #include "dpoutputgeometry.hxx"
      39             : #include "scitems.hxx"
      40             : #include "attrib.hxx"
      41             : 
      42             : #include "xltracer.hxx"
      43             : #include "xistream.hxx"
      44             : #include "xihelper.hxx"
      45             : #include "xilink.hxx"
      46             : #include "xiescher.hxx"
      47             : 
      48             : //! TODO ExcelToSc usage
      49             : #include "excform.hxx"
      50             : #include "xltable.hxx"
      51             : 
      52             : #include <vector>
      53             : 
      54             : using namespace com::sun::star;
      55             : 
      56             : using ::rtl::OUString;
      57             : using ::rtl::OUStringBuffer;
      58             : using ::com::sun::star::sheet::DataPilotFieldOrientation;
      59             : using ::com::sun::star::sheet::DataPilotFieldOrientation_DATA;
      60             : using ::com::sun::star::sheet::DataPilotFieldSortInfo;
      61             : using ::com::sun::star::sheet::DataPilotFieldAutoShowInfo;
      62             : using ::com::sun::star::sheet::DataPilotFieldLayoutInfo;
      63             : using ::com::sun::star::sheet::DataPilotFieldReference;
      64             : using ::std::vector;
      65             : 
      66             : // ============================================================================
      67             : // Pivot cache
      68             : // ============================================================================
      69             : 
      70           4 : XclImpPCItem::XclImpPCItem( XclImpStream& rStrm )
      71             : {
      72           4 :     switch( rStrm.GetRecId() )
      73             :     {
      74           0 :         case EXC_ID_SXDOUBLE:   ReadSxdouble( rStrm );      break;
      75           0 :         case EXC_ID_SXBOOLEAN:  ReadSxboolean( rStrm );     break;
      76           0 :         case EXC_ID_SXERROR:    ReadSxerror( rStrm );       break;
      77           0 :         case EXC_ID_SXINTEGER:  ReadSxinteger( rStrm );     break;
      78           4 :         case EXC_ID_SXSTRING:   ReadSxstring( rStrm );      break;
      79           0 :         case EXC_ID_SXDATETIME: ReadSxdatetime( rStrm );    break;
      80           0 :         case EXC_ID_SXEMPTY:    ReadSxempty( rStrm );       break;
      81             :         default:    OSL_FAIL( "XclImpPCItem::XclImpPCItem - unknown record id" );
      82             :     }
      83           4 : }
      84             : 
      85             : namespace {
      86             : 
      87           0 : void lclSetValue( const XclImpRoot& rRoot, const ScAddress& rScPos, double fValue, short nFormatType )
      88             : {
      89           0 :     ScDocument& rDoc = rRoot.GetDoc();
      90           0 :     rDoc.SetValue( rScPos.Col(), rScPos.Row(), rScPos.Tab(), fValue );
      91           0 :     sal_uInt32 nScNumFmt = rRoot.GetFormatter().GetStandardFormat( nFormatType, rRoot.GetDocLanguage() );
      92           0 :     rDoc.ApplyAttr( rScPos.Col(), rScPos.Row(), rScPos.Tab(), SfxUInt32Item( ATTR_VALUE_FORMAT, nScNumFmt ) );
      93           0 : }
      94             : 
      95             : } // namespace
      96             : 
      97           0 : void XclImpPCItem::WriteToSource( const XclImpRoot& rRoot, const ScAddress& rScPos ) const
      98             : {
      99           0 :     ScDocument& rDoc = rRoot.GetDoc();
     100           0 :     if( const rtl::OUString* pText = GetText() )
     101           0 :         rDoc.SetString( rScPos.Col(), rScPos.Row(), rScPos.Tab(), *pText );
     102           0 :     else if( const double* pfValue = GetDouble() )
     103           0 :         rDoc.SetValue( rScPos.Col(), rScPos.Row(), rScPos.Tab(), *pfValue );
     104           0 :     else if( const sal_Int16* pnValue = GetInteger() )
     105           0 :         rDoc.SetValue( rScPos.Col(), rScPos.Row(), rScPos.Tab(), *pnValue );
     106           0 :     else if( const bool* pbValue = GetBool() )
     107           0 :         lclSetValue( rRoot, rScPos, *pbValue ? 1.0 : 0.0, NUMBERFORMAT_LOGICAL );
     108           0 :     else if( const DateTime* pDateTime = GetDateTime() )
     109             :     {
     110             :         // set number format date, time, or date/time, depending on the value
     111           0 :         double fValue = rRoot.GetDoubleFromDateTime( *pDateTime );
     112           0 :         double fInt = 0.0;
     113           0 :         double fFrac = modf( fValue, &fInt );
     114             :         short nFormatType = ((fFrac == 0.0) && (fInt != 0.0)) ? NUMBERFORMAT_DATE :
     115           0 :             ((fInt == 0.0) ? NUMBERFORMAT_TIME : NUMBERFORMAT_DATETIME);
     116           0 :         lclSetValue( rRoot, rScPos, fValue, nFormatType );
     117             :     }
     118           0 :     else if( const sal_uInt16* pnError = GetError() )
     119             :     {
     120             :         double fValue;
     121           0 :         sal_uInt8 nErrCode = static_cast< sal_uInt8 >( *pnError );
     122           0 :         const ScTokenArray* pScTokArr = rRoot.GetOldFmlaConverter().GetBoolErr(
     123           0 :             XclTools::ErrorToEnum( fValue, EXC_BOOLERR_ERROR, nErrCode ) );
     124           0 :         ScFormulaCell* pCell = new ScFormulaCell( &rDoc, rScPos, pScTokArr );
     125           0 :         pCell->SetHybridDouble( fValue );
     126           0 :         rDoc.PutCell( rScPos, pCell );
     127             :     }
     128           0 : }
     129             : 
     130           0 : void XclImpPCItem::ReadSxdouble( XclImpStream& rStrm )
     131             : {
     132             :     OSL_ENSURE( rStrm.GetRecSize() == 8, "XclImpPCItem::ReadSxdouble - wrong record size" );
     133           0 :     SetDouble( rStrm.ReadDouble() );
     134           0 : }
     135             : 
     136           0 : void XclImpPCItem::ReadSxboolean( XclImpStream& rStrm )
     137             : {
     138             :     OSL_ENSURE( rStrm.GetRecSize() == 2, "XclImpPCItem::ReadSxboolean - wrong record size" );
     139           0 :     SetBool( rStrm.ReaduInt16() != 0 );
     140           0 : }
     141             : 
     142           0 : void XclImpPCItem::ReadSxerror( XclImpStream& rStrm )
     143             : {
     144             :     OSL_ENSURE( rStrm.GetRecSize() == 2, "XclImpPCItem::ReadSxerror - wrong record size" );
     145           0 :     SetError( rStrm.ReaduInt16() );
     146           0 : }
     147             : 
     148           0 : void XclImpPCItem::ReadSxinteger( XclImpStream& rStrm )
     149             : {
     150             :     OSL_ENSURE( rStrm.GetRecSize() == 2, "XclImpPCItem::ReadSxinteger - wrong record size" );
     151           0 :     SetInteger( rStrm.ReadInt16() );
     152           0 : }
     153             : 
     154           4 : void XclImpPCItem::ReadSxstring( XclImpStream& rStrm )
     155             : {
     156             :     OSL_ENSURE( rStrm.GetRecSize() >= 3, "XclImpPCItem::ReadSxstring - wrong record size" );
     157           4 :     SetText( rStrm.ReadUniString() );
     158           4 : }
     159             : 
     160           0 : void XclImpPCItem::ReadSxdatetime( XclImpStream& rStrm )
     161             : {
     162             :     OSL_ENSURE( rStrm.GetRecSize() == 8, "XclImpPCItem::ReadSxdatetime - wrong record size" );
     163             :     sal_uInt16 nYear, nMonth;
     164             :     sal_uInt8 nDay, nHour, nMin, nSec;
     165           0 :     rStrm >> nYear >> nMonth >> nDay >> nHour >> nMin >> nSec;
     166           0 :     SetDateTime( DateTime( Date( nDay, nMonth, nYear ), Time( nHour, nMin, nSec ) ) );
     167           0 : }
     168             : 
     169           0 : void XclImpPCItem::ReadSxempty( XclImpStream& rStrm )
     170             : {
     171             :     (void)rStrm;    // avoid compiler warning
     172             :     OSL_ENSURE( rStrm.GetRecSize() == 0, "XclImpPCItem::ReadSxempty - wrong record size" );
     173           0 :     SetEmpty();
     174           0 : }
     175             : 
     176             : // ============================================================================
     177             : 
     178           2 : XclImpPCField::XclImpPCField( const XclImpRoot& rRoot, XclImpPivotCache& rPCache, sal_uInt16 nFieldIdx ) :
     179             :     XclPCField( EXC_PCFIELD_UNKNOWN, nFieldIdx ),
     180             :     XclImpRoot( rRoot ),
     181             :     mrPCache( rPCache ),
     182             :     mnSourceScCol( -1 ),
     183           2 :     mbNumGroupInfoRead( false )
     184             : {
     185           2 : }
     186             : 
     187           4 : XclImpPCField::~XclImpPCField()
     188             : {
     189           4 : }
     190             : 
     191             : // general field/item access --------------------------------------------------
     192             : 
     193           0 : const rtl::OUString& XclImpPCField::GetFieldName( const ScfStringVec& rVisNames ) const
     194             : {
     195           0 :     if( IsGroupChildField() && (mnFieldIdx < rVisNames.size()) )
     196             :     {
     197           0 :         const rtl::OUString& rVisName = rVisNames[ mnFieldIdx ];
     198           0 :         if (!rVisName.isEmpty())
     199           0 :             return rVisName;
     200             :     }
     201           0 :     return maFieldInfo.maName;
     202             : }
     203             : 
     204           0 : const XclImpPCField* XclImpPCField::GetGroupBaseField() const
     205             : {
     206             :     OSL_ENSURE( IsGroupChildField(), "XclImpPCField::GetGroupBaseField - this field type does not have a base field" );
     207           0 :     return IsGroupChildField() ? mrPCache.GetField( maFieldInfo.mnGroupBase ) : 0;
     208             : }
     209             : 
     210           0 : const XclImpPCItem* XclImpPCField::GetItem( sal_uInt16 nItemIdx ) const
     211             : {
     212           0 :     return (nItemIdx < maItems.size()) ? maItems[ nItemIdx ].get() : 0;
     213             : }
     214             : 
     215           0 : const XclImpPCItem* XclImpPCField::GetLimitItem( sal_uInt16 nItemIdx ) const
     216             : {
     217             :     OSL_ENSURE( nItemIdx < 3, "XclImpPCField::GetLimitItem - invalid item index" );
     218             :     OSL_ENSURE( nItemIdx < maNumGroupItems.size(), "XclImpPCField::GetLimitItem - no item found" );
     219           0 :     return (nItemIdx < maNumGroupItems.size()) ? maNumGroupItems[ nItemIdx ].get() : 0;
     220             : }
     221             : 
     222           0 : void XclImpPCField::WriteFieldNameToSource( SCCOL nScCol, SCTAB nScTab ) const
     223             : {
     224             :     OSL_ENSURE( HasOrigItems(), "XclImpPCField::WriteFieldNameToSource - only for standard fields" );
     225           0 :     GetDoc().SetString( nScCol, 0, nScTab, maFieldInfo.maName );
     226           0 :     mnSourceScCol = nScCol;
     227           0 : }
     228             : 
     229           0 : void XclImpPCField::WriteOrigItemToSource( SCROW nScRow, SCTAB nScTab, sal_uInt16 nItemIdx ) const
     230             : {
     231           0 :     if( nItemIdx < maOrigItems.size() )
     232           0 :         maOrigItems[ nItemIdx ]->WriteToSource( GetRoot(), ScAddress( mnSourceScCol, nScRow, nScTab ) );
     233           0 : }
     234             : 
     235           0 : void XclImpPCField::WriteLastOrigItemToSource( SCROW nScRow, SCTAB nScTab ) const
     236             : {
     237           0 :     if( !maOrigItems.empty() )
     238           0 :         maOrigItems.back()->WriteToSource( GetRoot(), ScAddress( mnSourceScCol, nScRow, nScTab ) );
     239           0 : }
     240             : 
     241             : // records --------------------------------------------------------------------
     242             : 
     243           2 : void XclImpPCField::ReadSxfield( XclImpStream& rStrm )
     244             : {
     245           2 :     rStrm >> maFieldInfo;
     246             : 
     247             :     /*  Detect the type of this field. This is done very restrictive to detect
     248             :         any unexpected state. */
     249           2 :     meFieldType = EXC_PCFIELD_UNKNOWN;
     250             : 
     251           2 :     bool bItems  = ::get_flag( maFieldInfo.mnFlags, EXC_SXFIELD_HASITEMS );
     252           2 :     bool bPostp  = ::get_flag( maFieldInfo.mnFlags, EXC_SXFIELD_POSTPONE );
     253           2 :     bool bCalced = ::get_flag( maFieldInfo.mnFlags, EXC_SXFIELD_CALCED );
     254           2 :     bool bChild  = ::get_flag( maFieldInfo.mnFlags, EXC_SXFIELD_HASCHILD );
     255           2 :     bool bNum    = ::get_flag( maFieldInfo.mnFlags, EXC_SXFIELD_NUMGROUP );
     256             : 
     257           2 :     sal_uInt16 nVisC   = maFieldInfo.mnVisItems;
     258           2 :     sal_uInt16 nGroupC = maFieldInfo.mnGroupItems;
     259           2 :     sal_uInt16 nBaseC  = maFieldInfo.mnBaseItems;
     260           2 :     sal_uInt16 nOrigC  = maFieldInfo.mnOrigItems;
     261             :     OSL_ENSURE( nVisC > 0, "XclImpPCField::ReadSxfield - field without visible items" );
     262             : 
     263           2 :     sal_uInt16 nType = maFieldInfo.mnFlags & EXC_SXFIELD_DATA_MASK;
     264             :     bool bType =
     265             :         (nType == EXC_SXFIELD_DATA_STR) ||
     266             :         (nType == EXC_SXFIELD_DATA_INT) ||
     267             :         (nType == EXC_SXFIELD_DATA_DBL) ||
     268             :         (nType == EXC_SXFIELD_DATA_STR_INT) ||
     269             :         (nType == EXC_SXFIELD_DATA_STR_DBL) ||
     270             :         (nType == EXC_SXFIELD_DATA_DATE) ||
     271             :         (nType == EXC_SXFIELD_DATA_DATE_EMP) ||
     272             :         (nType == EXC_SXFIELD_DATA_DATE_NUM) ||
     273           2 :         (nType == EXC_SXFIELD_DATA_DATE_STR);
     274             :     bool bTypeNone =
     275           2 :         (nType == EXC_SXFIELD_DATA_NONE);
     276             :     // for now, ignore data type of calculated fields
     277             :     OSL_ENSURE( bCalced || bType || bTypeNone, "XclImpPCField::ReadSxfield - unknown item data type" );
     278             : 
     279           2 :     if( nVisC > 0 || bPostp )
     280             :     {
     281           2 :         if( bItems && !bPostp )
     282             :         {
     283           4 :             if( !bCalced )
     284             :             {
     285             :                 // 1) standard fields and standard grouping fields
     286           2 :                 if( !bNum )
     287             :                 {
     288             :                     // 1a) standard field without grouping
     289           2 :                     if( bType && (nGroupC == 0) && (nBaseC == 0) && (nOrigC == nVisC) )
     290           2 :                         meFieldType = EXC_PCFIELD_STANDARD;
     291             : 
     292             :                     // 1b) standard grouping field
     293           0 :                     else if( bTypeNone && (nGroupC == nVisC) && (nBaseC > 0) && (nOrigC == 0) )
     294           0 :                         meFieldType = EXC_PCFIELD_STDGROUP;
     295             :                 }
     296             :                 // 2) numerical grouping fields
     297           0 :                 else if( (nGroupC == nVisC) && (nBaseC == 0) )
     298             :                 {
     299             :                     // 2a) single num/date grouping field without child grouping field
     300           0 :                     if( !bChild && bType && (nOrigC > 0) )
     301             :                     {
     302           0 :                         switch( nType )
     303             :                         {
     304             :                             case EXC_SXFIELD_DATA_INT:
     305           0 :                             case EXC_SXFIELD_DATA_DBL:  meFieldType = EXC_PCFIELD_NUMGROUP;     break;
     306           0 :                             case EXC_SXFIELD_DATA_DATE: meFieldType = EXC_PCFIELD_DATEGROUP;    break;
     307             :                             default:    OSL_FAIL( "XclImpPCField::ReadSxfield - numeric group with wrong data type" );
     308             :                         }
     309             :                     }
     310             : 
     311             :                     // 2b) first date grouping field with child grouping field
     312           0 :                     else if( bChild && (nType == EXC_SXFIELD_DATA_DATE) && (nOrigC > 0) )
     313           0 :                         meFieldType = EXC_PCFIELD_DATEGROUP;
     314             : 
     315             :                     // 2c) additional date grouping field
     316           0 :                     else if( bTypeNone && (nOrigC == 0) )
     317           0 :                         meFieldType = EXC_PCFIELD_DATECHILD;
     318             :                 }
     319             :                 OSL_ENSURE( meFieldType != EXC_PCFIELD_UNKNOWN, "XclImpPCField::ReadSxfield - invalid standard or grouped field" );
     320             :             }
     321             : 
     322             :             // 3) calculated field
     323             :             else
     324             :             {
     325           0 :                 if( !bChild && !bNum && (nGroupC == 0) && (nBaseC == 0) && (nOrigC == 0) )
     326           0 :                     meFieldType = EXC_PCFIELD_CALCED;
     327             :                 OSL_ENSURE( meFieldType == EXC_PCFIELD_CALCED, "XclImpPCField::ReadSxfield - invalid calculated field" );
     328             :             }
     329             :         }
     330             : 
     331           0 :         else if( !bItems && bPostp )
     332             :         {
     333             :             // 4) standard field with postponed items
     334           0 :             if( !bCalced && !bChild && !bNum && bType && (nGroupC == 0) && (nBaseC == 0) && (nOrigC == 0) )
     335           0 :                 meFieldType = EXC_PCFIELD_STANDARD;
     336             :             OSL_ENSURE( meFieldType == EXC_PCFIELD_STANDARD, "XclImpPCField::ReadSxfield - invalid postponed field" );
     337             :         }
     338             :     }
     339           2 : }
     340             : 
     341           4 : void XclImpPCField::ReadItem( XclImpStream& rStrm )
     342             : {
     343             :     OSL_ENSURE( HasInlineItems() || HasPostponedItems(), "XclImpPCField::ReadItem - field does not expect items" );
     344             : 
     345             :     // read the item
     346           4 :     XclImpPCItemRef xItem( new XclImpPCItem( rStrm ) );
     347             : 
     348             :     // try to insert into an item list
     349           4 :     if( mbNumGroupInfoRead )
     350             :     {
     351             :         // there are 3 items after SXNUMGROUP that contain grouping limits and step count
     352           0 :         if( maNumGroupItems.size() < 3 )
     353           0 :             maNumGroupItems.push_back( xItem );
     354             :         else
     355           0 :             maOrigItems.push_back( xItem );
     356             :     }
     357           4 :     else if( HasInlineItems() || HasPostponedItems() )
     358             :     {
     359           4 :         maItems.push_back( xItem );
     360             :         // visible item is original item in standard fields
     361           4 :         if( IsStandardField() )
     362           4 :             maOrigItems.push_back( xItem );
     363           4 :     }
     364           4 : }
     365             : 
     366           0 : void XclImpPCField::ReadSxnumgroup( XclImpStream& rStrm )
     367             : {
     368             :     OSL_ENSURE( IsNumGroupField() || IsDateGroupField(), "XclImpPCField::ReadSxnumgroup - SXNUMGROUP outside numeric grouping field" );
     369             :     OSL_ENSURE( !mbNumGroupInfoRead, "XclImpPCField::ReadSxnumgroup - multiple SXNUMGROUP records" );
     370             :     OSL_ENSURE( maItems.size() == maFieldInfo.mnGroupItems, "XclImpPCField::ReadSxnumgroup - SXNUMGROUP out of record order" );
     371           0 :     rStrm >> maNumGroupInfo;
     372           0 :     mbNumGroupInfoRead = IsNumGroupField() || IsDateGroupField();
     373           0 : }
     374             : 
     375           0 : void XclImpPCField::ReadSxgroupinfo( XclImpStream& rStrm )
     376             : {
     377             :     OSL_ENSURE( IsStdGroupField(), "XclImpPCField::ReadSxgroupinfo - SXGROUPINFO outside grouping field" );
     378             :     OSL_ENSURE( maGroupOrder.empty(), "XclImpPCField::ReadSxgroupinfo - multiple SXGROUPINFO records" );
     379             :     OSL_ENSURE( maItems.size() == maFieldInfo.mnGroupItems, "XclImpPCField::ReadSxgroupinfo - SXGROUPINFO out of record order" );
     380             :     OSL_ENSURE( (rStrm.GetRecLeft() / 2) == maFieldInfo.mnBaseItems, "XclImpPCField::ReadSxgroupinfo - wrong SXGROUPINFO size" );
     381           0 :     maGroupOrder.clear();
     382           0 :     size_t nSize = rStrm.GetRecLeft() / 2;
     383           0 :     maGroupOrder.resize( nSize, 0 );
     384           0 :     for( size_t nIdx = 0; nIdx < nSize; ++nIdx )
     385           0 :         rStrm >> maGroupOrder[ nIdx ];
     386           0 : }
     387             : 
     388             : // grouping -------------------------------------------------------------------
     389             : 
     390           0 : void XclImpPCField::ConvertGroupField( ScDPSaveData& rSaveData, const ScfStringVec& rVisNames ) const
     391             : {
     392           0 :     if (!GetFieldName(rVisNames).isEmpty())
     393             :     {
     394           0 :         if( IsStdGroupField() )
     395           0 :             ConvertStdGroupField( rSaveData, rVisNames );
     396           0 :         else if( IsNumGroupField() )
     397           0 :             ConvertNumGroupField( rSaveData, rVisNames );
     398           0 :         else if( IsDateGroupField() )
     399           0 :             ConvertDateGroupField( rSaveData, rVisNames );
     400             :     }
     401           0 : }
     402             : 
     403             : // private --------------------------------------------------------------------
     404             : 
     405           0 : void XclImpPCField::ConvertStdGroupField( ScDPSaveData& rSaveData, const ScfStringVec& rVisNames ) const
     406             : {
     407           0 :     if( const XclImpPCField* pBaseField = GetGroupBaseField() )
     408             :     {
     409           0 :         const String& rBaseFieldName = pBaseField->GetFieldName( rVisNames );
     410           0 :         if( rBaseFieldName.Len() > 0 )
     411             :         {
     412             :             // *** create a ScDPSaveGroupItem for each own item, they collect base item names ***
     413           0 :             ScDPSaveGroupItemVec aGroupItems;
     414           0 :             aGroupItems.reserve( maItems.size() );
     415             :             // initialize with own item names
     416           0 :             for( XclImpPCItemVec::const_iterator aIt = maItems.begin(), aEnd = maItems.end(); aIt != aEnd; ++aIt )
     417           0 :                 aGroupItems.push_back( ScDPSaveGroupItem( (*aIt)->ConvertToText() ) );
     418             : 
     419             :             // *** iterate over all base items, set their names at corresponding own items ***
     420           0 :             for( sal_uInt16 nItemIdx = 0, nItemCount = static_cast< sal_uInt16 >( maGroupOrder.size() ); nItemIdx < nItemCount; ++nItemIdx )
     421           0 :                 if( maGroupOrder[ nItemIdx ] < aGroupItems.size() )
     422           0 :                     if( const XclImpPCItem* pBaseItem = pBaseField->GetItem( nItemIdx ) )
     423           0 :                         if( const XclImpPCItem* pGroupItem = GetItem( maGroupOrder[ nItemIdx ] ) )
     424           0 :                             if( *pBaseItem != *pGroupItem )
     425           0 :                                 aGroupItems[ maGroupOrder[ nItemIdx ] ].AddElement( pBaseItem->ConvertToText() );
     426             : 
     427             :             // *** create the ScDPSaveGroupDimension object, fill with grouping info ***
     428           0 :             ScDPSaveGroupDimension aGroupDim( rBaseFieldName, GetFieldName( rVisNames ) );
     429           0 :             for( ScDPSaveGroupItemVec::const_iterator aIt = aGroupItems.begin(), aEnd = aGroupItems.end(); aIt != aEnd; ++aIt )
     430           0 :                 if( !aIt->IsEmpty() )
     431           0 :                     aGroupDim.AddGroupItem( *aIt );
     432           0 :             rSaveData.GetDimensionData()->AddGroupDimension( aGroupDim );
     433           0 :         }
     434             :     }
     435           0 : }
     436             : 
     437           0 : void XclImpPCField::ConvertNumGroupField( ScDPSaveData& rSaveData, const ScfStringVec& rVisNames ) const
     438             : {
     439           0 :     ScDPNumGroupInfo aNumInfo( GetScNumGroupInfo() );
     440           0 :     ScDPSaveNumGroupDimension aNumGroupDim( GetFieldName( rVisNames ), aNumInfo );
     441           0 :     rSaveData.GetDimensionData()->AddNumGroupDimension( aNumGroupDim );
     442           0 : }
     443             : 
     444           0 : void XclImpPCField::ConvertDateGroupField( ScDPSaveData& rSaveData, const ScfStringVec& rVisNames ) const
     445             : {
     446           0 :     ScDPNumGroupInfo aDateInfo( GetScDateGroupInfo() );
     447           0 :     sal_Int32 nScDateType = maNumGroupInfo.GetScDateType();
     448             : 
     449           0 :     switch( meFieldType )
     450             :     {
     451             :         case EXC_PCFIELD_DATEGROUP:
     452             :         {
     453           0 :             if( aDateInfo.mbDateValues )
     454             :             {
     455             :                 // special case for days only with step value - create numeric grouping
     456           0 :                 ScDPSaveNumGroupDimension aNumGroupDim( GetFieldName( rVisNames ), aDateInfo );
     457           0 :                 rSaveData.GetDimensionData()->AddNumGroupDimension( aNumGroupDim );
     458             :             }
     459             :             else
     460             :             {
     461           0 :                 ScDPSaveNumGroupDimension aNumGroupDim( GetFieldName( rVisNames ), ScDPNumGroupInfo() );
     462           0 :                 aNumGroupDim.SetDateInfo( aDateInfo, nScDateType );
     463           0 :                 rSaveData.GetDimensionData()->AddNumGroupDimension( aNumGroupDim );
     464             :             }
     465             :         }
     466           0 :         break;
     467             : 
     468             :         case EXC_PCFIELD_DATECHILD:
     469             :         {
     470           0 :             if( const XclImpPCField* pBaseField = GetGroupBaseField() )
     471             :             {
     472           0 :                 const String& rBaseFieldName = pBaseField->GetFieldName( rVisNames );
     473           0 :                 if( rBaseFieldName.Len() > 0 )
     474             :                 {
     475           0 :                     ScDPSaveGroupDimension aGroupDim( rBaseFieldName, GetFieldName( rVisNames ) );
     476           0 :                     aGroupDim.SetDateInfo( aDateInfo, nScDateType );
     477           0 :                     rSaveData.GetDimensionData()->AddGroupDimension( aGroupDim );
     478           0 :                 }
     479             :             }
     480             :         }
     481           0 :         break;
     482             : 
     483             :         default:
     484             :             OSL_FAIL( "XclImpPCField::ConvertDateGroupField - unknown date field type" );
     485             :     }
     486           0 : }
     487             : 
     488           0 : ScDPNumGroupInfo XclImpPCField::GetScNumGroupInfo() const
     489             : {
     490           0 :     ScDPNumGroupInfo aNumInfo;
     491           0 :     aNumInfo.mbEnable = sal_True;
     492           0 :     aNumInfo.mbDateValues = false;
     493           0 :     aNumInfo.mbAutoStart = sal_True;
     494           0 :     aNumInfo.mbAutoEnd = sal_True;
     495             : 
     496           0 :     if( const double* pfMinValue = GetNumGroupLimit( EXC_SXFIELD_INDEX_MIN ) )
     497             :     {
     498           0 :         aNumInfo.mfStart = *pfMinValue;
     499           0 :         aNumInfo.mbAutoStart = ::get_flag( maNumGroupInfo.mnFlags, EXC_SXNUMGROUP_AUTOMIN );
     500             :     }
     501           0 :     if( const double* pfMaxValue = GetNumGroupLimit( EXC_SXFIELD_INDEX_MAX ) )
     502             :     {
     503           0 :         aNumInfo.mfEnd = *pfMaxValue;
     504           0 :         aNumInfo.mbAutoEnd = ::get_flag( maNumGroupInfo.mnFlags, EXC_SXNUMGROUP_AUTOMAX );
     505             :     }
     506           0 :     if( const double* pfStepValue = GetNumGroupLimit( EXC_SXFIELD_INDEX_STEP ) )
     507           0 :         aNumInfo.mfStep = *pfStepValue;
     508             : 
     509           0 :     return aNumInfo;
     510             : }
     511             : 
     512           0 : ScDPNumGroupInfo XclImpPCField::GetScDateGroupInfo() const
     513             : {
     514           0 :     ScDPNumGroupInfo aDateInfo;
     515           0 :     aDateInfo.mbEnable = sal_True;
     516           0 :     aDateInfo.mbDateValues = false;
     517           0 :     aDateInfo.mbAutoStart = sal_True;
     518           0 :     aDateInfo.mbAutoEnd = sal_True;
     519             : 
     520           0 :     if( const DateTime* pMinDate = GetDateGroupLimit( EXC_SXFIELD_INDEX_MIN ) )
     521             :     {
     522           0 :         aDateInfo.mfStart = GetDoubleFromDateTime( *pMinDate );
     523           0 :         aDateInfo.mbAutoStart = ::get_flag( maNumGroupInfo.mnFlags, EXC_SXNUMGROUP_AUTOMIN );
     524             :     }
     525           0 :     if( const DateTime* pMaxDate = GetDateGroupLimit( EXC_SXFIELD_INDEX_MAX ) )
     526             :     {
     527           0 :         aDateInfo.mfEnd = GetDoubleFromDateTime( *pMaxDate );
     528           0 :         aDateInfo.mbAutoEnd = ::get_flag( maNumGroupInfo.mnFlags, EXC_SXNUMGROUP_AUTOMAX );
     529             :     }
     530             :     // GetDateGroupStep() returns a value for date type "day" in single date groups only
     531           0 :     if( const sal_Int16* pnStepValue = GetDateGroupStep() )
     532             :     {
     533           0 :         aDateInfo.mfStep = *pnStepValue;
     534           0 :         aDateInfo.mbDateValues = sal_True;
     535             :     }
     536             : 
     537           0 :     return aDateInfo;
     538             : }
     539             : 
     540           0 : const double* XclImpPCField::GetNumGroupLimit( sal_uInt16 nLimitIdx ) const
     541             : {
     542             :     OSL_ENSURE( IsNumGroupField(), "XclImpPCField::GetNumGroupLimit - only for numeric grouping fields" );
     543           0 :     if( const XclImpPCItem* pItem = GetLimitItem( nLimitIdx ) )
     544             :     {
     545             :         OSL_ENSURE( pItem->GetDouble(), "XclImpPCField::GetNumGroupLimit - SXDOUBLE item expected" );
     546           0 :         return pItem->GetDouble();
     547             :     }
     548           0 :     return 0;
     549             : }
     550             : 
     551           0 : const DateTime* XclImpPCField::GetDateGroupLimit( sal_uInt16 nLimitIdx ) const
     552             : {
     553             :     OSL_ENSURE( IsDateGroupField(), "XclImpPCField::GetDateGroupLimit - only for date grouping fields" );
     554           0 :     if( const XclImpPCItem* pItem = GetLimitItem( nLimitIdx ) )
     555             :     {
     556             :         OSL_ENSURE( pItem->GetDateTime(), "XclImpPCField::GetDateGroupLimit - SXDATETIME item expected" );
     557           0 :         return pItem->GetDateTime();
     558             :     }
     559           0 :     return 0;
     560             : }
     561             : 
     562           0 : const sal_Int16* XclImpPCField::GetDateGroupStep() const
     563             : {
     564             :     // only for single date grouping fields, not for grouping chains
     565           0 :     if( !IsGroupBaseField() && !IsGroupChildField() )
     566             :     {
     567             :         // only days may have a step value, return 0 for all other date types
     568           0 :         if( maNumGroupInfo.GetXclDataType() == EXC_SXNUMGROUP_TYPE_DAY )
     569             :         {
     570           0 :             if( const XclImpPCItem* pItem = GetLimitItem( EXC_SXFIELD_INDEX_STEP ) )
     571             :             {
     572             :                 OSL_ENSURE( pItem->GetInteger(), "XclImpPCField::GetDateGroupStep - SXINTEGER item expected" );
     573           0 :                 if( const sal_Int16* pnStep = pItem->GetInteger() )
     574             :                 {
     575             :                     OSL_ENSURE( *pnStep > 0, "XclImpPCField::GetDateGroupStep - invalid step count" );
     576             :                     // return nothing for step count 1 - this is also a standard date group in Excel
     577           0 :                     return (*pnStep > 1) ? pnStep : 0;
     578             :                 }
     579             :             }
     580             :         }
     581             :     }
     582           0 :     return 0;
     583             : }
     584             : 
     585             : // ============================================================================
     586             : 
     587           1 : XclImpPivotCache::XclImpPivotCache( const XclImpRoot& rRoot ) :
     588             :     XclImpRoot( rRoot ),
     589             :     maSrcRange( ScAddress::INITIALIZE_INVALID ),
     590             :     mnStrmId( 0 ),
     591             :     mnSrcType( EXC_SXVS_UNKNOWN ),
     592           1 :     mbSelfRef( false )
     593             : {
     594           1 : }
     595             : 
     596           2 : XclImpPivotCache::~XclImpPivotCache()
     597             : {
     598           2 : }
     599             : 
     600             : // data access ----------------------------------------------------------------
     601             : 
     602           2 : sal_uInt16 XclImpPivotCache::GetFieldCount() const
     603             : {
     604           2 :     return static_cast< sal_uInt16 >( maFields.size() );
     605             : }
     606             : 
     607           0 : const XclImpPCField* XclImpPivotCache::GetField( sal_uInt16 nFieldIdx ) const
     608             : {
     609           0 :     return (nFieldIdx < maFields.size()) ? maFields[ nFieldIdx ].get() : 0;
     610             : }
     611             : 
     612             : // records --------------------------------------------------------------------
     613             : 
     614           1 : void XclImpPivotCache::ReadSxidstm( XclImpStream& rStrm )
     615             : {
     616           1 :     rStrm >> mnStrmId;
     617           1 : }
     618             : 
     619           1 : void XclImpPivotCache::ReadSxvs( XclImpStream& rStrm )
     620             : {
     621           1 :     rStrm >> mnSrcType;
     622           1 :     GetTracer().TracePivotDataSource( mnSrcType != EXC_SXVS_SHEET );
     623           1 : }
     624             : 
     625           1 : void XclImpPivotCache::ReadDconref( XclImpStream& rStrm )
     626             : {
     627             :     /*  Read DCONREF only once (by checking maTabName), there may be other
     628             :         DCONREF records in another context. Read reference only if a leading
     629             :         SXVS record is present (by checking mnSrcType). */
     630           1 :     if( (maTabName.Len() > 0) || (mnSrcType != EXC_SXVS_SHEET) )
     631           1 :         return;
     632             : 
     633           1 :     XclRange aXclRange( ScAddress::UNINITIALIZED );
     634           1 :     aXclRange.Read( rStrm, false );
     635           1 :     String aEncUrl = rStrm.ReadUniString();
     636             : 
     637           1 :     XclImpUrlHelper::DecodeUrl( maUrl, maTabName, mbSelfRef, GetRoot(), aEncUrl );
     638             : 
     639             :     /*  Do not convert maTabName to Calc sheet name -> original name is used to
     640             :         find the sheet in the document. Sheet index of source range will be
     641             :         found later in XclImpPivotCache::ReadPivotCacheStream(), because sheet
     642             :         may not exist yet. */
     643           1 :     if( mbSelfRef )
     644           1 :         GetAddressConverter().ConvertRange( maSrcRange, aXclRange, 0, 0, true );
     645             : }
     646             : 
     647           0 : void XclImpPivotCache::ReadDConName( XclImpStream& rStrm )
     648             : {
     649           0 :     maSrcRangeName = rStrm.ReadUniString();
     650             : 
     651             :     // This 2-byte value equals the length of string that follows, or if 0 it
     652             :     // indicates that the name has a workbook scope.  For now, we only support
     653             :     // internal defined name with a workbook scope.
     654             :     sal_uInt16 nFlag;
     655           0 :     rStrm >> nFlag;
     656           0 :     mbSelfRef = (nFlag == 0);
     657             : 
     658           0 :     if (!mbSelfRef)
     659             :         // External name is not supported yet.
     660           0 :         maSrcRangeName = OUString();
     661           0 : }
     662             : 
     663           1 : void XclImpPivotCache::ReadPivotCacheStream( XclImpStream& rStrm )
     664             : {
     665           1 :     if( (mnSrcType != EXC_SXVS_SHEET) && (mnSrcType != EXC_SXVS_EXTERN) )
     666             :         return;
     667             : 
     668           1 :     ScDocument& rDoc = GetDoc();
     669           1 :     SCCOL nFieldScCol = 0;              // column index of source data for next field
     670           1 :     SCROW nItemScRow = 0;               // row index of source data for current items
     671           1 :     SCTAB nScTab = 0;                   // sheet index of source data
     672           1 :     bool bGenerateSource = false;       // true = write source data from cache to dummy table
     673             : 
     674           1 :     if( mbSelfRef )
     675             :     {
     676           1 :         if (maSrcRangeName.isEmpty())
     677             :         {
     678             :             // try to find internal sheet containing the source data
     679           1 :             nScTab = GetTabInfo().GetScTabFromXclName( maTabName );
     680           1 :             if( rDoc.HasTable( nScTab ) )
     681             :             {
     682             :                 // set sheet index to source range
     683           1 :                 maSrcRange.aStart.SetTab( nScTab );
     684           1 :                 maSrcRange.aEnd.SetTab( nScTab );
     685             :             }
     686             :             else
     687             :             {
     688             :                 // create dummy sheet for deleted internal sheet
     689           0 :                 bGenerateSource = true;
     690             :             }
     691             :         }
     692             :     }
     693             :     else
     694             :     {
     695             :         // create dummy sheet for external sheet
     696           0 :         bGenerateSource = true;
     697             :     }
     698             : 
     699             :     // create dummy sheet for source data from external or deleted sheet
     700           1 :     if( bGenerateSource )
     701             :     {
     702           0 :         if( rDoc.GetTableCount() >= MAXTABCOUNT )
     703             :             // cannot create more sheets -> exit
     704             :             return;
     705             : 
     706           0 :         nScTab = rDoc.GetTableCount();
     707           0 :         rDoc.MakeTable( nScTab );
     708           0 :         rtl::OUStringBuffer aDummyName(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DPCache") ));
     709           0 :         if( maTabName.Len() > 0 )
     710           0 :             aDummyName.append( '_' ).append( maTabName );
     711           0 :         rtl::OUString aName = aDummyName.makeStringAndClear();
     712           0 :         rDoc.CreateValidTabName( aName );
     713           0 :         rDoc.RenameTab( nScTab, aName );
     714             :         // set sheet index to source range
     715           0 :         maSrcRange.aStart.SetTab( nScTab );
     716           0 :         maSrcRange.aEnd.SetTab( nScTab );
     717             :     }
     718             : 
     719             :     // open pivot cache storage stream
     720           1 :     SotStorageRef xSvStrg = OpenStorage( EXC_STORAGE_PTCACHE );
     721           1 :     SotStorageStreamRef xSvStrm = OpenStream( xSvStrg, ScfTools::GetHexStr( mnStrmId ) );
     722           1 :     if( !xSvStrm.Is() )
     723             :         return;
     724             : 
     725             :     // create Excel record stream object
     726           1 :     XclImpStream aPCStrm( *xSvStrm, GetRoot() );
     727           1 :     aPCStrm.CopyDecrypterFrom( rStrm );     // pivot cache streams are encrypted
     728             : 
     729           1 :     XclImpPCFieldRef xCurrField;    // current field for new items
     730           1 :     XclImpPCFieldVec aOrigFields;   // all standard fields with inline original  items
     731           1 :     XclImpPCFieldVec aPostpFields;  // all standard fields with postponed original items
     732           1 :     size_t nPostpIdx = 0;           // index to current field with postponed items
     733           1 :     bool bLoop = true;              // true = continue loop
     734             : 
     735          15 :     while( bLoop && aPCStrm.StartNextRecord() )
     736             :     {
     737          13 :         switch( aPCStrm.GetRecId() )
     738             :         {
     739             :             case EXC_ID_EOF:
     740           1 :                 bLoop = false;
     741           1 :             break;
     742             : 
     743             :             case EXC_ID_SXDB:
     744           1 :                 aPCStrm >> maPCInfo;
     745           1 :             break;
     746             : 
     747             :             case EXC_ID_SXFIELD:
     748             :             {
     749           2 :                 xCurrField.reset();
     750           2 :                 sal_uInt16 nNewFieldIdx = GetFieldCount();
     751           2 :                 if( nNewFieldIdx < EXC_PC_MAXFIELDCOUNT )
     752             :                 {
     753           2 :                     xCurrField.reset( new XclImpPCField( GetRoot(), *this, nNewFieldIdx ) );
     754           2 :                     maFields.push_back( xCurrField );
     755           2 :                     xCurrField->ReadSxfield( aPCStrm );
     756           2 :                     if( xCurrField->HasOrigItems() )
     757             :                     {
     758           2 :                         if( xCurrField->HasPostponedItems() )
     759           0 :                             aPostpFields.push_back( xCurrField );
     760             :                         else
     761           2 :                             aOrigFields.push_back( xCurrField );
     762             :                         // insert field name into generated source data, field remembers its column index
     763           2 :                         if( bGenerateSource && (nFieldScCol <= MAXCOL) )
     764           0 :                             xCurrField->WriteFieldNameToSource( nFieldScCol++, nScTab );
     765             :                     }
     766             :                     // do not read items into invalid/postponed fields
     767           2 :                     if( !xCurrField->HasInlineItems() )
     768           0 :                         xCurrField.reset();
     769             :                 }
     770             :             }
     771           2 :             break;
     772             : 
     773             :             case EXC_ID_SXINDEXLIST:
     774             :                 // read index list and insert all items into generated source data
     775           2 :                 if( bGenerateSource && (nItemScRow <= MAXROW) && (++nItemScRow <= MAXROW) )
     776             :                 {
     777           0 :                     for( XclImpPCFieldVec::const_iterator aIt = aOrigFields.begin(), aEnd = aOrigFields.end(); aIt != aEnd; ++aIt )
     778             :                     {
     779           0 :                         sal_uInt16 nItemIdx = (*aIt)->Has16BitIndexes() ? aPCStrm.ReaduInt16() : aPCStrm.ReaduInt8();
     780           0 :                         (*aIt)->WriteOrigItemToSource( nItemScRow, nScTab, nItemIdx );
     781             :                     }
     782             :                 }
     783           2 :                 xCurrField.reset();
     784           2 :             break;
     785             : 
     786             :             case EXC_ID_SXDOUBLE:
     787             :             case EXC_ID_SXBOOLEAN:
     788             :             case EXC_ID_SXERROR:
     789             :             case EXC_ID_SXINTEGER:
     790             :             case EXC_ID_SXSTRING:
     791             :             case EXC_ID_SXDATETIME:
     792             :             case EXC_ID_SXEMPTY:
     793           4 :                 if( xCurrField )                   // inline items
     794             :                 {
     795           4 :                     xCurrField->ReadItem( aPCStrm );
     796             :                 }
     797           0 :                 else if( !aPostpFields.empty() )        // postponed items
     798             :                 {
     799             :                     // read postponed item
     800           0 :                     aPostpFields[ nPostpIdx ]->ReadItem( aPCStrm );
     801             :                     // write item to source
     802           0 :                     if( bGenerateSource && (nItemScRow <= MAXROW) )
     803             :                     {
     804             :                         // start new row, if there are only postponed fields
     805           0 :                         if( aOrigFields.empty() && (nPostpIdx == 0) )
     806           0 :                             ++nItemScRow;
     807           0 :                         if( nItemScRow <= MAXROW )
     808           0 :                             aPostpFields[ nPostpIdx ]->WriteLastOrigItemToSource( nItemScRow, nScTab );
     809             :                     }
     810             :                     // get index of next postponed field
     811           0 :                     ++nPostpIdx;
     812           0 :                     if( nPostpIdx >= aPostpFields.size() )
     813           0 :                         nPostpIdx = 0;
     814             :                 }
     815           4 :             break;
     816             : 
     817             :             case EXC_ID_SXNUMGROUP:
     818           0 :                 if( xCurrField )
     819           0 :                     xCurrField->ReadSxnumgroup( aPCStrm );
     820           0 :             break;
     821             : 
     822             :             case EXC_ID_SXGROUPINFO:
     823           0 :                 if( xCurrField )
     824           0 :                     xCurrField->ReadSxgroupinfo( aPCStrm );
     825           0 :             break;
     826             : 
     827             :             // known but ignored records
     828             :             case EXC_ID_SXRULE:
     829             :             case EXC_ID_SXFILT:
     830             :             case EXC_ID_00F5:
     831             :             case EXC_ID_SXNAME:
     832             :             case EXC_ID_SXPAIR:
     833             :             case EXC_ID_SXFMLA:
     834             :             case EXC_ID_SXFORMULA:
     835             :             case EXC_ID_SXDBEX:
     836             :             case EXC_ID_SXFDBTYPE:
     837           3 :             break;
     838             : 
     839             :             default:
     840             :                 OSL_TRACE( "XclImpPivotCache::ReadPivotCacheStream - unknown record 0x%04hX", aPCStrm.GetRecId() );
     841             :         }
     842             :     }
     843             : 
     844             :     OSL_ENSURE( maPCInfo.mnTotalFields == maFields.size(),
     845             :         "XclImpPivotCache::ReadPivotCacheStream - field count mismatch" );
     846             : 
     847           1 :     if (HasCacheRecords())
     848             :     {
     849           1 :         SCROW nNewEnd = maSrcRange.aStart.Row() + maPCInfo.mnSrcRecs;
     850           1 :         maSrcRange.aEnd.SetRow(nNewEnd);
     851             :     }
     852             : 
     853             :     // set source range for external source data
     854           1 :     if( bGenerateSource && (nFieldScCol > 0) )
     855             :     {
     856           0 :         maSrcRange.aStart.SetCol( 0 );
     857           0 :         maSrcRange.aStart.SetRow( 0 );
     858             :         // nFieldScCol points to first unused column
     859           0 :         maSrcRange.aEnd.SetCol( nFieldScCol - 1 );
     860             :         // nItemScRow points to last used row
     861           0 :         maSrcRange.aEnd.SetRow( nItemScRow );
     862           1 :     }
     863             : }
     864             : 
     865           1 : bool XclImpPivotCache::HasCacheRecords() const
     866             : {
     867           1 :     return static_cast<bool>(maPCInfo.mnFlags & EXC_SXDB_SAVEDATA);
     868             : }
     869             : 
     870           0 : bool XclImpPivotCache::IsRefreshOnLoad() const
     871             : {
     872           0 :     return static_cast<bool>(maPCInfo.mnFlags & EXC_SXDB_REFRESH_LOAD);
     873             : }
     874             : 
     875           0 : bool XclImpPivotCache::IsValid() const
     876             : {
     877           0 :     if (!maSrcRangeName.isEmpty())
     878           0 :         return true;
     879             : 
     880           0 :     return maSrcRange.IsValid();
     881             : }
     882             : 
     883             : // ============================================================================
     884             : // Pivot table
     885             : // ============================================================================
     886             : 
     887           6 : XclImpPTItem::XclImpPTItem( const XclImpPCField* pCacheField ) :
     888           6 :     mpCacheField( pCacheField )
     889             : {
     890           6 : }
     891             : 
     892           0 : const rtl::OUString* XclImpPTItem::GetItemName() const
     893             : {
     894           0 :     if( mpCacheField )
     895           0 :         if( const XclImpPCItem* pCacheItem = mpCacheField->GetItem( maItemInfo.mnCacheIdx ) )
     896             :             //! TODO: use XclImpPCItem::ConvertToText(), if all conversions are available
     897           0 :             return pCacheItem->IsEmpty() ? NULL : pCacheItem->GetText();
     898           0 :     return 0;
     899             : }
     900             : 
     901           6 : void XclImpPTItem::ReadSxvi( XclImpStream& rStrm )
     902             : {
     903           6 :     rStrm >> maItemInfo;
     904           6 : }
     905             : 
     906           0 : void XclImpPTItem::ConvertItem( ScDPSaveDimension& rSaveDim ) const
     907             : {
     908           0 :     if (const rtl::OUString* pItemName = GetItemName())
     909             :     {
     910           0 :         ScDPSaveMember& rMember = *rSaveDim.GetMemberByName( *pItemName );
     911           0 :         rMember.SetIsVisible( !::get_flag( maItemInfo.mnFlags, EXC_SXVI_HIDDEN ) );
     912           0 :         rMember.SetShowDetails( !::get_flag( maItemInfo.mnFlags, EXC_SXVI_HIDEDETAIL ) );
     913           0 :         if (maItemInfo.HasVisName())
     914           0 :             rMember.SetLayoutName(*maItemInfo.GetVisName());
     915             :     }
     916           0 : }
     917             : 
     918             : // ============================================================================
     919             : 
     920           3 : XclImpPTField::XclImpPTField( const XclImpPivotTable& rPTable, sal_uInt16 nCacheIdx ) :
     921           3 :     mrPTable( rPTable )
     922             : {
     923           3 :     maFieldInfo.mnCacheIdx = nCacheIdx;
     924           3 : }
     925             : 
     926             : // general field/item access --------------------------------------------------
     927             : 
     928           6 : const XclImpPCField* XclImpPTField::GetCacheField() const
     929             : {
     930           6 :     XclImpPivotCacheRef xPCache = mrPTable.GetPivotCache();
     931           6 :     return xPCache ? xPCache->GetField( maFieldInfo.mnCacheIdx ) : 0;
     932             : }
     933             : 
     934           0 : rtl::OUString XclImpPTField::GetFieldName() const
     935             : {
     936           0 :     const XclImpPCField* pField = GetCacheField();
     937           0 :     return pField ? pField->GetFieldName( mrPTable.GetVisFieldNames() ) : rtl::OUString();
     938             : }
     939             : 
     940           2 : rtl::OUString XclImpPTField::GetVisFieldName() const
     941             : {
     942           2 :     const rtl::OUString* pVisName = maFieldInfo.GetVisName();
     943           2 :     return pVisName ? *pVisName : rtl::OUString();
     944             : }
     945             : 
     946           0 : const XclImpPTItem* XclImpPTField::GetItem( sal_uInt16 nItemIdx ) const
     947             : {
     948           0 :     return (nItemIdx < maItems.size()) ? maItems[ nItemIdx ].get() : 0;
     949             : }
     950             : 
     951           0 : const rtl::OUString* XclImpPTField::GetItemName( sal_uInt16 nItemIdx ) const
     952             : {
     953           0 :     const XclImpPTItem* pItem = GetItem( nItemIdx );
     954           0 :     return pItem ? pItem->GetItemName() : 0;
     955             : }
     956             : 
     957             : // records --------------------------------------------------------------------
     958             : 
     959           2 : void XclImpPTField::ReadSxvd( XclImpStream& rStrm )
     960             : {
     961           2 :     rStrm >> maFieldInfo;
     962           2 : }
     963             : 
     964           2 : void XclImpPTField::ReadSxvdex( XclImpStream& rStrm )
     965             : {
     966           2 :     rStrm >> maFieldExtInfo;
     967           2 : }
     968             : 
     969           6 : void XclImpPTField::ReadSxvi( XclImpStream& rStrm )
     970             : {
     971           6 :     XclImpPTItemRef xItem( new XclImpPTItem( GetCacheField() ) );
     972           6 :     maItems.push_back( xItem );
     973           6 :     xItem->ReadSxvi( rStrm );
     974           6 : }
     975             : 
     976             : // row/column fields ----------------------------------------------------------
     977             : 
     978           0 : void XclImpPTField::ConvertRowColField( ScDPSaveData& rSaveData ) const
     979             : {
     980             :     OSL_ENSURE( maFieldInfo.mnAxes & EXC_SXVD_AXIS_ROWCOL, "XclImpPTField::ConvertRowColField - no row/column field" );
     981             :     // special data orientation field?
     982           0 :     if( maFieldInfo.mnCacheIdx == EXC_SXIVD_DATA )
     983           0 :         rSaveData.GetDataLayoutDimension()->SetOrientation( static_cast< sal_uInt16 >( maFieldInfo.GetApiOrient( EXC_SXVD_AXIS_ROWCOL ) ) );
     984             :     else
     985           0 :         ConvertRCPField( rSaveData );
     986           0 : }
     987             : 
     988             : // page fields ----------------------------------------------------------------
     989             : 
     990           0 : void XclImpPTField::SetPageFieldInfo( const XclPTPageFieldInfo& rPageInfo )
     991             : {
     992           0 :     maPageInfo = rPageInfo;
     993           0 : }
     994             : 
     995           0 : void XclImpPTField::ConvertPageField( ScDPSaveData& rSaveData ) const
     996             : {
     997             :     OSL_ENSURE( maFieldInfo.mnAxes & EXC_SXVD_AXIS_PAGE, "XclImpPTField::ConvertPageField - no page field" );
     998           0 :     if( ScDPSaveDimension* pSaveDim = ConvertRCPField( rSaveData ) )
     999             :     {
    1000           0 :         const rtl::OUString* pName = GetItemName( maPageInfo.mnSelItem );
    1001           0 :         if (pName)
    1002           0 :             pSaveDim->SetCurrentPage(pName);
    1003             :     }
    1004           0 : }
    1005             : 
    1006             : // hidden fields --------------------------------------------------------------
    1007             : 
    1008           0 : void XclImpPTField::ConvertHiddenField( ScDPSaveData& rSaveData ) const
    1009             : {
    1010             :     OSL_ENSURE( (maFieldInfo.mnAxes & EXC_SXVD_AXIS_ROWCOLPAGE) == 0, "XclImpPTField::ConvertHiddenField - field not hidden" );
    1011           0 :     ConvertRCPField( rSaveData );
    1012           0 : }
    1013             : 
    1014             : // data fields ----------------------------------------------------------------
    1015             : 
    1016           0 : bool XclImpPTField::HasDataFieldInfo() const
    1017             : {
    1018           0 :     return !maDataInfoList.empty();
    1019             : }
    1020             : 
    1021           0 : void XclImpPTField::AddDataFieldInfo( const XclPTDataFieldInfo& rDataInfo )
    1022             : {
    1023             :     OSL_ENSURE( maFieldInfo.mnAxes & EXC_SXVD_AXIS_DATA, "XclImpPTField::AddDataFieldInfo - no data field" );
    1024           0 :     maDataInfoList.push_back( rDataInfo );
    1025           0 : }
    1026             : 
    1027           0 : void XclImpPTField::ConvertDataField( ScDPSaveData& rSaveData ) const
    1028             : {
    1029             :     OSL_ENSURE( maFieldInfo.mnAxes & EXC_SXVD_AXIS_DATA, "XclImpPTField::ConvertDataField - no data field" );
    1030             :     OSL_ENSURE( !maDataInfoList.empty(), "XclImpPTField::ConvertDataField - no data field info" );
    1031           0 :     if (maDataInfoList.empty())
    1032             :         return;
    1033             : 
    1034           0 :     rtl::OUString aFieldName = GetFieldName();
    1035           0 :     if (aFieldName.isEmpty())
    1036             :         return;
    1037             : 
    1038           0 :     XclPTDataFieldInfoList::const_iterator aIt = maDataInfoList.begin(), aEnd = maDataInfoList.end();
    1039             : 
    1040           0 :     ScDPSaveDimension& rSaveDim = *rSaveData.GetNewDimensionByName(aFieldName);
    1041           0 :     ConvertDataField( rSaveDim, *aIt );
    1042             : 
    1043             :     // multiple data fields -> clone dimension
    1044           0 :     for( ++aIt; aIt != aEnd; ++aIt )
    1045             :     {
    1046           0 :         ScDPSaveDimension& rDupDim = rSaveData.DuplicateDimension( rSaveDim );
    1047           0 :         ConvertDataFieldInfo( rDupDim, *aIt );
    1048           0 :     }
    1049             : }
    1050             : 
    1051             : // private --------------------------------------------------------------------
    1052             : 
    1053             : /**
    1054             :  * Convert Excel-encoded subtotal name to a Calc-encoded one.
    1055             :  */
    1056           0 : static OUString lcl_convertExcelSubtotalName(const OUString& rName)
    1057             : {
    1058           0 :     OUStringBuffer aBuf;
    1059           0 :     const sal_Unicode* p = rName.getStr();
    1060           0 :     sal_Int32 n = rName.getLength();
    1061           0 :     for (sal_Int32 i = 0; i < n; ++i)
    1062             :     {
    1063           0 :         const sal_Unicode c = p[i];
    1064           0 :         if (c == sal_Unicode('\\'))
    1065             :         {
    1066           0 :             aBuf.append(c);
    1067           0 :             aBuf.append(c);
    1068             :         }
    1069             :         else
    1070           0 :             aBuf.append(c);
    1071             :     }
    1072           0 :     return aBuf.makeStringAndClear();
    1073             : }
    1074             : 
    1075           0 : ScDPSaveDimension* XclImpPTField::ConvertRCPField( ScDPSaveData& rSaveData ) const
    1076             : {
    1077           0 :     const String& rFieldName = GetFieldName();
    1078           0 :     if( rFieldName.Len() == 0 )
    1079           0 :         return 0;
    1080             : 
    1081           0 :     const XclImpPCField* pCacheField = GetCacheField();
    1082           0 :     if( !pCacheField || !pCacheField->IsSupportedField() )
    1083           0 :         return 0;
    1084             : 
    1085           0 :     ScDPSaveDimension* pTest = rSaveData.GetNewDimensionByName(rFieldName);
    1086           0 :     if (!pTest)
    1087           0 :         return NULL;
    1088             : 
    1089           0 :     ScDPSaveDimension& rSaveDim = *pTest;
    1090             : 
    1091             :     // orientation
    1092           0 :     rSaveDim.SetOrientation( static_cast< sal_uInt16 >( maFieldInfo.GetApiOrient( EXC_SXVD_AXIS_ROWCOLPAGE ) ) );
    1093             : 
    1094             :     // general field info
    1095           0 :     ConvertFieldInfo( rSaveDim );
    1096             : 
    1097             :     // visible name
    1098           0 :     if (const rtl::OUString* pVisName = maFieldInfo.GetVisName())
    1099           0 :         if (!pVisName->isEmpty())
    1100           0 :             rSaveDim.SetLayoutName( *pVisName );
    1101             : 
    1102             :     // subtotal function(s)
    1103           0 :     XclPTSubtotalVec aSubtotalVec;
    1104           0 :     maFieldInfo.GetSubtotals( aSubtotalVec );
    1105           0 :     if( !aSubtotalVec.empty() )
    1106           0 :         rSaveDim.SetSubTotals( static_cast< long >( aSubtotalVec.size() ), &aSubtotalVec[ 0 ] );
    1107             : 
    1108             :     // sorting
    1109           0 :     DataPilotFieldSortInfo aSortInfo;
    1110           0 :     aSortInfo.Field = mrPTable.GetDataFieldName( maFieldExtInfo.mnSortField );
    1111           0 :     aSortInfo.IsAscending = ::get_flag( maFieldExtInfo.mnFlags, EXC_SXVDEX_SORT_ASC );
    1112           0 :     aSortInfo.Mode = maFieldExtInfo.GetApiSortMode();
    1113           0 :     rSaveDim.SetSortInfo( &aSortInfo );
    1114             : 
    1115             :     // auto show
    1116           0 :     DataPilotFieldAutoShowInfo aShowInfo;
    1117           0 :     aShowInfo.IsEnabled = ::get_flag( maFieldExtInfo.mnFlags, EXC_SXVDEX_AUTOSHOW );
    1118           0 :     aShowInfo.ShowItemsMode = maFieldExtInfo.GetApiAutoShowMode();
    1119           0 :     aShowInfo.ItemCount = maFieldExtInfo.GetApiAutoShowCount();
    1120           0 :     aShowInfo.DataField = mrPTable.GetDataFieldName( maFieldExtInfo.mnShowField );
    1121           0 :     rSaveDim.SetAutoShowInfo( &aShowInfo );
    1122             : 
    1123             :     // layout
    1124           0 :     DataPilotFieldLayoutInfo aLayoutInfo;
    1125           0 :     aLayoutInfo.LayoutMode = maFieldExtInfo.GetApiLayoutMode();
    1126           0 :     aLayoutInfo.AddEmptyLines = ::get_flag( maFieldExtInfo.mnFlags, EXC_SXVDEX_LAYOUT_BLANK );
    1127           0 :     rSaveDim.SetLayoutInfo( &aLayoutInfo );
    1128             : 
    1129             :     // grouping info
    1130           0 :     pCacheField->ConvertGroupField( rSaveData, mrPTable.GetVisFieldNames() );
    1131             : 
    1132             :     // custom subtotal name
    1133           0 :     if (maFieldExtInfo.mpFieldTotalName.get())
    1134             :     {
    1135           0 :         OUString aSubName = lcl_convertExcelSubtotalName(*maFieldExtInfo.mpFieldTotalName);
    1136           0 :         rSaveDim.SetSubtotalName(aSubName);
    1137             :     }
    1138             : 
    1139           0 :     return &rSaveDim;
    1140             : }
    1141             : 
    1142           0 : void XclImpPTField::ConvertFieldInfo( ScDPSaveDimension& rSaveDim ) const
    1143             : {
    1144           0 :     rSaveDim.SetShowEmpty( ::get_flag( maFieldExtInfo.mnFlags, EXC_SXVDEX_SHOWALL ) );
    1145           0 :     ConvertItems( rSaveDim );
    1146           0 : }
    1147             : 
    1148           0 : void XclImpPTField::ConvertDataField( ScDPSaveDimension& rSaveDim, const XclPTDataFieldInfo& rDataInfo ) const
    1149             : {
    1150             :     // orientation
    1151           0 :     rSaveDim.SetOrientation( DataPilotFieldOrientation_DATA );
    1152             :     // general field info
    1153           0 :     ConvertFieldInfo( rSaveDim );
    1154             :     // extended data field info
    1155           0 :     ConvertDataFieldInfo( rSaveDim, rDataInfo );
    1156           0 : }
    1157             : 
    1158           0 : void XclImpPTField::ConvertDataFieldInfo( ScDPSaveDimension& rSaveDim, const XclPTDataFieldInfo& rDataInfo ) const
    1159             : {
    1160             :     // visible name
    1161           0 :     const rtl::OUString* pVisName = rDataInfo.GetVisName();
    1162           0 :     if (pVisName && !pVisName->isEmpty())
    1163           0 :         rSaveDim.SetLayoutName(*pVisName);
    1164             : 
    1165             :     // aggregation function
    1166           0 :     rSaveDim.SetFunction( static_cast< sal_uInt16 >( rDataInfo.GetApiAggFunc() ) );
    1167             : 
    1168             :     // result field reference
    1169           0 :     sal_Int32 nRefType = rDataInfo.GetApiRefType();
    1170           0 :     DataPilotFieldReference aFieldRef;
    1171           0 :     aFieldRef.ReferenceType = nRefType;
    1172           0 :     const XclImpPTField* pRefField = mrPTable.GetField(rDataInfo.mnRefField);
    1173           0 :     if (pRefField)
    1174             :     {
    1175           0 :         aFieldRef.ReferenceField = pRefField->GetFieldName();
    1176           0 :         aFieldRef.ReferenceItemType = rDataInfo.GetApiRefItemType();
    1177           0 :         if (aFieldRef.ReferenceItemType == sheet::DataPilotFieldReferenceItemType::NAMED)
    1178             :         {
    1179           0 :             const rtl::OUString* pRefItemName = pRefField->GetItemName(rDataInfo.mnRefItem);
    1180           0 :             if (pRefItemName)
    1181           0 :                 aFieldRef.ReferenceItemName = *pRefItemName;
    1182             :         }
    1183             :     }
    1184             : 
    1185           0 :     rSaveDim.SetReferenceValue(&aFieldRef);
    1186           0 : }
    1187             : 
    1188           0 : void XclImpPTField::ConvertItems( ScDPSaveDimension& rSaveDim ) const
    1189             : {
    1190           0 :     for( XclImpPTItemVec::const_iterator aIt = maItems.begin(), aEnd = maItems.end(); aIt != aEnd; ++aIt )
    1191           0 :         (*aIt)->ConvertItem( rSaveDim );
    1192           0 : }
    1193             : 
    1194             : // ============================================================================
    1195             : 
    1196           1 : XclImpPivotTable::XclImpPivotTable( const XclImpRoot& rRoot ) :
    1197             :     XclImpRoot( rRoot ),
    1198             :     maDataOrientField( *this, EXC_SXIVD_DATA ),
    1199           1 :     mpDPObj(NULL)
    1200             : {
    1201           1 : }
    1202             : 
    1203           2 : XclImpPivotTable::~XclImpPivotTable()
    1204             : {
    1205           2 : }
    1206             : 
    1207             : // cache/field access, misc. --------------------------------------------------
    1208             : 
    1209           2 : sal_uInt16 XclImpPivotTable::GetFieldCount() const
    1210             : {
    1211           2 :     return static_cast< sal_uInt16 >( maFields.size() );
    1212             : }
    1213             : 
    1214           0 : const XclImpPTField* XclImpPivotTable::GetField( sal_uInt16 nFieldIdx ) const
    1215             : {
    1216             :     return (nFieldIdx == EXC_SXIVD_DATA) ? &maDataOrientField :
    1217           0 :         ((nFieldIdx < maFields.size()) ? maFields[ nFieldIdx ].get() : 0);
    1218             : }
    1219             : 
    1220           0 : XclImpPTField* XclImpPivotTable::GetFieldAcc( sal_uInt16 nFieldIdx )
    1221             : {
    1222             :     // do not return maDataOrientField
    1223           0 :     return (nFieldIdx < maFields.size()) ? maFields[ nFieldIdx ].get() : 0;
    1224             : }
    1225             : 
    1226           0 : const XclImpPTField* XclImpPivotTable::GetDataField( sal_uInt16 nDataFieldIdx ) const
    1227             : {
    1228           0 :     if( nDataFieldIdx < maOrigDataFields.size() )
    1229           0 :         return GetField( maOrigDataFields[ nDataFieldIdx ] );
    1230           0 :     return 0;
    1231             : }
    1232             : 
    1233           0 : rtl::OUString XclImpPivotTable::GetDataFieldName( sal_uInt16 nDataFieldIdx ) const
    1234             : {
    1235           0 :     if( const XclImpPTField* pField = GetDataField( nDataFieldIdx ) )
    1236           0 :         return pField->GetFieldName();
    1237           0 :     return rtl::OUString();
    1238             : }
    1239             : 
    1240             : // records --------------------------------------------------------------------
    1241             : 
    1242           1 : void XclImpPivotTable::ReadSxview( XclImpStream& rStrm )
    1243             : {
    1244           1 :     rStrm >> maPTInfo;
    1245             : 
    1246           1 :     GetAddressConverter().ConvertRange(
    1247           2 :         maOutScRange, maPTInfo.maOutXclRange, GetCurrScTab(), GetCurrScTab(), true );
    1248             : 
    1249           1 :     mxPCache = GetPivotTableManager().GetPivotCache( maPTInfo.mnCacheIdx );
    1250           1 :     mxCurrField.reset();
    1251           1 : }
    1252             : 
    1253           2 : void XclImpPivotTable::ReadSxvd( XclImpStream& rStrm )
    1254             : {
    1255           2 :     sal_uInt16 nFieldCount = GetFieldCount();
    1256           2 :     if( nFieldCount < EXC_PT_MAXFIELDCOUNT )
    1257             :     {
    1258             :         // cache index for the field is equal to the SXVD record index
    1259           2 :         mxCurrField.reset( new XclImpPTField( *this, nFieldCount ) );
    1260           2 :         maFields.push_back( mxCurrField );
    1261           2 :         mxCurrField->ReadSxvd( rStrm );
    1262             :         // add visible name of new field to list of visible names
    1263           2 :         maVisFieldNames.push_back( mxCurrField->GetVisFieldName() );
    1264             :         OSL_ENSURE( maFields.size() == maVisFieldNames.size(),
    1265             :             "XclImpPivotTable::ReadSxvd - wrong size of visible name array" );
    1266             :     }
    1267             :     else
    1268           0 :         mxCurrField.reset();
    1269           2 : }
    1270             : 
    1271           6 : void XclImpPivotTable::ReadSxvi( XclImpStream& rStrm )
    1272             : {
    1273           6 :     if( mxCurrField )
    1274           6 :         mxCurrField->ReadSxvi( rStrm );
    1275           6 : }
    1276             : 
    1277           2 : void XclImpPivotTable::ReadSxvdex( XclImpStream& rStrm )
    1278             : {
    1279           2 :     if( mxCurrField )
    1280           2 :         mxCurrField->ReadSxvdex( rStrm );
    1281           2 : }
    1282             : 
    1283           1 : void XclImpPivotTable::ReadSxivd( XclImpStream& rStrm )
    1284             : {
    1285           1 :     mxCurrField.reset();
    1286             : 
    1287             :     // find the index vector to fill (row SXIVD doesn't exist without row fields)
    1288           1 :     ScfUInt16Vec* pFieldVec = 0;
    1289           1 :     if( maRowFields.empty() && (maPTInfo.mnRowFields > 0) )
    1290           1 :         pFieldVec = &maRowFields;
    1291           0 :     else if( maColFields.empty() && (maPTInfo.mnColFields > 0) )
    1292           0 :         pFieldVec = &maColFields;
    1293             : 
    1294             :     // fill the vector from record data
    1295           1 :     if( pFieldVec )
    1296             :     {
    1297           1 :         sal_uInt16 nSize = ulimit_cast< sal_uInt16 >( rStrm.GetRecSize() / 2, EXC_PT_MAXROWCOLCOUNT );
    1298           1 :         pFieldVec->reserve( nSize );
    1299           3 :         for( sal_uInt16 nIdx = 0; nIdx < nSize; ++nIdx )
    1300             :         {
    1301             :             sal_uInt16 nFieldIdx;
    1302           2 :             rStrm >> nFieldIdx;
    1303           2 :             pFieldVec->push_back( nFieldIdx );
    1304             : 
    1305             :             // set orientation at special data orientation field
    1306           2 :             if( nFieldIdx == EXC_SXIVD_DATA )
    1307             :             {
    1308           0 :                 sal_uInt16 nAxis = (pFieldVec == &maRowFields) ? EXC_SXVD_AXIS_ROW : EXC_SXVD_AXIS_COL;
    1309           0 :                 maDataOrientField.SetAxes( nAxis );
    1310             :             }
    1311             :         }
    1312             :     }
    1313           1 : }
    1314             : 
    1315           0 : void XclImpPivotTable::ReadSxpi( XclImpStream& rStrm )
    1316             : {
    1317           0 :     mxCurrField.reset();
    1318             : 
    1319           0 :     sal_uInt16 nSize = ulimit_cast< sal_uInt16 >( rStrm.GetRecSize() / 6 );
    1320           0 :     for( sal_uInt16 nEntry = 0; nEntry < nSize; ++nEntry )
    1321             :     {
    1322           0 :         XclPTPageFieldInfo aPageInfo;
    1323           0 :         rStrm >> aPageInfo;
    1324           0 :         if( XclImpPTField* pField = GetFieldAcc( aPageInfo.mnField ) )
    1325             :         {
    1326           0 :             maPageFields.push_back( aPageInfo.mnField );
    1327           0 :             pField->SetPageFieldInfo( aPageInfo );
    1328             :         }
    1329           0 :         GetCurrSheetDrawing().SetSkipObj( aPageInfo.mnObjId );
    1330             :     }
    1331           0 : }
    1332             : 
    1333           0 : void XclImpPivotTable::ReadSxdi( XclImpStream& rStrm )
    1334             : {
    1335           0 :     mxCurrField.reset();
    1336             : 
    1337           0 :     XclPTDataFieldInfo aDataInfo;
    1338           0 :     rStrm >> aDataInfo;
    1339           0 :     if( XclImpPTField* pField = GetFieldAcc( aDataInfo.mnField ) )
    1340             :     {
    1341           0 :         maOrigDataFields.push_back( aDataInfo.mnField );
    1342             :         // DataPilot does not support double data fields -> add first appearence to index list only
    1343           0 :         if( !pField->HasDataFieldInfo() )
    1344           0 :             maFiltDataFields.push_back( aDataInfo.mnField );
    1345           0 :         pField->AddDataFieldInfo( aDataInfo );
    1346           0 :     }
    1347           0 : }
    1348             : 
    1349           1 : void XclImpPivotTable::ReadSxex( XclImpStream& rStrm )
    1350             : {
    1351           1 :     rStrm >> maPTExtInfo;
    1352           1 : }
    1353             : 
    1354           1 : void XclImpPivotTable::ReadSxViewEx9( XclImpStream& rStrm )
    1355             : {
    1356           1 :     rStrm >> maPTViewEx9Info;
    1357           1 : }
    1358             : 
    1359             : // ----------------------------------------------------------------------------
    1360             : 
    1361           1 : void XclImpPivotTable::Convert()
    1362             : {
    1363           1 :     if( !mxPCache || !mxPCache->IsValid() )
    1364           1 :         return;
    1365             : 
    1366           0 :     ScDPSaveData aSaveData;
    1367             : 
    1368             :     // *** global settings ***
    1369             : 
    1370           0 :     aSaveData.SetRowGrand( ::get_flag( maPTInfo.mnFlags, EXC_SXVIEW_ROWGRAND ) );
    1371           0 :     aSaveData.SetColumnGrand( ::get_flag( maPTInfo.mnFlags, EXC_SXVIEW_COLGRAND ) );
    1372           0 :     aSaveData.SetFilterButton( false );
    1373           0 :     aSaveData.SetDrillDown( ::get_flag( maPTExtInfo.mnFlags, EXC_SXEX_DRILLDOWN ) );
    1374             : 
    1375             :     // *** fields ***
    1376             : 
    1377           0 :     ScfUInt16Vec::const_iterator aIt, aEnd;
    1378             : 
    1379             :     // row fields
    1380           0 :     for( aIt = maRowFields.begin(), aEnd = maRowFields.end(); aIt != aEnd; ++aIt )
    1381           0 :         if( const XclImpPTField* pField = GetField( *aIt ) )
    1382           0 :             pField->ConvertRowColField( aSaveData );
    1383             : 
    1384             :     // column fields
    1385           0 :     for( aIt = maColFields.begin(), aEnd = maColFields.end(); aIt != aEnd; ++aIt )
    1386           0 :         if( const XclImpPTField* pField = GetField( *aIt ) )
    1387           0 :             pField->ConvertRowColField( aSaveData );
    1388             : 
    1389             :     // page fields
    1390           0 :     for( aIt = maPageFields.begin(), aEnd = maPageFields.end(); aIt != aEnd; ++aIt )
    1391           0 :         if( const XclImpPTField* pField = GetField( *aIt ) )
    1392           0 :             pField->ConvertPageField( aSaveData );
    1393             : 
    1394             :     // We need to import hidden fields because hidden fields may contain
    1395             :     // special settings for subtotals (aggregation function, filters, custom
    1396             :     // name etc.) and members (hidden, custom name etc.).
    1397             : 
    1398             :     // hidden fields
    1399           0 :     for( sal_uInt16 nField = 0, nCount = GetFieldCount(); nField < nCount; ++nField )
    1400           0 :         if( const XclImpPTField* pField = GetField( nField ) )
    1401           0 :             if (!pField->GetAxes())
    1402           0 :                 pField->ConvertHiddenField( aSaveData );
    1403             : 
    1404             :     // data fields
    1405           0 :     for( aIt = maFiltDataFields.begin(), aEnd = maFiltDataFields.end(); aIt != aEnd; ++aIt )
    1406           0 :         if( const XclImpPTField* pField = GetField( *aIt ) )
    1407           0 :             pField->ConvertDataField( aSaveData );
    1408             : 
    1409             :     // *** insert into Calc document ***
    1410             : 
    1411             :     // create source descriptor
    1412           0 :     ScSheetSourceDesc aDesc(GetDocPtr());
    1413           0 :     const OUString& rSrcName = mxPCache->GetSourceRangeName();
    1414           0 :     if (!rSrcName.isEmpty())
    1415             :         // Range name is the data source.
    1416           0 :         aDesc.SetRangeName(rSrcName);
    1417             :     else
    1418             :         // Normal cell range.
    1419           0 :         aDesc.SetSourceRange(mxPCache->GetSourceRange());
    1420             : 
    1421             :     // adjust output range to include the page fields
    1422           0 :     ScRange aOutRange( maOutScRange );
    1423           0 :     if( !maPageFields.empty() )
    1424             :     {
    1425           0 :         SCsROW nDecRows = ::std::min< SCsROW >( aOutRange.aStart.Row(), maPageFields.size() + 1 );
    1426           0 :         aOutRange.aStart.IncRow( -nDecRows );
    1427             :     }
    1428             : 
    1429             :     // create the DataPilot
    1430           0 :     ScDPObject* pDPObj = new ScDPObject( GetDocPtr() );
    1431           0 :     pDPObj->SetName( maPTInfo.maTableName );
    1432           0 :     if (!maPTInfo.maDataName.isEmpty())
    1433           0 :         aSaveData.GetDataLayoutDimension()->SetLayoutName(maPTInfo.maDataName);
    1434             : 
    1435           0 :     if (!maPTViewEx9Info.maGrandTotalName.isEmpty())
    1436           0 :         aSaveData.SetGrandTotalName(maPTViewEx9Info.maGrandTotalName);
    1437             : 
    1438           0 :     pDPObj->SetSaveData( aSaveData );
    1439           0 :     pDPObj->SetSheetDesc( aDesc );
    1440           0 :     pDPObj->SetOutRange( aOutRange );
    1441           0 :     pDPObj->SetAlive(true);
    1442           0 :     pDPObj->SetHeaderLayout( maPTViewEx9Info.mnGridLayout == 0 );
    1443             : 
    1444           0 :     GetDoc().GetDPCollection()->InsertNewTable(pDPObj);
    1445           0 :     mpDPObj = pDPObj;
    1446             : 
    1447           0 :     ApplyMergeFlags(aOutRange, aSaveData);
    1448             : }
    1449             : 
    1450           1 : void XclImpPivotTable::MaybeRefresh()
    1451             : {
    1452           1 :     if (mpDPObj && mxPCache->IsRefreshOnLoad())
    1453             :     {
    1454             :         // 'refresh table on load' flag is set.  Refresh the table now.  Some
    1455             :         // Excel files contain partial table output when this flag is set.
    1456           0 :         ScRange aOutRange = mpDPObj->GetOutRange();
    1457           0 :         mpDPObj->Output(aOutRange.aStart);
    1458             :     }
    1459           1 : }
    1460             : 
    1461           0 : void XclImpPivotTable::ApplyMergeFlags(const ScRange& rOutRange, const ScDPSaveData& rSaveData)
    1462             : {
    1463             :     // Apply merge flags for varoius datapilot controls.
    1464             : 
    1465           0 :     ScDPOutputGeometry aGeometry(rOutRange, false);
    1466           0 :     aGeometry.setColumnFieldCount(maPTInfo.mnColFields);
    1467           0 :     aGeometry.setPageFieldCount(maPTInfo.mnPageFields);
    1468           0 :     aGeometry.setDataFieldCount(maPTInfo.mnDataFields);
    1469           0 :     aGeometry.setRowFieldCount(maPTInfo.mnRowFields);
    1470             : 
    1471           0 :     ScDocument& rDoc = GetDoc();
    1472             : 
    1473           0 :     vector<const ScDPSaveDimension*> aFieldDims;
    1474           0 :     vector<ScAddress> aFieldBtns;
    1475             : 
    1476           0 :     aGeometry.getPageFieldPositions(aFieldBtns);
    1477           0 :     vector<ScAddress>::const_iterator itr = aFieldBtns.begin(), itrEnd = aFieldBtns.end();
    1478           0 :     for (; itr != itrEnd; ++itr)
    1479             :     {
    1480           0 :         rDoc.ApplyFlagsTab(itr->Col(), itr->Row(), itr->Col(), itr->Row(), itr->Tab(), SC_MF_BUTTON);
    1481             : 
    1482           0 :         sal_uInt16 nMFlag = SC_MF_BUTTON_POPUP;
    1483           0 :         rtl::OUString aName;
    1484           0 :         rDoc.GetString(itr->Col(), itr->Row(), itr->Tab(), aName);
    1485           0 :         if (rSaveData.HasInvisibleMember(aName))
    1486           0 :             nMFlag |= SC_MF_HIDDEN_MEMBER;
    1487             : 
    1488           0 :         rDoc.ApplyFlagsTab(itr->Col()+1, itr->Row(), itr->Col()+1, itr->Row(), itr->Tab(), nMFlag);
    1489           0 :     }
    1490             : 
    1491           0 :     aGeometry.getColumnFieldPositions(aFieldBtns);
    1492           0 :     rSaveData.GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_COLUMN, aFieldDims);
    1493           0 :     if (aFieldBtns.size() == aFieldDims.size())
    1494             :     {
    1495           0 :         itr    = aFieldBtns.begin();
    1496           0 :         itrEnd = aFieldBtns.end();
    1497           0 :         vector<const ScDPSaveDimension*>::const_iterator itDim = aFieldDims.begin();
    1498           0 :         for (; itr != itrEnd; ++itr, ++itDim)
    1499             :         {
    1500           0 :             sal_Int16 nMFlag = SC_MF_BUTTON;
    1501           0 :             const ScDPSaveDimension* pDim = *itDim;
    1502           0 :             if (pDim->HasInvisibleMember())
    1503           0 :                 nMFlag |= SC_MF_HIDDEN_MEMBER;
    1504           0 :             if (!pDim->IsDataLayout())
    1505           0 :                 nMFlag |= SC_MF_BUTTON_POPUP;
    1506           0 :             rDoc.ApplyFlagsTab(itr->Col(), itr->Row(), itr->Col(), itr->Row(), itr->Tab(), nMFlag);
    1507             :         }
    1508             :     }
    1509             : 
    1510           0 :     aGeometry.getRowFieldPositions(aFieldBtns);
    1511           0 :     rSaveData.GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_ROW, aFieldDims);
    1512           0 :     if (aFieldBtns.size() == aFieldDims.size())
    1513             :     {
    1514           0 :         itr    = aFieldBtns.begin();
    1515           0 :         itrEnd = aFieldBtns.end();
    1516           0 :         vector<const ScDPSaveDimension*>::const_iterator itDim = aFieldDims.begin();
    1517           0 :         for (; itr != itrEnd; ++itr, ++itDim)
    1518             :         {
    1519           0 :             sal_Int16 nMFlag = SC_MF_BUTTON;
    1520           0 :             const ScDPSaveDimension* pDim = *itDim;
    1521           0 :             if (pDim->HasInvisibleMember())
    1522           0 :                 nMFlag |= SC_MF_HIDDEN_MEMBER;
    1523           0 :             if (!pDim->IsDataLayout())
    1524           0 :                 nMFlag |= SC_MF_BUTTON_POPUP;
    1525           0 :             rDoc.ApplyFlagsTab(itr->Col(), itr->Row(), itr->Col(), itr->Row(), itr->Tab(), nMFlag);
    1526             :         }
    1527           0 :     }
    1528           0 : }
    1529             : 
    1530             : // ============================================================================
    1531             : 
    1532          20 : XclImpPivotTableManager::XclImpPivotTableManager( const XclImpRoot& rRoot ) :
    1533          20 :     XclImpRoot( rRoot )
    1534             : {
    1535          20 : }
    1536             : 
    1537          40 : XclImpPivotTableManager::~XclImpPivotTableManager()
    1538             : {
    1539          40 : }
    1540             : 
    1541             : // pivot cache records --------------------------------------------------------
    1542             : 
    1543           1 : XclImpPivotCacheRef XclImpPivotTableManager::GetPivotCache( sal_uInt16 nCacheIdx )
    1544             : {
    1545           1 :     XclImpPivotCacheRef xPCache;
    1546           1 :     if( nCacheIdx < maPCaches.size() )
    1547           0 :         xPCache = maPCaches[ nCacheIdx ];
    1548           1 :     return xPCache;
    1549             : }
    1550             : 
    1551           1 : void XclImpPivotTableManager::ReadSxidstm( XclImpStream& rStrm )
    1552             : {
    1553           1 :     XclImpPivotCacheRef xPCache( new XclImpPivotCache( GetRoot() ) );
    1554           1 :     maPCaches.push_back( xPCache );
    1555           1 :     xPCache->ReadSxidstm( rStrm );
    1556           1 : }
    1557             : 
    1558           1 : void XclImpPivotTableManager::ReadSxvs( XclImpStream& rStrm )
    1559             : {
    1560           1 :     if( !maPCaches.empty() )
    1561           1 :         maPCaches.back()->ReadSxvs( rStrm );
    1562           1 : }
    1563             : 
    1564           1 : void XclImpPivotTableManager::ReadDconref( XclImpStream& rStrm )
    1565             : {
    1566           1 :     if( !maPCaches.empty() )
    1567           1 :         maPCaches.back()->ReadDconref( rStrm );
    1568           1 : }
    1569             : 
    1570           0 : void XclImpPivotTableManager::ReadDConName( XclImpStream& rStrm )
    1571             : {
    1572           0 :     if( !maPCaches.empty() )
    1573           0 :         maPCaches.back()->ReadDConName( rStrm );
    1574           0 : }
    1575             : 
    1576             : // pivot table records --------------------------------------------------------
    1577             : 
    1578           1 : void XclImpPivotTableManager::ReadSxview( XclImpStream& rStrm )
    1579             : {
    1580           1 :     XclImpPivotTableRef xPTable( new XclImpPivotTable( GetRoot() ) );
    1581           1 :     maPTables.push_back( xPTable );
    1582           1 :     xPTable->ReadSxview( rStrm );
    1583           1 : }
    1584             : 
    1585           2 : void XclImpPivotTableManager::ReadSxvd( XclImpStream& rStrm )
    1586             : {
    1587           2 :     if( !maPTables.empty() )
    1588           2 :         maPTables.back()->ReadSxvd( rStrm );
    1589           2 : }
    1590             : 
    1591           2 : void XclImpPivotTableManager::ReadSxvdex( XclImpStream& rStrm )
    1592             : {
    1593           2 :     if( !maPTables.empty() )
    1594           2 :         maPTables.back()->ReadSxvdex( rStrm );
    1595           2 : }
    1596             : 
    1597           1 : void XclImpPivotTableManager::ReadSxivd( XclImpStream& rStrm )
    1598             : {
    1599           1 :     if( !maPTables.empty() )
    1600           1 :         maPTables.back()->ReadSxivd( rStrm );
    1601           1 : }
    1602             : 
    1603           0 : void XclImpPivotTableManager::ReadSxpi( XclImpStream& rStrm )
    1604             : {
    1605           0 :     if( !maPTables.empty() )
    1606           0 :         maPTables.back()->ReadSxpi( rStrm );
    1607           0 : }
    1608             : 
    1609           0 : void XclImpPivotTableManager::ReadSxdi( XclImpStream& rStrm )
    1610             : {
    1611           0 :     if( !maPTables.empty() )
    1612           0 :         maPTables.back()->ReadSxdi( rStrm );
    1613           0 : }
    1614             : 
    1615           6 : void XclImpPivotTableManager::ReadSxvi( XclImpStream& rStrm )
    1616             : {
    1617           6 :     if( !maPTables.empty() )
    1618           6 :         maPTables.back()->ReadSxvi( rStrm );
    1619           6 : }
    1620             : 
    1621           1 : void XclImpPivotTableManager::ReadSxex( XclImpStream& rStrm )
    1622             : {
    1623           1 :     if( !maPTables.empty() )
    1624           1 :         maPTables.back()->ReadSxex( rStrm );
    1625           1 : }
    1626             : 
    1627           1 : void XclImpPivotTableManager::ReadSxViewEx9( XclImpStream& rStrm )
    1628             : {
    1629           1 :     if( !maPTables.empty() )
    1630           1 :         maPTables.back()->ReadSxViewEx9( rStrm );
    1631           1 : }
    1632             : 
    1633             : // ----------------------------------------------------------------------------
    1634             : 
    1635          19 : void XclImpPivotTableManager::ReadPivotCaches( XclImpStream& rStrm )
    1636             : {
    1637          20 :     for( XclImpPivotCacheVec::iterator aIt = maPCaches.begin(), aEnd = maPCaches.end(); aIt != aEnd; ++aIt )
    1638           1 :         (*aIt)->ReadPivotCacheStream( rStrm );
    1639          19 : }
    1640             : 
    1641          20 : void XclImpPivotTableManager::ConvertPivotTables()
    1642             : {
    1643          21 :     for( XclImpPivotTableVec::iterator aIt = maPTables.begin(), aEnd = maPTables.end(); aIt != aEnd; ++aIt )
    1644           1 :         (*aIt)->Convert();
    1645          20 : }
    1646             : 
    1647          20 : void XclImpPivotTableManager::MaybeRefreshPivotTables()
    1648             : {
    1649          21 :     for( XclImpPivotTableVec::iterator aIt = maPTables.begin(), aEnd = maPTables.end(); aIt != aEnd; ++aIt )
    1650           1 :         (*aIt)->MaybeRefresh();
    1651          29 : }
    1652             : 
    1653             : // ============================================================================
    1654             : 
    1655             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10