LCOV - code coverage report
Current view: top level - sc/source/core/data - dpoutput.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 655 1044 62.7 %
Date: 2012-08-25 Functions: 42 54 77.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 626 1664 37.6 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  *
       4                 :            :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5                 :            :  *
       6                 :            :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       7                 :            :  *
       8                 :            :  * OpenOffice.org - a multi-platform office productivity suite
       9                 :            :  *
      10                 :            :  * This file is part of OpenOffice.org.
      11                 :            :  *
      12                 :            :  * OpenOffice.org is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU Lesser General Public License version 3
      14                 :            :  * only, as published by the Free Software Foundation.
      15                 :            :  *
      16                 :            :  * OpenOffice.org is distributed in the hope that it will be useful,
      17                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19                 :            :  * GNU Lesser General Public License version 3 for more details
      20                 :            :  * (a copy is included in the LICENSE file that accompanied this code).
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU Lesser General Public License
      23                 :            :  * version 3 along with OpenOffice.org.  If not, see
      24                 :            :  * <http://www.openoffice.org/license.html>
      25                 :            :  * for a copy of the LGPLv3 License.
      26                 :            :  *
      27                 :            :  ************************************************************************/
      28                 :            : 
      29                 :            : #include "scitems.hxx"
      30                 :            : #include <svx/algitem.hxx>
      31                 :            : #include <editeng/boxitem.hxx>
      32                 :            : #include <editeng/brshitem.hxx>
      33                 :            : #include <editeng/wghtitem.hxx>
      34                 :            : #include <editeng/justifyitem.hxx>
      35                 :            : #include <unotools/transliterationwrapper.hxx>
      36                 :            : 
      37                 :            : #include "dpoutput.hxx"
      38                 :            : #include "dptabsrc.hxx"
      39                 :            : #include "dpcachetable.hxx"
      40                 :            : #include "document.hxx"
      41                 :            : #include "patattr.hxx"
      42                 :            : #include "docpool.hxx"
      43                 :            : #include "markdata.hxx"
      44                 :            : #include "attrib.hxx"
      45                 :            : #include "formula/errorcodes.hxx"       // errNoValue
      46                 :            : #include "miscuno.hxx"
      47                 :            : #include "globstr.hrc"
      48                 :            : #include "stlpool.hxx"
      49                 :            : #include "stlsheet.hxx"
      50                 :            : #include "scresid.hxx"
      51                 :            : #include "unonames.hxx"
      52                 :            : #include "sc.hrc"
      53                 :            : #include "stringutil.hxx"
      54                 :            : #include "dputil.hxx"
      55                 :            : 
      56                 :            : #include <com/sun/star/beans/XPropertySet.hpp>
      57                 :            : #include <com/sun/star/sheet/DataPilotTableHeaderData.hpp>
      58                 :            : #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
      59                 :            : #include <com/sun/star/sheet/DataPilotTablePositionData.hpp>
      60                 :            : #include <com/sun/star/sheet/DataPilotTableResultData.hpp>
      61                 :            : #include <com/sun/star/sheet/MemberResultFlags.hpp>
      62                 :            : #include <com/sun/star/sheet/TableFilterField.hpp>
      63                 :            : #include <com/sun/star/sheet/DataResultFlags.hpp>
      64                 :            : #include <com/sun/star/sheet/DataPilotTablePositionType.hpp>
      65                 :            : 
      66                 :            : #include <vector>
      67                 :            : 
      68                 :            : using namespace com::sun::star;
      69                 :            : using ::std::vector;
      70                 :            : using ::com::sun::star::beans::XPropertySet;
      71                 :            : using ::com::sun::star::uno::Sequence;
      72                 :            : using ::com::sun::star::uno::UNO_QUERY;
      73                 :            : using ::com::sun::star::uno::Reference;
      74                 :            : using ::com::sun::star::sheet::DataPilotTablePositionData;
      75                 :            : using ::com::sun::star::sheet::DataPilotTableResultData;
      76                 :            : using ::com::sun::star::uno::makeAny;
      77                 :            : using ::com::sun::star::uno::Any;
      78                 :            : using ::rtl::OUString;
      79                 :            : 
      80                 :            : #define SC_DP_FRAME_INNER_BOLD      20
      81                 :            : #define SC_DP_FRAME_OUTER_BOLD      40
      82                 :            : 
      83                 :            : #define SC_DP_FRAME_COLOR           Color(0,0,0) //( 0x20, 0x40, 0x68 )
      84                 :            : 
      85                 :            : #define SC_DPOUT_MAXLEVELS  256
      86                 :            : 
      87                 :     107636 : struct ScDPOutLevelData
      88                 :            : {
      89                 :            :     long                                nDim;
      90                 :            :     long                                nHier;
      91                 :            :     long                                nLevel;
      92                 :            :     long                                nDimPos;
      93                 :            :     uno::Sequence<sheet::MemberResult>  aResult;
      94                 :            :     rtl::OUString                       maName;   /// Name is the internal field name.
      95                 :            :     rtl::OUString                       maCaption; /// Caption is the name visible in the output table.
      96                 :            :     bool                                mbHasHiddenMember:1;
      97                 :            :     bool                                mbDataLayout:1;
      98                 :            : 
      99                 :     107549 :     ScDPOutLevelData() :
     100                 :     107549 :         nDim(-1), nHier(-1), nLevel(-1), nDimPos(-1), mbHasHiddenMember(false), mbDataLayout(false)
     101                 :     107549 :     {}
     102                 :            : 
     103                 :         42 :     bool operator<(const ScDPOutLevelData& r) const
     104                 :            :         { return nDimPos<r.nDimPos || ( nDimPos==r.nDimPos && nHier<r.nHier ) ||
     105 [ +  + ][ -  + ]:         42 :             ( nDimPos==r.nDimPos && nHier==r.nHier && nLevel<r.nLevel ); }
         [ #  # ][ -  + ]
         [ #  # ][ #  # ]
     106                 :            : 
     107                 :         29 :     void Swap(ScDPOutLevelData& r)
     108 [ +  - ][ +  - ]:         29 :         { ScDPOutLevelData aTemp; aTemp = r; r = *this; *this = aTemp; }
         [ +  - ][ +  - ]
                 [ +  - ]
     109                 :            : 
     110                 :            :     //! bug (73840) in uno::Sequence - copy and then assign doesn't work!
     111                 :            : };
     112                 :            : 
     113                 :            : namespace {
     114                 :            : 
     115                 :        401 : bool lcl_compareColfuc ( SCCOL i,  SCCOL j) { return (i<j); }
     116                 :        548 : bool lcl_compareRowfuc ( SCROW i,  SCROW j) { return (i<j); }
     117                 :            : 
     118                 :        326 : class ScDPOutputImpl
     119                 :            : {
     120                 :            :     ScDocument*         mpDoc;
     121                 :            :     sal_uInt16          mnTab;
     122                 :            :     ::std::vector< bool > mbNeedLineCols;
     123                 :            :     ::std::vector< SCCOL > mnCols;
     124                 :            : 
     125                 :            :     ::std::vector< bool > mbNeedLineRows;
     126                 :            :     ::std::vector< SCROW > mnRows;
     127                 :            : 
     128                 :            :     SCCOL   mnTabStartCol;
     129                 :            :     SCROW   mnTabStartRow;
     130                 :            :     SCCOL   mnMemberStartCol;
     131                 :            :     SCROW   mnMemberStartRow;
     132                 :            : 
     133                 :            :     SCCOL   mnDataStartCol;
     134                 :            :     SCROW   mnDataStartRow;
     135                 :            :     SCCOL   mnTabEndCol;
     136                 :            :     SCROW   mnTabEndRow;
     137                 :            : 
     138                 :            : public:
     139                 :            :     ScDPOutputImpl( ScDocument* pDoc, sal_uInt16 nTab,
     140                 :            :         SCCOL   nTabStartCol,
     141                 :            :         SCROW   nTabStartRow,
     142                 :            :         SCCOL   nMemberStartCol,
     143                 :            :         SCROW   nMemberStartRow,
     144                 :            :         SCCOL nDataStartCol,
     145                 :            :         SCROW nDataStartRow,
     146                 :            :         SCCOL nTabEndCol,
     147                 :            :         SCROW nTabEndRow );
     148                 :            :     bool AddRow( SCROW nRow );
     149                 :            :     bool AddCol( SCCOL nCol );
     150                 :            : 
     151                 :            :     void OutputDataArea();
     152                 :            :     void OutputBlockFrame ( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, bool bHori = false );
     153                 :            : 
     154                 :            : };
     155                 :            : 
     156                 :        140 : void ScDPOutputImpl::OutputDataArea()
     157                 :            : {
     158                 :        140 :     AddRow( mnDataStartRow );
     159                 :        140 :     AddCol( mnDataStartCol );
     160                 :            : 
     161         [ +  - ]:        140 :     mnCols.push_back( mnTabEndCol+1); //set last row bottom
     162         [ +  - ]:        140 :     mnRows.push_back( mnTabEndRow+1); //set last col bottom
     163                 :            : 
     164                 :        140 :     bool bAllRows = ( ( mnTabEndRow - mnDataStartRow + 2 ) == (SCROW) mnRows.size() );
     165                 :            : 
     166                 :        140 :     std::sort( mnCols.begin(), mnCols.end(), lcl_compareColfuc );
     167                 :        140 :     std::sort( mnRows.begin(), mnRows.end(), lcl_compareRowfuc );
     168                 :            : 
     169         [ +  + ]:        374 :     for( SCCOL nCol = 0; nCol < (SCCOL)mnCols.size()-1; nCol ++ )
     170                 :            :     {
     171         [ +  + ]:        234 :         if ( !bAllRows )
     172                 :            :         {
     173         [ +  + ]:        169 :             if ( nCol < (SCCOL)mnCols.size()-2)
     174                 :            :             {
     175         [ +  + ]:        127 :                 for ( SCROW i = nCol%2; i < (SCROW)mnRows.size()-2; i +=2 )
     176                 :         65 :                     OutputBlockFrame( mnCols[nCol], mnRows[i], mnCols[nCol+1]-1, mnRows[i+1]-1 );
     177         [ +  - ]:         62 :                 if ( mnRows.size()>=2 )
     178                 :         62 :                     OutputBlockFrame(  mnCols[nCol], mnRows[mnRows.size()-2], mnCols[nCol+1]-1, mnRows[mnRows.size()-1]-1 );
     179                 :            :             }
     180                 :            :             else
     181                 :            :             {
     182         [ +  + ]:        354 :                 for ( SCROW i = 0 ; i < (SCROW)mnRows.size()-1; i++ )
     183                 :        247 :                     OutputBlockFrame(  mnCols[nCol], mnRows[i], mnCols[nCol+1]-1,  mnRows[i+1]-1 );
     184                 :            :             }
     185                 :            :         }
     186                 :            :         else
     187                 :         65 :             OutputBlockFrame( mnCols[nCol], mnRows.front(), mnCols[nCol+1]-1, mnRows.back()-1, bAllRows );
     188                 :            :     }
     189                 :            :     //out put rows area outer framer
     190         [ +  + ]:        140 :     if ( mnTabStartCol != mnDataStartCol )
     191                 :            :     {
     192         [ +  - ]:        118 :         if ( mnTabStartRow != mnDataStartRow )
     193                 :        118 :             OutputBlockFrame( mnTabStartCol, mnTabStartRow, mnDataStartCol-1, mnDataStartRow-1 );
     194                 :        118 :         OutputBlockFrame( mnTabStartCol, mnDataStartRow, mnDataStartCol-1, mnTabEndRow );
     195                 :            :     }
     196                 :            :     //out put cols area outer framer
     197                 :        140 :     OutputBlockFrame( mnDataStartCol, mnTabStartRow, mnTabEndCol, mnDataStartRow-1 );
     198                 :        140 : }
     199                 :            : 
     200                 :        326 : ScDPOutputImpl::ScDPOutputImpl( ScDocument* pDoc, sal_uInt16 nTab,
     201                 :            :         SCCOL   nTabStartCol,
     202                 :            :         SCROW   nTabStartRow,
     203                 :            :         SCCOL   nMemberStartCol,
     204                 :            :         SCROW   nMemberStartRow,
     205                 :            :         SCCOL nDataStartCol,
     206                 :            :         SCROW nDataStartRow,
     207                 :            :         SCCOL nTabEndCol,
     208                 :            :         SCROW nTabEndRow ):
     209                 :            :     mpDoc( pDoc ),
     210                 :            :     mnTab( nTab ),
     211                 :            :     mnTabStartCol( nTabStartCol ),
     212                 :            :     mnTabStartRow( nTabStartRow ),
     213                 :            :     mnMemberStartCol( nMemberStartCol),
     214                 :            :     mnMemberStartRow( nMemberStartRow),
     215                 :            :     mnDataStartCol ( nDataStartCol ),
     216                 :            :     mnDataStartRow ( nDataStartRow ),
     217                 :            :     mnTabEndCol(  nTabEndCol ),
     218 [ +  - ][ +  - ]:        326 :     mnTabEndRow(  nTabEndRow )
                 [ +  - ]
     219                 :            : {
     220         [ +  - ]:        326 :     mbNeedLineCols.resize( nTabEndCol-nDataStartCol+1, false );
     221         [ +  - ]:        326 :     mbNeedLineRows.resize( nTabEndRow-nDataStartRow+1, false );
     222                 :            : 
     223                 :        326 : }
     224                 :            : 
     225                 :        343 : bool ScDPOutputImpl::AddRow( SCROW nRow )
     226                 :            : {
     227         [ +  + ]:        343 :     if ( !mbNeedLineRows[ nRow - mnDataStartRow ] )
     228                 :            :     {
     229                 :        311 :         mbNeedLineRows[ nRow - mnDataStartRow ] = true;
     230                 :        311 :         mnRows.push_back( nRow );
     231                 :        311 :         return true;
     232                 :            :     }
     233                 :            :     else
     234                 :        343 :         return false;
     235                 :            : }
     236                 :            : 
     237                 :        241 : bool ScDPOutputImpl::AddCol( SCCOL nCol )
     238                 :            : {
     239                 :            : 
     240         [ +  + ]:        241 :     if ( !mbNeedLineCols[ nCol - mnDataStartCol ] )
     241                 :            :     {
     242                 :        234 :         mbNeedLineCols[ nCol - mnDataStartCol ] = true;
     243                 :        234 :         mnCols.push_back( nCol );
     244                 :        234 :         return true;
     245                 :            :     }
     246                 :            :     else
     247                 :        241 :         return false;
     248                 :            : }
     249                 :            : 
     250                 :       1326 : void ScDPOutputImpl::OutputBlockFrame ( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, bool bHori )
     251                 :            : {
     252                 :       1326 :     Color color = SC_DP_FRAME_COLOR;
     253         [ +  - ]:       1326 :     ::editeng::SvxBorderLine aLine( &color, SC_DP_FRAME_INNER_BOLD );
     254         [ +  - ]:       1326 :     ::editeng::SvxBorderLine aOutLine( &color, SC_DP_FRAME_OUTER_BOLD );
     255                 :            : 
     256         [ +  - ]:       1326 :     SvxBoxItem aBox( ATTR_BORDER );
     257                 :            : 
     258         [ +  + ]:       1326 :     if ( nStartCol == mnTabStartCol )
     259         [ +  - ]:        542 :         aBox.SetLine(&aOutLine, BOX_LINE_LEFT);
     260                 :            :     else
     261         [ +  - ]:        784 :         aBox.SetLine(&aLine, BOX_LINE_LEFT);
     262                 :            : 
     263         [ +  + ]:       1326 :     if ( nStartRow == mnTabStartRow )
     264         [ +  - ]:        328 :         aBox.SetLine(&aOutLine, BOX_LINE_TOP);
     265                 :            :     else
     266         [ +  - ]:        998 :         aBox.SetLine(&aLine, BOX_LINE_TOP);
     267                 :            : 
     268         [ +  + ]:       1326 :     if ( nEndCol == mnTabEndCol ) //bottom row
     269         [ +  - ]:        646 :         aBox.SetLine(&aOutLine, BOX_LINE_RIGHT);
     270                 :            :     else
     271         [ +  - ]:        680 :         aBox.SetLine(&aLine,  BOX_LINE_RIGHT);
     272                 :            : 
     273         [ +  + ]:       1326 :      if ( nEndRow == mnTabEndRow ) //bottom
     274         [ +  - ]:        461 :         aBox.SetLine(&aOutLine,  BOX_LINE_BOTTOM);
     275                 :            :     else
     276         [ +  - ]:        865 :         aBox.SetLine(&aLine,  BOX_LINE_BOTTOM);
     277                 :            : 
     278                 :            : 
     279         [ +  - ]:       1326 :     SvxBoxInfoItem aBoxInfo( ATTR_BORDER_INNER );
     280                 :       1326 :     aBoxInfo.SetValid(VALID_VERT,false );
     281         [ +  + ]:       1326 :     if ( bHori )
     282                 :            :     {
     283                 :         65 :         aBoxInfo.SetValid(VALID_HORI,true);
     284         [ +  - ]:         65 :         aBoxInfo.SetLine( &aLine, BOXINFO_LINE_HORI );
     285                 :            :     }
     286                 :            :     else
     287                 :       1261 :         aBoxInfo.SetValid(VALID_HORI,false );
     288                 :            : 
     289                 :       1326 :     aBoxInfo.SetValid(VALID_DISTANCE,false);
     290                 :            : 
     291 [ +  - ][ +  - ]:       1326 :     mpDoc->ApplyFrameAreaTab( ScRange(  nStartCol, nStartRow, mnTab, nEndCol, nEndRow , mnTab ), &aBox, &aBoxInfo );
                 [ +  - ]
     292                 :            : 
     293                 :       1326 : }
     294                 :            : 
     295                 :       1894 : void lcl_SetStyleById( ScDocument* pDoc, SCTAB nTab,
     296                 :            :                     SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
     297                 :            :                     sal_uInt16 nStrId )
     298                 :            : {
     299 [ +  - ][ +  - ]:       1894 :     if ( nCol1 > nCol2 || nRow1 > nRow2 )
     300                 :            :     {
     301                 :            :         OSL_FAIL("SetStyleById: invalid range");
     302                 :       1894 :         return;
     303                 :            :     }
     304                 :            : 
     305 [ +  - ][ +  - ]:       1894 :     rtl::OUString aStyleName = ScGlobal::GetRscString( nStrId );
     306         [ +  - ]:       1894 :     ScStyleSheetPool* pStlPool = pDoc->GetStyleSheetPool();
     307 [ +  - ][ +  - ]:       1894 :     ScStyleSheet* pStyle = (ScStyleSheet*) pStlPool->Find( aStyleName, SFX_STYLE_FAMILY_PARA );
                 [ +  - ]
     308         [ +  + ]:       1894 :     if (!pStyle)
     309                 :            :     {
     310                 :            :         //  create new style (was in ScPivot::SetStyle)
     311                 :            : 
     312                 :            :         pStyle = (ScStyleSheet*) &pStlPool->Make( aStyleName, SFX_STYLE_FAMILY_PARA,
     313 [ +  - ][ +  - ]:        288 :                                                     SFXSTYLEBIT_USERDEF );
                 [ +  - ]
     314 [ +  - ][ +  - ]:        288 :         pStyle->SetParent( ScGlobal::GetRscString(STR_STYLENAME_STANDARD) );
     315         [ +  - ]:        288 :         SfxItemSet& rSet = pStyle->GetItemSet();
     316 [ +  + ][ +  + ]:        288 :         if ( nStrId==STR_PIVOT_STYLE_RESULT || nStrId==STR_PIVOT_STYLE_TITLE )
     317 [ +  - ][ +  - ]:         88 :             rSet.Put( SvxWeightItem( WEIGHT_BOLD, ATTR_FONT_WEIGHT ) );
                 [ +  - ]
     318 [ +  + ][ +  + ]:        288 :         if ( nStrId==STR_PIVOT_STYLE_CATEGORY || nStrId==STR_PIVOT_STYLE_TITLE )
     319 [ +  - ][ +  - ]:         91 :             rSet.Put( SvxHorJustifyItem( SVX_HOR_JUSTIFY_LEFT, ATTR_HOR_JUSTIFY ) );
                 [ +  - ]
     320                 :            :     }
     321                 :            : 
     322         [ +  - ]:       1894 :     pDoc->ApplyStyleAreaTab( nCol1, nRow1, nCol2, nRow2, nTab, *pStyle );
     323                 :            : }
     324                 :            : 
     325                 :        269 : void lcl_SetFrame( ScDocument* pDoc, SCTAB nTab,
     326                 :            :                     SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
     327                 :            :                     sal_uInt16 nWidth )
     328                 :            : {
     329         [ +  - ]:        269 :     ::editeng::SvxBorderLine aLine(0, nWidth, table::BorderLineStyle::SOLID);
     330         [ +  - ]:        269 :     SvxBoxItem aBox( ATTR_BORDER );
     331         [ +  - ]:        269 :     aBox.SetLine(&aLine, BOX_LINE_LEFT);
     332         [ +  - ]:        269 :     aBox.SetLine(&aLine, BOX_LINE_TOP);
     333         [ +  - ]:        269 :     aBox.SetLine(&aLine, BOX_LINE_RIGHT);
     334         [ +  - ]:        269 :     aBox.SetLine(&aLine, BOX_LINE_BOTTOM);
     335         [ +  - ]:        269 :     SvxBoxInfoItem aBoxInfo( ATTR_BORDER_INNER );
     336                 :        269 :     aBoxInfo.SetValid(VALID_HORI,false);
     337                 :        269 :     aBoxInfo.SetValid(VALID_VERT,false);
     338                 :        269 :     aBoxInfo.SetValid(VALID_DISTANCE,false);
     339                 :            : 
     340 [ +  - ][ +  - ]:        269 :     pDoc->ApplyFrameAreaTab( ScRange( nCol1, nRow1, nTab, nCol2, nRow2, nTab ), &aBox, &aBoxInfo );
                 [ +  - ]
     341                 :        269 : }
     342                 :            : 
     343                 :            : // -----------------------------------------------------------------------
     344                 :            : 
     345                 :         84 : void lcl_FillNumberFormats( sal_uInt32*& rFormats, long& rCount,
     346                 :            :                             const uno::Reference<sheet::XDataPilotMemberResults>& xLevRes,
     347                 :            :                             const uno::Reference<container::XIndexAccess>& xDims )
     348                 :            : {
     349         [ +  - ]:         84 :     if ( rFormats )
     350                 :         84 :         return;                         // already set
     351                 :            : 
     352                 :            :     //  xLevRes is from the data layout dimension
     353                 :            :     //! use result sequence from ScDPOutLevelData!
     354                 :            : 
     355 [ +  - ][ +  - ]:         84 :     uno::Sequence<sheet::MemberResult> aResult = xLevRes->getResults();
     356                 :            : 
     357                 :         84 :     long nSize = aResult.getLength();
     358         [ +  - ]:         84 :     if (nSize)
     359                 :            :     {
     360                 :            :         //  get names/formats for all data dimensions
     361                 :            :         //! merge this with the loop to collect ScDPOutLevelData?
     362                 :            : 
     363         [ +  + ]:      43092 :         rtl::OUString aDataNames[SC_DPOUT_MAXLEVELS];
     364                 :            :         sal_uInt32 nDataFormats[SC_DPOUT_MAXLEVELS];
     365                 :         84 :         long nDataCount = 0;
     366                 :         84 :         bool bAnySet = false;
     367                 :            : 
     368 [ +  - ][ +  - ]:         84 :         long nDimCount = xDims->getCount();
     369         [ +  + ]:        461 :         for (long nDim=0; nDim<nDimCount; nDim++)
     370                 :            :         {
     371                 :            :             uno::Reference<uno::XInterface> xDim =
     372 [ +  - ][ +  - ]:        377 :                     ScUnoHelpFunctions::AnyToInterface( xDims->getByIndex(nDim) );
                 [ +  - ]
     373         [ +  - ]:        377 :             uno::Reference<beans::XPropertySet> xDimProp( xDim, uno::UNO_QUERY );
     374         [ +  - ]:        377 :             uno::Reference<container::XNamed> xDimName( xDim, uno::UNO_QUERY );
     375 [ +  - ][ +  - ]:        377 :             if ( xDimProp.is() && xDimName.is() )
                 [ +  - ]
     376                 :            :             {
     377                 :            :                 sheet::DataPilotFieldOrientation eDimOrient =
     378                 :            :                     (sheet::DataPilotFieldOrientation) ScUnoHelpFunctions::GetEnumProperty(
     379                 :            :                         xDimProp, rtl::OUString(SC_UNO_DP_ORIENTATION),
     380         [ +  - ]:        377 :                         sheet::DataPilotFieldOrientation_HIDDEN );
     381         [ +  + ]:        377 :                 if ( eDimOrient == sheet::DataPilotFieldOrientation_DATA )
     382                 :            :                 {
     383 [ +  - ][ +  - ]:         99 :                     aDataNames[nDataCount] = xDimName->getName();
     384                 :            :                     long nFormat = ScUnoHelpFunctions::GetLongProperty(
     385                 :            :                                             xDimProp,
     386         [ +  - ]:         99 :                                             rtl::OUString(SC_UNONAME_NUMFMT) );
     387                 :         99 :                     nDataFormats[nDataCount] = nFormat;
     388         [ -  + ]:         99 :                     if ( nFormat != 0 )
     389                 :          0 :                         bAnySet = true;
     390                 :         99 :                     ++nDataCount;
     391                 :            :                 }
     392                 :            :             }
     393                 :        377 :         }
     394                 :            : 
     395         [ -  + ]:         84 :         if ( bAnySet )      // forget everything if all formats are 0 (or no data dimensions)
     396                 :            :         {
     397                 :          0 :             const sheet::MemberResult* pArray = aResult.getConstArray();
     398                 :            : 
     399                 :          0 :             rtl::OUString aName;
     400         [ #  # ]:          0 :             sal_uInt32* pNumFmt = new sal_uInt32[nSize];
     401         [ #  # ]:          0 :             if (nDataCount == 1)
     402                 :            :             {
     403                 :            :                 //  only one data dimension -> use its numberformat everywhere
     404                 :          0 :                 long nFormat = nDataFormats[0];
     405         [ #  # ]:          0 :                 for (long nPos=0; nPos<nSize; nPos++)
     406                 :          0 :                     pNumFmt[nPos] = nFormat;
     407                 :            :             }
     408                 :            :             else
     409                 :            :             {
     410         [ #  # ]:          0 :                 for (long nPos=0; nPos<nSize; nPos++)
     411                 :            :                 {
     412                 :            :                     //  if CONTINUE bit is set, keep previous name
     413                 :            :                     //! keep number format instead!
     414         [ #  # ]:          0 :                     if ( !(pArray[nPos].Flags & sheet::MemberResultFlags::CONTINUE) )
     415                 :          0 :                         aName = pArray[nPos].Name;
     416                 :            : 
     417                 :          0 :                     sal_uInt32 nFormat = 0;
     418         [ #  # ]:          0 :                     for (long i=0; i<nDataCount; i++)
     419         [ #  # ]:          0 :                         if (aName == aDataNames[i])         //! search more efficiently?
     420                 :            :                         {
     421                 :          0 :                             nFormat = nDataFormats[i];
     422                 :          0 :                             break;
     423                 :            :                         }
     424                 :          0 :                     pNumFmt[nPos] = nFormat;
     425                 :            :                 }
     426                 :            :             }
     427                 :            : 
     428                 :          0 :             rFormats = pNumFmt;
     429                 :          0 :             rCount = nSize;
     430 [ +  + ][ #  # ]:      21588 :         }
     431         [ +  - ]:         84 :     }
     432                 :            : }
     433                 :            : 
     434                 :         56 : sal_uInt32 lcl_GetFirstNumberFormat( const uno::Reference<container::XIndexAccess>& xDims )
     435                 :            : {
     436                 :         56 :     long nDimCount = xDims->getCount();
     437         [ +  + ]:        249 :     for (long nDim=0; nDim<nDimCount; nDim++)
     438                 :            :     {
     439                 :            :         uno::Reference<uno::XInterface> xDim =
     440 [ +  - ][ +  - ]:        193 :                 ScUnoHelpFunctions::AnyToInterface( xDims->getByIndex(nDim) );
                 [ +  - ]
     441         [ +  - ]:        193 :         uno::Reference<beans::XPropertySet> xDimProp( xDim, uno::UNO_QUERY );
     442         [ +  - ]:        193 :         if ( xDimProp.is() )
     443                 :            :         {
     444                 :            :             sheet::DataPilotFieldOrientation eDimOrient =
     445                 :            :                 (sheet::DataPilotFieldOrientation) ScUnoHelpFunctions::GetEnumProperty(
     446                 :            :                     xDimProp, rtl::OUString(SC_UNO_DP_ORIENTATION),
     447         [ +  - ]:        193 :                     sheet::DataPilotFieldOrientation_HIDDEN );
     448         [ +  + ]:        193 :             if ( eDimOrient == sheet::DataPilotFieldOrientation_DATA )
     449                 :            :             {
     450                 :            :                 long nFormat = ScUnoHelpFunctions::GetLongProperty(
     451                 :            :                                         xDimProp,
     452         [ +  - ]:         41 :                                         rtl::OUString(SC_UNONAME_NUMFMT) );
     453                 :            : 
     454                 :        193 :                 return nFormat;     // use format from first found data dimension
     455                 :            :             }
     456                 :            :         }
     457 [ +  + ][ +  + ]:        193 :     }
     458                 :            : 
     459                 :         56 :     return 0;       // none found
     460                 :            : }
     461                 :            : 
     462                 :        420 : void lcl_SortFields( ScDPOutLevelData* pFields, long nFieldCount )
     463                 :            : {
     464         [ +  + ]:        456 :     for (long i=0; i+1<nFieldCount; i++)
     465                 :            :     {
     466         [ +  + ]:         78 :         for (long j=0; j+i+1<nFieldCount; j++)
     467         [ +  + ]:         42 :             if ( pFields[j+1] < pFields[j] )
     468                 :         29 :                 pFields[j].Swap( pFields[j+1] );
     469                 :            :     }
     470                 :        420 : }
     471                 :            : 
     472                 :        300 : bool lcl_MemberEmpty( const uno::Sequence<sheet::MemberResult>& rSeq )
     473                 :            : {
     474                 :            :     //  used to skip levels that have no members
     475                 :            : 
     476                 :        300 :     long nLen = rSeq.getLength();
     477                 :        300 :     const sheet::MemberResult* pArray = rSeq.getConstArray();
     478         [ +  + ]:        702 :     for (long i=0; i<nLen; i++)
     479         [ +  + ]:        633 :         if (pArray[i].Flags & sheet::MemberResultFlags::HASMEMBER)
     480                 :        231 :             return false;
     481                 :            : 
     482                 :        300 :     return true;    // no member data -> empty
     483                 :            : }
     484                 :            : 
     485                 :         38 : uno::Sequence<sheet::MemberResult> lcl_GetSelectedPageAsResult( const uno::Reference<beans::XPropertySet>& xDimProp )
     486                 :            : {
     487                 :         38 :     uno::Sequence<sheet::MemberResult> aRet;
     488         [ +  - ]:         38 :     if ( xDimProp.is() )
     489                 :            :     {
     490                 :            :         try
     491                 :            :         {
     492                 :            :             //! merge with ScDPDimension::setPropertyValue?
     493                 :            : 
     494 [ +  - ][ +  - ]:         38 :             uno::Any aValue = xDimProp->getPropertyValue( rtl::OUString(SC_UNO_DP_FILTER) );
     495                 :            : 
     496         [ +  - ]:         38 :             uno::Sequence<sheet::TableFilterField> aSeq;
     497 [ +  - ][ +  - ]:         38 :             if (aValue >>= aSeq)
     498                 :            :             {
     499         [ +  + ]:         38 :                 if ( aSeq.getLength() == 1 )
     500                 :            :                 {
     501         [ +  - ]:          6 :                     const sheet::TableFilterField& rField = aSeq[0];
     502 [ +  - ][ +  - ]:          6 :                     if ( rField.Field == 0 && rField.Operator == sheet::FilterOperator_EQUAL && !rField.IsNumeric )
                 [ +  - ]
     503                 :            :                     {
     504                 :          6 :                         rtl::OUString aSelectedPage( rField.StringValue );
     505                 :            :                         //! different name/caption string?
     506                 :          6 :                         sheet::MemberResult aResult( aSelectedPage, aSelectedPage, 0 );
     507 [ +  - ][ +  - ]:          6 :                         aRet = uno::Sequence<sheet::MemberResult>( &aResult, 1 );
                 [ +  - ]
     508                 :            :                     }
     509                 :            :                 }
     510                 :            :                 // else return empty sequence
     511 [ +  - ][ #  # ]:         38 :             }
     512                 :            :         }
     513         [ #  # ]:          0 :         catch ( uno::Exception& )
     514                 :            :         {
     515                 :            :             // recent addition - allow source to not handle it (no error)
     516                 :            :         }
     517                 :            :     }
     518                 :         38 :     return aRet;
     519                 :            : }
     520                 :            : 
     521                 :            : }
     522                 :            : 
     523                 :        140 : ScDPOutput::ScDPOutput( ScDocument* pD, const uno::Reference<sheet::XDimensionsSupplier>& xSrc,
     524                 :            :                         const ScAddress& rPos, bool bFilter ) :
     525                 :            :     pDoc( pD ),
     526                 :            :     xSource( xSrc ),
     527                 :            :     aStartPos( rPos ),
     528                 :            :     pColNumFmt( NULL ),
     529                 :            :     pRowNumFmt( NULL ),
     530                 :            :     nColFmtCount( 0 ),
     531                 :            :     nRowFmtCount( 0 ),
     532                 :            :     nSingleNumFmt( 0 ),
     533                 :            :     bDoFilter(bFilter),
     534                 :            :     bResultsError(false),
     535                 :            :     mbHasDataLayout(false),
     536                 :            :     bSizesValid(false),
     537                 :            :     bSizeOverflow(false),
     538         [ +  - ]:        140 :     mbHeaderLayout(false)
     539                 :            : {
     540                 :        140 :     nTabStartCol = nMemberStartCol = nDataStartCol = nTabEndCol = 0;
     541                 :        140 :     nTabStartRow = nMemberStartRow = nDataStartRow = nTabEndRow = 0;
     542                 :            : 
     543 [ +  - ][ +  +  :      35980 :     pColFields  = new ScDPOutLevelData[SC_DPOUT_MAXLEVELS];
             #  #  #  # ]
                 [ +  - ]
     544 [ +  - ][ +  - ]:      35980 :     pRowFields  = new ScDPOutLevelData[SC_DPOUT_MAXLEVELS];
           [ +  +  #  #  
                   #  # ]
     545 [ +  - ][ +  - ]:      35980 :     pPageFields = new ScDPOutLevelData[SC_DPOUT_MAXLEVELS];
           [ +  +  #  #  
                   #  # ]
     546                 :        140 :     nColFieldCount = 0;
     547                 :        140 :     nRowFieldCount = 0;
     548                 :        140 :     nPageFieldCount = 0;
     549                 :            : 
     550         [ +  - ]:        140 :     uno::Reference<sheet::XDataPilotResults> xResult( xSource, uno::UNO_QUERY );
     551 [ +  - ][ +  - ]:        140 :     if ( xSource.is() && xResult.is() )
                 [ +  - ]
     552                 :            :     {
     553                 :            :         //  get dimension results:
     554                 :            : 
     555                 :            :         uno::Reference<container::XIndexAccess> xDims =
     556 [ +  - ][ +  - ]:        140 :                 new ScNameToIndexAccess( xSource->getDimensions() );
         [ +  - ][ +  - ]
                 [ +  - ]
     557 [ +  - ][ +  - ]:        140 :         long nDimCount = xDims->getCount();
     558         [ +  + ]:        854 :         for (long nDim=0; nDim<nDimCount; nDim++)
     559                 :            :         {
     560                 :            :             uno::Reference<uno::XInterface> xDim =
     561 [ +  - ][ +  - ]:        714 :                     ScUnoHelpFunctions::AnyToInterface( xDims->getByIndex(nDim) );
                 [ +  - ]
     562         [ +  - ]:        714 :             uno::Reference<beans::XPropertySet> xDimProp( xDim, uno::UNO_QUERY );
     563         [ +  - ]:        714 :             uno::Reference<sheet::XHierarchiesSupplier> xDimSupp( xDim, uno::UNO_QUERY );
     564 [ +  - ][ +  - ]:        714 :             if ( xDimProp.is() && xDimSupp.is() )
                 [ +  - ]
     565                 :            :             {
     566                 :            :                 sheet::DataPilotFieldOrientation eDimOrient =
     567                 :            :                     (sheet::DataPilotFieldOrientation) ScUnoHelpFunctions::GetEnumProperty(
     568                 :            :                         xDimProp, rtl::OUString(SC_UNO_DP_ORIENTATION),
     569         [ +  - ]:        714 :                         sheet::DataPilotFieldOrientation_HIDDEN );
     570                 :            :                 long nDimPos = ScUnoHelpFunctions::GetLongProperty( xDimProp,
     571         [ +  - ]:        714 :                         rtl::OUString(SC_UNO_DP_POSITION) );
     572                 :            :                 bool bIsDataLayout = ScUnoHelpFunctions::GetBoolProperty(
     573         [ +  - ]:        714 :                     xDimProp, rtl::OUString(SC_UNO_DP_ISDATALAYOUT));
     574                 :            :                 bool bHasHiddenMember = ScUnoHelpFunctions::GetBoolProperty(
     575         [ +  - ]:        714 :                     xDimProp, OUString(SC_UNO_DP_HAS_HIDDEN_MEMBER));
     576                 :            : 
     577         [ +  + ]:        714 :                 if ( eDimOrient != sheet::DataPilotFieldOrientation_HIDDEN )
     578                 :            :                 {
     579                 :            :                     uno::Reference<container::XIndexAccess> xHiers =
     580 [ +  - ][ +  - ]:        478 :                             new ScNameToIndexAccess( xDimSupp->getHierarchies() );
         [ +  - ][ +  - ]
                 [ +  - ]
     581                 :            :                     long nHierarchy = ScUnoHelpFunctions::GetLongProperty(
     582                 :            :                                             xDimProp,
     583         [ +  - ]:        478 :                                             rtl::OUString(SC_UNO_DP_USEDHIERARCHY) );
     584 [ +  - ][ -  + ]:        478 :                     if ( nHierarchy >= xHiers->getCount() )
                 [ +  - ]
     585                 :          0 :                         nHierarchy = 0;
     586                 :            : 
     587                 :            :                     uno::Reference<uno::XInterface> xHier =
     588                 :            :                             ScUnoHelpFunctions::AnyToInterface(
     589 [ +  - ][ +  - ]:        478 :                                                 xHiers->getByIndex(nHierarchy) );
                 [ +  - ]
     590         [ +  - ]:        478 :                     uno::Reference<sheet::XLevelsSupplier> xHierSupp( xHier, uno::UNO_QUERY );
     591         [ +  - ]:        478 :                     if ( xHierSupp.is() )
     592                 :            :                     {
     593                 :            :                         uno::Reference<container::XIndexAccess> xLevels =
     594 [ +  - ][ +  - ]:        478 :                                 new ScNameToIndexAccess( xHierSupp->getLevels() );
         [ +  - ][ +  - ]
                 [ +  - ]
     595 [ +  - ][ +  - ]:        478 :                         long nLevCount = xLevels->getCount();
     596         [ +  + ]:        956 :                         for (long nLev=0; nLev<nLevCount; nLev++)
     597                 :            :                         {
     598                 :            :                             uno::Reference<uno::XInterface> xLevel =
     599                 :            :                                         ScUnoHelpFunctions::AnyToInterface(
     600 [ +  - ][ +  - ]:        478 :                                                             xLevels->getByIndex(nLev) );
                 [ +  - ]
     601         [ +  - ]:        478 :                             uno::Reference<container::XNamed> xLevNam( xLevel, uno::UNO_QUERY );
     602                 :            :                             uno::Reference<sheet::XDataPilotMemberResults> xLevRes(
     603         [ +  - ]:        478 :                                     xLevel, uno::UNO_QUERY );
     604 [ +  - ][ +  - ]:        478 :                             if ( xLevNam.is() && xLevRes.is() )
                 [ +  - ]
     605                 :            :                             {
     606 [ +  - ][ +  - ]:        478 :                                 rtl::OUString aName = xLevNam->getName();
     607         [ +  - ]:        478 :                                 Reference<XPropertySet> xPropSet(xLevel, UNO_QUERY);
     608                 :            :                                 // Caption equals the field name by default.
     609                 :            :                                 // #i108948# use ScUnoHelpFunctions::GetStringProperty, because
     610                 :            :                                 // LayoutName is new and may not be present in external implementation
     611                 :            :                                 OUString aCaption = ScUnoHelpFunctions::GetStringProperty( xPropSet,
     612         [ +  - ]:        478 :                                     OUString(SC_UNO_DP_LAYOUTNAME), aName );
     613                 :            : 
     614                 :        478 :                                 bool bRowFieldHasMember = false;
     615   [ +  +  +  + ]:        478 :                                 switch ( eDimOrient )
     616                 :            :                                 {
     617                 :            :                                     case sheet::DataPilotFieldOrientation_COLUMN:
     618                 :         84 :                                         pColFields[nColFieldCount].nDim    = nDim;
     619                 :         84 :                                         pColFields[nColFieldCount].nHier   = nHierarchy;
     620                 :         84 :                                         pColFields[nColFieldCount].nLevel  = nLev;
     621                 :         84 :                                         pColFields[nColFieldCount].nDimPos = nDimPos;
     622 [ +  - ][ +  - ]:         84 :                                         pColFields[nColFieldCount].aResult = xLevRes->getResults();
         [ +  - ][ +  - ]
     623                 :         84 :                                         pColFields[nColFieldCount].maName  = aName;
     624                 :         84 :                                         pColFields[nColFieldCount].maCaption= aCaption;
     625                 :         84 :                                         pColFields[nColFieldCount].mbHasHiddenMember = bHasHiddenMember;
     626                 :         84 :                                         pColFields[nColFieldCount].mbDataLayout = bIsDataLayout;
     627 [ +  - ][ +  - ]:         84 :                                         if (!lcl_MemberEmpty(pColFields[nColFieldCount].aResult))
     628                 :         84 :                                             ++nColFieldCount;
     629                 :         84 :                                         break;
     630                 :            :                                     case sheet::DataPilotFieldOrientation_ROW:
     631                 :        216 :                                         pRowFields[nRowFieldCount].nDim    = nDim;
     632                 :        216 :                                         pRowFields[nRowFieldCount].nHier   = nHierarchy;
     633                 :        216 :                                         pRowFields[nRowFieldCount].nLevel  = nLev;
     634                 :        216 :                                         pRowFields[nRowFieldCount].nDimPos = nDimPos;
     635 [ +  - ][ +  - ]:        216 :                                         pRowFields[nRowFieldCount].aResult = xLevRes->getResults();
         [ +  - ][ +  - ]
     636                 :        216 :                                         pRowFields[nRowFieldCount].maName  = aName;
     637                 :        216 :                                         pRowFields[nRowFieldCount].maCaption= aCaption;
     638                 :        216 :                                         pRowFields[nRowFieldCount].mbHasHiddenMember = bHasHiddenMember;
     639                 :        216 :                                         pRowFields[nRowFieldCount].mbDataLayout = bIsDataLayout;
     640 [ +  + ][ +  - ]:        216 :                                         if (!lcl_MemberEmpty(pRowFields[nRowFieldCount].aResult))
     641                 :            :                                         {
     642                 :        147 :                                             ++nRowFieldCount;
     643                 :        147 :                                             bRowFieldHasMember = true;
     644                 :            :                                         }
     645                 :        216 :                                         break;
     646                 :            :                                     case sheet::DataPilotFieldOrientation_PAGE:
     647                 :         38 :                                         pPageFields[nPageFieldCount].nDim    = nDim;
     648                 :         38 :                                         pPageFields[nPageFieldCount].nHier   = nHierarchy;
     649                 :         38 :                                         pPageFields[nPageFieldCount].nLevel  = nLev;
     650                 :         38 :                                         pPageFields[nPageFieldCount].nDimPos = nDimPos;
     651 [ +  - ][ +  - ]:         38 :                                         pPageFields[nPageFieldCount].aResult = lcl_GetSelectedPageAsResult(xDimProp);
                 [ +  - ]
     652                 :         38 :                                         pPageFields[nPageFieldCount].maName  = aName;
     653                 :         38 :                                         pPageFields[nPageFieldCount].maCaption= aCaption;
     654                 :         38 :                                         pPageFields[nPageFieldCount].mbHasHiddenMember = bHasHiddenMember;
     655                 :            :                                         // no check on results for page fields
     656                 :         38 :                                         ++nPageFieldCount;
     657                 :         38 :                                         break;
     658                 :            :                                     default:
     659                 :            :                                     {
     660                 :            :                                         // added to avoid warnings
     661                 :            :                                     }
     662                 :            :                                 }
     663                 :            : 
     664                 :            :                                 // get number formats from data dimensions
     665         [ +  + ]:        478 :                                 if ( bIsDataLayout )
     666                 :            :                                 {
     667         [ +  + ]:         84 :                                     if (bRowFieldHasMember)
     668                 :         12 :                                         mbHasDataLayout = true;
     669                 :            : 
     670                 :            :                                     OSL_ENSURE( nLevCount == 1, "data layout: multiple levels?" );
     671         [ +  + ]:         84 :                                     if ( eDimOrient == sheet::DataPilotFieldOrientation_COLUMN )
     672         [ +  - ]:          3 :                                         lcl_FillNumberFormats( pColNumFmt, nColFmtCount, xLevRes, xDims );
     673         [ +  - ]:         81 :                                     else if ( eDimOrient == sheet::DataPilotFieldOrientation_ROW )
     674         [ +  - ]:         81 :                                         lcl_FillNumberFormats( pRowNumFmt, nRowFmtCount, xLevRes, xDims );
     675                 :        478 :                                 }
     676                 :            :                             }
     677                 :        956 :                         }
     678                 :        478 :                     }
     679                 :            :                 }
     680         [ +  + ]:        236 :                 else if ( bIsDataLayout )
     681                 :            :                 {
     682                 :            :                     // data layout dimension is hidden (allowed if there is only one data dimension)
     683                 :            :                     // -> use the number format from the first data dimension for all results
     684                 :            : 
     685         [ +  - ]:         56 :                     nSingleNumFmt = lcl_GetFirstNumberFormat( xDims );
     686                 :            :                 }
     687                 :            :             }
     688                 :        714 :         }
     689         [ +  - ]:        140 :         lcl_SortFields( pColFields, nColFieldCount );
     690         [ +  - ]:        140 :         lcl_SortFields( pRowFields, nRowFieldCount );
     691         [ +  - ]:        140 :         lcl_SortFields( pPageFields, nPageFieldCount );
     692                 :            : 
     693                 :            :         //  get data results:
     694                 :            : 
     695                 :            :         try
     696                 :            :         {
     697 [ +  - ][ +  - ]:        140 :             aData = xResult->getResults();
         [ +  - ][ +  - ]
                 [ #  # ]
     698                 :            :         }
     699         [ #  # ]:          0 :         catch (uno::RuntimeException&)
     700                 :            :         {
     701                 :          0 :             bResultsError = true;
     702                 :        140 :         }
     703                 :            :     }
     704                 :            : 
     705                 :            :     // get "DataDescription" property (may be missing in external sources)
     706                 :            : 
     707         [ +  - ]:        140 :     uno::Reference<beans::XPropertySet> xSrcProp( xSource, uno::UNO_QUERY );
     708         [ +  - ]:        140 :     if ( xSrcProp.is() )
     709                 :            :     {
     710                 :            :         try
     711                 :            :         {
     712         [ +  - ]:        140 :             uno::Any aAny = xSrcProp->getPropertyValue(
     713 [ +  - ][ #  # ]:        140 :                     rtl::OUString(SC_UNO_DP_DATADESC) );
     714                 :        140 :             rtl::OUString aUStr;
     715                 :        140 :             aAny >>= aUStr;
     716                 :        140 :             aDataDescription = aUStr;
     717                 :            :         }
     718         [ #  # ]:          0 :         catch(uno::Exception&)
     719                 :            :         {
     720                 :            :         }
     721                 :        140 :     }
     722                 :        140 : }
     723                 :            : 
     724         [ +  - ]:        140 : ScDPOutput::~ScDPOutput()
     725                 :            : {
     726 [ +  - ][ +  + ]:      35980 :     delete[] pColFields;
                 [ +  - ]
     727 [ +  - ][ +  + ]:      35980 :     delete[] pRowFields;
                 [ +  - ]
     728 [ +  - ][ +  + ]:      35980 :     delete[] pPageFields;
                 [ +  - ]
     729                 :            : 
     730         [ -  + ]:        140 :     delete[] pColNumFmt;
     731         [ -  + ]:        140 :     delete[] pRowNumFmt;
     732                 :        140 : }
     733                 :            : 
     734                 :        210 : void ScDPOutput::SetPosition( const ScAddress& rPos )
     735                 :            : {
     736                 :        210 :     aStartPos = rPos;
     737                 :        210 :     bSizesValid = bSizeOverflow = false;
     738                 :        210 : }
     739                 :            : 
     740                 :       2439 : void ScDPOutput::DataCell( SCCOL nCol, SCROW nRow, SCTAB nTab, const sheet::DataResult& rData )
     741                 :            : {
     742                 :       2439 :     long nFlags = rData.Flags;
     743         [ -  + ]:       2439 :     if ( nFlags & sheet::DataResultFlags::ERROR )
     744                 :            :     {
     745                 :          0 :         pDoc->SetError( nCol, nRow, nTab, errNoValue );
     746                 :            :     }
     747         [ +  + ]:       2439 :     else if ( nFlags & sheet::DataResultFlags::HASDATA )
     748                 :            :     {
     749                 :       1244 :         pDoc->SetValue( nCol, nRow, nTab, rData.Value );
     750                 :            : 
     751                 :            :         //  use number formats from source
     752                 :            : 
     753                 :            :         OSL_ENSURE( bSizesValid, "DataCell: !bSizesValid" );
     754                 :       1244 :         sal_uInt32 nFormat = 0;
     755         [ -  + ]:       1244 :         if ( pColNumFmt )
     756                 :            :         {
     757         [ #  # ]:          0 :             if ( nCol >= nDataStartCol )
     758                 :            :             {
     759                 :          0 :                 long nIndex = nCol - nDataStartCol;
     760         [ #  # ]:          0 :                 if ( nIndex < nColFmtCount )
     761                 :          0 :                     nFormat = pColNumFmt[nIndex];
     762                 :            :             }
     763                 :            :         }
     764         [ -  + ]:       1244 :         else if ( pRowNumFmt )
     765                 :            :         {
     766         [ #  # ]:          0 :             if ( nRow >= nDataStartRow )
     767                 :            :             {
     768                 :          0 :                 long nIndex = nRow - nDataStartRow;
     769         [ #  # ]:          0 :                 if ( nIndex < nRowFmtCount )
     770                 :          0 :                     nFormat = pRowNumFmt[nIndex];
     771                 :            :             }
     772                 :            :         }
     773         [ -  + ]:       1244 :         else if ( nSingleNumFmt != 0 )
     774                 :          0 :             nFormat = nSingleNumFmt;        // single format is used everywhere
     775         [ -  + ]:       1244 :         if ( nFormat != 0 )
     776         [ #  # ]:          0 :             pDoc->ApplyAttr( nCol, nRow, nTab, SfxUInt32Item( ATTR_VALUE_FORMAT, nFormat ) );
     777                 :            :     }
     778                 :            :     //  SubTotal formatting is controlled by headers
     779                 :       2439 : }
     780                 :            : 
     781                 :       1266 : void ScDPOutput::HeaderCell( SCCOL nCol, SCROW nRow, SCTAB nTab,
     782                 :            :                              const sheet::MemberResult& rData, bool bColHeader, long nLevel )
     783                 :            : {
     784                 :       1266 :     long nFlags = rData.Flags;
     785                 :            : 
     786         [ +  + ]:       1266 :     if ( nFlags & sheet::MemberResultFlags::HASMEMBER )
     787                 :            :     {
     788                 :       1159 :         bool bNumeric = (nFlags & sheet::MemberResultFlags::NUMERIC) != 0;
     789         [ +  - ]:       1159 :         ScSetStringParam aParam;
     790         [ +  + ]:       1159 :         if (bNumeric)
     791                 :            :         {
     792                 :        551 :             aParam.mbDetectNumberFormat = true;
     793                 :        551 :             aParam.meSetTextNumFormat = ScSetStringParam::Never;
     794                 :        551 :             aParam.mbHandleApostrophe = true;
     795                 :            :         }
     796                 :            :         else
     797                 :            :         {
     798                 :        608 :             aParam.mbDetectNumberFormat = false;
     799                 :        608 :             aParam.meSetTextNumFormat = ScSetStringParam::Always;
     800                 :        608 :             aParam.mbHandleApostrophe = false;
     801                 :            :         }
     802         [ +  - ]:       1159 :         pDoc->SetString(nCol, nRow, nTab, rData.Caption, &aParam);
     803                 :            :     }
     804                 :            : 
     805         [ +  + ]:       1266 :     if ( nFlags & sheet::MemberResultFlags::SUBTOTAL )
     806                 :            :     {
     807                 :            :         ScDPOutputImpl outputimp( pDoc, nTab,
     808                 :            :             nTabStartCol, nTabStartRow, nMemberStartCol, nMemberStartRow,
     809         [ +  - ]:        186 :             nDataStartCol, nDataStartRow, nTabEndCol, nTabEndRow );
     810                 :            :         //! limit frames to horizontal or vertical?
     811         [ +  + ]:        186 :         if (bColHeader)
     812                 :            :         {
     813         [ +  - ]:         74 :             outputimp.OutputBlockFrame( nCol,nMemberStartRow+(SCROW)nLevel, nCol,nDataStartRow-1 );
     814                 :            : 
     815                 :            :             lcl_SetStyleById( pDoc,nTab, nCol,nMemberStartRow+(SCROW)nLevel, nCol,nDataStartRow-1,
     816         [ +  - ]:         74 :                                     STR_PIVOT_STYLE_TITLE );
     817                 :            :             lcl_SetStyleById( pDoc,nTab, nCol,nDataStartRow, nCol,nTabEndRow,
     818         [ +  - ]:         74 :                                     STR_PIVOT_STYLE_RESULT );
     819                 :            :         }
     820                 :            :         else
     821                 :            :         {
     822         [ +  - ]:        112 :             outputimp.OutputBlockFrame( nMemberStartCol+(SCCOL)nLevel,nRow, nDataStartCol-1,nRow );
     823                 :            :             lcl_SetStyleById( pDoc,nTab, nMemberStartCol+(SCCOL)nLevel,nRow, nDataStartCol-1,nRow,
     824         [ +  - ]:        112 :                                     STR_PIVOT_STYLE_TITLE );
     825                 :            :             lcl_SetStyleById( pDoc,nTab, nDataStartCol,nRow, nTabEndCol,nRow,
     826         [ +  - ]:        112 :                                     STR_PIVOT_STYLE_RESULT );
     827                 :        186 :         }
     828                 :            :     }
     829                 :       1266 : }
     830                 :            : 
     831                 :        269 : void ScDPOutput::FieldCell(
     832                 :            :     SCCOL nCol, SCROW nRow, SCTAB nTab, const ScDPOutLevelData& rData, bool bInTable)
     833                 :            : {
     834                 :            :     // Avoid unwanted automatic format detection.
     835         [ +  - ]:        269 :     ScSetStringParam aParam;
     836                 :        269 :     aParam.mbDetectNumberFormat = false;
     837                 :        269 :     aParam.meSetTextNumFormat = ScSetStringParam::Always;
     838                 :        269 :     aParam.mbHandleApostrophe = false;
     839         [ +  - ]:        269 :     pDoc->SetString(nCol, nRow, nTab, rData.maCaption, &aParam);
     840                 :            : 
     841         [ +  + ]:        269 :     if (bInTable)
     842         [ +  - ]:        231 :         lcl_SetFrame( pDoc,nTab, nCol,nRow, nCol,nRow, 20 );
     843                 :            : 
     844                 :            :     //  Button
     845                 :        269 :     sal_uInt16 nMergeFlag = SC_MF_BUTTON;
     846         [ +  + ]:        269 :     if (!rData.mbDataLayout)
     847                 :        254 :         nMergeFlag |= SC_MF_BUTTON_POPUP;
     848         [ +  + ]:        269 :     if (rData.mbHasHiddenMember)
     849                 :          3 :         nMergeFlag |= SC_MF_HIDDEN_MEMBER;
     850         [ +  - ]:        269 :     pDoc->ApplyFlagsTab(nCol, nRow, nCol, nRow, nTab, nMergeFlag);
     851                 :            : 
     852         [ +  - ]:        269 :     lcl_SetStyleById( pDoc,nTab, nCol,nRow, nCol,nRow, STR_PIVOT_STYLE_FIELDNAME );
     853                 :        269 : }
     854                 :            : 
     855                 :         83 : void lcl_DoFilterButton( ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab )
     856                 :            : {
     857         [ +  - ]:         83 :     pDoc->SetString( nCol, nRow, nTab, ScGlobal::GetRscString(STR_CELL_FILTER) );
     858                 :         83 :     pDoc->ApplyFlagsTab(nCol, nRow, nCol, nRow, nTab, SC_MF_BUTTON);
     859                 :         83 : }
     860                 :            : 
     861                 :       1816 : void ScDPOutput::CalcSizes()
     862                 :            : {
     863         [ +  + ]:       1816 :     if (!bSizesValid)
     864                 :            :     {
     865                 :            :         //  get column size of data from first row
     866                 :            :         //! allow different sizes (and clear following areas) ???
     867                 :            : 
     868                 :        289 :         nRowCount = aData.getLength();
     869                 :        289 :         const uno::Sequence<sheet::DataResult>* pRowAry = aData.getConstArray();
     870         [ +  + ]:        289 :         nColCount = nRowCount ? ( pRowAry[0].getLength() ) : 0;
     871                 :            : 
     872                 :        289 :         nHeaderSize = 1;
     873 [ -  + ][ #  # ]:        289 :         if (GetHeaderLayout() && nColFieldCount == 0)
                 [ -  + ]
     874                 :            :             // Insert an extra header row only when there is no column field.
     875                 :          0 :             nHeaderSize = 2;
     876                 :            : 
     877                 :            :         //  calculate output positions and sizes
     878                 :            : 
     879                 :        289 :         long nPageSize = 0;     //! use page fields!
     880 [ +  + ][ -  + ]:        289 :         if ( bDoFilter || nPageFieldCount )
     881                 :            :         {
     882                 :        181 :             nPageSize += nPageFieldCount + 1;   // plus one empty row
     883         [ +  - ]:        181 :             if ( bDoFilter )
     884                 :        181 :                 ++nPageSize;        //  filter button above the page fields
     885                 :            :         }
     886                 :            : 
     887   [ +  -  -  + ]:        578 :         if ( aStartPos.Col() + nRowFieldCount + nColCount - 1 > MAXCOL ||
                 [ -  + ]
     888                 :        289 :              aStartPos.Row() + nPageSize + nHeaderSize + nColFieldCount + nRowCount > MAXROW )
     889                 :            :         {
     890                 :          0 :             bSizeOverflow = true;
     891                 :            :         }
     892                 :            : 
     893                 :        289 :         nTabStartCol = aStartPos.Col();
     894                 :        289 :         nTabStartRow = aStartPos.Row() + (SCROW)nPageSize;          // below page fields
     895                 :        289 :         nMemberStartCol = nTabStartCol;
     896                 :        289 :         nMemberStartRow = nTabStartRow + (SCROW) nHeaderSize;
     897                 :        289 :         nDataStartCol = nMemberStartCol + (SCCOL)nRowFieldCount;
     898                 :        289 :         nDataStartRow = nMemberStartRow + (SCROW)nColFieldCount;
     899         [ +  + ]:        289 :         if ( nColCount > 0 )
     900                 :        283 :             nTabEndCol = nDataStartCol + (SCCOL)nColCount - 1;
     901                 :            :         else
     902                 :          6 :             nTabEndCol = nDataStartCol;     // single column will remain empty
     903                 :            :         // if page fields are involved, include the page selection cells
     904 [ +  + ][ -  + ]:        289 :         if ( nPageFieldCount > 0 && nTabEndCol < nTabStartCol + 1 )
     905                 :          0 :             nTabEndCol = nTabStartCol + 1;
     906         [ +  + ]:        289 :         if ( nRowCount > 0 )
     907                 :        283 :             nTabEndRow = nDataStartRow + (SCROW)nRowCount - 1;
     908                 :            :         else
     909                 :          6 :             nTabEndRow = nDataStartRow;     // single row will remain empty
     910                 :        289 :         bSizesValid = true;
     911                 :            :     }
     912                 :       1816 : }
     913                 :            : 
     914                 :        388 : sal_Int32 ScDPOutput::GetPositionType(const ScAddress& rPos)
     915                 :            : {
     916                 :            :     using namespace ::com::sun::star::sheet;
     917                 :            : 
     918                 :        388 :     SCCOL nCol = rPos.Col();
     919                 :        388 :     SCROW nRow = rPos.Row();
     920                 :        388 :     SCTAB nTab = rPos.Tab();
     921         [ -  + ]:        388 :     if ( nTab != aStartPos.Tab() )
     922                 :          0 :         return DataPilotTablePositionType::NOT_IN_TABLE;
     923                 :            : 
     924                 :        388 :     CalcSizes();
     925                 :            : 
     926                 :            :     // Make sure the cursor is within the table.
     927 [ +  - ][ +  - ]:        388 :     if (nCol < nTabStartCol || nRow < nTabStartRow || nCol > nTabEndCol || nRow > nTabEndRow)
         [ -  + ][ +  - ]
     928                 :          0 :         return DataPilotTablePositionType::NOT_IN_TABLE;
     929                 :            : 
     930                 :            :     // test for result data area.
     931 [ +  + ][ +  - ]:        388 :     if (nCol >= nDataStartCol && nCol <= nTabEndCol && nRow >= nDataStartRow && nRow <= nTabEndRow)
         [ +  + ][ +  - ]
     932                 :        280 :         return DataPilotTablePositionType::RESULT;
     933                 :            : 
     934 [ +  - ][ +  + ]:        108 :     bool bInColHeader = (nRow >= nTabStartRow && nRow < nDataStartRow);
     935 [ +  - ][ +  + ]:        108 :     bool bInRowHeader = (nCol >= nTabStartCol && nCol < nDataStartCol);
     936                 :            : 
     937 [ +  + ][ +  + ]:        108 :     if (bInColHeader && bInRowHeader)
     938                 :            :         // probably in that ugly little box at the upper-left corner of the table.
     939                 :         18 :         return DataPilotTablePositionType::OTHER;
     940                 :            : 
     941         [ +  + ]:         90 :     if (bInColHeader)
     942                 :            :     {
     943         [ +  + ]:         54 :         if (nRow == nTabStartRow)
     944                 :            :             // first row in the column header area is always used for column
     945                 :            :             // field buttons.
     946                 :         18 :             return DataPilotTablePositionType::OTHER;
     947                 :            : 
     948                 :         36 :         return DataPilotTablePositionType::COLUMN_HEADER;
     949                 :            :     }
     950                 :            : 
     951         [ +  - ]:         36 :     if (bInRowHeader)
     952                 :         36 :         return DataPilotTablePositionType::ROW_HEADER;
     953                 :            : 
     954                 :        388 :     return DataPilotTablePositionType::OTHER;
     955                 :            : }
     956                 :            : 
     957                 :        140 : void ScDPOutput::Output()
     958                 :            : {
     959                 :            :     long nField;
     960                 :        140 :     SCTAB nTab = aStartPos.Tab();
     961                 :        140 :     const uno::Sequence<sheet::DataResult>* pRowAry = aData.getConstArray();
     962                 :            : 
     963                 :            :     //  calculate output positions and sizes
     964                 :            : 
     965         [ +  - ]:        140 :     CalcSizes();
     966 [ +  - ][ +  - ]:        140 :     if ( bSizeOverflow || bResultsError )   // does output area exceed sheet limits?
     967                 :        140 :         return;                             // nothing
     968                 :            : 
     969                 :            :     //  clear whole (new) output area
     970                 :            :     //! when modifying table, clear old area
     971                 :            :     //! include IDF_OBJECTS ???
     972         [ +  - ]:        140 :     pDoc->DeleteAreaTab( aStartPos.Col(), aStartPos.Row(), nTabEndCol, nTabEndRow, nTab, IDF_ALL );
     973                 :            : 
     974         [ +  + ]:        140 :     if ( bDoFilter )
     975         [ +  - ]:         83 :         lcl_DoFilterButton( pDoc, aStartPos.Col(), aStartPos.Row(), nTab );
     976                 :            : 
     977                 :            :     //  output data results:
     978                 :            : 
     979         [ +  + ]:        796 :     for (long nRow=0; nRow<nRowCount; nRow++)
     980                 :            :     {
     981                 :        656 :         SCROW nRowPos = nDataStartRow + (SCROW)nRow;                    //! check for overflow
     982                 :        656 :         const sheet::DataResult* pColAry = pRowAry[nRow].getConstArray();
     983                 :        656 :         long nThisColCount = pRowAry[nRow].getLength();
     984                 :            :         OSL_ENSURE( nThisColCount == nColCount, "count mismatch" );     //! ???
     985         [ +  + ]:       3095 :         for (long nCol=0; nCol<nThisColCount; nCol++)
     986                 :            :         {
     987                 :       2439 :             SCCOL nColPos = nDataStartCol + (SCCOL)nCol;                //! check for overflow
     988         [ +  - ]:       2439 :             DataCell( nColPos, nRowPos, nTab, pColAry[nCol] );
     989                 :            :         }
     990                 :            :     }
     991                 :            :     //  output page fields:
     992                 :            : 
     993         [ +  + ]:        178 :     for (nField=0; nField<nPageFieldCount; nField++)
     994                 :            :     {
     995                 :         38 :         SCCOL nHdrCol = aStartPos.Col();
     996         [ +  - ]:         38 :         SCROW nHdrRow = aStartPos.Row() + nField + ( bDoFilter ? 1 : 0 );
     997                 :            :         // draw without frame for consistency with filter button:
     998         [ +  - ]:         38 :         FieldCell(nHdrCol, nHdrRow, nTab, pPageFields[nField], false);
     999                 :         38 :         SCCOL nFldCol = nHdrCol + 1;
    1000                 :            : 
    1001                 :         38 :         rtl::OUString aPageValue;
    1002         [ +  + ]:         38 :         if ( pPageFields[nField].aResult.getLength() == 1 )
    1003         [ +  - ]:          6 :             aPageValue = pPageFields[nField].aResult[0].Caption;
    1004                 :            :         else
    1005 [ +  - ][ +  - ]:         32 :             aPageValue = SC_RESSTR(SCSTR_ALL);        //! separate string?
    1006                 :            : 
    1007         [ +  - ]:         38 :         pDoc->SetString( nFldCol, nHdrRow, nTab, aPageValue );
    1008                 :            : 
    1009         [ +  - ]:         38 :         lcl_SetFrame( pDoc,nTab, nFldCol,nHdrRow, nFldCol,nHdrRow, 20 );
    1010 [ +  - ][ +  - ]:         38 :         pDoc->ApplyAttr( nFldCol, nHdrRow, nTab, ScMergeFlagAttr(SC_MF_AUTO) );
                 [ +  - ]
    1011                 :            :         //! which style?
    1012                 :         38 :     }
    1013                 :            : 
    1014                 :            :     //  data description
    1015                 :            :     //  (may get overwritten by first row field)
    1016                 :            : 
    1017                 :        140 :     if (aDataDescription.isEmpty())
    1018                 :            :     {
    1019                 :            :         //! use default string ("result") ?
    1020                 :            :     }
    1021         [ +  - ]:        140 :     pDoc->SetString(nTabStartCol, nTabStartRow, nTab, aDataDescription);
    1022                 :            : 
    1023                 :            :     //  set STR_PIVOT_STYLE_INNER for whole data area (subtotals are overwritten)
    1024                 :            : 
    1025         [ +  - ]:        140 :     if ( nDataStartRow > nTabStartRow )
    1026                 :            :         lcl_SetStyleById( pDoc, nTab, nTabStartCol, nTabStartRow, nTabEndCol, nDataStartRow-1,
    1027         [ +  - ]:        140 :                             STR_PIVOT_STYLE_TOP );
    1028                 :            :     lcl_SetStyleById( pDoc, nTab, nDataStartCol, nDataStartRow, nTabEndCol, nTabEndRow,
    1029         [ +  - ]:        140 :                         STR_PIVOT_STYLE_INNER );
    1030                 :            : 
    1031                 :            :     //  output column headers:
    1032                 :            :     ScDPOutputImpl outputimp( pDoc, nTab,
    1033                 :            :         nTabStartCol, nTabStartRow, nMemberStartCol, nMemberStartRow,
    1034         [ +  - ]:        140 :         nDataStartCol, nDataStartRow, nTabEndCol, nTabEndRow );
    1035         [ +  + ]:        224 :     for (nField=0; nField<nColFieldCount; nField++)
    1036                 :            :     {
    1037                 :         84 :         SCCOL nHdrCol = nDataStartCol + (SCCOL)nField;              //! check for overflow
    1038         [ +  - ]:         84 :         FieldCell(nHdrCol, nTabStartRow, nTab, pColFields[nField], true);
    1039                 :            : 
    1040                 :         84 :         SCROW nRowPos = nMemberStartRow + (SCROW)nField;                //! check for overflow
    1041         [ +  - ]:         84 :         const uno::Sequence<sheet::MemberResult> rSequence = pColFields[nField].aResult;
    1042                 :         84 :         const sheet::MemberResult* pArray = rSequence.getConstArray();
    1043                 :         84 :         long nThisColCount = rSequence.getLength();
    1044                 :            :         OSL_ENSURE( nThisColCount == nColCount, "count mismatch" );     //! ???
    1045         [ +  + ]:        530 :         for (long nCol=0; nCol<nThisColCount; nCol++)
    1046                 :            :         {
    1047                 :        446 :             SCCOL nColPos = nDataStartCol + (SCCOL)nCol;                //! check for overflow
    1048         [ +  - ]:        446 :             HeaderCell( nColPos, nRowPos, nTab, pArray[nCol], true, nField );
    1049 [ +  + ][ +  + ]:        446 :             if ( ( pArray[nCol].Flags & sheet::MemberResultFlags::HASMEMBER ) &&
    1050                 :        431 :                 !( pArray[nCol].Flags & sheet::MemberResultFlags::SUBTOTAL ) )
    1051                 :            :             {
    1052                 :        357 :                 long nEnd = nCol;
    1053 [ +  + ][ +  + ]:        365 :                 while ( nEnd+1 < nThisColCount && ( pArray[nEnd+1].Flags & sheet::MemberResultFlags::CONTINUE ) )
                 [ +  + ]
    1054                 :          8 :                     ++nEnd;
    1055                 :        357 :                 SCCOL nEndColPos = nDataStartCol + (SCCOL)nEnd;     //! check for overflow
    1056         [ +  + ]:        357 :                 if ( nField+1 < nColFieldCount )
    1057                 :            :                 {
    1058         [ +  - ]:         27 :                     if ( nField == nColFieldCount - 2 )
    1059                 :            :                     {
    1060         [ +  - ]:         27 :                         outputimp.AddCol( nColPos );
    1061         [ -  + ]:         27 :                         if ( nColPos + 1 == nEndColPos  )
    1062         [ #  # ]:          0 :                             outputimp.OutputBlockFrame( nColPos,nRowPos, nEndColPos,nRowPos+1, true );
    1063                 :            :                     }
    1064                 :            :                     else
    1065         [ #  # ]:          0 :                         outputimp.OutputBlockFrame( nColPos,nRowPos, nEndColPos,nRowPos );
    1066                 :            : 
    1067         [ +  - ]:         27 :                     lcl_SetStyleById( pDoc, nTab, nColPos,nRowPos, nEndColPos,nDataStartRow-1, STR_PIVOT_STYLE_CATEGORY );
    1068                 :            :                 }
    1069                 :            :                 else
    1070         [ +  - ]:        357 :                     lcl_SetStyleById( pDoc, nTab, nColPos,nRowPos, nColPos,nDataStartRow-1, STR_PIVOT_STYLE_CATEGORY );
    1071                 :            :             }
    1072         [ +  + ]:         89 :             else if (  pArray[nCol].Flags & sheet::MemberResultFlags::SUBTOTAL )
    1073         [ +  - ]:         74 :                 outputimp.AddCol( nColPos );
    1074                 :            :         }
    1075 [ +  + ][ +  + ]:         84 :         if ( nField== 0 && nColFieldCount == 1 )
    1076         [ +  - ]:         70 :             outputimp.OutputBlockFrame( nDataStartCol,nTabStartRow, nTabEndCol,nRowPos-1 );
    1077         [ +  - ]:         84 :     }
    1078                 :            : 
    1079                 :            :     //  output row headers:
    1080         [ +  - ]:        140 :     std::vector<bool> vbSetBorder;
    1081         [ +  - ]:        140 :     vbSetBorder.resize( nTabEndRow - nDataStartRow + 1, false );
    1082         [ +  + ]:        287 :     for (nField=0; nField<nRowFieldCount; nField++)
    1083                 :            :     {
    1084                 :        147 :         SCCOL nHdrCol = nTabStartCol + (SCCOL)nField;                   //! check for overflow
    1085                 :        147 :         SCROW nHdrRow = nDataStartRow - 1;
    1086         [ +  - ]:        147 :         FieldCell(nHdrCol, nHdrRow, nTab, pRowFields[nField], true);
    1087                 :            : 
    1088                 :        147 :         SCCOL nColPos = nMemberStartCol + (SCCOL)nField;                //! check for overflow
    1089         [ +  - ]:        147 :         const uno::Sequence<sheet::MemberResult> rSequence = pRowFields[nField].aResult;
    1090                 :        147 :         const sheet::MemberResult* pArray = rSequence.getConstArray();
    1091                 :        147 :         long nThisRowCount = rSequence.getLength();
    1092                 :            :         OSL_ENSURE( nThisRowCount == nRowCount, "count mismatch" );     //! ???
    1093         [ +  + ]:        967 :         for (long nRow=0; nRow<nThisRowCount; nRow++)
    1094                 :            :         {
    1095                 :        820 :             SCROW nRowPos = nDataStartRow + (SCROW)nRow;                //! check for overflow
    1096         [ +  - ]:        820 :             HeaderCell( nColPos, nRowPos, nTab, pArray[nRow], false, nField );
    1097 [ +  + ][ +  + ]:        820 :             if ( ( pArray[nRow].Flags & sheet::MemberResultFlags::HASMEMBER ) &&
    1098                 :        728 :                 !( pArray[nRow].Flags & sheet::MemberResultFlags::SUBTOTAL ) )
    1099                 :            :             {
    1100         [ +  + ]:        616 :                 if ( nField+1 < nRowFieldCount )
    1101                 :            :                 {
    1102                 :         91 :                     long nEnd = nRow;
    1103 [ +  - ][ +  + ]:        151 :                     while ( nEnd+1 < nThisRowCount && ( pArray[nEnd+1].Flags & sheet::MemberResultFlags::CONTINUE ) )
                 [ +  + ]
    1104                 :         60 :                         ++nEnd;
    1105                 :         91 :                     SCROW nEndRowPos = nDataStartRow + (SCROW)nEnd;     //! check for overflow
    1106         [ +  - ]:         91 :                     outputimp.AddRow( nRowPos );
    1107 [ +  - ][ +  + ]:         91 :                     if ( vbSetBorder[ nRow ] == false )
    1108                 :            :                     {
    1109         [ +  - ]:         82 :                         outputimp.OutputBlockFrame( nColPos, nRowPos, nTabEndCol, nEndRowPos );
    1110         [ +  - ]:         82 :                         vbSetBorder[ nRow ]  = true;
    1111                 :            :                     }
    1112         [ +  - ]:         91 :                     outputimp.OutputBlockFrame( nColPos, nRowPos, nColPos, nEndRowPos );
    1113                 :            : 
    1114         [ +  + ]:         91 :                     if ( nField == nRowFieldCount - 2 )
    1115         [ +  - ]:         82 :                         outputimp.OutputBlockFrame( nColPos+1, nRowPos, nColPos+1, nEndRowPos );
    1116                 :            : 
    1117         [ +  - ]:         91 :                     lcl_SetStyleById( pDoc, nTab, nColPos,nRowPos, nDataStartCol-1,nEndRowPos, STR_PIVOT_STYLE_CATEGORY );
    1118                 :            :                 }
    1119                 :            :                 else
    1120         [ +  - ]:        616 :                     lcl_SetStyleById( pDoc, nTab, nColPos,nRowPos, nDataStartCol-1,nRowPos, STR_PIVOT_STYLE_CATEGORY );
    1121                 :            :             }
    1122         [ +  + ]:        204 :             else if (  pArray[nRow].Flags & sheet::MemberResultFlags::SUBTOTAL )
    1123         [ +  - ]:        112 :                 outputimp.AddRow( nRowPos );
    1124                 :            :         }
    1125         [ +  - ]:        147 :     }
    1126                 :            : 
    1127         [ +  - ]:        140 :     outputimp.OutputDataArea();
    1128                 :            : }
    1129                 :            : 
    1130                 :        301 : ScRange ScDPOutput::GetOutputRange( sal_Int32 nRegionType )
    1131                 :            : {
    1132                 :            :     using namespace ::com::sun::star::sheet;
    1133                 :            : 
    1134                 :        301 :     CalcSizes();
    1135                 :            : 
    1136                 :        301 :     SCTAB nTab = aStartPos.Tab();
    1137      [ +  +  + ]:        301 :     switch (nRegionType)
    1138                 :            :     {
    1139                 :            :         case DataPilotOutputRangeType::RESULT:
    1140                 :          9 :             return ScRange(nDataStartCol, nDataStartRow, nTab, nTabEndCol, nTabEndRow, nTab);
    1141                 :            :         case DataPilotOutputRangeType::TABLE:
    1142                 :          9 :             return ScRange(aStartPos.Col(), nTabStartRow, nTab, nTabEndCol, nTabEndRow, nTab);
    1143                 :            :         default:
    1144                 :            :             OSL_ENSURE(nRegionType == DataPilotOutputRangeType::WHOLE, "ScDPOutput::GetOutputRange: unknown region type");
    1145                 :        283 :         break;
    1146                 :            :     }
    1147                 :        301 :     return ScRange(aStartPos.Col(), aStartPos.Row(), nTab, nTabEndCol, nTabEndRow, nTab);
    1148                 :            : }
    1149                 :            : 
    1150                 :        161 : bool ScDPOutput::HasError()
    1151                 :            : {
    1152                 :        161 :     CalcSizes();
    1153                 :            : 
    1154 [ -  + ][ +  - ]:        161 :     return bSizeOverflow || bResultsError;
    1155                 :            : }
    1156                 :            : 
    1157                 :        140 : long ScDPOutput::GetHeaderRows()
    1158                 :            : {
    1159         [ +  + ]:        140 :     return nPageFieldCount + ( bDoFilter ? 1 : 0 );
    1160                 :            : }
    1161                 :            : 
    1162                 :          0 : void ScDPOutput::GetMemberResultNames(ScDPUniqueStringSet& rNames, long nDimension)
    1163                 :            : {
    1164                 :            :     //  Return the list of all member names in a dimension's MemberResults.
    1165                 :            :     //  Only the dimension has to be compared because this is only used with table data,
    1166                 :            :     //  where each dimension occurs only once.
    1167                 :            : 
    1168         [ #  # ]:          0 :     uno::Sequence<sheet::MemberResult> aMemberResults;
    1169                 :          0 :     bool bFound = false;
    1170                 :            :     long nField;
    1171                 :            : 
    1172                 :            :     // look in column fields
    1173                 :            : 
    1174 [ #  # ][ #  # ]:          0 :     for (nField=0; nField<nColFieldCount && !bFound; nField++)
                 [ #  # ]
    1175         [ #  # ]:          0 :         if ( pColFields[nField].nDim == nDimension )
    1176                 :            :         {
    1177         [ #  # ]:          0 :             aMemberResults = pColFields[nField].aResult;
    1178                 :          0 :             bFound = true;
    1179                 :            :         }
    1180                 :            : 
    1181                 :            :     // look in row fields
    1182                 :            : 
    1183 [ #  # ][ #  # ]:          0 :     for (nField=0; nField<nRowFieldCount && !bFound; nField++)
                 [ #  # ]
    1184         [ #  # ]:          0 :         if ( pRowFields[nField].nDim == nDimension )
    1185                 :            :         {
    1186         [ #  # ]:          0 :             aMemberResults = pRowFields[nField].aResult;
    1187                 :          0 :             bFound = true;
    1188                 :            :         }
    1189                 :            : 
    1190                 :            :     // collect the member names
    1191                 :            : 
    1192         [ #  # ]:          0 :     if ( bFound )
    1193                 :            :     {
    1194                 :          0 :         const sheet::MemberResult* pArray = aMemberResults.getConstArray();
    1195                 :          0 :         long nResultCount = aMemberResults.getLength();
    1196                 :            : 
    1197         [ #  # ]:          0 :         for (long nItem=0; nItem<nResultCount; nItem++)
    1198                 :            :         {
    1199         [ #  # ]:          0 :             if ( pArray[nItem].Flags & sheet::MemberResultFlags::HASMEMBER )
    1200         [ #  # ]:          0 :                 rNames.insert(pArray[nItem].Name);
    1201                 :            :         }
    1202         [ #  # ]:          0 :     }
    1203                 :          0 : }
    1204                 :            : 
    1205                 :        140 : void ScDPOutput::SetHeaderLayout(bool bUseGrid)
    1206                 :            : {
    1207                 :        140 :     mbHeaderLayout = bUseGrid;
    1208                 :        140 :     bSizesValid = false;
    1209                 :        140 : }
    1210                 :            : 
    1211                 :        289 : bool ScDPOutput::GetHeaderLayout() const
    1212                 :            : {
    1213                 :        289 :     return mbHeaderLayout;
    1214                 :            : }
    1215                 :            : 
    1216                 :            : namespace {
    1217                 :            : 
    1218                 :        438 : void lcl_GetTableVars( sal_Int32& rGrandTotalCols, sal_Int32& rGrandTotalRows, sal_Int32& rDataLayoutIndex,
    1219                 :            :                        std::vector<rtl::OUString>& rDataNames, std::vector<rtl::OUString>& rGivenNames,
    1220                 :            :                        sheet::DataPilotFieldOrientation& rDataOrient,
    1221                 :            :                        const uno::Reference<sheet::XDimensionsSupplier>& xSource )
    1222                 :            : {
    1223                 :        438 :     rDataLayoutIndex = -1;  // invalid
    1224                 :        438 :     rGrandTotalCols = 0;
    1225                 :        438 :     rGrandTotalRows = 0;
    1226                 :        438 :     rDataOrient = sheet::DataPilotFieldOrientation_HIDDEN;
    1227                 :            : 
    1228         [ +  - ]:        438 :     uno::Reference<beans::XPropertySet> xSrcProp( xSource, uno::UNO_QUERY );
    1229                 :            :     bool bColGrand = ScUnoHelpFunctions::GetBoolProperty(
    1230         [ +  - ]:        438 :         xSrcProp, rtl::OUString(SC_UNO_DP_COLGRAND));
    1231         [ +  - ]:        438 :     if ( bColGrand )
    1232                 :        438 :         rGrandTotalCols = 1;    // default if data layout not in columns
    1233                 :            : 
    1234                 :            :     bool bRowGrand = ScUnoHelpFunctions::GetBoolProperty(
    1235         [ +  - ]:        438 :         xSrcProp, rtl::OUString(SC_UNO_DP_ROWGRAND));
    1236         [ +  - ]:        438 :     if ( bRowGrand )
    1237                 :        438 :         rGrandTotalRows = 1;    // default if data layout not in rows
    1238                 :            : 
    1239         [ +  - ]:        438 :     if ( xSource.is() )
    1240                 :            :     {
    1241                 :            :         // find index and orientation of "data layout" dimension, count data dimensions
    1242                 :            : 
    1243                 :        438 :         sal_Int32 nDataCount = 0;
    1244                 :            : 
    1245 [ +  - ][ +  - ]:        438 :         uno::Reference<container::XIndexAccess> xDims = new ScNameToIndexAccess( xSource->getDimensions() );
         [ +  - ][ +  - ]
                 [ +  - ]
    1246 [ +  - ][ +  - ]:        438 :         long nDimCount = xDims->getCount();
    1247         [ +  + ]:       3066 :         for (long nDim=0; nDim<nDimCount; nDim++)
    1248                 :            :         {
    1249                 :            :             uno::Reference<uno::XInterface> xDim =
    1250 [ +  - ][ +  - ]:       2628 :                     ScUnoHelpFunctions::AnyToInterface( xDims->getByIndex(nDim) );
                 [ +  - ]
    1251         [ +  - ]:       2628 :             uno::Reference<beans::XPropertySet> xDimProp( xDim, uno::UNO_QUERY );
    1252         [ +  - ]:       2628 :             if ( xDimProp.is() )
    1253                 :            :             {
    1254                 :            :                 sheet::DataPilotFieldOrientation eDimOrient =
    1255                 :            :                     (sheet::DataPilotFieldOrientation) ScUnoHelpFunctions::GetEnumProperty(
    1256                 :            :                         xDimProp, rtl::OUString(SC_UNO_DP_ORIENTATION),
    1257         [ +  - ]:       2628 :                         sheet::DataPilotFieldOrientation_HIDDEN );
    1258         [ +  + ]:       2628 :                 if ( ScUnoHelpFunctions::GetBoolProperty( xDimProp,
    1259         [ +  - ]:       2628 :                                          rtl::OUString(SC_UNO_DP_ISDATALAYOUT) ) )
    1260                 :            :                 {
    1261                 :        438 :                     rDataLayoutIndex = nDim;
    1262                 :        438 :                     rDataOrient = eDimOrient;
    1263                 :            :                 }
    1264         [ +  + ]:       2628 :                 if ( eDimOrient == sheet::DataPilotFieldOrientation_DATA )
    1265                 :            :                 {
    1266                 :        438 :                     rtl::OUString aSourceName;
    1267                 :        438 :                     rtl::OUString aGivenName;
    1268         [ +  - ]:        438 :                     ScDPOutput::GetDataDimensionNames( aSourceName, aGivenName, xDim );
    1269         [ +  - ]:        438 :                     rDataNames.push_back( aSourceName );
    1270         [ +  - ]:        438 :                     rGivenNames.push_back( aGivenName );
    1271                 :            : 
    1272                 :        438 :                     ++nDataCount;
    1273                 :            :                 }
    1274                 :            :             }
    1275                 :       2628 :         }
    1276                 :            : 
    1277 [ -  + ][ #  # ]:        438 :         if ( ( rDataOrient == sheet::DataPilotFieldOrientation_COLUMN ) && bColGrand )
    1278                 :          0 :             rGrandTotalCols = nDataCount;
    1279 [ -  + ][ #  # ]:        438 :         else if ( ( rDataOrient == sheet::DataPilotFieldOrientation_ROW ) && bRowGrand )
    1280                 :        438 :             rGrandTotalRows = nDataCount;
    1281                 :        438 :     }
    1282                 :        438 : }
    1283                 :            : 
    1284                 :            : }
    1285                 :            : 
    1286                 :        388 : void ScDPOutput::GetPositionData(const ScAddress& rPos, DataPilotTablePositionData& rPosData)
    1287                 :            : {
    1288                 :            :     using namespace ::com::sun::star::sheet;
    1289                 :            : 
    1290                 :        388 :     SCCOL nCol = rPos.Col();
    1291                 :        388 :     SCROW nRow = rPos.Row();
    1292                 :        388 :     SCTAB nTab = rPos.Tab();
    1293         [ -  + ]:        388 :     if ( nTab != aStartPos.Tab() )
    1294                 :          0 :         return;                                     // wrong sheet
    1295                 :            : 
    1296                 :            :     //  calculate output positions and sizes
    1297                 :            : 
    1298                 :        388 :     CalcSizes();
    1299                 :            : 
    1300                 :        388 :     rPosData.PositionType = GetPositionType(rPos);
    1301   [ +  +  +  + ]:        388 :     switch (rPosData.PositionType)
    1302                 :            :     {
    1303                 :            :         case DataPilotTablePositionType::RESULT:
    1304                 :            :         {
    1305         [ +  - ]:        280 :             vector<DataPilotFieldFilter> aFilters;
    1306         [ +  - ]:        280 :             GetDataResultPositionData(aFilters, rPos);
    1307                 :        280 :             sal_Int32 nSize = aFilters.size();
    1308                 :            : 
    1309         [ +  - ]:        280 :             DataPilotTableResultData aResData;
    1310         [ +  - ]:        280 :             aResData.FieldFilters.realloc(nSize);
    1311         [ +  + ]:       1280 :             for (sal_Int32 i = 0; i < nSize; ++i)
    1312         [ +  - ]:       1000 :                 aResData.FieldFilters[i] = aFilters[i];
    1313                 :            : 
    1314                 :        280 :             aResData.DataFieldIndex = 0;
    1315         [ +  - ]:        280 :             Reference<beans::XPropertySet> xPropSet(xSource, UNO_QUERY);
    1316         [ +  - ]:        280 :             if (xPropSet.is())
    1317                 :            :             {
    1318                 :            :                 sal_Int32 nDataFieldCount = ScUnoHelpFunctions::GetLongProperty( xPropSet,
    1319         [ +  - ]:        280 :                                             rtl::OUString(SC_UNO_DP_DATAFIELDCOUNT) );
    1320         [ +  - ]:        280 :                 if (nDataFieldCount > 0)
    1321                 :        280 :                     aResData.DataFieldIndex = (nRow - nDataStartRow) % nDataFieldCount;
    1322                 :            :             }
    1323                 :            : 
    1324                 :            :             // Copy appropriate DataResult object from the cached sheet::DataResult table.
    1325   [ +  -  +  - ]:        560 :             if (aData.getLength() > nRow - nDataStartRow &&
                 [ +  - ]
    1326         [ +  - ]:        280 :                 aData[nRow-nDataStartRow].getLength() > nCol-nDataStartCol)
    1327 [ +  - ][ +  - ]:        280 :                 aResData.Result = aData[nRow-nDataStartRow][nCol-nDataStartCol];
    1328                 :            : 
    1329         [ +  - ]:        280 :             rPosData.PositionData = makeAny(aResData);
    1330         [ +  - ]:        280 :             return;
    1331                 :            :         }
    1332                 :            :         case DataPilotTablePositionType::COLUMN_HEADER:
    1333                 :            :         {
    1334                 :         36 :             long nField = nRow - nTabStartRow - 1; // 1st line is used for the buttons
    1335         [ +  - ]:         36 :             if (nField < 0)
    1336                 :            :                 break;
    1337                 :            : 
    1338         [ +  - ]:         36 :             const uno::Sequence<sheet::MemberResult> rSequence = pColFields[nField].aResult;
    1339         [ -  + ]:         36 :             if (rSequence.getLength() == 0)
    1340                 :            :                 break;
    1341                 :         36 :             const sheet::MemberResult* pArray = rSequence.getConstArray();
    1342                 :            : 
    1343                 :         36 :             long nItem = nCol - nDataStartCol;
    1344                 :            :             //  get origin of "continue" fields
    1345 [ +  + ][ -  + ]:         36 :             while (nItem > 0 && ( pArray[nItem].Flags & sheet::MemberResultFlags::CONTINUE) )
                 [ -  + ]
    1346                 :          0 :                 --nItem;
    1347                 :            : 
    1348         [ -  + ]:         36 :             if (nItem < 0)
    1349                 :            :                 break;
    1350                 :            : 
    1351                 :         36 :             DataPilotTableHeaderData aHeaderData;
    1352                 :         36 :             aHeaderData.MemberName = OUString(pArray[nItem].Name);
    1353                 :         36 :             aHeaderData.Flags = pArray[nItem].Flags;
    1354                 :         36 :             aHeaderData.Dimension = static_cast<sal_Int32>(pColFields[nField].nDim);
    1355                 :         36 :             aHeaderData.Hierarchy = static_cast<sal_Int32>(pColFields[nField].nHier);
    1356                 :         36 :             aHeaderData.Level     = static_cast<sal_Int32>(pColFields[nField].nLevel);
    1357                 :            : 
    1358         [ +  - ]:         36 :             rPosData.PositionData = makeAny(aHeaderData);
    1359 [ +  - ][ -  + ]:         36 :             return;
    1360                 :            :         }
    1361                 :            :         case DataPilotTablePositionType::ROW_HEADER:
    1362                 :            :         {
    1363                 :         36 :             long nField = nCol - nTabStartCol;
    1364         [ +  - ]:         36 :             if (nField < 0)
    1365                 :            :                 break;
    1366                 :            : 
    1367         [ +  - ]:         36 :             const uno::Sequence<sheet::MemberResult> rSequence = pRowFields[nField].aResult;
    1368         [ -  + ]:         36 :             if (rSequence.getLength() == 0)
    1369                 :            :                 break;
    1370                 :         36 :             const sheet::MemberResult* pArray = rSequence.getConstArray();
    1371                 :            : 
    1372                 :         36 :             long nItem = nRow - nDataStartRow;
    1373                 :            :             //  get origin of "continue" fields
    1374 [ +  + ][ -  + ]:         36 :             while ( nItem > 0 && (pArray[nItem].Flags & sheet::MemberResultFlags::CONTINUE) )
                 [ -  + ]
    1375                 :          0 :                 --nItem;
    1376                 :            : 
    1377         [ -  + ]:         36 :             if (nItem < 0)
    1378                 :            :                 break;
    1379                 :            : 
    1380                 :         36 :             DataPilotTableHeaderData aHeaderData;
    1381                 :         36 :             aHeaderData.MemberName = OUString(pArray[nItem].Name);
    1382                 :         36 :             aHeaderData.Flags = pArray[nItem].Flags;
    1383                 :         36 :             aHeaderData.Dimension = static_cast<sal_Int32>(pRowFields[nField].nDim);
    1384                 :         36 :             aHeaderData.Hierarchy = static_cast<sal_Int32>(pRowFields[nField].nHier);
    1385                 :         36 :             aHeaderData.Level     = static_cast<sal_Int32>(pRowFields[nField].nLevel);
    1386                 :            : 
    1387         [ +  - ]:         36 :             rPosData.PositionData = makeAny(aHeaderData);
    1388 [ +  - ][ -  + ]:        388 :             return;
    1389                 :            :         }
    1390                 :            :     }
    1391                 :            : }
    1392                 :            : 
    1393                 :        438 : bool ScDPOutput::GetDataResultPositionData(vector<sheet::DataPilotFieldFilter>& rFilters, const ScAddress& rPos)
    1394                 :            : {
    1395                 :            :     // Check to make sure there is at least one data field.
    1396         [ +  - ]:        438 :     Reference<beans::XPropertySet> xPropSet(xSource, UNO_QUERY);
    1397         [ -  + ]:        438 :     if (!xPropSet.is())
    1398                 :          0 :         return false;
    1399                 :            : 
    1400                 :            :     sal_Int32 nDataFieldCount = ScUnoHelpFunctions::GetLongProperty( xPropSet,
    1401         [ +  - ]:        438 :                                 rtl::OUString(SC_UNO_DP_DATAFIELDCOUNT) );
    1402         [ -  + ]:        438 :     if (nDataFieldCount == 0)
    1403                 :            :         // No data field is present in this datapilot table.
    1404                 :          0 :         return false;
    1405                 :            : 
    1406                 :            :     // #i111421# use lcl_GetTableVars for correct size of totals and data layout position
    1407                 :            :     sal_Int32 nGrandTotalCols;
    1408                 :            :     sal_Int32 nGrandTotalRows;
    1409                 :            :     sal_Int32 nDataLayoutIndex;
    1410         [ +  - ]:        438 :     std::vector<rtl::OUString> aDataNames;
    1411         [ +  - ]:        438 :     std::vector<rtl::OUString> aGivenNames;
    1412                 :            :     sheet::DataPilotFieldOrientation eDataOrient;
    1413         [ +  - ]:        438 :     lcl_GetTableVars( nGrandTotalCols, nGrandTotalRows, nDataLayoutIndex, aDataNames, aGivenNames, eDataOrient, xSource );
    1414                 :            : 
    1415                 :        438 :     SCCOL nCol = rPos.Col();
    1416                 :        438 :     SCROW nRow = rPos.Row();
    1417                 :        438 :     SCTAB nTab = rPos.Tab();
    1418         [ -  + ]:        438 :     if ( nTab != aStartPos.Tab() )
    1419                 :          0 :         return false;                                     // wrong sheet
    1420                 :            : 
    1421         [ +  - ]:        438 :     CalcSizes();
    1422                 :            : 
    1423                 :            :     // test for data area.
    1424 [ +  - ][ +  - ]:        438 :     if (nCol < nDataStartCol || nCol > nTabEndCol || nRow < nDataStartRow || nRow > nTabEndRow)
         [ +  - ][ -  + ]
    1425                 :            :     {
    1426                 :            :         // Cell is outside the data field area.
    1427                 :          0 :         return false;
    1428                 :            :     }
    1429                 :            : 
    1430                 :        438 :     bool bFilterByCol = (nCol <= static_cast<SCCOL>(nTabEndCol - nGrandTotalCols));
    1431                 :        438 :     bool bFilterByRow = (nRow <= static_cast<SCROW>(nTabEndRow - nGrandTotalRows));
    1432                 :            : 
    1433                 :            :     // column fields
    1434 [ +  + ][ +  + ]:       1218 :     for (SCCOL nColField = 0; nColField < nColFieldCount && bFilterByCol; ++nColField)
                 [ +  + ]
    1435                 :            :     {
    1436         [ -  + ]:        780 :         if (pColFields[nColField].nDim == nDataLayoutIndex)
    1437                 :            :             // There is no sense including the data layout field for filtering.
    1438                 :          0 :             continue;
    1439                 :            : 
    1440                 :        780 :         sheet::DataPilotFieldFilter filter;
    1441                 :        780 :         filter.FieldName = pColFields[nColField].maName;
    1442                 :            : 
    1443         [ +  - ]:        780 :         const uno::Sequence<sheet::MemberResult> rSequence = pColFields[nColField].aResult;
    1444                 :        780 :         const sheet::MemberResult* pArray = rSequence.getConstArray();
    1445                 :            : 
    1446                 :            :         OSL_ENSURE(nDataStartCol + rSequence.getLength() - 1 == nTabEndCol, "ScDPOutput::GetDataFieldCellData: error in geometric assumption");
    1447                 :            : 
    1448                 :        780 :         long nItem = nCol - nDataStartCol;
    1449                 :            :                 //  get origin of "continue" fields
    1450 [ +  + ][ -  + ]:        780 :         while ( nItem > 0 && (pArray[nItem].Flags & sheet::MemberResultFlags::CONTINUE) )
                 [ -  + ]
    1451                 :          0 :             --nItem;
    1452                 :            : 
    1453                 :        780 :         filter.MatchValue = pArray[nItem].Name;
    1454         [ +  - ]:        780 :         rFilters.push_back(filter);
    1455         [ +  - ]:        780 :     }
    1456                 :            : 
    1457                 :            :     // row fields
    1458 [ +  + ][ +  + ]:       1218 :     for (SCROW nRowField = 0; nRowField < nRowFieldCount && bFilterByRow; ++nRowField)
                 [ +  + ]
    1459                 :            :     {
    1460         [ -  + ]:        780 :         if (pRowFields[nRowField].nDim == nDataLayoutIndex)
    1461                 :            :             // There is no sense including the data layout field for filtering.
    1462                 :          0 :             continue;
    1463                 :            : 
    1464                 :        780 :         sheet::DataPilotFieldFilter filter;
    1465                 :        780 :         filter.FieldName = pRowFields[nRowField].maName;
    1466                 :            : 
    1467         [ +  - ]:        780 :         const uno::Sequence<sheet::MemberResult> rSequence = pRowFields[nRowField].aResult;
    1468                 :        780 :         const sheet::MemberResult* pArray = rSequence.getConstArray();
    1469                 :            : 
    1470                 :            :         OSL_ENSURE(nDataStartRow + rSequence.getLength() - 1 == nTabEndRow, "ScDPOutput::GetDataFieldCellData: error in geometric assumption");
    1471                 :            : 
    1472                 :        780 :         long nItem = nRow - nDataStartRow;
    1473                 :            :             //  get origin of "continue" fields
    1474 [ +  + ][ -  + ]:        780 :         while ( nItem > 0 && (pArray[nItem].Flags & sheet::MemberResultFlags::CONTINUE) )
                 [ -  + ]
    1475                 :          0 :             --nItem;
    1476                 :            : 
    1477                 :        780 :         filter.MatchValue = pArray[nItem].Name;
    1478         [ +  - ]:        780 :         rFilters.push_back(filter);
    1479         [ +  - ]:        780 :     }
    1480                 :            : 
    1481                 :        438 :     return true;
    1482                 :            : }
    1483                 :            : 
    1484                 :            : namespace {
    1485                 :            : 
    1486                 :            : //
    1487                 :            : //  helper functions for ScDPOutput::GetPivotData
    1488                 :            : //
    1489                 :            : 
    1490                 :          0 : bool lcl_IsNamedDataField( const ScDPGetPivotDataField& rTarget, const rtl::OUString& rSourceName, const rtl::OUString& rGivenName )
    1491                 :            : {
    1492                 :            :     // match one of the names, ignoring case
    1493 [ #  # ][ #  # ]:          0 :     return ScGlobal::GetpTransliteration()->isEqual( rTarget.maFieldName, rSourceName ) ||
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
           [ #  #  #  # ]
    1494 [ #  # ][ #  # ]:          0 :            ScGlobal::GetpTransliteration()->isEqual( rTarget.maFieldName, rGivenName );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
           [ #  #  #  # ]
    1495                 :            : }
    1496                 :            : 
    1497                 :          0 : bool lcl_IsNamedCategoryField( const ScDPGetPivotDataField& rFilter, const ScDPOutLevelData& rField )
    1498                 :            : {
    1499 [ #  # ][ #  # ]:          0 :     return ScGlobal::GetpTransliteration()->isEqual( rFilter.maFieldName, rField.maName );
         [ #  # ][ #  # ]
    1500                 :            : }
    1501                 :            : 
    1502                 :          0 : bool lcl_IsCondition( const sheet::MemberResult& rResultEntry, const ScDPGetPivotDataField& rFilter )
    1503                 :            : {
    1504                 :            :     //! handle numeric conditions?
    1505 [ #  # ][ #  # ]:          0 :     return ScGlobal::GetpTransliteration()->isEqual( rResultEntry.Name, rFilter.maValStr );
         [ #  # ][ #  # ]
    1506                 :            : }
    1507                 :            : 
    1508                 :          0 : bool lcl_CheckPageField( const ScDPOutLevelData& rField,
    1509                 :            :                          const std::vector< ScDPGetPivotDataField >& rFilters,
    1510                 :            :                          std::vector<bool>& rFilterUsed )
    1511                 :            : {
    1512         [ #  # ]:          0 :     for (SCSIZE nFilterPos = 0; nFilterPos < rFilters.size(); ++nFilterPos)
    1513                 :            :     {
    1514         [ #  # ]:          0 :         if ( lcl_IsNamedCategoryField( rFilters[nFilterPos], rField ) )
    1515                 :            :         {
    1516                 :          0 :             rFilterUsed[nFilterPos] = true;
    1517                 :            : 
    1518                 :            :             // page field result is empty or the selection as single entry (see lcl_GetSelectedPageAsResult)
    1519         [ #  # ]:          0 :             if ( rField.aResult.getLength() == 1 &&
           [ #  #  #  # ]
    1520                 :          0 :                  lcl_IsCondition( rField.aResult[0], rFilters[nFilterPos] ) )
    1521                 :            :             {
    1522                 :          0 :                 return true;        // condition matches page selection
    1523                 :            :             }
    1524                 :            :             else
    1525                 :            :             {
    1526                 :          0 :                 return false;       // no page selection or different entry
    1527                 :            :             }
    1528                 :            :         }
    1529                 :            :     }
    1530                 :            : 
    1531                 :          0 :     return true;    // valid if the page field doesn't have a filter
    1532                 :            : }
    1533                 :            : 
    1534                 :          0 : uno::Sequence<sheet::GeneralFunction> lcl_GetSubTotals(
    1535                 :            :         const uno::Reference<sheet::XDimensionsSupplier>& xSource, const ScDPOutLevelData& rField )
    1536                 :            : {
    1537         [ #  # ]:          0 :     uno::Sequence<sheet::GeneralFunction> aSubTotals;
    1538                 :            : 
    1539                 :          0 :     uno::Reference<sheet::XHierarchiesSupplier> xHierSupp;
    1540 [ #  # ][ #  # ]:          0 :     uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
    1541 [ #  # ][ #  # ]:          0 :     uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName );
                 [ #  # ]
    1542 [ #  # ][ #  # ]:          0 :     sal_Int32 nIntCount = xIntDims->getCount();
    1543         [ #  # ]:          0 :     if ( rField.nDim < nIntCount )
    1544                 :            :     {
    1545                 :            :         uno::Reference<uno::XInterface> xIntDim = ScUnoHelpFunctions::AnyToInterface(
    1546 [ #  # ][ #  # ]:          0 :                                     xIntDims->getByIndex( rField.nDim ) );
                 [ #  # ]
    1547 [ #  # ][ #  # ]:          0 :         xHierSupp = uno::Reference<sheet::XHierarchiesSupplier>( xIntDim, uno::UNO_QUERY );
    1548                 :            :     }
    1549                 :            :     OSL_ENSURE( xHierSupp.is(), "dimension not found" );
    1550                 :            : 
    1551                 :          0 :     sal_Int32 nHierCount = 0;
    1552                 :          0 :     uno::Reference<container::XIndexAccess> xHiers;
    1553         [ #  # ]:          0 :     if ( xHierSupp.is() )
    1554                 :            :     {
    1555 [ #  # ][ #  # ]:          0 :         uno::Reference<container::XNameAccess> xHiersName = xHierSupp->getHierarchies();
    1556 [ #  # ][ #  # ]:          0 :         xHiers = new ScNameToIndexAccess( xHiersName );
                 [ #  # ]
    1557 [ #  # ][ #  # ]:          0 :         nHierCount = xHiers->getCount();
    1558                 :            :     }
    1559                 :          0 :     uno::Reference<uno::XInterface> xHier;
    1560         [ #  # ]:          0 :     if ( rField.nHier < nHierCount )
    1561 [ #  # ][ #  # ]:          0 :         xHier = ScUnoHelpFunctions::AnyToInterface( xHiers->getByIndex( rField.nHier ) );
         [ #  # ][ #  # ]
    1562                 :            :     OSL_ENSURE( xHier.is(), "hierarchy not found" );
    1563                 :            : 
    1564                 :          0 :     sal_Int32 nLevCount = 0;
    1565                 :          0 :     uno::Reference<container::XIndexAccess> xLevels;
    1566         [ #  # ]:          0 :     uno::Reference<sheet::XLevelsSupplier> xLevSupp( xHier, uno::UNO_QUERY );
    1567         [ #  # ]:          0 :     if ( xLevSupp.is() )
    1568                 :            :     {
    1569 [ #  # ][ #  # ]:          0 :         uno::Reference<container::XNameAccess> xLevsName = xLevSupp->getLevels();
    1570 [ #  # ][ #  # ]:          0 :         xLevels = new ScNameToIndexAccess( xLevsName );
                 [ #  # ]
    1571 [ #  # ][ #  # ]:          0 :         nLevCount = xLevels->getCount();
    1572                 :            :     }
    1573                 :          0 :     uno::Reference<uno::XInterface> xLevel;
    1574         [ #  # ]:          0 :     if ( rField.nLevel < nLevCount )
    1575 [ #  # ][ #  # ]:          0 :         xLevel = ScUnoHelpFunctions::AnyToInterface( xLevels->getByIndex( rField.nLevel ) );
         [ #  # ][ #  # ]
    1576                 :            :     OSL_ENSURE( xLevel.is(), "level not found" );
    1577                 :            : 
    1578         [ #  # ]:          0 :     uno::Reference<beans::XPropertySet> xLevelProp( xLevel, uno::UNO_QUERY );
    1579         [ #  # ]:          0 :     if ( xLevelProp.is() )
    1580                 :            :     {
    1581                 :            :         try
    1582                 :            :         {
    1583 [ #  # ][ #  # ]:          0 :             uno::Any aValue = xLevelProp->getPropertyValue( rtl::OUString(SC_UNO_DP_SUBTOTAL) );
    1584 [ #  # ][ #  # ]:          0 :             aValue >>= aSubTotals;
    1585                 :            :         }
    1586         [ #  # ]:          0 :         catch(uno::Exception&)
    1587                 :            :         {
    1588                 :            :         }
    1589                 :            :     }
    1590                 :            : 
    1591                 :          0 :     return aSubTotals;
    1592                 :            : }
    1593                 :            : 
    1594                 :          0 : void lcl_FilterInclude( std::vector<bool>& rResult, std::vector< sal_Int32 >& rSubtotal,
    1595                 :            :                         const ScDPOutLevelData& rField,
    1596                 :            :                         const std::vector< ScDPGetPivotDataField >& rFilters,
    1597                 :            :                         std::vector<bool>& rFilterUsed,
    1598                 :            :                         bool& rBeforeDataLayout,
    1599                 :            :                         sal_Int32 nGrandTotals, sal_Int32 nDataLayoutIndex,
    1600                 :            :                         const std::vector<rtl::OUString>& rDataNames, const std::vector<rtl::OUString>& rGivenNames,
    1601                 :            :                         const ScDPGetPivotDataField& rTarget, const uno::Reference<sheet::XDimensionsSupplier>& xSource )
    1602                 :            : {
    1603                 :            :     // returns true if a filter was given for the field
    1604                 :            : 
    1605                 :            :     OSL_ENSURE( rFilters.size() == rFilterUsed.size(), "wrong size" );
    1606                 :            : 
    1607                 :          0 :     const bool bIsDataLayout = ( rField.nDim == nDataLayoutIndex );
    1608         [ #  # ]:          0 :     if (bIsDataLayout)
    1609                 :          0 :         rBeforeDataLayout = false;
    1610                 :            : 
    1611                 :          0 :     bool bHasFilter = false;
    1612                 :          0 :     ScDPGetPivotDataField aFilter;
    1613         [ #  # ]:          0 :     if ( !bIsDataLayout )          // selection of data field is handled separately
    1614                 :            :     {
    1615 [ #  # ][ #  # ]:          0 :         for (SCSIZE nFilterPos = 0; nFilterPos < rFilters.size() && !bHasFilter; ++nFilterPos)
                 [ #  # ]
    1616                 :            :         {
    1617 [ #  # ][ #  # ]:          0 :             if ( lcl_IsNamedCategoryField( rFilters[nFilterPos], rField ) )
    1618                 :            :             {
    1619                 :          0 :                 aFilter = rFilters[nFilterPos];
    1620         [ #  # ]:          0 :                 rFilterUsed[nFilterPos] = true;
    1621                 :          0 :                 bHasFilter = true;
    1622                 :            :             }
    1623                 :            :         }
    1624                 :            :     }
    1625                 :            : 
    1626 [ #  # ][ #  # ]:          0 :     bool bHasFunc = bHasFilter && aFilter.meFunction != sheet::GeneralFunction_NONE;
    1627                 :            : 
    1628         [ #  # ]:          0 :     uno::Sequence<sheet::GeneralFunction> aSubTotals;
    1629         [ #  # ]:          0 :     if ( !bIsDataLayout )
    1630 [ #  # ][ #  # ]:          0 :         aSubTotals = lcl_GetSubTotals( xSource, rField );
                 [ #  # ]
    1631 [ #  # ][ #  # ]:          0 :     bool bManualSub = ( aSubTotals.getLength() > 0 && aSubTotals[0] != sheet::GeneralFunction_AUTO );
                 [ #  # ]
    1632                 :            : 
    1633                 :          0 :     const uno::Sequence<sheet::MemberResult>& rSequence = rField.aResult;
    1634                 :          0 :     const sheet::MemberResult* pArray = rSequence.getConstArray();
    1635                 :          0 :     sal_Int32 nSize = rSequence.getLength();
    1636                 :            : 
    1637                 :            :     OSL_ENSURE( (sal_Int32)rResult.size() == nSize, "Number of fields do not match result count" );
    1638                 :            : 
    1639                 :          0 :     sal_Int32 nContCount = 0;
    1640                 :          0 :     sal_Int32 nSubTotalCount = 0;
    1641                 :          0 :     sheet::MemberResult aPrevious;
    1642         [ #  # ]:          0 :     for( sal_Int32 j=0; j < nSize; j++ )
    1643                 :            :     {
    1644                 :          0 :         sheet::MemberResult aResultEntry = pArray[j];
    1645         [ #  # ]:          0 :         if ( aResultEntry.Flags & sheet::MemberResultFlags::CONTINUE )
    1646                 :            :         {
    1647                 :          0 :             aResultEntry = aPrevious;
    1648                 :          0 :             ++nContCount;
    1649                 :            :         }
    1650         [ #  # ]:          0 :         else if ( ( aResultEntry.Flags & sheet::MemberResultFlags::SUBTOTAL ) == 0 )
    1651                 :            :         {
    1652                 :            :             // count the CONTINUE entries before a SUBTOTAL
    1653                 :          0 :             nContCount = 0;
    1654                 :            :         }
    1655                 :            : 
    1656         [ #  # ]:          0 :         if ( j >= nSize - nGrandTotals )
    1657                 :            :         {
    1658                 :            :             // mark as subtotal for the preceding data
    1659         [ #  # ]:          0 :             if ( ( aResultEntry.Flags & sheet::MemberResultFlags::SUBTOTAL ) != 0 )
    1660                 :            :             {
    1661         [ #  # ]:          0 :                 rSubtotal[j] = nSize - nGrandTotals;
    1662                 :            : 
    1663 [ #  # ][ #  # ]:          0 :                 if ( rResult[j] && nGrandTotals > 1 )
         [ #  # ][ #  # ]
           [ #  #  #  # ]
    1664                 :            :                 {
    1665                 :            :                     // grand total is always automatic
    1666                 :          0 :                     sal_Int32 nDataPos = j - ( nSize - nGrandTotals );
    1667                 :            :                     OSL_ENSURE( nDataPos < (sal_Int32)rDataNames.size(), "wrong data count" );
    1668                 :          0 :                     rtl::OUString aSourceName( rDataNames[nDataPos] );     // vector contains source names
    1669                 :          0 :                     rtl::OUString aGivenName( rGivenNames[nDataPos] );
    1670                 :            : 
    1671 [ #  # ][ #  # ]:          0 :                     rResult[j] = lcl_IsNamedDataField( rTarget, aSourceName, aGivenName );
    1672                 :            :                 }
    1673                 :            :             }
    1674                 :            : 
    1675                 :            :             // treat "grand total" columns/rows as empty description, as if they were marked
    1676                 :            :             // in a previous field
    1677                 :            : 
    1678                 :            :             OSL_ENSURE( ( aResultEntry.Flags &
    1679                 :            :                             ( sheet::MemberResultFlags::HASMEMBER | sheet::MemberResultFlags::SUBTOTAL ) ) == 0 ||
    1680                 :            :                         ( aResultEntry.Flags &
    1681                 :            :                             ( sheet::MemberResultFlags::HASMEMBER | sheet::MemberResultFlags::SUBTOTAL ) ) ==
    1682                 :            :                                 ( sheet::MemberResultFlags::HASMEMBER | sheet::MemberResultFlags::SUBTOTAL ),
    1683                 :            :                         "non-subtotal member found in grand total result" );
    1684                 :          0 :             aResultEntry.Flags = 0;
    1685                 :            :         }
    1686                 :            : 
    1687                 :            :         // mark subtotals (not grand total) for preceding data (assume CONTINUE is set)
    1688         [ #  # ]:          0 :         if ( ( aResultEntry.Flags & sheet::MemberResultFlags::SUBTOTAL ) != 0 )
    1689                 :            :         {
    1690         [ #  # ]:          0 :             rSubtotal[j] = nContCount + 1 + nSubTotalCount;
    1691                 :            : 
    1692 [ #  # ][ #  # ]:          0 :             if ( rResult[j] )
    1693                 :            :             {
    1694         [ #  # ]:          0 :                 if ( bManualSub )
    1695                 :            :                 {
    1696         [ #  # ]:          0 :                     if ( rBeforeDataLayout )
    1697                 :            :                     {
    1698                 :            :                         // manual subtotals and several data fields
    1699                 :            : 
    1700                 :          0 :                         sal_Int32 nDataCount = rDataNames.size();
    1701                 :          0 :                         sal_Int32 nFuncPos = nSubTotalCount / nDataCount;       // outer order: subtotal functions
    1702                 :          0 :                         sal_Int32 nDataPos = nSubTotalCount % nDataCount;       // inner order: data fields
    1703                 :            : 
    1704                 :          0 :                         rtl::OUString aSourceName( rDataNames[nDataPos] );             // vector contains source names
    1705                 :          0 :                         rtl::OUString aGivenName( rGivenNames[nDataPos] );
    1706                 :            : 
    1707                 :            :                         OSL_ENSURE( nFuncPos < aSubTotals.getLength(), "wrong subtotal count" );
    1708         [ #  # ]:          0 :                         rResult[j] = lcl_IsNamedDataField( rTarget, aSourceName, aGivenName ) &&
    1709 [ #  # ][ #  # ]:          0 :                                      aSubTotals[nFuncPos] == aFilter.meFunction;
         [ #  # ][ #  # ]
    1710                 :            :                     }
    1711                 :            :                     else
    1712                 :            :                     {
    1713                 :            :                         // manual subtotals for a single data field
    1714                 :            : 
    1715                 :            :                         OSL_ENSURE( nSubTotalCount < aSubTotals.getLength(), "wrong subtotal count" );
    1716 [ #  # ][ #  # ]:          0 :                         rResult[j] = ( aSubTotals[nSubTotalCount] == aFilter.meFunction );
    1717                 :            :                     }
    1718                 :            :                 }
    1719                 :            :                 else    // automatic subtotals
    1720                 :            :                 {
    1721         [ #  # ]:          0 :                     if ( rBeforeDataLayout )
    1722                 :            :                     {
    1723                 :            :                         OSL_ENSURE( nSubTotalCount < (sal_Int32)rDataNames.size(), "wrong data count" );
    1724                 :          0 :                         rtl::OUString aSourceName( rDataNames[nSubTotalCount] );       // vector contains source names
    1725                 :          0 :                         rtl::OUString aGivenName( rGivenNames[nSubTotalCount] );
    1726                 :            : 
    1727 [ #  # ][ #  # ]:          0 :                         rResult[j] = lcl_IsNamedDataField( rTarget, aSourceName, aGivenName );
    1728                 :            :                     }
    1729                 :            : 
    1730                 :            :                     // if a function was specified, automatic subtotals never match
    1731         [ #  # ]:          0 :                     if ( bHasFunc )
    1732         [ #  # ]:          0 :                         rResult[j] = false;
    1733                 :            :                 }
    1734                 :            :             }
    1735                 :            : 
    1736                 :          0 :             ++nSubTotalCount;
    1737                 :            :         }
    1738                 :            :         else
    1739                 :          0 :             nSubTotalCount = 0;
    1740                 :            : 
    1741 [ #  # ][ #  # ]:          0 :         if( rResult[j] )
    1742                 :            :         {
    1743         [ #  # ]:          0 :             if ( bIsDataLayout )
    1744                 :            :             {
    1745         [ #  # ]:          0 :                 if ( ( aResultEntry.Flags & sheet::MemberResultFlags::HASMEMBER ) != 0 )
    1746                 :            :                 {
    1747                 :            :                     // Asterisks are added in ScDPSaveData::WriteToSource to create unique names.
    1748                 :            :                     //! preserve original name there?
    1749         [ #  # ]:          0 :                     rtl::OUString aSourceName = ScDPUtil::getSourceDimensionName(aResultEntry.Name);
    1750                 :            : 
    1751                 :          0 :                     rResult[j] = lcl_IsNamedDataField(
    1752 [ #  # ][ #  # ]:          0 :                         rTarget, aSourceName, aResultEntry.Caption);
    1753                 :            :                 }
    1754                 :            :             }
    1755         [ #  # ]:          0 :             else if ( bHasFilter )
    1756                 :            :             {
    1757                 :            :                 // name must match (simple value or subtotal)
    1758                 :          0 :                 rResult[j] = ( ( aResultEntry.Flags & sheet::MemberResultFlags::HASMEMBER ) != 0 ) &&
    1759 [ #  # ][ #  # ]:          0 :                              lcl_IsCondition( aResultEntry, aFilter );
         [ #  # ][ #  # ]
    1760                 :            : 
    1761                 :            :                 // if a function was specified, simple (non-subtotal) values never match
    1762 [ #  # ][ #  # ]:          0 :                 if ( bHasFunc && nSubTotalCount == 0 )
    1763         [ #  # ]:          0 :                     rResult[j] = false;
    1764                 :            :             }
    1765                 :            :             // if no condition is given, keep the columns/rows included
    1766                 :            :         }
    1767                 :          0 :         aPrevious = aResultEntry;
    1768         [ #  # ]:          0 :     }
    1769                 :          0 : }
    1770                 :            : 
    1771                 :          0 : void lcl_StripSubTotals( std::vector<bool>& rResult, const std::vector<sal_Int32>& rSubtotal )
    1772                 :            : {
    1773                 :          0 :     sal_Int32 nSize = rResult.size();
    1774                 :            :     OSL_ENSURE( (sal_Int32)rSubtotal.size() == nSize, "sizes don't match" );
    1775                 :            : 
    1776         [ #  # ]:          0 :     for (sal_Int32 nPos=0; nPos<nSize; nPos++)
    1777 [ #  # ][ #  # ]:          0 :         if ( rResult[nPos] && rSubtotal[nPos] )
         [ #  # ][ #  # ]
                 [ #  # ]
           [ #  #  #  # ]
    1778                 :            :         {
    1779                 :            :             // if a subtotal is included, clear the result flag for the columns/rows that the subtotal includes
    1780                 :          0 :             sal_Int32 nStart = nPos - rSubtotal[nPos];
    1781                 :            :             OSL_ENSURE( nStart >= 0, "invalid subtotal count" );
    1782                 :            : 
    1783         [ #  # ]:          0 :             for (sal_Int32 nPrev = nStart; nPrev < nPos; nPrev++)
    1784                 :          0 :                 rResult[nPrev] = false;
    1785                 :            :         }
    1786                 :          0 : }
    1787                 :            : 
    1788                 :        438 : rtl::OUString lcl_GetDataFieldName( const rtl::OUString& rSourceName, sheet::GeneralFunction eFunc )
    1789                 :            : {
    1790                 :        438 :     sal_uInt16 nStrId = 0;
    1791   [ -  -  -  -  :        438 :     switch ( eFunc )
             -  -  -  -  
                      + ]
    1792                 :            :     {
    1793                 :          0 :         case sheet::GeneralFunction_SUM:        nStrId = STR_FUN_TEXT_SUM;      break;
    1794                 :            :         case sheet::GeneralFunction_COUNT:
    1795                 :          0 :         case sheet::GeneralFunction_COUNTNUMS:  nStrId = STR_FUN_TEXT_COUNT;    break;
    1796                 :          0 :         case sheet::GeneralFunction_AVERAGE:    nStrId = STR_FUN_TEXT_AVG;      break;
    1797                 :          0 :         case sheet::GeneralFunction_MAX:        nStrId = STR_FUN_TEXT_MAX;      break;
    1798                 :          0 :         case sheet::GeneralFunction_MIN:        nStrId = STR_FUN_TEXT_MIN;      break;
    1799                 :          0 :         case sheet::GeneralFunction_PRODUCT:    nStrId = STR_FUN_TEXT_PRODUCT;  break;
    1800                 :            :         case sheet::GeneralFunction_STDEV:
    1801                 :          0 :         case sheet::GeneralFunction_STDEVP:     nStrId = STR_FUN_TEXT_STDDEV;   break;
    1802                 :            :         case sheet::GeneralFunction_VAR:
    1803                 :          0 :         case sheet::GeneralFunction_VARP:       nStrId = STR_FUN_TEXT_VAR;      break;
    1804                 :            :         case sheet::GeneralFunction_NONE:
    1805                 :            :         case sheet::GeneralFunction_AUTO:
    1806                 :            :         default:
    1807                 :            :         {
    1808                 :            :             OSL_FAIL("wrong function");
    1809                 :            :         }
    1810                 :            :     }
    1811         [ +  - ]:        438 :     if ( !nStrId )
    1812                 :        438 :         return rtl::OUString();
    1813                 :            : 
    1814 [ #  # ][ #  # ]:          0 :     rtl::OUStringBuffer aRet( ScGlobal::GetRscString( nStrId ) );
                 [ #  # ]
    1815         [ #  # ]:          0 :     aRet.appendAscii(RTL_CONSTASCII_STRINGPARAM(" - "));
    1816         [ #  # ]:          0 :     aRet.append(rSourceName);
    1817         [ #  # ]:        438 :     return aRet.makeStringAndClear();
    1818                 :            : }
    1819                 :            : 
    1820                 :            : }
    1821                 :            : 
    1822                 :        438 : void ScDPOutput::GetDataDimensionNames(
    1823                 :            :     rtl::OUString& rSourceName, rtl::OUString& rGivenName, const uno::Reference<uno::XInterface>& xDim )
    1824                 :            : {
    1825         [ +  - ]:        438 :     uno::Reference<beans::XPropertySet> xDimProp( xDim, uno::UNO_QUERY );
    1826         [ +  - ]:        438 :     uno::Reference<container::XNamed> xDimName( xDim, uno::UNO_QUERY );
    1827 [ +  - ][ +  - ]:        438 :     if ( xDimProp.is() && xDimName.is() )
                 [ +  - ]
    1828                 :            :     {
    1829                 :            :         // Asterisks are added in ScDPSaveData::WriteToSource to create unique names.
    1830                 :            :         //! preserve original name there?
    1831 [ +  - ][ +  - ]:        438 :         rSourceName = ScDPUtil::getSourceDimensionName(xDimName->getName());
                 [ +  - ]
    1832                 :            : 
    1833                 :            :         // Generate "given name" the same way as in dptabres.
    1834                 :            :         //! Should use a stored name when available
    1835                 :            : 
    1836                 :            :         sheet::GeneralFunction eFunc = (sheet::GeneralFunction)ScUnoHelpFunctions::GetEnumProperty(
    1837                 :            :                                 xDimProp, rtl::OUString(SC_UNO_DP_FUNCTION),
    1838         [ +  - ]:        438 :                                 sheet::GeneralFunction_NONE );
    1839         [ +  - ]:        438 :         rGivenName = lcl_GetDataFieldName( rSourceName, eFunc );
    1840                 :        438 :     }
    1841                 :        438 : }
    1842                 :            : 
    1843                 :          0 : bool ScDPOutput::GetPivotData( ScDPGetPivotDataField& rTarget,
    1844                 :            :                                const std::vector< ScDPGetPivotDataField >& rFilters )
    1845                 :            : {
    1846         [ #  # ]:          0 :     CalcSizes();
    1847                 :            : 
    1848                 :            :     // need to know about grand total columns/rows:
    1849                 :            :     sal_Int32 nGrandTotalCols;
    1850                 :            :     sal_Int32 nGrandTotalRows;
    1851                 :            :     sal_Int32 nDataLayoutIndex;
    1852         [ #  # ]:          0 :     std::vector<rtl::OUString> aDataNames;
    1853         [ #  # ]:          0 :     std::vector<rtl::OUString> aGivenNames;
    1854                 :            :     sheet::DataPilotFieldOrientation eDataOrient;
    1855         [ #  # ]:          0 :     lcl_GetTableVars( nGrandTotalCols, nGrandTotalRows, nDataLayoutIndex, aDataNames, aGivenNames, eDataOrient, xSource );
    1856                 :            : 
    1857         [ #  # ]:          0 :     if ( aDataNames.empty() )
    1858                 :          0 :         return false;               // incomplete table without data fields -> no result
    1859                 :            : 
    1860         [ #  # ]:          0 :     if ( eDataOrient == sheet::DataPilotFieldOrientation_HIDDEN )
    1861                 :            :     {
    1862                 :            :         // no data layout field -> single data field -> must match the selected field in rTarget
    1863                 :            : 
    1864                 :            :         OSL_ENSURE( aDataNames.size() == 1, "several data fields but no data layout field" );
    1865 [ #  # ][ #  # ]:          0 :         if ( !lcl_IsNamedDataField( rTarget, aDataNames[0], aGivenNames[0] ) )
    1866                 :          0 :             return false;
    1867                 :            :     }
    1868                 :            : 
    1869         [ #  # ]:          0 :     std::vector<bool> aIncludeCol(nColCount, true);
    1870         [ #  # ]:          0 :     std::vector< sal_Int32 > aSubtotalCol( nColCount, 0 );
    1871         [ #  # ]:          0 :     std::vector<bool> aIncludeRow(nRowCount, true);
    1872         [ #  # ]:          0 :     std::vector< sal_Int32 > aSubtotalRow( nRowCount, 0 );
    1873                 :            : 
    1874         [ #  # ]:          0 :     std::vector<bool> aFilterUsed(rFilters.size(), false);
    1875                 :            : 
    1876                 :            :     long nField;
    1877                 :            :     long nCol;
    1878                 :            :     long nRow;
    1879                 :            :     bool bBeforeDataLayout;
    1880                 :            : 
    1881                 :            :     // look in column fields
    1882                 :            : 
    1883                 :          0 :     bBeforeDataLayout = ( eDataOrient == sheet::DataPilotFieldOrientation_COLUMN );
    1884         [ #  # ]:          0 :     for (nField=0; nField<nColFieldCount; nField++)
    1885                 :            :         lcl_FilterInclude( aIncludeCol, aSubtotalCol, pColFields[nField], rFilters, aFilterUsed, bBeforeDataLayout,
    1886         [ #  # ]:          0 :                            nGrandTotalCols, nDataLayoutIndex, aDataNames, aGivenNames, rTarget, xSource );
    1887                 :            : 
    1888                 :            :     // look in row fields
    1889                 :            : 
    1890                 :          0 :     bBeforeDataLayout = ( eDataOrient == sheet::DataPilotFieldOrientation_ROW );
    1891         [ #  # ]:          0 :     for (nField=0; nField<nRowFieldCount; nField++)
    1892                 :            :         lcl_FilterInclude( aIncludeRow, aSubtotalRow, pRowFields[nField], rFilters, aFilterUsed, bBeforeDataLayout,
    1893         [ #  # ]:          0 :                            nGrandTotalRows, nDataLayoutIndex, aDataNames, aGivenNames, rTarget, xSource );
    1894                 :            : 
    1895                 :            :     // page fields
    1896                 :            : 
    1897         [ #  # ]:          0 :     for (nField=0; nField<nPageFieldCount; nField++)
    1898 [ #  # ][ #  # ]:          0 :         if ( !lcl_CheckPageField( pPageFields[nField], rFilters, aFilterUsed ) )
    1899                 :          0 :             return false;
    1900                 :            : 
    1901                 :            :     // all filter fields must be used
    1902         [ #  # ]:          0 :     for (SCSIZE nFilter=0; nFilter<aFilterUsed.size(); nFilter++)
    1903 [ #  # ][ #  # ]:          0 :         if (!aFilterUsed[nFilter])
    1904                 :          0 :             return false;
    1905                 :            : 
    1906         [ #  # ]:          0 :     lcl_StripSubTotals( aIncludeCol, aSubtotalCol );
    1907         [ #  # ]:          0 :     lcl_StripSubTotals( aIncludeRow, aSubtotalRow );
    1908                 :            : 
    1909                 :          0 :     long nColPos = 0;
    1910                 :          0 :     long nColIncluded = 0;
    1911         [ #  # ]:          0 :     for (nCol=0; nCol<nColCount; nCol++)
    1912 [ #  # ][ #  # ]:          0 :         if (aIncludeCol[nCol])
    1913                 :            :         {
    1914                 :          0 :             nColPos = nCol;
    1915                 :          0 :             ++nColIncluded;
    1916                 :            :         }
    1917                 :            : 
    1918                 :          0 :     long nRowPos = 0;
    1919                 :          0 :     long nRowIncluded = 0;
    1920         [ #  # ]:          0 :     for (nRow=0; nRow<nRowCount; nRow++)
    1921 [ #  # ][ #  # ]:          0 :         if (aIncludeRow[nRow])
    1922                 :            :         {
    1923                 :          0 :             nRowPos = nRow;
    1924                 :          0 :             ++nRowIncluded;
    1925                 :            :         }
    1926                 :            : 
    1927 [ #  # ][ #  # ]:          0 :     if ( nColIncluded != 1 || nRowIncluded != 1 )
    1928                 :          0 :         return false;
    1929                 :            : 
    1930         [ #  # ]:          0 :     const uno::Sequence<sheet::DataResult>& rDataRow = aData[nRowPos];
    1931         [ #  # ]:          0 :     if ( nColPos >= rDataRow.getLength() )
    1932                 :          0 :         return false;
    1933                 :            : 
    1934                 :          0 :     const sheet::DataResult& rResult = rDataRow[nColPos];
    1935         [ #  # ]:          0 :     if ( rResult.Flags & sheet::DataResultFlags::ERROR )
    1936                 :          0 :         return false;                                       //! different error?
    1937                 :            : 
    1938                 :          0 :     rTarget.mbValIsStr = false;
    1939                 :          0 :     rTarget.mnValNum = rResult.Value;
    1940                 :            : 
    1941                 :          0 :     return true;
    1942                 :            : }
    1943                 :            : 
    1944                 :          0 : bool ScDPOutput::IsFilterButton( const ScAddress& rPos )
    1945                 :            : {
    1946                 :          0 :     SCCOL nCol = rPos.Col();
    1947                 :          0 :     SCROW nRow = rPos.Row();
    1948                 :          0 :     SCTAB nTab = rPos.Tab();
    1949 [ #  # ][ #  # ]:          0 :     if ( nTab != aStartPos.Tab() || !bDoFilter )
                 [ #  # ]
    1950                 :          0 :         return false;                               // wrong sheet or no button at all
    1951                 :            : 
    1952                 :            :     //  filter button is at top left
    1953 [ #  # ][ #  # ]:          0 :     return ( nCol == aStartPos.Col() && nRow == aStartPos.Row() );
    1954                 :            : }
    1955                 :            : 
    1956                 :          0 : long ScDPOutput::GetHeaderDim( const ScAddress& rPos, sal_uInt16& rOrient )
    1957                 :            : {
    1958                 :          0 :     SCCOL nCol = rPos.Col();
    1959                 :          0 :     SCROW nRow = rPos.Row();
    1960                 :          0 :     SCTAB nTab = rPos.Tab();
    1961         [ #  # ]:          0 :     if ( nTab != aStartPos.Tab() )
    1962                 :          0 :         return -1;                                      // wrong sheet
    1963                 :            : 
    1964                 :            :     //  calculate output positions and sizes
    1965                 :            : 
    1966                 :          0 :     CalcSizes();
    1967                 :            : 
    1968                 :            :     //  test for column header
    1969                 :            : 
    1970 [ #  # ][ #  # ]:          0 :     if ( nRow == nTabStartRow && nCol >= nDataStartCol && nCol < nDataStartCol + nColFieldCount )
                 [ #  # ]
    1971                 :            :     {
    1972                 :          0 :         rOrient = sheet::DataPilotFieldOrientation_COLUMN;
    1973                 :          0 :         long nField = nCol - nDataStartCol;
    1974                 :          0 :         return pColFields[nField].nDim;
    1975                 :            :     }
    1976                 :            : 
    1977                 :            :     //  test for row header
    1978                 :            : 
    1979 [ #  # ][ #  # ]:          0 :     if ( nRow+1 == nDataStartRow && nCol >= nTabStartCol && nCol < nTabStartCol + nRowFieldCount )
                 [ #  # ]
    1980                 :            :     {
    1981                 :          0 :         rOrient = sheet::DataPilotFieldOrientation_ROW;
    1982                 :          0 :         long nField = nCol - nTabStartCol;
    1983                 :          0 :         return pRowFields[nField].nDim;
    1984                 :            :     }
    1985                 :            : 
    1986                 :            :     //  test for page field
    1987                 :            : 
    1988         [ #  # ]:          0 :     SCROW nPageStartRow = aStartPos.Row() + ( bDoFilter ? 1 : 0 );
    1989 [ #  # ][ #  # ]:          0 :     if ( nCol == aStartPos.Col() && nRow >= nPageStartRow && nRow < nPageStartRow + nPageFieldCount )
         [ #  # ][ #  # ]
    1990                 :            :     {
    1991                 :          0 :         rOrient = sheet::DataPilotFieldOrientation_PAGE;
    1992                 :          0 :         long nField = nRow - nPageStartRow;
    1993                 :          0 :         return pPageFields[nField].nDim;
    1994                 :            :     }
    1995                 :            : 
    1996                 :            :     //! single data field (?)
    1997                 :            : 
    1998                 :          0 :     rOrient = sheet::DataPilotFieldOrientation_HIDDEN;
    1999                 :          0 :     return -1;      // invalid
    2000                 :            : }
    2001                 :            : 
    2002                 :          0 : bool ScDPOutput::GetHeaderDrag( const ScAddress& rPos, bool bMouseLeft, bool bMouseTop,
    2003                 :            :                                 long nDragDim,
    2004                 :            :                                 Rectangle& rPosRect, sal_uInt16& rOrient, long& rDimPos )
    2005                 :            : {
    2006                 :            :     //  Rectangle instead of ScRange for rPosRect to allow for negative values
    2007                 :            : 
    2008                 :          0 :     SCCOL nCol = rPos.Col();
    2009                 :          0 :     SCROW nRow = rPos.Row();
    2010                 :          0 :     SCTAB nTab = rPos.Tab();
    2011         [ #  # ]:          0 :     if ( nTab != aStartPos.Tab() )
    2012                 :          0 :         return false;                                       // wrong sheet
    2013                 :            : 
    2014                 :            :     //  calculate output positions and sizes
    2015                 :            : 
    2016                 :          0 :     CalcSizes();
    2017                 :            : 
    2018                 :            :     //  test for column header
    2019                 :            : 
    2020 [ #  # ][ #  # ]:          0 :     if ( nCol >= nDataStartCol && nCol <= nTabEndCol &&
         [ #  # ][ #  # ]
    2021                 :            :             nRow + 1 >= nMemberStartRow && nRow < nMemberStartRow + nColFieldCount )
    2022                 :            :     {
    2023                 :          0 :         long nField = nRow - nMemberStartRow;
    2024         [ #  # ]:          0 :         if (nField < 0)
    2025                 :            :         {
    2026                 :          0 :             nField = 0;
    2027                 :          0 :             bMouseTop = true;
    2028                 :            :         }
    2029                 :            :         //! find start of dimension
    2030                 :            : 
    2031                 :            :         rPosRect = Rectangle( nDataStartCol, nMemberStartRow + nField,
    2032                 :          0 :                               nTabEndCol, nMemberStartRow + nField -1 );
    2033                 :            : 
    2034                 :          0 :         bool bFound = false;            // is this within the same orientation?
    2035                 :          0 :         bool bBeforeDrag = false;
    2036                 :          0 :         bool bAfterDrag = false;
    2037 [ #  # ][ #  # ]:          0 :         for (long nPos=0; nPos<nColFieldCount && !bFound; nPos++)
                 [ #  # ]
    2038                 :            :         {
    2039         [ #  # ]:          0 :             if (pColFields[nPos].nDim == nDragDim)
    2040                 :            :             {
    2041                 :          0 :                 bFound = true;
    2042         [ #  # ]:          0 :                 if ( nField < nPos )
    2043                 :          0 :                     bBeforeDrag = true;
    2044         [ #  # ]:          0 :                 else if ( nField > nPos )
    2045                 :          0 :                     bAfterDrag = true;
    2046                 :            :             }
    2047                 :            :         }
    2048                 :            : 
    2049         [ #  # ]:          0 :         if ( bFound )
    2050                 :            :         {
    2051         [ #  # ]:          0 :             if (!bBeforeDrag)
    2052                 :            :             {
    2053                 :          0 :                 ++rPosRect.Bottom();
    2054         [ #  # ]:          0 :                 if (bAfterDrag)
    2055                 :          0 :                     ++rPosRect.Top();
    2056                 :            :             }
    2057                 :            :         }
    2058                 :            :         else
    2059                 :            :         {
    2060         [ #  # ]:          0 :             if ( !bMouseTop )
    2061                 :            :             {
    2062                 :          0 :                 ++rPosRect.Top();
    2063                 :          0 :                 ++rPosRect.Bottom();
    2064                 :          0 :                 ++nField;
    2065                 :            :             }
    2066                 :            :         }
    2067                 :            : 
    2068                 :          0 :         rOrient = sheet::DataPilotFieldOrientation_COLUMN;
    2069                 :          0 :         rDimPos = nField;                       //!...
    2070                 :          0 :         return true;
    2071                 :            :     }
    2072                 :            : 
    2073                 :            :     //  test for row header
    2074                 :            : 
    2075                 :            :     //  special case if no row fields
    2076                 :            :     bool bSpecial = ( nRow+1 >= nDataStartRow && nRow <= nTabEndRow &&
    2077 [ #  # ][ #  # ]:          0 :                         nRowFieldCount == 0 && nCol == nTabStartCol && bMouseLeft );
         [ #  # ][ #  # ]
                 [ #  # ]
    2078                 :            : 
    2079 [ #  # ][ #  # ]:          0 :     if ( bSpecial || ( nRow+1 >= nDataStartRow && nRow <= nTabEndRow &&
         [ #  # ][ #  # ]
                 [ #  # ]
    2080                 :            :                         nCol + 1 >= nTabStartCol && nCol < nTabStartCol + nRowFieldCount ) )
    2081                 :            :     {
    2082                 :          0 :         long nField = nCol - nTabStartCol;
    2083                 :            :         //! find start of dimension
    2084                 :            : 
    2085                 :            :         rPosRect = Rectangle( nTabStartCol + nField, nDataStartRow - 1,
    2086                 :          0 :                               nTabStartCol + nField - 1, nTabEndRow );
    2087                 :            : 
    2088                 :          0 :         bool bFound = false;            // is this within the same orientation?
    2089                 :          0 :         bool bBeforeDrag = false;
    2090                 :          0 :         bool bAfterDrag = false;
    2091 [ #  # ][ #  # ]:          0 :         for (long nPos=0; nPos<nRowFieldCount && !bFound; nPos++)
                 [ #  # ]
    2092                 :            :         {
    2093         [ #  # ]:          0 :             if (pRowFields[nPos].nDim == nDragDim)
    2094                 :            :             {
    2095                 :          0 :                 bFound = true;
    2096         [ #  # ]:          0 :                 if ( nField < nPos )
    2097                 :          0 :                     bBeforeDrag = true;
    2098         [ #  # ]:          0 :                 else if ( nField > nPos )
    2099                 :          0 :                     bAfterDrag = true;
    2100                 :            :             }
    2101                 :            :         }
    2102                 :            : 
    2103         [ #  # ]:          0 :         if ( bFound )
    2104                 :            :         {
    2105         [ #  # ]:          0 :             if (!bBeforeDrag)
    2106                 :            :             {
    2107                 :          0 :                 ++rPosRect.Right();
    2108         [ #  # ]:          0 :                 if (bAfterDrag)
    2109                 :          0 :                     ++rPosRect.Left();
    2110                 :            :             }
    2111                 :            :         }
    2112                 :            :         else
    2113                 :            :         {
    2114         [ #  # ]:          0 :             if ( !bMouseLeft )
    2115                 :            :             {
    2116                 :          0 :                 ++rPosRect.Left();
    2117                 :          0 :                 ++rPosRect.Right();
    2118                 :          0 :                 ++nField;
    2119                 :            :             }
    2120                 :            :         }
    2121                 :            : 
    2122                 :          0 :         rOrient = sheet::DataPilotFieldOrientation_ROW;
    2123                 :          0 :         rDimPos = nField;                       //!...
    2124                 :          0 :         return true;
    2125                 :            :     }
    2126                 :            : 
    2127                 :            :     //  test for page fields
    2128                 :            : 
    2129         [ #  # ]:          0 :     SCROW nPageStartRow = aStartPos.Row() + ( bDoFilter ? 1 : 0 );
    2130 [ #  # ][ #  # ]:          0 :     if ( nCol >= aStartPos.Col() && nCol <= nTabEndCol &&
         [ #  # ][ #  # ]
                 [ #  # ]
    2131                 :            :             nRow + 1 >= nPageStartRow && nRow < nPageStartRow + nPageFieldCount )
    2132                 :            :     {
    2133                 :          0 :         long nField = nRow - nPageStartRow;
    2134         [ #  # ]:          0 :         if (nField < 0)
    2135                 :            :         {
    2136                 :          0 :             nField = 0;
    2137                 :          0 :             bMouseTop = true;
    2138                 :            :         }
    2139                 :            :         //! find start of dimension
    2140                 :            : 
    2141                 :          0 :         rPosRect = Rectangle( aStartPos.Col(), nPageStartRow + nField,
    2142                 :          0 :                               nTabEndCol, nPageStartRow + nField - 1 );
    2143                 :            : 
    2144                 :          0 :         bool bFound = false;            // is this within the same orientation?
    2145                 :          0 :         bool bBeforeDrag = false;
    2146                 :          0 :         bool bAfterDrag = false;
    2147 [ #  # ][ #  # ]:          0 :         for (long nPos=0; nPos<nPageFieldCount && !bFound; nPos++)
                 [ #  # ]
    2148                 :            :         {
    2149         [ #  # ]:          0 :             if (pPageFields[nPos].nDim == nDragDim)
    2150                 :            :             {
    2151                 :          0 :                 bFound = true;
    2152         [ #  # ]:          0 :                 if ( nField < nPos )
    2153                 :          0 :                     bBeforeDrag = true;
    2154         [ #  # ]:          0 :                 else if ( nField > nPos )
    2155                 :          0 :                     bAfterDrag = true;
    2156                 :            :             }
    2157                 :            :         }
    2158                 :            : 
    2159         [ #  # ]:          0 :         if ( bFound )
    2160                 :            :         {
    2161         [ #  # ]:          0 :             if (!bBeforeDrag)
    2162                 :            :             {
    2163                 :          0 :                 ++rPosRect.Bottom();
    2164         [ #  # ]:          0 :                 if (bAfterDrag)
    2165                 :          0 :                     ++rPosRect.Top();
    2166                 :            :             }
    2167                 :            :         }
    2168                 :            :         else
    2169                 :            :         {
    2170         [ #  # ]:          0 :             if ( !bMouseTop )
    2171                 :            :             {
    2172                 :          0 :                 ++rPosRect.Top();
    2173                 :          0 :                 ++rPosRect.Bottom();
    2174                 :          0 :                 ++nField;
    2175                 :            :             }
    2176                 :            :         }
    2177                 :            : 
    2178                 :          0 :         rOrient = sheet::DataPilotFieldOrientation_PAGE;
    2179                 :          0 :         rDimPos = nField;                       //!...
    2180                 :          0 :         return true;
    2181                 :            :     }
    2182                 :            : 
    2183                 :          0 :     return false;
    2184 [ +  - ][ +  - ]:        153 : }
    2185                 :            : 
    2186                 :            : 
    2187                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10