xref: /aoo41x/main/sc/source/ui/unoobj/dapiuno.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sc.hxx"
30 
31 #include <algorithm>
32 #include <svl/smplhint.hxx>
33 #include <rtl/uuid.h>
34 
35 #include "dapiuno.hxx"
36 #include "datauno.hxx"
37 #include "miscuno.hxx"
38 #include "convuno.hxx"
39 #include "docsh.hxx"
40 #include "tabvwsh.hxx"
41 #include "pivot.hxx"
42 #include "rangeutl.hxx"
43 #include "unoguard.hxx"
44 #include "dpobject.hxx"
45 #include "dpshttab.hxx"
46 #include "dpsdbtab.hxx"
47 #include "dpsave.hxx"
48 #include "dbdocfun.hxx"
49 #include "unonames.hxx"
50 #include "dpgroup.hxx"
51 #include "dpdimsave.hxx"
52 #include "hints.hxx"
53 
54 #include <com/sun/star/sheet/XHierarchiesSupplier.hpp>
55 #include <com/sun/star/sheet/XLevelsSupplier.hpp>
56 #include <com/sun/star/sheet/XMembersSupplier.hpp>
57 #include <com/sun/star/beans/PropertyAttribute.hpp>
58 #include <com/sun/star/sheet/DataImportMode.hpp>
59 #include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
60 #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
61 #include <com/sun/star/sheet/DataPilotOutputRangeType.hpp>
62 #include <com/sun/star/sheet/DataPilotTablePositionData.hpp>
63 
64 #include <comphelper/extract.hxx>
65 #include <comphelper/sequence.hxx>
66 
67 using namespace com::sun::star;
68 using namespace com::sun::star::sheet;
69 
70 using ::rtl::OUString;
71 
72 using ::com::sun::star::uno::Any;
73 using ::com::sun::star::uno::Exception;
74 using ::com::sun::star::uno::Reference;
75 using ::com::sun::star::uno::RuntimeException;
76 using ::com::sun::star::uno::Sequence;
77 using ::com::sun::star::uno::UNO_QUERY;
78 using ::com::sun::star::uno::UNO_QUERY_THROW;
79 
80 using ::com::sun::star::container::ElementExistException;
81 using ::com::sun::star::container::NoSuchElementException;
82 using ::com::sun::star::container::XEnumeration;
83 using ::com::sun::star::container::XIndexAccess;
84 using ::com::sun::star::container::XNameAccess;
85 using ::com::sun::star::container::XNamed;
86 
87 using ::com::sun::star::beans::PropertyVetoException;
88 using ::com::sun::star::beans::UnknownPropertyException;
89 using ::com::sun::star::beans::XPropertyChangeListener;
90 using ::com::sun::star::beans::XPropertySet;
91 using ::com::sun::star::beans::XPropertySetInfo;
92 using ::com::sun::star::beans::XVetoableChangeListener;
93 
94 using ::com::sun::star::lang::IllegalArgumentException;
95 using ::com::sun::star::lang::IndexOutOfBoundsException;
96 using ::com::sun::star::lang::WrappedTargetException;
97 
98 using ::com::sun::star::table::CellAddress;
99 using ::com::sun::star::table::CellRangeAddress;
100 
101 // ============================================================================
102 
103 namespace {
104 
105 const SfxItemPropertyMapEntry* lcl_GetDataPilotDescriptorBaseMap()
106 {
107     static SfxItemPropertyMapEntry aDataPilotDescriptorBaseMap_Impl[] =
108 	{
109         {MAP_CHAR_LEN(SC_UNO_COLGRAND),     0,  &getBooleanCppuType(),  0, 0 },
110         {MAP_CHAR_LEN(SC_UNO_DRILLDOWN),    0,  &getBooleanCppuType(),  0, 0 },
111         {MAP_CHAR_LEN(SC_UNO_GRANDTOTAL_NAME),0,&getCppuType((rtl::OUString*)0), beans::PropertyAttribute::MAYBEVOID, 0 },
112         {MAP_CHAR_LEN(SC_UNO_IGNEMPROWS),   0,  &getBooleanCppuType(),  0, 0 },
113         {MAP_CHAR_LEN(SC_UNO_IMPORTDESC),   0,  &getCppuType((uno::Sequence<beans::PropertyValue>*)0), 0, 0 },
114         {MAP_CHAR_LEN(SC_UNO_RPTEMPTY),     0,  &getBooleanCppuType(),  0, 0 },
115         {MAP_CHAR_LEN(SC_UNO_ROWGRAND),     0,  &getBooleanCppuType(),  0, 0 },
116         {MAP_CHAR_LEN(SC_UNO_SERVICEARG),   0,  &getCppuType((uno::Sequence<beans::PropertyValue>*)0), 0, 0 },
117         {MAP_CHAR_LEN(SC_UNO_SHOWFILT),     0,  &getBooleanCppuType(),  0, 0 },
118         {MAP_CHAR_LEN(SC_UNO_SOURCESERV),   0,  &getCppuType((rtl::OUString*)0), 0, 0 },
119         {0,0,0,0,0,0}
120 	};
121 	return aDataPilotDescriptorBaseMap_Impl;
122 }
123 
124 // ----------------------------------------------------------------------------
125 
126 const SfxItemPropertyMapEntry* lcl_GetDataPilotFieldMap()
127 {
128     using namespace ::com::sun::star::beans::PropertyAttribute;
129     static SfxItemPropertyMapEntry aDataPilotFieldMap_Impl[] =
130 	{
131         {MAP_CHAR_LEN(SC_UNONAME_AUTOSHOW),     0,  &getCppuType((DataPilotFieldAutoShowInfo*)0),   MAYBEVOID, 0 },
132         {MAP_CHAR_LEN(SC_UNONAME_FUNCTION),     0,  &getCppuType((GeneralFunction*)0),              0, 0 },
133         {MAP_CHAR_LEN(SC_UNONAME_GROUPINFO),    0,  &getCppuType((DataPilotFieldGroupInfo*)0),      MAYBEVOID, 0 },
134         {MAP_CHAR_LEN(SC_UNONAME_HASAUTOSHOW),  0,  &getBooleanCppuType(),                          0, 0 },
135         {MAP_CHAR_LEN(SC_UNONAME_HASLAYOUTINFO),0,  &getBooleanCppuType(),                          0, 0 },
136         {MAP_CHAR_LEN(SC_UNONAME_HASREFERENCE), 0,  &getBooleanCppuType(),                          0, 0 },
137         {MAP_CHAR_LEN(SC_UNONAME_HASSORTINFO),  0,  &getBooleanCppuType(),                          0, 0 },
138         {MAP_CHAR_LEN(SC_UNONAME_ISGROUP),      0,  &getBooleanCppuType(),                          0, 0 },
139         {MAP_CHAR_LEN(SC_UNONAME_LAYOUTINFO),   0,  &getCppuType((DataPilotFieldLayoutInfo*)0),     MAYBEVOID, 0 },
140         {MAP_CHAR_LEN(SC_UNONAME_ORIENT),       0,  &getCppuType((DataPilotFieldOrientation*)0),    MAYBEVOID, 0 },
141         {MAP_CHAR_LEN(SC_UNONAME_REFERENCE),    0,  &getCppuType((DataPilotFieldReference*)0),      MAYBEVOID, 0 },
142         {MAP_CHAR_LEN(SC_UNONAME_SELPAGE),      0,  &getCppuType((OUString*)0),                     0, 0 },
143         {MAP_CHAR_LEN(SC_UNONAME_SHOWEMPTY),    0,  &getBooleanCppuType(),                          0, 0 },
144         {MAP_CHAR_LEN(SC_UNONAME_SORTINFO),     0,  &getCppuType((DataPilotFieldSortInfo*)0),       MAYBEVOID, 0 },
145         {MAP_CHAR_LEN(SC_UNONAME_SUBTOTALS),    0,  &getCppuType((Sequence<GeneralFunction>*)0),    0, 0 },
146         {MAP_CHAR_LEN(SC_UNONAME_USESELPAGE),   0,  &getBooleanCppuType(),                          0, 0 },
147         {0,0,0,0,0,0}
148 	};
149 	return aDataPilotFieldMap_Impl;
150 }
151 
152 // ----------------------------------------------------------------------------
153 
154 const SfxItemPropertyMapEntry* lcl_GetDataPilotItemMap()
155 {
156     static SfxItemPropertyMapEntry aDataPilotItemMap_Impl[] =
157 	{
158         {MAP_CHAR_LEN(SC_UNONAME_ISHIDDEN),     0,  &getBooleanCppuType(),          0, 0 },
159         {MAP_CHAR_LEN(SC_UNONAME_POS),          0,  &getCppuType((sal_Int32*)0),    0, 0 },
160         {MAP_CHAR_LEN(SC_UNONAME_SHOWDETAIL),   0,  &getBooleanCppuType(),          0, 0 },
161         {0,0,0,0,0,0}
162 	};
163 	return aDataPilotItemMap_Impl;
164 }
165 
166 // ----------------------------------------------------------------------------
167 
168 inline bool lclCheckValidDouble( double fValue, sal_Bool bAuto )
169 {
170     return bAuto || ::rtl::math::isFinite( fValue );
171 }
172 
173 bool lclCheckMinMaxStep( const DataPilotFieldGroupInfo& rInfo )
174 {
175     return
176         lclCheckValidDouble( rInfo.Start, rInfo.HasAutoStart ) &&
177         lclCheckValidDouble( rInfo.End, rInfo.HasAutoEnd ) &&
178         (rInfo.HasAutoStart || rInfo.HasAutoEnd || (rInfo.Start <= rInfo.End)) &&
179         lclCheckValidDouble( rInfo.Step, sal_False ) &&
180         (0.0 <= rInfo.Step);
181 }
182 
183 } // namespace
184 
185 // ============================================================================
186 
187 SC_SIMPLE_SERVICE_INFO( ScDataPilotDescriptor, "ScDataPilotDescriptor", "stardiv::one::sheet::DataPilotDescriptor" )
188 SC_SIMPLE_SERVICE_INFO( ScDataPilotFieldObj, "ScDataPilotFieldObj", "com.sun.star.sheet.DataPilotField" )
189 SC_SIMPLE_SERVICE_INFO( ScDataPilotFieldsObj, "ScDataPilotFieldsObj", "com.sun.star.sheet.DataPilotFields" )
190 SC_SIMPLE_SERVICE_INFO( ScDataPilotTableObj, "ScDataPilotTableObj", "com.sun.star.sheet.DataPilotTable" )
191 SC_SIMPLE_SERVICE_INFO( ScDataPilotTablesObj, "ScDataPilotTablesObj", "com.sun.star.sheet.DataPilotTables" )
192 SC_SIMPLE_SERVICE_INFO( ScDataPilotItemsObj, "ScDataPilotItemsObj", "com.sun.star.sheet.DataPilotItems" )
193 SC_SIMPLE_SERVICE_INFO( ScDataPilotItemObj, "ScDataPilotItemObj", "com.sun.star.sheet.DataPilotItem" )
194 
195 SC_SIMPLE_SERVICE_INFO( ScDataPilotFieldGroupsObj, "ScDataPilotFieldGroupsObj", "com.sun.star.sheet.DataPilotFieldGroups" )
196 SC_SIMPLE_SERVICE_INFO( ScDataPilotFieldGroupObj, "ScDataPilotFieldGroupObj", "com.sun.star.sheet.DataPilotFieldGroup" )
197 SC_SIMPLE_SERVICE_INFO( ScDataPilotFieldGroupItemObj, "ScDataPilotFieldGroupItemObj", "com.sun.star.sheet.DataPilotFieldGroupItem" )
198 
199 //------------------------------------------------------------------------
200 
201 // name that is used in the API for the data layout field
202 #define SC_DATALAYOUT_NAME  "Data"
203 
204 //------------------------------------------------------------------------
205 
206 GeneralFunction ScDataPilotConversion::FirstFunc( sal_uInt16 nBits )
207 {
208     if ( nBits & PIVOT_FUNC_SUM )       return GeneralFunction_SUM;
209     if ( nBits & PIVOT_FUNC_COUNT )     return GeneralFunction_COUNT;
210     if ( nBits & PIVOT_FUNC_AVERAGE )   return GeneralFunction_AVERAGE;
211     if ( nBits & PIVOT_FUNC_MAX )       return GeneralFunction_MAX;
212     if ( nBits & PIVOT_FUNC_MIN )       return GeneralFunction_MIN;
213     if ( nBits & PIVOT_FUNC_PRODUCT )   return GeneralFunction_PRODUCT;
214     if ( nBits & PIVOT_FUNC_COUNT_NUM ) return GeneralFunction_COUNTNUMS;
215     if ( nBits & PIVOT_FUNC_STD_DEV )   return GeneralFunction_STDEV;
216     if ( nBits & PIVOT_FUNC_STD_DEVP )  return GeneralFunction_STDEVP;
217     if ( nBits & PIVOT_FUNC_STD_VAR )   return GeneralFunction_VAR;
218     if ( nBits & PIVOT_FUNC_STD_VARP )  return GeneralFunction_VARP;
219     if ( nBits & PIVOT_FUNC_AUTO )      return GeneralFunction_AUTO;
220     return GeneralFunction_NONE;
221 }
222 
223 sal_uInt16 ScDataPilotConversion::FunctionBit( GeneralFunction eFunc )
224 {
225 	sal_uInt16 nRet = PIVOT_FUNC_NONE;	// 0
226 	switch (eFunc)
227 	{
228         case GeneralFunction_SUM:       nRet = PIVOT_FUNC_SUM;       break;
229         case GeneralFunction_COUNT:     nRet = PIVOT_FUNC_COUNT;     break;
230         case GeneralFunction_AVERAGE:   nRet = PIVOT_FUNC_AVERAGE;   break;
231         case GeneralFunction_MAX:       nRet = PIVOT_FUNC_MAX;       break;
232         case GeneralFunction_MIN:       nRet = PIVOT_FUNC_MIN;       break;
233         case GeneralFunction_PRODUCT:   nRet = PIVOT_FUNC_PRODUCT;   break;
234         case GeneralFunction_COUNTNUMS: nRet = PIVOT_FUNC_COUNT_NUM; break;
235         case GeneralFunction_STDEV:     nRet = PIVOT_FUNC_STD_DEV;   break;
236         case GeneralFunction_STDEVP:    nRet = PIVOT_FUNC_STD_DEVP;  break;
237         case GeneralFunction_VAR:       nRet = PIVOT_FUNC_STD_VAR;   break;
238         case GeneralFunction_VARP:      nRet = PIVOT_FUNC_STD_VARP;  break;
239         case GeneralFunction_AUTO:      nRet = PIVOT_FUNC_AUTO;      break;
240         default:
241         {
242             // added to avoid warnings
243         }
244 	}
245 	return nRet;
246 }
247 
248 void ScDataPilotConversion::FillGroupInfo( DataPilotFieldGroupInfo& rInfo, const ScDPNumGroupInfo& rGroupInfo )
249 {
250     rInfo.HasDateValues = rGroupInfo.DateValues;
251     rInfo.HasAutoStart  = rGroupInfo.AutoStart;
252     rInfo.Start         = rGroupInfo.Start;
253     rInfo.HasAutoEnd    = rGroupInfo.AutoEnd;
254     rInfo.End           = rGroupInfo.End;
255     rInfo.Step          = rGroupInfo.Step;
256 }
257 
258 //------------------------------------------------------------------------
259 
260 ScDPObject* lcl_GetDPObject( ScDocShell* pDocShell, SCTAB nTab, const String& rName )
261 {
262 	if (pDocShell)
263 	{
264 		ScDocument* pDoc = pDocShell->GetDocument();
265 		ScDPCollection* pColl = pDoc->GetDPCollection();
266 		if ( pColl )
267 		{
268 			sal_uInt16 nCount = pColl->GetCount();
269 			for (sal_uInt16 i=0; i<nCount; i++)
270 			{
271 				ScDPObject* pDPObj = (*pColl)[i];
272                 if ( pDPObj->GetOutRange().aStart.Tab() == nTab &&
273 					 pDPObj->GetName() == rName )
274 					return pDPObj;
275 			}
276 		}
277 	}
278 	return NULL;	// nicht gefunden
279 }
280 
281 String lcl_CreatePivotName( ScDocShell* pDocShell )
282 {
283 	if (pDocShell)
284 	{
285 		ScDocument* pDoc = pDocShell->GetDocument();
286 		ScDPCollection* pColl = pDoc->GetDPCollection();
287 		if ( pColl )
288 			return pColl->CreateNewName();
289 	}
290 	return String();					// sollte nicht vorkommen
291 }
292 
293 sal_Int32 lcl_GetObjectIndex( ScDPObject* pDPObj, const ScFieldIdentifier& rFieldId )
294 {
295     // used for items - nRepeat in identifier can be ignored
296     if ( pDPObj )
297     {
298         sal_Int32 nCount = pDPObj->GetDimCount();
299         for ( sal_Int32 nDim = 0; nDim < nCount; ++nDim )
300         {
301             sal_Bool bIsDataLayout = sal_False;
302             OUString aDimName( pDPObj->GetDimName( nDim, bIsDataLayout ) );
303             if ( rFieldId.mbDataLayout ? bIsDataLayout : (aDimName == rFieldId.maFieldName) )
304                 return nDim;
305         }
306     }
307     return -1;  // none
308 }
309 
310 //------------------------------------------------------------------------
311 
312 ScDataPilotTablesObj::ScDataPilotTablesObj(ScDocShell* pDocSh, SCTAB nT) :
313 	pDocShell( pDocSh ),
314 	nTab( nT )
315 {
316 	pDocShell->GetDocument()->AddUnoObject(*this);
317 }
318 
319 ScDataPilotTablesObj::~ScDataPilotTablesObj()
320 {
321 	if (pDocShell)
322 		pDocShell->GetDocument()->RemoveUnoObject(*this);
323 }
324 
325 void ScDataPilotTablesObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
326 {
327 	//!	Referenz-Update
328 
329 	if ( rHint.ISA( SfxSimpleHint ) &&
330 			((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING )
331 	{
332 		pDocShell = NULL;		// ungueltig geworden
333 	}
334 }
335 
336 // XDataPilotTables
337 
338 ScDataPilotTableObj* ScDataPilotTablesObj::GetObjectByIndex_Impl( sal_Int32 nIndex )
339 {
340 	if (pDocShell)
341 	{
342 		ScDocument* pDoc = pDocShell->GetDocument();
343 		ScDPCollection* pColl = pDoc->GetDPCollection();
344 		if ( pColl )
345 		{
346 			//	count tables on this sheet
347             sal_Int32 nFound = 0;
348 			sal_uInt16 nCount = pColl->GetCount();
349 			for (sal_uInt16 i=0; i<nCount; i++)
350 			{
351 				ScDPObject* pDPObj = (*pColl)[i];
352                 if ( pDPObj->GetOutRange().aStart.Tab() == nTab )
353 				{
354 					if ( nFound == nIndex )
355 					{
356 						String aName = pDPObj->GetName();
357 						return new ScDataPilotTableObj( pDocShell, nTab, aName );
358 					}
359 					++nFound;
360 				}
361 			}
362 		}
363 	}
364 	return NULL;
365 }
366 
367 ScDataPilotTableObj* ScDataPilotTablesObj::GetObjectByName_Impl(const OUString& rName)
368 {
369     if (hasByName(rName))
370         return new ScDataPilotTableObj( pDocShell, nTab, rName );
371     return 0;
372 }
373 
374 Reference<XDataPilotDescriptor> SAL_CALL ScDataPilotTablesObj::createDataPilotDescriptor()
375                                             throw(RuntimeException)
376 {
377 	ScUnoGuard aGuard;
378 	if (pDocShell)
379 		return new ScDataPilotDescriptor(pDocShell);
380 	return NULL;
381 }
382 
383 bool lcl_IsDuplicated( const Reference<XPropertySet> xDimProps )
384 {
385     try
386     {
387         Any aAny = xDimProps->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNO_ORIGINAL ) ) );
388         Reference< XNamed > xOriginal( aAny, UNO_QUERY );
389         return xOriginal.is();
390     }
391     catch( Exception& )
392     {
393     }
394     return false;
395 }
396 
397 OUString lcl_GetOriginalName( const Reference< XNamed > xDim )
398 {
399     Reference< XNamed > xOriginal;
400 
401     Reference< XPropertySet > xDimProps( xDim, UNO_QUERY );
402     if ( xDimProps.is() )
403     {
404         try
405         {
406             Any aAny = xDimProps->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_ORIGINAL)));
407             aAny >>= xOriginal;
408         }
409         catch( Exception& )
410         {
411         }
412     }
413 
414     if ( !xOriginal.is() )
415         xOriginal = xDim;
416 
417     return xOriginal->getName();
418 }
419 
420 void SAL_CALL ScDataPilotTablesObj::insertNewByName( const OUString& aNewName,
421                                     const CellAddress& aOutputAddress,
422                                     const Reference<XDataPilotDescriptor>& xDescriptor )
423                                 throw(RuntimeException)
424 {
425 	ScUnoGuard aGuard;
426 	if (!xDescriptor.is()) return;
427 
428 	// inserting with already existing name?
429 	if ( aNewName.getLength() && hasByName( aNewName ) )
430         throw RuntimeException();       // no other exceptions specified
431 
432 	sal_Bool bDone = sal_False;
433 	ScDataPilotDescriptorBase* pImp = ScDataPilotDescriptorBase::getImplementation( xDescriptor );
434 	if ( pDocShell && pImp )
435 	{
436         ScDPObject* pNewObj = pImp->GetDPObject();
437 
438         if (pNewObj)
439         {
440             ScRange aOutputRange((SCCOL)aOutputAddress.Column, (SCROW)aOutputAddress.Row, (SCTAB)aOutputAddress.Sheet,
441                                 (SCCOL)aOutputAddress.Column, (SCROW)aOutputAddress.Row, (SCTAB)aOutputAddress.Sheet);
442             pNewObj->SetOutRange(aOutputRange);
443 		    String aName = aNewName;
444 		    if (!aName.Len())
445 			    aName = lcl_CreatePivotName( pDocShell );
446             pNewObj->SetName(aName);
447 		    String aTag = xDescriptor->getTag();
448             pNewObj->SetTag(aTag);
449 
450     // todo: handle double fields (for more information see ScDPObject
451 
452             ScDBDocFunc aFunc(*pDocShell);
453 		    bDone = aFunc.DataPilotUpdate( NULL, pNewObj, sal_True, sal_True );
454         }
455 	}
456 
457 	if (!bDone)
458         throw RuntimeException();       // no other exceptions specified
459 }
460 
461 void SAL_CALL ScDataPilotTablesObj::removeByName( const OUString& aName )
462                                         throw(RuntimeException)
463 {
464 	ScUnoGuard aGuard;
465 	String aNameStr(aName);
466 	ScDPObject* pDPObj = lcl_GetDPObject( pDocShell, nTab, aNameStr );
467 	if (pDPObj && pDocShell)
468 	{
469 		ScDBDocFunc aFunc(*pDocShell);
470 		aFunc.DataPilotUpdate( pDPObj, NULL, sal_True, sal_True );	// remove - incl. undo etc.
471 	}
472 	else
473         throw RuntimeException();       // no other exceptions specified
474 }
475 
476 // XEnumerationAccess
477 
478 Reference< XEnumeration > SAL_CALL ScDataPilotTablesObj::createEnumeration() throw(RuntimeException)
479 {
480 	ScUnoGuard aGuard;
481     return new ScIndexEnumeration(this, OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.DataPilotTablesEnumeration")));
482 }
483 
484 // XIndexAccess
485 
486 sal_Int32 SAL_CALL ScDataPilotTablesObj::getCount() throw(RuntimeException)
487 {
488 	ScUnoGuard aGuard;
489 	if ( pDocShell )
490 	{
491 		ScDocument* pDoc = pDocShell->GetDocument();
492 		ScDPCollection* pColl = pDoc->GetDPCollection();
493 		if ( pColl )
494 		{
495 			//	count tables on this sheet
496 
497 			sal_uInt16 nFound = 0;
498 			sal_uInt16 nCount = pColl->GetCount();
499 			for (sal_uInt16 i=0; i<nCount; i++)
500 			{
501 				ScDPObject* pDPObj = (*pColl)[i];
502                 if ( pDPObj->GetOutRange().aStart.Tab() == nTab )
503 					++nFound;
504 			}
505 			return nFound;
506 		}
507 	}
508 
509 	return 0;
510 }
511 
512 Any SAL_CALL ScDataPilotTablesObj::getByIndex( sal_Int32 nIndex )
513         throw(IndexOutOfBoundsException, WrappedTargetException, RuntimeException)
514 {
515 	ScUnoGuard aGuard;
516     Reference<XDataPilotTable2> xTable(GetObjectByIndex_Impl(nIndex));
517     if (!xTable.is())
518         throw IndexOutOfBoundsException();
519     return Any( xTable );
520 }
521 
522 uno::Type SAL_CALL ScDataPilotTablesObj::getElementType() throw(RuntimeException)
523 {
524 	ScUnoGuard aGuard;
525     return getCppuType((Reference<XDataPilotTable2>*)0);
526 }
527 
528 sal_Bool SAL_CALL ScDataPilotTablesObj::hasElements() throw(RuntimeException)
529 {
530 	ScUnoGuard aGuard;
531 	return ( getCount() != 0 );
532 }
533 
534 // XNameAccess
535 
536 Any SAL_CALL ScDataPilotTablesObj::getByName( const OUString& aName )
537         throw(NoSuchElementException, WrappedTargetException, RuntimeException)
538 {
539 	ScUnoGuard aGuard;
540     Reference<XDataPilotTable2> xTable(GetObjectByName_Impl(aName));
541     if (!xTable.is())
542         throw NoSuchElementException();
543     return Any( xTable );
544 }
545 
546 Sequence<OUString> SAL_CALL ScDataPilotTablesObj::getElementNames()
547                                                 throw(RuntimeException)
548 {
549 	ScUnoGuard aGuard;
550 	if (pDocShell)
551 	{
552 		ScDocument* pDoc = pDocShell->GetDocument();
553 		ScDPCollection* pColl = pDoc->GetDPCollection();
554 		if ( pColl )
555 		{
556 			//	count tables on this sheet
557 
558 			sal_uInt16 nFound = 0;
559 			sal_uInt16 nCount = pColl->GetCount();
560 			sal_uInt16 i;
561 			for (i=0; i<nCount; i++)
562 			{
563 				ScDPObject* pDPObj = (*pColl)[i];
564                 if ( pDPObj->GetOutRange().aStart.Tab() == nTab )
565 					++nFound;
566 			}
567 
568 			sal_uInt16 nPos = 0;
569             Sequence<OUString> aSeq(nFound);
570             OUString* pAry = aSeq.getArray();
571 			for (i=0; i<nCount; i++)
572 			{
573 				ScDPObject* pDPObj = (*pColl)[i];
574                 if ( pDPObj->GetOutRange().aStart.Tab() == nTab )
575 					pAry[nPos++] = pDPObj->GetName();
576 			}
577 
578 			return aSeq;
579 		}
580 	}
581     return Sequence<OUString>(0);
582 }
583 
584 sal_Bool SAL_CALL ScDataPilotTablesObj::hasByName( const OUString& aName )
585                                         throw(RuntimeException)
586 {
587 	ScUnoGuard aGuard;
588 	if (pDocShell)
589 	{
590 		ScDocument* pDoc = pDocShell->GetDocument();
591 		ScDPCollection* pColl = pDoc->GetDPCollection();
592 		if ( pColl )
593 		{
594 			String aNamStr(aName);
595 			sal_uInt16 nCount = pColl->GetCount();
596 			for (sal_uInt16 i=0; i<nCount; i++)
597 			{
598 				ScDPObject* pDPObj = (*pColl)[i];
599                 if ( pDPObj->GetOutRange().aStart.Tab() == nTab &&
600 					 pDPObj->GetName() == aNamStr )
601 					return sal_True;
602 			}
603 		}
604 	}
605 	return sal_False;
606 }
607 
608 //------------------------------------------------------------------------
609 
610 ScDataPilotDescriptorBase::ScDataPilotDescriptorBase(ScDocShell* pDocSh) :
611     maPropSet( lcl_GetDataPilotDescriptorBaseMap() ),
612 	pDocShell( pDocSh )
613 {
614 	pDocShell->GetDocument()->AddUnoObject(*this);
615 }
616 
617 ScDataPilotDescriptorBase::~ScDataPilotDescriptorBase()
618 {
619 	if (pDocShell)
620 		pDocShell->GetDocument()->RemoveUnoObject(*this);
621 }
622 
623 Any SAL_CALL ScDataPilotDescriptorBase::queryInterface( const uno::Type& rType )
624                                                 throw(RuntimeException)
625 {
626     SC_QUERYINTERFACE( XDataPilotDescriptor )
627     SC_QUERYINTERFACE( XPropertySet )
628     SC_QUERYINTERFACE( XDataPilotDataLayoutFieldSupplier )
629     SC_QUERYINTERFACE( XNamed )                 // base of XDataPilotDescriptor
630 	SC_QUERYINTERFACE( lang::XUnoTunnel )
631 	SC_QUERYINTERFACE( lang::XTypeProvider )
632 	SC_QUERYINTERFACE( lang::XServiceInfo )
633 
634 	return OWeakObject::queryInterface( rType );
635 }
636 
637 void SAL_CALL ScDataPilotDescriptorBase::acquire() throw()
638 {
639 	OWeakObject::acquire();
640 }
641 
642 void SAL_CALL ScDataPilotDescriptorBase::release() throw()
643 {
644 	OWeakObject::release();
645 }
646 
647 Sequence< uno::Type > SAL_CALL ScDataPilotDescriptorBase::getTypes()
648                                                     throw(RuntimeException)
649 {
650     static Sequence< uno::Type > aTypes;
651 	if ( aTypes.getLength() == 0 )
652 	{
653         aTypes.realloc( 6 );
654         uno::Type* pPtr = aTypes.getArray();
655         pPtr[ 0 ] = getCppuType( (const Reference< XDataPilotDescriptor >*)0 );
656         pPtr[ 1 ] = getCppuType( (const Reference< XPropertySet >*)0 );
657         pPtr[ 2 ] = getCppuType( (const Reference< XDataPilotDataLayoutFieldSupplier >*)0 );
658         pPtr[ 3 ] = getCppuType( (const Reference< lang::XUnoTunnel >*)0 );
659         pPtr[ 4 ] = getCppuType( (const Reference< lang::XTypeProvider >*)0 );
660         pPtr[ 5 ] = getCppuType( (const Reference< lang::XServiceInfo >*)0 );
661 	}
662 	return aTypes;
663 }
664 
665 Sequence<sal_Int8> SAL_CALL ScDataPilotDescriptorBase::getImplementationId()
666                                                     throw(RuntimeException)
667 {
668     static Sequence< sal_Int8 > aId;
669 	if( aId.getLength() == 0 )
670 	{
671 		aId.realloc( 16 );
672 		rtl_createUuid( (sal_uInt8 *)aId.getArray(), 0, sal_True );
673 	}
674 	return aId;
675 }
676 
677 void ScDataPilotDescriptorBase::Notify( SfxBroadcaster&, const SfxHint& rHint )
678 {
679 	//!	Referenz-Update?
680 
681 	if ( rHint.ISA( SfxSimpleHint ) &&
682 			((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING )
683 	{
684 		pDocShell = NULL;		// ungueltig geworden
685 	}
686 }
687 
688 // XDataPilotDescriptor
689 
690 CellRangeAddress SAL_CALL ScDataPilotDescriptorBase::getSourceRange()
691                                             throw(RuntimeException)
692 {
693 	ScUnoGuard aGuard;
694 
695     ScDPObject* pDPObject(GetDPObject());
696     if (!pDPObject)
697         throw RuntimeException();
698 
699     CellRangeAddress aRet;
700     if (pDPObject->IsSheetData())
701         ScUnoConversion::FillApiRange( aRet, pDPObject->GetSheetDesc()->aSourceRange );
702     return aRet;
703 }
704 
705 void SAL_CALL ScDataPilotDescriptorBase::setSourceRange( const CellRangeAddress& aSourceRange ) throw(RuntimeException)
706 {
707 	ScUnoGuard aGuard;
708 
709     ScDPObject* pDPObject = GetDPObject();
710     if (!pDPObject)
711         throw RuntimeException();
712 
713     ScSheetSourceDesc aSheetDesc;
714     if (pDPObject->IsSheetData())
715         aSheetDesc = *pDPObject->GetSheetDesc();
716     ScUnoConversion::FillScRange( aSheetDesc.aSourceRange, aSourceRange );
717     pDPObject->SetSheetDesc( aSheetDesc );
718     SetDPObject( pDPObject );
719 }
720 
721 Reference<XSheetFilterDescriptor> SAL_CALL ScDataPilotDescriptorBase::getFilterDescriptor()
722                                                 throw(RuntimeException)
723 {
724 	ScUnoGuard aGuard;
725 	return new ScDataPilotFilterDescriptor( pDocShell, this );
726 }
727 
728 Reference<XIndexAccess> SAL_CALL ScDataPilotDescriptorBase::getDataPilotFields()
729                                                 throw(RuntimeException)
730 {
731 	ScUnoGuard aGuard;
732     return new ScDataPilotFieldsObj( *this );
733 }
734 
735 Reference<XIndexAccess> SAL_CALL ScDataPilotDescriptorBase::getColumnFields()
736                                                 throw(RuntimeException)
737 {
738 	ScUnoGuard aGuard;
739     return new ScDataPilotFieldsObj( *this, DataPilotFieldOrientation_COLUMN );
740 }
741 
742 Reference<XIndexAccess> SAL_CALL ScDataPilotDescriptorBase::getRowFields()
743                                                 throw(RuntimeException)
744 {
745 	ScUnoGuard aGuard;
746     return new ScDataPilotFieldsObj( *this, DataPilotFieldOrientation_ROW );
747 }
748 
749 Reference<XIndexAccess> SAL_CALL ScDataPilotDescriptorBase::getPageFields()
750                                                 throw(RuntimeException)
751 {
752 	ScUnoGuard aGuard;
753     return new ScDataPilotFieldsObj( *this, DataPilotFieldOrientation_PAGE );
754 }
755 
756 Reference<XIndexAccess> SAL_CALL ScDataPilotDescriptorBase::getDataFields()
757                                                 throw(RuntimeException)
758 {
759 	ScUnoGuard aGuard;
760     return new ScDataPilotFieldsObj( *this, DataPilotFieldOrientation_DATA );
761 }
762 
763 Reference<XIndexAccess> SAL_CALL ScDataPilotDescriptorBase::getHiddenFields()
764                                                 throw(RuntimeException)
765 {
766 	ScUnoGuard aGuard;
767     return new ScDataPilotFieldsObj( *this, DataPilotFieldOrientation_HIDDEN );
768 }
769 
770 // XPropertySet
771 Reference< XPropertySetInfo > SAL_CALL ScDataPilotDescriptorBase::getPropertySetInfo(  )
772                                                 throw(RuntimeException)
773 {
774 	ScUnoGuard aGuard;
775     static Reference<XPropertySetInfo> aRef =
776         new SfxItemPropertySetInfo( maPropSet.getPropertyMap() );
777 	return aRef;
778 }
779 
780 void SAL_CALL ScDataPilotDescriptorBase::setPropertyValue( const OUString& aPropertyName, const Any& aValue )
781         throw(UnknownPropertyException, PropertyVetoException, IllegalArgumentException,
782                 WrappedTargetException, RuntimeException)
783 {
784 	ScUnoGuard aGuard;
785     ScDPObject* pDPObject = GetDPObject();
786     if (pDPObject)
787     {
788 	    ScDPSaveData* pOldData = pDPObject->GetSaveData();
789         DBG_ASSERT(pOldData, "Here should be a SaveData");
790 	    if ( pOldData )
791 	    {
792 		    ScDPSaveData aNewData( *pOldData );
793 
794     	    String aNameString = aPropertyName;
795     	    if ( aNameString.EqualsAscii( SC_UNO_COLGRAND ) )
796             {
797 	            aNewData.SetColumnGrand(::cppu::any2bool( aValue ));
798             }
799     	    else if ( aNameString.EqualsAscii( SC_UNO_IGNEMPROWS ) )
800             {
801                 aNewData.SetIgnoreEmptyRows(::cppu::any2bool( aValue ));
802             }
803     	    else if ( aNameString.EqualsAscii( SC_UNO_RPTEMPTY ) )
804             {
805     	        aNewData.SetRepeatIfEmpty(::cppu::any2bool( aValue ));
806             }
807     	    else if ( aNameString.EqualsAscii( SC_UNO_ROWGRAND ) )
808             {
809 	            aNewData.SetRowGrand(::cppu::any2bool( aValue ));
810             }
811             else if ( aNameString.EqualsAscii( SC_UNO_SHOWFILT ) )
812             {
813                 aNewData.SetFilterButton(::cppu::any2bool( aValue ));
814             }
815             else if ( aNameString.EqualsAscii( SC_UNO_DRILLDOWN ) )
816             {
817                 aNewData.SetDrillDown(::cppu::any2bool( aValue ));
818             }
819             else if ( aNameString.EqualsAscii( SC_UNO_GRANDTOTAL_NAME ) )
820             {
821                 rtl::OUString aStrVal;
822                 if ( aValue >>= aStrVal )
823                     aNewData.SetGrandTotalName(aStrVal);
824             }
825             else if ( aNameString.EqualsAscii( SC_UNO_IMPORTDESC ) )
826             {
827                 uno::Sequence<beans::PropertyValue> aArgSeq;
828                 if ( aValue >>= aArgSeq )
829                 {
830                     ScImportSourceDesc aImportDesc;
831 
832                     const ScImportSourceDesc* pOldDesc = pDPObject->GetImportSourceDesc();
833                     if (pOldDesc)
834                         aImportDesc = *pOldDesc;
835 
836                     ScImportParam aParam;
837                     ScImportDescriptor::FillImportParam( aParam, aArgSeq );
838 
839                     sal_uInt16 nNewType = sheet::DataImportMode_NONE;
840                     if ( aParam.bImport )
841                     {
842                         if ( aParam.bSql )
843                             nNewType = sheet::DataImportMode_SQL;
844                         else if ( aParam.nType == ScDbQuery )
845                             nNewType = sheet::DataImportMode_QUERY;
846                         else
847                             nNewType = sheet::DataImportMode_TABLE;
848                     }
849                     aImportDesc.nType   = nNewType;
850                     aImportDesc.aDBName = aParam.aDBName;
851                     aImportDesc.aObject = aParam.aStatement;
852                     aImportDesc.bNative = aParam.bNative;
853 
854                     pDPObject->SetImportDesc( aImportDesc );
855                 }
856             }
857             else if ( aNameString.EqualsAscii( SC_UNO_SOURCESERV ) )
858             {
859                 rtl::OUString aStrVal;
860                 if ( aValue >>= aStrVal )
861                 {
862                     String aEmpty;
863                     ScDPServiceDesc aServiceDesc(aEmpty, aEmpty, aEmpty, aEmpty, aEmpty);
864 
865                     const ScDPServiceDesc* pOldDesc = pDPObject->GetDPServiceDesc();
866                     if (pOldDesc)
867                         aServiceDesc = *pOldDesc;
868 
869                     aServiceDesc.aServiceName = aStrVal;
870 
871                     pDPObject->SetServiceData( aServiceDesc );
872                 }
873             }
874             else if ( aNameString.EqualsAscii( SC_UNO_SERVICEARG ) )
875             {
876                 uno::Sequence<beans::PropertyValue> aArgSeq;
877                 if ( aValue >>= aArgSeq )
878                 {
879                     String aEmpty;
880                     ScDPServiceDesc aServiceDesc(aEmpty, aEmpty, aEmpty, aEmpty, aEmpty);
881 
882                     const ScDPServiceDesc* pOldDesc = pDPObject->GetDPServiceDesc();
883                     if (pOldDesc)
884                         aServiceDesc = *pOldDesc;
885 
886                     rtl::OUString aStrVal;
887                     sal_Int32 nArgs = aArgSeq.getLength();
888                     for (sal_Int32 nArgPos=0; nArgPos<nArgs; ++nArgPos)
889                     {
890                         const beans::PropertyValue& rProp = aArgSeq[nArgPos];
891                         String aPropName(rProp.Name);
892 
893                         if (aPropName.EqualsAscii( SC_UNO_SOURCENAME ))
894                         {
895                             if ( rProp.Value >>= aStrVal )
896                                 aServiceDesc.aParSource = aStrVal;
897                         }
898                         else if (aPropName.EqualsAscii( SC_UNO_OBJECTNAME ))
899                         {
900                             if ( rProp.Value >>= aStrVal )
901                                 aServiceDesc.aParName = aStrVal;
902                         }
903                         else if (aPropName.EqualsAscii( SC_UNO_USERNAME ))
904                         {
905                             if ( rProp.Value >>= aStrVal )
906                                 aServiceDesc.aParUser = aStrVal;
907                         }
908                         else if (aPropName.EqualsAscii( SC_UNO_PASSWORD ))
909                         {
910                             if ( rProp.Value >>= aStrVal )
911                                 aServiceDesc.aParPass = aStrVal;
912                         }
913                     }
914 
915                     pDPObject->SetServiceData( aServiceDesc );
916                 }
917             }
918             else
919                 throw UnknownPropertyException();
920 
921             pDPObject->SetSaveData( aNewData );
922         }
923 
924         SetDPObject(pDPObject);
925     }
926 }
927 
928 Any SAL_CALL ScDataPilotDescriptorBase::getPropertyValue( const OUString& aPropertyName )
929         throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
930 {
931 	ScUnoGuard aGuard;
932     Any aRet;
933 
934     ScDPObject* pDPObject(GetDPObject());
935     if (pDPObject)
936     {
937 	    ScDPSaveData* pOldData = pDPObject->GetSaveData();
938         DBG_ASSERT(pOldData, "Here should be a SaveData");
939 	    if ( pOldData )
940 	    {
941 		    ScDPSaveData aNewData( *pOldData );
942 
943     	    String aNameString = aPropertyName;
944     	    if ( aNameString.EqualsAscii( SC_UNO_COLGRAND ) )
945             {
946 	            aRet = ::cppu::bool2any( aNewData.GetColumnGrand() );
947             }
948     	    else if ( aNameString.EqualsAscii( SC_UNO_IGNEMPROWS ) )
949             {
950                 aRet = ::cppu::bool2any( aNewData.GetIgnoreEmptyRows() );
951             }
952     	    else if ( aNameString.EqualsAscii( SC_UNO_RPTEMPTY ) )
953             {
954     	        aRet = ::cppu::bool2any( aNewData.GetRepeatIfEmpty() );
955             }
956     	    else if ( aNameString.EqualsAscii( SC_UNO_ROWGRAND ) )
957             {
958 	            aRet = ::cppu::bool2any( aNewData.GetRowGrand() );
959             }
960             else if ( aNameString.EqualsAscii( SC_UNO_SHOWFILT ) )
961             {
962                 aRet = ::cppu::bool2any( aNewData.GetFilterButton() );
963             }
964             else if ( aNameString.EqualsAscii( SC_UNO_DRILLDOWN ) )
965             {
966                 aRet = ::cppu::bool2any( aNewData.GetDrillDown() );
967             }
968             else if ( aNameString.EqualsAscii( SC_UNO_GRANDTOTAL_NAME ) )
969             {
970                 const rtl::OUString* pGrandTotalName = aNewData.GetGrandTotalName();
971                 if (pGrandTotalName)
972                     aRet <<= *pGrandTotalName;      // same behavior as in ScDPSource
973             }
974             else if ( aNameString.EqualsAscii( SC_UNO_IMPORTDESC ) )
975             {
976                 const ScImportSourceDesc* pImportDesc = pDPObject->GetImportSourceDesc();
977                 if ( pImportDesc )
978                 {
979                     // fill ScImportParam so ScImportDescriptor::FillProperties can be used
980                     ScImportParam aParam;
981                     aParam.bImport    = ( pImportDesc->nType != sheet::DataImportMode_NONE );
982                     aParam.aDBName    = pImportDesc->aDBName;
983                     aParam.aStatement = pImportDesc->aObject;
984                     aParam.bNative    = pImportDesc->bNative;
985                     aParam.bSql       = ( pImportDesc->nType == sheet::DataImportMode_SQL );
986                     aParam.nType      = static_cast<sal_uInt8>(( pImportDesc->nType == sheet::DataImportMode_QUERY ) ? ScDbQuery : ScDbTable);
987 
988                     uno::Sequence<beans::PropertyValue> aSeq( ScImportDescriptor::GetPropertyCount() );
989                     ScImportDescriptor::FillProperties( aSeq, aParam );
990                     aRet <<= aSeq;
991                 }
992                 else
993                 {
994                     // empty sequence
995                     uno::Sequence<beans::PropertyValue> aEmpty(0);
996                     aRet <<= aEmpty;
997                 }
998             }
999             else if ( aNameString.EqualsAscii( SC_UNO_SOURCESERV ) )
1000             {
1001                 rtl::OUString aServiceName;
1002                 const ScDPServiceDesc* pServiceDesc = pDPObject->GetDPServiceDesc();
1003                 if (pServiceDesc)
1004                     aServiceName = pServiceDesc->aServiceName;
1005                 aRet <<= aServiceName;      // empty string if no ServiceDesc set
1006             }
1007             else if ( aNameString.EqualsAscii( SC_UNO_SERVICEARG ) )
1008             {
1009                 const ScDPServiceDesc* pServiceDesc = pDPObject->GetDPServiceDesc();
1010                 if (pServiceDesc)
1011                 {
1012                     uno::Sequence<beans::PropertyValue> aSeq( 4 );
1013                     beans::PropertyValue* pArray = aSeq.getArray();
1014                     pArray[0].Name = rtl::OUString::createFromAscii( SC_UNO_SOURCENAME );
1015                     pArray[0].Value <<= rtl::OUString( pServiceDesc->aParSource );
1016                     pArray[1].Name = rtl::OUString::createFromAscii( SC_UNO_OBJECTNAME );
1017                     pArray[1].Value <<= rtl::OUString( pServiceDesc->aParName );
1018                     pArray[2].Name = rtl::OUString::createFromAscii( SC_UNO_USERNAME );
1019                     pArray[2].Value <<= rtl::OUString( pServiceDesc->aParUser );
1020                     pArray[3].Name = rtl::OUString::createFromAscii( SC_UNO_PASSWORD );
1021                     pArray[3].Value <<= rtl::OUString( pServiceDesc->aParPass );
1022                     aRet <<= aSeq;
1023                 }
1024                 else
1025                 {
1026                     // empty sequence
1027                     uno::Sequence<beans::PropertyValue> aEmpty(0);
1028                     aRet <<= aEmpty;
1029                 }
1030             }
1031             else
1032                 throw UnknownPropertyException();
1033         }
1034     }
1035 
1036     return aRet;
1037 }
1038 
1039 void SAL_CALL ScDataPilotDescriptorBase::addPropertyChangeListener(
1040         const OUString& /* aPropertyName */, const Reference<XPropertyChangeListener >& /* xListener */ )
1041         throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
1042 {
1043 }
1044 
1045 void SAL_CALL ScDataPilotDescriptorBase::removePropertyChangeListener(
1046         const OUString& /* aPropertyName */, const Reference<XPropertyChangeListener >& /* aListener */ )
1047         throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
1048 {
1049 }
1050 
1051 void SAL_CALL ScDataPilotDescriptorBase::addVetoableChangeListener(
1052         const OUString& /* PropertyName */, const Reference<XVetoableChangeListener >& /* aListener */ )
1053         throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
1054 {
1055 }
1056 
1057 void SAL_CALL ScDataPilotDescriptorBase::removeVetoableChangeListener(
1058         const OUString& /* PropertyName */, const Reference<XVetoableChangeListener >& /* aListener */ )
1059         throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
1060 {
1061 }
1062 
1063 // XDataPilotDataLayoutFieldSupplier
1064 
1065 Reference< XDataPilotField > SAL_CALL ScDataPilotDescriptorBase::getDataLayoutField() throw(RuntimeException)
1066 {
1067     ScUnoGuard aGuard;
1068     if( ScDPObject* pDPObject = GetDPObject() )
1069     {
1070         if( ScDPSaveData* pSaveData = pDPObject->GetSaveData() )
1071         {
1072             if( /*ScDPSaveDimension* pDataDim =*/ pSaveData->GetDataLayoutDimension() )
1073             {
1074                 ScFieldIdentifier aFieldId( OUString( RTL_CONSTASCII_USTRINGPARAM( SC_DATALAYOUT_NAME ) ), 0, true );
1075                 return new ScDataPilotFieldObj( *this, aFieldId );
1076             }
1077         }
1078     }
1079     return 0;
1080 }
1081 
1082 // XUnoTunnel
1083 
1084 sal_Int64 SAL_CALL ScDataPilotDescriptorBase::getSomething(
1085                 const Sequence<sal_Int8 >& rId ) throw(RuntimeException)
1086 {
1087 	if ( rId.getLength() == 16 &&
1088           0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
1089 									rId.getConstArray(), 16 ) )
1090 	{
1091         return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this));
1092 	}
1093 	return 0;
1094 }
1095 
1096 // static
1097 const Sequence<sal_Int8>& ScDataPilotDescriptorBase::getUnoTunnelId()
1098 {
1099     static Sequence<sal_Int8> * pSeq = 0;
1100 	if( !pSeq )
1101 	{
1102 		osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
1103 		if( !pSeq )
1104 		{
1105             static Sequence< sal_Int8 > aSeq( 16 );
1106 			rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
1107 			pSeq = &aSeq;
1108 		}
1109 	}
1110 	return *pSeq;
1111 }
1112 
1113 // static
1114 ScDataPilotDescriptorBase* ScDataPilotDescriptorBase::getImplementation(
1115                                 const Reference<XDataPilotDescriptor> xObj )
1116 {
1117 	ScDataPilotDescriptorBase* pRet = NULL;
1118     Reference<lang::XUnoTunnel> xUT( xObj, UNO_QUERY );
1119 	if (xUT.is())
1120         pRet = reinterpret_cast<ScDataPilotDescriptorBase*>(sal::static_int_cast<sal_IntPtr>(xUT->getSomething(getUnoTunnelId())));
1121 	return pRet;
1122 }
1123 
1124 //------------------------------------------------------------------------
1125 
1126 ScDataPilotTableObj::ScDataPilotTableObj(ScDocShell* pDocSh, SCTAB nT, const String& rN) :
1127 	ScDataPilotDescriptorBase( pDocSh ),
1128 	nTab( nT ),
1129     aName( rN ),
1130     aModifyListeners( 0 )
1131 {
1132 }
1133 
1134 ScDataPilotTableObj::~ScDataPilotTableObj()
1135 {
1136 }
1137 
1138 Any SAL_CALL ScDataPilotTableObj::queryInterface( const uno::Type& rType )
1139                                                 throw(RuntimeException)
1140 {
1141     // since we manually do resolve the query for XDataPilotTable2
1142     // we also need to do the same for XDataPilotTable
1143     SC_QUERYINTERFACE( XDataPilotTable )
1144     SC_QUERYINTERFACE( XDataPilotTable2 )
1145     SC_QUERYINTERFACE( XModifyBroadcaster )
1146 
1147 	return ScDataPilotDescriptorBase::queryInterface( rType );
1148 }
1149 
1150 void SAL_CALL ScDataPilotTableObj::acquire() throw()
1151 {
1152 	ScDataPilotDescriptorBase::acquire();
1153 }
1154 
1155 void SAL_CALL ScDataPilotTableObj::release() throw()
1156 {
1157 	ScDataPilotDescriptorBase::release();
1158 }
1159 
1160 Sequence< uno::Type > SAL_CALL ScDataPilotTableObj::getTypes() throw(RuntimeException)
1161 {
1162     static Sequence< uno::Type > aTypes;
1163 	if ( aTypes.getLength() == 0 )
1164 	{
1165         Sequence< uno::Type > aParentTypes = ScDataPilotDescriptorBase::getTypes();
1166         sal_Int32 nParentLen = aParentTypes.getLength();
1167 		const uno::Type* pParentPtr = aParentTypes.getConstArray();
1168 
1169         aTypes.realloc( nParentLen + 2 );
1170 		uno::Type* pPtr = aTypes.getArray();
1171         for (sal_Int32 i = 0; i < nParentLen; ++i)
1172             pPtr[ i ] = pParentPtr[ i ];               // parent types first
1173 
1174         pPtr[ nParentLen ] = getCppuType( (const Reference< XDataPilotTable2 >*)0 );
1175         pPtr[ nParentLen+1 ] = getCppuType( (const Reference< XModifyBroadcaster >*)0 );
1176 	}
1177 	return aTypes;
1178 }
1179 
1180 Sequence<sal_Int8> SAL_CALL ScDataPilotTableObj::getImplementationId()
1181                                                     throw(RuntimeException)
1182 {
1183     static Sequence< sal_Int8 > aId;
1184 	if( aId.getLength() == 0 )
1185 	{
1186 		aId.realloc( 16 );
1187 		rtl_createUuid( (sal_uInt8 *)aId.getArray(), 0, sal_True );
1188 	}
1189 	return aId;
1190 }
1191 
1192 // ---
1193 ScDPObject* ScDataPilotTableObj::GetDPObject() const
1194 {
1195     return lcl_GetDPObject(GetDocShell(), nTab, aName);
1196 }
1197 
1198 void ScDataPilotTableObj::SetDPObject( ScDPObject* pDPObject )
1199 {
1200 	ScDocShell* pDocSh = GetDocShell();
1201 	ScDPObject* pDPObj = lcl_GetDPObject(pDocSh, nTab, aName);
1202 	if ( pDPObj && pDocSh )
1203 	{
1204         ScDBDocFunc aFunc(*pDocSh);
1205         aFunc.DataPilotUpdate( pDPObj, pDPObject, sal_True, sal_True );
1206     }
1207 }
1208 
1209 // "rest of XDataPilotDescriptor"
1210 
1211 OUString SAL_CALL ScDataPilotTableObj::getName() throw(RuntimeException)
1212 {
1213 	ScUnoGuard aGuard;
1214 	ScDPObject* pDPObj = lcl_GetDPObject(GetDocShell(), nTab, aName);
1215 	if (pDPObj)
1216 		return pDPObj->GetName();
1217     return OUString();
1218 }
1219 
1220 void SAL_CALL ScDataPilotTableObj::setName( const OUString& aNewName )
1221                                                 throw(RuntimeException)
1222 {
1223 	ScUnoGuard aGuard;
1224 	ScDPObject* pDPObj = lcl_GetDPObject(GetDocShell(), nTab, aName);
1225 	if (pDPObj)
1226 	{
1227 		//!	test for existing names !!!
1228 
1229 		String aString(aNewName);
1230 		pDPObj->SetName( aString );		//! Undo - DBDocFunc ???
1231 		aName = aString;
1232 
1233 		//	DataPilotUpdate would do too much (output table is not changed)
1234 		GetDocShell()->SetDocumentModified();
1235 	}
1236 }
1237 
1238 OUString SAL_CALL ScDataPilotTableObj::getTag() throw(RuntimeException)
1239 {
1240 	ScUnoGuard aGuard;
1241 	ScDPObject* pDPObj = lcl_GetDPObject(GetDocShell(), nTab, aName);
1242 	if (pDPObj)
1243 		return pDPObj->GetTag();
1244     return OUString();
1245 }
1246 
1247 void SAL_CALL ScDataPilotTableObj::setTag( const OUString& aNewTag )
1248                                                 throw(RuntimeException)
1249 {
1250 	ScUnoGuard aGuard;
1251 	ScDPObject* pDPObj = lcl_GetDPObject(GetDocShell(), nTab, aName);
1252 	if (pDPObj)
1253 	{
1254 		String aString(aNewTag);
1255 		pDPObj->SetTag( aString );		//! Undo - DBDocFunc ???
1256 
1257 		//	DataPilotUpdate would do too much (output table is not changed)
1258 		GetDocShell()->SetDocumentModified();
1259 	}
1260 }
1261 
1262 // XDataPilotTable
1263 
1264 CellRangeAddress SAL_CALL ScDataPilotTableObj::getOutputRange() throw(RuntimeException)
1265 {
1266 	ScUnoGuard aGuard;
1267     CellRangeAddress aRet;
1268 	ScDPObject* pDPObj = lcl_GetDPObject(GetDocShell(), nTab, aName);
1269 	if (pDPObj)
1270 	{
1271 		ScRange aRange(pDPObj->GetOutRange());
1272 		aRet.Sheet		 = aRange.aStart.Tab();
1273 		aRet.StartColumn = aRange.aStart.Col();
1274 		aRet.StartRow	 = aRange.aStart.Row();
1275 		aRet.EndColumn	 = aRange.aEnd.Col();
1276 		aRet.EndRow		 = aRange.aEnd.Row();
1277 	}
1278 	return aRet;
1279 }
1280 
1281 sal_uLong RefreshDPObject( ScDPObject *pDPObj, ScDocument *pDoc, ScDocShell *pDocSh, sal_Bool bRecord, sal_Bool bApi );
1282 
1283 void SAL_CALL ScDataPilotTableObj::refresh() throw(RuntimeException)
1284 {
1285 	ScUnoGuard aGuard;
1286 	if( ScDPObject* pDPObj = lcl_GetDPObject(GetDocShell(), nTab, aName) )
1287 		RefreshDPObject( pDPObj, NULL, GetDocShell(), sal_True, sal_True );
1288 	//if (pDPObj)
1289 	//{
1290 	//	ScDPObject* pNew = new ScDPObject(*pDPObj);
1291 	//	ScDBDocFunc aFunc(*GetDocShell());
1292 	//	aFunc.DataPilotUpdate( pDPObj, pNew, sal_True, sal_True );
1293 	//	delete pNew;		// DataPilotUpdate copies settings from "new" object
1294 	//}
1295 
1296 }
1297 
1298 Sequence< Sequence<Any> > SAL_CALL ScDataPilotTableObj::getDrillDownData(const CellAddress& aAddr)
1299     throw (RuntimeException)
1300 {
1301     ScUnoGuard aGuard;
1302     Sequence< Sequence<Any> > aTabData;
1303     ScAddress aAddr2(static_cast<SCCOL>(aAddr.Column), static_cast<SCROW>(aAddr.Row), aAddr.Sheet);
1304     ScDPObject* pObj = GetDPObject();
1305     if (!pObj)
1306         throw RuntimeException();
1307 
1308     pObj->GetDrillDownData(aAddr2, aTabData);
1309     return aTabData;
1310 }
1311 
1312 DataPilotTablePositionData SAL_CALL ScDataPilotTableObj::getPositionData(const CellAddress& aAddr)
1313     throw (RuntimeException)
1314 {
1315     ScUnoGuard aGuard;
1316     DataPilotTablePositionData aPosData;
1317     ScAddress aAddr2(static_cast<SCCOL>(aAddr.Column), static_cast<SCROW>(aAddr.Row), aAddr.Sheet);
1318     ScDPObject* pObj = GetDPObject();
1319     if (!pObj)
1320         throw RuntimeException();
1321 
1322     pObj->GetPositionData(aAddr2, aPosData);
1323     return aPosData;
1324 }
1325 
1326 void SAL_CALL ScDataPilotTableObj::insertDrillDownSheet(const CellAddress& aAddr)
1327     throw (RuntimeException)
1328 {
1329     ScUnoGuard aGuard;
1330     ScDPObject* pDPObj = GetDPObject();
1331     if (!pDPObj)
1332         throw RuntimeException();
1333 
1334     Sequence<DataPilotFieldFilter> aFilters;
1335     pDPObj->GetDataFieldPositionData(
1336         ScAddress(static_cast<SCCOL>(aAddr.Column), static_cast<SCROW>(aAddr.Row), aAddr.Sheet), aFilters);
1337     GetDocShell()->GetBestViewShell()->ShowDataPilotSourceData(*pDPObj, aFilters);
1338 }
1339 
1340 CellRangeAddress SAL_CALL ScDataPilotTableObj::getOutputRangeByType( sal_Int32 nType )
1341     throw (IllegalArgumentException, RuntimeException)
1342 {
1343     ScUnoGuard aGuard;
1344     if (nType < 0 || nType > DataPilotOutputRangeType::RESULT)
1345         throw IllegalArgumentException();
1346 
1347     CellRangeAddress aRet;
1348     if (ScDPObject* pDPObj = lcl_GetDPObject(GetDocShell(), nTab, aName))
1349         ScUnoConversion::FillApiRange( aRet, pDPObj->GetOutputRangeByType( nType ) );
1350     return aRet;
1351 }
1352 
1353 void SAL_CALL ScDataPilotTableObj::addModifyListener( const uno::Reference<util::XModifyListener>& aListener )
1354     throw (uno::RuntimeException)
1355 {
1356     ScUnoGuard aGuard;
1357 
1358     uno::Reference<util::XModifyListener> *pObj = new uno::Reference<util::XModifyListener>( aListener );
1359     aModifyListeners.Insert( pObj, aModifyListeners.Count() );
1360 
1361     if ( aModifyListeners.Count() == 1 )
1362     {
1363         acquire();  // don't lose this object (one ref for all listeners)
1364     }
1365 }
1366 
1367 void SAL_CALL ScDataPilotTableObj::removeModifyListener( const uno::Reference<util::XModifyListener>& aListener )
1368     throw (uno::RuntimeException)
1369 {
1370     ScUnoGuard aGuard;
1371 
1372     acquire();      // in case the listeners have the last ref - released below
1373 
1374     sal_uInt16 nCount = aModifyListeners.Count();
1375     for ( sal_uInt16 n=nCount; n--; )
1376     {
1377         uno::Reference<util::XModifyListener> *pObj = aModifyListeners[n];
1378         if ( *pObj == aListener )
1379         {
1380             aModifyListeners.DeleteAndDestroy( n );
1381 
1382             if ( aModifyListeners.Count() == 0 )
1383             {
1384                 release();      // release the ref for the listeners
1385             }
1386 
1387             break;
1388         }
1389     }
1390 
1391     release();      // might delete this object
1392 }
1393 
1394 void ScDataPilotTableObj::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
1395 {
1396     if ( rHint.ISA(ScDataPilotModifiedHint) &&
1397          static_cast<const ScDataPilotModifiedHint&>(rHint).GetName() == aName )
1398     {
1399         Refreshed_Impl();
1400     }
1401     else if ( rHint.ISA( ScUpdateRefHint ) )
1402     {
1403         ScRange aRange( 0, 0, nTab );
1404         ScRangeList aRanges;
1405         aRanges.Append( aRange );
1406         const ScUpdateRefHint& rRef = static_cast< const ScUpdateRefHint& >( rHint );
1407         if ( aRanges.UpdateReference( rRef.GetMode(), GetDocShell()->GetDocument(), rRef.GetRange(),
1408                  rRef.GetDx(), rRef.GetDy(), rRef.GetDz() ) &&
1409              aRanges.Count() == 1 )
1410         {
1411             const ScRange* pRange = aRanges.GetObject( 0 );
1412             if ( pRange )
1413             {
1414                 nTab = pRange->aStart.Tab();
1415             }
1416         }
1417     }
1418 
1419     ScDataPilotDescriptorBase::Notify( rBC, rHint );
1420 }
1421 
1422 void ScDataPilotTableObj::Refreshed_Impl()
1423 {
1424     lang::EventObject aEvent;
1425     aEvent.Source.set((cppu::OWeakObject*)this);
1426 
1427     // the EventObject holds a Ref to this object until after the listener calls
1428 
1429     ScDocument* pDoc = GetDocShell()->GetDocument();
1430     for ( sal_uInt16 n=0; n<aModifyListeners.Count(); n++ )
1431         pDoc->AddUnoListenerCall( *aModifyListeners[n], aEvent );
1432 }
1433 
1434 // ============================================================================
1435 
1436 ScDataPilotDescriptor::ScDataPilotDescriptor(ScDocShell* pDocSh) :
1437 	ScDataPilotDescriptorBase( pDocSh ),
1438     mpDPObject(new ScDPObject(pDocSh ? pDocSh->GetDocument() : NULL) )
1439 {
1440     mpDPObject->SetAlive(sal_True);
1441     ScDPSaveData aSaveData;
1442     // set defaults like in ScPivotParam constructor
1443  	aSaveData.SetColumnGrand( sal_True );
1444 	aSaveData.SetRowGrand( sal_True );
1445 	aSaveData.SetIgnoreEmptyRows( sal_False );
1446 	aSaveData.SetRepeatIfEmpty( sal_False );
1447     mpDPObject->SetSaveData(aSaveData);
1448     ScSheetSourceDesc aSheetDesc;
1449     mpDPObject->SetSheetDesc(aSheetDesc);
1450     mpDPObject->GetSource();
1451 }
1452 
1453 ScDataPilotDescriptor::~ScDataPilotDescriptor()
1454 {
1455     delete mpDPObject;
1456 }
1457 
1458 ScDPObject* ScDataPilotDescriptor::GetDPObject() const
1459 {
1460     return mpDPObject;
1461 }
1462 
1463 void ScDataPilotDescriptor::SetDPObject( ScDPObject* pDPObject )
1464 {
1465     if (mpDPObject != pDPObject)
1466     {
1467         delete mpDPObject;
1468         mpDPObject = pDPObject;
1469         DBG_ERROR("replace DPObject should not happen");
1470     }
1471 }
1472 
1473 // "rest of XDataPilotDescriptor"
1474 
1475 OUString SAL_CALL ScDataPilotDescriptor::getName() throw(RuntimeException)
1476 {
1477 	ScUnoGuard aGuard;
1478 	return mpDPObject->GetName();
1479 }
1480 
1481 void SAL_CALL ScDataPilotDescriptor::setName( const OUString& aNewName )
1482                                                 throw(RuntimeException)
1483 {
1484 	ScUnoGuard aGuard;
1485 	mpDPObject->SetName( aNewName );
1486 }
1487 
1488 OUString SAL_CALL ScDataPilotDescriptor::getTag() throw(RuntimeException)
1489 {
1490 	ScUnoGuard aGuard;
1491 	return mpDPObject->GetTag();
1492 }
1493 
1494 void SAL_CALL ScDataPilotDescriptor::setTag( const OUString& aNewTag )
1495                                                 throw(RuntimeException)
1496 {
1497 	ScUnoGuard aGuard;
1498 	mpDPObject->SetTag( aNewTag );
1499 }
1500 
1501 // ============================================================================
1502 
1503 ScDataPilotChildObjBase::ScDataPilotChildObjBase( ScDataPilotDescriptorBase& rParent ) :
1504     mrParent( rParent )
1505 {
1506     mrParent.acquire();
1507 }
1508 
1509 ScDataPilotChildObjBase::ScDataPilotChildObjBase( ScDataPilotDescriptorBase& rParent, const ScFieldIdentifier& rFieldId ) :
1510     mrParent( rParent ),
1511     maFieldId( rFieldId )
1512 {
1513     mrParent.acquire();
1514 }
1515 
1516 ScDataPilotChildObjBase::~ScDataPilotChildObjBase()
1517 {
1518     mrParent.release();
1519 }
1520 
1521 ScDPObject* ScDataPilotChildObjBase::GetDPObject() const
1522 {
1523     return mrParent.GetDPObject();
1524 }
1525 
1526 void ScDataPilotChildObjBase::SetDPObject( ScDPObject* pDPObject )
1527 {
1528     mrParent.SetDPObject( pDPObject );
1529 }
1530 
1531 ScDPSaveDimension* ScDataPilotChildObjBase::GetDPDimension( ScDPObject** ppDPObject ) const
1532 {
1533     if( ScDPObject* pDPObj = GetDPObject() )
1534     {
1535         if( ppDPObject ) *ppDPObject = pDPObj;
1536         if( ScDPSaveData* pSaveData = pDPObj->GetSaveData() )
1537         {
1538             if( maFieldId.mbDataLayout )
1539                 return pSaveData->GetDataLayoutDimension();
1540 
1541             if( maFieldId.mnFieldIdx == 0 )
1542                 return pSaveData->GetDimensionByName( maFieldId.maFieldName );
1543 
1544             // find dimension with specified index (search in duplicated dimensions)
1545             String aFieldName = maFieldId.maFieldName;  // needed for comparison
1546             const List& rDimensions = pSaveData->GetDimensions();
1547             sal_uLong nDimCount = rDimensions.Count();
1548             sal_Int32 nFoundIdx = 0;
1549             for( sal_uLong nDim = 0; nDim < nDimCount; ++nDim )
1550             {
1551                 ScDPSaveDimension* pDim = static_cast< ScDPSaveDimension* >( rDimensions.GetObject( nDim ) );
1552                 if( !pDim->IsDataLayout() && (pDim->GetName() == aFieldName) )
1553                 {
1554                     if( nFoundIdx == maFieldId.mnFieldIdx )
1555                         return pDim;
1556                     ++nFoundIdx;
1557                 }
1558             }
1559         }
1560     }
1561     return 0;
1562 }
1563 
1564 sal_Int32 ScDataPilotChildObjBase::GetMemberCount() const
1565 {
1566     sal_Int32 nRet = 0;
1567     Reference<XNameAccess> xMembersNA = GetMembers();
1568     if (xMembersNA.is())
1569     {
1570         Reference< XIndexAccess > xMembersIA( new ScNameToIndexAccess( xMembersNA ) );
1571         nRet = xMembersIA->getCount();
1572     }
1573     return nRet;
1574 }
1575 
1576 Reference< XNameAccess > ScDataPilotChildObjBase::GetMembers() const
1577 {
1578     Reference< XNameAccess > xMembersNA;
1579     if( ScDPObject* pDPObj = GetDPObject() )
1580         pDPObj->GetMembersNA( lcl_GetObjectIndex( pDPObj, maFieldId ), xMembersNA );
1581     return xMembersNA;
1582 }
1583 
1584 // ============================================================================
1585 
1586 ScDataPilotFieldsObj::ScDataPilotFieldsObj( ScDataPilotDescriptorBase& rParent ) :
1587     ScDataPilotChildObjBase( rParent )
1588 {
1589 }
1590 
1591 ScDataPilotFieldsObj::ScDataPilotFieldsObj( ScDataPilotDescriptorBase& rParent, DataPilotFieldOrientation eOrient ) :
1592     ScDataPilotChildObjBase( rParent ),
1593     maOrient( eOrient )
1594 {
1595 }
1596 
1597 ScDataPilotFieldsObj::~ScDataPilotFieldsObj()
1598 {
1599 }
1600 
1601 sal_Int32 lcl_GetFieldCount( const Reference<XDimensionsSupplier>& rSource, const Any& rOrient )
1602 {
1603     sal_Int32 nRet = 0;
1604 
1605     Reference<XNameAccess> xDimsName(rSource->getDimensions());
1606     Reference<XIndexAccess> xIntDims(new ScNameToIndexAccess( xDimsName ));
1607 	sal_Int32 nIntCount = xIntDims->getCount();
1608     if (rOrient.hasValue())
1609     {
1610         // all fields of the specified orientation, including duplicated
1611         Reference<XPropertySet> xDim;
1612         for (sal_Int32 i = 0; i < nIntCount; ++i)
1613         {
1614             xDim.set(xIntDims->getByIndex(i), UNO_QUERY);
1615             if (xDim.is() && (xDim->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_ORIENTAT))) == rOrient))
1616                 ++nRet;
1617         }
1618     }
1619     else
1620     {
1621         // count all non-duplicated fields
1622 
1623         Reference<XPropertySet> xDim;
1624         for (sal_Int32 i = 0; i < nIntCount; ++i)
1625         {
1626             xDim.set(xIntDims->getByIndex(i), UNO_QUERY);
1627             if ( xDim.is() && !lcl_IsDuplicated( xDim ) )
1628                 ++nRet;
1629         }
1630     }
1631 
1632 	return nRet;
1633 }
1634 
1635 sal_Bool lcl_GetFieldDataByIndex( const Reference<XDimensionsSupplier>& rSource,
1636                                 const Any& rOrient, SCSIZE nIndex, ScFieldIdentifier& rFieldId )
1637 {
1638 	sal_Bool bOk = sal_False;
1639 	SCSIZE nPos = 0;
1640 	sal_Int32 nDimIndex = 0;
1641 
1642     Reference<XNameAccess> xDimsName(rSource->getDimensions());
1643     Reference<XIndexAccess> xIntDims(new ScNameToIndexAccess( xDimsName ));
1644 	sal_Int32 nIntCount = xIntDims->getCount();
1645     Reference<XPropertySet> xDim;
1646     if (rOrient.hasValue())
1647     {
1648         sal_Int32 i = 0;
1649         while (i < nIntCount && !bOk)
1650         {
1651             xDim.set(xIntDims->getByIndex(i), UNO_QUERY);
1652             if (xDim.is() && (xDim->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_ORIENTAT))) == rOrient))
1653             {
1654                 if (nPos == nIndex)
1655                 {
1656                     bOk = sal_True;
1657                     nDimIndex = i;
1658                 }
1659                 else
1660                     ++nPos;
1661             }
1662             ++i;
1663         }
1664     }
1665     else
1666     {
1667         sal_Int32 i = 0;
1668         while (i < nIntCount && !bOk)
1669         {
1670             xDim.set(xIntDims->getByIndex(i), UNO_QUERY);
1671             if ( xDim.is() && !lcl_IsDuplicated( xDim ) )
1672             {
1673                 if (nPos == nIndex)
1674                 {
1675                     bOk = sal_True;
1676                     nDimIndex = i;
1677                 }
1678                 else
1679                     ++nPos;
1680             }
1681             ++i;
1682         }
1683     }
1684 
1685     if ( bOk )
1686     {
1687         xDim.set( xIntDims->getByIndex(nDimIndex), UNO_QUERY );
1688         Reference<XNamed> xDimName( xDim, UNO_QUERY );
1689         if ( xDimName.is() )
1690         {
1691             OUString sOriginalName( lcl_GetOriginalName( xDimName ) );
1692             rFieldId.maFieldName = sOriginalName;
1693             rFieldId.mbDataLayout = ScUnoHelpFunctions::GetBoolProperty( xDim,
1694                         OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_ISDATALA)) );
1695 
1696             sal_Int32 nRepeat = 0;
1697             if ( rOrient.hasValue() && lcl_IsDuplicated( xDim ) )
1698             {
1699                 // find the repeat count
1700                 // (this relies on the original dimension always being before the duplicates)
1701 
1702                 Reference<XNamed> xPrevName;
1703                 for (sal_Int32 i = 0; i < nDimIndex; ++i)
1704                 {
1705                     xPrevName.set( xIntDims->getByIndex(i), UNO_QUERY );
1706                     if ( xPrevName.is() && lcl_GetOriginalName( xPrevName ) == sOriginalName )
1707                         ++nRepeat;
1708                 }
1709             }
1710             rFieldId.mnFieldIdx = nRepeat;
1711         }
1712         else
1713             bOk = sal_False;
1714     }
1715 
1716 	return bOk;
1717 }
1718 
1719 sal_Bool lcl_GetFieldDataByName( ScDPObject* pDPObj, const OUString& rFieldName, ScFieldIdentifier& rFieldId )
1720 {
1721     // "By name" is always the first match.
1722     // The name "Data" always refers to the data layout field.
1723     rFieldId.maFieldName = rFieldName;
1724     rFieldId.mnFieldIdx = 0;
1725     rFieldId.mbDataLayout = rFieldName.equalsAscii( SC_DATALAYOUT_NAME );
1726 
1727     pDPObj->GetSource();    // IsDimNameInUse doesn't update source data
1728 
1729     // check if the named field exists (not for data layout)
1730     return rFieldId.mbDataLayout || pDPObj->IsDimNameInUse( rFieldName );
1731 }
1732 
1733 // XDataPilotFields
1734 
1735 ScDataPilotFieldObj* ScDataPilotFieldsObj::GetObjectByIndex_Impl( sal_Int32 nIndex ) const
1736 {
1737 // TODO
1738     if (ScDPObject* pObj = GetDPObject())
1739     {
1740         ScFieldIdentifier aFieldId;
1741         if (lcl_GetFieldDataByIndex( pObj->GetSource(), maOrient, nIndex, aFieldId ))
1742             return new ScDataPilotFieldObj( mrParent, aFieldId, maOrient );
1743     }
1744     return 0;
1745 }
1746 
1747 ScDataPilotFieldObj* ScDataPilotFieldsObj::GetObjectByName_Impl(const OUString& aName) const
1748 {
1749     if (ScDPObject* pDPObj = GetDPObject())
1750     {
1751         ScFieldIdentifier aFieldId;
1752         if (lcl_GetFieldDataByName( pDPObj, aName, aFieldId ))
1753             return new ScDataPilotFieldObj( mrParent, aFieldId, maOrient );
1754     }
1755     return 0;
1756 }
1757 
1758 // XEnumerationAccess
1759 
1760 Reference<XEnumeration> SAL_CALL ScDataPilotFieldsObj::createEnumeration()
1761                                                     throw(RuntimeException)
1762 {
1763 	ScUnoGuard aGuard;
1764     return new ScIndexEnumeration(this, OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.DataPilotFieldsEnumeration")));
1765 }
1766 
1767 // XIndexAccess
1768 
1769 sal_Int32 SAL_CALL ScDataPilotFieldsObj::getCount() throw(RuntimeException)
1770 {
1771 	ScUnoGuard aGuard;
1772 // TODO
1773     ScDPObject* pDPObj = GetDPObject();
1774     return pDPObj ? lcl_GetFieldCount( pDPObj->GetSource(), maOrient ) : 0;
1775 }
1776 
1777 Any SAL_CALL ScDataPilotFieldsObj::getByIndex( sal_Int32 nIndex )
1778         throw(IndexOutOfBoundsException, WrappedTargetException, RuntimeException)
1779 {
1780 	ScUnoGuard aGuard;
1781     Reference< XPropertySet > xField( GetObjectByIndex_Impl( nIndex ) );
1782     if (!xField.is())
1783         throw IndexOutOfBoundsException();
1784     return Any( xField );
1785 }
1786 
1787 uno::Type SAL_CALL ScDataPilotFieldsObj::getElementType() throw(RuntimeException)
1788 {
1789 	ScUnoGuard aGuard;
1790     return getCppuType((Reference<XPropertySet>*)0);
1791 }
1792 
1793 sal_Bool SAL_CALL ScDataPilotFieldsObj::hasElements() throw(RuntimeException)
1794 {
1795 	ScUnoGuard aGuard;
1796 	return ( getCount() != 0 );
1797 }
1798 
1799 Any SAL_CALL ScDataPilotFieldsObj::getByName( const OUString& aName )
1800         throw(NoSuchElementException, WrappedTargetException, RuntimeException)
1801 {
1802 	ScUnoGuard aGuard;
1803     Reference<XPropertySet> xField(GetObjectByName_Impl(aName));
1804     if (!xField.is())
1805         throw NoSuchElementException();
1806     return Any( xField );
1807 }
1808 
1809 Sequence<OUString> SAL_CALL ScDataPilotFieldsObj::getElementNames()
1810                                                 throw(RuntimeException)
1811 {
1812 	ScUnoGuard aGuard;
1813 // TODO
1814     if (ScDPObject* pDPObj = GetDPObject())
1815     {
1816         Sequence< OUString > aSeq( lcl_GetFieldCount( pDPObj->GetSource(), maOrient ) );
1817         OUString* pAry = aSeq.getArray();
1818         const List& rDimensions = pDPObj->GetSaveData()->GetDimensions();
1819         sal_Int32 nDimCount = rDimensions.Count();
1820 	    for (sal_Int32 nDim = 0; nDim < nDimCount; nDim++)
1821 	    {
1822             ScDPSaveDimension* pDim = (ScDPSaveDimension*)rDimensions.GetObject(nDim);
1823             if(maOrient.hasValue() && (pDim->GetOrientation() == maOrient.get< DataPilotFieldOrientation >()))
1824             {
1825                 *pAry = pDim->GetName();
1826                 ++pAry;
1827             }
1828         }
1829     	return aSeq;
1830     }
1831     return Sequence<OUString>();
1832 }
1833 
1834 sal_Bool SAL_CALL ScDataPilotFieldsObj::hasByName( const OUString& aName )
1835                                         throw(RuntimeException)
1836 {
1837 	ScUnoGuard aGuard;
1838 
1839 	return GetObjectByName_Impl(aName) != NULL;
1840 }
1841 
1842 //------------------------------------------------------------------------
1843 
1844 ScDataPilotFieldObj::ScDataPilotFieldObj(
1845         ScDataPilotDescriptorBase& rParent, const ScFieldIdentifier& rFieldId ) :
1846     ScDataPilotChildObjBase( rParent, rFieldId ),
1847     maPropSet( lcl_GetDataPilotFieldMap() )
1848 {
1849 }
1850 
1851 ScDataPilotFieldObj::ScDataPilotFieldObj( ScDataPilotDescriptorBase& rParent,
1852         const ScFieldIdentifier& rFieldId, const Any& rOrient ) :
1853     ScDataPilotChildObjBase( rParent, rFieldId ),
1854     maPropSet( lcl_GetDataPilotFieldMap() ),
1855     maOrient( rOrient )
1856 {
1857 }
1858 
1859 ScDataPilotFieldObj::~ScDataPilotFieldObj()
1860 {
1861 }
1862 
1863 // XNamed
1864 
1865 OUString SAL_CALL ScDataPilotFieldObj::getName() throw(RuntimeException)
1866 {
1867 	ScUnoGuard aGuard;
1868     OUString aName;
1869     if( ScDPSaveDimension* pDim = GetDPDimension() )
1870     {
1871         if( pDim->IsDataLayout() )
1872             aName = OUString( RTL_CONSTASCII_USTRINGPARAM( SC_DATALAYOUT_NAME ) );
1873         else
1874         {
1875             const rtl::OUString* pLayoutName = pDim->GetLayoutName();
1876             if (pLayoutName)
1877                 aName = *pLayoutName;
1878             else
1879                 aName = pDim->GetName();
1880         }                                                                }
1881     return aName;
1882 }
1883 
1884 void SAL_CALL ScDataPilotFieldObj::setName( const OUString& rName ) throw(RuntimeException)
1885 {
1886 	ScUnoGuard aGuard;
1887     ScDPObject* pDPObj = 0;
1888     ScDPSaveDimension* pDim = GetDPDimension( &pDPObj );
1889     if( pDim && !pDim->IsDataLayout() )
1890     {
1891         String aName( rName );
1892         pDim->SetLayoutName(aName);
1893         SetDPObject( pDPObj );
1894     }
1895 }
1896 
1897 // XPropertySet
1898 
1899 Reference<XPropertySetInfo> SAL_CALL ScDataPilotFieldObj::getPropertySetInfo()
1900                                                         throw(RuntimeException)
1901 {
1902 	ScUnoGuard aGuard;
1903     static Reference<XPropertySetInfo> aRef(
1904         new SfxItemPropertySetInfo( maPropSet.getPropertyMap() ));
1905 	return aRef;
1906 }
1907 
1908 void SAL_CALL ScDataPilotFieldObj::setPropertyValue( const OUString& aPropertyName, const Any& aValue )
1909         throw(UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
1910 {
1911 	ScUnoGuard aGuard;
1912 	String aNameString(aPropertyName);
1913 	if ( aNameString.EqualsAscii( SC_UNONAME_FUNCTION ) )
1914 	{
1915         // #i109350# use GetEnumFromAny because it also allows sal_Int32
1916         GeneralFunction eFunction = (GeneralFunction)
1917                             ScUnoHelpFunctions::GetEnumFromAny( aValue );
1918         setFunction( eFunction );
1919 	}
1920     else if ( aNameString.EqualsAscii( SC_UNONAME_SUBTOTALS ) )
1921     {
1922         Sequence< GeneralFunction > aSubtotals;
1923         if( aValue >>= aSubtotals )
1924             setSubtotals( aSubtotals );
1925     }
1926 	else if ( aNameString.EqualsAscii( SC_UNONAME_ORIENT ) )
1927 	{
1928 		//!	test for correct enum type?
1929         DataPilotFieldOrientation eOrient = (DataPilotFieldOrientation)
1930 							ScUnoHelpFunctions::GetEnumFromAny( aValue );
1931 		setOrientation( eOrient );
1932 	}
1933 	else if ( aNameString.EqualsAscii( SC_UNONAME_SELPAGE ) )
1934     {
1935         OUString sCurrentPage;
1936         if (aValue >>= sCurrentPage)
1937             setCurrentPage(sCurrentPage);
1938     }
1939 	else if ( aNameString.EqualsAscii( SC_UNONAME_USESELPAGE ) )
1940     {
1941         setUseCurrentPage(cppu::any2bool(aValue));
1942     }
1943 	else if ( aNameString.EqualsAscii( SC_UNONAME_HASAUTOSHOW ) )
1944     {
1945         if (!cppu::any2bool(aValue))
1946             setAutoShowInfo(NULL);
1947     }
1948 	else if ( aNameString.EqualsAscii( SC_UNONAME_AUTOSHOW ) )
1949     {
1950         DataPilotFieldAutoShowInfo aInfo;
1951         if (aValue >>= aInfo)
1952             setAutoShowInfo(&aInfo);
1953     }
1954 	else if ( aNameString.EqualsAscii( SC_UNONAME_HASLAYOUTINFO ) )
1955     {
1956         if (!cppu::any2bool(aValue))
1957             setLayoutInfo(NULL);
1958     }
1959 	else if ( aNameString.EqualsAscii( SC_UNONAME_LAYOUTINFO ) )
1960     {
1961         DataPilotFieldLayoutInfo aInfo;
1962         if (aValue >>= aInfo)
1963             setLayoutInfo(&aInfo);
1964     }
1965 	else if ( aNameString.EqualsAscii( SC_UNONAME_HASREFERENCE ) )
1966     {
1967         if (!cppu::any2bool(aValue))
1968             setReference(NULL);
1969     }
1970 	else if ( aNameString.EqualsAscii( SC_UNONAME_REFERENCE ) )
1971     {
1972         DataPilotFieldReference aRef;
1973         if (aValue >>= aRef)
1974             setReference(&aRef);
1975     }
1976 	else if ( aNameString.EqualsAscii( SC_UNONAME_HASSORTINFO ) )
1977     {
1978         if (!cppu::any2bool(aValue))
1979             setSortInfo(NULL);
1980     }
1981 	else if ( aNameString.EqualsAscii( SC_UNONAME_SORTINFO ) )
1982     {
1983         DataPilotFieldSortInfo aInfo;
1984         if (aValue >>= aInfo)
1985             setSortInfo(&aInfo);
1986     }
1987     else if ( aNameString.EqualsAscii( SC_UNONAME_ISGROUP ) )
1988     {
1989         if (!cppu::any2bool(aValue))
1990             setGroupInfo(NULL);
1991     }
1992     else if ( aNameString.EqualsAscii( SC_UNONAME_GROUPINFO ) )
1993     {
1994         DataPilotFieldGroupInfo aInfo;
1995         if (aValue >>= aInfo)
1996             setGroupInfo(&aInfo);
1997     }
1998     else if ( aNameString.EqualsAscii( SC_UNONAME_SHOWEMPTY ) )
1999     {
2000         setShowEmpty(cppu::any2bool(aValue));
2001     }
2002 }
2003 
2004 Any SAL_CALL ScDataPilotFieldObj::getPropertyValue( const OUString& aPropertyName )
2005         throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
2006 {
2007 	ScUnoGuard aGuard;
2008 	String aNameString(aPropertyName);
2009     Any aRet;
2010 
2011 	if ( aNameString.EqualsAscii( SC_UNONAME_FUNCTION ) )
2012 		aRet <<= getFunction();
2013     else if ( aNameString.EqualsAscii( SC_UNONAME_SUBTOTALS ) )
2014         aRet <<= getSubtotals();
2015 	else if ( aNameString.EqualsAscii( SC_UNONAME_ORIENT ) )
2016 		aRet <<= getOrientation();
2017 	else if ( aNameString.EqualsAscii( SC_UNONAME_SELPAGE ) )
2018         aRet <<= getCurrentPage();
2019 	else if ( aNameString.EqualsAscii( SC_UNONAME_USESELPAGE ) )
2020         aRet <<= getUseCurrentPage();
2021 	else if ( aNameString.EqualsAscii( SC_UNONAME_HASAUTOSHOW ) )
2022         aRet = ::cppu::bool2any(getAutoShowInfo() != NULL);
2023 	else if ( aNameString.EqualsAscii( SC_UNONAME_AUTOSHOW ) )
2024     {
2025         const DataPilotFieldAutoShowInfo* pInfo = getAutoShowInfo();
2026         if (pInfo)
2027             aRet <<= DataPilotFieldAutoShowInfo(*pInfo);
2028     }
2029 	else if ( aNameString.EqualsAscii( SC_UNONAME_HASLAYOUTINFO ) )
2030         aRet = ::cppu::bool2any(getLayoutInfo() != NULL);
2031 	else if ( aNameString.EqualsAscii( SC_UNONAME_LAYOUTINFO ) )
2032     {
2033         const DataPilotFieldLayoutInfo* pInfo = getLayoutInfo();
2034         if (pInfo)
2035             aRet <<= DataPilotFieldLayoutInfo(*pInfo);
2036     }
2037 	else if ( aNameString.EqualsAscii( SC_UNONAME_HASREFERENCE ) )
2038         aRet = ::cppu::bool2any(getReference() != NULL);
2039 	else if ( aNameString.EqualsAscii( SC_UNONAME_REFERENCE ) )
2040     {
2041         const DataPilotFieldReference* pRef = getReference();
2042         if (pRef)
2043             aRet <<= DataPilotFieldReference(*pRef);
2044     }
2045 	else if ( aNameString.EqualsAscii( SC_UNONAME_HASSORTINFO ) )
2046         aRet = ::cppu::bool2any(getSortInfo() != NULL);
2047 	else if ( aNameString.EqualsAscii( SC_UNONAME_SORTINFO ) )
2048     {
2049         const DataPilotFieldSortInfo* pInfo = getSortInfo();
2050         if (pInfo)
2051             aRet <<= DataPilotFieldSortInfo(*pInfo);
2052     }
2053 	else if ( aNameString.EqualsAscii( SC_UNONAME_ISGROUP ) )
2054         aRet = ::cppu::bool2any(hasGroupInfo());
2055 	else if ( aNameString.EqualsAscii( SC_UNONAME_GROUPINFO ) )
2056     {
2057         aRet <<= getGroupInfo();
2058     }
2059     else if ( aNameString.EqualsAscii( SC_UNONAME_SHOWEMPTY ) )
2060         aRet <<= getShowEmpty();
2061 
2062 	return aRet;
2063 }
2064 
2065 // XDatePilotField
2066 
2067 Reference<XIndexAccess> SAL_CALL ScDataPilotFieldObj::getItems()
2068                 throw (RuntimeException)
2069 {
2070     ScUnoGuard aGuard;
2071     if (!mxItems.is())
2072         mxItems.set( new ScDataPilotItemsObj( mrParent, maFieldId ) );
2073     return mxItems;
2074 }
2075 
2076 SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDataPilotFieldObj )
2077 
2078 DataPilotFieldOrientation ScDataPilotFieldObj::getOrientation() const
2079 {
2080     ScUnoGuard aGuard;
2081     ScDPSaveDimension* pDim = GetDPDimension();
2082     return pDim ? static_cast< DataPilotFieldOrientation >( pDim->GetOrientation() ) : DataPilotFieldOrientation_HIDDEN;
2083 }
2084 
2085 void ScDataPilotFieldObj::setOrientation(DataPilotFieldOrientation eNew)
2086 {
2087     ScUnoGuard aGuard;
2088     if (maOrient.hasValue() && (eNew == maOrient.get< DataPilotFieldOrientation >()))
2089         return;
2090 
2091     ScDPObject* pDPObj = 0;
2092     if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) )
2093     {
2094         ScDPSaveData* pSaveData = pDPObj->GetSaveData();
2095 
2096         /*  If the field was taken from getDataPilotFields(), don't reset the
2097             orientation for an existing use, but create a duplicated field
2098             instead (for "Data" orientation only). */
2099         if ( !maOrient.hasValue() && !maFieldId.mbDataLayout &&
2100              (pDim->GetOrientation() != DataPilotFieldOrientation_HIDDEN) &&
2101              (eNew == DataPilotFieldOrientation_DATA) )
2102         {
2103 
2104             ScDPSaveDimension* pNewDim = 0;
2105 
2106             // look for existing duplicate with orientation "hidden"
2107 
2108             String aNameStr( maFieldId.maFieldName );
2109             const List& rDimensions = pSaveData->GetDimensions();
2110             sal_Int32 nDimCount = rDimensions.Count();
2111             sal_Int32 nFound = 0;
2112             for ( sal_Int32 nDim = 0; nDim < nDimCount && !pNewDim; nDim++ )
2113             {
2114                 ScDPSaveDimension* pOneDim = static_cast<ScDPSaveDimension*>(rDimensions.GetObject(nDim));
2115                 if ( !pOneDim->IsDataLayout() && (pOneDim->GetName() == aNameStr) )
2116                 {
2117                     if ( pOneDim->GetOrientation() == DataPilotFieldOrientation_HIDDEN )
2118                         pNewDim = pOneDim;      // use this one
2119                     else
2120                         ++nFound;               // count existing non-hidden occurences
2121                 }
2122             }
2123 
2124             if ( !pNewDim )     // if none found, create a new duplicated dimension
2125                 pNewDim = &pSaveData->DuplicateDimension( *pDim );
2126 
2127             maFieldId.mnFieldIdx = nFound;      // keep accessing the new one
2128             pDim = pNewDim;
2129         }
2130 
2131         pDim->SetOrientation(sal::static_int_cast<sal_uInt16>(eNew));
2132 
2133         // move changed field behind all other fields (make it the last field in dimension)
2134         pSaveData->SetPosition( pDim, pSaveData->GetDimensions().Count() );
2135 
2136         SetDPObject( pDPObj );
2137 
2138         maOrient <<= eNew;   // modifying the same object's orientation again doesn't create another duplicate
2139     }
2140 }
2141 
2142 GeneralFunction ScDataPilotFieldObj::getFunction() const
2143 {
2144     ScUnoGuard aGuard;
2145     GeneralFunction eRet = GeneralFunction_NONE;
2146     if( ScDPSaveDimension* pDim = GetDPDimension() )
2147     {
2148         if( pDim->GetOrientation() != DataPilotFieldOrientation_DATA )
2149         {
2150             // for non-data fields, property Function is the subtotals
2151             long nSubCount = pDim->GetSubTotalsCount();
2152             if ( nSubCount > 0 )
2153                 eRet = (GeneralFunction)pDim->GetSubTotalFunc(0);    // always use the first one
2154             // else keep NONE
2155         }
2156         else
2157             eRet = (GeneralFunction)pDim->GetFunction();
2158     }
2159     return eRet;
2160 }
2161 
2162 void ScDataPilotFieldObj::setFunction(GeneralFunction eNewFunc)
2163 {
2164     ScUnoGuard aGuard;
2165     ScDPObject* pDPObj = 0;
2166     if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) )
2167     {
2168         if( pDim->GetOrientation() != DataPilotFieldOrientation_DATA )
2169         {
2170             // for non-data fields, property Function is the subtotals
2171             if ( eNewFunc == GeneralFunction_NONE )
2172                 pDim->SetSubTotals( 0, NULL );
2173             else
2174             {
2175                 sal_uInt16 nFunc = sal::static_int_cast<sal_uInt16>( eNewFunc );
2176                 pDim->SetSubTotals( 1, &nFunc );
2177             }
2178         }
2179         else
2180             pDim->SetFunction( sal::static_int_cast<sal_uInt16>( eNewFunc ) );
2181         SetDPObject( pDPObj );
2182     }
2183 }
2184 
2185 Sequence< GeneralFunction > ScDataPilotFieldObj::getSubtotals() const
2186 {
2187     ScUnoGuard aGuard;
2188     Sequence< GeneralFunction > aRet;
2189     if( ScDPSaveDimension* pDim = GetDPDimension() )
2190     {
2191         if( pDim->GetOrientation() != DataPilotFieldOrientation_DATA )
2192         {
2193             // for non-data fields, property Functions is the sequence of subtotals
2194             sal_Int32 nCount = static_cast< sal_Int32 >( pDim->GetSubTotalsCount() );
2195             if ( nCount > 0 )
2196             {
2197                 aRet.realloc( nCount );
2198                 for( sal_Int32 nIdx = 0; nIdx < nCount; ++nIdx )
2199                     aRet[ nIdx ] = (GeneralFunction)pDim->GetSubTotalFunc( nIdx );
2200             }
2201         }
2202     }
2203     return aRet;
2204 }
2205 
2206 void ScDataPilotFieldObj::setSubtotals( const Sequence< GeneralFunction >& rSubtotals )
2207 {
2208     ScUnoGuard aGuard;
2209     ScDPObject* pDPObj = 0;
2210     if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) )
2211     {
2212         if( pDim->GetOrientation() != DataPilotFieldOrientation_DATA )
2213         {
2214             sal_Int32 nCount = rSubtotals.getLength();
2215             if( nCount == 1 )
2216             {
2217                 // count 1: all values are allowed (including NONE and AUTO)
2218                 if( rSubtotals[ 0 ] == GeneralFunction_NONE )
2219                     pDim->SetSubTotals( 0, NULL );
2220                 else
2221                 {
2222                     sal_uInt16 nFunc = sal::static_int_cast<sal_uInt16>( rSubtotals[ 0 ] );
2223                     pDim->SetSubTotals( 1, &nFunc );
2224                 }
2225             }
2226             else if( nCount > 1 )
2227             {
2228                 // set multiple functions, ignore NONE and AUTO in this case
2229                 ::std::vector< sal_uInt16 > aSubt;
2230                 for( sal_Int32 nIdx = 0; nIdx < nCount; ++nIdx )
2231                 {
2232                     GeneralFunction eFunc = rSubtotals[ nIdx ];
2233                     if( (eFunc != GeneralFunction_NONE) && (eFunc != GeneralFunction_AUTO) )
2234                     {
2235                         // do not insert functions twice
2236                         sal_uInt16 nFunc = static_cast< sal_uInt16 >( eFunc );
2237                         if( ::std::find( aSubt.begin(), aSubt.end(), nFunc ) == aSubt.end() )
2238                             aSubt.push_back( nFunc );
2239                     }
2240                 }
2241                 // set values from vector to ScDPSaveDimension
2242                 if ( aSubt.empty() )
2243                     pDim->SetSubTotals( 0, NULL );
2244                 else
2245                     pDim->SetSubTotals( static_cast< long >( aSubt.size() ), &aSubt.front() );
2246             }
2247         }
2248         SetDPObject( pDPObj );
2249     }
2250 }
2251 
2252 OUString ScDataPilotFieldObj::getCurrentPage() const
2253 {
2254     ScUnoGuard aGuard;
2255     ScDPSaveDimension* pDim = GetDPDimension();
2256     if( pDim && pDim->HasCurrentPage() )
2257         return pDim->GetCurrentPage();
2258     return OUString();
2259 }
2260 
2261 void ScDataPilotFieldObj::setCurrentPage( const OUString& rPage )
2262 {
2263     ScUnoGuard aGuard;
2264     ScDPObject* pDPObj = 0;
2265     if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) )
2266     {
2267         String aPage( rPage );
2268         pDim->SetCurrentPage( &aPage );
2269         SetDPObject( pDPObj );
2270     }
2271 }
2272 
2273 sal_Bool ScDataPilotFieldObj::getUseCurrentPage() const
2274 {
2275     ScUnoGuard aGuard;
2276     ScDPSaveDimension* pDim = GetDPDimension();
2277     return pDim && pDim->HasCurrentPage();
2278 }
2279 
2280 void ScDataPilotFieldObj::setUseCurrentPage( sal_Bool bUse )
2281 {
2282     ScUnoGuard aGuard;
2283     ScDPObject* pDPObj = 0;
2284     if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) )
2285     {
2286         if( bUse )
2287         {
2288             /*  It is somehow useless to set the property "HasSelectedPage" to
2289                 true, because it is still needed to set an explicit page name. */
2290             if( !pDim->HasCurrentPage() )
2291             {
2292                 String aPage;
2293                 pDim->SetCurrentPage( &aPage );
2294             }
2295         }
2296         else
2297             pDim->SetCurrentPage( 0 );
2298         SetDPObject( pDPObj );
2299     }
2300 }
2301 
2302 const DataPilotFieldAutoShowInfo* ScDataPilotFieldObj::getAutoShowInfo()
2303 {
2304     ScUnoGuard aGuard;
2305     ScDPSaveDimension* pDim = GetDPDimension();
2306     return pDim ? pDim->GetAutoShowInfo() : 0;
2307 }
2308 
2309 void ScDataPilotFieldObj::setAutoShowInfo( const DataPilotFieldAutoShowInfo* pInfo )
2310 {
2311     ScUnoGuard aGuard;
2312     ScDPObject* pDPObj = 0;
2313     if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) )
2314     {
2315         pDim->SetAutoShowInfo( pInfo );
2316         SetDPObject( pDPObj );
2317     }
2318 }
2319 
2320 const DataPilotFieldLayoutInfo* ScDataPilotFieldObj::getLayoutInfo()
2321 {
2322     ScUnoGuard aGuard;
2323     ScDPSaveDimension* pDim = GetDPDimension();
2324     return pDim ? pDim->GetLayoutInfo() : 0;
2325 }
2326 
2327 void ScDataPilotFieldObj::setLayoutInfo( const DataPilotFieldLayoutInfo* pInfo )
2328 {
2329     ScUnoGuard aGuard;
2330     ScDPObject* pDPObj = 0;
2331     if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) )
2332     {
2333         pDim->SetLayoutInfo( pInfo );
2334         SetDPObject( pDPObj );
2335     }
2336 }
2337 
2338 const DataPilotFieldReference* ScDataPilotFieldObj::getReference()
2339 {
2340     ScUnoGuard aGuard;
2341     ScDPSaveDimension* pDim = GetDPDimension();
2342     return pDim ? pDim->GetReferenceValue() : 0;
2343 }
2344 
2345 void ScDataPilotFieldObj::setReference( const DataPilotFieldReference* pInfo )
2346 {
2347     ScUnoGuard aGuard;
2348     ScDPObject* pDPObj = 0;
2349     if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) )
2350     {
2351         pDim->SetReferenceValue( pInfo );
2352         SetDPObject( pDPObj );
2353     }
2354 }
2355 
2356 const DataPilotFieldSortInfo* ScDataPilotFieldObj::getSortInfo()
2357 {
2358     ScUnoGuard aGuard;
2359     ScDPSaveDimension* pDim = GetDPDimension();
2360     return pDim ? pDim->GetSortInfo() : 0;
2361 }
2362 
2363 void ScDataPilotFieldObj::setSortInfo( const DataPilotFieldSortInfo* pInfo )
2364 {
2365     ScUnoGuard aGuard;
2366     ScDPObject* pDPObj = 0;
2367     if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) )
2368     {
2369         pDim->SetSortInfo( pInfo );
2370         SetDPObject( pDPObj );
2371     }
2372 }
2373 
2374 sal_Bool ScDataPilotFieldObj::getShowEmpty() const
2375 {
2376     ScUnoGuard aGuard;
2377     ScDPSaveDimension* pDim = GetDPDimension();
2378     return pDim && pDim->GetShowEmpty();
2379 }
2380 
2381 void ScDataPilotFieldObj::setShowEmpty( sal_Bool bShow )
2382 {
2383     ScUnoGuard aGuard;
2384     ScDPObject* pDPObj = 0;
2385     if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) )
2386     {
2387         pDim->SetShowEmpty( bShow );
2388         SetDPObject( pDPObj );
2389     }
2390 }
2391 
2392 sal_Bool ScDataPilotFieldObj::hasGroupInfo()
2393 {
2394     ScUnoGuard aGuard;
2395     ScDPObject* pDPObj = 0;
2396     if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) )
2397         if( const ScDPDimensionSaveData* pDimData = pDPObj->GetSaveData()->GetExistingDimensionData() )
2398             return pDimData->GetNamedGroupDim( pDim->GetName() ) || pDimData->GetNumGroupDim( pDim->GetName() );
2399     return sal_False;
2400 }
2401 
2402 DataPilotFieldGroupInfo ScDataPilotFieldObj::getGroupInfo()
2403 {
2404     ScUnoGuard aGuard;
2405     DataPilotFieldGroupInfo aInfo;
2406     ScDPObject* pDPObj = 0;
2407     if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) )
2408     {
2409         if( const ScDPDimensionSaveData* pDimData = pDPObj->GetSaveData()->GetExistingDimensionData() )
2410         {
2411             if( const ScDPSaveGroupDimension* pGroupDim = pDimData->GetNamedGroupDim( pDim->GetName() ) )
2412             {
2413                 // grouped by ...
2414                 aInfo.GroupBy = pGroupDim->GetDatePart();
2415 
2416                 // find source field
2417                 try
2418                 {
2419                     Reference< XNameAccess > xFields( mrParent.getDataPilotFields(), UNO_QUERY_THROW );
2420                     aInfo.SourceField.set( xFields->getByName( pGroupDim->GetSourceDimName() ), UNO_QUERY );
2421                 }
2422                 catch( Exception& )
2423                 {
2424                 }
2425 
2426                 ScDataPilotConversion::FillGroupInfo( aInfo, pGroupDim->GetDateInfo() );
2427                 if( pGroupDim->GetDatePart() == 0 )
2428                 {
2429                     // fill vector of group and group member information
2430                     ScFieldGroups aGroups;
2431                     for( sal_Int32 nIdx = 0, nCount = pGroupDim->GetGroupCount(); nIdx < nCount; ++nIdx )
2432                     {
2433                         if( const ScDPSaveGroupItem* pGroup = pGroupDim->GetGroupByIndex( nIdx ) )
2434                         {
2435                             ScFieldGroup aGroup;
2436                             aGroup.maName = pGroup->GetGroupName();
2437                             for( sal_Int32 nMemIdx = 0, nMemCount = pGroup->GetElementCount(); nMemIdx < nMemCount; ++nMemIdx )
2438                                 if( const String* pMem = pGroup->GetElementByIndex( nMemIdx ) )
2439                                     aGroup.maMembers.push_back( *pMem );
2440                             aGroups.push_back( aGroup );
2441                         }
2442                     }
2443                     aInfo.Groups = new ScDataPilotFieldGroupsObj( aGroups );
2444                 }
2445             }
2446             else if( const ScDPSaveNumGroupDimension* pNumGroupDim = pDimData->GetNumGroupDim( pDim->GetName() ) )
2447             {
2448                 if (pNumGroupDim->GetDatePart())
2449                 {
2450                     ScDataPilotConversion::FillGroupInfo( aInfo, pNumGroupDim->GetDateInfo() );
2451                     aInfo.GroupBy = pNumGroupDim->GetDatePart();
2452                 }
2453                 else
2454                 {
2455                     ScDataPilotConversion::FillGroupInfo( aInfo, pNumGroupDim->GetInfo() );
2456                 }
2457             }
2458         }
2459     }
2460     return aInfo;
2461 }
2462 
2463 void ScDataPilotFieldObj::setGroupInfo( const DataPilotFieldGroupInfo* pInfo )
2464 {
2465     ScUnoGuard aGuard;
2466     ScDPObject* pDPObj = 0;
2467     if( /*ScDPSaveDimension* pDim =*/ GetDPDimension( &pDPObj ) )
2468     {
2469         ScDPSaveData* pSaveData = pDPObj->GetSaveData();
2470         if( pInfo && lclCheckMinMaxStep( *pInfo ) )
2471         {
2472             ScDPNumGroupInfo aInfo;
2473             aInfo.Enable = sal_True;
2474             aInfo.DateValues = pInfo->HasDateValues;
2475             aInfo.AutoStart = pInfo->HasAutoStart;
2476             aInfo.AutoEnd = pInfo->HasAutoEnd;
2477             aInfo.Start = pInfo->Start;
2478             aInfo.End = pInfo->End;
2479             aInfo.Step = pInfo->Step;
2480             Reference< XNamed > xNamed( pInfo->SourceField, UNO_QUERY );
2481             if( xNamed.is() )
2482             {
2483                 ScDPSaveGroupDimension aGroupDim( xNamed->getName(), getName() );
2484                 if( pInfo->GroupBy )
2485                     aGroupDim.SetDateInfo(aInfo, pInfo->GroupBy);
2486                 else
2487                 {
2488                     Reference<XIndexAccess> xIndex(pInfo->Groups, UNO_QUERY);
2489                     if (xIndex.is())
2490                     {
2491                         sal_Int32 nCount(xIndex->getCount());
2492                         for(sal_Int32 i = 0; i < nCount; i++)
2493                         {
2494                             Reference<XNamed> xGroupNamed(xIndex->getByIndex(i), UNO_QUERY);
2495                             if (xGroupNamed.is())
2496                             {
2497                                 ScDPSaveGroupItem aItem(xGroupNamed->getName());
2498                                 Reference<XIndexAccess> xGroupIndex(xGroupNamed, UNO_QUERY);
2499                                 if (xGroupIndex.is())
2500                                 {
2501                                     sal_Int32 nItemCount(xGroupIndex->getCount());
2502                                     for (sal_Int32 j = 0; j < nItemCount; ++j)
2503                                     {
2504                                         Reference<XNamed> xItemNamed(xGroupIndex->getByIndex(j), UNO_QUERY);
2505                                         if (xItemNamed.is())
2506                                             aItem.AddElement(xItemNamed->getName());
2507                                     }
2508                                 }
2509                                 aGroupDim.AddGroupItem(aItem);
2510                             }
2511                         }
2512                     }
2513                 }
2514 
2515                 // get dimension savedata or create new if none
2516                 ScDPDimensionSaveData& rDimSaveData = *pSaveData->GetDimensionData();
2517                 rDimSaveData.ReplaceGroupDimension( aGroupDim );
2518             }
2519             else    // no source field in group info -> numeric group
2520             {
2521                 ScDPDimensionSaveData* pDimData = pSaveData->GetDimensionData();     // created if not there
2522 
2523                 ScDPSaveNumGroupDimension* pExisting = pDimData->GetNumGroupDimAcc( getName() );
2524                 if ( pExisting )
2525                 {
2526                     if (pInfo->GroupBy)
2527                         pExisting->SetDateInfo(aInfo, pInfo->GroupBy);
2528                     // modify existing group dimension
2529                     pExisting->SetGroupInfo( aInfo );
2530                 }
2531                 else if (pInfo->GroupBy)
2532                 {
2533                     // create new group dimension
2534                     ScDPSaveNumGroupDimension aNumGroupDim( getName(), aInfo, pInfo->GroupBy );
2535                     pDimData->AddNumGroupDimension( aNumGroupDim );
2536                 }
2537                 else
2538                 {
2539                     // create new group dimension
2540                     ScDPSaveNumGroupDimension aNumGroupDim( getName(), aInfo );
2541                     pDimData->AddNumGroupDimension( aNumGroupDim );
2542                 }
2543             }
2544         }
2545         else    // null passed as argument
2546         {
2547             pSaveData->SetDimensionData( 0 );
2548         }
2549 
2550         pDPObj->SetSaveData( *pSaveData );
2551         SetDPObject( pDPObj );
2552     }
2553 }
2554 
2555 sal_Bool ScDataPilotFieldObj::HasString(const Sequence< OUString >& rItems, const OUString& aString)
2556 {
2557     sal_Bool bRet = sal_False;
2558 
2559     sal_Int32 nCount(rItems.getLength());
2560     sal_Int32 nItem(0);
2561     while (nItem < nCount && !bRet)
2562     {
2563         bRet = rItems[nItem] == aString;
2564         ++nItem;
2565     }
2566 
2567     return bRet;
2568 }
2569 
2570 // XDataPilotFieldGrouping
2571 Reference< XDataPilotField > SAL_CALL ScDataPilotFieldObj::createNameGroup( const Sequence< OUString >& rItems )
2572          throw (RuntimeException, IllegalArgumentException)
2573 {
2574 	ScUnoGuard aGuard;
2575 
2576     Reference< XDataPilotField > xRet;
2577     OUString sNewDim;
2578 
2579     if( !rItems.hasElements() )
2580         throw IllegalArgumentException();
2581 
2582     ScDPObject* pDPObj = 0;
2583     if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) )
2584     {
2585         String aDimName = pDim->GetName();
2586 
2587         ScDPSaveData aSaveData = *pDPObj->GetSaveData();
2588         ScDPDimensionSaveData* pDimData = aSaveData.GetDimensionData();     // created if not there
2589 
2590         // find original base
2591         String aBaseDimName( aDimName );
2592         const ScDPSaveGroupDimension* pBaseGroupDim = pDimData->GetNamedGroupDim( aDimName );
2593         if ( pBaseGroupDim )
2594         {
2595             // any entry's SourceDimName is the original base
2596             aBaseDimName = pBaseGroupDim->GetSourceDimName();
2597         }
2598 
2599         // find existing group dimension
2600         // (using the selected dim, can be intermediate group dim)
2601         ScDPSaveGroupDimension* pGroupDimension = pDimData->GetGroupDimAccForBase( aDimName );
2602 
2603         // remove the selected items from their groups
2604         // (empty groups are removed, too)
2605         sal_Int32 nEntryCount = rItems.getLength();
2606         sal_Int32 nEntry;
2607         if ( pGroupDimension )
2608         {
2609             for (nEntry=0; nEntry<nEntryCount; nEntry++)
2610             {
2611                 String aEntryName(rItems[nEntry]);
2612                 if ( pBaseGroupDim )
2613                 {
2614                     // for each selected (intermediate) group, remove all its items
2615                     // (same logic as for adding, below)
2616                     const ScDPSaveGroupItem* pBaseGroup = pBaseGroupDim->GetNamedGroup( aEntryName );
2617                     if ( pBaseGroup )
2618                         pBaseGroup->RemoveElementsFromGroups( *pGroupDimension );   // remove all elements
2619                     else
2620                         pGroupDimension->RemoveFromGroups( aEntryName );
2621                 }
2622                 else
2623                     pGroupDimension->RemoveFromGroups( aEntryName );
2624             }
2625         }
2626 
2627         ScDPSaveGroupDimension* pNewGroupDim = 0;
2628         if ( !pGroupDimension )
2629         {
2630             // create a new group dimension
2631             String aGroupDimName = pDimData->CreateGroupDimName( aBaseDimName, *pDPObj, false, NULL );
2632             pNewGroupDim = new ScDPSaveGroupDimension( aBaseDimName, aGroupDimName );
2633             sNewDim = aGroupDimName;
2634 
2635             pGroupDimension = pNewGroupDim;     // make changes to the new dim if none existed
2636 
2637             if ( pBaseGroupDim )
2638             {
2639                 // If it's a higher-order group dimension, pre-allocate groups for all
2640                 // non-selected original groups, so the individual base members aren't
2641                 // used for automatic groups (this would make the original groups hard
2642                 // to find).
2643                 //! Also do this when removing groups?
2644                 //! Handle this case dynamically with automatic groups?
2645 
2646                 long nGroupCount = pBaseGroupDim->GetGroupCount();
2647                 for ( long nGroup = 0; nGroup < nGroupCount; nGroup++ )
2648                 {
2649                     const ScDPSaveGroupItem* pBaseGroup = pBaseGroupDim->GetGroupByIndex( nGroup );
2650 
2651                     StrData aStrData( pBaseGroup->GetGroupName() );
2652                     if ( !HasString(rItems, aStrData.GetString()) )    //! ignore case?
2653                     {
2654                         // add an additional group for each item that is not in the selection
2655                         ScDPSaveGroupItem aGroup( pBaseGroup->GetGroupName() );
2656                         aGroup.AddElementsFromGroup( *pBaseGroup );
2657                         pGroupDimension->AddGroupItem( aGroup );
2658                     }
2659                 }
2660             }
2661         }
2662         String aGroupDimName = pGroupDimension->GetGroupDimName();
2663 
2664         //! localized prefix string
2665         String aGroupName = pGroupDimension->CreateGroupName( String( RTL_CONSTASCII_USTRINGPARAM( "Group" ) ) );
2666         ScDPSaveGroupItem aGroup( aGroupName );
2667         Reference< XNameAccess > xMembers = GetMembers();
2668         if (!xMembers.is())
2669         {
2670             delete pNewGroupDim;
2671             throw RuntimeException();
2672         }
2673 
2674         for (nEntry=0; nEntry<nEntryCount; nEntry++)
2675         {
2676             String aEntryName(rItems[nEntry]);
2677 
2678             if (!xMembers->hasByName(aEntryName))
2679             {
2680                 delete pNewGroupDim;
2681                 throw IllegalArgumentException();
2682             }
2683 
2684             if ( pBaseGroupDim )
2685             {
2686                 // for each selected (intermediate) group, add all its items
2687                 const ScDPSaveGroupItem* pBaseGroup = pBaseGroupDim->GetNamedGroup( aEntryName );
2688                 if ( pBaseGroup )
2689                     aGroup.AddElementsFromGroup( *pBaseGroup );
2690                 else
2691                     aGroup.AddElement( aEntryName );    // no group found -> automatic group, add the item itself
2692             }
2693             else
2694                 aGroup.AddElement( aEntryName );        // no group dimension, add all items directly
2695         }
2696 
2697         pGroupDimension->AddGroupItem( aGroup );
2698 
2699         if ( pNewGroupDim )
2700         {
2701             pDimData->AddGroupDimension( *pNewGroupDim );
2702             delete pNewGroupDim;        // AddGroupDimension copies the object
2703             // don't access pGroupDimension after here
2704         }
2705         pGroupDimension = pNewGroupDim = NULL;
2706 
2707         // set orientation
2708         ScDPSaveDimension* pSaveDimension = aSaveData.GetDimensionByName( aGroupDimName );
2709         if ( pSaveDimension->GetOrientation() == DataPilotFieldOrientation_HIDDEN )
2710         {
2711             ScDPSaveDimension* pOldDimension = aSaveData.GetDimensionByName( aDimName );
2712             pSaveDimension->SetOrientation( pOldDimension->GetOrientation() );
2713             long nPosition = 0;     //! before (immediate) base
2714             aSaveData.SetPosition( pSaveDimension, nPosition );
2715         }
2716 
2717         // apply changes
2718         pDPObj->SetSaveData( aSaveData );
2719         SetDPObject( pDPObj );
2720     }
2721 
2722     // if new grouping field has been created (on first group), return it
2723     if( sNewDim.getLength() > 0 )
2724     {
2725         Reference< XNameAccess > xFields(mrParent.getDataPilotFields(), UNO_QUERY);
2726         if (xFields.is())
2727         {
2728             xRet.set(xFields->getByName(sNewDim), UNO_QUERY);
2729             DBG_ASSERT(xRet.is(), "there is a name, so there should be also a field");
2730         }
2731     }
2732     return xRet;
2733 }
2734 
2735 Reference < XDataPilotField > SAL_CALL ScDataPilotFieldObj::createDateGroup( const DataPilotFieldGroupInfo& rInfo )
2736         throw (RuntimeException, IllegalArgumentException)
2737 {
2738 	ScUnoGuard aGuard;
2739     using namespace ::com::sun::star::sheet::DataPilotFieldGroupBy;
2740 
2741     // check min/max/step, HasDateValues must be set always
2742     if( !rInfo.HasDateValues || !lclCheckMinMaxStep( rInfo ) )
2743         throw IllegalArgumentException();
2744     // only a single date flag is allowed
2745     if( (rInfo.GroupBy == 0) || (rInfo.GroupBy > YEARS) || ((rInfo.GroupBy & (rInfo.GroupBy - 1)) != 0) )
2746         throw IllegalArgumentException();
2747     // step must be zero, if something else than DAYS is specified
2748     if( rInfo.Step >= ((rInfo.GroupBy == DAYS) ? 32768.0 : 1.0) )
2749         throw IllegalArgumentException();
2750 
2751     String aGroupDimName;
2752     ScDPObject* pDPObj = 0;
2753     if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) )
2754     {
2755         ScDPNumGroupInfo aInfo;
2756         aInfo.Enable = sal_True;
2757         aInfo.DateValues = (rInfo.GroupBy == DAYS) && (rInfo.Step >= 1.0);
2758         aInfo.AutoStart = rInfo.HasAutoStart;
2759         aInfo.AutoEnd = rInfo.HasAutoEnd;
2760         aInfo.Start = rInfo.Start;
2761         aInfo.End = rInfo.End;
2762         aInfo.Step = static_cast< sal_Int32 >( rInfo.Step );
2763 
2764         // create a local copy of the entire save data (will be written back below)
2765         ScDPSaveData aSaveData = *pDPObj->GetSaveData();
2766         // get or create dimension save data
2767         ScDPDimensionSaveData& rDimData = *aSaveData.GetDimensionData();
2768 
2769         // find source dimension name
2770         const String& rDimName = pDim->GetName();
2771         const ScDPSaveGroupDimension* pGroupDim = rDimData.GetNamedGroupDim( rDimName );
2772         String aSrcDimName = pGroupDim ? pGroupDim->GetSourceDimName() : rDimName;
2773 
2774         // find a group dimension for the base field, or get numeric grouping
2775         pGroupDim = rDimData.GetFirstNamedGroupDim( aSrcDimName );
2776         const ScDPSaveNumGroupDimension* pNumGroupDim = rDimData.GetNumGroupDim( aSrcDimName );
2777 
2778         // do not group by dates, if named groups or numeric grouping is present
2779         bool bHasNamedGrouping = pGroupDim && !pGroupDim->GetDateInfo().Enable;
2780         bool bHasNumGrouping = pNumGroupDim && pNumGroupDim->GetInfo().Enable && !pNumGroupDim->GetInfo().DateValues && !pNumGroupDim->GetDateInfo().Enable;
2781         if( bHasNamedGrouping || bHasNumGrouping )
2782             throw IllegalArgumentException();
2783 
2784         if( aInfo.DateValues )  // create day ranges grouping
2785         {
2786             // first remove all named group dimensions
2787             while( pGroupDim )
2788             {
2789                 String aGroupDimName2 = pGroupDim->GetGroupDimName();
2790                 // find next group dimension before deleting this group
2791                 pGroupDim = rDimData.GetNextNamedGroupDim( aGroupDimName2 );
2792                 // remove from dimension save data
2793                 rDimData.RemoveGroupDimension( aGroupDimName2 );
2794                 // also remove save data settings for the dimension that no longer exists
2795                 aSaveData.RemoveDimensionByName( aGroupDimName2 );
2796             }
2797             // create or replace the number grouping dimension
2798             ScDPSaveNumGroupDimension aNumGroupDim( aSrcDimName, aInfo );
2799             rDimData.ReplaceNumGroupDimension( aNumGroupDim );
2800         }
2801         else    // create date grouping
2802         {
2803             // collect all existing date flags
2804             sal_Int32 nDateParts = rDimData.CollectDateParts( aSrcDimName );
2805             if( nDateParts == 0 )
2806             {
2807                 // insert numeric group dimension, if no date groups exist yet (or replace day range grouping)
2808                 ScDPSaveNumGroupDimension aNumGroupDim( aSrcDimName, aInfo, rInfo.GroupBy );
2809                 rDimData.ReplaceNumGroupDimension( aNumGroupDim );
2810             }
2811             else if( (nDateParts & rInfo.GroupBy) == 0 )    // do nothing if date field exists already
2812             {
2813                 // create new named group dimension for additional date groups
2814                 aGroupDimName = rDimData.CreateDateGroupDimName( rInfo.GroupBy, *pDPObj, true, 0 );
2815                 ScDPSaveGroupDimension aGroupDim( aSrcDimName, aGroupDimName, aInfo, rInfo.GroupBy );
2816                 rDimData.AddGroupDimension( aGroupDim );
2817 
2818                 // set orientation of new named group dimension
2819                 ScDPSaveDimension& rSaveDim = *aSaveData.GetDimensionByName( aGroupDimName );
2820                 if( rSaveDim.GetOrientation() == DataPilotFieldOrientation_HIDDEN )
2821                 {
2822                     ScDPSaveDimension& rOldDim = *aSaveData.GetDimensionByName( aSrcDimName );
2823                     rSaveDim.SetOrientation( rOldDim.GetOrientation() );
2824                     aSaveData.SetPosition( &rSaveDim, 0 );  //! before (immediate) base
2825                 }
2826             }
2827         }
2828 
2829         // apply changes
2830         pDPObj->SetSaveData( aSaveData );
2831         SetDPObject( pDPObj );
2832     }
2833 
2834     // return the UNO object of the new dimension, after writing back saved data
2835     Reference< XDataPilotField > xRet;
2836     if( aGroupDimName.Len() > 0 ) try
2837     {
2838         Reference< XNameAccess > xFields( mrParent.getDataPilotFields(), UNO_QUERY_THROW );
2839         xRet.set( xFields->getByName( aGroupDimName ), UNO_QUERY );
2840     }
2841     catch( Exception& )
2842     {
2843     }
2844     return xRet;
2845 }
2846 
2847 // ============================================================================
2848 
2849 namespace {
2850 
2851 bool lclExtractGroupMembers( ScFieldGroupMembers& rMembers, const Any& rElement )
2852 {
2853     // allow empty value to create a new group
2854     if( !rElement.hasValue() )
2855         return true;
2856 
2857     // try to extract a simple sequence of strings
2858     Sequence< OUString > aSeq;
2859     if( rElement >>= aSeq )
2860     {
2861         if( aSeq.hasElements() )
2862             rMembers.insert( rMembers.end(), aSeq.getConstArray(), aSeq.getConstArray() + aSeq.getLength() );
2863         return true;
2864     }
2865 
2866     // try to use XIndexAccess providing objects that support XNamed
2867     Reference< XIndexAccess > xItemsIA( rElement, UNO_QUERY );
2868     if( xItemsIA.is() )
2869     {
2870         for( sal_Int32 nIdx = 0, nCount = xItemsIA->getCount(); nIdx < nCount; ++nIdx )
2871         {
2872             try // getByIndex() should not throw, but we cannot be sure
2873             {
2874                 Reference< XNamed > xItemName( xItemsIA->getByIndex( nIdx ), UNO_QUERY_THROW );
2875                 rMembers.push_back( xItemName->getName() );
2876             }
2877             catch( Exception& )
2878             {
2879                 // ignore exceptions, go ahead with next element in the array
2880             }
2881         }
2882         return true;
2883     }
2884 
2885     // nothing valid inside the Any -> return false
2886     return false;
2887 }
2888 
2889 } // namespace
2890 
2891 // ----------------------------------------------------------------------------
2892 
2893 ScDataPilotFieldGroupsObj::ScDataPilotFieldGroupsObj( const ScFieldGroups& rGroups ) :
2894     maGroups( rGroups )
2895 {
2896 }
2897 
2898 ScDataPilotFieldGroupsObj::~ScDataPilotFieldGroupsObj()
2899 {
2900 }
2901 
2902 // XNameAccess
2903 
2904 Any SAL_CALL ScDataPilotFieldGroupsObj::getByName( const OUString& rName )
2905         throw(NoSuchElementException, WrappedTargetException, RuntimeException)
2906 {
2907 	ScUnoGuard aGuard;
2908     if( implFindByName( rName ) == maGroups.end() )
2909         throw NoSuchElementException();
2910     return Any( Reference< XNameAccess >( new ScDataPilotFieldGroupObj( *this, rName ) ) );
2911 }
2912 
2913 Sequence< OUString > SAL_CALL ScDataPilotFieldGroupsObj::getElementNames() throw(RuntimeException)
2914 {
2915 	ScUnoGuard aGuard;
2916     Sequence< OUString > aSeq;
2917     if( !maGroups.empty() )
2918     {
2919         aSeq.realloc( static_cast< sal_Int32 >( maGroups.size() ) );
2920         OUString* pName = aSeq.getArray();
2921         for( ScFieldGroups::iterator aIt = maGroups.begin(), aEnd = maGroups.end(); aIt != aEnd; ++aIt, ++pName )
2922             *pName = aIt->maName;
2923     }
2924     return aSeq;
2925 }
2926 
2927 sal_Bool SAL_CALL ScDataPilotFieldGroupsObj::hasByName( const OUString& rName ) throw(RuntimeException)
2928 {
2929 	ScUnoGuard aGuard;
2930     return implFindByName( rName ) != maGroups.end();
2931 }
2932 
2933 // XNameReplace
2934 
2935 void SAL_CALL ScDataPilotFieldGroupsObj::replaceByName( const OUString& rName, const Any& rElement )
2936         throw (IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException)
2937 {
2938     ScUnoGuard aGuard;
2939 
2940     if( rName.getLength() == 0 )
2941         throw IllegalArgumentException();
2942 
2943     ScFieldGroups::iterator aIt = implFindByName( rName );
2944     if( aIt == maGroups.end() )
2945         throw NoSuchElementException();
2946 
2947     // read all item names provided by the passed object
2948     ScFieldGroupMembers aMembers;
2949     if( !lclExtractGroupMembers( aMembers, rElement ) )
2950         throw IllegalArgumentException();
2951 
2952     // copy and forget, faster than vector assignment
2953     aIt->maMembers.swap( aMembers );
2954 }
2955 
2956 // XNameContainer
2957 
2958 void SAL_CALL ScDataPilotFieldGroupsObj::insertByName( const OUString& rName, const Any& rElement )
2959         throw (IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException)
2960 {
2961     ScUnoGuard aGuard;
2962 
2963     if( rName.getLength() == 0 )
2964         throw IllegalArgumentException();
2965 
2966     ScFieldGroups::iterator aIt = implFindByName( rName );
2967     if( aIt != maGroups.end() )
2968         throw ElementExistException();
2969 
2970     // read all item names provided by the passed object
2971     ScFieldGroupMembers aMembers;
2972     if( !lclExtractGroupMembers( aMembers, rElement ) )
2973         throw IllegalArgumentException();
2974 
2975     // create the new entry if no error has been occured
2976     maGroups.resize( maGroups.size() + 1 );
2977     ScFieldGroup& rGroup = maGroups.back();
2978     rGroup.maName = rName;
2979     rGroup.maMembers.swap( aMembers );
2980 }
2981 
2982 void SAL_CALL ScDataPilotFieldGroupsObj::removeByName( const OUString& rName )
2983         throw (NoSuchElementException, WrappedTargetException, RuntimeException)
2984 {
2985     ScUnoGuard aGuard;
2986 
2987     if( rName.getLength() == 0 )
2988         throw IllegalArgumentException();
2989 
2990     ScFieldGroups::iterator aIt = implFindByName( rName );
2991     if( aIt == maGroups.end() )
2992         throw NoSuchElementException();
2993 
2994     maGroups.erase( aIt );
2995 }
2996 
2997 // XIndexAccess
2998 
2999 sal_Int32 SAL_CALL ScDataPilotFieldGroupsObj::getCount() throw(RuntimeException)
3000 {
3001 	ScUnoGuard aGuard;
3002     return static_cast< sal_Int32 >( maGroups.size() );
3003 }
3004 
3005 Any SAL_CALL ScDataPilotFieldGroupsObj::getByIndex( sal_Int32 nIndex )
3006         throw(IndexOutOfBoundsException, WrappedTargetException, RuntimeException)
3007 {
3008 	ScUnoGuard aGuard;
3009     if ((nIndex < 0) || (nIndex >= static_cast< sal_Int32 >( maGroups.size() )))
3010         throw IndexOutOfBoundsException();
3011     return Any( Reference< XNameAccess >( new ScDataPilotFieldGroupObj( *this, maGroups[ nIndex ].maName ) ) );
3012 }
3013 
3014 // XEnumerationAccess
3015 
3016 Reference<XEnumeration> SAL_CALL ScDataPilotFieldGroupsObj::createEnumeration() throw(RuntimeException)
3017 {
3018     ScUnoGuard aGuard;
3019     return new ScIndexEnumeration( this, OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sheet.DataPilotFieldGroupsEnumeration" ) ) );
3020 }
3021 
3022 // XElementAccess
3023 
3024 uno::Type SAL_CALL ScDataPilotFieldGroupsObj::getElementType() throw(RuntimeException)
3025 {
3026 	ScUnoGuard aGuard;
3027     return getCppuType( (Reference< XNameAccess >*)0 );
3028 }
3029 
3030 sal_Bool SAL_CALL ScDataPilotFieldGroupsObj::hasElements() throw(RuntimeException)
3031 {
3032 	ScUnoGuard aGuard;
3033     return !maGroups.empty();
3034 }
3035 
3036 // implementation
3037 
3038 ScFieldGroup& ScDataPilotFieldGroupsObj::getFieldGroup( const OUString& rName ) throw(RuntimeException)
3039 {
3040     ScUnoGuard aGuard;
3041     ScFieldGroups::iterator aIt = implFindByName( rName );
3042     if( aIt == maGroups.end() )
3043         throw RuntimeException();
3044      return *aIt;
3045 }
3046 
3047 void ScDataPilotFieldGroupsObj::renameFieldGroup( const OUString& rOldName, const OUString& rNewName ) throw(RuntimeException)
3048 {
3049     ScUnoGuard aGuard;
3050     ScFieldGroups::iterator aOldIt = implFindByName( rOldName );
3051     ScFieldGroups::iterator aNewIt = implFindByName( rNewName );
3052     // new name must not exist yet
3053     if( (aOldIt == maGroups.end()) || ((aNewIt != maGroups.end()) && (aNewIt != aOldIt)) )
3054         throw RuntimeException();
3055     aOldIt->maName = rNewName;
3056 }
3057 
3058 // private
3059 
3060 ScFieldGroups::iterator ScDataPilotFieldGroupsObj::implFindByName( const OUString& rName )
3061 {
3062     for( ScFieldGroups::iterator aIt = maGroups.begin(), aEnd = maGroups.end(); aIt != aEnd; ++aIt )
3063         if( aIt->maName == rName )
3064             return aIt;
3065     return maGroups.end();
3066 }
3067 
3068 // ============================================================================
3069 
3070 namespace {
3071 
3072 OUString lclExtractMember( const Any& rElement )
3073 {
3074     if( rElement.has< OUString >() )
3075         return rElement.get< OUString >();
3076 
3077     Reference< XNamed > xNamed( rElement, UNO_QUERY );
3078     if( xNamed.is() )
3079         return xNamed->getName();
3080 
3081     return OUString();
3082 }
3083 
3084 } // namespace
3085 
3086 // ----------------------------------------------------------------------------
3087 
3088 ScDataPilotFieldGroupObj::ScDataPilotFieldGroupObj( ScDataPilotFieldGroupsObj& rParent, const OUString& rGroupName ) :
3089     mrParent( rParent ),
3090     maGroupName( rGroupName )
3091 {
3092     mrParent.acquire();
3093 }
3094 
3095 ScDataPilotFieldGroupObj::~ScDataPilotFieldGroupObj()
3096 {
3097     mrParent.release();
3098 }
3099 
3100 // XNameAccess
3101 
3102 Any SAL_CALL ScDataPilotFieldGroupObj::getByName( const OUString& rName )
3103         throw(NoSuchElementException, WrappedTargetException, RuntimeException)
3104 {
3105 	ScUnoGuard aGuard;
3106     ScFieldGroupMembers& rMembers = mrParent.getFieldGroup( maGroupName ).maMembers;
3107     ScFieldGroupMembers::iterator aIt = ::std::find( rMembers.begin(), rMembers.end(), rName );
3108     if( aIt == rMembers.end() )
3109         throw NoSuchElementException();
3110     return Any( Reference< XNamed >( new ScDataPilotFieldGroupItemObj( *this, *aIt ) ) );
3111 }
3112 
3113 Sequence< OUString > SAL_CALL ScDataPilotFieldGroupObj::getElementNames() throw(RuntimeException)
3114 {
3115 	ScUnoGuard aGuard;
3116     return ::comphelper::containerToSequence( mrParent.getFieldGroup( maGroupName ).maMembers );
3117 }
3118 
3119 sal_Bool SAL_CALL ScDataPilotFieldGroupObj::hasByName( const OUString& rName ) throw(RuntimeException)
3120 {
3121 	ScUnoGuard aGuard;
3122     ScFieldGroupMembers& rMembers = mrParent.getFieldGroup( maGroupName ).maMembers;
3123     return ::std::find( rMembers.begin(), rMembers.end(), rName ) != rMembers.end();
3124 }
3125 
3126 // XNameReplace
3127 
3128 void SAL_CALL ScDataPilotFieldGroupObj::replaceByName( const OUString& rName, const Any& rElement )
3129         throw (IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException)
3130 {
3131     ScUnoGuard aGuard;
3132 
3133     // it should be possible to quickly rename an item -> accept string or XNamed
3134     OUString aNewName = lclExtractMember( rElement );
3135     if( (rName.getLength() == 0) || (aNewName.getLength() == 0) )
3136         throw IllegalArgumentException();
3137     if( rName == aNewName )
3138         return;
3139 
3140     ScFieldGroupMembers& rMembers = mrParent.getFieldGroup( maGroupName ).maMembers;
3141     ScFieldGroupMembers::iterator aOldIt = ::std::find( rMembers.begin(), rMembers.end(), rName );
3142     ScFieldGroupMembers::iterator aNewIt = ::std::find( rMembers.begin(), rMembers.end(), aNewName );
3143     // throw if passed member name does not exist
3144     if( aOldIt == rMembers.end() )
3145         throw NoSuchElementException();
3146     // throw if new name already exists
3147     if( aNewIt != rMembers.end() )
3148         throw IllegalArgumentException();
3149     *aOldIt = aNewName;
3150 }
3151 
3152 // XNameContainer
3153 
3154 void SAL_CALL ScDataPilotFieldGroupObj::insertByName( const OUString& rName, const Any& /*rElement*/ )
3155         throw (IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException)
3156 {
3157     ScUnoGuard aGuard;
3158 
3159     // we will ignore the passed element and just try to insert the name
3160     if( rName.getLength() == 0 )
3161         throw IllegalArgumentException();
3162 
3163     ScFieldGroupMembers& rMembers = mrParent.getFieldGroup( maGroupName ).maMembers;
3164     ScFieldGroupMembers::iterator aIt = ::std::find( rMembers.begin(), rMembers.end(), rName );
3165     // throw if passed name already exists
3166     if( aIt != rMembers.end() )
3167         throw IllegalArgumentException();
3168     rMembers.push_back( rName );
3169 }
3170 
3171 void SAL_CALL ScDataPilotFieldGroupObj::removeByName( const OUString& rName )
3172         throw (NoSuchElementException, WrappedTargetException, RuntimeException)
3173 {
3174     ScUnoGuard aGuard;
3175 
3176     if( rName.getLength() == 0 )
3177         throw IllegalArgumentException();
3178     ScFieldGroupMembers& rMembers = mrParent.getFieldGroup( maGroupName ).maMembers;
3179     ScFieldGroupMembers::iterator aIt = ::std::find( rMembers.begin(), rMembers.end(), rName );
3180     // throw if passed name does not exist
3181     if( aIt == rMembers.end() )
3182         throw NoSuchElementException();
3183     rMembers.erase( aIt );
3184 }
3185 
3186 // XIndexAccess
3187 
3188 sal_Int32 SAL_CALL ScDataPilotFieldGroupObj::getCount() throw(RuntimeException)
3189 {
3190 	ScUnoGuard aGuard;
3191     return static_cast< sal_Int32 >( mrParent.getFieldGroup( maGroupName ).maMembers.size() );
3192 }
3193 
3194 Any SAL_CALL ScDataPilotFieldGroupObj::getByIndex( sal_Int32 nIndex )
3195         throw(IndexOutOfBoundsException, WrappedTargetException, RuntimeException)
3196 {
3197 	ScUnoGuard aGuard;
3198     ScFieldGroupMembers& rMembers = mrParent.getFieldGroup( maGroupName ).maMembers;
3199     if ((nIndex < 0) || (nIndex >= static_cast< sal_Int32 >( rMembers.size() )))
3200         throw IndexOutOfBoundsException();
3201     return Any( Reference< XNamed >( new ScDataPilotFieldGroupItemObj( *this, rMembers[ nIndex ] ) ) );
3202 }
3203 
3204 // XEnumerationAccess
3205 
3206 Reference< XEnumeration > SAL_CALL ScDataPilotFieldGroupObj::createEnumeration() throw(RuntimeException)
3207 {
3208     ScUnoGuard aGuard;
3209     return new ScIndexEnumeration( this, OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sheet.DataPilotFieldGroupEnumeration" ) ) );
3210 }
3211 
3212 // XElementAccess
3213 
3214 uno::Type SAL_CALL ScDataPilotFieldGroupObj::getElementType() throw(RuntimeException)
3215 {
3216 	ScUnoGuard aGuard;
3217     return getCppuType( (Reference< XNamed >*)0 );
3218 }
3219 
3220 sal_Bool SAL_CALL ScDataPilotFieldGroupObj::hasElements() throw(RuntimeException)
3221 {
3222 	ScUnoGuard aGuard;
3223     return !mrParent.getFieldGroup( maGroupName ).maMembers.empty();
3224 }
3225 
3226 // XNamed
3227 
3228 OUString SAL_CALL ScDataPilotFieldGroupObj::getName() throw(RuntimeException)
3229 {
3230 	ScUnoGuard aGuard;
3231     return maGroupName;
3232 }
3233 
3234 void SAL_CALL ScDataPilotFieldGroupObj::setName( const OUString& rName ) throw(RuntimeException)
3235 {
3236 	ScUnoGuard aGuard;
3237     mrParent.renameFieldGroup( maGroupName, rName );
3238     // if call to renameFieldGroup() did not throw, remember the new name
3239     maGroupName = rName;
3240 }
3241 
3242 // ============================================================================
3243 
3244 ScDataPilotFieldGroupItemObj::ScDataPilotFieldGroupItemObj( ScDataPilotFieldGroupObj& rParent, const OUString& rName ) :
3245     mrParent( rParent ),
3246     maName( rName )
3247 {
3248     mrParent.acquire();
3249 }
3250 
3251 ScDataPilotFieldGroupItemObj::~ScDataPilotFieldGroupItemObj()
3252 {
3253     mrParent.release();
3254 }
3255 
3256 // XNamed
3257 
3258 OUString SAL_CALL ScDataPilotFieldGroupItemObj::getName() throw(RuntimeException)
3259 {
3260 	ScUnoGuard aGuard;
3261     return maName;
3262 }
3263 
3264 void SAL_CALL ScDataPilotFieldGroupItemObj::setName( const OUString& rName ) throw(RuntimeException)
3265 {
3266 	ScUnoGuard aGuard;
3267     mrParent.replaceByName( maName, Any( rName ) );
3268     // if call to replaceByName() did not throw, remember the new name
3269     maName = rName;
3270 }
3271 
3272 // ============================================================================
3273 
3274 ScDataPilotItemsObj::ScDataPilotItemsObj( ScDataPilotDescriptorBase& rParent, const ScFieldIdentifier& rFieldId ) :
3275     ScDataPilotChildObjBase( rParent, rFieldId )
3276 {
3277 }
3278 
3279 ScDataPilotItemsObj::~ScDataPilotItemsObj()
3280 {
3281 }
3282 
3283 // XDataPilotItems
3284 
3285 ScDataPilotItemObj* ScDataPilotItemsObj::GetObjectByIndex_Impl( sal_Int32 nIndex ) const
3286 {
3287     return ((0 <= nIndex) && (nIndex < GetMemberCount())) ?
3288         new ScDataPilotItemObj( mrParent, maFieldId, nIndex ) : 0;
3289 }
3290 
3291 // XNameAccess
3292 
3293 Any SAL_CALL ScDataPilotItemsObj::getByName( const OUString& aName )
3294         throw(NoSuchElementException, WrappedTargetException, RuntimeException)
3295 {
3296 	ScUnoGuard aGuard;
3297     Reference<XNameAccess> xMembers = GetMembers();
3298     if (xMembers.is())
3299     {
3300         Reference<XIndexAccess> xMembersIndex(new ScNameToIndexAccess( xMembers ));
3301         sal_Int32 nCount = xMembersIndex->getCount();
3302         sal_Bool bFound(sal_False);
3303         sal_Int32 nItem = 0;
3304         while (nItem < nCount && !bFound )
3305         {
3306             Reference<XNamed> xMember(xMembersIndex->getByIndex(nItem), UNO_QUERY);
3307             if (xMember.is() && (aName == xMember->getName()))
3308                 return Any( Reference< XPropertySet >( GetObjectByIndex_Impl( nItem ) ) );
3309             ++nItem;
3310         }
3311         if (!bFound)
3312             throw NoSuchElementException();
3313     }
3314     return Any();
3315 }
3316 
3317 Sequence<OUString> SAL_CALL ScDataPilotItemsObj::getElementNames()
3318                                                 throw(RuntimeException)
3319 {
3320 	ScUnoGuard aGuard;
3321     Sequence< OUString > aSeq;
3322     if( ScDPObject* pDPObj = GetDPObject() )
3323         pDPObj->GetMemberNames( lcl_GetObjectIndex( pDPObj, maFieldId ), aSeq );
3324     return aSeq;
3325 }
3326 
3327 sal_Bool SAL_CALL ScDataPilotItemsObj::hasByName( const OUString& aName )
3328                                         throw(RuntimeException)
3329 {
3330 	ScUnoGuard aGuard;
3331     sal_Bool bFound = sal_False;
3332     Reference<XNameAccess> xMembers = GetMembers();
3333     if (xMembers.is())
3334     {
3335         Reference<XIndexAccess> xMembersIndex(new ScNameToIndexAccess( xMembers ));
3336         sal_Int32 nCount = xMembersIndex->getCount();
3337         sal_Int32 nItem = 0;
3338         while (nItem < nCount && !bFound )
3339         {
3340             Reference<XNamed> xMember(xMembersIndex->getByIndex(nItem), UNO_QUERY);
3341             if (xMember.is() && aName == xMember->getName())
3342                 bFound = sal_True;
3343             else
3344                 nItem++;
3345         }
3346     }
3347     return bFound;
3348 }
3349 
3350 // XEnumerationAccess
3351 
3352 Reference<XEnumeration> SAL_CALL ScDataPilotItemsObj::createEnumeration()
3353                                                     throw(RuntimeException)
3354 {
3355 	ScUnoGuard aGuard;
3356     return new ScIndexEnumeration(this, OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.DataPilotItemsEnumeration")));
3357 }
3358 
3359 // XIndexAccess
3360 
3361 sal_Int32 SAL_CALL ScDataPilotItemsObj::getCount() throw(RuntimeException)
3362 {
3363 	ScUnoGuard aGuard;
3364     return GetMemberCount();
3365 }
3366 
3367 Any SAL_CALL ScDataPilotItemsObj::getByIndex( sal_Int32 nIndex )
3368         throw(IndexOutOfBoundsException, WrappedTargetException, RuntimeException)
3369 {
3370 	ScUnoGuard aGuard;
3371     Reference< XPropertySet > xItem( GetObjectByIndex_Impl( nIndex ) );
3372     if (!xItem.is())
3373         throw IndexOutOfBoundsException();
3374     return Any( xItem );
3375 }
3376 
3377 uno::Type SAL_CALL ScDataPilotItemsObj::getElementType() throw(RuntimeException)
3378 {
3379 	ScUnoGuard aGuard;
3380     return getCppuType((Reference<XPropertySet>*)0);
3381 }
3382 
3383 sal_Bool SAL_CALL ScDataPilotItemsObj::hasElements() throw(RuntimeException)
3384 {
3385 	ScUnoGuard aGuard;
3386 	return ( getCount() != 0 );
3387 }
3388 
3389 //------------------------------------------------------------------------
3390 
3391 ScDataPilotItemObj::ScDataPilotItemObj( ScDataPilotDescriptorBase& rParent, const ScFieldIdentifier& rFieldId, sal_Int32 nIndex ) :
3392     ScDataPilotChildObjBase( rParent, rFieldId ),
3393     maPropSet( lcl_GetDataPilotItemMap() ),
3394     mnIndex( nIndex )
3395 {
3396 }
3397 
3398 ScDataPilotItemObj::~ScDataPilotItemObj()
3399 {
3400 }
3401 
3402 							// XNamed
3403 OUString SAL_CALL ScDataPilotItemObj::getName() throw(RuntimeException)
3404 {
3405 	ScUnoGuard aGuard;
3406     OUString sRet;
3407     Reference<XNameAccess> xMembers = GetMembers();
3408     if (xMembers.is())
3409     {
3410         Reference<XIndexAccess> xMembersIndex(new ScNameToIndexAccess( xMembers ));
3411         sal_Int32 nCount = xMembersIndex->getCount();
3412         if (mnIndex < nCount)
3413         {
3414             Reference<XNamed> xMember(xMembersIndex->getByIndex(mnIndex), UNO_QUERY);
3415             sRet = xMember->getName();
3416         }
3417     }
3418     return sRet;
3419 }
3420 
3421 void SAL_CALL ScDataPilotItemObj::setName( const OUString& /* aName */ )
3422                                 throw(RuntimeException)
3423 {
3424 }
3425 
3426 							// XPropertySet
3427 Reference< XPropertySetInfo >
3428 							SAL_CALL ScDataPilotItemObj::getPropertySetInfo(  )
3429                                 throw(RuntimeException)
3430 {
3431 	ScUnoGuard aGuard;
3432     static Reference<XPropertySetInfo> aRef =
3433         new SfxItemPropertySetInfo( maPropSet.getPropertyMap() );
3434 	return aRef;
3435 }
3436 
3437 void SAL_CALL ScDataPilotItemObj::setPropertyValue( const OUString& aPropertyName, const Any& aValue )
3438         throw(UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
3439 {
3440 	ScUnoGuard aGuard;
3441     ScDPObject* pDPObj = 0;
3442     if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) )
3443     {
3444         Reference<XNameAccess> xMembers = GetMembers();
3445         if( xMembers.is() )
3446         {
3447             Reference<XIndexAccess> xMembersIndex( new ScNameToIndexAccess( xMembers ) );
3448             sal_Int32 nCount = xMembersIndex->getCount();
3449             if( mnIndex < nCount )
3450 	        {
3451                 Reference<XNamed> xMember(xMembersIndex->getByIndex(mnIndex), UNO_QUERY);
3452                 String sName(xMember->getName());
3453                 ScDPSaveMember* pMember = pDim->GetMemberByName(sName);
3454                 if (pMember)
3455                 {
3456                     bool bGetNewIndex = false;
3457                     if ( aPropertyName.equalsAscii( SC_UNONAME_SHOWDETAIL ) )
3458                         pMember->SetShowDetails(cppu::any2bool(aValue));
3459                     else if ( aPropertyName.equalsAscii( SC_UNONAME_ISHIDDEN ) )
3460                         pMember->SetIsVisible(!cppu::any2bool(aValue));
3461                     else if ( aPropertyName.equalsAscii( SC_UNONAME_POS ) )
3462                     {
3463                         sal_Int32 nNewPos = 0;
3464                         if ( ( aValue >>= nNewPos ) && nNewPos >= 0 && nNewPos < nCount )
3465                         {
3466                             pDim->SetMemberPosition( sName, nNewPos );
3467                             // get new effective index (depends on sorting mode, which isn't modified)
3468                             bGetNewIndex = true;
3469                         }
3470                         else
3471                             throw IllegalArgumentException();
3472                     }
3473                     SetDPObject( pDPObj );
3474 
3475                     if ( bGetNewIndex )     // after SetDPObject, get the new index
3476                     {
3477                         OUString aOUName( sName );
3478                         Sequence< OUString > aItemNames = xMembers->getElementNames();
3479                         sal_Int32 nItemCount = aItemNames.getLength();
3480                         for (sal_Int32 nItem=0; nItem<nItemCount; ++nItem)
3481                             if (aItemNames[nItem] == aOUName)
3482                                 mnIndex = nItem;
3483                     }
3484                 }
3485             }
3486         }
3487     }
3488 }
3489 
3490 Any SAL_CALL ScDataPilotItemObj::getPropertyValue( const OUString& aPropertyName )
3491         throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
3492 {
3493 	ScUnoGuard aGuard;
3494     Any aRet;
3495     if( ScDPSaveDimension* pDim = GetDPDimension() )
3496     {
3497         Reference< XNameAccess > xMembers = GetMembers();
3498         if( xMembers.is() )
3499         {
3500             Reference< XIndexAccess > xMembersIndex( new ScNameToIndexAccess( xMembers ) );
3501             sal_Int32 nCount = xMembersIndex->getCount();
3502             if( mnIndex < nCount )
3503 	        {
3504                 Reference< XNamed > xMember( xMembersIndex->getByIndex( mnIndex ), UNO_QUERY );
3505                 String sName( xMember->getName() );
3506                 ScDPSaveMember* pMember = pDim->GetExistingMemberByName( sName );
3507                 if( aPropertyName.equalsAscii( SC_UNONAME_SHOWDETAIL ) )
3508                 {
3509                     if (pMember && pMember->HasShowDetails())
3510                     {
3511                         aRet <<= (bool)pMember->GetShowDetails();
3512                     }
3513                     else
3514                     {
3515                         Reference< XPropertySet > xMemberProps( xMember, UNO_QUERY );
3516                         if( xMemberProps.is() )
3517                             aRet = xMemberProps->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNO_SHOWDETA ) ) );
3518                         else
3519                             aRet <<= true;
3520                     }
3521                 }
3522                 else if ( aPropertyName.equalsAscii( SC_UNONAME_ISHIDDEN ) )
3523                 {
3524                     if (pMember && pMember->HasIsVisible())
3525                     {
3526                         aRet <<= !pMember->GetIsVisible();
3527                     }
3528                     else
3529                     {
3530                         Reference< XPropertySet > xMemberProps( xMember, UNO_QUERY );
3531                         if( xMemberProps.is() )
3532                             aRet <<= !cppu::any2bool( xMemberProps->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNO_ISVISIBL ) ) ) );
3533                         else
3534                             aRet <<= false;
3535                     }
3536                 }
3537                 else if ( aPropertyName.equalsAscii( SC_UNONAME_POS ) )
3538                 {
3539                     aRet <<= mnIndex;
3540                 }
3541             }
3542         }
3543     }
3544     return aRet;
3545 }
3546 
3547 void SAL_CALL ScDataPilotItemObj::addPropertyChangeListener(
3548         const OUString& /* aPropertyName */, const Reference< XPropertyChangeListener >& /* xListener */ )
3549         throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
3550 {
3551 }
3552 
3553 void SAL_CALL ScDataPilotItemObj::removePropertyChangeListener(
3554         const OUString& /* aPropertyName */, const Reference< XPropertyChangeListener >& /* aListener */ )
3555         throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
3556 {
3557 }
3558 
3559 void SAL_CALL ScDataPilotItemObj::addVetoableChangeListener(
3560         const OUString& /* PropertyName */, const Reference< XVetoableChangeListener >& /* aListener */ )
3561         throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
3562 {
3563 }
3564 
3565 void SAL_CALL ScDataPilotItemObj::removeVetoableChangeListener(
3566         const OUString& /* PropertyName */, const Reference< XVetoableChangeListener >& /* aListener */ )
3567         throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
3568 {
3569 }
3570 
3571 //------------------------------------------------------------------------
3572 
3573 
3574 
3575 
3576