LCOV - code coverage report
Current view: top level - sc/source/core/data - dpoutput.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 726 915 79.3 %
Date: 2015-06-13 12:38:46 Functions: 42 46 91.3 %
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 "scitems.hxx"
      21             : #include <svx/algitem.hxx>
      22             : #include <editeng/boxitem.hxx>
      23             : #include <editeng/brushitem.hxx>
      24             : #include <editeng/wghtitem.hxx>
      25             : #include <editeng/justifyitem.hxx>
      26             : #include <unotools/transliterationwrapper.hxx>
      27             : 
      28             : #include "dpoutput.hxx"
      29             : #include "dptabsrc.hxx"
      30             : #include "dpfilteredcache.hxx"
      31             : #include "document.hxx"
      32             : #include "patattr.hxx"
      33             : #include "docpool.hxx"
      34             : #include "markdata.hxx"
      35             : #include "attrib.hxx"
      36             : #include <formula/errorcodes.hxx>
      37             : #include "miscuno.hxx"
      38             : #include "globstr.hrc"
      39             : #include "stlpool.hxx"
      40             : #include "stlsheet.hxx"
      41             : #include "scresid.hxx"
      42             : #include "unonames.hxx"
      43             : #include "sc.hrc"
      44             : #include "stringutil.hxx"
      45             : #include "dputil.hxx"
      46             : 
      47             : #include <com/sun/star/beans/XPropertySet.hpp>
      48             : #include <com/sun/star/sheet/DataPilotTableHeaderData.hpp>
      49             : #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
      50             : #include <com/sun/star/sheet/DataPilotTablePositionData.hpp>
      51             : #include <com/sun/star/sheet/DataPilotTableResultData.hpp>
      52             : #include <com/sun/star/sheet/MemberResultFlags.hpp>
      53             : #include <com/sun/star/sheet/TableFilterField.hpp>
      54             : #include <com/sun/star/sheet/DataResultFlags.hpp>
      55             : #include <com/sun/star/sheet/DataPilotTablePositionType.hpp>
      56             : 
      57             : #include <vector>
      58             : 
      59             : using namespace com::sun::star;
      60             : using ::std::vector;
      61             : using ::com::sun::star::beans::XPropertySet;
      62             : using ::com::sun::star::uno::Sequence;
      63             : using ::com::sun::star::uno::UNO_QUERY;
      64             : using ::com::sun::star::uno::Reference;
      65             : using ::com::sun::star::sheet::DataPilotTablePositionData;
      66             : using ::com::sun::star::sheet::DataPilotTableResultData;
      67             : using ::com::sun::star::uno::makeAny;
      68             : using ::com::sun::star::uno::Any;
      69             : 
      70             : #define SC_DP_FRAME_INNER_BOLD      20
      71             : #define SC_DP_FRAME_OUTER_BOLD      40
      72             : 
      73             : #define SC_DP_FRAME_COLOR           Color(0,0,0) //( 0x20, 0x40, 0x68 )
      74             : 
      75             : #define SC_DPOUT_MAXLEVELS  256
      76             : 
      77       67640 : struct ScDPOutLevelData
      78             : {
      79             :     long                                nDim;
      80             :     long                                nHier;
      81             :     long                                nLevel;
      82             :     long                                nDimPos;
      83             :     sal_uInt32 mnSrcNumFmt; /// Prevailing number format used in the source data.
      84             :     uno::Sequence<sheet::MemberResult>  aResult;
      85             :     OUString                       maName;   /// Name is the internal field name.
      86             :     OUString                       maCaption; /// Caption is the name visible in the output table.
      87             :     bool                                mbHasHiddenMember:1;
      88             :     bool                                mbDataLayout:1;
      89             :     bool                                mbPageDim:1;
      90             : 
      91       67598 :     ScDPOutLevelData() :
      92       67598 :         nDim(-1), nHier(-1), nLevel(-1), nDimPos(-1), mnSrcNumFmt(0), mbHasHiddenMember(false), mbDataLayout(false), mbPageDim(false)
      93       67598 :     {}
      94             : 
      95          26 :     bool operator<(const ScDPOutLevelData& r) const
      96          52 :         { return nDimPos<r.nDimPos || ( nDimPos==r.nDimPos && nHier<r.nHier ) ||
      97          38 :             ( nDimPos==r.nDimPos && nHier==r.nHier && nLevel<r.nLevel ); }
      98             : 
      99          14 :     void Swap(ScDPOutLevelData& r)
     100          14 :         { ScDPOutLevelData aTemp; aTemp = r; r = *this; *this = aTemp; }
     101             : 
     102             :     // bug (73840) in uno::Sequence - copy and then assign doesn't work!
     103             : };
     104             : 
     105             : namespace {
     106             : 
     107         244 : bool lcl_compareColfuc ( SCCOL i,  SCCOL j) { return (i<j); }
     108         340 : bool lcl_compareRowfuc ( SCROW i,  SCROW j) { return (i<j); }
     109             : 
     110         199 : class ScDPOutputImpl
     111             : {
     112             :     ScDocument*         mpDoc;
     113             :     sal_uInt16          mnTab;
     114             :     ::std::vector< bool > mbNeedLineCols;
     115             :     ::std::vector< SCCOL > mnCols;
     116             : 
     117             :     ::std::vector< bool > mbNeedLineRows;
     118             :     ::std::vector< SCROW > mnRows;
     119             : 
     120             :     SCCOL   mnTabStartCol;
     121             :     SCROW   mnTabStartRow;
     122             : 
     123             :     SCCOL   mnDataStartCol;
     124             :     SCROW   mnDataStartRow;
     125             :     SCCOL   mnTabEndCol;
     126             :     SCROW   mnTabEndRow;
     127             : 
     128             : public:
     129             :     ScDPOutputImpl( ScDocument* pDoc, sal_uInt16 nTab,
     130             :         SCCOL   nTabStartCol,
     131             :         SCROW   nTabStartRow,
     132             :         SCCOL nDataStartCol,
     133             :         SCROW nDataStartRow,
     134             :         SCCOL nTabEndCol,
     135             :         SCROW nTabEndRow );
     136             :     bool AddRow( SCROW nRow );
     137             :     bool AddCol( SCCOL nCol );
     138             : 
     139             :     void OutputDataArea();
     140             :     void OutputBlockFrame ( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, bool bHori = false );
     141             : 
     142             : };
     143             : 
     144          87 : void ScDPOutputImpl::OutputDataArea()
     145             : {
     146          87 :     AddRow( mnDataStartRow );
     147          87 :     AddCol( mnDataStartCol );
     148             : 
     149          87 :     mnCols.push_back( mnTabEndCol+1); //set last row bottom
     150          87 :     mnRows.push_back( mnTabEndRow+1); //set last col bottom
     151             : 
     152          87 :     bool bAllRows = ( ( mnTabEndRow - mnDataStartRow + 2 ) == (SCROW) mnRows.size() );
     153             : 
     154          87 :     std::sort( mnCols.begin(), mnCols.end(), lcl_compareColfuc );
     155          87 :     std::sort( mnRows.begin(), mnRows.end(), lcl_compareRowfuc );
     156             : 
     157         228 :     for( SCCOL nCol = 0; nCol < (SCCOL)mnCols.size()-1; nCol ++ )
     158             :     {
     159         141 :         if ( !bAllRows )
     160             :         {
     161         102 :             if ( nCol < (SCCOL)mnCols.size()-2)
     162             :             {
     163          75 :                 for ( SCROW i = nCol%2; i < (SCROW)mnRows.size()-2; i +=2 )
     164          39 :                     OutputBlockFrame( mnCols[nCol], mnRows[i], mnCols[nCol+1]-1, mnRows[i+1]-1 );
     165          36 :                 if ( mnRows.size()>=2 )
     166          36 :                     OutputBlockFrame(  mnCols[nCol], mnRows[mnRows.size()-2], mnCols[nCol+1]-1, mnRows[mnRows.size()-1]-1 );
     167             :             }
     168             :             else
     169             :             {
     170         215 :                 for ( SCROW i = 0 ; i < (SCROW)mnRows.size()-1; i++ )
     171         149 :                     OutputBlockFrame(  mnCols[nCol], mnRows[i], mnCols[nCol+1]-1,  mnRows[i+1]-1 );
     172             :             }
     173             :         }
     174             :         else
     175          39 :             OutputBlockFrame( mnCols[nCol], mnRows.front(), mnCols[nCol+1]-1, mnRows.back()-1, bAllRows );
     176             :     }
     177             :     //out put rows area outer framer
     178          87 :     if ( mnTabStartCol != mnDataStartCol )
     179             :     {
     180          72 :         if ( mnTabStartRow != mnDataStartRow )
     181          72 :             OutputBlockFrame( mnTabStartCol, mnTabStartRow, mnDataStartCol-1, mnDataStartRow-1 );
     182          72 :         OutputBlockFrame( mnTabStartCol, mnDataStartRow, mnDataStartCol-1, mnTabEndRow );
     183             :     }
     184             :     //out put cols area outer framer
     185          87 :     OutputBlockFrame( mnDataStartCol, mnTabStartRow, mnTabEndCol, mnDataStartRow-1 );
     186          87 : }
     187             : 
     188         199 : ScDPOutputImpl::ScDPOutputImpl( ScDocument* pDoc, sal_uInt16 nTab,
     189             :         SCCOL   nTabStartCol,
     190             :         SCROW   nTabStartRow,
     191             :         SCCOL nDataStartCol,
     192             :         SCROW nDataStartRow,
     193             :         SCCOL nTabEndCol,
     194             :         SCROW nTabEndRow ):
     195             :     mpDoc( pDoc ),
     196             :     mnTab( nTab ),
     197             :     mnTabStartCol( nTabStartCol ),
     198             :     mnTabStartRow( nTabStartRow ),
     199             :     mnDataStartCol ( nDataStartCol ),
     200             :     mnDataStartRow ( nDataStartRow ),
     201             :     mnTabEndCol(  nTabEndCol ),
     202         199 :     mnTabEndRow(  nTabEndRow )
     203             : {
     204         199 :     mbNeedLineCols.resize( nTabEndCol-nDataStartCol+1, false );
     205         199 :     mbNeedLineRows.resize( nTabEndRow-nDataStartRow+1, false );
     206             : 
     207         199 : }
     208             : 
     209         216 : bool ScDPOutputImpl::AddRow( SCROW nRow )
     210             : {
     211         216 :     if ( !mbNeedLineRows[ nRow - mnDataStartRow ] )
     212             :     {
     213         195 :         mbNeedLineRows[ nRow - mnDataStartRow ] = true;
     214         195 :         mnRows.push_back( nRow );
     215         195 :         return true;
     216             :     }
     217             :     else
     218          21 :         return false;
     219             : }
     220             : 
     221         145 : bool ScDPOutputImpl::AddCol( SCCOL nCol )
     222             : {
     223             : 
     224         145 :     if ( !mbNeedLineCols[ nCol - mnDataStartCol ] )
     225             :     {
     226         141 :         mbNeedLineCols[ nCol - mnDataStartCol ] = true;
     227         141 :         mnCols.push_back( nCol );
     228         141 :         return true;
     229             :     }
     230             :     else
     231           4 :         return false;
     232             : }
     233             : 
     234         806 : void ScDPOutputImpl::OutputBlockFrame ( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, bool bHori )
     235             : {
     236         806 :     Color color = SC_DP_FRAME_COLOR;
     237         806 :     ::editeng::SvxBorderLine aLine( &color, SC_DP_FRAME_INNER_BOLD );
     238         806 :     ::editeng::SvxBorderLine aOutLine( &color, SC_DP_FRAME_OUTER_BOLD );
     239             : 
     240         806 :     SvxBoxItem aBox( ATTR_BORDER );
     241             : 
     242         806 :     if ( nStartCol == mnTabStartCol )
     243         344 :         aBox.SetLine(&aOutLine, SvxBoxItemLine::LEFT);
     244             :     else
     245         462 :         aBox.SetLine(&aLine, SvxBoxItemLine::LEFT);
     246             : 
     247         806 :     if ( nStartRow == mnTabStartRow )
     248         200 :         aBox.SetLine(&aOutLine, SvxBoxItemLine::TOP);
     249             :     else
     250         606 :         aBox.SetLine(&aLine, SvxBoxItemLine::TOP);
     251             : 
     252         806 :     if ( nEndCol == mnTabEndCol ) //bottom row
     253         392 :         aBox.SetLine(&aOutLine, SvxBoxItemLine::RIGHT);
     254             :     else
     255         414 :         aBox.SetLine(&aLine,  SvxBoxItemLine::RIGHT);
     256             : 
     257         806 :      if ( nEndRow == mnTabEndRow ) //bottom
     258         281 :         aBox.SetLine(&aOutLine,  SvxBoxItemLine::BOTTOM);
     259             :     else
     260         525 :         aBox.SetLine(&aLine,  SvxBoxItemLine::BOTTOM);
     261             : 
     262        1612 :     SvxBoxInfoItem aBoxInfo( ATTR_BORDER_INNER );
     263         806 :     aBoxInfo.SetValid(SvxBoxInfoItemValidFlags::VERT,false );
     264         806 :     if ( bHori )
     265             :     {
     266          39 :         aBoxInfo.SetValid(SvxBoxInfoItemValidFlags::HORI,true);
     267          39 :         aBoxInfo.SetLine( &aLine, SvxBoxInfoItemLine::HORI );
     268             :     }
     269             :     else
     270         767 :         aBoxInfo.SetValid(SvxBoxInfoItemValidFlags::HORI,false );
     271             : 
     272         806 :     aBoxInfo.SetValid(SvxBoxInfoItemValidFlags::DISTANCE,false);
     273             : 
     274        1612 :     mpDoc->ApplyFrameAreaTab( ScRange(  nStartCol, nStartRow, mnTab, nEndCol, nEndRow , mnTab ), &aBox, &aBoxInfo );
     275             : 
     276         806 : }
     277             : 
     278        1152 : void lcl_SetStyleById( ScDocument* pDoc, SCTAB nTab,
     279             :                     SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
     280             :                     sal_uInt16 nStrId )
     281             : {
     282        1152 :     if ( nCol1 > nCol2 || nRow1 > nRow2 )
     283             :     {
     284             :         OSL_FAIL("SetStyleById: invalid range");
     285        1152 :         return;
     286             :     }
     287             : 
     288        1152 :     OUString aStyleName = ScGlobal::GetRscString( nStrId );
     289        1152 :     ScStyleSheetPool* pStlPool = pDoc->GetStyleSheetPool();
     290        1152 :     ScStyleSheet* pStyle = static_cast<ScStyleSheet*>( pStlPool->Find( aStyleName, SFX_STYLE_FAMILY_PARA ) );
     291        1152 :     if (!pStyle)
     292             :     {
     293             :         //  create new style (was in ScPivot::SetStyle)
     294             : 
     295             :         pStyle = static_cast<ScStyleSheet*>( &pStlPool->Make( aStyleName, SFX_STYLE_FAMILY_PARA,
     296         200 :                                                     SFXSTYLEBIT_USERDEF ) );
     297         200 :         pStyle->SetParent( ScGlobal::GetRscString(STR_STYLENAME_STANDARD) );
     298         200 :         SfxItemSet& rSet = pStyle->GetItemSet();
     299         200 :         if ( nStrId==STR_PIVOT_STYLE_RESULT || nStrId==STR_PIVOT_STYLE_TITLE )
     300          62 :             rSet.Put( SvxWeightItem( WEIGHT_BOLD, ATTR_FONT_WEIGHT ) );
     301         200 :         if ( nStrId==STR_PIVOT_STYLE_CATEGORY || nStrId==STR_PIVOT_STYLE_TITLE )
     302          63 :             rSet.Put( SvxHorJustifyItem( SVX_HOR_JUSTIFY_LEFT, ATTR_HOR_JUSTIFY ) );
     303             :     }
     304             : 
     305        1152 :     pDoc->ApplyStyleAreaTab( nCol1, nRow1, nCol2, nRow2, nTab, *pStyle );
     306             : }
     307             : 
     308         164 : void lcl_SetFrame( ScDocument* pDoc, SCTAB nTab,
     309             :                     SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
     310             :                     sal_uInt16 nWidth )
     311             : {
     312         164 :     ::editeng::SvxBorderLine aLine(0, nWidth, table::BorderLineStyle::SOLID);
     313         164 :     SvxBoxItem aBox( ATTR_BORDER );
     314         164 :     aBox.SetLine(&aLine, SvxBoxItemLine::LEFT);
     315         164 :     aBox.SetLine(&aLine, SvxBoxItemLine::TOP);
     316         164 :     aBox.SetLine(&aLine, SvxBoxItemLine::RIGHT);
     317         164 :     aBox.SetLine(&aLine, SvxBoxItemLine::BOTTOM);
     318         328 :     SvxBoxInfoItem aBoxInfo( ATTR_BORDER_INNER );
     319         164 :     aBoxInfo.SetValid(SvxBoxInfoItemValidFlags::HORI,false);
     320         164 :     aBoxInfo.SetValid(SvxBoxInfoItemValidFlags::VERT,false);
     321         164 :     aBoxInfo.SetValid(SvxBoxInfoItemValidFlags::DISTANCE,false);
     322             : 
     323         328 :     pDoc->ApplyFrameAreaTab( ScRange( nCol1, nRow1, nTab, nCol2, nRow2, nTab ), &aBox, &aBoxInfo );
     324         164 : }
     325             : 
     326          49 : void lcl_FillNumberFormats( sal_uInt32*& rFormats, long& rCount,
     327             :                             const uno::Reference<sheet::XDataPilotMemberResults>& xLevRes,
     328             :                             const uno::Reference<container::XIndexAccess>& xDims )
     329             : {
     330          49 :     if ( rFormats )
     331           1 :         return;                         // already set
     332             : 
     333             :     //  xLevRes is from the data layout dimension
     334             :     //TODO: use result sequence from ScDPOutLevelData!
     335             : 
     336          49 :     uno::Sequence<sheet::MemberResult> aResult = xLevRes->getResults();
     337             : 
     338          49 :     long nSize = aResult.getLength();
     339          49 :     if (!nSize)
     340           0 :         return;
     341             : 
     342             :     //  get names/formats for all data dimensions
     343             :     //TODO: merge this with the loop to collect ScDPOutLevelData?
     344             : 
     345       12593 :     OUString aDataNames[SC_DPOUT_MAXLEVELS];
     346             :     sal_uInt32 nDataFormats[SC_DPOUT_MAXLEVELS];
     347          49 :     long nDataCount = 0;
     348          49 :     long nDimCount = xDims->getCount();
     349         258 :     for (long nDim=0; nDim<nDimCount; nDim++)
     350             :     {
     351             :         uno::Reference<uno::XInterface> xDim =
     352         209 :                 ScUnoHelpFunctions::AnyToInterface( xDims->getByIndex(nDim) );
     353         418 :         uno::Reference<beans::XPropertySet> xDimProp( xDim, uno::UNO_QUERY );
     354         418 :         uno::Reference<container::XNamed> xDimName( xDim, uno::UNO_QUERY );
     355         209 :         if ( xDimProp.is() && xDimName.is() )
     356             :         {
     357             :             sheet::DataPilotFieldOrientation eDimOrient =
     358             :                 (sheet::DataPilotFieldOrientation) ScUnoHelpFunctions::GetEnumProperty(
     359             :                     xDimProp, OUString(SC_UNO_DP_ORIENTATION),
     360         209 :                     sheet::DataPilotFieldOrientation_HIDDEN );
     361         209 :             if ( eDimOrient == sheet::DataPilotFieldOrientation_DATA )
     362             :             {
     363          57 :                 aDataNames[nDataCount] = xDimName->getName();
     364             :                 long nFormat = ScUnoHelpFunctions::GetLongProperty(
     365             :                                         xDimProp,
     366          57 :                                         OUString(SC_UNONAME_NUMFMT) );
     367          57 :                 nDataFormats[nDataCount] = nFormat;
     368          57 :                 ++nDataCount;
     369             :             }
     370             :         }
     371         209 :     }
     372             : 
     373          49 :     if (!nDataCount)
     374           1 :         return;
     375             : 
     376          48 :     const sheet::MemberResult* pArray = aResult.getConstArray();
     377             : 
     378          96 :     OUString aName;
     379          48 :     sal_uInt32* pNumFmt = new sal_uInt32[nSize];
     380          48 :     if (nDataCount == 1)
     381             :     {
     382             :         //  only one data dimension -> use its numberformat everywhere
     383          39 :         long nFormat = nDataFormats[0];
     384         259 :         for (long nPos=0; nPos<nSize; nPos++)
     385         220 :             pNumFmt[nPos] = nFormat;
     386             :     }
     387             :     else
     388             :     {
     389          35 :         for (long nPos=0; nPos<nSize; nPos++)
     390             :         {
     391             :             //  if CONTINUE bit is set, keep previous name
     392             :             //TODO: keep number format instead!
     393          26 :             if ( !(pArray[nPos].Flags & sheet::MemberResultFlags::CONTINUE) )
     394          26 :                 aName = pArray[nPos].Name;
     395             : 
     396          26 :             sal_uInt32 nFormat = 0;
     397          39 :             for (long i=0; i<nDataCount; i++)
     398          39 :                 if (aName == aDataNames[i])         //TODO: search more efficiently?
     399             :                 {
     400          26 :                     nFormat = nDataFormats[i];
     401          26 :                     break;
     402             :                 }
     403          26 :             pNumFmt[nPos] = nFormat;
     404             :         }
     405             :     }
     406             : 
     407          48 :     rFormats = pNumFmt;
     408          96 :     rCount = nSize;
     409             : }
     410             : 
     411          39 : sal_uInt32 lcl_GetFirstNumberFormat( const uno::Reference<container::XIndexAccess>& xDims )
     412             : {
     413          39 :     long nDimCount = xDims->getCount();
     414         155 :     for (long nDim=0; nDim<nDimCount; nDim++)
     415             :     {
     416             :         uno::Reference<uno::XInterface> xDim =
     417         145 :                 ScUnoHelpFunctions::AnyToInterface( xDims->getByIndex(nDim) );
     418         261 :         uno::Reference<beans::XPropertySet> xDimProp( xDim, uno::UNO_QUERY );
     419         145 :         if ( xDimProp.is() )
     420             :         {
     421             :             sheet::DataPilotFieldOrientation eDimOrient =
     422             :                 (sheet::DataPilotFieldOrientation) ScUnoHelpFunctions::GetEnumProperty(
     423             :                     xDimProp, OUString(SC_UNO_DP_ORIENTATION),
     424         145 :                     sheet::DataPilotFieldOrientation_HIDDEN );
     425         145 :             if ( eDimOrient == sheet::DataPilotFieldOrientation_DATA )
     426             :             {
     427             :                 long nFormat = ScUnoHelpFunctions::GetLongProperty(
     428             :                                         xDimProp,
     429          29 :                                         OUString(SC_UNONAME_NUMFMT) );
     430             : 
     431          29 :                 return nFormat;     // use format from first found data dimension
     432             :             }
     433             :         }
     434         116 :     }
     435             : 
     436          10 :     return 0;       // none found
     437             : }
     438             : 
     439         264 : void lcl_SortFields( ScDPOutLevelData* pFields, long nFieldCount )
     440             : {
     441         287 :     for (long i=0; i+1<nFieldCount; i++)
     442             :     {
     443          49 :         for (long j=0; j+i+1<nFieldCount; j++)
     444          26 :             if ( pFields[j+1] < pFields[j] )
     445          14 :                 pFields[j].Swap( pFields[j+1] );
     446             :     }
     447         264 : }
     448             : 
     449         179 : bool lcl_MemberEmpty( const uno::Sequence<sheet::MemberResult>& rSeq )
     450             : {
     451             :     //  used to skip levels that have no members
     452             : 
     453         179 :     long nLen = rSeq.getLength();
     454         179 :     const sheet::MemberResult* pArray = rSeq.getConstArray();
     455         404 :     for (long i=0; i<nLen; i++)
     456         364 :         if (pArray[i].Flags & sheet::MemberResultFlags::HASMEMBER)
     457         139 :             return false;
     458             : 
     459          40 :     return true;    // no member data -> empty
     460             : }
     461             : 
     462             : /**
     463             :  * Get visible page dimension members as results, except that, if all
     464             :  * members are visible, then this function returns empty result.
     465             :  */
     466          27 : uno::Sequence<sheet::MemberResult> getVisiblePageMembersAsResults( const uno::Reference<uno::XInterface>& xLevel )
     467             : {
     468          27 :     if (!xLevel.is())
     469           0 :         return uno::Sequence<sheet::MemberResult>();
     470             : 
     471          27 :     uno::Reference<sheet::XMembersSupplier> xMSupplier(xLevel, UNO_QUERY);
     472          27 :     if (!xMSupplier.is())
     473           0 :         return uno::Sequence<sheet::MemberResult>();
     474             : 
     475          54 :     uno::Reference<container::XNameAccess> xNA = xMSupplier->getMembers();
     476          27 :     if (!xNA.is())
     477           0 :         return uno::Sequence<sheet::MemberResult>();
     478             : 
     479          54 :     std::vector<sheet::MemberResult> aRes;
     480          54 :     uno::Sequence<OUString> aNames = xNA->getElementNames();
     481         138 :     for (sal_Int32 i = 0; i < aNames.getLength(); ++i)
     482             :     {
     483         111 :         const OUString& rName = aNames[i];
     484         111 :         xNA->getByName(rName);
     485             : 
     486         111 :         uno::Reference<beans::XPropertySet> xMemPS(xNA->getByName(rName), UNO_QUERY);
     487         111 :         if (!xMemPS.is())
     488           0 :             continue;
     489             : 
     490         222 :         OUString aCaption = ScUnoHelpFunctions::GetStringProperty(xMemPS, SC_UNO_DP_LAYOUTNAME, OUString());
     491         111 :         if (aCaption.isEmpty())
     492         111 :             aCaption = rName;
     493             : 
     494         111 :         bool bVisible = ScUnoHelpFunctions::GetBoolProperty(xMemPS, SC_UNO_DP_ISVISIBLE, false);
     495             : 
     496         111 :         if (bVisible)
     497         103 :             aRes.push_back(sheet::MemberResult(rName, aCaption, 0));
     498         111 :     }
     499             : 
     500          27 :     if (aNames.getLength() == static_cast<sal_Int32>(aRes.size()))
     501             :         // All members are visible.  Return empty result.
     502          23 :         return uno::Sequence<sheet::MemberResult>();
     503             : 
     504          31 :     return ScUnoHelpFunctions::VectorToSequence(aRes);
     505             : }
     506             : 
     507             : }
     508             : 
     509          88 : ScDPOutput::ScDPOutput( ScDocument* pD, const uno::Reference<sheet::XDimensionsSupplier>& xSrc,
     510             :                         const ScAddress& rPos, bool bFilter ) :
     511             :     pDoc( pD ),
     512             :     xSource( xSrc ),
     513             :     aStartPos( rPos ),
     514             :     pColNumFmt( NULL ),
     515             :     pRowNumFmt( NULL ),
     516             :     nColFmtCount( 0 ),
     517             :     nRowFmtCount( 0 ),
     518             :     nSingleNumFmt( 0 ),
     519             :     nColCount(0),
     520             :     nRowCount(0),
     521             :     nHeaderSize(0),
     522             :     bDoFilter(bFilter),
     523             :     bResultsError(false),
     524             :     mbHasDataLayout(false),
     525             :     bSizesValid(false),
     526             :     bSizeOverflow(false),
     527          88 :     mbHeaderLayout(false)
     528             : {
     529          88 :     nTabStartCol = nMemberStartCol = nDataStartCol = nTabEndCol = 0;
     530          88 :     nTabStartRow = nMemberStartRow = nDataStartRow = nTabEndRow = 0;
     531             : 
     532          88 :     pColFields  = new ScDPOutLevelData[SC_DPOUT_MAXLEVELS];
     533          88 :     pRowFields  = new ScDPOutLevelData[SC_DPOUT_MAXLEVELS];
     534          88 :     pPageFields = new ScDPOutLevelData[SC_DPOUT_MAXLEVELS];
     535          88 :     nColFieldCount = 0;
     536          88 :     nRowFieldCount = 0;
     537          88 :     nPageFieldCount = 0;
     538             : 
     539          88 :     uno::Reference<sheet::XDataPilotResults> xResult( xSource, uno::UNO_QUERY );
     540          88 :     if ( xSource.is() && xResult.is() )
     541             :     {
     542             :         //  get dimension results:
     543             : 
     544             :         uno::Reference<container::XIndexAccess> xDims =
     545          88 :                 new ScNameToIndexAccess( xSource->getDimensions() );
     546          88 :         long nDimCount = xDims->getCount();
     547         540 :         for (long nDim=0; nDim<nDimCount; nDim++)
     548             :         {
     549             :             uno::Reference<uno::XInterface> xDim =
     550         452 :                     ScUnoHelpFunctions::AnyToInterface( xDims->getByIndex(nDim) );
     551         904 :             uno::Reference<beans::XPropertySet> xDimProp( xDim, uno::UNO_QUERY );
     552         904 :             uno::Reference<sheet::XHierarchiesSupplier> xDimSupp( xDim, uno::UNO_QUERY );
     553         452 :             if ( xDimProp.is() && xDimSupp.is() )
     554             :             {
     555             :                 sheet::DataPilotFieldOrientation eDimOrient =
     556             :                     (sheet::DataPilotFieldOrientation) ScUnoHelpFunctions::GetEnumProperty(
     557             :                         xDimProp, OUString(SC_UNO_DP_ORIENTATION),
     558         452 :                         sheet::DataPilotFieldOrientation_HIDDEN );
     559             :                 long nDimPos = ScUnoHelpFunctions::GetLongProperty( xDimProp,
     560         452 :                         OUString(SC_UNO_DP_POSITION) );
     561             :                 bool bIsDataLayout = ScUnoHelpFunctions::GetBoolProperty(
     562         452 :                     xDimProp, OUString(SC_UNO_DP_ISDATALAYOUT));
     563             :                 bool bHasHiddenMember = ScUnoHelpFunctions::GetBoolProperty(
     564         452 :                     xDimProp, OUString(SC_UNO_DP_HAS_HIDDEN_MEMBER));
     565             :                 sal_Int32 nNumFmt = ScUnoHelpFunctions::GetLongProperty(
     566         452 :                     xDimProp, SC_UNO_DP_NUMBERFO, 0);
     567             : 
     568         452 :                 if ( eDimOrient != sheet::DataPilotFieldOrientation_HIDDEN )
     569             :                 {
     570             :                     uno::Reference<container::XIndexAccess> xHiers =
     571         292 :                             new ScNameToIndexAccess( xDimSupp->getHierarchies() );
     572             :                     long nHierarchy = ScUnoHelpFunctions::GetLongProperty(
     573             :                                             xDimProp,
     574         292 :                                             OUString(SC_UNO_DP_USEDHIERARCHY) );
     575         292 :                     if ( nHierarchy >= xHiers->getCount() )
     576           0 :                         nHierarchy = 0;
     577             : 
     578             :                     uno::Reference<uno::XInterface> xHier =
     579             :                             ScUnoHelpFunctions::AnyToInterface(
     580         584 :                                                 xHiers->getByIndex(nHierarchy) );
     581         584 :                     uno::Reference<sheet::XLevelsSupplier> xHierSupp( xHier, uno::UNO_QUERY );
     582         292 :                     if ( xHierSupp.is() )
     583             :                     {
     584             :                         uno::Reference<container::XIndexAccess> xLevels =
     585         292 :                                 new ScNameToIndexAccess( xHierSupp->getLevels() );
     586         292 :                         long nLevCount = xLevels->getCount();
     587         584 :                         for (long nLev=0; nLev<nLevCount; nLev++)
     588             :                         {
     589             :                             uno::Reference<uno::XInterface> xLevel =
     590             :                                         ScUnoHelpFunctions::AnyToInterface(
     591         292 :                                                             xLevels->getByIndex(nLev) );
     592         584 :                             uno::Reference<container::XNamed> xLevNam( xLevel, uno::UNO_QUERY );
     593             :                             uno::Reference<sheet::XDataPilotMemberResults> xLevRes(
     594         584 :                                     xLevel, uno::UNO_QUERY );
     595         292 :                             if ( xLevNam.is() && xLevRes.is() )
     596             :                             {
     597         292 :                                 OUString aName = xLevNam->getName();
     598         584 :                                 Reference<XPropertySet> xPropSet(xLevel, UNO_QUERY);
     599             :                                 // Caption equals the field name by default.
     600             :                                 // #i108948# use ScUnoHelpFunctions::GetStringProperty, because
     601             :                                 // LayoutName is new and may not be present in external implementation
     602             :                                 OUString aCaption = ScUnoHelpFunctions::GetStringProperty( xPropSet,
     603         584 :                                     OUString(SC_UNO_DP_LAYOUTNAME), aName );
     604             : 
     605         292 :                                 bool bRowFieldHasMember = false;
     606         292 :                                 switch ( eDimOrient )
     607             :                                 {
     608             :                                     case sheet::DataPilotFieldOrientation_COLUMN:
     609          49 :                                         pColFields[nColFieldCount].nDim    = nDim;
     610          49 :                                         pColFields[nColFieldCount].nHier   = nHierarchy;
     611          49 :                                         pColFields[nColFieldCount].nLevel  = nLev;
     612          49 :                                         pColFields[nColFieldCount].nDimPos = nDimPos;
     613          49 :                                         pColFields[nColFieldCount].aResult = xLevRes->getResults();
     614          49 :                                         pColFields[nColFieldCount].mnSrcNumFmt = nNumFmt;
     615          49 :                                         pColFields[nColFieldCount].maName  = aName;
     616          49 :                                         pColFields[nColFieldCount].maCaption= aCaption;
     617          49 :                                         pColFields[nColFieldCount].mbHasHiddenMember = bHasHiddenMember;
     618          49 :                                         pColFields[nColFieldCount].mbDataLayout = bIsDataLayout;
     619          49 :                                         if (!lcl_MemberEmpty(pColFields[nColFieldCount].aResult))
     620          49 :                                             ++nColFieldCount;
     621          49 :                                         break;
     622             :                                     case sheet::DataPilotFieldOrientation_ROW:
     623         130 :                                         pRowFields[nRowFieldCount].nDim    = nDim;
     624         130 :                                         pRowFields[nRowFieldCount].nHier   = nHierarchy;
     625         130 :                                         pRowFields[nRowFieldCount].nLevel  = nLev;
     626         130 :                                         pRowFields[nRowFieldCount].nDimPos = nDimPos;
     627         130 :                                         pRowFields[nRowFieldCount].aResult = xLevRes->getResults();
     628         130 :                                         pRowFields[nRowFieldCount].mnSrcNumFmt = nNumFmt;
     629         130 :                                         pRowFields[nRowFieldCount].maName  = aName;
     630         130 :                                         pRowFields[nRowFieldCount].maCaption= aCaption;
     631         130 :                                         pRowFields[nRowFieldCount].mbHasHiddenMember = bHasHiddenMember;
     632         130 :                                         pRowFields[nRowFieldCount].mbDataLayout = bIsDataLayout;
     633         130 :                                         if (!lcl_MemberEmpty(pRowFields[nRowFieldCount].aResult))
     634             :                                         {
     635          90 :                                             ++nRowFieldCount;
     636          90 :                                             bRowFieldHasMember = true;
     637             :                                         }
     638         130 :                                         break;
     639             :                                     case sheet::DataPilotFieldOrientation_PAGE:
     640          27 :                                         pPageFields[nPageFieldCount].nDim    = nDim;
     641          27 :                                         pPageFields[nPageFieldCount].nHier   = nHierarchy;
     642          27 :                                         pPageFields[nPageFieldCount].nLevel  = nLev;
     643          27 :                                         pPageFields[nPageFieldCount].nDimPos = nDimPos;
     644          27 :                                         pPageFields[nPageFieldCount].aResult = getVisiblePageMembersAsResults(xLevel);
     645          27 :                                         pPageFields[nPageFieldCount].mnSrcNumFmt = nNumFmt;
     646          27 :                                         pPageFields[nPageFieldCount].maName  = aName;
     647          27 :                                         pPageFields[nPageFieldCount].maCaption= aCaption;
     648          27 :                                         pPageFields[nPageFieldCount].mbHasHiddenMember = bHasHiddenMember;
     649          27 :                                         pPageFields[nPageFieldCount].mbPageDim = true;
     650             :                                         // no check on results for page fields
     651          27 :                                         ++nPageFieldCount;
     652          27 :                                         break;
     653             :                                     default:
     654             :                                     {
     655             :                                         // added to avoid warnings
     656             :                                     }
     657             :                                 }
     658             : 
     659             :                                 // get number formats from data dimensions
     660         292 :                                 if ( bIsDataLayout )
     661             :                                 {
     662          49 :                                     if (bRowFieldHasMember)
     663           6 :                                         mbHasDataLayout = true;
     664             : 
     665             :                                     OSL_ENSURE( nLevCount == 1, "data layout: multiple levels?" );
     666          49 :                                     if ( eDimOrient == sheet::DataPilotFieldOrientation_COLUMN )
     667           3 :                                         lcl_FillNumberFormats( pColNumFmt, nColFmtCount, xLevRes, xDims );
     668          46 :                                     else if ( eDimOrient == sheet::DataPilotFieldOrientation_ROW )
     669          46 :                                         lcl_FillNumberFormats( pRowNumFmt, nRowFmtCount, xLevRes, xDims );
     670         292 :                                 }
     671             :                             }
     672         584 :                         }
     673         292 :                     }
     674             :                 }
     675         160 :                 else if ( bIsDataLayout )
     676             :                 {
     677             :                     // data layout dimension is hidden (allowed if there is only one data dimension)
     678             :                     // -> use the number format from the first data dimension for all results
     679             : 
     680          39 :                     nSingleNumFmt = lcl_GetFirstNumberFormat( xDims );
     681             :                 }
     682             :             }
     683         452 :         }
     684          88 :         lcl_SortFields( pColFields, nColFieldCount );
     685          88 :         lcl_SortFields( pRowFields, nRowFieldCount );
     686          88 :         lcl_SortFields( pPageFields, nPageFieldCount );
     687             : 
     688             :         //  get data results:
     689             : 
     690             :         try
     691             :         {
     692          88 :             aData = xResult->getResults();
     693             :         }
     694           0 :         catch (const uno::RuntimeException&)
     695             :         {
     696           0 :             bResultsError = true;
     697          88 :         }
     698             :     }
     699             : 
     700             :     // get "DataDescription" property (may be missing in external sources)
     701             : 
     702          88 :     uno::Reference<beans::XPropertySet> xSrcProp( xSource, uno::UNO_QUERY );
     703          88 :     if ( xSrcProp.is() )
     704             :     {
     705             :         try
     706             :         {
     707          88 :             uno::Any aAny = xSrcProp->getPropertyValue(
     708          88 :                     OUString(SC_UNO_DP_DATADESC) );
     709         176 :             OUString aUStr;
     710          88 :             aAny >>= aUStr;
     711         176 :             aDataDescription = aUStr;
     712             :         }
     713           0 :         catch(const uno::Exception&)
     714             :         {
     715             :         }
     716          88 :     }
     717          88 : }
     718             : 
     719         176 : ScDPOutput::~ScDPOutput()
     720             : {
     721          88 :     delete[] pColFields;
     722          88 :     delete[] pRowFields;
     723          88 :     delete[] pPageFields;
     724             : 
     725          88 :     delete[] pColNumFmt;
     726          88 :     delete[] pRowNumFmt;
     727          88 : }
     728             : 
     729         153 : void ScDPOutput::SetPosition( const ScAddress& rPos )
     730             : {
     731         153 :     aStartPos = rPos;
     732         153 :     bSizesValid = bSizeOverflow = false;
     733         153 : }
     734             : 
     735        1438 : void ScDPOutput::DataCell( SCCOL nCol, SCROW nRow, SCTAB nTab, const sheet::DataResult& rData )
     736             : {
     737        1438 :     long nFlags = rData.Flags;
     738        1438 :     if ( nFlags & sheet::DataResultFlags::ERROR )
     739             :     {
     740           0 :         pDoc->SetError( nCol, nRow, nTab, errNoValue );
     741             :     }
     742        1438 :     else if ( nFlags & sheet::DataResultFlags::HASDATA )
     743             :     {
     744         750 :         pDoc->SetValue( nCol, nRow, nTab, rData.Value );
     745             : 
     746             :         //  use number formats from source
     747             : 
     748             :         OSL_ENSURE( bSizesValid, "DataCell: !bSizesValid" );
     749         750 :         sal_uInt32 nFormat = 0;
     750         750 :         bool bApplyFormat = false;
     751         750 :         if ( pColNumFmt )
     752             :         {
     753          38 :             if ( nCol >= nDataStartCol )
     754             :             {
     755          38 :                 long nIndex = nCol - nDataStartCol;
     756          38 :                 if ( nIndex < nColFmtCount )
     757             :                 {
     758          38 :                     nFormat = pColNumFmt[nIndex];
     759          38 :                     bApplyFormat = true;
     760             :                 }
     761             :             }
     762             :         }
     763         712 :         else if ( pRowNumFmt )
     764             :         {
     765         371 :             if ( nRow >= nDataStartRow )
     766             :             {
     767         371 :                 long nIndex = nRow - nDataStartRow;
     768         371 :                 if ( nIndex < nRowFmtCount )
     769             :                 {
     770         371 :                     nFormat = pRowNumFmt[nIndex];
     771         371 :                     bApplyFormat = true;
     772             :                 }
     773             :             }
     774             :         }
     775         341 :         else if ( nSingleNumFmt != 0 )
     776             :         {
     777           0 :             nFormat = nSingleNumFmt;        // single format is used everywhere
     778           0 :             bApplyFormat = true;
     779             :         }
     780             : 
     781         750 :         if (bApplyFormat)
     782         409 :             pDoc->ApplyAttr(nCol, nRow, nTab, SfxUInt32Item(ATTR_VALUE_FORMAT, nFormat));
     783             :     }
     784             :     //  SubTotal formatting is controlled by headers
     785        1438 : }
     786             : 
     787         759 : void ScDPOutput::HeaderCell( SCCOL nCol, SCROW nRow, SCTAB nTab,
     788             :                              const sheet::MemberResult& rData, bool bColHeader, long nLevel )
     789             : {
     790         759 :     long nFlags = rData.Flags;
     791             : 
     792         759 :     if ( nFlags & sheet::MemberResultFlags::HASMEMBER )
     793             :     {
     794         702 :         bool bNumeric = (nFlags & sheet::MemberResultFlags::NUMERIC) != 0;
     795         702 :         ScSetStringParam aParam;
     796         702 :         if (bNumeric)
     797         340 :             aParam.setNumericInput();
     798             :         else
     799         362 :             aParam.setTextInput();
     800             : 
     801         702 :         pDoc->SetString(nCol, nRow, nTab, rData.Caption, &aParam);
     802             :     }
     803             : 
     804         759 :     if ( nFlags & sheet::MemberResultFlags::SUBTOTAL )
     805             :     {
     806             :         ScDPOutputImpl outputimp( pDoc, nTab,
     807             :             nTabStartCol, nTabStartRow,
     808         112 :             nDataStartCol, nDataStartRow, nTabEndCol, nTabEndRow );
     809             :         //TODO: limit frames to horizontal or vertical?
     810         112 :         if (bColHeader)
     811             :         {
     812          42 :             outputimp.OutputBlockFrame( nCol,nMemberStartRow+(SCROW)nLevel, nCol,nDataStartRow-1 );
     813             : 
     814             :             lcl_SetStyleById( pDoc,nTab, nCol,nMemberStartRow+(SCROW)nLevel, nCol,nDataStartRow-1,
     815          42 :                                     STR_PIVOT_STYLE_TITLE );
     816             :             lcl_SetStyleById( pDoc,nTab, nCol,nDataStartRow, nCol,nTabEndRow,
     817          42 :                                     STR_PIVOT_STYLE_RESULT );
     818             :         }
     819             :         else
     820             :         {
     821          70 :             outputimp.OutputBlockFrame( nMemberStartCol+(SCCOL)nLevel,nRow, nDataStartCol-1,nRow );
     822             :             lcl_SetStyleById( pDoc,nTab, nMemberStartCol+(SCCOL)nLevel,nRow, nDataStartCol-1,nRow,
     823          70 :                                     STR_PIVOT_STYLE_TITLE );
     824             :             lcl_SetStyleById( pDoc,nTab, nDataStartCol,nRow, nTabEndCol,nRow,
     825          70 :                                     STR_PIVOT_STYLE_RESULT );
     826         112 :         }
     827             :     }
     828         759 : }
     829             : 
     830         164 : void ScDPOutput::FieldCell(
     831             :     SCCOL nCol, SCROW nRow, SCTAB nTab, const ScDPOutLevelData& rData, bool bInTable)
     832             : {
     833             :     // Avoid unwanted automatic format detection.
     834         164 :     ScSetStringParam aParam;
     835         164 :     aParam.mbDetectNumberFormat = false;
     836         164 :     aParam.meSetTextNumFormat = ScSetStringParam::Always;
     837         164 :     aParam.mbHandleApostrophe = false;
     838         164 :     pDoc->SetString(nCol, nRow, nTab, rData.maCaption, &aParam);
     839             : 
     840         164 :     if (bInTable)
     841         138 :         lcl_SetFrame( pDoc,nTab, nCol,nRow, nCol,nRow, 20 );
     842             : 
     843             :     // For field button drawing
     844         164 :     sal_uInt16 nMergeFlag = 0;
     845         164 :     if (rData.mbHasHiddenMember)
     846           4 :         nMergeFlag |= SC_MF_HIDDEN_MEMBER;
     847             : 
     848         164 :     if (rData.mbPageDim)
     849             :     {
     850          26 :         nMergeFlag |= SC_MF_BUTTON_POPUP;
     851          26 :         pDoc->ApplyFlagsTab(nCol, nRow, nCol, nRow, nTab, SC_MF_BUTTON);
     852          26 :         pDoc->ApplyFlagsTab(nCol+1, nRow, nCol+1, nRow, nTab, nMergeFlag);
     853             :     }
     854             :     else
     855             :     {
     856         138 :         nMergeFlag |= SC_MF_BUTTON;
     857         138 :         if (!rData.mbDataLayout)
     858         129 :             nMergeFlag |= SC_MF_BUTTON_POPUP;
     859         138 :         pDoc->ApplyFlagsTab(nCol, nRow, nCol, nRow, nTab, nMergeFlag);
     860             :     }
     861             : 
     862         164 :     lcl_SetStyleById( pDoc,nTab, nCol,nRow, nCol,nRow, STR_PIVOT_STYLE_FIELDNAME );
     863         164 : }
     864             : 
     865          50 : static void lcl_DoFilterButton( ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab )
     866             : {
     867          50 :     pDoc->SetString( nCol, nRow, nTab, ScGlobal::GetRscString(STR_CELL_FILTER) );
     868          50 :     pDoc->ApplyFlagsTab(nCol, nRow, nCol, nRow, nTab, SC_MF_BUTTON);
     869          50 : }
     870             : 
     871        1242 : void ScDPOutput::CalcSizes()
     872             : {
     873        1242 :     if (!bSizesValid)
     874             :     {
     875             :         //  get column size of data from first row
     876             :         //TODO: allow different sizes (and clear following areas) ???
     877             : 
     878         188 :         nRowCount = aData.getLength();
     879         188 :         const uno::Sequence<sheet::DataResult>* pRowAry = aData.getConstArray();
     880         188 :         nColCount = nRowCount ? ( pRowAry[0].getLength() ) : 0;
     881             : 
     882         188 :         nHeaderSize = 1;
     883         188 :         if (GetHeaderLayout() && nColFieldCount == 0)
     884             :             // Insert an extra header row only when there is no column field.
     885           0 :             nHeaderSize = 2;
     886             : 
     887             :         //  calculate output positions and sizes
     888             : 
     889         188 :         long nPageSize = 0;     // use page fields!
     890         188 :         if ( bDoFilter || nPageFieldCount )
     891             :         {
     892         122 :             nPageSize += nPageFieldCount + 1;   // plus one empty row
     893         122 :             if ( bDoFilter )
     894         116 :                 ++nPageSize;        //  filter button above the page fields
     895             :         }
     896             : 
     897         376 :         if ( aStartPos.Col() + nRowFieldCount + nColCount - 1 > MAXCOL ||
     898         188 :              aStartPos.Row() + nPageSize + nHeaderSize + nColFieldCount + nRowCount > MAXROW )
     899             :         {
     900           0 :             bSizeOverflow = true;
     901             :         }
     902             : 
     903         188 :         nTabStartCol = aStartPos.Col();
     904         188 :         nTabStartRow = aStartPos.Row() + (SCROW)nPageSize;          // below page fields
     905         188 :         nMemberStartCol = nTabStartCol;
     906         188 :         nMemberStartRow = nTabStartRow + (SCROW) nHeaderSize;
     907         188 :         nDataStartCol = nMemberStartCol + (SCCOL)nRowFieldCount;
     908         188 :         nDataStartRow = nMemberStartRow + (SCROW)nColFieldCount;
     909         188 :         if ( nColCount > 0 )
     910         186 :             nTabEndCol = nDataStartCol + (SCCOL)nColCount - 1;
     911             :         else
     912           2 :             nTabEndCol = nDataStartCol;     // single column will remain empty
     913             :         // if page fields are involved, include the page selection cells
     914         188 :         if ( nPageFieldCount > 0 && nTabEndCol < nTabStartCol + 1 )
     915           2 :             nTabEndCol = nTabStartCol + 1;
     916         188 :         if ( nRowCount > 0 )
     917         186 :             nTabEndRow = nDataStartRow + (SCROW)nRowCount - 1;
     918             :         else
     919           2 :             nTabEndRow = nDataStartRow;     // single row will remain empty
     920         188 :         bSizesValid = true;
     921             :     }
     922        1242 : }
     923             : 
     924         266 : sal_Int32 ScDPOutput::GetPositionType(const ScAddress& rPos)
     925             : {
     926             :     using namespace ::com::sun::star::sheet;
     927             : 
     928         266 :     SCCOL nCol = rPos.Col();
     929         266 :     SCROW nRow = rPos.Row();
     930         266 :     SCTAB nTab = rPos.Tab();
     931         266 :     if ( nTab != aStartPos.Tab() )
     932           0 :         return DataPilotTablePositionType::NOT_IN_TABLE;
     933             : 
     934         266 :     CalcSizes();
     935             : 
     936             :     // Make sure the cursor is within the table.
     937         266 :     if (nCol < nTabStartCol || nRow < nTabStartRow || nCol > nTabEndCol || nRow > nTabEndRow)
     938           0 :         return DataPilotTablePositionType::NOT_IN_TABLE;
     939             : 
     940             :     // test for result data area.
     941         266 :     if (nCol >= nDataStartCol && nCol <= nTabEndCol && nRow >= nDataStartRow && nRow <= nTabEndRow)
     942         194 :         return DataPilotTablePositionType::RESULT;
     943             : 
     944          72 :     bool bInColHeader = (nRow >= nTabStartRow && nRow < nDataStartRow);
     945          72 :     bool bInRowHeader = (nCol >= nTabStartCol && nCol < nDataStartCol);
     946             : 
     947          72 :     if (bInColHeader && bInRowHeader)
     948             :         // probably in that ugly little box at the upper-left corner of the table.
     949          12 :         return DataPilotTablePositionType::OTHER;
     950             : 
     951          60 :     if (bInColHeader)
     952             :     {
     953          36 :         if (nRow == nTabStartRow)
     954             :             // first row in the column header area is always used for column
     955             :             // field buttons.
     956          12 :             return DataPilotTablePositionType::OTHER;
     957             : 
     958          24 :         return DataPilotTablePositionType::COLUMN_HEADER;
     959             :     }
     960             : 
     961          24 :     if (bInRowHeader)
     962          24 :         return DataPilotTablePositionType::ROW_HEADER;
     963             : 
     964           0 :     return DataPilotTablePositionType::OTHER;
     965             : }
     966             : 
     967          87 : void ScDPOutput::Output()
     968             : {
     969             :     long nField;
     970          87 :     SCTAB nTab = aStartPos.Tab();
     971          87 :     const uno::Sequence<sheet::DataResult>* pRowAry = aData.getConstArray();
     972             : 
     973             :     //  calculate output positions and sizes
     974             : 
     975          87 :     CalcSizes();
     976          87 :     if ( bSizeOverflow || bResultsError )   // does output area exceed sheet limits?
     977          87 :         return;                             // nothing
     978             : 
     979             :     //  clear whole (new) output area
     980             :     // when modifying table, clear old area !
     981             :     //TODO: include IDF_OBJECTS ???
     982          87 :     pDoc->DeleteAreaTab( aStartPos.Col(), aStartPos.Row(), nTabEndCol, nTabEndRow, nTab, IDF_ALL );
     983             : 
     984          87 :     if ( bDoFilter )
     985          50 :         lcl_DoFilterButton( pDoc, aStartPos.Col(), aStartPos.Row(), nTab );
     986             : 
     987             :     //  output page fields:
     988             : 
     989         113 :     for (nField=0; nField<nPageFieldCount; nField++)
     990             :     {
     991          26 :         SCCOL nHdrCol = aStartPos.Col();
     992          26 :         SCROW nHdrRow = aStartPos.Row() + nField + ( bDoFilter ? 1 : 0 );
     993             :         // draw without frame for consistency with filter button:
     994          26 :         FieldCell(nHdrCol, nHdrRow, nTab, pPageFields[nField], false);
     995          26 :         SCCOL nFldCol = nHdrCol + 1;
     996             : 
     997          26 :         OUString aPageValue = ScResId(SCSTR_ALL).toString();
     998          26 :         const uno::Sequence<sheet::MemberResult>& rRes = pPageFields[nField].aResult;
     999          26 :         sal_Int32 n = rRes.getLength();
    1000          26 :         if (n == 1)
    1001           3 :             aPageValue = rRes[0].Caption;
    1002          23 :         else if (n > 1)
    1003           0 :             aPageValue = ScResId(SCSTR_MULTIPLE).toString();
    1004             : 
    1005          26 :         ScSetStringParam aParam;
    1006          26 :         aParam.setTextInput();
    1007          26 :         pDoc->SetString(nFldCol, nHdrRow, nTab, aPageValue, &aParam);
    1008             : 
    1009          26 :         lcl_SetFrame( pDoc,nTab, nFldCol,nHdrRow, nFldCol,nHdrRow, 20 );
    1010          26 :     }
    1011             : 
    1012             :     //  data description
    1013             :     //  (may get overwritten by first row field)
    1014             : 
    1015          87 :     if (aDataDescription.isEmpty())
    1016             :     {
    1017             :         //TODO: use default string ("result") ?
    1018             :     }
    1019          87 :     pDoc->SetString(nTabStartCol, nTabStartRow, nTab, aDataDescription);
    1020             : 
    1021             :     //  set STR_PIVOT_STYLE_INNER for whole data area (subtotals are overwritten)
    1022             : 
    1023          87 :     if ( nDataStartRow > nTabStartRow )
    1024             :         lcl_SetStyleById( pDoc, nTab, nTabStartCol, nTabStartRow, nTabEndCol, nDataStartRow-1,
    1025          87 :                             STR_PIVOT_STYLE_TOP );
    1026             :     lcl_SetStyleById( pDoc, nTab, nDataStartCol, nDataStartRow, nTabEndCol, nTabEndRow,
    1027          87 :                         STR_PIVOT_STYLE_INNER );
    1028             : 
    1029             :     //  output column headers:
    1030             :     ScDPOutputImpl outputimp( pDoc, nTab,
    1031             :         nTabStartCol, nTabStartRow,
    1032          87 :         nDataStartCol, nDataStartRow, nTabEndCol, nTabEndRow );
    1033         136 :     for (nField=0; nField<nColFieldCount; nField++)
    1034             :     {
    1035          49 :         SCCOL nHdrCol = nDataStartCol + (SCCOL)nField;              //TODO: check for overflow
    1036          49 :         FieldCell(nHdrCol, nTabStartRow, nTab, pColFields[nField], true);
    1037             : 
    1038          49 :         SCROW nRowPos = nMemberStartRow + (SCROW)nField;                //TODO: check for overflow
    1039          49 :         const uno::Sequence<sheet::MemberResult> rSequence = pColFields[nField].aResult;
    1040          49 :         const sheet::MemberResult* pArray = rSequence.getConstArray();
    1041          49 :         long nThisColCount = rSequence.getLength();
    1042             :         OSL_ENSURE( nThisColCount == nColCount, "count mismatch" );     //TODO: ???
    1043         308 :         for (long nCol=0; nCol<nThisColCount; nCol++)
    1044             :         {
    1045         259 :             SCCOL nColPos = nDataStartCol + (SCCOL)nCol;                //TODO: check for overflow
    1046         259 :             HeaderCell( nColPos, nRowPos, nTab, pArray[nCol], true, nField );
    1047         510 :             if ( ( pArray[nCol].Flags & sheet::MemberResultFlags::HASMEMBER ) &&
    1048         251 :                 !( pArray[nCol].Flags & sheet::MemberResultFlags::SUBTOTAL ) )
    1049             :             {
    1050         209 :                 long nEnd = nCol;
    1051         422 :                 while ( nEnd+1 < nThisColCount && ( pArray[nEnd+1].Flags & sheet::MemberResultFlags::CONTINUE ) )
    1052           4 :                     ++nEnd;
    1053         209 :                 SCCOL nEndColPos = nDataStartCol + (SCCOL)nEnd;     //TODO: check for overflow
    1054         209 :                 if ( nField+1 < nColFieldCount )
    1055             :                 {
    1056          16 :                     if ( nField == nColFieldCount - 2 )
    1057             :                     {
    1058          16 :                         outputimp.AddCol( nColPos );
    1059          16 :                         if ( nColPos + 1 == nEndColPos  )
    1060           0 :                             outputimp.OutputBlockFrame( nColPos,nRowPos, nEndColPos,nRowPos+1, true );
    1061             :                     }
    1062             :                     else
    1063           0 :                         outputimp.OutputBlockFrame( nColPos,nRowPos, nEndColPos,nRowPos );
    1064             : 
    1065          16 :                     lcl_SetStyleById( pDoc, nTab, nColPos,nRowPos, nEndColPos,nDataStartRow-1, STR_PIVOT_STYLE_CATEGORY );
    1066             :                 }
    1067             :                 else
    1068         193 :                     lcl_SetStyleById( pDoc, nTab, nColPos,nRowPos, nColPos,nDataStartRow-1, STR_PIVOT_STYLE_CATEGORY );
    1069             :             }
    1070          50 :             else if (  pArray[nCol].Flags & sheet::MemberResultFlags::SUBTOTAL )
    1071          42 :                 outputimp.AddCol( nColPos );
    1072             : 
    1073             :             // Apply the same number format as in data source.
    1074         259 :             pDoc->ApplyAttr(nColPos, nRowPos, nTab, SfxUInt32Item(ATTR_VALUE_FORMAT, pColFields[nField].mnSrcNumFmt));
    1075             :         }
    1076          49 :         if ( nField== 0 && nColFieldCount == 1 )
    1077          41 :             outputimp.OutputBlockFrame( nDataStartCol,nTabStartRow, nTabEndCol,nRowPos-1 );
    1078          49 :     }
    1079             : 
    1080             :     //  output row headers:
    1081         174 :     std::vector<bool> vbSetBorder;
    1082          87 :     vbSetBorder.resize( nTabEndRow - nDataStartRow + 1, false );
    1083         176 :     for (nField=0; nField<nRowFieldCount; nField++)
    1084             :     {
    1085          89 :         SCCOL nHdrCol = nTabStartCol + (SCCOL)nField;                   //TODO: check for overflow
    1086          89 :         SCROW nHdrRow = nDataStartRow - 1;
    1087          89 :         FieldCell(nHdrCol, nHdrRow, nTab, pRowFields[nField], true);
    1088             : 
    1089          89 :         SCCOL nColPos = nMemberStartCol + (SCCOL)nField;                //TODO: check for overflow
    1090          89 :         const uno::Sequence<sheet::MemberResult> rSequence = pRowFields[nField].aResult;
    1091          89 :         const sheet::MemberResult* pArray = rSequence.getConstArray();
    1092          89 :         long nThisRowCount = rSequence.getLength();
    1093             :         OSL_ENSURE( nThisRowCount == nRowCount, "count mismatch" );     //TODO: ???
    1094         589 :         for (long nRow=0; nRow<nThisRowCount; nRow++)
    1095             :         {
    1096         500 :             SCROW nRowPos = nDataStartRow + (SCROW)nRow;                //TODO: check for overflow
    1097         500 :             HeaderCell( nColPos, nRowPos, nTab, pArray[nRow], false, nField );
    1098         951 :             if ( ( pArray[nRow].Flags & sheet::MemberResultFlags::HASMEMBER ) &&
    1099         451 :                 !( pArray[nRow].Flags & sheet::MemberResultFlags::SUBTOTAL ) )
    1100             :             {
    1101         381 :                 if ( nField+1 < nRowFieldCount )
    1102             :                 {
    1103          59 :                     long nEnd = nRow;
    1104         154 :                     while ( nEnd+1 < nThisRowCount && ( pArray[nEnd+1].Flags & sheet::MemberResultFlags::CONTINUE ) )
    1105          36 :                         ++nEnd;
    1106          59 :                     SCROW nEndRowPos = nDataStartRow + (SCROW)nEnd;     //TODO: check for overflow
    1107          59 :                     outputimp.AddRow( nRowPos );
    1108          59 :                     if ( !vbSetBorder[ nRow ] )
    1109             :                     {
    1110          52 :                         outputimp.OutputBlockFrame( nColPos, nRowPos, nTabEndCol, nEndRowPos );
    1111          52 :                         vbSetBorder[ nRow ]  = true;
    1112             :                     }
    1113          59 :                     outputimp.OutputBlockFrame( nColPos, nRowPos, nColPos, nEndRowPos );
    1114             : 
    1115          59 :                     if ( nField == nRowFieldCount - 2 )
    1116          48 :                         outputimp.OutputBlockFrame( nColPos+1, nRowPos, nColPos+1, nEndRowPos );
    1117             : 
    1118          59 :                     lcl_SetStyleById( pDoc, nTab, nColPos,nRowPos, nDataStartCol-1,nEndRowPos, STR_PIVOT_STYLE_CATEGORY );
    1119             :                 }
    1120             :                 else
    1121         322 :                     lcl_SetStyleById( pDoc, nTab, nColPos,nRowPos, nDataStartCol-1,nRowPos, STR_PIVOT_STYLE_CATEGORY );
    1122             :             }
    1123         119 :             else if (  pArray[nRow].Flags & sheet::MemberResultFlags::SUBTOTAL )
    1124          70 :                 outputimp.AddRow( nRowPos );
    1125             : 
    1126             :             // Apply the same number format as in data source.
    1127         500 :             pDoc->ApplyAttr(nColPos, nRowPos, nTab, SfxUInt32Item(ATTR_VALUE_FORMAT, pRowFields[nField].mnSrcNumFmt));
    1128             :         }
    1129          89 :     }
    1130             : 
    1131          87 :     if (nColCount == 1 && nRowCount > 0 && nColFieldCount == 0)
    1132             :     {
    1133             :         // the table contains exactly one data field and no column fields.
    1134             :         // Display data description at top right corner.
    1135          41 :         ScSetStringParam aParam;
    1136          41 :         aParam.setTextInput();
    1137          41 :         pDoc->SetString(nDataStartCol, nDataStartRow-1, nTab, aDataDescription, &aParam);
    1138             :     }
    1139             : 
    1140             :     //  output data results:
    1141             : 
    1142         493 :     for (long nRow=0; nRow<nRowCount; nRow++)
    1143             :     {
    1144         406 :         SCROW nRowPos = nDataStartRow + (SCROW)nRow;                    //TODO: check for overflow
    1145         406 :         const sheet::DataResult* pColAry = pRowAry[nRow].getConstArray();
    1146         406 :         long nThisColCount = pRowAry[nRow].getLength();
    1147             :         OSL_ENSURE( nThisColCount == nColCount, "count mismatch" );     //TODO: ???
    1148        1844 :         for (long nCol=0; nCol<nThisColCount; nCol++)
    1149             :         {
    1150        1438 :             SCCOL nColPos = nDataStartCol + (SCCOL)nCol;                //TODO: check for overflow
    1151        1438 :             DataCell( nColPos, nRowPos, nTab, pColAry[nCol] );
    1152             :         }
    1153             :     }
    1154             : 
    1155         174 :     outputimp.OutputDataArea();
    1156             : }
    1157             : 
    1158         191 : ScRange ScDPOutput::GetOutputRange( sal_Int32 nRegionType )
    1159             : {
    1160             :     using namespace ::com::sun::star::sheet;
    1161             : 
    1162         191 :     CalcSizes();
    1163             : 
    1164         191 :     SCTAB nTab = aStartPos.Tab();
    1165         191 :     switch (nRegionType)
    1166             :     {
    1167             :         case DataPilotOutputRangeType::RESULT:
    1168           7 :             return ScRange(nDataStartCol, nDataStartRow, nTab, nTabEndCol, nTabEndRow, nTab);
    1169             :         case DataPilotOutputRangeType::TABLE:
    1170           7 :             return ScRange(aStartPos.Col(), nTabStartRow, nTab, nTabEndCol, nTabEndRow, nTab);
    1171             :         default:
    1172             :             OSL_ENSURE(nRegionType == DataPilotOutputRangeType::WHOLE, "ScDPOutput::GetOutputRange: unknown region type");
    1173         177 :         break;
    1174             :     }
    1175         177 :     return ScRange(aStartPos.Col(), aStartPos.Row(), nTab, nTabEndCol, nTabEndRow, nTab);
    1176             : }
    1177             : 
    1178           0 : ScRange ScDPOutput::GetOutputRange( sal_Int32 nRegionType ) const
    1179             : {
    1180             :     using namespace ::com::sun::star::sheet;
    1181             : 
    1182           0 :     if (!bSizesValid)
    1183           0 :         return ScRange(ScAddress::INITIALIZE_INVALID);
    1184             : 
    1185           0 :     SCTAB nTab = aStartPos.Tab();
    1186           0 :     switch (nRegionType)
    1187             :     {
    1188             :         case DataPilotOutputRangeType::RESULT:
    1189           0 :             return ScRange(nDataStartCol, nDataStartRow, nTab, nTabEndCol, nTabEndRow, nTab);
    1190             :         case DataPilotOutputRangeType::TABLE:
    1191           0 :             return ScRange(aStartPos.Col(), nTabStartRow, nTab, nTabEndCol, nTabEndRow, nTab);
    1192             :         default:
    1193             :             OSL_ENSURE(nRegionType == DataPilotOutputRangeType::WHOLE, "ScDPOutput::GetOutputRange: unknown region type");
    1194           0 :         break;
    1195             :     }
    1196           0 :     return ScRange(aStartPos.Col(), aStartPos.Row(), nTab, nTabEndCol, nTabEndRow, nTab);
    1197             : }
    1198             : 
    1199         104 : bool ScDPOutput::HasError()
    1200             : {
    1201         104 :     CalcSizes();
    1202             : 
    1203         104 :     return bSizeOverflow || bResultsError;
    1204             : }
    1205             : 
    1206          88 : long ScDPOutput::GetHeaderRows()
    1207             : {
    1208          88 :     return nPageFieldCount + ( bDoFilter ? 1 : 0 );
    1209             : }
    1210             : 
    1211           0 : void ScDPOutput::GetMemberResultNames(ScDPUniqueStringSet& rNames, long nDimension)
    1212             : {
    1213             :     //  Return the list of all member names in a dimension's MemberResults.
    1214             :     //  Only the dimension has to be compared because this is only used with table data,
    1215             :     //  where each dimension occurs only once.
    1216             : 
    1217           0 :     uno::Sequence<sheet::MemberResult> aMemberResults;
    1218           0 :     bool bFound = false;
    1219             :     long nField;
    1220             : 
    1221             :     // look in column fields
    1222             : 
    1223           0 :     for (nField=0; nField<nColFieldCount && !bFound; nField++)
    1224           0 :         if ( pColFields[nField].nDim == nDimension )
    1225             :         {
    1226           0 :             aMemberResults = pColFields[nField].aResult;
    1227           0 :             bFound = true;
    1228             :         }
    1229             : 
    1230             :     // look in row fields
    1231             : 
    1232           0 :     for (nField=0; nField<nRowFieldCount && !bFound; nField++)
    1233           0 :         if ( pRowFields[nField].nDim == nDimension )
    1234             :         {
    1235           0 :             aMemberResults = pRowFields[nField].aResult;
    1236           0 :             bFound = true;
    1237             :         }
    1238             : 
    1239             :     // collect the member names
    1240             : 
    1241           0 :     if ( bFound )
    1242             :     {
    1243           0 :         const sheet::MemberResult* pArray = aMemberResults.getConstArray();
    1244           0 :         long nResultCount = aMemberResults.getLength();
    1245             : 
    1246           0 :         for (long nItem=0; nItem<nResultCount; nItem++)
    1247             :         {
    1248           0 :             if ( pArray[nItem].Flags & sheet::MemberResultFlags::HASMEMBER )
    1249           0 :                 rNames.insert(pArray[nItem].Name);
    1250             :         }
    1251           0 :     }
    1252           0 : }
    1253             : 
    1254          88 : void ScDPOutput::SetHeaderLayout(bool bUseGrid)
    1255             : {
    1256          88 :     mbHeaderLayout = bUseGrid;
    1257          88 :     bSizesValid = false;
    1258          88 : }
    1259             : 
    1260             : namespace {
    1261             : 
    1262         327 : void lcl_GetTableVars( sal_Int32& rGrandTotalCols, sal_Int32& rGrandTotalRows, sal_Int32& rDataLayoutIndex,
    1263             :                        std::vector<OUString>& rDataNames, std::vector<OUString>& rGivenNames,
    1264             :                        sheet::DataPilotFieldOrientation& rDataOrient,
    1265             :                        const uno::Reference<sheet::XDimensionsSupplier>& xSource )
    1266             : {
    1267         327 :     rDataLayoutIndex = -1;  // invalid
    1268         327 :     rGrandTotalCols = 0;
    1269         327 :     rGrandTotalRows = 0;
    1270         327 :     rDataOrient = sheet::DataPilotFieldOrientation_HIDDEN;
    1271             : 
    1272         327 :     uno::Reference<beans::XPropertySet> xSrcProp( xSource, uno::UNO_QUERY );
    1273             :     bool bColGrand = ScUnoHelpFunctions::GetBoolProperty(
    1274         327 :         xSrcProp, OUString(SC_UNO_DP_COLGRAND));
    1275         327 :     if ( bColGrand )
    1276         327 :         rGrandTotalCols = 1;    // default if data layout not in columns
    1277             : 
    1278             :     bool bRowGrand = ScUnoHelpFunctions::GetBoolProperty(
    1279         327 :         xSrcProp, OUString(SC_UNO_DP_ROWGRAND));
    1280         327 :     if ( bRowGrand )
    1281         327 :         rGrandTotalRows = 1;    // default if data layout not in rows
    1282             : 
    1283         327 :     if ( xSource.is() )
    1284             :     {
    1285             :         // find index and orientation of "data layout" dimension, count data dimensions
    1286             : 
    1287         327 :         sal_Int32 nDataCount = 0;
    1288             : 
    1289         327 :         uno::Reference<container::XIndexAccess> xDims = new ScNameToIndexAccess( xSource->getDimensions() );
    1290         327 :         long nDimCount = xDims->getCount();
    1291        2289 :         for (long nDim=0; nDim<nDimCount; nDim++)
    1292             :         {
    1293             :             uno::Reference<uno::XInterface> xDim =
    1294        1962 :                     ScUnoHelpFunctions::AnyToInterface( xDims->getByIndex(nDim) );
    1295        3924 :             uno::Reference<beans::XPropertySet> xDimProp( xDim, uno::UNO_QUERY );
    1296        1962 :             if ( xDimProp.is() )
    1297             :             {
    1298             :                 sheet::DataPilotFieldOrientation eDimOrient =
    1299             :                     (sheet::DataPilotFieldOrientation) ScUnoHelpFunctions::GetEnumProperty(
    1300             :                         xDimProp, OUString(SC_UNO_DP_ORIENTATION),
    1301        1962 :                         sheet::DataPilotFieldOrientation_HIDDEN );
    1302        3924 :                 if ( ScUnoHelpFunctions::GetBoolProperty( xDimProp,
    1303        3924 :                                          OUString(SC_UNO_DP_ISDATALAYOUT) ) )
    1304             :                 {
    1305         327 :                     rDataLayoutIndex = nDim;
    1306         327 :                     rDataOrient = eDimOrient;
    1307             :                 }
    1308        1962 :                 if ( eDimOrient == sheet::DataPilotFieldOrientation_DATA )
    1309             :                 {
    1310         327 :                     OUString aSourceName;
    1311         654 :                     OUString aGivenName;
    1312         327 :                     ScDPOutput::GetDataDimensionNames( aSourceName, aGivenName, xDim );
    1313             :                     try
    1314             :                     {
    1315         327 :                         uno::Any aValue = xDimProp->getPropertyValue( SC_UNO_DP_LAYOUTNAME );
    1316             : 
    1317         327 :                         if( aValue.hasValue() )
    1318             :                         {
    1319         327 :                             OUString strLayoutName;
    1320             : 
    1321         327 :                             if( ( aValue >>= strLayoutName ) && !strLayoutName.isEmpty() )
    1322           0 :                                 aGivenName = strLayoutName;
    1323         327 :                         }
    1324             :                     }
    1325           0 :                     catch(const uno::Exception&)
    1326             :                     {
    1327             :                     }
    1328         327 :                     rDataNames.push_back( aSourceName );
    1329         327 :                     rGivenNames.push_back( aGivenName );
    1330             : 
    1331         654 :                     ++nDataCount;
    1332             :                 }
    1333             :             }
    1334        1962 :         }
    1335             : 
    1336         327 :         if ( ( rDataOrient == sheet::DataPilotFieldOrientation_COLUMN ) && bColGrand )
    1337           0 :             rGrandTotalCols = nDataCount;
    1338         327 :         else if ( ( rDataOrient == sheet::DataPilotFieldOrientation_ROW ) && bRowGrand )
    1339           0 :             rGrandTotalRows = nDataCount;
    1340         327 :     }
    1341         327 : }
    1342             : 
    1343             : }
    1344             : 
    1345         266 : void ScDPOutput::GetPositionData(const ScAddress& rPos, DataPilotTablePositionData& rPosData)
    1346             : {
    1347             :     using namespace ::com::sun::star::sheet;
    1348             : 
    1349         266 :     SCCOL nCol = rPos.Col();
    1350         266 :     SCROW nRow = rPos.Row();
    1351         266 :     SCTAB nTab = rPos.Tab();
    1352         266 :     if ( nTab != aStartPos.Tab() )
    1353           0 :         return;                                     // wrong sheet
    1354             : 
    1355             :     //  calculate output positions and sizes
    1356             : 
    1357         266 :     CalcSizes();
    1358             : 
    1359         266 :     rPosData.PositionType = GetPositionType(rPos);
    1360         266 :     switch (rPosData.PositionType)
    1361             :     {
    1362             :         case DataPilotTablePositionType::RESULT:
    1363             :         {
    1364         194 :             vector<DataPilotFieldFilter> aFilters;
    1365         194 :             GetDataResultPositionData(aFilters, rPos);
    1366         194 :             sal_Int32 nSize = aFilters.size();
    1367             : 
    1368         388 :             DataPilotTableResultData aResData;
    1369         194 :             aResData.FieldFilters.realloc(nSize);
    1370         874 :             for (sal_Int32 i = 0; i < nSize; ++i)
    1371         680 :                 aResData.FieldFilters[i] = aFilters[i];
    1372             : 
    1373         194 :             aResData.DataFieldIndex = 0;
    1374         388 :             Reference<beans::XPropertySet> xPropSet(xSource, UNO_QUERY);
    1375         194 :             if (xPropSet.is())
    1376             :             {
    1377             :                 sal_Int32 nDataFieldCount = ScUnoHelpFunctions::GetLongProperty( xPropSet,
    1378         194 :                                             OUString(SC_UNO_DP_DATAFIELDCOUNT) );
    1379         194 :                 if (nDataFieldCount > 0)
    1380         194 :                     aResData.DataFieldIndex = (nRow - nDataStartRow) % nDataFieldCount;
    1381             :             }
    1382             : 
    1383             :             // Copy appropriate DataResult object from the cached sheet::DataResult table.
    1384         388 :             if (aData.getLength() > nRow - nDataStartRow &&
    1385         194 :                 aData[nRow-nDataStartRow].getLength() > nCol-nDataStartCol)
    1386         194 :                 aResData.Result = aData[nRow-nDataStartRow][nCol-nDataStartCol];
    1387             : 
    1388         194 :             rPosData.PositionData = makeAny(aResData);
    1389         388 :             return;
    1390             :         }
    1391             :         case DataPilotTablePositionType::COLUMN_HEADER:
    1392             :         {
    1393          24 :             long nField = nRow - nTabStartRow - 1; // 1st line is used for the buttons
    1394          24 :             if (nField < 0)
    1395           0 :                 break;
    1396             : 
    1397          24 :             const uno::Sequence<sheet::MemberResult> rSequence = pColFields[nField].aResult;
    1398          24 :             if (rSequence.getLength() == 0)
    1399           0 :                 break;
    1400          24 :             const sheet::MemberResult* pArray = rSequence.getConstArray();
    1401             : 
    1402          24 :             long nItem = nCol - nDataStartCol;
    1403             :             //  get origin of "continue" fields
    1404          48 :             while (nItem > 0 && ( pArray[nItem].Flags & sheet::MemberResultFlags::CONTINUE) )
    1405           0 :                 --nItem;
    1406             : 
    1407          24 :             if (nItem < 0)
    1408           0 :                 break;
    1409             : 
    1410          48 :             DataPilotTableHeaderData aHeaderData;
    1411          24 :             aHeaderData.MemberName = OUString(pArray[nItem].Name);
    1412          24 :             aHeaderData.Flags = pArray[nItem].Flags;
    1413          24 :             aHeaderData.Dimension = static_cast<sal_Int32>(pColFields[nField].nDim);
    1414          24 :             aHeaderData.Hierarchy = static_cast<sal_Int32>(pColFields[nField].nHier);
    1415          24 :             aHeaderData.Level     = static_cast<sal_Int32>(pColFields[nField].nLevel);
    1416             : 
    1417          24 :             rPosData.PositionData = makeAny(aHeaderData);
    1418          24 :             return;
    1419             :         }
    1420             :         case DataPilotTablePositionType::ROW_HEADER:
    1421             :         {
    1422          24 :             long nField = nCol - nTabStartCol;
    1423          24 :             if (nField < 0)
    1424           0 :                 break;
    1425             : 
    1426          24 :             const uno::Sequence<sheet::MemberResult> rSequence = pRowFields[nField].aResult;
    1427          24 :             if (rSequence.getLength() == 0)
    1428           0 :                 break;
    1429          24 :             const sheet::MemberResult* pArray = rSequence.getConstArray();
    1430             : 
    1431          24 :             long nItem = nRow - nDataStartRow;
    1432             :             //  get origin of "continue" fields
    1433          48 :             while ( nItem > 0 && (pArray[nItem].Flags & sheet::MemberResultFlags::CONTINUE) )
    1434           0 :                 --nItem;
    1435             : 
    1436          24 :             if (nItem < 0)
    1437           0 :                 break;
    1438             : 
    1439          48 :             DataPilotTableHeaderData aHeaderData;
    1440          24 :             aHeaderData.MemberName = OUString(pArray[nItem].Name);
    1441          24 :             aHeaderData.Flags = pArray[nItem].Flags;
    1442          24 :             aHeaderData.Dimension = static_cast<sal_Int32>(pRowFields[nField].nDim);
    1443          24 :             aHeaderData.Hierarchy = static_cast<sal_Int32>(pRowFields[nField].nHier);
    1444          24 :             aHeaderData.Level     = static_cast<sal_Int32>(pRowFields[nField].nLevel);
    1445             : 
    1446          24 :             rPosData.PositionData = makeAny(aHeaderData);
    1447          24 :             return;
    1448             :         }
    1449             :     }
    1450             : }
    1451             : 
    1452         327 : bool ScDPOutput::GetDataResultPositionData(vector<sheet::DataPilotFieldFilter>& rFilters, const ScAddress& rPos)
    1453             : {
    1454             :     // Check to make sure there is at least one data field.
    1455         327 :     Reference<beans::XPropertySet> xPropSet(xSource, UNO_QUERY);
    1456         327 :     if (!xPropSet.is())
    1457           0 :         return false;
    1458             : 
    1459             :     sal_Int32 nDataFieldCount = ScUnoHelpFunctions::GetLongProperty( xPropSet,
    1460         327 :                                 OUString(SC_UNO_DP_DATAFIELDCOUNT) );
    1461         327 :     if (nDataFieldCount == 0)
    1462             :         // No data field is present in this datapilot table.
    1463           0 :         return false;
    1464             : 
    1465             :     // #i111421# use lcl_GetTableVars for correct size of totals and data layout position
    1466             :     sal_Int32 nGrandTotalCols;
    1467             :     sal_Int32 nGrandTotalRows;
    1468             :     sal_Int32 nDataLayoutIndex;
    1469         654 :     std::vector<OUString> aDataNames;
    1470         654 :     std::vector<OUString> aGivenNames;
    1471             :     sheet::DataPilotFieldOrientation eDataOrient;
    1472         327 :     lcl_GetTableVars( nGrandTotalCols, nGrandTotalRows, nDataLayoutIndex, aDataNames, aGivenNames, eDataOrient, xSource );
    1473             : 
    1474         327 :     SCCOL nCol = rPos.Col();
    1475         327 :     SCROW nRow = rPos.Row();
    1476         327 :     SCTAB nTab = rPos.Tab();
    1477         327 :     if ( nTab != aStartPos.Tab() )
    1478           0 :         return false;                                     // wrong sheet
    1479             : 
    1480         327 :     CalcSizes();
    1481             : 
    1482             :     // test for data area.
    1483         327 :     if (nCol < nDataStartCol || nCol > nTabEndCol || nRow < nDataStartRow || nRow > nTabEndRow)
    1484             :     {
    1485             :         // Cell is outside the data field area.
    1486           0 :         return false;
    1487             :     }
    1488             : 
    1489         327 :     bool bFilterByCol = (nCol <= static_cast<SCCOL>(nTabEndCol - nGrandTotalCols));
    1490         327 :     bool bFilterByRow = (nRow <= static_cast<SCROW>(nTabEndRow - nGrandTotalRows));
    1491             : 
    1492             :     // column fields
    1493         897 :     for (SCCOL nColField = 0; nColField < nColFieldCount && bFilterByCol; ++nColField)
    1494             :     {
    1495         570 :         if (pColFields[nColField].nDim == nDataLayoutIndex)
    1496             :             // There is no sense including the data layout field for filtering.
    1497           0 :             continue;
    1498             : 
    1499         570 :         sheet::DataPilotFieldFilter filter;
    1500         570 :         filter.FieldName = pColFields[nColField].maName;
    1501             : 
    1502        1140 :         const uno::Sequence<sheet::MemberResult> rSequence = pColFields[nColField].aResult;
    1503         570 :         const sheet::MemberResult* pArray = rSequence.getConstArray();
    1504             : 
    1505             :         OSL_ENSURE(nDataStartCol + rSequence.getLength() - 1 == nTabEndCol, "ScDPOutput::GetDataFieldCellData: error in geometric assumption");
    1506             : 
    1507         570 :         long nItem = nCol - nDataStartCol;
    1508             :                 //  get origin of "continue" fields
    1509        1140 :         while ( nItem > 0 && (pArray[nItem].Flags & sheet::MemberResultFlags::CONTINUE) )
    1510           0 :             --nItem;
    1511             : 
    1512         570 :         filter.MatchValue = pArray[nItem].Name;
    1513         570 :         rFilters.push_back(filter);
    1514         570 :     }
    1515             : 
    1516             :     // row fields
    1517         897 :     for (SCROW nRowField = 0; nRowField < nRowFieldCount && bFilterByRow; ++nRowField)
    1518             :     {
    1519         570 :         if (pRowFields[nRowField].nDim == nDataLayoutIndex)
    1520             :             // There is no sense including the data layout field for filtering.
    1521           0 :             continue;
    1522             : 
    1523         570 :         sheet::DataPilotFieldFilter filter;
    1524         570 :         filter.FieldName = pRowFields[nRowField].maName;
    1525             : 
    1526        1140 :         const uno::Sequence<sheet::MemberResult> rSequence = pRowFields[nRowField].aResult;
    1527         570 :         const sheet::MemberResult* pArray = rSequence.getConstArray();
    1528             : 
    1529             :         OSL_ENSURE(nDataStartRow + rSequence.getLength() - 1 == nTabEndRow, "ScDPOutput::GetDataFieldCellData: error in geometric assumption");
    1530             : 
    1531         570 :         long nItem = nRow - nDataStartRow;
    1532             :             //  get origin of "continue" fields
    1533        1140 :         while ( nItem > 0 && (pArray[nItem].Flags & sheet::MemberResultFlags::CONTINUE) )
    1534           0 :             --nItem;
    1535             : 
    1536         570 :         filter.MatchValue = pArray[nItem].Name;
    1537         570 :         rFilters.push_back(filter);
    1538         570 :     }
    1539             : 
    1540         654 :     return true;
    1541             : }
    1542             : 
    1543             : namespace {
    1544             : 
    1545         346 : OUString lcl_GetDataFieldName( const OUString& rSourceName, sheet::GeneralFunction eFunc )
    1546             : {
    1547         346 :     sal_uInt16 nStrId = 0;
    1548         346 :     switch ( eFunc )
    1549             :     {
    1550          19 :         case sheet::GeneralFunction_SUM:        nStrId = STR_FUN_TEXT_SUM;      break;
    1551             :         case sheet::GeneralFunction_COUNT:
    1552           0 :         case sheet::GeneralFunction_COUNTNUMS:  nStrId = STR_FUN_TEXT_COUNT;    break;
    1553           0 :         case sheet::GeneralFunction_AVERAGE:    nStrId = STR_FUN_TEXT_AVG;      break;
    1554           0 :         case sheet::GeneralFunction_MAX:        nStrId = STR_FUN_TEXT_MAX;      break;
    1555           0 :         case sheet::GeneralFunction_MIN:        nStrId = STR_FUN_TEXT_MIN;      break;
    1556           0 :         case sheet::GeneralFunction_PRODUCT:    nStrId = STR_FUN_TEXT_PRODUCT;  break;
    1557             :         case sheet::GeneralFunction_STDEV:
    1558           0 :         case sheet::GeneralFunction_STDEVP:     nStrId = STR_FUN_TEXT_STDDEV;   break;
    1559             :         case sheet::GeneralFunction_VAR:
    1560           0 :         case sheet::GeneralFunction_VARP:       nStrId = STR_FUN_TEXT_VAR;      break;
    1561             :         case sheet::GeneralFunction_NONE:
    1562             :         case sheet::GeneralFunction_AUTO:
    1563             :         default:
    1564             :         {
    1565             :             OSL_FAIL("wrong function");
    1566             :         }
    1567             :     }
    1568         346 :     if ( !nStrId )
    1569         327 :         return OUString();
    1570             : 
    1571          19 :     OUStringBuffer aRet( ScGlobal::GetRscString( nStrId ) );
    1572          19 :     aRet.append(" - ");
    1573          19 :     aRet.append(rSourceName);
    1574          19 :     return aRet.makeStringAndClear();
    1575             : }
    1576             : 
    1577             : }
    1578             : 
    1579         346 : void ScDPOutput::GetDataDimensionNames(
    1580             :     OUString& rSourceName, OUString& rGivenName, const uno::Reference<uno::XInterface>& xDim )
    1581             : {
    1582         346 :     uno::Reference<beans::XPropertySet> xDimProp( xDim, uno::UNO_QUERY );
    1583         692 :     uno::Reference<container::XNamed> xDimName( xDim, uno::UNO_QUERY );
    1584         346 :     if ( xDimProp.is() && xDimName.is() )
    1585             :     {
    1586             :         // Asterisks are added in ScDPSaveData::WriteToSource to create unique names.
    1587             :         //TODO: preserve original name there?
    1588         346 :         rSourceName = ScDPUtil::getSourceDimensionName(xDimName->getName());
    1589             : 
    1590             :         // Generate "given name" the same way as in dptabres.
    1591             :         //TODO: Should use a stored name when available
    1592             : 
    1593             :         sheet::GeneralFunction eFunc = (sheet::GeneralFunction)ScUnoHelpFunctions::GetEnumProperty(
    1594             :                                 xDimProp, OUString(SC_UNO_DP_FUNCTION),
    1595         346 :                                 sheet::GeneralFunction_NONE );
    1596         346 :         rGivenName = lcl_GetDataFieldName( rSourceName, eFunc );
    1597         346 :     }
    1598         346 : }
    1599             : 
    1600           0 : bool ScDPOutput::IsFilterButton( const ScAddress& rPos )
    1601             : {
    1602           0 :     SCCOL nCol = rPos.Col();
    1603           0 :     SCROW nRow = rPos.Row();
    1604           0 :     SCTAB nTab = rPos.Tab();
    1605           0 :     if ( nTab != aStartPos.Tab() || !bDoFilter )
    1606           0 :         return false;                               // wrong sheet or no button at all
    1607             : 
    1608             :     //  filter button is at top left
    1609           0 :     return ( nCol == aStartPos.Col() && nRow == aStartPos.Row() );
    1610             : }
    1611             : 
    1612           1 : long ScDPOutput::GetHeaderDim( const ScAddress& rPos, sal_uInt16& rOrient )
    1613             : {
    1614           1 :     SCCOL nCol = rPos.Col();
    1615           1 :     SCROW nRow = rPos.Row();
    1616           1 :     SCTAB nTab = rPos.Tab();
    1617           1 :     if ( nTab != aStartPos.Tab() )
    1618           0 :         return -1;                                      // wrong sheet
    1619             : 
    1620             :     //  calculate output positions and sizes
    1621             : 
    1622           1 :     CalcSizes();
    1623             : 
    1624             :     //  test for column header
    1625             : 
    1626           1 :     if ( nRow == nTabStartRow && nCol >= nDataStartCol && nCol < nDataStartCol + nColFieldCount )
    1627             :     {
    1628           0 :         rOrient = sheet::DataPilotFieldOrientation_COLUMN;
    1629           0 :         long nField = nCol - nDataStartCol;
    1630           0 :         return pColFields[nField].nDim;
    1631             :     }
    1632             : 
    1633             :     //  test for row header
    1634             : 
    1635           1 :     if ( nRow+1 == nDataStartRow && nCol >= nTabStartCol && nCol < nTabStartCol + nRowFieldCount )
    1636             :     {
    1637           0 :         rOrient = sheet::DataPilotFieldOrientation_ROW;
    1638           0 :         long nField = nCol - nTabStartCol;
    1639           0 :         return pRowFields[nField].nDim;
    1640             :     }
    1641             : 
    1642             :     //  test for page field
    1643             : 
    1644           1 :     SCROW nPageStartRow = aStartPos.Row() + ( bDoFilter ? 1 : 0 );
    1645           1 :     if ( nCol == aStartPos.Col() && nRow >= nPageStartRow && nRow < nPageStartRow + nPageFieldCount )
    1646             :     {
    1647           1 :         rOrient = sheet::DataPilotFieldOrientation_PAGE;
    1648           1 :         long nField = nRow - nPageStartRow;
    1649           1 :         return pPageFields[nField].nDim;
    1650             :     }
    1651             : 
    1652             :     //TODO: single data field (?)
    1653             : 
    1654           0 :     rOrient = sheet::DataPilotFieldOrientation_HIDDEN;
    1655           0 :     return -1;      // invalid
    1656             : }
    1657             : 
    1658           0 : bool ScDPOutput::GetHeaderDrag( const ScAddress& rPos, bool bMouseLeft, bool bMouseTop,
    1659             :                                 long nDragDim,
    1660             :                                 Rectangle& rPosRect, sal_uInt16& rOrient, long& rDimPos )
    1661             : {
    1662             :     //  Rectangle instead of ScRange for rPosRect to allow for negative values
    1663             : 
    1664           0 :     SCCOL nCol = rPos.Col();
    1665           0 :     SCROW nRow = rPos.Row();
    1666           0 :     SCTAB nTab = rPos.Tab();
    1667           0 :     if ( nTab != aStartPos.Tab() )
    1668           0 :         return false;                                       // wrong sheet
    1669             : 
    1670             :     //  calculate output positions and sizes
    1671             : 
    1672           0 :     CalcSizes();
    1673             : 
    1674             :     //  test for column header
    1675             : 
    1676           0 :     if ( nCol >= nDataStartCol && nCol <= nTabEndCol &&
    1677           0 :             nRow + 1 >= nMemberStartRow && nRow < nMemberStartRow + nColFieldCount )
    1678             :     {
    1679           0 :         long nField = nRow - nMemberStartRow;
    1680           0 :         if (nField < 0)
    1681             :         {
    1682           0 :             nField = 0;
    1683           0 :             bMouseTop = true;
    1684             :         }
    1685             :         //TODO: find start of dimension
    1686             : 
    1687             :         rPosRect = Rectangle( nDataStartCol, nMemberStartRow + nField,
    1688           0 :                               nTabEndCol, nMemberStartRow + nField -1 );
    1689             : 
    1690           0 :         bool bFound = false;            // is this within the same orientation?
    1691           0 :         bool bBeforeDrag = false;
    1692           0 :         bool bAfterDrag = false;
    1693           0 :         for (long nPos=0; nPos<nColFieldCount && !bFound; nPos++)
    1694             :         {
    1695           0 :             if (pColFields[nPos].nDim == nDragDim)
    1696             :             {
    1697           0 :                 bFound = true;
    1698           0 :                 if ( nField < nPos )
    1699           0 :                     bBeforeDrag = true;
    1700           0 :                 else if ( nField > nPos )
    1701           0 :                     bAfterDrag = true;
    1702             :             }
    1703             :         }
    1704             : 
    1705           0 :         if ( bFound )
    1706             :         {
    1707           0 :             if (!bBeforeDrag)
    1708             :             {
    1709           0 :                 ++rPosRect.Bottom();
    1710           0 :                 if (bAfterDrag)
    1711           0 :                     ++rPosRect.Top();
    1712             :             }
    1713             :         }
    1714             :         else
    1715             :         {
    1716           0 :             if ( !bMouseTop )
    1717             :             {
    1718           0 :                 ++rPosRect.Top();
    1719           0 :                 ++rPosRect.Bottom();
    1720           0 :                 ++nField;
    1721             :             }
    1722             :         }
    1723             : 
    1724           0 :         rOrient = sheet::DataPilotFieldOrientation_COLUMN;
    1725           0 :         rDimPos = nField;                       //!...
    1726           0 :         return true;
    1727             :     }
    1728             : 
    1729             :     //  test for row header
    1730             : 
    1731             :     //  special case if no row fields
    1732           0 :     bool bSpecial = ( nRow+1 >= nDataStartRow && nRow <= nTabEndRow &&
    1733           0 :                         nRowFieldCount == 0 && nCol == nTabStartCol && bMouseLeft );
    1734             : 
    1735           0 :     if ( bSpecial || ( nRow+1 >= nDataStartRow && nRow <= nTabEndRow &&
    1736           0 :                         nCol + 1 >= nTabStartCol && nCol < nTabStartCol + nRowFieldCount ) )
    1737             :     {
    1738           0 :         long nField = nCol - nTabStartCol;
    1739             :         //TODO: find start of dimension
    1740             : 
    1741           0 :         rPosRect = Rectangle( nTabStartCol + nField, nDataStartRow - 1,
    1742           0 :                               nTabStartCol + nField - 1, nTabEndRow );
    1743             : 
    1744           0 :         bool bFound = false;            // is this within the same orientation?
    1745           0 :         bool bBeforeDrag = false;
    1746           0 :         bool bAfterDrag = false;
    1747           0 :         for (long nPos=0; nPos<nRowFieldCount && !bFound; nPos++)
    1748             :         {
    1749           0 :             if (pRowFields[nPos].nDim == nDragDim)
    1750             :             {
    1751           0 :                 bFound = true;
    1752           0 :                 if ( nField < nPos )
    1753           0 :                     bBeforeDrag = true;
    1754           0 :                 else if ( nField > nPos )
    1755           0 :                     bAfterDrag = true;
    1756             :             }
    1757             :         }
    1758             : 
    1759           0 :         if ( bFound )
    1760             :         {
    1761           0 :             if (!bBeforeDrag)
    1762             :             {
    1763           0 :                 ++rPosRect.Right();
    1764           0 :                 if (bAfterDrag)
    1765           0 :                     ++rPosRect.Left();
    1766             :             }
    1767             :         }
    1768             :         else
    1769             :         {
    1770           0 :             if ( !bMouseLeft )
    1771             :             {
    1772           0 :                 ++rPosRect.Left();
    1773           0 :                 ++rPosRect.Right();
    1774           0 :                 ++nField;
    1775             :             }
    1776             :         }
    1777             : 
    1778           0 :         rOrient = sheet::DataPilotFieldOrientation_ROW;
    1779           0 :         rDimPos = nField;                       //!...
    1780           0 :         return true;
    1781             :     }
    1782             : 
    1783             :     //  test for page fields
    1784             : 
    1785           0 :     SCROW nPageStartRow = aStartPos.Row() + ( bDoFilter ? 1 : 0 );
    1786           0 :     if ( nCol >= aStartPos.Col() && nCol <= nTabEndCol &&
    1787           0 :             nRow + 1 >= nPageStartRow && nRow < nPageStartRow + nPageFieldCount )
    1788             :     {
    1789           0 :         long nField = nRow - nPageStartRow;
    1790           0 :         if (nField < 0)
    1791             :         {
    1792           0 :             nField = 0;
    1793           0 :             bMouseTop = true;
    1794             :         }
    1795             :         //TODO: find start of dimension
    1796             : 
    1797           0 :         rPosRect = Rectangle( aStartPos.Col(), nPageStartRow + nField,
    1798           0 :                               nTabEndCol, nPageStartRow + nField - 1 );
    1799             : 
    1800           0 :         bool bFound = false;            // is this within the same orientation?
    1801           0 :         bool bBeforeDrag = false;
    1802           0 :         bool bAfterDrag = false;
    1803           0 :         for (long nPos=0; nPos<nPageFieldCount && !bFound; nPos++)
    1804             :         {
    1805           0 :             if (pPageFields[nPos].nDim == nDragDim)
    1806             :             {
    1807           0 :                 bFound = true;
    1808           0 :                 if ( nField < nPos )
    1809           0 :                     bBeforeDrag = true;
    1810           0 :                 else if ( nField > nPos )
    1811           0 :                     bAfterDrag = true;
    1812             :             }
    1813             :         }
    1814             : 
    1815           0 :         if ( bFound )
    1816             :         {
    1817           0 :             if (!bBeforeDrag)
    1818             :             {
    1819           0 :                 ++rPosRect.Bottom();
    1820           0 :                 if (bAfterDrag)
    1821           0 :                     ++rPosRect.Top();
    1822             :             }
    1823             :         }
    1824             :         else
    1825             :         {
    1826           0 :             if ( !bMouseTop )
    1827             :             {
    1828           0 :                 ++rPosRect.Top();
    1829           0 :                 ++rPosRect.Bottom();
    1830           0 :                 ++nField;
    1831             :             }
    1832             :         }
    1833             : 
    1834           0 :         rOrient = sheet::DataPilotFieldOrientation_PAGE;
    1835           0 :         rDimPos = nField;                       //!...
    1836           0 :         return true;
    1837             :     }
    1838             : 
    1839           0 :     return false;
    1840         156 : }
    1841             : 
    1842             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11