LibreOffice Module sc (master) 1
dpdimsave.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <dpcache.hxx>
21#include <dpdimsave.hxx>
22#include <dpgroup.hxx>
23#include <dpobject.hxx>
24#include <dputil.hxx>
25#include <document.hxx>
26
27#include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
28
29#include <svl/numformat.hxx>
30#include <osl/diagnose.h>
31#include <rtl/math.hxx>
32#include <algorithm>
33
34#include <globstr.hrc>
35#include <scresid.hxx>
36#include <utility>
37
38using namespace com::sun::star;
39
41 aGroupName(std::move(aName)) {}
42
44
45void ScDPSaveGroupItem::AddElement( const OUString& rName )
46{
47 aElements.push_back(rName);
48}
49
51{
52 // add all elements of the other group (used for nested grouping)
53 aElements.insert( aElements.end(), rGroup.aElements.begin(), rGroup.aElements.end() );
54}
55
56bool ScDPSaveGroupItem::RemoveElement( const OUString& rName )
57{
58 auto it = std::find(aElements.begin(), aElements.end(), rName); //TODO: ignore case
59 if (it != aElements.end())
60 {
61 aElements.erase(it);
62 return true;
63 }
64 return false; // not found
65}
66
68{
69 return aElements.empty();
70}
71
73{
74 return aElements.size();
75}
76
77const OUString* ScDPSaveGroupItem::GetElementByIndex(size_t nIndex) const
78{
79 return (nIndex < aElements.size()) ? &aElements[ nIndex ] : nullptr;
80}
81
82void ScDPSaveGroupItem::Rename( const OUString& rNewName )
83{
84 aGroupName = rNewName;
85}
86
88{
89 // remove this group's elements from their groups in rDimension
90 // (rDimension must be a different dimension from the one which contains this)
91
92 for ( const auto& rElement : aElements )
93 rDimension.RemoveFromGroups( rElement );
94}
95
97{
98 maItems.reserve(aElements.size());
99 for (const auto& rElement : aElements)
100 {
101 sal_uInt32 nFormat = 0;
102 double fValue;
104 if (pFormatter->IsNumberFormat(rElement, nFormat, fValue))
105 aData.SetValue(fValue);
106 else
107 aData.SetString(rElement);
108
109 maItems.push_back(aData);
110 }
111}
112
114{
115 return std::find(maItems.begin(), maItems.end(), rItem) != maItems.end();
116}
117
119{
121 for (const auto& rItem : maItems)
122 aGroup.AddElement(rItem);
123
124 rDataDim.AddItem(aGroup);
125}
126
127ScDPSaveGroupDimension::ScDPSaveGroupDimension( OUString aSource, OUString aName ) :
128 aSourceDim(std::move( aSource )),
129 aGroupDimName(std::move( aName )),
130 nDatePart( 0 )
131{
132}
133
134ScDPSaveGroupDimension::ScDPSaveGroupDimension( OUString aSource, OUString aName, const ScDPNumGroupInfo& rDateInfo, sal_Int32 nPart ) :
135 aSourceDim(std::move( aSource )),
136 aGroupDimName(std::move( aName )),
137 aDateInfo( rDateInfo ),
138 nDatePart( nPart )
139{
140}
141
142void ScDPSaveGroupDimension::SetDateInfo( const ScDPNumGroupInfo& rInfo, sal_Int32 nPart )
143{
144 aDateInfo = rInfo;
145 nDatePart = nPart;
146}
147
149{
150 aGroups.push_back( rItem );
151}
152
153OUString ScDPSaveGroupDimension::CreateGroupName(std::u16string_view rPrefix)
154{
155 // create a name for a new group, using "Group1", "Group2" etc. (translated prefix in rPrefix)
156
157 //TODO: look in all dimensions, to avoid clashes with automatic groups (=name of base element)?
158 //TODO: (only dimensions for the same base)
159
160 sal_Int32 nAdd = 1; // first try is "Group1"
161 const sal_Int32 nMaxAdd = nAdd + aGroups.size(); // limit the loop
162 while ( nAdd <= nMaxAdd )
163 {
164 OUString aGroupName = rPrefix + OUString::number( nAdd );
165
166 // look for existing groups
167 bool bExists = std::any_of(aGroups.begin(), aGroups.end(),
168 [&aGroupName](const ScDPSaveGroupItem& rGroup) {
169 return rGroup.GetGroupName() == aGroupName; //TODO: ignore case
170 });
171
172 if ( !bExists )
173 return aGroupName; // found a new name
174
175 ++nAdd; // continue with higher number
176 }
177
178 OSL_FAIL("CreateGroupName: no valid name found");
179 return OUString();
180}
181
182const ScDPSaveGroupItem* ScDPSaveGroupDimension::GetNamedGroup( const OUString& rGroupName ) const
183{
184 return const_cast< ScDPSaveGroupDimension* >( this )->GetNamedGroupAcc( rGroupName );
185}
186
188{
189 auto aIter = std::find_if(aGroups.begin(), aGroups.end(),
190 [&rGroupName](const ScDPSaveGroupItem& rGroup) {
191 return rGroup.GetGroupName() == rGroupName; //TODO: ignore case
192 });
193 if (aIter != aGroups.end())
194 return &*aIter;
195
196 return nullptr; // none found
197}
198
200{
201 return aGroups.size();
202}
203
205{
206 return aGroups[nIndex];
207}
208
209
210void ScDPSaveGroupDimension::RemoveFromGroups( const OUString& rItemName )
211{
212 // if the item is in any group, remove it from the group,
213 // also remove the group if it is empty afterwards
214
215 for ( ScDPSaveGroupItemVec::iterator aIter(aGroups.begin()); aIter != aGroups.end(); ++aIter )
216 if ( aIter->RemoveElement( rItemName ) )
217 {
218 if ( aIter->IsEmpty() ) // removed last item from the group?
219 aGroups.erase( aIter ); // then remove the group
220
221 return; // don't have to look further
222 }
223}
224
225void ScDPSaveGroupDimension::RemoveGroup(const OUString& rGroupName)
226{
227 auto aIter = std::find_if(aGroups.begin(), aGroups.end(),
228 [&rGroupName](const ScDPSaveGroupItem& rGroup) {
229 return rGroup.GetGroupName() == rGroupName; //TODO: ignore case
230 });
231 if (aIter != aGroups.end())
232 aGroups.erase( aIter );
233}
234
236{
237 return aGroups.empty();
238}
239
241{
242 // check if there are only groups that don't appear in the list of visible names
243
244 return std::none_of(aGroups.begin(), aGroups.end(),
245 [&rVisible](const ScDPSaveGroupItem& rGroup) { return rVisible.count(rGroup.GetGroupName()) > 0; });
246}
247
248void ScDPSaveGroupDimension::Rename( const OUString& rNewName )
249{
250 aGroupDimName = rNewName;
251}
252
254{
255 return std::any_of(aGroups.begin(), aGroups.end(),
256 [&rItem](const ScDPSaveGroupItem& rGroup) { return rGroup.HasInGroup(rItem); });
257}
258
259namespace {
260
261bool isInteger(double fValue)
262{
263 return rtl::math::approxEqual(fValue, rtl::math::approxFloor(fValue));
264}
265
266void fillDateGroupDimension(
267 ScDPCache& rCache, ScDPNumGroupInfo& rDateInfo, tools::Long nSourceDim, tools::Long nGroupDim,
268 sal_Int32 nDatePart, const SvNumberFormatter* pFormatter)
269{
270 // Auto min/max is only used for "Years" part, but the loop is always
271 // needed.
272 double fSourceMin = 0.0;
273 double fSourceMax = 0.0;
274 bool bFirst = true;
275
276 const ScDPCache::ScDPItemDataVec& rItems = rCache.GetDimMemberValues(nSourceDim);
277 for (const ScDPItemData& rItem : rItems)
278 {
279 if (rItem.GetType() != ScDPItemData::Value)
280 continue;
281
282 double fVal = rItem.GetValue();
283 if (bFirst)
284 {
285 fSourceMin = fSourceMax = fVal;
286 bFirst = false;
287 }
288 else
289 {
290 if (fVal < fSourceMin)
291 fSourceMin = fVal;
292 if ( fVal > fSourceMax )
293 fSourceMax = fVal;
294 }
295 }
296
297 // For the start/end values, use the same date rounding as in
298 // ScDPNumGroupDimension::GetNumEntries (but not for the list of
299 // available years).
300 if (rDateInfo.mbAutoStart)
301 rDateInfo.mfStart = rtl::math::approxFloor(fSourceMin);
302 if (rDateInfo.mbAutoEnd)
303 rDateInfo.mfEnd = rtl::math::approxFloor(fSourceMax) + 1;
304
305 //TODO: if not automatic, limit fSourceMin/fSourceMax for list of year values?
306
307 tools::Long nStart = 0, nEnd = 0; // end is inclusive
308
309 switch (nDatePart)
310 {
311 case sheet::DataPilotFieldGroupBy::YEARS:
313 fSourceMin, nullptr, sheet::DataPilotFieldGroupBy::YEARS, pFormatter);
314 nEnd = ScDPUtil::getDatePartValue(fSourceMax, nullptr, sheet::DataPilotFieldGroupBy::YEARS, pFormatter);
315 break;
316 case sheet::DataPilotFieldGroupBy::QUARTERS: nStart = 1; nEnd = 4; break;
317 case sheet::DataPilotFieldGroupBy::MONTHS: nStart = 1; nEnd = 12; break;
318 case sheet::DataPilotFieldGroupBy::DAYS: nStart = 1; nEnd = 366; break;
319 case sheet::DataPilotFieldGroupBy::HOURS: nStart = 0; nEnd = 23; break;
320 case sheet::DataPilotFieldGroupBy::MINUTES: nStart = 0; nEnd = 59; break;
321 case sheet::DataPilotFieldGroupBy::SECONDS: nStart = 0; nEnd = 59; break;
322 default:
323 OSL_FAIL("invalid date part");
324 }
325
326 // Now, populate the group items in the cache.
327 rCache.ResetGroupItems(nGroupDim, rDateInfo, nDatePart);
328
329 for (tools::Long nValue = nStart; nValue <= nEnd; ++nValue)
330 rCache.SetGroupItem(nGroupDim, ScDPItemData(nDatePart, nValue));
331
332 // add first/last entry (min/max)
333 rCache.SetGroupItem(nGroupDim, ScDPItemData(nDatePart, ScDPItemData::DateFirst));
334 rCache.SetGroupItem(nGroupDim, ScDPItemData(nDatePart, ScDPItemData::DateLast));
335}
336
337}
338
340{
341 tools::Long nSourceIndex = rData.GetDimensionIndex( aSourceDim );
342 if ( nSourceIndex < 0 )
343 return;
344
345 ScDPGroupDimension aDim( nSourceIndex, aGroupDimName );
346 if ( nDatePart )
347 {
348 // date grouping
349
350 aDim.SetDateDimension();
351 }
352 else
353 {
354 // normal (manual) grouping
355
356 for (const auto& rGroup : aGroups)
357 rGroup.AddToData(aDim);
358 }
359
360 rData.AddGroupDimension( aDim );
361}
362
364{
365 tools::Long nSourceDim = rCache.GetDimensionIndex(aSourceDim);
366 if (nSourceDim < 0)
367 return;
368
369 tools::Long nDim = rCache.AppendGroupField();
370 SvNumberFormatter* pFormatter = rCache.GetDoc().GetFormatTable();
371
372 if (nDatePart)
373 {
374 fillDateGroupDimension(rCache, aDateInfo, nSourceDim, nDim, nDatePart, pFormatter);
375 return;
376 }
377
378 rCache.ResetGroupItems(nDim, aDateInfo, 0);
379 for (const ScDPSaveGroupItem& rGI : aGroups)
380 {
381 rGI.ConvertElementsToItems(pFormatter);
382 rCache.SetGroupItem(nDim, ScDPItemData(rGI.GetGroupName()));
383 }
384
385 const ScDPCache::ScDPItemDataVec& rItems = rCache.GetDimMemberValues(nSourceDim);
386 for (const ScDPItemData& rItem : rItems)
387 {
388 if (!IsInGroup(rItem))
389 // Not in any group. Add as its own group.
390 rCache.SetGroupItem(nDim, rItem);
391 }
392}
393
395 aDimensionName(std::move( aName )),
396 aGroupInfo( rInfo ),
397 nDatePart( 0 )
398{
399}
400
401ScDPSaveNumGroupDimension::ScDPSaveNumGroupDimension( OUString aName, const ScDPNumGroupInfo& rDateInfo, sal_Int32 nPart ) :
402 aDimensionName(std::move( aName )),
403 aDateInfo( rDateInfo ),
404 nDatePart( nPart )
405{
406}
407
409{
411 if ( nSource >= 0 )
412 {
413 ScDPNumGroupDimension aDim( aGroupInfo ); // aGroupInfo: value grouping
414 if ( nDatePart )
415 aDim.SetDateDimension();
416
417 rData.SetNumGroupDimension( nSource, aDim );
418 }
419}
420
422{
424 if (nDim < 0)
425 return;
426
428 {
429 // Date grouping
430 SvNumberFormatter* pFormatter = rCache.GetDoc().GetFormatTable();
431 fillDateGroupDimension(rCache, aDateInfo, nDim, nDim, nDatePart, pFormatter);
432 }
433 else if (aGroupInfo.mbEnable)
434 {
435 // Number-range grouping
436
437 // Look through the source entries for non-integer numbers, minimum
438 // and maximum.
439
440 // non-integer GroupInfo values count, too
442 (aGroupInfo.mbAutoStart || isInteger(aGroupInfo.mfStart)) &&
443 (aGroupInfo.mbAutoEnd || isInteger(aGroupInfo.mfEnd)) &&
444 isInteger(aGroupInfo.mfStep);
445
446 double fSourceMin = 0.0;
447 double fSourceMax = 0.0;
448 bool bFirst = true;
449
450 const ScDPCache::ScDPItemDataVec& rItems = rCache.GetDimMemberValues(nDim);
451 for (const ScDPItemData& rItem : rItems)
452 {
453 if (rItem.GetType() != ScDPItemData::Value)
454 continue;
455
456 double fValue = rItem.GetValue();
457 if (bFirst)
458 {
459 fSourceMin = fSourceMax = fValue;
460 bFirst = false;
461 continue;
462 }
463
464 if (fValue < fSourceMin)
465 fSourceMin = fValue;
466 if (fValue > fSourceMax)
467 fSourceMax = fValue;
468
469 if (aGroupInfo.mbIntegerOnly && !isInteger(fValue))
470 {
471 // If any non-integer numbers are involved, the group labels
472 // are shown including their upper limit.
474 }
475 }
476
478 {
479 // special handling for dates: always integer, round down limits
481 fSourceMin = rtl::math::approxFloor(fSourceMin);
482 fSourceMax = rtl::math::approxFloor(fSourceMax) + 1;
483 }
484
486 aGroupInfo.mfStart = fSourceMin;
488 aGroupInfo.mfEnd = fSourceMax;
489
490 //TODO: limit number of entries?
491
492 tools::Long nLoopCount = 0;
493 double fLoop = aGroupInfo.mfStart;
494
495 rCache.ResetGroupItems(nDim, aGroupInfo, 0);
496
497 // Use "less than" instead of "less or equal" for the loop - don't
498 // create a group that consists only of the end value. Instead, the
499 // end value is then included in the last group (last group is bigger
500 // than the others). The first group has to be created nonetheless.
501 // GetNumGroupForValue has corresponding logic.
502
503 bool bFirstGroup = true;
504 while (bFirstGroup || (fLoop < aGroupInfo.mfEnd && !rtl::math::approxEqual(fLoop, aGroupInfo.mfEnd)))
505 {
506 ScDPItemData aItem;
507 aItem.SetRangeStart(fLoop);
508 rCache.SetGroupItem(nDim, aItem);
509 ++nLoopCount;
510 fLoop = aGroupInfo.mfStart + nLoopCount * aGroupInfo.mfStep;
511 bFirstGroup = false;
512
513 // ScDPItemData values are compared with approxEqual
514 }
515
516 ScDPItemData aItem;
517 aItem.SetRangeFirst();
518 rCache.SetGroupItem(nDim, aItem);
519
520 aItem.SetRangeLast();
521 rCache.SetGroupItem(nDim, aItem);
522 }
523}
524
526{
527 aGroupInfo = rNew;
528}
529
530void ScDPSaveNumGroupDimension::SetDateInfo( const ScDPNumGroupInfo& rInfo, sal_Int32 nPart )
531{
532 aDateInfo = rInfo;
533 nDatePart = nPart;
534}
535
536namespace {
537
538struct ScDPSaveGroupDimNameFunc
539{
540 OUString maDimName;
541 explicit ScDPSaveGroupDimNameFunc( OUString aDimName ) : maDimName(std::move( aDimName )) {}
542 bool operator()( const ScDPSaveGroupDimension& rGroupDim ) const { return rGroupDim.GetGroupDimName() == maDimName; }
543};
544
545struct ScDPSaveGroupSourceNameFunc
546{
547 OUString maSrcDimName;
548 explicit ScDPSaveGroupSourceNameFunc( OUString aSrcDimName ) : maSrcDimName(std::move( aSrcDimName )) {}
549 bool operator()( const ScDPSaveGroupDimension& rGroupDim ) const { return rGroupDim.GetSourceDimName() == maSrcDimName; }
550};
551
552} // namespace
553
555{
556}
557
559{
560 return false;
561}
562
564{
565 OSL_ENSURE( ::std::none_of( maGroupDims.begin(), maGroupDims.end(), ScDPSaveGroupDimNameFunc( rGroupDim.GetGroupDimName() ) ),
566 "ScDPDimensionSaveData::AddGroupDimension - group dimension exists already" );
567 // ReplaceGroupDimension() adds new or replaces existing
568 ReplaceGroupDimension( rGroupDim );
569}
570
572{
573 ScDPSaveGroupDimVec::iterator aIt = ::std::find_if(
574 maGroupDims.begin(), maGroupDims.end(), ScDPSaveGroupDimNameFunc( rGroupDim.GetGroupDimName() ) );
575 if( aIt == maGroupDims.end() )
576 maGroupDims.push_back( rGroupDim );
577 else
578 *aIt = rGroupDim;
579}
580
581void ScDPDimensionSaveData::RemoveGroupDimension( const OUString& rGroupDimName )
582{
583 ScDPSaveGroupDimVec::iterator aIt = ::std::find_if(
584 maGroupDims.begin(), maGroupDims.end(), ScDPSaveGroupDimNameFunc( rGroupDimName ) );
585 if( aIt != maGroupDims.end() )
586 maGroupDims.erase( aIt );
587}
588
590{
591 OSL_ENSURE( maNumGroupDims.count( rGroupDim.GetDimensionName() ) == 0,
592 "ScDPDimensionSaveData::AddNumGroupDimension - numeric group dimension exists already" );
593 // ReplaceNumGroupDimension() adds new or replaces existing
594 ReplaceNumGroupDimension( rGroupDim );
595}
596
598{
599 ScDPSaveNumGroupDimMap::iterator aIt = maNumGroupDims.find( rGroupDim.GetDimensionName() );
600 if( aIt == maNumGroupDims.end() )
601 maNumGroupDims.emplace( rGroupDim.GetDimensionName(), rGroupDim );
602 else
603 aIt->second = rGroupDim;
604}
605
606void ScDPDimensionSaveData::RemoveNumGroupDimension( const OUString& rGroupDimName )
607{
608 maNumGroupDims.erase( rGroupDimName );
609}
610
612{
613 // rData is assumed to be empty
614 // AddToData also handles date grouping
615
616 for( const auto& rGroupDim : maGroupDims )
617 rGroupDim.AddToData( rData );
618
619 for( const auto& rEntry : maNumGroupDims )
620 rEntry.second.AddToData( rData );
621}
622
624{
625 for (const auto& rEntry : maGroupDims)
626 rEntry.AddToCache(rCache);
627 for (const auto& rEntry : maNumGroupDims)
628 rEntry.second.AddToCache(rCache);
629}
630
631const ScDPSaveGroupDimension* ScDPDimensionSaveData::GetGroupDimForBase( const OUString& rBaseDimName ) const
632{
633 return const_cast< ScDPDimensionSaveData* >( this )->GetGroupDimAccForBase( rBaseDimName );
634}
635
636const ScDPSaveGroupDimension* ScDPDimensionSaveData::GetNamedGroupDim( const OUString& rGroupDimName ) const
637{
638 return const_cast< ScDPDimensionSaveData* >( this )->GetNamedGroupDimAcc( rGroupDimName );
639}
640
642{
643 return const_cast< ScDPDimensionSaveData* >( this )->GetFirstNamedGroupDimAcc( rBaseDimName );
644}
645
646const ScDPSaveGroupDimension* ScDPDimensionSaveData::GetNextNamedGroupDim( const OUString& rGroupDimName ) const
647{
648 return const_cast< ScDPDimensionSaveData* >( this )->GetNextNamedGroupDimAcc( rGroupDimName );
649}
650
651const ScDPSaveNumGroupDimension* ScDPDimensionSaveData::GetNumGroupDim( const OUString& rGroupDimName ) const
652{
653 return const_cast< ScDPDimensionSaveData* >( this )->GetNumGroupDimAcc( rGroupDimName );
654}
655
657{
658 ScDPSaveGroupDimension* pGroupDim = GetFirstNamedGroupDimAcc( rBaseDimName );
659 return pGroupDim ? pGroupDim : GetNextNamedGroupDimAcc( rBaseDimName );
660}
661
663{
664 ScDPSaveGroupDimVec::iterator aIt = ::std::find_if(
665 maGroupDims.begin(), maGroupDims.end(), ScDPSaveGroupDimNameFunc( rGroupDimName ) );
666 return (aIt == maGroupDims.end()) ? nullptr : &*aIt;
667}
668
670{
671 ScDPSaveGroupDimVec::iterator aIt = ::std::find_if(
672 maGroupDims.begin(), maGroupDims.end(), ScDPSaveGroupSourceNameFunc( rBaseDimName ) );
673 return (aIt == maGroupDims.end()) ? nullptr : &*aIt;
674}
675
677{
678 // find the group dimension with the passed name
679 ScDPSaveGroupDimVec::iterator aIt = ::std::find_if(
680 maGroupDims.begin(), maGroupDims.end(), ScDPSaveGroupDimNameFunc( rGroupDimName ) );
681 // find next group dimension based on the same source dimension name
682 if( aIt != maGroupDims.end() )
683 aIt = ::std::find_if( aIt + 1, maGroupDims.end(), ScDPSaveGroupSourceNameFunc( aIt->GetSourceDimName() ) );
684 return (aIt == maGroupDims.end()) ? nullptr : &*aIt;
685}
686
688{
689 ScDPSaveNumGroupDimMap::iterator aIt = maNumGroupDims.find( rGroupDimName );
690 return (aIt == maNumGroupDims.end()) ? nullptr : &aIt->second;
691}
692
694{
695 return !maGroupDims.empty() || !maNumGroupDims.empty();
696}
697
698sal_Int32 ScDPDimensionSaveData::CollectDateParts( const OUString& rBaseDimName ) const
699{
700 sal_Int32 nParts = 0;
701 // start with part of numeric group
702 if( const ScDPSaveNumGroupDimension* pNumDim = GetNumGroupDim( rBaseDimName ) )
703 nParts |= pNumDim->GetDatePart();
704 // collect parts from all matching group dimensions
705 for( const ScDPSaveGroupDimension* pGroupDim = GetFirstNamedGroupDim( rBaseDimName ); pGroupDim; pGroupDim = GetNextNamedGroupDim( pGroupDim->GetGroupDimName() ) )
706 nParts |= pGroupDim->GetDatePart();
707
708 return nParts;
709}
710
712 const OUString& rSourceName, const ScDPObject& rObject, bool bAllowSource,
713 const std::vector<OUString>* pDeletedNames )
714{
715 // create a name for the new dimension by appending a number to the original
716 // dimension's name
717
718 bool bUseSource = bAllowSource; // if set, try the unchanged original name first
719
720 sal_Int32 nAdd = 2; // first try is "Name2"
721 const sal_Int32 nMaxAdd = 1000; // limit the loop
722 while ( nAdd <= nMaxAdd )
723 {
724 OUString aDimName( rSourceName );
725 if ( !bUseSource )
726 aDimName += OUString::number(nAdd);
727
728 // look for existing group dimensions
729 bool bExists = std::any_of(maGroupDims.begin(), maGroupDims.end(),
730 [&aDimName](const ScDPSaveGroupDimension& rDim) {
731 return rDim.GetGroupDimName() == aDimName; //TODO: ignore case
732 });
733
734 // look for base dimensions that happen to have that name
735 if ( !bExists && rObject.IsDimNameInUse( aDimName ) )
736 {
737 if ( pDeletedNames &&
738 std::find( pDeletedNames->begin(), pDeletedNames->end(), aDimName ) != pDeletedNames->end() )
739 {
740 // allow the name anyway if the name is in pDeletedNames
741 }
742 else
743 bExists = true;
744 }
745
746 if ( !bExists )
747 return aDimName; // found a new name
748
749 if ( bUseSource )
750 bUseSource = false;
751 else
752 ++nAdd; // continue with higher number
753 }
754 OSL_FAIL("CreateGroupDimName: no valid name found");
755 return OUString();
756}
757
758namespace
759{
760 const TranslateId aDatePartIds[] =
761 {
762 STR_DPFIELD_GROUP_BY_SECONDS,
763 STR_DPFIELD_GROUP_BY_MINUTES,
764 STR_DPFIELD_GROUP_BY_HOURS,
765 STR_DPFIELD_GROUP_BY_DAYS,
766 STR_DPFIELD_GROUP_BY_MONTHS,
767 STR_DPFIELD_GROUP_BY_QUARTERS,
768 STR_DPFIELD_GROUP_BY_YEARS
769 };
770}
771
773 sal_Int32 nDatePart, const ScDPObject& rObject, bool bAllowSource,
774 const std::vector<OUString>* pDeletedNames )
775{
776 using namespace css::sheet::DataPilotFieldGroupBy;
777 OUString aPartName;
778 switch( nDatePart )
779 {
780 case SECONDS: aPartName = ScResId(aDatePartIds[0]); break;
781 case MINUTES: aPartName = ScResId(aDatePartIds[1]); break;
782 case HOURS: aPartName = ScResId(aDatePartIds[2]); break;
783 case DAYS: aPartName = ScResId(aDatePartIds[3]); break;
784 case MONTHS: aPartName = ScResId(aDatePartIds[4]); break;
785 case QUARTERS: aPartName = ScResId(aDatePartIds[5]); break;
786 case YEARS: aPartName = ScResId(aDatePartIds[6]); break;
787 }
788 OSL_ENSURE(!aPartName.isEmpty(), "ScDPDimensionSaveData::CreateDateGroupDimName - invalid date part");
789 return CreateGroupDimName( aPartName, rObject, bAllowSource, pDeletedNames );
790}
791
792/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
This class represents the cached data part of the datapilot cache table implementation.
Definition: dpcache.hxx:48
void ResetGroupItems(tools::Long nDim, const ScDPNumGroupInfo &rNumInfo, sal_Int32 nGroupType)
Definition: dpcache.cxx:1270
ScDocument & GetDoc() const
Definition: dpcache.cxx:883
SCROW SetGroupItem(tools::Long nDim, const ScDPItemData &rData)
Definition: dpcache.cxx:1292
tools::Long AppendGroupField()
Definition: dpcache.cxx:1264
const ScDPItemDataVec & GetDimMemberValues(SCCOL nDim) const
Definition: dpcache.cxx:1050
std::vector< ScDPItemData > ScDPItemDataVec
Definition: dpcache.hxx:52
SCCOL GetDimensionIndex(std::u16string_view sName) const
Definition: dpcache.cxx:1085
This class has to do with handling exclusively grouped dimensions? TODO: Find out what this class doe...
Definition: dpdimsave.hxx:164
void WriteToCache(ScDPCache &rCache) const
Definition: dpdimsave.cxx:623
const ScDPSaveGroupDimension * GetNamedGroupDim(const OUString &rGroupDimName) const
Definition: dpdimsave.cxx:636
bool HasGroupDimensions() const
Definition: dpdimsave.cxx:693
OUString CreateGroupDimName(const OUString &rSourceName, const ScDPObject &rObject, bool bAllowSource, const ::std::vector< OUString > *pDeletedNames)
Definition: dpdimsave.cxx:711
void ReplaceNumGroupDimension(const ScDPSaveNumGroupDimension &rGroupDim)
Definition: dpdimsave.cxx:597
void WriteToData(ScDPGroupTableData &rData) const
Definition: dpdimsave.cxx:611
sal_Int32 CollectDateParts(const OUString &rBaseDimName) const
Definition: dpdimsave.cxx:698
void ReplaceGroupDimension(const ScDPSaveGroupDimension &rGroupDim)
Definition: dpdimsave.cxx:571
const ScDPSaveGroupDimension * GetFirstNamedGroupDim(const OUString &rBaseDimName) const
Definition: dpdimsave.cxx:641
const ScDPSaveGroupDimension * GetGroupDimForBase(const OUString &rBaseDimName) const
Definition: dpdimsave.cxx:631
void AddNumGroupDimension(const ScDPSaveNumGroupDimension &rGroupDim)
Definition: dpdimsave.cxx:589
void RemoveNumGroupDimension(const OUString &rGroupDimName)
Definition: dpdimsave.cxx:606
const ScDPSaveNumGroupDimension * GetNumGroupDim(const OUString &rGroupDimName) const
Definition: dpdimsave.cxx:651
OUString CreateDateGroupDimName(sal_Int32 nDatePart, const ScDPObject &rObject, bool bAllowSource, const ::std::vector< OUString > *pDeletedNames)
Definition: dpdimsave.cxx:772
void AddGroupDimension(const ScDPSaveGroupDimension &rGroupDim)
Definition: dpdimsave.cxx:563
ScDPSaveNumGroupDimension * GetNumGroupDimAcc(const OUString &rGroupDimName)
Definition: dpdimsave.cxx:687
ScDPSaveGroupDimension * GetFirstNamedGroupDimAcc(const OUString &rBaseDimName)
Definition: dpdimsave.cxx:669
ScDPSaveGroupDimVec maGroupDims
Definition: dpdimsave.hxx:214
ScDPSaveGroupDimension * GetGroupDimAccForBase(const OUString &rBaseDimName)
Definition: dpdimsave.cxx:656
ScDPSaveGroupDimension * GetNamedGroupDimAcc(const OUString &rGroupDimName)
Definition: dpdimsave.cxx:662
const ScDPSaveGroupDimension * GetNextNamedGroupDim(const OUString &rGroupDimName) const
Definition: dpdimsave.cxx:646
bool operator==(const ScDPDimensionSaveData &r) const
Definition: dpdimsave.cxx:558
ScDPSaveNumGroupDimMap maNumGroupDims
Definition: dpdimsave.hxx:215
void RemoveGroupDimension(const OUString &rGroupDimName)
Definition: dpdimsave.cxx:581
ScDPSaveGroupDimension * GetNextNamedGroupDimAcc(const OUString &rGroupDimName)
Definition: dpdimsave.cxx:676
void SetDateDimension()
Definition: dpgroup.cxx:419
void AddItem(const ScDPGroupItem &rItem)
Definition: dpgroup.cxx:366
void AddElement(const ScDPItemData &rName)
Definition: dpgroup.cxx:311
sal_Int32 GetDimensionIndex(std::u16string_view rName)
Definition: dpgroup.cxx:498
void SetNumGroupDimension(sal_Int32 nIndex, const ScDPNumGroupDimension &rGroup)
Definition: dpgroup.cxx:488
void AddGroupDimension(const ScDPGroupDimension &rGroup)
Definition: dpgroup.cxx:481
When assigning a string value, you can also assign an interned string whose life-cycle is managed by ...
Definition: dpitemdata.hxx:29
void SetRangeLast()
Definition: dpitemdata.cxx:174
void SetRangeStart(double fVal)
Definition: dpitemdata.cxx:160
void SetRangeFirst()
Definition: dpitemdata.cxx:167
static const sal_Int32 DateFirst
Definition: dpitemdata.hxx:35
static const sal_Int32 DateLast
Definition: dpitemdata.hxx:36
bool IsDimNameInUse(std::u16string_view rName) const
Definition: dpobject.cxx:1183
Represents a new group dimension whose dimension ID is higher than the highest source dimension ID.
Definition: dpdimsave.hxx:91
bool IsInGroup(const ScDPItemData &rItem) const
Definition: dpdimsave.cxx:253
void AddToCache(ScDPCache &rCache) const
Definition: dpdimsave.cxx:363
ScDPSaveGroupItem * GetNamedGroupAcc(const OUString &rGroupName)
Definition: dpdimsave.cxx:187
OUString aSourceDim
always the real source from the original data
Definition: dpdimsave.hxx:92
void Rename(const OUString &rNewName)
Definition: dpdimsave.cxx:248
void AddGroupItem(const ScDPSaveGroupItem &rItem)
Definition: dpdimsave.cxx:148
void RemoveFromGroups(const OUString &rItemName)
Definition: dpdimsave.cxx:210
const OUString & GetSourceDimName() const
Definition: dpdimsave.hxx:108
const OUString & GetGroupDimName() const
Definition: dpdimsave.hxx:107
void RemoveGroup(const OUString &rGroupName)
Definition: dpdimsave.cxx:225
void SetDateInfo(const ScDPNumGroupInfo &rInfo, sal_Int32 nPart)
Definition: dpdimsave.cxx:142
ScDPNumGroupInfo aDateInfo
Definition: dpdimsave.hxx:95
const ScDPSaveGroupItem * GetNamedGroup(const OUString &rGroupName) const
Definition: dpdimsave.cxx:182
OUString CreateGroupName(std::u16string_view rPrefix)
Definition: dpdimsave.cxx:153
ScDPSaveGroupDimension(OUString aSource, OUString aName)
Definition: dpdimsave.cxx:127
bool HasOnlyHidden(const ScDPUniqueStringSet &rVisible)
Definition: dpdimsave.cxx:240
bool IsEmpty() const
Definition: dpdimsave.cxx:235
void AddToData(ScDPGroupTableData &rData) const
Definition: dpdimsave.cxx:339
tools::Long GetGroupCount() const
Definition: dpdimsave.cxx:199
ScDPSaveGroupItemVec aGroups
Definition: dpdimsave.hxx:94
const ScDPSaveGroupItem & GetGroupByIndex(tools::Long nIndex) const
Definition: dpdimsave.cxx:204
Classes to save Data Pilot settings that create new dimensions (fields).
Definition: dpdimsave.hxx:47
void Rename(const OUString &rNewName)
Definition: dpdimsave.cxx:82
ScDPSaveGroupItem(OUString aName)
Definition: dpdimsave.cxx:40
void AddElementsFromGroup(const ScDPSaveGroupItem &rGroup)
Definition: dpdimsave.cxx:50
void AddToData(ScDPGroupDimension &rDataDim) const
Definition: dpdimsave.cxx:118
size_t GetElementCount() const
Definition: dpdimsave.cxx:72
void RemoveElementsFromGroups(ScDPSaveGroupDimension &rDimension) const
remove this group's elements from their groups in rDimension (rDimension must be a different dimensio...
Definition: dpdimsave.cxx:87
OUString aGroupName
name of group
Definition: dpdimsave.hxx:48
void AddElement(const OUString &rName)
Definition: dpdimsave.cxx:45
bool HasInGroup(const ScDPItemData &rItem) const
Definition: dpdimsave.cxx:113
void ConvertElementsToItems(SvNumberFormatter *pFormatter) const
Definition: dpdimsave.cxx:96
bool RemoveElement(const OUString &rName)
Definition: dpdimsave.cxx:56
const OUString * GetElementByIndex(size_t nIndex) const
Definition: dpdimsave.cxx:77
std::vector< ScDPItemData > maItems
items converted from the strings.
Definition: dpdimsave.hxx:50
std::vector< OUString > aElements
names of items in original dimension
Definition: dpdimsave.hxx:49
bool IsEmpty() const
Definition: dpdimsave.cxx:67
Represents a group dimension that introduces a new hierarchy for an existing dimension.
Definition: dpdimsave.hxx:136
const OUString & GetDimensionName() const
Definition: dpdimsave.hxx:149
ScDPNumGroupInfo aGroupInfo
Definition: dpdimsave.hxx:138
void SetDateInfo(const ScDPNumGroupInfo &rInfo, sal_Int32 nPart)
Definition: dpdimsave.cxx:530
void AddToCache(ScDPCache &rCache) const
Definition: dpdimsave.cxx:421
ScDPSaveNumGroupDimension(OUString aName, const ScDPNumGroupInfo &rInfo)
Definition: dpdimsave.cxx:394
void AddToData(ScDPGroupTableData &rData) const
Definition: dpdimsave.cxx:408
ScDPNumGroupInfo aDateInfo
Definition: dpdimsave.hxx:139
void SetGroupInfo(const ScDPNumGroupInfo &rNew)
Definition: dpdimsave.cxx:525
static sal_Int32 getDatePartValue(double fValue, const ScDPNumGroupInfo *pInfo, sal_Int32 nDatePart, const SvNumberFormatter *pFormatter)
Definition: dputil.cxx:287
SC_DLLPUBLIC SvNumberFormatter * GetFormatTable() const
Definition: documen2.cxx:467
bool IsNumberFormat(const OUString &sString, sal_uInt32 &F_Index, double &fOutNumber, SvNumInputOptions eInputOptions=SvNumInputOptions::NONE)
std::unordered_set< OUString > ScDPUniqueStringSet
Definition: dptypes.hxx:16
sal_Int16 nValue
sal_Int32 nIndex
OUString aName
constexpr OUStringLiteral aData
long Long
OUString ScResId(TranslateId aId)
Definition: scdll.cxx:90