update dev300-m58
[ooovba.git] / sc / source / core / data / dpsave.cxx
blob3161155fbcfe20d3f58582585a7133201cb37dc4
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: dpsave.cxx,v $
10 * $Revision: 1.13.32.3 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
36 // INCLUDE ---------------------------------------------------------------
38 #include "dpsave.hxx"
39 #include "dpdimsave.hxx"
40 #include "miscuno.hxx"
41 #include "scerrors.hxx"
42 #include "unonames.hxx"
43 #include "global.hxx"
45 #include <tools/debug.hxx>
47 #include <com/sun/star/sheet/GeneralFunction.hpp>
48 #include <com/sun/star/sheet/DataPilotFieldAutoShowInfo.hpp>
49 #include <com/sun/star/sheet/DataPilotFieldLayoutInfo.hpp>
50 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
51 #include <com/sun/star/sheet/DataPilotFieldReference.hpp>
52 #include <com/sun/star/sheet/DataPilotFieldSortInfo.hpp>
53 #include <com/sun/star/sheet/DataPilotFieldSortMode.hpp>
54 #include <com/sun/star/sheet/TableFilterField.hpp>
55 #include <com/sun/star/sheet/XHierarchiesSupplier.hpp>
56 #include <com/sun/star/sheet/XLevelsSupplier.hpp>
57 #include <com/sun/star/sheet/XMembersSupplier.hpp>
58 #include <com/sun/star/container/XNamed.hpp>
59 #include <com/sun/star/util/XCloneable.hpp>
61 #include <hash_map>
63 using namespace com::sun::star;
64 using ::com::sun::star::uno::Reference;
65 using ::com::sun::star::uno::Any;
66 using ::rtl::OUString;
67 using ::rtl::OUStringHash;
68 using ::std::hash_map;
69 using ::std::auto_ptr;
71 // -----------------------------------------------------------------------
73 #define SC_DPSAVEMODE_NO 0
74 #define SC_DPSAVEMODE_YES 1
75 #define SC_DPSAVEMODE_DONTKNOW 2
77 // -----------------------------------------------------------------------
79 //! move to a header file
80 //! use names from unonames.hxx?
81 #define DP_PROP_COLUMNGRAND "ColumnGrand"
82 #define DP_PROP_FUNCTION "Function"
83 #define DP_PROP_IGNOREEMPTY "IgnoreEmptyRows"
84 #define DP_PROP_ISDATALAYOUT "IsDataLayoutDimension"
85 #define DP_PROP_ISVISIBLE "IsVisible"
86 #define DP_PROP_ORIENTATION "Orientation"
87 #define DP_PROP_REPEATIFEMPTY "RepeatIfEmpty"
88 #define DP_PROP_ROWGRAND "RowGrand"
89 #define DP_PROP_SHOWDETAILS "ShowDetails"
90 #define DP_PROP_SHOWEMPTY "ShowEmpty"
91 #define DP_PROP_SUBTOTALS "SubTotals"
92 #define DP_PROP_USEDHIERARCHY "UsedHierarchy"
93 #define DP_PROP_FILTER "Filter"
94 #define DP_PROP_POSITION "Position"
96 // -----------------------------------------------------------------------
98 void lcl_SetBoolProperty( const uno::Reference<beans::XPropertySet>& xProp,
99 const rtl::OUString& rName, sal_Bool bValue )
101 //! move to ScUnoHelpFunctions?
103 xProp->setPropertyValue( rName, uno::Any( &bValue, getBooleanCppuType() ) );
106 // -----------------------------------------------------------------------
108 ScDPSaveMember::ScDPSaveMember(const String& rName) :
109 aName( rName ),
110 mpLayoutName(NULL),
111 nVisibleMode( SC_DPSAVEMODE_DONTKNOW ),
112 nShowDetailsMode( SC_DPSAVEMODE_DONTKNOW )
116 ScDPSaveMember::ScDPSaveMember(const ScDPSaveMember& r) :
117 aName( r.aName ),
118 mpLayoutName(NULL),
119 nVisibleMode( r.nVisibleMode ),
120 nShowDetailsMode( r.nShowDetailsMode )
122 if (r.mpLayoutName.get())
123 mpLayoutName.reset(new OUString(*r.mpLayoutName));
126 ScDPSaveMember::~ScDPSaveMember()
130 BOOL ScDPSaveMember::operator== ( const ScDPSaveMember& r ) const
132 if ( aName != r.aName ||
133 nVisibleMode != r.nVisibleMode ||
134 nShowDetailsMode != r.nShowDetailsMode )
135 return FALSE;
137 return TRUE;
140 BOOL ScDPSaveMember::HasIsVisible() const
142 return nVisibleMode != SC_DPSAVEMODE_DONTKNOW;
145 void ScDPSaveMember::SetIsVisible(BOOL bSet)
147 nVisibleMode = bSet;
150 BOOL ScDPSaveMember::HasShowDetails() const
152 return nShowDetailsMode != SC_DPSAVEMODE_DONTKNOW;
155 void ScDPSaveMember::SetShowDetails(BOOL bSet)
157 nShowDetailsMode = bSet;
160 void ScDPSaveMember::SetName( const String& rNew )
162 // Used only if the source member was renamed (groups).
163 // For UI renaming of members, a layout name must be used.
165 aName = rNew;
168 void ScDPSaveMember::SetLayoutName( const OUString& rName )
170 mpLayoutName.reset(new OUString(rName));
173 const OUString* ScDPSaveMember::GetLayoutName() const
175 return mpLayoutName.get();
178 void ScDPSaveMember::RemoveLayoutName()
180 mpLayoutName.reset(NULL);
183 void ScDPSaveMember::WriteToSource( const uno::Reference<uno::XInterface>& xMember, sal_Int32 nPosition )
185 uno::Reference<beans::XPropertySet> xMembProp( xMember, uno::UNO_QUERY );
186 DBG_ASSERT( xMembProp.is(), "no properties at member" );
187 if ( xMembProp.is() )
189 // exceptions are caught at ScDPSaveData::WriteToSource
191 if ( nVisibleMode != SC_DPSAVEMODE_DONTKNOW )
192 lcl_SetBoolProperty( xMembProp,
193 rtl::OUString::createFromAscii(DP_PROP_ISVISIBLE), (BOOL)nVisibleMode );
195 if ( nShowDetailsMode != SC_DPSAVEMODE_DONTKNOW )
196 lcl_SetBoolProperty( xMembProp,
197 rtl::OUString::createFromAscii(DP_PROP_SHOWDETAILS), (BOOL)nShowDetailsMode );
199 if (mpLayoutName.get())
200 ScUnoHelpFunctions::SetOptionalPropertyValue(xMembProp, SC_UNO_LAYOUTNAME, *mpLayoutName);
202 if ( nPosition >= 0 )
203 ScUnoHelpFunctions::SetOptionalPropertyValue(xMembProp, DP_PROP_POSITION, nPosition);
207 // -----------------------------------------------------------------------
209 ScDPSaveDimension::ScDPSaveDimension(const String& rName, BOOL bDataLayout) :
210 aName( rName ),
211 pSelectedPage( NULL ),
212 mpLayoutName(NULL),
213 mpSubtotalName(NULL),
214 bIsDataLayout( bDataLayout ),
215 bDupFlag( FALSE ),
216 nOrientation( sheet::DataPilotFieldOrientation_HIDDEN ),
217 nFunction( sheet::GeneralFunction_AUTO ),
218 nUsedHierarchy( -1 ),
219 nShowEmptyMode( SC_DPSAVEMODE_DONTKNOW ),
220 bSubTotalDefault( TRUE ),
221 nSubTotalCount( 0 ),
222 pSubTotalFuncs( NULL ),
223 pReferenceValue( NULL ),
224 pSortInfo( NULL ),
225 pAutoShowInfo( NULL ),
226 pLayoutInfo( NULL )
230 ScDPSaveDimension::ScDPSaveDimension(const ScDPSaveDimension& r) :
231 aName( r.aName ),
232 mpLayoutName(NULL),
233 mpSubtotalName(NULL),
234 bIsDataLayout( r.bIsDataLayout ),
235 bDupFlag( r.bDupFlag ),
236 nOrientation( r.nOrientation ),
237 nFunction( r.nFunction ),
238 nUsedHierarchy( r.nUsedHierarchy ),
239 nShowEmptyMode( r.nShowEmptyMode ),
240 bSubTotalDefault( r.bSubTotalDefault ),
241 nSubTotalCount( r.nSubTotalCount ),
242 pSubTotalFuncs( NULL )
244 if ( nSubTotalCount && r.pSubTotalFuncs )
246 pSubTotalFuncs = new USHORT[nSubTotalCount];
247 for (long nSub=0; nSub<nSubTotalCount; nSub++)
248 pSubTotalFuncs[nSub] = r.pSubTotalFuncs[nSub];
251 for (MemberList::const_iterator i=r.maMemberList.begin(); i != r.maMemberList.end() ; i++)
253 const String& rName = (*i)->GetName();
254 ScDPSaveMember* pNew = new ScDPSaveMember( **i );
255 maMemberHash[rName] = pNew;
256 maMemberList.push_back( pNew );
258 if (r.pReferenceValue)
259 pReferenceValue = new sheet::DataPilotFieldReference( *(r.pReferenceValue) );
260 else
261 pReferenceValue = NULL;
262 if (r.pSortInfo)
263 pSortInfo = new sheet::DataPilotFieldSortInfo( *(r.pSortInfo) );
264 else
265 pSortInfo = NULL;
266 if (r.pAutoShowInfo)
267 pAutoShowInfo = new sheet::DataPilotFieldAutoShowInfo( *(r.pAutoShowInfo) );
268 else
269 pAutoShowInfo = NULL;
270 if (r.pLayoutInfo)
271 pLayoutInfo = new sheet::DataPilotFieldLayoutInfo( *(r.pLayoutInfo) );
272 else
273 pLayoutInfo = NULL;
274 if (r.pSelectedPage)
275 pSelectedPage = new String( *(r.pSelectedPage) );
276 else
277 pSelectedPage = NULL;
278 if (r.mpLayoutName.get())
279 mpLayoutName.reset(new OUString(*r.mpLayoutName));
280 if (r.mpSubtotalName.get())
281 mpSubtotalName.reset(new OUString(*r.mpSubtotalName));
284 ScDPSaveDimension::~ScDPSaveDimension()
286 for (MemberHash::const_iterator i=maMemberHash.begin(); i != maMemberHash.end() ; i++)
287 delete i->second;
288 delete pReferenceValue;
289 delete pSortInfo;
290 delete pAutoShowInfo;
291 delete pLayoutInfo;
292 delete pSelectedPage;
293 delete [] pSubTotalFuncs;
296 BOOL ScDPSaveDimension::operator== ( const ScDPSaveDimension& r ) const
298 if ( aName != r.aName ||
299 bIsDataLayout != r.bIsDataLayout ||
300 bDupFlag != r.bDupFlag ||
301 nOrientation != r.nOrientation ||
302 nFunction != r.nFunction ||
303 nUsedHierarchy != r.nUsedHierarchy ||
304 nShowEmptyMode != r.nShowEmptyMode ||
305 bSubTotalDefault != r.bSubTotalDefault ||
306 nSubTotalCount != r.nSubTotalCount )
307 return FALSE;
309 if ( nSubTotalCount && ( !pSubTotalFuncs || !r.pSubTotalFuncs ) ) // should not happen
310 return FALSE;
312 long i;
313 for (i=0; i<nSubTotalCount; i++)
314 if ( pSubTotalFuncs[i] != r.pSubTotalFuncs[i] )
315 return FALSE;
317 if (maMemberHash.size() != r.maMemberHash.size() )
318 return FALSE;
320 MemberList::const_iterator a=maMemberList.begin();
321 MemberList::const_iterator b=r.maMemberList.begin();
322 for (; a != maMemberList.end() ; ++a, ++b)
323 if (!(**a == **b))
324 return FALSE;
326 return TRUE;
329 void ScDPSaveDimension::AddMember(ScDPSaveMember* pMember)
331 const String & rName = pMember->GetName();
332 MemberHash::iterator aExisting = maMemberHash.find( rName );
333 if ( aExisting == maMemberHash.end() )
335 std::pair< const String, ScDPSaveMember *> key( rName, pMember );
336 maMemberHash.insert ( key );
338 else
340 maMemberList.remove( aExisting->second );
341 delete aExisting->second;
342 aExisting->second = pMember;
344 maMemberList.push_back( pMember );
347 void ScDPSaveDimension::SetName( const String& rNew )
349 // Used only if the source dim was renamed (groups).
350 // For UI renaming of dimensions, the layout name must be used.
352 aName = rNew;
355 void ScDPSaveDimension::SetOrientation(USHORT nNew)
357 nOrientation = nNew;
360 void ScDPSaveDimension::SetSubTotals(long nCount, const USHORT* pFuncs)
362 if (pSubTotalFuncs)
363 delete [] pSubTotalFuncs;
364 nSubTotalCount = nCount;
365 if ( nCount && pFuncs )
367 pSubTotalFuncs = new USHORT[nCount];
368 for (long i=0; i<nCount; i++)
369 pSubTotalFuncs[i] = pFuncs[i];
371 else
372 pSubTotalFuncs = NULL;
374 bSubTotalDefault = FALSE;
377 void ScDPSaveDimension::SetShowEmpty(BOOL bSet)
379 nShowEmptyMode = bSet;
382 void ScDPSaveDimension::SetFunction(USHORT nNew)
384 nFunction = nNew;
387 void ScDPSaveDimension::SetUsedHierarchy(long nNew)
389 nUsedHierarchy = nNew;
392 void ScDPSaveDimension::SetSubtotalName(const OUString& rName)
394 mpSubtotalName.reset(new OUString(rName));
397 const OUString* ScDPSaveDimension::GetSubtotalName() const
399 return mpSubtotalName.get();
402 bool ScDPSaveDimension::IsMemberNameInUse(const OUString& rName) const
404 MemberList::const_iterator itr = maMemberList.begin(), itrEnd = maMemberList.end();
405 for (; itr != itrEnd; ++itr)
407 const ScDPSaveMember* pMem = *itr;
408 if (rName.equalsIgnoreAsciiCase(pMem->GetName()))
409 return true;
411 const OUString* pLayoutName = pMem->GetLayoutName();
412 if (pLayoutName && rName.equalsIgnoreAsciiCase(*pLayoutName))
413 return true;
415 return false;
418 void ScDPSaveDimension::SetLayoutName(const OUString& rName)
420 mpLayoutName.reset(new OUString(rName));
423 const OUString* ScDPSaveDimension::GetLayoutName() const
425 return mpLayoutName.get();
428 void ScDPSaveDimension::RemoveLayoutName()
430 mpLayoutName.reset(NULL);
433 void ScDPSaveDimension::SetReferenceValue(const sheet::DataPilotFieldReference* pNew)
435 delete pReferenceValue;
436 if (pNew)
437 pReferenceValue = new sheet::DataPilotFieldReference(*pNew);
438 else
439 pReferenceValue = NULL;
442 void ScDPSaveDimension::SetSortInfo(const sheet::DataPilotFieldSortInfo* pNew)
444 delete pSortInfo;
445 if (pNew)
446 pSortInfo = new sheet::DataPilotFieldSortInfo(*pNew);
447 else
448 pSortInfo = NULL;
451 void ScDPSaveDimension::SetAutoShowInfo(const sheet::DataPilotFieldAutoShowInfo* pNew)
453 delete pAutoShowInfo;
454 if (pNew)
455 pAutoShowInfo = new sheet::DataPilotFieldAutoShowInfo(*pNew);
456 else
457 pAutoShowInfo = NULL;
460 void ScDPSaveDimension::SetLayoutInfo(const sheet::DataPilotFieldLayoutInfo* pNew)
462 delete pLayoutInfo;
463 if (pNew)
464 pLayoutInfo = new sheet::DataPilotFieldLayoutInfo(*pNew);
465 else
466 pLayoutInfo = NULL;
469 void ScDPSaveDimension::SetCurrentPage( const String* pPage )
471 delete pSelectedPage;
472 if (pPage)
473 pSelectedPage = new String( *pPage );
474 else
475 pSelectedPage = NULL;
478 BOOL ScDPSaveDimension::HasCurrentPage() const
480 return ( pSelectedPage != NULL );
483 const String& ScDPSaveDimension::GetCurrentPage() const
485 if (pSelectedPage)
486 return *pSelectedPage;
487 return EMPTY_STRING;
490 ScDPSaveMember* ScDPSaveDimension::GetExistingMemberByName(const String& rName)
492 MemberHash::const_iterator res = maMemberHash.find (rName);
493 if (res != maMemberHash.end())
494 return res->second;
495 return NULL;
499 ScDPSaveMember* ScDPSaveDimension::GetMemberByName(const String& rName)
501 MemberHash::const_iterator res = maMemberHash.find (rName);
502 if (res != maMemberHash.end())
503 return res->second;
505 ScDPSaveMember* pNew = new ScDPSaveMember( rName );
506 maMemberHash[rName] = pNew;
507 maMemberList.push_back( pNew );
508 return pNew;
511 void ScDPSaveDimension::SetMemberPosition( const String& rName, sal_Int32 nNewPos )
513 ScDPSaveMember* pMember = GetMemberByName( rName ); // make sure it exists and is in the hash
515 maMemberList.remove( pMember );
517 MemberList::iterator aIter = maMemberList.begin();
518 for (sal_Int32 i=0; i<nNewPos && aIter != maMemberList.end(); i++)
519 ++aIter;
520 maMemberList.insert( aIter, pMember );
523 void ScDPSaveDimension::WriteToSource( const uno::Reference<uno::XInterface>& xDim )
525 uno::Reference<beans::XPropertySet> xDimProp( xDim, uno::UNO_QUERY );
526 DBG_ASSERT( xDimProp.is(), "no properties at dimension" );
527 if ( xDimProp.is() )
529 // exceptions are caught at ScDPSaveData::WriteToSource
530 uno::Any aAny;
532 sheet::DataPilotFieldOrientation eOrient = (sheet::DataPilotFieldOrientation)nOrientation;
533 aAny <<= eOrient;
534 xDimProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_ORIENTATION), aAny );
536 sheet::GeneralFunction eFunc = (sheet::GeneralFunction)nFunction;
537 aAny <<= eFunc;
538 xDimProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_FUNCTION), aAny );
540 if ( nUsedHierarchy >= 0 )
542 aAny <<= (INT32)nUsedHierarchy;
543 xDimProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_USEDHIERARCHY), aAny );
546 if ( pReferenceValue )
548 aAny <<= *pReferenceValue;
549 xDimProp->setPropertyValue( rtl::OUString::createFromAscii(SC_UNO_REFVALUE), aAny );
552 uno::Sequence<sheet::TableFilterField> aFilter;
553 // set the selected page field only if the dimension is used as page dimension
554 if ( pSelectedPage && nOrientation == sheet::DataPilotFieldOrientation_PAGE )
556 // single filter field: first field equal to selected string
557 sheet::TableFilterField aField( sheet::FilterConnection_AND, 0,
558 sheet::FilterOperator_EQUAL, sal_False, 0.0, *pSelectedPage );
559 aFilter = uno::Sequence<sheet::TableFilterField>( &aField, 1 );
561 // else keep empty sequence
563 ScUnoHelpFunctions::SetOptionalPropertyValue(xDimProp, DP_PROP_FILTER, aFilter);
564 if (mpLayoutName.get())
565 ScUnoHelpFunctions::SetOptionalPropertyValue(xDimProp, SC_UNO_LAYOUTNAME, *mpLayoutName);
567 const OUString* pSubTotalName = GetSubtotalName();
568 if (pSubTotalName)
569 // Custom subtotal name, with '?' being replaced by the visible field name later.
570 ScUnoHelpFunctions::SetOptionalPropertyValue(xDimProp, SC_UNO_FIELD_SUBTOTALNAME, *pSubTotalName);
573 // Level loop outside of maMemberList loop
574 // because SubTotals have to be set independently of known members
576 long nCount = maMemberHash.size();
578 long nHierCount = 0;
579 uno::Reference<container::XIndexAccess> xHiers;
580 uno::Reference<sheet::XHierarchiesSupplier> xHierSupp( xDim, uno::UNO_QUERY );
581 if ( xHierSupp.is() )
583 uno::Reference<container::XNameAccess> xHiersName = xHierSupp->getHierarchies();
584 xHiers = new ScNameToIndexAccess( xHiersName );
585 nHierCount = xHiers->getCount();
588 sal_Bool bHasHiddenMember = false;
590 for (long nHier=0; nHier<nHierCount; nHier++)
592 uno::Reference<uno::XInterface> xHierarchy = ScUnoHelpFunctions::AnyToInterface( xHiers->getByIndex(nHier) );
594 long nLevCount = 0;
595 uno::Reference<container::XIndexAccess> xLevels;
596 uno::Reference<sheet::XLevelsSupplier> xLevSupp( xHierarchy, uno::UNO_QUERY );
597 if ( xLevSupp.is() )
599 uno::Reference<container::XNameAccess> xLevelsName = xLevSupp->getLevels();
600 xLevels = new ScNameToIndexAccess( xLevelsName );
601 nLevCount = xLevels->getCount();
604 for (long nLev=0; nLev<nLevCount; nLev++)
606 uno::Reference<uno::XInterface> xLevel = ScUnoHelpFunctions::AnyToInterface( xLevels->getByIndex(nLev) );
607 uno::Reference<beans::XPropertySet> xLevProp( xLevel, uno::UNO_QUERY );
608 DBG_ASSERT( xLevProp.is(), "no properties at level" );
609 if ( xLevProp.is() )
611 uno::Any aAny;
612 if ( !bSubTotalDefault )
614 if ( !pSubTotalFuncs )
615 nSubTotalCount = 0;
617 uno::Sequence<sheet::GeneralFunction> aSeq(nSubTotalCount);
618 sheet::GeneralFunction* pArray = aSeq.getArray();
619 for (long i=0; i<nSubTotalCount; i++)
620 pArray[i] = (sheet::GeneralFunction)pSubTotalFuncs[i];
621 aAny <<= aSeq;
622 xLevProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_SUBTOTALS), aAny );
624 if ( nShowEmptyMode != SC_DPSAVEMODE_DONTKNOW )
625 lcl_SetBoolProperty( xLevProp,
626 rtl::OUString::createFromAscii(DP_PROP_SHOWEMPTY), (BOOL)nShowEmptyMode );
628 if ( pSortInfo )
629 ScUnoHelpFunctions::SetOptionalPropertyValue(xLevProp, SC_UNO_SORTING, *pSortInfo);
631 if ( pAutoShowInfo )
632 ScUnoHelpFunctions::SetOptionalPropertyValue(xLevProp, SC_UNO_AUTOSHOW, *pAutoShowInfo);
634 if ( pLayoutInfo )
635 ScUnoHelpFunctions::SetOptionalPropertyValue(xLevProp, SC_UNO_LAYOUT, *pLayoutInfo);
637 // exceptions are caught at ScDPSaveData::WriteToSource
640 if ( nCount > 0 )
642 uno::Reference<sheet::XMembersSupplier> xMembSupp( xLevel, uno::UNO_QUERY );
643 if ( xMembSupp.is() )
645 uno::Reference<container::XNameAccess> xMembers = xMembSupp->getMembers();
646 if ( xMembers.is() )
648 sal_Int32 nPosition = -1; // set position only in manual mode
649 if ( !pSortInfo || pSortInfo->Mode == sheet::DataPilotFieldSortMode::MANUAL )
650 nPosition = 0;
652 for (MemberList::const_iterator i=maMemberList.begin(); i != maMemberList.end() ; i++)
654 ScDPSaveMember* pMember = *i;
655 if (!pMember->GetIsVisible())
656 bHasHiddenMember = true;
657 rtl::OUString aMemberName = pMember->GetName();
658 if ( xMembers->hasByName( aMemberName ) )
660 uno::Reference<uno::XInterface> xMemberInt = ScUnoHelpFunctions::AnyToInterface(
661 xMembers->getByName( aMemberName ) );
662 pMember->WriteToSource( xMemberInt, nPosition );
664 if ( nPosition >= 0 )
665 ++nPosition; // increase if initialized
667 // missing member is no error
675 if (xDimProp.is())
676 ScUnoHelpFunctions::SetOptionalPropertyValue(xDimProp, SC_UNO_HAS_HIDDEN_MEMBER, bHasHiddenMember);
679 void ScDPSaveDimension::UpdateMemberVisibility(const hash_map<OUString, bool, OUStringHash>& rData)
681 typedef hash_map<OUString, bool, OUStringHash> DataMap;
682 MemberList::iterator itrMem = maMemberList.begin(), itrMemEnd = maMemberList.end();
683 for (; itrMem != itrMemEnd; ++itrMem)
685 ScDPSaveMember* pMem = *itrMem;
686 const String& rMemName = pMem->GetName();
687 DataMap::const_iterator itr = rData.find(rMemName);
688 if (itr != rData.end())
689 pMem->SetIsVisible(itr->second);
693 bool ScDPSaveDimension::HasInvisibleMember() const
695 MemberList::const_iterator itrMem = maMemberList.begin(), itrMemEnd = maMemberList.end();
696 for (; itrMem != itrMemEnd; ++itrMem)
698 const ScDPSaveMember* pMem = *itrMem;
699 if (!pMem->GetIsVisible())
700 return true;
702 return false;
705 // -----------------------------------------------------------------------
707 ScDPSaveData::ScDPSaveData() :
708 pDimensionData( NULL ),
709 nColumnGrandMode( SC_DPSAVEMODE_DONTKNOW ),
710 nRowGrandMode( SC_DPSAVEMODE_DONTKNOW ),
711 nIgnoreEmptyMode( SC_DPSAVEMODE_DONTKNOW ),
712 nRepeatEmptyMode( SC_DPSAVEMODE_DONTKNOW ),
713 bFilterButton( TRUE ),
714 bDrillDown( TRUE ),
715 mbDimensionMembersBuilt(false),
716 mpGrandTotalName(NULL)
720 ScDPSaveData::ScDPSaveData(const ScDPSaveData& r) :
721 nColumnGrandMode( r.nColumnGrandMode ),
722 nRowGrandMode( r.nRowGrandMode ),
723 nIgnoreEmptyMode( r.nIgnoreEmptyMode ),
724 nRepeatEmptyMode( r.nRepeatEmptyMode ),
725 bFilterButton( r.bFilterButton ),
726 bDrillDown( r.bDrillDown ),
727 mbDimensionMembersBuilt(r.mbDimensionMembersBuilt),
728 mpGrandTotalName(NULL)
730 if ( r.pDimensionData )
731 pDimensionData = new ScDPDimensionSaveData( *r.pDimensionData );
732 else
733 pDimensionData = NULL;
735 long nCount = r.aDimList.Count();
736 for (long i=0; i<nCount; i++)
738 ScDPSaveDimension* pNew = new ScDPSaveDimension( *(ScDPSaveDimension*)r.aDimList.GetObject(i) );
739 aDimList.Insert( pNew, LIST_APPEND );
742 if (r.mpGrandTotalName.get())
743 mpGrandTotalName.reset(new OUString(*r.mpGrandTotalName));
746 ScDPSaveData& ScDPSaveData::operator= ( const ScDPSaveData& r )
748 if ( &r != this )
750 delete pDimensionData;
751 if ( r.pDimensionData )
752 pDimensionData = new ScDPDimensionSaveData( *r.pDimensionData );
753 else
754 pDimensionData = NULL;
756 nColumnGrandMode = r.nColumnGrandMode;
757 nRowGrandMode = r.nRowGrandMode;
758 nIgnoreEmptyMode = r.nIgnoreEmptyMode;
759 nRepeatEmptyMode = r.nRepeatEmptyMode;
760 bFilterButton = r.bFilterButton;
761 bDrillDown = r.bDrillDown;
762 mbDimensionMembersBuilt = r.mbDimensionMembersBuilt;
764 // remove old dimensions
766 long nCount = aDimList.Count();
767 long i;
768 for (i=0; i<nCount; i++)
769 delete (ScDPSaveDimension*)aDimList.GetObject(i);
770 aDimList.Clear();
772 // copy new dimensions
774 nCount = r.aDimList.Count();
775 for (i=0; i<nCount; i++)
777 ScDPSaveDimension* pNew =
778 new ScDPSaveDimension( *(ScDPSaveDimension*)r.aDimList.GetObject(i) );
779 aDimList.Insert( pNew, LIST_APPEND );
782 if (r.mpGrandTotalName.get())
783 mpGrandTotalName.reset(new OUString(*r.mpGrandTotalName));
785 return *this;
788 BOOL ScDPSaveData::operator== ( const ScDPSaveData& r ) const
790 if ( nColumnGrandMode != r.nColumnGrandMode ||
791 nRowGrandMode != r.nRowGrandMode ||
792 nIgnoreEmptyMode != r.nIgnoreEmptyMode ||
793 nRepeatEmptyMode != r.nRepeatEmptyMode ||
794 bFilterButton != r.bFilterButton ||
795 bDrillDown != r.bDrillDown ||
796 mbDimensionMembersBuilt != r.mbDimensionMembersBuilt)
797 return FALSE;
799 if ( pDimensionData || r.pDimensionData )
800 if ( !pDimensionData || !r.pDimensionData || !( *pDimensionData == *r.pDimensionData ) )
801 return FALSE;
803 ULONG nCount = aDimList.Count();
804 if ( nCount != r.aDimList.Count() )
805 return FALSE;
807 for (ULONG i=0; i<nCount; i++)
808 if ( !( *(ScDPSaveDimension*)aDimList.GetObject(i) ==
809 *(ScDPSaveDimension*)r.aDimList.GetObject(i) ) )
810 return FALSE;
812 if (mpGrandTotalName.get())
814 if (!r.mpGrandTotalName.get())
815 return false;
816 if (!mpGrandTotalName->equals(*r.mpGrandTotalName))
817 return false;
819 else if (r.mpGrandTotalName.get())
820 return false;
822 return TRUE;
825 ScDPSaveData::~ScDPSaveData()
827 long nCount = aDimList.Count();
828 for (long i=0; i<nCount; i++)
829 delete (ScDPSaveDimension*)aDimList.GetObject(i);
830 aDimList.Clear();
832 delete pDimensionData;
835 void ScDPSaveData::SetGrandTotalName(const OUString& rName)
837 mpGrandTotalName.reset(new OUString(rName));
840 const OUString* ScDPSaveData::GetGrandTotalName() const
842 return mpGrandTotalName.get();
845 ScDPSaveDimension* ScDPSaveData::GetDimensionByName(const String& rName)
847 long nCount = aDimList.Count();
848 for (long i=0; i<nCount; i++)
850 ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
851 if ( pDim->GetName() == rName && !pDim->IsDataLayout() )
852 return pDim;
854 ScDPSaveDimension* pNew = new ScDPSaveDimension( rName, FALSE );
855 aDimList.Insert( pNew, LIST_APPEND );
856 return pNew;
859 ScDPSaveDimension* ScDPSaveData::GetExistingDimensionByName(const String& rName) const
861 long nCount = aDimList.Count();
862 for (long i=0; i<nCount; i++)
864 ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
865 if ( pDim->GetName() == rName && !pDim->IsDataLayout() )
866 return pDim;
868 return NULL; // don't create new
871 ScDPSaveDimension* ScDPSaveData::GetNewDimensionByName(const String& rName)
873 long nCount = aDimList.Count();
874 for (long i=0; i<nCount; i++)
876 ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
877 if ( pDim->GetName() == rName && !pDim->IsDataLayout() )
878 return DuplicateDimension(rName);
880 ScDPSaveDimension* pNew = new ScDPSaveDimension( rName, FALSE );
881 aDimList.Insert( pNew, LIST_APPEND );
882 return pNew;
885 ScDPSaveDimension* ScDPSaveData::GetDataLayoutDimension()
887 ScDPSaveDimension* pDim = GetExistingDataLayoutDimension();
888 if (pDim)
889 return pDim;
891 ScDPSaveDimension* pNew = new ScDPSaveDimension( String(), TRUE );
892 aDimList.Insert( pNew, LIST_APPEND );
893 return pNew;
896 ScDPSaveDimension* ScDPSaveData::GetExistingDataLayoutDimension() const
898 long nCount = aDimList.Count();
899 for (long i=0; i<nCount; i++)
901 ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
902 if ( pDim->IsDataLayout() )
903 return pDim;
905 return NULL;
908 ScDPSaveDimension* ScDPSaveData::DuplicateDimension(const String& rName)
910 // always insert new
911 //! check if dimension is there?
913 ScDPSaveDimension* pOld = GetDimensionByName( rName );
914 ScDPSaveDimension* pNew = new ScDPSaveDimension( *pOld );
915 pNew->SetDupFlag( TRUE );
916 aDimList.Insert( pNew, LIST_APPEND );
917 return pNew;
920 void ScDPSaveData::RemoveDimensionByName(const String& rName)
922 long nCount = aDimList.Count();
923 for (long i=0; i<nCount; i++)
925 ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
926 if ( pDim->GetName() == rName && !pDim->IsDataLayout() )
928 delete pDim;
929 aDimList.Remove(i);
930 break;
935 ScDPSaveDimension& ScDPSaveData::DuplicateDimension( const ScDPSaveDimension& rDim )
937 ScDPSaveDimension* pNew = new ScDPSaveDimension( rDim );
938 pNew->SetDupFlag( TRUE );
939 aDimList.Insert( pNew, LIST_APPEND );
940 return *pNew;
943 ScDPSaveDimension* ScDPSaveData::GetInnermostDimension(USHORT nOrientation)
945 // return the innermost dimension for the given orientation,
946 // excluding data layout dimension
948 ScDPSaveDimension* pInner = NULL;
949 long nCount = aDimList.Count();
950 for (long i=0; i<nCount; i++)
952 ScDPSaveDimension* pDim = static_cast<ScDPSaveDimension*>(aDimList.GetObject(i));
953 if ( pDim->GetOrientation() == nOrientation && !pDim->IsDataLayout() )
954 pInner = pDim;
956 return pInner; // the last matching one
959 ScDPSaveDimension* ScDPSaveData::GetFirstDimension(sheet::DataPilotFieldOrientation eOrientation)
961 long nCount = aDimList.Count();
962 for (long i = 0; i < nCount; ++i)
964 ScDPSaveDimension* pDim = static_cast<ScDPSaveDimension*>(aDimList.GetObject(i));
965 if (pDim->GetOrientation() == eOrientation && !pDim->IsDataLayout())
966 return pDim;
968 return NULL;
971 long ScDPSaveData::GetDataDimensionCount() const
973 long nDataCount = 0;
975 long nCount = aDimList.Count();
976 for (long i=0; i<nCount; i++)
978 const ScDPSaveDimension* pDim = static_cast<const ScDPSaveDimension*>(aDimList.GetObject(i));
979 if ( pDim->GetOrientation() == sheet::DataPilotFieldOrientation_DATA )
980 ++nDataCount;
983 return nDataCount;
986 void ScDPSaveData::SetPosition( ScDPSaveDimension* pDim, long nNew )
988 // position (nNew) is counted within dimensions of the same orientation
990 USHORT nOrient = pDim->GetOrientation();
992 aDimList.Remove( pDim );
993 ULONG nCount = aDimList.Count(); // after remove
995 ULONG nInsPos = 0;
996 while ( nNew > 0 && nInsPos < nCount )
998 if ( ((ScDPSaveDimension*)aDimList.GetObject(nInsPos))->GetOrientation() == nOrient )
999 --nNew;
1000 ++nInsPos;
1003 aDimList.Insert( pDim, nInsPos );
1006 void ScDPSaveData::SetColumnGrand(BOOL bSet)
1008 nColumnGrandMode = bSet;
1011 void ScDPSaveData::SetRowGrand(BOOL bSet)
1013 nRowGrandMode = bSet;
1016 void ScDPSaveData::SetIgnoreEmptyRows(BOOL bSet)
1018 nIgnoreEmptyMode = bSet;
1021 void ScDPSaveData::SetRepeatIfEmpty(BOOL bSet)
1023 nRepeatEmptyMode = bSet;
1026 void ScDPSaveData::SetFilterButton(BOOL bSet)
1028 bFilterButton = bSet;
1031 void ScDPSaveData::SetDrillDown(BOOL bSet)
1033 bDrillDown = bSet;
1036 void lcl_ResetOrient( const uno::Reference<sheet::XDimensionsSupplier>& xSource )
1038 sheet::DataPilotFieldOrientation eOrient = sheet::DataPilotFieldOrientation_HIDDEN;
1040 uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
1041 uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName );
1042 long nIntCount = xIntDims->getCount();
1043 for (long nIntDim=0; nIntDim<nIntCount; nIntDim++)
1045 uno::Reference<uno::XInterface> xIntDim = ScUnoHelpFunctions::AnyToInterface( xIntDims->getByIndex(nIntDim) );
1046 uno::Reference<beans::XPropertySet> xDimProp( xIntDim, uno::UNO_QUERY );
1047 if (xDimProp.is())
1049 uno::Any aAny;
1050 aAny <<= eOrient;
1051 xDimProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_ORIENTATION), aAny );
1056 void ScDPSaveData::WriteToSource( const uno::Reference<sheet::XDimensionsSupplier>& xSource )
1058 if (!xSource.is())
1059 return;
1061 // source options must be first!
1063 uno::Reference<beans::XPropertySet> xSourceProp( xSource, uno::UNO_QUERY );
1064 DBG_ASSERT( xSourceProp.is(), "no properties at source" );
1065 if ( xSourceProp.is() )
1067 // source options are not available for external sources
1068 //! use XPropertySetInfo to test for availability?
1072 if ( nIgnoreEmptyMode != SC_DPSAVEMODE_DONTKNOW )
1073 lcl_SetBoolProperty( xSourceProp,
1074 rtl::OUString::createFromAscii(DP_PROP_IGNOREEMPTY), (BOOL)nIgnoreEmptyMode );
1075 if ( nRepeatEmptyMode != SC_DPSAVEMODE_DONTKNOW )
1076 lcl_SetBoolProperty( xSourceProp,
1077 rtl::OUString::createFromAscii(DP_PROP_REPEATIFEMPTY), (BOOL)nRepeatEmptyMode );
1079 catch(uno::Exception&)
1081 // no error
1084 const OUString* pGrandTotalName = GetGrandTotalName();
1085 if (pGrandTotalName)
1086 ScUnoHelpFunctions::SetOptionalPropertyValue(xSourceProp, SC_UNO_GRANDTOTAL_NAME, *pGrandTotalName);
1089 // exceptions in the other calls are errors
1092 // reset all orientations
1093 //! "forgetSettings" or similar at source ?????
1094 //! reset all duplicated dimensions, or reuse them below !!!
1096 lcl_ResetOrient( xSource );
1098 long nCount = aDimList.Count();
1099 for (long i=0; i<nCount; i++)
1101 ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
1102 rtl::OUString aName = pDim->GetName();
1103 BOOL bData = pDim->IsDataLayout();
1105 //! getByName for ScDPSource, including DataLayoutDimension !!!!!!!!
1107 uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
1108 uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName );
1109 long nIntCount = xIntDims->getCount();
1110 BOOL bFound = FALSE;
1111 for (long nIntDim=0; nIntDim<nIntCount && !bFound; nIntDim++)
1113 uno::Reference<uno::XInterface> xIntDim = ScUnoHelpFunctions::AnyToInterface( xIntDims->getByIndex(nIntDim) );
1114 if ( bData )
1116 uno::Reference<beans::XPropertySet> xDimProp( xIntDim, uno::UNO_QUERY );
1117 if ( xDimProp.is() )
1119 bFound = ScUnoHelpFunctions::GetBoolProperty( xDimProp,
1120 rtl::OUString::createFromAscii(DP_PROP_ISDATALAYOUT) );
1121 //! error checking -- is "IsDataLayoutDimension" property required??
1124 else
1126 uno::Reference<container::XNamed> xDimName( xIntDim, uno::UNO_QUERY );
1127 if ( xDimName.is() && xDimName->getName() == aName )
1128 bFound = TRUE;
1131 if ( bFound )
1133 if ( pDim->GetDupFlag() )
1135 String aNewName = pDim->GetName();
1137 // different name for each duplication of a (real) dimension...
1138 for (long j=0; j<=i; j++) //! Test !!!!!!
1139 aNewName += '*'; //! modify name at creation of SaveDimension
1141 uno::Reference<util::XCloneable> xCloneable( xIntDim, uno::UNO_QUERY );
1142 DBG_ASSERT( xCloneable.is(), "cannot clone dimension" );
1143 if (xCloneable.is())
1145 uno::Reference<util::XCloneable> xNew = xCloneable->createClone();
1146 uno::Reference<container::XNamed> xNewName( xNew, uno::UNO_QUERY );
1147 if (xNewName.is())
1149 xNewName->setName( aNewName );
1150 pDim->WriteToSource( xNew );
1154 else
1155 pDim->WriteToSource( xIntDim );
1158 DBG_ASSERT(bFound, "WriteToSource: Dimension not found");
1161 if ( xSourceProp.is() )
1163 if ( nColumnGrandMode != SC_DPSAVEMODE_DONTKNOW )
1164 lcl_SetBoolProperty( xSourceProp,
1165 rtl::OUString::createFromAscii(DP_PROP_COLUMNGRAND), (BOOL)nColumnGrandMode );
1166 if ( nRowGrandMode != SC_DPSAVEMODE_DONTKNOW )
1167 lcl_SetBoolProperty( xSourceProp,
1168 rtl::OUString::createFromAscii(DP_PROP_ROWGRAND), (BOOL)nRowGrandMode );
1171 catch(uno::Exception&)
1173 DBG_ERROR("exception in WriteToSource");
1177 BOOL ScDPSaveData::IsEmpty() const
1179 long nCount = aDimList.Count();
1180 for (long i=0; i<nCount; i++)
1182 ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
1183 if ( pDim->GetOrientation() != sheet::DataPilotFieldOrientation_HIDDEN && !pDim->IsDataLayout() )
1184 return FALSE;
1186 return TRUE; // no entries that are not hidden
1189 ScDPDimensionSaveData* ScDPSaveData::GetDimensionData()
1191 if (!pDimensionData)
1192 pDimensionData = new ScDPDimensionSaveData;
1193 return pDimensionData;
1196 void ScDPSaveData::SetDimensionData( const ScDPDimensionSaveData* pNew )
1198 delete pDimensionData;
1199 if ( pNew )
1200 pDimensionData = new ScDPDimensionSaveData( *pNew );
1201 else
1202 pDimensionData = NULL;
1205 void ScDPSaveData::BuildAllDimensionMembers(ScDPTableData* pData)
1207 if (mbDimensionMembersBuilt)
1208 return;
1210 // First, build a dimension name-to-index map.
1211 typedef hash_map<OUString, long, ::rtl::OUStringHash> NameIndexMap;
1212 NameIndexMap aMap;
1213 long nColCount = pData->GetColumnCount();
1214 for (long i = 0; i < nColCount; ++i)
1215 aMap.insert( NameIndexMap::value_type(pData->getDimensionName(i), i));
1217 NameIndexMap::const_iterator itrEnd = aMap.end();
1219 sal_uInt32 n = aDimList.Count();
1220 for (sal_uInt32 i = 0; i < n; ++i)
1222 ScDPSaveDimension* pDim = static_cast<ScDPSaveDimension*>(aDimList.GetObject(i));
1223 const String& rDimName = pDim->GetName();
1224 if (!rDimName.Len())
1225 // empty dimension name. It must be data layout.
1226 continue;
1228 NameIndexMap::const_iterator itr = aMap.find(rDimName);
1229 if (itr == itrEnd)
1230 // dimension name not in the data. This should never happen!
1231 continue;
1233 long nDimIndex = itr->second;
1234 const TypedScStrCollection& rMembers = pData->GetColumnEntries(nDimIndex);
1235 sal_uInt16 nMemberCount = rMembers.GetCount();
1236 for (sal_uInt16 j = 0; j < nMemberCount; ++j)
1238 const String& rMemName = rMembers[j]->GetString();
1239 if (pDim->GetExistingMemberByName(rMemName))
1240 // this member instance already exists. nothing to do.
1241 continue;
1243 auto_ptr<ScDPSaveMember> pNewMember(new ScDPSaveMember(rMemName));
1244 pNewMember->SetIsVisible(true);
1245 pDim->AddMember(pNewMember.release());
1249 mbDimensionMembersBuilt = true;
1252 bool ScDPSaveData::HasInvisibleMember(const OUString& rDimName) const
1254 ScDPSaveDimension* pDim = GetExistingDimensionByName(rDimName);
1255 if (!pDim)
1256 return false;
1258 return pDim->HasInvisibleMember();