1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26
27
28
29 // INCLUDE ---------------------------------------------------------------
30
31 #include "dpsave.hxx"
32 #include "dpdimsave.hxx"
33 #include "dpobject.hxx" // GetMemberNames used in BuildAllDimensionMembersFromSource
34 #include "miscuno.hxx"
35 #include "scerrors.hxx"
36 #include "unonames.hxx"
37 #include "global.hxx"
38
39 #include <tools/debug.hxx>
40
41 #include <com/sun/star/sheet/GeneralFunction.hpp>
42 #include <com/sun/star/sheet/DataPilotFieldAutoShowInfo.hpp>
43 #include <com/sun/star/sheet/DataPilotFieldLayoutInfo.hpp>
44 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
45 #include <com/sun/star/sheet/DataPilotFieldReference.hpp>
46 #include <com/sun/star/sheet/DataPilotFieldSortInfo.hpp>
47 #include <com/sun/star/sheet/DataPilotFieldSortMode.hpp>
48 #include <com/sun/star/sheet/TableFilterField.hpp>
49 #include <com/sun/star/sheet/XHierarchiesSupplier.hpp>
50 #include <com/sun/star/sheet/XLevelsSupplier.hpp>
51 #include <com/sun/star/sheet/XMembersSupplier.hpp>
52 #include <com/sun/star/container/XNamed.hpp>
53 #include <com/sun/star/util/XCloneable.hpp>
54 // Wang Xu Ming -- 2009-8-17
55 // DataPilot Migration - Cache&&Performance
56 #include "dptabsrc.hxx"
57 #include "dpglobal.hxx"
58 using namespace ScDPGlobal;
59 #ifndef _COM_SUN_STAR_SHEET_DATAPILOTFIELDREFERENCETYPE_HPP_
60 #include <com/sun/star/sheet/DataPilotFieldReferenceType.hpp>
61 #endif
62 #ifndef _COM_SUN_STAR_SHEET_DATAPILOTFIELDREFERENCEITEMTYPE_HPP_
63 #include <com/sun/star/sheet/DataPilotFieldReferenceItemType.hpp>
64 #endif
65 using namespace com::sun::star::sheet;
66 // End Comments
67
68 #include <hash_map>
69
70 using namespace com::sun::star;
71 using ::com::sun::star::uno::Reference;
72 using ::com::sun::star::uno::Any;
73 using ::rtl::OUString;
74 using ::rtl::OUStringHash;
75 using ::std::hash_map;
76 using ::std::auto_ptr;
77
78 // -----------------------------------------------------------------------
79
80 #define SC_DPSAVEMODE_NO 0
81 #define SC_DPSAVEMODE_YES 1
82 #define SC_DPSAVEMODE_DONTKNOW 2
83
84 // -----------------------------------------------------------------------
85
lcl_SetBoolProperty(const uno::Reference<beans::XPropertySet> & xProp,const rtl::OUString & rName,sal_Bool bValue)86 void lcl_SetBoolProperty( const uno::Reference<beans::XPropertySet>& xProp,
87 const rtl::OUString& rName, sal_Bool bValue )
88 {
89 //! move to ScUnoHelpFunctions?
90
91 xProp->setPropertyValue( rName, uno::Any( &bValue, getBooleanCppuType() ) );
92 }
93
94 // -----------------------------------------------------------------------
95
ScDPSaveMember(const String & rName)96 ScDPSaveMember::ScDPSaveMember(const String& rName) :
97 aName( rName ),
98 mpLayoutName(NULL),
99 nVisibleMode( SC_DPSAVEMODE_DONTKNOW ),
100 nShowDetailsMode( SC_DPSAVEMODE_DONTKNOW )
101 {
102 }
103
ScDPSaveMember(const ScDPSaveMember & r)104 ScDPSaveMember::ScDPSaveMember(const ScDPSaveMember& r) :
105 aName( r.aName ),
106 mpLayoutName(NULL),
107 nVisibleMode( r.nVisibleMode ),
108 nShowDetailsMode( r.nShowDetailsMode )
109 {
110 if (r.mpLayoutName.get())
111 mpLayoutName.reset(new OUString(*r.mpLayoutName));
112 }
113
~ScDPSaveMember()114 ScDPSaveMember::~ScDPSaveMember()
115 {
116 }
117
operator ==(const ScDPSaveMember & r) const118 sal_Bool ScDPSaveMember::operator== ( const ScDPSaveMember& r ) const
119 {
120 if ( aName != r.aName ||
121 nVisibleMode != r.nVisibleMode ||
122 nShowDetailsMode != r.nShowDetailsMode )
123 return sal_False;
124
125 return sal_True;
126 }
127
HasIsVisible() const128 sal_Bool ScDPSaveMember::HasIsVisible() const
129 {
130 return nVisibleMode != SC_DPSAVEMODE_DONTKNOW;
131 }
132
SetIsVisible(sal_Bool bSet)133 void ScDPSaveMember::SetIsVisible(sal_Bool bSet)
134 {
135 nVisibleMode = bSet;
136 }
137
HasShowDetails() const138 sal_Bool ScDPSaveMember::HasShowDetails() const
139 {
140 return nShowDetailsMode != SC_DPSAVEMODE_DONTKNOW;
141 }
142
SetShowDetails(sal_Bool bSet)143 void ScDPSaveMember::SetShowDetails(sal_Bool bSet)
144 {
145 nShowDetailsMode = bSet;
146 }
147
SetName(const String & rNew)148 void ScDPSaveMember::SetName( const String& rNew )
149 {
150 // Used only if the source member was renamed (groups).
151 // For UI renaming of members, a layout name must be used.
152
153 aName = rNew;
154 }
155
SetLayoutName(const OUString & rName)156 void ScDPSaveMember::SetLayoutName( const OUString& rName )
157 {
158 mpLayoutName.reset(new OUString(rName));
159 }
160
GetLayoutName() const161 const OUString* ScDPSaveMember::GetLayoutName() const
162 {
163 return mpLayoutName.get();
164 }
165
RemoveLayoutName()166 void ScDPSaveMember::RemoveLayoutName()
167 {
168 mpLayoutName.reset();
169 }
170
WriteToSource(const uno::Reference<uno::XInterface> & xMember,sal_Int32 nPosition)171 void ScDPSaveMember::WriteToSource( const uno::Reference<uno::XInterface>& xMember, sal_Int32 nPosition )
172 {
173 uno::Reference<beans::XPropertySet> xMembProp( xMember, uno::UNO_QUERY );
174 DBG_ASSERT( xMembProp.is(), "no properties at member" );
175 if ( xMembProp.is() )
176 {
177 // exceptions are caught at ScDPSaveData::WriteToSource
178
179 if ( nVisibleMode != SC_DPSAVEMODE_DONTKNOW )
180 lcl_SetBoolProperty( xMembProp,
181 rtl::OUString::createFromAscii(DP_PROP_ISVISIBLE), (sal_Bool)nVisibleMode );
182
183 if ( nShowDetailsMode != SC_DPSAVEMODE_DONTKNOW )
184 lcl_SetBoolProperty( xMembProp,
185 rtl::OUString::createFromAscii(DP_PROP_SHOWDETAILS), (sal_Bool)nShowDetailsMode );
186
187 if (mpLayoutName.get())
188 ScUnoHelpFunctions::SetOptionalPropertyValue(xMembProp, SC_UNO_LAYOUTNAME, *mpLayoutName);
189
190 if ( nPosition >= 0 )
191 ScUnoHelpFunctions::SetOptionalPropertyValue(xMembProp, DP_PROP_POSITION, nPosition);
192 }
193 }
194
195 // -----------------------------------------------------------------------
196
ScDPSaveDimension(const String & rName,sal_Bool bDataLayout)197 ScDPSaveDimension::ScDPSaveDimension(const String& rName, sal_Bool bDataLayout) :
198 aName( rName ),
199 pSelectedPage( NULL ),
200 mpLayoutName(NULL),
201 mpSubtotalName(NULL),
202 bIsDataLayout( bDataLayout ),
203 bDupFlag( sal_False ),
204 nOrientation( sheet::DataPilotFieldOrientation_HIDDEN ),
205 nFunction( sheet::GeneralFunction_AUTO ),
206 nUsedHierarchy( -1 ),
207 nShowEmptyMode( SC_DPSAVEMODE_DONTKNOW ),
208 bSubTotalDefault( sal_True ),
209 nSubTotalCount( 0 ),
210 pSubTotalFuncs( NULL ),
211 pReferenceValue( NULL ),
212 pSortInfo( NULL ),
213 pAutoShowInfo( NULL ),
214 pLayoutInfo( NULL )
215 {
216 }
217
ScDPSaveDimension(const ScDPSaveDimension & r)218 ScDPSaveDimension::ScDPSaveDimension(const ScDPSaveDimension& r) :
219 aName( r.aName ),
220 mpLayoutName(NULL),
221 mpSubtotalName(NULL),
222 bIsDataLayout( r.bIsDataLayout ),
223 bDupFlag( r.bDupFlag ),
224 nOrientation( r.nOrientation ),
225 nFunction( r.nFunction ),
226 nUsedHierarchy( r.nUsedHierarchy ),
227 nShowEmptyMode( r.nShowEmptyMode ),
228 bSubTotalDefault( r.bSubTotalDefault ),
229 nSubTotalCount( r.nSubTotalCount ),
230 pSubTotalFuncs( NULL )
231 {
232 if ( nSubTotalCount && r.pSubTotalFuncs )
233 {
234 pSubTotalFuncs = new sal_uInt16[nSubTotalCount];
235 for (long nSub=0; nSub<nSubTotalCount; nSub++)
236 pSubTotalFuncs[nSub] = r.pSubTotalFuncs[nSub];
237 }
238
239 for (MemberList::const_iterator i=r.maMemberList.begin(); i != r.maMemberList.end() ; i++)
240 {
241 const String& rName = (*i)->GetName();
242 ScDPSaveMember* pNew = new ScDPSaveMember( **i );
243 maMemberHash[rName] = pNew;
244 maMemberList.push_back( pNew );
245 }
246 if (r.pReferenceValue)
247 pReferenceValue = new sheet::DataPilotFieldReference( *(r.pReferenceValue) );
248 else
249 pReferenceValue = NULL;
250 if (r.pSortInfo)
251 pSortInfo = new sheet::DataPilotFieldSortInfo( *(r.pSortInfo) );
252 else
253 pSortInfo = NULL;
254 if (r.pAutoShowInfo)
255 pAutoShowInfo = new sheet::DataPilotFieldAutoShowInfo( *(r.pAutoShowInfo) );
256 else
257 pAutoShowInfo = NULL;
258 if (r.pLayoutInfo)
259 pLayoutInfo = new sheet::DataPilotFieldLayoutInfo( *(r.pLayoutInfo) );
260 else
261 pLayoutInfo = NULL;
262 if (r.pSelectedPage)
263 pSelectedPage = new String( *(r.pSelectedPage) );
264 else
265 pSelectedPage = NULL;
266 if (r.mpLayoutName.get())
267 mpLayoutName.reset(new OUString(*r.mpLayoutName));
268 if (r.mpSubtotalName.get())
269 mpSubtotalName.reset(new OUString(*r.mpSubtotalName));
270 }
271
~ScDPSaveDimension()272 ScDPSaveDimension::~ScDPSaveDimension()
273 {
274 for (MemberHash::const_iterator i=maMemberHash.begin(); i != maMemberHash.end() ; i++)
275 delete i->second;
276 delete pReferenceValue;
277 delete pSortInfo;
278 delete pAutoShowInfo;
279 delete pLayoutInfo;
280 delete pSelectedPage;
281 delete [] pSubTotalFuncs;
282 }
283
operator ==(const ScDPSaveDimension & r) const284 sal_Bool ScDPSaveDimension::operator== ( const ScDPSaveDimension& r ) const
285 {
286 if ( aName != r.aName ||
287 bIsDataLayout != r.bIsDataLayout ||
288 bDupFlag != r.bDupFlag ||
289 nOrientation != r.nOrientation ||
290 nFunction != r.nFunction ||
291 nUsedHierarchy != r.nUsedHierarchy ||
292 nShowEmptyMode != r.nShowEmptyMode ||
293 bSubTotalDefault != r.bSubTotalDefault ||
294 nSubTotalCount != r.nSubTotalCount )
295 return sal_False;
296
297 if ( nSubTotalCount && ( !pSubTotalFuncs || !r.pSubTotalFuncs ) ) // should not happen
298 return sal_False;
299
300 long i;
301 for (i=0; i<nSubTotalCount; i++)
302 if ( pSubTotalFuncs[i] != r.pSubTotalFuncs[i] )
303 return sal_False;
304
305 if (maMemberHash.size() != r.maMemberHash.size() )
306 return sal_False;
307
308 MemberList::const_iterator a=maMemberList.begin();
309 MemberList::const_iterator b=r.maMemberList.begin();
310 for (; a != maMemberList.end() ; ++a, ++b)
311 if (!(**a == **b))
312 return sal_False;
313
314 if ( this->HasCurrentPage() && r.HasCurrentPage() )
315 {
316 if ( this->GetCurrentPage() != r.GetCurrentPage() )
317 {
318 return sal_False;
319 }
320 }
321 else if ( this->HasCurrentPage() || r.HasCurrentPage() )
322 {
323 return sal_False;
324 }
325 if( pReferenceValue && r.pReferenceValue )
326 {
327 if ( !(*pReferenceValue == *r.pReferenceValue) )
328 {
329 return sal_False;
330 }
331 }
332 else if ( pReferenceValue || r.pReferenceValue )
333 {
334 return sal_False;
335 }
336 if( this->pSortInfo && r.pSortInfo )
337 {
338 if ( !(*this->pSortInfo == *r.pSortInfo) )
339 {
340 return sal_False;
341 }
342 }
343 else if ( this->pSortInfo || r.pSortInfo )
344 {
345 return sal_False;
346 }
347 if( this->pAutoShowInfo && r.pAutoShowInfo )
348 {
349 if ( !(*this->pAutoShowInfo == *r.pAutoShowInfo) )
350 {
351 return sal_False;
352 }
353 }
354 else if ( this->pAutoShowInfo || r.pAutoShowInfo )
355 {
356 return sal_False;
357 }
358
359 return sal_True;
360 }
361
AddMember(ScDPSaveMember * pMember)362 void ScDPSaveDimension::AddMember(ScDPSaveMember* pMember)
363 {
364 const String & rName = pMember->GetName();
365 MemberHash::iterator aExisting = maMemberHash.find( rName );
366 if ( aExisting == maMemberHash.end() )
367 {
368 std::pair< const String, ScDPSaveMember *> key( rName, pMember );
369 maMemberHash.insert ( key );
370 }
371 else
372 {
373 maMemberList.remove( aExisting->second );
374 delete aExisting->second;
375 aExisting->second = pMember;
376 }
377 maMemberList.push_back( pMember );
378 }
379
SetName(const String & rNew)380 void ScDPSaveDimension::SetName( const String& rNew )
381 {
382 // Used only if the source dim was renamed (groups).
383 // For UI renaming of dimensions, the layout name must be used.
384
385 aName = rNew;
386 }
387
SetOrientation(sal_uInt16 nNew)388 void ScDPSaveDimension::SetOrientation(sal_uInt16 nNew)
389 {
390 nOrientation = nNew;
391 }
392
SetSubTotals(long nCount,const sal_uInt16 * pFuncs)393 void ScDPSaveDimension::SetSubTotals(long nCount, const sal_uInt16* pFuncs)
394 {
395 if (pSubTotalFuncs)
396 delete [] pSubTotalFuncs;
397 nSubTotalCount = nCount;
398 if ( nCount && pFuncs )
399 {
400 pSubTotalFuncs = new sal_uInt16[nCount];
401 for (long i=0; i<nCount; i++)
402 pSubTotalFuncs[i] = pFuncs[i];
403 }
404 else
405 pSubTotalFuncs = NULL;
406
407 bSubTotalDefault = sal_False;
408 }
409
HasShowEmpty() const410 bool ScDPSaveDimension::HasShowEmpty() const
411 {
412 return nShowEmptyMode != SC_DPSAVEMODE_DONTKNOW;
413 }
414
SetShowEmpty(sal_Bool bSet)415 void ScDPSaveDimension::SetShowEmpty(sal_Bool bSet)
416 {
417 nShowEmptyMode = bSet;
418 }
419
SetFunction(sal_uInt16 nNew)420 void ScDPSaveDimension::SetFunction(sal_uInt16 nNew)
421 {
422 nFunction = nNew;
423 }
424
SetUsedHierarchy(long nNew)425 void ScDPSaveDimension::SetUsedHierarchy(long nNew)
426 {
427 nUsedHierarchy = nNew;
428 }
429
SetSubtotalName(const OUString & rName)430 void ScDPSaveDimension::SetSubtotalName(const OUString& rName)
431 {
432 mpSubtotalName.reset(new OUString(rName));
433 }
434
GetSubtotalName() const435 const OUString* ScDPSaveDimension::GetSubtotalName() const
436 {
437 return mpSubtotalName.get();
438 }
439
IsMemberNameInUse(const OUString & rName) const440 bool ScDPSaveDimension::IsMemberNameInUse(const OUString& rName) const
441 {
442 MemberList::const_iterator itr = maMemberList.begin(), itrEnd = maMemberList.end();
443 for (; itr != itrEnd; ++itr)
444 {
445 const ScDPSaveMember* pMem = *itr;
446 if (rName.equalsIgnoreAsciiCase(pMem->GetName()))
447 return true;
448
449 const OUString* pLayoutName = pMem->GetLayoutName();
450 if (pLayoutName && rName.equalsIgnoreAsciiCase(*pLayoutName))
451 return true;
452 }
453 return false;
454 }
455
SetLayoutName(const OUString & rName)456 void ScDPSaveDimension::SetLayoutName(const OUString& rName)
457 {
458 mpLayoutName.reset(new OUString(rName));
459 }
460
GetLayoutName() const461 const OUString* ScDPSaveDimension::GetLayoutName() const
462 {
463 return mpLayoutName.get();
464 }
465
RemoveLayoutName()466 void ScDPSaveDimension::RemoveLayoutName()
467 {
468 mpLayoutName.reset();
469 }
470
SetReferenceValue(const sheet::DataPilotFieldReference * pNew)471 void ScDPSaveDimension::SetReferenceValue(const sheet::DataPilotFieldReference* pNew)
472 {
473 delete pReferenceValue;
474 if (pNew)
475 pReferenceValue = new sheet::DataPilotFieldReference(*pNew);
476 else
477 pReferenceValue = NULL;
478 }
479
SetSortInfo(const sheet::DataPilotFieldSortInfo * pNew)480 void ScDPSaveDimension::SetSortInfo(const sheet::DataPilotFieldSortInfo* pNew)
481 {
482 delete pSortInfo;
483 if (pNew)
484 pSortInfo = new sheet::DataPilotFieldSortInfo(*pNew);
485 else
486 pSortInfo = NULL;
487 }
488
SetAutoShowInfo(const sheet::DataPilotFieldAutoShowInfo * pNew)489 void ScDPSaveDimension::SetAutoShowInfo(const sheet::DataPilotFieldAutoShowInfo* pNew)
490 {
491 delete pAutoShowInfo;
492 if (pNew)
493 pAutoShowInfo = new sheet::DataPilotFieldAutoShowInfo(*pNew);
494 else
495 pAutoShowInfo = NULL;
496 }
497
SetLayoutInfo(const sheet::DataPilotFieldLayoutInfo * pNew)498 void ScDPSaveDimension::SetLayoutInfo(const sheet::DataPilotFieldLayoutInfo* pNew)
499 {
500 delete pLayoutInfo;
501 if (pNew)
502 pLayoutInfo = new sheet::DataPilotFieldLayoutInfo(*pNew);
503 else
504 pLayoutInfo = NULL;
505 }
506
SetCurrentPage(const String * pPage)507 void ScDPSaveDimension::SetCurrentPage( const String* pPage )
508 {
509 delete pSelectedPage;
510 if (pPage)
511 pSelectedPage = new String( *pPage );
512 else
513 pSelectedPage = NULL;
514 }
515
HasCurrentPage() const516 sal_Bool ScDPSaveDimension::HasCurrentPage() const
517 {
518 return ( pSelectedPage != NULL );
519 }
520
GetCurrentPage() const521 const String& ScDPSaveDimension::GetCurrentPage() const
522 {
523 if (pSelectedPage)
524 return *pSelectedPage;
525 return EMPTY_STRING;
526 }
527
GetExistingMemberByName(const String & rName)528 ScDPSaveMember* ScDPSaveDimension::GetExistingMemberByName(const String& rName)
529 {
530 MemberHash::const_iterator res = maMemberHash.find (rName);
531 if (res != maMemberHash.end())
532 return res->second;
533 return NULL;
534 }
535
536
GetMemberByName(const String & rName)537 ScDPSaveMember* ScDPSaveDimension::GetMemberByName(const String& rName)
538 {
539 MemberHash::const_iterator res = maMemberHash.find (rName);
540 if (res != maMemberHash.end())
541 return res->second;
542
543 ScDPSaveMember* pNew = new ScDPSaveMember( rName );
544 maMemberHash[rName] = pNew;
545 maMemberList.push_back( pNew );
546 return pNew;
547 }
548
SetMemberPosition(const String & rName,sal_Int32 nNewPos)549 void ScDPSaveDimension::SetMemberPosition( const String& rName, sal_Int32 nNewPos )
550 {
551 ScDPSaveMember* pMember = GetMemberByName( rName ); // make sure it exists and is in the hash
552
553 maMemberList.remove( pMember );
554
555 MemberList::iterator aIter = maMemberList.begin();
556 for (sal_Int32 i=0; i<nNewPos && aIter != maMemberList.end(); i++)
557 ++aIter;
558 maMemberList.insert( aIter, pMember );
559 }
560
WriteToSource(const uno::Reference<uno::XInterface> & xDim)561 void ScDPSaveDimension::WriteToSource( const uno::Reference<uno::XInterface>& xDim )
562 {
563 uno::Reference<beans::XPropertySet> xDimProp( xDim, uno::UNO_QUERY );
564 DBG_ASSERT( xDimProp.is(), "no properties at dimension" );
565 if ( xDimProp.is() )
566 {
567 // exceptions are caught at ScDPSaveData::WriteToSource
568 uno::Any aAny;
569
570 sheet::DataPilotFieldOrientation eOrient = (sheet::DataPilotFieldOrientation)nOrientation;
571 aAny <<= eOrient;
572 xDimProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_ORIENTATION), aAny );
573
574 sheet::GeneralFunction eFunc = (sheet::GeneralFunction)nFunction;
575 aAny <<= eFunc;
576 xDimProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_FUNCTION), aAny );
577
578 if ( nUsedHierarchy >= 0 )
579 {
580 aAny <<= (sal_Int32)nUsedHierarchy;
581 xDimProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_USEDHIERARCHY), aAny );
582 }
583
584 if ( pReferenceValue )
585 {
586 aAny <<= *pReferenceValue;
587 xDimProp->setPropertyValue( rtl::OUString::createFromAscii(SC_UNO_REFVALUE), aAny );
588 }
589
590 uno::Sequence<sheet::TableFilterField> aFilter;
591 // set the selected page field only if the dimension is used as page dimension
592 if ( pSelectedPage && nOrientation == sheet::DataPilotFieldOrientation_PAGE )
593 {
594 // single filter field: first field equal to selected string
595 sheet::TableFilterField aField( sheet::FilterConnection_AND, 0,
596 sheet::FilterOperator_EQUAL, sal_False, 0.0, *pSelectedPage );
597 aFilter = uno::Sequence<sheet::TableFilterField>( &aField, 1 );
598 }
599 // else keep empty sequence
600
601 ScUnoHelpFunctions::SetOptionalPropertyValue(xDimProp, DP_PROP_FILTER, aFilter);
602 if (mpLayoutName.get())
603 ScUnoHelpFunctions::SetOptionalPropertyValue(xDimProp, SC_UNO_LAYOUTNAME, *mpLayoutName);
604
605 const OUString* pSubTotalName = GetSubtotalName();
606 if (pSubTotalName)
607 // Custom subtotal name, with '?' being replaced by the visible field name later.
608 ScUnoHelpFunctions::SetOptionalPropertyValue(xDimProp, SC_UNO_FIELD_SUBTOTALNAME, *pSubTotalName);
609 }
610
611 // Level loop outside of maMemberList loop
612 // because SubTotals have to be set independently of known members
613
614 long nCount = maMemberHash.size();
615
616 long nHierCount = 0;
617 uno::Reference<container::XIndexAccess> xHiers;
618 uno::Reference<sheet::XHierarchiesSupplier> xHierSupp( xDim, uno::UNO_QUERY );
619 if ( xHierSupp.is() )
620 {
621 uno::Reference<container::XNameAccess> xHiersName = xHierSupp->getHierarchies();
622 xHiers = new ScNameToIndexAccess( xHiersName );
623 nHierCount = xHiers->getCount();
624 }
625
626 sal_Bool bHasHiddenMember = false;
627
628 for (long nHier=0; nHier<nHierCount; nHier++)
629 {
630 uno::Reference<uno::XInterface> xHierarchy = ScUnoHelpFunctions::AnyToInterface( xHiers->getByIndex(nHier) );
631
632 long nLevCount = 0;
633 uno::Reference<container::XIndexAccess> xLevels;
634 uno::Reference<sheet::XLevelsSupplier> xLevSupp( xHierarchy, uno::UNO_QUERY );
635 if ( xLevSupp.is() )
636 {
637 uno::Reference<container::XNameAccess> xLevelsName = xLevSupp->getLevels();
638 xLevels = new ScNameToIndexAccess( xLevelsName );
639 nLevCount = xLevels->getCount();
640 }
641
642 for (long nLev=0; nLev<nLevCount; nLev++)
643 {
644 uno::Reference<uno::XInterface> xLevel = ScUnoHelpFunctions::AnyToInterface( xLevels->getByIndex(nLev) );
645 uno::Reference<beans::XPropertySet> xLevProp( xLevel, uno::UNO_QUERY );
646 DBG_ASSERT( xLevProp.is(), "no properties at level" );
647 if ( xLevProp.is() )
648 {
649 uno::Any aAny;
650 if ( !bSubTotalDefault )
651 {
652 if ( !pSubTotalFuncs )
653 nSubTotalCount = 0;
654
655 uno::Sequence<sheet::GeneralFunction> aSeq(nSubTotalCount);
656 sheet::GeneralFunction* pArray = aSeq.getArray();
657 for (long i=0; i<nSubTotalCount; i++)
658 pArray[i] = (sheet::GeneralFunction)pSubTotalFuncs[i];
659 aAny <<= aSeq;
660 xLevProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_SUBTOTALS), aAny );
661 }
662 if ( nShowEmptyMode != SC_DPSAVEMODE_DONTKNOW )
663 lcl_SetBoolProperty( xLevProp,
664 rtl::OUString::createFromAscii(DP_PROP_SHOWEMPTY), (sal_Bool)nShowEmptyMode );
665
666 if ( pSortInfo )
667 ScUnoHelpFunctions::SetOptionalPropertyValue(xLevProp, SC_UNO_SORTING, *pSortInfo);
668
669 if ( pAutoShowInfo )
670 ScUnoHelpFunctions::SetOptionalPropertyValue(xLevProp, SC_UNO_AUTOSHOW, *pAutoShowInfo);
671
672 if ( pLayoutInfo )
673 ScUnoHelpFunctions::SetOptionalPropertyValue(xLevProp, SC_UNO_LAYOUT, *pLayoutInfo);
674
675 // exceptions are caught at ScDPSaveData::WriteToSource
676 }
677
678 if ( nCount > 0 )
679 {
680 uno::Reference<sheet::XMembersSupplier> xMembSupp( xLevel, uno::UNO_QUERY );
681 if ( xMembSupp.is() )
682 {
683 uno::Reference<container::XNameAccess> xMembers = xMembSupp->getMembers();
684 if ( xMembers.is() )
685 {
686 sal_Int32 nPosition = -1; // set position only in manual mode
687 if ( !pSortInfo || pSortInfo->Mode == sheet::DataPilotFieldSortMode::MANUAL )
688 nPosition = 0;
689
690 for (MemberList::const_iterator i=maMemberList.begin(); i != maMemberList.end() ; i++)
691 {
692 ScDPSaveMember* pMember = *i;
693 if (!pMember->GetIsVisible())
694 bHasHiddenMember = true;
695 rtl::OUString aMemberName = pMember->GetName();
696 if ( xMembers->hasByName( aMemberName ) )
697 {
698 uno::Reference<uno::XInterface> xMemberInt = ScUnoHelpFunctions::AnyToInterface(
699 xMembers->getByName( aMemberName ) );
700 pMember->WriteToSource( xMemberInt, nPosition );
701
702 if ( nPosition >= 0 )
703 ++nPosition; // increase if initialized
704 }
705 // missing member is no error
706 }
707 }
708 }
709 }
710 }
711 }
712
713 if (xDimProp.is())
714 ScUnoHelpFunctions::SetOptionalPropertyValue(xDimProp, SC_UNO_HAS_HIDDEN_MEMBER, bHasHiddenMember);
715 }
716
UpdateMemberVisibility(const hash_map<OUString,bool,OUStringHash> & rData)717 void ScDPSaveDimension::UpdateMemberVisibility(const hash_map<OUString, bool, OUStringHash>& rData)
718 {
719 typedef hash_map<OUString, bool, OUStringHash> DataMap;
720 MemberList::iterator itrMem = maMemberList.begin(), itrMemEnd = maMemberList.end();
721 for (; itrMem != itrMemEnd; ++itrMem)
722 {
723 ScDPSaveMember* pMem = *itrMem;
724 const String& rMemName = pMem->GetName();
725 DataMap::const_iterator itr = rData.find(rMemName);
726 if (itr != rData.end())
727 pMem->SetIsVisible(itr->second);
728 }
729 }
730
HasInvisibleMember() const731 bool ScDPSaveDimension::HasInvisibleMember() const
732 {
733 MemberList::const_iterator itrMem = maMemberList.begin(), itrMemEnd = maMemberList.end();
734 for (; itrMem != itrMemEnd; ++itrMem)
735 {
736 const ScDPSaveMember* pMem = *itrMem;
737 if (!pMem->GetIsVisible())
738 return true;
739 }
740 return false;
741 }
742
743 // -----------------------------------------------------------------------
744
ScDPSaveData()745 ScDPSaveData::ScDPSaveData() :
746 pDimensionData( NULL ),
747 nColumnGrandMode( SC_DPSAVEMODE_DONTKNOW ),
748 nRowGrandMode( SC_DPSAVEMODE_DONTKNOW ),
749 nIgnoreEmptyMode( SC_DPSAVEMODE_DONTKNOW ),
750 nRepeatEmptyMode( SC_DPSAVEMODE_DONTKNOW ),
751 bFilterButton( sal_True ),
752 bDrillDown( sal_True ),
753 // Wang Xu Ming -- 2009-8-17
754 // DataPilot Migration - Cache&&Performance
755 mnCacheId( -1),
756 // End Comments
757 mbDimensionMembersBuilt(false),
758 mpGrandTotalName(NULL)
759 {
760 }
761
ScDPSaveData(const ScDPSaveData & r)762 ScDPSaveData::ScDPSaveData(const ScDPSaveData& r) :
763 nColumnGrandMode( r.nColumnGrandMode ),
764 nRowGrandMode( r.nRowGrandMode ),
765 nIgnoreEmptyMode( r.nIgnoreEmptyMode ),
766 nRepeatEmptyMode( r.nRepeatEmptyMode ),
767 bFilterButton( r.bFilterButton ),
768 bDrillDown( r.bDrillDown ),
769 // Wang Xu Ming -- 2009-8-17
770 // DataPilot Migration - Cache&&Performance
771 mnCacheId( r.mnCacheId ),
772 // End Comments
773 mbDimensionMembersBuilt(r.mbDimensionMembersBuilt),
774 mpGrandTotalName(NULL)
775 {
776 if ( r.pDimensionData )
777 pDimensionData = new ScDPDimensionSaveData( *r.pDimensionData );
778 else
779 pDimensionData = NULL;
780
781 long nCount = r.aDimList.Count();
782 for (long i=0; i<nCount; i++)
783 {
784 ScDPSaveDimension* pNew = new ScDPSaveDimension( *(ScDPSaveDimension*)r.aDimList.GetObject(i) );
785 aDimList.Insert( pNew, LIST_APPEND );
786 }
787
788 if (r.mpGrandTotalName.get())
789 mpGrandTotalName.reset(new OUString(*r.mpGrandTotalName));
790 }
791
operator =(const ScDPSaveData & r)792 ScDPSaveData& ScDPSaveData::operator= ( const ScDPSaveData& r )
793 {
794 if ( &r != this )
795 {
796 // Wang Xu Ming -- 2009-8-17
797 // DataPilot Migration - Cache&&Performance
798 this->~ScDPSaveData();
799 new( this ) ScDPSaveData ( r );
800 // End Comments
801 }
802 return *this;
803 }
804
operator ==(const ScDPSaveData & r) const805 sal_Bool ScDPSaveData::operator== ( const ScDPSaveData& r ) const
806 {
807 if ( nColumnGrandMode != r.nColumnGrandMode ||
808 nRowGrandMode != r.nRowGrandMode ||
809 nIgnoreEmptyMode != r.nIgnoreEmptyMode ||
810 nRepeatEmptyMode != r.nRepeatEmptyMode ||
811 bFilterButton != r.bFilterButton ||
812 mnCacheId != r.mnCacheId ||/// Wang Xu Ming -- 2009-6-18 DataPilot Migration
813 bDrillDown != r.bDrillDown ||
814 mbDimensionMembersBuilt != r.mbDimensionMembersBuilt)
815 return sal_False;
816
817 if ( pDimensionData || r.pDimensionData )
818 if ( !pDimensionData || !r.pDimensionData || !( *pDimensionData == *r.pDimensionData ) )
819 return sal_False;
820
821 sal_uLong nCount = aDimList.Count();
822 if ( nCount != r.aDimList.Count() )
823 return sal_False;
824
825 for (sal_uLong i=0; i<nCount; i++)
826 if ( !( *(ScDPSaveDimension*)aDimList.GetObject(i) ==
827 *(ScDPSaveDimension*)r.aDimList.GetObject(i) ) )
828 return sal_False;
829
830 if (mpGrandTotalName.get())
831 {
832 if (!r.mpGrandTotalName.get())
833 return false;
834 if (!mpGrandTotalName->equals(*r.mpGrandTotalName))
835 return false;
836 }
837 else if (r.mpGrandTotalName.get())
838 return false;
839
840 return sal_True;
841 }
842
~ScDPSaveData()843 ScDPSaveData::~ScDPSaveData()
844 {
845 long nCount = aDimList.Count();
846 for (long i=0; i<nCount; i++)
847 delete (ScDPSaveDimension*)aDimList.GetObject(i);
848 aDimList.Clear();
849
850 delete pDimensionData;
851 }
852
SetGrandTotalName(const OUString & rName)853 void ScDPSaveData::SetGrandTotalName(const OUString& rName)
854 {
855 mpGrandTotalName.reset(new OUString(rName));
856 }
857
GetGrandTotalName() const858 const OUString* ScDPSaveData::GetGrandTotalName() const
859 {
860 return mpGrandTotalName.get();
861 }
862
GetDimensionByName(const String & rName)863 ScDPSaveDimension* ScDPSaveData::GetDimensionByName(const String& rName)
864 {
865 long nCount = aDimList.Count();
866 for (long i=0; i<nCount; i++)
867 {
868 ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
869 if ( pDim->GetName() == rName && !pDim->IsDataLayout() )
870 return pDim;
871 }
872 ScDPSaveDimension* pNew = new ScDPSaveDimension( rName, sal_False );
873 aDimList.Insert( pNew, LIST_APPEND );
874 mbDimensionMembersBuilt = false; // BuildAllDimensionMembers only handles existing entries in aDimList
875 return pNew;
876 }
877
GetExistingDimensionByName(const String & rName) const878 ScDPSaveDimension* ScDPSaveData::GetExistingDimensionByName(const String& rName) const
879 {
880 long nCount = aDimList.Count();
881 for (long i=0; i<nCount; i++)
882 {
883 ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
884 if ( pDim->GetName() == rName && !pDim->IsDataLayout() )
885 return pDim;
886 }
887 return NULL; // don't create new
888 }
889
GetNewDimensionByName(const String & rName)890 ScDPSaveDimension* ScDPSaveData::GetNewDimensionByName(const String& rName)
891 {
892 long nCount = aDimList.Count();
893 for (long i=0; i<nCount; i++)
894 {
895 ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
896 if ( pDim->GetName() == rName && !pDim->IsDataLayout() )
897 return DuplicateDimension(rName);
898 }
899 ScDPSaveDimension* pNew = new ScDPSaveDimension( rName, sal_False );
900 aDimList.Insert( pNew, LIST_APPEND );
901 mbDimensionMembersBuilt = false; // BuildAllDimensionMembers only handles existing entries in aDimList
902 return pNew;
903 }
904
GetDataLayoutDimension()905 ScDPSaveDimension* ScDPSaveData::GetDataLayoutDimension()
906 {
907 ScDPSaveDimension* pDim = GetExistingDataLayoutDimension();
908 if (pDim)
909 return pDim;
910
911 ScDPSaveDimension* pNew = new ScDPSaveDimension( String(), sal_True );
912 aDimList.Insert( pNew, LIST_APPEND );
913 mbDimensionMembersBuilt = false; // BuildAllDimensionMembers only handles existing entries in aDimList
914 return pNew;
915 }
916
GetExistingDataLayoutDimension() const917 ScDPSaveDimension* ScDPSaveData::GetExistingDataLayoutDimension() const
918 {
919 long nCount = aDimList.Count();
920 for (long i=0; i<nCount; i++)
921 {
922 ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
923 if ( pDim->IsDataLayout() )
924 return pDim;
925 }
926 return NULL;
927 }
928
DuplicateDimension(const String & rName)929 ScDPSaveDimension* ScDPSaveData::DuplicateDimension(const String& rName)
930 {
931 // always insert new
932 //! check if dimension is there?
933
934 ScDPSaveDimension* pOld = GetDimensionByName( rName );
935 ScDPSaveDimension* pNew = new ScDPSaveDimension( *pOld );
936 pNew->SetDupFlag( sal_True );
937 aDimList.Insert( pNew, LIST_APPEND );
938 mbDimensionMembersBuilt = false; // BuildAllDimensionMembers only handles existing entries in aDimList
939 return pNew;
940 }
941
RemoveDimensionByName(const String & rName)942 void ScDPSaveData::RemoveDimensionByName(const String& rName)
943 {
944 long nCount = aDimList.Count();
945 for (long i=0; i<nCount; i++)
946 {
947 ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
948 if ( pDim->GetName() == rName && !pDim->IsDataLayout() )
949 {
950 delete pDim;
951 aDimList.Remove(i);
952 break;
953 }
954 }
955 }
956
DuplicateDimension(const ScDPSaveDimension & rDim)957 ScDPSaveDimension& ScDPSaveData::DuplicateDimension( const ScDPSaveDimension& rDim )
958 {
959 ScDPSaveDimension* pNew = new ScDPSaveDimension( rDim );
960 pNew->SetDupFlag( sal_True );
961 aDimList.Insert( pNew, LIST_APPEND );
962 mbDimensionMembersBuilt = false; // BuildAllDimensionMembers only handles existing entries in aDimList
963 return *pNew;
964 }
965
GetInnermostDimension(sal_uInt16 nOrientation)966 ScDPSaveDimension* ScDPSaveData::GetInnermostDimension(sal_uInt16 nOrientation)
967 {
968 // return the innermost dimension for the given orientation,
969 // excluding data layout dimension
970
971 ScDPSaveDimension* pInner = NULL;
972 long nCount = aDimList.Count();
973 for (long i=0; i<nCount; i++)
974 {
975 ScDPSaveDimension* pDim = static_cast<ScDPSaveDimension*>(aDimList.GetObject(i));
976 if ( pDim->GetOrientation() == nOrientation && !pDim->IsDataLayout() )
977 pInner = pDim;
978 }
979 return pInner; // the last matching one
980 }
981
GetFirstDimension(sheet::DataPilotFieldOrientation eOrientation)982 ScDPSaveDimension* ScDPSaveData::GetFirstDimension(sheet::DataPilotFieldOrientation eOrientation)
983 {
984 long nCount = aDimList.Count();
985 for (long i = 0; i < nCount; ++i)
986 {
987 ScDPSaveDimension* pDim = static_cast<ScDPSaveDimension*>(aDimList.GetObject(i));
988 if (pDim->GetOrientation() == eOrientation && !pDim->IsDataLayout())
989 return pDim;
990 }
991 return NULL;
992 }
993
GetDataDimensionCount() const994 long ScDPSaveData::GetDataDimensionCount() const
995 {
996 long nDataCount = 0;
997
998 long nCount = aDimList.Count();
999 for (long i=0; i<nCount; i++)
1000 {
1001 const ScDPSaveDimension* pDim = static_cast<const ScDPSaveDimension*>(aDimList.GetObject(i));
1002 if ( pDim->GetOrientation() == sheet::DataPilotFieldOrientation_DATA )
1003 ++nDataCount;
1004 }
1005
1006 return nDataCount;
1007 }
1008
SetPosition(ScDPSaveDimension * pDim,long nNew)1009 void ScDPSaveData::SetPosition( ScDPSaveDimension* pDim, long nNew )
1010 {
1011 // position (nNew) is counted within dimensions of the same orientation
1012
1013 sal_uInt16 nOrient = pDim->GetOrientation();
1014
1015 aDimList.Remove( pDim );
1016 sal_uLong nCount = aDimList.Count(); // after remove
1017
1018 sal_uLong nInsPos = 0;
1019 while ( nNew > 0 && nInsPos < nCount )
1020 {
1021 if ( ((ScDPSaveDimension*)aDimList.GetObject(nInsPos))->GetOrientation() == nOrient )
1022 --nNew;
1023 ++nInsPos;
1024 }
1025
1026 aDimList.Insert( pDim, nInsPos );
1027 }
1028
SetColumnGrand(sal_Bool bSet)1029 void ScDPSaveData::SetColumnGrand(sal_Bool bSet)
1030 {
1031 nColumnGrandMode = bSet;
1032 }
1033
SetRowGrand(sal_Bool bSet)1034 void ScDPSaveData::SetRowGrand(sal_Bool bSet)
1035 {
1036 nRowGrandMode = bSet;
1037 }
1038
SetIgnoreEmptyRows(sal_Bool bSet)1039 void ScDPSaveData::SetIgnoreEmptyRows(sal_Bool bSet)
1040 {
1041 nIgnoreEmptyMode = bSet;
1042 }
1043
SetRepeatIfEmpty(sal_Bool bSet)1044 void ScDPSaveData::SetRepeatIfEmpty(sal_Bool bSet)
1045 {
1046 nRepeatEmptyMode = bSet;
1047 }
1048
SetFilterButton(sal_Bool bSet)1049 void ScDPSaveData::SetFilterButton(sal_Bool bSet)
1050 {
1051 bFilterButton = bSet;
1052 }
1053
SetDrillDown(sal_Bool bSet)1054 void ScDPSaveData::SetDrillDown(sal_Bool bSet)
1055 {
1056 bDrillDown = bSet;
1057 }
1058
lcl_ResetOrient(const uno::Reference<sheet::XDimensionsSupplier> & xSource)1059 void lcl_ResetOrient( const uno::Reference<sheet::XDimensionsSupplier>& xSource )
1060 {
1061 sheet::DataPilotFieldOrientation eOrient = sheet::DataPilotFieldOrientation_HIDDEN;
1062
1063 uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
1064 uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName );
1065 long nIntCount = xIntDims->getCount();
1066 for (long nIntDim=0; nIntDim<nIntCount; nIntDim++)
1067 {
1068 uno::Reference<uno::XInterface> xIntDim = ScUnoHelpFunctions::AnyToInterface( xIntDims->getByIndex(nIntDim) );
1069 uno::Reference<beans::XPropertySet> xDimProp( xIntDim, uno::UNO_QUERY );
1070 if (xDimProp.is())
1071 {
1072 uno::Any aAny;
1073 aAny <<= eOrient;
1074 xDimProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_ORIENTATION), aAny );
1075 }
1076 }
1077 }
1078
WriteToSource(const uno::Reference<sheet::XDimensionsSupplier> & xSource)1079 void ScDPSaveData::WriteToSource( const uno::Reference<sheet::XDimensionsSupplier>& xSource )
1080 {
1081 if (!xSource.is())
1082 return;
1083
1084 // source options must be first!
1085
1086 uno::Reference<beans::XPropertySet> xSourceProp( xSource, uno::UNO_QUERY );
1087 DBG_ASSERT( xSourceProp.is(), "no properties at source" );
1088 if ( xSourceProp.is() )
1089 {
1090 // source options are not available for external sources
1091 //! use XPropertySetInfo to test for availability?
1092
1093 try
1094 {
1095 if ( nIgnoreEmptyMode != SC_DPSAVEMODE_DONTKNOW )
1096 lcl_SetBoolProperty( xSourceProp,
1097 rtl::OUString::createFromAscii(DP_PROP_IGNOREEMPTY), (sal_Bool)nIgnoreEmptyMode );
1098 if ( nRepeatEmptyMode != SC_DPSAVEMODE_DONTKNOW )
1099 lcl_SetBoolProperty( xSourceProp,
1100 rtl::OUString::createFromAscii(DP_PROP_REPEATIFEMPTY), (sal_Bool)nRepeatEmptyMode );
1101 }
1102 catch(uno::Exception&)
1103 {
1104 // no error
1105 }
1106
1107 const OUString* pGrandTotalName = GetGrandTotalName();
1108 if (pGrandTotalName)
1109 ScUnoHelpFunctions::SetOptionalPropertyValue(xSourceProp, SC_UNO_GRANDTOTAL_NAME, *pGrandTotalName);
1110 }
1111
1112 // exceptions in the other calls are errors
1113 try
1114 {
1115 // reset all orientations
1116 //! "forgetSettings" or similar at source ?????
1117 //! reset all duplicated dimensions, or reuse them below !!!
1118 DBG_TRACE( "ScDPSaveData::WriteToSource" );
1119
1120 lcl_ResetOrient( xSource );
1121
1122 long nCount = aDimList.Count();
1123 for (long i=0; i<nCount; i++)
1124 {
1125 ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
1126 rtl::OUString aName = pDim->GetName();
1127
1128 DBG_TRACESTR(pDim->GetName());
1129
1130 sal_Bool bData = pDim->IsDataLayout();
1131
1132 //! getByName for ScDPSource, including DataLayoutDimension !!!!!!!!
1133
1134 uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
1135 uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName );
1136 long nIntCount = xIntDims->getCount();
1137 sal_Bool bFound = sal_False;
1138 for (long nIntDim=0; nIntDim<nIntCount && !bFound; nIntDim++)
1139 {
1140 uno::Reference<uno::XInterface> xIntDim = ScUnoHelpFunctions::AnyToInterface( xIntDims->getByIndex(nIntDim) );
1141 if ( bData )
1142 {
1143 uno::Reference<beans::XPropertySet> xDimProp( xIntDim, uno::UNO_QUERY );
1144 if ( xDimProp.is() )
1145 {
1146 bFound = ScUnoHelpFunctions::GetBoolProperty( xDimProp,
1147 rtl::OUString::createFromAscii(DP_PROP_ISDATALAYOUT) );
1148 //! error checking -- is "IsDataLayoutDimension" property required??
1149 }
1150 }
1151 else
1152 {
1153 uno::Reference<container::XNamed> xDimName( xIntDim, uno::UNO_QUERY );
1154 if ( xDimName.is() && xDimName->getName() == aName )
1155 bFound = sal_True;
1156 }
1157
1158 if ( bFound )
1159 {
1160 if ( pDim->GetDupFlag() )
1161 {
1162 String aNewName = pDim->GetName();
1163
1164 // different name for each duplication of a (real) dimension...
1165 for (long j=0; j<=i; j++) //! Test !!!!!!
1166 aNewName += '*'; //! modify name at creation of SaveDimension
1167
1168 uno::Reference<util::XCloneable> xCloneable( xIntDim, uno::UNO_QUERY );
1169 DBG_ASSERT( xCloneable.is(), "cannot clone dimension" );
1170 if (xCloneable.is())
1171 {
1172 uno::Reference<util::XCloneable> xNew = xCloneable->createClone();
1173 uno::Reference<container::XNamed> xNewName( xNew, uno::UNO_QUERY );
1174 if (xNewName.is())
1175 {
1176 xNewName->setName( aNewName );
1177 pDim->WriteToSource( xNew );
1178 }
1179 }
1180 }
1181 else
1182 pDim->WriteToSource( xIntDim );
1183 }
1184 }
1185 DBG_ASSERT(bFound, "WriteToSource: Dimension not found");
1186 }
1187
1188 if ( xSourceProp.is() )
1189 {
1190 if ( nColumnGrandMode != SC_DPSAVEMODE_DONTKNOW )
1191 lcl_SetBoolProperty( xSourceProp,
1192 rtl::OUString::createFromAscii(DP_PROP_COLUMNGRAND), (sal_Bool)nColumnGrandMode );
1193 if ( nRowGrandMode != SC_DPSAVEMODE_DONTKNOW )
1194 lcl_SetBoolProperty( xSourceProp,
1195 rtl::OUString::createFromAscii(DP_PROP_ROWGRAND), (sal_Bool)nRowGrandMode );
1196 }
1197 }
1198 catch(uno::Exception&)
1199 {
1200 DBG_ERROR("exception in WriteToSource");
1201 }
1202 }
1203
IsEmpty() const1204 sal_Bool ScDPSaveData::IsEmpty() const
1205 {
1206 long nCount = aDimList.Count();
1207 for (long i=0; i<nCount; i++)
1208 {
1209 ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
1210 if ( pDim->GetOrientation() != sheet::DataPilotFieldOrientation_HIDDEN && !pDim->IsDataLayout() )
1211 return sal_False;
1212 }
1213 return sal_True; // no entries that are not hidden
1214 }
1215
GetDimensionData()1216 ScDPDimensionSaveData* ScDPSaveData::GetDimensionData()
1217 {
1218 if (!pDimensionData)
1219 pDimensionData = new ScDPDimensionSaveData;
1220 return pDimensionData;
1221 }
1222
SetDimensionData(const ScDPDimensionSaveData * pNew)1223 void ScDPSaveData::SetDimensionData( const ScDPDimensionSaveData* pNew )
1224 {
1225 delete pDimensionData;
1226 if ( pNew )
1227 pDimensionData = new ScDPDimensionSaveData( *pNew );
1228 else
1229 pDimensionData = NULL;
1230 }
1231
BuildAllDimensionMembers(ScDPTableData * pData)1232 void ScDPSaveData::BuildAllDimensionMembers(ScDPTableData* pData)
1233 {
1234 if (mbDimensionMembersBuilt)
1235 return;
1236
1237 // First, build a dimension name-to-index map.
1238 typedef hash_map<OUString, long, ::rtl::OUStringHash> NameIndexMap;
1239 NameIndexMap aMap;
1240 long nColCount = pData->GetColumnCount();
1241 for (long i = 0; i < nColCount; ++i)
1242 aMap.insert( NameIndexMap::value_type(pData->getDimensionName(i), i));
1243
1244 NameIndexMap::const_iterator itrEnd = aMap.end();
1245
1246 sal_uInt32 n = aDimList.Count();
1247 for (sal_uInt32 i = 0; i < n; ++i)
1248 {
1249 ScDPSaveDimension* pDim = static_cast<ScDPSaveDimension*>(aDimList.GetObject(i));
1250 const String& rDimName = pDim->GetName();
1251 if (!rDimName.Len())
1252 // empty dimension name. It must be data layout.
1253 continue;
1254
1255 NameIndexMap::const_iterator itr = aMap.find(rDimName);
1256 if (itr == itrEnd)
1257 // dimension name not in the data. This should never happen!
1258 continue;
1259
1260 long nDimIndex = itr->second;
1261 const std::vector<SCROW>& rMembers = pData->GetColumnEntries(nDimIndex);
1262 size_t mMemberCount = rMembers.size();
1263 for (size_t j = 0; j < mMemberCount; ++j)
1264 {
1265 const ScDPItemData* pMemberData = pData->GetMemberById( nDimIndex, rMembers[j] );
1266 String aMemName = pMemberData->GetString();
1267 if (pDim->GetExistingMemberByName(aMemName))
1268 // this member instance already exists. nothing to do.
1269 continue;
1270
1271 auto_ptr<ScDPSaveMember> pNewMember(new ScDPSaveMember(aMemName));
1272 pNewMember->SetIsVisible(true);
1273 pDim->AddMember(pNewMember.release());
1274 }
1275 }
1276
1277 mbDimensionMembersBuilt = true;
1278 }
1279
BuildAllDimensionMembersFromSource(ScDPObject * pDPObj)1280 void ScDPSaveData::BuildAllDimensionMembersFromSource( ScDPObject* pDPObj )
1281 {
1282 // Initialize all members like BuildAllDimensionMembers, but access only the DataPilotSource, not the table data.
1283 // This could also replace BuildAllDimensionMembers, but the performance implications still have to be checked.
1284 // ScDPObject is used for the helper method GetMemberNames.
1285
1286 if (mbDimensionMembersBuilt)
1287 return;
1288
1289 uno::Reference<sheet::XDimensionsSupplier> xSource = pDPObj->GetSource();
1290 uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
1291 // GetMemberNames uses the dimension index from getElementNames
1292 uno::Sequence<OUString> aDimNames = xDimsName->getElementNames();
1293
1294 // First, build a dimension name-to-index map.
1295 typedef hash_map<OUString, long, ::rtl::OUStringHash> NameIndexMap;
1296 NameIndexMap aMap;
1297 long nColCount = aDimNames.getLength();
1298 for (long i = 0; i < nColCount; ++i)
1299 aMap.insert( NameIndexMap::value_type(aDimNames[i], i) );
1300
1301 NameIndexMap::const_iterator itrEnd = aMap.end();
1302
1303 sal_uInt32 n = aDimList.Count();
1304 for (sal_uInt32 i = 0; i < n; ++i)
1305 {
1306 ScDPSaveDimension* pDim = static_cast<ScDPSaveDimension*>(aDimList.GetObject(i));
1307 const String& rDimName = pDim->GetName();
1308 if (!rDimName.Len())
1309 // empty dimension name. It must be data layout.
1310 continue;
1311
1312 NameIndexMap::const_iterator itr = aMap.find(rDimName);
1313 if (itr == itrEnd)
1314 // dimension name not in the data. This should never happen!
1315 continue;
1316
1317 long nDimIndex = itr->second;
1318 uno::Sequence<OUString> aMemberNames;
1319 pDPObj->GetMemberNames( nDimIndex, aMemberNames );
1320 sal_Int32 nMemberCount = aMemberNames.getLength();
1321 for (sal_Int32 j = 0; j < nMemberCount; ++j)
1322 {
1323 String aMemName = aMemberNames[j];
1324 if (pDim->GetExistingMemberByName(aMemName))
1325 // this member instance already exists. nothing to do.
1326 continue;
1327
1328 auto_ptr<ScDPSaveMember> pNewMember(new ScDPSaveMember(aMemName));
1329 pNewMember->SetIsVisible(true);
1330 pDim->AddMember(pNewMember.release());
1331 }
1332 }
1333
1334 mbDimensionMembersBuilt = true;
1335 }
1336
HasInvisibleMember(const OUString & rDimName) const1337 bool ScDPSaveData::HasInvisibleMember(const OUString& rDimName) const
1338 {
1339 ScDPSaveDimension* pDim = GetExistingDimensionByName(rDimName);
1340 if (!pDim)
1341 return false;
1342
1343 return pDim->HasInvisibleMember();
1344 }
1345
Refresh(const uno::Reference<sheet::XDimensionsSupplier> & xSource)1346 void ScDPSaveData::Refresh( const uno::Reference<sheet::XDimensionsSupplier>& xSource )
1347 {
1348 try
1349 {
1350 long nCount = aDimList.Count();
1351 std::list<String> deletedDims;
1352 for (long i=nCount-1; i >=0 ; i--)
1353 {
1354 ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
1355
1356 rtl::OUString aName = pDim->GetName();
1357 if ( pDim->IsDataLayout() )
1358 continue;
1359
1360 uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
1361 uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName );
1362 long nIntCount = xIntDims->getCount();
1363 sal_Bool bFound = sal_False;
1364 for (long nIntDim=0; nIntDim<nIntCount && !bFound; nIntDim++)
1365 {
1366 uno::Reference<uno::XInterface> xIntDim = ScUnoHelpFunctions::AnyToInterface( xIntDims->getByIndex(nIntDim) );
1367 uno::Reference<container::XNamed> xDimName( xIntDim, uno::UNO_QUERY );
1368 if ( xDimName.is() && xDimName->getName() == aName )
1369 bFound = sal_True;
1370 }
1371 if ( !bFound )
1372 {
1373 deletedDims.push_back( aName );
1374 aDimList.Remove(i);
1375 DBG_TRACE( "\n Remove dim: \t" );
1376 DBG_TRACESTR( String( aName ) );
1377 }
1378
1379 }
1380
1381 nCount = aDimList.Count();
1382 for (long i=nCount-1; i >=0 ; i--) //check every dimension ??
1383 {
1384 ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
1385
1386 rtl::OUString aName = pDim->GetName();
1387 if ( pDim->IsDataLayout() )
1388 continue;
1389 pDim->Refresh( xSource, deletedDims );
1390
1391 }
1392
1393 mbDimensionMembersBuilt = false; // there may be new members
1394 }
1395 catch(uno::Exception&)
1396 {
1397 DBG_ERROR("error in ScDPSaveData::Refresh");
1398 }
1399
1400 }
Refresh(const com::sun::star::uno::Reference<com::sun::star::sheet::XDimensionsSupplier> & xSource,const std::list<String> & deletedDims)1401 void ScDPSaveDimension::Refresh( const com::sun::star::uno::Reference<
1402 com::sun::star::sheet::XDimensionsSupplier>& xSource ,
1403 const std::list<String>& deletedDims)
1404 {
1405 if ( xSource.is() )
1406 {
1407 ScDPSource* pTabSource = static_cast<ScDPSource*>( xSource.get() );
1408 ScDPTableDataCache* pCache = pTabSource->GetCache();
1409 if ( pCache->GetId() == -1 )
1410 return;
1411
1412 SCCOL nSrcDim = pCache->GetDimensionIndex( GetName() );
1413
1414 if ( nSrcDim == -1 )
1415 return;
1416 if ( pSelectedPage )
1417 {//check pSelected page
1418 DBG_TRACESTR( (*pSelectedPage) );
1419 if ( pCache->GetIdByItemData( nSrcDim, *pSelectedPage ) == -1 )
1420 {
1421 delete pSelectedPage;
1422 pSelectedPage = NULL;
1423 }
1424
1425 };
1426
1427 if ( pReferenceValue && pReferenceValue->ReferenceItemType == DataPilotFieldReferenceItemType::NAMED )
1428 {//check pReferenceValue
1429 #ifdef DEBUG
1430 switch( pReferenceValue->ReferenceType)
1431 {
1432 case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE: //both
1433 DBG_TRACE( "\n sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE \n" );
1434 break;
1435 case sheet::DataPilotFieldReferenceType::ITEM_DIFFERENCE: //both
1436 DBG_TRACE( "\n sheet::DataPilotFieldReferenceType::ITEM_DIFFERENCE \n" );
1437 break;
1438 case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE: //both
1439 DBG_TRACE( "\n sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE \n" );
1440 break;
1441 case sheet::DataPilotFieldReferenceType::RUNNING_TOTAL:
1442 DBG_TRACE( "\n sheet::DataPilotFieldReferenceType::RUNNING_TOTAL \n" ); //enable name
1443 break;
1444 }
1445 #endif
1446 switch( pReferenceValue->ReferenceType)
1447 {
1448 case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE:
1449 case sheet::DataPilotFieldReferenceType::ITEM_DIFFERENCE:
1450 case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE:
1451 case sheet::DataPilotFieldReferenceType::RUNNING_TOTAL:
1452 {
1453 if( pReferenceValue->ReferenceItemType == DataPilotFieldReferenceItemType::NAMED )
1454 {
1455 const String& sReferenceFieldName = pReferenceValue->ReferenceField;
1456 DBG_TRACESTR( sReferenceFieldName );
1457 SCCOL nRefDim = pCache->GetDimensionIndex( sReferenceFieldName );
1458 bool bValid = true;
1459 if ( nRefDim == -1 )
1460 bValid = false;
1461 else if ( pReferenceValue->ReferenceType != sheet::DataPilotFieldReferenceType::RUNNING_TOTAL )
1462 { //running total has not reference item
1463 const String& sReferenceItemName = pReferenceValue->ReferenceItemName;
1464 DBG_TRACESTR( sReferenceItemName );
1465 if ( pCache->GetIdByItemData( nRefDim, sReferenceItemName ) == -1 )
1466 bValid = false;
1467 }
1468 if ( !bValid )
1469 {
1470 delete pReferenceValue;
1471 pReferenceValue = NULL;
1472 }
1473 }
1474 }
1475 break;
1476 }
1477
1478 };
1479
1480 if ( pSortInfo )
1481 { //check sortinfo
1482 if ( pSortInfo->Mode == DataPilotFieldSortMode::DATA )
1483 {
1484 DBG_TRACE( "\n DataPilotFieldSortMode::DATA \n" );
1485 const String& sFieldDimName = pSortInfo->Field;
1486 std::list<String>::const_iterator iter = std::find( deletedDims.begin(), deletedDims.end(), sFieldDimName );
1487 if ( iter != deletedDims.end() && pCache->GetDimensionIndex( sFieldDimName ) == -1 )
1488 {
1489 pSortInfo->Mode = DataPilotFieldSortMode::MANUAL;
1490 pSortInfo->Field = GetName();
1491 }
1492 }
1493
1494 };
1495
1496 if ( pAutoShowInfo )
1497 { //check autoshow
1498 const String& sFieldDimName = pAutoShowInfo->DataField;
1499 std::list<String>::const_iterator iter = std::find( deletedDims.begin(), deletedDims.end(), sFieldDimName );
1500 if ( iter != deletedDims.end() && pCache->GetDimensionIndex( sFieldDimName ) == -1 )
1501 {
1502 delete pAutoShowInfo;
1503 pAutoShowInfo = NULL;
1504 }
1505
1506 };
1507
1508 //remove unused members
1509 for (MemberList::iterator i=maMemberList.begin(); i != maMemberList.end() ; )
1510 {
1511 rtl::OUString aMemberName = (*i)->GetName();
1512 if ( pCache->GetIdByItemData( nSrcDim, aMemberName ) == -1 )
1513 i = maMemberList.erase( i );
1514 else
1515 i++;
1516 }
1517 }
1518 }
1519 // End Comments
operator ==(const::com::sun::star::sheet::DataPilotFieldSortInfo & l,const::com::sun::star::sheet::DataPilotFieldSortInfo & r)1520 bool operator == (const ::com::sun::star::sheet::DataPilotFieldSortInfo &l, const ::com::sun::star::sheet::DataPilotFieldSortInfo &r )
1521 {
1522 return l.Field == r.Field && l.IsAscending == r.IsAscending && l.Mode == r.Mode;
1523 }
operator ==(const::com::sun::star::sheet::DataPilotFieldAutoShowInfo & l,const::com::sun::star::sheet::DataPilotFieldAutoShowInfo & r)1524 bool operator == (const ::com::sun::star::sheet::DataPilotFieldAutoShowInfo &l, const ::com::sun::star::sheet::DataPilotFieldAutoShowInfo &r )
1525 {
1526 return l.IsEnabled == r.IsEnabled &&
1527 l.ShowItemsMode == r.ShowItemsMode &&
1528 l.ItemCount == r.ItemCount &&
1529 l.DataField == r.DataField;
1530 }
operator ==(const::com::sun::star::sheet::DataPilotFieldReference & l,const::com::sun::star::sheet::DataPilotFieldReference & r)1531 bool operator == (const ::com::sun::star::sheet::DataPilotFieldReference &l, const ::com::sun::star::sheet::DataPilotFieldReference &r )
1532 {
1533 return l.ReferenceType == r.ReferenceType &&
1534 l.ReferenceField == r.ReferenceField &&
1535 l.ReferenceItemType == r.ReferenceItemType &&
1536 l.ReferenceItemName == r.ReferenceItemName;
1537 }
1538
1539