1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include "dpdimsave.hxx"
22 #include "dpgroup.hxx"
23 #include "dpobject.hxx"
25 #include "document.hxx"
27 #include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
29 #include <svl/zforlist.hxx>
30 #include <rtl/math.hxx>
34 #include "scresid.hxx"
35 #include "globstr.hrc"
37 using namespace com::sun::star
;
39 // ============================================================================
41 ScDPSaveGroupItem::ScDPSaveGroupItem( const OUString
& rName
) :
44 ScDPSaveGroupItem::~ScDPSaveGroupItem() {}
46 void ScDPSaveGroupItem::AddElement( const OUString
& rName
)
48 aElements
.push_back(rName
);
51 void ScDPSaveGroupItem::AddElementsFromGroup( const ScDPSaveGroupItem
& rGroup
)
53 // add all elements of the other group (used for nested grouping)
55 for ( std::vector
<OUString
>::const_iterator
aIter(rGroup
.aElements
.begin());
56 aIter
!= rGroup
.aElements
.end(); ++aIter
)
57 aElements
.push_back( *aIter
);
60 bool ScDPSaveGroupItem::RemoveElement( const OUString
& rName
)
62 for (std::vector
<OUString
>::iterator aIter
= aElements
.begin(); aIter
!= aElements
.end(); ++aIter
)
63 if (*aIter
== rName
) //! ignore case
65 aElements
.erase(aIter
); // found -> remove
66 return true; // don't have to look further
69 return false; // not found
72 bool ScDPSaveGroupItem::IsEmpty() const
74 return aElements
.empty();
77 size_t ScDPSaveGroupItem::GetElementCount() const
79 return aElements
.size();
82 const OUString
* ScDPSaveGroupItem::GetElementByIndex(size_t nIndex
) const
84 return (nIndex
< aElements
.size()) ? &aElements
[ nIndex
] : 0;
87 void ScDPSaveGroupItem::Rename( const OUString
& rNewName
)
89 aGroupName
= rNewName
;
92 void ScDPSaveGroupItem::RemoveElementsFromGroups( ScDPSaveGroupDimension
& rDimension
) const
94 // remove this group's elements from their groups in rDimension
95 // (rDimension must be a different dimension from the one which contains this)
97 for ( std::vector
<OUString
>::const_iterator
aIter(aElements
.begin()); aIter
!= aElements
.end(); ++aIter
)
98 rDimension
.RemoveFromGroups( *aIter
);
101 void ScDPSaveGroupItem::ConvertElementsToItems(SvNumberFormatter
* pFormatter
) const
103 maItems
.reserve(aElements
.size());
104 std::vector
<OUString
>::const_iterator it
= aElements
.begin(), itEnd
= aElements
.end();
105 for (; it
!= itEnd
; ++it
)
107 sal_uInt32 nFormat
= 0;
110 if (pFormatter
->IsNumberFormat(*it
, nFormat
, fValue
))
111 aData
.SetValue(fValue
);
113 aData
.SetString(*it
);
115 maItems
.push_back(aData
);
119 bool ScDPSaveGroupItem::HasInGroup(const ScDPItemData
& rItem
) const
121 return std::find(maItems
.begin(), maItems
.end(), rItem
) != maItems
.end();
124 void ScDPSaveGroupItem::AddToData(ScDPGroupDimension
& rDataDim
) const
126 ScDPGroupItem
aGroup(aGroupName
);
127 std::vector
<ScDPItemData
>::const_iterator it
= maItems
.begin(), itEnd
= maItems
.end();
128 for (; it
!= itEnd
; ++it
)
129 aGroup
.AddElement(*it
);
131 rDataDim
.AddItem(aGroup
);
134 // ============================================================================
136 ScDPSaveGroupDimension::ScDPSaveGroupDimension( const OUString
& rSource
, const OUString
& rName
) :
137 aSourceDim( rSource
),
138 aGroupDimName( rName
),
143 ScDPSaveGroupDimension::ScDPSaveGroupDimension( const OUString
& rSource
, const OUString
& rName
, const ScDPNumGroupInfo
& rDateInfo
, sal_Int32 nPart
) :
144 aSourceDim( rSource
),
145 aGroupDimName( rName
),
146 aDateInfo( rDateInfo
),
151 ScDPSaveGroupDimension::~ScDPSaveGroupDimension()
155 void ScDPSaveGroupDimension::SetDateInfo( const ScDPNumGroupInfo
& rInfo
, sal_Int32 nPart
)
161 void ScDPSaveGroupDimension::AddGroupItem( const ScDPSaveGroupItem
& rItem
)
163 aGroups
.push_back( rItem
);
166 OUString
ScDPSaveGroupDimension::CreateGroupName(const OUString
& rPrefix
)
168 // create a name for a new group, using "Group1", "Group2" etc. (translated prefix in rPrefix)
170 //! look in all dimensions, to avoid clashes with automatic groups (=name of base element)?
171 //! (only dimensions for the same base)
173 sal_Int32 nAdd
= 1; // first try is "Group1"
174 const sal_Int32 nMaxAdd
= nAdd
+ aGroups
.size(); // limit the loop
175 while ( nAdd
<= nMaxAdd
)
177 OUString aGroupName
= rPrefix
+ OUString::number( nAdd
);
178 bool bExists
= false;
180 // look for existing groups
181 for ( ScDPSaveGroupItemVec::const_iterator
aIter(aGroups
.begin());
182 aIter
!= aGroups
.end() && !bExists
; ++aIter
)
183 if (aIter
->GetGroupName().equals(aGroupName
)) //! ignore case
187 return aGroupName
; // found a new name
189 ++nAdd
; // continue with higher number
192 OSL_FAIL("CreateGroupName: no valid name found");
196 const ScDPSaveGroupItem
* ScDPSaveGroupDimension::GetNamedGroup( const OUString
& rGroupName
) const
198 return const_cast< ScDPSaveGroupDimension
* >( this )->GetNamedGroupAcc( rGroupName
);
201 ScDPSaveGroupItem
* ScDPSaveGroupDimension::GetNamedGroupAcc( const OUString
& rGroupName
)
203 for (ScDPSaveGroupItemVec::iterator aIter
= aGroups
.begin(); aIter
!= aGroups
.end(); ++aIter
)
204 if (aIter
->GetGroupName().equals(rGroupName
)) //! ignore case
207 return NULL
; // none found
210 long ScDPSaveGroupDimension::GetGroupCount() const
212 return aGroups
.size();
215 const ScDPSaveGroupItem
* ScDPSaveGroupDimension::GetGroupByIndex( long nIndex
) const
217 return const_cast< ScDPSaveGroupDimension
* >( this )->GetGroupAccByIndex( nIndex
);
220 ScDPSaveGroupItem
* ScDPSaveGroupDimension::GetGroupAccByIndex( long nIndex
)
222 return &aGroups
[nIndex
];
225 void ScDPSaveGroupDimension::RemoveFromGroups( const OUString
& rItemName
)
227 // if the item is in any group, remove it from the group,
228 // also remove the group if it is empty afterwards
230 for ( ScDPSaveGroupItemVec::iterator
aIter(aGroups
.begin()); aIter
!= aGroups
.end(); ++aIter
)
231 if ( aIter
->RemoveElement( rItemName
) )
233 if ( aIter
->IsEmpty() ) // removed last item from the group?
234 aGroups
.erase( aIter
); // then remove the group
236 return; // don't have to look further
240 void ScDPSaveGroupDimension::RemoveGroup(const OUString
& rGroupName
)
242 for (ScDPSaveGroupItemVec::iterator aIter
= aGroups
.begin(); aIter
!= aGroups
.end(); ++aIter
)
243 if (aIter
->GetGroupName().equals(rGroupName
)) //! ignore case
245 aGroups
.erase( aIter
);
246 return; // don't have to look further
250 bool ScDPSaveGroupDimension::IsEmpty() const
252 return aGroups
.empty();
255 bool ScDPSaveGroupDimension::HasOnlyHidden(const ScDPUniqueStringSet
& rVisible
)
257 // check if there are only groups that don't appear in the list of visible names
259 bool bAllHidden
= true;
260 for (ScDPSaveGroupItemVec::const_iterator aIter
= aGroups
.begin(); aIter
!= aGroups
.end() && bAllHidden
; ++aIter
)
262 if (rVisible
.count(aIter
->GetGroupName()) > 0)
268 void ScDPSaveGroupDimension::Rename( const OUString
& rNewName
)
270 aGroupDimName
= rNewName
;
273 bool ScDPSaveGroupDimension::IsInGroup(const ScDPItemData
& rItem
) const
275 ScDPSaveGroupItemVec::const_iterator it
= aGroups
.begin(), itEnd
= aGroups
.end();
276 for (; it
!= itEnd
; ++it
)
278 if (it
->HasInGroup(rItem
))
286 inline bool isInteger(double fValue
)
288 return rtl::math::approxEqual(fValue
, rtl::math::approxFloor(fValue
));
291 void fillDateGroupDimension(
292 ScDPCache
& rCache
, ScDPNumGroupInfo
& rDateInfo
, long nSourceDim
, long nGroupDim
,
293 sal_Int32 nDatePart
, SvNumberFormatter
* pFormatter
)
295 // Auto min/max is only used for "Years" part, but the loop is always
297 double fSourceMin
= 0.0;
298 double fSourceMax
= 0.0;
301 const ScDPCache::ItemsType
& rItems
= rCache
.GetDimMemberValues(nSourceDim
);
302 ScDPCache::ItemsType::const_iterator it
= rItems
.begin(), itEnd
= rItems
.end();
303 for (; it
!= itEnd
; ++it
)
305 const ScDPItemData
& rItem
= *it
;
306 if (rItem
.GetType() != ScDPItemData::Value
)
309 double fVal
= rItem
.GetValue();
312 fSourceMin
= fSourceMax
= fVal
;
317 if (fVal
< fSourceMin
)
319 if ( fVal
> fSourceMax
)
324 // For the start/end values, use the same date rounding as in
325 // ScDPNumGroupDimension::GetNumEntries (but not for the list of
327 if (rDateInfo
.mbAutoStart
)
328 rDateInfo
.mfStart
= rtl::math::approxFloor(fSourceMin
);
329 if (rDateInfo
.mbAutoEnd
)
330 rDateInfo
.mfEnd
= rtl::math::approxFloor(fSourceMax
) + 1;
332 //! if not automatic, limit fSourceMin/fSourceMax for list of year values?
334 long nStart
= 0, nEnd
= 0; // end is inclusive
338 case sheet::DataPilotFieldGroupBy::YEARS
:
339 nStart
= ScDPUtil::getDatePartValue(
340 fSourceMin
, rDateInfo
, sheet::DataPilotFieldGroupBy::YEARS
, pFormatter
);
341 nEnd
= ScDPUtil::getDatePartValue(fSourceMax
, rDateInfo
, sheet::DataPilotFieldGroupBy::YEARS
, pFormatter
);
343 case sheet::DataPilotFieldGroupBy::QUARTERS
: nStart
= 1; nEnd
= 4; break;
344 case sheet::DataPilotFieldGroupBy::MONTHS
: nStart
= 1; nEnd
= 12; break;
345 case sheet::DataPilotFieldGroupBy::DAYS
: nStart
= 1; nEnd
= 366; break;
346 case sheet::DataPilotFieldGroupBy::HOURS
: nStart
= 0; nEnd
= 23; break;
347 case sheet::DataPilotFieldGroupBy::MINUTES
: nStart
= 0; nEnd
= 59; break;
348 case sheet::DataPilotFieldGroupBy::SECONDS
: nStart
= 0; nEnd
= 59; break;
350 OSL_FAIL("invalid date part");
353 // Now, populate the group items in the cache.
354 rCache
.ResetGroupItems(nGroupDim
, rDateInfo
, nDatePart
);
356 for (sal_Int32 nValue
= nStart
; nValue
<= nEnd
; ++nValue
)
357 rCache
.SetGroupItem(nGroupDim
, ScDPItemData(nDatePart
, nValue
));
359 // add first/last entry (min/max)
360 rCache
.SetGroupItem(nGroupDim
, ScDPItemData(nDatePart
, ScDPItemData::DateFirst
));
361 rCache
.SetGroupItem(nGroupDim
, ScDPItemData(nDatePart
, ScDPItemData::DateLast
));
366 void ScDPSaveGroupDimension::AddToData( ScDPGroupTableData
& rData
) const
368 long nSourceIndex
= rData
.GetDimensionIndex( aSourceDim
);
369 if ( nSourceIndex
>= 0 )
371 ScDPGroupDimension
aDim( nSourceIndex
, aGroupDimName
);
376 aDim
.SetDateDimension();
380 // normal (manual) grouping
382 for (ScDPSaveGroupItemVec::const_iterator
aIter(aGroups
.begin()); aIter
!= aGroups
.end(); ++aIter
)
383 aIter
->AddToData(aDim
);
386 rData
.AddGroupDimension( aDim
);
390 void ScDPSaveGroupDimension::AddToCache(ScDPCache
& rCache
) const
392 long nSourceDim
= rCache
.GetDimensionIndex(aSourceDim
);
396 long nDim
= rCache
.AppendGroupField();
397 SvNumberFormatter
* pFormatter
= rCache
.GetDoc()->GetFormatTable();
401 fillDateGroupDimension(rCache
, aDateInfo
, nSourceDim
, nDim
, nDatePart
, pFormatter
);
405 rCache
.ResetGroupItems(nDim
, aDateInfo
, 0);
407 ScDPSaveGroupItemVec::const_iterator it
= aGroups
.begin(), itEnd
= aGroups
.end();
408 for (; it
!= itEnd
; ++it
)
410 const ScDPSaveGroupItem
& rGI
= *it
;
411 rGI
.ConvertElementsToItems(pFormatter
);
412 rCache
.SetGroupItem(nDim
, ScDPItemData(rGI
.GetGroupName()));
416 const ScDPCache::ItemsType
& rItems
= rCache
.GetDimMemberValues(nSourceDim
);
418 ScDPCache::ItemsType::const_iterator it
= rItems
.begin(), itEnd
= rItems
.end();
419 for (; it
!= itEnd
; ++it
)
421 const ScDPItemData
& rItem
= *it
;
422 if (!IsInGroup(rItem
))
423 // Not in any group. Add as its own group.
424 rCache
.SetGroupItem(nDim
, rItem
);
429 // ============================================================================
431 ScDPSaveNumGroupDimension::ScDPSaveNumGroupDimension( const OUString
& rName
, const ScDPNumGroupInfo
& rInfo
) :
432 aDimensionName( rName
),
438 ScDPSaveNumGroupDimension::ScDPSaveNumGroupDimension( const OUString
& rName
, const ScDPNumGroupInfo
& rDateInfo
, sal_Int32 nPart
) :
439 aDimensionName( rName
),
440 aDateInfo( rDateInfo
),
445 ScDPSaveNumGroupDimension::~ScDPSaveNumGroupDimension()
449 void ScDPSaveNumGroupDimension::AddToData( ScDPGroupTableData
& rData
) const
451 long nSource
= rData
.GetDimensionIndex( aDimensionName
);
454 ScDPNumGroupDimension
aDim( aGroupInfo
); // aGroupInfo: value grouping
456 aDim
.SetDateDimension();
458 rData
.SetNumGroupDimension( nSource
, aDim
);
462 void ScDPSaveNumGroupDimension::AddToCache(ScDPCache
& rCache
) const
464 long nDim
= rCache
.GetDimensionIndex(aDimensionName
);
468 if (aDateInfo
.mbEnable
)
471 SvNumberFormatter
* pFormatter
= rCache
.GetDoc()->GetFormatTable();
472 fillDateGroupDimension(rCache
, aDateInfo
, nDim
, nDim
, nDatePart
, pFormatter
);
474 else if (aGroupInfo
.mbEnable
)
476 // Number-range grouping
478 // Look through the source entries for non-integer numbers, minimum
481 // non-integer GroupInfo values count, too
482 aGroupInfo
.mbIntegerOnly
=
483 (aGroupInfo
.mbAutoStart
|| isInteger(aGroupInfo
.mfStart
)) &&
484 (aGroupInfo
.mbAutoEnd
|| isInteger(aGroupInfo
.mfEnd
)) &&
485 isInteger(aGroupInfo
.mfStep
);
487 double fSourceMin
= 0.0;
488 double fSourceMax
= 0.0;
491 const ScDPCache::ItemsType
& rItems
= rCache
.GetDimMemberValues(nDim
);
492 ScDPCache::ItemsType::const_iterator it
= rItems
.begin(), itEnd
= rItems
.end();
493 for (; it
!= itEnd
; ++it
)
495 const ScDPItemData
& rItem
= *it
;
496 if (rItem
.GetType() != ScDPItemData::Value
)
499 double fValue
= rItem
.GetValue();
502 fSourceMin
= fSourceMax
= fValue
;
507 if (fValue
< fSourceMin
)
509 if (fValue
> fSourceMax
)
512 if (aGroupInfo
.mbIntegerOnly
&& !isInteger(fValue
))
514 // If any non-integer numbers are involved, the group labels
515 // are shown including their upper limit.
516 aGroupInfo
.mbIntegerOnly
= false;
520 if (aGroupInfo
.mbDateValues
)
522 // special handling for dates: always integer, round down limits
523 aGroupInfo
.mbIntegerOnly
= true;
524 fSourceMin
= rtl::math::approxFloor(fSourceMin
);
525 fSourceMax
= rtl::math::approxFloor(fSourceMax
) + 1;
528 if (aGroupInfo
.mbAutoStart
)
529 aGroupInfo
.mfStart
= fSourceMin
;
530 if (aGroupInfo
.mbAutoEnd
)
531 aGroupInfo
.mfEnd
= fSourceMax
;
533 //! limit number of entries?
536 double fLoop
= aGroupInfo
.mfStart
;
538 rCache
.ResetGroupItems(nDim
, aGroupInfo
, 0);
540 // Use "less than" instead of "less or equal" for the loop - don't
541 // create a group that consists only of the end value. Instead, the
542 // end value is then included in the last group (last group is bigger
543 // than the others). The first group has to be created nonetheless.
544 // GetNumGroupForValue has corresponding logic.
546 bool bFirstGroup
= true;
547 while (bFirstGroup
|| (fLoop
< aGroupInfo
.mfEnd
&& !rtl::math::approxEqual(fLoop
, aGroupInfo
.mfEnd
)))
550 aItem
.SetRangeStart(fLoop
);
551 rCache
.SetGroupItem(nDim
, aItem
);
553 fLoop
= aGroupInfo
.mfStart
+ nLoopCount
* aGroupInfo
.mfStep
;
556 // ScDPItemData values are compared with approxEqual
560 aItem
.SetRangeFirst();
561 rCache
.SetGroupItem(nDim
, aItem
);
563 aItem
.SetRangeLast();
564 rCache
.SetGroupItem(nDim
, aItem
);
568 void ScDPSaveNumGroupDimension::SetGroupInfo( const ScDPNumGroupInfo
& rNew
)
573 void ScDPSaveNumGroupDimension::SetDateInfo( const ScDPNumGroupInfo
& rInfo
, sal_Int32 nPart
)
579 // ============================================================================
583 struct ScDPSaveGroupDimNameFunc
586 inline explicit ScDPSaveGroupDimNameFunc( const OUString
& rDimName
) : maDimName( rDimName
) {}
587 inline bool operator()( const ScDPSaveGroupDimension
& rGroupDim
) const { return rGroupDim
.GetGroupDimName() == maDimName
; }
590 struct ScDPSaveGroupSourceNameFunc
592 OUString maSrcDimName
;
593 inline explicit ScDPSaveGroupSourceNameFunc( const OUString
& rSrcDimName
) : maSrcDimName( rSrcDimName
) {}
594 inline bool operator()( const ScDPSaveGroupDimension
& rGroupDim
) const { return rGroupDim
.GetSourceDimName() == maSrcDimName
; }
599 // ----------------------------------------------------------------------------
601 ScDPDimensionSaveData::ScDPDimensionSaveData()
605 ScDPDimensionSaveData::~ScDPDimensionSaveData()
609 bool ScDPDimensionSaveData::operator==( const ScDPDimensionSaveData
& ) const
614 void ScDPDimensionSaveData::AddGroupDimension( const ScDPSaveGroupDimension
& rGroupDim
)
616 OSL_ENSURE( ::std::find_if( maGroupDims
.begin(), maGroupDims
.end(), ScDPSaveGroupDimNameFunc( rGroupDim
.GetGroupDimName() ) ) == maGroupDims
.end(),
617 "ScDPDimensionSaveData::AddGroupDimension - group dimension exists already" );
618 // ReplaceGroupDimension() adds new or replaces existing
619 ReplaceGroupDimension( rGroupDim
);
622 void ScDPDimensionSaveData::ReplaceGroupDimension( const ScDPSaveGroupDimension
& rGroupDim
)
624 ScDPSaveGroupDimVec::iterator aIt
= ::std::find_if(
625 maGroupDims
.begin(), maGroupDims
.end(), ScDPSaveGroupDimNameFunc( rGroupDim
.GetGroupDimName() ) );
626 if( aIt
== maGroupDims
.end() )
627 maGroupDims
.push_back( rGroupDim
);
632 void ScDPDimensionSaveData::RemoveGroupDimension( const OUString
& rGroupDimName
)
634 ScDPSaveGroupDimVec::iterator aIt
= ::std::find_if(
635 maGroupDims
.begin(), maGroupDims
.end(), ScDPSaveGroupDimNameFunc( rGroupDimName
) );
636 if( aIt
!= maGroupDims
.end() )
637 maGroupDims
.erase( aIt
);
640 void ScDPDimensionSaveData::AddNumGroupDimension( const ScDPSaveNumGroupDimension
& rGroupDim
)
642 OSL_ENSURE( maNumGroupDims
.count( rGroupDim
.GetDimensionName() ) == 0,
643 "ScDPDimensionSaveData::AddNumGroupDimension - numeric group dimension exists already" );
644 // ReplaceNumGroupDimension() adds new or replaces existing
645 ReplaceNumGroupDimension( rGroupDim
);
648 void ScDPDimensionSaveData::ReplaceNumGroupDimension( const ScDPSaveNumGroupDimension
& rGroupDim
)
650 ScDPSaveNumGroupDimMap::iterator aIt
= maNumGroupDims
.find( rGroupDim
.GetDimensionName() );
651 if( aIt
== maNumGroupDims
.end() )
652 maNumGroupDims
.insert( ScDPSaveNumGroupDimMap::value_type( rGroupDim
.GetDimensionName(), rGroupDim
) );
654 aIt
->second
= rGroupDim
;
657 void ScDPDimensionSaveData::RemoveNumGroupDimension( const OUString
& rGroupDimName
)
659 maNumGroupDims
.erase( rGroupDimName
);
662 void ScDPDimensionSaveData::WriteToData( ScDPGroupTableData
& rData
) const
664 // rData is assumed to be empty
665 // AddToData also handles date grouping
667 for( ScDPSaveGroupDimVec::const_iterator aIt
= maGroupDims
.begin(), aEnd
= maGroupDims
.end(); aIt
!= aEnd
; ++aIt
)
668 aIt
->AddToData( rData
);
670 for( ScDPSaveNumGroupDimMap::const_iterator aIt
= maNumGroupDims
.begin(), aEnd
= maNumGroupDims
.end(); aIt
!= aEnd
; ++aIt
)
671 aIt
->second
.AddToData( rData
);
676 class AddGroupDimToCache
: std::unary_function
<ScDPSaveGroupDimension
, void>
680 AddGroupDimToCache(ScDPCache
& rCache
) : mrCache(rCache
) {}
681 void operator() (const ScDPSaveGroupDimension
& rDim
)
683 rDim
.AddToCache(mrCache
);
689 void ScDPDimensionSaveData::WriteToCache(ScDPCache
& rCache
) const
691 std::for_each(maGroupDims
.begin(), maGroupDims
.end(), AddGroupDimToCache(rCache
));
692 ScDPSaveNumGroupDimMap::const_iterator it
= maNumGroupDims
.begin(), itEnd
= maNumGroupDims
.end();
693 for (; it
!= itEnd
; ++it
)
694 it
->second
.AddToCache(rCache
);
697 const ScDPSaveGroupDimension
* ScDPDimensionSaveData::GetGroupDimForBase( const OUString
& rBaseDimName
) const
699 return const_cast< ScDPDimensionSaveData
* >( this )->GetGroupDimAccForBase( rBaseDimName
);
702 const ScDPSaveGroupDimension
* ScDPDimensionSaveData::GetNamedGroupDim( const OUString
& rGroupDimName
) const
704 return const_cast< ScDPDimensionSaveData
* >( this )->GetNamedGroupDimAcc( rGroupDimName
);
707 const ScDPSaveGroupDimension
* ScDPDimensionSaveData::GetFirstNamedGroupDim( const OUString
& rBaseDimName
) const
709 return const_cast< ScDPDimensionSaveData
* >( this )->GetFirstNamedGroupDimAcc( rBaseDimName
);
712 const ScDPSaveGroupDimension
* ScDPDimensionSaveData::GetNextNamedGroupDim( const OUString
& rGroupDimName
) const
714 return const_cast< ScDPDimensionSaveData
* >( this )->GetNextNamedGroupDimAcc( rGroupDimName
);
717 const ScDPSaveNumGroupDimension
* ScDPDimensionSaveData::GetNumGroupDim( const OUString
& rGroupDimName
) const
719 return const_cast< ScDPDimensionSaveData
* >( this )->GetNumGroupDimAcc( rGroupDimName
);
722 ScDPSaveGroupDimension
* ScDPDimensionSaveData::GetGroupDimAccForBase( const OUString
& rBaseDimName
)
724 ScDPSaveGroupDimension
* pGroupDim
= GetFirstNamedGroupDimAcc( rBaseDimName
);
725 return pGroupDim
? pGroupDim
: GetNextNamedGroupDimAcc( rBaseDimName
);
728 ScDPSaveGroupDimension
* ScDPDimensionSaveData::GetNamedGroupDimAcc( const OUString
& rGroupDimName
)
730 ScDPSaveGroupDimVec::iterator aIt
= ::std::find_if(
731 maGroupDims
.begin(), maGroupDims
.end(), ScDPSaveGroupDimNameFunc( rGroupDimName
) );
732 return (aIt
== maGroupDims
.end()) ? 0 : &*aIt
;
735 ScDPSaveGroupDimension
* ScDPDimensionSaveData::GetFirstNamedGroupDimAcc( const OUString
& rBaseDimName
)
737 ScDPSaveGroupDimVec::iterator aIt
= ::std::find_if(
738 maGroupDims
.begin(), maGroupDims
.end(), ScDPSaveGroupSourceNameFunc( rBaseDimName
) );
739 return (aIt
== maGroupDims
.end()) ? 0 : &*aIt
;
742 ScDPSaveGroupDimension
* ScDPDimensionSaveData::GetNextNamedGroupDimAcc( const OUString
& rGroupDimName
)
744 // find the group dimension with the passed name
745 ScDPSaveGroupDimVec::iterator aIt
= ::std::find_if(
746 maGroupDims
.begin(), maGroupDims
.end(), ScDPSaveGroupDimNameFunc( rGroupDimName
) );
747 // find next group dimension based on the same source dimension name
748 if( aIt
!= maGroupDims
.end() )
749 aIt
= ::std::find_if( aIt
+ 1, maGroupDims
.end(), ScDPSaveGroupSourceNameFunc( aIt
->GetSourceDimName() ) );
750 return (aIt
== maGroupDims
.end()) ? 0 : &*aIt
;
753 ScDPSaveNumGroupDimension
* ScDPDimensionSaveData::GetNumGroupDimAcc( const OUString
& rGroupDimName
)
755 ScDPSaveNumGroupDimMap::iterator aIt
= maNumGroupDims
.find( rGroupDimName
);
756 return (aIt
== maNumGroupDims
.end()) ? 0 : &aIt
->second
;
759 bool ScDPDimensionSaveData::HasGroupDimensions() const
761 return !maGroupDims
.empty() || !maNumGroupDims
.empty();
764 sal_Int32
ScDPDimensionSaveData::CollectDateParts( const OUString
& rBaseDimName
) const
766 sal_Int32 nParts
= 0;
767 // start with part of numeric group
768 if( const ScDPSaveNumGroupDimension
* pNumDim
= GetNumGroupDim( rBaseDimName
) )
769 nParts
|= pNumDim
->GetDatePart();
770 // collect parts from all matching group dimensions
771 for( const ScDPSaveGroupDimension
* pGroupDim
= GetFirstNamedGroupDim( rBaseDimName
); pGroupDim
; pGroupDim
= GetNextNamedGroupDim( pGroupDim
->GetGroupDimName() ) )
772 nParts
|= pGroupDim
->GetDatePart();
777 OUString
ScDPDimensionSaveData::CreateGroupDimName(
778 const OUString
& rSourceName
, const ScDPObject
& rObject
, bool bAllowSource
,
779 const std::vector
<OUString
>* pDeletedNames
)
781 // create a name for the new dimension by appending a number to the original
784 bool bUseSource
= bAllowSource
; // if set, try the unchanged original name first
786 sal_Int32 nAdd
= 2; // first try is "Name2"
787 const sal_Int32 nMaxAdd
= 1000; // limit the loop
788 while ( nAdd
<= nMaxAdd
)
790 OUString
aDimName( rSourceName
);
792 aDimName
+= OUString::number(nAdd
);
793 bool bExists
= false;
795 // look for existing group dimensions
796 for( ScDPSaveGroupDimVec::const_iterator aIt
= maGroupDims
.begin(), aEnd
= maGroupDims
.end(); (aIt
!= aEnd
) && !bExists
; ++aIt
)
797 if( aIt
->GetGroupDimName() == aDimName
) //! ignore case
800 // look for base dimensions that happen to have that name
801 if ( !bExists
&& rObject
.IsDimNameInUse( aDimName
) )
803 if ( pDeletedNames
&&
804 std::find( pDeletedNames
->begin(), pDeletedNames
->end(), aDimName
) != pDeletedNames
->end() )
806 // allow the name anyway if the name is in pDeletedNames
813 return aDimName
; // found a new name
818 ++nAdd
; // continue with higher number
820 OSL_FAIL("CreateGroupDimName: no valid name found");
826 static const sal_uInt16 nDatePartIds
[] =
828 STR_DPFIELD_GROUP_BY_SECONDS
,
829 STR_DPFIELD_GROUP_BY_MINUTES
,
830 STR_DPFIELD_GROUP_BY_HOURS
,
831 STR_DPFIELD_GROUP_BY_DAYS
,
832 STR_DPFIELD_GROUP_BY_MONTHS
,
833 STR_DPFIELD_GROUP_BY_QUARTERS
,
834 STR_DPFIELD_GROUP_BY_YEARS
838 OUString
ScDPDimensionSaveData::CreateDateGroupDimName(
839 sal_Int32 nDatePart
, const ScDPObject
& rObject
, bool bAllowSource
,
840 const std::vector
<OUString
>* pDeletedNames
)
842 using namespace ::com::sun::star::sheet::DataPilotFieldGroupBy
;
846 case SECONDS
: aPartName
= ScGlobal::GetRscString( nDatePartIds
[0] ); break;
847 case MINUTES
: aPartName
= ScGlobal::GetRscString( nDatePartIds
[1] ); break;
848 case HOURS
: aPartName
= ScGlobal::GetRscString( nDatePartIds
[2] ); break;
849 case DAYS
: aPartName
= ScGlobal::GetRscString( nDatePartIds
[3] ); break;
850 case MONTHS
: aPartName
= ScGlobal::GetRscString( nDatePartIds
[4] ); break;
851 case QUARTERS
: aPartName
= ScGlobal::GetRscString( nDatePartIds
[5] ); break;
852 case YEARS
: aPartName
= ScGlobal::GetRscString( nDatePartIds
[6] ); break;
854 OSL_ENSURE(!aPartName
.isEmpty(), "ScDPDimensionSaveData::CreateDateGroupDimName - invalid date part");
855 return CreateGroupDimName( aPartName
, rObject
, bAllowSource
, pDeletedNames
);
858 // ============================================================================
860 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */