LCOV - code coverage report
Current view: top level - sc/source/filter/excel - xipivot.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 489 827 59.1 %
Date: 2014-11-03 Functions: 84 114 73.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10