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 ---------------------------------------------------------------
39 #include "dpdimsave.hxx"
40 #include "miscuno.hxx"
41 #include "scerrors.hxx"
42 #include "unonames.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>
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
) :
109 nVisibleMode( SC_DPSAVEMODE_DONTKNOW
),
110 nShowDetailsMode( SC_DPSAVEMODE_DONTKNOW
)
114 ScDPSaveMember::ScDPSaveMember(const ScDPSaveMember
& r
) :
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
)
138 BOOL
ScDPSaveMember::HasIsVisible() const
140 return nVisibleMode
!= SC_DPSAVEMODE_DONTKNOW
;
143 void ScDPSaveMember::SetIsVisible(BOOL 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.
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
)
184 if ( nVisibleMode
== SC_DPSAVEMODE_DONTKNOW
&& nShowDetailsMode
== SC_DPSAVEMODE_DONTKNOW
&& nPosition
< 0 )
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())
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
) :
231 pSelectedPage( NULL
),
233 mpSubtotalName(NULL
),
234 bIsDataLayout( bDataLayout
),
236 nOrientation( sheet::DataPilotFieldOrientation_HIDDEN
),
237 nFunction( sheet::GeneralFunction_AUTO
),
238 nUsedHierarchy( -1 ),
239 nShowEmptyMode( SC_DPSAVEMODE_DONTKNOW
),
240 bSubTotalDefault( TRUE
),
242 pSubTotalFuncs( NULL
),
243 pReferenceValue( NULL
),
245 pAutoShowInfo( NULL
),
250 ScDPSaveDimension::ScDPSaveDimension(const ScDPSaveDimension
& r
) :
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
) );
281 pReferenceValue
= NULL
;
283 pSortInfo
= new sheet::DataPilotFieldSortInfo( *(r
.pSortInfo
) );
287 pAutoShowInfo
= new sheet::DataPilotFieldAutoShowInfo( *(r
.pAutoShowInfo
) );
289 pAutoShowInfo
= NULL
;
291 pLayoutInfo
= new sheet::DataPilotFieldLayoutInfo( *(r
.pLayoutInfo
) );
295 pSelectedPage
= new String( *(r
.pSelectedPage
) );
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
++)
308 delete pReferenceValue
;
310 delete pAutoShowInfo
;
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
)
329 if ( nSubTotalCount
&& ( !pSubTotalFuncs
|| !r
.pSubTotalFuncs
) ) // should not happen
333 for (i
=0; i
<nSubTotalCount
; i
++)
334 if ( pSubTotalFuncs
[i
] != r
.pSubTotalFuncs
[i
] )
337 if (maMemberHash
.size() != r
.maMemberHash
.size() )
340 MemberList::const_iterator a
=maMemberList
.begin();
341 MemberList::const_iterator b
=r
.maMemberList
.begin();
342 for (; a
!= maMemberList
.end() ; ++a
, ++b
)
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
);
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.
375 void ScDPSaveDimension::SetOrientation(USHORT nNew
)
380 void ScDPSaveDimension::SetSubTotals(long nCount
, const USHORT
* pFuncs
)
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
];
392 pSubTotalFuncs
= NULL
;
394 bSubTotalDefault
= FALSE
;
397 void ScDPSaveDimension::SetShowEmpty(BOOL bSet
)
399 nShowEmptyMode
= bSet
;
402 void ScDPSaveDimension::SetFunction(USHORT 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()))
431 const OUString
* pLayoutName
= pMem
->GetLayoutName();
432 if (pLayoutName
&& rName
.equalsIgnoreAsciiCase(*pLayoutName
))
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
;
457 pReferenceValue
= new sheet::DataPilotFieldReference(*pNew
);
459 pReferenceValue
= NULL
;
462 void ScDPSaveDimension::SetSortInfo(const sheet::DataPilotFieldSortInfo
* pNew
)
466 pSortInfo
= new sheet::DataPilotFieldSortInfo(*pNew
);
471 void ScDPSaveDimension::SetAutoShowInfo(const sheet::DataPilotFieldAutoShowInfo
* pNew
)
473 delete pAutoShowInfo
;
475 pAutoShowInfo
= new sheet::DataPilotFieldAutoShowInfo(*pNew
);
477 pAutoShowInfo
= NULL
;
480 void ScDPSaveDimension::SetLayoutInfo(const sheet::DataPilotFieldLayoutInfo
* pNew
)
484 pLayoutInfo
= new sheet::DataPilotFieldLayoutInfo(*pNew
);
489 void ScDPSaveDimension::SetCurrentPage( const String
* pPage
)
491 delete pSelectedPage
;
493 pSelectedPage
= new String( *pPage
);
495 pSelectedPage
= NULL
;
498 BOOL
ScDPSaveDimension::HasCurrentPage() const
500 return ( pSelectedPage
!= NULL
);
503 const String
& ScDPSaveDimension::GetCurrentPage() const
506 return *pSelectedPage
;
510 ScDPSaveMember
* ScDPSaveDimension::GetExistingMemberByName(const String
& rName
)
512 MemberHash::const_iterator res
= maMemberHash
.find (rName
);
513 if (res
!= maMemberHash
.end())
519 ScDPSaveMember
* ScDPSaveDimension::GetMemberByName(const String
& rName
)
521 MemberHash::const_iterator res
= maMemberHash
.find (rName
);
522 if (res
!= maMemberHash
.end())
525 ScDPSaveMember
* pNew
= new ScDPSaveMember( rName
);
526 maMemberHash
[rName
] = pNew
;
527 maMemberList
.push_back( 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
++)
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" );
549 // exceptions are caught at ScDPSaveData::WriteToSource
552 sheet::DataPilotFieldOrientation eOrient
= (sheet::DataPilotFieldOrientation
)nOrientation
;
554 xDimProp
->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_ORIENTATION
), aAny
);
556 sheet::GeneralFunction eFunc
= (sheet::GeneralFunction
)nFunction
;
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
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();
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();
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
) );
628 uno::Reference
<container::XIndexAccess
> xLevels
;
629 uno::Reference
<sheet::XLevelsSupplier
> xLevSupp( xHierarchy
, uno::UNO_QUERY
);
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" );
645 if ( !bSubTotalDefault
)
647 if ( !pSubTotalFuncs
)
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
];
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
);
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)
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)
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
703 uno::Reference
<sheet::XMembersSupplier
> xMembSupp( xLevel
, uno::UNO_QUERY
);
704 if ( xMembSupp
.is() )
706 uno::Reference
<container::XNameAccess
> xMembers
= xMembSupp
->getMembers();
709 sal_Int32 nPosition
= -1; // set position only in manual mode
710 if ( !pSortInfo
|| pSortInfo
->Mode
== sheet::DataPilotFieldSortMode::MANUAL
)
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
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())
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
),
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
);
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
)
816 delete pDimensionData
;
817 if ( r
.pDimensionData
)
818 pDimensionData
= new ScDPDimensionSaveData( *r
.pDimensionData
);
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();
834 for (i
=0; i
<nCount
; i
++)
835 delete (ScDPSaveDimension
*)aDimList
.GetObject(i
);
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
));
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
)
865 if ( pDimensionData
|| r
.pDimensionData
)
866 if ( !pDimensionData
|| !r
.pDimensionData
|| !( *pDimensionData
== *r
.pDimensionData
) )
869 ULONG nCount
= aDimList
.Count();
870 if ( nCount
!= r
.aDimList
.Count() )
873 for (ULONG i
=0; i
<nCount
; i
++)
874 if ( !( *(ScDPSaveDimension
*)aDimList
.GetObject(i
) ==
875 *(ScDPSaveDimension
*)r
.aDimList
.GetObject(i
) ) )
878 if (mpGrandTotalName
.get())
880 if (!r
.mpGrandTotalName
.get())
882 if (!mpGrandTotalName
->equals(*r
.mpGrandTotalName
))
885 else if (r
.mpGrandTotalName
.get())
891 ScDPSaveData::~ScDPSaveData()
893 long nCount
= aDimList
.Count();
894 for (long i
=0; i
<nCount
; i
++)
895 delete (ScDPSaveDimension
*)aDimList
.GetObject(i
);
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() )
920 ScDPSaveDimension
* pNew
= new ScDPSaveDimension( rName
, FALSE
);
921 aDimList
.Insert( pNew
, LIST_APPEND
);
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() )
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
);
951 ScDPSaveDimension
* ScDPSaveData::GetDataLayoutDimension()
953 ScDPSaveDimension
* pDim
= GetExistingDataLayoutDimension();
957 ScDPSaveDimension
* pNew
= new ScDPSaveDimension( String(), TRUE
);
958 aDimList
.Insert( pNew
, LIST_APPEND
);
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() )
974 ScDPSaveDimension
* ScDPSaveData::DuplicateDimension(const String
& rName
)
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
);
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() )
1001 ScDPSaveDimension
& ScDPSaveData::DuplicateDimension( const ScDPSaveDimension
& rDim
)
1003 ScDPSaveDimension
* pNew
= new ScDPSaveDimension( rDim
);
1004 pNew
->SetDupFlag( TRUE
);
1005 aDimList
.Insert( pNew
, LIST_APPEND
);
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() )
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())
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
)
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
1062 while ( nNew
> 0 && nInsPos
< nCount
)
1064 if ( ((ScDPSaveDimension
*)aDimList
.GetObject(nInsPos
))->GetOrientation() == nOrient
)
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
)
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
);
1117 xDimProp
->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_ORIENTATION
), aAny
);
1122 void ScDPSaveData::WriteToSource( const uno::Reference
<sheet::XDimensionsSupplier
>& xSource
)
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
)
1149 any
<<= *pGrandTotalName
;
1150 xSourceProp
->setPropertyValue(OUString::createFromAscii(SC_UNO_GRANDTOTAL_NAME
), any
);
1153 catch(uno::Exception
&)
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
) );
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??
1196 uno::Reference
<container::XNamed
> xDimName( xIntDim
, uno::UNO_QUERY
);
1197 if ( xDimName
.is() && xDimName
->getName() == aName
)
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
);
1219 xNewName
->setName( aNewName
);
1220 pDim
->WriteToSource( xNew
);
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() )
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
;
1270 pDimensionData
= new ScDPDimensionSaveData( *pNew
);
1272 pDimensionData
= NULL
;
1275 void ScDPSaveData::BuildAllDimensionMembers(ScDPTableData
* pData
)
1277 if (mbDimensionMembersBuilt
)
1280 // First, build a dimension name-to-index map.
1281 typedef hash_map
<OUString
, long, ::rtl::OUStringHash
> NameIndexMap
;
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.
1298 NameIndexMap::const_iterator itr
= aMap
.find(rDimName
);
1300 // dimension name not in the data. This should never happen!
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.
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
);
1328 return pDim
->HasInvisibleMember();