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 void lcl_SkipExtra( SvStream
& rStream
)
112 rStream
.SeekRel( nExtra
);
113 if ( rStream
.GetError() == SVSTREAM_OK
)
114 rStream
.SetError( SCWARN_IMPORT_INFOLOST
);
118 // -----------------------------------------------------------------------
120 ScDPSaveMember::ScDPSaveMember(const String
& rName
) :
123 nVisibleMode( SC_DPSAVEMODE_DONTKNOW
),
124 nShowDetailsMode( SC_DPSAVEMODE_DONTKNOW
)
128 ScDPSaveMember::ScDPSaveMember(const ScDPSaveMember
& r
) :
131 nVisibleMode( r
.nVisibleMode
),
132 nShowDetailsMode( r
.nShowDetailsMode
)
134 if (r
.mpLayoutName
.get())
135 mpLayoutName
.reset(new OUString(*r
.mpLayoutName
));
138 ScDPSaveMember::~ScDPSaveMember()
142 BOOL
ScDPSaveMember::operator== ( const ScDPSaveMember
& r
) const
144 if ( aName
!= r
.aName
||
145 nVisibleMode
!= r
.nVisibleMode
||
146 nShowDetailsMode
!= r
.nShowDetailsMode
)
152 BOOL
ScDPSaveMember::HasIsVisible() const
154 return nVisibleMode
!= SC_DPSAVEMODE_DONTKNOW
;
157 void ScDPSaveMember::SetIsVisible(BOOL bSet
)
162 BOOL
ScDPSaveMember::HasShowDetails() const
164 return nShowDetailsMode
!= SC_DPSAVEMODE_DONTKNOW
;
167 void ScDPSaveMember::SetShowDetails(BOOL bSet
)
169 nShowDetailsMode
= bSet
;
172 void ScDPSaveMember::SetName( const String
& rNew
)
174 // Used only if the source member was renamed (groups).
175 // For UI renaming of members, a layout name must be used.
180 void ScDPSaveMember::SetLayoutName( const OUString
& rName
)
182 mpLayoutName
.reset(new OUString(rName
));
185 const OUString
* ScDPSaveMember::GetLayoutName() const
187 return mpLayoutName
.get();
190 void ScDPSaveMember::RemoveLayoutName()
192 mpLayoutName
.reset(NULL
);
195 void ScDPSaveMember::WriteToSource( const uno::Reference
<uno::XInterface
>& xMember
, sal_Int32 nPosition
)
198 if ( nVisibleMode
== SC_DPSAVEMODE_DONTKNOW
&& nShowDetailsMode
== SC_DPSAVEMODE_DONTKNOW
&& nPosition
< 0 )
201 uno::Reference
<beans::XPropertySet
> xMembProp( xMember
, uno::UNO_QUERY
);
202 DBG_ASSERT( xMembProp
.is(), "no properties at member" );
203 if ( xMembProp
.is() )
205 // exceptions are caught at ScDPSaveData::WriteToSource
207 if ( nVisibleMode
!= SC_DPSAVEMODE_DONTKNOW
)
208 lcl_SetBoolProperty( xMembProp
,
209 rtl::OUString::createFromAscii(DP_PROP_ISVISIBLE
), (BOOL
)nVisibleMode
);
211 if ( nShowDetailsMode
!= SC_DPSAVEMODE_DONTKNOW
)
212 lcl_SetBoolProperty( xMembProp
,
213 rtl::OUString::createFromAscii(DP_PROP_SHOWDETAILS
), (BOOL
)nShowDetailsMode
);
215 if (mpLayoutName
.get())
220 any
<<= rtl::OUString(*mpLayoutName
);
221 xMembProp
->setPropertyValue(rtl::OUString::createFromAscii(SC_UNO_LAYOUTNAME
), any
);
223 catch (uno::Exception
&)
227 if ( nPosition
>= 0 )
231 xMembProp
->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_POSITION
), uno::Any(nPosition
) );
233 catch ( uno::Exception
& )
235 // position is optional - exception must be ignored
241 // -----------------------------------------------------------------------
243 ScDPSaveDimension::ScDPSaveDimension(const String
& rName
, BOOL bDataLayout
) :
245 pSelectedPage( NULL
),
247 mpSubtotalName(NULL
),
248 bIsDataLayout( bDataLayout
),
250 nOrientation( sheet::DataPilotFieldOrientation_HIDDEN
),
251 nFunction( sheet::GeneralFunction_AUTO
),
252 nUsedHierarchy( -1 ),
253 nShowEmptyMode( SC_DPSAVEMODE_DONTKNOW
),
254 bSubTotalDefault( TRUE
),
256 pSubTotalFuncs( NULL
),
257 pReferenceValue( NULL
),
259 pAutoShowInfo( NULL
),
264 ScDPSaveDimension::ScDPSaveDimension(const ScDPSaveDimension
& r
) :
267 mpSubtotalName(NULL
),
268 bIsDataLayout( r
.bIsDataLayout
),
269 bDupFlag( r
.bDupFlag
),
270 nOrientation( r
.nOrientation
),
271 nFunction( r
.nFunction
),
272 nUsedHierarchy( r
.nUsedHierarchy
),
273 nShowEmptyMode( r
.nShowEmptyMode
),
274 bSubTotalDefault( r
.bSubTotalDefault
),
275 nSubTotalCount( r
.nSubTotalCount
),
276 pSubTotalFuncs( NULL
)
278 if ( nSubTotalCount
&& r
.pSubTotalFuncs
)
280 pSubTotalFuncs
= new USHORT
[nSubTotalCount
];
281 for (long nSub
=0; nSub
<nSubTotalCount
; nSub
++)
282 pSubTotalFuncs
[nSub
] = r
.pSubTotalFuncs
[nSub
];
285 for (MemberList::const_iterator i
=r
.maMemberList
.begin(); i
!= r
.maMemberList
.end() ; i
++)
287 const String
& rName
= (*i
)->GetName();
288 ScDPSaveMember
* pNew
= new ScDPSaveMember( **i
);
289 maMemberHash
[rName
] = pNew
;
290 maMemberList
.push_back( pNew
);
292 if (r
.pReferenceValue
)
293 pReferenceValue
= new sheet::DataPilotFieldReference( *(r
.pReferenceValue
) );
295 pReferenceValue
= NULL
;
297 pSortInfo
= new sheet::DataPilotFieldSortInfo( *(r
.pSortInfo
) );
301 pAutoShowInfo
= new sheet::DataPilotFieldAutoShowInfo( *(r
.pAutoShowInfo
) );
303 pAutoShowInfo
= NULL
;
305 pLayoutInfo
= new sheet::DataPilotFieldLayoutInfo( *(r
.pLayoutInfo
) );
309 pSelectedPage
= new String( *(r
.pSelectedPage
) );
311 pSelectedPage
= NULL
;
312 if (r
.mpLayoutName
.get())
313 mpLayoutName
.reset(new OUString(*r
.mpLayoutName
));
314 if (r
.mpSubtotalName
.get())
315 mpSubtotalName
.reset(new OUString(*r
.mpSubtotalName
));
318 ScDPSaveDimension::~ScDPSaveDimension()
320 for (MemberHash::const_iterator i
=maMemberHash
.begin(); i
!= maMemberHash
.end() ; i
++)
322 delete pReferenceValue
;
324 delete pAutoShowInfo
;
326 delete pSelectedPage
;
327 delete [] pSubTotalFuncs
;
330 BOOL
ScDPSaveDimension::operator== ( const ScDPSaveDimension
& r
) const
332 if ( aName
!= r
.aName
||
333 bIsDataLayout
!= r
.bIsDataLayout
||
334 bDupFlag
!= r
.bDupFlag
||
335 nOrientation
!= r
.nOrientation
||
336 nFunction
!= r
.nFunction
||
337 nUsedHierarchy
!= r
.nUsedHierarchy
||
338 nShowEmptyMode
!= r
.nShowEmptyMode
||
339 bSubTotalDefault
!= r
.bSubTotalDefault
||
340 nSubTotalCount
!= r
.nSubTotalCount
)
343 if ( nSubTotalCount
&& ( !pSubTotalFuncs
|| !r
.pSubTotalFuncs
) ) // should not happen
347 for (i
=0; i
<nSubTotalCount
; i
++)
348 if ( pSubTotalFuncs
[i
] != r
.pSubTotalFuncs
[i
] )
351 if (maMemberHash
.size() != r
.maMemberHash
.size() )
354 MemberList::const_iterator a
=maMemberList
.begin();
355 MemberList::const_iterator b
=r
.maMemberList
.begin();
356 for (; a
!= maMemberList
.end() ; ++a
, ++b
)
363 void ScDPSaveDimension::AddMember(ScDPSaveMember
* pMember
)
365 const String
& rName
= pMember
->GetName();
366 MemberHash::iterator aExisting
= maMemberHash
.find( rName
);
367 if ( aExisting
== maMemberHash
.end() )
369 std::pair
< const String
, ScDPSaveMember
*> key( rName
, pMember
);
370 maMemberHash
.insert ( key
);
374 maMemberList
.remove( aExisting
->second
);
375 delete aExisting
->second
;
376 aExisting
->second
= pMember
;
378 maMemberList
.push_back( pMember
);
381 void ScDPSaveDimension::SetName( const String
& rNew
)
383 // Used only if the source dim was renamed (groups).
384 // For UI renaming of dimensions, the layout name must be used.
389 void ScDPSaveDimension::SetOrientation(USHORT nNew
)
394 void ScDPSaveDimension::SetSubTotals(BOOL bSet
)
398 USHORT nFunc
= sheet::GeneralFunction_AUTO
;
399 SetSubTotals( 1, &nFunc
);
402 SetSubTotals( 0, NULL
);
405 void ScDPSaveDimension::SetSubTotals(long nCount
, const USHORT
* pFuncs
)
408 delete [] pSubTotalFuncs
;
409 nSubTotalCount
= nCount
;
410 if ( nCount
&& pFuncs
)
412 pSubTotalFuncs
= new USHORT
[nCount
];
413 for (long i
=0; i
<nCount
; i
++)
414 pSubTotalFuncs
[i
] = pFuncs
[i
];
417 pSubTotalFuncs
= NULL
;
419 bSubTotalDefault
= FALSE
;
422 void ScDPSaveDimension::SetShowEmpty(BOOL bSet
)
424 nShowEmptyMode
= bSet
;
427 void ScDPSaveDimension::SetFunction(USHORT nNew
)
432 void ScDPSaveDimension::SetUsedHierarchy(long nNew
)
434 nUsedHierarchy
= nNew
;
437 void ScDPSaveDimension::SetSubtotalName(const OUString
& rName
)
439 mpSubtotalName
.reset(new OUString(rName
));
442 const OUString
* ScDPSaveDimension::GetSubtotalName() const
444 return mpSubtotalName
.get();
447 bool ScDPSaveDimension::IsMemberNameInUse(const OUString
& rName
) const
449 MemberList::const_iterator itr
= maMemberList
.begin(), itrEnd
= maMemberList
.end();
450 for (; itr
!= itrEnd
; ++itr
)
452 const ScDPSaveMember
* pMem
= *itr
;
453 if (rName
.equalsIgnoreAsciiCase(pMem
->GetName()))
456 const OUString
* pLayoutName
= pMem
->GetLayoutName();
457 if (pLayoutName
&& rName
.equalsIgnoreAsciiCase(*pLayoutName
))
463 void ScDPSaveDimension::SetLayoutName(const OUString
& rName
)
465 mpLayoutName
.reset(new OUString(rName
));
468 const OUString
* ScDPSaveDimension::GetLayoutName() const
470 return mpLayoutName
.get();
473 void ScDPSaveDimension::RemoveLayoutName()
475 mpLayoutName
.reset(NULL
);
478 void ScDPSaveDimension::SetReferenceValue(const sheet::DataPilotFieldReference
* pNew
)
480 delete pReferenceValue
;
482 pReferenceValue
= new sheet::DataPilotFieldReference(*pNew
);
484 pReferenceValue
= NULL
;
487 void ScDPSaveDimension::SetSortInfo(const sheet::DataPilotFieldSortInfo
* pNew
)
491 pSortInfo
= new sheet::DataPilotFieldSortInfo(*pNew
);
496 void ScDPSaveDimension::SetAutoShowInfo(const sheet::DataPilotFieldAutoShowInfo
* pNew
)
498 delete pAutoShowInfo
;
500 pAutoShowInfo
= new sheet::DataPilotFieldAutoShowInfo(*pNew
);
502 pAutoShowInfo
= NULL
;
505 void ScDPSaveDimension::SetLayoutInfo(const sheet::DataPilotFieldLayoutInfo
* pNew
)
509 pLayoutInfo
= new sheet::DataPilotFieldLayoutInfo(*pNew
);
514 void ScDPSaveDimension::SetCurrentPage( const String
* pPage
)
516 delete pSelectedPage
;
518 pSelectedPage
= new String( *pPage
);
520 pSelectedPage
= NULL
;
523 BOOL
ScDPSaveDimension::HasCurrentPage() const
525 return ( pSelectedPage
!= NULL
);
528 const String
& ScDPSaveDimension::GetCurrentPage() const
531 return *pSelectedPage
;
535 ScDPSaveMember
* ScDPSaveDimension::GetExistingMemberByName(const String
& rName
)
537 MemberHash::const_iterator res
= maMemberHash
.find (rName
);
538 if (res
!= maMemberHash
.end())
544 ScDPSaveMember
* ScDPSaveDimension::GetMemberByName(const String
& rName
)
546 MemberHash::const_iterator res
= maMemberHash
.find (rName
);
547 if (res
!= maMemberHash
.end())
550 ScDPSaveMember
* pNew
= new ScDPSaveMember( rName
);
551 maMemberHash
[rName
] = pNew
;
552 maMemberList
.push_back( pNew
);
556 void ScDPSaveDimension::SetMemberPosition( const String
& rName
, sal_Int32 nNewPos
)
558 ScDPSaveMember
* pMember
= GetMemberByName( rName
); // make sure it exists and is in the hash
560 maMemberList
.remove( pMember
);
562 MemberList::iterator aIter
= maMemberList
.begin();
563 for (sal_Int32 i
=0; i
<nNewPos
&& aIter
!= maMemberList
.end(); i
++)
565 maMemberList
.insert( aIter
, pMember
);
568 void ScDPSaveDimension::WriteToSource( const uno::Reference
<uno::XInterface
>& xDim
)
570 uno::Reference
<beans::XPropertySet
> xDimProp( xDim
, uno::UNO_QUERY
);
571 DBG_ASSERT( xDimProp
.is(), "no properties at dimension" );
574 // exceptions are caught at ScDPSaveData::WriteToSource
577 sheet::DataPilotFieldOrientation eOrient
= (sheet::DataPilotFieldOrientation
)nOrientation
;
579 xDimProp
->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_ORIENTATION
), aAny
);
581 sheet::GeneralFunction eFunc
= (sheet::GeneralFunction
)nFunction
;
583 xDimProp
->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_FUNCTION
), aAny
);
585 if ( nUsedHierarchy
>= 0 )
587 aAny
<<= (INT32
)nUsedHierarchy
;
588 xDimProp
->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_USEDHIERARCHY
), aAny
);
591 if ( pReferenceValue
)
593 aAny
<<= *pReferenceValue
;
594 xDimProp
->setPropertyValue( rtl::OUString::createFromAscii(SC_UNO_REFVALUE
), aAny
);
597 uno::Sequence
<sheet::TableFilterField
> aFilter
;
598 // set the selected page field only if the dimension is used as page dimension
599 if ( pSelectedPage
&& nOrientation
== sheet::DataPilotFieldOrientation_PAGE
)
601 // single filter field: first field equal to selected string
602 sheet::TableFilterField
aField( sheet::FilterConnection_AND
, 0,
603 sheet::FilterOperator_EQUAL
, sal_False
, 0.0, *pSelectedPage
);
604 aFilter
= uno::Sequence
<sheet::TableFilterField
>( &aField
, 1 );
606 // else keep empty sequence
610 xDimProp
->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_FILTER
), aAny
);
611 if (mpLayoutName
.get())
613 aAny
<<= *mpLayoutName
;
614 xDimProp
->setPropertyValue(rtl::OUString::createFromAscii(SC_UNO_LAYOUTNAME
), aAny
);
617 const OUString
* pSubTotalName
= GetSubtotalName();
620 // Custom subtotal name, with '?' being replaced by the visible field name later.
621 aAny
<<= *pSubTotalName
;
622 xDimProp
->setPropertyValue(OUString::createFromAscii(SC_UNO_FIELD_SUBTOTALNAME
), aAny
);
625 catch ( beans::UnknownPropertyException
& )
627 // recent addition - allow source to not handle it (no error)
631 // Level loop outside of maMemberList loop
632 // because SubTotals have to be set independently of known members
634 long nCount
= maMemberHash
.size();
637 uno::Reference
<container::XIndexAccess
> xHiers
;
638 uno::Reference
<sheet::XHierarchiesSupplier
> xHierSupp( xDim
, uno::UNO_QUERY
);
639 if ( xHierSupp
.is() )
641 uno::Reference
<container::XNameAccess
> xHiersName
= xHierSupp
->getHierarchies();
642 xHiers
= new ScNameToIndexAccess( xHiersName
);
643 nHierCount
= xHiers
->getCount();
646 sal_Bool bHasHiddenMember
= false;
648 for (long nHier
=0; nHier
<nHierCount
; nHier
++)
650 uno::Reference
<uno::XInterface
> xHierarchy
= ScUnoHelpFunctions::AnyToInterface( xHiers
->getByIndex(nHier
) );
653 uno::Reference
<container::XIndexAccess
> xLevels
;
654 uno::Reference
<sheet::XLevelsSupplier
> xLevSupp( xHierarchy
, uno::UNO_QUERY
);
657 uno::Reference
<container::XNameAccess
> xLevelsName
= xLevSupp
->getLevels();
658 xLevels
= new ScNameToIndexAccess( xLevelsName
);
659 nLevCount
= xLevels
->getCount();
662 for (long nLev
=0; nLev
<nLevCount
; nLev
++)
664 uno::Reference
<uno::XInterface
> xLevel
= ScUnoHelpFunctions::AnyToInterface( xLevels
->getByIndex(nLev
) );
665 uno::Reference
<beans::XPropertySet
> xLevProp( xLevel
, uno::UNO_QUERY
);
666 DBG_ASSERT( xLevProp
.is(), "no properties at level" );
670 if ( !bSubTotalDefault
)
672 if ( !pSubTotalFuncs
)
675 uno::Sequence
<sheet::GeneralFunction
> aSeq(nSubTotalCount
);
676 sheet::GeneralFunction
* pArray
= aSeq
.getArray();
677 for (long i
=0; i
<nSubTotalCount
; i
++)
678 pArray
[i
] = (sheet::GeneralFunction
)pSubTotalFuncs
[i
];
680 xLevProp
->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_SUBTOTALS
), aAny
);
682 if ( nShowEmptyMode
!= SC_DPSAVEMODE_DONTKNOW
)
683 lcl_SetBoolProperty( xLevProp
,
684 rtl::OUString::createFromAscii(DP_PROP_SHOWEMPTY
), (BOOL
)nShowEmptyMode
);
691 xLevProp
->setPropertyValue( rtl::OUString::createFromAscii(SC_UNO_SORTING
), aAny
);
693 catch ( beans::UnknownPropertyException
& )
695 // recent addition - allow source to not handle it (no error)
700 aAny
<<= *pAutoShowInfo
;
703 xLevProp
->setPropertyValue( rtl::OUString::createFromAscii(SC_UNO_AUTOSHOW
), aAny
);
705 catch ( beans::UnknownPropertyException
& )
707 // recent addition - allow source to not handle it (no error)
712 aAny
<<= *pLayoutInfo
;
715 xLevProp
->setPropertyValue( rtl::OUString::createFromAscii(SC_UNO_LAYOUT
), aAny
);
717 catch ( beans::UnknownPropertyException
& )
719 // recent addition - allow source to not handle it (no error)
723 // exceptions are caught at ScDPSaveData::WriteToSource
728 uno::Reference
<sheet::XMembersSupplier
> xMembSupp( xLevel
, uno::UNO_QUERY
);
729 if ( xMembSupp
.is() )
731 uno::Reference
<container::XNameAccess
> xMembers
= xMembSupp
->getMembers();
734 sal_Int32 nPosition
= -1; // set position only in manual mode
735 if ( !pSortInfo
|| pSortInfo
->Mode
== sheet::DataPilotFieldSortMode::MANUAL
)
738 for (MemberList::const_iterator i
=maMemberList
.begin(); i
!= maMemberList
.end() ; i
++)
740 ScDPSaveMember
* pMember
= *i
;
741 if (!pMember
->GetIsVisible())
742 bHasHiddenMember
= true;
743 rtl::OUString aMemberName
= pMember
->GetName();
744 if ( xMembers
->hasByName( aMemberName
) )
746 uno::Reference
<uno::XInterface
> xMemberInt
= ScUnoHelpFunctions::AnyToInterface(
747 xMembers
->getByName( aMemberName
) );
748 pMember
->WriteToSource( xMemberInt
, nPosition
);
750 if ( nPosition
>= 0 )
751 ++nPosition
; // increase if initialized
753 // missing member is no error
764 any
<<= bHasHiddenMember
;
765 xDimProp
->setPropertyValue(
766 OUString::createFromAscii(SC_UNO_HAS_HIDDEN_MEMBER
), any
);
770 void ScDPSaveDimension::UpdateMemberVisibility(const hash_map
<OUString
, bool, OUStringHash
>& rData
)
772 typedef hash_map
<OUString
, bool, OUStringHash
> DataMap
;
773 MemberList::iterator itrMem
= maMemberList
.begin(), itrMemEnd
= maMemberList
.end();
774 for (; itrMem
!= itrMemEnd
; ++itrMem
)
776 ScDPSaveMember
* pMem
= *itrMem
;
777 const String
& rMemName
= pMem
->GetName();
778 DataMap::const_iterator itr
= rData
.find(rMemName
);
779 if (itr
!= rData
.end())
780 pMem
->SetIsVisible(itr
->second
);
784 bool ScDPSaveDimension::HasInvisibleMember() const
786 MemberList::const_iterator itrMem
= maMemberList
.begin(), itrMemEnd
= maMemberList
.end();
787 for (; itrMem
!= itrMemEnd
; ++itrMem
)
789 const ScDPSaveMember
* pMem
= *itrMem
;
790 if (!pMem
->GetIsVisible())
796 // -----------------------------------------------------------------------
798 ScDPSaveData::ScDPSaveData() :
799 pDimensionData( NULL
),
800 nColumnGrandMode( SC_DPSAVEMODE_DONTKNOW
),
801 nRowGrandMode( SC_DPSAVEMODE_DONTKNOW
),
802 nIgnoreEmptyMode( SC_DPSAVEMODE_DONTKNOW
),
803 nRepeatEmptyMode( SC_DPSAVEMODE_DONTKNOW
),
804 bFilterButton( TRUE
),
806 mbDimensionMembersBuilt(false),
807 mpGrandTotalName(NULL
)
811 ScDPSaveData::ScDPSaveData(const ScDPSaveData
& r
) :
812 nColumnGrandMode( r
.nColumnGrandMode
),
813 nRowGrandMode( r
.nRowGrandMode
),
814 nIgnoreEmptyMode( r
.nIgnoreEmptyMode
),
815 nRepeatEmptyMode( r
.nRepeatEmptyMode
),
816 bFilterButton( r
.bFilterButton
),
817 bDrillDown( r
.bDrillDown
),
818 mbDimensionMembersBuilt(r
.mbDimensionMembersBuilt
),
819 mpGrandTotalName(NULL
)
821 if ( r
.pDimensionData
)
822 pDimensionData
= new ScDPDimensionSaveData( *r
.pDimensionData
);
824 pDimensionData
= NULL
;
826 long nCount
= r
.aDimList
.Count();
827 for (long i
=0; i
<nCount
; i
++)
829 ScDPSaveDimension
* pNew
= new ScDPSaveDimension( *(ScDPSaveDimension
*)r
.aDimList
.GetObject(i
) );
830 aDimList
.Insert( pNew
, LIST_APPEND
);
833 if (r
.mpGrandTotalName
.get())
834 mpGrandTotalName
.reset(new OUString(*r
.mpGrandTotalName
));
837 ScDPSaveData
& ScDPSaveData::operator= ( const ScDPSaveData
& r
)
841 delete pDimensionData
;
842 if ( r
.pDimensionData
)
843 pDimensionData
= new ScDPDimensionSaveData( *r
.pDimensionData
);
845 pDimensionData
= NULL
;
847 nColumnGrandMode
= r
.nColumnGrandMode
;
848 nRowGrandMode
= r
.nRowGrandMode
;
849 nIgnoreEmptyMode
= r
.nIgnoreEmptyMode
;
850 nRepeatEmptyMode
= r
.nRepeatEmptyMode
;
851 bFilterButton
= r
.bFilterButton
;
852 bDrillDown
= r
.bDrillDown
;
853 mbDimensionMembersBuilt
= r
.mbDimensionMembersBuilt
;
855 // remove old dimensions
857 long nCount
= aDimList
.Count();
859 for (i
=0; i
<nCount
; i
++)
860 delete (ScDPSaveDimension
*)aDimList
.GetObject(i
);
863 // copy new dimensions
865 nCount
= r
.aDimList
.Count();
866 for (i
=0; i
<nCount
; i
++)
868 ScDPSaveDimension
* pNew
=
869 new ScDPSaveDimension( *(ScDPSaveDimension
*)r
.aDimList
.GetObject(i
) );
870 aDimList
.Insert( pNew
, LIST_APPEND
);
873 if (r
.mpGrandTotalName
.get())
874 mpGrandTotalName
.reset(new OUString(*r
.mpGrandTotalName
));
879 BOOL
ScDPSaveData::operator== ( const ScDPSaveData
& r
) const
881 if ( nColumnGrandMode
!= r
.nColumnGrandMode
||
882 nRowGrandMode
!= r
.nRowGrandMode
||
883 nIgnoreEmptyMode
!= r
.nIgnoreEmptyMode
||
884 nRepeatEmptyMode
!= r
.nRepeatEmptyMode
||
885 bFilterButton
!= r
.bFilterButton
||
886 bDrillDown
!= r
.bDrillDown
||
887 mbDimensionMembersBuilt
!= r
.mbDimensionMembersBuilt
)
890 if ( pDimensionData
|| r
.pDimensionData
)
891 if ( !pDimensionData
|| !r
.pDimensionData
|| !( *pDimensionData
== *r
.pDimensionData
) )
894 ULONG nCount
= aDimList
.Count();
895 if ( nCount
!= r
.aDimList
.Count() )
898 for (ULONG i
=0; i
<nCount
; i
++)
899 if ( !( *(ScDPSaveDimension
*)aDimList
.GetObject(i
) ==
900 *(ScDPSaveDimension
*)r
.aDimList
.GetObject(i
) ) )
903 if (mpGrandTotalName
.get())
905 if (!r
.mpGrandTotalName
.get())
907 if (!mpGrandTotalName
->equals(*r
.mpGrandTotalName
))
910 else if (r
.mpGrandTotalName
.get())
916 ScDPSaveData::~ScDPSaveData()
918 long nCount
= aDimList
.Count();
919 for (long i
=0; i
<nCount
; i
++)
920 delete (ScDPSaveDimension
*)aDimList
.GetObject(i
);
923 delete pDimensionData
;
926 void ScDPSaveData::SetGrandTotalName(const OUString
& rName
)
928 mpGrandTotalName
.reset(new OUString(rName
));
931 const OUString
* ScDPSaveData::GetGrandTotalName() const
933 return mpGrandTotalName
.get();
936 ScDPSaveDimension
* ScDPSaveData::GetDimensionByName(const String
& rName
)
938 long nCount
= aDimList
.Count();
939 for (long i
=0; i
<nCount
; i
++)
941 ScDPSaveDimension
* pDim
= (ScDPSaveDimension
*)aDimList
.GetObject(i
);
942 if ( pDim
->GetName() == rName
&& !pDim
->IsDataLayout() )
945 ScDPSaveDimension
* pNew
= new ScDPSaveDimension( rName
, FALSE
);
946 aDimList
.Insert( pNew
, LIST_APPEND
);
950 ScDPSaveDimension
* ScDPSaveData::GetExistingDimensionByName(const String
& rName
) const
952 long nCount
= aDimList
.Count();
953 for (long i
=0; i
<nCount
; i
++)
955 ScDPSaveDimension
* pDim
= (ScDPSaveDimension
*)aDimList
.GetObject(i
);
956 if ( pDim
->GetName() == rName
&& !pDim
->IsDataLayout() )
959 return NULL
; // don't create new
962 ScDPSaveDimension
* ScDPSaveData::GetNewDimensionByName(const String
& rName
)
964 long nCount
= aDimList
.Count();
965 for (long i
=0; i
<nCount
; i
++)
967 ScDPSaveDimension
* pDim
= (ScDPSaveDimension
*)aDimList
.GetObject(i
);
968 if ( pDim
->GetName() == rName
&& !pDim
->IsDataLayout() )
969 return DuplicateDimension(rName
);
971 ScDPSaveDimension
* pNew
= new ScDPSaveDimension( rName
, FALSE
);
972 aDimList
.Insert( pNew
, LIST_APPEND
);
976 ScDPSaveDimension
* ScDPSaveData::GetDataLayoutDimension()
978 ScDPSaveDimension
* pDim
= GetExistingDataLayoutDimension();
982 ScDPSaveDimension
* pNew
= new ScDPSaveDimension( String(), TRUE
);
983 aDimList
.Insert( pNew
, LIST_APPEND
);
987 ScDPSaveDimension
* ScDPSaveData::GetExistingDataLayoutDimension() const
989 long nCount
= aDimList
.Count();
990 for (long i
=0; i
<nCount
; i
++)
992 ScDPSaveDimension
* pDim
= (ScDPSaveDimension
*)aDimList
.GetObject(i
);
993 if ( pDim
->IsDataLayout() )
999 ScDPSaveDimension
* ScDPSaveData::DuplicateDimension(const String
& rName
)
1001 // always insert new
1002 //! check if dimension is there?
1004 ScDPSaveDimension
* pOld
= GetDimensionByName( rName
);
1005 ScDPSaveDimension
* pNew
= new ScDPSaveDimension( *pOld
);
1006 pNew
->SetDupFlag( TRUE
);
1007 aDimList
.Insert( pNew
, LIST_APPEND
);
1011 void ScDPSaveData::RemoveDimensionByName(const String
& rName
)
1013 long nCount
= aDimList
.Count();
1014 for (long i
=0; i
<nCount
; i
++)
1016 ScDPSaveDimension
* pDim
= (ScDPSaveDimension
*)aDimList
.GetObject(i
);
1017 if ( pDim
->GetName() == rName
&& !pDim
->IsDataLayout() )
1026 ScDPSaveDimension
& ScDPSaveData::DuplicateDimension( const ScDPSaveDimension
& rDim
)
1028 ScDPSaveDimension
* pNew
= new ScDPSaveDimension( rDim
);
1029 pNew
->SetDupFlag( TRUE
);
1030 aDimList
.Insert( pNew
, LIST_APPEND
);
1034 ScDPSaveDimension
* ScDPSaveData::GetInnermostDimension(USHORT nOrientation
)
1036 // return the innermost dimension for the given orientation,
1037 // excluding data layout dimension
1039 ScDPSaveDimension
* pInner
= NULL
;
1040 long nCount
= aDimList
.Count();
1041 for (long i
=0; i
<nCount
; i
++)
1043 ScDPSaveDimension
* pDim
= static_cast<ScDPSaveDimension
*>(aDimList
.GetObject(i
));
1044 if ( pDim
->GetOrientation() == nOrientation
&& !pDim
->IsDataLayout() )
1047 return pInner
; // the last matching one
1050 ScDPSaveDimension
* ScDPSaveData::GetFirstDimension(sheet::DataPilotFieldOrientation eOrientation
)
1052 long nCount
= aDimList
.Count();
1053 for (long i
= 0; i
< nCount
; ++i
)
1055 ScDPSaveDimension
* pDim
= static_cast<ScDPSaveDimension
*>(aDimList
.GetObject(i
));
1056 if (pDim
->GetOrientation() == eOrientation
&& !pDim
->IsDataLayout())
1062 long ScDPSaveData::GetDataDimensionCount() const
1064 long nDataCount
= 0;
1066 long nCount
= aDimList
.Count();
1067 for (long i
=0; i
<nCount
; i
++)
1069 const ScDPSaveDimension
* pDim
= static_cast<const ScDPSaveDimension
*>(aDimList
.GetObject(i
));
1070 if ( pDim
->GetOrientation() == sheet::DataPilotFieldOrientation_DATA
)
1077 void ScDPSaveData::SetPosition( ScDPSaveDimension
* pDim
, long nNew
)
1079 // position (nNew) is counted within dimensions of the same orientation
1081 USHORT nOrient
= pDim
->GetOrientation();
1083 aDimList
.Remove( pDim
);
1084 ULONG nCount
= aDimList
.Count(); // after remove
1087 while ( nNew
> 0 && nInsPos
< nCount
)
1089 if ( ((ScDPSaveDimension
*)aDimList
.GetObject(nInsPos
))->GetOrientation() == nOrient
)
1094 aDimList
.Insert( pDim
, nInsPos
);
1097 void ScDPSaveData::SetColumnGrand(BOOL bSet
)
1099 nColumnGrandMode
= bSet
;
1102 void ScDPSaveData::SetRowGrand(BOOL bSet
)
1104 nRowGrandMode
= bSet
;
1107 void ScDPSaveData::SetIgnoreEmptyRows(BOOL bSet
)
1109 nIgnoreEmptyMode
= bSet
;
1112 void ScDPSaveData::SetRepeatIfEmpty(BOOL bSet
)
1114 nRepeatEmptyMode
= bSet
;
1117 void ScDPSaveData::SetFilterButton(BOOL bSet
)
1119 bFilterButton
= bSet
;
1122 void ScDPSaveData::SetDrillDown(BOOL bSet
)
1127 void lcl_ResetOrient( const uno::Reference
<sheet::XDimensionsSupplier
>& xSource
)
1129 sheet::DataPilotFieldOrientation eOrient
= sheet::DataPilotFieldOrientation_HIDDEN
;
1131 uno::Reference
<container::XNameAccess
> xDimsName
= xSource
->getDimensions();
1132 uno::Reference
<container::XIndexAccess
> xIntDims
= new ScNameToIndexAccess( xDimsName
);
1133 long nIntCount
= xIntDims
->getCount();
1134 for (long nIntDim
=0; nIntDim
<nIntCount
; nIntDim
++)
1136 uno::Reference
<uno::XInterface
> xIntDim
= ScUnoHelpFunctions::AnyToInterface( xIntDims
->getByIndex(nIntDim
) );
1137 uno::Reference
<beans::XPropertySet
> xDimProp( xIntDim
, uno::UNO_QUERY
);
1142 xDimProp
->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_ORIENTATION
), aAny
);
1147 void ScDPSaveData::WriteToSource( const uno::Reference
<sheet::XDimensionsSupplier
>& xSource
)
1152 // source options must be first!
1154 uno::Reference
<beans::XPropertySet
> xSourceProp( xSource
, uno::UNO_QUERY
);
1155 DBG_ASSERT( xSourceProp
.is(), "no properties at source" );
1156 if ( xSourceProp
.is() )
1158 // source options are not available for external sources
1159 //! use XPropertySetInfo to test for availability?
1163 if ( nIgnoreEmptyMode
!= SC_DPSAVEMODE_DONTKNOW
)
1164 lcl_SetBoolProperty( xSourceProp
,
1165 rtl::OUString::createFromAscii(DP_PROP_IGNOREEMPTY
), (BOOL
)nIgnoreEmptyMode
);
1166 if ( nRepeatEmptyMode
!= SC_DPSAVEMODE_DONTKNOW
)
1167 lcl_SetBoolProperty( xSourceProp
,
1168 rtl::OUString::createFromAscii(DP_PROP_REPEATIFEMPTY
), (BOOL
)nRepeatEmptyMode
);
1170 const OUString
* pGrandTotalName
= GetGrandTotalName();
1171 if (pGrandTotalName
)
1174 any
<<= *pGrandTotalName
;
1175 xSourceProp
->setPropertyValue(OUString::createFromAscii(SC_UNO_GRANDTOTAL_NAME
), any
);
1178 catch(uno::Exception
&)
1184 // exceptions in the other calls are errors
1187 // reset all orientations
1188 //! "forgetSettings" or similar at source ?????
1189 //! reset all duplicated dimensions, or reuse them below !!!
1191 lcl_ResetOrient( xSource
);
1193 long nCount
= aDimList
.Count();
1194 for (long i
=0; i
<nCount
; i
++)
1196 ScDPSaveDimension
* pDim
= (ScDPSaveDimension
*)aDimList
.GetObject(i
);
1197 rtl::OUString aName
= pDim
->GetName();
1198 BOOL bData
= pDim
->IsDataLayout();
1200 //! getByName for ScDPSource, including DataLayoutDimension !!!!!!!!
1202 uno::Reference
<container::XNameAccess
> xDimsName
= xSource
->getDimensions();
1203 uno::Reference
<container::XIndexAccess
> xIntDims
= new ScNameToIndexAccess( xDimsName
);
1204 long nIntCount
= xIntDims
->getCount();
1205 BOOL bFound
= FALSE
;
1206 for (long nIntDim
=0; nIntDim
<nIntCount
&& !bFound
; nIntDim
++)
1208 uno::Reference
<uno::XInterface
> xIntDim
= ScUnoHelpFunctions::AnyToInterface( xIntDims
->getByIndex(nIntDim
) );
1211 uno::Reference
<beans::XPropertySet
> xDimProp( xIntDim
, uno::UNO_QUERY
);
1212 if ( xDimProp
.is() )
1214 bFound
= ScUnoHelpFunctions::GetBoolProperty( xDimProp
,
1215 rtl::OUString::createFromAscii(DP_PROP_ISDATALAYOUT
) );
1216 //! error checking -- is "IsDataLayoutDimension" property required??
1221 uno::Reference
<container::XNamed
> xDimName( xIntDim
, uno::UNO_QUERY
);
1222 if ( xDimName
.is() && xDimName
->getName() == aName
)
1228 if ( pDim
->GetDupFlag() )
1230 String aNewName
= pDim
->GetName();
1232 // different name for each duplication of a (real) dimension...
1233 for (long j
=0; j
<=i
; j
++) //! Test !!!!!!
1234 aNewName
+= '*'; //! modify name at creation of SaveDimension
1236 uno::Reference
<util::XCloneable
> xCloneable( xIntDim
, uno::UNO_QUERY
);
1237 DBG_ASSERT( xCloneable
.is(), "cannot clone dimension" );
1238 if (xCloneable
.is())
1240 uno::Reference
<util::XCloneable
> xNew
= xCloneable
->createClone();
1241 uno::Reference
<container::XNamed
> xNewName( xNew
, uno::UNO_QUERY
);
1244 xNewName
->setName( aNewName
);
1245 pDim
->WriteToSource( xNew
);
1250 pDim
->WriteToSource( xIntDim
);
1253 DBG_ASSERT(bFound
, "WriteToSource: Dimension not found");
1256 if ( xSourceProp
.is() )
1258 if ( nColumnGrandMode
!= SC_DPSAVEMODE_DONTKNOW
)
1259 lcl_SetBoolProperty( xSourceProp
,
1260 rtl::OUString::createFromAscii(DP_PROP_COLUMNGRAND
), (BOOL
)nColumnGrandMode
);
1261 if ( nRowGrandMode
!= SC_DPSAVEMODE_DONTKNOW
)
1262 lcl_SetBoolProperty( xSourceProp
,
1263 rtl::OUString::createFromAscii(DP_PROP_ROWGRAND
), (BOOL
)nRowGrandMode
);
1266 catch(uno::Exception
&)
1268 DBG_ERROR("exception in WriteToSource");
1272 BOOL
ScDPSaveData::IsEmpty() const
1274 long nCount
= aDimList
.Count();
1275 for (long i
=0; i
<nCount
; i
++)
1277 ScDPSaveDimension
* pDim
= (ScDPSaveDimension
*)aDimList
.GetObject(i
);
1278 if ( pDim
->GetOrientation() != sheet::DataPilotFieldOrientation_HIDDEN
&& !pDim
->IsDataLayout() )
1281 return TRUE
; // no entries that are not hidden
1284 ScDPDimensionSaveData
* ScDPSaveData::GetDimensionData()
1286 if (!pDimensionData
)
1287 pDimensionData
= new ScDPDimensionSaveData
;
1288 return pDimensionData
;
1291 void ScDPSaveData::SetDimensionData( const ScDPDimensionSaveData
* pNew
)
1293 delete pDimensionData
;
1295 pDimensionData
= new ScDPDimensionSaveData( *pNew
);
1297 pDimensionData
= NULL
;
1300 void ScDPSaveData::BuildAllDimensionMembers(ScDPTableData
* pData
)
1302 if (mbDimensionMembersBuilt
)
1305 // First, build a dimension name-to-index map.
1306 typedef hash_map
<OUString
, long, ::rtl::OUStringHash
> NameIndexMap
;
1308 long nColCount
= pData
->GetColumnCount();
1309 for (long i
= 0; i
< nColCount
; ++i
)
1310 aMap
.insert( NameIndexMap::value_type(pData
->getDimensionName(i
), i
));
1312 NameIndexMap::const_iterator itrEnd
= aMap
.end();
1314 sal_uInt32 n
= aDimList
.Count();
1315 for (sal_uInt32 i
= 0; i
< n
; ++i
)
1317 ScDPSaveDimension
* pDim
= static_cast<ScDPSaveDimension
*>(aDimList
.GetObject(i
));
1318 const String
& rDimName
= pDim
->GetName();
1319 if (!rDimName
.Len())
1320 // empty dimension name. It must be data layout.
1323 NameIndexMap::const_iterator itr
= aMap
.find(rDimName
);
1325 // dimension name not in the data. This should never happen!
1328 long nDimIndex
= itr
->second
;
1329 const TypedScStrCollection
& rMembers
= pData
->GetColumnEntries(nDimIndex
);
1330 sal_uInt16 nMemberCount
= rMembers
.GetCount();
1331 for (sal_uInt16 j
= 0; j
< nMemberCount
; ++j
)
1333 const String
& rMemName
= rMembers
[j
]->GetString();
1334 if (pDim
->GetExistingMemberByName(rMemName
))
1335 // this member instance already exists. nothing to do.
1338 auto_ptr
<ScDPSaveMember
> pNewMember(new ScDPSaveMember(rMemName
));
1339 pNewMember
->SetIsVisible(true);
1340 pDim
->AddMember(pNewMember
.release());
1344 mbDimensionMembersBuilt
= true;
1347 bool ScDPSaveData::HasInvisibleMember(const OUString
& rDimName
) const
1349 ScDPSaveDimension
* pDim
= GetExistingDimensionByName(rDimName
);
1353 return pDim
->HasInvisibleMember();