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