LCOV - code coverage report
Current view: top level - sc/source/filter/excel - xipivot.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 489 832 58.8 %
Date: 2015-06-13 12:38:46 Functions: 84 114 73.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11