1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: dpdimsave.cxx,v $
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>
48 // -----------------------------------------------------------------------
50 ScDPSaveGroupItem::ScDPSaveGroupItem( const String
& 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
);
125 for ( std::vector
<String
>::const_iterator
aIter(aElements
.begin()); aIter
!= aElements
.end(); aIter
++ )
127 sal_uInt32 nFormat
= 0; //! ...
129 if ( pFormatter
->IsNumberFormat( *aIter
, nFormat
, fValue
) )
130 aData
= ScDPItemData( *aIter
, fValue
, TRUE
);
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
),
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
)
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
196 return aGroupName
; // found a new name
198 ++nAdd
; // continue with higher number
201 DBG_ERROR("CreateGroupName: no valid name found");
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
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() );
273 if ( rVisible
.Search( &aSearch
, nCollIndex
) )
274 bAllHidden
= false; // found one that is visible
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
);
294 aDim
.MakeDateHelper( aDateInfo
, nDatePart
);
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
),
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
);
336 ScDPNumGroupDimension
aDim( aGroupInfo
); // aGroupInfo: value grouping
338 aDim
.MakeDateHelper( aDateInfo
, nDatePart
); // date grouping
340 rData
.SetNumGroupDimension( nSource
, aDim
);
344 void ScDPSaveNumGroupDimension::SetGroupInfo( const ScDPNumGroupInfo
& rNew
)
349 void ScDPSaveNumGroupDimension::SetDateInfo( const ScDPNumGroupInfo
& rInfo
, sal_Int32 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
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
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
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
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
);
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
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
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
);
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
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
544 return aDimName
; // found a new name
549 ++nAdd
; // continue with higher number
551 DBG_ERROR("CreateGroupDimName: no valid name found");