update dev300-m57
[ooovba.git] / sc / source / core / data / dpsave.cxx
blob881d2cd8fccf758f275d59186724f30f577598ed
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: dpsave.cxx,v $
10 * $Revision: 1.13.32.3 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
36 // INCLUDE ---------------------------------------------------------------
38 #include "dpsave.hxx"
39 #include "dpdimsave.hxx"
40 #include "miscuno.hxx"
41 #include "scerrors.hxx"
42 #include "unonames.hxx"
43 #include "global.hxx"
45 #include <tools/debug.hxx>
47 #include <com/sun/star/sheet/GeneralFunction.hpp>
48 #include <com/sun/star/sheet/DataPilotFieldAutoShowInfo.hpp>
49 #include <com/sun/star/sheet/DataPilotFieldLayoutInfo.hpp>
50 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
51 #include <com/sun/star/sheet/DataPilotFieldReference.hpp>
52 #include <com/sun/star/sheet/DataPilotFieldSortInfo.hpp>
53 #include <com/sun/star/sheet/DataPilotFieldSortMode.hpp>
54 #include <com/sun/star/sheet/TableFilterField.hpp>
55 #include <com/sun/star/sheet/XHierarchiesSupplier.hpp>
56 #include <com/sun/star/sheet/XLevelsSupplier.hpp>
57 #include <com/sun/star/sheet/XMembersSupplier.hpp>
58 #include <com/sun/star/container/XNamed.hpp>
59 #include <com/sun/star/util/XCloneable.hpp>
61 #include <hash_map>
63 using namespace com::sun::star;
64 using ::rtl::OUString;
65 using ::rtl::OUStringHash;
66 using ::std::hash_map;
67 using ::std::auto_ptr;
69 // -----------------------------------------------------------------------
71 #define SC_DPSAVEMODE_NO 0
72 #define SC_DPSAVEMODE_YES 1
73 #define SC_DPSAVEMODE_DONTKNOW 2
75 // -----------------------------------------------------------------------
77 //! move to a header file
78 //! use names from unonames.hxx?
79 #define DP_PROP_COLUMNGRAND "ColumnGrand"
80 #define DP_PROP_FUNCTION "Function"
81 #define DP_PROP_IGNOREEMPTY "IgnoreEmptyRows"
82 #define DP_PROP_ISDATALAYOUT "IsDataLayoutDimension"
83 #define DP_PROP_ISVISIBLE "IsVisible"
84 #define DP_PROP_ORIENTATION "Orientation"
85 #define DP_PROP_REPEATIFEMPTY "RepeatIfEmpty"
86 #define DP_PROP_ROWGRAND "RowGrand"
87 #define DP_PROP_SHOWDETAILS "ShowDetails"
88 #define DP_PROP_SHOWEMPTY "ShowEmpty"
89 #define DP_PROP_SUBTOTALS "SubTotals"
90 #define DP_PROP_USEDHIERARCHY "UsedHierarchy"
91 #define DP_PROP_FILTER "Filter"
92 #define DP_PROP_POSITION "Position"
94 // -----------------------------------------------------------------------
96 void lcl_SetBoolProperty( const uno::Reference<beans::XPropertySet>& xProp,
97 const rtl::OUString& rName, sal_Bool bValue )
99 //! move to ScUnoHelpFunctions?
101 xProp->setPropertyValue( rName, uno::Any( &bValue, getBooleanCppuType() ) );
104 // -----------------------------------------------------------------------
106 ScDPSaveMember::ScDPSaveMember(const String& rName) :
107 aName( rName ),
108 mpLayoutName(NULL),
109 nVisibleMode( SC_DPSAVEMODE_DONTKNOW ),
110 nShowDetailsMode( SC_DPSAVEMODE_DONTKNOW )
114 ScDPSaveMember::ScDPSaveMember(const ScDPSaveMember& r) :
115 aName( r.aName ),
116 mpLayoutName(NULL),
117 nVisibleMode( r.nVisibleMode ),
118 nShowDetailsMode( r.nShowDetailsMode )
120 if (r.mpLayoutName.get())
121 mpLayoutName.reset(new OUString(*r.mpLayoutName));
124 ScDPSaveMember::~ScDPSaveMember()
128 BOOL ScDPSaveMember::operator== ( const ScDPSaveMember& r ) const
130 if ( aName != r.aName ||
131 nVisibleMode != r.nVisibleMode ||
132 nShowDetailsMode != r.nShowDetailsMode )
133 return FALSE;
135 return TRUE;
138 BOOL ScDPSaveMember::HasIsVisible() const
140 return nVisibleMode != SC_DPSAVEMODE_DONTKNOW;
143 void ScDPSaveMember::SetIsVisible(BOOL bSet)
145 nVisibleMode = bSet;
148 BOOL ScDPSaveMember::HasShowDetails() const
150 return nShowDetailsMode != SC_DPSAVEMODE_DONTKNOW;
153 void ScDPSaveMember::SetShowDetails(BOOL bSet)
155 nShowDetailsMode = bSet;
158 void ScDPSaveMember::SetName( const String& rNew )
160 // Used only if the source member was renamed (groups).
161 // For UI renaming of members, a layout name must be used.
163 aName = rNew;
166 void ScDPSaveMember::SetLayoutName( const OUString& rName )
168 mpLayoutName.reset(new OUString(rName));
171 const OUString* ScDPSaveMember::GetLayoutName() const
173 return mpLayoutName.get();
176 void ScDPSaveMember::RemoveLayoutName()
178 mpLayoutName.reset(NULL);
181 void ScDPSaveMember::WriteToSource( const uno::Reference<uno::XInterface>& xMember, sal_Int32 nPosition )
183 // nothing to do?
184 if ( nVisibleMode == SC_DPSAVEMODE_DONTKNOW && nShowDetailsMode == SC_DPSAVEMODE_DONTKNOW && nPosition < 0 )
185 return;
187 uno::Reference<beans::XPropertySet> xMembProp( xMember, uno::UNO_QUERY );
188 DBG_ASSERT( xMembProp.is(), "no properties at member" );
189 if ( xMembProp.is() )
191 // exceptions are caught at ScDPSaveData::WriteToSource
193 if ( nVisibleMode != SC_DPSAVEMODE_DONTKNOW )
194 lcl_SetBoolProperty( xMembProp,
195 rtl::OUString::createFromAscii(DP_PROP_ISVISIBLE), (BOOL)nVisibleMode );
197 if ( nShowDetailsMode != SC_DPSAVEMODE_DONTKNOW )
198 lcl_SetBoolProperty( xMembProp,
199 rtl::OUString::createFromAscii(DP_PROP_SHOWDETAILS), (BOOL)nShowDetailsMode );
201 if (mpLayoutName.get())
205 uno::Any any;
206 any <<= rtl::OUString(*mpLayoutName);
207 xMembProp->setPropertyValue(rtl::OUString::createFromAscii(SC_UNO_LAYOUTNAME), any);
209 catch (uno::Exception&)
213 if ( nPosition >= 0 )
217 xMembProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_POSITION), uno::Any(nPosition) );
219 catch ( uno::Exception& )
221 // position is optional - exception must be ignored
227 // -----------------------------------------------------------------------
229 ScDPSaveDimension::ScDPSaveDimension(const String& rName, BOOL bDataLayout) :
230 aName( rName ),
231 pSelectedPage( NULL ),
232 mpLayoutName(NULL),
233 mpSubtotalName(NULL),
234 bIsDataLayout( bDataLayout ),
235 bDupFlag( FALSE ),
236 nOrientation( sheet::DataPilotFieldOrientation_HIDDEN ),
237 nFunction( sheet::GeneralFunction_AUTO ),
238 nUsedHierarchy( -1 ),
239 nShowEmptyMode( SC_DPSAVEMODE_DONTKNOW ),
240 bSubTotalDefault( TRUE ),
241 nSubTotalCount( 0 ),
242 pSubTotalFuncs( NULL ),
243 pReferenceValue( NULL ),
244 pSortInfo( NULL ),
245 pAutoShowInfo( NULL ),
246 pLayoutInfo( NULL )
250 ScDPSaveDimension::ScDPSaveDimension(const ScDPSaveDimension& r) :
251 aName( r.aName ),
252 mpLayoutName(NULL),
253 mpSubtotalName(NULL),
254 bIsDataLayout( r.bIsDataLayout ),
255 bDupFlag( r.bDupFlag ),
256 nOrientation( r.nOrientation ),
257 nFunction( r.nFunction ),
258 nUsedHierarchy( r.nUsedHierarchy ),
259 nShowEmptyMode( r.nShowEmptyMode ),
260 bSubTotalDefault( r.bSubTotalDefault ),
261 nSubTotalCount( r.nSubTotalCount ),
262 pSubTotalFuncs( NULL )
264 if ( nSubTotalCount && r.pSubTotalFuncs )
266 pSubTotalFuncs = new USHORT[nSubTotalCount];
267 for (long nSub=0; nSub<nSubTotalCount; nSub++)
268 pSubTotalFuncs[nSub] = r.pSubTotalFuncs[nSub];
271 for (MemberList::const_iterator i=r.maMemberList.begin(); i != r.maMemberList.end() ; i++)
273 const String& rName = (*i)->GetName();
274 ScDPSaveMember* pNew = new ScDPSaveMember( **i );
275 maMemberHash[rName] = pNew;
276 maMemberList.push_back( pNew );
278 if (r.pReferenceValue)
279 pReferenceValue = new sheet::DataPilotFieldReference( *(r.pReferenceValue) );
280 else
281 pReferenceValue = NULL;
282 if (r.pSortInfo)
283 pSortInfo = new sheet::DataPilotFieldSortInfo( *(r.pSortInfo) );
284 else
285 pSortInfo = NULL;
286 if (r.pAutoShowInfo)
287 pAutoShowInfo = new sheet::DataPilotFieldAutoShowInfo( *(r.pAutoShowInfo) );
288 else
289 pAutoShowInfo = NULL;
290 if (r.pLayoutInfo)
291 pLayoutInfo = new sheet::DataPilotFieldLayoutInfo( *(r.pLayoutInfo) );
292 else
293 pLayoutInfo = NULL;
294 if (r.pSelectedPage)
295 pSelectedPage = new String( *(r.pSelectedPage) );
296 else
297 pSelectedPage = NULL;
298 if (r.mpLayoutName.get())
299 mpLayoutName.reset(new OUString(*r.mpLayoutName));
300 if (r.mpSubtotalName.get())
301 mpSubtotalName.reset(new OUString(*r.mpSubtotalName));
304 ScDPSaveDimension::~ScDPSaveDimension()
306 for (MemberHash::const_iterator i=maMemberHash.begin(); i != maMemberHash.end() ; i++)
307 delete i->second;
308 delete pReferenceValue;
309 delete pSortInfo;
310 delete pAutoShowInfo;
311 delete pLayoutInfo;
312 delete pSelectedPage;
313 delete [] pSubTotalFuncs;
316 BOOL ScDPSaveDimension::operator== ( const ScDPSaveDimension& r ) const
318 if ( aName != r.aName ||
319 bIsDataLayout != r.bIsDataLayout ||
320 bDupFlag != r.bDupFlag ||
321 nOrientation != r.nOrientation ||
322 nFunction != r.nFunction ||
323 nUsedHierarchy != r.nUsedHierarchy ||
324 nShowEmptyMode != r.nShowEmptyMode ||
325 bSubTotalDefault != r.bSubTotalDefault ||
326 nSubTotalCount != r.nSubTotalCount )
327 return FALSE;
329 if ( nSubTotalCount && ( !pSubTotalFuncs || !r.pSubTotalFuncs ) ) // should not happen
330 return FALSE;
332 long i;
333 for (i=0; i<nSubTotalCount; i++)
334 if ( pSubTotalFuncs[i] != r.pSubTotalFuncs[i] )
335 return FALSE;
337 if (maMemberHash.size() != r.maMemberHash.size() )
338 return FALSE;
340 MemberList::const_iterator a=maMemberList.begin();
341 MemberList::const_iterator b=r.maMemberList.begin();
342 for (; a != maMemberList.end() ; ++a, ++b)
343 if (!(**a == **b))
344 return FALSE;
346 return TRUE;
349 void ScDPSaveDimension::AddMember(ScDPSaveMember* pMember)
351 const String & rName = pMember->GetName();
352 MemberHash::iterator aExisting = maMemberHash.find( rName );
353 if ( aExisting == maMemberHash.end() )
355 std::pair< const String, ScDPSaveMember *> key( rName, pMember );
356 maMemberHash.insert ( key );
358 else
360 maMemberList.remove( aExisting->second );
361 delete aExisting->second;
362 aExisting->second = pMember;
364 maMemberList.push_back( pMember );
367 void ScDPSaveDimension::SetName( const String& rNew )
369 // Used only if the source dim was renamed (groups).
370 // For UI renaming of dimensions, the layout name must be used.
372 aName = rNew;
375 void ScDPSaveDimension::SetOrientation(USHORT nNew)
377 nOrientation = nNew;
380 void ScDPSaveDimension::SetSubTotals(long nCount, const USHORT* pFuncs)
382 if (pSubTotalFuncs)
383 delete [] pSubTotalFuncs;
384 nSubTotalCount = nCount;
385 if ( nCount && pFuncs )
387 pSubTotalFuncs = new USHORT[nCount];
388 for (long i=0; i<nCount; i++)
389 pSubTotalFuncs[i] = pFuncs[i];
391 else
392 pSubTotalFuncs = NULL;
394 bSubTotalDefault = FALSE;
397 void ScDPSaveDimension::SetShowEmpty(BOOL bSet)
399 nShowEmptyMode = bSet;
402 void ScDPSaveDimension::SetFunction(USHORT nNew)
404 nFunction = nNew;
407 void ScDPSaveDimension::SetUsedHierarchy(long nNew)
409 nUsedHierarchy = nNew;
412 void ScDPSaveDimension::SetSubtotalName(const OUString& rName)
414 mpSubtotalName.reset(new OUString(rName));
417 const OUString* ScDPSaveDimension::GetSubtotalName() const
419 return mpSubtotalName.get();
422 bool ScDPSaveDimension::IsMemberNameInUse(const OUString& rName) const
424 MemberList::const_iterator itr = maMemberList.begin(), itrEnd = maMemberList.end();
425 for (; itr != itrEnd; ++itr)
427 const ScDPSaveMember* pMem = *itr;
428 if (rName.equalsIgnoreAsciiCase(pMem->GetName()))
429 return true;
431 const OUString* pLayoutName = pMem->GetLayoutName();
432 if (pLayoutName && rName.equalsIgnoreAsciiCase(*pLayoutName))
433 return true;
435 return false;
438 void ScDPSaveDimension::SetLayoutName(const OUString& rName)
440 mpLayoutName.reset(new OUString(rName));
443 const OUString* ScDPSaveDimension::GetLayoutName() const
445 return mpLayoutName.get();
448 void ScDPSaveDimension::RemoveLayoutName()
450 mpLayoutName.reset(NULL);
453 void ScDPSaveDimension::SetReferenceValue(const sheet::DataPilotFieldReference* pNew)
455 delete pReferenceValue;
456 if (pNew)
457 pReferenceValue = new sheet::DataPilotFieldReference(*pNew);
458 else
459 pReferenceValue = NULL;
462 void ScDPSaveDimension::SetSortInfo(const sheet::DataPilotFieldSortInfo* pNew)
464 delete pSortInfo;
465 if (pNew)
466 pSortInfo = new sheet::DataPilotFieldSortInfo(*pNew);
467 else
468 pSortInfo = NULL;
471 void ScDPSaveDimension::SetAutoShowInfo(const sheet::DataPilotFieldAutoShowInfo* pNew)
473 delete pAutoShowInfo;
474 if (pNew)
475 pAutoShowInfo = new sheet::DataPilotFieldAutoShowInfo(*pNew);
476 else
477 pAutoShowInfo = NULL;
480 void ScDPSaveDimension::SetLayoutInfo(const sheet::DataPilotFieldLayoutInfo* pNew)
482 delete pLayoutInfo;
483 if (pNew)
484 pLayoutInfo = new sheet::DataPilotFieldLayoutInfo(*pNew);
485 else
486 pLayoutInfo = NULL;
489 void ScDPSaveDimension::SetCurrentPage( const String* pPage )
491 delete pSelectedPage;
492 if (pPage)
493 pSelectedPage = new String( *pPage );
494 else
495 pSelectedPage = NULL;
498 BOOL ScDPSaveDimension::HasCurrentPage() const
500 return ( pSelectedPage != NULL );
503 const String& ScDPSaveDimension::GetCurrentPage() const
505 if (pSelectedPage)
506 return *pSelectedPage;
507 return EMPTY_STRING;
510 ScDPSaveMember* ScDPSaveDimension::GetExistingMemberByName(const String& rName)
512 MemberHash::const_iterator res = maMemberHash.find (rName);
513 if (res != maMemberHash.end())
514 return res->second;
515 return NULL;
519 ScDPSaveMember* ScDPSaveDimension::GetMemberByName(const String& rName)
521 MemberHash::const_iterator res = maMemberHash.find (rName);
522 if (res != maMemberHash.end())
523 return res->second;
525 ScDPSaveMember* pNew = new ScDPSaveMember( rName );
526 maMemberHash[rName] = pNew;
527 maMemberList.push_back( pNew );
528 return pNew;
531 void ScDPSaveDimension::SetMemberPosition( const String& rName, sal_Int32 nNewPos )
533 ScDPSaveMember* pMember = GetMemberByName( rName ); // make sure it exists and is in the hash
535 maMemberList.remove( pMember );
537 MemberList::iterator aIter = maMemberList.begin();
538 for (sal_Int32 i=0; i<nNewPos && aIter != maMemberList.end(); i++)
539 ++aIter;
540 maMemberList.insert( aIter, pMember );
543 void ScDPSaveDimension::WriteToSource( const uno::Reference<uno::XInterface>& xDim )
545 uno::Reference<beans::XPropertySet> xDimProp( xDim, uno::UNO_QUERY );
546 DBG_ASSERT( xDimProp.is(), "no properties at dimension" );
547 if ( xDimProp.is() )
549 // exceptions are caught at ScDPSaveData::WriteToSource
550 uno::Any aAny;
552 sheet::DataPilotFieldOrientation eOrient = (sheet::DataPilotFieldOrientation)nOrientation;
553 aAny <<= eOrient;
554 xDimProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_ORIENTATION), aAny );
556 sheet::GeneralFunction eFunc = (sheet::GeneralFunction)nFunction;
557 aAny <<= eFunc;
558 xDimProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_FUNCTION), aAny );
560 if ( nUsedHierarchy >= 0 )
562 aAny <<= (INT32)nUsedHierarchy;
563 xDimProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_USEDHIERARCHY), aAny );
566 if ( pReferenceValue )
568 aAny <<= *pReferenceValue;
569 xDimProp->setPropertyValue( rtl::OUString::createFromAscii(SC_UNO_REFVALUE), aAny );
572 uno::Sequence<sheet::TableFilterField> aFilter;
573 // set the selected page field only if the dimension is used as page dimension
574 if ( pSelectedPage && nOrientation == sheet::DataPilotFieldOrientation_PAGE )
576 // single filter field: first field equal to selected string
577 sheet::TableFilterField aField( sheet::FilterConnection_AND, 0,
578 sheet::FilterOperator_EQUAL, sal_False, 0.0, *pSelectedPage );
579 aFilter = uno::Sequence<sheet::TableFilterField>( &aField, 1 );
581 // else keep empty sequence
584 aAny <<= aFilter;
585 xDimProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_FILTER), aAny );
586 if (mpLayoutName.get())
588 aAny <<= *mpLayoutName;
589 xDimProp->setPropertyValue(rtl::OUString::createFromAscii(SC_UNO_LAYOUTNAME), aAny);
592 const OUString* pSubTotalName = GetSubtotalName();
593 if (pSubTotalName)
595 // Custom subtotal name, with '?' being replaced by the visible field name later.
596 aAny <<= *pSubTotalName;
597 xDimProp->setPropertyValue(OUString::createFromAscii(SC_UNO_FIELD_SUBTOTALNAME), aAny);
600 catch ( beans::UnknownPropertyException& )
602 // recent addition - allow source to not handle it (no error)
606 // Level loop outside of maMemberList loop
607 // because SubTotals have to be set independently of known members
609 long nCount = maMemberHash.size();
611 long nHierCount = 0;
612 uno::Reference<container::XIndexAccess> xHiers;
613 uno::Reference<sheet::XHierarchiesSupplier> xHierSupp( xDim, uno::UNO_QUERY );
614 if ( xHierSupp.is() )
616 uno::Reference<container::XNameAccess> xHiersName = xHierSupp->getHierarchies();
617 xHiers = new ScNameToIndexAccess( xHiersName );
618 nHierCount = xHiers->getCount();
621 sal_Bool bHasHiddenMember = false;
623 for (long nHier=0; nHier<nHierCount; nHier++)
625 uno::Reference<uno::XInterface> xHierarchy = ScUnoHelpFunctions::AnyToInterface( xHiers->getByIndex(nHier) );
627 long nLevCount = 0;
628 uno::Reference<container::XIndexAccess> xLevels;
629 uno::Reference<sheet::XLevelsSupplier> xLevSupp( xHierarchy, uno::UNO_QUERY );
630 if ( xLevSupp.is() )
632 uno::Reference<container::XNameAccess> xLevelsName = xLevSupp->getLevels();
633 xLevels = new ScNameToIndexAccess( xLevelsName );
634 nLevCount = xLevels->getCount();
637 for (long nLev=0; nLev<nLevCount; nLev++)
639 uno::Reference<uno::XInterface> xLevel = ScUnoHelpFunctions::AnyToInterface( xLevels->getByIndex(nLev) );
640 uno::Reference<beans::XPropertySet> xLevProp( xLevel, uno::UNO_QUERY );
641 DBG_ASSERT( xLevProp.is(), "no properties at level" );
642 if ( xLevProp.is() )
644 uno::Any aAny;
645 if ( !bSubTotalDefault )
647 if ( !pSubTotalFuncs )
648 nSubTotalCount = 0;
650 uno::Sequence<sheet::GeneralFunction> aSeq(nSubTotalCount);
651 sheet::GeneralFunction* pArray = aSeq.getArray();
652 for (long i=0; i<nSubTotalCount; i++)
653 pArray[i] = (sheet::GeneralFunction)pSubTotalFuncs[i];
654 aAny <<= aSeq;
655 xLevProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_SUBTOTALS), aAny );
657 if ( nShowEmptyMode != SC_DPSAVEMODE_DONTKNOW )
658 lcl_SetBoolProperty( xLevProp,
659 rtl::OUString::createFromAscii(DP_PROP_SHOWEMPTY), (BOOL)nShowEmptyMode );
661 if ( pSortInfo )
663 aAny <<= *pSortInfo;
666 xLevProp->setPropertyValue( rtl::OUString::createFromAscii(SC_UNO_SORTING), aAny );
668 catch ( beans::UnknownPropertyException& )
670 // recent addition - allow source to not handle it (no error)
673 if ( pAutoShowInfo )
675 aAny <<= *pAutoShowInfo;
678 xLevProp->setPropertyValue( rtl::OUString::createFromAscii(SC_UNO_AUTOSHOW), aAny );
680 catch ( beans::UnknownPropertyException& )
682 // recent addition - allow source to not handle it (no error)
685 if ( pLayoutInfo )
687 aAny <<= *pLayoutInfo;
690 xLevProp->setPropertyValue( rtl::OUString::createFromAscii(SC_UNO_LAYOUT), aAny );
692 catch ( beans::UnknownPropertyException& )
694 // recent addition - allow source to not handle it (no error)
698 // exceptions are caught at ScDPSaveData::WriteToSource
701 if ( nCount > 0 )
703 uno::Reference<sheet::XMembersSupplier> xMembSupp( xLevel, uno::UNO_QUERY );
704 if ( xMembSupp.is() )
706 uno::Reference<container::XNameAccess> xMembers = xMembSupp->getMembers();
707 if ( xMembers.is() )
709 sal_Int32 nPosition = -1; // set position only in manual mode
710 if ( !pSortInfo || pSortInfo->Mode == sheet::DataPilotFieldSortMode::MANUAL )
711 nPosition = 0;
713 for (MemberList::const_iterator i=maMemberList.begin(); i != maMemberList.end() ; i++)
715 ScDPSaveMember* pMember = *i;
716 if (!pMember->GetIsVisible())
717 bHasHiddenMember = true;
718 rtl::OUString aMemberName = pMember->GetName();
719 if ( xMembers->hasByName( aMemberName ) )
721 uno::Reference<uno::XInterface> xMemberInt = ScUnoHelpFunctions::AnyToInterface(
722 xMembers->getByName( aMemberName ) );
723 pMember->WriteToSource( xMemberInt, nPosition );
725 if ( nPosition >= 0 )
726 ++nPosition; // increase if initialized
728 // missing member is no error
736 if (xDimProp.is())
738 uno::Any any;
739 any <<= bHasHiddenMember;
740 xDimProp->setPropertyValue(
741 OUString::createFromAscii(SC_UNO_HAS_HIDDEN_MEMBER), any);
745 void ScDPSaveDimension::UpdateMemberVisibility(const hash_map<OUString, bool, OUStringHash>& rData)
747 typedef hash_map<OUString, bool, OUStringHash> DataMap;
748 MemberList::iterator itrMem = maMemberList.begin(), itrMemEnd = maMemberList.end();
749 for (; itrMem != itrMemEnd; ++itrMem)
751 ScDPSaveMember* pMem = *itrMem;
752 const String& rMemName = pMem->GetName();
753 DataMap::const_iterator itr = rData.find(rMemName);
754 if (itr != rData.end())
755 pMem->SetIsVisible(itr->second);
759 bool ScDPSaveDimension::HasInvisibleMember() const
761 MemberList::const_iterator itrMem = maMemberList.begin(), itrMemEnd = maMemberList.end();
762 for (; itrMem != itrMemEnd; ++itrMem)
764 const ScDPSaveMember* pMem = *itrMem;
765 if (!pMem->GetIsVisible())
766 return true;
768 return false;
771 // -----------------------------------------------------------------------
773 ScDPSaveData::ScDPSaveData() :
774 pDimensionData( NULL ),
775 nColumnGrandMode( SC_DPSAVEMODE_DONTKNOW ),
776 nRowGrandMode( SC_DPSAVEMODE_DONTKNOW ),
777 nIgnoreEmptyMode( SC_DPSAVEMODE_DONTKNOW ),
778 nRepeatEmptyMode( SC_DPSAVEMODE_DONTKNOW ),
779 bFilterButton( TRUE ),
780 bDrillDown( TRUE ),
781 mbDimensionMembersBuilt(false),
782 mpGrandTotalName(NULL)
786 ScDPSaveData::ScDPSaveData(const ScDPSaveData& r) :
787 nColumnGrandMode( r.nColumnGrandMode ),
788 nRowGrandMode( r.nRowGrandMode ),
789 nIgnoreEmptyMode( r.nIgnoreEmptyMode ),
790 nRepeatEmptyMode( r.nRepeatEmptyMode ),
791 bFilterButton( r.bFilterButton ),
792 bDrillDown( r.bDrillDown ),
793 mbDimensionMembersBuilt(r.mbDimensionMembersBuilt),
794 mpGrandTotalName(NULL)
796 if ( r.pDimensionData )
797 pDimensionData = new ScDPDimensionSaveData( *r.pDimensionData );
798 else
799 pDimensionData = NULL;
801 long nCount = r.aDimList.Count();
802 for (long i=0; i<nCount; i++)
804 ScDPSaveDimension* pNew = new ScDPSaveDimension( *(ScDPSaveDimension*)r.aDimList.GetObject(i) );
805 aDimList.Insert( pNew, LIST_APPEND );
808 if (r.mpGrandTotalName.get())
809 mpGrandTotalName.reset(new OUString(*r.mpGrandTotalName));
812 ScDPSaveData& ScDPSaveData::operator= ( const ScDPSaveData& r )
814 if ( &r != this )
816 delete pDimensionData;
817 if ( r.pDimensionData )
818 pDimensionData = new ScDPDimensionSaveData( *r.pDimensionData );
819 else
820 pDimensionData = NULL;
822 nColumnGrandMode = r.nColumnGrandMode;
823 nRowGrandMode = r.nRowGrandMode;
824 nIgnoreEmptyMode = r.nIgnoreEmptyMode;
825 nRepeatEmptyMode = r.nRepeatEmptyMode;
826 bFilterButton = r.bFilterButton;
827 bDrillDown = r.bDrillDown;
828 mbDimensionMembersBuilt = r.mbDimensionMembersBuilt;
830 // remove old dimensions
832 long nCount = aDimList.Count();
833 long i;
834 for (i=0; i<nCount; i++)
835 delete (ScDPSaveDimension*)aDimList.GetObject(i);
836 aDimList.Clear();
838 // copy new dimensions
840 nCount = r.aDimList.Count();
841 for (i=0; i<nCount; i++)
843 ScDPSaveDimension* pNew =
844 new ScDPSaveDimension( *(ScDPSaveDimension*)r.aDimList.GetObject(i) );
845 aDimList.Insert( pNew, LIST_APPEND );
848 if (r.mpGrandTotalName.get())
849 mpGrandTotalName.reset(new OUString(*r.mpGrandTotalName));
851 return *this;
854 BOOL ScDPSaveData::operator== ( const ScDPSaveData& r ) const
856 if ( nColumnGrandMode != r.nColumnGrandMode ||
857 nRowGrandMode != r.nRowGrandMode ||
858 nIgnoreEmptyMode != r.nIgnoreEmptyMode ||
859 nRepeatEmptyMode != r.nRepeatEmptyMode ||
860 bFilterButton != r.bFilterButton ||
861 bDrillDown != r.bDrillDown ||
862 mbDimensionMembersBuilt != r.mbDimensionMembersBuilt)
863 return FALSE;
865 if ( pDimensionData || r.pDimensionData )
866 if ( !pDimensionData || !r.pDimensionData || !( *pDimensionData == *r.pDimensionData ) )
867 return FALSE;
869 ULONG nCount = aDimList.Count();
870 if ( nCount != r.aDimList.Count() )
871 return FALSE;
873 for (ULONG i=0; i<nCount; i++)
874 if ( !( *(ScDPSaveDimension*)aDimList.GetObject(i) ==
875 *(ScDPSaveDimension*)r.aDimList.GetObject(i) ) )
876 return FALSE;
878 if (mpGrandTotalName.get())
880 if (!r.mpGrandTotalName.get())
881 return false;
882 if (!mpGrandTotalName->equals(*r.mpGrandTotalName))
883 return false;
885 else if (r.mpGrandTotalName.get())
886 return false;
888 return TRUE;
891 ScDPSaveData::~ScDPSaveData()
893 long nCount = aDimList.Count();
894 for (long i=0; i<nCount; i++)
895 delete (ScDPSaveDimension*)aDimList.GetObject(i);
896 aDimList.Clear();
898 delete pDimensionData;
901 void ScDPSaveData::SetGrandTotalName(const OUString& rName)
903 mpGrandTotalName.reset(new OUString(rName));
906 const OUString* ScDPSaveData::GetGrandTotalName() const
908 return mpGrandTotalName.get();
911 ScDPSaveDimension* ScDPSaveData::GetDimensionByName(const String& rName)
913 long nCount = aDimList.Count();
914 for (long i=0; i<nCount; i++)
916 ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
917 if ( pDim->GetName() == rName && !pDim->IsDataLayout() )
918 return pDim;
920 ScDPSaveDimension* pNew = new ScDPSaveDimension( rName, FALSE );
921 aDimList.Insert( pNew, LIST_APPEND );
922 return pNew;
925 ScDPSaveDimension* ScDPSaveData::GetExistingDimensionByName(const String& rName) const
927 long nCount = aDimList.Count();
928 for (long i=0; i<nCount; i++)
930 ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
931 if ( pDim->GetName() == rName && !pDim->IsDataLayout() )
932 return pDim;
934 return NULL; // don't create new
937 ScDPSaveDimension* ScDPSaveData::GetNewDimensionByName(const String& rName)
939 long nCount = aDimList.Count();
940 for (long i=0; i<nCount; i++)
942 ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
943 if ( pDim->GetName() == rName && !pDim->IsDataLayout() )
944 return DuplicateDimension(rName);
946 ScDPSaveDimension* pNew = new ScDPSaveDimension( rName, FALSE );
947 aDimList.Insert( pNew, LIST_APPEND );
948 return pNew;
951 ScDPSaveDimension* ScDPSaveData::GetDataLayoutDimension()
953 ScDPSaveDimension* pDim = GetExistingDataLayoutDimension();
954 if (pDim)
955 return pDim;
957 ScDPSaveDimension* pNew = new ScDPSaveDimension( String(), TRUE );
958 aDimList.Insert( pNew, LIST_APPEND );
959 return pNew;
962 ScDPSaveDimension* ScDPSaveData::GetExistingDataLayoutDimension() const
964 ULONG nCount = aDimList.Count();
965 for (ULONG i=0; i<nCount; i++)
967 ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
968 if ( pDim->IsDataLayout() )
969 return pDim;
971 return NULL;
974 ScDPSaveDimension* ScDPSaveData::DuplicateDimension(const String& rName)
976 // always insert new
977 //! check if dimension is there?
979 ScDPSaveDimension* pOld = GetDimensionByName( rName );
980 ScDPSaveDimension* pNew = new ScDPSaveDimension( *pOld );
981 pNew->SetDupFlag( TRUE );
982 aDimList.Insert( pNew, LIST_APPEND );
983 return pNew;
986 void ScDPSaveData::RemoveDimensionByName(const String& rName)
988 long nCount = aDimList.Count();
989 for (long i=0; i<nCount; i++)
991 ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
992 if ( pDim->GetName() == rName && !pDim->IsDataLayout() )
994 delete pDim;
995 aDimList.Remove(i);
996 break;
1001 ScDPSaveDimension& ScDPSaveData::DuplicateDimension( const ScDPSaveDimension& rDim )
1003 ScDPSaveDimension* pNew = new ScDPSaveDimension( rDim );
1004 pNew->SetDupFlag( TRUE );
1005 aDimList.Insert( pNew, LIST_APPEND );
1006 return *pNew;
1009 ScDPSaveDimension* ScDPSaveData::GetInnermostDimension(USHORT nOrientation)
1011 // return the innermost dimension for the given orientation,
1012 // excluding data layout dimension
1014 ScDPSaveDimension* pInner = NULL;
1015 long nCount = aDimList.Count();
1016 for (long i=0; i<nCount; i++)
1018 ScDPSaveDimension* pDim = static_cast<ScDPSaveDimension*>(aDimList.GetObject(i));
1019 if ( pDim->GetOrientation() == nOrientation && !pDim->IsDataLayout() )
1020 pInner = pDim;
1022 return pInner; // the last matching one
1025 ScDPSaveDimension* ScDPSaveData::GetFirstDimension(sheet::DataPilotFieldOrientation eOrientation)
1027 long nCount = aDimList.Count();
1028 for (long i = 0; i < nCount; ++i)
1030 ScDPSaveDimension* pDim = static_cast<ScDPSaveDimension*>(aDimList.GetObject(i));
1031 if (pDim->GetOrientation() == eOrientation && !pDim->IsDataLayout())
1032 return pDim;
1034 return NULL;
1037 long ScDPSaveData::GetDataDimensionCount() const
1039 long nDataCount = 0;
1041 long nCount = aDimList.Count();
1042 for (long i=0; i<nCount; i++)
1044 const ScDPSaveDimension* pDim = static_cast<const ScDPSaveDimension*>(aDimList.GetObject(i));
1045 if ( pDim->GetOrientation() == sheet::DataPilotFieldOrientation_DATA )
1046 ++nDataCount;
1049 return nDataCount;
1052 void ScDPSaveData::SetPosition( ScDPSaveDimension* pDim, long nNew )
1054 // position (nNew) is counted within dimensions of the same orientation
1056 USHORT nOrient = pDim->GetOrientation();
1058 aDimList.Remove( pDim );
1059 ULONG nCount = aDimList.Count(); // after remove
1061 ULONG nInsPos = 0;
1062 while ( nNew > 0 && nInsPos < nCount )
1064 if ( ((ScDPSaveDimension*)aDimList.GetObject(nInsPos))->GetOrientation() == nOrient )
1065 --nNew;
1066 ++nInsPos;
1069 aDimList.Insert( pDim, nInsPos );
1072 void ScDPSaveData::SetColumnGrand(BOOL bSet)
1074 nColumnGrandMode = bSet;
1077 void ScDPSaveData::SetRowGrand(BOOL bSet)
1079 nRowGrandMode = bSet;
1082 void ScDPSaveData::SetIgnoreEmptyRows(BOOL bSet)
1084 nIgnoreEmptyMode = bSet;
1087 void ScDPSaveData::SetRepeatIfEmpty(BOOL bSet)
1089 nRepeatEmptyMode = bSet;
1092 void ScDPSaveData::SetFilterButton(BOOL bSet)
1094 bFilterButton = bSet;
1097 void ScDPSaveData::SetDrillDown(BOOL bSet)
1099 bDrillDown = bSet;
1102 void lcl_ResetOrient( const uno::Reference<sheet::XDimensionsSupplier>& xSource )
1104 sheet::DataPilotFieldOrientation eOrient = sheet::DataPilotFieldOrientation_HIDDEN;
1106 uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
1107 uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName );
1108 long nIntCount = xIntDims->getCount();
1109 for (long nIntDim=0; nIntDim<nIntCount; nIntDim++)
1111 uno::Reference<uno::XInterface> xIntDim = ScUnoHelpFunctions::AnyToInterface( xIntDims->getByIndex(nIntDim) );
1112 uno::Reference<beans::XPropertySet> xDimProp( xIntDim, uno::UNO_QUERY );
1113 if (xDimProp.is())
1115 uno::Any aAny;
1116 aAny <<= eOrient;
1117 xDimProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_ORIENTATION), aAny );
1122 void ScDPSaveData::WriteToSource( const uno::Reference<sheet::XDimensionsSupplier>& xSource )
1124 if (!xSource.is())
1125 return;
1127 // source options must be first!
1129 uno::Reference<beans::XPropertySet> xSourceProp( xSource, uno::UNO_QUERY );
1130 DBG_ASSERT( xSourceProp.is(), "no properties at source" );
1131 if ( xSourceProp.is() )
1133 // source options are not available for external sources
1134 //! use XPropertySetInfo to test for availability?
1138 if ( nIgnoreEmptyMode != SC_DPSAVEMODE_DONTKNOW )
1139 lcl_SetBoolProperty( xSourceProp,
1140 rtl::OUString::createFromAscii(DP_PROP_IGNOREEMPTY), (BOOL)nIgnoreEmptyMode );
1141 if ( nRepeatEmptyMode != SC_DPSAVEMODE_DONTKNOW )
1142 lcl_SetBoolProperty( xSourceProp,
1143 rtl::OUString::createFromAscii(DP_PROP_REPEATIFEMPTY), (BOOL)nRepeatEmptyMode );
1145 const OUString* pGrandTotalName = GetGrandTotalName();
1146 if (pGrandTotalName)
1148 uno::Any any;
1149 any <<= *pGrandTotalName;
1150 xSourceProp->setPropertyValue(OUString::createFromAscii(SC_UNO_GRANDTOTAL_NAME), any);
1153 catch(uno::Exception&)
1155 // no error
1159 // exceptions in the other calls are errors
1162 // reset all orientations
1163 //! "forgetSettings" or similar at source ?????
1164 //! reset all duplicated dimensions, or reuse them below !!!
1166 lcl_ResetOrient( xSource );
1168 long nCount = aDimList.Count();
1169 for (long i=0; i<nCount; i++)
1171 ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
1172 rtl::OUString aName = pDim->GetName();
1173 BOOL bData = pDim->IsDataLayout();
1175 //! getByName for ScDPSource, including DataLayoutDimension !!!!!!!!
1177 uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
1178 uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName );
1179 long nIntCount = xIntDims->getCount();
1180 BOOL bFound = FALSE;
1181 for (long nIntDim=0; nIntDim<nIntCount && !bFound; nIntDim++)
1183 uno::Reference<uno::XInterface> xIntDim = ScUnoHelpFunctions::AnyToInterface( xIntDims->getByIndex(nIntDim) );
1184 if ( bData )
1186 uno::Reference<beans::XPropertySet> xDimProp( xIntDim, uno::UNO_QUERY );
1187 if ( xDimProp.is() )
1189 bFound = ScUnoHelpFunctions::GetBoolProperty( xDimProp,
1190 rtl::OUString::createFromAscii(DP_PROP_ISDATALAYOUT) );
1191 //! error checking -- is "IsDataLayoutDimension" property required??
1194 else
1196 uno::Reference<container::XNamed> xDimName( xIntDim, uno::UNO_QUERY );
1197 if ( xDimName.is() && xDimName->getName() == aName )
1198 bFound = TRUE;
1201 if ( bFound )
1203 if ( pDim->GetDupFlag() )
1205 String aNewName = pDim->GetName();
1207 // different name for each duplication of a (real) dimension...
1208 for (long j=0; j<=i; j++) //! Test !!!!!!
1209 aNewName += '*'; //! modify name at creation of SaveDimension
1211 uno::Reference<util::XCloneable> xCloneable( xIntDim, uno::UNO_QUERY );
1212 DBG_ASSERT( xCloneable.is(), "cannot clone dimension" );
1213 if (xCloneable.is())
1215 uno::Reference<util::XCloneable> xNew = xCloneable->createClone();
1216 uno::Reference<container::XNamed> xNewName( xNew, uno::UNO_QUERY );
1217 if (xNewName.is())
1219 xNewName->setName( aNewName );
1220 pDim->WriteToSource( xNew );
1224 else
1225 pDim->WriteToSource( xIntDim );
1228 DBG_ASSERT(bFound, "WriteToSource: Dimension not found");
1231 if ( xSourceProp.is() )
1233 if ( nColumnGrandMode != SC_DPSAVEMODE_DONTKNOW )
1234 lcl_SetBoolProperty( xSourceProp,
1235 rtl::OUString::createFromAscii(DP_PROP_COLUMNGRAND), (BOOL)nColumnGrandMode );
1236 if ( nRowGrandMode != SC_DPSAVEMODE_DONTKNOW )
1237 lcl_SetBoolProperty( xSourceProp,
1238 rtl::OUString::createFromAscii(DP_PROP_ROWGRAND), (BOOL)nRowGrandMode );
1241 catch(uno::Exception&)
1243 DBG_ERROR("exception in WriteToSource");
1247 BOOL ScDPSaveData::IsEmpty() const
1249 long nCount = aDimList.Count();
1250 for (long i=0; i<nCount; i++)
1252 ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
1253 if ( pDim->GetOrientation() != sheet::DataPilotFieldOrientation_HIDDEN && !pDim->IsDataLayout() )
1254 return FALSE;
1256 return TRUE; // no entries that are not hidden
1259 ScDPDimensionSaveData* ScDPSaveData::GetDimensionData()
1261 if (!pDimensionData)
1262 pDimensionData = new ScDPDimensionSaveData;
1263 return pDimensionData;
1266 void ScDPSaveData::SetDimensionData( const ScDPDimensionSaveData* pNew )
1268 delete pDimensionData;
1269 if ( pNew )
1270 pDimensionData = new ScDPDimensionSaveData( *pNew );
1271 else
1272 pDimensionData = NULL;
1275 void ScDPSaveData::BuildAllDimensionMembers(ScDPTableData* pData)
1277 if (mbDimensionMembersBuilt)
1278 return;
1280 // First, build a dimension name-to-index map.
1281 typedef hash_map<OUString, long, ::rtl::OUStringHash> NameIndexMap;
1282 NameIndexMap aMap;
1283 long nColCount = pData->GetColumnCount();
1284 for (long i = 0; i < nColCount; ++i)
1285 aMap.insert( NameIndexMap::value_type(pData->getDimensionName(i), i));
1287 NameIndexMap::const_iterator itrEnd = aMap.end();
1289 sal_uInt32 n = aDimList.Count();
1290 for (sal_uInt32 i = 0; i < n; ++i)
1292 ScDPSaveDimension* pDim = static_cast<ScDPSaveDimension*>(aDimList.GetObject(i));
1293 const String& rDimName = pDim->GetName();
1294 if (!rDimName.Len())
1295 // empty dimension name. It must be data layout.
1296 continue;
1298 NameIndexMap::const_iterator itr = aMap.find(rDimName);
1299 if (itr == itrEnd)
1300 // dimension name not in the data. This should never happen!
1301 continue;
1303 long nDimIndex = itr->second;
1304 const TypedScStrCollection& rMembers = pData->GetColumnEntries(nDimIndex);
1305 sal_uInt16 nMemberCount = rMembers.GetCount();
1306 for (sal_uInt16 j = 0; j < nMemberCount; ++j)
1308 const String& rMemName = rMembers[j]->GetString();
1309 if (pDim->GetExistingMemberByName(rMemName))
1310 // this member instance already exists. nothing to do.
1311 continue;
1313 auto_ptr<ScDPSaveMember> pNewMember(new ScDPSaveMember(rMemName));
1314 pNewMember->SetIsVisible(true);
1315 pDim->AddMember(pNewMember.release());
1319 mbDimensionMembersBuilt = true;
1322 bool ScDPSaveData::HasInvisibleMember(const OUString& rDimName) const
1324 ScDPSaveDimension* pDim = GetExistingDimensionByName(rDimName);
1325 if (!pDim)
1326 return false;
1328 return pDim->HasInvisibleMember();