update ooo310-m15
[ooovba.git] / sc / source / core / data / dpdimsave.cxx
blob0e83625f9be3af4bfb9f3f6841f1e27a020f06d2
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: dpdimsave.cxx,v $
10 * $Revision: 1.7 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
36 // INCLUDE ---------------------------------------------------------------
38 #include "dpdimsave.hxx"
39 #include "dpgroup.hxx"
40 #include "dpobject.hxx"
41 #include "document.hxx"
43 #include <svtools/zforlist.hxx>
44 #include <tools/debug.hxx>
45 #include <rtl/math.hxx>
46 #include <algorithm>
48 // -----------------------------------------------------------------------
50 ScDPSaveGroupItem::ScDPSaveGroupItem( const String& rName ) :
51 aGroupName( rName )
55 ScDPSaveGroupItem::ScDPSaveGroupItem( const ScDPSaveGroupItem& r ) :
56 aGroupName( r.aGroupName ),
57 aElements( r.aElements )
61 ScDPSaveGroupItem::~ScDPSaveGroupItem()
65 void ScDPSaveGroupItem::AddElement( const String& rName )
67 aElements.push_back( rName );
70 void ScDPSaveGroupItem::AddElementsFromGroup( const ScDPSaveGroupItem& rGroup )
72 // add all elements of the other group (used for nested grouping)
74 for ( std::vector<String>::const_iterator aIter(rGroup.aElements.begin());
75 aIter != rGroup.aElements.end(); aIter++ )
76 aElements.push_back( *aIter );
79 bool ScDPSaveGroupItem::RemoveElement( const String& rName )
81 for ( std::vector<String>::iterator aIter(aElements.begin()); aIter != aElements.end(); aIter++ )
82 if ( *aIter == rName ) //! ignore case
84 aElements.erase( aIter ); // found -> remove
85 return true; // don't have to look further
88 return false; // not found
91 bool ScDPSaveGroupItem::IsEmpty() const
93 return aElements.empty();
96 size_t ScDPSaveGroupItem::GetElementCount() const
98 return aElements.size();
101 const String* ScDPSaveGroupItem::GetElementByIndex( size_t nIndex ) const
103 return (nIndex < aElements.size()) ? &aElements[ nIndex ] : 0;
106 void ScDPSaveGroupItem::Rename( const String& rNewName )
108 aGroupName = rNewName;
111 void ScDPSaveGroupItem::RemoveElementsFromGroups( ScDPSaveGroupDimension& rDimension ) const
113 // remove this group's elements from their groups in rDimension
114 // (rDimension must be a different dimension from the one which contains this)
116 for ( std::vector<String>::const_iterator aIter(aElements.begin()); aIter != aElements.end(); aIter++ )
117 rDimension.RemoveFromGroups( *aIter );
120 void ScDPSaveGroupItem::AddToData( ScDPGroupDimension& rDataDim, SvNumberFormatter* pFormatter ) const
122 ScDPGroupItem aGroup( aGroupName );
123 ScDPItemData aData;
125 for ( std::vector<String>::const_iterator aIter(aElements.begin()); aIter != aElements.end(); aIter++ )
127 sal_uInt32 nFormat = 0; //! ...
128 double fValue;
129 if ( pFormatter->IsNumberFormat( *aIter, nFormat, fValue ) )
130 aData = ScDPItemData( *aIter, fValue, TRUE );
131 else
132 aData.SetString( *aIter );
134 aGroup.AddElement( aData );
135 //! for numeric data, look at source members?
138 rDataDim.AddItem( aGroup );
141 // -----------------------------------------------------------------------
143 ScDPSaveGroupDimension::ScDPSaveGroupDimension( const String& rSource, const String& rName ) :
144 aSourceDim( rSource ),
145 aGroupDimName( rName ),
146 nDatePart( 0 )
150 ScDPSaveGroupDimension::ScDPSaveGroupDimension( const ScDPSaveGroupDimension& r ) :
151 aSourceDim( r.aSourceDim ),
152 aGroupDimName( r.aGroupDimName ),
153 aGroups( r.aGroups ),
154 aDateInfo( r.aDateInfo ),
155 nDatePart( r.nDatePart )
159 ScDPSaveGroupDimension::~ScDPSaveGroupDimension()
163 void ScDPSaveGroupDimension::SetDateInfo( const ScDPNumGroupInfo& rInfo, sal_Int32 nPart )
165 aDateInfo = rInfo;
166 nDatePart = nPart;
169 void ScDPSaveGroupDimension::AddGroupItem( const ScDPSaveGroupItem& rItem )
171 aGroups.push_back( rItem );
174 String ScDPSaveGroupDimension::CreateGroupName( const String& rPrefix )
176 // create a name for a new group, using "Group1", "Group2" etc. (translated prefix in rPrefix)
178 //! look in all dimensions, to avoid clashes with automatic groups (=name of base element)?
179 //! (only dimensions for the same base)
181 sal_Int32 nAdd = 1; // first try is "Group1"
182 const sal_Int32 nMaxAdd = nAdd + aGroups.size(); // limit the loop
183 while ( nAdd <= nMaxAdd )
185 String aGroupName( rPrefix );
186 aGroupName.Append( String::CreateFromInt32( nAdd ) );
187 bool bExists = false;
189 // look for existing groups
190 for ( ScDPSaveGroupItemVec::const_iterator aIter(aGroups.begin());
191 aIter != aGroups.end() && !bExists; aIter++ )
192 if ( aIter->GetGroupName() == aGroupName ) //! ignore case
193 bExists = true;
195 if ( !bExists )
196 return aGroupName; // found a new name
198 ++nAdd; // continue with higher number
201 DBG_ERROR("CreateGroupName: no valid name found");
202 return EMPTY_STRING;
205 const ScDPSaveGroupItem* ScDPSaveGroupDimension::GetNamedGroup( const String& rGroupName ) const
207 return const_cast< ScDPSaveGroupDimension* >( this )->GetNamedGroupAcc( rGroupName );
210 ScDPSaveGroupItem* ScDPSaveGroupDimension::GetNamedGroupAcc( const String& rGroupName )
212 for ( ScDPSaveGroupItemVec::iterator aIter(aGroups.begin()); aIter != aGroups.end(); aIter++ )
213 if ( aIter->GetGroupName() == rGroupName ) //! ignore case
214 return &*aIter;
216 return NULL; // none found
219 long ScDPSaveGroupDimension::GetGroupCount() const
221 return aGroups.size();
224 const ScDPSaveGroupItem* ScDPSaveGroupDimension::GetGroupByIndex( long nIndex ) const
226 return const_cast< ScDPSaveGroupDimension* >( this )->GetGroupAccByIndex( nIndex );
229 ScDPSaveGroupItem* ScDPSaveGroupDimension::GetGroupAccByIndex( long nIndex )
231 return &aGroups[nIndex];
234 void ScDPSaveGroupDimension::RemoveFromGroups( const String& rItemName )
236 // if the item is in any group, remove it from the group,
237 // also remove the group if it is empty afterwards
239 for ( ScDPSaveGroupItemVec::iterator aIter(aGroups.begin()); aIter != aGroups.end(); aIter++ )
240 if ( aIter->RemoveElement( rItemName ) )
242 if ( aIter->IsEmpty() ) // removed last item from the group?
243 aGroups.erase( aIter ); // then remove the group
245 return; // don't have to look further
249 void ScDPSaveGroupDimension::RemoveGroup( const String& rGroupName )
251 for ( ScDPSaveGroupItemVec::iterator aIter(aGroups.begin()); aIter != aGroups.end(); aIter++ )
252 if ( aIter->GetGroupName() == rGroupName ) //! ignore case
254 aGroups.erase( aIter );
255 return; // don't have to look further
259 bool ScDPSaveGroupDimension::IsEmpty() const
261 return aGroups.empty();
264 bool ScDPSaveGroupDimension::HasOnlyHidden( const ScStrCollection& rVisible )
266 // check if there are only groups that don't appear in the list of visible names
268 bool bAllHidden = true;
269 for ( ScDPSaveGroupItemVec::const_iterator aIter(aGroups.begin()); aIter != aGroups.end() && bAllHidden; aIter++ )
271 StrData aSearch( aIter->GetGroupName() );
272 USHORT nCollIndex;
273 if ( rVisible.Search( &aSearch, nCollIndex ) )
274 bAllHidden = false; // found one that is visible
276 return bAllHidden;
279 void ScDPSaveGroupDimension::Rename( const String& rNewName )
281 aGroupDimName = rNewName;
284 void ScDPSaveGroupDimension::AddToData( ScDPGroupTableData& rData ) const
286 long nSourceIndex = rData.GetDimensionIndex( aSourceDim );
287 if ( nSourceIndex >= 0 )
289 ScDPGroupDimension aDim( nSourceIndex, aGroupDimName );
290 if ( nDatePart )
292 // date grouping
294 aDim.MakeDateHelper( aDateInfo, nDatePart );
296 else
298 // normal (manual) grouping
300 SvNumberFormatter* pFormatter = rData.GetDocument()->GetFormatTable();
302 for ( ScDPSaveGroupItemVec::const_iterator aIter(aGroups.begin()); aIter != aGroups.end(); aIter++ )
303 aIter->AddToData( aDim, pFormatter );
306 rData.AddGroupDimension( aDim );
310 // -----------------------------------------------------------------------
312 ScDPSaveNumGroupDimension::ScDPSaveNumGroupDimension( const String& rName, const ScDPNumGroupInfo& rInfo ) :
313 aDimensionName( rName ),
314 aGroupInfo( rInfo ),
315 nDatePart( 0 )
319 ScDPSaveNumGroupDimension::ScDPSaveNumGroupDimension( const ScDPSaveNumGroupDimension& r ) :
320 aDimensionName( r.aDimensionName ),
321 aGroupInfo( r.aGroupInfo ),
322 aDateInfo( r.aDateInfo ),
323 nDatePart( r.nDatePart )
327 ScDPSaveNumGroupDimension::~ScDPSaveNumGroupDimension()
331 void ScDPSaveNumGroupDimension::AddToData( ScDPGroupTableData& rData ) const
333 long nSource = rData.GetDimensionIndex( aDimensionName );
334 if ( nSource >= 0 )
336 ScDPNumGroupDimension aDim( aGroupInfo ); // aGroupInfo: value grouping
337 if ( nDatePart )
338 aDim.MakeDateHelper( aDateInfo, nDatePart ); // date grouping
340 rData.SetNumGroupDimension( nSource, aDim );
344 void ScDPSaveNumGroupDimension::SetGroupInfo( const ScDPNumGroupInfo& rNew )
346 aGroupInfo = rNew;
349 void ScDPSaveNumGroupDimension::SetDateInfo( const ScDPNumGroupInfo& rInfo, sal_Int32 nPart )
351 aDateInfo = rInfo;
352 nDatePart = nPart;
355 // -----------------------------------------------------------------------
357 ScDPDimensionSaveData::ScDPDimensionSaveData()
361 ScDPDimensionSaveData::ScDPDimensionSaveData( const ScDPDimensionSaveData& r ) :
362 aGroupDimensions( r.aGroupDimensions ),
363 aNumGroupDimensions( r.aNumGroupDimensions )
367 ScDPDimensionSaveData::~ScDPDimensionSaveData()
371 bool ScDPDimensionSaveData::operator==( const ScDPDimensionSaveData& ) const
373 return false;
376 void ScDPDimensionSaveData::AddGroupDimension( const ScDPSaveGroupDimension& rGroup )
378 aGroupDimensions.push_back( rGroup );
381 void ScDPDimensionSaveData::AddNumGroupDimension( const ScDPSaveNumGroupDimension& rGroup )
383 aNumGroupDimensions.push_back( rGroup );
386 void ScDPDimensionSaveData::RemoveGroupDimension( const String& rDimensionName )
388 for ( ScDPSaveGroupDimensionVec::iterator aIter(aGroupDimensions.begin());
389 aIter != aGroupDimensions.end(); aIter++ )
391 if ( aIter->GetGroupDimName() == rDimensionName ) //! ignore case
393 aGroupDimensions.erase( aIter ); // found -> remove
394 return; // don't have to look further
399 void ScDPDimensionSaveData::RemoveNumGroupDimension( const String& rDimensionName )
401 for ( ScDPSaveNumGroupDimensionVec::iterator aIter(aNumGroupDimensions.begin());
402 aIter != aNumGroupDimensions.end(); aIter++ )
404 if ( aIter->GetDimensionName() == rDimensionName ) //! ignore case
406 aNumGroupDimensions.erase( aIter ); // found -> remove
407 return; // don't have to look further
412 void ScDPDimensionSaveData::WriteToData( ScDPGroupTableData& rData ) const
414 // rData is assumed to be empty
415 // AddToData also handles date grouping
417 for ( ScDPSaveGroupDimensionVec::const_iterator aIter(aGroupDimensions.begin());
418 aIter != aGroupDimensions.end(); aIter++ )
419 aIter->AddToData( rData );
421 for ( ScDPSaveNumGroupDimensionVec::const_iterator aNumIter(aNumGroupDimensions.begin());
422 aNumIter != aNumGroupDimensions.end(); aNumIter++ )
423 aNumIter->AddToData( rData );
426 ScDPSaveGroupDimension* ScDPDimensionSaveData::GetGroupDimAccForBase( const String& rBaseName )
428 String aOrigBase( rBaseName ); // the original base dim in the case of nested group dims
430 for ( ScDPSaveGroupDimensionVec::iterator aIter(aGroupDimensions.begin());
431 aIter != aGroupDimensions.end(); aIter++ )
433 if ( aIter->GetSourceDimName() == aOrigBase ) //! ignore case
435 return &*aIter; // return the first one directly - it's the immediate derivative
437 else if ( aIter->GetGroupDimName() == aOrigBase )
439 // found the definition of rBaseName in the array - look for the next occurrence
440 // of this definitions's base
442 aOrigBase = aIter->GetSourceDimName(); // and continue the loop
446 return NULL; // none
449 const ScDPSaveGroupDimension* ScDPDimensionSaveData::GetGroupDimForBase( const String& rBaseName ) const
451 return const_cast< ScDPDimensionSaveData* >( this )->GetGroupDimAccForBase( rBaseName );
454 const ScDPSaveGroupDimension* ScDPDimensionSaveData::GetNamedGroupDim( const String& rGroupDim ) const
456 return const_cast< ScDPDimensionSaveData* >( this )->GetNamedGroupDimAcc( rGroupDim );
459 const ScDPSaveNumGroupDimension* ScDPDimensionSaveData::GetNumGroupDim( const String& rName ) const
461 return const_cast< ScDPDimensionSaveData* >( this )->GetNumGroupDimAcc( rName );
464 ScDPSaveGroupDimension* ScDPDimensionSaveData::GetNamedGroupDimAcc( const String& rGroupDim )
466 for ( ScDPSaveGroupDimensionVec::iterator aIter(aGroupDimensions.begin());
467 aIter != aGroupDimensions.end(); aIter++ )
468 if ( aIter->GetGroupDimName() == rGroupDim ) //! ignore case
469 return &*aIter; // there should be only one - use it directly
471 return NULL; // none
474 ScDPSaveNumGroupDimension* ScDPDimensionSaveData::GetNumGroupDimAcc( const String& rName )
476 for ( ScDPSaveNumGroupDimensionVec::iterator aIter(aNumGroupDimensions.begin());
477 aIter != aNumGroupDimensions.end(); aIter++ )
478 if ( aIter->GetDimensionName() == rName ) //! ignore case
479 return &*aIter; // there should be only one - use it directly
481 return NULL; // none
484 bool ScDPDimensionSaveData::HasGroupDimensions() const
486 return !aGroupDimensions.empty() || !aNumGroupDimensions.empty();
489 sal_Int32 ScDPDimensionSaveData::CollectDateParts( const String& rBaseDimName ) const
491 sal_Int32 nParts = 0;
492 const ScDPSaveNumGroupDimension* pNumDim = GetNumGroupDim( rBaseDimName );
493 if ( pNumDim )
494 nParts |= pNumDim->GetDatePart();
496 for ( ScDPSaveGroupDimensionVec::const_iterator aIter(aGroupDimensions.begin());
497 aIter != aGroupDimensions.end(); aIter++ )
498 if ( aIter->GetSourceDimName() == rBaseDimName ) //! ignore case
500 nParts |= aIter->GetDatePart();
501 // continue loop, collect parts from all matching group dimensions
504 return nParts;
507 String ScDPDimensionSaveData::CreateGroupDimName( const String& rSourceName,
508 const ScDPObject& rObject, bool bAllowSource,
509 const std::vector<String>* pDeletedNames )
511 // create a name for the new dimension by appending a number to the original
512 // dimension's name
514 bool bUseSource = bAllowSource; // if set, try the unchanged original name first
516 sal_Int32 nAdd = 2; // first try is "Name2"
517 const sal_Int32 nMaxAdd = 1000; // limit the loop
518 while ( nAdd <= nMaxAdd )
520 String aDimName( rSourceName );
521 if ( !bUseSource )
522 aDimName.Append( String::CreateFromInt32( nAdd ) );
523 bool bExists = false;
525 // look for existing group dimensions
526 for ( ScDPSaveGroupDimensionVec::const_iterator aIter(aGroupDimensions.begin());
527 aIter != aGroupDimensions.end() && !bExists; aIter++ )
528 if ( aIter->GetGroupDimName() == aDimName ) //! ignore case
529 bExists = true;
531 // look for base dimensions that happen to have that name
532 if ( !bExists && rObject.IsDimNameInUse( aDimName ) )
534 if ( pDeletedNames &&
535 std::find( pDeletedNames->begin(), pDeletedNames->end(), aDimName ) != pDeletedNames->end() )
537 // allow the name anyway if the name is in pDeletedNames
539 else
540 bExists = true;
543 if ( !bExists )
544 return aDimName; // found a new name
546 if ( bUseSource )
547 bUseSource = false;
548 else
549 ++nAdd; // continue with higher number
551 DBG_ERROR("CreateGroupDimName: no valid name found");
552 return EMPTY_STRING;