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: */
|