xref: /trunk/main/sc/source/core/data/dpdimsave.cxx (revision 58ae0c86)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26 
27 #include "dpdimsave.hxx"
28 #include "dpgroup.hxx"
29 #include "dpobject.hxx"
30 #include "document.hxx"
31 
32 #include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
33 
34 #include <svl/zforlist.hxx>
35 #include <tools/debug.hxx>
36 #include <rtl/math.hxx>
37 #include <algorithm>
38 
39 #include "global.hxx"
40 #include "scresid.hxx"
41 #include "globstr.hrc"
42 
43 // ============================================================================
44 
ScDPSaveGroupItem(const String & rName)45 ScDPSaveGroupItem::ScDPSaveGroupItem( const String& rName ) :
46     aGroupName( rName )
47 {
48 }
49 
~ScDPSaveGroupItem()50 ScDPSaveGroupItem::~ScDPSaveGroupItem()
51 {
52 }
53 
AddElement(const String & rName)54 void ScDPSaveGroupItem::AddElement( const String& rName )
55 {
56     aElements.push_back( rName );
57 }
58 
AddElementsFromGroup(const ScDPSaveGroupItem & rGroup)59 void ScDPSaveGroupItem::AddElementsFromGroup( const ScDPSaveGroupItem& rGroup )
60 {
61     // add all elements of the other group (used for nested grouping)
62 
63     for ( std::vector<String>::const_iterator aIter(rGroup.aElements.begin());
64                                 aIter != rGroup.aElements.end(); aIter++ )
65         aElements.push_back( *aIter );
66 }
67 
RemoveElement(const String & rName)68 bool ScDPSaveGroupItem::RemoveElement( const String& rName )
69 {
70     for ( std::vector<String>::iterator aIter(aElements.begin()); aIter != aElements.end(); aIter++ )
71         if ( *aIter == rName )          //! ignore case
72         {
73             aElements.erase( aIter );   // found -> remove
74             return true;                // don't have to look further
75         }
76 
77     return false;   // not found
78 }
79 
IsEmpty() const80 bool ScDPSaveGroupItem::IsEmpty() const
81 {
82     return aElements.empty();
83 }
84 
GetElementCount() const85 size_t ScDPSaveGroupItem::GetElementCount() const
86 {
87     return aElements.size();
88 }
89 
GetElementByIndex(size_t nIndex) const90 const String* ScDPSaveGroupItem::GetElementByIndex( size_t nIndex ) const
91 {
92     return (nIndex < aElements.size()) ? &aElements[ nIndex ] : 0;
93 }
94 
Rename(const String & rNewName)95 void ScDPSaveGroupItem::Rename( const String& rNewName )
96 {
97     aGroupName = rNewName;
98 }
99 
RemoveElementsFromGroups(ScDPSaveGroupDimension & rDimension) const100 void ScDPSaveGroupItem::RemoveElementsFromGroups( ScDPSaveGroupDimension& rDimension ) const
101 {
102     // remove this group's elements from their groups in rDimension
103     // (rDimension must be a different dimension from the one which contains this)
104 
105     for ( std::vector<String>::const_iterator aIter(aElements.begin()); aIter != aElements.end(); aIter++ )
106         rDimension.RemoveFromGroups( *aIter );
107 }
108 
AddToData(ScDPGroupDimension & rDataDim,SvNumberFormatter * pFormatter) const109 void ScDPSaveGroupItem::AddToData( ScDPGroupDimension& rDataDim, SvNumberFormatter* pFormatter ) const
110 {
111     ScDPGroupItem aGroup( aGroupName );
112     ScDPItemData aData;
113 
114     for ( std::vector<String>::const_iterator aIter(aElements.begin()); aIter != aElements.end(); aIter++ )
115     {
116         sal_uInt32 nFormat = 0;      //! ...
117         double fValue;
118         if ( pFormatter->IsNumberFormat( *aIter, nFormat, fValue ) )
119             aData = ScDPItemData( *aIter, fValue, sal_True );
120         else
121             aData.SetString( *aIter );
122 
123         aGroup.AddElement( aData );
124         //! for numeric data, look at source members?
125     }
126 
127     rDataDim.AddItem( aGroup );
128 }
129 
130 // ============================================================================
131 
ScDPSaveGroupDimension(const String & rSource,const String & rName)132 ScDPSaveGroupDimension::ScDPSaveGroupDimension( const String& rSource, const String& rName ) :
133     aSourceDim( rSource ),
134     aGroupDimName( rName ),
135     nDatePart( 0 )
136 {
137 }
138 
ScDPSaveGroupDimension(const String & rSource,const String & rName,const ScDPNumGroupInfo & rDateInfo,sal_Int32 nPart)139 ScDPSaveGroupDimension::ScDPSaveGroupDimension( const String& rSource, const String& rName, const ScDPNumGroupInfo& rDateInfo, sal_Int32 nPart ) :
140     aSourceDim( rSource ),
141     aGroupDimName( rName ),
142     aDateInfo( rDateInfo ),
143     nDatePart( nPart )
144 {
145 }
146 
~ScDPSaveGroupDimension()147 ScDPSaveGroupDimension::~ScDPSaveGroupDimension()
148 {
149 }
150 
SetDateInfo(const ScDPNumGroupInfo & rInfo,sal_Int32 nPart)151 void ScDPSaveGroupDimension::SetDateInfo( const ScDPNumGroupInfo& rInfo, sal_Int32 nPart )
152 {
153     aDateInfo = rInfo;
154     nDatePart = nPart;
155 }
156 
AddGroupItem(const ScDPSaveGroupItem & rItem)157 void ScDPSaveGroupDimension::AddGroupItem( const ScDPSaveGroupItem& rItem )
158 {
159     aGroups.push_back( rItem );
160 }
161 
CreateGroupName(const String & rPrefix)162 String ScDPSaveGroupDimension::CreateGroupName( const String& rPrefix )
163 {
164     // create a name for a new group, using "Group1", "Group2" etc. (translated prefix in rPrefix)
165 
166     //! look in all dimensions, to avoid clashes with automatic groups (=name of base element)?
167     //! (only dimensions for the same base)
168 
169     sal_Int32 nAdd = 1;                                 // first try is "Group1"
170     const sal_Int32 nMaxAdd = nAdd + aGroups.size();    // limit the loop
171     while ( nAdd <= nMaxAdd )
172     {
173         String aGroupName( rPrefix );
174         aGroupName.Append( String::CreateFromInt32( nAdd ) );
175         bool bExists = false;
176 
177         // look for existing groups
178         for ( ScDPSaveGroupItemVec::const_iterator aIter(aGroups.begin());
179                                     aIter != aGroups.end() && !bExists; aIter++ )
180             if ( aIter->GetGroupName() == aGroupName )         //! ignore case
181                 bExists = true;
182 
183         if ( !bExists )
184             return aGroupName;          // found a new name
185 
186         ++nAdd;                         // continue with higher number
187     }
188 
189     DBG_ERROR("CreateGroupName: no valid name found");
190     return EMPTY_STRING;
191 }
192 
GetNamedGroup(const String & rGroupName) const193 const ScDPSaveGroupItem* ScDPSaveGroupDimension::GetNamedGroup( const String& rGroupName ) const
194 {
195     return const_cast< ScDPSaveGroupDimension* >( this )->GetNamedGroupAcc( rGroupName );
196 }
197 
GetNamedGroupAcc(const String & rGroupName)198 ScDPSaveGroupItem* ScDPSaveGroupDimension::GetNamedGroupAcc( const String& rGroupName )
199 {
200     for ( ScDPSaveGroupItemVec::iterator aIter(aGroups.begin()); aIter != aGroups.end(); aIter++ )
201         if ( aIter->GetGroupName() == rGroupName )         //! ignore case
202             return &*aIter;
203 
204     return NULL;        // none found
205 }
206 
GetGroupCount() const207 long ScDPSaveGroupDimension::GetGroupCount() const
208 {
209     return aGroups.size();
210 }
211 
GetGroupByIndex(long nIndex) const212 const ScDPSaveGroupItem* ScDPSaveGroupDimension::GetGroupByIndex( long nIndex ) const
213 {
214     return const_cast< ScDPSaveGroupDimension* >( this )->GetGroupAccByIndex( nIndex );
215 }
216 
GetGroupAccByIndex(long nIndex)217 ScDPSaveGroupItem* ScDPSaveGroupDimension::GetGroupAccByIndex( long nIndex )
218 {
219     return &aGroups[nIndex];
220 }
221 
RemoveFromGroups(const String & rItemName)222 void ScDPSaveGroupDimension::RemoveFromGroups( const String& rItemName )
223 {
224     //  if the item is in any group, remove it from the group,
225     //  also remove the group if it is empty afterwards
226 
227     for ( ScDPSaveGroupItemVec::iterator aIter(aGroups.begin()); aIter != aGroups.end(); aIter++ )
228         if ( aIter->RemoveElement( rItemName ) )
229         {
230             if ( aIter->IsEmpty() )         // removed last item from the group?
231                 aGroups.erase( aIter );     // then remove the group
232 
233             return;     // don't have to look further
234         }
235 }
236 
RemoveGroup(const String & rGroupName)237 void ScDPSaveGroupDimension::RemoveGroup( const String& rGroupName )
238 {
239     for ( ScDPSaveGroupItemVec::iterator aIter(aGroups.begin()); aIter != aGroups.end(); aIter++ )
240         if ( aIter->GetGroupName() == rGroupName )          //! ignore case
241         {
242             aGroups.erase( aIter );
243             return;                     // don't have to look further
244         }
245 }
246 
IsEmpty() const247 bool ScDPSaveGroupDimension::IsEmpty() const
248 {
249     return aGroups.empty();
250 }
251 
HasOnlyHidden(const ScStrCollection & rVisible)252 bool ScDPSaveGroupDimension::HasOnlyHidden( const ScStrCollection& rVisible )
253 {
254     // check if there are only groups that don't appear in the list of visible names
255 
256     bool bAllHidden = true;
257     for ( ScDPSaveGroupItemVec::const_iterator aIter(aGroups.begin()); aIter != aGroups.end() && bAllHidden; aIter++ )
258     {
259         StrData aSearch( aIter->GetGroupName() );
260         sal_uInt16 nCollIndex;
261         if ( rVisible.Search( &aSearch, nCollIndex ) )
262             bAllHidden = false;                             // found one that is visible
263     }
264     return bAllHidden;
265 }
266 
Rename(const String & rNewName)267 void ScDPSaveGroupDimension::Rename( const String& rNewName )
268 {
269     aGroupDimName = rNewName;
270 }
271 
AddToData(ScDPGroupTableData & rData) const272 void ScDPSaveGroupDimension::AddToData( ScDPGroupTableData& rData ) const
273 {
274     long nSourceIndex = rData.GetDimensionIndex( aSourceDim );
275     if ( nSourceIndex >= 0 )
276     {
277         ScDPGroupDimension aDim( nSourceIndex, aGroupDimName );
278         if ( nDatePart )
279         {
280             // date grouping
281 
282             aDim.MakeDateHelper( aDateInfo, nDatePart );
283         }
284         else
285         {
286             // normal (manual) grouping
287 
288             SvNumberFormatter* pFormatter = rData.GetDocument()->GetFormatTable();
289 
290             for ( ScDPSaveGroupItemVec::const_iterator aIter(aGroups.begin()); aIter != aGroups.end(); aIter++ )
291                 aIter->AddToData( aDim, pFormatter );
292         }
293 
294         rData.AddGroupDimension( aDim );
295     }
296 }
297 
298 // ============================================================================
299 
ScDPSaveNumGroupDimension(const String & rName,const ScDPNumGroupInfo & rInfo)300 ScDPSaveNumGroupDimension::ScDPSaveNumGroupDimension( const String& rName, const ScDPNumGroupInfo& rInfo ) :
301     aDimensionName( rName ),
302     aGroupInfo( rInfo ),
303     nDatePart( 0 )
304 {
305 }
306 
ScDPSaveNumGroupDimension(const String & rName,const ScDPNumGroupInfo & rDateInfo,sal_Int32 nPart)307 ScDPSaveNumGroupDimension::ScDPSaveNumGroupDimension( const String& rName, const ScDPNumGroupInfo& rDateInfo, sal_Int32 nPart ) :
308     aDimensionName( rName ),
309     aDateInfo( rDateInfo ),
310     nDatePart( nPart )
311 {
312 }
313 
~ScDPSaveNumGroupDimension()314 ScDPSaveNumGroupDimension::~ScDPSaveNumGroupDimension()
315 {
316 }
317 
AddToData(ScDPGroupTableData & rData) const318 void ScDPSaveNumGroupDimension::AddToData( ScDPGroupTableData& rData ) const
319 {
320     long nSource = rData.GetDimensionIndex( aDimensionName );
321     if ( nSource >= 0 )
322     {
323         ScDPNumGroupDimension aDim( aGroupInfo );           // aGroupInfo: value grouping
324         if ( nDatePart )
325             aDim.MakeDateHelper( aDateInfo, nDatePart );    // date grouping
326 
327         rData.SetNumGroupDimension( nSource, aDim );
328     }
329 }
330 
SetGroupInfo(const ScDPNumGroupInfo & rNew)331 void ScDPSaveNumGroupDimension::SetGroupInfo( const ScDPNumGroupInfo& rNew )
332 {
333     aGroupInfo = rNew;
334 }
335 
SetDateInfo(const ScDPNumGroupInfo & rInfo,sal_Int32 nPart)336 void ScDPSaveNumGroupDimension::SetDateInfo( const ScDPNumGroupInfo& rInfo, sal_Int32 nPart )
337 {
338     aDateInfo = rInfo;
339     nDatePart = nPart;
340 }
341 
342 // ============================================================================
343 
344 namespace {
345 
346 struct ScDPSaveGroupDimNameFunc
347 {
348     String              maDimName;
ScDPSaveGroupDimNameFunc__anone04a89f20111::ScDPSaveGroupDimNameFunc349     inline explicit     ScDPSaveGroupDimNameFunc( const String& rDimName ) : maDimName( rDimName ) {}
operator ()__anone04a89f20111::ScDPSaveGroupDimNameFunc350     inline bool         operator()( const ScDPSaveGroupDimension& rGroupDim ) const { return rGroupDim.GetGroupDimName() == maDimName; }
351 };
352 
353 struct ScDPSaveGroupSourceNameFunc
354 {
355     String              maSrcDimName;
ScDPSaveGroupSourceNameFunc__anone04a89f20111::ScDPSaveGroupSourceNameFunc356     inline explicit     ScDPSaveGroupSourceNameFunc( const String& rSrcDimName ) : maSrcDimName( rSrcDimName ) {}
operator ()__anone04a89f20111::ScDPSaveGroupSourceNameFunc357     inline bool         operator()( const ScDPSaveGroupDimension& rGroupDim ) const { return rGroupDim.GetSourceDimName() == maSrcDimName; }
358 };
359 
360 } // namespace
361 
362 // ----------------------------------------------------------------------------
363 
ScDPDimensionSaveData()364 ScDPDimensionSaveData::ScDPDimensionSaveData()
365 {
366 }
367 
~ScDPDimensionSaveData()368 ScDPDimensionSaveData::~ScDPDimensionSaveData()
369 {
370 }
371 
operator ==(const ScDPDimensionSaveData &) const372 bool ScDPDimensionSaveData::operator==( const ScDPDimensionSaveData& ) const
373 {
374     return false;
375 }
376 
AddGroupDimension(const ScDPSaveGroupDimension & rGroupDim)377 void ScDPDimensionSaveData::AddGroupDimension( const ScDPSaveGroupDimension& rGroupDim )
378 {
379     DBG_ASSERT( ::std::find_if( maGroupDims.begin(), maGroupDims.end(), ScDPSaveGroupDimNameFunc( rGroupDim.GetGroupDimName() ) ) == maGroupDims.end(),
380         "ScDPDimensionSaveData::AddGroupDimension - group dimension exists already" );
381     // ReplaceGroupDimension() adds new or replaces existing
382     ReplaceGroupDimension( rGroupDim );
383 }
384 
ReplaceGroupDimension(const ScDPSaveGroupDimension & rGroupDim)385 void ScDPDimensionSaveData::ReplaceGroupDimension( const ScDPSaveGroupDimension& rGroupDim )
386 {
387     ScDPSaveGroupDimVec::iterator aIt = ::std::find_if(
388         maGroupDims.begin(), maGroupDims.end(), ScDPSaveGroupDimNameFunc( rGroupDim.GetGroupDimName() ) );
389     if( aIt == maGroupDims.end() )
390         maGroupDims.push_back( rGroupDim );
391     else
392         *aIt = rGroupDim;
393 }
394 
RemoveGroupDimension(const String & rGroupDimName)395 void ScDPDimensionSaveData::RemoveGroupDimension( const String& rGroupDimName )
396 {
397     ScDPSaveGroupDimVec::iterator aIt = ::std::find_if(
398         maGroupDims.begin(), maGroupDims.end(), ScDPSaveGroupDimNameFunc( rGroupDimName ) );
399     if( aIt != maGroupDims.end() )
400         maGroupDims.erase( aIt );
401 }
402 
AddNumGroupDimension(const ScDPSaveNumGroupDimension & rGroupDim)403 void ScDPDimensionSaveData::AddNumGroupDimension( const ScDPSaveNumGroupDimension& rGroupDim )
404 {
405     DBG_ASSERT( maNumGroupDims.count( rGroupDim.GetDimensionName() ) == 0,
406         "ScDPDimensionSaveData::AddNumGroupDimension - numeric group dimension exists already" );
407     // ReplaceNumGroupDimension() adds new or replaces existing
408     ReplaceNumGroupDimension( rGroupDim );
409 }
410 
ReplaceNumGroupDimension(const ScDPSaveNumGroupDimension & rGroupDim)411 void ScDPDimensionSaveData::ReplaceNumGroupDimension( const ScDPSaveNumGroupDimension& rGroupDim )
412 {
413     ScDPSaveNumGroupDimMap::iterator aIt = maNumGroupDims.find( rGroupDim.GetDimensionName() );
414     if( aIt == maNumGroupDims.end() )
415         maNumGroupDims.insert( ScDPSaveNumGroupDimMap::value_type( rGroupDim.GetDimensionName(), rGroupDim ) );
416     else
417         aIt->second = rGroupDim;
418 }
419 
RemoveNumGroupDimension(const String & rGroupDimName)420 void ScDPDimensionSaveData::RemoveNumGroupDimension( const String& rGroupDimName )
421 {
422     maNumGroupDims.erase( rGroupDimName );
423 }
424 
WriteToData(ScDPGroupTableData & rData) const425 void ScDPDimensionSaveData::WriteToData( ScDPGroupTableData& rData ) const
426 {
427     //  rData is assumed to be empty
428     //  AddToData also handles date grouping
429 
430     for( ScDPSaveGroupDimVec::const_iterator aIt = maGroupDims.begin(), aEnd = maGroupDims.end(); aIt != aEnd; ++aIt )
431         aIt->AddToData( rData );
432 
433     for( ScDPSaveNumGroupDimMap::const_iterator aIt = maNumGroupDims.begin(), aEnd = maNumGroupDims.end(); aIt != aEnd; ++aIt )
434         aIt->second.AddToData( rData );
435 }
436 
GetGroupDimForBase(const String & rBaseDimName) const437 const ScDPSaveGroupDimension* ScDPDimensionSaveData::GetGroupDimForBase( const String& rBaseDimName ) const
438 {
439     return const_cast< ScDPDimensionSaveData* >( this )->GetGroupDimAccForBase( rBaseDimName );
440 }
441 
GetNamedGroupDim(const String & rGroupDimName) const442 const ScDPSaveGroupDimension* ScDPDimensionSaveData::GetNamedGroupDim( const String& rGroupDimName ) const
443 {
444     return const_cast< ScDPDimensionSaveData* >( this )->GetNamedGroupDimAcc( rGroupDimName );
445 }
446 
GetFirstNamedGroupDim(const String & rBaseDimName) const447 const ScDPSaveGroupDimension* ScDPDimensionSaveData::GetFirstNamedGroupDim( const String& rBaseDimName ) const
448 {
449     return const_cast< ScDPDimensionSaveData* >( this )->GetFirstNamedGroupDimAcc( rBaseDimName );
450 }
451 
GetNextNamedGroupDim(const String & rGroupDimName) const452 const ScDPSaveGroupDimension* ScDPDimensionSaveData::GetNextNamedGroupDim( const String& rGroupDimName ) const
453 {
454     return const_cast< ScDPDimensionSaveData* >( this )->GetNextNamedGroupDimAcc( rGroupDimName );
455 }
456 
GetNumGroupDim(const String & rGroupDimName) const457 const ScDPSaveNumGroupDimension* ScDPDimensionSaveData::GetNumGroupDim( const String& rGroupDimName ) const
458 {
459     return const_cast< ScDPDimensionSaveData* >( this )->GetNumGroupDimAcc( rGroupDimName );
460 }
461 
GetGroupDimAccForBase(const String & rBaseDimName)462 ScDPSaveGroupDimension* ScDPDimensionSaveData::GetGroupDimAccForBase( const String& rBaseDimName )
463 {
464     ScDPSaveGroupDimension* pGroupDim = GetFirstNamedGroupDimAcc( rBaseDimName );
465     return pGroupDim ? pGroupDim : GetNextNamedGroupDimAcc( rBaseDimName );
466 }
467 
GetNamedGroupDimAcc(const String & rGroupDimName)468 ScDPSaveGroupDimension* ScDPDimensionSaveData::GetNamedGroupDimAcc( const String& rGroupDimName )
469 {
470     ScDPSaveGroupDimVec::iterator aIt = ::std::find_if(
471         maGroupDims.begin(), maGroupDims.end(), ScDPSaveGroupDimNameFunc( rGroupDimName ) );
472     return (aIt == maGroupDims.end()) ? 0 : &*aIt;
473 }
474 
GetFirstNamedGroupDimAcc(const String & rBaseDimName)475 ScDPSaveGroupDimension* ScDPDimensionSaveData::GetFirstNamedGroupDimAcc( const String& rBaseDimName )
476 {
477     ScDPSaveGroupDimVec::iterator aIt = ::std::find_if(
478         maGroupDims.begin(), maGroupDims.end(), ScDPSaveGroupSourceNameFunc( rBaseDimName ) );
479     return (aIt == maGroupDims.end()) ? 0 : &*aIt;
480 }
481 
GetNextNamedGroupDimAcc(const String & rGroupDimName)482 ScDPSaveGroupDimension* ScDPDimensionSaveData::GetNextNamedGroupDimAcc( const String& rGroupDimName )
483 {
484     // find the group dimension with the passed name
485     ScDPSaveGroupDimVec::iterator aIt = ::std::find_if(
486         maGroupDims.begin(), maGroupDims.end(), ScDPSaveGroupDimNameFunc( rGroupDimName ) );
487     // find next group dimension based on the same source dimension name
488     if( aIt != maGroupDims.end() )
489         aIt = ::std::find_if( aIt + 1, maGroupDims.end(), ScDPSaveGroupSourceNameFunc( aIt->GetSourceDimName() ) );
490     return (aIt == maGroupDims.end()) ? 0 : &*aIt;
491 }
492 
GetNumGroupDimAcc(const String & rGroupDimName)493 ScDPSaveNumGroupDimension* ScDPDimensionSaveData::GetNumGroupDimAcc( const String& rGroupDimName )
494 {
495     ScDPSaveNumGroupDimMap::iterator aIt = maNumGroupDims.find( rGroupDimName );
496     return (aIt == maNumGroupDims.end()) ? 0 : &aIt->second;
497 }
498 
HasGroupDimensions() const499 bool ScDPDimensionSaveData::HasGroupDimensions() const
500 {
501     return !maGroupDims.empty() || !maNumGroupDims.empty();
502 }
503 
CollectDateParts(const String & rBaseDimName) const504 sal_Int32 ScDPDimensionSaveData::CollectDateParts( const String& rBaseDimName ) const
505 {
506     sal_Int32 nParts = 0;
507     // start with part of numeric group
508     if( const ScDPSaveNumGroupDimension* pNumDim = GetNumGroupDim( rBaseDimName ) )
509         nParts |= pNumDim->GetDatePart();
510     // collect parts from all matching group dimensions
511     for( const ScDPSaveGroupDimension* pGroupDim = GetFirstNamedGroupDim( rBaseDimName ); pGroupDim; pGroupDim = GetNextNamedGroupDim( pGroupDim->GetGroupDimName() ) )
512         nParts |= pGroupDim->GetDatePart();
513 
514     return nParts;
515 }
516 
CreateGroupDimName(const String & rSourceName,const ScDPObject & rObject,bool bAllowSource,const std::vector<String> * pDeletedNames)517 String ScDPDimensionSaveData::CreateGroupDimName( const String& rSourceName,
518                                         const ScDPObject& rObject, bool bAllowSource,
519                                         const std::vector<String>* pDeletedNames )
520 {
521     // create a name for the new dimension by appending a number to the original
522     // dimension's name
523 
524     bool bUseSource = bAllowSource;     // if set, try the unchanged original name first
525 
526     sal_Int32 nAdd = 2;                 // first try is "Name2"
527     const sal_Int32 nMaxAdd = 1000;     // limit the loop
528     while ( nAdd <= nMaxAdd )
529     {
530         String aDimName( rSourceName );
531         if ( !bUseSource )
532             aDimName.Append( String::CreateFromInt32( nAdd ) );
533         bool bExists = false;
534 
535         // look for existing group dimensions
536         for( ScDPSaveGroupDimVec::const_iterator aIt = maGroupDims.begin(), aEnd = maGroupDims.end(); (aIt != aEnd) && !bExists; ++aIt )
537             if( aIt->GetGroupDimName() == aDimName )         //! ignore case
538                 bExists = true;
539 
540         // look for base dimensions that happen to have that name
541         if ( !bExists && rObject.IsDimNameInUse( aDimName ) )
542         {
543             if ( pDeletedNames &&
544                  std::find( pDeletedNames->begin(), pDeletedNames->end(), aDimName ) != pDeletedNames->end() )
545             {
546                 // allow the name anyway if the name is in pDeletedNames
547             }
548             else
549                 bExists = true;
550         }
551 
552         if ( !bExists )
553             return aDimName;            // found a new name
554 
555         if ( bUseSource )
556             bUseSource = false;
557         else
558             ++nAdd;                     // continue with higher number
559     }
560     DBG_ERROR("CreateGroupDimName: no valid name found");
561     return EMPTY_STRING;
562 }
563 
564 namespace {
565 
566 static const sal_uInt16 nDatePartIds[] =
567 {
568     STR_DPFIELD_GROUP_BY_SECONDS,
569     STR_DPFIELD_GROUP_BY_MINUTES,
570     STR_DPFIELD_GROUP_BY_HOURS,
571     STR_DPFIELD_GROUP_BY_DAYS,
572     STR_DPFIELD_GROUP_BY_MONTHS,
573     STR_DPFIELD_GROUP_BY_QUARTERS,
574     STR_DPFIELD_GROUP_BY_YEARS
575 };
576 
577 }
CreateDateGroupDimName(sal_Int32 nDatePart,const ScDPObject & rObject,bool bAllowSource,const::std::vector<String> * pDeletedNames)578 String ScDPDimensionSaveData::CreateDateGroupDimName( sal_Int32 nDatePart, const ScDPObject& rObject, bool bAllowSource, const ::std::vector< String >* pDeletedNames )
579 {
580     using namespace ::com::sun::star::sheet::DataPilotFieldGroupBy;
581     String aPartName;
582     switch( nDatePart )
583     {
584         case SECONDS:  aPartName = ScGlobal::GetRscString( nDatePartIds[0] ); break;
585         case MINUTES:  aPartName = ScGlobal::GetRscString( nDatePartIds[1] ); break;
586         case HOURS:    aPartName = ScGlobal::GetRscString( nDatePartIds[2] ); break;
587         case DAYS:     aPartName = ScGlobal::GetRscString( nDatePartIds[3] ); break;
588         case MONTHS:   aPartName = ScGlobal::GetRscString( nDatePartIds[4] ); break;
589         case QUARTERS: aPartName = ScGlobal::GetRscString( nDatePartIds[5] ); break;
590         case YEARS:    aPartName = ScGlobal::GetRscString( nDatePartIds[6] ); break;
591     }
592     DBG_ASSERT( aPartName.Len() > 0, "ScDPDimensionSaveData::CreateDateGroupDimName - invalid date part" );
593     return CreateGroupDimName( aPartName, rObject, bAllowSource, pDeletedNames );
594 }
595 
596 // ============================================================================
597 
598