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