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