1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "scitems.hxx"
21 #include <svx/algitem.hxx>
22 #include <editeng/boxitem.hxx>
23 #include <editeng/brushitem.hxx>
24 #include <editeng/wghtitem.hxx>
25 #include <editeng/justifyitem.hxx>
26 #include <unotools/transliterationwrapper.hxx>
28 #include "dpoutput.hxx"
29 #include "dptabsrc.hxx"
30 #include "dpfilteredcache.hxx"
31 #include "document.hxx"
32 #include "patattr.hxx"
33 #include "docpool.hxx"
34 #include "markdata.hxx"
36 #include <formula/errorcodes.hxx>
37 #include "miscuno.hxx"
38 #include "globstr.hrc"
39 #include "stlpool.hxx"
40 #include "stlsheet.hxx"
41 #include "scresid.hxx"
42 #include "unonames.hxx"
44 #include "stringutil.hxx"
47 #include <com/sun/star/beans/XPropertySet.hpp>
48 #include <com/sun/star/sheet/DataPilotTableHeaderData.hpp>
49 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
50 #include <com/sun/star/sheet/DataPilotTablePositionData.hpp>
51 #include <com/sun/star/sheet/DataPilotTableResultData.hpp>
52 #include <com/sun/star/sheet/MemberResultFlags.hpp>
53 #include <com/sun/star/sheet/TableFilterField.hpp>
54 #include <com/sun/star/sheet/DataResultFlags.hpp>
55 #include <com/sun/star/sheet/DataPilotTablePositionType.hpp>
59 using namespace com::sun::star
;
61 using ::com::sun::star::beans::XPropertySet
;
62 using ::com::sun::star::uno::Sequence
;
63 using ::com::sun::star::uno::UNO_QUERY
;
64 using ::com::sun::star::uno::Reference
;
65 using ::com::sun::star::sheet::DataPilotTablePositionData
;
66 using ::com::sun::star::sheet::DataPilotTableResultData
;
67 using ::com::sun::star::uno::makeAny
;
68 using ::com::sun::star::uno::Any
;
70 #define SC_DP_FRAME_INNER_BOLD 20
71 #define SC_DP_FRAME_OUTER_BOLD 40
73 #define SC_DP_FRAME_COLOR Color(0,0,0) //( 0x20, 0x40, 0x68 )
75 #define SC_DPOUT_MAXLEVELS 256
77 struct ScDPOutLevelData
83 sal_uInt32 mnSrcNumFmt
; /// Prevailing number format used in the source data.
84 uno::Sequence
<sheet::MemberResult
> aResult
;
85 OUString maName
; /// Name is the internal field name.
86 OUString maCaption
; /// Caption is the name visible in the output table.
87 bool mbHasHiddenMember
:1;
92 nDim(-1), nHier(-1), nLevel(-1), nDimPos(-1), mnSrcNumFmt(0), mbHasHiddenMember(false), mbDataLayout(false), mbPageDim(false)
95 bool operator<(const ScDPOutLevelData
& r
) const
96 { return nDimPos
<r
.nDimPos
|| ( nDimPos
==r
.nDimPos
&& nHier
<r
.nHier
) ||
97 ( nDimPos
==r
.nDimPos
&& nHier
==r
.nHier
&& nLevel
<r
.nLevel
); }
99 void Swap(ScDPOutLevelData
& r
)
100 { ScDPOutLevelData aTemp
; aTemp
= r
; r
= *this; *this = aTemp
; }
102 // bug (73840) in uno::Sequence - copy and then assign doesn't work!
107 bool lcl_compareColfuc ( SCCOL i
, SCCOL j
) { return (i
<j
); }
108 bool lcl_compareRowfuc ( SCROW i
, SCROW j
) { return (i
<j
); }
114 ::std::vector
< bool > mbNeedLineCols
;
115 ::std::vector
< SCCOL
> mnCols
;
117 ::std::vector
< bool > mbNeedLineRows
;
118 ::std::vector
< SCROW
> mnRows
;
123 SCCOL mnDataStartCol
;
124 SCROW mnDataStartRow
;
129 ScDPOutputImpl( ScDocument
* pDoc
, sal_uInt16 nTab
,
136 bool AddRow( SCROW nRow
);
137 bool AddCol( SCCOL nCol
);
139 void OutputDataArea();
140 void OutputBlockFrame ( SCCOL nStartCol
, SCROW nStartRow
, SCCOL nEndCol
, SCROW nEndRow
, bool bHori
= false );
144 void ScDPOutputImpl::OutputDataArea()
146 AddRow( mnDataStartRow
);
147 AddCol( mnDataStartCol
);
149 mnCols
.push_back( mnTabEndCol
+1); //set last row bottom
150 mnRows
.push_back( mnTabEndRow
+1); //set last col bottom
152 bool bAllRows
= ( ( mnTabEndRow
- mnDataStartRow
+ 2 ) == (SCROW
) mnRows
.size() );
154 std::sort( mnCols
.begin(), mnCols
.end(), lcl_compareColfuc
);
155 std::sort( mnRows
.begin(), mnRows
.end(), lcl_compareRowfuc
);
157 for( SCCOL nCol
= 0; nCol
< (SCCOL
)mnCols
.size()-1; nCol
++ )
161 if ( nCol
< (SCCOL
)mnCols
.size()-2)
163 for ( SCROW i
= nCol
%2; i
< (SCROW
)mnRows
.size()-2; i
+=2 )
164 OutputBlockFrame( mnCols
[nCol
], mnRows
[i
], mnCols
[nCol
+1]-1, mnRows
[i
+1]-1 );
165 if ( mnRows
.size()>=2 )
166 OutputBlockFrame( mnCols
[nCol
], mnRows
[mnRows
.size()-2], mnCols
[nCol
+1]-1, mnRows
[mnRows
.size()-1]-1 );
170 for ( SCROW i
= 0 ; i
< (SCROW
)mnRows
.size()-1; i
++ )
171 OutputBlockFrame( mnCols
[nCol
], mnRows
[i
], mnCols
[nCol
+1]-1, mnRows
[i
+1]-1 );
175 OutputBlockFrame( mnCols
[nCol
], mnRows
.front(), mnCols
[nCol
+1]-1, mnRows
.back()-1, bAllRows
);
177 //out put rows area outer framer
178 if ( mnTabStartCol
!= mnDataStartCol
)
180 if ( mnTabStartRow
!= mnDataStartRow
)
181 OutputBlockFrame( mnTabStartCol
, mnTabStartRow
, mnDataStartCol
-1, mnDataStartRow
-1 );
182 OutputBlockFrame( mnTabStartCol
, mnDataStartRow
, mnDataStartCol
-1, mnTabEndRow
);
184 //out put cols area outer framer
185 OutputBlockFrame( mnDataStartCol
, mnTabStartRow
, mnTabEndCol
, mnDataStartRow
-1 );
188 ScDPOutputImpl::ScDPOutputImpl( ScDocument
* pDoc
, sal_uInt16 nTab
,
197 mnTabStartCol( nTabStartCol
),
198 mnTabStartRow( nTabStartRow
),
199 mnDataStartCol ( nDataStartCol
),
200 mnDataStartRow ( nDataStartRow
),
201 mnTabEndCol( nTabEndCol
),
202 mnTabEndRow( nTabEndRow
)
204 mbNeedLineCols
.resize( nTabEndCol
-nDataStartCol
+1, false );
205 mbNeedLineRows
.resize( nTabEndRow
-nDataStartRow
+1, false );
209 bool ScDPOutputImpl::AddRow( SCROW nRow
)
211 if ( !mbNeedLineRows
[ nRow
- mnDataStartRow
] )
213 mbNeedLineRows
[ nRow
- mnDataStartRow
] = true;
214 mnRows
.push_back( nRow
);
221 bool ScDPOutputImpl::AddCol( SCCOL nCol
)
224 if ( !mbNeedLineCols
[ nCol
- mnDataStartCol
] )
226 mbNeedLineCols
[ nCol
- mnDataStartCol
] = true;
227 mnCols
.push_back( nCol
);
234 void ScDPOutputImpl::OutputBlockFrame ( SCCOL nStartCol
, SCROW nStartRow
, SCCOL nEndCol
, SCROW nEndRow
, bool bHori
)
236 Color color
= SC_DP_FRAME_COLOR
;
237 ::editeng::SvxBorderLine
aLine( &color
, SC_DP_FRAME_INNER_BOLD
);
238 ::editeng::SvxBorderLine
aOutLine( &color
, SC_DP_FRAME_OUTER_BOLD
);
240 SvxBoxItem
aBox( ATTR_BORDER
);
242 if ( nStartCol
== mnTabStartCol
)
243 aBox
.SetLine(&aOutLine
, SvxBoxItemLine::LEFT
);
245 aBox
.SetLine(&aLine
, SvxBoxItemLine::LEFT
);
247 if ( nStartRow
== mnTabStartRow
)
248 aBox
.SetLine(&aOutLine
, SvxBoxItemLine::TOP
);
250 aBox
.SetLine(&aLine
, SvxBoxItemLine::TOP
);
252 if ( nEndCol
== mnTabEndCol
) //bottom row
253 aBox
.SetLine(&aOutLine
, SvxBoxItemLine::RIGHT
);
255 aBox
.SetLine(&aLine
, SvxBoxItemLine::RIGHT
);
257 if ( nEndRow
== mnTabEndRow
) //bottom
258 aBox
.SetLine(&aOutLine
, SvxBoxItemLine::BOTTOM
);
260 aBox
.SetLine(&aLine
, SvxBoxItemLine::BOTTOM
);
262 SvxBoxInfoItem
aBoxInfo( ATTR_BORDER_INNER
);
263 aBoxInfo
.SetValid(SvxBoxInfoItemValidFlags::VERT
,false );
266 aBoxInfo
.SetValid(SvxBoxInfoItemValidFlags::HORI
,true);
267 aBoxInfo
.SetLine( &aLine
, SvxBoxInfoItemLine::HORI
);
270 aBoxInfo
.SetValid(SvxBoxInfoItemValidFlags::HORI
,false );
272 aBoxInfo
.SetValid(SvxBoxInfoItemValidFlags::DISTANCE
,false);
274 mpDoc
->ApplyFrameAreaTab( ScRange( nStartCol
, nStartRow
, mnTab
, nEndCol
, nEndRow
, mnTab
), &aBox
, &aBoxInfo
);
278 void lcl_SetStyleById( ScDocument
* pDoc
, SCTAB nTab
,
279 SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
,
282 if ( nCol1
> nCol2
|| nRow1
> nRow2
)
284 OSL_FAIL("SetStyleById: invalid range");
288 OUString aStyleName
= ScGlobal::GetRscString( nStrId
);
289 ScStyleSheetPool
* pStlPool
= pDoc
->GetStyleSheetPool();
290 ScStyleSheet
* pStyle
= static_cast<ScStyleSheet
*>( pStlPool
->Find( aStyleName
, SFX_STYLE_FAMILY_PARA
) );
293 // create new style (was in ScPivot::SetStyle)
295 pStyle
= static_cast<ScStyleSheet
*>( &pStlPool
->Make( aStyleName
, SFX_STYLE_FAMILY_PARA
,
296 SFXSTYLEBIT_USERDEF
) );
297 pStyle
->SetParent( ScGlobal::GetRscString(STR_STYLENAME_STANDARD
) );
298 SfxItemSet
& rSet
= pStyle
->GetItemSet();
299 if ( nStrId
==STR_PIVOT_STYLE_RESULT
|| nStrId
==STR_PIVOT_STYLE_TITLE
)
300 rSet
.Put( SvxWeightItem( WEIGHT_BOLD
, ATTR_FONT_WEIGHT
) );
301 if ( nStrId
==STR_PIVOT_STYLE_CATEGORY
|| nStrId
==STR_PIVOT_STYLE_TITLE
)
302 rSet
.Put( SvxHorJustifyItem( SVX_HOR_JUSTIFY_LEFT
, ATTR_HOR_JUSTIFY
) );
305 pDoc
->ApplyStyleAreaTab( nCol1
, nRow1
, nCol2
, nRow2
, nTab
, *pStyle
);
308 void lcl_SetFrame( ScDocument
* pDoc
, SCTAB nTab
,
309 SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
,
312 ::editeng::SvxBorderLine
aLine(0, nWidth
, table::BorderLineStyle::SOLID
);
313 SvxBoxItem
aBox( ATTR_BORDER
);
314 aBox
.SetLine(&aLine
, SvxBoxItemLine::LEFT
);
315 aBox
.SetLine(&aLine
, SvxBoxItemLine::TOP
);
316 aBox
.SetLine(&aLine
, SvxBoxItemLine::RIGHT
);
317 aBox
.SetLine(&aLine
, SvxBoxItemLine::BOTTOM
);
318 SvxBoxInfoItem
aBoxInfo( ATTR_BORDER_INNER
);
319 aBoxInfo
.SetValid(SvxBoxInfoItemValidFlags::HORI
,false);
320 aBoxInfo
.SetValid(SvxBoxInfoItemValidFlags::VERT
,false);
321 aBoxInfo
.SetValid(SvxBoxInfoItemValidFlags::DISTANCE
,false);
323 pDoc
->ApplyFrameAreaTab( ScRange( nCol1
, nRow1
, nTab
, nCol2
, nRow2
, nTab
), &aBox
, &aBoxInfo
);
326 void lcl_FillNumberFormats( sal_uInt32
*& rFormats
, long& rCount
,
327 const uno::Reference
<sheet::XDataPilotMemberResults
>& xLevRes
,
328 const uno::Reference
<container::XIndexAccess
>& xDims
)
331 return; // already set
333 // xLevRes is from the data layout dimension
334 //TODO: use result sequence from ScDPOutLevelData!
336 uno::Sequence
<sheet::MemberResult
> aResult
= xLevRes
->getResults();
338 long nSize
= aResult
.getLength();
342 // get names/formats for all data dimensions
343 //TODO: merge this with the loop to collect ScDPOutLevelData?
345 OUString aDataNames
[SC_DPOUT_MAXLEVELS
];
346 sal_uInt32 nDataFormats
[SC_DPOUT_MAXLEVELS
];
348 long nDimCount
= xDims
->getCount();
349 for (long nDim
=0; nDim
<nDimCount
; nDim
++)
351 uno::Reference
<uno::XInterface
> xDim
=
352 ScUnoHelpFunctions::AnyToInterface( xDims
->getByIndex(nDim
) );
353 uno::Reference
<beans::XPropertySet
> xDimProp( xDim
, uno::UNO_QUERY
);
354 uno::Reference
<container::XNamed
> xDimName( xDim
, uno::UNO_QUERY
);
355 if ( xDimProp
.is() && xDimName
.is() )
357 sheet::DataPilotFieldOrientation eDimOrient
=
358 (sheet::DataPilotFieldOrientation
) ScUnoHelpFunctions::GetEnumProperty(
359 xDimProp
, OUString(SC_UNO_DP_ORIENTATION
),
360 sheet::DataPilotFieldOrientation_HIDDEN
);
361 if ( eDimOrient
== sheet::DataPilotFieldOrientation_DATA
)
363 aDataNames
[nDataCount
] = xDimName
->getName();
364 long nFormat
= ScUnoHelpFunctions::GetLongProperty(
366 OUString(SC_UNONAME_NUMFMT
) );
367 nDataFormats
[nDataCount
] = nFormat
;
376 const sheet::MemberResult
* pArray
= aResult
.getConstArray();
379 sal_uInt32
* pNumFmt
= new sal_uInt32
[nSize
];
382 // only one data dimension -> use its numberformat everywhere
383 long nFormat
= nDataFormats
[0];
384 for (long nPos
=0; nPos
<nSize
; nPos
++)
385 pNumFmt
[nPos
] = nFormat
;
389 for (long nPos
=0; nPos
<nSize
; nPos
++)
391 // if CONTINUE bit is set, keep previous name
392 //TODO: keep number format instead!
393 if ( !(pArray
[nPos
].Flags
& sheet::MemberResultFlags::CONTINUE
) )
394 aName
= pArray
[nPos
].Name
;
396 sal_uInt32 nFormat
= 0;
397 for (long i
=0; i
<nDataCount
; i
++)
398 if (aName
== aDataNames
[i
]) //TODO: search more efficiently?
400 nFormat
= nDataFormats
[i
];
403 pNumFmt
[nPos
] = nFormat
;
411 sal_uInt32
lcl_GetFirstNumberFormat( const uno::Reference
<container::XIndexAccess
>& xDims
)
413 long nDimCount
= xDims
->getCount();
414 for (long nDim
=0; nDim
<nDimCount
; nDim
++)
416 uno::Reference
<uno::XInterface
> xDim
=
417 ScUnoHelpFunctions::AnyToInterface( xDims
->getByIndex(nDim
) );
418 uno::Reference
<beans::XPropertySet
> xDimProp( xDim
, uno::UNO_QUERY
);
421 sheet::DataPilotFieldOrientation eDimOrient
=
422 (sheet::DataPilotFieldOrientation
) ScUnoHelpFunctions::GetEnumProperty(
423 xDimProp
, OUString(SC_UNO_DP_ORIENTATION
),
424 sheet::DataPilotFieldOrientation_HIDDEN
);
425 if ( eDimOrient
== sheet::DataPilotFieldOrientation_DATA
)
427 long nFormat
= ScUnoHelpFunctions::GetLongProperty(
429 OUString(SC_UNONAME_NUMFMT
) );
431 return nFormat
; // use format from first found data dimension
436 return 0; // none found
439 void lcl_SortFields( ScDPOutLevelData
* pFields
, long nFieldCount
)
441 for (long i
=0; i
+1<nFieldCount
; i
++)
443 for (long j
=0; j
+i
+1<nFieldCount
; j
++)
444 if ( pFields
[j
+1] < pFields
[j
] )
445 pFields
[j
].Swap( pFields
[j
+1] );
449 bool lcl_MemberEmpty( const uno::Sequence
<sheet::MemberResult
>& rSeq
)
451 // used to skip levels that have no members
453 long nLen
= rSeq
.getLength();
454 const sheet::MemberResult
* pArray
= rSeq
.getConstArray();
455 for (long i
=0; i
<nLen
; i
++)
456 if (pArray
[i
].Flags
& sheet::MemberResultFlags::HASMEMBER
)
459 return true; // no member data -> empty
463 * Get visible page dimension members as results, except that, if all
464 * members are visible, then this function returns empty result.
466 uno::Sequence
<sheet::MemberResult
> getVisiblePageMembersAsResults( const uno::Reference
<uno::XInterface
>& xLevel
)
469 return uno::Sequence
<sheet::MemberResult
>();
471 uno::Reference
<sheet::XMembersSupplier
> xMSupplier(xLevel
, UNO_QUERY
);
472 if (!xMSupplier
.is())
473 return uno::Sequence
<sheet::MemberResult
>();
475 uno::Reference
<container::XNameAccess
> xNA
= xMSupplier
->getMembers();
477 return uno::Sequence
<sheet::MemberResult
>();
479 std::vector
<sheet::MemberResult
> aRes
;
480 uno::Sequence
<OUString
> aNames
= xNA
->getElementNames();
481 for (sal_Int32 i
= 0; i
< aNames
.getLength(); ++i
)
483 const OUString
& rName
= aNames
[i
];
484 xNA
->getByName(rName
);
486 uno::Reference
<beans::XPropertySet
> xMemPS(xNA
->getByName(rName
), UNO_QUERY
);
490 OUString aCaption
= ScUnoHelpFunctions::GetStringProperty(xMemPS
, SC_UNO_DP_LAYOUTNAME
, OUString());
491 if (aCaption
.isEmpty())
494 bool bVisible
= ScUnoHelpFunctions::GetBoolProperty(xMemPS
, SC_UNO_DP_ISVISIBLE
, false);
497 aRes
.push_back(sheet::MemberResult(rName
, aCaption
, 0));
500 if (aNames
.getLength() == static_cast<sal_Int32
>(aRes
.size()))
501 // All members are visible. Return empty result.
502 return uno::Sequence
<sheet::MemberResult
>();
504 return ScUnoHelpFunctions::VectorToSequence(aRes
);
509 ScDPOutput::ScDPOutput( ScDocument
* pD
, const uno::Reference
<sheet::XDimensionsSupplier
>& xSrc
,
510 const ScAddress
& rPos
, bool bFilter
) :
523 bResultsError(false),
524 mbHasDataLayout(false),
526 bSizeOverflow(false),
527 mbHeaderLayout(false)
529 nTabStartCol
= nMemberStartCol
= nDataStartCol
= nTabEndCol
= 0;
530 nTabStartRow
= nMemberStartRow
= nDataStartRow
= nTabEndRow
= 0;
532 pColFields
= new ScDPOutLevelData
[SC_DPOUT_MAXLEVELS
];
533 pRowFields
= new ScDPOutLevelData
[SC_DPOUT_MAXLEVELS
];
534 pPageFields
= new ScDPOutLevelData
[SC_DPOUT_MAXLEVELS
];
539 uno::Reference
<sheet::XDataPilotResults
> xResult( xSource
, uno::UNO_QUERY
);
540 if ( xSource
.is() && xResult
.is() )
542 // get dimension results:
544 uno::Reference
<container::XIndexAccess
> xDims
=
545 new ScNameToIndexAccess( xSource
->getDimensions() );
546 long nDimCount
= xDims
->getCount();
547 for (long nDim
=0; nDim
<nDimCount
; nDim
++)
549 uno::Reference
<uno::XInterface
> xDim
=
550 ScUnoHelpFunctions::AnyToInterface( xDims
->getByIndex(nDim
) );
551 uno::Reference
<beans::XPropertySet
> xDimProp( xDim
, uno::UNO_QUERY
);
552 uno::Reference
<sheet::XHierarchiesSupplier
> xDimSupp( xDim
, uno::UNO_QUERY
);
553 if ( xDimProp
.is() && xDimSupp
.is() )
555 sheet::DataPilotFieldOrientation eDimOrient
=
556 (sheet::DataPilotFieldOrientation
) ScUnoHelpFunctions::GetEnumProperty(
557 xDimProp
, OUString(SC_UNO_DP_ORIENTATION
),
558 sheet::DataPilotFieldOrientation_HIDDEN
);
559 long nDimPos
= ScUnoHelpFunctions::GetLongProperty( xDimProp
,
560 OUString(SC_UNO_DP_POSITION
) );
561 bool bIsDataLayout
= ScUnoHelpFunctions::GetBoolProperty(
562 xDimProp
, OUString(SC_UNO_DP_ISDATALAYOUT
));
563 bool bHasHiddenMember
= ScUnoHelpFunctions::GetBoolProperty(
564 xDimProp
, OUString(SC_UNO_DP_HAS_HIDDEN_MEMBER
));
565 sal_Int32 nNumFmt
= ScUnoHelpFunctions::GetLongProperty(
566 xDimProp
, SC_UNO_DP_NUMBERFO
, 0);
568 if ( eDimOrient
!= sheet::DataPilotFieldOrientation_HIDDEN
)
570 uno::Reference
<container::XIndexAccess
> xHiers
=
571 new ScNameToIndexAccess( xDimSupp
->getHierarchies() );
572 long nHierarchy
= ScUnoHelpFunctions::GetLongProperty(
574 OUString(SC_UNO_DP_USEDHIERARCHY
) );
575 if ( nHierarchy
>= xHiers
->getCount() )
578 uno::Reference
<uno::XInterface
> xHier
=
579 ScUnoHelpFunctions::AnyToInterface(
580 xHiers
->getByIndex(nHierarchy
) );
581 uno::Reference
<sheet::XLevelsSupplier
> xHierSupp( xHier
, uno::UNO_QUERY
);
582 if ( xHierSupp
.is() )
584 uno::Reference
<container::XIndexAccess
> xLevels
=
585 new ScNameToIndexAccess( xHierSupp
->getLevels() );
586 long nLevCount
= xLevels
->getCount();
587 for (long nLev
=0; nLev
<nLevCount
; nLev
++)
589 uno::Reference
<uno::XInterface
> xLevel
=
590 ScUnoHelpFunctions::AnyToInterface(
591 xLevels
->getByIndex(nLev
) );
592 uno::Reference
<container::XNamed
> xLevNam( xLevel
, uno::UNO_QUERY
);
593 uno::Reference
<sheet::XDataPilotMemberResults
> xLevRes(
594 xLevel
, uno::UNO_QUERY
);
595 if ( xLevNam
.is() && xLevRes
.is() )
597 OUString aName
= xLevNam
->getName();
598 Reference
<XPropertySet
> xPropSet(xLevel
, UNO_QUERY
);
599 // Caption equals the field name by default.
600 // #i108948# use ScUnoHelpFunctions::GetStringProperty, because
601 // LayoutName is new and may not be present in external implementation
602 OUString aCaption
= ScUnoHelpFunctions::GetStringProperty( xPropSet
,
603 OUString(SC_UNO_DP_LAYOUTNAME
), aName
);
605 bool bRowFieldHasMember
= false;
606 switch ( eDimOrient
)
608 case sheet::DataPilotFieldOrientation_COLUMN
:
609 pColFields
[nColFieldCount
].nDim
= nDim
;
610 pColFields
[nColFieldCount
].nHier
= nHierarchy
;
611 pColFields
[nColFieldCount
].nLevel
= nLev
;
612 pColFields
[nColFieldCount
].nDimPos
= nDimPos
;
613 pColFields
[nColFieldCount
].aResult
= xLevRes
->getResults();
614 pColFields
[nColFieldCount
].mnSrcNumFmt
= nNumFmt
;
615 pColFields
[nColFieldCount
].maName
= aName
;
616 pColFields
[nColFieldCount
].maCaption
= aCaption
;
617 pColFields
[nColFieldCount
].mbHasHiddenMember
= bHasHiddenMember
;
618 pColFields
[nColFieldCount
].mbDataLayout
= bIsDataLayout
;
619 if (!lcl_MemberEmpty(pColFields
[nColFieldCount
].aResult
))
622 case sheet::DataPilotFieldOrientation_ROW
:
623 pRowFields
[nRowFieldCount
].nDim
= nDim
;
624 pRowFields
[nRowFieldCount
].nHier
= nHierarchy
;
625 pRowFields
[nRowFieldCount
].nLevel
= nLev
;
626 pRowFields
[nRowFieldCount
].nDimPos
= nDimPos
;
627 pRowFields
[nRowFieldCount
].aResult
= xLevRes
->getResults();
628 pRowFields
[nRowFieldCount
].mnSrcNumFmt
= nNumFmt
;
629 pRowFields
[nRowFieldCount
].maName
= aName
;
630 pRowFields
[nRowFieldCount
].maCaption
= aCaption
;
631 pRowFields
[nRowFieldCount
].mbHasHiddenMember
= bHasHiddenMember
;
632 pRowFields
[nRowFieldCount
].mbDataLayout
= bIsDataLayout
;
633 if (!lcl_MemberEmpty(pRowFields
[nRowFieldCount
].aResult
))
636 bRowFieldHasMember
= true;
639 case sheet::DataPilotFieldOrientation_PAGE
:
640 pPageFields
[nPageFieldCount
].nDim
= nDim
;
641 pPageFields
[nPageFieldCount
].nHier
= nHierarchy
;
642 pPageFields
[nPageFieldCount
].nLevel
= nLev
;
643 pPageFields
[nPageFieldCount
].nDimPos
= nDimPos
;
644 pPageFields
[nPageFieldCount
].aResult
= getVisiblePageMembersAsResults(xLevel
);
645 pPageFields
[nPageFieldCount
].mnSrcNumFmt
= nNumFmt
;
646 pPageFields
[nPageFieldCount
].maName
= aName
;
647 pPageFields
[nPageFieldCount
].maCaption
= aCaption
;
648 pPageFields
[nPageFieldCount
].mbHasHiddenMember
= bHasHiddenMember
;
649 pPageFields
[nPageFieldCount
].mbPageDim
= true;
650 // no check on results for page fields
655 // added to avoid warnings
659 // get number formats from data dimensions
662 if (bRowFieldHasMember
)
663 mbHasDataLayout
= true;
665 OSL_ENSURE( nLevCount
== 1, "data layout: multiple levels?" );
666 if ( eDimOrient
== sheet::DataPilotFieldOrientation_COLUMN
)
667 lcl_FillNumberFormats( pColNumFmt
, nColFmtCount
, xLevRes
, xDims
);
668 else if ( eDimOrient
== sheet::DataPilotFieldOrientation_ROW
)
669 lcl_FillNumberFormats( pRowNumFmt
, nRowFmtCount
, xLevRes
, xDims
);
675 else if ( bIsDataLayout
)
677 // data layout dimension is hidden (allowed if there is only one data dimension)
678 // -> use the number format from the first data dimension for all results
680 nSingleNumFmt
= lcl_GetFirstNumberFormat( xDims
);
684 lcl_SortFields( pColFields
, nColFieldCount
);
685 lcl_SortFields( pRowFields
, nRowFieldCount
);
686 lcl_SortFields( pPageFields
, nPageFieldCount
);
692 aData
= xResult
->getResults();
694 catch (const uno::RuntimeException
&)
696 bResultsError
= true;
700 // get "DataDescription" property (may be missing in external sources)
702 uno::Reference
<beans::XPropertySet
> xSrcProp( xSource
, uno::UNO_QUERY
);
707 uno::Any aAny
= xSrcProp
->getPropertyValue(
708 OUString(SC_UNO_DP_DATADESC
) );
711 aDataDescription
= aUStr
;
713 catch(const uno::Exception
&)
719 ScDPOutput::~ScDPOutput()
723 delete[] pPageFields
;
729 void ScDPOutput::SetPosition( const ScAddress
& rPos
)
732 bSizesValid
= bSizeOverflow
= false;
735 void ScDPOutput::DataCell( SCCOL nCol
, SCROW nRow
, SCTAB nTab
, const sheet::DataResult
& rData
)
737 long nFlags
= rData
.Flags
;
738 if ( nFlags
& sheet::DataResultFlags::ERROR
)
740 pDoc
->SetError( nCol
, nRow
, nTab
, errNoValue
);
742 else if ( nFlags
& sheet::DataResultFlags::HASDATA
)
744 pDoc
->SetValue( nCol
, nRow
, nTab
, rData
.Value
);
746 // use number formats from source
748 OSL_ENSURE( bSizesValid
, "DataCell: !bSizesValid" );
749 sal_uInt32 nFormat
= 0;
750 bool bApplyFormat
= false;
753 if ( nCol
>= nDataStartCol
)
755 long nIndex
= nCol
- nDataStartCol
;
756 if ( nIndex
< nColFmtCount
)
758 nFormat
= pColNumFmt
[nIndex
];
763 else if ( pRowNumFmt
)
765 if ( nRow
>= nDataStartRow
)
767 long nIndex
= nRow
- nDataStartRow
;
768 if ( nIndex
< nRowFmtCount
)
770 nFormat
= pRowNumFmt
[nIndex
];
775 else if ( nSingleNumFmt
!= 0 )
777 nFormat
= nSingleNumFmt
; // single format is used everywhere
782 pDoc
->ApplyAttr(nCol
, nRow
, nTab
, SfxUInt32Item(ATTR_VALUE_FORMAT
, nFormat
));
784 // SubTotal formatting is controlled by headers
787 void ScDPOutput::HeaderCell( SCCOL nCol
, SCROW nRow
, SCTAB nTab
,
788 const sheet::MemberResult
& rData
, bool bColHeader
, long nLevel
)
790 long nFlags
= rData
.Flags
;
792 if ( nFlags
& sheet::MemberResultFlags::HASMEMBER
)
794 bool bNumeric
= (nFlags
& sheet::MemberResultFlags::NUMERIC
) != 0;
795 ScSetStringParam aParam
;
797 aParam
.setNumericInput();
799 aParam
.setTextInput();
801 pDoc
->SetString(nCol
, nRow
, nTab
, rData
.Caption
, &aParam
);
804 if ( nFlags
& sheet::MemberResultFlags::SUBTOTAL
)
806 ScDPOutputImpl
outputimp( pDoc
, nTab
,
807 nTabStartCol
, nTabStartRow
,
808 nDataStartCol
, nDataStartRow
, nTabEndCol
, nTabEndRow
);
809 //TODO: limit frames to horizontal or vertical?
812 outputimp
.OutputBlockFrame( nCol
,nMemberStartRow
+(SCROW
)nLevel
, nCol
,nDataStartRow
-1 );
814 lcl_SetStyleById( pDoc
,nTab
, nCol
,nMemberStartRow
+(SCROW
)nLevel
, nCol
,nDataStartRow
-1,
815 STR_PIVOT_STYLE_TITLE
);
816 lcl_SetStyleById( pDoc
,nTab
, nCol
,nDataStartRow
, nCol
,nTabEndRow
,
817 STR_PIVOT_STYLE_RESULT
);
821 outputimp
.OutputBlockFrame( nMemberStartCol
+(SCCOL
)nLevel
,nRow
, nDataStartCol
-1,nRow
);
822 lcl_SetStyleById( pDoc
,nTab
, nMemberStartCol
+(SCCOL
)nLevel
,nRow
, nDataStartCol
-1,nRow
,
823 STR_PIVOT_STYLE_TITLE
);
824 lcl_SetStyleById( pDoc
,nTab
, nDataStartCol
,nRow
, nTabEndCol
,nRow
,
825 STR_PIVOT_STYLE_RESULT
);
830 void ScDPOutput::FieldCell(
831 SCCOL nCol
, SCROW nRow
, SCTAB nTab
, const ScDPOutLevelData
& rData
, bool bInTable
)
833 // Avoid unwanted automatic format detection.
834 ScSetStringParam aParam
;
835 aParam
.mbDetectNumberFormat
= false;
836 aParam
.meSetTextNumFormat
= ScSetStringParam::Always
;
837 aParam
.mbHandleApostrophe
= false;
838 pDoc
->SetString(nCol
, nRow
, nTab
, rData
.maCaption
, &aParam
);
841 lcl_SetFrame( pDoc
,nTab
, nCol
,nRow
, nCol
,nRow
, 20 );
843 // For field button drawing
844 sal_uInt16 nMergeFlag
= 0;
845 if (rData
.mbHasHiddenMember
)
846 nMergeFlag
|= SC_MF_HIDDEN_MEMBER
;
850 nMergeFlag
|= SC_MF_BUTTON_POPUP
;
851 pDoc
->ApplyFlagsTab(nCol
, nRow
, nCol
, nRow
, nTab
, SC_MF_BUTTON
);
852 pDoc
->ApplyFlagsTab(nCol
+1, nRow
, nCol
+1, nRow
, nTab
, nMergeFlag
);
856 nMergeFlag
|= SC_MF_BUTTON
;
857 if (!rData
.mbDataLayout
)
858 nMergeFlag
|= SC_MF_BUTTON_POPUP
;
859 pDoc
->ApplyFlagsTab(nCol
, nRow
, nCol
, nRow
, nTab
, nMergeFlag
);
862 lcl_SetStyleById( pDoc
,nTab
, nCol
,nRow
, nCol
,nRow
, STR_PIVOT_STYLE_FIELDNAME
);
865 static void lcl_DoFilterButton( ScDocument
* pDoc
, SCCOL nCol
, SCROW nRow
, SCTAB nTab
)
867 pDoc
->SetString( nCol
, nRow
, nTab
, ScGlobal::GetRscString(STR_CELL_FILTER
) );
868 pDoc
->ApplyFlagsTab(nCol
, nRow
, nCol
, nRow
, nTab
, SC_MF_BUTTON
);
871 void ScDPOutput::CalcSizes()
875 // get column size of data from first row
876 //TODO: allow different sizes (and clear following areas) ???
878 nRowCount
= aData
.getLength();
879 const uno::Sequence
<sheet::DataResult
>* pRowAry
= aData
.getConstArray();
880 nColCount
= nRowCount
? ( pRowAry
[0].getLength() ) : 0;
883 if (GetHeaderLayout() && nColFieldCount
== 0)
884 // Insert an extra header row only when there is no column field.
887 // calculate output positions and sizes
889 long nPageSize
= 0; // use page fields!
890 if ( bDoFilter
|| nPageFieldCount
)
892 nPageSize
+= nPageFieldCount
+ 1; // plus one empty row
894 ++nPageSize
; // filter button above the page fields
897 if ( aStartPos
.Col() + nRowFieldCount
+ nColCount
- 1 > MAXCOL
||
898 aStartPos
.Row() + nPageSize
+ nHeaderSize
+ nColFieldCount
+ nRowCount
> MAXROW
)
900 bSizeOverflow
= true;
903 nTabStartCol
= aStartPos
.Col();
904 nTabStartRow
= aStartPos
.Row() + (SCROW
)nPageSize
; // below page fields
905 nMemberStartCol
= nTabStartCol
;
906 nMemberStartRow
= nTabStartRow
+ (SCROW
) nHeaderSize
;
907 nDataStartCol
= nMemberStartCol
+ (SCCOL
)nRowFieldCount
;
908 nDataStartRow
= nMemberStartRow
+ (SCROW
)nColFieldCount
;
910 nTabEndCol
= nDataStartCol
+ (SCCOL
)nColCount
- 1;
912 nTabEndCol
= nDataStartCol
; // single column will remain empty
913 // if page fields are involved, include the page selection cells
914 if ( nPageFieldCount
> 0 && nTabEndCol
< nTabStartCol
+ 1 )
915 nTabEndCol
= nTabStartCol
+ 1;
917 nTabEndRow
= nDataStartRow
+ (SCROW
)nRowCount
- 1;
919 nTabEndRow
= nDataStartRow
; // single row will remain empty
924 sal_Int32
ScDPOutput::GetPositionType(const ScAddress
& rPos
)
926 using namespace ::com::sun::star::sheet
;
928 SCCOL nCol
= rPos
.Col();
929 SCROW nRow
= rPos
.Row();
930 SCTAB nTab
= rPos
.Tab();
931 if ( nTab
!= aStartPos
.Tab() )
932 return DataPilotTablePositionType::NOT_IN_TABLE
;
936 // Make sure the cursor is within the table.
937 if (nCol
< nTabStartCol
|| nRow
< nTabStartRow
|| nCol
> nTabEndCol
|| nRow
> nTabEndRow
)
938 return DataPilotTablePositionType::NOT_IN_TABLE
;
940 // test for result data area.
941 if (nCol
>= nDataStartCol
&& nCol
<= nTabEndCol
&& nRow
>= nDataStartRow
&& nRow
<= nTabEndRow
)
942 return DataPilotTablePositionType::RESULT
;
944 bool bInColHeader
= (nRow
>= nTabStartRow
&& nRow
< nDataStartRow
);
945 bool bInRowHeader
= (nCol
>= nTabStartCol
&& nCol
< nDataStartCol
);
947 if (bInColHeader
&& bInRowHeader
)
948 // probably in that ugly little box at the upper-left corner of the table.
949 return DataPilotTablePositionType::OTHER
;
953 if (nRow
== nTabStartRow
)
954 // first row in the column header area is always used for column
956 return DataPilotTablePositionType::OTHER
;
958 return DataPilotTablePositionType::COLUMN_HEADER
;
962 return DataPilotTablePositionType::ROW_HEADER
;
964 return DataPilotTablePositionType::OTHER
;
967 void ScDPOutput::Output()
970 SCTAB nTab
= aStartPos
.Tab();
971 const uno::Sequence
<sheet::DataResult
>* pRowAry
= aData
.getConstArray();
973 // calculate output positions and sizes
976 if ( bSizeOverflow
|| bResultsError
) // does output area exceed sheet limits?
979 // clear whole (new) output area
980 // when modifying table, clear old area !
981 //TODO: include IDF_OBJECTS ???
982 pDoc
->DeleteAreaTab( aStartPos
.Col(), aStartPos
.Row(), nTabEndCol
, nTabEndRow
, nTab
, IDF_ALL
);
985 lcl_DoFilterButton( pDoc
, aStartPos
.Col(), aStartPos
.Row(), nTab
);
987 // output page fields:
989 for (nField
=0; nField
<nPageFieldCount
; nField
++)
991 SCCOL nHdrCol
= aStartPos
.Col();
992 SCROW nHdrRow
= aStartPos
.Row() + nField
+ ( bDoFilter
? 1 : 0 );
993 // draw without frame for consistency with filter button:
994 FieldCell(nHdrCol
, nHdrRow
, nTab
, pPageFields
[nField
], false);
995 SCCOL nFldCol
= nHdrCol
+ 1;
997 OUString aPageValue
= ScResId(SCSTR_ALL
).toString();
998 const uno::Sequence
<sheet::MemberResult
>& rRes
= pPageFields
[nField
].aResult
;
999 sal_Int32 n
= rRes
.getLength();
1001 aPageValue
= rRes
[0].Caption
;
1003 aPageValue
= ScResId(SCSTR_MULTIPLE
).toString();
1005 ScSetStringParam aParam
;
1006 aParam
.setTextInput();
1007 pDoc
->SetString(nFldCol
, nHdrRow
, nTab
, aPageValue
, &aParam
);
1009 lcl_SetFrame( pDoc
,nTab
, nFldCol
,nHdrRow
, nFldCol
,nHdrRow
, 20 );
1013 // (may get overwritten by first row field)
1015 if (aDataDescription
.isEmpty())
1017 //TODO: use default string ("result") ?
1019 pDoc
->SetString(nTabStartCol
, nTabStartRow
, nTab
, aDataDescription
);
1021 // set STR_PIVOT_STYLE_INNER for whole data area (subtotals are overwritten)
1023 if ( nDataStartRow
> nTabStartRow
)
1024 lcl_SetStyleById( pDoc
, nTab
, nTabStartCol
, nTabStartRow
, nTabEndCol
, nDataStartRow
-1,
1025 STR_PIVOT_STYLE_TOP
);
1026 lcl_SetStyleById( pDoc
, nTab
, nDataStartCol
, nDataStartRow
, nTabEndCol
, nTabEndRow
,
1027 STR_PIVOT_STYLE_INNER
);
1029 // output column headers:
1030 ScDPOutputImpl
outputimp( pDoc
, nTab
,
1031 nTabStartCol
, nTabStartRow
,
1032 nDataStartCol
, nDataStartRow
, nTabEndCol
, nTabEndRow
);
1033 for (nField
=0; nField
<nColFieldCount
; nField
++)
1035 SCCOL nHdrCol
= nDataStartCol
+ (SCCOL
)nField
; //TODO: check for overflow
1036 FieldCell(nHdrCol
, nTabStartRow
, nTab
, pColFields
[nField
], true);
1038 SCROW nRowPos
= nMemberStartRow
+ (SCROW
)nField
; //TODO: check for overflow
1039 const uno::Sequence
<sheet::MemberResult
> rSequence
= pColFields
[nField
].aResult
;
1040 const sheet::MemberResult
* pArray
= rSequence
.getConstArray();
1041 long nThisColCount
= rSequence
.getLength();
1042 OSL_ENSURE( nThisColCount
== nColCount
, "count mismatch" ); //TODO: ???
1043 for (long nCol
=0; nCol
<nThisColCount
; nCol
++)
1045 SCCOL nColPos
= nDataStartCol
+ (SCCOL
)nCol
; //TODO: check for overflow
1046 HeaderCell( nColPos
, nRowPos
, nTab
, pArray
[nCol
], true, nField
);
1047 if ( ( pArray
[nCol
].Flags
& sheet::MemberResultFlags::HASMEMBER
) &&
1048 !( pArray
[nCol
].Flags
& sheet::MemberResultFlags::SUBTOTAL
) )
1051 while ( nEnd
+1 < nThisColCount
&& ( pArray
[nEnd
+1].Flags
& sheet::MemberResultFlags::CONTINUE
) )
1053 SCCOL nEndColPos
= nDataStartCol
+ (SCCOL
)nEnd
; //TODO: check for overflow
1054 if ( nField
+1 < nColFieldCount
)
1056 if ( nField
== nColFieldCount
- 2 )
1058 outputimp
.AddCol( nColPos
);
1059 if ( nColPos
+ 1 == nEndColPos
)
1060 outputimp
.OutputBlockFrame( nColPos
,nRowPos
, nEndColPos
,nRowPos
+1, true );
1063 outputimp
.OutputBlockFrame( nColPos
,nRowPos
, nEndColPos
,nRowPos
);
1065 lcl_SetStyleById( pDoc
, nTab
, nColPos
,nRowPos
, nEndColPos
,nDataStartRow
-1, STR_PIVOT_STYLE_CATEGORY
);
1068 lcl_SetStyleById( pDoc
, nTab
, nColPos
,nRowPos
, nColPos
,nDataStartRow
-1, STR_PIVOT_STYLE_CATEGORY
);
1070 else if ( pArray
[nCol
].Flags
& sheet::MemberResultFlags::SUBTOTAL
)
1071 outputimp
.AddCol( nColPos
);
1073 // Apply the same number format as in data source.
1074 pDoc
->ApplyAttr(nColPos
, nRowPos
, nTab
, SfxUInt32Item(ATTR_VALUE_FORMAT
, pColFields
[nField
].mnSrcNumFmt
));
1076 if ( nField
== 0 && nColFieldCount
== 1 )
1077 outputimp
.OutputBlockFrame( nDataStartCol
,nTabStartRow
, nTabEndCol
,nRowPos
-1 );
1080 // output row headers:
1081 std::vector
<bool> vbSetBorder
;
1082 vbSetBorder
.resize( nTabEndRow
- nDataStartRow
+ 1, false );
1083 for (nField
=0; nField
<nRowFieldCount
; nField
++)
1085 SCCOL nHdrCol
= nTabStartCol
+ (SCCOL
)nField
; //TODO: check for overflow
1086 SCROW nHdrRow
= nDataStartRow
- 1;
1087 FieldCell(nHdrCol
, nHdrRow
, nTab
, pRowFields
[nField
], true);
1089 SCCOL nColPos
= nMemberStartCol
+ (SCCOL
)nField
; //TODO: check for overflow
1090 const uno::Sequence
<sheet::MemberResult
> rSequence
= pRowFields
[nField
].aResult
;
1091 const sheet::MemberResult
* pArray
= rSequence
.getConstArray();
1092 long nThisRowCount
= rSequence
.getLength();
1093 OSL_ENSURE( nThisRowCount
== nRowCount
, "count mismatch" ); //TODO: ???
1094 for (long nRow
=0; nRow
<nThisRowCount
; nRow
++)
1096 SCROW nRowPos
= nDataStartRow
+ (SCROW
)nRow
; //TODO: check for overflow
1097 HeaderCell( nColPos
, nRowPos
, nTab
, pArray
[nRow
], false, nField
);
1098 if ( ( pArray
[nRow
].Flags
& sheet::MemberResultFlags::HASMEMBER
) &&
1099 !( pArray
[nRow
].Flags
& sheet::MemberResultFlags::SUBTOTAL
) )
1101 if ( nField
+1 < nRowFieldCount
)
1104 while ( nEnd
+1 < nThisRowCount
&& ( pArray
[nEnd
+1].Flags
& sheet::MemberResultFlags::CONTINUE
) )
1106 SCROW nEndRowPos
= nDataStartRow
+ (SCROW
)nEnd
; //TODO: check for overflow
1107 outputimp
.AddRow( nRowPos
);
1108 if ( !vbSetBorder
[ nRow
] )
1110 outputimp
.OutputBlockFrame( nColPos
, nRowPos
, nTabEndCol
, nEndRowPos
);
1111 vbSetBorder
[ nRow
] = true;
1113 outputimp
.OutputBlockFrame( nColPos
, nRowPos
, nColPos
, nEndRowPos
);
1115 if ( nField
== nRowFieldCount
- 2 )
1116 outputimp
.OutputBlockFrame( nColPos
+1, nRowPos
, nColPos
+1, nEndRowPos
);
1118 lcl_SetStyleById( pDoc
, nTab
, nColPos
,nRowPos
, nDataStartCol
-1,nEndRowPos
, STR_PIVOT_STYLE_CATEGORY
);
1121 lcl_SetStyleById( pDoc
, nTab
, nColPos
,nRowPos
, nDataStartCol
-1,nRowPos
, STR_PIVOT_STYLE_CATEGORY
);
1123 else if ( pArray
[nRow
].Flags
& sheet::MemberResultFlags::SUBTOTAL
)
1124 outputimp
.AddRow( nRowPos
);
1126 // Apply the same number format as in data source.
1127 pDoc
->ApplyAttr(nColPos
, nRowPos
, nTab
, SfxUInt32Item(ATTR_VALUE_FORMAT
, pRowFields
[nField
].mnSrcNumFmt
));
1131 if (nColCount
== 1 && nRowCount
> 0 && nColFieldCount
== 0)
1133 // the table contains exactly one data field and no column fields.
1134 // Display data description at top right corner.
1135 ScSetStringParam aParam
;
1136 aParam
.setTextInput();
1137 pDoc
->SetString(nDataStartCol
, nDataStartRow
-1, nTab
, aDataDescription
, &aParam
);
1140 // output data results:
1142 for (long nRow
=0; nRow
<nRowCount
; nRow
++)
1144 SCROW nRowPos
= nDataStartRow
+ (SCROW
)nRow
; //TODO: check for overflow
1145 const sheet::DataResult
* pColAry
= pRowAry
[nRow
].getConstArray();
1146 long nThisColCount
= pRowAry
[nRow
].getLength();
1147 OSL_ENSURE( nThisColCount
== nColCount
, "count mismatch" ); //TODO: ???
1148 for (long nCol
=0; nCol
<nThisColCount
; nCol
++)
1150 SCCOL nColPos
= nDataStartCol
+ (SCCOL
)nCol
; //TODO: check for overflow
1151 DataCell( nColPos
, nRowPos
, nTab
, pColAry
[nCol
] );
1155 outputimp
.OutputDataArea();
1158 ScRange
ScDPOutput::GetOutputRange( sal_Int32 nRegionType
)
1160 using namespace ::com::sun::star::sheet
;
1164 SCTAB nTab
= aStartPos
.Tab();
1165 switch (nRegionType
)
1167 case DataPilotOutputRangeType::RESULT
:
1168 return ScRange(nDataStartCol
, nDataStartRow
, nTab
, nTabEndCol
, nTabEndRow
, nTab
);
1169 case DataPilotOutputRangeType::TABLE
:
1170 return ScRange(aStartPos
.Col(), nTabStartRow
, nTab
, nTabEndCol
, nTabEndRow
, nTab
);
1172 OSL_ENSURE(nRegionType
== DataPilotOutputRangeType::WHOLE
, "ScDPOutput::GetOutputRange: unknown region type");
1175 return ScRange(aStartPos
.Col(), aStartPos
.Row(), nTab
, nTabEndCol
, nTabEndRow
, nTab
);
1178 ScRange
ScDPOutput::GetOutputRange( sal_Int32 nRegionType
) const
1180 using namespace ::com::sun::star::sheet
;
1183 return ScRange(ScAddress::INITIALIZE_INVALID
);
1185 SCTAB nTab
= aStartPos
.Tab();
1186 switch (nRegionType
)
1188 case DataPilotOutputRangeType::RESULT
:
1189 return ScRange(nDataStartCol
, nDataStartRow
, nTab
, nTabEndCol
, nTabEndRow
, nTab
);
1190 case DataPilotOutputRangeType::TABLE
:
1191 return ScRange(aStartPos
.Col(), nTabStartRow
, nTab
, nTabEndCol
, nTabEndRow
, nTab
);
1193 OSL_ENSURE(nRegionType
== DataPilotOutputRangeType::WHOLE
, "ScDPOutput::GetOutputRange: unknown region type");
1196 return ScRange(aStartPos
.Col(), aStartPos
.Row(), nTab
, nTabEndCol
, nTabEndRow
, nTab
);
1199 bool ScDPOutput::HasError()
1203 return bSizeOverflow
|| bResultsError
;
1206 long ScDPOutput::GetHeaderRows()
1208 return nPageFieldCount
+ ( bDoFilter
? 1 : 0 );
1211 void ScDPOutput::GetMemberResultNames(ScDPUniqueStringSet
& rNames
, long nDimension
)
1213 // Return the list of all member names in a dimension's MemberResults.
1214 // Only the dimension has to be compared because this is only used with table data,
1215 // where each dimension occurs only once.
1217 uno::Sequence
<sheet::MemberResult
> aMemberResults
;
1218 bool bFound
= false;
1221 // look in column fields
1223 for (nField
=0; nField
<nColFieldCount
&& !bFound
; nField
++)
1224 if ( pColFields
[nField
].nDim
== nDimension
)
1226 aMemberResults
= pColFields
[nField
].aResult
;
1230 // look in row fields
1232 for (nField
=0; nField
<nRowFieldCount
&& !bFound
; nField
++)
1233 if ( pRowFields
[nField
].nDim
== nDimension
)
1235 aMemberResults
= pRowFields
[nField
].aResult
;
1239 // collect the member names
1243 const sheet::MemberResult
* pArray
= aMemberResults
.getConstArray();
1244 long nResultCount
= aMemberResults
.getLength();
1246 for (long nItem
=0; nItem
<nResultCount
; nItem
++)
1248 if ( pArray
[nItem
].Flags
& sheet::MemberResultFlags::HASMEMBER
)
1249 rNames
.insert(pArray
[nItem
].Name
);
1254 void ScDPOutput::SetHeaderLayout(bool bUseGrid
)
1256 mbHeaderLayout
= bUseGrid
;
1257 bSizesValid
= false;
1262 void lcl_GetTableVars( sal_Int32
& rGrandTotalCols
, sal_Int32
& rGrandTotalRows
, sal_Int32
& rDataLayoutIndex
,
1263 std::vector
<OUString
>& rDataNames
, std::vector
<OUString
>& rGivenNames
,
1264 sheet::DataPilotFieldOrientation
& rDataOrient
,
1265 const uno::Reference
<sheet::XDimensionsSupplier
>& xSource
)
1267 rDataLayoutIndex
= -1; // invalid
1268 rGrandTotalCols
= 0;
1269 rGrandTotalRows
= 0;
1270 rDataOrient
= sheet::DataPilotFieldOrientation_HIDDEN
;
1272 uno::Reference
<beans::XPropertySet
> xSrcProp( xSource
, uno::UNO_QUERY
);
1273 bool bColGrand
= ScUnoHelpFunctions::GetBoolProperty(
1274 xSrcProp
, OUString(SC_UNO_DP_COLGRAND
));
1276 rGrandTotalCols
= 1; // default if data layout not in columns
1278 bool bRowGrand
= ScUnoHelpFunctions::GetBoolProperty(
1279 xSrcProp
, OUString(SC_UNO_DP_ROWGRAND
));
1281 rGrandTotalRows
= 1; // default if data layout not in rows
1285 // find index and orientation of "data layout" dimension, count data dimensions
1287 sal_Int32 nDataCount
= 0;
1289 uno::Reference
<container::XIndexAccess
> xDims
= new ScNameToIndexAccess( xSource
->getDimensions() );
1290 long nDimCount
= xDims
->getCount();
1291 for (long nDim
=0; nDim
<nDimCount
; nDim
++)
1293 uno::Reference
<uno::XInterface
> xDim
=
1294 ScUnoHelpFunctions::AnyToInterface( xDims
->getByIndex(nDim
) );
1295 uno::Reference
<beans::XPropertySet
> xDimProp( xDim
, uno::UNO_QUERY
);
1296 if ( xDimProp
.is() )
1298 sheet::DataPilotFieldOrientation eDimOrient
=
1299 (sheet::DataPilotFieldOrientation
) ScUnoHelpFunctions::GetEnumProperty(
1300 xDimProp
, OUString(SC_UNO_DP_ORIENTATION
),
1301 sheet::DataPilotFieldOrientation_HIDDEN
);
1302 if ( ScUnoHelpFunctions::GetBoolProperty( xDimProp
,
1303 OUString(SC_UNO_DP_ISDATALAYOUT
) ) )
1305 rDataLayoutIndex
= nDim
;
1306 rDataOrient
= eDimOrient
;
1308 if ( eDimOrient
== sheet::DataPilotFieldOrientation_DATA
)
1310 OUString aSourceName
;
1311 OUString aGivenName
;
1312 ScDPOutput::GetDataDimensionNames( aSourceName
, aGivenName
, xDim
);
1315 uno::Any aValue
= xDimProp
->getPropertyValue( SC_UNO_DP_LAYOUTNAME
);
1317 if( aValue
.hasValue() )
1319 OUString strLayoutName
;
1321 if( ( aValue
>>= strLayoutName
) && !strLayoutName
.isEmpty() )
1322 aGivenName
= strLayoutName
;
1325 catch(const uno::Exception
&)
1328 rDataNames
.push_back( aSourceName
);
1329 rGivenNames
.push_back( aGivenName
);
1336 if ( ( rDataOrient
== sheet::DataPilotFieldOrientation_COLUMN
) && bColGrand
)
1337 rGrandTotalCols
= nDataCount
;
1338 else if ( ( rDataOrient
== sheet::DataPilotFieldOrientation_ROW
) && bRowGrand
)
1339 rGrandTotalRows
= nDataCount
;
1345 void ScDPOutput::GetPositionData(const ScAddress
& rPos
, DataPilotTablePositionData
& rPosData
)
1347 using namespace ::com::sun::star::sheet
;
1349 SCCOL nCol
= rPos
.Col();
1350 SCROW nRow
= rPos
.Row();
1351 SCTAB nTab
= rPos
.Tab();
1352 if ( nTab
!= aStartPos
.Tab() )
1353 return; // wrong sheet
1355 // calculate output positions and sizes
1359 rPosData
.PositionType
= GetPositionType(rPos
);
1360 switch (rPosData
.PositionType
)
1362 case DataPilotTablePositionType::RESULT
:
1364 vector
<DataPilotFieldFilter
> aFilters
;
1365 GetDataResultPositionData(aFilters
, rPos
);
1366 sal_Int32 nSize
= aFilters
.size();
1368 DataPilotTableResultData aResData
;
1369 aResData
.FieldFilters
.realloc(nSize
);
1370 for (sal_Int32 i
= 0; i
< nSize
; ++i
)
1371 aResData
.FieldFilters
[i
] = aFilters
[i
];
1373 aResData
.DataFieldIndex
= 0;
1374 Reference
<beans::XPropertySet
> xPropSet(xSource
, UNO_QUERY
);
1377 sal_Int32 nDataFieldCount
= ScUnoHelpFunctions::GetLongProperty( xPropSet
,
1378 OUString(SC_UNO_DP_DATAFIELDCOUNT
) );
1379 if (nDataFieldCount
> 0)
1380 aResData
.DataFieldIndex
= (nRow
- nDataStartRow
) % nDataFieldCount
;
1383 // Copy appropriate DataResult object from the cached sheet::DataResult table.
1384 if (aData
.getLength() > nRow
- nDataStartRow
&&
1385 aData
[nRow
-nDataStartRow
].getLength() > nCol
-nDataStartCol
)
1386 aResData
.Result
= aData
[nRow
-nDataStartRow
][nCol
-nDataStartCol
];
1388 rPosData
.PositionData
= makeAny(aResData
);
1391 case DataPilotTablePositionType::COLUMN_HEADER
:
1393 long nField
= nRow
- nTabStartRow
- 1; // 1st line is used for the buttons
1397 const uno::Sequence
<sheet::MemberResult
> rSequence
= pColFields
[nField
].aResult
;
1398 if (rSequence
.getLength() == 0)
1400 const sheet::MemberResult
* pArray
= rSequence
.getConstArray();
1402 long nItem
= nCol
- nDataStartCol
;
1403 // get origin of "continue" fields
1404 while (nItem
> 0 && ( pArray
[nItem
].Flags
& sheet::MemberResultFlags::CONTINUE
) )
1410 DataPilotTableHeaderData aHeaderData
;
1411 aHeaderData
.MemberName
= OUString(pArray
[nItem
].Name
);
1412 aHeaderData
.Flags
= pArray
[nItem
].Flags
;
1413 aHeaderData
.Dimension
= static_cast<sal_Int32
>(pColFields
[nField
].nDim
);
1414 aHeaderData
.Hierarchy
= static_cast<sal_Int32
>(pColFields
[nField
].nHier
);
1415 aHeaderData
.Level
= static_cast<sal_Int32
>(pColFields
[nField
].nLevel
);
1417 rPosData
.PositionData
= makeAny(aHeaderData
);
1420 case DataPilotTablePositionType::ROW_HEADER
:
1422 long nField
= nCol
- nTabStartCol
;
1426 const uno::Sequence
<sheet::MemberResult
> rSequence
= pRowFields
[nField
].aResult
;
1427 if (rSequence
.getLength() == 0)
1429 const sheet::MemberResult
* pArray
= rSequence
.getConstArray();
1431 long nItem
= nRow
- nDataStartRow
;
1432 // get origin of "continue" fields
1433 while ( nItem
> 0 && (pArray
[nItem
].Flags
& sheet::MemberResultFlags::CONTINUE
) )
1439 DataPilotTableHeaderData aHeaderData
;
1440 aHeaderData
.MemberName
= OUString(pArray
[nItem
].Name
);
1441 aHeaderData
.Flags
= pArray
[nItem
].Flags
;
1442 aHeaderData
.Dimension
= static_cast<sal_Int32
>(pRowFields
[nField
].nDim
);
1443 aHeaderData
.Hierarchy
= static_cast<sal_Int32
>(pRowFields
[nField
].nHier
);
1444 aHeaderData
.Level
= static_cast<sal_Int32
>(pRowFields
[nField
].nLevel
);
1446 rPosData
.PositionData
= makeAny(aHeaderData
);
1452 bool ScDPOutput::GetDataResultPositionData(vector
<sheet::DataPilotFieldFilter
>& rFilters
, const ScAddress
& rPos
)
1454 // Check to make sure there is at least one data field.
1455 Reference
<beans::XPropertySet
> xPropSet(xSource
, UNO_QUERY
);
1459 sal_Int32 nDataFieldCount
= ScUnoHelpFunctions::GetLongProperty( xPropSet
,
1460 OUString(SC_UNO_DP_DATAFIELDCOUNT
) );
1461 if (nDataFieldCount
== 0)
1462 // No data field is present in this datapilot table.
1465 // #i111421# use lcl_GetTableVars for correct size of totals and data layout position
1466 sal_Int32 nGrandTotalCols
;
1467 sal_Int32 nGrandTotalRows
;
1468 sal_Int32 nDataLayoutIndex
;
1469 std::vector
<OUString
> aDataNames
;
1470 std::vector
<OUString
> aGivenNames
;
1471 sheet::DataPilotFieldOrientation eDataOrient
;
1472 lcl_GetTableVars( nGrandTotalCols
, nGrandTotalRows
, nDataLayoutIndex
, aDataNames
, aGivenNames
, eDataOrient
, xSource
);
1474 SCCOL nCol
= rPos
.Col();
1475 SCROW nRow
= rPos
.Row();
1476 SCTAB nTab
= rPos
.Tab();
1477 if ( nTab
!= aStartPos
.Tab() )
1478 return false; // wrong sheet
1482 // test for data area.
1483 if (nCol
< nDataStartCol
|| nCol
> nTabEndCol
|| nRow
< nDataStartRow
|| nRow
> nTabEndRow
)
1485 // Cell is outside the data field area.
1489 bool bFilterByCol
= (nCol
<= static_cast<SCCOL
>(nTabEndCol
- nGrandTotalCols
));
1490 bool bFilterByRow
= (nRow
<= static_cast<SCROW
>(nTabEndRow
- nGrandTotalRows
));
1493 for (SCCOL nColField
= 0; nColField
< nColFieldCount
&& bFilterByCol
; ++nColField
)
1495 if (pColFields
[nColField
].nDim
== nDataLayoutIndex
)
1496 // There is no sense including the data layout field for filtering.
1499 sheet::DataPilotFieldFilter filter
;
1500 filter
.FieldName
= pColFields
[nColField
].maName
;
1502 const uno::Sequence
<sheet::MemberResult
> rSequence
= pColFields
[nColField
].aResult
;
1503 const sheet::MemberResult
* pArray
= rSequence
.getConstArray();
1505 OSL_ENSURE(nDataStartCol
+ rSequence
.getLength() - 1 == nTabEndCol
, "ScDPOutput::GetDataFieldCellData: error in geometric assumption");
1507 long nItem
= nCol
- nDataStartCol
;
1508 // get origin of "continue" fields
1509 while ( nItem
> 0 && (pArray
[nItem
].Flags
& sheet::MemberResultFlags::CONTINUE
) )
1512 filter
.MatchValue
= pArray
[nItem
].Name
;
1513 rFilters
.push_back(filter
);
1517 for (SCROW nRowField
= 0; nRowField
< nRowFieldCount
&& bFilterByRow
; ++nRowField
)
1519 if (pRowFields
[nRowField
].nDim
== nDataLayoutIndex
)
1520 // There is no sense including the data layout field for filtering.
1523 sheet::DataPilotFieldFilter filter
;
1524 filter
.FieldName
= pRowFields
[nRowField
].maName
;
1526 const uno::Sequence
<sheet::MemberResult
> rSequence
= pRowFields
[nRowField
].aResult
;
1527 const sheet::MemberResult
* pArray
= rSequence
.getConstArray();
1529 OSL_ENSURE(nDataStartRow
+ rSequence
.getLength() - 1 == nTabEndRow
, "ScDPOutput::GetDataFieldCellData: error in geometric assumption");
1531 long nItem
= nRow
- nDataStartRow
;
1532 // get origin of "continue" fields
1533 while ( nItem
> 0 && (pArray
[nItem
].Flags
& sheet::MemberResultFlags::CONTINUE
) )
1536 filter
.MatchValue
= pArray
[nItem
].Name
;
1537 rFilters
.push_back(filter
);
1545 OUString
lcl_GetDataFieldName( const OUString
& rSourceName
, sheet::GeneralFunction eFunc
)
1547 sal_uInt16 nStrId
= 0;
1550 case sheet::GeneralFunction_SUM
: nStrId
= STR_FUN_TEXT_SUM
; break;
1551 case sheet::GeneralFunction_COUNT
:
1552 case sheet::GeneralFunction_COUNTNUMS
: nStrId
= STR_FUN_TEXT_COUNT
; break;
1553 case sheet::GeneralFunction_AVERAGE
: nStrId
= STR_FUN_TEXT_AVG
; break;
1554 case sheet::GeneralFunction_MAX
: nStrId
= STR_FUN_TEXT_MAX
; break;
1555 case sheet::GeneralFunction_MIN
: nStrId
= STR_FUN_TEXT_MIN
; break;
1556 case sheet::GeneralFunction_PRODUCT
: nStrId
= STR_FUN_TEXT_PRODUCT
; break;
1557 case sheet::GeneralFunction_STDEV
:
1558 case sheet::GeneralFunction_STDEVP
: nStrId
= STR_FUN_TEXT_STDDEV
; break;
1559 case sheet::GeneralFunction_VAR
:
1560 case sheet::GeneralFunction_VARP
: nStrId
= STR_FUN_TEXT_VAR
; break;
1561 case sheet::GeneralFunction_NONE
:
1562 case sheet::GeneralFunction_AUTO
:
1565 OSL_FAIL("wrong function");
1571 OUStringBuffer
aRet( ScGlobal::GetRscString( nStrId
) );
1573 aRet
.append(rSourceName
);
1574 return aRet
.makeStringAndClear();
1579 void ScDPOutput::GetDataDimensionNames(
1580 OUString
& rSourceName
, OUString
& rGivenName
, const uno::Reference
<uno::XInterface
>& xDim
)
1582 uno::Reference
<beans::XPropertySet
> xDimProp( xDim
, uno::UNO_QUERY
);
1583 uno::Reference
<container::XNamed
> xDimName( xDim
, uno::UNO_QUERY
);
1584 if ( xDimProp
.is() && xDimName
.is() )
1586 // Asterisks are added in ScDPSaveData::WriteToSource to create unique names.
1587 //TODO: preserve original name there?
1588 rSourceName
= ScDPUtil::getSourceDimensionName(xDimName
->getName());
1590 // Generate "given name" the same way as in dptabres.
1591 //TODO: Should use a stored name when available
1593 sheet::GeneralFunction eFunc
= (sheet::GeneralFunction
)ScUnoHelpFunctions::GetEnumProperty(
1594 xDimProp
, OUString(SC_UNO_DP_FUNCTION
),
1595 sheet::GeneralFunction_NONE
);
1596 rGivenName
= lcl_GetDataFieldName( rSourceName
, eFunc
);
1600 bool ScDPOutput::IsFilterButton( const ScAddress
& rPos
)
1602 SCCOL nCol
= rPos
.Col();
1603 SCROW nRow
= rPos
.Row();
1604 SCTAB nTab
= rPos
.Tab();
1605 if ( nTab
!= aStartPos
.Tab() || !bDoFilter
)
1606 return false; // wrong sheet or no button at all
1608 // filter button is at top left
1609 return ( nCol
== aStartPos
.Col() && nRow
== aStartPos
.Row() );
1612 long ScDPOutput::GetHeaderDim( const ScAddress
& rPos
, sal_uInt16
& rOrient
)
1614 SCCOL nCol
= rPos
.Col();
1615 SCROW nRow
= rPos
.Row();
1616 SCTAB nTab
= rPos
.Tab();
1617 if ( nTab
!= aStartPos
.Tab() )
1618 return -1; // wrong sheet
1620 // calculate output positions and sizes
1624 // test for column header
1626 if ( nRow
== nTabStartRow
&& nCol
>= nDataStartCol
&& nCol
< nDataStartCol
+ nColFieldCount
)
1628 rOrient
= sheet::DataPilotFieldOrientation_COLUMN
;
1629 long nField
= nCol
- nDataStartCol
;
1630 return pColFields
[nField
].nDim
;
1633 // test for row header
1635 if ( nRow
+1 == nDataStartRow
&& nCol
>= nTabStartCol
&& nCol
< nTabStartCol
+ nRowFieldCount
)
1637 rOrient
= sheet::DataPilotFieldOrientation_ROW
;
1638 long nField
= nCol
- nTabStartCol
;
1639 return pRowFields
[nField
].nDim
;
1642 // test for page field
1644 SCROW nPageStartRow
= aStartPos
.Row() + ( bDoFilter
? 1 : 0 );
1645 if ( nCol
== aStartPos
.Col() && nRow
>= nPageStartRow
&& nRow
< nPageStartRow
+ nPageFieldCount
)
1647 rOrient
= sheet::DataPilotFieldOrientation_PAGE
;
1648 long nField
= nRow
- nPageStartRow
;
1649 return pPageFields
[nField
].nDim
;
1652 //TODO: single data field (?)
1654 rOrient
= sheet::DataPilotFieldOrientation_HIDDEN
;
1655 return -1; // invalid
1658 bool ScDPOutput::GetHeaderDrag( const ScAddress
& rPos
, bool bMouseLeft
, bool bMouseTop
,
1660 Rectangle
& rPosRect
, sal_uInt16
& rOrient
, long& rDimPos
)
1662 // Rectangle instead of ScRange for rPosRect to allow for negative values
1664 SCCOL nCol
= rPos
.Col();
1665 SCROW nRow
= rPos
.Row();
1666 SCTAB nTab
= rPos
.Tab();
1667 if ( nTab
!= aStartPos
.Tab() )
1668 return false; // wrong sheet
1670 // calculate output positions and sizes
1674 // test for column header
1676 if ( nCol
>= nDataStartCol
&& nCol
<= nTabEndCol
&&
1677 nRow
+ 1 >= nMemberStartRow
&& nRow
< nMemberStartRow
+ nColFieldCount
)
1679 long nField
= nRow
- nMemberStartRow
;
1685 //TODO: find start of dimension
1687 rPosRect
= Rectangle( nDataStartCol
, nMemberStartRow
+ nField
,
1688 nTabEndCol
, nMemberStartRow
+ nField
-1 );
1690 bool bFound
= false; // is this within the same orientation?
1691 bool bBeforeDrag
= false;
1692 bool bAfterDrag
= false;
1693 for (long nPos
=0; nPos
<nColFieldCount
&& !bFound
; nPos
++)
1695 if (pColFields
[nPos
].nDim
== nDragDim
)
1698 if ( nField
< nPos
)
1700 else if ( nField
> nPos
)
1709 ++rPosRect
.Bottom();
1719 ++rPosRect
.Bottom();
1724 rOrient
= sheet::DataPilotFieldOrientation_COLUMN
;
1725 rDimPos
= nField
; //!...
1729 // test for row header
1731 // special case if no row fields
1732 bool bSpecial
= ( nRow
+1 >= nDataStartRow
&& nRow
<= nTabEndRow
&&
1733 nRowFieldCount
== 0 && nCol
== nTabStartCol
&& bMouseLeft
);
1735 if ( bSpecial
|| ( nRow
+1 >= nDataStartRow
&& nRow
<= nTabEndRow
&&
1736 nCol
+ 1 >= nTabStartCol
&& nCol
< nTabStartCol
+ nRowFieldCount
) )
1738 long nField
= nCol
- nTabStartCol
;
1739 //TODO: find start of dimension
1741 rPosRect
= Rectangle( nTabStartCol
+ nField
, nDataStartRow
- 1,
1742 nTabStartCol
+ nField
- 1, nTabEndRow
);
1744 bool bFound
= false; // is this within the same orientation?
1745 bool bBeforeDrag
= false;
1746 bool bAfterDrag
= false;
1747 for (long nPos
=0; nPos
<nRowFieldCount
&& !bFound
; nPos
++)
1749 if (pRowFields
[nPos
].nDim
== nDragDim
)
1752 if ( nField
< nPos
)
1754 else if ( nField
> nPos
)
1778 rOrient
= sheet::DataPilotFieldOrientation_ROW
;
1779 rDimPos
= nField
; //!...
1783 // test for page fields
1785 SCROW nPageStartRow
= aStartPos
.Row() + ( bDoFilter
? 1 : 0 );
1786 if ( nCol
>= aStartPos
.Col() && nCol
<= nTabEndCol
&&
1787 nRow
+ 1 >= nPageStartRow
&& nRow
< nPageStartRow
+ nPageFieldCount
)
1789 long nField
= nRow
- nPageStartRow
;
1795 //TODO: find start of dimension
1797 rPosRect
= Rectangle( aStartPos
.Col(), nPageStartRow
+ nField
,
1798 nTabEndCol
, nPageStartRow
+ nField
- 1 );
1800 bool bFound
= false; // is this within the same orientation?
1801 bool bBeforeDrag
= false;
1802 bool bAfterDrag
= false;
1803 for (long nPos
=0; nPos
<nPageFieldCount
&& !bFound
; nPos
++)
1805 if (pPageFields
[nPos
].nDim
== nDragDim
)
1808 if ( nField
< nPos
)
1810 else if ( nField
> nPos
)
1819 ++rPosRect
.Bottom();
1829 ++rPosRect
.Bottom();
1834 rOrient
= sheet::DataPilotFieldOrientation_PAGE
;
1835 rDimPos
= nField
; //!...
1842 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */