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 .
20 #include "dpdimsave.hxx"
21 #include "dpgroup.hxx"
22 #include "dpobject.hxx"
24 #include "document.hxx"
26 #include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
28 #include <svl/zforlist.hxx>
29 #include <rtl/math.hxx>
33 #include "scresid.hxx"
34 #include "globstr.hrc"
36 using namespace com::sun::star
;
38 ScDPSaveGroupItem::ScDPSaveGroupItem( const OUString
& rName
) :
41 ScDPSaveGroupItem::~ScDPSaveGroupItem() {}
43 void ScDPSaveGroupItem::AddElement( const OUString
& rName
)
45 aElements
.push_back(rName
);
48 void ScDPSaveGroupItem::AddElementsFromGroup( const ScDPSaveGroupItem
& rGroup
)
50 // add all elements of the other group (used for nested grouping)
52 for ( std::vector
<OUString
>::const_iterator
aIter(rGroup
.aElements
.begin());
53 aIter
!= rGroup
.aElements
.end(); ++aIter
)
54 aElements
.push_back( *aIter
);
57 bool ScDPSaveGroupItem::RemoveElement( const OUString
& rName
)
59 for (std::vector
<OUString
>::iterator aIter
= aElements
.begin(); aIter
!= aElements
.end(); ++aIter
)
60 if (*aIter
== rName
) //TODO: ignore case
62 aElements
.erase(aIter
); // found -> remove
63 return true; // don't have to look further
66 return false; // not found
69 bool ScDPSaveGroupItem::IsEmpty() const
71 return aElements
.empty();
74 size_t ScDPSaveGroupItem::GetElementCount() const
76 return aElements
.size();
79 const OUString
* ScDPSaveGroupItem::GetElementByIndex(size_t nIndex
) const
81 return (nIndex
< aElements
.size()) ? &aElements
[ nIndex
] : 0;
84 void ScDPSaveGroupItem::Rename( const OUString
& rNewName
)
86 aGroupName
= rNewName
;
89 void ScDPSaveGroupItem::RemoveElementsFromGroups( ScDPSaveGroupDimension
& rDimension
) const
91 // remove this group's elements from their groups in rDimension
92 // (rDimension must be a different dimension from the one which contains this)
94 for ( std::vector
<OUString
>::const_iterator
aIter(aElements
.begin()); aIter
!= aElements
.end(); ++aIter
)
95 rDimension
.RemoveFromGroups( *aIter
);
98 void ScDPSaveGroupItem::ConvertElementsToItems(SvNumberFormatter
* pFormatter
) const
100 maItems
.reserve(aElements
.size());
101 std::vector
<OUString
>::const_iterator it
= aElements
.begin(), itEnd
= aElements
.end();
102 for (; it
!= itEnd
; ++it
)
104 sal_uInt32 nFormat
= 0;
107 if (pFormatter
->IsNumberFormat(*it
, nFormat
, fValue
))
108 aData
.SetValue(fValue
);
110 aData
.SetString(*it
);
112 maItems
.push_back(aData
);
116 bool ScDPSaveGroupItem::HasInGroup(const ScDPItemData
& rItem
) const
118 return std::find(maItems
.begin(), maItems
.end(), rItem
) != maItems
.end();
121 void ScDPSaveGroupItem::AddToData(ScDPGroupDimension
& rDataDim
) const
123 ScDPGroupItem
aGroup(aGroupName
);
124 std::vector
<ScDPItemData
>::const_iterator it
= maItems
.begin(), itEnd
= maItems
.end();
125 for (; it
!= itEnd
; ++it
)
126 aGroup
.AddElement(*it
);
128 rDataDim
.AddItem(aGroup
);
131 ScDPSaveGroupDimension::ScDPSaveGroupDimension( const OUString
& rSource
, const OUString
& rName
) :
132 aSourceDim( rSource
),
133 aGroupDimName( rName
),
138 ScDPSaveGroupDimension::ScDPSaveGroupDimension( const OUString
& rSource
, const OUString
& rName
, const ScDPNumGroupInfo
& rDateInfo
, sal_Int32 nPart
) :
139 aSourceDim( rSource
),
140 aGroupDimName( rName
),
141 aDateInfo( rDateInfo
),
146 ScDPSaveGroupDimension::~ScDPSaveGroupDimension()
150 void ScDPSaveGroupDimension::SetDateInfo( const ScDPNumGroupInfo
& rInfo
, sal_Int32 nPart
)
156 void ScDPSaveGroupDimension::AddGroupItem( const ScDPSaveGroupItem
& rItem
)
158 aGroups
.push_back( rItem
);
161 OUString
ScDPSaveGroupDimension::CreateGroupName(const OUString
& rPrefix
)
163 // create a name for a new group, using "Group1", "Group2" etc. (translated prefix in rPrefix)
165 //TODO: look in all dimensions, to avoid clashes with automatic groups (=name of base element)?
166 //TODO: (only dimensions for the same base)
168 sal_Int32 nAdd
= 1; // first try is "Group1"
169 const sal_Int32 nMaxAdd
= nAdd
+ aGroups
.size(); // limit the loop
170 while ( nAdd
<= nMaxAdd
)
172 OUString aGroupName
= rPrefix
+ OUString::number( nAdd
);
173 bool bExists
= false;
175 // look for existing groups
176 for ( ScDPSaveGroupItemVec::const_iterator
aIter(aGroups
.begin());
177 aIter
!= aGroups
.end() && !bExists
; ++aIter
)
178 if (aIter
->GetGroupName().equals(aGroupName
)) //TODO: ignore case
182 return aGroupName
; // found a new name
184 ++nAdd
; // continue with higher number
187 OSL_FAIL("CreateGroupName: no valid name found");
191 const ScDPSaveGroupItem
* ScDPSaveGroupDimension::GetNamedGroup( const OUString
& rGroupName
) const
193 return const_cast< ScDPSaveGroupDimension
* >( this )->GetNamedGroupAcc( rGroupName
);
196 ScDPSaveGroupItem
* ScDPSaveGroupDimension::GetNamedGroupAcc( const OUString
& rGroupName
)
198 for (ScDPSaveGroupItemVec::iterator aIter
= aGroups
.begin(); aIter
!= aGroups
.end(); ++aIter
)
199 if (aIter
->GetGroupName().equals(rGroupName
)) //TODO: ignore case
202 return NULL
; // none found
205 long ScDPSaveGroupDimension::GetGroupCount() const
207 return aGroups
.size();
210 const ScDPSaveGroupItem
* ScDPSaveGroupDimension::GetGroupByIndex( long nIndex
) const
212 return const_cast< ScDPSaveGroupDimension
* >( this )->GetGroupAccByIndex( nIndex
);
215 ScDPSaveGroupItem
* ScDPSaveGroupDimension::GetGroupAccByIndex( long nIndex
)
217 return &aGroups
[nIndex
];
220 void ScDPSaveGroupDimension::RemoveFromGroups( const OUString
& rItemName
)
222 // if the item is in any group, remove it from the group,
223 // also remove the group if it is empty afterwards
225 for ( ScDPSaveGroupItemVec::iterator
aIter(aGroups
.begin()); aIter
!= aGroups
.end(); ++aIter
)
226 if ( aIter
->RemoveElement( rItemName
) )
228 if ( aIter
->IsEmpty() ) // removed last item from the group?
229 aGroups
.erase( aIter
); // then remove the group
231 return; // don't have to look further
235 void ScDPSaveGroupDimension::RemoveGroup(const OUString
& rGroupName
)
237 for (ScDPSaveGroupItemVec::iterator aIter
= aGroups
.begin(); aIter
!= aGroups
.end(); ++aIter
)
238 if (aIter
->GetGroupName().equals(rGroupName
)) //TODO: ignore case
240 aGroups
.erase( aIter
);
241 return; // don't have to look further
245 bool ScDPSaveGroupDimension::IsEmpty() const
247 return aGroups
.empty();
250 bool ScDPSaveGroupDimension::HasOnlyHidden(const ScDPUniqueStringSet
& rVisible
)
252 // check if there are only groups that don't appear in the list of visible names
254 bool bAllHidden
= true;
255 for (ScDPSaveGroupItemVec::const_iterator aIter
= aGroups
.begin(); aIter
!= aGroups
.end() && bAllHidden
; ++aIter
)
257 if (rVisible
.count(aIter
->GetGroupName()) > 0)
263 void ScDPSaveGroupDimension::Rename( const OUString
& rNewName
)
265 aGroupDimName
= rNewName
;
268 bool ScDPSaveGroupDimension::IsInGroup(const ScDPItemData
& rItem
) const
270 ScDPSaveGroupItemVec::const_iterator it
= aGroups
.begin(), itEnd
= aGroups
.end();
271 for (; it
!= itEnd
; ++it
)
273 if (it
->HasInGroup(rItem
))
281 inline bool isInteger(double fValue
)
283 return rtl::math::approxEqual(fValue
, rtl::math::approxFloor(fValue
));
286 void fillDateGroupDimension(
287 ScDPCache
& rCache
, ScDPNumGroupInfo
& rDateInfo
, long nSourceDim
, long nGroupDim
,
288 sal_Int32 nDatePart
, SvNumberFormatter
* pFormatter
)
290 // Auto min/max is only used for "Years" part, but the loop is always
292 double fSourceMin
= 0.0;
293 double fSourceMax
= 0.0;
296 const ScDPCache::ItemsType
& rItems
= rCache
.GetDimMemberValues(nSourceDim
);
297 ScDPCache::ItemsType::const_iterator it
= rItems
.begin(), itEnd
= rItems
.end();
298 for (; it
!= itEnd
; ++it
)
300 const ScDPItemData
& rItem
= *it
;
301 if (rItem
.GetType() != ScDPItemData::Value
)
304 double fVal
= rItem
.GetValue();
307 fSourceMin
= fSourceMax
= fVal
;
312 if (fVal
< fSourceMin
)
314 if ( fVal
> fSourceMax
)
319 // For the start/end values, use the same date rounding as in
320 // ScDPNumGroupDimension::GetNumEntries (but not for the list of
322 if (rDateInfo
.mbAutoStart
)
323 rDateInfo
.mfStart
= rtl::math::approxFloor(fSourceMin
);
324 if (rDateInfo
.mbAutoEnd
)
325 rDateInfo
.mfEnd
= rtl::math::approxFloor(fSourceMax
) + 1;
327 //TODO: if not automatic, limit fSourceMin/fSourceMax for list of year values?
329 long nStart
= 0, nEnd
= 0; // end is inclusive
333 case sheet::DataPilotFieldGroupBy::YEARS
:
334 nStart
= ScDPUtil::getDatePartValue(
335 fSourceMin
, NULL
, sheet::DataPilotFieldGroupBy::YEARS
, pFormatter
);
336 nEnd
= ScDPUtil::getDatePartValue(fSourceMax
, NULL
, sheet::DataPilotFieldGroupBy::YEARS
, pFormatter
);
338 case sheet::DataPilotFieldGroupBy::QUARTERS
: nStart
= 1; nEnd
= 4; break;
339 case sheet::DataPilotFieldGroupBy::MONTHS
: nStart
= 1; nEnd
= 12; break;
340 case sheet::DataPilotFieldGroupBy::DAYS
: nStart
= 1; nEnd
= 366; break;
341 case sheet::DataPilotFieldGroupBy::HOURS
: nStart
= 0; nEnd
= 23; break;
342 case sheet::DataPilotFieldGroupBy::MINUTES
: nStart
= 0; nEnd
= 59; break;
343 case sheet::DataPilotFieldGroupBy::SECONDS
: nStart
= 0; nEnd
= 59; break;
345 OSL_FAIL("invalid date part");
348 // Now, populate the group items in the cache.
349 rCache
.ResetGroupItems(nGroupDim
, rDateInfo
, nDatePart
);
351 for (sal_Int32 nValue
= nStart
; nValue
<= nEnd
; ++nValue
)
352 rCache
.SetGroupItem(nGroupDim
, ScDPItemData(nDatePart
, nValue
));
354 // add first/last entry (min/max)
355 rCache
.SetGroupItem(nGroupDim
, ScDPItemData(nDatePart
, ScDPItemData::DateFirst
));
356 rCache
.SetGroupItem(nGroupDim
, ScDPItemData(nDatePart
, ScDPItemData::DateLast
));
361 void ScDPSaveGroupDimension::AddToData( ScDPGroupTableData
& rData
) const
363 long nSourceIndex
= rData
.GetDimensionIndex( aSourceDim
);
364 if ( nSourceIndex
>= 0 )
366 ScDPGroupDimension
aDim( nSourceIndex
, aGroupDimName
);
371 aDim
.SetDateDimension();
375 // normal (manual) grouping
377 for (ScDPSaveGroupItemVec::const_iterator
aIter(aGroups
.begin()); aIter
!= aGroups
.end(); ++aIter
)
378 aIter
->AddToData(aDim
);
381 rData
.AddGroupDimension( aDim
);
385 void ScDPSaveGroupDimension::AddToCache(ScDPCache
& rCache
) const
387 long nSourceDim
= rCache
.GetDimensionIndex(aSourceDim
);
391 long nDim
= rCache
.AppendGroupField();
392 SvNumberFormatter
* pFormatter
= rCache
.GetDoc()->GetFormatTable();
396 fillDateGroupDimension(rCache
, aDateInfo
, nSourceDim
, nDim
, nDatePart
, pFormatter
);
400 rCache
.ResetGroupItems(nDim
, aDateInfo
, 0);
402 ScDPSaveGroupItemVec::const_iterator it
= aGroups
.begin(), itEnd
= aGroups
.end();
403 for (; it
!= itEnd
; ++it
)
405 const ScDPSaveGroupItem
& rGI
= *it
;
406 rGI
.ConvertElementsToItems(pFormatter
);
407 rCache
.SetGroupItem(nDim
, ScDPItemData(rGI
.GetGroupName()));
411 const ScDPCache::ItemsType
& rItems
= rCache
.GetDimMemberValues(nSourceDim
);
413 ScDPCache::ItemsType::const_iterator it
= rItems
.begin(), itEnd
= rItems
.end();
414 for (; it
!= itEnd
; ++it
)
416 const ScDPItemData
& rItem
= *it
;
417 if (!IsInGroup(rItem
))
418 // Not in any group. Add as its own group.
419 rCache
.SetGroupItem(nDim
, rItem
);
424 ScDPSaveNumGroupDimension::ScDPSaveNumGroupDimension( const OUString
& rName
, const ScDPNumGroupInfo
& rInfo
) :
425 aDimensionName( rName
),
431 ScDPSaveNumGroupDimension::ScDPSaveNumGroupDimension( const OUString
& rName
, const ScDPNumGroupInfo
& rDateInfo
, sal_Int32 nPart
) :
432 aDimensionName( rName
),
433 aDateInfo( rDateInfo
),
438 ScDPSaveNumGroupDimension::~ScDPSaveNumGroupDimension()
442 void ScDPSaveNumGroupDimension::AddToData( ScDPGroupTableData
& rData
) const
444 long nSource
= rData
.GetDimensionIndex( aDimensionName
);
447 ScDPNumGroupDimension
aDim( aGroupInfo
); // aGroupInfo: value grouping
449 aDim
.SetDateDimension();
451 rData
.SetNumGroupDimension( nSource
, aDim
);
455 void ScDPSaveNumGroupDimension::AddToCache(ScDPCache
& rCache
) const
457 long nDim
= rCache
.GetDimensionIndex(aDimensionName
);
461 if (aDateInfo
.mbEnable
)
464 SvNumberFormatter
* pFormatter
= rCache
.GetDoc()->GetFormatTable();
465 fillDateGroupDimension(rCache
, aDateInfo
, nDim
, nDim
, nDatePart
, pFormatter
);
467 else if (aGroupInfo
.mbEnable
)
469 // Number-range grouping
471 // Look through the source entries for non-integer numbers, minimum
474 // non-integer GroupInfo values count, too
475 aGroupInfo
.mbIntegerOnly
=
476 (aGroupInfo
.mbAutoStart
|| isInteger(aGroupInfo
.mfStart
)) &&
477 (aGroupInfo
.mbAutoEnd
|| isInteger(aGroupInfo
.mfEnd
)) &&
478 isInteger(aGroupInfo
.mfStep
);
480 double fSourceMin
= 0.0;
481 double fSourceMax
= 0.0;
484 const ScDPCache::ItemsType
& rItems
= rCache
.GetDimMemberValues(nDim
);
485 ScDPCache::ItemsType::const_iterator it
= rItems
.begin(), itEnd
= rItems
.end();
486 for (; it
!= itEnd
; ++it
)
488 const ScDPItemData
& rItem
= *it
;
489 if (rItem
.GetType() != ScDPItemData::Value
)
492 double fValue
= rItem
.GetValue();
495 fSourceMin
= fSourceMax
= fValue
;
500 if (fValue
< fSourceMin
)
502 if (fValue
> fSourceMax
)
505 if (aGroupInfo
.mbIntegerOnly
&& !isInteger(fValue
))
507 // If any non-integer numbers are involved, the group labels
508 // are shown including their upper limit.
509 aGroupInfo
.mbIntegerOnly
= false;
513 if (aGroupInfo
.mbDateValues
)
515 // special handling for dates: always integer, round down limits
516 aGroupInfo
.mbIntegerOnly
= true;
517 fSourceMin
= rtl::math::approxFloor(fSourceMin
);
518 fSourceMax
= rtl::math::approxFloor(fSourceMax
) + 1;
521 if (aGroupInfo
.mbAutoStart
)
522 aGroupInfo
.mfStart
= fSourceMin
;
523 if (aGroupInfo
.mbAutoEnd
)
524 aGroupInfo
.mfEnd
= fSourceMax
;
526 //TODO: limit number of entries?
529 double fLoop
= aGroupInfo
.mfStart
;
531 rCache
.ResetGroupItems(nDim
, aGroupInfo
, 0);
533 // Use "less than" instead of "less or equal" for the loop - don't
534 // create a group that consists only of the end value. Instead, the
535 // end value is then included in the last group (last group is bigger
536 // than the others). The first group has to be created nonetheless.
537 // GetNumGroupForValue has corresponding logic.
539 bool bFirstGroup
= true;
540 while (bFirstGroup
|| (fLoop
< aGroupInfo
.mfEnd
&& !rtl::math::approxEqual(fLoop
, aGroupInfo
.mfEnd
)))
543 aItem
.SetRangeStart(fLoop
);
544 rCache
.SetGroupItem(nDim
, aItem
);
546 fLoop
= aGroupInfo
.mfStart
+ nLoopCount
* aGroupInfo
.mfStep
;
549 // ScDPItemData values are compared with approxEqual
553 aItem
.SetRangeFirst();
554 rCache
.SetGroupItem(nDim
, aItem
);
556 aItem
.SetRangeLast();
557 rCache
.SetGroupItem(nDim
, aItem
);
561 void ScDPSaveNumGroupDimension::SetGroupInfo( const ScDPNumGroupInfo
& rNew
)
566 void ScDPSaveNumGroupDimension::SetDateInfo( const ScDPNumGroupInfo
& rInfo
, sal_Int32 nPart
)
574 struct ScDPSaveGroupDimNameFunc
577 inline explicit ScDPSaveGroupDimNameFunc( const OUString
& rDimName
) : maDimName( rDimName
) {}
578 inline bool operator()( const ScDPSaveGroupDimension
& rGroupDim
) const { return rGroupDim
.GetGroupDimName() == maDimName
; }
581 struct ScDPSaveGroupSourceNameFunc
583 OUString maSrcDimName
;
584 inline explicit ScDPSaveGroupSourceNameFunc( const OUString
& rSrcDimName
) : maSrcDimName( rSrcDimName
) {}
585 inline bool operator()( const ScDPSaveGroupDimension
& rGroupDim
) const { return rGroupDim
.GetSourceDimName() == maSrcDimName
; }
590 ScDPDimensionSaveData::ScDPDimensionSaveData()
594 ScDPDimensionSaveData::~ScDPDimensionSaveData()
598 bool ScDPDimensionSaveData::operator==( const ScDPDimensionSaveData
& ) const
603 void ScDPDimensionSaveData::AddGroupDimension( const ScDPSaveGroupDimension
& rGroupDim
)
605 OSL_ENSURE( ::std::none_of( maGroupDims
.begin(), maGroupDims
.end(), ScDPSaveGroupDimNameFunc( rGroupDim
.GetGroupDimName() ) ),
606 "ScDPDimensionSaveData::AddGroupDimension - group dimension exists already" );
607 // ReplaceGroupDimension() adds new or replaces existing
608 ReplaceGroupDimension( rGroupDim
);
611 void ScDPDimensionSaveData::ReplaceGroupDimension( const ScDPSaveGroupDimension
& rGroupDim
)
613 ScDPSaveGroupDimVec::iterator aIt
= ::std::find_if(
614 maGroupDims
.begin(), maGroupDims
.end(), ScDPSaveGroupDimNameFunc( rGroupDim
.GetGroupDimName() ) );
615 if( aIt
== maGroupDims
.end() )
616 maGroupDims
.push_back( rGroupDim
);
621 void ScDPDimensionSaveData::RemoveGroupDimension( const OUString
& rGroupDimName
)
623 ScDPSaveGroupDimVec::iterator aIt
= ::std::find_if(
624 maGroupDims
.begin(), maGroupDims
.end(), ScDPSaveGroupDimNameFunc( rGroupDimName
) );
625 if( aIt
!= maGroupDims
.end() )
626 maGroupDims
.erase( aIt
);
629 void ScDPDimensionSaveData::AddNumGroupDimension( const ScDPSaveNumGroupDimension
& rGroupDim
)
631 OSL_ENSURE( maNumGroupDims
.count( rGroupDim
.GetDimensionName() ) == 0,
632 "ScDPDimensionSaveData::AddNumGroupDimension - numeric group dimension exists already" );
633 // ReplaceNumGroupDimension() adds new or replaces existing
634 ReplaceNumGroupDimension( rGroupDim
);
637 void ScDPDimensionSaveData::ReplaceNumGroupDimension( const ScDPSaveNumGroupDimension
& rGroupDim
)
639 ScDPSaveNumGroupDimMap::iterator aIt
= maNumGroupDims
.find( rGroupDim
.GetDimensionName() );
640 if( aIt
== maNumGroupDims
.end() )
641 maNumGroupDims
.insert( ScDPSaveNumGroupDimMap::value_type( rGroupDim
.GetDimensionName(), rGroupDim
) );
643 aIt
->second
= rGroupDim
;
646 void ScDPDimensionSaveData::RemoveNumGroupDimension( const OUString
& rGroupDimName
)
648 maNumGroupDims
.erase( rGroupDimName
);
651 void ScDPDimensionSaveData::WriteToData( ScDPGroupTableData
& rData
) const
653 // rData is assumed to be empty
654 // AddToData also handles date grouping
656 for( ScDPSaveGroupDimVec::const_iterator aIt
= maGroupDims
.begin(), aEnd
= maGroupDims
.end(); aIt
!= aEnd
; ++aIt
)
657 aIt
->AddToData( rData
);
659 for( ScDPSaveNumGroupDimMap::const_iterator aIt
= maNumGroupDims
.begin(), aEnd
= maNumGroupDims
.end(); aIt
!= aEnd
; ++aIt
)
660 aIt
->second
.AddToData( rData
);
665 class AddGroupDimToCache
: std::unary_function
<ScDPSaveGroupDimension
, void>
669 AddGroupDimToCache(ScDPCache
& rCache
) : mrCache(rCache
) {}
670 void operator() (const ScDPSaveGroupDimension
& rDim
)
672 rDim
.AddToCache(mrCache
);
678 void ScDPDimensionSaveData::WriteToCache(ScDPCache
& rCache
) const
680 std::for_each(maGroupDims
.begin(), maGroupDims
.end(), AddGroupDimToCache(rCache
));
681 ScDPSaveNumGroupDimMap::const_iterator it
= maNumGroupDims
.begin(), itEnd
= maNumGroupDims
.end();
682 for (; it
!= itEnd
; ++it
)
683 it
->second
.AddToCache(rCache
);
686 const ScDPSaveGroupDimension
* ScDPDimensionSaveData::GetGroupDimForBase( const OUString
& rBaseDimName
) const
688 return const_cast< ScDPDimensionSaveData
* >( this )->GetGroupDimAccForBase( rBaseDimName
);
691 const ScDPSaveGroupDimension
* ScDPDimensionSaveData::GetNamedGroupDim( const OUString
& rGroupDimName
) const
693 return const_cast< ScDPDimensionSaveData
* >( this )->GetNamedGroupDimAcc( rGroupDimName
);
696 const ScDPSaveGroupDimension
* ScDPDimensionSaveData::GetFirstNamedGroupDim( const OUString
& rBaseDimName
) const
698 return const_cast< ScDPDimensionSaveData
* >( this )->GetFirstNamedGroupDimAcc( rBaseDimName
);
701 const ScDPSaveGroupDimension
* ScDPDimensionSaveData::GetNextNamedGroupDim( const OUString
& rGroupDimName
) const
703 return const_cast< ScDPDimensionSaveData
* >( this )->GetNextNamedGroupDimAcc( rGroupDimName
);
706 const ScDPSaveNumGroupDimension
* ScDPDimensionSaveData::GetNumGroupDim( const OUString
& rGroupDimName
) const
708 return const_cast< ScDPDimensionSaveData
* >( this )->GetNumGroupDimAcc( rGroupDimName
);
711 ScDPSaveGroupDimension
* ScDPDimensionSaveData::GetGroupDimAccForBase( const OUString
& rBaseDimName
)
713 ScDPSaveGroupDimension
* pGroupDim
= GetFirstNamedGroupDimAcc( rBaseDimName
);
714 return pGroupDim
? pGroupDim
: GetNextNamedGroupDimAcc( rBaseDimName
);
717 ScDPSaveGroupDimension
* ScDPDimensionSaveData::GetNamedGroupDimAcc( const OUString
& rGroupDimName
)
719 ScDPSaveGroupDimVec::iterator aIt
= ::std::find_if(
720 maGroupDims
.begin(), maGroupDims
.end(), ScDPSaveGroupDimNameFunc( rGroupDimName
) );
721 return (aIt
== maGroupDims
.end()) ? 0 : &*aIt
;
724 ScDPSaveGroupDimension
* ScDPDimensionSaveData::GetFirstNamedGroupDimAcc( const OUString
& rBaseDimName
)
726 ScDPSaveGroupDimVec::iterator aIt
= ::std::find_if(
727 maGroupDims
.begin(), maGroupDims
.end(), ScDPSaveGroupSourceNameFunc( rBaseDimName
) );
728 return (aIt
== maGroupDims
.end()) ? 0 : &*aIt
;
731 ScDPSaveGroupDimension
* ScDPDimensionSaveData::GetNextNamedGroupDimAcc( const OUString
& rGroupDimName
)
733 // find the group dimension with the passed name
734 ScDPSaveGroupDimVec::iterator aIt
= ::std::find_if(
735 maGroupDims
.begin(), maGroupDims
.end(), ScDPSaveGroupDimNameFunc( rGroupDimName
) );
736 // find next group dimension based on the same source dimension name
737 if( aIt
!= maGroupDims
.end() )
738 aIt
= ::std::find_if( aIt
+ 1, maGroupDims
.end(), ScDPSaveGroupSourceNameFunc( aIt
->GetSourceDimName() ) );
739 return (aIt
== maGroupDims
.end()) ? 0 : &*aIt
;
742 ScDPSaveNumGroupDimension
* ScDPDimensionSaveData::GetNumGroupDimAcc( const OUString
& rGroupDimName
)
744 ScDPSaveNumGroupDimMap::iterator aIt
= maNumGroupDims
.find( rGroupDimName
);
745 return (aIt
== maNumGroupDims
.end()) ? 0 : &aIt
->second
;
748 bool ScDPDimensionSaveData::HasGroupDimensions() const
750 return !maGroupDims
.empty() || !maNumGroupDims
.empty();
753 sal_Int32
ScDPDimensionSaveData::CollectDateParts( const OUString
& rBaseDimName
) const
755 sal_Int32 nParts
= 0;
756 // start with part of numeric group
757 if( const ScDPSaveNumGroupDimension
* pNumDim
= GetNumGroupDim( rBaseDimName
) )
758 nParts
|= pNumDim
->GetDatePart();
759 // collect parts from all matching group dimensions
760 for( const ScDPSaveGroupDimension
* pGroupDim
= GetFirstNamedGroupDim( rBaseDimName
); pGroupDim
; pGroupDim
= GetNextNamedGroupDim( pGroupDim
->GetGroupDimName() ) )
761 nParts
|= pGroupDim
->GetDatePart();
766 OUString
ScDPDimensionSaveData::CreateGroupDimName(
767 const OUString
& rSourceName
, const ScDPObject
& rObject
, bool bAllowSource
,
768 const std::vector
<OUString
>* pDeletedNames
)
770 // create a name for the new dimension by appending a number to the original
773 bool bUseSource
= bAllowSource
; // if set, try the unchanged original name first
775 sal_Int32 nAdd
= 2; // first try is "Name2"
776 const sal_Int32 nMaxAdd
= 1000; // limit the loop
777 while ( nAdd
<= nMaxAdd
)
779 OUString
aDimName( rSourceName
);
781 aDimName
+= OUString::number(nAdd
);
782 bool bExists
= false;
784 // look for existing group dimensions
785 for( ScDPSaveGroupDimVec::const_iterator aIt
= maGroupDims
.begin(), aEnd
= maGroupDims
.end(); (aIt
!= aEnd
) && !bExists
; ++aIt
)
786 if( aIt
->GetGroupDimName() == aDimName
) //TODO: ignore case
789 // look for base dimensions that happen to have that name
790 if ( !bExists
&& rObject
.IsDimNameInUse( aDimName
) )
792 if ( pDeletedNames
&&
793 std::find( pDeletedNames
->begin(), pDeletedNames
->end(), aDimName
) != pDeletedNames
->end() )
795 // allow the name anyway if the name is in pDeletedNames
802 return aDimName
; // found a new name
807 ++nAdd
; // continue with higher number
809 OSL_FAIL("CreateGroupDimName: no valid name found");
815 static const sal_uInt16 nDatePartIds
[] =
817 STR_DPFIELD_GROUP_BY_SECONDS
,
818 STR_DPFIELD_GROUP_BY_MINUTES
,
819 STR_DPFIELD_GROUP_BY_HOURS
,
820 STR_DPFIELD_GROUP_BY_DAYS
,
821 STR_DPFIELD_GROUP_BY_MONTHS
,
822 STR_DPFIELD_GROUP_BY_QUARTERS
,
823 STR_DPFIELD_GROUP_BY_YEARS
827 OUString
ScDPDimensionSaveData::CreateDateGroupDimName(
828 sal_Int32 nDatePart
, const ScDPObject
& rObject
, bool bAllowSource
,
829 const std::vector
<OUString
>* pDeletedNames
)
831 using namespace ::com::sun::star::sheet::DataPilotFieldGroupBy
;
835 case SECONDS
: aPartName
= ScGlobal::GetRscString( nDatePartIds
[0] ); break;
836 case MINUTES
: aPartName
= ScGlobal::GetRscString( nDatePartIds
[1] ); break;
837 case HOURS
: aPartName
= ScGlobal::GetRscString( nDatePartIds
[2] ); break;
838 case DAYS
: aPartName
= ScGlobal::GetRscString( nDatePartIds
[3] ); break;
839 case MONTHS
: aPartName
= ScGlobal::GetRscString( nDatePartIds
[4] ); break;
840 case QUARTERS
: aPartName
= ScGlobal::GetRscString( nDatePartIds
[5] ); break;
841 case YEARS
: aPartName
= ScGlobal::GetRscString( nDatePartIds
[6] ); break;
843 OSL_ENSURE(!aPartName
.isEmpty(), "ScDPDimensionSaveData::CreateDateGroupDimName - invalid date part");
844 return CreateGroupDimName( aPartName
, rObject
, bAllowSource
, pDeletedNames
);
847 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */