xref: /aoo42x/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