xref: /aoo41x/main/sc/source/core/data/dpdimsave.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sc.hxx"
30 
31 #include "dpdimsave.hxx"
32 #include "dpgroup.hxx"
33 #include "dpobject.hxx"
34 #include "document.hxx"
35 
36 #include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
37 
38 #include <svl/zforlist.hxx>
39 #include <tools/debug.hxx>
40 #include <rtl/math.hxx>
41 #include <algorithm>
42 
43 // ============================================================================
44 
45 ScDPSaveGroupItem::ScDPSaveGroupItem( const String& rName ) :
46     aGroupName( rName )
47 {
48 }
49 
50 ScDPSaveGroupItem::~ScDPSaveGroupItem()
51 {
52 }
53 
54 void ScDPSaveGroupItem::AddElement( const String& rName )
55 {
56     aElements.push_back( rName );
57 }
58 
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 
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 
80 bool ScDPSaveGroupItem::IsEmpty() const
81 {
82     return aElements.empty();
83 }
84 
85 size_t ScDPSaveGroupItem::GetElementCount() const
86 {
87     return aElements.size();
88 }
89 
90 const String* ScDPSaveGroupItem::GetElementByIndex( size_t nIndex ) const
91 {
92     return (nIndex < aElements.size()) ? &aElements[ nIndex ] : 0;
93 }
94 
95 void ScDPSaveGroupItem::Rename( const String& rNewName )
96 {
97     aGroupName = rNewName;
98 }
99 
100 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 
109 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 
132 ScDPSaveGroupDimension::ScDPSaveGroupDimension( const String& rSource, const String& rName ) :
133     aSourceDim( rSource ),
134     aGroupDimName( rName ),
135     nDatePart( 0 )
136 {
137 }
138 
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 
147 ScDPSaveGroupDimension::~ScDPSaveGroupDimension()
148 {
149 }
150 
151 void ScDPSaveGroupDimension::SetDateInfo( const ScDPNumGroupInfo& rInfo, sal_Int32 nPart )
152 {
153     aDateInfo = rInfo;
154     nDatePart = nPart;
155 }
156 
157 void ScDPSaveGroupDimension::AddGroupItem( const ScDPSaveGroupItem& rItem )
158 {
159     aGroups.push_back( rItem );
160 }
161 
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 
193 const ScDPSaveGroupItem* ScDPSaveGroupDimension::GetNamedGroup( const String& rGroupName ) const
194 {
195     return const_cast< ScDPSaveGroupDimension* >( this )->GetNamedGroupAcc( rGroupName );
196 }
197 
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 
207 long ScDPSaveGroupDimension::GetGroupCount() const
208 {
209     return aGroups.size();
210 }
211 
212 const ScDPSaveGroupItem* ScDPSaveGroupDimension::GetGroupByIndex( long nIndex ) const
213 {
214     return const_cast< ScDPSaveGroupDimension* >( this )->GetGroupAccByIndex( nIndex );
215 }
216 
217 ScDPSaveGroupItem* ScDPSaveGroupDimension::GetGroupAccByIndex( long nIndex )
218 {
219     return &aGroups[nIndex];
220 }
221 
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 
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 
247 bool ScDPSaveGroupDimension::IsEmpty() const
248 {
249     return aGroups.empty();
250 }
251 
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 
267 void ScDPSaveGroupDimension::Rename( const String& rNewName )
268 {
269     aGroupDimName = rNewName;
270 }
271 
272 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 
300 ScDPSaveNumGroupDimension::ScDPSaveNumGroupDimension( const String& rName, const ScDPNumGroupInfo& rInfo ) :
301     aDimensionName( rName ),
302     aGroupInfo( rInfo ),
303     nDatePart( 0 )
304 {
305 }
306 
307 ScDPSaveNumGroupDimension::ScDPSaveNumGroupDimension( const String& rName, const ScDPNumGroupInfo& rDateInfo, sal_Int32 nPart ) :
308     aDimensionName( rName ),
309     aDateInfo( rDateInfo ),
310     nDatePart( nPart )
311 {
312 }
313 
314 ScDPSaveNumGroupDimension::~ScDPSaveNumGroupDimension()
315 {
316 }
317 
318 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 
331 void ScDPSaveNumGroupDimension::SetGroupInfo( const ScDPNumGroupInfo& rNew )
332 {
333     aGroupInfo = rNew;
334 }
335 
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;
349     inline explicit     ScDPSaveGroupDimNameFunc( const String& rDimName ) : maDimName( rDimName ) {}
350     inline bool         operator()( const ScDPSaveGroupDimension& rGroupDim ) const { return rGroupDim.GetGroupDimName() == maDimName; }
351 };
352 
353 struct ScDPSaveGroupSourceNameFunc
354 {
355     String              maSrcDimName;
356     inline explicit     ScDPSaveGroupSourceNameFunc( const String& rSrcDimName ) : maSrcDimName( rSrcDimName ) {}
357     inline bool         operator()( const ScDPSaveGroupDimension& rGroupDim ) const { return rGroupDim.GetSourceDimName() == maSrcDimName; }
358 };
359 
360 } // namespace
361 
362 // ----------------------------------------------------------------------------
363 
364 ScDPDimensionSaveData::ScDPDimensionSaveData()
365 {
366 }
367 
368 ScDPDimensionSaveData::~ScDPDimensionSaveData()
369 {
370 }
371 
372 bool ScDPDimensionSaveData::operator==( const ScDPDimensionSaveData& ) const
373 {
374     return false;
375 }
376 
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 
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 
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 
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 
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 
420 void ScDPDimensionSaveData::RemoveNumGroupDimension( const String& rGroupDimName )
421 {
422     maNumGroupDims.erase( rGroupDimName );
423 }
424 
425 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 
437 const ScDPSaveGroupDimension* ScDPDimensionSaveData::GetGroupDimForBase( const String& rBaseDimName ) const
438 {
439     return const_cast< ScDPDimensionSaveData* >( this )->GetGroupDimAccForBase( rBaseDimName );
440 }
441 
442 const ScDPSaveGroupDimension* ScDPDimensionSaveData::GetNamedGroupDim( const String& rGroupDimName ) const
443 {
444     return const_cast< ScDPDimensionSaveData* >( this )->GetNamedGroupDimAcc( rGroupDimName );
445 }
446 
447 const ScDPSaveGroupDimension* ScDPDimensionSaveData::GetFirstNamedGroupDim( const String& rBaseDimName ) const
448 {
449     return const_cast< ScDPDimensionSaveData* >( this )->GetFirstNamedGroupDimAcc( rBaseDimName );
450 }
451 
452 const ScDPSaveGroupDimension* ScDPDimensionSaveData::GetNextNamedGroupDim( const String& rGroupDimName ) const
453 {
454     return const_cast< ScDPDimensionSaveData* >( this )->GetNextNamedGroupDimAcc( rGroupDimName );
455 }
456 
457 const ScDPSaveNumGroupDimension* ScDPDimensionSaveData::GetNumGroupDim( const String& rGroupDimName ) const
458 {
459     return const_cast< ScDPDimensionSaveData* >( this )->GetNumGroupDimAcc( rGroupDimName );
460 }
461 
462 ScDPSaveGroupDimension* ScDPDimensionSaveData::GetGroupDimAccForBase( const String& rBaseDimName )
463 {
464     ScDPSaveGroupDimension* pGroupDim = GetFirstNamedGroupDimAcc( rBaseDimName );
465     return pGroupDim ? pGroupDim : GetNextNamedGroupDimAcc( rBaseDimName );
466 }
467 
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 
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 
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 
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 
499 bool ScDPDimensionSaveData::HasGroupDimensions() const
500 {
501     return !maGroupDims.empty() || !maNumGroupDims.empty();
502 }
503 
504 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 
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 String ScDPDimensionSaveData::CreateDateGroupDimName( sal_Int32 nDatePart, const ScDPObject& rObject, bool bAllowSource, const ::std::vector< String >* pDeletedNames )
565 {
566     using namespace ::com::sun::star::sheet::DataPilotFieldGroupBy;
567     String aPartName;
568     switch( nDatePart )
569     {
570         //! use translated strings from globstr.src
571         case SECONDS:  aPartName = String::CreateFromAscii( "Seconds" );    break;
572         case MINUTES:  aPartName = String::CreateFromAscii( "Minutes" );    break;
573         case HOURS:    aPartName = String::CreateFromAscii( "Hours" );      break;
574         case DAYS:     aPartName = String::CreateFromAscii( "Days" );       break;
575         case MONTHS:   aPartName = String::CreateFromAscii( "Months" );     break;
576         case QUARTERS: aPartName = String::CreateFromAscii( "Quarters" );   break;
577         case YEARS:    aPartName = String::CreateFromAscii( "Years" );      break;
578     }
579     DBG_ASSERT( aPartName.Len() > 0, "ScDPDimensionSaveData::CreateDateGroupDimName - invalid date part" );
580     return CreateGroupDimName( aPartName, rObject, bAllowSource, pDeletedNames );
581 }
582 
583 // ============================================================================
584 
585