update ooo310-m15
[ooovba.git] / sc / source / core / data / dpsave.cxx
blob4432eb9d85a023d619e554698a20a96be8bdef32
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
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 void lcl_SkipExtra( SvStream& rStream )
108 USHORT nExtra;
109 rStream >> nExtra;
110 if ( nExtra )
112 rStream.SeekRel( nExtra );
113 if ( rStream.GetError() == SVSTREAM_OK )
114 rStream.SetError( SCWARN_IMPORT_INFOLOST );
118 // -----------------------------------------------------------------------
120 ScDPSaveMember::ScDPSaveMember(const String& rName) :
121 aName( rName ),
122 mpLayoutName(NULL),
123 nVisibleMode( SC_DPSAVEMODE_DONTKNOW ),
124 nShowDetailsMode( SC_DPSAVEMODE_DONTKNOW )
128 ScDPSaveMember::ScDPSaveMember(const ScDPSaveMember& r) :
129 aName( r.aName ),
130 mpLayoutName(NULL),
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 )
147 return FALSE;
149 return TRUE;
152 BOOL ScDPSaveMember::HasIsVisible() const
154 return nVisibleMode != SC_DPSAVEMODE_DONTKNOW;
157 void ScDPSaveMember::SetIsVisible(BOOL bSet)
159 nVisibleMode = 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.
177 aName = rNew;
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 )
197 // nothing to do?
198 if ( nVisibleMode == SC_DPSAVEMODE_DONTKNOW && nShowDetailsMode == SC_DPSAVEMODE_DONTKNOW && nPosition < 0 )
199 return;
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())
219 uno::Any any;
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) :
244 aName( rName ),
245 pSelectedPage( NULL ),
246 mpLayoutName(NULL),
247 mpSubtotalName(NULL),
248 bIsDataLayout( bDataLayout ),
249 bDupFlag( FALSE ),
250 nOrientation( sheet::DataPilotFieldOrientation_HIDDEN ),
251 nFunction( sheet::GeneralFunction_AUTO ),
252 nUsedHierarchy( -1 ),
253 nShowEmptyMode( SC_DPSAVEMODE_DONTKNOW ),
254 bSubTotalDefault( TRUE ),
255 nSubTotalCount( 0 ),
256 pSubTotalFuncs( NULL ),
257 pReferenceValue( NULL ),
258 pSortInfo( NULL ),
259 pAutoShowInfo( NULL ),
260 pLayoutInfo( NULL )
264 ScDPSaveDimension::ScDPSaveDimension(const ScDPSaveDimension& r) :
265 aName( r.aName ),
266 mpLayoutName(NULL),
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) );
294 else
295 pReferenceValue = NULL;
296 if (r.pSortInfo)
297 pSortInfo = new sheet::DataPilotFieldSortInfo( *(r.pSortInfo) );
298 else
299 pSortInfo = NULL;
300 if (r.pAutoShowInfo)
301 pAutoShowInfo = new sheet::DataPilotFieldAutoShowInfo( *(r.pAutoShowInfo) );
302 else
303 pAutoShowInfo = NULL;
304 if (r.pLayoutInfo)
305 pLayoutInfo = new sheet::DataPilotFieldLayoutInfo( *(r.pLayoutInfo) );
306 else
307 pLayoutInfo = NULL;
308 if (r.pSelectedPage)
309 pSelectedPage = new String( *(r.pSelectedPage) );
310 else
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++)
321 delete i->second;
322 delete pReferenceValue;
323 delete pSortInfo;
324 delete pAutoShowInfo;
325 delete pLayoutInfo;
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 )
341 return FALSE;
343 if ( nSubTotalCount && ( !pSubTotalFuncs || !r.pSubTotalFuncs ) ) // should not happen
344 return FALSE;
346 long i;
347 for (i=0; i<nSubTotalCount; i++)
348 if ( pSubTotalFuncs[i] != r.pSubTotalFuncs[i] )
349 return FALSE;
351 if (maMemberHash.size() != r.maMemberHash.size() )
352 return FALSE;
354 MemberList::const_iterator a=maMemberList.begin();
355 MemberList::const_iterator b=r.maMemberList.begin();
356 for (; a != maMemberList.end() ; ++a, ++b)
357 if (!(**a == **b))
358 return FALSE;
360 return TRUE;
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 );
372 else
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.
386 aName = rNew;
389 void ScDPSaveDimension::SetOrientation(USHORT nNew)
391 nOrientation = nNew;
394 void ScDPSaveDimension::SetSubTotals(BOOL bSet)
396 if (bSet)
398 USHORT nFunc = sheet::GeneralFunction_AUTO;
399 SetSubTotals( 1, &nFunc );
401 else
402 SetSubTotals( 0, NULL );
405 void ScDPSaveDimension::SetSubTotals(long nCount, const USHORT* pFuncs)
407 if (pSubTotalFuncs)
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];
416 else
417 pSubTotalFuncs = NULL;
419 bSubTotalDefault = FALSE;
422 void ScDPSaveDimension::SetShowEmpty(BOOL bSet)
424 nShowEmptyMode = bSet;
427 void ScDPSaveDimension::SetFunction(USHORT nNew)
429 nFunction = 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()))
454 return true;
456 const OUString* pLayoutName = pMem->GetLayoutName();
457 if (pLayoutName && rName.equalsIgnoreAsciiCase(*pLayoutName))
458 return true;
460 return false;
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;
481 if (pNew)
482 pReferenceValue = new sheet::DataPilotFieldReference(*pNew);
483 else
484 pReferenceValue = NULL;
487 void ScDPSaveDimension::SetSortInfo(const sheet::DataPilotFieldSortInfo* pNew)
489 delete pSortInfo;
490 if (pNew)
491 pSortInfo = new sheet::DataPilotFieldSortInfo(*pNew);
492 else
493 pSortInfo = NULL;
496 void ScDPSaveDimension::SetAutoShowInfo(const sheet::DataPilotFieldAutoShowInfo* pNew)
498 delete pAutoShowInfo;
499 if (pNew)
500 pAutoShowInfo = new sheet::DataPilotFieldAutoShowInfo(*pNew);
501 else
502 pAutoShowInfo = NULL;
505 void ScDPSaveDimension::SetLayoutInfo(const sheet::DataPilotFieldLayoutInfo* pNew)
507 delete pLayoutInfo;
508 if (pNew)
509 pLayoutInfo = new sheet::DataPilotFieldLayoutInfo(*pNew);
510 else
511 pLayoutInfo = NULL;
514 void ScDPSaveDimension::SetCurrentPage( const String* pPage )
516 delete pSelectedPage;
517 if (pPage)
518 pSelectedPage = new String( *pPage );
519 else
520 pSelectedPage = NULL;
523 BOOL ScDPSaveDimension::HasCurrentPage() const
525 return ( pSelectedPage != NULL );
528 const String& ScDPSaveDimension::GetCurrentPage() const
530 if (pSelectedPage)
531 return *pSelectedPage;
532 return EMPTY_STRING;
535 ScDPSaveMember* ScDPSaveDimension::GetExistingMemberByName(const String& rName)
537 MemberHash::const_iterator res = maMemberHash.find (rName);
538 if (res != maMemberHash.end())
539 return res->second;
540 return NULL;
544 ScDPSaveMember* ScDPSaveDimension::GetMemberByName(const String& rName)
546 MemberHash::const_iterator res = maMemberHash.find (rName);
547 if (res != maMemberHash.end())
548 return res->second;
550 ScDPSaveMember* pNew = new ScDPSaveMember( rName );
551 maMemberHash[rName] = pNew;
552 maMemberList.push_back( pNew );
553 return 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++)
564 ++aIter;
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" );
572 if ( xDimProp.is() )
574 // exceptions are caught at ScDPSaveData::WriteToSource
575 uno::Any aAny;
577 sheet::DataPilotFieldOrientation eOrient = (sheet::DataPilotFieldOrientation)nOrientation;
578 aAny <<= eOrient;
579 xDimProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_ORIENTATION), aAny );
581 sheet::GeneralFunction eFunc = (sheet::GeneralFunction)nFunction;
582 aAny <<= eFunc;
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
609 aAny <<= aFilter;
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();
618 if (pSubTotalName)
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();
636 long nHierCount = 0;
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) );
652 long nLevCount = 0;
653 uno::Reference<container::XIndexAccess> xLevels;
654 uno::Reference<sheet::XLevelsSupplier> xLevSupp( xHierarchy, uno::UNO_QUERY );
655 if ( xLevSupp.is() )
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" );
667 if ( xLevProp.is() )
669 uno::Any aAny;
670 if ( !bSubTotalDefault )
672 if ( !pSubTotalFuncs )
673 nSubTotalCount = 0;
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];
679 aAny <<= aSeq;
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 );
686 if ( pSortInfo )
688 aAny <<= *pSortInfo;
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)
698 if ( pAutoShowInfo )
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)
710 if ( pLayoutInfo )
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
726 if ( nCount > 0 )
728 uno::Reference<sheet::XMembersSupplier> xMembSupp( xLevel, uno::UNO_QUERY );
729 if ( xMembSupp.is() )
731 uno::Reference<container::XNameAccess> xMembers = xMembSupp->getMembers();
732 if ( xMembers.is() )
734 sal_Int32 nPosition = -1; // set position only in manual mode
735 if ( !pSortInfo || pSortInfo->Mode == sheet::DataPilotFieldSortMode::MANUAL )
736 nPosition = 0;
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
761 if (xDimProp.is())
763 uno::Any any;
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())
791 return true;
793 return false;
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 ),
805 bDrillDown( 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 );
823 else
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 )
839 if ( &r != this )
841 delete pDimensionData;
842 if ( r.pDimensionData )
843 pDimensionData = new ScDPDimensionSaveData( *r.pDimensionData );
844 else
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();
858 long i;
859 for (i=0; i<nCount; i++)
860 delete (ScDPSaveDimension*)aDimList.GetObject(i);
861 aDimList.Clear();
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));
876 return *this;
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)
888 return FALSE;
890 if ( pDimensionData || r.pDimensionData )
891 if ( !pDimensionData || !r.pDimensionData || !( *pDimensionData == *r.pDimensionData ) )
892 return FALSE;
894 ULONG nCount = aDimList.Count();
895 if ( nCount != r.aDimList.Count() )
896 return FALSE;
898 for (ULONG i=0; i<nCount; i++)
899 if ( !( *(ScDPSaveDimension*)aDimList.GetObject(i) ==
900 *(ScDPSaveDimension*)r.aDimList.GetObject(i) ) )
901 return FALSE;
903 if (mpGrandTotalName.get())
905 if (!r.mpGrandTotalName.get())
906 return false;
907 if (!mpGrandTotalName->equals(*r.mpGrandTotalName))
908 return false;
910 else if (r.mpGrandTotalName.get())
911 return false;
913 return TRUE;
916 ScDPSaveData::~ScDPSaveData()
918 long nCount = aDimList.Count();
919 for (long i=0; i<nCount; i++)
920 delete (ScDPSaveDimension*)aDimList.GetObject(i);
921 aDimList.Clear();
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() )
943 return pDim;
945 ScDPSaveDimension* pNew = new ScDPSaveDimension( rName, FALSE );
946 aDimList.Insert( pNew, LIST_APPEND );
947 return pNew;
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() )
957 return pDim;
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 );
973 return pNew;
976 ScDPSaveDimension* ScDPSaveData::GetDataLayoutDimension()
978 ScDPSaveDimension* pDim = GetExistingDataLayoutDimension();
979 if (pDim)
980 return pDim;
982 ScDPSaveDimension* pNew = new ScDPSaveDimension( String(), TRUE );
983 aDimList.Insert( pNew, LIST_APPEND );
984 return pNew;
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() )
994 return pDim;
996 return NULL;
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 );
1008 return pNew;
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() )
1019 delete pDim;
1020 aDimList.Remove(i);
1021 break;
1026 ScDPSaveDimension& ScDPSaveData::DuplicateDimension( const ScDPSaveDimension& rDim )
1028 ScDPSaveDimension* pNew = new ScDPSaveDimension( rDim );
1029 pNew->SetDupFlag( TRUE );
1030 aDimList.Insert( pNew, LIST_APPEND );
1031 return *pNew;
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() )
1045 pInner = pDim;
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())
1057 return pDim;
1059 return NULL;
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 )
1071 ++nDataCount;
1074 return nDataCount;
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
1086 ULONG nInsPos = 0;
1087 while ( nNew > 0 && nInsPos < nCount )
1089 if ( ((ScDPSaveDimension*)aDimList.GetObject(nInsPos))->GetOrientation() == nOrient )
1090 --nNew;
1091 ++nInsPos;
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)
1124 bDrillDown = 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 );
1138 if (xDimProp.is())
1140 uno::Any aAny;
1141 aAny <<= eOrient;
1142 xDimProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_ORIENTATION), aAny );
1147 void ScDPSaveData::WriteToSource( const uno::Reference<sheet::XDimensionsSupplier>& xSource )
1149 if (!xSource.is())
1150 return;
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)
1173 uno::Any any;
1174 any <<= *pGrandTotalName;
1175 xSourceProp->setPropertyValue(OUString::createFromAscii(SC_UNO_GRANDTOTAL_NAME), any);
1178 catch(uno::Exception&)
1180 // no error
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) );
1209 if ( bData )
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??
1219 else
1221 uno::Reference<container::XNamed> xDimName( xIntDim, uno::UNO_QUERY );
1222 if ( xDimName.is() && xDimName->getName() == aName )
1223 bFound = TRUE;
1226 if ( bFound )
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 );
1242 if (xNewName.is())
1244 xNewName->setName( aNewName );
1245 pDim->WriteToSource( xNew );
1249 else
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() )
1279 return FALSE;
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;
1294 if ( pNew )
1295 pDimensionData = new ScDPDimensionSaveData( *pNew );
1296 else
1297 pDimensionData = NULL;
1300 void ScDPSaveData::BuildAllDimensionMembers(ScDPTableData* pData)
1302 if (mbDimensionMembersBuilt)
1303 return;
1305 // First, build a dimension name-to-index map.
1306 typedef hash_map<OUString, long, ::rtl::OUStringHash> NameIndexMap;
1307 NameIndexMap aMap;
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.
1321 continue;
1323 NameIndexMap::const_iterator itr = aMap.find(rDimName);
1324 if (itr == itrEnd)
1325 // dimension name not in the data. This should never happen!
1326 continue;
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.
1336 continue;
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);
1350 if (!pDim)
1351 return false;
1353 return pDim->HasInvisibleMember();