LCOV - code coverage report
Current view: top level - sc/source/filter/excel - xipivot.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 827 0.0 %
Date: 2014-04-14 Functions: 0 114 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10